diff --git a/Adapter/Adapter_AddressFactory.php b/Adapter/Adapter_AddressFactory.php index 927f2be0..b76ce74d 100644 --- a/Adapter/Adapter_AddressFactory.php +++ b/Adapter/Adapter_AddressFactory.php @@ -26,25 +26,25 @@ class Adapter_AddressFactory { - /** - * Initilize an address corresponding to the specified id address or if empty to the - * default shop configuration - * @param null $id_address - * @param bool $with_geoloc - * @return Address - */ - public function findOrCreate($id_address = null, $with_geoloc = false) + /** + * Initilize an address corresponding to the specified id address or if empty to the + * default shop configuration + * @param null $id_address + * @param bool $with_geoloc + * @return Address + */ + public function findOrCreate($id_address = null, $with_geoloc = false) { $func_args = func_get_args(); return call_user_func_array(array('Address', 'initialize'), $func_args); } - /** - * Check if an address exists depending on given $id_address - * @param $id_address - * @return bool - */ - public function addressExists($id_address) + /** + * Check if an address exists depending on given $id_address + * @param $id_address + * @return bool + */ + public function addressExists($id_address) { return Address::addressExists($id_address); } diff --git a/Adapter/Adapter_CacheManager.php b/Adapter/Adapter_CacheManager.php new file mode 100644 index 00000000..9bd57f52 --- /dev/null +++ b/Adapter/Adapter_CacheManager.php @@ -0,0 +1,38 @@ + + * @copyright 2007-2015 PrestaShop SA + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +class Adapter_CacheManager +{ + /** + * Cleans the cache for specific cache key. + * + * @param $key + */ + public function clean($key) + { + Cache::clean($key); + } +} diff --git a/Adapter/Adapter_Configuration.php b/Adapter/Adapter_Configuration.php index bcc3aebb..7e7c3ec8 100644 --- a/Adapter/Adapter_Configuration.php +++ b/Adapter/Adapter_Configuration.php @@ -26,14 +26,13 @@ class Adapter_Configuration implements Core_Business_ConfigurationInterface { - - /** - * Returns constant defined by given $key if exists or check directly into PrestaShop - * Configuration - * @param $key - * @return mixed - */ - public function get($key) + /** + * Returns constant defined by given $key if exists or check directly into PrestaShop + * Configuration + * @param $key + * @return mixed + */ + public function get($key) { if (defined($key)) { return constant($key); diff --git a/Adapter/Adapter_Database.php b/Adapter/Adapter_Database.php index 53d74def..2d95f721 100644 --- a/Adapter/Adapter_Database.php +++ b/Adapter/Adapter_Database.php @@ -26,23 +26,23 @@ class Adapter_Database implements Core_Foundation_Database_DatabaseInterface { - /** - * Perform a SELECT sql statement - * @param $sqlString - * @return array|false - * @throws PrestaShopDatabaseException - */ - public function select($sqlString) + /** + * Perform a SELECT sql statement + * @param $sqlString + * @return array|false + * @throws PrestaShopDatabaseException + */ + public function select($sqlString) { return Db::getInstance()->executeS($sqlString); } - /** - * Escape $unsafe to be used into a SQL statement - * @param $unsafeData - * @return string - */ - public function escape($unsafeData) + /** + * Escape $unsafe to be used into a SQL statement + * @param $unsafeData + * @return string + */ + public function escape($unsafeData) { // Prepare required params $html_ok = true; diff --git a/Adapter/Adapter_EntityMapper.php b/Adapter/Adapter_EntityMapper.php index ffa0a44c..b677edca 100644 --- a/Adapter/Adapter_EntityMapper.php +++ b/Adapter/Adapter_EntityMapper.php @@ -24,84 +24,81 @@ * International Registered Trademark & Property of PrestaShop SA */ -class Adapter_EntityMapper { +class Adapter_EntityMapper +{ + /** + * Load ObjectModel + * @param $id + * @param $id_lang + * @param $entity ObjectModel + * @param $entity_defs + * @param $id_shop + * @param $should_cache_objects + * @throws PrestaShopDatabaseException + */ + public function load($id, $id_lang, $entity, $entity_defs, $id_shop, $should_cache_objects) + { + // Load object from database if object id is present + $cache_id = 'objectmodel_' . $entity_defs['classname'] . '_' . (int)$id . '_' . (int)$id_shop . '_' . (int)$id_lang; + if (!$should_cache_objects || !Cache::isStored($cache_id)) { + $sql = new DbQuery(); + $sql->from($entity_defs['table'], 'a'); + $sql->where('a.`' . bqSQL($entity_defs['primary']) . '` = ' . (int)$id); - /** - * Load ObjectModel - * @param $id - * @param $id_lang - * @param $entity ObjectModel - * @param $entity_defs - * @param $id_shop - * @param $should_cache_objects - * @throws PrestaShopDatabaseException - */ - public function load($id, $id_lang, $entity, $entity_defs, $id_shop, $should_cache_objects) - { - // Load object from database if object id is present - $cache_id = 'objectmodel_' . $entity_defs['classname'] . '_' . (int)$id . '_' . (int)$id_shop . '_' . (int)$id_lang; - if (!$should_cache_objects || !Cache::isStored($cache_id)) { - $sql = new DbQuery(); - $sql->from($entity_defs['table'], 'a'); - $sql->where('a.`' . bqSQL($entity_defs['primary']) . '` = ' . (int)$id); + // Get lang informations + if ($id_lang && isset($entity_defs['multilang']) && $entity_defs['multilang']) { + $sql->leftJoin($entity_defs['table'] . '_lang', 'b', 'a.`' . bqSQL($entity_defs['primary']) . '` = b.`' . bqSQL($entity_defs['primary']) . '` AND b.`id_lang` = ' . (int)$id_lang); + if ($id_shop && !empty($entity_defs['multilang_shop'])) { + $sql->where('b.`id_shop` = ' . (int)$id_shop); + } + } - // Get lang informations - if ($id_lang && isset($entity_defs['multilang']) && $entity_defs['multilang']) { + // Get shop informations + if (Shop::isTableAssociated($entity_defs['table'])) { + $sql->leftJoin($entity_defs['table'] . '_shop', 'c', 'a.`' . bqSQL($entity_defs['primary']) . '` = c.`' . bqSQL($entity_defs['primary']) . '` AND c.`id_shop` = ' . (int)$id_shop); + } - $sql->leftJoin($entity_defs['table'] . '_lang', 'b', 'a.`' . bqSQL($entity_defs['primary']) . '` = b.`' . bqSQL($entity_defs['primary']) . '` AND b.`id_lang` = ' . (int)$id_lang); - if ($id_shop && !empty($entity_defs['multilang_shop'])) { - $sql->where('b.`id_shop` = ' . (int)$id_shop); - } - } - - // Get shop informations - if (Shop::isTableAssociated($entity_defs['table'])) { - $sql->leftJoin($entity_defs['table'] . '_shop', 'c', 'a.`' . bqSQL($entity_defs['primary']) . '` = c.`' . bqSQL($entity_defs['primary']) . '` AND c.`id_shop` = ' . (int)$id_shop); - } - - if ($object_datas = Db::getInstance()->getRow($sql)) { - if (!$id_lang && isset($entity_defs['multilang']) && $entity_defs['multilang']) { - - $sql = 'SELECT * + if ($object_datas = Db::getInstance()->getRow($sql)) { + if (!$id_lang && isset($entity_defs['multilang']) && $entity_defs['multilang']) { + $sql = 'SELECT * FROM `' . bqSQL(_DB_PREFIX_ . $entity_defs['table']) . '_lang` WHERE `' . bqSQL($entity_defs['primary']) . '` = ' . (int)$id - .(($id_shop && $entity->isLangMultishop()) ? ' AND `id_shop` = ' . (int)$id_shop : ''); + .(($id_shop && $entity->isLangMultishop()) ? ' AND `id_shop` = ' . (int)$id_shop : ''); - if ($object_datas_lang = Db::getInstance()->executeS($sql)) { - - foreach ($object_datas_lang as $row) { - foreach ($row as $key => $value) { - if ($key != $entity_defs['primary'] && array_key_exists($key, $entity)) { - if (!isset($object_datas[$key]) || !is_array($object_datas[$key])) - $object_datas[$key] = array(); - - $object_datas[$key][$row['id_lang']] = $value; - } - } - } - } - } - $entity->id = (int)$id; - foreach ($object_datas as $key => $value) { - if (array_key_exists($key, $entity)) { - $entity->{$key} = $value; - } else { - unset($object_datas[$key]); - } - } - if ($should_cache_objects) { - Cache::store($cache_id, $object_datas); - } - } - } else { - $object_datas = Cache::retrieve($cache_id); - if ($object_datas) { - $entity->id = (int)$id; - foreach ($object_datas as $key => $value) { - $entity->{$key} = $value; - } - } - } - } + if ($object_datas_lang = Db::getInstance()->executeS($sql)) { + foreach ($object_datas_lang as $row) { + foreach ($row as $key => $value) { + if ($key != $entity_defs['primary'] && array_key_exists($key, $entity)) { + if (!isset($object_datas[$key]) || !is_array($object_datas[$key])) { + $object_datas[$key] = array(); + } + $object_datas[$key][$row['id_lang']] = $value; + } + } + } + } + } + $entity->id = (int)$id; + foreach ($object_datas as $key => $value) { + if (array_key_exists($key, $entity)) { + $entity->{$key} = $value; + } else { + unset($object_datas[$key]); + } + } + if ($should_cache_objects) { + Cache::store($cache_id, $object_datas); + } + } + } else { + $object_datas = Cache::retrieve($cache_id); + if ($object_datas) { + $entity->id = (int)$id; + foreach ($object_datas as $key => $value) { + $entity->{$key} = $value; + } + } + } + } } diff --git a/Adapter/Adapter_Exception.php b/Adapter/Adapter_Exception.php index e8108f42..3472d628 100644 --- a/Adapter/Adapter_Exception.php +++ b/Adapter/Adapter_Exception.php @@ -26,4 +26,4 @@ class Adapter_Exception extends Core_Foundation_Exception_Exception { -} \ No newline at end of file +} diff --git a/Adapter/Adapter_HookManager.php b/Adapter/Adapter_HookManager.php new file mode 100644 index 00000000..1817d55d --- /dev/null +++ b/Adapter/Adapter_HookManager.php @@ -0,0 +1,54 @@ + + * @copyright 2007-2015 PrestaShop SA + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +class Adapter_HookManager +{ + /** + * Execute modules for specified hook + * + * @param string $hook_name Hook Name + * @param array $hook_args Parameters for the functions + * @param int $id_module Execute hook for this module only + * @param bool $array_return If specified, module output will be set by name in an array + * @param bool $check_exceptions Check permission exceptions + * @param bool $use_push Force change to be refreshed on Dashboard widgets + * @param int $id_shop If specified, hook will be execute the shop with this ID + * + * @throws PrestaShopException + * + * @return string/array modules output + */ + public function exec($hook_name, + $hook_args = array(), + $id_module = null, + $array_return = false, + $check_exceptions = true, + $use_push = false, + $id_shop = null) + { + return Hook::exec($hook_name, $hook_args, $id_module, $array_return, $check_exceptions, $use_push, $id_shop); + } +} diff --git a/Adapter/Adapter_PackItemsManager.php b/Adapter/Adapter_PackItemsManager.php new file mode 100644 index 00000000..e535d84d --- /dev/null +++ b/Adapter/Adapter_PackItemsManager.php @@ -0,0 +1,87 @@ + + * @copyright 2007-2015 PrestaShop SA + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +class Adapter_PackItemsManager +{ + /** + * Get the Products contained in the given Pack. + * + * @param Pack $pack + * @param integer $id_lang Optional + * @return Array[Product] The products contained in this Pack, with special dynamic attributes [pack_quantity, id_pack_product_attribute] + */ + public function getPackItems($pack, $id_lang = false) + { + if ($id_lang === false) { + $configuration = Adapter_ServiceLocator::get('Core_Business_ConfigurationInterface'); + $id_lang = (int)$configuration->get('PS_LANG_DEFAULT'); + } + return Pack::getItems($pack->id, $id_lang); + } + + /** + * Get all Packs that contains the given item in the corresponding declination. + * + * @param Product $item + * @param integer $item_attribute_id + * @param integer $id_lang Optional + * @return Array[Pack] The packs that contains the given item, with special dynamic attribute [pack_item_quantity] + */ + public function getPacksContainingItem($item, $item_attribute_id, $id_lang = false) + { + if ($id_lang === false) { + $configuration = Adapter_ServiceLocator::get('Core_Business_ConfigurationInterface'); + $id_lang = (int)$configuration->get('PS_LANG_DEFAULT'); + } + return Pack::getPacksContainingItem($item->id, $item_attribute_id, $id_lang); + } + + /** + * Is this product a pack? + * + * @param Product $product + * @return boolean + */ + public function isPack($product) + { + return Pack::isPack($product->id); + } + + /** + * Is this product in a pack? + * If $id_product_attribute specified, then will restrict search on the given combination, + * else this method will match a product if at least one of all its combination is in a pack. + * + * @param Product $product + * @param integer $id_product_attribute Optional combination of the product + * @return boolean + */ + public function isPacked($product, $id_product_attribute = false) + { + return Pack::isPacked($product->id, $id_product_attribute); + } + +} diff --git a/Adapter/Adapter_ProductPriceCalculator.php b/Adapter/Adapter_ProductPriceCalculator.php index 53676297..e87335f4 100644 --- a/Adapter/Adapter_ProductPriceCalculator.php +++ b/Adapter/Adapter_ProductPriceCalculator.php @@ -32,20 +32,19 @@ class Adapter_ProductPriceCalculator $id_product_attribute = null, $decimals = 6, $divisor = null, - $only_reduc = false, + $only_reduc = false, $usereduc = true, $quantity = 1, $force_associated_tax = false, $id_customer = null, $id_cart = null, - $id_address = null, + $id_address = null, &$specific_price_output = null, $with_ecotax = true, $use_group_reduction = true, Context $context = null, - $use_customer_price = true - ) - { + $use_customer_price = true + ) { return Product::getPriceStatic( $id_product, $usetax, diff --git a/Adapter/Adapter_ServiceLocator.php b/Adapter/Adapter_ServiceLocator.php index ba3ced50..2807eaca 100644 --- a/Adapter/Adapter_ServiceLocator.php +++ b/Adapter/Adapter_ServiceLocator.php @@ -26,29 +26,29 @@ class Adapter_ServiceLocator { - /** - * Set a service container Instance - * @var Core_Foundation_IoC_Container - */ - private static $service_container; + /** + * Set a service container Instance + * @var Core_Foundation_IoC_Container + */ + private static $service_container; - public static function setServiceContainerInstance(Core_Foundation_IoC_Container $container) - { - self::$service_container = $container; - } + public static function setServiceContainerInstance(Core_Foundation_IoC_Container $container) + { + self::$service_container = $container; + } - /** - * Get a service depending on its given $serviceName - * @param $serviceName - * @return mixed|object - * @throws Adapter_Exception - */ - public static function get($serviceName) - { - if (empty(self::$service_container) || is_null(self::$service_container)) { - throw new Adapter_Exception('Service container is not set.'); - } + /** + * Get a service depending on its given $serviceName + * @param $serviceName + * @return mixed|object + * @throws Adapter_Exception + */ + public static function get($serviceName) + { + if (empty(self::$service_container) || is_null(self::$service_container)) { + throw new Adapter_Exception('Service container is not set.'); + } - return self::$service_container->make($serviceName); - } + return self::$service_container->make($serviceName); + } } diff --git a/Adapter/Adapter_StockManager.php b/Adapter/Adapter_StockManager.php new file mode 100644 index 00000000..8fb21e33 --- /dev/null +++ b/Adapter/Adapter_StockManager.php @@ -0,0 +1,34 @@ + + * @copyright 2007-2015 PrestaShop SA + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +class Adapter_StockManager +{ + + public function getStockAvailableByProduct($product, $id_product_attribute = null, $id_shop = null) + { + return new StockAvailable(StockAvailable::getStockAvailableIdByProductId($product->id, $id_product_attribute, $id_shop)); + } +} diff --git a/Core/Business/CMS/Core_Business_CMS_CMSRepository.php b/Core/Business/CMS/Core_Business_CMS_CMSRepository.php index 28bbec31..a7ea3a88 100644 --- a/Core/Business/CMS/Core_Business_CMS_CMSRepository.php +++ b/Core/Business/CMS/Core_Business_CMS_CMSRepository.php @@ -26,24 +26,24 @@ class Core_Business_CMS_CMSRepository extends Core_Foundation_Database_EntityRepository { - /** - * Return CMSRepository lang associative table name - * @return string - */ - private function getLanguageTableNameWithPrefix() - { - return $this->getTableNameWithPrefix() . '_lang'; - } + /** + * Return CMSRepository lang associative table name + * @return string + */ + private function getLanguageTableNameWithPrefix() + { + return $this->getTableNameWithPrefix() . '_lang'; + } - /** - * Return all CMSRepositories depending on $id_lang/$id_shop tuple - * @param $id_lang - * @param $id_shop - * @return array|null - */ - public function i10nFindAll($id_lang, $id_shop) - { - $sql = ' + /** + * Return all CMSRepositories depending on $id_lang/$id_shop tuple + * @param $id_lang + * @param $id_shop + * @return array|null + */ + public function i10nFindAll($id_lang, $id_shop) + { + $sql = ' SELECT * FROM `'.$this->getTableNameWithPrefix().'` c JOIN `'.$this->getPrefix().'cms_lang` cl ON c.`id_cms`= cl.`id_cms` @@ -52,20 +52,20 @@ class Core_Business_CMS_CMSRepository extends Core_Foundation_Database_EntityRep '; - return $this->hydrateMany($this->db->select($sql)); - } + return $this->hydrateMany($this->db->select($sql)); + } - /** - * Return all CMSRepositories depending on $id_lang/$id_shop tuple - * @param $id_cms - * @param $id_lang - * @param $id_shop - * @return CMS|null - * @throws Core_Foundation_Database_Exception - */ - public function i10nFindOneById($id_cms, $id_lang, $id_shop) - { - $sql = ' + /** + * Return all CMSRepositories depending on $id_lang/$id_shop tuple + * @param $id_cms + * @param $id_lang + * @param $id_shop + * @return CMS|null + * @throws Core_Foundation_Database_Exception + */ + public function i10nFindOneById($id_cms, $id_lang, $id_shop) + { + $sql = ' SELECT * FROM `'.$this->getTableNameWithPrefix().'` c JOIN `'.$this->getPrefix().'cms_lang` cl ON c.`id_cms`= cl.`id_cms` @@ -75,6 +75,6 @@ class Core_Business_CMS_CMSRepository extends Core_Foundation_Database_EntityRep LIMIT 0 , 1 '; - return $this->hydrateOne($this->db->select($sql)); - } + return $this->hydrateOne($this->db->select($sql)); + } } diff --git a/Core/Business/CMS/Core_Business_CMS_CMSRoleRepository.php b/Core/Business/CMS/Core_Business_CMS_CMSRoleRepository.php index 454f59e7..0d5e4bb8 100644 --- a/Core/Business/CMS/Core_Business_CMS_CMSRoleRepository.php +++ b/Core/Business/CMS/Core_Business_CMS_CMSRoleRepository.php @@ -26,19 +26,17 @@ class Core_Business_CMS_CMSRoleRepository extends Core_Foundation_Database_EntityRepository { - /** - * Return all CMSRoles which are already associated - * @return array|null - */ - public function getCMSRolesAssociated() - { - $sql = ' + /** + * Return all CMSRoles which are already associated + * @return array|null + */ + public function getCMSRolesAssociated() + { + $sql = ' SELECT * FROM `'.$this->getTableNameWithPrefix().'` WHERE `id_cms` != 0'; - return $this->hydrateMany($this->db->select($sql)); - } - - -} \ No newline at end of file + return $this->hydrateMany($this->db->select($sql)); + } +} diff --git a/Core/Business/Core_Business_ContainerBuilder.php b/Core/Business/Core_Business_ContainerBuilder.php index 9d624598..86e0f132 100644 --- a/Core/Business/Core_Business_ContainerBuilder.php +++ b/Core/Business/Core_Business_ContainerBuilder.php @@ -26,12 +26,12 @@ class Core_Business_ContainerBuilder { - /** - * Construct PrestaShop Core Service container - * @return Core_Foundation_IoC_Container - * @throws Core_Foundation_IoC_Exception - */ - public function build() + /** + * Construct PrestaShop Core Service container + * @return Core_Foundation_IoC_Container + * @throws Core_Foundation_IoC_Exception + */ + public function build() { $container = new Core_Foundation_IoC_Container; diff --git a/Core/Business/Email/Core_Business_Email_EmailLister.php b/Core/Business/Email/Core_Business_Email_EmailLister.php index 7aabfcff..7c5911e7 100644 --- a/Core/Business/Email/Core_Business_Email_EmailLister.php +++ b/Core/Business/Email/Core_Business_Email_EmailLister.php @@ -26,67 +26,66 @@ class Core_Business_Email_EmailLister { - private $filesystem; + private $filesystem; - public function __construct(Core_Foundation_FileSystem_FileSystem $fs) - { - // Register dependencies - $this->filesystem = $fs; - } + public function __construct(Core_Foundation_FileSystem_FileSystem $fs) + { + // Register dependencies + $this->filesystem = $fs; + } - /** - * Return the list of available mails - * @param null $lang - * @param null $dir - * @return array|null - */ - public function getAvailableMails($dir) - { - if (!is_dir($dir)) { - return null; - } + /** + * Return the list of available mails + * @param null $lang + * @param null $dir + * @return array|null + */ + public function getAvailableMails($dir) + { + if (!is_dir($dir)) { + return null; + } - $mail_directory = $this->filesystem->listEntriesRecursively($dir); - $mail_list = array(); + $mail_directory = $this->filesystem->listEntriesRecursively($dir); + $mail_list = array(); - // Remove unwanted .html / .txt / .tpl / .php / . / .. - foreach ($mail_directory as $mail) { + // Remove unwanted .html / .txt / .tpl / .php / . / .. + foreach ($mail_directory as $mail) { + if (strpos($mail->getFilename(), '.') !== false) { + $tmp = explode('.', $mail->getFilename()); - if (strpos($mail->getFilename(), '.') !== false) { - $tmp = explode('.', $mail->getFilename()); + // Check for filename existence (left part) and if extension is html (right part) + if (($tmp === false || !isset($tmp[0])) || (isset($tmp[1]) && $tmp[1] !== 'html')) { + continue; + } - // Check for filename existence (left part) and if extension is html (right part) - if ( ($tmp === false || !isset($tmp[0])) || (isset($tmp[1]) && $tmp[1] !== 'html')) { - continue; - } + $mail_name_no_ext = $tmp[0]; + if (!in_array($mail_name_no_ext, $mail_list)) { + $mail_list[] = $mail_name_no_ext; + } + } + } - $mail_name_no_ext = $tmp[0]; - if (!in_array($mail_name_no_ext, $mail_list)) { - $mail_list[] = $mail_name_no_ext; - } - } - } - - return $mail_list; - } + return $mail_list; + } - /** - * Give in input getAvailableMails(), will output a human readable and proper string name - * @return string - */ - public function getCleanedMailName($mail_name) - { - if (strpos($mail_name, '.') !== false) { - $tmp = explode('.', $mail_name); + /** + * Give in input getAvailableMails(), will output a human readable and proper string name + * @return string + */ + public function getCleanedMailName($mail_name) + { + if (strpos($mail_name, '.') !== false) { + $tmp = explode('.', $mail_name); - if ($tmp === false || !isset($tmp[0])) { - return $mail_name; - } + if ($tmp === false || !isset($tmp[0])) { + return $mail_name; + } - $mail_name = $tmp[0]; - } + $mail_name = $tmp[0]; + } - return ucfirst(str_replace(array('_', '-'), ' ', $mail_name)); - } -} \ No newline at end of file + return ucfirst(str_replace(array('_', '-'), ' ', $mail_name)); + } +} diff --git a/Core/Business/Payment/Core_Business_Payment_PaymentOption.php b/Core/Business/Payment/Core_Business_Payment_PaymentOption.php index 5c75f3ad..5f7b564a 100644 --- a/Core/Business/Payment/Core_Business_Payment_PaymentOption.php +++ b/Core/Business/Payment/Core_Business_Payment_PaymentOption.php @@ -26,189 +26,189 @@ class Core_Business_Payment_PaymentOption { - private $callToActionText; - private $logo; - private $action; - private $method; - private $inputs; - private $form; - private $moduleName; + private $callToActionText; + private $logo; + private $action; + private $method; + private $inputs; + private $form; + private $moduleName; - /** - * Return Call to Action Text - * @return string - */ - public function getCallToActionText() - { - return $this->callToActionText; - } + /** + * Return Call to Action Text + * @return string + */ + public function getCallToActionText() + { + return $this->callToActionText; + } - /** - * Set Call To Action Text - * @param $callToActionText - * @return $this - */ - public function setCallToActionText($callToActionText) - { - $this->callToActionText = $callToActionText; - return $this; - } + /** + * Set Call To Action Text + * @param $callToActionText + * @return $this + */ + public function setCallToActionText($callToActionText) + { + $this->callToActionText = $callToActionText; + return $this; + } - /** - * Return logo path - * @return string - */ - public function getLogo() - { - return $this->logo; - } + /** + * Return logo path + * @return string + */ + public function getLogo() + { + return $this->logo; + } - /** - * Set logo path - * @param $logo - * @return $this - */ - public function setLogo($logo) - { - $this->logo = $logo; - return $this; - } + /** + * Set logo path + * @param $logo + * @return $this + */ + public function setLogo($logo) + { + $this->logo = $logo; + return $this; + } - /** - * Return action to perform (POST/GET) - * @return string - */ - public function getAction() - { - return $this->action; - } + /** + * Return action to perform (POST/GET) + * @return string + */ + public function getAction() + { + return $this->action; + } - /** - * Set action to be performed by this option - * @param $action - * @return $this - */ - public function setAction($action) - { - $this->action = $action; - return $this; - } + /** + * Set action to be performed by this option + * @param $action + * @return $this + */ + public function setAction($action) + { + $this->action = $action; + return $this; + } - public function getMethod() - { - return $this->method; - } + public function getMethod() + { + return $this->method; + } - public function setMethod($method) - { - $this->method = $method; - return $this; - } + public function setMethod($method) + { + $this->method = $method; + return $this; + } - /** - * Return inputs contained in this payment option - * @return mixed - */ - public function getInputs() - { - return $this->inputs; - } + /** + * Return inputs contained in this payment option + * @return mixed + */ + public function getInputs() + { + return $this->inputs; + } - /** - * Set inputs for this payment option - * @param $inputs - * @return $this - */ - public function setInputs($inputs) - { - $this->inputs = $inputs; - return $this; - } + /** + * Set inputs for this payment option + * @param $inputs + * @return $this + */ + public function setInputs($inputs) + { + $this->inputs = $inputs; + return $this; + } - /** - * Get payment option form - * @return mixed - */ - public function getForm() - { - return $this->form; - } + /** + * Get payment option form + * @return mixed + */ + public function getForm() + { + return $this->form; + } - /** - * Set payment option form - * @param $form - * @return $this - */ - public function setForm($form) - { - $this->form = $form; - return $this; - } + /** + * Set payment option form + * @param $form + * @return $this + */ + public function setForm($form) + { + $this->form = $form; + return $this; + } - /** - * Get related module name to this payment option - * @return string - */ - public function getModuleName() - { - return $this->moduleName; - } + /** + * Get related module name to this payment option + * @return string + */ + public function getModuleName() + { + return $this->moduleName; + } - /** - * Set related module name to this payment option - * @param $moduleName - * @return $this - */ - public function setModuleName($moduleName) - { - $this->moduleName = $moduleName; - return $this; - } + /** + * Set related module name to this payment option + * @param $moduleName + * @return $this + */ + public function setModuleName($moduleName) + { + $this->moduleName = $moduleName; + return $this; + } - /** - * Legacy options were specified this way: - * - either an array with a top level property 'cta_text' - * and then the other properties - * - or a numerically indexed array or arrays as described above - * Since this was a mess, this method is provided to convert them. - * It takes as input a legacy option (in either form) and always - * returns an array of instances of Core_Business_Payment_PaymentOption - */ - public static function convertLegacyOption(array $legacyOption) - { - if (!$legacyOption) - return; + /** + * Legacy options were specified this way: + * - either an array with a top level property 'cta_text' + * and then the other properties + * - or a numerically indexed array or arrays as described above + * Since this was a mess, this method is provided to convert them. + * It takes as input a legacy option (in either form) and always + * returns an array of instances of Core_Business_Payment_PaymentOption + */ + public static function convertLegacyOption(array $legacyOption) + { + if (!$legacyOption) { + return; + } - if (array_key_exists('cta_text', $legacyOption)) { - $legacyOption = array($legacyOption); - } + if (array_key_exists('cta_text', $legacyOption)) { + $legacyOption = array($legacyOption); + } - $newOptions = array(); + $newOptions = array(); - $defaults = array( - 'action' => null, - 'form' => null, - 'method' => null, - 'inputs' => array(), - 'logo' => null - ); + $defaults = array( + 'action' => null, + 'form' => null, + 'method' => null, + 'inputs' => array(), + 'logo' => null + ); - foreach ($legacyOption as $option) { + foreach ($legacyOption as $option) { + $option = array_merge($defaults, $option); - $option = array_merge($defaults, $option); + $newOption = new Core_Business_Payment_PaymentOption(); + $newOption->setCallToActionText($option['cta_text']) + ->setAction($option['action']) + ->setForm($option['form']) + ->setInputs($option['inputs']) + ->setLogo($option['logo']) + ->setMethod($option['method']); - $newOption = new Core_Business_Payment_PaymentOption(); - $newOption->setCallToActionText($option['cta_text']) - ->setAction($option['action']) - ->setForm($option['form']) - ->setInputs($option['inputs']) - ->setLogo($option['logo']) - ->setMethod($option['method']); + $newOptions[] = $newOption; + } - $newOptions[] = $newOption; - } - - return $newOptions; - } + return $newOptions; + } } diff --git a/Core/Business/Stock/Core_Business_Stock_StockManager.php b/Core/Business/Stock/Core_Business_Stock_StockManager.php new file mode 100644 index 00000000..3e17f046 --- /dev/null +++ b/Core/Business/Stock/Core_Business_Stock_StockManager.php @@ -0,0 +1,150 @@ + + * @copyright 2007-2015 PrestaShop SA + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +class Core_Business_Stock_StockManager +{ + /** + * This will update a Pack quantity and will decrease the quantity of containing Products if needed. + * + * @param Product $product A product pack object to update its quantity + * @param StockAvailable $stock_available the stock of the product to fix with correct quantity + * @param integer $delta_quantity The movement of the stock (negative for a decrease) + * @param integer|null $id_shop Opional shop ID + */ + public function updatePackQuantity($product, $stock_available, $delta_quantity, $id_shop = null) + { + $configuration = Adapter_ServiceLocator::get('Core_Business_ConfigurationInterface'); + if ($product->pack_stock_type == 1 || $product->pack_stock_type == 2 || ($product->pack_stock_type == 3 && $configuration->get('PS_PACK_STOCK_TYPE') > 0)) { + $packItemsManager = Adapter_ServiceLocator::get('Adapter_PackItemsManager'); + $products_pack = $packItemsManager->getPackItems($product); + $stockAvailable = new Core_Business_Stock_StockManager(); + $stockManager = Adapter_ServiceLocator::get('Adapter_StockManager'); + $cacheManager = Adapter_ServiceLocator::get('Adapter_CacheManager'); + foreach ($products_pack as $product_pack) { + $productStockAvailable = $stockManager->getStockAvailableByProduct($product_pack, $product_pack->id_pack_product_attribute, $id_shop); + $productStockAvailable->quantity = $productStockAvailable->quantity + ($delta_quantity * $product_pack->pack_quantity); + $productStockAvailable->update(); + + $cacheManager->clean('StockAvailable::getQuantityAvailableByProduct_'.(int)$product_pack->id.'*'); + } + } + + $stock_available->quantity = $stock_available->quantity + $delta_quantity; + + if ($product->pack_stock_type == 0 || $product->pack_stock_type == 2 || + ($product->pack_stock_type == 3 && ($configuration->get('PS_PACK_STOCK_TYPE') == 0 || $configuration->get('PS_PACK_STOCK_TYPE') == 2))) { + $stock_available->update(); + } + } + + /** + * This will decrease (if needed) Packs containing this product + * (with the right declinaison) if there is not enough product in stocks. + * + * @param Product $product A product object to update its quantity + * @param integer $id_product_attribute The product attribute to update + * @param StockAvailable $stock_available the stock of the product to fix with correct quantity + * @param integer|null $id_shop Opional shop ID + */ + public function updatePacksQuantityContainingProduct($product, $id_product_attribute, $stock_available, $id_shop = null) + { + $configuration = Adapter_ServiceLocator::get('Core_Business_ConfigurationInterface'); + $packItemsManager = Adapter_ServiceLocator::get('Adapter_PackItemsManager'); + $stockManager = Adapter_ServiceLocator::get('Adapter_StockManager'); + $cacheManager = Adapter_ServiceLocator::get('Adapter_CacheManager'); + $packs = $packItemsManager->getPacksContainingItem($product, $id_product_attribute); + foreach($packs as $pack) { + // Decrease stocks of the pack only if pack is in linked stock mode (option called 'Decrement both') + if (!((int)$pack->pack_stock_type == 2) && + !((int)$pack->pack_stock_type == 3 && $configuration->get('PS_PACK_STOCK_TYPE') == 2) + ) { + continue; + } + + // Decrease stocks of the pack only if there is not enough items to constituate the actual pack stocks. + + // How many packs can be constituated with the remaining product stocks + $quantity_by_pack = $pack->pack_item_quantity; + $max_pack_quantity = max(array(0, floor($stock_available->quantity / $quantity_by_pack))); + + $stock_available_pack = $stockManager->getStockAvailableByProduct($pack, null, $id_shop); + if ($stock_available_pack->quantity > $max_pack_quantity) { + $stock_available_pack->quantity = $max_pack_quantity; + $stock_available_pack->update(); + + $cacheManager->clean('StockAvailable::getQuantityAvailableByProduct_'.(int)$pack->id.'*'); + } + } + } + + /** + * Will update Product available stock int he given declinaison. If product is a Pack, could decrease the sub products. + * If Product is contained in a Pack, Pack could be decreased or not (only if sub product stocks become not sufficient). + * + * @param Product $product The product to update its stockAvailable + * @param integer $id_product_attribute The declinaison to update (null if not) + * @param integer $delta_quantity The quantity change (positive or negative) + * @param integer|null $id_shop Optional + */ + public function updateQuantity($product, $id_product_attribute, $delta_quantity, $id_shop = null) + { + $stockManager = Adapter_ServiceLocator::get('Adapter_StockManager'); + $stockAvailable = $stockManager->getStockAvailableByProduct($product, $id_product_attribute, $id_shop); + $packItemsManager = Adapter_ServiceLocator::get('Adapter_PackItemsManager'); + $cacheManager = Adapter_ServiceLocator::get('Adapter_CacheManager'); + $hookManager = Adapter_ServiceLocator::get('Adapter_HookManager'); + + // Update quantity of the pack products + if ($packItemsManager->isPack($product)) { + // The product is a pack + $this->updatePackQuantity($product, $stockAvailable, $delta_quantity, $id_shop); + } else { + // The product is not a pack + $stockAvailable->quantity = $stockAvailable->quantity + $delta_quantity; + $stockAvailable->update(); + + // Decrease case only: the stock of linked packs should be decreased too. + if ($delta_quantity < 0) { + // The product is not a pack, but the product combination is part of a pack (use of isPacked, not isPack) + if ($packItemsManager->isPacked($product, $id_product_attribute)) { + $this->updatePacksQuantityContainingProduct($product, $id_product_attribute, $stockAvailable, $id_shop); + } + } + } + + $cacheManager->clean('StockAvailable::getQuantityAvailableByProduct_'.(int)$product->id.'*'); + + $hookManager->exec('actionUpdateQuantity', + array( + 'id_product' => $product->id, + 'id_product_attribute' => $id_product_attribute, + 'quantity' => $stockAvailable->quantity + ) + ); + } + + +} diff --git a/Core/Foundation/Database/Core_Foundation_Database_EntityInterface.php b/Core/Foundation/Database/Core_Foundation_Database_EntityInterface.php index b489c421..aab6cf87 100644 --- a/Core/Foundation/Database/Core_Foundation_Database_EntityInterface.php +++ b/Core/Foundation/Database/Core_Foundation_Database_EntityInterface.php @@ -26,17 +26,17 @@ interface Core_Foundation_Database_EntityInterface { - /** - * Returns the name of the repository class for this entity. - * If unspecified, a generic repository will be used for the entity. - * - * @return string or falsey value - */ - public static function getRepositoryClassName(); + /** + * Returns the name of the repository class for this entity. + * If unspecified, a generic repository will be used for the entity. + * + * @return string or falsey value + */ + public static function getRepositoryClassName(); - public function save(); + public function save(); - public function delete(); + public function delete(); - public function hydrate(array $keyValueData); + public function hydrate(array $keyValueData); } diff --git a/Core/Foundation/Database/Core_Foundation_Database_EntityManager.php b/Core/Foundation/Database/Core_Foundation_Database_EntityManager.php index 44d7b767..b63151e6 100644 --- a/Core/Foundation/Database/Core_Foundation_Database_EntityManager.php +++ b/Core/Foundation/Database/Core_Foundation_Database_EntityManager.php @@ -26,90 +26,89 @@ class Core_Foundation_Database_EntityManager { - private $db; - private $configuration; + private $db; + private $configuration; - private $entityMetaData = array(); + private $entityMetaData = array(); - public function __construct( + public function __construct( Core_Foundation_Database_DatabaseInterface $db, Core_Business_ConfigurationInterface $configuration - ) - { - $this->db = $db; - $this->configuration = $configuration; + ) { + $this->db = $db; + $this->configuration = $configuration; } - /** - * Return current database object used - * @return Core_Foundation_Database_DatabaseInterface - */ - public function getDatabase() - { - return $this->db; - } + /** + * Return current database object used + * @return Core_Foundation_Database_DatabaseInterface + */ + public function getDatabase() + { + return $this->db; + } - /** - * Return current repository used - * @param $className - * @return mixed - */ - public function getRepository($className) - { + /** + * Return current repository used + * @param $className + * @return mixed + */ + public function getRepository($className) + { if (is_callable(array($className, 'getRepositoryClassName'))) { $repositoryClass = call_user_func(array($className, 'getRepositoryClassName')); } else { $repositoryClass = null; } - if (!$repositoryClass) { - $repositoryClass = 'Core_Foundation_Database_EntityRepository'; - } + if (!$repositoryClass) { + $repositoryClass = 'Core_Foundation_Database_EntityRepository'; + } $repository = new $repositoryClass( - $this, - $this->configuration->get('_DB_PREFIX_'), - $this->getEntityMetaData($className) - ); + $this, + $this->configuration->get('_DB_PREFIX_'), + $this->getEntityMetaData($className) + ); - return $repository; - } + return $repository; + } - /** - * Return entity's meta data - * @param $className - * @return mixed - * @throws Adapter_Exception - */ - public function getEntityMetaData($className) - { - if (!array_key_exists($className, $this->entityMetaData)) { - $metaDataRetriever = new Adapter_EntityMetaDataRetriever; - $this->entityMetaData[$className] = $metaDataRetriever->getEntityMetaData($className); - } + /** + * Return entity's meta data + * @param $className + * @return mixed + * @throws Adapter_Exception + */ + public function getEntityMetaData($className) + { + if (!array_key_exists($className, $this->entityMetaData)) { + $metaDataRetriever = new Adapter_EntityMetaDataRetriever; + $this->entityMetaData[$className] = $metaDataRetriever->getEntityMetaData($className); + } - return $this->entityMetaData[$className]; - } + return $this->entityMetaData[$className]; + } - /** - * Flush entity to DB - * @param Core_Foundation_Database_EntityInterface $entity - * @return $this - */ - public function save(Core_Foundation_Database_EntityInterface $entity) - { - $entity->save(); - return $this; - } + /** + * Flush entity to DB + * @param Core_Foundation_Database_EntityInterface $entity + * @return $this + */ + public function save(Core_Foundation_Database_EntityInterface $entity) + { + $entity->save(); + return $this; + } - /** - * DElete entity from DB - * @param Core_Foundation_Database_EntityInterface $entity - * @return $this - */ - public function delete(Core_Foundation_Database_EntityInterface $entity) - { - $entity->delete(); - return $this; - } + /** + * DElete entity from DB + * @param Core_Foundation_Database_EntityInterface $entity + * @return $this + */ + public function delete(Core_Foundation_Database_EntityInterface $entity) + { + $entity->delete(); + return $this; + } } diff --git a/Core/Foundation/Database/Core_Foundation_Database_EntityRepository.php b/Core/Foundation/Database/Core_Foundation_Database_EntityRepository.php index 22b6b7d5..30ab5d5e 100644 --- a/Core/Foundation/Database/Core_Foundation_Database_EntityRepository.php +++ b/Core/Foundation/Database/Core_Foundation_Database_EntityRepository.php @@ -26,99 +26,98 @@ class Core_Foundation_Database_EntityRepository { - protected $entityManager; - protected $db; - protected $tablesPrefix; - protected $entityMetaData; - protected $queryBuilder; + protected $entityManager; + protected $db; + protected $tablesPrefix; + protected $entityMetaData; + protected $queryBuilder; - public function __construct( - Core_Foundation_Database_EntityManager $entityManager, - $tablesPrefix, - Core_Foundation_Database_EntityMetaData $entityMetaData - ) - { - $this->entityManager = $entityManager; - $this->db = $this->entityManager->getDatabase(); - $this->tablesPrefix = $tablesPrefix; - $this->entityMetaData = $entityMetaData; - $this->queryBuilder = new Core_Foundation_Database_EntityManager_QueryBuilder($this->db); - } + public function __construct( + Core_Foundation_Database_EntityManager $entityManager, + $tablesPrefix, + Core_Foundation_Database_EntityMetaData $entityMetaData + ) { + $this->entityManager = $entityManager; + $this->db = $this->entityManager->getDatabase(); + $this->tablesPrefix = $tablesPrefix; + $this->entityMetaData = $entityMetaData; + $this->queryBuilder = new Core_Foundation_Database_EntityManager_QueryBuilder($this->db); + } - public function __call($method, $arguments) - { - if (0 === strpos($method, 'findOneBy')) { - $one = true; - $by = substr($method, 9); - } else if (0 === strpos($method, 'findBy')) { - $one = false; - $by = substr($method, 6); - } else { - throw new Core_Foundation_Database_Exception(sprintf('Undefind method %s.', $method)); - } + public function __call($method, $arguments) + { + if (0 === strpos($method, 'findOneBy')) { + $one = true; + $by = substr($method, 9); + } elseif (0 === strpos($method, 'findBy')) { + $one = false; + $by = substr($method, 6); + } else { + throw new Core_Foundation_Database_Exception(sprintf('Undefind method %s.', $method)); + } - if (count($arguments) !== 1) { - throw new Core_Foundation_Database_Exception(sprintf('Method %s takes exactly one argument.', $method)); - } + if (count($arguments) !== 1) { + throw new Core_Foundation_Database_Exception(sprintf('Method %s takes exactly one argument.', $method)); + } - if (!$by) { - $where = $arguments[0]; - } else { - $where = array(); - $by = $this->convertToDbFieldName($by); - $where[$by] = $arguments[0]; - } + if (!$by) { + $where = $arguments[0]; + } else { + $where = array(); + $by = $this->convertToDbFieldName($by); + $where[$by] = $arguments[0]; + } - return $this->doFind($one, $where); - } + return $this->doFind($one, $where); + } - /** - * Convert a camelCase field name to a snakeCase one - * e.g.: findAllByIdCMS => id_cms - * @param $camel_case_field_name - * @return string - */ - private function convertToDbFieldName($camel_case_field_name) - { - return strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $camel_case_field_name)); - } + /** + * Convert a camelCase field name to a snakeCase one + * e.g.: findAllByIdCMS => id_cms + * @param $camel_case_field_name + * @return string + */ + private function convertToDbFieldName($camel_case_field_name) + { + return strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $camel_case_field_name)); + } - /** - * Return ID field name - * @return mixed - * @throws Core_Foundation_Database_Exception - */ - protected function getIdFieldName() - { - $primary = $this->entityMetaData->getPrimaryKeyFieldnames(); + /** + * Return ID field name + * @return mixed + * @throws Core_Foundation_Database_Exception + */ + protected function getIdFieldName() + { + $primary = $this->entityMetaData->getPrimaryKeyFieldnames(); - if (count($primary) === 0) { - throw new Core_Foundation_Database_Exception( - sprintf( - 'No primary key defined in entity `%s`.', - $this->entityMetaData->getEntityClassName() - ) - ); - } else if (count($primary) > 1) { - throw new Core_Foundation_Database_Exception( - sprintf( - 'Entity `%s` has a composite primary key, which is not supported by entity repositories.', - $this->entityMetaData->getEntityClassName() - ) - ); - } + if (count($primary) === 0) { + throw new Core_Foundation_Database_Exception( + sprintf( + 'No primary key defined in entity `%s`.', + $this->entityMetaData->getEntityClassName() + ) + ); + } elseif (count($primary) > 1) { + throw new Core_Foundation_Database_Exception( + sprintf( + 'Entity `%s` has a composite primary key, which is not supported by entity repositories.', + $this->entityMetaData->getEntityClassName() + ) + ); + } - return $primary[0]; - } + return $primary[0]; + } - /** - * Returns escaped+prefixed current table name - * @return mixed - */ - protected function getTableNameWithPrefix() - { - return $this->db->escape($this->tablesPrefix . $this->entityMetaData->getTableName()); - } + /** + * Returns escaped+prefixed current table name + * @return mixed + */ + protected function getTableNameWithPrefix() + { + return $this->db->escape($this->tablesPrefix . $this->entityMetaData->getTableName()); + } /** * Returns escaped DB table prefix @@ -129,93 +128,93 @@ class Core_Foundation_Database_EntityRepository return $this->db->escape($this->tablesPrefix); } - /** - * Return a new empty Entity depending on current Repository selected - * @return mixed - */ - public function getNewEntity() - { - $entityClassName = $this->entityMetaData->getEntityClassName(); - return new $entityClassName; - } + /** + * Return a new empty Entity depending on current Repository selected + * @return mixed + */ + public function getNewEntity() + { + $entityClassName = $this->entityMetaData->getEntityClassName(); + return new $entityClassName; + } - /** - * This function takes an array of database rows as input - * and returns an hydrated entity if there is one row only. - * - * Null is returned when there are no rows, and an exception is thrown - * if there are too many rows. - * - * @param array $rows Database rows - */ - protected function hydrateOne(array $rows) - { - if (count($rows) === 0) { - return null; - } else if (count($rows) > 1) { - throw new Core_Foundation_Database_Exception('Too many rows returned.'); - } else { - $data = $rows[0]; - $entity = $this-> getNewEntity(); - $entity->hydrate($data); - return $entity; - } - } + /** + * This function takes an array of database rows as input + * and returns an hydrated entity if there is one row only. + * + * Null is returned when there are no rows, and an exception is thrown + * if there are too many rows. + * + * @param array $rows Database rows + */ + protected function hydrateOne(array $rows) + { + if (count($rows) === 0) { + return null; + } elseif (count($rows) > 1) { + throw new Core_Foundation_Database_Exception('Too many rows returned.'); + } else { + $data = $rows[0]; + $entity = $this-> getNewEntity(); + $entity->hydrate($data); + return $entity; + } + } - protected function hydrateMany(array $rows) - { - $entities = array(); - foreach ($rows as $row) { - $entity = $this->getNewEntity(); - $entity->hydrate($row); - $entities[] = $entity; - } - return $entities; - } + protected function hydrateMany(array $rows) + { + $entities = array(); + foreach ($rows as $row) { + $entity = $this->getNewEntity(); + $entity->hydrate($row); + $entities[] = $entity; + } + return $entities; + } - /** - * Constructs and performs 'SELECT' in DB - * @param $one - * @param array $cumulativeConditions - * @return array|mixed|null - * @throws Core_Foundation_Database_Exception - */ - private function doFind($one, array $cumulativeConditions) - { - $whereClause = $this->queryBuilder->buildWhereConditions('AND', $cumulativeConditions); + /** + * Constructs and performs 'SELECT' in DB + * @param $one + * @param array $cumulativeConditions + * @return array|mixed|null + * @throws Core_Foundation_Database_Exception + */ + private function doFind($one, array $cumulativeConditions) + { + $whereClause = $this->queryBuilder->buildWhereConditions('AND', $cumulativeConditions); - $sql = 'SELECT * FROM ' . $this->getTableNameWithPrefix() . ' WHERE ' . $whereClause; + $sql = 'SELECT * FROM ' . $this->getTableNameWithPrefix() . ' WHERE ' . $whereClause; - $rows = $this->db->select($sql); + $rows = $this->db->select($sql); - if ($one) { - return $this->hydrateOne($rows); - } else { - return $this->hydrateMany($rows); - } - } + if ($one) { + return $this->hydrateOne($rows); + } else { + return $this->hydrateMany($rows); + } + } - /** - * Find one entity in DB - * @param $id - * @return array|mixed|null - * @throws Core_Foundation_Database_Exception - */ - public function findOne($id) - { - $conditions = array(); - $conditions[$this->getIdFieldName()] = $id; + /** + * Find one entity in DB + * @param $id + * @return array|mixed|null + * @throws Core_Foundation_Database_Exception + */ + public function findOne($id) + { + $conditions = array(); + $conditions[$this->getIdFieldName()] = $id; - return $this->doFind(true, $conditions); - } + return $this->doFind(true, $conditions); + } - /** - * Find all entities in DB - * @return array - */ - public function findAll() - { - $sql = 'SELECT * FROM ' . $this->getTableNameWithPrefix(); - return $this->hydrateMany($this->db->select($sql)); - } + /** + * Find all entities in DB + * @return array + */ + public function findAll() + { + $sql = 'SELECT * FROM ' . $this->getTableNameWithPrefix(); + return $this->hydrateMany($this->db->select($sql)); + } } diff --git a/Core/Foundation/Database/Core_Foundation_Database_Exception.php b/Core/Foundation/Database/Core_Foundation_Database_Exception.php index cd13c0e9..e19c0832 100644 --- a/Core/Foundation/Database/Core_Foundation_Database_Exception.php +++ b/Core/Foundation/Database/Core_Foundation_Database_Exception.php @@ -26,4 +26,4 @@ class Core_Foundation_Database_Exception extends Core_Foundation_Exception_Exception { -} \ No newline at end of file +} diff --git a/Core/Foundation/Exception/Core_Foundation_Exception_Exception.php b/Core/Foundation/Exception/Core_Foundation_Exception_Exception.php index 81f28457..942aa5b2 100644 --- a/Core/Foundation/Exception/Core_Foundation_Exception_Exception.php +++ b/Core/Foundation/Exception/Core_Foundation_Exception_Exception.php @@ -26,8 +26,8 @@ class Core_Foundation_Exception_Exception extends Exception { - public function __construct($message = null, $code = 0, Exception $previous = null) - { - parent::__construct($message, $code, $previous); - } -} \ No newline at end of file + public function __construct($message = null, $code = 0, Exception $previous = null) + { + parent::__construct($message, $code, $previous); + } +} diff --git a/Core/Foundation/Filesystem/Core_Foundation_FileSystem_Exception.php b/Core/Foundation/Filesystem/Core_Foundation_FileSystem_Exception.php index ececb41f..bcc82d61 100644 --- a/Core/Foundation/Filesystem/Core_Foundation_FileSystem_Exception.php +++ b/Core/Foundation/Filesystem/Core_Foundation_FileSystem_Exception.php @@ -26,4 +26,4 @@ class Core_Foundation_FileSystem_Exception extends Core_Foundation_Exception_Exception { -} \ No newline at end of file +} diff --git a/Core/Foundation/Filesystem/Core_Foundation_FileSystem_FileSystem.php b/Core/Foundation/Filesystem/Core_Foundation_FileSystem_FileSystem.php index 314a75e1..3afaf4ea 100644 --- a/Core/Foundation/Filesystem/Core_Foundation_FileSystem_FileSystem.php +++ b/Core/Foundation/Filesystem/Core_Foundation_FileSystem_FileSystem.php @@ -26,109 +26,116 @@ class Core_Foundation_FileSystem_FileSystem { - /** - * Replaces directory separators with the system's native one - * and trims the trailing separator. - */ - public function normalizePath($path) - { - return rtrim( - str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path), - DIRECTORY_SEPARATOR - ); - } + /** + * Replaces directory separators with the system's native one + * and trims the trailing separator. + */ + public function normalizePath($path) + { + return rtrim( + str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path), + DIRECTORY_SEPARATOR + ); + } - private function joinTwoPaths($a, $b) - { - return $this->normalizePath($a) . DIRECTORY_SEPARATOR . $this->normalizePath($b); - } + private function joinTwoPaths($a, $b) + { + return $this->normalizePath($a) . DIRECTORY_SEPARATOR . $this->normalizePath($b); + } - /** - * Joins an arbitrary number of paths, normalizing them along the way. - */ - public function joinPaths() - { - if (func_num_args() < 2) { - throw new Core_Foundation_FileSystem_Exception('joinPaths requires at least 2 arguments.'); - } else if (func_num_args() === 2) { - return $this->joinTwoPaths(func_get_arg(0), func_get_arg(1)); - } else if (func_num_args() > 2) { - return $this->joinPaths( - func_get_arg(0), - call_user_func_array( - array($this, 'joinPaths'), - array_slice(func_get_args(), 1) - ) - ); - } - } + /** + * Joins an arbitrary number of paths, normalizing them along the way. + */ + public function joinPaths() + { + if (func_num_args() < 2) { + throw new Core_Foundation_FileSystem_Exception('joinPaths requires at least 2 arguments.'); + } else if (func_num_args() === 2) { + $arg_O = func_get_arg(0); + $arg_1 = func_get_arg(1); - /** - * Performs a depth first listing of directory entries. - * Throws exception if $path is not a file. - * If $path is a file and not a directory, just gets the file info for it - * and return it in an array. - * @return an array of SplFileInfo object indexed by file path - */ - public function listEntriesRecursively($path) - { - if (!file_exists($path)) { - throw new Core_Foundation_FileSystem_Exception( - sprintf( - 'No such file or directory: %s', - $path - ) - ); - } + return $this->joinTwoPaths($arg_O, $arg_1); + } else if (func_num_args() > 2) { + $func_args = func_get_args(); + $arg_0 = func_get_arg(0); - if (!is_dir($path)) { - throw new Core_Foundation_FileSystem_Exception( - sprintf( - '%s is not a directory', - $path - ) - ); - } + return $this->joinPaths( + $arg_0, + call_user_func_array( + array($this, + 'joinPaths'), + array_slice($func_args, 1) + ) + ); + } + } - $entries = array(); + /** + * Performs a depth first listing of directory entries. + * Throws exception if $path is not a file. + * If $path is a file and not a directory, just gets the file info for it + * and return it in an array. + * @return an array of SplFileInfo object indexed by file path + */ + public function listEntriesRecursively($path) + { + if (!file_exists($path)) { + throw new Core_Foundation_FileSystem_Exception( + sprintf( + 'No such file or directory: %s', + $path + ) + ); + } - foreach (scandir($path) as $entry) { - if ($entry === '.' || $entry === '..') { - continue; - } + if (!is_dir($path)) { + throw new Core_Foundation_FileSystem_Exception( + sprintf( + '%s is not a directory', + $path + ) + ); + } - $newPath = $this->joinPaths($path, $entry); - $info = new SplFileInfo($newPath); + $entries = array(); - $entries[$newPath] = $info; + foreach (scandir($path) as $entry) { + if ($entry === '.' || $entry === '..') { + continue; + } - if ($info->isDir()) { - $entries = array_merge( - $entries, - $this->listEntriesRecursively($newPath) - ); - } - } + $newPath = $this->joinPaths($path, $entry); + $info = new SplFileInfo($newPath); - return $entries; - } + $entries[$newPath] = $info; - /** - * Filter used by listFilesRecursively. - */ - private function matchOnlyFiles(SplFileInfo $info) - { - return $info->isFile(); - } + if ($info->isDir()) { + $entries = array_merge( + $entries, + $this->listEntriesRecursively($newPath) + ); + } + } - /** - * Same as listEntriesRecursively but returns only files. - */ - public function listFilesRecursively($path) - { - return array_filter( - $this->listEntriesRecursively($path), - array($this, 'matchOnlyFiles') - ); - } + return $entries; + } + + /** + * Filter used by listFilesRecursively. + */ + private function matchOnlyFiles(SplFileInfo $info) + { + return $info->isFile(); + } + + /** + * Same as listEntriesRecursively but returns only files. + */ + public function listFilesRecursively($path) + { + return array_filter( + $this->listEntriesRecursively($path), + array($this, 'matchOnlyFiles') + ); + } } diff --git a/Core/Foundation/IoC/Core_Foundation_IoC_Container.php b/Core/Foundation/IoC/Core_Foundation_IoC_Container.php index 40dafdbf..762a101c 100644 --- a/Core/Foundation/IoC/Core_Foundation_IoC_Container.php +++ b/Core/Foundation/IoC/Core_Foundation_IoC_Container.php @@ -108,7 +108,7 @@ class Core_Foundation_IoC_Container $paramClass = $param->getClass(); if ($paramClass) { $args[] = $this->doMake($param->getClass()->getName(), $alreadySeen); - } else if ($param->isDefaultValueAvailable()) { + } elseif ($param->isDefaultValueAvailable()) { $args[] = $param->getDefaultValue(); } else { throw new Core_Foundation_IoC_Exception(sprintf('Cannot build a `%s`.', $className)); @@ -149,7 +149,7 @@ class Core_Foundation_IoC_Container if (is_callable($constructor)) { $service = call_user_func($constructor); - } else if (!is_string($constructor)) { + } elseif (!is_string($constructor)) { // user already provided the value, no need to construct it. $service = $constructor; } else { diff --git a/adm/ajax-tab.php b/adm/ajax-tab.php index 35a1d75d..6ef614a9 100644 --- a/adm/ajax-tab.php +++ b/adm/ajax-tab.php @@ -24,19 +24,23 @@ * International Registered Trademark & Property of PrestaShop SA */ -if (!defined('_PS_ADMIN_DIR_')) - define('_PS_ADMIN_DIR_', getcwd()); +if (!defined('_PS_ADMIN_DIR_')) { + define('_PS_ADMIN_DIR_', getcwd()); +} require(_PS_ADMIN_DIR_.'/../config/config.inc.php'); require(_PS_ADMIN_DIR_.'/functions.php'); // For retrocompatibility with "tab" parameter -if (!isset($_GET['controller']) && isset($_GET['tab'])) - $_GET['controller'] = strtolower($_GET['tab']); -if (!isset($_POST['controller']) && isset($_POST['tab'])) - $_POST['controller'] = strtolower($_POST['tab']); -if (!isset($_REQUEST['controller']) && isset($_REQUEST['tab'])) - $_REQUEST['controller'] = strtolower($_REQUEST['tab']); +if (!isset($_GET['controller']) && isset($_GET['tab'])) { + $_GET['controller'] = strtolower($_GET['tab']); +} +if (!isset($_POST['controller']) && isset($_POST['tab'])) { + $_POST['controller'] = strtolower($_POST['tab']); +} +if (!isset($_REQUEST['controller']) && isset($_REQUEST['tab'])) { + $_REQUEST['controller'] = strtolower($_REQUEST['tab']); +} // Retrocompatibility with 1.4 $_REQUEST['ajaxMode'] = $_POST['ajaxMode'] = $_GET['ajaxMode'] = $_REQUEST['ajax'] = $_POST['ajax'] = $_GET['ajax'] = 1; diff --git a/adm/ajax.php b/adm/ajax.php index 2e805159..ad2e2544 100644 --- a/adm/ajax.php +++ b/adm/ajax.php @@ -24,8 +24,9 @@ * International Registered Trademark & Property of PrestaShop SA */ -if (!defined('_PS_ADMIN_DIR_')) - define('_PS_ADMIN_DIR_', getcwd()); +if (!defined('_PS_ADMIN_DIR_')) { + define('_PS_ADMIN_DIR_', getcwd()); +} include(_PS_ADMIN_DIR_.'/../config/config.inc.php'); /* Getting cookie or logout */ @@ -33,27 +34,28 @@ require_once(_PS_ADMIN_DIR_.'/init.php'); $context = Context::getContext(); -if (Tools::isSubmit('ajaxReferrers')) - require(_PS_CONTROLLER_DIR_.'admin/AdminReferrersController.php'); - -if (Tools::getValue('page') == 'prestastore' AND @fsockopen('addons.prestashop.com', 80, $errno, $errst, 3)) - readfile('http://addons.prestashop.com/adminmodules.php?lang='.$context->language->iso_code); - -if (Tools::isSubmit('getAvailableFields') AND Tools::isSubmit('entity')) -{ - $jsonArray = array(); - $import = new AdminImportController(); - - $fields = $import->getAvailableFields(true); - foreach ($fields as $field) - $jsonArray[] = '{"field":"'.addslashes($field).'"}'; - die('['.implode(',', $jsonArray).']'); +if (Tools::isSubmit('ajaxReferrers')) { + require(_PS_CONTROLLER_DIR_.'admin/AdminReferrersController.php'); } -if (Tools::isSubmit('ajaxProductPackItems')) -{ - $jsonArray = array(); - $products = Db::getInstance()->executeS(' +if (Tools::getValue('page') == 'prestastore' and @fsockopen('addons.prestashop.com', 80, $errno, $errst, 3)) { + readfile('http://addons.prestashop.com/adminmodules.php?lang='.$context->language->iso_code); +} + +if (Tools::isSubmit('getAvailableFields') and Tools::isSubmit('entity')) { + $jsonArray = array(); + $import = new AdminImportController(); + + $fields = $import->getAvailableFields(true); + foreach ($fields as $field) { + $jsonArray[] = '{"field":"'.addslashes($field).'"}'; + } + die('['.implode(',', $jsonArray).']'); +} + +if (Tools::isSubmit('ajaxProductPackItems')) { + $jsonArray = array(); + $products = Db::getInstance()->executeS(' SELECT p.`id_product`, pl.`name` FROM `'._DB_PREFIX_.'product` p NATURAL LEFT JOIN `'._DB_PREFIX_.'product_lang` pl @@ -62,35 +64,32 @@ if (Tools::isSubmit('ajaxProductPackItems')) AND NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'pack` WHERE `id_product_pack` = p.`id_product`) AND p.`id_product` != '.(int)(Tools::getValue('id_product'))); - foreach ($products as $packItem) - $jsonArray[] = '{"value": "'.(int)($packItem['id_product']).'-'.addslashes($packItem['name']).'", "text":"'.(int)($packItem['id_product']).' - '.addslashes($packItem['name']).'"}'; - die('['.implode(',', $jsonArray).']'); + foreach ($products as $packItem) { + $jsonArray[] = '{"value": "'.(int)($packItem['id_product']).'-'.addslashes($packItem['name']).'", "text":"'.(int)($packItem['id_product']).' - '.addslashes($packItem['name']).'"}'; + } + die('['.implode(',', $jsonArray).']'); } -if (Tools::isSubmit('getChildrenCategories') && Tools::isSubmit('id_category_parent')) -{ - $children_categories = Category::getChildrenWithNbSelectedSubCat(Tools::getValue('id_category_parent'), Tools::getValue('selectedCat'), Context::getContext()->language->id, null, Tools::getValue('use_shop_context')); - die(Tools::jsonEncode($children_categories)); +if (Tools::isSubmit('getChildrenCategories') && Tools::isSubmit('id_category_parent')) { + $children_categories = Category::getChildrenWithNbSelectedSubCat(Tools::getValue('id_category_parent'), Tools::getValue('selectedCat'), Context::getContext()->language->id, null, Tools::getValue('use_shop_context')); + die(Tools::jsonEncode($children_categories)); } -if (Tools::isSubmit('getNotifications')) -{ - $notification = new Notification; - die(Tools::jsonEncode($notification->getLastElements())); +if (Tools::isSubmit('getNotifications')) { + $notification = new Notification; + die(Tools::jsonEncode($notification->getLastElements())); } -if (Tools::isSubmit('updateElementEmployee') && Tools::getValue('updateElementEmployeeType')) -{ - $notification = new Notification; - die($notification->updateEmployeeLastElement(Tools::getValue('updateElementEmployeeType'))); +if (Tools::isSubmit('updateElementEmployee') && Tools::getValue('updateElementEmployeeType')) { + $notification = new Notification; + die($notification->updateEmployeeLastElement(Tools::getValue('updateElementEmployeeType'))); } -if (Tools::isSubmit('searchCategory')) -{ - $q = Tools::getValue('q'); - $limit = Tools::getValue('limit'); - $results = Db::getInstance()->executeS( - 'SELECT c.`id_category`, cl.`name` +if (Tools::isSubmit('searchCategory')) { + $q = Tools::getValue('q'); + $limit = Tools::getValue('limit'); + $results = Db::getInstance()->executeS( + 'SELECT c.`id_category`, cl.`name` FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category`'.Shop::addSqlRestrictionOnLang('cl').') WHERE cl.`id_lang` = '.(int)$context->language->id.' AND c.`level_depth` <> 0 @@ -98,28 +97,30 @@ if (Tools::isSubmit('searchCategory')) GROUP BY c.id_category ORDER BY c.`position` LIMIT '.(int)$limit); - if ($results) - foreach ($results as $result) - echo trim($result['name']).'|'.(int)$result['id_category']."\n"; + if ($results) { + foreach ($results as $result) { + echo trim($result['name']).'|'.(int)$result['id_category']."\n"; + } + } } -if (Tools::isSubmit('getParentCategoriesId') && $id_category = Tools::getValue('id_category')) -{ - $category = new Category((int)$id_category); - $results = Db::getInstance()->executeS('SELECT `id_category` FROM `'._DB_PREFIX_.'category` c WHERE c.`nleft` < '.(int)$category->nleft.' AND c.`nright` > '.(int)$category->nright.''); - $output = array(); - foreach ($results as $result) - $output[] = $result; +if (Tools::isSubmit('getParentCategoriesId') && $id_category = Tools::getValue('id_category')) { + $category = new Category((int)$id_category); + $results = Db::getInstance()->executeS('SELECT `id_category` FROM `'._DB_PREFIX_.'category` c WHERE c.`nleft` < '.(int)$category->nleft.' AND c.`nright` > '.(int)$category->nright.''); + $output = array(); + foreach ($results as $result) { + $output[] = $result; + } - die(Tools::jsonEncode($output)); + die(Tools::jsonEncode($output)); } -if (Tools::isSubmit('getZones')) -{ - $html = ''; - $array = array('hasError' => false, 'errors' => '', 'data' => $html); - die(Tools::jsonEncode($array)); +if (Tools::isSubmit('getZones')) { + $html = ''; + $array = array('hasError' => false, 'errors' => '', 'data' => $html); + die(Tools::jsonEncode($array)); } diff --git a/adm/ajax_products_list.php b/adm/ajax_products_list.php index d0fd73ed..64415c49 100644 --- a/adm/ajax_products_list.php +++ b/adm/ajax_products_list.php @@ -23,15 +23,17 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * International Registered Trademark & Property of PrestaShop SA */ -if (!defined('_PS_ADMIN_DIR_')) - define('_PS_ADMIN_DIR_', getcwd()); +if (!defined('_PS_ADMIN_DIR_')) { + define('_PS_ADMIN_DIR_', getcwd()); +} include(_PS_ADMIN_DIR_.'/../config/config.inc.php'); /* Getting cookie or logout */ require_once(_PS_ADMIN_DIR_.'/init.php'); $query = Tools::getValue('q', false); -if (!$query OR $query == '' OR strlen($query) < 1) - die(); +if (!$query or $query == '' or strlen($query) < 1) { + die(); +} /* * In the SQL request the "q" param is used entirely to match result in database. @@ -40,14 +42,16 @@ if (!$query OR $query == '' OR strlen($query) < 1) * is not write in the name field of the product. * So the ref pattern will be cut for the search request. */ -if($pos = strpos($query, ' (ref:')) - $query = substr($query, 0, $pos); +if ($pos = strpos($query, ' (ref:')) { + $query = substr($query, 0, $pos); +} $excludeIds = Tools::getValue('excludeIds', false); -if ($excludeIds && $excludeIds != 'NaN') - $excludeIds = implode(',', array_map('intval', explode(',', $excludeIds))); -else - $excludeIds = ''; +if ($excludeIds && $excludeIds != 'NaN') { + $excludeIds = implode(',', array_map('intval', explode(',', $excludeIds))); +} else { + $excludeIds = ''; +} // Excluding downloadable products from packs because download from pack is not supported $excludeVirtuals = (bool)Tools::getValue('excludeVirtuals', true); @@ -63,26 +67,24 @@ $sql = 'SELECT p.`id_product`, pl.`link_rewrite`, p.`reference`, pl.`name`, imag ON (image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop='.(int)$context->shop->id.') LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$context->language->id.') WHERE (pl.name LIKE \'%'.pSQL($query).'%\' OR p.reference LIKE \'%'.pSQL($query).'%\')'. - (!empty($excludeIds) ? ' AND p.id_product NOT IN ('.$excludeIds.') ' : ' '). - ($excludeVirtuals ? 'AND NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'product_download` pd WHERE (pd.id_product = p.id_product))' : ''). - ($exclude_packs ? 'AND (p.cache_is_pack IS NULL OR p.cache_is_pack = 0)' : ''). - ' GROUP BY p.id_product'; + (!empty($excludeIds) ? ' AND p.id_product NOT IN ('.$excludeIds.') ' : ' '). + ($excludeVirtuals ? 'AND NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'product_download` pd WHERE (pd.id_product = p.id_product))' : ''). + ($exclude_packs ? 'AND (p.cache_is_pack IS NULL OR p.cache_is_pack = 0)' : ''). + ' GROUP BY p.id_product'; $items = Db::getInstance()->executeS($sql); -if ($items && ($excludeIds || strpos($_SERVER['HTTP_REFERER'], 'AdminScenes') !== false)) - foreach ($items as $item) - echo trim($item['name']).(!empty($item['reference']) ? ' (ref: '.$item['reference'].')' : '').'|'.(int)($item['id_product'])."\n"; -elseif ($items) -{ - // packs - $results = array(); - foreach ($items as $item) - { - // check if product have combination - if (Combination::isFeatureActive() && $item['cache_default_attribute']) - { - $sql = 'SELECT pa.`id_product_attribute`, pa.`reference`, ag.`id_attribute_group`, pai.`id_image`, agl.`name` AS group_name, al.`name` AS attribute_name, +if ($items && ($excludeIds || strpos($_SERVER['HTTP_REFERER'], 'AdminScenes') !== false)) { + foreach ($items as $item) { + echo trim($item['name']).(!empty($item['reference']) ? ' (ref: '.$item['reference'].')' : '').'|'.(int)($item['id_product'])."\n"; + } +} elseif ($items) { + // packs + $results = array(); + foreach ($items as $item) { + // check if product have combination + if (Combination::isFeatureActive() && $item['cache_default_attribute']) { + $sql = 'SELECT pa.`id_product_attribute`, pa.`reference`, ag.`id_attribute_group`, pai.`id_image`, agl.`name` AS group_name, al.`name` AS attribute_name, a.`id_attribute` FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' @@ -96,47 +98,43 @@ elseif ($items) GROUP BY pa.`id_product_attribute`, ag.`id_attribute_group` ORDER BY pa.`id_product_attribute`'; - $combinations = Db::getInstance()->executeS($sql); - if (!empty($combinations)) - { - foreach ($combinations as $k => $combination) - { - $results[$combination['id_product_attribute']]['id'] = $item['id_product']; - $results[$combination['id_product_attribute']]['id_product_attribute'] = $combination['id_product_attribute']; - !empty($results[$combination['id_product_attribute']]['name']) ? $results[$combination['id_product_attribute']]['name'] .= ' '.$combination['group_name'].'-'.$combination['attribute_name'] - : $results[$combination['id_product_attribute']]['name'] = $item['name'].' '.$combination['group_name'].'-'.$combination['attribute_name']; - if (!empty($combination['reference'])) - $results[$combination['id_product_attribute']]['ref'] = $combination['reference']; - else - $results[$combination['id_product_attribute']]['ref'] = !empty($item['reference']) ? $item['reference'] : ''; - if (empty($results[$combination['id_product_attribute']]['image'])) - $results[$combination['id_product_attribute']]['image'] = str_replace('http://', Tools::getShopProtocol(), $context->link->getImageLink($item['link_rewrite'], $combination['id_image'], 'home_default')); - } - } - else - { - $product = array( - 'id' => (int)($item['id_product']), - 'name' => $item['name'], - 'ref' => (!empty($item['reference']) ? $item['reference'] : ''), - 'image' => str_replace('http://', Tools::getShopProtocol(), $context->link->getImageLink($item['link_rewrite'], $item['id_image'], 'home_default')), - ); - array_push($results, $product); - } - } - else - { - $product = array( - 'id' => (int)($item['id_product']), - 'name' => $item['name'], - 'ref' => (!empty($item['reference']) ? $item['reference'] : ''), - 'image' => str_replace('http://', Tools::getShopProtocol(), $context->link->getImageLink($item['link_rewrite'], $item['id_image'], 'home_default')), - ); - array_push($results, $product); - } - } - $results = array_values($results); - echo Tools::jsonEncode($results); + $combinations = Db::getInstance()->executeS($sql); + if (!empty($combinations)) { + foreach ($combinations as $k => $combination) { + $results[$combination['id_product_attribute']]['id'] = $item['id_product']; + $results[$combination['id_product_attribute']]['id_product_attribute'] = $combination['id_product_attribute']; + !empty($results[$combination['id_product_attribute']]['name']) ? $results[$combination['id_product_attribute']]['name'] .= ' '.$combination['group_name'].'-'.$combination['attribute_name'] + : $results[$combination['id_product_attribute']]['name'] = $item['name'].' '.$combination['group_name'].'-'.$combination['attribute_name']; + if (!empty($combination['reference'])) { + $results[$combination['id_product_attribute']]['ref'] = $combination['reference']; + } else { + $results[$combination['id_product_attribute']]['ref'] = !empty($item['reference']) ? $item['reference'] : ''; + } + if (empty($results[$combination['id_product_attribute']]['image'])) { + $results[$combination['id_product_attribute']]['image'] = str_replace('http://', Tools::getShopProtocol(), $context->link->getImageLink($item['link_rewrite'], $combination['id_image'], 'home_default')); + } + } + } else { + $product = array( + 'id' => (int)($item['id_product']), + 'name' => $item['name'], + 'ref' => (!empty($item['reference']) ? $item['reference'] : ''), + 'image' => str_replace('http://', Tools::getShopProtocol(), $context->link->getImageLink($item['link_rewrite'], $item['id_image'], 'home_default')), + ); + array_push($results, $product); + } + } else { + $product = array( + 'id' => (int)($item['id_product']), + 'name' => $item['name'], + 'ref' => (!empty($item['reference']) ? $item['reference'] : ''), + 'image' => str_replace('http://', Tools::getShopProtocol(), $context->link->getImageLink($item['link_rewrite'], $item['id_image'], 'home_default')), + ); + array_push($results, $product); + } + } + $results = array_values($results); + echo Tools::jsonEncode($results); +} else { + Tools::jsonEncode(new stdClass); } -else - Tools::jsonEncode(new stdClass); diff --git a/adm/backup.php b/adm/backup.php index aa5d3151..5b6ab464 100644 --- a/adm/backup.php +++ b/adm/backup.php @@ -24,53 +24,63 @@ * International Registered Trademark & Property of PrestaShop SA */ -if (!defined('_PS_ADMIN_DIR_')) - define('_PS_ADMIN_DIR_', getcwd()); +if (!defined('_PS_ADMIN_DIR_')) { + define('_PS_ADMIN_DIR_', getcwd()); +} include(_PS_ADMIN_DIR_.'/../config/config.inc.php'); -if (!Context::getContext()->employee->isLoggedBack()) - Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminLogin')); +if (!Context::getContext()->employee->isLoggedBack()) { + Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminLogin')); +} $tabAccess = Profile::getProfileAccess(Context::getContext()->employee->id_profile, - Tab::getIdFromClassName('AdminBackup')); + Tab::getIdFromClassName('AdminBackup')); -if ($tabAccess['view'] !== '1') - die (Tools::displayError('You do not have permission to view this.')); +if ($tabAccess['view'] !== '1') { + die(Tools::displayError('You do not have permission to view this.')); +} $backupdir = realpath(PrestaShopBackup::getBackupPath()); -if ($backupdir === false) - die (Tools::displayError('There is no "/backup" directory.')); +if ($backupdir === false) { + die(Tools::displayError('There is no "/backup" directory.')); +} -if (!$backupfile = Tools::getValue('filename')) - die (Tools::displayError('No file has been specified.')); +if (!$backupfile = Tools::getValue('filename')) { + die(Tools::displayError('No file has been specified.')); +} // Check the realpath so we can validate the backup file is under the backup directory $backupfile = realpath($backupdir.DIRECTORY_SEPARATOR.$backupfile); -if ($backupfile === false OR strncmp($backupdir, $backupfile, strlen($backupdir)) != 0 ) - die (Tools::dieOrLog('The backup file does not exist.')); +if ($backupfile === false or strncmp($backupdir, $backupfile, strlen($backupdir)) != 0) { + die(Tools::dieOrLog('The backup file does not exist.')); +} -if (substr($backupfile, -4) == '.bz2') +if (substr($backupfile, -4) == '.bz2') { $contentType = 'application/x-bzip2'; -else if (substr($backupfile, -3) == '.gz') +} elseif (substr($backupfile, -3) == '.gz') { $contentType = 'application/x-gzip'; -else +} else { $contentType = 'text/x-sql'; +} $fp = @fopen($backupfile, 'r'); -if ($fp === false) - die (Tools::displayError('Unable to open backup file(s).').' "'.addslashes($backupfile).'"'); +if ($fp === false) { + die(Tools::displayError('Unable to open backup file(s).').' "'.addslashes($backupfile).'"'); +} // Add the correct headers, this forces the file is saved header('Content-Type: '.$contentType); header('Content-Disposition: attachment; filename="'.Tools::getValue('filename'). '"'); -if (ob_get_level() && ob_get_length() > 0) - ob_clean(); +if (ob_get_level() && ob_get_length() > 0) { + ob_clean(); +} $ret = @fpassthru($fp); fclose($fp); -if ($ret === false) - die (Tools::displayError('Unable to display backup file(s).').' "'.addslashes($backupfile).'"'); +if ($ret === false) { + die(Tools::displayError('Unable to display backup file(s).').' "'.addslashes($backupfile).'"'); +} diff --git a/adm/cron_currency_rates.php b/adm/cron_currency_rates.php index 6f481094..b7389299 100644 --- a/adm/cron_currency_rates.php +++ b/adm/cron_currency_rates.php @@ -24,20 +24,18 @@ * International Registered Trademark & Property of PrestaShop SA */ -if (!defined('_PS_ADMIN_DIR_')) - define('_PS_ADMIN_DIR_', getcwd()); +if (!defined('_PS_ADMIN_DIR_')) { + define('_PS_ADMIN_DIR_', getcwd()); +} include(_PS_ADMIN_DIR_.'/../config/config.inc.php'); -if (isset($_GET['secure_key'])) -{ - $secureKey = md5(_COOKIE_KEY_.Configuration::get('PS_SHOP_NAME')); - if (!empty($secureKey) && $secureKey === $_GET['secure_key']) - { - $shop_ids = Shop::getCompleteListOfShopsID(); - foreach($shop_ids as $shop_id) - { - Shop::setContext(Shop::CONTEXT_SHOP, (int)$shop_id); - Currency::refreshCurrencies(); - } - } -} \ No newline at end of file +if (isset($_GET['secure_key'])) { + $secureKey = md5(_COOKIE_KEY_.Configuration::get('PS_SHOP_NAME')); + if (!empty($secureKey) && $secureKey === $_GET['secure_key']) { + $shop_ids = Shop::getCompleteListOfShopsID(); + foreach ($shop_ids as $shop_id) { + Shop::setContext(Shop::CONTEXT_SHOP, (int)$shop_id); + Currency::refreshCurrencies(); + } + } +} diff --git a/adm/displayImage.php b/adm/displayImage.php index 5bcfd9de..6b0ef9c9 100644 --- a/adm/displayImage.php +++ b/adm/displayImage.php @@ -24,14 +24,14 @@ * International Registered Trademark & Property of PrestaShop SA */ -if (!defined('_PS_ADMIN_DIR_')) - define('_PS_ADMIN_DIR_', getcwd()); +if (!defined('_PS_ADMIN_DIR_')) { + define('_PS_ADMIN_DIR_', getcwd()); +} require_once(_PS_ADMIN_DIR_.'/../config/config.inc.php'); require_once(_PS_ADMIN_DIR_.'/init.php'); -if (isset($_GET['img']) AND Validate::isMd5($_GET['img']) AND isset($_GET['name']) AND Validate::isGenericName($_GET['name']) AND file_exists(_PS_UPLOAD_DIR_.$_GET['img'])) -{ - header('Content-type: image/jpeg'); - header('Content-Disposition: attachment; filename="'.$_GET['name'].'.jpg"'); - echo file_get_contents(_PS_UPLOAD_DIR_.$_GET['img']); +if (isset($_GET['img']) and Validate::isMd5($_GET['img']) and isset($_GET['name']) and Validate::isGenericName($_GET['name']) and file_exists(_PS_UPLOAD_DIR_.$_GET['img'])) { + header('Content-type: image/jpeg'); + header('Content-Disposition: attachment; filename="'.$_GET['name'].'.jpg"'); + echo file_get_contents(_PS_UPLOAD_DIR_.$_GET['img']); } diff --git a/adm/drawer.php b/adm/drawer.php index c77f2601..dec7f464 100644 --- a/adm/drawer.php +++ b/adm/drawer.php @@ -24,8 +24,9 @@ * International Registered Trademark & Property of PrestaShop SA */ -if (!defined('_PS_ADMIN_DIR_')) - define('_PS_ADMIN_DIR_', getcwd()); +if (!defined('_PS_ADMIN_DIR_')) { + define('_PS_ADMIN_DIR_', getcwd()); +} include_once(_PS_ADMIN_DIR_.'/../config/config.inc.php'); $module = Tools::getValue('module'); @@ -38,67 +39,65 @@ $height = Tools::getValue('height'); $id_employee = Tools::getValue('id_employee'); $id_lang = Tools::getValue('id_lang'); -if (!isset($cookie->id_employee) || !$cookie->id_employee || $cookie->id_employee != $id_employee) +if (!isset($cookie->id_employee) || !$cookie->id_employee || $cookie->id_employee != $id_employee) { die(Tools::displayError()); +} -if (!Validate::isModuleName($module)) - die(Tools::displayError()); +if (!Validate::isModuleName($module)) { + die(Tools::displayError()); +} -if (!Tools::file_exists_cache($module_path = _PS_ROOT_DIR_.'/modules/'.$module.'/'.$module.'.php')) - die(Tools::displayError()); +if (!Tools::file_exists_cache($module_path = _PS_ROOT_DIR_.'/modules/'.$module.'/'.$module.'.php')) { + die(Tools::displayError()); +} $shop_id = ''; Shop::setContext(Shop::CONTEXT_ALL); -if (Context::getContext()->cookie->shopContext) -{ - $split = explode('-', Context::getContext()->cookie->shopContext); - if (count($split) == 2) - { - if ($split[0] == 'g') - { - if (Context::getContext()->employee->hasAuthOnShopGroup($split[1])) - Shop::setContext(Shop::CONTEXT_GROUP, $split[1]); - else - { - $shop_id = Context::getContext()->employee->getDefaultShopID(); - Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); - } - } - else if (Shop::getShop($split[1]) && Context::getContext()->employee->hasAuthOnShop($split[1])) - { - $shop_id = $split[1]; - Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); - } - else - { - $shop_id = Context::getContext()->employee->getDefaultShopID(); - Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); - } - } +if (Context::getContext()->cookie->shopContext) { + $split = explode('-', Context::getContext()->cookie->shopContext); + if (count($split) == 2) { + if ($split[0] == 'g') { + if (Context::getContext()->employee->hasAuthOnShopGroup($split[1])) { + Shop::setContext(Shop::CONTEXT_GROUP, $split[1]); + } else { + $shop_id = Context::getContext()->employee->getDefaultShopID(); + Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); + } + } elseif (Shop::getShop($split[1]) && Context::getContext()->employee->hasAuthOnShop($split[1])) { + $shop_id = $split[1]; + Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); + } else { + $shop_id = Context::getContext()->employee->getDefaultShopID(); + Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); + } + } } // Check multishop context and set right context if need -if (Shop::getContext()) -{ - if (Shop::getContext() == Shop::CONTEXT_SHOP && !Shop::CONTEXT_SHOP) - Shop::setContext(Shop::CONTEXT_GROUP, Shop::getContextShopGroupID()); - if (Shop::getContext() == Shop::CONTEXT_GROUP && !Shop::CONTEXT_GROUP) - Shop::setContext(Shop::CONTEXT_ALL); +if (Shop::getContext()) { + if (Shop::getContext() == Shop::CONTEXT_SHOP && !Shop::CONTEXT_SHOP) { + Shop::setContext(Shop::CONTEXT_GROUP, Shop::getContextShopGroupID()); + } + if (Shop::getContext() == Shop::CONTEXT_GROUP && !Shop::CONTEXT_GROUP) { + Shop::setContext(Shop::CONTEXT_ALL); + } } // Replace existing shop if necessary -if (!$shop_id) - Context::getContext()->shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); -elseif (Context::getContext()->shop->id != $shop_id) - Context::getContext()->shop = new Shop($shop_id); +if (!$shop_id) { + Context::getContext()->shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); +} elseif (Context::getContext()->shop->id != $shop_id) { + Context::getContext()->shop = new Shop($shop_id); +} require_once($module_path); $graph = new $module(); $graph->setEmployee($id_employee); $graph->setLang($id_lang); -if ($option) - $graph->setOption($option, $layers); +if ($option) { + $graph->setOption($option, $layers); +} $graph->create($render, $type, $width, $height, $layers); $graph->draw(); diff --git a/adm/filemanager/ajax_calls.php b/adm/filemanager/ajax_calls.php index 343f6008..e571d3fa 100644 --- a/adm/filemanager/ajax_calls.php +++ b/adm/filemanager/ajax_calls.php @@ -2,132 +2,131 @@ include('config/config.php'); -if ($_SESSION['verify'] != 'RESPONSIVEfilemanager') - die('forbiden'); +if ($_SESSION['verify'] != 'RESPONSIVEfilemanager') { + die('forbiden'); +} include('include/utils.php'); -if (isset($_GET['action'])) - switch ($_GET['action']) - { - case 'view': - if (isset($_GET['type'])) - $_SESSION['view_type'] = $_GET['type']; - else - die('view type number missing'); - break; - case 'sort': - if (isset($_GET['sort_by'])) - $_SESSION['sort_by'] = $_GET['sort_by']; - if (isset($_GET['descending'])) - $_SESSION['descending'] = $_GET['descending'] === 'true'; - break; - case 'image_size': - if (realpath(dirname(_PS_ROOT_DIR_.$_POST['path'])) != realpath(_PS_ROOT_DIR_.$upload_dir)) - die(); - $pos = strpos($_POST['path'], $upload_dir); - if ($pos !== false) - { - $info = getimagesize(substr_replace($_POST['path'], $current_path, $pos, strlen($upload_dir))); - echo json_encode($info); - } +if (isset($_GET['action'])) { + switch ($_GET['action']) { + case 'view': + if (isset($_GET['type'])) { + $_SESSION['view_type'] = $_GET['type']; + } else { + die('view type number missing'); + } + break; + case 'sort': + if (isset($_GET['sort_by'])) { + $_SESSION['sort_by'] = $_GET['sort_by']; + } + if (isset($_GET['descending'])) { + $_SESSION['descending'] = $_GET['descending'] === 'true'; + } + break; + case 'image_size': + if (realpath(dirname(_PS_ROOT_DIR_.$_POST['path'])) != realpath(_PS_ROOT_DIR_.$upload_dir)) { + die(); + } + $pos = strpos($_POST['path'], $upload_dir); + if ($pos !== false) { + $info = getimagesize(substr_replace($_POST['path'], $current_path, $pos, strlen($upload_dir))); + echo json_encode($info); + } - break; - case 'save_img': - $info = pathinfo($_POST['name']); - if (strpos($_POST['path'], '/') === 0 - || strpos($_POST['path'], '../') !== false - || strpos($_POST['path'], './') === 0 - || strpos($_POST['url'], 'http://featherfiles.aviary.com/') !== 0 - || $_POST['name'] != fix_filename($_POST['name'], $transliteration) - || !in_array(strtolower($info['extension']), array('jpg', 'jpeg', 'png')) - ) - die('wrong data'); - $image_data = get_file_by_url($_POST['url']); - if ($image_data === false) - { - die('file could not be loaded'); - } + break; + case 'save_img': + $info = pathinfo($_POST['name']); + if (strpos($_POST['path'], '/') === 0 + || strpos($_POST['path'], '../') !== false + || strpos($_POST['path'], './') === 0 + || strpos($_POST['url'], 'http://featherfiles.aviary.com/') !== 0 + || $_POST['name'] != fix_filename($_POST['name'], $transliteration) + || !in_array(strtolower($info['extension']), array('jpg', 'jpeg', 'png')) + ) { + die('wrong data'); + } + $image_data = get_file_by_url($_POST['url']); + if ($image_data === false) { + die('file could not be loaded'); + } - $put_contents_path = $current_path; + $put_contents_path = $current_path; - if (isset($_POST['path'])) - $put_contents_path .= str_replace("\0", "", $_POST['path']); + if (isset($_POST['path'])) { + $put_contents_path .= str_replace("\0", "", $_POST['path']); + } - if (isset($_POST['name'])) - $put_contents_path .= str_replace("\0", "", $_POST['name']); + if (isset($_POST['name'])) { + $put_contents_path .= str_replace("\0", "", $_POST['name']); + } - file_put_contents($put_contents_path, $image_data); - //new thumb creation - //try{ - create_img_gd($current_path.$_POST['path'].$_POST['name'], $thumbs_base_path.$_POST['path'].$_POST['name'], 122, 91); - new_thumbnails_creation($current_path.$_POST['path'], $current_path.$_POST['path'].$_POST['name'], $_POST['name'], $current_path, $relative_image_creation, $relative_path_from_current_pos, $relative_image_creation_name_to_prepend, $relative_image_creation_name_to_append, $relative_image_creation_width, $relative_image_creation_height, $fixed_image_creation, $fixed_path_from_filemanager, $fixed_image_creation_name_to_prepend, $fixed_image_creation_to_append, $fixed_image_creation_width, $fixed_image_creation_height); - /*} catch (Exception $e) { - $src_thumb=$mini_src=""; - }*/ - break; - case 'extract': - if (strpos($_POST['path'], '/') === 0 || strpos($_POST['path'], '../') !== false || strpos($_POST['path'], './') === 0) - die('wrong path'); - $path = $current_path.$_POST['path']; - $info = pathinfo($path); - $base_folder = $current_path.fix_dirname($_POST['path']).'/'; - switch ($info['extension']) - { - case 'zip': - $zip = new ZipArchive; - if ($zip->open($path) === true) - { - //make all the folders - for ($i = 0; $i < $zip->numFiles; $i++) - { - $OnlyFileName = $zip->getNameIndex($i); - $FullFileName = $zip->statIndex($i); - if ($FullFileName['name'][strlen($FullFileName['name']) - 1] == '/') - { - create_folder($base_folder.$FullFileName['name']); - } - } - //unzip into the folders - for ($i = 0; $i < $zip->numFiles; $i++) - { - $OnlyFileName = $zip->getNameIndex($i); - $FullFileName = $zip->statIndex($i); + file_put_contents($put_contents_path, $image_data); + //new thumb creation + //try{ + create_img_gd($current_path.$_POST['path'].$_POST['name'], $thumbs_base_path.$_POST['path'].$_POST['name'], 122, 91); + new_thumbnails_creation($current_path.$_POST['path'], $current_path.$_POST['path'].$_POST['name'], $_POST['name'], $current_path, $relative_image_creation, $relative_path_from_current_pos, $relative_image_creation_name_to_prepend, $relative_image_creation_name_to_append, $relative_image_creation_width, $relative_image_creation_height, $fixed_image_creation, $fixed_path_from_filemanager, $fixed_image_creation_name_to_prepend, $fixed_image_creation_to_append, $fixed_image_creation_width, $fixed_image_creation_height); + /*} catch (Exception $e) { + $src_thumb=$mini_src=""; + }*/ + break; + case 'extract': + if (strpos($_POST['path'], '/') === 0 || strpos($_POST['path'], '../') !== false || strpos($_POST['path'], './') === 0) { + die('wrong path'); + } + $path = $current_path.$_POST['path']; + $info = pathinfo($path); + $base_folder = $current_path.fix_dirname($_POST['path']).'/'; + switch ($info['extension']) { + case 'zip': + $zip = new ZipArchive; + if ($zip->open($path) === true) { + //make all the folders + for ($i = 0; $i < $zip->numFiles; $i++) { + $OnlyFileName = $zip->getNameIndex($i); + $FullFileName = $zip->statIndex($i); + if ($FullFileName['name'][strlen($FullFileName['name']) - 1] == '/') { + create_folder($base_folder.$FullFileName['name']); + } + } + //unzip into the folders + for ($i = 0; $i < $zip->numFiles; $i++) { + $OnlyFileName = $zip->getNameIndex($i); + $FullFileName = $zip->statIndex($i); - if (!($FullFileName['name'][strlen($FullFileName['name']) - 1] == '/')) - { - $fileinfo = pathinfo($OnlyFileName); - if (in_array(strtolower($fileinfo['extension']), $ext)) - { - copy('zip://'.$path.'#'.$OnlyFileName, $base_folder.$FullFileName['name']); - } - } - } - $zip->close(); - } - else - echo 'failed to open file'; - break; - case 'gz': - $p = new PharData($path); - $p->decompress(); // creates files.tar - break; - case 'tar': - // unarchive from the tar - $phar = new PharData($path); - $phar->decompressFiles(); - $files = array(); - check_files_extensions_on_phar($phar, $files, '', $ext); - $phar->extractTo($current_path.fix_dirname($_POST['path']).'/', $files, true); + if (!($FullFileName['name'][strlen($FullFileName['name']) - 1] == '/')) { + $fileinfo = pathinfo($OnlyFileName); + if (in_array(strtolower($fileinfo['extension']), $ext)) { + copy('zip://'.$path.'#'.$OnlyFileName, $base_folder.$FullFileName['name']); + } + } + } + $zip->close(); + } else { + echo 'failed to open file'; + } + break; + case 'gz': + $p = new PharData($path); + $p->decompress(); // creates files.tar + break; + case 'tar': + // unarchive from the tar + $phar = new PharData($path); + $phar->decompressFiles(); + $files = array(); + check_files_extensions_on_phar($phar, $files, '', $ext); + $phar->extractTo($current_path.fix_dirname($_POST['path']).'/', $files, true); - break; - } - break; - case 'media_preview': + break; + } + break; + case 'media_preview': - $preview_file = $_GET['file']; - $info = pathinfo($preview_file); - ?> + $preview_file = $_GET['file']; + $info = pathinfo($preview_file); + ?>
@@ -184,9 +183,8 @@ if (isset($_GET['action']))
+ if (in_array(strtolower($info['extension']), $ext_music)) { + ?> + + } elseif (in_array(strtolower($info['extension']), $ext_video)) { + ?> diff --git a/adm/filemanager/config/config.php b/adm/filemanager/config/config.php index 53f6c7f0..119423e2 100644 --- a/adm/filemanager/config/config.php +++ b/adm/filemanager/config/config.php @@ -1,20 +1,23 @@ employee->id_profile, Tab::getIdFromClassName('AdminProducts')); $cms_accesses = Profile::getProfileAccess(Context::getContext()->employee->id_profile, Tab::getIdFromClassName('AdminCmsContent')); -if (!$products_accesses['edit'] && !$cms_accesses['edit']) - die(Tools::displayError()); +if (!$products_accesses['edit'] && !$cms_accesses['edit']) { + die(Tools::displayError()); +} //------------------------------------------------------------------------------ // DON'T COPY THIS VARIABLES IN FOLDERS config.php FILES //------------------------------------------------------------------------------ @@ -105,7 +108,7 @@ $ext_video = array('mov', 'mpeg', 'mp4', 'avi', 'mpg', 'wma', 'flv', 'webm'); // $ext_music = array();//array('mp3', 'm4a', 'ac3', 'aiff', 'mid','ogg','wav'); //Audio $ext_misc = array();// array('zip', 'rar','gz','tar','iso','dmg'); //Archives -$ext=array_merge($ext_img, $ext_file, $ext_misc, $ext_video,$ext_music); //allowed extensions +$ext=array_merge($ext_img, $ext_file, $ext_misc, $ext_video, $ext_music); //allowed extensions /****************** @@ -167,5 +170,3 @@ $relative_image_creation_name_to_prepend= array('','test_'); //name to prepend o $relative_image_creation_name_to_append = array('_test',''); //name to append on filename $relative_image_creation_width = array(300,400); //width of image (you can leave empty if you set height) $relative_image_creation_height = array(200,''); //height of image (you can leave empty if you set width) - -?> diff --git a/adm/filemanager/dialog.php b/adm/filemanager/dialog.php index d2888ae3..b67d1954 100644 --- a/adm/filemanager/dialog.php +++ b/adm/filemanager/dialog.php @@ -3,152 +3,178 @@ include('config/config.php'); $_SESSION["verify"] = "RESPONSIVEfilemanager"; -if (isset($_POST['submit'])) - include('upload.php'); -else -{ - - include('include/utils.php'); +if (isset($_POST['submit'])) { + include('upload.php'); +} else { + include('include/utils.php'); - if (isset($_GET['fldr']) - && !empty($_GET['fldr']) - && preg_match('/\.{1,2}[\/|\\\]/', urldecode($_GET['fldr'])) === 0 - ) - $subdir = str_replace("\0", '', urldecode(trim($_GET['fldr'], '/').'/')); - else - $subdir = ''; + if (isset($_GET['fldr']) + && !empty($_GET['fldr']) + && preg_match('/\.{1,2}[\/|\\\]/', urldecode($_GET['fldr'])) === 0 + ) { + $subdir = str_replace("\0", '', urldecode(trim($_GET['fldr'], '/').'/')); + } else { + $subdir = ''; + } //remember last position - setcookie('last_position', $subdir, time() + (86400 * 7)); + setcookie('last_position', $subdir, time() + (86400 * 7)); - if ($subdir == '') - { - if (!empty($_COOKIE['last_position']) - && strpos($_COOKIE['last_position'], '.') === false - ) - $subdir = trim($_COOKIE['last_position']); - } + if ($subdir == '') { + if (!empty($_COOKIE['last_position']) + && strpos($_COOKIE['last_position'], '.') === false + ) { + $subdir = trim($_COOKIE['last_position']); + } + } - if ($subdir == '/') - $subdir = ''; + if ($subdir == '/') { + $subdir = ''; + } - /*** - *SUB-DIR CODE - ***/ - if (!isset($_SESSION['subfolder'])) $_SESSION['subfolder'] = ''; - $subfolder = ''; - if (!empty($_SESSION['subfolder']) && strpos($_SESSION['subfolder'], '../') === false - && strpos($_SESSION['subfolder'], './') === false && strpos($_SESSION['subfolder'], '/') !== 0 - && strpos($_SESSION['subfolder'], '.') === false - ) $subfolder = $_SESSION['subfolder']; + /*** + *SUB-DIR CODE + ***/ + if (!isset($_SESSION['subfolder'])) { + $_SESSION['subfolder'] = ''; + } + $subfolder = ''; + if (!empty($_SESSION['subfolder']) && strpos($_SESSION['subfolder'], '../') === false + && strpos($_SESSION['subfolder'], './') === false && strpos($_SESSION['subfolder'], '/') !== 0 + && strpos($_SESSION['subfolder'], '.') === false + ) { + $subfolder = $_SESSION['subfolder']; + } - if ($subfolder != '' && $subfolder[strlen($subfolder) - 1] != '/') $subfolder .= '/'; + if ($subfolder != '' && $subfolder[strlen($subfolder) - 1] != '/') { + $subfolder .= '/'; + } - if (!file_exists($current_path.$subfolder.$subdir)) - { - $subdir = ''; - if (!file_exists($current_path.$subfolder.$subdir)) - $subfolder = ''; - } + if (!file_exists($current_path.$subfolder.$subdir)) { + $subdir = ''; + if (!file_exists($current_path.$subfolder.$subdir)) { + $subfolder = ''; + } + } - if (trim($subfolder) == '') - { - $cur_dir = $upload_dir.$subdir; - $cur_path = $current_path.$subdir; - $thumbs_path = $thumbs_base_path; - $parent = $subdir; - } else - { - $cur_dir = $upload_dir.$subfolder.$subdir; - $cur_path = $current_path.$subfolder.$subdir; - $thumbs_path = $thumbs_base_path.$subfolder; - $parent = $subfolder.$subdir; - } + if (trim($subfolder) == '') { + $cur_dir = $upload_dir.$subdir; + $cur_path = $current_path.$subdir; + $thumbs_path = $thumbs_base_path; + $parent = $subdir; + } else { + $cur_dir = $upload_dir.$subfolder.$subdir; + $cur_path = $current_path.$subfolder.$subdir; + $thumbs_path = $thumbs_base_path.$subfolder; + $parent = $subfolder.$subdir; + } - $cycle = true; - $max_cycles = 50; - $i = 0; - while ($cycle && $i < $max_cycles) - { - $i++; - if ($parent == './') $parent = ''; - if (file_exists($current_path.$parent.'config.php')) - { - require_once($current_path.$parent.'config.php'); - $cycle = false; - } + $cycle = true; + $max_cycles = 50; + $i = 0; + while ($cycle && $i < $max_cycles) { + $i++; + if ($parent == './') { + $parent = ''; + } + if (file_exists($current_path.$parent.'config.php')) { + require_once($current_path.$parent.'config.php'); + $cycle = false; + } - if ($parent == '') $cycle = false; - else $parent = fix_dirname($parent).'/'; - } + if ($parent == '') { + $cycle = false; + } else { + $parent = fix_dirname($parent).'/'; + } + } - if (!is_dir($thumbs_path.$subdir)) - { - create_folder(false, $thumbs_path.$subdir); - } + if (!is_dir($thumbs_path.$subdir)) { + create_folder(false, $thumbs_path.$subdir); + } - if (isset($_GET['popup'])) $popup = $_GET['popup']; else $popup = 0; + if (isset($_GET['popup'])) { + $popup = $_GET['popup']; + } else { + $popup = 0; + } //Sanitize popup - $popup = !!$popup; + $popup = !!$popup; //view type - if (!isset($_SESSION['view_type'])) - { - $view = $default_view; - $_SESSION['view_type'] = $view; - } - if (isset($_GET['view'])) - { - $view = $_GET['view']; - $_SESSION['view_type'] = $view; - } - $view = $_SESSION['view_type']; + if (!isset($_SESSION['view_type'])) { + $view = $default_view; + $_SESSION['view_type'] = $view; + } + if (isset($_GET['view'])) { + $view = $_GET['view']; + $_SESSION['view_type'] = $view; + } + $view = $_SESSION['view_type']; - if (isset($_GET['filter'])) $filter = fix_filename($_GET['filter'], $transliteration); - else $filter = ''; + if (isset($_GET['filter'])) { + $filter = fix_filename($_GET['filter'], $transliteration); + } else { + $filter = ''; + } - if (!isset($_SESSION['sort_by'])) $_SESSION['sort_by'] = ''; - if (isset($_GET['sort_by'])) $sort_by = $_SESSION['sort_by'] = fix_filename($_GET['sort_by'], $transliteration); - else $sort_by = $_SESSION['sort_by']; + if (!isset($_SESSION['sort_by'])) { + $_SESSION['sort_by'] = ''; + } + if (isset($_GET['sort_by'])) { + $sort_by = $_SESSION['sort_by'] = fix_filename($_GET['sort_by'], $transliteration); + } else { + $sort_by = $_SESSION['sort_by']; + } - if (!isset($_SESSION['descending'])) $_SESSION['descending'] = false; - if (isset($_GET['descending'])) $descending = $_SESSION['descending'] = fix_filename($_GET['descending'], $transliteration) === 'true'; - else $descending = $_SESSION['descending']; + if (!isset($_SESSION['descending'])) { + $_SESSION['descending'] = false; + } + if (isset($_GET['descending'])) { + $descending = $_SESSION['descending'] = fix_filename($_GET['descending'], $transliteration) === 'true'; + } else { + $descending = $_SESSION['descending']; + } - $lang = $default_language; - if (isset($_GET['lang']) && $_GET['lang'] != 'undefined' && $_GET['lang'] != '') - $lang = $_GET['lang']; + $lang = $default_language; + if (isset($_GET['lang']) && $_GET['lang'] != 'undefined' && $_GET['lang'] != '') { + $lang = $_GET['lang']; + } - $language_file = 'lang/'.$default_language.'.php'; - if ($lang != $default_language) - { - $path_parts = pathinfo($lang); - if (is_readable('lang/'.$path_parts['basename'].'.php')) - $language_file = 'lang/'.$path_parts['basename'].'.php'; - else - $lang = $default_language; - } + $language_file = 'lang/'.$default_language.'.php'; + if ($lang != $default_language) { + $path_parts = pathinfo($lang); + if (is_readable('lang/'.$path_parts['basename'].'.php')) { + $language_file = 'lang/'.$path_parts['basename'].'.php'; + } else { + $lang = $default_language; + } + } - require_once $language_file; + require_once $language_file; - if (!isset($_GET['type'])) $_GET['type'] = 0; - if (!isset($_GET['field_id'])) $_GET['field_id'] = ''; + if (!isset($_GET['type'])) { + $_GET['type'] = 0; + } + if (!isset($_GET['field_id'])) { + $_GET['field_id'] = ''; + } - $get_params = http_build_query( - array( - 'type' => Tools::safeOutput($_GET['type']), - 'lang' => Tools::safeOutput($lang), - 'popup' => $popup, - 'field_id' => isset($_GET['field_id']) ? (int)$_GET['field_id'] : '', - 'fldr' => '' - ) - ); - ?> + $get_params = http_build_query( + array( + 'type' => Tools::safeOutput($_GET['type']), + 'lang' => Tools::safeOutput($lang), + 'popup' => $popup, + 'field_id' => isset($_GET['field_id']) ? (int)$_GET['field_id'] : '', + 'fldr' => '' + ) + ); + ?> @@ -192,17 +218,19 @@ else + if ($aviary_active) { + if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) { + ?> - + + + } + } + ?>
@@ -309,140 +372,166 @@ else
- +
- +
- - + +
:
- - - - - - - + + + + + + +
-
- +
+
-
+
- +
- +
$file) - { - if ($file == ".") $current_folder = array('file' => $file); - elseif ($file == "..") $prev_folder = array('file' => $file); - elseif (is_dir($current_path.$subfolder.$subdir.$file)) - { - $date = filemtime($current_path.$subfolder.$subdir.$file); - $size = foldersize($current_path.$subfolder.$subdir.$file); - $file_ext = lang_Type_dir; - $sorted[$k] = array('file' => $file, 'date' => $date, 'size' => $size, 'extension' => $file_ext); - } else - { - $file_path = $current_path.$subfolder.$subdir.$file; - $date = filemtime($file_path); - $size = filesize($file_path); - $file_ext = substr(strrchr($file, '.'), 1); - $sorted[$k] = array('file' => $file, 'date' => $date, 'size' => $size, 'extension' => $file_ext); - } - } + //php sorting + $sorted = array(); + $current_folder = array(); + $prev_folder = array(); + foreach ($files as $k => $file) { + if ($file == ".") { + $current_folder = array('file' => $file); + } elseif ($file == "..") { + $prev_folder = array('file' => $file); + } elseif (is_dir($current_path.$subfolder.$subdir.$file)) { + $date = filemtime($current_path.$subfolder.$subdir.$file); + $size = foldersize($current_path.$subfolder.$subdir.$file); + $file_ext = lang_Type_dir; + $sorted[$k] = array('file' => $file, 'date' => $date, 'size' => $size, 'extension' => $file_ext); + } else { + $file_path = $current_path.$subfolder.$subdir.$file; + $date = filemtime($file_path); + $size = filesize($file_path); + $file_ext = substr(strrchr($file, '.'), 1); + $sorted[$k] = array('file' => $file, 'date' => $date, 'size' => $size, 'extension' => $file_ext); + } + } - function filenameSort($x, $y) - { - return $x['file'] < $y['file']; - } + function filenameSort($x, $y) + { + return $x['file'] < $y['file']; + } - function dateSort($x, $y) - { - return $x['date'] < $y['date']; - } + function dateSort($x, $y) + { + return $x['date'] < $y['date']; + } - function sizeSort($x, $y) - { - return $x['size'] - $y['size']; - } + function sizeSort($x, $y) + { + return $x['size'] - $y['size']; + } - function extensionSort($x, $y) - { - return $x['extension'] < $y['extension']; - } + function extensionSort($x, $y) + { + return $x['extension'] < $y['extension']; + } - switch ($sort_by) - { - case 'name': - usort($sorted, 'filenameSort'); - break; - case 'date': - usort($sorted, 'dateSort'); - break; - case 'size': - usort($sorted, 'sizeSort'); - break; - case 'extension': - usort($sorted, 'extensionSort'); - break; - default: - break; + switch ($sort_by) { + case 'name': + usort($sorted, 'filenameSort'); + break; + case 'date': + usort($sorted, 'dateSort'); + break; + case 'size': + usort($sorted, 'sizeSort'); + break; + case 'extension': + usort($sorted, 'extensionSort'); + break; + default: + break; - } + } - if ($descending) - { - $sorted = array_reverse($sorted); - } + if ($descending) { + $sorted = array_reverse($sorted); + } - $files = array(); - if (!empty($prev_folder)) - $files = array($prev_folder); - if (!empty($current_folder)) - $files = array_merge($files, array($current_folder)); - $files = array_merge($files, $sorted); - ?> + $files = array(); + if (!empty($prev_folder)) { + $files = array($prev_folder); + } + if (!empty($current_folder)) { + $files = array_merge($files, array($current_folder)); + } + $files = array_merge($files, $sorted); + ?> '; + echo $html; + } - /** - * Get current URL - * - * @param array $remove List of keys to remove from URL - * @return string - */ - protected function getCurrentUrl($remove = array()) - { - $url = $_SERVER['REQUEST_URI']; - if (!$remove) - return $url; + /** + * Get current URL + * + * @param array $remove List of keys to remove from URL + * @return string + */ + protected function getCurrentUrl($remove = array()) + { + $url = $_SERVER['REQUEST_URI']; + if (!$remove) { + return $url; + } - if (!is_array($remove)) - $remove = array($remove); + if (!is_array($remove)) { + $remove = array($remove); + } - $url = preg_replace('#(?<=&|\?)('.implode('|', $remove).')=.*?(&|$)#i', '', $url); - $len = Tools::strlen($url); - if ($url[$len - 1] == '&') - $url = Tools::substr($url, 0, $len - 1); - return $url; - } + $url = preg_replace('#(?<=&|\?)('.implode('|', $remove).')=.*?(&|$)#i', '', $url); + $len = Tools::strlen($url); + if ($url[$len - 1] == '&') { + $url = Tools::substr($url, 0, $len - 1); + } + return $url; + } } diff --git a/classes/Alias.php b/classes/Alias.php index ba42231e..c2778a23 100644 --- a/classes/Alias.php +++ b/classes/Alias.php @@ -26,122 +26,114 @@ class AliasCore extends ObjectModel { - public $alias; - public $search; - public $active = true; + public $alias; + public $search; + public $active = true; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'alias', - 'primary' => 'id_alias', - 'fields' => array( - 'search' => array('type' => self::TYPE_STRING, 'validate' => 'isValidSearch', 'required' => true, 'size' => 255), - 'alias' => array('type' => self::TYPE_STRING, 'validate' => 'isValidSearch', 'required' => true, 'size' => 255), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'alias', + 'primary' => 'id_alias', + 'fields' => array( + 'search' => array('type' => self::TYPE_STRING, 'validate' => 'isValidSearch', 'required' => true, 'size' => 255), + 'alias' => array('type' => self::TYPE_STRING, 'validate' => 'isValidSearch', 'required' => true, 'size' => 255), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + ), + ); - public function __construct($id = null, $alias = null, $search = null, $id_lang = null) - { - $this->def = Alias::getDefinition($this); - $this->setDefinitionRetrocompatibility(); + public function __construct($id = null, $alias = null, $search = null, $id_lang = null) + { + $this->def = Alias::getDefinition($this); + $this->setDefinitionRetrocompatibility(); - if ($id) - parent::__construct($id); - elseif ($alias && Validate::isValidSearch($alias)) - { - if (!Alias::isFeatureActive()) - { - $this->alias = trim($alias); - $this->search = trim($search); - } - else - { - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + if ($id) { + parent::__construct($id); + } elseif ($alias && Validate::isValidSearch($alias)) { + if (!Alias::isFeatureActive()) { + $this->alias = trim($alias); + $this->search = trim($search); + } else { + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT a.id_alias, a.search, a.alias FROM `'._DB_PREFIX_.'alias` a WHERE `alias` = \''.pSQL($alias).'\' AND `active` = 1'); - if ($row) - { - $this->id = (int)$row['id_alias']; - $this->search = $search ? trim($search) : $row['search']; - $this->alias = $row['alias']; - } - else - { - $this->alias = trim($alias); - $this->search = trim($search); - } - } - } - } + if ($row) { + $this->id = (int)$row['id_alias']; + $this->search = $search ? trim($search) : $row['search']; + $this->alias = $row['alias']; + } else { + $this->alias = trim($alias); + $this->search = trim($search); + } + } + } + } - public function add($autodate = true, $nullValues = false) - { - $this->alias = Tools::replaceAccentedChars($this->alias); - $this->search = Tools::replaceAccentedChars($this->search); + public function add($autodate = true, $nullValues = false) + { + $this->alias = Tools::replaceAccentedChars($this->alias); + $this->search = Tools::replaceAccentedChars($this->search); - if (parent::add($autodate, $nullValues)) - { - // Set cache of feature detachable to true - Configuration::updateGlobalValue('PS_ALIAS_FEATURE_ACTIVE', '1'); - return true; - } - return false; - } + if (parent::add($autodate, $nullValues)) { + // Set cache of feature detachable to true + Configuration::updateGlobalValue('PS_ALIAS_FEATURE_ACTIVE', '1'); + return true; + } + return false; + } - public function delete() - { - if (parent::delete()) - { - // Refresh cache of feature detachable - Configuration::updateGlobalValue('PS_ALIAS_FEATURE_ACTIVE', Alias::isCurrentlyUsed($this->def['table'], true)); - return true; - } - return false; - } + public function delete() + { + if (parent::delete()) { + // Refresh cache of feature detachable + Configuration::updateGlobalValue('PS_ALIAS_FEATURE_ACTIVE', Alias::isCurrentlyUsed($this->def['table'], true)); + return true; + } + return false; + } - public function getAliases() - { - if (!Alias::isFeatureActive()) - return ''; + public function getAliases() + { + if (!Alias::isFeatureActive()) { + return ''; + } - $aliases = Db::getInstance()->executeS(' + $aliases = Db::getInstance()->executeS(' SELECT a.alias FROM `'._DB_PREFIX_.'alias` a WHERE `search` = \''.pSQL($this->search).'\''); - $aliases = array_map('implode', $aliases); - return implode(', ', $aliases); - } + $aliases = array_map('implode', $aliases); + return implode(', ', $aliases); + } - /** - * This method is allow to know if a feature is used or active - * @since 1.5.0.1 - * @return bool - */ - public static function isFeatureActive() - { - return Configuration::get('PS_ALIAS_FEATURE_ACTIVE'); - } + /** + * This method is allow to know if a feature is used or active + * @since 1.5.0.1 + * @return bool + */ + public static function isFeatureActive() + { + return Configuration::get('PS_ALIAS_FEATURE_ACTIVE'); + } - /** - * This method is allow to know if a alias exist for AdminImportController - * @since 1.5.6.0 - * @return bool - */ - public static function aliasExists($id_alias) - { - $row = Db::getInstance()->getRow(' + /** + * This method is allow to know if a alias exist for AdminImportController + * @since 1.5.6.0 + * @return bool + */ + public static function aliasExists($id_alias) + { + $row = Db::getInstance()->getRow(' SELECT `id_alias` FROM '._DB_PREFIX_.'alias a WHERE a.`id_alias` = '.(int)$id_alias - ); + ); - return isset($row['id_alias']); - } -} \ No newline at end of file + return isset($row['id_alias']); + } +} diff --git a/classes/Attachment.php b/classes/Attachment.php index f432d1ab..de45a20f 100644 --- a/classes/Attachment.php +++ b/classes/Attachment.php @@ -26,78 +26,78 @@ class AttachmentCore extends ObjectModel { - public $file; - public $file_name; - public $file_size; - public $name; - public $mime; - public $description; + public $file; + public $file_name; + public $file_size; + public $name; + public $mime; + public $description; - /** @var int position */ - public $position; + /** @var int position */ + public $position; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'attachment', - 'primary' => 'id_attachment', - 'multilang' => true, - 'fields' => array( - 'file' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 40), - 'mime' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'required' => true, 'size' => 128), - 'file_name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 128), - 'file_size' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'attachment', + 'primary' => 'id_attachment', + 'multilang' => true, + 'fields' => array( + 'file' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 40), + 'mime' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'required' => true, 'size' => 128), + 'file_name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 128), + 'file_size' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), - 'description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCleanHtml'), - ), - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), + 'description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCleanHtml'), + ), + ); - public function add($autodate = true, $null_values = false) - { - $this->file_size = filesize(_PS_DOWNLOAD_DIR_.$this->file); - return parent::add($autodate, $null_values); - } + public function add($autodate = true, $null_values = false) + { + $this->file_size = filesize(_PS_DOWNLOAD_DIR_.$this->file); + return parent::add($autodate, $null_values); + } - public function update($null_values = false) - { - $this->file_size = filesize(_PS_DOWNLOAD_DIR_.$this->file); - return parent::update($null_values); - } + public function update($null_values = false) + { + $this->file_size = filesize(_PS_DOWNLOAD_DIR_.$this->file); + return parent::update($null_values); + } - public function delete() - { - @unlink(_PS_DOWNLOAD_DIR_.$this->file); + public function delete() + { + @unlink(_PS_DOWNLOAD_DIR_.$this->file); - $products = Db::getInstance()->executeS(' + $products = Db::getInstance()->executeS(' SELECT id_product FROM '._DB_PREFIX_.'product_attachment WHERE id_attachment = '.(int)$this->id); - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'product_attachment WHERE id_attachment = '.(int)$this->id); + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'product_attachment WHERE id_attachment = '.(int)$this->id); - foreach ($products as $product) - Product::updateCacheAttachment((int)$product['id_product']); + foreach ($products as $product) { + Product::updateCacheAttachment((int)$product['id_product']); + } - return parent::delete(); - } + return parent::delete(); + } - public function deleteSelection($attachments) - { - $return = 1; - foreach ($attachments as $id_attachment) - { - $attachment = new Attachment((int)$id_attachment); - $return &= $attachment->delete(); - } - return $return; - } + public function deleteSelection($attachments) + { + $return = 1; + foreach ($attachments as $id_attachment) { + $attachment = new Attachment((int)$id_attachment); + $return &= $attachment->delete(); + } + return $return; + } - public static function getAttachments($id_lang, $id_product, $include = true) - { - return Db::getInstance()->executeS(' + public static function getAttachments($id_lang, $id_product, $include = true) + { + return Db::getInstance()->executeS(' SELECT * FROM '._DB_PREFIX_.'attachment a LEFT JOIN '._DB_PREFIX_.'attachment_lang al @@ -107,94 +107,97 @@ class AttachmentCore extends ObjectModel FROM '._DB_PREFIX_.'product_attachment pa WHERE id_product = '.(int)$id_product.' )' - ); - } + ); + } - /** - * Unassociate $id_product from the current object - * - * @param $id_product int - * @return bool - */ - public static function deleteProductAttachments($id_product) - { - $res = Db::getInstance()->execute(' + /** + * Unassociate $id_product from the current object + * + * @param $id_product int + * @return bool + */ + public static function deleteProductAttachments($id_product) + { + $res = Db::getInstance()->execute(' DELETE FROM '._DB_PREFIX_.'product_attachment WHERE id_product = '.(int)$id_product); - Product::updateCacheAttachment((int)$id_product); + Product::updateCacheAttachment((int)$id_product); - return $res; - } + return $res; + } - /** - * associate $id_product to the current object. - * - * @param int $id_product id of the product to associate - * @return bool true if succed - */ - public function attachProduct($id_product) - { - $res = Db::getInstance()->execute(' + /** + * associate $id_product to the current object. + * + * @param int $id_product id of the product to associate + * @return bool true if succed + */ + public function attachProduct($id_product) + { + $res = Db::getInstance()->execute(' INSERT INTO '._DB_PREFIX_.'product_attachment (id_attachment, id_product) VALUES ('.(int)$this->id.', '.(int)$id_product.')'); - Product::updateCacheAttachment((int)$id_product); + Product::updateCacheAttachment((int)$id_product); - return $res; - } + return $res; + } - /** - * Associate an array of id_attachment $array to the product $id_product - * and remove eventual previous association - * - * @param $id_product - * @param $array - * @return bool - */ - public static function attachToProduct($id_product, $array) - { - $result1 = Attachment::deleteProductAttachments($id_product); + /** + * Associate an array of id_attachment $array to the product $id_product + * and remove eventual previous association + * + * @param $id_product + * @param $array + * @return bool + */ + public static function attachToProduct($id_product, $array) + { + $result1 = Attachment::deleteProductAttachments($id_product); - if (is_array($array)) - { - $ids = array(); - foreach ($array as $id_attachment) - if ((int)$id_attachment > 0) - $ids[] = array('id_product' => (int)$id_product, 'id_attachment' => (int)$id_attachment); + if (is_array($array)) { + $ids = array(); + foreach ($array as $id_attachment) { + if ((int)$id_attachment > 0) { + $ids[] = array('id_product' => (int)$id_product, 'id_attachment' => (int)$id_attachment); + } + } - if (!empty($ids)) - $result2 = Db::getInstance()->insert('product_attachment', $ids); + if (!empty($ids)) { + $result2 = Db::getInstance()->insert('product_attachment', $ids); + } + } - } + Product::updateCacheAttachment((int)$id_product); + if (is_array($array)) { + return ($result1 && (!isset($result2) || $result2)); + } - Product::updateCacheAttachment((int)$id_product); - if (is_array($array)) - return ($result1 && (!isset($result2) || $result2)); + return $result1; + } - return $result1; - } + public static function getProductAttached($id_lang, $list) + { + $ids_attachements = array(); + if (is_array($list)) { + foreach ($list as $attachement) { + $ids_attachements[] = $attachement['id_attachment']; + } - public static function getProductAttached($id_lang, $list) - { - $ids_attachements = array(); - if (is_array($list)) - { - foreach ($list as $attachement) - $ids_attachements[] = $attachement['id_attachment']; - - $sql = 'SELECT * FROM `'._DB_PREFIX_.'product_attachment` pa + $sql = 'SELECT * FROM `'._DB_PREFIX_.'product_attachment` pa LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (pa.`id_product` = pl.`id_product`'.Shop::addSqlRestrictionOnLang('pl').') WHERE `id_attachment` IN ('.implode(',', array_map('intval', $ids_attachements)).') AND pl.`id_lang` = '.(int)$id_lang; - $tmp = Db::getInstance()->executeS($sql); - $product_attachements = array(); - foreach ($tmp as $t) - $product_attachements[$t['id_attachment']][] = $t['name']; - return $product_attachements; - } - else - return false; - } -} \ No newline at end of file + $tmp = Db::getInstance()->executeS($sql); + $product_attachements = array(); + foreach ($tmp as $t) { + $product_attachements[$t['id_attachment']][] = $t['name']; + } + return $product_attachements; + } else { + return false; + } + } +} diff --git a/classes/Attribute.php b/classes/Attribute.php index f6f3647e..0ceedb32 100644 --- a/classes/Attribute.php +++ b/classes/Attribute.php @@ -26,127 +26,131 @@ class AttributeCore extends ObjectModel { - /** @var int Group id which attribute belongs */ - public $id_attribute_group; + /** @var int Group id which attribute belongs */ + public $id_attribute_group; - /** @var string Name */ - public $name; - public $color; - public $position; - public $default; + /** @var string Name */ + public $name; + public $color; + public $position; + public $default; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'attribute', - 'primary' => 'id_attribute', - 'multilang' => true, - 'fields' => array( - 'id_attribute_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'color' => array('type' => self::TYPE_STRING, 'validate' => 'isColor'), - 'position' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'attribute', + 'primary' => 'id_attribute', + 'multilang' => true, + 'fields' => array( + 'id_attribute_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'color' => array('type' => self::TYPE_STRING, 'validate' => 'isColor'), + 'position' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), - ) - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), + ) + ); - protected $image_dir = _PS_COL_IMG_DIR_; + protected $image_dir = _PS_COL_IMG_DIR_; - protected $webserviceParameters = array( - 'objectsNodeName' => 'product_option_values', - 'objectNodeName' => 'product_option_value', - 'fields' => array( - 'id_attribute_group' => array('xlink_resource'=> 'product_options'), - ) - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'product_option_values', + 'objectNodeName' => 'product_option_value', + 'fields' => array( + 'id_attribute_group' => array('xlink_resource'=> 'product_options'), + ) + ); - public function __construct($id = null, $id_lang = null, $id_shop = null) - { - $this->image_dir = _PS_COL_IMG_DIR_; + public function __construct($id = null, $id_lang = null, $id_shop = null) + { + $this->image_dir = _PS_COL_IMG_DIR_; - parent::__construct($id, $id_lang, $id_shop); - } + parent::__construct($id, $id_lang, $id_shop); + } - public function delete() - { - if (!$this->hasMultishopEntries() || Shop::getContext() == Shop::CONTEXT_ALL) - { - $result = Db::getInstance()->executeS('SELECT id_product_attribute FROM '._DB_PREFIX_.'product_attribute_combination WHERE id_attribute = '.(int)$this->id); - $products = array(); + public function delete() + { + if (!$this->hasMultishopEntries() || Shop::getContext() == Shop::CONTEXT_ALL) { + $result = Db::getInstance()->executeS('SELECT id_product_attribute FROM '._DB_PREFIX_.'product_attribute_combination WHERE id_attribute = '.(int)$this->id); + $products = array(); - foreach ($result as $row) - { - $combination = new Combination($row['id_product_attribute']); - $new_request = Db::getInstance()->executeS('SELECT id_product, default_on FROM '._DB_PREFIX_.'product_attribute WHERE id_product_attribute = '.(int)$row['id_product_attribute']); - foreach ($new_request as $value) - if ($value['default_on'] == 1) - $products[] = $value['id_product']; - $combination->delete(); - } + foreach ($result as $row) { + $combination = new Combination($row['id_product_attribute']); + $new_request = Db::getInstance()->executeS('SELECT id_product, default_on FROM '._DB_PREFIX_.'product_attribute WHERE id_product_attribute = '.(int)$row['id_product_attribute']); + foreach ($new_request as $value) { + if ($value['default_on'] == 1) { + $products[] = $value['id_product']; + } + } + $combination->delete(); + } - foreach ($products as $product) - { - $result = Db::getInstance()->executeS('SELECT id_product_attribute FROM '._DB_PREFIX_.'product_attribute WHERE id_product = '.(int)$product.' LIMIT 1'); - foreach ($result as $row) - if (Validate::isLoadedObject($product = new Product((int)$product))) - { - $product->deleteDefaultAttributes(); - $product->setDefaultAttribute($row['id_product_attribute']); - } - } + foreach ($products as $product) { + $result = Db::getInstance()->executeS('SELECT id_product_attribute FROM '._DB_PREFIX_.'product_attribute WHERE id_product = '.(int)$product.' LIMIT 1'); + foreach ($result as $row) { + if (Validate::isLoadedObject($product = new Product((int)$product))) { + $product->deleteDefaultAttributes(); + $product->setDefaultAttribute($row['id_product_attribute']); + } + } + } - // Delete associated restrictions on cart rules - CartRule::cleanProductRuleIntegrity('attributes', $this->id); + // Delete associated restrictions on cart rules + CartRule::cleanProductRuleIntegrity('attributes', $this->id); - /* Reinitializing position */ - $this->cleanPositions((int)$this->id_attribute_group); - } - $return = parent::delete(); - if ($return) - Hook::exec('actionAttributeDelete', array('id_attribute' => $this->id)); + /* Reinitializing position */ + $this->cleanPositions((int)$this->id_attribute_group); + } + $return = parent::delete(); + if ($return) { + Hook::exec('actionAttributeDelete', array('id_attribute' => $this->id)); + } - return $return; - } + return $return; + } - public function update($null_values = false) - { - $return = parent::update($null_values); + public function update($null_values = false) + { + $return = parent::update($null_values); - if ($return) - Hook::exec('actionAttributeSave', array('id_attribute' => $this->id)); + if ($return) { + Hook::exec('actionAttributeSave', array('id_attribute' => $this->id)); + } - return $return; - } + return $return; + } - public function add($autodate = true, $null_values = false) - { - if ($this->position <= 0) - $this->position = Attribute::getHigherPosition($this->id_attribute_group) + 1; + public function add($autodate = true, $null_values = false) + { + if ($this->position <= 0) { + $this->position = Attribute::getHigherPosition($this->id_attribute_group) + 1; + } - $return = parent::add($autodate, $null_values); + $return = parent::add($autodate, $null_values); - if ($return) - Hook::exec('actionAttributeSave', array('id_attribute' => $this->id)); + if ($return) { + Hook::exec('actionAttributeSave', array('id_attribute' => $this->id)); + } - return $return; - } + return $return; + } - /** - * Get all attributes for a given language - * - * @param int $id_lang Language id - * @param bool $notNull Get only not null fields if true - * @return array Attributes - */ - public static function getAttributes($id_lang, $not_null = false) - { - if (!Combination::isFeatureActive()) - return array(); + /** + * Get all attributes for a given language + * + * @param int $id_lang Language id + * @param bool $notNull Get only not null fields if true + * @return array Attributes + */ + public static function getAttributes($id_lang, $not_null = false) + { + if (!Combination::isFeatureActive()) { + return array(); + } - return Db::getInstance()->executeS(' + return Db::getInstance()->executeS(' SELECT DISTINCT ag.*, agl.*, a.`id_attribute`, al.`name`, agl.`name` AS `attribute_group` FROM `'._DB_PREFIX_.'attribute_group` ag LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl @@ -160,14 +164,15 @@ class AttributeCore extends ObjectModel '.($not_null ? 'WHERE a.`id_attribute` IS NOT NULL AND al.`name` IS NOT NULL AND agl.`id_attribute_group` IS NOT NULL' : '').' ORDER BY agl.`name` ASC, a.`position` ASC '); - } + } - public static function isAttribute($id_attribute_group, $name, $id_lang) - { - if (!Combination::isFeatureActive()) - return array(); + public static function isAttribute($id_attribute_group, $name, $id_lang) + { + if (!Combination::isFeatureActive()) { + return array(); + } - $result = Db::getInstance()->getValue(' + $result = Db::getInstance()->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'attribute_group` ag LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl @@ -182,189 +187,198 @@ class AttributeCore extends ObjectModel ORDER BY agl.`name` ASC, a.`position` ASC '); - return ((int)$result > 0); - } + return ((int)$result > 0); + } - /** - * Get quantity for a given attribute combination - * Check if quantity is enough to deserve customer - * - * @param int $id_product_attribute Product attribute combination id - * @param int $qty Quantity needed - * @return bool Quantity is available or not - */ - public static function checkAttributeQty($id_product_attribute, $qty, Shop $shop = null) - { - if (!$shop) - $shop = Context::getContext()->shop; + /** + * Get quantity for a given attribute combination + * Check if quantity is enough to deserve customer + * + * @param int $id_product_attribute Product attribute combination id + * @param int $qty Quantity needed + * @return bool Quantity is available or not + */ + public static function checkAttributeQty($id_product_attribute, $qty, Shop $shop = null) + { + if (!$shop) { + $shop = Context::getContext()->shop; + } - $result = StockAvailable::getQuantityAvailableByProduct(null, (int)$id_product_attribute, $shop->id); + $result = StockAvailable::getQuantityAvailableByProduct(null, (int)$id_product_attribute, $shop->id); - return ($result && $qty <= $result); - } + return ($result && $qty <= $result); + } - /** - * @deprecated 1.5.0, use StockAvailable::getQuantityAvailableByProduct() - */ - public static function getAttributeQty($id_product) - { - Tools::displayAsDeprecated(); + /** + * @deprecated 1.5.0, use StockAvailable::getQuantityAvailableByProduct() + */ + public static function getAttributeQty($id_product) + { + Tools::displayAsDeprecated(); - return StockAvailable::getQuantityAvailableByProduct($id_product); - } + return StockAvailable::getQuantityAvailableByProduct($id_product); + } - /** - * Update array with veritable quantity - * - * @deprecated since 1.5.0 - * @param array &$arr - * @return bool - */ - public static function updateQtyProduct(&$arr) - { - Tools::displayAsDeprecated(); + /** + * Update array with veritable quantity + * + * @deprecated since 1.5.0 + * @param array &$arr + * @return bool + */ + public static function updateQtyProduct(&$arr) + { + Tools::displayAsDeprecated(); - $id_product = (int)$arr['id_product']; - $qty = Attribute::getAttributeQty($id_product); + $id_product = (int)$arr['id_product']; + $qty = Attribute::getAttributeQty($id_product); - if ($qty !== false) - { - $arr['quantity'] = (int)$qty; - return true; - } + if ($qty !== false) { + $arr['quantity'] = (int)$qty; + return true; + } - return false; - } + return false; + } - /** - * Return true if attribute is color type - * - * @acces public - * @return bool - */ - public function isColorAttribute() - { - if (!Db::getInstance()->getRow(' + /** + * Return true if attribute is color type + * + * @acces public + * @return bool + */ + public function isColorAttribute() + { + if (!Db::getInstance()->getRow(' SELECT `group_type` FROM `'._DB_PREFIX_.'attribute_group` WHERE `id_attribute_group` = ( SELECT `id_attribute_group` FROM `'._DB_PREFIX_.'attribute` WHERE `id_attribute` = '.(int)$this->id.') - AND group_type = \'color\'')) - return false; + AND group_type = \'color\'')) { + return false; + } - return Db::getInstance()->numRows(); - } + return Db::getInstance()->numRows(); + } - /** - * Get minimal quantity for product with attributes quantity - * - * @acces public static - * @param int $id_product_attribute - * @return mixed Minimal Quantity or false - */ - public static function getAttributeMinimalQty($id_product_attribute) - { - $minimal_quantity = Db::getInstance()->getValue(' + /** + * Get minimal quantity for product with attributes quantity + * + * @acces public static + * @param int $id_product_attribute + * @return mixed Minimal Quantity or false + */ + public static function getAttributeMinimalQty($id_product_attribute) + { + $minimal_quantity = Db::getInstance()->getValue(' SELECT `minimal_quantity` FROM `'._DB_PREFIX_.'product_attribute_shop` pas WHERE `id_shop` = '.(int)Context::getContext()->shop->id.' AND `id_product_attribute` = '.(int)$id_product_attribute - ); + ); - if ($minimal_quantity > 1) - return (int)$minimal_quantity; + if ($minimal_quantity > 1) { + return (int)$minimal_quantity; + } - return false; - } + return false; + } - /** - * Move an attribute inside its group - * @param bool $way Up (1) or Down (0) - * @param int $position - * @return bool Update result - */ - public function updatePosition($way, $position) - { - if (!$id_attribute_group = (int)Tools::getValue('id_attribute_group')) - $id_attribute_group = (int)$this->id_attribute_group; + /** + * Move an attribute inside its group + * @param bool $way Up (1) or Down (0) + * @param int $position + * @return bool Update result + */ + public function updatePosition($way, $position) + { + if (!$id_attribute_group = (int)Tools::getValue('id_attribute_group')) { + $id_attribute_group = (int)$this->id_attribute_group; + } - $sql = ' + $sql = ' SELECT a.`id_attribute`, a.`position`, a.`id_attribute_group` FROM `'._DB_PREFIX_.'attribute` a WHERE a.`id_attribute_group` = '.(int)$id_attribute_group.' ORDER BY a.`position` ASC'; - if (!$res = Db::getInstance()->executeS($sql)) - return false; + if (!$res = Db::getInstance()->executeS($sql)) { + return false; + } - foreach ($res as $attribute) - if ((int)$attribute['id_attribute'] == (int)$this->id) - $moved_attribute = $attribute; + foreach ($res as $attribute) { + if ((int)$attribute['id_attribute'] == (int)$this->id) { + $moved_attribute = $attribute; + } + } - if (!isset($moved_attribute) || !isset($position)) - return false; + if (!isset($moved_attribute) || !isset($position)) { + return false; + } - // < and > statements rather than BETWEEN operator - // since BETWEEN is treated differently according to databases + // < and > statements rather than BETWEEN operator + // since BETWEEN is treated differently according to databases - $res1 = Db::getInstance()->execute(' + $res1 = Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'attribute` SET `position`= `position` '.($way ? '- 1' : '+ 1').' WHERE `position` '.($way - ? '> '.(int)$moved_attribute['position'].' AND `position` <= '.(int)$position - : '< '.(int)$moved_attribute['position'].' AND `position` >= '.(int)$position).' + ? '> '.(int)$moved_attribute['position'].' AND `position` <= '.(int)$position + : '< '.(int)$moved_attribute['position'].' AND `position` >= '.(int)$position).' AND `id_attribute_group`='.(int)$moved_attribute['id_attribute_group'] - ); + ); - $res2 = Db::getInstance()->execute(' + $res2 = Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'attribute` SET `position` = '.(int)$position.' WHERE `id_attribute` = '.(int)$moved_attribute['id_attribute'].' AND `id_attribute_group`='.(int)$moved_attribute['id_attribute_group'] - ); + ); - return ($res1 && $res2); - } + return ($res1 && $res2); + } - /** - * Reorder attribute position in group $id_attribute_group. - * Call it after deleting an attribute from a group. - * - * @param int $id_attribute_group - * @param bool $use_last_attribute - * @return bool $return - */ - public function cleanPositions($id_attribute_group, $use_last_attribute = true) - { - $sql = 'SET @i = -1; UPDATE `'._DB_PREFIX_.'attribute` SET `position` = @i:=@i+1 WHERE'; + /** + * Reorder attribute position in group $id_attribute_group. + * Call it after deleting an attribute from a group. + * + * @param int $id_attribute_group + * @param bool $use_last_attribute + * @return bool $return + */ + public function cleanPositions($id_attribute_group, $use_last_attribute = true) + { + Db::getInstance()->execute('SET @i = -1', false); + $sql = 'UPDATE `'._DB_PREFIX_.'attribute` SET `position` = @i:=@i+1 WHERE'; - if ($use_last_attribute) - $sql .= ' `id_attribute` != '.(int)$this->id.' AND'; + if ($use_last_attribute) { + $sql .= ' `id_attribute` != '.(int)$this->id.' AND'; + } - $sql .= ' `id_attribute_group` = '.(int)$id_attribute_group.' ORDER BY `position` ASC'; + $sql .= ' `id_attribute_group` = '.(int)$id_attribute_group.' ORDER BY `position` ASC'; - $return = Db::getInstance()->execute($sql); - } + $return = Db::getInstance()->execute($sql); + } - /** - * getHigherPosition - * - * Get the higher attribute position from a group attribute - * - * @param int $id_attribute_group - * @return int $position - */ - public static function getHigherPosition($id_attribute_group) - { - $sql = 'SELECT MAX(`position`) + /** + * getHigherPosition + * + * Get the higher attribute position from a group attribute + * + * @param int $id_attribute_group + * @return int $position + */ + public static function getHigherPosition($id_attribute_group) + { + $sql = 'SELECT MAX(`position`) FROM `'._DB_PREFIX_.'attribute` WHERE id_attribute_group = '.(int)$id_attribute_group; - $position = DB::getInstance()->getValue($sql); + $position = DB::getInstance()->getValue($sql); - return (is_numeric($position)) ? $position : -1; - } + return (is_numeric($position)) ? $position : -1; + } } diff --git a/classes/AttributeGroup.php b/classes/AttributeGroup.php index ee0649a7..593ffc11 100644 --- a/classes/AttributeGroup.php +++ b/classes/AttributeGroup.php @@ -26,151 +26,163 @@ class AttributeGroupCore extends ObjectModel { - /** @var string Name */ - public $name; - public $is_color_group; - public $position; - public $group_type; + /** @var string Name */ + public $name; + public $is_color_group; + public $position; + public $group_type; - /** @var string Public Name */ - public $public_name; + /** @var string Public Name */ + public $public_name; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'attribute_group', - 'primary' => 'id_attribute_group', - 'multilang' => true, - 'fields' => array( - 'is_color_group' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'group_type' => array('type' => self::TYPE_STRING, 'required' => true), - 'position' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'attribute_group', + 'primary' => 'id_attribute_group', + 'multilang' => true, + 'fields' => array( + 'is_color_group' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'group_type' => array('type' => self::TYPE_STRING, 'required' => true), + 'position' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), - 'public_name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), - ), - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), + 'public_name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), + ), + ); - protected $webserviceParameters = array( - 'objectsNodeName' => 'product_options', - 'objectNodeName' => 'product_option', - 'fields' => array(), - 'associations' => array( - 'product_option_values' => array( - 'resource' => 'product_option_value', - 'fields' => array( - 'id' => array() - ), - ), - ), - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'product_options', + 'objectNodeName' => 'product_option', + 'fields' => array(), + 'associations' => array( + 'product_option_values' => array( + 'resource' => 'product_option_value', + 'fields' => array( + 'id' => array() + ), + ), + ), + ); - public function add($autodate = true, $nullValues = false) - { - if ($this->group_type == 'color') - $this->is_color_group = 1; - else - $this->is_color_group = 0; + public function add($autodate = true, $nullValues = false) + { + if ($this->group_type == 'color') { + $this->is_color_group = 1; + } else { + $this->is_color_group = 0; + } - if ($this->position <= 0) - $this->position = AttributeGroup::getHigherPosition() + 1; + if ($this->position <= 0) { + $this->position = AttributeGroup::getHigherPosition() + 1; + } - $return = parent::add($autodate, true); - Hook::exec('actionAttributeGroupSave', array('id_attribute_group' => $this->id)); - return $return; - } + $return = parent::add($autodate, true); + Hook::exec('actionAttributeGroupSave', array('id_attribute_group' => $this->id)); + return $return; + } - public function update($nullValues = false) - { - if ($this->group_type == 'color') - $this->is_color_group = 1; - else - $this->is_color_group = 0; + public function update($nullValues = false) + { + if ($this->group_type == 'color') { + $this->is_color_group = 1; + } else { + $this->is_color_group = 0; + } - $return = parent::update($nullValues); - Hook::exec('actionAttributeGroupSave', array('id_attribute_group' => $this->id)); - return $return; - } + $return = parent::update($nullValues); + Hook::exec('actionAttributeGroupSave', array('id_attribute_group' => $this->id)); + return $return; + } - public static function cleanDeadCombinations() - { - $attribute_combinations = Db::getInstance()->executeS(' + public static function cleanDeadCombinations() + { + $attribute_combinations = Db::getInstance()->executeS(' SELECT pac.`id_attribute`, pa.`id_product_attribute` FROM `'._DB_PREFIX_.'product_attribute` pa LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON (pa.`id_product_attribute` = pac.`id_product_attribute`) '); - $to_remove = array(); - foreach ($attribute_combinations as $attribute_combination) - if ((int)$attribute_combination['id_attribute'] == 0) - $to_remove[] = (int)$attribute_combination['id_product_attribute']; - $return = true; - if (!empty($to_remove)) - foreach ($to_remove as $remove) - { - $combination = new Combination($remove); - $return &= $combination->delete(); - } - return $return; - } + $to_remove = array(); + foreach ($attribute_combinations as $attribute_combination) { + if ((int)$attribute_combination['id_attribute'] == 0) { + $to_remove[] = (int)$attribute_combination['id_product_attribute']; + } + } + $return = true; + if (!empty($to_remove)) { + foreach ($to_remove as $remove) { + $combination = new Combination($remove); + $return &= $combination->delete(); + } + } + return $return; + } - public function delete() - { - if (!$this->hasMultishopEntries() || Shop::getContext() == Shop::CONTEXT_ALL) - { - /* Select children in order to find linked combinations */ - $attribute_ids = Db::getInstance()->executeS(' + public function delete() + { + if (!$this->hasMultishopEntries() || Shop::getContext() == Shop::CONTEXT_ALL) { + /* Select children in order to find linked combinations */ + $attribute_ids = Db::getInstance()->executeS(' SELECT `id_attribute` FROM `'._DB_PREFIX_.'attribute` WHERE `id_attribute_group` = '.(int)$this->id - ); - if ($attribute_ids === false) - return false; - /* Removing attributes to the found combinations */ - $to_remove = array(); - foreach ($attribute_ids as $attribute) - $to_remove[] = (int)$attribute['id_attribute']; - if (!empty($to_remove) && Db::getInstance()->execute(' + ); + if ($attribute_ids === false) { + return false; + } + /* Removing attributes to the found combinations */ + $to_remove = array(); + foreach ($attribute_ids as $attribute) { + $to_remove[] = (int)$attribute['id_attribute']; + } + if (!empty($to_remove) && Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'product_attribute_combination` WHERE `id_attribute` - IN ('.implode(', ', $to_remove).')') === false) - return false; - /* Remove combinations if they do not possess attributes anymore */ - if (!AttributeGroup::cleanDeadCombinations()) - return false; - /* Also delete related attributes */ - if (count($to_remove)) - if (!Db::getInstance()->execute(' + IN ('.implode(', ', $to_remove).')') === false) { + return false; + } + /* Remove combinations if they do not possess attributes anymore */ + if (!AttributeGroup::cleanDeadCombinations()) { + return false; + } + /* Also delete related attributes */ + if (count($to_remove)) { + if (!Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'attribute_lang` WHERE `id_attribute` IN ('.implode(',', $to_remove).')') || - !Db::getInstance()->execute(' + !Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'attribute_shop` WHERE `id_attribute` IN ('.implode(',', $to_remove).')') || - !Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'attribute` WHERE `id_attribute_group` = '.(int)$this->id)) - return false; - $this->cleanPositions(); - } - $return = parent::delete(); - if ($return) - Hook::exec('actionAttributeGroupDelete', array('id_attribute_group' => $this->id)); - return $return; - } + !Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'attribute` WHERE `id_attribute_group` = '.(int)$this->id)) { + return false; + } + } + $this->cleanPositions(); + } + $return = parent::delete(); + if ($return) { + Hook::exec('actionAttributeGroupDelete', array('id_attribute_group' => $this->id)); + } + return $return; + } - /** - * Get all attributes for a given language / group - * - * @param int $id_lang Language id - * @param bool $id_attribute_group Attribute group id - * @return array Attributes - */ - public static function getAttributes($id_lang, $id_attribute_group) - { - if (!Combination::isFeatureActive()) - return array(); - return Db::getInstance()->executeS(' + /** + * Get all attributes for a given language / group + * + * @param int $id_lang Language id + * @param bool $id_attribute_group Attribute group id + * @return array Attributes + */ + public static function getAttributes($id_lang, $id_attribute_group) + { + if (!Combination::isFeatureActive()) { + return array(); + } + return Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'attribute` a '.Shop::addSqlAssociation('attribute', 'a').' @@ -179,20 +191,21 @@ class AttributeGroupCore extends ObjectModel WHERE a.`id_attribute_group` = '.(int)$id_attribute_group.' ORDER BY `position` ASC '); - } + } - /** - * Get all attributes groups for a given language - * - * @param int $id_lang Language id - * @return array Attributes groups - */ - public static function getAttributesGroups($id_lang) - { - if (!Combination::isFeatureActive()) - return array(); + /** + * Get all attributes groups for a given language + * + * @param int $id_lang Language id + * @return array Attributes groups + */ + public static function getAttributesGroups($id_lang) + { + if (!Combination::isFeatureActive()) { + return array(); + } - return Db::getInstance()->executeS(' + return Db::getInstance()->executeS(' SELECT DISTINCT agl.`name`, ag.*, agl.* FROM `'._DB_PREFIX_.'attribute_group` ag '.Shop::addSqlAssociation('attribute_group', 'ag').' @@ -200,137 +213,143 @@ class AttributeGroupCore extends ObjectModel ON (ag.`id_attribute_group` = agl.`id_attribute_group` AND `id_lang` = '.(int)$id_lang.') ORDER BY `name` ASC '); - } + } - /** - * Delete several objects from database - * - * return boolean Deletion result - */ - public function deleteSelection($selection) - { - /* Also delete Attributes */ - foreach ($selection as $value) - { - $obj = new AttributeGroup($value); - if (!$obj->delete()) - return false; - } - return true; - } + /** + * Delete several objects from database + * + * return boolean Deletion result + */ + public function deleteSelection($selection) + { + /* Also delete Attributes */ + foreach ($selection as $value) { + $obj = new AttributeGroup($value); + if (!$obj->delete()) { + return false; + } + } + return true; + } - public function setWsProductOptionValues($values) - { - $ids = array(); - foreach ($values as $value) - $ids[] = intval($value['id']); - Db::getInstance()->execute(' + public function setWsProductOptionValues($values) + { + $ids = array(); + foreach ($values as $value) { + $ids[] = intval($value['id']); + } + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'attribute` WHERE `id_attribute_group` = '.(int)$this->id.' AND `id_attribute` NOT IN ('.implode(',', $ids).')' - ); - $ok = true; - foreach ($values as $value) - { - $result = Db::getInstance()->execute(' + ); + $ok = true; + foreach ($values as $value) { + $result = Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'attribute` SET `id_attribute_group` = '.(int)$this->id.' WHERE `id_attribute` = '.(int)$value['id'] - ); - if ($result === false) - $ok = false; - } - return $ok; - } + ); + if ($result === false) { + $ok = false; + } + } + return $ok; + } - public function getWsProductOptionValues() - { - $result = Db::getInstance()->executeS(' + public function getWsProductOptionValues() + { + $result = Db::getInstance()->executeS(' SELECT a.id_attribute AS id FROM `'._DB_PREFIX_.'attribute` a '.Shop::addSqlAssociation('attribute', 'a').' WHERE a.id_attribute_group = '.(int)$this->id - ); - return $result; - } + ); + return $result; + } - /** - * Move a group attribute - * @param bool $way Up (1) or Down (0) - * @param int $position - * @return bool Update result - */ - public function updatePosition($way, $position) - { - if (!$res = Db::getInstance()->executeS(' + /** + * Move a group attribute + * @param bool $way Up (1) or Down (0) + * @param int $position + * @return bool Update result + */ + public function updatePosition($way, $position) + { + if (!$res = Db::getInstance()->executeS(' SELECT ag.`position`, ag.`id_attribute_group` FROM `'._DB_PREFIX_.'attribute_group` ag WHERE ag.`id_attribute_group` = '.(int)Tools::getValue('id_attribute_group', 1).' ORDER BY ag.`position` ASC' - )) - return false; + )) { + return false; + } - foreach ($res as $group_attribute) - if ((int)$group_attribute['id_attribute_group'] == (int)$this->id) - $moved_group_attribute = $group_attribute; + foreach ($res as $group_attribute) { + if ((int)$group_attribute['id_attribute_group'] == (int)$this->id) { + $moved_group_attribute = $group_attribute; + } + } - if (!isset($moved_group_attribute) || !isset($position)) - return false; + if (!isset($moved_group_attribute) || !isset($position)) { + return false; + } - // < and > statements rather than BETWEEN operator - // since BETWEEN is treated differently according to databases - return (Db::getInstance()->execute(' + // < and > statements rather than BETWEEN operator + // since BETWEEN is treated differently according to databases + return (Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'attribute_group` SET `position`= `position` '.($way ? '- 1' : '+ 1').' WHERE `position` '.($way - ? '> '.(int)$moved_group_attribute['position'].' AND `position` <= '.(int)$position - : '< '.(int)$moved_group_attribute['position'].' AND `position` >= '.(int)$position) - ) && Db::getInstance()->execute(' + ? '> '.(int)$moved_group_attribute['position'].' AND `position` <= '.(int)$position + : '< '.(int)$moved_group_attribute['position'].' AND `position` >= '.(int)$position) + ) && Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'attribute_group` SET `position` = '.(int)$position.' WHERE `id_attribute_group`='.(int)$moved_group_attribute['id_attribute_group']) - ); - } + ); + } - /** - * Reorder group attribute position - * Call it after deleting a group attribute. - * - * @return bool $return - */ - public static function cleanPositions() - { - $return = true; + /** + * Reorder group attribute position + * Call it after deleting a group attribute. + * + * @return bool $return + */ + public static function cleanPositions() + { + $return = true; - $sql = ' + $sql = ' SELECT `id_attribute_group` FROM `'._DB_PREFIX_.'attribute_group` ORDER BY `position`'; - $result = Db::getInstance()->executeS($sql); + $result = Db::getInstance()->executeS($sql); - $i = 0; - foreach ($result as $value) - $return = Db::getInstance()->execute(' + $i = 0; + foreach ($result as $value) { + $return = Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'attribute_group` SET `position` = '.(int)$i++.' WHERE `id_attribute_group` = '.(int)$value['id_attribute_group'] - ); - return $return; - } + ); + } + return $return; + } - /** - * getHigherPosition - * - * Get the higher group attribute position - * - * @return int $position - */ - public static function getHigherPosition() - { - $sql = 'SELECT MAX(`position`) + /** + * getHigherPosition + * + * Get the higher group attribute position + * + * @return int $position + */ + public static function getHigherPosition() + { + $sql = 'SELECT MAX(`position`) FROM `'._DB_PREFIX_.'attribute_group`'; - $position = DB::getInstance()->getValue($sql); - return (is_numeric($position)) ? $position : -1; - } -} \ No newline at end of file + $position = DB::getInstance()->getValue($sql); + return (is_numeric($position)) ? $position : -1; + } +} diff --git a/classes/Blowfish.php b/classes/Blowfish.php index 930aa724..95538057 100644 --- a/classes/Blowfish.php +++ b/classes/Blowfish.php @@ -29,459 +29,449 @@ define('PS_UNPACK_MODIFIED', 2); class BlowfishCore extends Crypt_Blowfish { - public function encrypt($plaintext) - { - if (($length = strlen($plaintext)) >= 1048576) - return false; + public function encrypt($plaintext) + { + if (($length = strlen($plaintext)) >= 1048576) { + return false; + } - $ciphertext = ''; - $paddedtext = $this->maxi_pad($plaintext); - $strlen = strlen($paddedtext); - for ($x = 0; $x < $strlen; $x += 8) - { - $piece = substr($paddedtext, $x, 8); - $cipher_piece = parent::encrypt($piece); - $encoded = base64_encode($cipher_piece); - $ciphertext = $ciphertext.$encoded; - } - return $ciphertext.sprintf('%06d', $length); - } + $ciphertext = ''; + $paddedtext = $this->maxi_pad($plaintext); + $strlen = strlen($paddedtext); + for ($x = 0; $x < $strlen; $x += 8) { + $piece = substr($paddedtext, $x, 8); + $cipher_piece = parent::encrypt($piece); + $encoded = base64_encode($cipher_piece); + $ciphertext = $ciphertext.$encoded; + } + return $ciphertext.sprintf('%06d', $length); + } - public function decrypt($ciphertext) - { - $plainTextLength = intval(substr($ciphertext, -6)); - $ciphertext = substr($ciphertext, 0, -6); + public function decrypt($ciphertext) + { + $plainTextLength = intval(substr($ciphertext, -6)); + $ciphertext = substr($ciphertext, 0, -6); - $plaintext = ''; - $chunks = explode('=', $ciphertext); - $ending_value = count($chunks); - for ($counter = 0; $counter < ($ending_value - 1); $counter++) - { - $chunk = $chunks[$counter].'='; - $decoded = base64_decode($chunk); - $piece = parent::decrypt($decoded); - $plaintext = $plaintext.$piece; - } - return substr($plaintext, 0, $plainTextLength); - } + $plaintext = ''; + $chunks = explode('=', $ciphertext); + $ending_value = count($chunks); + for ($counter = 0; $counter < ($ending_value - 1); $counter++) { + $chunk = $chunks[$counter].'='; + $decoded = base64_decode($chunk); + $piece = parent::decrypt($decoded); + $plaintext = $plaintext.$piece; + } + return substr($plaintext, 0, $plainTextLength); + } - public function maxi_pad($plaintext) - { - $str_len = count($plaintext); - $pad_len = $str_len % 8; - for ($x = 0; $x < $pad_len; $x++) - $plaintext = $plaintext.' '; - return $plaintext; - } + public function maxi_pad($plaintext) + { + $str_len = count($plaintext); + $pad_len = $str_len % 8; + for ($x = 0; $x < $pad_len; $x++) { + $plaintext = $plaintext.' '; + } + return $plaintext; + } } class Crypt_Blowfish { + public $_P = array( + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, + 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, + 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, + 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, + 0x9216D5D9, 0x8979FB1B + ); - var $_P = array( - 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, - 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, - 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, - 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, - 0x9216D5D9, 0x8979FB1B - ); + public $_S = array( + array( + 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, + 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, + 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, + 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, + 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, + 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, + 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, + 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, + 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, + 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, + 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, + 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, + 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, + 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, + 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, + 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, + 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, + 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, + 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, + 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, + 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, + 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, + 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, + 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, + 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, + 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, + 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, + 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, + 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, + 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, + 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, + 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09, + 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, + 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, + 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, + 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, + 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, + 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, + 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, + 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, + 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, + 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, + 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, + 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, + 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, + 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, + 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, + 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C, + 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, + 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, + 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, + 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, + 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, + 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, + 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, + 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, + 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, + 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, + 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, + 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, + 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, + 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, + 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, + 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A + ), + array( + 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, + 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, + 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, + 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, + 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, + 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, + 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, + 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, + 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, + 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, + 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, + 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, + 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, + 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, + 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, + 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, + 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, + 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, + 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, + 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, + 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, + 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, + 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, + 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, + 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, + 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, + 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, + 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, + 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, + 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, + 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, + 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960, + 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, + 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, + 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, + 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, + 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, + 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, + 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, + 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, + 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, + 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, + 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, + 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, + 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, + 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, + 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, + 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, + 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, + 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, + 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, + 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, + 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, + 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, + 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, + 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, + 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, + 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, + 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, + 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, + 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, + 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, + 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, + 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7 + ), + array( + 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, + 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, + 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, + 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, + 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, + 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, + 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, + 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, + 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, + 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, + 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, + 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, + 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, + 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, + 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, + 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B, + 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, + 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, + 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, + 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, + 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, + 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, + 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, + 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, + 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, + 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, + 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, + 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, + 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, + 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, + 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, + 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B, + 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, + 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, + 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, + 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, + 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, + 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, + 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, + 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, + 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, + 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, + 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, + 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, + 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, + 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, + 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, + 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C, + 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, + 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, + 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, + 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, + 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, + 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, + 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, + 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, + 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, + 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, + 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, + 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, + 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, + 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, + 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, + 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0 + ), + array( + 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, + 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, + 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, + 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, + 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, + 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, + 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, + 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, + 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, + 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, + 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, + 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, + 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, + 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, + 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, + 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, + 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, + 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, + 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, + 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, + 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, + 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, + 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, + 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, + 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, + 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, + 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, + 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, + 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, + 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, + 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, + 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47, + 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, + 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, + 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, + 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, + 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, + 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, + 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, + 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, + 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, + 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, + 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, + 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, + 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, + 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, + 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, + 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E, + 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, + 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, + 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, + 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, + 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, + 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, + 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, + 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, + 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, + 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, + 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, + 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, + 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, + 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, + 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, + 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 + ) + ); - var $_S = array( - array( - 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, - 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, - 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, - 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, - 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, - 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, - 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, - 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, - 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, - 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, - 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, - 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, - 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, - 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, - 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, - 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, - 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, - 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, - 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, - 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, - 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, - 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, - 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, - 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, - 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, - 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, - 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, - 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, - 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, - 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, - 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, - 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09, - 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, - 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, - 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, - 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, - 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, - 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, - 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, - 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, - 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, - 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, - 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, - 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, - 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, - 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, - 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, - 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C, - 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, - 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, - 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, - 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, - 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, - 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, - 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, - 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, - 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, - 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, - 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, - 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, - 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, - 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, - 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, - 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A - ), - array( - 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, - 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, - 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, - 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, - 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, - 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, - 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, - 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, - 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, - 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, - 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, - 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, - 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, - 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, - 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, - 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, - 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, - 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, - 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, - 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, - 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, - 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, - 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, - 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, - 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, - 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, - 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, - 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, - 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, - 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, - 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, - 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960, - 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, - 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, - 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, - 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, - 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, - 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, - 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, - 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, - 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, - 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, - 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, - 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, - 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, - 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, - 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, - 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, - 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, - 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, - 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, - 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, - 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, - 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, - 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, - 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, - 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, - 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, - 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, - 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, - 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, - 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, - 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, - 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7 - ), - array( - 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, - 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, - 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, - 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, - 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, - 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, - 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, - 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, - 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, - 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, - 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, - 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, - 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, - 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, - 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, - 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B, - 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, - 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, - 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, - 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, - 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, - 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, - 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, - 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, - 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, - 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, - 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, - 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, - 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, - 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, - 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, - 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B, - 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, - 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, - 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, - 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, - 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, - 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, - 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, - 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, - 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, - 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, - 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, - 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, - 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, - 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, - 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, - 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C, - 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, - 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, - 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, - 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, - 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, - 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, - 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, - 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, - 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, - 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, - 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, - 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, - 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, - 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, - 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, - 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0 - ), - array( - 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, - 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, - 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, - 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, - 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, - 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, - 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, - 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, - 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, - 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, - 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, - 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, - 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, - 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, - 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, - 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, - 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, - 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, - 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, - 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, - 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, - 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, - 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, - 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, - 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, - 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, - 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, - 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, - 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, - 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, - 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, - 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47, - 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, - 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, - 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, - 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, - 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, - 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, - 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, - 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, - 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, - 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, - 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, - 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, - 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, - 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, - 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, - 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E, - 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, - 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, - 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, - 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, - 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, - 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, - 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, - 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, - 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, - 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, - 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, - 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, - 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, - 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, - 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, - 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 - ) - ); + public $_iv = null; - var $_iv = null; + protected $_unpackMode = PS_UNPACK_NATIVE; - protected $_unpackMode = PS_UNPACK_NATIVE; + public function __construct($key, $iv) + { + $_iv = $iv; - public function __construct($key, $iv) - { - $_iv = $iv; + $len = strlen($key); - $len = strlen($key); + $k = 0; + $data = 0; + $datal = 0; + $datar = 0; - $k = 0; - $data = 0; - $datal = 0; - $datar = 0; + if (PHP_VERSION_ID == '50201' || PHP_VERSION_ID == '50206') { + $this->_unpackMode = PS_UNPACK_MODIFIED; + } - if (PHP_VERSION_ID == '50201' || PHP_VERSION_ID == '50206') - $this->_unpackMode = PS_UNPACK_MODIFIED; + for ($i = 0; $i < 18; $i++) { + $data = 0; + for ($j = 4; $j > 0; $j--) { + $data = $data << 8 | ord($key{$k}); + $k = ($k + 1) % $len; + } + $this->_P[$i] ^= $data; + } - for ($i = 0; $i < 18; $i++) - { - $data = 0; - for ($j = 4; $j > 0; $j--) - { - $data = $data << 8 | ord($key{$k}); - $k = ($k + 1) % $len; - } - $this->_P[$i] ^= $data; - } + for ($i = 0; $i <= 16; $i += 2) { + $this->_encipher($datal, $datar); + $this->_P[$i] = $datal; + $this->_P[$i+1] = $datar; + } + for ($i = 0; $i < 256; $i += 2) { + $this->_encipher($datal, $datar); + $this->_S[0][$i] = $datal; + $this->_S[0][$i+1] = $datar; + } + for ($i = 0; $i < 256; $i += 2) { + $this->_encipher($datal, $datar); + $this->_S[1][$i] = $datal; + $this->_S[1][$i+1] = $datar; + } + for ($i = 0; $i < 256; $i += 2) { + $this->_encipher($datal, $datar); + $this->_S[2][$i] = $datal; + $this->_S[2][$i+1] = $datar; + } + for ($i = 0; $i < 256; $i += 2) { + $this->_encipher($datal, $datar); + $this->_S[3][$i] = $datal; + $this->_S[3][$i+1] = $datar; + } + } - for ($i = 0; $i <= 16; $i += 2) - { - $this->_encipher($datal, $datar); - $this->_P[$i] = $datal; - $this->_P[$i+1] = $datar; - } - for ($i = 0; $i < 256; $i += 2) - { - $this->_encipher($datal, $datar); - $this->_S[0][$i] = $datal; - $this->_S[0][$i+1] = $datar; - } - for ($i = 0; $i < 256; $i += 2) - { - $this->_encipher($datal, $datar); - $this->_S[1][$i] = $datal; - $this->_S[1][$i+1] = $datar; - } - for ($i = 0; $i < 256; $i += 2) - { - $this->_encipher($datal, $datar); - $this->_S[2][$i] = $datal; - $this->_S[2][$i+1] = $datar; - } - for ($i = 0; $i < 256; $i += 2) - { - $this->_encipher($datal, $datar); - $this->_S[3][$i] = $datal; - $this->_S[3][$i+1] = $datar; - } - } + public function _encipher(&$Xl, &$Xr) + { + for ($i = 0; $i < 16; $i++) { + $temp = $Xl ^ $this->_P[$i]; + $Xl = ((($this->_S[0][($temp>>24) & 255] + + $this->_S[1][($temp>>16) & 255]) ^ + $this->_S[2][($temp>>8) & 255]) + + $this->_S[3][$temp & 255]) ^ $Xr; + $Xr = $temp; + } + $Xr = $Xl ^ $this->_P[16]; + $Xl = $temp ^ $this->_P[17]; + } - public function _encipher(&$Xl, &$Xr) - { - for ($i = 0; $i < 16; $i++) - { - $temp = $Xl ^ $this->_P[$i]; - $Xl = ((($this->_S[0][($temp>>24) & 255] + - $this->_S[1][($temp>>16) & 255]) ^ - $this->_S[2][($temp>>8) & 255]) + - $this->_S[3][$temp & 255]) ^ $Xr; - $Xr = $temp; - } - $Xr = $Xl ^ $this->_P[16]; - $Xl = $temp ^ $this->_P[17]; - } + public function _decipher(&$Xl, &$Xr) + { + for ($i = 17; $i > 1; $i--) { + $temp = $Xl ^ $this->_P[$i]; + $Xl = ((($this->_S[0][($temp>>24) & 255] + + $this->_S[1][($temp>>16) & 255]) ^ + $this->_S[2][($temp>>8) & 255]) + + $this->_S[3][$temp & 255]) ^ $Xr; + $Xr = $temp; + } + $Xr = $Xl ^ $this->_P[1]; + $Xl = $temp ^ $this->_P[0]; + } - public function _decipher(&$Xl, &$Xr) - { - for ($i = 17; $i > 1; $i--) - { - $temp = $Xl ^ $this->_P[$i]; - $Xl = ((($this->_S[0][($temp>>24) & 255] + - $this->_S[1][($temp>>16) & 255]) ^ - $this->_S[2][($temp>>8) & 255]) + - $this->_S[3][$temp & 255]) ^ $Xr; - $Xr = $temp; - } - $Xr = $Xl ^ $this->_P[1]; - $Xl = $temp ^ $this->_P[0]; - } + public function encrypt($plainText) + { + $cipherText = ''; + $len = strlen($plainText); + $plainText .= str_repeat(chr(0), (8 - ($len % 8)) % 8); + for ($i = 0; $i < $len; $i += 8) { + list(, $Xl, $Xr) = ($this->_unpackMode == PS_UNPACK_NATIVE ? unpack('N2', substr($plainText, $i, 8)) : $this->myUnpackN2(substr($plainText, $i, 8))); + $this->_encipher($Xl, $Xr); + $cipherText .= pack('N2', $Xl, $Xr); + } + return $cipherText; + } - public function encrypt($plainText) - { - $cipherText = ''; - $len = strlen($plainText); - $plainText .= str_repeat(chr(0), (8 - ($len % 8)) % 8); - for ($i = 0; $i < $len; $i += 8) - { - list(, $Xl, $Xr) = ($this->_unpackMode == PS_UNPACK_NATIVE ? unpack('N2', substr($plainText, $i, 8)) : $this->myUnpackN2(substr($plainText, $i, 8))); - $this->_encipher($Xl, $Xr); - $cipherText .= pack('N2', $Xl, $Xr); - } - return $cipherText; - } + public function decrypt($cipherText) + { + $plainText = ''; + $len = strlen($cipherText); + $cipherText .= str_repeat(chr(0), (8 - ($len % 8)) % 8); + for ($i = 0; $i < $len; $i += 8) { + list(, $Xl, $Xr) = ($this->_unpackMode == PS_UNPACK_NATIVE ? unpack('N2', substr($cipherText, $i, 8)) : $this->myUnpackN2(substr($cipherText, $i, 8))); + $this->_decipher($Xl, $Xr); + $plainText .= pack('N2', $Xl, $Xr); + } + return $plainText; + } - public function decrypt($cipherText) - { - $plainText = ''; - $len = strlen($cipherText); - $cipherText .= str_repeat(chr(0), (8 - ($len % 8)) % 8); - for ($i = 0; $i < $len; $i += 8) - { - list(, $Xl, $Xr) = ($this->_unpackMode == PS_UNPACK_NATIVE ? unpack('N2', substr($cipherText, $i, 8)) : $this->myUnpackN2(substr($cipherText, $i, 8))); - $this->_decipher($Xl, $Xr); - $plainText .= pack('N2', $Xl, $Xr); - } - return $plainText; - } + public function myUnpackN($str) + { + if (pack('L', 0x6162797A) == pack('V', 0x6162797A)) { + return ((ord($str) << 24) | (ord(substr($str, 1)) << 16) | (ord(substr($str, 2)) << 8) | ord(substr($str, 3))); + } else { + return (ord($str) | (ord(substr($str, 1)) << 8) | (ord(substr($str, 2)) << 16) | (ord(substr($str, 3)) << 24)); + } + } - public function myUnpackN($str) - { - if (pack('L', 0x6162797A) == pack('V', 0x6162797A)) - return ((ord($str) << 24) | (ord(substr($str, 1)) << 16) | (ord(substr($str, 2)) << 8) | ord(substr($str, 3))); - else - return (ord($str) | (ord(substr($str, 1)) << 8) | (ord(substr($str, 2)) << 16) | (ord(substr($str, 3)) << 24)); - } - - public function myUnpackN2($str) - { - return array('1' => $this->myUnpackN($str), '2' => $this->myUnpackN(substr($str, 4))); - } + public function myUnpackN2($str) + { + return array('1' => $this->myUnpackN($str), '2' => $this->myUnpackN(substr($str, 4))); + } } diff --git a/classes/CMS.php b/classes/CMS.php index 6f39fa2a..6c43b6f5 100644 --- a/classes/CMS.php +++ b/classes/CMS.php @@ -26,96 +26,100 @@ class CMSCore extends ObjectModel { - /** @var string Name */ - public $meta_title; - public $meta_description; - public $meta_keywords; - public $content; - public $link_rewrite; - public $id_cms_category; - public $position; - public $indexation; - public $active; + /** @var string Name */ + public $meta_title; + public $meta_description; + public $meta_keywords; + public $content; + public $link_rewrite; + public $id_cms_category; + public $position; + public $indexation; + public $active; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'cms', - 'primary' => 'id_cms', - 'multilang' => true, - 'multilang_shop' => true, - 'fields' => array( - 'id_cms_category' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'position' => array('type' => self::TYPE_INT), - 'indexation' => array('type' => self::TYPE_BOOL), - 'active' => array('type' => self::TYPE_BOOL), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'cms', + 'primary' => 'id_cms', + 'multilang' => true, + 'multilang_shop' => true, + 'fields' => array( + 'id_cms_category' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'position' => array('type' => self::TYPE_INT), + 'indexation' => array('type' => self::TYPE_BOOL), + 'active' => array('type' => self::TYPE_BOOL), - /* Lang fields */ - 'meta_description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - 'meta_keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), - 'link_rewrite' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isLinkRewrite', 'required' => true, 'size' => 128), - 'content' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml', 'size' => 3999999999999), - ), - ); + /* Lang fields */ + 'meta_description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + 'meta_keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), + 'link_rewrite' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isLinkRewrite', 'required' => true, 'size' => 128), + 'content' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml', 'size' => 3999999999999), + ), + ); - protected $webserviceParameters = array( - 'objectNodeName' => 'content', - 'objectsNodeName' => 'content_management_system', - ); + protected $webserviceParameters = array( + 'objectNodeName' => 'content', + 'objectsNodeName' => 'content_management_system', + ); - public function add($autodate = true, $null_values = false) - { - $this->position = CMS::getLastPosition((int)$this->id_cms_category); - return parent::add($autodate, true); - } + public function add($autodate = true, $null_values = false) + { + $this->position = CMS::getLastPosition((int)$this->id_cms_category); + return parent::add($autodate, true); + } - public function update($null_values = false) - { - if (parent::update($null_values)) - return $this->cleanPositions($this->id_cms_category); - return false; - } + public function update($null_values = false) + { + if (parent::update($null_values)) { + return $this->cleanPositions($this->id_cms_category); + } + return false; + } - public function delete() - { - if (parent::delete()) - return $this->cleanPositions($this->id_cms_category); - return false; - } + public function delete() + { + if (parent::delete()) { + return $this->cleanPositions($this->id_cms_category); + } + return false; + } - public static function getLinks($id_lang, $selection = null, $active = true, Link $link = null) - { - if (!$link) - $link = Context::getContext()->link; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getLinks($id_lang, $selection = null, $active = true, Link $link = null) + { + if (!$link) { + $link = Context::getContext()->link; + } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT c.id_cms, cl.link_rewrite, cl.meta_title FROM '._DB_PREFIX_.'cms c LEFT JOIN '._DB_PREFIX_.'cms_lang cl ON (c.id_cms = cl.id_cms AND cl.id_lang = '.(int)$id_lang.') '.Shop::addSqlAssociation('cms', 'c').' WHERE 1 '.(($selection !== null) ? ' AND c.id_cms IN ('.implode(',', array_map('intval', $selection)).')' : ''). - ($active ? ' AND c.`active` = 1 ' : ''). - 'GROUP BY c.id_cms + ($active ? ' AND c.`active` = 1 ' : ''). + 'GROUP BY c.id_cms ORDER BY c.`position`'); - $links = array(); - if ($result) - foreach ($result as $row) - { - $row['link'] = $link->getCMSLink((int)$row['id_cms'], $row['link_rewrite']); - $links[] = $row; - } - return $links; - } + $links = array(); + if ($result) { + foreach ($result as $row) { + $row['link'] = $link->getCMSLink((int)$row['id_cms'], $row['link_rewrite']); + $links[] = $row; + } + } + return $links; + } - public static function listCms($id_lang = null, $id_block = false, $active = true) - { - if (empty($id_lang)) - $id_lang = (int)Configuration::get('PS_LANG_DEFAULT'); + public static function listCms($id_lang = null, $id_block = false, $active = true) + { + if (empty($id_lang)) { + $id_lang = (int)Configuration::get('PS_LANG_DEFAULT'); + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT c.id_cms, l.meta_title FROM '._DB_PREFIX_.'cms c JOIN '._DB_PREFIX_.'cms_lang l ON (c.id_cms = l.id_cms) @@ -124,130 +128,138 @@ class CMSCore extends ObjectModel WHERE l.id_lang = '.(int)$id_lang.(($id_block) ? ' AND b.id_block = '.(int)$id_block : '').($active ? ' AND c.`active` = 1 ' : '').' GROUP BY c.id_cms ORDER BY c.`position`'); - } + } - public function updatePosition($way, $position) - { - if (!$res = Db::getInstance()->executeS(' + public function updatePosition($way, $position) + { + if (!$res = Db::getInstance()->executeS(' SELECT cp.`id_cms`, cp.`position`, cp.`id_cms_category` FROM `'._DB_PREFIX_.'cms` cp WHERE cp.`id_cms_category` = '.(int)$this->id_cms_category.' ORDER BY cp.`position` ASC' - )) - return false; + )) { + return false; + } - foreach ($res as $cms) - if ((int)$cms['id_cms'] == (int)$this->id) - $moved_cms = $cms; + foreach ($res as $cms) { + if ((int)$cms['id_cms'] == (int)$this->id) { + $moved_cms = $cms; + } + } - if (!isset($moved_cms) || !isset($position)) - return false; + if (!isset($moved_cms) || !isset($position)) { + return false; + } - // < and > statements rather than BETWEEN operator - // since BETWEEN is treated differently according to databases - return (Db::getInstance()->execute(' + // < and > statements rather than BETWEEN operator + // since BETWEEN is treated differently according to databases + return (Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'cms` SET `position`= `position` '.($way ? '- 1' : '+ 1').' WHERE `position` '.($way - ? '> '.(int)$moved_cms['position'].' AND `position` <= '.(int)$position - : '< '.(int)$moved_cms['position'].' AND `position` >= '.(int)$position).' + ? '> '.(int)$moved_cms['position'].' AND `position` <= '.(int)$position + : '< '.(int)$moved_cms['position'].' AND `position` >= '.(int)$position).' AND `id_cms_category`='.(int)$moved_cms['id_cms_category']) - && Db::getInstance()->execute(' + && Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'cms` SET `position` = '.(int)$position.' WHERE `id_cms` = '.(int)$moved_cms['id_cms'].' AND `id_cms_category`='.(int)$moved_cms['id_cms_category'])); - } + } - public static function cleanPositions($id_category) - { - $sql = ' + public static function cleanPositions($id_category) + { + $sql = ' SELECT `id_cms` FROM `'._DB_PREFIX_.'cms` WHERE `id_cms_category` = '.(int)$id_category.' ORDER BY `position`'; - $result = Db::getInstance()->executeS($sql); + $result = Db::getInstance()->executeS($sql); - for ($i = 0, $total = count($result); $i < $total; ++$i) - { - $sql = 'UPDATE `'._DB_PREFIX_.'cms` + for ($i = 0, $total = count($result); $i < $total; ++$i) { + $sql = 'UPDATE `'._DB_PREFIX_.'cms` SET `position` = '.(int)$i.' WHERE `id_cms_category` = '.(int)$id_category.' AND `id_cms` = '.(int)$result[$i]['id_cms']; - Db::getInstance()->execute($sql); - } - return true; - } + Db::getInstance()->execute($sql); + } + return true; + } - public static function getLastPosition($id_category) - { - $sql = ' + public static function getLastPosition($id_category) + { + $sql = ' SELECT MAX(position) + 1 FROM `'._DB_PREFIX_.'cms` WHERE `id_cms_category` = '.(int)$id_category; - return (Db::getInstance()->getValue($sql)); - } + return (Db::getInstance()->getValue($sql)); + } - public static function getCMSPages($id_lang = null, $id_cms_category = null, $active = true, $id_shop = null) - { - $sql = new DbQuery(); - $sql->select('*'); - $sql->from('cms', 'c'); + public static function getCMSPages($id_lang = null, $id_cms_category = null, $active = true, $id_shop = null) + { + $sql = new DbQuery(); + $sql->select('*'); + $sql->from('cms', 'c'); - if ($id_lang) - { - if ($id_shop) - $sql->innerJoin('cms_lang', 'l', 'c.id_cms = l.id_cms AND l.id_lang = '.(int)$id_lang.' AND l.id_shop = '.(int)$id_shop); - else - $sql->innerJoin('cms_lang', 'l', 'c.id_cms = l.id_cms AND l.id_lang = '.(int)$id_lang); - } + if ($id_lang) { + if ($id_shop) { + $sql->innerJoin('cms_lang', 'l', 'c.id_cms = l.id_cms AND l.id_lang = '.(int)$id_lang.' AND l.id_shop = '.(int)$id_shop); + } else { + $sql->innerJoin('cms_lang', 'l', 'c.id_cms = l.id_cms AND l.id_lang = '.(int)$id_lang); + } + } - if ($id_shop) - $sql->innerJoin('cms_shop', 'cs', 'c.id_cms = cs.id_cms AND cs.id_shop = '.(int)$id_shop); + if ($id_shop) { + $sql->innerJoin('cms_shop', 'cs', 'c.id_cms = cs.id_cms AND cs.id_shop = '.(int)$id_shop); + } - if ($active) - $sql->where('c.active = 1'); + if ($active) { + $sql->where('c.active = 1'); + } - if ($id_cms_category) - $sql->where('c.id_cms_category = '.(int)$id_cms_category); + if ($id_cms_category) { + $sql->where('c.id_cms_category = '.(int)$id_cms_category); + } - $sql->orderBy('position'); + $sql->orderBy('position'); - return Db::getInstance()->executeS($sql); - } + return Db::getInstance()->executeS($sql); + } - public static function getUrlRewriteInformations($id_cms) - { - $sql = 'SELECT l.`id_lang`, c.`link_rewrite` + public static function getUrlRewriteInformations($id_cms) + { + $sql = 'SELECT l.`id_lang`, c.`link_rewrite` FROM `'._DB_PREFIX_.'cms_lang` AS c LEFT JOIN `'._DB_PREFIX_.'lang` AS l ON c.`id_lang` = l.`id_lang` WHERE c.`id_cms` = '.(int)$id_cms.' AND l.`active` = 1'; - return Db::getInstance()->executeS($sql); - } + return Db::getInstance()->executeS($sql); + } - public static function getCMSContent($id_cms, $id_lang = null, $id_shop = null) - { - if (is_null($id_lang)) - $id_lang = (int)Configuration::get('PS_SHOP_DEFAULT'); - if (is_null($id_shop)) - $id_shop = (int)Configuration::get('PS_LANG_DEFAULT'); + public static function getCMSContent($id_cms, $id_lang = null, $id_shop = null) + { + if (is_null($id_lang)) { + $id_lang = (int)Configuration::get('PS_SHOP_DEFAULT'); + } + if (is_null($id_shop)) { + $id_shop = (int)Configuration::get('PS_LANG_DEFAULT'); + } - $sql = ' + $sql = ' SELECT `content` FROM `'._DB_PREFIX_.'cms_lang` WHERE `id_cms` = '.(int)$id_cms.' AND `id_lang` = '.(int)$id_lang.' AND `id_shop` = '.(int)$id_shop; - return Db::getInstance()->getRow($sql); - } + return Db::getInstance()->getRow($sql); + } - /* Method required for new PrestaShop Core */ - public static function getRepositoryClassName() - { - return 'Core_Business_CMS_CMSRepository'; - } -} \ No newline at end of file + /* Method required for new PrestaShop Core */ + public static function getRepositoryClassName() + { + return 'Core_Business_CMS_CMSRepository'; + } +} diff --git a/classes/CMSCategory.php b/classes/CMSCategory.php index 6336d411..19a91bc7 100644 --- a/classes/CMSCategory.php +++ b/classes/CMSCategory.php @@ -26,162 +26,170 @@ class CMSCategoryCore extends ObjectModel { - public $id; + public $id; - /** @var int CMSCategory ID */ - public $id_cms_category; + /** @var int CMSCategory ID */ + public $id_cms_category; - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var bool Status for display */ - public $active = 1; + /** @var bool Status for display */ + public $active = 1; - /** @var string Description */ - public $description; + /** @var string Description */ + public $description; - /** @var int Parent CMSCategory ID */ - public $id_parent; + /** @var int Parent CMSCategory ID */ + public $id_parent; - /** @var int category position */ - public $position; + /** @var int category position */ + public $position; - /** @var int Parents number */ - public $level_depth; + /** @var int Parents number */ + public $level_depth; - /** @var string string used in rewrited URL */ - public $link_rewrite; + /** @var string string used in rewrited URL */ + public $link_rewrite; - /** @var string Meta title */ - public $meta_title; + /** @var string Meta title */ + public $meta_title; - /** @var string Meta keywords */ - public $meta_keywords; + /** @var string Meta keywords */ + public $meta_keywords; - /** @var string Meta description */ - public $meta_description; + /** @var string Meta description */ + public $meta_description; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** @var string Object last modification date */ - public $date_upd; + /** @var string Object last modification date */ + public $date_upd; - protected static $_links = array(); + protected static $_links = array(); - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'cms_category', - 'primary' => 'id_cms_category', - 'multilang' => true, - 'multilang_shop' => true, - 'fields' => array( - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), - 'id_parent' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), - 'position' => array('type' => self::TYPE_INT), - 'level_depth' => array('type' => self::TYPE_INT), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'cms_category', + 'primary' => 'id_cms_category', + 'multilang' => true, + 'multilang_shop' => true, + 'fields' => array( + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), + 'id_parent' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), + 'position' => array('type' => self::TYPE_INT), + 'level_depth' => array('type' => self::TYPE_INT), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCatalogName', 'required' => true, 'size' => 64), - 'link_rewrite' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isLinkRewrite', 'required' => true, 'size' => 64), - 'description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCleanHtml'), - 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), - 'meta_description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - 'meta_keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - ), - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCatalogName', 'required' => true, 'size' => 64), + 'link_rewrite' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isLinkRewrite', 'required' => true, 'size' => 64), + 'description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCleanHtml'), + 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), + 'meta_description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + 'meta_keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + ), + ); - public function add($autodate = true, $null_values = false) - { - $this->position = CMSCategory::getLastPosition((int)$this->id_parent); - $this->level_depth = $this->calcLevelDepth(); - foreach ($this->name as $k => $value) - if (preg_match('/^[1-9]\./', $value)) - $this->name[$k] = '0'.$value; - $ret = parent::add($autodate, $null_values); - $this->cleanPositions($this->id_parent); - return $ret; - } + public function add($autodate = true, $null_values = false) + { + $this->position = CMSCategory::getLastPosition((int)$this->id_parent); + $this->level_depth = $this->calcLevelDepth(); + foreach ($this->name as $k => $value) { + if (preg_match('/^[1-9]\./', $value)) { + $this->name[$k] = '0'.$value; + } + } + $ret = parent::add($autodate, $null_values); + $this->cleanPositions($this->id_parent); + return $ret; + } - public function update($null_values = false) - { - $this->level_depth = $this->calcLevelDepth(); - foreach ($this->name as $k => $value) - if (preg_match('/^[1-9]\./', $value)) - $this->name[$k] = '0'.$value; - return parent::update($null_values); - } + public function update($null_values = false) + { + $this->level_depth = $this->calcLevelDepth(); + foreach ($this->name as $k => $value) { + if (preg_match('/^[1-9]\./', $value)) { + $this->name[$k] = '0'.$value; + } + } + return parent::update($null_values); + } - /** - * Recursive scan of subcategories - * - * @param int $max_depth Maximum depth of the tree (i.e. 2 => 3 levels depth) - * @param int $currentDepth specify the current depth in the tree (don't use it, only for rucursivity!) - * @param array $excluded_ids_array specify a list of ids to exclude of results - * @param int $idLang Specify the id of the language used - * - * @return array Subcategories lite tree - */ - public function recurseLiteCategTree($max_depth = 3, $currentDepth = 0, $id_lang = null, $excluded_ids_array = null, Link $link = null) - { - if (!$link) - $link = Context::getContext()->link; + /** + * Recursive scan of subcategories + * + * @param int $max_depth Maximum depth of the tree (i.e. 2 => 3 levels depth) + * @param int $currentDepth specify the current depth in the tree (don't use it, only for rucursivity!) + * @param array $excluded_ids_array specify a list of ids to exclude of results + * @param int $idLang Specify the id of the language used + * + * @return array Subcategories lite tree + */ + public function recurseLiteCategTree($max_depth = 3, $currentDepth = 0, $id_lang = null, $excluded_ids_array = null, Link $link = null) + { + if (!$link) { + $link = Context::getContext()->link; + } - if (is_null($id_lang)) - $id_lang = Context::getContext()->language->id; + if (is_null($id_lang)) { + $id_lang = Context::getContext()->language->id; + } - // recursivity for subcategories - $children = array(); - $subcats = $this->getSubCategories($id_lang, true); - if (($max_depth == 0 || $currentDepth < $max_depth) && $subcats && count($subcats)) - foreach ($subcats as &$subcat) - { - if (!$subcat['id_cms_category']) - break; - elseif (!is_array($excluded_ids_array) || !in_array($subcat['id_cms_category'], $excluded_ids_array)) - { - $categ = new CMSCategory($subcat['id_cms_category'], $id_lang); - $categ->name = CMSCategory::hideCMSCategoryPosition($categ->name); - $children[] = $categ->recurseLiteCategTree($max_depth, $currentDepth + 1, $id_lang, $excluded_ids_array); - } - } + // recursivity for subcategories + $children = array(); + $subcats = $this->getSubCategories($id_lang, true); + if (($max_depth == 0 || $currentDepth < $max_depth) && $subcats && count($subcats)) { + foreach ($subcats as &$subcat) { + if (!$subcat['id_cms_category']) { + break; + } elseif (!is_array($excluded_ids_array) || !in_array($subcat['id_cms_category'], $excluded_ids_array)) { + $categ = new CMSCategory($subcat['id_cms_category'], $id_lang); + $categ->name = CMSCategory::hideCMSCategoryPosition($categ->name); + $children[] = $categ->recurseLiteCategTree($max_depth, $currentDepth + 1, $id_lang, $excluded_ids_array); + } + } + } - return array( - 'id' => $this->id_cms_category, - 'link' => $link->getCMSCategoryLink($this->id, $this->link_rewrite), - 'name' => $this->name, - 'desc'=> $this->description, - 'children' => $children - ); - } + return array( + 'id' => $this->id_cms_category, + 'link' => $link->getCMSCategoryLink($this->id, $this->link_rewrite), + 'name' => $this->name, + 'desc'=> $this->description, + 'children' => $children + ); + } - public static function getRecurseCategory($id_lang = null, $current = 1, $active = 1, $links = 0, Link $link = null) - { - if (!$link) - $link = Context::getContext()->link; - if (is_null($id_lang)) - $id_lang = Context::getContext()->language->id; + public static function getRecurseCategory($id_lang = null, $current = 1, $active = 1, $links = 0, Link $link = null) + { + if (!$link) { + $link = Context::getContext()->link; + } + if (is_null($id_lang)) { + $id_lang = Context::getContext()->language->id; + } - $sql = 'SELECT c.`id_cms_category`, c.`id_parent`, c.`level_depth`, cl.`name`, cl.`link_rewrite` + $sql = 'SELECT c.`id_cms_category`, c.`id_parent`, c.`level_depth`, cl.`name`, cl.`link_rewrite` FROM `'._DB_PREFIX_.'cms_category` c JOIN `'._DB_PREFIX_.'cms_category_lang` cl ON c.`id_cms_category` = cl.`id_cms_category` WHERE c.`id_cms_category` = '.(int)$current.' AND `id_lang` = '.(int)$id_lang; - $category = Db::getInstance()->getRow($sql); + $category = Db::getInstance()->getRow($sql); - $sql = 'SELECT c.`id_cms_category` + $sql = 'SELECT c.`id_cms_category` FROM `'._DB_PREFIX_.'cms_category` c WHERE c.`id_parent` = '.(int)$current. - ($active ? ' AND c.`active` = 1' : ''); - $result = Db::getInstance()->executeS($sql); - foreach ($result as $row) - $category['children'][] = CMSCategory::getRecurseCategory($id_lang, $row['id_cms_category'], $active, $links); + ($active ? ' AND c.`active` = 1' : ''); + $result = Db::getInstance()->executeS($sql); + foreach ($result as $row) { + $category['children'][] = CMSCategory::getRecurseCategory($id_lang, $row['id_cms_category'], $active, $links); + } - $sql = 'SELECT c.`id_cms`, cl.`meta_title`, cl.`link_rewrite` + $sql = 'SELECT c.`id_cms`, cl.`meta_title`, cl.`link_rewrite` FROM `'._DB_PREFIX_.'cms` c '.Shop::addSqlAssociation('cms', 'c').' JOIN `'._DB_PREFIX_.'cms_lang` cl ON c.`id_cms` = cl.`id_cms` @@ -189,135 +197,141 @@ class CMSCategoryCore extends ObjectModel AND cl.`id_lang` = '.(int)$id_lang.($active ? ' AND c.`active` = 1' : '').' GROUP BY c.id_cms ORDER BY c.`position`'; - $category['cms'] = Db::getInstance()->executeS($sql); - if ($links == 1) - { - $category['link'] = $link->getCMSCategoryLink($current, $category['link_rewrite']); - foreach ($category['cms'] as $key => $cms) - $category['cms'][$key]['link'] = $link->getCMSLink($cms['id_cms'], $cms['link_rewrite']); - } - return $category; - } + $category['cms'] = Db::getInstance()->executeS($sql); + if ($links == 1) { + $category['link'] = $link->getCMSCategoryLink($current, $category['link_rewrite']); + foreach ($category['cms'] as $key => $cms) { + $category['cms'][$key]['link'] = $link->getCMSLink($cms['id_cms'], $cms['link_rewrite']); + } + } + return $category; + } - public static function recurseCMSCategory($categories, $current, $id_cms_category = 1, $id_selected = 1, $is_html = 0) - { - $html = ''; - if ($is_html == 0) - echo $html; - if (isset($categories[$id_cms_category])) - foreach (array_keys($categories[$id_cms_category]) as $key) - $html .= CMSCategory::recurseCMSCategory($categories, $categories[$id_cms_category][$key], $key, $id_selected, $is_html); - return $html; - } + public static function recurseCMSCategory($categories, $current, $id_cms_category = 1, $id_selected = 1, $is_html = 0) + { + $html = ''; + if ($is_html == 0) { + echo $html; + } + if (isset($categories[$id_cms_category])) { + foreach (array_keys($categories[$id_cms_category]) as $key) { + $html .= CMSCategory::recurseCMSCategory($categories, $categories[$id_cms_category][$key], $key, $id_selected, $is_html); + } + } + return $html; + } - /** - * Recursively add specified CMSCategory childs to $toDelete array - * - * @param array &$toDelete Array reference where categories ID will be saved - * @param array|int $id_cms_category Parent CMSCategory ID - */ - protected function recursiveDelete(&$to_delete, $id_cms_category) - { - if (!is_array($to_delete) || !$id_cms_category) - die(Tools::displayError()); + /** + * Recursively add specified CMSCategory childs to $toDelete array + * + * @param array &$toDelete Array reference where categories ID will be saved + * @param array|int $id_cms_category Parent CMSCategory ID + */ + protected function recursiveDelete(&$to_delete, $id_cms_category) + { + if (!is_array($to_delete) || !$id_cms_category) { + die(Tools::displayError()); + } - $result = Db::getInstance()->executeS(' + $result = Db::getInstance()->executeS(' SELECT `id_cms_category` FROM `'._DB_PREFIX_.'cms_category` WHERE `id_parent` = '.(int)$id_cms_category); - foreach ($result as $row) - { - $to_delete[] = (int)$row['id_cms_category']; - $this->recursiveDelete($to_delete, (int)$row['id_cms_category']); - } - } + foreach ($result as $row) { + $to_delete[] = (int)$row['id_cms_category']; + $this->recursiveDelete($to_delete, (int)$row['id_cms_category']); + } + } - public function delete() - { - if ($this->id == 1) return false; + public function delete() + { + if ($this->id == 1) { + return false; + } - $this->clearCache(); + $this->clearCache(); - // Get children categories - $to_delete = array((int)$this->id); - $this->recursiveDelete($to_delete, (int)$this->id); - $to_delete = array_unique($to_delete); + // Get children categories + $to_delete = array((int)$this->id); + $this->recursiveDelete($to_delete, (int)$this->id); + $to_delete = array_unique($to_delete); - // Delete CMS Category and its child from database - $list = count($to_delete) > 1 ? implode(',', $to_delete) : (int)$this->id; - $id_shop_list = Shop::getContextListShopID(); - if (count($this->id_shop_list)) - $id_shop_list = $this->id_shop_list; + // Delete CMS Category and its child from database + $list = count($to_delete) > 1 ? implode(',', $to_delete) : (int)$this->id; + $id_shop_list = Shop::getContextListShopID(); + if (count($this->id_shop_list)) { + $id_shop_list = $this->id_shop_list; + } - Db::getInstance()->delete($this->def['table'].'_shop', '`'.$this->def['primary'].'` IN ('.$list.') AND id_shop IN ('.implode(', ', $id_shop_list).')'); + Db::getInstance()->delete($this->def['table'].'_shop', '`'.$this->def['primary'].'` IN ('.$list.') AND id_shop IN ('.implode(', ', $id_shop_list).')'); - $has_multishop_entries = $this->hasMultishopEntries(); - if (!$has_multishop_entries) - { - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cms_category` WHERE `id_cms_category` IN ('.$list.')'); - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cms_category_lang` WHERE `id_cms_category` IN ('.$list.')'); - } + $has_multishop_entries = $this->hasMultishopEntries(); + if (!$has_multishop_entries) { + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cms_category` WHERE `id_cms_category` IN ('.$list.')'); + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cms_category_lang` WHERE `id_cms_category` IN ('.$list.')'); + } - CMSCategory::cleanPositions($this->id_parent); + CMSCategory::cleanPositions($this->id_parent); - // Delete pages which are in categories to delete - $result = Db::getInstance()->executeS(' + // Delete pages which are in categories to delete + $result = Db::getInstance()->executeS(' SELECT `id_cms` FROM `'._DB_PREFIX_.'cms` WHERE `id_cms_category` IN ('.$list.')'); - foreach ($result as $c) - { - $cms = new CMS((int)$c['id_cms']); - if (Validate::isLoadedObject($cms)) - $cms->delete(); - } - return true; - } + foreach ($result as $c) { + $cms = new CMS((int)$c['id_cms']); + if (Validate::isLoadedObject($cms)) { + $cms->delete(); + } + } + return true; + } - /** - * Delete several categories from database - * - * return boolean Deletion result - */ - public function deleteSelection($categories) - { - $return = 1; - foreach ($categories as $id_category_cms) - { - $category_cms = new CMSCategory($id_category_cms); - $return &= $category_cms->delete(); - } - return $return; - } + /** + * Delete several categories from database + * + * return boolean Deletion result + */ + public function deleteSelection($categories) + { + $return = 1; + foreach ($categories as $id_category_cms) { + $category_cms = new CMSCategory($id_category_cms); + $return &= $category_cms->delete(); + } + return $return; + } - /** - * Get the number of parent categories - * - * @return int Level depth - */ - public function calcLevelDepth() - { - $parentCMSCategory = new CMSCategory($this->id_parent); - if (!$parentCMSCategory) - die('parent CMS Category does not exist'); - return $parentCMSCategory->level_depth + 1; - } + /** + * Get the number of parent categories + * + * @return int Level depth + */ + public function calcLevelDepth() + { + $parentCMSCategory = new CMSCategory($this->id_parent); + if (!$parentCMSCategory) { + die('parent CMS Category does not exist'); + } + return $parentCMSCategory->level_depth + 1; + } - /** - * Return available categories - * - * @param int $id_lang Language ID - * @param bool $active return only active categories - * @return array Categories - */ - public static function getCategories($id_lang, $active = true, $order = true) - { - if (!Validate::isBool($active)) - die(Tools::displayError()); + /** + * Return available categories + * + * @param int $id_lang Language ID + * @param bool $active return only active categories + * @return array Categories + */ + public static function getCategories($id_lang, $active = true, $order = true) + { + if (!Validate::isBool($active)) { + die(Tools::displayError()); + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'cms_category` c LEFT JOIN `'._DB_PREFIX_.'cms_category_lang` cl ON c.`id_cms_category` = cl.`id_cms_category` @@ -325,38 +339,41 @@ class CMSCategoryCore extends ObjectModel '.($active ? 'AND `active` = 1' : '').' ORDER BY `name` ASC'); - if (!$order) - return $result; + if (!$order) { + return $result; + } - $categories = array(); - foreach ($result as $row) - $categories[$row['id_parent']][$row['id_cms_category']]['infos'] = $row; - return $categories; - } + $categories = array(); + foreach ($result as $row) { + $categories[$row['id_parent']][$row['id_cms_category']]['infos'] = $row; + } + return $categories; + } - public static function getSimpleCategories($id_lang) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getSimpleCategories($id_lang) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT c.`id_cms_category`, cl.`name` FROM `'._DB_PREFIX_.'cms_category` c LEFT JOIN `'._DB_PREFIX_.'cms_category_lang` cl ON (c.`id_cms_category` = cl.`id_cms_category`) WHERE cl.`id_lang` = '.(int)$id_lang.' ORDER BY cl.`name`'); - } + } - /** - * Return current CMSCategory childs - * - * @param int $id_lang Language ID - * @param bool $active return only active categories - * @return array Categories - */ - public function getSubCategories($id_lang, $active = true) - { - if (!Validate::isBool($active)) - die(Tools::displayError()); + /** + * Return current CMSCategory childs + * + * @param int $id_lang Language ID + * @param bool $active return only active categories + * @return array Categories + */ + public function getSubCategories($id_lang, $active = true) + { + if (!Validate::isBool($active)) { + die(Tools::displayError()); + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT c.*, cl.id_lang, cl.name, cl.description, cl.link_rewrite, cl.meta_title, cl.meta_keywords, cl.meta_description FROM `'._DB_PREFIX_.'cms_category` c LEFT JOIN `'._DB_PREFIX_.'cms_category_lang` cl ON (c.`id_cms_category` = cl.`id_cms_category` AND `id_lang` = '.(int)$id_lang.') @@ -365,41 +382,43 @@ class CMSCategoryCore extends ObjectModel GROUP BY c.`id_cms_category` ORDER BY `name` ASC'); - // Modify SQL result - foreach ($result as &$row) - $row['name'] = CMSCategory::hideCMSCategoryPosition($row['name']); - return $result; - } + // Modify SQL result + foreach ($result as &$row) { + $row['name'] = CMSCategory::hideCMSCategoryPosition($row['name']); + } + return $result; + } - /** - * Hide CMSCategory prefix used for position - * - * @param string $name CMSCategory name - * @return string Name without position - */ - public static function hideCMSCategoryPosition($name) - { - return preg_replace('/^[0-9]+\./', '', $name); - } + /** + * Hide CMSCategory prefix used for position + * + * @param string $name CMSCategory name + * @return string Name without position + */ + public static function hideCMSCategoryPosition($name) + { + return preg_replace('/^[0-9]+\./', '', $name); + } - /** - * Return main categories - * - * @param int $id_lang Language ID - * @param bool $active return only active categories - * @return array categories - */ - public static function getHomeCategories($id_lang, $active = true) - { - return CMSCategory::getChildren(1, $id_lang, $active); - } + /** + * Return main categories + * + * @param int $id_lang Language ID + * @param bool $active return only active categories + * @return array categories + */ + public static function getHomeCategories($id_lang, $active = true) + { + return CMSCategory::getChildren(1, $id_lang, $active); + } - public static function getChildren($id_parent, $id_lang, $active = true) - { - if (!Validate::isBool($active)) - die(Tools::displayError()); + public static function getChildren($id_parent, $id_lang, $active = true) + { + if (!Validate::isBool($active)) { + die(Tools::displayError()); + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT c.`id_cms_category`, cl.`name`, cl.`link_rewrite` FROM `'._DB_PREFIX_.'cms_category` c LEFT JOIN `'._DB_PREFIX_.'cms_category_lang` cl ON c.`id_cms_category` = cl.`id_cms_category` @@ -408,217 +427,233 @@ class CMSCategoryCore extends ObjectModel '.($active ? 'AND `active` = 1' : '').' ORDER BY `name` ASC'); - // Modify SQL result - $results_array = array(); - foreach ($result as $row) - { - $row['name'] = CMSCategory::hideCMSCategoryPosition($row['name']); - $results_array[] = $row; - } - return $results_array; - } + // Modify SQL result + $results_array = array(); + foreach ($result as $row) { + $row['name'] = CMSCategory::hideCMSCategoryPosition($row['name']); + $results_array[] = $row; + } + return $results_array; + } - /** - * Check if CMSCategory can be moved in another one - * - * @param int $id_parent Parent candidate - * @return bool Parent validity - */ - public static function checkBeforeMove($id_cms_category, $id_parent) - { - if ($id_cms_category == $id_parent) return false; - if ($id_parent == 1) return true; - $i = (int)$id_parent; + /** + * Check if CMSCategory can be moved in another one + * + * @param int $id_parent Parent candidate + * @return bool Parent validity + */ + public static function checkBeforeMove($id_cms_category, $id_parent) + { + if ($id_cms_category == $id_parent) { + return false; + } + if ($id_parent == 1) { + return true; + } + $i = (int)$id_parent; - while (42) - { - $result = Db::getInstance()->getRow('SELECT `id_parent` FROM `'._DB_PREFIX_.'cms_category` WHERE `id_cms_category` = '.(int)$i); - if (!isset($result['id_parent'])) return false; - if ($result['id_parent'] == $id_cms_category) return false; - if ($result['id_parent'] == 1) return true; - $i = $result['id_parent']; - } - } + while (42) { + $result = Db::getInstance()->getRow('SELECT `id_parent` FROM `'._DB_PREFIX_.'cms_category` WHERE `id_cms_category` = '.(int)$i); + if (!isset($result['id_parent'])) { + return false; + } + if ($result['id_parent'] == $id_cms_category) { + return false; + } + if ($result['id_parent'] == 1) { + return true; + } + $i = $result['id_parent']; + } + } - public static function getLinkRewrite($id_cms_category, $id_lang) - { - if (!Validate::isUnsignedId($id_cms_category) || !Validate::isUnsignedId($id_lang)) - return false; + public static function getLinkRewrite($id_cms_category, $id_lang) + { + if (!Validate::isUnsignedId($id_cms_category) || !Validate::isUnsignedId($id_lang)) { + return false; + } - if (isset(self::$_links[$id_cms_category.'-'.$id_lang])) - return self::$_links[$id_cms_category.'-'.$id_lang]; + if (isset(self::$_links[$id_cms_category.'-'.$id_lang])) { + return self::$_links[$id_cms_category.'-'.$id_lang]; + } - $result = Db::getInstance()->getRow(' + $result = Db::getInstance()->getRow(' SELECT cl.`link_rewrite` FROM `'._DB_PREFIX_.'cms_category` c LEFT JOIN `'._DB_PREFIX_.'cms_category_lang` cl ON c.`id_cms_category` = cl.`id_cms_category` WHERE `id_lang` = '.(int)$id_lang.' AND c.`id_cms_category` = '.(int)$id_cms_category); - self::$_links[$id_cms_category.'-'.$id_lang] = $result['link_rewrite']; - return $result['link_rewrite']; - } + self::$_links[$id_cms_category.'-'.$id_lang] = $result['link_rewrite']; + return $result['link_rewrite']; + } - public function getLink(Link $link = null) - { - if (!$link) - $link = Context::getContext()->link; - return $link->getCMSCategoryLink($this->id, $this->link_rewrite); - } + public function getLink(Link $link = null) + { + if (!$link) { + $link = Context::getContext()->link; + } + return $link->getCMSCategoryLink($this->id, $this->link_rewrite); + } - public function getName($id_lang = null) - { - $context = Context::getContext(); - if (!$id_lang) - { - if (isset($this->name[$context->language->id])) - $id_lang = $context->language->id; - else - $id_lang = (int)Configuration::get('PS_LANG_DEFAULT'); - } - return isset($this->name[$id_lang]) ? $this->name[$id_lang] : ''; - } + public function getName($id_lang = null) + { + $context = Context::getContext(); + if (!$id_lang) { + if (isset($this->name[$context->language->id])) { + $id_lang = $context->language->id; + } else { + $id_lang = (int)Configuration::get('PS_LANG_DEFAULT'); + } + } + return isset($this->name[$id_lang]) ? $this->name[$id_lang] : ''; + } - /** - * Light back office search for categories - * - * @param int $id_lang Language ID - * @param string $query Searched string - * @param bool $unrestricted allows search without lang and includes first CMSCategory and exact match - * @return array Corresponding categories - */ - public static function searchByName($id_lang, $query, $unrestricted = false) - { - if ($unrestricted === true) - return Db::getInstance()->getRow(' + /** + * Light back office search for categories + * + * @param int $id_lang Language ID + * @param string $query Searched string + * @param bool $unrestricted allows search without lang and includes first CMSCategory and exact match + * @return array Corresponding categories + */ + public static function searchByName($id_lang, $query, $unrestricted = false) + { + if ($unrestricted === true) { + return Db::getInstance()->getRow(' SELECT c.*, cl.* FROM `'._DB_PREFIX_.'cms_category` c LEFT JOIN `'._DB_PREFIX_.'cms_category_lang` cl ON (c.`id_cms_category` = cl.`id_cms_category`) WHERE `name` = \''.pSQL($query).'\''); - else - return Db::getInstance()->executeS(' + } else { + return Db::getInstance()->executeS(' SELECT c.*, cl.* FROM `'._DB_PREFIX_.'cms_category` c LEFT JOIN `'._DB_PREFIX_.'cms_category_lang` cl ON (c.`id_cms_category` = cl.`id_cms_category` AND `id_lang` = '.(int)$id_lang.') WHERE `name` LIKE \'%'.pSQL($query).'%\' AND c.`id_cms_category` != 1'); - } + } + } - /** - * Retrieve CMSCategory by name and parent CMSCategory id - * - * @param int $id_lang Language ID - * @param string $CMSCategory_name Searched CMSCategory name - * @param int $id_parent_CMSCategory parent CMSCategory ID - * @return array Corresponding CMSCategory - * @deprecated 1.5.3.0 - */ - public static function searchByNameAndParentCMSCategoryId($id_lang, $CMSCategory_name, $id_parent_CMSCategory) - { - Tools::displayAsDeprecated(); - return Db::getInstance()->getRow(' + /** + * Retrieve CMSCategory by name and parent CMSCategory id + * + * @param int $id_lang Language ID + * @param string $CMSCategory_name Searched CMSCategory name + * @param int $id_parent_CMSCategory parent CMSCategory ID + * @return array Corresponding CMSCategory + * @deprecated 1.5.3.0 + */ + public static function searchByNameAndParentCMSCategoryId($id_lang, $CMSCategory_name, $id_parent_CMSCategory) + { + Tools::displayAsDeprecated(); + return Db::getInstance()->getRow(' SELECT c.*, cl.* FROM `'._DB_PREFIX_.'cms_category` c LEFT JOIN `'._DB_PREFIX_.'cms_category_lang` cl ON (c.`id_cms_category` = cl.`id_cms_category` AND `id_lang` = '.(int)$id_lang.') WHERE `name` = \''.pSQL($CMSCategory_name).'\' AND c.`id_cms_category` != 1 AND c.`id_parent` = '.(int)$id_parent_CMSCategory); - } + } - /** - * Get Each parent CMSCategory of this CMSCategory until the root CMSCategory - * - * @param int $id_lang Language ID - * @return array Corresponding categories - */ - public function getParentsCategories($id_lang = null) - { - if (is_null($id_lang)) - $id_lang = Context::getContext()->language->id; + /** + * Get Each parent CMSCategory of this CMSCategory until the root CMSCategory + * + * @param int $id_lang Language ID + * @return array Corresponding categories + */ + public function getParentsCategories($id_lang = null) + { + if (is_null($id_lang)) { + $id_lang = Context::getContext()->language->id; + } - $categories = null; - $id_current = $this->id; - while (true) - { - $query = ' + $categories = null; + $id_current = $this->id; + while (true) { + $query = ' SELECT c.*, cl.* FROM `'._DB_PREFIX_.'cms_category` c LEFT JOIN `'._DB_PREFIX_.'cms_category_lang` cl ON (c.`id_cms_category` = cl.`id_cms_category` AND `id_lang` = '.(int)$id_lang.') WHERE c.`id_cms_category` = '.(int)$id_current.' AND c.`id_parent` != 0 '; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - $categories[] = $result[0]; - if (!$result || $result[0]['id_parent'] == 1) - return $categories; - $id_current = $result[0]['id_parent']; - } - } + $categories[] = $result[0]; + if (!$result || $result[0]['id_parent'] == 1) { + return $categories; + } + $id_current = $result[0]['id_parent']; + } + } - public function updatePosition($way, $position) - { - if (!$res = Db::getInstance()->executeS(' + public function updatePosition($way, $position) + { + if (!$res = Db::getInstance()->executeS(' SELECT cp.`id_cms_category`, cp.`position`, cp.`id_parent` FROM `'._DB_PREFIX_.'cms_category` cp WHERE cp.`id_parent` = '.(int)$this->id_parent.' ORDER BY cp.`position` ASC' - )) - return false; - foreach ($res as $category) - if ((int)$category['id_cms_category'] == (int)$this->id) - $moved_category = $category; + )) { + return false; + } + foreach ($res as $category) { + if ((int)$category['id_cms_category'] == (int)$this->id) { + $moved_category = $category; + } + } - if (!isset($moved_category) || !isset($position)) - return false; - // < and > statements rather than BETWEEN operator - // since BETWEEN is treated differently according to databases - return (Db::getInstance()->execute(' + if (!isset($moved_category) || !isset($position)) { + return false; + } + // < and > statements rather than BETWEEN operator + // since BETWEEN is treated differently according to databases + return (Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'cms_category` SET `position`= `position` '.($way ? '- 1' : '+ 1').' WHERE `position` '.($way - ? '> '.(int)$moved_category['position'].' AND `position` <= '.(int)$position - : '< '.(int)$moved_category['position'].' AND `position` >= '.(int)$position).' + ? '> '.(int)$moved_category['position'].' AND `position` <= '.(int)$position + : '< '.(int)$moved_category['position'].' AND `position` >= '.(int)$position).' AND `id_parent`='.(int)$moved_category['id_parent']) - && Db::getInstance()->execute(' + && Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'cms_category` SET `position` = '.(int)$position.' WHERE `id_parent` = '.(int)$moved_category['id_parent'].' AND `id_cms_category`='.(int)$moved_category['id_cms_category'])); - } + } - public static function cleanPositions($id_category_parent) - { - $result = Db::getInstance()->executeS(' + public static function cleanPositions($id_category_parent) + { + $result = Db::getInstance()->executeS(' SELECT `id_cms_category` FROM `'._DB_PREFIX_.'cms_category` WHERE `id_parent` = '.(int)$id_category_parent.' ORDER BY `position`'); - $sizeof = count($result); - for ($i = 0; $i < $sizeof; ++$i) - { - $sql = ' + $sizeof = count($result); + for ($i = 0; $i < $sizeof; ++$i) { + $sql = ' UPDATE `'._DB_PREFIX_.'cms_category` SET `position` = '.(int)$i.' WHERE `id_parent` = '.(int)$id_category_parent.' AND `id_cms_category` = '.(int)$result[$i]['id_cms_category']; - Db::getInstance()->execute($sql); - } - return true; - } + Db::getInstance()->execute($sql); + } + return true; + } - public static function getLastPosition($id_category_parent) - { - return (Db::getInstance()->getValue('SELECT MAX(position)+1 FROM `'._DB_PREFIX_.'cms_category` WHERE `id_parent` = '.(int)$id_category_parent)); - } + public static function getLastPosition($id_category_parent) + { + return (Db::getInstance()->getValue('SELECT MAX(position)+1 FROM `'._DB_PREFIX_.'cms_category` WHERE `id_parent` = '.(int)$id_category_parent)); + } - public static function getUrlRewriteInformations($id_category) - { - $sql = ' + public static function getUrlRewriteInformations($id_category) + { + $sql = ' SELECT l.`id_lang`, c.`link_rewrite` FROM `'._DB_PREFIX_.'cms_category_lang` AS c LEFT JOIN `'._DB_PREFIX_.'lang` AS l ON c.`id_lang` = l.`id_lang` WHERE c.`id_cms_category` = '.(int)$id_category.' AND l.`active` = 1'; - $arr_return = Db::getInstance()->executeS($sql); - return $arr_return; - } + $arr_return = Db::getInstance()->executeS($sql); + return $arr_return; + } } diff --git a/classes/CMSRole.php b/classes/CMSRole.php index 694c1eab..a5f1cb15 100644 --- a/classes/CMSRole.php +++ b/classes/CMSRole.php @@ -27,26 +27,25 @@ class CMSRoleCore extends ObjectModel { - /** @var string name */ - public $name; - /** @var integer id_cms */ - public $id_cms; + /** @var string name */ + public $name; + /** @var integer id_cms */ + public $id_cms; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'cms_role', - 'primary' => 'id_cms_role', - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 50), - 'id_cms' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - ), - ); - - public static function getRepositoryClassName() - { - return 'Core_Business_CMS_CMSRoleRepository'; - } + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'cms_role', + 'primary' => 'id_cms_role', + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 50), + 'id_cms' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + ), + ); + public static function getRepositoryClassName() + { + return 'Core_Business_CMS_CMSRoleRepository'; + } } diff --git a/classes/CSV.php b/classes/CSV.php index b1d4c19c..1ce5e40a 100644 --- a/classes/CSV.php +++ b/classes/CSV.php @@ -31,78 +31,76 @@ */ class CSVCore { - public $filename; - public $collection; - public $delimiter; + public $filename; + public $collection; + public $delimiter; - /** - * Loads objects, filename and optionnaly a delimiter. - * @param array|Iterator $collection Collection of objects / arrays (of non-objects) - * @param string $filename : used later to save the file - * @param string $delimiter Optional : delimiter used - */ - public function __construct($collection, $filename, $delimiter = ';') - { - $this->filename = $filename; - $this->delimiter = $delimiter; - $this->collection = $collection; - } + /** + * Loads objects, filename and optionnaly a delimiter. + * @param array|Iterator $collection Collection of objects / arrays (of non-objects) + * @param string $filename : used later to save the file + * @param string $delimiter Optional : delimiter used + */ + public function __construct($collection, $filename, $delimiter = ';') + { + $this->filename = $filename; + $this->delimiter = $delimiter; + $this->collection = $collection; + } - /** - * Main function - * Adds headers - * Outputs - */ - public function export() - { - $this->headers(); + /** + * Main function + * Adds headers + * Outputs + */ + public function export() + { + $this->headers(); - $header_line = false; + $header_line = false; - foreach ($this->collection as $object) - { - $vars = get_object_vars($object); - if (!$header_line) - { - $this->output(array_keys($vars)); - $header_line = true; - } + foreach ($this->collection as $object) { + $vars = get_object_vars($object); + if (!$header_line) { + $this->output(array_keys($vars)); + $header_line = true; + } - // outputs values - $this->output($vars); - unset($vars); - } - } + // outputs values + $this->output($vars); + unset($vars); + } + } - /** - * Wraps data and echoes - * Uses defined delimiter - */ - public function output($data) - { - $wraped_data = array_map(array('CSVCore', 'wrap'), $data); - echo sprintf("%s\n", implode($this->delimiter, $wraped_data)); - } + /** + * Wraps data and echoes + * Uses defined delimiter + */ + public function output($data) + { + $wraped_data = array_map(array('CSVCore', 'wrap'), $data); + echo sprintf("%s\n", implode($this->delimiter, $wraped_data)); + } - /** - * Escapes data - * @param string $data - * @return string $data - */ - public static function wrap($data) - { - $data = Tools::str_replace(array('"', ';'), '', $data); - return sprintf('"%s"', $data); - } + /** + * Escapes data + * @param string $data + * @return string $data + */ + public static function wrap($data) + { + $data = str_replace(array('"', ';'), '', $data); + return sprintf('"%s"', $data); + } - /** - * Adds headers - */ - public function headers() - { - header('Content-type: text/csv'); - header('Content-Type: application/force-download; charset=UTF-8'); - header('Cache-Control: no-store, no-cache'); - header('Content-disposition: attachment; filename="'.$this->filename.'.csv"'); - } -} \ No newline at end of file + /** + * Adds headers + */ + public function headers() + { + header('Content-type: text/csv'); + header('Content-Type: application/force-download; charset=UTF-8'); + header('Cache-Control: no-store, no-cache'); + header('Content-disposition: attachment; filename="'.$this->filename.'.csv"'); + } +} diff --git a/classes/Carrier.php b/classes/Carrier.php index 3e74a445..2adc2410 100644 --- a/classes/Carrier.php +++ b/classes/Carrier.php @@ -26,225 +26,231 @@ class CarrierCore extends ObjectModel { - /** - * getCarriers method filter - */ - const PS_CARRIERS_ONLY = 1; - const CARRIERS_MODULE = 2; - const CARRIERS_MODULE_NEED_RANGE = 3; - const PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE = 4; - const ALL_CARRIERS = 5; + /** + * getCarriers method filter + */ + const PS_CARRIERS_ONLY = 1; + const CARRIERS_MODULE = 2; + const CARRIERS_MODULE_NEED_RANGE = 3; + const PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE = 4; + const ALL_CARRIERS = 5; - const SHIPPING_METHOD_DEFAULT = 0; - const SHIPPING_METHOD_WEIGHT = 1; - const SHIPPING_METHOD_PRICE = 2; - const SHIPPING_METHOD_FREE = 3; + const SHIPPING_METHOD_DEFAULT = 0; + const SHIPPING_METHOD_WEIGHT = 1; + const SHIPPING_METHOD_PRICE = 2; + const SHIPPING_METHOD_FREE = 3; - const SHIPPING_PRICE_EXCEPTION = 0; - const SHIPPING_WEIGHT_EXCEPTION = 1; - const SHIPPING_SIZE_EXCEPTION = 2; + const SHIPPING_PRICE_EXCEPTION = 0; + const SHIPPING_WEIGHT_EXCEPTION = 1; + const SHIPPING_SIZE_EXCEPTION = 2; - const SORT_BY_PRICE = 0; - const SORT_BY_POSITION = 1; + const SORT_BY_PRICE = 0; + const SORT_BY_POSITION = 1; - const SORT_BY_ASC = 0; - const SORT_BY_DESC = 1; + const SORT_BY_ASC = 0; + const SORT_BY_DESC = 1; - /** @var int common id for carrier historization */ - public $id_reference; + /** @var int common id for carrier historization */ + public $id_reference; - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var string URL with a '@' for */ - public $url; + /** @var string URL with a '@' for */ + public $url; - /** @var string Delay needed to deliver customer */ - public $delay; + /** @var string Delay needed to deliver customer */ + public $delay; - /** @var bool Carrier statuts */ - public $active = true; + /** @var bool Carrier statuts */ + public $active = true; - /** @var bool True if carrier has been deleted (staying in database as deleted) */ - public $deleted = 0; + /** @var bool True if carrier has been deleted (staying in database as deleted) */ + public $deleted = 0; - /** @var bool Active or not the shipping handling */ - public $shipping_handling = true; + /** @var bool Active or not the shipping handling */ + public $shipping_handling = true; - /** @var int Behavior taken for unknown range */ - public $range_behavior; + /** @var int Behavior taken for unknown range */ + public $range_behavior; - /** @var bool Carrier module */ - public $is_module; + /** @var bool Carrier module */ + public $is_module; - /** @var bool Free carrier */ - public $is_free = false; + /** @var bool Free carrier */ + public $is_free = false; - /** @var int shipping behavior: by weight or by price */ - public $shipping_method = 0; + /** @var int shipping behavior: by weight or by price */ + public $shipping_method = 0; - /** @var bool Shipping external */ - public $shipping_external = 0; + /** @var bool Shipping external */ + public $shipping_external = 0; - /** @var string Shipping external */ - public $external_module_name = null; + /** @var string Shipping external */ + public $external_module_name = null; - /** @var bool Need Range */ - public $need_range = 0; + /** @var bool Need Range */ + public $need_range = 0; - /** @var int Position */ - public $position; + /** @var int Position */ + public $position; - /** @var int maximum package width managed by the transporter */ - public $max_width; + /** @var int maximum package width managed by the transporter */ + public $max_width; - /** @var int maximum package height managed by the transporter */ - public $max_height; + /** @var int maximum package height managed by the transporter */ + public $max_height; - /** @var int maximum package deep managed by the transporter */ - public $max_depth; + /** @var int maximum package deep managed by the transporter */ + public $max_depth; - /** @var int maximum package weight managed by the transporter */ - public $max_weight; + /** @var int maximum package weight managed by the transporter */ + public $max_weight; - /** @var int grade of the shipping delay (0 for longest, 9 for shortest) */ - public $grade; + /** @var int grade of the shipping delay (0 for longest, 9 for shortest) */ + public $grade; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'carrier', - 'primary' => 'id_carrier', - 'multilang' => true, - 'multilang_shop' => true, - 'fields' => array( - /* Classic fields */ - 'id_reference' => array('type' => self::TYPE_INT), - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isCarrierName', 'required' => true, 'size' => 64), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), - 'is_free' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'url' => array('type' => self::TYPE_STRING, 'validate' => 'isAbsoluteUrl'), - 'shipping_handling' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'shipping_external' => array('type' => self::TYPE_BOOL), - 'range_behavior' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'shipping_method' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'max_width' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'max_height' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'max_depth' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'max_weight' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'grade' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'size' => 1), - 'external_module_name' => array('type' => self::TYPE_STRING, 'size' => 64), - 'is_module' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'need_range' => array('type' => self::TYPE_BOOL), - 'position' => array('type' => self::TYPE_INT), - 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'carrier', + 'primary' => 'id_carrier', + 'multilang' => true, + 'multilang_shop' => true, + 'fields' => array( + /* Classic fields */ + 'id_reference' => array('type' => self::TYPE_INT), + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isCarrierName', 'required' => true, 'size' => 64), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), + 'is_free' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'url' => array('type' => self::TYPE_STRING, 'validate' => 'isAbsoluteUrl'), + 'shipping_handling' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'shipping_external' => array('type' => self::TYPE_BOOL), + 'range_behavior' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'shipping_method' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'max_width' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'max_height' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'max_depth' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'max_weight' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'grade' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'size' => 1), + 'external_module_name' => array('type' => self::TYPE_STRING, 'size' => 64), + 'is_module' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'need_range' => array('type' => self::TYPE_BOOL), + 'position' => array('type' => self::TYPE_INT), + 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - /* Lang fields */ - 'delay' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), - ), - ); + /* Lang fields */ + 'delay' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), + ), + ); - protected static $price_by_weight = array(); - protected static $price_by_weight2 = array(); - protected static $price_by_price = array(); - protected static $price_by_price2 = array(); + protected static $price_by_weight = array(); + protected static $price_by_weight2 = array(); + protected static $price_by_price = array(); + protected static $price_by_price2 = array(); - protected static $cache_tax_rule = array(); + protected static $cache_tax_rule = array(); - protected $webserviceParameters = array( - 'fields' => array( - 'deleted' => array(), - 'is_module' => array(), - 'id_tax_rules_group' => array( - 'getter' => 'getIdTaxRulesGroup', - 'setter' => 'setTaxRulesGroup', - 'xlink_resource' => array( - 'resourceName' => 'tax_rule_groups' - ) - ), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'deleted' => array(), + 'is_module' => array(), + 'id_tax_rules_group' => array( + 'getter' => 'getIdTaxRulesGroup', + 'setter' => 'setTaxRulesGroup', + 'xlink_resource' => array( + 'resourceName' => 'tax_rule_groups' + ) + ), + ), + ); - public function __construct($id = null, $id_lang = null) - { - parent::__construct($id, $id_lang); + public function __construct($id = null, $id_lang = null) + { + parent::__construct($id, $id_lang); - /** - * keep retrocompatibility SHIPPING_METHOD_DEFAULT - * @deprecated 1.5.5 - */ - if ($this->shipping_method == Carrier::SHIPPING_METHOD_DEFAULT) - $this->shipping_method = ((int)Configuration::get('PS_SHIPPING_METHOD') ? Carrier::SHIPPING_METHOD_WEIGHT : Carrier::SHIPPING_METHOD_PRICE); + /** + * keep retrocompatibility SHIPPING_METHOD_DEFAULT + * @deprecated 1.5.5 + */ + if ($this->shipping_method == Carrier::SHIPPING_METHOD_DEFAULT) { + $this->shipping_method = ((int)Configuration::get('PS_SHIPPING_METHOD') ? Carrier::SHIPPING_METHOD_WEIGHT : Carrier::SHIPPING_METHOD_PRICE); + } - /** - * keep retrocompatibility id_tax_rules_group - * @deprecated 1.5.0 - */ - if ($this->id) - $this->id_tax_rules_group = $this->getIdTaxRulesGroup(Context::getContext()); + /** + * keep retrocompatibility id_tax_rules_group + * @deprecated 1.5.0 + */ + if ($this->id) { + $this->id_tax_rules_group = $this->getIdTaxRulesGroup(Context::getContext()); + } - if ($this->name == '0') - $this->name = Carrier::getCarrierNameFromShopName(); + if ($this->name == '0') { + $this->name = Carrier::getCarrierNameFromShopName(); + } - $this->image_dir = _PS_SHIP_IMG_DIR_; - } + $this->image_dir = _PS_SHIP_IMG_DIR_; + } - public function add($autodate = true, $null_values = false) - { - if ($this->position <= 0) - $this->position = Carrier::getHigherPosition() + 1; - if (!parent::add($autodate, $null_values) || !Validate::isLoadedObject($this)) - return false; - if (!$count = Db::getInstance()->getValue('SELECT count(`id_carrier`) FROM `'._DB_PREFIX_.$this->def['table'].'` WHERE `deleted` = 0')) - return false; - if ($count == 1) - Configuration::updateValue('PS_CARRIER_DEFAULT', (int)$this->id); + public function add($autodate = true, $null_values = false) + { + if ($this->position <= 0) { + $this->position = Carrier::getHigherPosition() + 1; + } + if (!parent::add($autodate, $null_values) || !Validate::isLoadedObject($this)) { + return false; + } + if (!$count = Db::getInstance()->getValue('SELECT count(`id_carrier`) FROM `'._DB_PREFIX_.$this->def['table'].'` WHERE `deleted` = 0')) { + return false; + } + if ($count == 1) { + Configuration::updateValue('PS_CARRIER_DEFAULT', (int)$this->id); + } - // Register reference - Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.$this->def['table'].'` SET `id_reference` = '.$this->id.' WHERE `id_carrier` = '.$this->id); + // Register reference + Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.$this->def['table'].'` SET `id_reference` = '.$this->id.' WHERE `id_carrier` = '.$this->id); - return true; - } + return true; + } - /** - * @since 1.5.0 - * @see ObjectModel::delete() - */ - public function delete() - { - if (!parent::delete()) - return false; - Carrier::cleanPositions(); - return (Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'cart_rule_carrier WHERE id_carrier = '.(int)$this->id) && - $this->deleteTaxRulesGroup(Shop::getShops(true, null, true))); + /** + * @since 1.5.0 + * @see ObjectModel::delete() + */ + public function delete() + { + if (!parent::delete()) { + return false; + } + Carrier::cleanPositions(); + return (Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'cart_rule_carrier WHERE id_carrier = '.(int)$this->id) && + $this->deleteTaxRulesGroup(Shop::getShops(true, null, true))); + } - } + /** + * Change carrier id in delivery prices when updating a carrier + * + * @param int $id_old Old id carrier + */ + public function setConfiguration($id_old) + { + Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'delivery` SET `id_carrier` = '.(int)$this->id.' WHERE `id_carrier` = '.(int)$id_old); + } - /** - * Change carrier id in delivery prices when updating a carrier - * - * @param int $id_old Old id carrier - */ - public function setConfiguration($id_old) - { - Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'delivery` SET `id_carrier` = '.(int)$this->id.' WHERE `id_carrier` = '.(int)$id_old); - } - - /** - * Get delivery prices for a given order - * - * @param float $total_weight Total order weight - * @param int $id_zone Zone ID (for customer delivery address) - * @return float Delivery price - */ - public function getDeliveryPriceByWeight($total_weight, $id_zone) - { - $id_carrier = (int)$this->id; - $cache_key = $id_carrier.'_'.$total_weight.'_'.$id_zone; - if (!isset(self::$price_by_weight[$cache_key])) - { - $sql = 'SELECT d.`price` + /** + * Get delivery prices for a given order + * + * @param float $total_weight Total order weight + * @param int $id_zone Zone ID (for customer delivery address) + * @return float Delivery price + */ + public function getDeliveryPriceByWeight($total_weight, $id_zone) + { + $id_carrier = (int)$this->id; + $cache_key = $id_carrier.'_'.$total_weight.'_'.$id_zone; + if (!isset(self::$price_by_weight[$cache_key])) { + $sql = 'SELECT d.`price` FROM `'._DB_PREFIX_.'delivery` d LEFT JOIN `'._DB_PREFIX_.'range_weight` w ON (d.`id_range_weight` = w.`id_range_weight`) WHERE d.`id_zone` = '.(int)$id_zone.' @@ -253,27 +259,28 @@ class CarrierCore extends ObjectModel AND d.`id_carrier` = '.$id_carrier.' '.Carrier::sqlDeliveryRangeShop('range_weight').' ORDER BY w.`delimiter1` ASC'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); - if (!isset($result['price'])) - self::$price_by_weight[$cache_key] = $this->getMaxDeliveryPriceByWeight($id_zone); - else - self::$price_by_weight[$cache_key] = $result['price']; - } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + if (!isset($result['price'])) { + self::$price_by_weight[$cache_key] = $this->getMaxDeliveryPriceByWeight($id_zone); + } else { + self::$price_by_weight[$cache_key] = $result['price']; + } + } - $price_by_weight = Hook::exec('actionDeliveryPriceByWeight', array('id_carrier' => $id_carrier, 'total_weight' => $total_weight, 'id_zone' => $id_zone)); - if (is_numeric($price_by_weight)) - self::$price_by_weight[$cache_key] = $price_by_weight; + $price_by_weight = Hook::exec('actionDeliveryPriceByWeight', array('id_carrier' => $id_carrier, 'total_weight' => $total_weight, 'id_zone' => $id_zone)); + if (is_numeric($price_by_weight)) { + self::$price_by_weight[$cache_key] = $price_by_weight; + } - return self::$price_by_weight[$cache_key]; - } + return self::$price_by_weight[$cache_key]; + } - public static function checkDeliveryPriceByWeight($id_carrier, $total_weight, $id_zone) - { - $id_carrier = (int)$id_carrier; - $cache_key = $id_carrier.'_'.$total_weight.'_'.$id_zone; - if (!isset(self::$price_by_weight2[$cache_key])) - { - $sql = 'SELECT d.`price` + public static function checkDeliveryPriceByWeight($id_carrier, $total_weight, $id_zone) + { + $id_carrier = (int)$id_carrier; + $cache_key = $id_carrier.'_'.$total_weight.'_'.$id_zone; + if (!isset(self::$price_by_weight2[$cache_key])) { + $sql = 'SELECT d.`price` FROM `'._DB_PREFIX_.'delivery` d LEFT JOIN `'._DB_PREFIX_.'range_weight` w ON d.`id_range_weight` = w.`id_range_weight` WHERE d.`id_zone` = '.(int)$id_zone.' @@ -282,54 +289,54 @@ class CarrierCore extends ObjectModel AND d.`id_carrier` = '.$id_carrier.' '.Carrier::sqlDeliveryRangeShop('range_weight').' ORDER BY w.`delimiter1` ASC'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); - self::$price_by_weight2[$cache_key] = (isset($result['price'])); - } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + self::$price_by_weight2[$cache_key] = (isset($result['price'])); + } - $price_by_weight = Hook::exec('actionDeliveryPriceByWeight', array('id_carrier' => $id_carrier, 'total_weight' => $total_weight, 'id_zone' => $id_zone)); - if (is_numeric($price_by_weight)) - self::$price_by_weight2[$cache_key] = $price_by_weight; + $price_by_weight = Hook::exec('actionDeliveryPriceByWeight', array('id_carrier' => $id_carrier, 'total_weight' => $total_weight, 'id_zone' => $id_zone)); + if (is_numeric($price_by_weight)) { + self::$price_by_weight2[$cache_key] = $price_by_weight; + } - return self::$price_by_weight2[$cache_key]; - } + return self::$price_by_weight2[$cache_key]; + } - public function getMaxDeliveryPriceByWeight($id_zone) - { - $cache_id = 'Carrier::getMaxDeliveryPriceByWeight_'.(int)$this->id.'-'.(int)$id_zone; - if (!Cache::isStored($cache_id)) - { - $sql = 'SELECT d.`price` + public function getMaxDeliveryPriceByWeight($id_zone) + { + $cache_id = 'Carrier::getMaxDeliveryPriceByWeight_'.(int)$this->id.'-'.(int)$id_zone; + if (!Cache::isStored($cache_id)) { + $sql = 'SELECT d.`price` FROM `'._DB_PREFIX_.'delivery` d INNER JOIN `'._DB_PREFIX_.'range_weight` w ON d.`id_range_weight` = w.`id_range_weight` WHERE d.`id_zone` = '.(int)$id_zone.' AND d.`id_carrier` = '.(int)$this->id.' '.Carrier::sqlDeliveryRangeShop('range_weight').' ORDER BY w.`delimiter2` DESC'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Get delivery prices for a given order - * - * @param float $order_total Order total to pay - * @param int $id_zone Zone id (for customer delivery address) - * @param int|null $id_currency - * @return float Delivery price - */ - public function getDeliveryPriceByPrice($order_total, $id_zone, $id_currency = null) - { - $id_carrier = (int)$this->id; - $cache_key = $this->id.'_'.$order_total.'_'.$id_zone.'_'.$id_currency; - if (!isset(self::$price_by_price[$cache_key])) - { - if (!empty($id_currency)) - $order_total = Tools::convertPrice($order_total, $id_currency, false); + /** + * Get delivery prices for a given order + * + * @param float $order_total Order total to pay + * @param int $id_zone Zone id (for customer delivery address) + * @param int|null $id_currency + * @return float Delivery price + */ + public function getDeliveryPriceByPrice($order_total, $id_zone, $id_currency = null) + { + $id_carrier = (int)$this->id; + $cache_key = $this->id.'_'.$order_total.'_'.$id_zone.'_'.$id_currency; + if (!isset(self::$price_by_price[$cache_key])) { + if (!empty($id_currency)) { + $order_total = Tools::convertPrice($order_total, $id_currency, false); + } - $sql = 'SELECT d.`price` + $sql = 'SELECT d.`price` FROM `'._DB_PREFIX_.'delivery` d LEFT JOIN `'._DB_PREFIX_.'range_price` r ON d.`id_range_price` = r.`id_range_price` WHERE d.`id_zone` = '.(int)$id_zone.' @@ -338,39 +345,41 @@ class CarrierCore extends ObjectModel AND d.`id_carrier` = '.$id_carrier.' '.Carrier::sqlDeliveryRangeShop('range_price').' ORDER BY r.`delimiter1` ASC'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); - if (!isset($result['price'])) - self::$price_by_price[$cache_key] = $this->getMaxDeliveryPriceByPrice($id_zone); - else - self::$price_by_price[$cache_key] = $result['price']; - } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + if (!isset($result['price'])) { + self::$price_by_price[$cache_key] = $this->getMaxDeliveryPriceByPrice($id_zone); + } else { + self::$price_by_price[$cache_key] = $result['price']; + } + } - $price_by_price = Hook::exec('actionDeliveryPriceByPrice', array('id_carrier' => $id_carrier, 'order_total' => $order_total, 'id_zone' => $id_zone)); - if (is_numeric($price_by_price)) - self::$price_by_price[$cache_key] = $price_by_price; + $price_by_price = Hook::exec('actionDeliveryPriceByPrice', array('id_carrier' => $id_carrier, 'order_total' => $order_total, 'id_zone' => $id_zone)); + if (is_numeric($price_by_price)) { + self::$price_by_price[$cache_key] = $price_by_price; + } - return self::$price_by_price[$cache_key]; - } + return self::$price_by_price[$cache_key]; + } - /** - * Check delivery prices for a given order - * - * @param int $id_carrier - * @param float $order_total Order total to pay - * @param int $id_zone Zone id (for customer delivery address) - * @param int|null $id_currency - * @return float Delivery price - */ - public static function checkDeliveryPriceByPrice($id_carrier, $order_total, $id_zone, $id_currency = null) - { - $id_carrier = (int)$id_carrier; - $cache_key = $id_carrier.'_'.$order_total.'_'.$id_zone.'_'.$id_currency; - if (!isset(self::$price_by_price2[$cache_key])) - { - if (!empty($id_currency)) - $order_total = Tools::convertPrice($order_total, $id_currency, false); + /** + * Check delivery prices for a given order + * + * @param int $id_carrier + * @param float $order_total Order total to pay + * @param int $id_zone Zone id (for customer delivery address) + * @param int|null $id_currency + * @return float Delivery price + */ + public static function checkDeliveryPriceByPrice($id_carrier, $order_total, $id_zone, $id_currency = null) + { + $id_carrier = (int)$id_carrier; + $cache_key = $id_carrier.'_'.$order_total.'_'.$id_zone.'_'.$id_currency; + if (!isset(self::$price_by_price2[$cache_key])) { + if (!empty($id_currency)) { + $order_total = Tools::convertPrice($order_total, $id_currency, false); + } - $sql = 'SELECT d.`price` + $sql = 'SELECT d.`price` FROM `'._DB_PREFIX_.'delivery` d LEFT JOIN `'._DB_PREFIX_.'range_price` r ON d.`id_range_price` = r.`id_range_price` WHERE d.`id_zone` = '.(int)$id_zone.' @@ -379,44 +388,44 @@ class CarrierCore extends ObjectModel AND d.`id_carrier` = '.$id_carrier.' '.Carrier::sqlDeliveryRangeShop('range_price').' ORDER BY r.`delimiter1` ASC'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); - self::$price_by_price2[$cache_key] = (isset($result['price'])); - } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + self::$price_by_price2[$cache_key] = (isset($result['price'])); + } - $price_by_price = Hook::exec('actionDeliveryPriceByPrice', array('id_carrier' => $id_carrier, 'order_total' => $order_total, 'id_zone' => $id_zone)); - if (is_numeric($price_by_price)) - self::$price_by_price2[$cache_key] = $price_by_price; + $price_by_price = Hook::exec('actionDeliveryPriceByPrice', array('id_carrier' => $id_carrier, 'order_total' => $order_total, 'id_zone' => $id_zone)); + if (is_numeric($price_by_price)) { + self::$price_by_price2[$cache_key] = $price_by_price; + } - return self::$price_by_price2[$cache_key]; - } + return self::$price_by_price2[$cache_key]; + } - public function getMaxDeliveryPriceByPrice($id_zone) - { - $cache_id = 'Carrier::getMaxDeliveryPriceByPrice_'.(int)$this->id.'-'.(int)$id_zone; - if (!Cache::isStored($cache_id)) - { - $sql = 'SELECT d.`price` + public function getMaxDeliveryPriceByPrice($id_zone) + { + $cache_id = 'Carrier::getMaxDeliveryPriceByPrice_'.(int)$this->id.'-'.(int)$id_zone; + if (!Cache::isStored($cache_id)) { + $sql = 'SELECT d.`price` FROM `'._DB_PREFIX_.'delivery` d INNER JOIN `'._DB_PREFIX_.'range_price` r ON d.`id_range_price` = r.`id_range_price` WHERE d.`id_zone` = '.(int)$id_zone.' AND d.`id_carrier` = '.(int)$this->id.' '.Carrier::sqlDeliveryRangeShop('range_price').' ORDER BY r.`delimiter2` DESC'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); - Cache::store($cache_id, $result); - } - return Cache::retrieve($cache_id); - } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); + Cache::store($cache_id, $result); + } + return Cache::retrieve($cache_id); + } - /** - * Get delivery prices for a given shipping method (price/weight) - * - * @param string $rangeTable Table name (price or weight) - * @return array Delivery prices - */ - public static function getDeliveryPriceByRanges($range_table, $id_carrier) - { - $sql = 'SELECT d.`id_'.bqSQL($range_table).'`, d.id_carrier, d.id_zone, d.price + /** + * Get delivery prices for a given shipping method (price/weight) + * + * @param string $rangeTable Table name (price or weight) + * @return array Delivery prices + */ + public static function getDeliveryPriceByRanges($range_table, $id_carrier) + { + $sql = 'SELECT d.`id_'.bqSQL($range_table).'`, d.id_carrier, d.id_zone, d.price FROM '._DB_PREFIX_.'delivery d LEFT JOIN `'._DB_PREFIX_.bqSQL($range_table).'` r ON r.`id_'.bqSQL($range_table).'` = d.`id_'.bqSQL($range_table).'` WHERE d.id_carrier = '.(int)$id_carrier.' @@ -424,80 +433,84 @@ class CarrierCore extends ObjectModel AND d.`id_'.bqSQL($range_table).'` != 0 '.Carrier::sqlDeliveryRangeShop($range_table).' ORDER BY r.delimiter1'; - return Db::getInstance()->executeS($sql); - } + return Db::getInstance()->executeS($sql); + } - /** - * Get all carriers in a given language - * - * @param int $id_lang Language id - * @param $modules_filters, possible values: - PS_CARRIERS_ONLY - CARRIERS_MODULE - CARRIERS_MODULE_NEED_RANGE - PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE - ALL_CARRIERS - * @param bool $active Returns only active carriers when true - * @return array Carriers - */ - public static function getCarriers($id_lang, $active = false, $delete = false, $id_zone = false, $ids_group = null, $modules_filters = self::PS_CARRIERS_ONLY) - { - // Filter by groups and no groups => return empty array - if ($ids_group && (!is_array($ids_group) || !count($ids_group))) - return array(); + /** + * Get all carriers in a given language + * + * @param int $id_lang Language id + * @param $modules_filters, possible values: + PS_CARRIERS_ONLY + CARRIERS_MODULE + CARRIERS_MODULE_NEED_RANGE + PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE + ALL_CARRIERS + * @param bool $active Returns only active carriers when true + * @return array Carriers + */ + public static function getCarriers($id_lang, $active = false, $delete = false, $id_zone = false, $ids_group = null, $modules_filters = self::PS_CARRIERS_ONLY) + { + // Filter by groups and no groups => return empty array + if ($ids_group && (!is_array($ids_group) || !count($ids_group))) { + return array(); + } - $sql = ' + $sql = ' SELECT c.*, cl.delay FROM `'._DB_PREFIX_.'carrier` c LEFT JOIN `'._DB_PREFIX_.'carrier_lang` cl ON (c.`id_carrier` = cl.`id_carrier` AND cl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('cl').') LEFT JOIN `'._DB_PREFIX_.'carrier_zone` cz ON (cz.`id_carrier` = c.`id_carrier`)'. - ($id_zone ? 'LEFT JOIN `'._DB_PREFIX_.'zone` z ON (z.`id_zone` = '.(int)$id_zone.')' : '').' + ($id_zone ? 'LEFT JOIN `'._DB_PREFIX_.'zone` z ON (z.`id_zone` = '.(int)$id_zone.')' : '').' '.Shop::addSqlAssociation('carrier', 'c').' WHERE c.`deleted` = '.($delete ? '1' : '0'); - if ($active) - $sql .= ' AND c.`active` = 1 '; - if ($id_zone) - $sql .= ' AND cz.`id_zone` = '.(int)$id_zone.' AND z.`active` = 1 '; - if ($ids_group) - $sql .= ' AND EXISTS (SELECT 1 FROM '._DB_PREFIX_.'carrier_group + if ($active) { + $sql .= ' AND c.`active` = 1 '; + } + if ($id_zone) { + $sql .= ' AND cz.`id_zone` = '.(int)$id_zone.' AND z.`active` = 1 '; + } + if ($ids_group) { + $sql .= ' AND EXISTS (SELECT 1 FROM '._DB_PREFIX_.'carrier_group WHERE '._DB_PREFIX_.'carrier_group.id_carrier = c.id_carrier AND id_group IN ('.implode(',', array_map('intval', $ids_group)).')) '; + } - switch ($modules_filters) - { - case 1 : - $sql .= ' AND c.is_module = 0 '; - break; - case 2 : - $sql .= ' AND c.is_module = 1 '; - break; - case 3 : - $sql .= ' AND c.is_module = 1 AND c.need_range = 1 '; - break; - case 4 : - $sql .= ' AND (c.is_module = 0 OR c.need_range = 1) '; - break; - } - $sql .= ' GROUP BY c.`id_carrier` ORDER BY c.`position` ASC'; + switch ($modules_filters) { + case 1 : + $sql .= ' AND c.is_module = 0 '; + break; + case 2 : + $sql .= ' AND c.is_module = 1 '; + break; + case 3 : + $sql .= ' AND c.is_module = 1 AND c.need_range = 1 '; + break; + case 4 : + $sql .= ' AND (c.is_module = 0 OR c.need_range = 1) '; + break; + } + $sql .= ' GROUP BY c.`id_carrier` ORDER BY c.`position` ASC'; - $cache_id = 'Carrier::getCarriers_'.md5($sql); - if (!Cache::isStored($cache_id)) - { - $carriers = Db::getInstance()->executeS($sql); - Cache::store($cache_id, $carriers); - } - else - $carriers = Cache::retrieve($cache_id); + $cache_id = 'Carrier::getCarriers_'.md5($sql); + if (!Cache::isStored($cache_id)) { + $carriers = Db::getInstance()->executeS($sql); + Cache::store($cache_id, $carriers); + } else { + $carriers = Cache::retrieve($cache_id); + } - foreach ($carriers as $key => $carrier) - if ($carrier['name'] == '0') - $carriers[$key]['name'] = Carrier::getCarrierNameFromShopName(); - return $carriers; - } + foreach ($carriers as $key => $carrier) { + if ($carrier['name'] == '0') { + $carriers[$key]['name'] = Carrier::getCarrierNameFromShopName(); + } + } + return $carriers; + } - public static function getIdTaxRulesGroupMostUsed() - { - return Db::getInstance()->getValue(' + public static function getIdTaxRulesGroupMostUsed() + { + return Db::getInstance()->getValue(' SELECT id_tax_rules_group FROM ( SELECT COUNT(*) n, c.id_tax_rules_group @@ -508,169 +521,176 @@ class CarrierCore extends ObjectModel ORDER BY n DESC LIMIT 1 ) most_used' - ); - } + ); + } - public static function getDeliveredCountries($id_lang, $active_countries = false, $active_carriers = false, $contain_states = null) - { - if (!Validate::isBool($active_countries) || !Validate::isBool($active_carriers)) - die(Tools::displayError()); + public static function getDeliveredCountries($id_lang, $active_countries = false, $active_carriers = false, $contain_states = null) + { + if (!Validate::isBool($active_countries) || !Validate::isBool($active_carriers)) { + die(Tools::displayError()); + } - $states = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $states = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT s.* FROM `'._DB_PREFIX_.'state` s ORDER BY s.`name` ASC'); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT cl.*,c.*, cl.`name` AS country, zz.`name` AS zone FROM `'._DB_PREFIX_.'country` c'. - Shop::addSqlAssociation('country', 'c').' + Shop::addSqlAssociation('country', 'c').' LEFT JOIN `'._DB_PREFIX_.'country_lang` cl ON (c.`id_country` = cl.`id_country` AND cl.`id_lang` = '.(int)$id_lang.') INNER JOIN (`'._DB_PREFIX_.'carrier_zone` cz INNER JOIN `'._DB_PREFIX_.'carrier` cr ON ( cr.id_carrier = cz.id_carrier AND cr.deleted = 0 '. - ($active_carriers ? 'AND cr.active = 1) ' : ') ').' + ($active_carriers ? 'AND cr.active = 1) ' : ') ').' LEFT JOIN `'._DB_PREFIX_.'zone` zz ON cz.id_zone = zz.id_zone) ON zz.`id_zone` = c.`id_zone` WHERE 1 '.($active_countries ? 'AND c.active = 1' : '').' '.(!is_null($contain_states) ? 'AND c.`contains_states` = '.(int)$contain_states : '').' ORDER BY cl.name ASC'); - $countries = array(); - foreach ($result as &$country) - $countries[$country['id_country']] = $country; - foreach ($states as &$state) - if (isset($countries[$state['id_country']])) /* Does not keep the state if its country has been disabled and not selected */ - if ($state['active'] == 1) - $countries[$state['id_country']]['states'][] = $state; + $countries = array(); + foreach ($result as &$country) { + $countries[$country['id_country']] = $country; + } + foreach ($states as &$state) { + if (isset($countries[$state['id_country']])) { /* Does not keep the state if its country has been disabled and not selected */ + if ($state['active'] == 1) { + $countries[$state['id_country']]['states'][] = $state; + } + } + } - return $countries; - } + return $countries; + } - /** - * Return the default carrier to use - * - * @param array $carriers - * @param array $defaultCarrier the last carrier selected - * @return number the id of the default carrier - */ - public static function getDefaultCarrierSelection($carriers, $default_carrier = 0) - { - if (empty($carriers)) - return 0; + /** + * Return the default carrier to use + * + * @param array $carriers + * @param array $defaultCarrier the last carrier selected + * @return number the id of the default carrier + */ + public static function getDefaultCarrierSelection($carriers, $default_carrier = 0) + { + if (empty($carriers)) { + return 0; + } - if ((int)$default_carrier != 0) - foreach ($carriers as $carrier) - if ($carrier['id_carrier'] == (int)$default_carrier) - return (int)$carrier['id_carrier']; - foreach ($carriers as $carrier) - if ($carrier['id_carrier'] == (int)Configuration::get('PS_CARRIER_DEFAULT')) - return (int)$carrier['id_carrier']; + if ((int)$default_carrier != 0) { + foreach ($carriers as $carrier) { + if ($carrier['id_carrier'] == (int)$default_carrier) { + return (int)$carrier['id_carrier']; + } + } + } + foreach ($carriers as $carrier) { + if ($carrier['id_carrier'] == (int)Configuration::get('PS_CARRIER_DEFAULT')) { + return (int)$carrier['id_carrier']; + } + } - return (int)$carriers[0]['id_carrier']; - } + return (int)$carriers[0]['id_carrier']; + } - /** - * - * @param int $id_zone - * @param Array $groups group of the customer - * @param array &$error contain an error message if an error occurs - * @return Array - */ - public static function getCarriersForOrder($id_zone, $groups = null, $cart = null, &$error = array()) - { - $context = Context::getContext(); - $id_lang = $context->language->id; - if (is_null($cart)) - $cart = $context->cart; - if (isset($context->currency)) - $id_currency = $context->currency->id; + /** + * + * @param int $id_zone + * @param Array $groups group of the customer + * @param array &$error contain an error message if an error occurs + * @return Array + */ + public static function getCarriersForOrder($id_zone, $groups = null, $cart = null, &$error = array()) + { + $context = Context::getContext(); + $id_lang = $context->language->id; + if (is_null($cart)) { + $cart = $context->cart; + } + if (isset($context->currency)) { + $id_currency = $context->currency->id; + } - if (is_array($groups) && !empty($groups)) - $result = Carrier::getCarriers($id_lang, true, false, (int)$id_zone, $groups, self::PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE); - else - $result = Carrier::getCarriers($id_lang, true, false, (int)$id_zone, array(Configuration::get('PS_UNIDENTIFIED_GROUP')), self::PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE); - $results_array = array(); + if (is_array($groups) && !empty($groups)) { + $result = Carrier::getCarriers($id_lang, true, false, (int)$id_zone, $groups, self::PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE); + } else { + $result = Carrier::getCarriers($id_lang, true, false, (int)$id_zone, array(Configuration::get('PS_UNIDENTIFIED_GROUP')), self::PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE); + } + $results_array = array(); - foreach ($result as $k => $row) - { - $carrier = new Carrier((int)$row['id_carrier']); - $shipping_method = $carrier->getShippingMethod(); - if ($shipping_method != Carrier::SHIPPING_METHOD_FREE) - { - // Get only carriers that are compliant with shipping method - if (($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && $carrier->getMaxDeliveryPriceByWeight($id_zone) === false)) - { - $error[$carrier->id] = Carrier::SHIPPING_WEIGHT_EXCEPTION; - unset($result[$k]); - continue; - } - if (($shipping_method == Carrier::SHIPPING_METHOD_PRICE && $carrier->getMaxDeliveryPriceByPrice($id_zone) === false)) - { - $error[$carrier->id] = Carrier::SHIPPING_PRICE_EXCEPTION; - unset($result[$k]); - continue; - } + foreach ($result as $k => $row) { + $carrier = new Carrier((int)$row['id_carrier']); + $shipping_method = $carrier->getShippingMethod(); + if ($shipping_method != Carrier::SHIPPING_METHOD_FREE) { + // Get only carriers that are compliant with shipping method + if (($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && $carrier->getMaxDeliveryPriceByWeight($id_zone) === false)) { + $error[$carrier->id] = Carrier::SHIPPING_WEIGHT_EXCEPTION; + unset($result[$k]); + continue; + } + if (($shipping_method == Carrier::SHIPPING_METHOD_PRICE && $carrier->getMaxDeliveryPriceByPrice($id_zone) === false)) { + $error[$carrier->id] = Carrier::SHIPPING_PRICE_EXCEPTION; + unset($result[$k]); + continue; + } - // If out-of-range behavior carrier is set on "Desactivate carrier" - if ($row['range_behavior']) - { - // Get id zone - if (!$id_zone) - $id_zone = Country::getIdZone(Country::getDefaultCountryId()); + // If out-of-range behavior carrier is set on "Desactivate carrier" + if ($row['range_behavior']) { + // Get id zone + if (!$id_zone) { + $id_zone = (int)Country::getIdZone(Country::getDefaultCountryId()); + } - // Get only carriers that have a range compatible with cart - if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT - && (!Carrier::checkDeliveryPriceByWeight($row['id_carrier'], $cart->getTotalWeight(), $id_zone))) - { - $error[$carrier->id] = Carrier::SHIPPING_WEIGHT_EXCEPTION; - unset($result[$k]); - continue; - } + // Get only carriers that have a range compatible with cart + if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT + && (!Carrier::checkDeliveryPriceByWeight($row['id_carrier'], $cart->getTotalWeight(), $id_zone))) { + $error[$carrier->id] = Carrier::SHIPPING_WEIGHT_EXCEPTION; + unset($result[$k]); + continue; + } - if ($shipping_method == Carrier::SHIPPING_METHOD_PRICE - && (!Carrier::checkDeliveryPriceByPrice($row['id_carrier'], $cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING), $id_zone, $id_currency))) - { - $error[$carrier->id] = Carrier::SHIPPING_PRICE_EXCEPTION; - unset($result[$k]); - continue; - } - } - } + if ($shipping_method == Carrier::SHIPPING_METHOD_PRICE + && (!Carrier::checkDeliveryPriceByPrice($row['id_carrier'], $cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING), $id_zone, $id_currency))) { + $error[$carrier->id] = Carrier::SHIPPING_PRICE_EXCEPTION; + unset($result[$k]); + continue; + } + } + } - $row['name'] = (strval($row['name']) != '0' ? $row['name'] : Carrier::getCarrierNameFromShopName()); - $row['price'] = (($shipping_method == Carrier::SHIPPING_METHOD_FREE) ? 0 : $cart->getPackageShippingCost((int)$row['id_carrier'], true, null, null, $id_zone)); - $row['price_tax_exc'] = (($shipping_method == Carrier::SHIPPING_METHOD_FREE) ? 0 : $cart->getPackageShippingCost((int)$row['id_carrier'], false, null, null, $id_zone)); - $row['img'] = file_exists(_PS_SHIP_IMG_DIR_.(int)$row['id_carrier']).'.jpg' ? _THEME_SHIP_DIR_.(int)$row['id_carrier'].'.jpg' : ''; + $row['name'] = (strval($row['name']) != '0' ? $row['name'] : Carrier::getCarrierNameFromShopName()); + $row['price'] = (($shipping_method == Carrier::SHIPPING_METHOD_FREE) ? 0 : $cart->getPackageShippingCost((int)$row['id_carrier'], true, null, null, $id_zone)); + $row['price_tax_exc'] = (($shipping_method == Carrier::SHIPPING_METHOD_FREE) ? 0 : $cart->getPackageShippingCost((int)$row['id_carrier'], false, null, null, $id_zone)); + $row['img'] = file_exists(_PS_SHIP_IMG_DIR_.(int)$row['id_carrier']).'.jpg' ? _THEME_SHIP_DIR_.(int)$row['id_carrier'].'.jpg' : ''; - // If price is false, then the carrier is unavailable (carrier module) - if ($row['price'] === false) - { - unset($result[$k]); - continue; - } - $results_array[] = $row; - } + // If price is false, then the carrier is unavailable (carrier module) + if ($row['price'] === false) { + unset($result[$k]); + continue; + } + $results_array[] = $row; + } - // if we have to sort carriers by price - $prices = array(); - if (Configuration::get('PS_CARRIER_DEFAULT_SORT') == Carrier::SORT_BY_PRICE) - { - foreach ($results_array as $r) - $prices[] = $r['price']; - if (Configuration::get('PS_CARRIER_DEFAULT_ORDER') == Carrier::SORT_BY_ASC) - array_multisort($prices, SORT_ASC, SORT_NUMERIC, $results_array); - else - array_multisort($prices, SORT_DESC, SORT_NUMERIC, $results_array); - } + // if we have to sort carriers by price + $prices = array(); + if (Configuration::get('PS_CARRIER_DEFAULT_SORT') == Carrier::SORT_BY_PRICE) { + foreach ($results_array as $r) { + $prices[] = $r['price']; + } + if (Configuration::get('PS_CARRIER_DEFAULT_ORDER') == Carrier::SORT_BY_ASC) { + array_multisort($prices, SORT_ASC, SORT_NUMERIC, $results_array); + } else { + array_multisort($prices, SORT_DESC, SORT_NUMERIC, $results_array); + } + } - return $results_array; - } + return $results_array; + } - public static function checkCarrierZone($id_carrier, $id_zone) - { - $cache_id = 'Carrier::checkCarrierZone_'.(int)$id_carrier.'-'.(int)$id_zone; - if (!Cache::isStored($cache_id)) - { - $sql = 'SELECT c.`id_carrier` + public static function checkCarrierZone($id_carrier, $id_zone) + { + $cache_id = 'Carrier::checkCarrierZone_'.(int)$id_carrier.'-'.(int)$id_zone; + if (!Cache::isStored($cache_id)) { + $sql = 'SELECT c.`id_carrier` FROM `'._DB_PREFIX_.'carrier` c LEFT JOIN `'._DB_PREFIX_.'carrier_zone` cz ON (cz.`id_carrier` = c.`id_carrier`) LEFT JOIN `'._DB_PREFIX_.'zone` z ON (z.`id_zone` = '.(int)$id_zone.') @@ -679,223 +699,231 @@ class CarrierCore extends ObjectModel AND c.`active` = 1 AND cz.`id_zone` = '.(int)$id_zone.' AND z.`active` = 1'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); - Cache::store($cache_id, $result); - } - return Cache::retrieve($cache_id); - } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); + Cache::store($cache_id, $result); + } + return Cache::retrieve($cache_id); + } - /** - * Get all zones - * - * @return array Zones - */ - public function getZones() - { - return Db::getInstance()->executeS(' + /** + * Get all zones + * + * @return array Zones + */ + public function getZones() + { + return Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'carrier_zone` cz LEFT JOIN `'._DB_PREFIX_.'zone` z ON cz.`id_zone` = z.`id_zone` WHERE cz.`id_carrier` = '.(int)$this->id); - } + } - /** - * Get a specific zones - * - * @return array Zone - */ - public function getZone($id_zone) - { - return Db::getInstance()->executeS(' + /** + * Get a specific zones + * + * @return array Zone + */ + public function getZone($id_zone) + { + return Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'carrier_zone` WHERE `id_carrier` = '.(int)$this->id.' AND `id_zone` = '.(int)$id_zone); - } + } - /** - * Add zone - */ - public function addZone($id_zone) - { - if (Db::getInstance()->execute(' + /** + * Add zone + */ + public function addZone($id_zone) + { + if (Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'carrier_zone` (`id_carrier` , `id_zone`) VALUES ('.(int)$this->id.', '.(int)$id_zone.') - ')) - { - // Get all ranges for this carrier - $ranges_price = RangePrice::getRanges($this->id); - $ranges_weight = RangeWeight::getRanges($this->id); - // Create row in ps_delivery table - if (count($ranges_price) || count($ranges_weight)) - { - $sql = 'INSERT INTO `'._DB_PREFIX_.'delivery` (`id_carrier`, `id_range_price`, `id_range_weight`, `id_zone`, `price`) VALUES '; - if (count($ranges_price)) - foreach ($ranges_price as $range) - $sql .= '('.(int)$this->id.', '.(int)$range['id_range_price'].', 0, '.(int)$id_zone.', 0),'; + ')) { + // Get all ranges for this carrier + $ranges_price = RangePrice::getRanges($this->id); + $ranges_weight = RangeWeight::getRanges($this->id); + // Create row in ps_delivery table + if (count($ranges_price) || count($ranges_weight)) { + $sql = 'INSERT INTO `'._DB_PREFIX_.'delivery` (`id_carrier`, `id_range_price`, `id_range_weight`, `id_zone`, `price`) VALUES '; + if (count($ranges_price)) { + foreach ($ranges_price as $range) { + $sql .= '('.(int)$this->id.', '.(int)$range['id_range_price'].', 0, '.(int)$id_zone.', 0),'; + } + } - if (count($ranges_weight)) - foreach ($ranges_weight as $range) - $sql .= '('.(int)$this->id.', 0, '.(int)$range['id_range_weight'].', '.(int)$id_zone.', 0),'; - $sql = rtrim($sql, ','); + if (count($ranges_weight)) { + foreach ($ranges_weight as $range) { + $sql .= '('.(int)$this->id.', 0, '.(int)$range['id_range_weight'].', '.(int)$id_zone.', 0),'; + } + } + $sql = rtrim($sql, ','); - return Db::getInstance()->execute($sql); - } - return true; - } - return false; - } + return Db::getInstance()->execute($sql); + } + return true; + } + return false; + } - /** - * Delete zone - */ - public function deleteZone($id_zone) - { - if (Db::getInstance()->execute(' + /** + * Delete zone + */ + public function deleteZone($id_zone) + { + if (Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'carrier_zone` WHERE `id_carrier` = '.(int)$this->id.' AND `id_zone` = '.(int)$id_zone.' LIMIT 1 - ')) - { - return Db::getInstance()->execute(' + ')) { + return Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'delivery` WHERE `id_carrier` = '.(int)$this->id.' AND `id_zone` = '.(int)$id_zone); - } - return false; - } + } + return false; + } - /** - * Gets a specific group - * - * @since 1.5.0 - * @return array Group - */ - public function getGroups() - { - return Db::getInstance()->executeS(' + /** + * Gets a specific group + * + * @since 1.5.0 + * @return array Group + */ + public function getGroups() + { + return Db::getInstance()->executeS(' SELECT id_group FROM '._DB_PREFIX_.'carrier_group WHERE id_carrier='.(int)$this->id); - } + } - /** - * Clean delivery prices (weight/price) - * - * @param string $rangeTable Table name to clean (weight or price according to shipping method) - * @return bool Deletion result - */ - public function deleteDeliveryPrice($range_table) - { - $where = '`id_carrier` = '.(int)$this->id.' AND (`id_'.bqSQL($range_table).'` IS NOT NULL OR `id_'.bqSQL($range_table).'` = 0) '; + /** + * Clean delivery prices (weight/price) + * + * @param string $rangeTable Table name to clean (weight or price according to shipping method) + * @return bool Deletion result + */ + public function deleteDeliveryPrice($range_table) + { + $where = '`id_carrier` = '.(int)$this->id.' AND (`id_'.bqSQL($range_table).'` IS NOT NULL OR `id_'.bqSQL($range_table).'` = 0) '; - if (Shop::getContext() == Shop::CONTEXT_ALL) - $where .= 'AND id_shop IS NULL AND id_shop_group IS NULL'; - elseif (Shop::getContext() == Shop::CONTEXT_GROUP) - $where .= 'AND id_shop IS NULL AND id_shop_group = '.(int)Shop::getContextShopGroupID(); - else - $where .= 'AND id_shop = '.(int)Shop::getContextShopID(); + if (Shop::getContext() == Shop::CONTEXT_ALL) { + $where .= 'AND id_shop IS NULL AND id_shop_group IS NULL'; + } elseif (Shop::getContext() == Shop::CONTEXT_GROUP) { + $where .= 'AND id_shop IS NULL AND id_shop_group = '.(int)Shop::getContextShopGroupID(); + } else { + $where .= 'AND id_shop = '.(int)Shop::getContextShopID(); + } - return Db::getInstance()->delete('delivery', $where); - } + return Db::getInstance()->delete('delivery', $where); + } - /** - * Add new delivery prices - * - * @param array $priceList Prices list in multiple arrays (changed to array since 1.5.0) - * @return bool Insertion result - */ - public function addDeliveryPrice($price_list, $delete = false) - { - if (!$price_list) - return false; + /** + * Add new delivery prices + * + * @param array $priceList Prices list in multiple arrays (changed to array since 1.5.0) + * @return bool Insertion result + */ + public function addDeliveryPrice($price_list, $delete = false) + { + if (!$price_list) { + return false; + } - $keys = array_keys($price_list[0]); - if (!in_array('id_shop', $keys)) - $keys[] = 'id_shop'; - if (!in_array('id_shop_group', $keys)) - $keys[] = 'id_shop_group'; + $keys = array_keys($price_list[0]); + if (!in_array('id_shop', $keys)) { + $keys[] = 'id_shop'; + } + if (!in_array('id_shop_group', $keys)) { + $keys[] = 'id_shop_group'; + } - $sql = 'INSERT INTO `'._DB_PREFIX_.'delivery` ('.implode(', ', $keys).') VALUES '; - foreach ($price_list as $values) - { - if (!isset($values['id_shop'])) - $values['id_shop'] = (Shop::getContext() == Shop::CONTEXT_SHOP) ? Shop::getContextShopID() : null; - if (!isset($values['id_shop_group'])) - $values['id_shop_group'] = (Shop::getContext() != Shop::CONTEXT_ALL) ? Shop::getContextShopGroupID() : null; + $sql = 'INSERT INTO `'._DB_PREFIX_.'delivery` ('.implode(', ', $keys).') VALUES '; + foreach ($price_list as $values) { + if (!isset($values['id_shop'])) { + $values['id_shop'] = (Shop::getContext() == Shop::CONTEXT_SHOP) ? Shop::getContextShopID() : null; + } + if (!isset($values['id_shop_group'])) { + $values['id_shop_group'] = (Shop::getContext() != Shop::CONTEXT_ALL) ? Shop::getContextShopGroupID() : null; + } - if ($delete) - Db::getInstance()->execute(' + if ($delete) { + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'delivery` WHERE '.(is_null($values['id_shop']) ? 'ISNULL(`id_shop`) ' : 'id_shop = '.(int)$values['id_shop']).' AND '.(is_null($values['id_shop_group']) ? 'ISNULL(`id_shop`) ' : 'id_shop_group='.(int)$values['id_shop_group']).' AND id_carrier='.(int)$values['id_carrier']. - ($values['id_range_price'] !== null ? ' AND id_range_price='.(int)$values['id_range_price'] : ' AND (ISNULL(`id_range_price`) OR `id_range_price` = 0)'). - ($values['id_range_weight'] !== null ? ' AND id_range_weight='.(int)$values['id_range_weight'] : ' AND (ISNULL(`id_range_weight`) OR `id_range_weight` = 0)').' + ($values['id_range_price'] !== null ? ' AND id_range_price='.(int)$values['id_range_price'] : ' AND (ISNULL(`id_range_price`) OR `id_range_price` = 0)'). + ($values['id_range_weight'] !== null ? ' AND id_range_weight='.(int)$values['id_range_weight'] : ' AND (ISNULL(`id_range_weight`) OR `id_range_weight` = 0)').' AND id_zone='.(int)$values['id_zone'] - ); + ); + } - $sql .= '('; - foreach ($values as $v) - { - if (is_null($v)) - $sql .= 'NULL'; - elseif (is_int($v) || is_float($v)) - $sql .= $v; - else - $sql .= '\''.$v.'\''; - $sql .= ', '; - } - $sql = rtrim($sql, ', ').'), '; - } - $sql = rtrim($sql, ', '); - return Db::getInstance()->execute($sql); - } + $sql .= '('; + foreach ($values as $v) { + if (is_null($v)) { + $sql .= 'NULL'; + } elseif (is_int($v) || is_float($v)) { + $sql .= $v; + } else { + $sql .= '\''.$v.'\''; + } + $sql .= ', '; + } + $sql = rtrim($sql, ', ').'), '; + } + $sql = rtrim($sql, ', '); + return Db::getInstance()->execute($sql); + } - /** - * Copy old carrier informations when update carrier - * - * @param int $oldId Old id carrier (copy from that id) - */ - public function copyCarrierData($old_id) - { - if (!Validate::isUnsignedId($old_id)) - throw new PrestaShopException('Incorrect identifier for carrier'); + /** + * Copy old carrier informations when update carrier + * + * @param int $oldId Old id carrier (copy from that id) + */ + public function copyCarrierData($old_id) + { + if (!Validate::isUnsignedId($old_id)) { + throw new PrestaShopException('Incorrect identifier for carrier'); + } - if (!$this->id) - return false; + if (!$this->id) { + return false; + } - $old_logo = _PS_SHIP_IMG_DIR_.'/'.(int)$old_id.'.jpg'; - if (file_exists($old_logo)) - copy($old_logo, _PS_SHIP_IMG_DIR_.'/'.(int)$this->id.'.jpg'); + $old_logo = _PS_SHIP_IMG_DIR_.'/'.(int)$old_id.'.jpg'; + if (file_exists($old_logo)) { + copy($old_logo, _PS_SHIP_IMG_DIR_.'/'.(int)$this->id.'.jpg'); + } - $old_tmp_logo = _PS_TMP_IMG_DIR_.'/carrier_mini_'.(int)$old_id.'.jpg'; - if (file_exists($old_tmp_logo)) - { - if (!isset($_FILES['logo'])) - copy($old_tmp_logo, _PS_TMP_IMG_DIR_.'/carrier_mini_'.$this->id.'.jpg'); - unlink($old_tmp_logo); - } + $old_tmp_logo = _PS_TMP_IMG_DIR_.'/carrier_mini_'.(int)$old_id.'.jpg'; + if (file_exists($old_tmp_logo)) { + if (!isset($_FILES['logo'])) { + copy($old_tmp_logo, _PS_TMP_IMG_DIR_.'/carrier_mini_'.$this->id.'.jpg'); + } + unlink($old_tmp_logo); + } - // Copy existing ranges price - foreach (array('range_price', 'range_weight') as $range) - { - $res = Db::getInstance()->executeS(' + // Copy existing ranges price + foreach (array('range_price', 'range_weight') as $range) { + $res = Db::getInstance()->executeS(' SELECT `id_'.$range.'` as id_range, `delimiter1`, `delimiter2` FROM `'._DB_PREFIX_.$range.'` WHERE `id_carrier` = '.(int)$old_id); - if (count($res)) - foreach ($res as $val) - { - Db::getInstance()->execute(' + if (count($res)) { + foreach ($res as $val) { + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.$range.'` (`id_carrier`, `delimiter1`, `delimiter2`) VALUES ('.$this->id.','.(float)$val['delimiter1'].','.(float)$val['delimiter2'].')'); - $range_id = (int)Db::getInstance()->Insert_ID(); + $range_id = (int)Db::getInstance()->Insert_ID(); - $range_price_id = ($range == 'range_price') ? $range_id : 'NULL'; - $range_weight_id = ($range == 'range_weight') ? $range_id : 'NULL'; + $range_price_id = ($range == 'range_price') ? $range_id : 'NULL'; + $range_weight_id = ($range == 'range_weight') ? $range_id : 'NULL'; - Db::getInstance()->execute(' + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'delivery` (`id_carrier`, `id_shop`, `id_shop_group`, `id_range_price`, `id_range_weight`, `id_zone`, `price`) ( SELECT '.(int)$this->id.', `id_shop`, `id_shop_group`, '.(int)$range_price_id.', '.(int)$range_weight_id.', `id_zone`, `price` FROM `'._DB_PREFIX_.'delivery` @@ -903,227 +931,242 @@ class CarrierCore extends ObjectModel AND `id_'.$range.'` = '.(int)$val['id_range'].' ) '); - } - } + } + } + } - // Copy existing zones - $res = Db::getInstance()->executeS(' + // Copy existing zones + $res = Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'carrier_zone` WHERE id_carrier = '.(int)$old_id); - foreach ($res as $val) - Db::getInstance()->execute(' + foreach ($res as $val) { + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'carrier_zone` (`id_carrier`, `id_zone`) VALUES ('.$this->id.','.(int)$val['id_zone'].') '); + } - //Copy default carrier - if (Configuration::get('PS_CARRIER_DEFAULT') == $old_id) - Configuration::updateValue('PS_CARRIER_DEFAULT', (int)$this->id); + //Copy default carrier + if (Configuration::get('PS_CARRIER_DEFAULT') == $old_id) { + Configuration::updateValue('PS_CARRIER_DEFAULT', (int)$this->id); + } - // Copy reference - $id_reference = Db::getInstance()->getValue(' + // Copy reference + $id_reference = Db::getInstance()->getValue(' SELECT `id_reference` FROM `'._DB_PREFIX_.$this->def['table'].'` WHERE id_carrier = '.(int)$old_id); - Db::getInstance()->execute(' + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.$this->def['table'].'` SET `id_reference` = '.(int)$id_reference.' WHERE `id_carrier` = '.(int)$this->id); - $this->id_reference = (int)$id_reference; + $this->id_reference = (int)$id_reference; - // Copy tax rules group - Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'carrier_tax_rules_group_shop` (`id_carrier`, `id_tax_rules_group`, `id_shop`) + // Copy tax rules group + Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'carrier_tax_rules_group_shop` (`id_carrier`, `id_tax_rules_group`, `id_shop`) (SELECT '.(int)$this->id.', `id_tax_rules_group`, `id_shop` FROM `'._DB_PREFIX_.'carrier_tax_rules_group_shop` WHERE `id_carrier`='.(int)$old_id.')'); + } - } - - /** - * Get carrier using the reference id - */ - public static function getCarrierByReference($id_reference) - { - // @todo class var $table must became static. here I have to use 'carrier' because this method is static - $id_carrier = Db::getInstance()->getValue('SELECT `id_carrier` FROM `'._DB_PREFIX_.'carrier` + /** + * Get carrier using the reference id + */ + public static function getCarrierByReference($id_reference) + { + // @todo class var $table must became static. here I have to use 'carrier' because this method is static + $id_carrier = Db::getInstance()->getValue('SELECT `id_carrier` FROM `'._DB_PREFIX_.'carrier` WHERE id_reference = '.(int)$id_reference.' AND deleted = 0 ORDER BY id_carrier DESC'); - if (!$id_carrier) - return false; - return new Carrier($id_carrier); - } + if (!$id_carrier) { + return false; + } + return new Carrier($id_carrier); + } - /** - * Check if carrier is used (at least one order placed) - * - * @return int Order count for this carrier - */ - public function isUsed() - { - $row = Db::getInstance()->getRow(' + /** + * Check if carrier is used (at least one order placed) + * + * @return int Order count for this carrier + */ + public function isUsed() + { + $row = Db::getInstance()->getRow(' SELECT COUNT(`id_carrier`) AS total FROM `'._DB_PREFIX_.'orders` WHERE `id_carrier` = '.(int)$this->id); - return (int)$row['total']; - } + return (int)$row['total']; + } - public function getShippingMethod() - { - if ($this->is_free) - return Carrier::SHIPPING_METHOD_FREE; + public function getShippingMethod() + { + if ($this->is_free) { + return Carrier::SHIPPING_METHOD_FREE; + } - $method = (int)$this->shipping_method; + $method = (int)$this->shipping_method; - if ($this->shipping_method == Carrier::SHIPPING_METHOD_DEFAULT) - { - // backward compatibility - if ((int)Configuration::get('PS_SHIPPING_METHOD')) - $method = Carrier::SHIPPING_METHOD_WEIGHT; - else - $method = Carrier::SHIPPING_METHOD_PRICE; - } + if ($this->shipping_method == Carrier::SHIPPING_METHOD_DEFAULT) { + // backward compatibility + if ((int)Configuration::get('PS_SHIPPING_METHOD')) { + $method = Carrier::SHIPPING_METHOD_WEIGHT; + } else { + $method = Carrier::SHIPPING_METHOD_PRICE; + } + } - return $method; - } + return $method; + } - public function getRangeTable() - { - $shipping_method = $this->getShippingMethod(); - if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) - return 'range_weight'; - elseif ($shipping_method == Carrier::SHIPPING_METHOD_PRICE) - return 'range_price'; - return false; - } + public function getRangeTable() + { + $shipping_method = $this->getShippingMethod(); + if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) { + return 'range_weight'; + } elseif ($shipping_method == Carrier::SHIPPING_METHOD_PRICE) { + return 'range_price'; + } + return false; + } - public function getRangeObject($shipping_method = false) - { - if (!$shipping_method) - $shipping_method = $this->getShippingMethod(); + public function getRangeObject($shipping_method = false) + { + if (!$shipping_method) { + $shipping_method = $this->getShippingMethod(); + } - if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) - return new RangeWeight(); - elseif ($shipping_method == Carrier::SHIPPING_METHOD_PRICE) - return new RangePrice(); - return false; - } + if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) { + return new RangeWeight(); + } elseif ($shipping_method == Carrier::SHIPPING_METHOD_PRICE) { + return new RangePrice(); + } + return false; + } - public function getRangeSuffix($currency = null) - { - if (!$currency) - $currency = Context::getContext()->currency; - $suffix = Configuration::get('PS_WEIGHT_UNIT'); - if ($this->getShippingMethod() == Carrier::SHIPPING_METHOD_PRICE) - $suffix = $currency->sign; - return $suffix; - } + public function getRangeSuffix($currency = null) + { + if (!$currency) { + $currency = Context::getContext()->currency; + } + $suffix = Configuration::get('PS_WEIGHT_UNIT'); + if ($this->getShippingMethod() == Carrier::SHIPPING_METHOD_PRICE) { + $suffix = $currency->sign; + } + return $suffix; + } - public function getIdTaxRulesGroup(Context $context = null) - { - return Carrier::getIdTaxRulesGroupByIdCarrier((int)$this->id, $context); - } + public function getIdTaxRulesGroup(Context $context = null) + { + return Carrier::getIdTaxRulesGroupByIdCarrier((int)$this->id, $context); + } - public static function getIdTaxRulesGroupByIdCarrier($id_carrier, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - $key = 'carrier_id_tax_rules_group_'.(int)$id_carrier.'_'.(int)$context->shop->id; - if (!Cache::isStored($key)) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getIdTaxRulesGroupByIdCarrier($id_carrier, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + $key = 'carrier_id_tax_rules_group_'.(int)$id_carrier.'_'.(int)$context->shop->id; + if (!Cache::isStored($key)) { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_tax_rules_group` FROM `'._DB_PREFIX_.'carrier_tax_rules_group_shop` WHERE `id_carrier` = '.(int)$id_carrier.' AND id_shop='.(int)Context::getContext()->shop->id); - Cache::store($key, $result); - return $result; - } - return Cache::retrieve($key); - } + Cache::store($key, $result); + return $result; + } + return Cache::retrieve($key); + } - public function deleteTaxRulesGroup(array $shops = null) - { - if (!$shops) - $shops = Shop::getContextListShopID(); + public function deleteTaxRulesGroup(array $shops = null) + { + if (!$shops) { + $shops = Shop::getContextListShopID(); + } - $where = 'id_carrier = '.(int)$this->id; - if ($shops) - $where .= ' AND id_shop IN('.implode(', ', array_map('intval', $shops)).')'; - return Db::getInstance()->delete('carrier_tax_rules_group_shop', $where); - } + $where = 'id_carrier = '.(int)$this->id; + if ($shops) { + $where .= ' AND id_shop IN('.implode(', ', array_map('intval', $shops)).')'; + } + return Db::getInstance()->delete('carrier_tax_rules_group_shop', $where); + } - public function setTaxRulesGroup($id_tax_rules_group, $all_shops = false) - { - if (!Validate::isUnsignedId($id_tax_rules_group)) - die(Tools::displayError()); + public function setTaxRulesGroup($id_tax_rules_group, $all_shops = false) + { + if (!Validate::isUnsignedId($id_tax_rules_group)) { + die(Tools::displayError()); + } - if (!$all_shops) - $shops = Shop::getContextListShopID(); - else - $shops = Shop::getShops(true, null, true); + if (!$all_shops) { + $shops = Shop::getContextListShopID(); + } else { + $shops = Shop::getShops(true, null, true); + } - $this->deleteTaxRulesGroup($shops); + $this->deleteTaxRulesGroup($shops); - $values = array(); - foreach ($shops as $id_shop) - $values[] = array( - 'id_carrier' => (int)$this->id, - 'id_tax_rules_group' => (int)$id_tax_rules_group, - 'id_shop' => (int)$id_shop, - ); - Cache::clean('carrier_id_tax_rules_group_'.(int)$this->id.'_'.(int)Context::getContext()->shop->id); - return Db::getInstance()->insert('carrier_tax_rules_group_shop', $values); - } + $values = array(); + foreach ($shops as $id_shop) { + $values[] = array( + 'id_carrier' => (int)$this->id, + 'id_tax_rules_group' => (int)$id_tax_rules_group, + 'id_shop' => (int)$id_shop, + ); + } + Cache::clean('carrier_id_tax_rules_group_'.(int)$this->id.'_'.(int)Context::getContext()->shop->id); + return Db::getInstance()->insert('carrier_tax_rules_group_shop', $values); + } - /** - * Returns the taxes rate associated to the carrier - * - * @since 1.5 - * @param Address $address - * @return - */ - public function getTaxesRate(Address $address) - { - $tax_calculator = $this->getTaxCalculator($address); - return $tax_calculator->getTotalRate(); - } + /** + * Returns the taxes rate associated to the carrier + * + * @since 1.5 + * @param Address $address + * @return + */ + public function getTaxesRate(Address $address) + { + $tax_calculator = $this->getTaxCalculator($address); + return $tax_calculator->getTotalRate(); + } - /** - * Returns the taxes calculator associated to the carrier - * - * @since 1.5 - * @param Address $address - * @return - */ - public function getTaxCalculator(Address $address, $id_order = null, $use_average_tax_of_products = false) - { - if ($use_average_tax_of_products) { - return Adapter_ServiceLocator::get('AverageTaxOfProductsTaxCalculator')->setIdOrder($id_order); - } else { - $tax_manager = TaxManagerFactory::getManager($address, $this->getIdTaxRulesGroup()); - return $tax_manager->getTaxCalculator(); - } - } + /** + * Returns the taxes calculator associated to the carrier + * + * @since 1.5 + * @param Address $address + * @return + */ + public function getTaxCalculator(Address $address, $id_order = null, $use_average_tax_of_products = false) + { + if ($use_average_tax_of_products) { + return Adapter_ServiceLocator::get('AverageTaxOfProductsTaxCalculator')->setIdOrder($id_order); + } else { + $tax_manager = TaxManagerFactory::getManager($address, $this->getIdTaxRulesGroup()); + return $tax_manager->getTaxCalculator(); + } + } - /** - * This tricky method generates a sql clause to check if ranged data are overloaded by multishop - * - * @since 1.5.0 - * @param string $rangeTable - * @return string - */ - public static function sqlDeliveryRangeShop($range_table, $alias = 'd') - { - if (Shop::getContext() == Shop::CONTEXT_ALL) - $where = 'AND d2.id_shop IS NULL AND d2.id_shop_group IS NULL'; - elseif (Shop::getContext() == Shop::CONTEXT_GROUP) - $where = 'AND ((d2.id_shop_group IS NULL OR d2.id_shop_group = '.Shop::getContextShopGroupID().') AND d2.id_shop IS NULL)'; - else - $where = 'AND (d2.id_shop = '.Shop::getContextShopID().' OR (d2.id_shop_group = '.Shop::getContextShopGroupID().' + /** + * This tricky method generates a sql clause to check if ranged data are overloaded by multishop + * + * @since 1.5.0 + * @param string $rangeTable + * @return string + */ + public static function sqlDeliveryRangeShop($range_table, $alias = 'd') + { + if (Shop::getContext() == Shop::CONTEXT_ALL) { + $where = 'AND d2.id_shop IS NULL AND d2.id_shop_group IS NULL'; + } elseif (Shop::getContext() == Shop::CONTEXT_GROUP) { + $where = 'AND ((d2.id_shop_group IS NULL OR d2.id_shop_group = '.Shop::getContextShopGroupID().') AND d2.id_shop IS NULL)'; + } else { + $where = 'AND (d2.id_shop = '.Shop::getContextShopID().' OR (d2.id_shop_group = '.Shop::getContextShopGroupID().' AND d2.id_shop IS NULL) OR (d2.id_shop_group IS NULL AND d2.id_shop IS NULL))'; + } - $sql = 'AND '.$alias.'.id_delivery = ( + $sql = 'AND '.$alias.'.id_delivery = ( SELECT d2.id_delivery FROM '._DB_PREFIX_.'delivery d2 WHERE d2.id_carrier = `'.bqSQL($alias).'`.id_carrier @@ -1133,293 +1176,307 @@ class CarrierCore extends ObjectModel ORDER BY d2.id_shop DESC, d2.id_shop_group DESC LIMIT 1 )'; - return $sql; - } + return $sql; + } - /** - * Moves a carrier - * - * @since 1.5.0 - * @param bool $way Up (1) or Down (0) - * @param int $position - * @return bool Update result - */ - public function updatePosition($way, $position) - { - if (!$res = Db::getInstance()->executeS(' + /** + * Moves a carrier + * + * @since 1.5.0 + * @param bool $way Up (1) or Down (0) + * @param int $position + * @return bool Update result + */ + public function updatePosition($way, $position) + { + if (!$res = Db::getInstance()->executeS(' SELECT `id_carrier`, `position` FROM `'._DB_PREFIX_.'carrier` WHERE `deleted` = 0 ORDER BY `position` ASC' - )) - return false; + )) { + return false; + } - foreach ($res as $carrier) - if ((int)$carrier['id_carrier'] == (int)$this->id) - $moved_carrier = $carrier; + foreach ($res as $carrier) { + if ((int)$carrier['id_carrier'] == (int)$this->id) { + $moved_carrier = $carrier; + } + } - if (!isset($moved_carrier) || !isset($position)) - return false; + if (!isset($moved_carrier) || !isset($position)) { + return false; + } - // < and > statements rather than BETWEEN operator - // since BETWEEN is treated differently according to databases - return (Db::getInstance()->execute(' + // < and > statements rather than BETWEEN operator + // since BETWEEN is treated differently according to databases + return (Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'carrier` SET `position`= `position` '.($way ? '- 1' : '+ 1').' WHERE `position` '.($way - ? '> '.(int)$moved_carrier['position'].' AND `position` <= '.(int)$position - : '< '.(int)$moved_carrier['position'].' AND `position` >= '.(int)$position.' + ? '> '.(int)$moved_carrier['position'].' AND `position` <= '.(int)$position + : '< '.(int)$moved_carrier['position'].' AND `position` >= '.(int)$position.' AND `deleted` = 0')) - && Db::getInstance()->execute(' + && Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'carrier` SET `position` = '.(int)$position.' WHERE `id_carrier` = '.(int)$moved_carrier['id_carrier'])); - } + } - /** - * Reorders carrier positions. - * Called after deleting a carrier. - * - * @since 1.5.0 - * @return bool $return - */ - public static function cleanPositions() - { - $return = true; + /** + * Reorders carrier positions. + * Called after deleting a carrier. + * + * @since 1.5.0 + * @return bool $return + */ + public static function cleanPositions() + { + $return = true; - $sql = ' + $sql = ' SELECT `id_carrier` FROM `'._DB_PREFIX_.'carrier` WHERE `deleted` = 0 ORDER BY `position` ASC'; - $result = Db::getInstance()->executeS($sql); + $result = Db::getInstance()->executeS($sql); - $i = 0; - foreach ($result as $value) - $return = Db::getInstance()->execute(' + $i = 0; + foreach ($result as $value) { + $return = Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'carrier` SET `position` = '.(int)$i++.' WHERE `id_carrier` = '.(int)$value['id_carrier']); - return $return; - } + } + return $return; + } - /** - * Gets the highest carrier position - * - * @since 1.5.0 - * @return int $position - */ - public static function getHigherPosition() - { - $sql = 'SELECT MAX(`position`) + /** + * Gets the highest carrier position + * + * @since 1.5.0 + * @return int $position + */ + public static function getHigherPosition() + { + $sql = 'SELECT MAX(`position`) FROM `'._DB_PREFIX_.'carrier` WHERE `deleted` = 0'; - $position = DB::getInstance()->getValue($sql); - return (is_numeric($position)) ? $position : -1; - } + $position = DB::getInstance()->getValue($sql); + return (is_numeric($position)) ? $position : -1; + } - /** - * For a given {product, warehouse}, gets the carrier available - * - * @since 1.5.0 - * @param Product $product The id of the product, or an array with at least the package size and weight - * @param $id_warehouse - * @param int $id_address_delivery - * @param int $id_shop - * @param Cart $cart - * @param array &$error contain an error message if an error occurs - * @return array - * @throws PrestaShopDatabaseException - */ - public static function getAvailableCarrierList(Product $product, $id_warehouse, $id_address_delivery = null, $id_shop = null, $cart = null, &$error = array()) - { - static $ps_country_default = null; + /** + * For a given {product, warehouse}, gets the carrier available + * + * @since 1.5.0 + * @param Product $product The id of the product, or an array with at least the package size and weight + * @param $id_warehouse + * @param int $id_address_delivery + * @param int $id_shop + * @param Cart $cart + * @param array &$error contain an error message if an error occurs + * @return array + * @throws PrestaShopDatabaseException + */ + public static function getAvailableCarrierList(Product $product, $id_warehouse, $id_address_delivery = null, $id_shop = null, $cart = null, &$error = array()) + { + static $ps_country_default = null; - if ($ps_country_default === null) - $ps_country_default = Configuration::get('PS_COUNTRY_DEFAULT'); + if ($ps_country_default === null) { + $ps_country_default = Configuration::get('PS_COUNTRY_DEFAULT'); + } - if (is_null($id_shop)) - $id_shop = Context::getContext()->shop->id; - if (is_null($cart)) - $cart = Context::getContext()->cart; + if (is_null($id_shop)) { + $id_shop = Context::getContext()->shop->id; + } + if (is_null($cart)) { + $cart = Context::getContext()->cart; + } - $id_address = (int)((!is_null($id_address_delivery) && $id_address_delivery != 0) ? $id_address_delivery : $cart->id_address_delivery); - if ($id_address) - { - $id_zone = Address::getZoneById($id_address); + if (is_null($error) || !is_array($error)) { + $error = array(); + } - // Check the country of the address is activated - if (!Address::isCountryActiveById($id_address)) - return array(); - } - else - { - $country = new Country($ps_country_default); - $id_zone = $country->id_zone; - } + $id_address = (int)((!is_null($id_address_delivery) && $id_address_delivery != 0) ? $id_address_delivery : $cart->id_address_delivery); + if ($id_address) { + $id_zone = Address::getZoneById($id_address); - // Does the product is linked with carriers? - $cache_id = 'Carrier::getAvailableCarrierList_'.(int)$product->id.'-'.(int)$id_shop; - if (!Cache::isStored($cache_id)) - { - $query = new DbQuery(); - $query->select('id_carrier'); - $query->from('product_carrier', 'pc'); - $query->innerJoin('carrier', 'c', - 'c.id_reference = pc.id_carrier_reference AND c.deleted = 0 AND c.active = 1'); - $query->where('pc.id_product = '.(int)$product->id); - $query->where('pc.id_shop = '.(int)$id_shop); + // Check the country of the address is activated + if (!Address::isCountryActiveById($id_address)) { + return array(); + } + } else { + $country = new Country($ps_country_default); + $id_zone = $country->id_zone; + } - $carriers_for_product = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - Cache::store($cache_id, $carriers_for_product); - } - else - $carriers_for_product = Cache::retrieve($cache_id); + // Does the product is linked with carriers? + $cache_id = 'Carrier::getAvailableCarrierList_'.(int)$product->id.'-'.(int)$id_shop; + if (!Cache::isStored($cache_id)) { + $query = new DbQuery(); + $query->select('id_carrier'); + $query->from('product_carrier', 'pc'); + $query->innerJoin('carrier', 'c', + 'c.id_reference = pc.id_carrier_reference AND c.deleted = 0 AND c.active = 1'); + $query->where('pc.id_product = '.(int)$product->id); + $query->where('pc.id_shop = '.(int)$id_shop); - $carrier_list = array(); - if (!empty($carriers_for_product)) - { - //the product is linked with carriers - foreach ($carriers_for_product as $carrier) //check if the linked carriers are available in current zone - if (Carrier::checkCarrierZone($carrier['id_carrier'], $id_zone)) - $carrier_list[$carrier['id_carrier']] = $carrier['id_carrier']; - if (empty($carrier_list)) - return array();//no linked carrier are available for this zone - } + $carriers_for_product = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + Cache::store($cache_id, $carriers_for_product); + } else { + $carriers_for_product = Cache::retrieve($cache_id); + } - // The product is not dirrectly linked with a carrier - // Get all the carriers linked to a warehouse - if ($id_warehouse) - { - $warehouse = new Warehouse($id_warehouse); - $warehouse_carrier_list = $warehouse->getCarriers(); - } + $carrier_list = array(); + if (!empty($carriers_for_product)) { + //the product is linked with carriers + foreach ($carriers_for_product as $carrier) { //check if the linked carriers are available in current zone + if (Carrier::checkCarrierZone($carrier['id_carrier'], $id_zone)) { + $carrier_list[$carrier['id_carrier']] = $carrier['id_carrier']; + } + } + if (empty($carrier_list)) { + return array(); + }//no linked carrier are available for this zone + } - $available_carrier_list = array(); - $cache_id = 'Carrier::getAvailableCarrierList_getCarriersForOrder_'.(int)$id_zone.'-'.(int)$cart->id; - if (!Cache::isStored($cache_id)) - { - $customer = new Customer($cart->id_customer); - $carrier_error = array(); - $carriers = Carrier::getCarriersForOrder($id_zone, $customer->getGroups(), $cart, $carrier_error); - Cache::store($cache_id, array($carriers, $carrier_error)); - } else - list($carriers, $carrier_error) = Cache::retrieve($cache_id); + // The product is not dirrectly linked with a carrier + // Get all the carriers linked to a warehouse + if ($id_warehouse) { + $warehouse = new Warehouse($id_warehouse); + $warehouse_carrier_list = $warehouse->getCarriers(); + } - $error = array_merge($error, $carrier_error); + $available_carrier_list = array(); + $cache_id = 'Carrier::getAvailableCarrierList_getCarriersForOrder_'.(int)$id_zone.'-'.(int)$cart->id; + if (!Cache::isStored($cache_id)) { + $customer = new Customer($cart->id_customer); + $carrier_error = array(); + $carriers = Carrier::getCarriersForOrder($id_zone, $customer->getGroups(), $cart, $carrier_error); + Cache::store($cache_id, array($carriers, $carrier_error)); + } else { + list($carriers, $carrier_error) = Cache::retrieve($cache_id); + } - foreach ($carriers as $carrier) - $available_carrier_list[$carrier['id_carrier']] = $carrier['id_carrier']; + $error = array_merge($error, $carrier_error); - if ($carrier_list) - $carrier_list = array_intersect($available_carrier_list, $carrier_list); - else - $carrier_list = $available_carrier_list; + foreach ($carriers as $carrier) { + $available_carrier_list[$carrier['id_carrier']] = $carrier['id_carrier']; + } - if (isset($warehouse_carrier_list)) - $carrier_list = array_intersect($carrier_list, $warehouse_carrier_list); + if ($carrier_list) { + $carrier_list = array_intersect($available_carrier_list, $carrier_list); + } else { + $carrier_list = $available_carrier_list; + } - $cart_quantity = 0; + if (isset($warehouse_carrier_list)) { + $carrier_list = array_intersect($carrier_list, $warehouse_carrier_list); + } - foreach ($cart->getProducts(false, $product->id) as $cart_product) - if ($cart_product['id_product'] == $product->id) - $cart_quantity += $cart_product['cart_quantity']; + $cart_quantity = 0; - if ($product->width > 0 || $product->height > 0 || $product->depth > 0 || $product->weight > 0) - { - foreach ($carrier_list as $key => $id_carrier) - { - $carrier = new Carrier($id_carrier); + foreach ($cart->getProducts(false, $product->id) as $cart_product) { + if ($cart_product['id_product'] == $product->id) { + $cart_quantity += $cart_product['cart_quantity']; + } + } - // Get the sizes of the carrier and the product and sort them to check if the carrier can take the product. - $carrier_sizes = array((int)$carrier->max_width, (int)$carrier->max_height, (int)$carrier->max_depth); - $product_sizes = array((int)$product->width, (int)$product->height, (int)$product->depth); - rsort($carrier_sizes, SORT_NUMERIC); - rsort($product_sizes, SORT_NUMERIC); + if ($product->width > 0 || $product->height > 0 || $product->depth > 0 || $product->weight > 0) { + foreach ($carrier_list as $key => $id_carrier) { + $carrier = new Carrier($id_carrier); - if (($carrier_sizes[0] > 0 && $carrier_sizes[0] < $product_sizes[0]) - || ($carrier_sizes[1] > 0 && $carrier_sizes[1] < $product_sizes[1]) - || ($carrier_sizes[2] > 0 && $carrier_sizes[2] < $product_sizes[2])) - { - $error[$carrier->id] = Carrier::SHIPPING_SIZE_EXCEPTION; - unset($carrier_list[$key]); - } + // Get the sizes of the carrier and the product and sort them to check if the carrier can take the product. + $carrier_sizes = array((int)$carrier->max_width, (int)$carrier->max_height, (int)$carrier->max_depth); + $product_sizes = array((int)$product->width, (int)$product->height, (int)$product->depth); + rsort($carrier_sizes, SORT_NUMERIC); + rsort($product_sizes, SORT_NUMERIC); - if ($carrier->max_weight > 0 && $carrier->max_weight < $product->weight * $cart_quantity) - { - $error[$carrier->id] = Carrier::SHIPPING_WEIGHT_EXCEPTION; - unset($carrier_list[$key]); - } - } - } - return $carrier_list; - } + if (($carrier_sizes[0] > 0 && $carrier_sizes[0] < $product_sizes[0]) + || ($carrier_sizes[1] > 0 && $carrier_sizes[1] < $product_sizes[1]) + || ($carrier_sizes[2] > 0 && $carrier_sizes[2] < $product_sizes[2])) { + $error[$carrier->id] = Carrier::SHIPPING_SIZE_EXCEPTION; + unset($carrier_list[$key]); + } - /** - * Assign one (ore more) group to all carriers - * - * @since 1.5.0 - * @param int|array $id_group_list group id or list of group ids - * @param array $exception list of id carriers to ignore - */ - public static function assignGroupToAllCarriers($id_group_list, $exception = null) - { - if (!is_array($id_group_list)) - $id_group_list = array($id_group_list); + if ($carrier->max_weight > 0 && $carrier->max_weight < $product->weight * $cart_quantity) { + $error[$carrier->id] = Carrier::SHIPPING_WEIGHT_EXCEPTION; + unset($carrier_list[$key]); + } + } + } + return $carrier_list; + } - Db::getInstance()->execute(' + /** + * Assign one (ore more) group to all carriers + * + * @since 1.5.0 + * @param int|array $id_group_list group id or list of group ids + * @param array $exception list of id carriers to ignore + */ + public static function assignGroupToAllCarriers($id_group_list, $exception = null) + { + if (!is_array($id_group_list)) { + $id_group_list = array($id_group_list); + } + + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'carrier_group` WHERE `id_group` IN ('.join(',', $id_group_list).')'); - $carrier_list = Db::getInstance()->executeS(' + $carrier_list = Db::getInstance()->executeS(' SELECT id_carrier FROM `'._DB_PREFIX_.'carrier` WHERE deleted = 0 '.(is_array($exception) ? 'AND id_carrier NOT IN ('.join(',', $exception).')' : '')); - if ($carrier_list) - { - $data = array(); - foreach ($carrier_list as $carrier) - { - foreach ($id_group_list as $id_group) - $data[] = array( - 'id_carrier' => $carrier['id_carrier'], - 'id_group' => $id_group, - ); - } - return Db::getInstance()->insert('carrier_group', $data, false, false, Db::INSERT); - } + if ($carrier_list) { + $data = array(); + foreach ($carrier_list as $carrier) { + foreach ($id_group_list as $id_group) { + $data[] = array( + 'id_carrier' => $carrier['id_carrier'], + 'id_group' => $id_group, + ); + } + } + return Db::getInstance()->insert('carrier_group', $data, false, false, Db::INSERT); + } - return true; - } + return true; + } - public function setGroups($groups, $delete = true) - { - if ($delete) - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'carrier_group WHERE id_carrier = '.(int)$this->id); - if (!is_array($groups) || !count($groups)) - return true; - $sql = 'INSERT INTO '._DB_PREFIX_.'carrier_group (id_carrier, id_group) VALUES '; - foreach ($groups as $id_group) - $sql .= '('.(int)$this->id.', '.(int)$id_group.'),'; + public function setGroups($groups, $delete = true) + { + if ($delete) { + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'carrier_group WHERE id_carrier = '.(int)$this->id); + } + if (!is_array($groups) || !count($groups)) { + return true; + } + $sql = 'INSERT INTO '._DB_PREFIX_.'carrier_group (id_carrier, id_group) VALUES '; + foreach ($groups as $id_group) { + $sql .= '('.(int)$this->id.', '.(int)$id_group.'),'; + } - return Db::getInstance()->execute(rtrim($sql, ',')); - } + return Db::getInstance()->execute(rtrim($sql, ',')); + } - /** - * Return the carrier name from the shop name (e.g. if the carrier name is '0'). - * - * The returned carrier name is the shop name without '#' and ';' because this is not the same validation. - * - * @return string Carrier name - */ - public static function getCarrierNameFromShopName() - { - return str_replace( - array('#', ';'), - '', - Configuration::get('PS_SHOP_NAME') - ); - } + /** + * Return the carrier name from the shop name (e.g. if the carrier name is '0'). + * + * The returned carrier name is the shop name without '#' and ';' because this is not the same validation. + * + * @return string Carrier name + */ + public static function getCarrierNameFromShopName() + { + return str_replace( + array('#', ';'), + '', + Configuration::get('PS_SHOP_NAME') + ); + } } diff --git a/classes/Cart.php b/classes/Cart.php index fba5e810..6db6f946 100644 --- a/classes/Cart.php +++ b/classes/Cart.php @@ -26,339 +26,351 @@ class CartCore extends ObjectModel { - public $id; + public $id; - public $id_shop_group; + public $id_shop_group; - public $id_shop; + public $id_shop; - /** @var int Customer delivery address ID */ - public $id_address_delivery; + /** @var int Customer delivery address ID */ + public $id_address_delivery; - /** @var int Customer invoicing address ID */ - public $id_address_invoice; + /** @var int Customer invoicing address ID */ + public $id_address_invoice; - /** @var int Customer currency ID */ - public $id_currency; + /** @var int Customer currency ID */ + public $id_currency; - /** @var int Customer ID */ - public $id_customer; + /** @var int Customer ID */ + public $id_customer; - /** @var int Guest ID */ - public $id_guest; + /** @var int Guest ID */ + public $id_guest; - /** @var int Language ID */ - public $id_lang; + /** @var int Language ID */ + public $id_lang; - /** @var bool True if the customer wants a recycled package */ - public $recyclable = 0; + /** @var bool True if the customer wants a recycled package */ + public $recyclable = 0; - /** @var bool True if the customer wants a gift wrapping */ - public $gift = 0; + /** @var bool True if the customer wants a gift wrapping */ + public $gift = 0; - /** @var string Gift message if specified */ - public $gift_message; + /** @var string Gift message if specified */ + public $gift_message; - /** @var bool Mobile Theme */ - public $mobile_theme; + /** @var bool Mobile Theme */ + public $mobile_theme; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** @var string secure_key */ - public $secure_key; + /** @var string secure_key */ + public $secure_key; - /** @var int Carrier ID */ - public $id_carrier = 0; + /** @var int Carrier ID */ + public $id_carrier = 0; - /** @var string Object last modification date */ - public $date_upd; + /** @var string Object last modification date */ + public $date_upd; - public $checkedTos = false; - public $pictures; - public $textFields; + public $checkedTos = false; + public $pictures; + public $textFields; - public $delivery_option; + public $delivery_option; - /** @var bool Allow to seperate order in multiple package in order to recieve as soon as possible the available products */ - public $allow_seperated_package = false; + /** @var bool Allow to seperate order in multiple package in order to recieve as soon as possible the available products */ + public $allow_seperated_package = false; - protected static $_nbProducts = array(); - protected static $_isVirtualCart = array(); + protected static $_nbProducts = array(); + protected static $_isVirtualCart = array(); - protected $_products = null; - protected static $_totalWeight = array(); - protected $_taxCalculationMethod = PS_TAX_EXC; - protected static $_carriers = null; - protected static $_taxes_rate = null; - protected static $_attributesLists = array(); + protected $_products = null; + protected static $_totalWeight = array(); + protected $_taxCalculationMethod = PS_TAX_EXC; + protected static $_carriers = null; + protected static $_taxes_rate = null; + protected static $_attributesLists = array(); - /** @var Customer|null */ - protected static $_customer = null; + /** @var Customer|null */ + protected static $_customer = null; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'cart', - 'primary' => 'id_cart', - 'fields' => array( - 'id_shop_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_address_delivery' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_address_invoice' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_carrier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_guest' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'recyclable' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'gift' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'gift_message' => array('type' => self::TYPE_STRING, 'validate' => 'isMessage'), - 'mobile_theme' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'delivery_option' => array('type' => self::TYPE_STRING), - 'secure_key' => array('type' => self::TYPE_STRING, 'size' => 32), - 'allow_seperated_package' =>array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'cart', + 'primary' => 'id_cart', + 'fields' => array( + 'id_shop_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_address_delivery' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_address_invoice' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_carrier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_guest' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'recyclable' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'gift' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'gift_message' => array('type' => self::TYPE_STRING, 'validate' => 'isMessage'), + 'mobile_theme' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'delivery_option' => array('type' => self::TYPE_STRING), + 'secure_key' => array('type' => self::TYPE_STRING, 'size' => 32), + 'allow_seperated_package' =>array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_address_delivery' => array('xlink_resource' => 'addresses'), - 'id_address_invoice' => array('xlink_resource' => 'addresses'), - 'id_currency' => array('xlink_resource' => 'currencies'), - 'id_customer' => array('xlink_resource' => 'customers'), - 'id_guest' => array('xlink_resource' => 'guests'), - 'id_lang' => array('xlink_resource' => 'languages'), - ), - 'associations' => array( - 'cart_rows' => array('resource' => 'cart_row', 'virtual_entity' => true, 'fields' => array( - 'id_product' => array('required' => true, 'xlink_resource' => 'products'), - 'id_product_attribute' => array('required' => true, 'xlink_resource' => 'combinations'), - 'id_address_delivery' => array('required' => true, 'xlink_resource' => 'addresses'), - 'quantity' => array('required' => true), - ) - ), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_address_delivery' => array('xlink_resource' => 'addresses'), + 'id_address_invoice' => array('xlink_resource' => 'addresses'), + 'id_currency' => array('xlink_resource' => 'currencies'), + 'id_customer' => array('xlink_resource' => 'customers'), + 'id_guest' => array('xlink_resource' => 'guests'), + 'id_lang' => array('xlink_resource' => 'languages'), + ), + 'associations' => array( + 'cart_rows' => array('resource' => 'cart_row', 'virtual_entity' => true, 'fields' => array( + 'id_product' => array('required' => true, 'xlink_resource' => 'products'), + 'id_product_attribute' => array('required' => true, 'xlink_resource' => 'combinations'), + 'id_address_delivery' => array('required' => true, 'xlink_resource' => 'addresses'), + 'quantity' => array('required' => true), + ) + ), + ), + ); - const ONLY_PRODUCTS = 1; - const ONLY_DISCOUNTS = 2; - const BOTH = 3; - const BOTH_WITHOUT_SHIPPING = 4; - const ONLY_SHIPPING = 5; - const ONLY_WRAPPING = 6; - const ONLY_PRODUCTS_WITHOUT_SHIPPING = 7; - const ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING = 8; + const ONLY_PRODUCTS = 1; + const ONLY_DISCOUNTS = 2; + const BOTH = 3; + const BOTH_WITHOUT_SHIPPING = 4; + const ONLY_SHIPPING = 5; + const ONLY_WRAPPING = 6; + const ONLY_PRODUCTS_WITHOUT_SHIPPING = 7; + const ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING = 8; - public function __construct($id = null, $id_lang = null) - { - parent::__construct($id); + public function __construct($id = null, $id_lang = null) + { + parent::__construct($id); - if (!is_null($id_lang)) - $this->id_lang = (int)(Language::getLanguage($id_lang) !== false) ? $id_lang : Configuration::get('PS_LANG_DEFAULT'); + if (!is_null($id_lang)) { + $this->id_lang = (int)(Language::getLanguage($id_lang) !== false) ? $id_lang : Configuration::get('PS_LANG_DEFAULT'); + } - if ($this->id_customer) - { - if (isset(Context::getContext()->customer) && Context::getContext()->customer->id == $this->id_customer) - $customer = Context::getContext()->customer; - else - $customer = new Customer((int)$this->id_customer); + if ($this->id_customer) { + if (isset(Context::getContext()->customer) && Context::getContext()->customer->id == $this->id_customer) { + $customer = Context::getContext()->customer; + } else { + $customer = new Customer((int)$this->id_customer); + } - Cart::$_customer = $customer; + Cart::$_customer = $customer; - if ((!$this->secure_key || $this->secure_key == '-1') && $customer->secure_key) - { - $this->secure_key = $customer->secure_key; - $this->save(); - } - } + if ((!$this->secure_key || $this->secure_key == '-1') && $customer->secure_key) { + $this->secure_key = $customer->secure_key; + $this->save(); + } + } - $this->setTaxCalculationMethod(); - } + $this->setTaxCalculationMethod(); + } - public function setTaxCalculationMethod() - { - $this->_taxCalculationMethod = Group::getPriceDisplayMethod(Group::getCurrent()->id); - } + public function setTaxCalculationMethod() + { + $this->_taxCalculationMethod = Group::getPriceDisplayMethod(Group::getCurrent()->id); + } - public function add($autodate = true, $null_values = false) - { - if (!$this->id_lang) - $this->id_lang = Configuration::get('PS_LANG_DEFAULT'); - if (!$this->id_shop) - $this->id_shop = Context::getContext()->shop->id; + public function add($autodate = true, $null_values = false) + { + if (!$this->id_lang) { + $this->id_lang = Configuration::get('PS_LANG_DEFAULT'); + } + if (!$this->id_shop) { + $this->id_shop = Context::getContext()->shop->id; + } - $return = parent::add($autodate, $null_values); - Hook::exec('actionCartSave'); + $return = parent::add($autodate, $null_values); + Hook::exec('actionCartSave'); - return $return; - } + return $return; + } - public function update($null_values = false) - { - if (isset(self::$_nbProducts[$this->id])) - unset(self::$_nbProducts[$this->id]); + public function update($null_values = false) + { + if (isset(self::$_nbProducts[$this->id])) { + unset(self::$_nbProducts[$this->id]); + } - if (isset(self::$_totalWeight[$this->id])) - unset(self::$_totalWeight[$this->id]); + if (isset(self::$_totalWeight[$this->id])) { + unset(self::$_totalWeight[$this->id]); + } - $this->_products = null; - $return = parent::update($null_values); - Hook::exec('actionCartSave'); + $this->_products = null; + $return = parent::update($null_values); + Hook::exec('actionCartSave'); - return $return; - } + return $return; + } - /** - * Update the address id of the cart - * - * @param int $id_address Current address id to change - * @param int $id_address_new New address id - */ - public function updateAddressId($id_address, $id_address_new) - { - $to_update = false; - if (!isset($this->id_address_invoice) || $this->id_address_invoice == $id_address) - { - $to_update = true; - $this->id_address_invoice = $id_address_new; - } - if (!isset($this->id_address_delivery) || $this->id_address_delivery == $id_address) - { - $to_update = true; - $this->id_address_delivery = $id_address_new; - } - if ($to_update) - $this->update(); + /** + * Update the address id of the cart + * + * @param int $id_address Current address id to change + * @param int $id_address_new New address id + */ + public function updateAddressId($id_address, $id_address_new) + { + $to_update = false; + if (!isset($this->id_address_invoice) || $this->id_address_invoice == $id_address) { + $to_update = true; + $this->id_address_invoice = $id_address_new; + } + if (!isset($this->id_address_delivery) || $this->id_address_delivery == $id_address) { + $to_update = true; + $this->id_address_delivery = $id_address_new; + } + if ($to_update) { + $this->update(); + } - $sql = 'UPDATE `'._DB_PREFIX_.'cart_product` + $sql = 'UPDATE `'._DB_PREFIX_.'cart_product` SET `id_address_delivery` = '.(int)$id_address_new.' WHERE `id_cart` = '.(int)$this->id.' AND `id_address_delivery` = '.(int)$id_address; - Db::getInstance()->execute($sql); + Db::getInstance()->execute($sql); - $sql = 'UPDATE `'._DB_PREFIX_.'customization` + $sql = 'UPDATE `'._DB_PREFIX_.'customization` SET `id_address_delivery` = '.(int)$id_address_new.' WHERE `id_cart` = '.(int)$this->id.' AND `id_address_delivery` = '.(int)$id_address; - Db::getInstance()->execute($sql); - } + Db::getInstance()->execute($sql); + } - public function delete() - { - if ($this->OrderExists()) //NOT delete a cart which is associated with an order - return false; + public function delete() + { + if ($this->OrderExists()) { //NOT delete a cart which is associated with an order + return false; + } - $uploaded_files = Db::getInstance()->executeS(' + $uploaded_files = Db::getInstance()->executeS(' SELECT cd.`value` FROM `'._DB_PREFIX_.'customized_data` cd INNER JOIN `'._DB_PREFIX_.'customization` c ON (cd.`id_customization`= c.`id_customization`) WHERE cd.`type`= 0 AND c.`id_cart`='.(int)$this->id - ); + ); - foreach ($uploaded_files as $must_unlink) - { - unlink(_PS_UPLOAD_DIR_.$must_unlink['value'].'_small'); - unlink(_PS_UPLOAD_DIR_.$must_unlink['value']); - } + foreach ($uploaded_files as $must_unlink) { + unlink(_PS_UPLOAD_DIR_.$must_unlink['value'].'_small'); + unlink(_PS_UPLOAD_DIR_.$must_unlink['value']); + } - Db::getInstance()->execute(' + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'customized_data` WHERE `id_customization` IN ( SELECT `id_customization` FROM `'._DB_PREFIX_.'customization` WHERE `id_cart`='.(int)$this->id.' )' - ); + ); - Db::getInstance()->execute(' + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'customization` WHERE `id_cart` = '.(int)$this->id - ); + ); - if (!Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cart_cart_rule` WHERE `id_cart` = '.(int)$this->id) - || !Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cart_product` WHERE `id_cart` = '.(int)$this->id)) - return false; + if (!Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cart_cart_rule` WHERE `id_cart` = '.(int)$this->id) + || !Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cart_product` WHERE `id_cart` = '.(int)$this->id)) { + return false; + } - return parent::delete(); - } + return parent::delete(); + } - public static function getTaxesAverageUsed($id_cart) - { - $cart = new Cart((int)$id_cart); - if (!Validate::isLoadedObject($cart)) - die(Tools::displayError()); + public static function getTaxesAverageUsed($id_cart) + { + $cart = new Cart((int)$id_cart); + if (!Validate::isLoadedObject($cart)) { + die(Tools::displayError()); + } - if (!Configuration::get('PS_TAX')) - return 0; + if (!Configuration::get('PS_TAX')) { + return 0; + } - $products = $cart->getProducts(); - $total_products_moy = 0; - $ratio_tax = 0; + $products = $cart->getProducts(); + $total_products_moy = 0; + $ratio_tax = 0; - if (!count($products)) - return 0; + if (!count($products)) { + return 0; + } - foreach ($products as $product) // products refer to the cart details - { - if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_invoice') - $address_id = (int)$cart->id_address_invoice; - else - $address_id = (int)$product['id_address_delivery']; // Get delivery address of the product from the cart - if (!Address::addressExists($address_id)) - $address_id = null; + foreach ($products as $product) { + // products refer to the cart details - $total_products_moy += $product['total_wt']; - $ratio_tax += $product['total_wt'] * Tax::getProductTaxRate( - (int)$product['id_product'], - (int)$address_id - ); - } + if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_invoice') { + $address_id = (int)$cart->id_address_invoice; + } else { + $address_id = (int)$product['id_address_delivery']; + } // Get delivery address of the product from the cart + if (!Address::addressExists($address_id)) { + $address_id = null; + } - if ($total_products_moy > 0) - return $ratio_tax / $total_products_moy; + $total_products_moy += $product['total_wt']; + $ratio_tax += $product['total_wt'] * Tax::getProductTaxRate( + (int)$product['id_product'], + (int)$address_id + ); + } - return 0; - } + if ($total_products_moy > 0) { + return $ratio_tax / $total_products_moy; + } - /** - * The arguments are optional and only serve as return values in case caller needs the details. - */ - public function getAverageProductsTaxRate(&$cart_amount_te = null, &$cart_amount_ti = null) - { - $cart_amount_ti = $this->getOrderTotal(true, Cart::ONLY_PRODUCTS); - $cart_amount_te = $this->getOrderTotal(false, Cart::ONLY_PRODUCTS); + return 0; + } - $cart_vat_amount = $cart_amount_ti - $cart_amount_te; + /** + * The arguments are optional and only serve as return values in case caller needs the details. + */ + public function getAverageProductsTaxRate(&$cart_amount_te = null, &$cart_amount_ti = null) + { + $cart_amount_ti = $this->getOrderTotal(true, Cart::ONLY_PRODUCTS); + $cart_amount_te = $this->getOrderTotal(false, Cart::ONLY_PRODUCTS); - if ($cart_vat_amount == 0 || $cart_amount_te == 0) - return 0; - else - return Tools::ps_round($cart_vat_amount / $cart_amount_te, 3); - } + $cart_vat_amount = $cart_amount_ti - $cart_amount_te; - /** - * @deprecated 1.5.0, use Cart->getCartRules() - */ - public function getDiscounts($lite = false, $refresh = false) - { - Tools::displayAsDeprecated(); - return $this->getCartRules(); - } + if ($cart_vat_amount == 0 || $cart_amount_te == 0) { + return 0; + } else { + return Tools::ps_round($cart_vat_amount / $cart_amount_te, 3); + } + } - public function getCartRules($filter = CartRule::FILTER_ACTION_ALL) - { - // If the cart has not been saved, then there can't be any cart rule applied - if (!CartRule::isFeatureActive() || !$this->id) - return array(); + /** + * @deprecated 1.5.0, use Cart->getCartRules() + */ + public function getDiscounts($lite = false, $refresh = false) + { + Tools::displayAsDeprecated(); + return $this->getCartRules(); + } - $cache_key = 'Cart::getCartRules_'.$this->id.'-'.$filter; - if (!Cache::isStored($cache_key)) - { - $result = Db::getInstance()->executeS(' + public function getCartRules($filter = CartRule::FILTER_ACTION_ALL) + { + // If the cart has not been saved, then there can't be any cart rule applied + if (!CartRule::isFeatureActive() || !$this->id) { + return array(); + } + + $cache_key = 'Cart::getCartRules_'.$this->id.'-'.$filter; + if (!Cache::isStored($cache_key)) { + $result = Db::getInstance()->executeS(' SELECT cr.*, crl.`id_lang`, crl.`name`, cd.`id_cart` FROM `'._DB_PREFIX_.'cart_cart_rule` cd LEFT JOIN `'._DB_PREFIX_.'cart_rule` cr ON cd.`id_cart_rule` = cr.`id_cart_rule` @@ -370,42 +382,40 @@ class CartCore extends ObjectModel '.($filter == CartRule::FILTER_ACTION_SHIPPING ? 'AND free_shipping = 1' : '').' '.($filter == CartRule::FILTER_ACTION_GIFT ? 'AND gift_product != 0' : '').' '.($filter == CartRule::FILTER_ACTION_REDUCTION ? 'AND (reduction_percent != 0 OR reduction_amount != 0)' : '') - .' ORDER by cr.priority ASC' - ); - Cache::store($cache_key, $result); - } - else - $result = Cache::retrieve($cache_key); + .' ORDER by cr.priority ASC' + ); + Cache::store($cache_key, $result); + } else { + $result = Cache::retrieve($cache_key); + } - // Define virtual context to prevent case where the cart is not the in the global context - $virtual_context = Context::getContext()->cloneContext(); - $virtual_context->cart = $this; + // Define virtual context to prevent case where the cart is not the in the global context + $virtual_context = Context::getContext()->cloneContext(); + $virtual_context->cart = $this; - foreach ($result as &$row) - { - $row['obj'] = new CartRule($row['id_cart_rule'], (int)$this->id_lang); - $row['value_real'] = $row['obj']->getContextualValue(true, $virtual_context, $filter); - $row['value_tax_exc'] = $row['obj']->getContextualValue(false, $virtual_context, $filter); - // Retro compatibility < 1.5.0.2 - $row['id_discount'] = $row['id_cart_rule']; - $row['description'] = $row['name']; - } + foreach ($result as &$row) { + $row['obj'] = new CartRule($row['id_cart_rule'], (int)$this->id_lang); + $row['value_real'] = $row['obj']->getContextualValue(true, $virtual_context, $filter); + $row['value_tax_exc'] = $row['obj']->getContextualValue(false, $virtual_context, $filter); + // Retro compatibility < 1.5.0.2 + $row['id_discount'] = $row['id_cart_rule']; + $row['description'] = $row['name']; + } - return $result; - } + return $result; + } - /** - * Return the cart rules Ids on the cart. - * @param $filter - * @return array - * @throws PrestaShopDatabaseException - */ - public function getOrderedCartRulesIds($filter = CartRule::FILTER_ACTION_ALL) - { - $cache_key = 'Cart::getCartRules_'.$this->id.'-'.$filter.'-ids'; - if (!Cache::isStored($cache_key)) - { - $result = Db::getInstance()->executeS(' + /** + * Return the cart rules Ids on the cart. + * @param $filter + * @return array + * @throws PrestaShopDatabaseException + */ + public function getOrderedCartRulesIds($filter = CartRule::FILTER_ACTION_ALL) + { + $cache_key = 'Cart::getCartRules_'.$this->id.'-'.$filter.'-ids'; + if (!Cache::isStored($cache_key)) { + $result = Db::getInstance()->executeS(' SELECT cr.`id_cart_rule` FROM `'._DB_PREFIX_.'cart_cart_rule` cd LEFT JOIN `'._DB_PREFIX_.'cart_rule` cr ON cd.`id_cart_rule` = cr.`id_cart_rule` @@ -417,82 +427,86 @@ class CartCore extends ObjectModel '.($filter == CartRule::FILTER_ACTION_SHIPPING ? 'AND free_shipping = 1' : '').' '.($filter == CartRule::FILTER_ACTION_GIFT ? 'AND gift_product != 0' : '').' '.($filter == CartRule::FILTER_ACTION_REDUCTION ? 'AND (reduction_percent != 0 OR reduction_amount != 0)' : '') - .' ORDER BY cr.priority ASC' - ); - Cache::store($cache_key, $result); - } - else - $result = Cache::retrieve($cache_key); + .' ORDER BY cr.priority ASC' + ); + Cache::store($cache_key, $result); + } else { + $result = Cache::retrieve($cache_key); + } - return $result; - } + return $result; + } - public function getDiscountsCustomer($id_cart_rule) - { - if (!CartRule::isFeatureActive()) - return 0; - $cache_id = 'Cart::getDiscountsCustomer_'.(int)$this->id.'-'.(int)$id_cart_rule; - if (!Cache::isStored($cache_id)) - { - $result = (int)Db::getInstance()->getValue(' + public function getDiscountsCustomer($id_cart_rule) + { + if (!CartRule::isFeatureActive()) { + return 0; + } + $cache_id = 'Cart::getDiscountsCustomer_'.(int)$this->id.'-'.(int)$id_cart_rule; + if (!Cache::isStored($cache_id)) { + $result = (int)Db::getInstance()->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'cart_cart_rule` WHERE `id_cart_rule` = '.(int)$id_cart_rule.' AND `id_cart` = '.(int)$this->id); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - public function getLastProduct() - { - $sql = ' + public function getLastProduct() + { + $sql = ' SELECT `id_product`, `id_product_attribute`, id_shop FROM `'._DB_PREFIX_.'cart_product` WHERE `id_cart` = '.(int)$this->id.' ORDER BY `date_add` DESC'; - $result = Db::getInstance()->getRow($sql); - if ($result && isset($result['id_product']) && $result['id_product']) - foreach ($this->getProducts() as $product) - if ($result['id_product'] == $product['id_product'] - && ( - !$result['id_product_attribute'] - || $result['id_product_attribute'] == $product['id_product_attribute'] - )) - return $product; + $result = Db::getInstance()->getRow($sql); + if ($result && isset($result['id_product']) && $result['id_product']) { + foreach ($this->getProducts() as $product) { + if ($result['id_product'] == $product['id_product'] + && ( + !$result['id_product_attribute'] + || $result['id_product_attribute'] == $product['id_product_attribute'] + )) { + return $product; + } + } + } - return false; - } + return false; + } - /** - * Return cart products - * - * @result array Products - */ - public function getProducts($refresh = false, $id_product = false, $id_country = null) - { - if (!$this->id) - return array(); - // Product cache must be strictly compared to NULL, or else an empty cart will add dozens of queries - if ($this->_products !== null && !$refresh) - { - // Return product row with specified ID if it exists - if (is_int($id_product)) - { - foreach ($this->_products as $product) - if ($product['id_product'] == $id_product) - return array($product); - return array(); - } - return $this->_products; - } + /** + * Return cart products + * + * @result array Products + */ + public function getProducts($refresh = false, $id_product = false, $id_country = null) + { + if (!$this->id) { + return array(); + } + // Product cache must be strictly compared to NULL, or else an empty cart will add dozens of queries + if ($this->_products !== null && !$refresh) { + // Return product row with specified ID if it exists + if (is_int($id_product)) { + foreach ($this->_products as $product) { + if ($product['id_product'] == $id_product) { + return array($product); + } + } + return array(); + } + return $this->_products; + } - // Build query - $sql = new DbQuery(); + // Build query + $sql = new DbQuery(); - // Build SELECT - $sql->select('cp.`id_product_attribute`, cp.`id_product`, cp.`quantity` AS cart_quantity, cp.id_shop, pl.`name`, p.`is_virtual`, + // Build SELECT + $sql->select('cp.`id_product_attribute`, cp.`id_product`, cp.`quantity` AS cart_quantity, cp.id_shop, pl.`name`, p.`is_virtual`, pl.`description_short`, pl.`available_now`, pl.`available_later`, product_shop.`id_category_default`, p.`id_supplier`, p.`id_manufacturer`, product_shop.`on_sale`, product_shop.`ecotax`, product_shop.`additional_shipping_cost`, product_shop.`available_for_order`, product_shop.`price`, product_shop.`active`, product_shop.`unity`, product_shop.`unit_price_ratio`, @@ -501,247 +515,255 @@ class CartCore extends ObjectModel CONCAT(LPAD(cp.`id_product`, 10, 0), LPAD(IFNULL(cp.`id_product_attribute`, 0), 10, 0), IFNULL(cp.`id_address_delivery`, 0)) AS unique_id, cp.id_address_delivery, product_shop.advanced_stock_management, ps.product_supplier_reference supplier_reference'); - // Build FROM - $sql->from('cart_product', 'cp'); + // Build FROM + $sql->from('cart_product', 'cp'); - // Build JOIN - $sql->leftJoin('product', 'p', 'p.`id_product` = cp.`id_product`'); - $sql->innerJoin('product_shop', 'product_shop', '(product_shop.`id_shop` = cp.`id_shop` AND product_shop.`id_product` = p.`id_product`)'); - $sql->leftJoin('product_lang', 'pl', ' + // Build JOIN + $sql->leftJoin('product', 'p', 'p.`id_product` = cp.`id_product`'); + $sql->innerJoin('product_shop', 'product_shop', '(product_shop.`id_shop` = cp.`id_shop` AND product_shop.`id_product` = p.`id_product`)'); + $sql->leftJoin('product_lang', 'pl', ' p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$this->id_lang.Shop::addSqlRestrictionOnLang('pl', 'cp.id_shop') - ); + ); - $sql->leftJoin('category_lang', 'cl', ' + $sql->leftJoin('category_lang', 'cl', ' product_shop.`id_category_default` = cl.`id_category` AND cl.`id_lang` = '.(int)$this->id_lang.Shop::addSqlRestrictionOnLang('cl', 'cp.id_shop') - ); + ); - $sql->leftJoin('product_supplier', 'ps', 'ps.`id_product` = cp.`id_product` AND ps.`id_product_attribute` = cp.`id_product_attribute` AND ps.`id_supplier` = p.`id_supplier`'); + $sql->leftJoin('product_supplier', 'ps', 'ps.`id_product` = cp.`id_product` AND ps.`id_product_attribute` = cp.`id_product_attribute` AND ps.`id_supplier` = p.`id_supplier`'); - // @todo test if everything is ok, then refactorise call of this method - $sql->join(Product::sqlStock('cp', 'cp')); + // @todo test if everything is ok, then refactorise call of this method + $sql->join(Product::sqlStock('cp', 'cp')); - // Build WHERE clauses - $sql->where('cp.`id_cart` = '.(int)$this->id); - if ($id_product) - $sql->where('cp.`id_product` = '.(int)$id_product); - $sql->where('p.`id_product` IS NOT NULL'); + // Build WHERE clauses + $sql->where('cp.`id_cart` = '.(int)$this->id); + if ($id_product) { + $sql->where('cp.`id_product` = '.(int)$id_product); + } + $sql->where('p.`id_product` IS NOT NULL'); - // Build ORDER BY - $sql->orderBy('cp.`date_add`, cp.`id_product`, cp.`id_product_attribute` ASC'); + // Build ORDER BY + $sql->orderBy('cp.`date_add`, cp.`id_product`, cp.`id_product_attribute` ASC'); - if (Customization::isFeatureActive()) - { - $sql->select('cu.`id_customization`, cu.`quantity` AS customization_quantity'); - $sql->leftJoin('customization', 'cu', - 'p.`id_product` = cu.`id_product` AND cp.`id_product_attribute` = cu.`id_product_attribute` AND cu.`id_cart` = '.(int)$this->id); - $sql->groupBy('cp.`id_product_attribute`, cp.`id_product`, cp.`id_shop`'); - } - else - $sql->select('NULL AS customization_quantity, NULL AS id_customization'); + if (Customization::isFeatureActive()) { + $sql->select('cu.`id_customization`, cu.`quantity` AS customization_quantity'); + $sql->leftJoin('customization', 'cu', + 'p.`id_product` = cu.`id_product` AND cp.`id_product_attribute` = cu.`id_product_attribute` AND cu.`id_cart` = '.(int)$this->id); + $sql->groupBy('cp.`id_product_attribute`, cp.`id_product`, cp.`id_shop`'); + } else { + $sql->select('NULL AS customization_quantity, NULL AS id_customization'); + } - if (Combination::isFeatureActive()) - { - $sql->select(' + if (Combination::isFeatureActive()) { + $sql->select(' product_attribute_shop.`price` AS price_attribute, product_attribute_shop.`ecotax` AS ecotax_attr, IF (IFNULL(pa.`reference`, \'\') = \'\', p.`reference`, pa.`reference`) AS reference, (p.`weight`+ pa.`weight`) weight_attribute, IF (IFNULL(pa.`ean13`, \'\') = \'\', p.`ean13`, pa.`ean13`) AS ean13, IF (IFNULL(pa.`upc`, \'\') = \'\', p.`upc`, pa.`upc`) AS upc, - image_shop.`id_image` id_image, il.`legend`, IFNULL(product_attribute_shop.`minimal_quantity`, product_shop.`minimal_quantity`) as minimal_quantity, IF(product_attribute_shop.wholesale_price > 0, product_attribute_shop.wholesale_price, product_shop.`wholesale_price`) wholesale_price '); - $sql->leftJoin('product_attribute', 'pa', 'pa.`id_product_attribute` = cp.`id_product_attribute`'); - $sql->leftJoin('product_attribute_shop', 'product_attribute_shop', '(product_attribute_shop.`id_shop` = cp.`id_shop` AND product_attribute_shop.`id_product_attribute` = pa.`id_product_attribute`)'); - - $sql->leftJoin('image_shop', 'image_shop', 'image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop='.(int)$this->id_shop); - $sql->leftJoin('image_lang', 'il', 'il.`id_image` = image_shop.`id_image` AND il.`id_lang` = '.(int)$this->id_lang); - } - else - $sql->select( - 'p.`reference` AS reference, p.`ean13`, + $sql->leftJoin('product_attribute', 'pa', 'pa.`id_product_attribute` = cp.`id_product_attribute`'); + $sql->leftJoin('product_attribute_shop', 'product_attribute_shop', '(product_attribute_shop.`id_shop` = cp.`id_shop` AND product_attribute_shop.`id_product_attribute` = pa.`id_product_attribute`)'); + } else { + $sql->select( + 'p.`reference` AS reference, p.`ean13`, p.`upc` AS upc, product_shop.`minimal_quantity` AS minimal_quantity, product_shop.`wholesale_price` wholesale_price' - ); - $result = Db::getInstance()->executeS($sql); + ); + } - // Reset the cache before the following return, or else an empty cart will add dozens of queries - $products_ids = array(); - $pa_ids = array(); - if ($result) - foreach ($result as $key => $row) - { - $products_ids[] = $row['id_product']; - $pa_ids[] = $row['id_product_attribute']; - $specific_price = SpecificPrice::getSpecificPrice($row['id_product'], $this->id_shop, $this->id_currency, $id_country, $this->id_shop_group, $row['cart_quantity'], $row['id_product_attribute'], $this->id_customer, $this->id); - if ($specific_price) - $reduction_type_row = array('reduction_type' => $specific_price['reduction_type']); - else - $reduction_type_row = array('reduction_type' => 0); + $sql->select('image_shop.`id_image` id_image, il.`legend`'); + $sql->leftJoin('image_shop', 'image_shop', 'image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop='.(int)$this->id_shop); + $sql->leftJoin('image_lang', 'il', 'il.`id_image` = image_shop.`id_image` AND il.`id_lang` = '.(int)$this->id_lang); - $result[$key] = array_merge($row, $reduction_type_row); - } - // Thus you can avoid one query per product, because there will be only one query for all the products of the cart - Product::cacheProductsFeatures($products_ids); - Cart::cacheSomeAttributesLists($pa_ids, $this->id_lang); + $result = Db::getInstance()->executeS($sql); - $this->_products = array(); - if (empty($result)) - return array(); + // Reset the cache before the following return, or else an empty cart will add dozens of queries + $products_ids = array(); + $pa_ids = array(); + if ($result) { + foreach ($result as $key => $row) { + $products_ids[] = $row['id_product']; + $pa_ids[] = $row['id_product_attribute']; + $specific_price = SpecificPrice::getSpecificPrice($row['id_product'], $this->id_shop, $this->id_currency, $id_country, $this->id_shop_group, $row['cart_quantity'], $row['id_product_attribute'], $this->id_customer, $this->id); + if ($specific_price) { + $reduction_type_row = array('reduction_type' => $specific_price['reduction_type']); + } else { + $reduction_type_row = array('reduction_type' => 0); + } - $ecotax_rate = (float)Tax::getProductEcotaxRate($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); - $apply_eco_tax = Product::$_taxCalculationMethod == PS_TAX_INC && (int)Configuration::get('PS_TAX'); - $cart_shop_context = Context::getContext()->cloneContext(); + $result[$key] = array_merge($row, $reduction_type_row); + } + } + // Thus you can avoid one query per product, because there will be only one query for all the products of the cart + Product::cacheProductsFeatures($products_ids); + Cart::cacheSomeAttributesLists($pa_ids, $this->id_lang); - foreach ($result as &$row) - { - if (isset($row['ecotax_attr']) && $row['ecotax_attr'] > 0) - $row['ecotax'] = (float)$row['ecotax_attr']; + $this->_products = array(); + if (empty($result)) { + return array(); + } - $row['stock_quantity'] = (int)$row['quantity']; - // for compatibility with 1.2 themes - $row['quantity'] = (int)$row['cart_quantity']; + $ecotax_rate = (float)Tax::getProductEcotaxRate($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); + $apply_eco_tax = Product::$_taxCalculationMethod == PS_TAX_INC && (int)Configuration::get('PS_TAX'); + $cart_shop_context = Context::getContext()->cloneContext(); - if (isset($row['id_product_attribute']) && (int)$row['id_product_attribute'] && isset($row['weight_attribute'])) - $row['weight'] = (float)$row['weight_attribute']; + foreach ($result as &$row) { + if (isset($row['ecotax_attr']) && $row['ecotax_attr'] > 0) { + $row['ecotax'] = (float)$row['ecotax_attr']; + } - if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_invoice') - $address_id = (int)$this->id_address_invoice; - else - $address_id = (int)$row['id_address_delivery']; - if (!Address::addressExists($address_id)) - $address_id = null; + $row['stock_quantity'] = (int)$row['quantity']; + // for compatibility with 1.2 themes + $row['quantity'] = (int)$row['cart_quantity']; - if ($cart_shop_context->shop->id != $row['id_shop']) - $cart_shop_context->shop = new Shop((int)$row['id_shop']); + if (isset($row['id_product_attribute']) && (int)$row['id_product_attribute'] && isset($row['weight_attribute'])) { + $row['weight'] = (float)$row['weight_attribute']; + } - $address = Address::initialize($address_id, true); - $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int)$row['id_product'], $cart_shop_context); - $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator(); + if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_invoice') { + $address_id = (int)$this->id_address_invoice; + } else { + $address_id = (int)$row['id_address_delivery']; + } + if (!Address::addressExists($address_id)) { + $address_id = null; + } - $row['price_without_reduction'] = Product::getPriceStatic( - (int)$row['id_product'], - true, - isset($row['id_product_attribute']) ? (int)$row['id_product_attribute'] : null, - 6, - null, - false, - false, - $row['cart_quantity'], - false, - (int)$this->id_customer ? (int)$this->id_customer : null, - (int)$this->id, - $address_id, - $specific_price_output, - true, - true, - $cart_shop_context - ); + if ($cart_shop_context->shop->id != $row['id_shop']) { + $cart_shop_context->shop = new Shop((int)$row['id_shop']); + } - $row['price_with_reduction'] = Product::getPriceStatic( - (int)$row['id_product'], - true, - isset($row['id_product_attribute']) ? (int)$row['id_product_attribute'] : null, - 6, - null, - false, - true, - $row['cart_quantity'], - false, - (int)$this->id_customer ? (int)$this->id_customer : null, - (int)$this->id, - $address_id, - $specific_price_output, - true, - true, - $cart_shop_context - ); + $address = Address::initialize($address_id, true); + $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int)$row['id_product'], $cart_shop_context); + $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator(); - $row['price'] = $row['price_with_reduction_without_tax'] = Product::getPriceStatic( - (int)$row['id_product'], - false, - isset($row['id_product_attribute']) ? (int)$row['id_product_attribute'] : null, - 6, - null, - false, - true, - $row['cart_quantity'], - false, - (int)$this->id_customer ? (int)$this->id_customer : null, - (int)$this->id, - $address_id, - $specific_price_output, - true, - true, - $cart_shop_context - ); + $row['price_without_reduction'] = Product::getPriceStatic( + (int)$row['id_product'], + true, + isset($row['id_product_attribute']) ? (int)$row['id_product_attribute'] : null, + 6, + null, + false, + false, + $row['cart_quantity'], + false, + (int)$this->id_customer ? (int)$this->id_customer : null, + (int)$this->id, + $address_id, + $specific_price_output, + true, + true, + $cart_shop_context + ); - switch (Configuration::get('PS_ROUND_TYPE')) - { - case Order::ROUND_TOTAL: - $row['total'] = $row['price_with_reduction_without_tax'] * (int)$row['cart_quantity']; - $row['total_wt'] = $row['price_with_reduction'] * (int)$row['cart_quantity']; - break; - case Order::ROUND_LINE: - $row['total'] = Tools::ps_round($row['price_with_reduction_without_tax'] * (int)$row['cart_quantity'], _PS_PRICE_COMPUTE_PRECISION_); - $row['total_wt'] = Tools::ps_round($row['price_with_reduction'] * (int)$row['cart_quantity'], _PS_PRICE_COMPUTE_PRECISION_); - break; + $row['price_with_reduction'] = Product::getPriceStatic( + (int)$row['id_product'], + true, + isset($row['id_product_attribute']) ? (int)$row['id_product_attribute'] : null, + 6, + null, + false, + true, + $row['cart_quantity'], + false, + (int)$this->id_customer ? (int)$this->id_customer : null, + (int)$this->id, + $address_id, + $specific_price_output, + true, + true, + $cart_shop_context + ); - case Order::ROUND_ITEM: - default: - $row['total'] = Tools::ps_round($row['price_with_reduction_without_tax'], _PS_PRICE_COMPUTE_PRECISION_) * (int)$row['cart_quantity']; - $row['total_wt'] = Tools::ps_round($row['price_with_reduction'], _PS_PRICE_COMPUTE_PRECISION_) * (int)$row['cart_quantity']; - break; - } + $row['price'] = $row['price_with_reduction_without_tax'] = Product::getPriceStatic( + (int)$row['id_product'], + false, + isset($row['id_product_attribute']) ? (int)$row['id_product_attribute'] : null, + 6, + null, + false, + true, + $row['cart_quantity'], + false, + (int)$this->id_customer ? (int)$this->id_customer : null, + (int)$this->id, + $address_id, + $specific_price_output, + true, + true, + $cart_shop_context + ); - $row['price_wt'] = $row['price_with_reduction']; - $row['description_short'] = Tools::nl2br($row['description_short']); + switch (Configuration::get('PS_ROUND_TYPE')) { + case Order::ROUND_TOTAL: + $row['total'] = $row['price_with_reduction_without_tax'] * (int)$row['cart_quantity']; + $row['total_wt'] = $row['price_with_reduction'] * (int)$row['cart_quantity']; + break; + case Order::ROUND_LINE: + $row['total'] = Tools::ps_round($row['price_with_reduction_without_tax'] * (int)$row['cart_quantity'], _PS_PRICE_COMPUTE_PRECISION_); + $row['total_wt'] = Tools::ps_round($row['price_with_reduction'] * (int)$row['cart_quantity'], _PS_PRICE_COMPUTE_PRECISION_); + break; - // check if a image associated with the attribute exists - if ($row['id_product_attribute']) - { - $row2 = Image::getBestImageAttribute($row['id_shop'], $this->id_lang, $row['id_product'], $row['id_product_attribute']); - if ($row2) - $row = array_merge($row, $row2); - } + case Order::ROUND_ITEM: + default: + $row['total'] = Tools::ps_round($row['price_with_reduction_without_tax'], _PS_PRICE_COMPUTE_PRECISION_) * (int)$row['cart_quantity']; + $row['total_wt'] = Tools::ps_round($row['price_with_reduction'], _PS_PRICE_COMPUTE_PRECISION_) * (int)$row['cart_quantity']; + break; + } - $row['reduction_applies'] = ($specific_price_output && (float)$specific_price_output['reduction']); - $row['quantity_discount_applies'] = ($specific_price_output && $row['cart_quantity'] >= (int)$specific_price_output['from_quantity']); - $row['id_image'] = Product::defineProductImage($row, $this->id_lang); - $row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']); - $row['features'] = Product::getFeaturesStatic((int)$row['id_product']); + $row['price_wt'] = $row['price_with_reduction']; + $row['description_short'] = Tools::nl2br($row['description_short']); - if (array_key_exists($row['id_product_attribute'].'-'.$this->id_lang, self::$_attributesLists)) - $row = array_merge($row, self::$_attributesLists[$row['id_product_attribute'].'-'.$this->id_lang]); + // check if a image associated with the attribute exists + if ($row['id_product_attribute']) { + $row2 = Image::getBestImageAttribute($row['id_shop'], $this->id_lang, $row['id_product'], $row['id_product_attribute']); + if ($row2) { + $row = array_merge($row, $row2); + } + } - $row = Product::getTaxesInformations($row, $cart_shop_context); + $row['reduction_applies'] = ($specific_price_output && (float)$specific_price_output['reduction']); + $row['quantity_discount_applies'] = ($specific_price_output && $row['cart_quantity'] >= (int)$specific_price_output['from_quantity']); + $row['id_image'] = Product::defineProductImage($row, $this->id_lang); + $row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']); + $row['features'] = Product::getFeaturesStatic((int)$row['id_product']); - $this->_products[] = $row; - } + if (array_key_exists($row['id_product_attribute'].'-'.$this->id_lang, self::$_attributesLists)) { + $row = array_merge($row, self::$_attributesLists[$row['id_product_attribute'].'-'.$this->id_lang]); + } - return $this->_products; - } + $row = Product::getTaxesInformations($row, $cart_shop_context); - public static function cacheSomeAttributesLists($ipa_list, $id_lang) - { - if (!Combination::isFeatureActive()) - return; + $this->_products[] = $row; + } - $pa_implode = array(); + return $this->_products; + } - foreach ($ipa_list as $id_product_attribute) - if ((int)$id_product_attribute && !array_key_exists($id_product_attribute.'-'.$id_lang, self::$_attributesLists)) - { - $pa_implode[] = (int)$id_product_attribute; - self::$_attributesLists[(int)$id_product_attribute.'-'.$id_lang] = array('attributes' => '', 'attributes_small' => ''); - } + public static function cacheSomeAttributesLists($ipa_list, $id_lang) + { + if (!Combination::isFeatureActive()) { + return; + } - if (!count($pa_implode)) - return; + $pa_implode = array(); - $result = Db::getInstance()->executeS(' + foreach ($ipa_list as $id_product_attribute) { + if ((int)$id_product_attribute && !array_key_exists($id_product_attribute.'-'.$id_lang, self::$_attributesLists)) { + $pa_implode[] = (int)$id_product_attribute; + self::$_attributesLists[(int)$id_product_attribute.'-'.$id_lang] = array('attributes' => '', 'attributes_small' => ''); + } + } + + if (!count($pa_implode)) { + return; + } + + $result = Db::getInstance()->executeS(' SELECT pac.`id_product_attribute`, agl.`public_name` AS public_group_name, al.`name` AS attribute_name FROM `'._DB_PREFIX_.'product_attribute_combination` pac LEFT JOIN `'._DB_PREFIX_.'attribute` a ON a.`id_attribute` = pac.`id_attribute` @@ -756,485 +778,496 @@ class CartCore extends ObjectModel ) WHERE pac.`id_product_attribute` IN ('.implode(',', $pa_implode).') ORDER BY ag.`position` ASC, a.`position` ASC' - ); + ); - foreach ($result as $row) - { - self::$_attributesLists[$row['id_product_attribute'].'-'.$id_lang]['attributes'] .= $row['public_group_name'].' : '.$row['attribute_name'].', '; - self::$_attributesLists[$row['id_product_attribute'].'-'.$id_lang]['attributes_small'] .= $row['attribute_name'].', '; - } + foreach ($result as $row) { + self::$_attributesLists[$row['id_product_attribute'].'-'.$id_lang]['attributes'] .= $row['public_group_name'].' : '.$row['attribute_name'].', '; + self::$_attributesLists[$row['id_product_attribute'].'-'.$id_lang]['attributes_small'] .= $row['attribute_name'].', '; + } - foreach ($pa_implode as $id_product_attribute) - { - self::$_attributesLists[$id_product_attribute.'-'.$id_lang]['attributes'] = rtrim( - self::$_attributesLists[$id_product_attribute.'-'.$id_lang]['attributes'], - ', ' - ); + foreach ($pa_implode as $id_product_attribute) { + self::$_attributesLists[$id_product_attribute.'-'.$id_lang]['attributes'] = rtrim( + self::$_attributesLists[$id_product_attribute.'-'.$id_lang]['attributes'], + ', ' + ); - self::$_attributesLists[$id_product_attribute.'-'.$id_lang]['attributes_small'] = rtrim( - self::$_attributesLists[$id_product_attribute.'-'.$id_lang]['attributes_small'], - ', ' - ); - } - } + self::$_attributesLists[$id_product_attribute.'-'.$id_lang]['attributes_small'] = rtrim( + self::$_attributesLists[$id_product_attribute.'-'.$id_lang]['attributes_small'], + ', ' + ); + } + } - /** - * Return cart products quantity - * - * @result integer Products quantity - */ - public function nbProducts() - { - if (!$this->id) - return 0; + /** + * Return cart products quantity + * + * @result integer Products quantity + */ + public function nbProducts() + { + if (!$this->id) { + return 0; + } - return Cart::getNbProducts($this->id); - } + return Cart::getNbProducts($this->id); + } - public static function getNbProducts($id) - { - // Must be strictly compared to NULL, or else an empty cart will bypass the cache and add dozens of queries - if (isset(self::$_nbProducts[$id]) && self::$_nbProducts[$id] !== null) - return self::$_nbProducts[$id]; + public static function getNbProducts($id) + { + // Must be strictly compared to NULL, or else an empty cart will bypass the cache and add dozens of queries + if (isset(self::$_nbProducts[$id]) && self::$_nbProducts[$id] !== null) { + return self::$_nbProducts[$id]; + } - self::$_nbProducts[$id] = (int)Db::getInstance()->getValue(' + self::$_nbProducts[$id] = (int)Db::getInstance()->getValue(' SELECT SUM(`quantity`) FROM `'._DB_PREFIX_.'cart_product` WHERE `id_cart` = '.(int)$id - ); + ); - return self::$_nbProducts[$id]; - } + return self::$_nbProducts[$id]; + } - /** - * @deprecated 1.5.0, use Cart->addCartRule() - */ - public function addDiscount($id_cart_rule) - { - Tools::displayAsDeprecated(); - return $this->addCartRule($id_cart_rule); - } + /** + * @deprecated 1.5.0, use Cart->addCartRule() + */ + public function addDiscount($id_cart_rule) + { + Tools::displayAsDeprecated(); + return $this->addCartRule($id_cart_rule); + } - public function addCartRule($id_cart_rule) - { - // You can't add a cart rule that does not exist - $cartRule = new CartRule($id_cart_rule, Context::getContext()->language->id); + public function addCartRule($id_cart_rule) + { + // You can't add a cart rule that does not exist + $cartRule = new CartRule($id_cart_rule, Context::getContext()->language->id); - if (!Validate::isLoadedObject($cartRule)) - return false; + if (!Validate::isLoadedObject($cartRule)) { + return false; + } - if (Db::getInstance()->getValue('SELECT id_cart_rule FROM '._DB_PREFIX_.'cart_cart_rule WHERE id_cart_rule = '.(int)$id_cart_rule.' AND id_cart = '.(int)$this->id)) - return false; + if (Db::getInstance()->getValue('SELECT id_cart_rule FROM '._DB_PREFIX_.'cart_cart_rule WHERE id_cart_rule = '.(int)$id_cart_rule.' AND id_cart = '.(int)$this->id)) { + return false; + } - // Add the cart rule to the cart - if (!Db::getInstance()->insert('cart_cart_rule', array( - 'id_cart_rule' => (int)$id_cart_rule, - 'id_cart' => (int)$this->id - ))) - return false; + // Add the cart rule to the cart + if (!Db::getInstance()->insert('cart_cart_rule', array( + 'id_cart_rule' => (int)$id_cart_rule, + 'id_cart' => (int)$this->id + ))) { + return false; + } - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_ALL); - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_SHIPPING); - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_REDUCTION); - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_GIFT); - - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_ALL). '-ids'; - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_SHIPPING). '-ids'; - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_REDUCTION). '-ids'; - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_GIFT). '-ids'; + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_ALL); + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_SHIPPING); + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_REDUCTION); + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_GIFT); - if ((int)$cartRule->gift_product) - $this->updateQty(1, $cartRule->gift_product, $cartRule->gift_product_attribute, false, 'up', 0, null, false); + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_ALL). '-ids'; + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_SHIPPING). '-ids'; + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_REDUCTION). '-ids'; + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_GIFT). '-ids'; - return true; - } + if ((int)$cartRule->gift_product) { + $this->updateQty(1, $cartRule->gift_product, $cartRule->gift_product_attribute, false, 'up', 0, null, false); + } - public function containsProduct($id_product, $id_product_attribute = 0, $id_customization = 0, $id_address_delivery = 0) - { - $sql = 'SELECT cp.`quantity` FROM `'._DB_PREFIX_.'cart_product` cp'; + return true; + } - if ($id_customization) - $sql .= ' + public function containsProduct($id_product, $id_product_attribute = 0, $id_customization = 0, $id_address_delivery = 0) + { + $sql = 'SELECT cp.`quantity` FROM `'._DB_PREFIX_.'cart_product` cp'; + + if ($id_customization) { + $sql .= ' LEFT JOIN `'._DB_PREFIX_.'customization` c ON ( c.`id_product` = cp.`id_product` AND c.`id_product_attribute` = cp.`id_product_attribute` )'; + } - $sql .= ' + $sql .= ' WHERE cp.`id_product` = '.(int)$id_product.' AND cp.`id_product_attribute` = '.(int)$id_product_attribute.' AND cp.`id_cart` = '.(int)$this->id; - if (Configuration::get('PS_ALLOW_MULTISHIPPING') && $this->isMultiAddressDelivery()) - $sql .= ' AND cp.`id_address_delivery` = '.(int)$id_address_delivery; + if (Configuration::get('PS_ALLOW_MULTISHIPPING') && $this->isMultiAddressDelivery()) { + $sql .= ' AND cp.`id_address_delivery` = '.(int)$id_address_delivery; + } - if ($id_customization) - $sql .= ' AND c.`id_customization` = '.(int)$id_customization; + if ($id_customization) { + $sql .= ' AND c.`id_customization` = '.(int)$id_customization; + } - return Db::getInstance()->getRow($sql); - } + return Db::getInstance()->getRow($sql); + } - /** - * Update product quantity - * - * @param int $quantity Quantity to add (or substract) - * @param int $id_product Product ID - * @param int $id_product_attribute Attribute ID if needed - * @param string $operator Indicate if quantity must be increased or decreased - */ - public function updateQty($quantity, $id_product, $id_product_attribute = null, $id_customization = false, - $operator = 'up', $id_address_delivery = 0, Shop $shop = null, $auto_add_cart_rule = true) - { - if (!$shop) - $shop = Context::getContext()->shop; + /** + * Update product quantity + * + * @param int $quantity Quantity to add (or substract) + * @param int $id_product Product ID + * @param int $id_product_attribute Attribute ID if needed + * @param string $operator Indicate if quantity must be increased or decreased + */ + public function updateQty($quantity, $id_product, $id_product_attribute = null, $id_customization = false, + $operator = 'up', $id_address_delivery = 0, Shop $shop = null, $auto_add_cart_rule = true) + { + if (!$shop) { + $shop = Context::getContext()->shop; + } - if (Context::getContext()->customer->id) - { - if ($id_address_delivery == 0 && (int)$this->id_address_delivery) // The $id_address_delivery is null, use the cart delivery address - $id_address_delivery = $this->id_address_delivery; - elseif ($id_address_delivery == 0) // The $id_address_delivery is null, get the default customer address - $id_address_delivery = (int)Address::getFirstCustomerAddressId((int)Context::getContext()->customer->id); - elseif (!Customer::customerHasAddress(Context::getContext()->customer->id, $id_address_delivery)) // The $id_address_delivery must be linked with customer - $id_address_delivery = 0; - } + if (Context::getContext()->customer->id) { + if ($id_address_delivery == 0 && (int)$this->id_address_delivery) { // The $id_address_delivery is null, use the cart delivery address + $id_address_delivery = $this->id_address_delivery; + } elseif ($id_address_delivery == 0) { // The $id_address_delivery is null, get the default customer address + $id_address_delivery = (int)Address::getFirstCustomerAddressId((int)Context::getContext()->customer->id); + } elseif (!Customer::customerHasAddress(Context::getContext()->customer->id, $id_address_delivery)) { // The $id_address_delivery must be linked with customer + $id_address_delivery = 0; + } + } - $quantity = (int)$quantity; - $id_product = (int)$id_product; - $id_product_attribute = (int)$id_product_attribute; - $product = new Product($id_product, false, Configuration::get('PS_LANG_DEFAULT'), $shop->id); + $quantity = (int)$quantity; + $id_product = (int)$id_product; + $id_product_attribute = (int)$id_product_attribute; + $product = new Product($id_product, false, Configuration::get('PS_LANG_DEFAULT'), $shop->id); - if ($id_product_attribute) - { - $combination = new Combination((int)$id_product_attribute); - if ($combination->id_product != $id_product) - return false; - } + if ($id_product_attribute) { + $combination = new Combination((int)$id_product_attribute); + if ($combination->id_product != $id_product) { + return false; + } + } - /* If we have a product combination, the minimal quantity is set with the one of this combination */ - if (!empty($id_product_attribute)) - $minimal_quantity = (int)Attribute::getAttributeMinimalQty($id_product_attribute); - else - $minimal_quantity = (int)$product->minimal_quantity; + /* If we have a product combination, the minimal quantity is set with the one of this combination */ + if (!empty($id_product_attribute)) { + $minimal_quantity = (int)Attribute::getAttributeMinimalQty($id_product_attribute); + } else { + $minimal_quantity = (int)$product->minimal_quantity; + } - if (!Validate::isLoadedObject($product)) - die(Tools::displayError()); + if (!Validate::isLoadedObject($product)) { + die(Tools::displayError()); + } - if (isset(self::$_nbProducts[$this->id])) - unset(self::$_nbProducts[$this->id]); + if (isset(self::$_nbProducts[$this->id])) { + unset(self::$_nbProducts[$this->id]); + } - if (isset(self::$_totalWeight[$this->id])) - unset(self::$_totalWeight[$this->id]); + if (isset(self::$_totalWeight[$this->id])) { + unset(self::$_totalWeight[$this->id]); + } - Hook::exec('actionBeforeCartUpdateQty', array( - 'cart' => $this, - 'product' => $product, - 'id_product_attribute' => $id_product_attribute, - 'id_customization' => $id_customization, - 'quantity' => $quantity, - 'operator' => $operator, - 'id_address_delivery' => $id_address_delivery, - 'shop' => $shop, - 'auto_add_cart_rule' => $auto_add_cart_rule, - )); + Hook::exec('actionBeforeCartUpdateQty', array( + 'cart' => $this, + 'product' => $product, + 'id_product_attribute' => $id_product_attribute, + 'id_customization' => $id_customization, + 'quantity' => $quantity, + 'operator' => $operator, + 'id_address_delivery' => $id_address_delivery, + 'shop' => $shop, + 'auto_add_cart_rule' => $auto_add_cart_rule, + )); - if ((int)$quantity <= 0) - return $this->deleteProduct($id_product, $id_product_attribute, (int)$id_customization); - elseif (!$product->available_for_order || (Configuration::get('PS_CATALOG_MODE') && !defined('_PS_ADMIN_DIR_'))) - return false; - else - { - /* Check if the product is already in the cart */ - $result = $this->containsProduct($id_product, $id_product_attribute, (int)$id_customization, (int)$id_address_delivery); + if ((int)$quantity <= 0) { + return $this->deleteProduct($id_product, $id_product_attribute, (int)$id_customization); + } elseif (!$product->available_for_order || (Configuration::get('PS_CATALOG_MODE') && !defined('_PS_ADMIN_DIR_'))) { + return false; + } else { + /* Check if the product is already in the cart */ + $result = $this->containsProduct($id_product, $id_product_attribute, (int)$id_customization, (int)$id_address_delivery); - /* Update quantity if product already exist */ - if ($result) - { - if ($operator == 'up') - { - $sql = 'SELECT stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity + /* Update quantity if product already exist */ + if ($result) { + if ($operator == 'up') { + $sql = 'SELECT stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity FROM '._DB_PREFIX_.'product p '.Product::sqlStock('p', $id_product_attribute, true, $shop).' WHERE p.id_product = '.$id_product; - $result2 = Db::getInstance()->getRow($sql); - $product_qty = (int)$result2['quantity']; - // Quantity for product pack - if (Pack::isPack($id_product)) - $product_qty = Pack::getQuantity($id_product, $id_product_attribute); - $new_qty = (int)$result['quantity'] + (int)$quantity; - $qty = '+ '.(int)$quantity; + $result2 = Db::getInstance()->getRow($sql); + $product_qty = (int)$result2['quantity']; + // Quantity for product pack + if (Pack::isPack($id_product)) { + $product_qty = Pack::getQuantity($id_product, $id_product_attribute); + } + $new_qty = (int)$result['quantity'] + (int)$quantity; + $qty = '+ '.(int)$quantity; - if (!Product::isAvailableWhenOutOfStock((int)$result2['out_of_stock'])) - if ($new_qty > $product_qty) - return false; - } - elseif ($operator == 'down') - { - $qty = '- '.(int)$quantity; - $new_qty = (int)$result['quantity'] - (int)$quantity; - if ($new_qty < $minimal_quantity && $minimal_quantity > 1) - return -1; - } - else - return false; + if (!Product::isAvailableWhenOutOfStock((int)$result2['out_of_stock'])) { + if ($new_qty > $product_qty) { + return false; + } + } + } elseif ($operator == 'down') { + $qty = '- '.(int)$quantity; + $new_qty = (int)$result['quantity'] - (int)$quantity; + if ($new_qty < $minimal_quantity && $minimal_quantity > 1) { + return -1; + } + } else { + return false; + } - /* Delete product from cart */ - if ($new_qty <= 0) - return $this->deleteProduct((int)$id_product, (int)$id_product_attribute, (int)$id_customization); - elseif ($new_qty < $minimal_quantity) - return -1; - else - Db::getInstance()->execute(' + /* Delete product from cart */ + if ($new_qty <= 0) { + return $this->deleteProduct((int)$id_product, (int)$id_product_attribute, (int)$id_customization); + } elseif ($new_qty < $minimal_quantity) { + return -1; + } else { + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'cart_product` SET `quantity` = `quantity` '.$qty.', `date_add` = NOW() WHERE `id_product` = '.(int)$id_product. - (!empty($id_product_attribute) ? ' AND `id_product_attribute` = '.(int)$id_product_attribute : '').' + (!empty($id_product_attribute) ? ' AND `id_product_attribute` = '.(int)$id_product_attribute : '').' AND `id_cart` = '.(int)$this->id.(Configuration::get('PS_ALLOW_MULTISHIPPING') && $this->isMultiAddressDelivery() ? ' AND `id_address_delivery` = '.(int)$id_address_delivery : '').' LIMIT 1' - ); - } - /* Add product to the cart */ - elseif ($operator == 'up') - { - $sql = 'SELECT stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity + ); + } + } + /* Add product to the cart */ + elseif ($operator == 'up') { + $sql = 'SELECT stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity FROM '._DB_PREFIX_.'product p '.Product::sqlStock('p', $id_product_attribute, true, $shop).' WHERE p.id_product = '.$id_product; - $result2 = Db::getInstance()->getRow($sql); + $result2 = Db::getInstance()->getRow($sql); - // Quantity for product pack - if (Pack::isPack($id_product)) - $result2['quantity'] = Pack::getQuantity($id_product, $id_product_attribute); + // Quantity for product pack + if (Pack::isPack($id_product)) { + $result2['quantity'] = Pack::getQuantity($id_product, $id_product_attribute); + } - if (!Product::isAvailableWhenOutOfStock((int)$result2['out_of_stock'])) - if ((int)$quantity > $result2['quantity']) - return false; + if (!Product::isAvailableWhenOutOfStock((int)$result2['out_of_stock'])) { + if ((int)$quantity > $result2['quantity']) { + return false; + } + } - if ((int)$quantity < $minimal_quantity) - return -1; + if ((int)$quantity < $minimal_quantity) { + return -1; + } - $result_add = Db::getInstance()->insert('cart_product', array( - 'id_product' => (int)$id_product, - 'id_product_attribute' => (int)$id_product_attribute, - 'id_cart' => (int)$this->id, - 'id_address_delivery' => (int)$id_address_delivery, - 'id_shop' => $shop->id, - 'quantity' => (int)$quantity, - 'date_add' => date('Y-m-d H:i:s') - )); + $result_add = Db::getInstance()->insert('cart_product', array( + 'id_product' => (int)$id_product, + 'id_product_attribute' => (int)$id_product_attribute, + 'id_cart' => (int)$this->id, + 'id_address_delivery' => (int)$id_address_delivery, + 'id_shop' => $shop->id, + 'quantity' => (int)$quantity, + 'date_add' => date('Y-m-d H:i:s') + )); - if (!$result_add) - return false; - } - } + if (!$result_add) { + return false; + } + } + } - // refresh cache of self::_products - $this->_products = $this->getProducts(true); - $this->update(); - $context = Context::getContext()->cloneContext(); - $context->cart = $this; - Cache::clean('getContextualValue_*'); - if ($auto_add_cart_rule) - CartRule::autoAddToCart($context); + // refresh cache of self::_products + $this->_products = $this->getProducts(true); + $this->update(); + $context = Context::getContext()->cloneContext(); + $context->cart = $this; + Cache::clean('getContextualValue_*'); + if ($auto_add_cart_rule) { + CartRule::autoAddToCart($context); + } - if ($product->customizable) - return $this->_updateCustomizationQuantity((int)$quantity, (int)$id_customization, (int)$id_product, (int)$id_product_attribute, (int)$id_address_delivery, $operator); - else - return true; - } + if ($product->customizable) { + return $this->_updateCustomizationQuantity((int)$quantity, (int)$id_customization, (int)$id_product, (int)$id_product_attribute, (int)$id_address_delivery, $operator); + } else { + return true; + } + } - /* - ** Customization management - */ - protected function _updateCustomizationQuantity($quantity, $id_customization, $id_product, $id_product_attribute, $id_address_delivery, $operator = 'up') - { - // Link customization to product combination when it is first added to cart - if (empty($id_customization)) - { - $customization = $this->getProductCustomization($id_product, null, true); - foreach ($customization as $field) - { - if ($field['quantity'] == 0) - { - Db::getInstance()->execute(' + /* + ** Customization management + */ + protected function _updateCustomizationQuantity($quantity, $id_customization, $id_product, $id_product_attribute, $id_address_delivery, $operator = 'up') + { + // Link customization to product combination when it is first added to cart + if (empty($id_customization)) { + $customization = $this->getProductCustomization($id_product, null, true); + foreach ($customization as $field) { + if ($field['quantity'] == 0) { + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'customization` SET `quantity` = '.(int)$quantity.', `id_product_attribute` = '.(int)$id_product_attribute.', `id_address_delivery` = '.(int)$id_address_delivery.', `in_cart` = 1 WHERE `id_customization` = '.(int)$field['id_customization']); - } - } - } + } + } + } - /* Deletion */ - if (!empty($id_customization) && (int)$quantity < 1) - return $this->_deleteCustomization((int)$id_customization, (int)$id_product, (int)$id_product_attribute); + /* Deletion */ + if (!empty($id_customization) && (int)$quantity < 1) { + return $this->_deleteCustomization((int)$id_customization, (int)$id_product, (int)$id_product_attribute); + } - /* Quantity update */ - if (!empty($id_customization)) - { - $result = Db::getInstance()->getRow('SELECT `quantity` FROM `'._DB_PREFIX_.'customization` WHERE `id_customization` = '.(int)$id_customization); - if ($result && Db::getInstance()->NumRows()) - { - if ($operator == 'down' && (int)$result['quantity'] - (int)$quantity < 1) - return Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'customization` WHERE `id_customization` = '.(int)$id_customization); + /* Quantity update */ + if (!empty($id_customization)) { + $result = Db::getInstance()->getRow('SELECT `quantity` FROM `'._DB_PREFIX_.'customization` WHERE `id_customization` = '.(int)$id_customization); + if ($result && Db::getInstance()->NumRows()) { + if ($operator == 'down' && (int)$result['quantity'] - (int)$quantity < 1) { + return Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'customization` WHERE `id_customization` = '.(int)$id_customization); + } - return Db::getInstance()->execute(' + return Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'customization` SET `quantity` = `quantity` '.($operator == 'up' ? '+ ' : '- ').(int)$quantity.', `id_address_delivery` = '.(int)$id_address_delivery.', `in_cart` = 1 WHERE `id_customization` = '.(int)$id_customization); - } - else - Db::getInstance()->execute(' + } else { + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'customization` SET `id_address_delivery` = '.(int)$id_address_delivery.', `in_cart` = 1 WHERE `id_customization` = '.(int)$id_customization); - } - // refresh cache of self::_products - $this->_products = $this->getProducts(true); - $this->update(); - return true; - } + } + } + // refresh cache of self::_products + $this->_products = $this->getProducts(true); + $this->update(); + return true; + } - /** - * Add customization item to database - * - * @param int $id_product - * @param int $id_product_attribute - * @param int $index - * @param int $type - * @param string $field - * @param int $quantity - * @return bool success - */ - public function _addCustomization($id_product, $id_product_attribute, $index, $type, $field, $quantity) - { - $exising_customization = Db::getInstance()->executeS(' + /** + * Add customization item to database + * + * @param int $id_product + * @param int $id_product_attribute + * @param int $index + * @param int $type + * @param string $field + * @param int $quantity + * @return bool success + */ + public function _addCustomization($id_product, $id_product_attribute, $index, $type, $field, $quantity) + { + $exising_customization = Db::getInstance()->executeS(' SELECT cu.`id_customization`, cd.`index`, cd.`value`, cd.`type` FROM `'._DB_PREFIX_.'customization` cu LEFT JOIN `'._DB_PREFIX_.'customized_data` cd ON cu.`id_customization` = cd.`id_customization` WHERE cu.id_cart = '.(int)$this->id.' AND cu.id_product = '.(int)$id_product.' AND in_cart = 0' - ); + ); - if ($exising_customization) - { - // If the customization field is alreay filled, delete it - foreach ($exising_customization as $customization) - { - if ($customization['type'] == $type && $customization['index'] == $index) - { - Db::getInstance()->execute(' + if ($exising_customization) { + // If the customization field is alreay filled, delete it + foreach ($exising_customization as $customization) { + if ($customization['type'] == $type && $customization['index'] == $index) { + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'customized_data` WHERE id_customization = '.(int)$customization['id_customization'].' AND type = '.(int)$customization['type'].' AND `index` = '.(int)$customization['index']); - if ($type == Product::CUSTOMIZE_FILE) - { - @unlink(_PS_UPLOAD_DIR_.$customization['value']); - @unlink(_PS_UPLOAD_DIR_.$customization['value'].'_small'); - } - break; - } - } - $id_customization = $exising_customization[0]['id_customization']; - } - else - { - Db::getInstance()->execute( - 'INSERT INTO `'._DB_PREFIX_.'customization` (`id_cart`, `id_product`, `id_product_attribute`, `quantity`) + if ($type == Product::CUSTOMIZE_FILE) { + @unlink(_PS_UPLOAD_DIR_.$customization['value']); + @unlink(_PS_UPLOAD_DIR_.$customization['value'].'_small'); + } + break; + } + } + $id_customization = $exising_customization[0]['id_customization']; + } else { + Db::getInstance()->execute( + 'INSERT INTO `'._DB_PREFIX_.'customization` (`id_cart`, `id_product`, `id_product_attribute`, `quantity`) VALUES ('.(int)$this->id.', '.(int)$id_product.', '.(int)$id_product_attribute.', '.(int)$quantity.')' - ); - $id_customization = Db::getInstance()->Insert_ID(); - } + ); + $id_customization = Db::getInstance()->Insert_ID(); + } - $query = 'INSERT INTO `'._DB_PREFIX_.'customized_data` (`id_customization`, `type`, `index`, `value`) + $query = 'INSERT INTO `'._DB_PREFIX_.'customized_data` (`id_customization`, `type`, `index`, `value`) VALUES ('.(int)$id_customization.', '.(int)$type.', '.(int)$index.', \''.pSQL($field).'\')'; - if (!Db::getInstance()->execute($query)) - return false; - return true; - } + if (!Db::getInstance()->execute($query)) { + return false; + } + return true; + } - /** - * Check if order has already been placed - * - * @return bool result - */ - public function orderExists() - { - $cache_id = 'Cart::orderExists_'.(int)$this->id; - if (!Cache::isStored($cache_id)) - { - $result = (bool)Db::getInstance()->getValue('SELECT count(*) FROM `'._DB_PREFIX_.'orders` WHERE `id_cart` = '.(int)$this->id); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + /** + * Check if order has already been placed + * + * @return bool result + */ + public function orderExists() + { + $cache_id = 'Cart::orderExists_'.(int)$this->id; + if (!Cache::isStored($cache_id)) { + $result = (bool)Db::getInstance()->getValue('SELECT count(*) FROM `'._DB_PREFIX_.'orders` WHERE `id_cart` = '.(int)$this->id); + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * @deprecated 1.5.0, use Cart->removeCartRule() - */ - public function deleteDiscount($id_cart_rule) - { - Tools::displayAsDeprecated(); - return $this->removeCartRule($id_cart_rule); - } + /** + * @deprecated 1.5.0, use Cart->removeCartRule() + */ + public function deleteDiscount($id_cart_rule) + { + Tools::displayAsDeprecated(); + return $this->removeCartRule($id_cart_rule); + } - public function removeCartRule($id_cart_rule) - { - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_ALL); - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_SHIPPING); - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_REDUCTION); - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_GIFT); - - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_ALL). '-ids'; - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_SHIPPING). '-ids'; - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_REDUCTION). '-ids'; - Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_GIFT). '-ids'; + public function removeCartRule($id_cart_rule) + { + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_ALL); + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_SHIPPING); + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_REDUCTION); + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_GIFT); - $result = Db::getInstance()->delete('cart_cart_rule', '`id_cart_rule` = '.(int)$id_cart_rule.' AND `id_cart` = '.(int)$this->id, 1); + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_ALL). '-ids'; + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_SHIPPING). '-ids'; + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_REDUCTION). '-ids'; + Cache::clean('Cart::getCartRules_'.$this->id.'-'.CartRule::FILTER_ACTION_GIFT). '-ids'; - $cart_rule = new CartRule($id_cart_rule, Configuration::get('PS_LANG_DEFAULT')); - if ((int)$cart_rule->gift_product) - $this->updateQty(1, $cart_rule->gift_product, $cart_rule->gift_product_attribute, null, 'down', 0, null, false); + $result = Db::getInstance()->delete('cart_cart_rule', '`id_cart_rule` = '.(int)$id_cart_rule.' AND `id_cart` = '.(int)$this->id, 1); - return $result; - } + $cart_rule = new CartRule($id_cart_rule, Configuration::get('PS_LANG_DEFAULT')); + if ((int)$cart_rule->gift_product) { + $this->updateQty(1, $cart_rule->gift_product, $cart_rule->gift_product_attribute, null, 'down', 0, null, false); + } - /** - * Delete a product from the cart - * - * @param int $id_product Product ID - * @param int $id_product_attribute Attribute ID if needed - * @param int $id_customization Customization id - * @return bool result - */ - public function deleteProduct($id_product, $id_product_attribute = null, $id_customization = null, $id_address_delivery = 0) - { - if (isset(self::$_nbProducts[$this->id])) - unset(self::$_nbProducts[$this->id]); + return $result; + } - if (isset(self::$_totalWeight[$this->id])) - unset(self::$_totalWeight[$this->id]); + /** + * Delete a product from the cart + * + * @param int $id_product Product ID + * @param int $id_product_attribute Attribute ID if needed + * @param int $id_customization Customization id + * @return bool result + */ + public function deleteProduct($id_product, $id_product_attribute = null, $id_customization = null, $id_address_delivery = 0) + { + if (isset(self::$_nbProducts[$this->id])) { + unset(self::$_nbProducts[$this->id]); + } - if ((int)$id_customization) - { - $product_total_quantity = (int)Db::getInstance()->getValue( - 'SELECT `quantity` + if (isset(self::$_totalWeight[$this->id])) { + unset(self::$_totalWeight[$this->id]); + } + + if ((int)$id_customization) { + $product_total_quantity = (int)Db::getInstance()->getValue( + 'SELECT `quantity` FROM `'._DB_PREFIX_.'cart_product` WHERE `id_product` = '.(int)$id_product.' AND `id_cart` = '.(int)$this->id.' AND `id_product_attribute` = '.(int)$id_product_attribute); - $customization_quantity = (int)Db::getInstance()->getValue(' + $customization_quantity = (int)Db::getInstance()->getValue(' SELECT `quantity` FROM `'._DB_PREFIX_.'customization` WHERE `id_cart` = '.(int)$this->id.' @@ -1242,1996 +1275,2026 @@ class CartCore extends ObjectModel AND `id_product_attribute` = '.(int)$id_product_attribute.' '.((int)$id_address_delivery ? 'AND `id_address_delivery` = '.(int)$id_address_delivery : '')); - if (!$this->_deleteCustomization((int)$id_customization, (int)$id_product, (int)$id_product_attribute, (int)$id_address_delivery)) - return false; + if (!$this->_deleteCustomization((int)$id_customization, (int)$id_product, (int)$id_product_attribute, (int)$id_address_delivery)) { + return false; + } - // refresh cache of self::_products - $this->_products = $this->getProducts(true); - return ($customization_quantity == $product_total_quantity && $this->deleteProduct((int)$id_product, (int)$id_product_attribute, null, (int)$id_address_delivery)); - } + // refresh cache of self::_products + $this->_products = $this->getProducts(true); + return ($customization_quantity == $product_total_quantity && $this->deleteProduct((int)$id_product, (int)$id_product_attribute, null, (int)$id_address_delivery)); + } - /* Get customization quantity */ - $result = Db::getInstance()->getRow(' + /* Get customization quantity */ + $result = Db::getInstance()->getRow(' SELECT SUM(`quantity`) AS \'quantity\' FROM `'._DB_PREFIX_.'customization` WHERE `id_cart` = '.(int)$this->id.' AND `id_product` = '.(int)$id_product.' AND `id_product_attribute` = '.(int)$id_product_attribute); - if ($result === false) - return false; + if ($result === false) { + return false; + } - /* If the product still possesses customization it does not have to be deleted */ - if (Db::getInstance()->NumRows() && (int)$result['quantity']) - return Db::getInstance()->execute(' + /* If the product still possesses customization it does not have to be deleted */ + if (Db::getInstance()->NumRows() && (int)$result['quantity']) { + return Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'cart_product` SET `quantity` = '.(int)$result['quantity'].' WHERE `id_cart` = '.(int)$this->id.' AND `id_product` = '.(int)$id_product. - ($id_product_attribute != null ? ' AND `id_product_attribute` = '.(int)$id_product_attribute : '') - ); + ($id_product_attribute != null ? ' AND `id_product_attribute` = '.(int)$id_product_attribute : '') + ); + } - /* Product deletion */ - $result = Db::getInstance()->execute(' + /* Product deletion */ + $result = Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'cart_product` WHERE `id_product` = '.(int)$id_product.' '.(!is_null($id_product_attribute) ? ' AND `id_product_attribute` = '.(int)$id_product_attribute : '').' AND `id_cart` = '.(int)$this->id.' '.((int)$id_address_delivery ? 'AND `id_address_delivery` = '.(int)$id_address_delivery : '')); - if ($result) - { - $return = $this->update(); - // refresh cache of self::_products - $this->_products = $this->getProducts(true); - CartRule::autoRemoveFromCart(); - CartRule::autoAddToCart(); + if ($result) { + $return = $this->update(); + // refresh cache of self::_products + $this->_products = $this->getProducts(true); + CartRule::autoRemoveFromCart(); + CartRule::autoAddToCart(); - return $return; - } + return $return; + } - return false; - } + return false; + } - /** - * Delete a customization from the cart. If customization is a Picture, - * then the image is also deleted - * - * @param int $id_customization - * @return bool result - */ - protected function _deleteCustomization($id_customization, $id_product, $id_product_attribute, $id_address_delivery = 0) - { - $result = true; - $customization = Db::getInstance()->getRow('SELECT * + /** + * Delete a customization from the cart. If customization is a Picture, + * then the image is also deleted + * + * @param int $id_customization + * @return bool result + */ + protected function _deleteCustomization($id_customization, $id_product, $id_product_attribute, $id_address_delivery = 0) + { + $result = true; + $customization = Db::getInstance()->getRow('SELECT * FROM `'._DB_PREFIX_.'customization` WHERE `id_customization` = '.(int)$id_customization); - if ($customization) - { - $cust_data = Db::getInstance()->getRow('SELECT * + if ($customization) { + $cust_data = Db::getInstance()->getRow('SELECT * FROM `'._DB_PREFIX_.'customized_data` WHERE `id_customization` = '.(int)$id_customization); - // Delete customization picture if necessary - if (isset($cust_data['type']) && $cust_data['type'] == 0) - $result &= (@unlink(_PS_UPLOAD_DIR_.$cust_data['value']) && @unlink(_PS_UPLOAD_DIR_.$cust_data['value'].'_small')); + // Delete customization picture if necessary + if (isset($cust_data['type']) && $cust_data['type'] == 0) { + $result &= (@unlink(_PS_UPLOAD_DIR_.$cust_data['value']) && @unlink(_PS_UPLOAD_DIR_.$cust_data['value'].'_small')); + } - $result &= Db::getInstance()->execute( - 'DELETE FROM `'._DB_PREFIX_.'customized_data` + $result &= Db::getInstance()->execute( + 'DELETE FROM `'._DB_PREFIX_.'customized_data` WHERE `id_customization` = '.(int)$id_customization - ); + ); - if ($result) - $result &= Db::getInstance()->execute( - 'UPDATE `'._DB_PREFIX_.'cart_product` + if ($result) { + $result &= Db::getInstance()->execute( + 'UPDATE `'._DB_PREFIX_.'cart_product` SET `quantity` = `quantity` - '.(int)$customization['quantity'].' WHERE `id_cart` = '.(int)$this->id.' AND `id_product` = '.(int)$id_product. - ((int)$id_product_attribute ? ' AND `id_product_attribute` = '.(int)$id_product_attribute : '').' + ((int)$id_product_attribute ? ' AND `id_product_attribute` = '.(int)$id_product_attribute : '').' AND `id_address_delivery` = '.(int)$id_address_delivery - ); + ); + } - if (!$result) - return false; + if (!$result) { + return false; + } - return Db::getInstance()->execute( - 'DELETE FROM `'._DB_PREFIX_.'customization` + return Db::getInstance()->execute( + 'DELETE FROM `'._DB_PREFIX_.'customization` WHERE `id_customization` = '.(int)$id_customization - ); - } - - return true; - } - - public static function getTotalCart($id_cart, $use_tax_display = false, $type = Cart::BOTH) - { - $cart = new Cart($id_cart); - if (!Validate::isLoadedObject($cart)) - die(Tools::displayError()); - - $with_taxes = $use_tax_display ? $cart->_taxCalculationMethod != PS_TAX_EXC : true; - return Tools::displayPrice($cart->getOrderTotal($with_taxes, $type), Currency::getCurrencyInstance((int)$cart->id_currency), false); - } - - - public static function getOrderTotalUsingTaxCalculationMethod($id_cart) - { - return Cart::getTotalCart($id_cart, true); - } - - /** - * This function returns the total cart amount - * - * Possible values for $type: - * Cart::ONLY_PRODUCTS - * Cart::ONLY_DISCOUNTS - * Cart::BOTH - * Cart::BOTH_WITHOUT_SHIPPING - * Cart::ONLY_SHIPPING - * Cart::ONLY_WRAPPING - * Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING - * Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING - * - * @param bool $withTaxes With or without taxes - * @param int $type Total type - * @param bool $use_cache Allow using cache of the method CartRule::getContextualValue - * @return float Order total - */ - public function getOrderTotal($with_taxes = true, $type = Cart::BOTH, $products = null, $id_carrier = null, $use_cache = true) - { - // Dependencies - $address_factory = Adapter_ServiceLocator::get('Adapter_AddressFactory'); - $price_calculator = Adapter_ServiceLocator::get('Adapter_ProductPriceCalculator'); - $configuration = Adapter_ServiceLocator::get('Core_Business_ConfigurationInterface'); - - $ps_tax_address_type = $configuration->get('PS_TAX_ADDRESS_TYPE'); - $ps_use_ecotax = $configuration->get('PS_USE_ECOTAX'); - $ps_round_type = $configuration->get('PS_ROUND_TYPE'); - $ps_ecotax_tax_rules_group_id = $configuration->get('PS_ECOTAX_TAX_RULES_GROUP_ID'); - $compute_precision = $configuration->get('_PS_PRICE_COMPUTE_PRECISION_'); - - if (!$this->id) - return 0; - - $type = (int)$type; - $array_type = array( - Cart::ONLY_PRODUCTS, - Cart::ONLY_DISCOUNTS, - Cart::BOTH, - Cart::BOTH_WITHOUT_SHIPPING, - Cart::ONLY_SHIPPING, - Cart::ONLY_WRAPPING, - Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING, - Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING, - ); - - // Define virtual context to prevent case where the cart is not the in the global context - $virtual_context = Context::getContext()->cloneContext(); - $virtual_context->cart = $this; - - if (!in_array($type, $array_type)) - die(Tools::displayError()); - - $with_shipping = in_array($type, array(Cart::BOTH, Cart::ONLY_SHIPPING)); - - // if cart rules are not used - if ($type == Cart::ONLY_DISCOUNTS && !CartRule::isFeatureActive()) - return 0; - - // no shipping cost if is a cart with only virtuals products - $virtual = $this->isVirtualCart(); - if ($virtual && $type == Cart::ONLY_SHIPPING) - return 0; - - if ($virtual && $type == Cart::BOTH) - $type = Cart::BOTH_WITHOUT_SHIPPING; - - if ($with_shipping || $type == Cart::ONLY_DISCOUNTS) - { - if (is_null($products) && is_null($id_carrier)) - $shipping_fees = $this->getTotalShippingCost(null, (bool)$with_taxes); - else - $shipping_fees = $this->getPackageShippingCost($id_carrier, (bool)$with_taxes, null, $products); - } - else - $shipping_fees = 0; - - if ($type == Cart::ONLY_SHIPPING) - return $shipping_fees; - - if ($type == Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING) - $type = Cart::ONLY_PRODUCTS; - - $param_product = true; - if (is_null($products)) - { - $param_product = false; - $products = $this->getProducts(); - } - - if ($type == Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING) - { - foreach ($products as $key => $product) - if ($product['is_virtual']) - unset($products[$key]); - $type = Cart::ONLY_PRODUCTS; - } - - $order_total = 0; - if (Tax::excludeTaxeOption()) - $with_taxes = false; - - $products_total = array(); - $ecotax_total = 0; - - foreach ($products as $product) // products refer to the cart details - { - if ($virtual_context->shop->id != $product['id_shop']) - $virtual_context->shop = new Shop((int)$product['id_shop']); - - if ($ps_tax_address_type == 'id_address_invoice') - $id_address = (int)$this->id_address_invoice; - else - $id_address = (int)$product['id_address_delivery']; // Get delivery address of the product from the cart - if (!$address_factory->addressExists($id_address)) - $id_address = null; - - // The $null variable below is not used, - // but it is necessary to pass it to getProductPrice because - // it expects a reference. - $null = null; - $price = $price_calculator->getProductPrice( - (int)$product['id_product'], - $with_taxes, - (int)$product['id_product_attribute'], - 6, - null, - false, - true, - $product['cart_quantity'], - false, - (int)$this->id_customer ? (int)$this->id_customer : null, - (int)$this->id, - $id_address, - $null, - $ps_use_ecotax, - true, - $virtual_context - ); - - $address = $address_factory->findOrCreate($id_address, true); - - if ($with_taxes) - { - $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int)$product['id_product'], $virtual_context); - $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator(); - } - else - $id_tax_rules_group = 0; - - if (in_array($ps_round_type, array(Order::ROUND_ITEM, Order::ROUND_LINE))) - { - if (!isset($products_total[$id_tax_rules_group])) - $products_total[$id_tax_rules_group] = 0; - } - else - if (!isset($products_total[$id_tax_rules_group.'_'.$id_address])) - $products_total[$id_tax_rules_group.'_'.$id_address] = 0; - - switch ($ps_round_type) - { - case Order::ROUND_TOTAL: - $products_total[$id_tax_rules_group.'_'.$id_address] += $price * (int)$product['cart_quantity']; - break; - - case Order::ROUND_LINE: - $product_price = $price * $product['cart_quantity']; - $products_total[$id_tax_rules_group] += Tools::ps_round($product_price, $compute_precision); - break; - - case Order::ROUND_ITEM: - default: - $product_price = /*$with_taxes ? $tax_calculator->addTaxes($price) : */$price; - $products_total[$id_tax_rules_group] += Tools::ps_round($product_price, $compute_precision) * (int)$product['cart_quantity']; - break; - } - } - - foreach ($products_total as $key => $price) - $order_total += $price; - - $order_total_products = $order_total; - - if ($type == Cart::ONLY_DISCOUNTS) - $order_total = 0; - - // Wrapping Fees - $wrapping_fees = 0; - - // With PS_ATCP_SHIPWRAP on the gift wrapping cost computation calls getOrderTotal with $type === Cart::ONLY_PRODUCTS, so the flag below prevents an infinite recursion. - $include_gift_wrapping = (!$configuration->get('PS_ATCP_SHIPWRAP') || $type !== Cart::ONLY_PRODUCTS); - - if ($this->gift && $include_gift_wrapping) - $wrapping_fees = Tools::convertPrice(Tools::ps_round($this->getGiftWrappingPrice($with_taxes), $compute_precision), Currency::getCurrencyInstance((int)$this->id_currency)); - if ($type == Cart::ONLY_WRAPPING) - return $wrapping_fees; - - $order_total_discount = 0; - $order_shipping_discount = 0; - if (!in_array($type, array(Cart::ONLY_SHIPPING, Cart::ONLY_PRODUCTS)) && CartRule::isFeatureActive()) - { - // First, retrieve the cart rules associated to this "getOrderTotal" - if ($with_shipping || $type == Cart::ONLY_DISCOUNTS) - $cart_rules = $this->getCartRules(CartRule::FILTER_ACTION_ALL); - else - { - $cart_rules = $this->getCartRules(CartRule::FILTER_ACTION_REDUCTION); - // Cart Rules array are merged manually in order to avoid doubles - foreach ($this->getCartRules(CartRule::FILTER_ACTION_GIFT) as $tmp_cart_rule) - { - $flag = false; - foreach ($cart_rules as $cart_rule) - if ($tmp_cart_rule['id_cart_rule'] == $cart_rule['id_cart_rule']) - $flag = true; - if (!$flag) - $cart_rules[] = $tmp_cart_rule; - } - } - - $id_address_delivery = 0; - if (isset($products[0])) - $id_address_delivery = (is_null($products) ? $this->id_address_delivery : $products[0]['id_address_delivery']); - $package = array('id_carrier' => $id_carrier, 'id_address' => $id_address_delivery, 'products' => $products); - - // Then, calculate the contextual value for each one - $flag = false; - foreach ($cart_rules as $cart_rule) - { - // If the cart rule offers free shipping, add the shipping cost - if (($with_shipping || $type == Cart::ONLY_DISCOUNTS) && $cart_rule['obj']->free_shipping && !$flag) - { - $order_shipping_discount = (float)Tools::ps_round($cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_SHIPPING, ($param_product ? $package : null), $use_cache), $compute_precision); - $flag = true; - } - - // If the cart rule is a free gift, then add the free gift value only if the gift is in this package - if ((int)$cart_rule['obj']->gift_product) - { - $in_order = false; - if (is_null($products)) - $in_order = true; - else - foreach ($products as $product) - if ($cart_rule['obj']->gift_product == $product['id_product'] && $cart_rule['obj']->gift_product_attribute == $product['id_product_attribute']) - $in_order = true; - - if ($in_order) - $order_total_discount += $cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_GIFT, $package, $use_cache); - } - - // If the cart rule offers a reduction, the amount is prorated (with the products in the package) - if ($cart_rule['obj']->reduction_percent > 0 || $cart_rule['obj']->reduction_amount > 0) - $order_total_discount += Tools::ps_round($cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_REDUCTION, $package, $use_cache), $compute_precision); - } - $order_total_discount = min(Tools::ps_round($order_total_discount, 2), (float)$order_total_products) + (float)$order_shipping_discount; - $order_total -= $order_total_discount; - } - - if ($type == Cart::BOTH) - $order_total += $shipping_fees + $wrapping_fees; - - if ($order_total < 0 && $type != Cart::ONLY_DISCOUNTS) - return 0; - - if ($type == Cart::ONLY_DISCOUNTS) - return $order_total_discount; - - return Tools::ps_round((float)$order_total, $compute_precision); - } - - /** - * Get the gift wrapping price - * @param bool $with_taxes With or without taxes - * @return float wrapping price - */ - public function getGiftWrappingPrice($with_taxes = true, $id_address = null) - { - static $address = array(); - - $wrapping_fees = (float)Configuration::get('PS_GIFT_WRAPPING_PRICE'); - - if ($wrapping_fees <= 0) - { - return $wrapping_fees; - } - - if ($with_taxes) - { - if (Configuration::get('PS_ATCP_SHIPWRAP')) - { - // With PS_ATCP_SHIPWRAP, wrapping fee is by default tax included - // so nothing to do here. - } - else - { - if (!isset($address[$this->id])) - { - if ($id_address === null) - $id_address = (int)$this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; - try - { - $address[$this->id] = Address::initialize($id_address); - } - catch (Exception $e) - { - $address[$this->id] = new Address(); - $address[$this->id]->id_country = Configuration::get('PS_COUNTRY_DEFAULT'); - } - } - - $tax_manager = TaxManagerFactory::getManager($address[$this->id], (int)Configuration::get('PS_GIFT_WRAPPING_TAX_RULES_GROUP')); - $tax_calculator = $tax_manager->getTaxCalculator(); - $wrapping_fees = $tax_calculator->addTaxes($wrapping_fees); - } - } - else if (Configuration::get('PS_ATCP_SHIPWRAP')) - { - // With PS_ATCP_SHIPWRAP, wrapping fee is by default tax included, so we convert it - // when asked for the pre tax price. - $wrapping_fees = Tools::ps_round( - $wrapping_fees / (1 + $this->getAverageProductsTaxRate()), - _PS_PRICE_COMPUTE_PRECISION_ - ); - } - - return $wrapping_fees; - } - - /** - * Get the number of packages - * - * @return int number of packages - */ - public function getNbOfPackages() - { - static $nb_packages = array(); - - if (!isset($nb_packages[$this->id])) - { - $nb_packages[$this->id] = 0; - foreach ($this->getPackageList() as $by_address) - $nb_packages[$this->id] += count($by_address); - } - - return $nb_packages[$this->id]; - } - - /** - * Get products grouped by package and by addresses to be sent individualy (one package = one shipping cost). - * - * @return array array( - * 0 => array( // First address - * 0 => array( // First package - * 'product_list' => array(...), - * 'carrier_list' => array(...), - * 'id_warehouse' => array(...), - * ), - * ), - * ); - * @todo Add avaibility check - */ - public function getPackageList($flush = false) - { - static $cache = array(); - $cache_key = (int)$this->id.'_'.(int)$this->id_address_delivery; - if (isset($cache[$cache_key]) && $cache[$cache_key] !== false && !$flush) - return $cache[$cache_key]; - - $product_list = $this->getProducts($flush); - // Step 1 : Get product informations (warehouse_list and carrier_list), count warehouse - // Determine the best warehouse to determine the packages - // For that we count the number of time we can use a warehouse for a specific delivery address - $warehouse_count_by_address = array(); - - $stock_management_active = Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'); - - foreach ($product_list as &$product) - { - if ((int)$product['id_address_delivery'] == 0) - $product['id_address_delivery'] = (int)$this->id_address_delivery; - - if (!isset($warehouse_count_by_address[$product['id_address_delivery']])) - $warehouse_count_by_address[$product['id_address_delivery']] = array(); - - $product['warehouse_list'] = array(); - - if ($stock_management_active && - (int)$product['advanced_stock_management'] == 1) - { - $warehouse_list = Warehouse::getProductWarehouseList($product['id_product'], $product['id_product_attribute'], $this->id_shop); - if (count($warehouse_list) == 0) - $warehouse_list = Warehouse::getProductWarehouseList($product['id_product'], $product['id_product_attribute']); - // Does the product is in stock ? - // If yes, get only warehouse where the product is in stock - - $warehouse_in_stock = array(); - $manager = StockManagerFactory::getManager(); - - foreach ($warehouse_list as $key => $warehouse) - { - $product_real_quantities = $manager->getProductRealQuantities( - $product['id_product'], - $product['id_product_attribute'], - array($warehouse['id_warehouse']), - true - ); - - if ($product_real_quantities > 0 || Pack::isPack((int)$product['id_product'])) - $warehouse_in_stock[] = $warehouse; - } - - if (!empty($warehouse_in_stock)) - { - $warehouse_list = $warehouse_in_stock; - $product['in_stock'] = true; - } - else - $product['in_stock'] = false; - } - else - { - //simulate default warehouse - $warehouse_list = array(0 => array('id_warehouse' => 0)); - $product['in_stock'] = StockAvailable::getQuantityAvailableByProduct($product['id_product'], $product['id_product_attribute']) > 0; - } - - foreach ($warehouse_list as $warehouse) - { - $product['warehouse_list'][$warehouse['id_warehouse']] = $warehouse['id_warehouse']; - if (!isset($warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']])) - $warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']] = 0; - - $warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']]++; - } - } - unset($product); - - arsort($warehouse_count_by_address); - - // Step 2 : Group product by warehouse - $grouped_by_warehouse = array(); - - foreach ($product_list as &$product) - { - if (!isset($grouped_by_warehouse[$product['id_address_delivery']])) - $grouped_by_warehouse[$product['id_address_delivery']] = array( - 'in_stock' => array(), - 'out_of_stock' => array(), - ); - - $product['carrier_list'] = array(); - $id_warehouse = 0; - foreach ($warehouse_count_by_address[$product['id_address_delivery']] as $id_war => $val) - { - if (array_key_exists((int)$id_war, $product['warehouse_list'])) - { - $product['carrier_list'] = Tools::array_replace($product['carrier_list'], Carrier::getAvailableCarrierList(new Product($product['id_product']), $id_war, $product['id_address_delivery'], null, $this)); - if (!$id_warehouse) - $id_warehouse = (int)$id_war; - } - } - - if (!isset($grouped_by_warehouse[$product['id_address_delivery']]['in_stock'][$id_warehouse])) - { - $grouped_by_warehouse[$product['id_address_delivery']]['in_stock'][$id_warehouse] = array(); - $grouped_by_warehouse[$product['id_address_delivery']]['out_of_stock'][$id_warehouse] = array(); - } - - if (!$this->allow_seperated_package) - $key = 'in_stock'; - else - { - $key = $product['in_stock'] ? 'in_stock' : 'out_of_stock'; - if ($product['in_stock']) - { - $out_stock_part = $product['cart_quantity'] - $product['in_stock']; - $product_bis = $product; - $product_bis['cart_quantity'] = $out_stock_part; - $product_bis['in_stock'] = 0; - $product['cart_quantity'] -= $out_stock_part; - $grouped_by_warehouse[$product['id_address_delivery']]['out_of_stock'][$id_warehouse][] = $product_bis; - } - } - - if (empty($product['carrier_list'])) - $product['carrier_list'] = array(0 => 0); - - $grouped_by_warehouse[$product['id_address_delivery']][$key][$id_warehouse][] = $product; - } - unset($product); - - // Step 3 : grouped product from grouped_by_warehouse by available carriers - $grouped_by_carriers = array(); - foreach ($grouped_by_warehouse as $id_address_delivery => $products_in_stock_list) - { - if (!isset($grouped_by_carriers[$id_address_delivery])) - $grouped_by_carriers[$id_address_delivery] = array( - 'in_stock' => array(), - 'out_of_stock' => array(), - ); - foreach ($products_in_stock_list as $key => $warehouse_list) - { - if (!isset($grouped_by_carriers[$id_address_delivery][$key])) - $grouped_by_carriers[$id_address_delivery][$key] = array(); - foreach ($warehouse_list as $id_warehouse => $product_list) - { - if (!isset($grouped_by_carriers[$id_address_delivery][$key][$id_warehouse])) - $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse] = array(); - foreach ($product_list as $product) - { - $package_carriers_key = implode(',', $product['carrier_list']); - - if (!isset($grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key])) - $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key] = array( - 'product_list' => array(), - 'carrier_list' => $product['carrier_list'], - 'warehouse_list' => $product['warehouse_list'] - ); - - $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key]['product_list'][] = $product; - } - } - } - } - - $package_list = array(); - // Step 4 : merge product from grouped_by_carriers into $package to minimize the number of package - foreach ($grouped_by_carriers as $id_address_delivery => $products_in_stock_list) - { - if (!isset($package_list[$id_address_delivery])) - $package_list[$id_address_delivery] = array( - 'in_stock' => array(), - 'out_of_stock' => array(), - ); - - foreach ($products_in_stock_list as $key => $warehouse_list) - { - if (!isset($package_list[$id_address_delivery][$key])) - $package_list[$id_address_delivery][$key] = array(); - // Count occurance of each carriers to minimize the number of packages - $carrier_count = array(); - foreach ($warehouse_list as $id_warehouse => $products_grouped_by_carriers) - { - foreach ($products_grouped_by_carriers as $data) - { - foreach ($data['carrier_list'] as $id_carrier) - { - if (!isset($carrier_count[$id_carrier])) - $carrier_count[$id_carrier] = 0; - $carrier_count[$id_carrier]++; - } - } - } - arsort($carrier_count); - foreach ($warehouse_list as $id_warehouse => $products_grouped_by_carriers) - { - if (!isset($package_list[$id_address_delivery][$key][$id_warehouse])) - $package_list[$id_address_delivery][$key][$id_warehouse] = array(); - foreach ($products_grouped_by_carriers as $data) - { - foreach ($carrier_count as $id_carrier => $rate) - { - if (array_key_exists($id_carrier, $data['carrier_list'])) - { - if (!isset($package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier])) - $package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier] = array( - 'carrier_list' => $data['carrier_list'], - 'warehouse_list' => $data['warehouse_list'], - 'product_list' => array(), - ); - $package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['carrier_list'] = - array_intersect($package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['carrier_list'], $data['carrier_list']); - $package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['product_list'] = - array_merge($package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['product_list'], $data['product_list']); - - break; - } - } - } - } - } - } - - // Step 5 : Reduce depth of $package_list - $final_package_list = array(); - foreach ($package_list as $id_address_delivery => $products_in_stock_list) - { - if (!isset($final_package_list[$id_address_delivery])) - $final_package_list[$id_address_delivery] = array(); - - foreach ($products_in_stock_list as $key => $warehouse_list) - foreach ($warehouse_list as $id_warehouse => $products_grouped_by_carriers) - foreach ($products_grouped_by_carriers as $data) - { - $final_package_list[$id_address_delivery][] = array( - 'product_list' => $data['product_list'], - 'carrier_list' => $data['carrier_list'], - 'warehouse_list' => $data['warehouse_list'], - 'id_warehouse' => $id_warehouse, - ); - } - } - $cache[$cache_key] = $final_package_list; - return $final_package_list; - } - - public function getPackageIdWarehouse($package, $id_carrier = null) - { - if ($id_carrier === null) - if (isset($package['id_carrier'])) - $id_carrier = (int)$package['id_carrier']; - - if ($id_carrier == null) - return $package['id_warehouse']; - - foreach ($package['warehouse_list'] as $id_warehouse) - { - $warehouse = new Warehouse((int)$id_warehouse); - $available_warehouse_carriers = $warehouse->getCarriers(); - if (in_array($id_carrier, $available_warehouse_carriers)) - return (int)$id_warehouse; - } - return 0; - } - - /** - * Get all deliveries options available for the current cart - * @param Country $default_country - * @param bool $flush Force flushing cache - * - * @return array array( - * 0 => array( // First address - * '12,' => array( // First delivery option available for this address - * carrier_list => array( - * 12 => array( // First carrier for this option - * 'instance' => Carrier Object, - * 'logo' => , - * 'price_with_tax' => 12.4, - * 'price_without_tax' => 12.4, - * 'package_list' => array( - * 1, - * 3, - * ), - * ), - * ), - * is_best_grade => true, // Does this option have the biggest grade (quick shipping) for this shipping address - * is_best_price => true, // Does this option have the lower price for this shipping address - * unique_carrier => true, // Does this option use a unique carrier - * total_price_with_tax => 12.5, - * total_price_without_tax => 12.5, - * position => 5, // Average of the carrier position - * ), - * ), - * ); - * If there are no carriers available for an address, return an empty array - */ - public function getDeliveryOptionList(Country $default_country = null, $flush = false) - { - static $cache = array(); - if (isset($cache[$this->id]) && !$flush) - return $cache[$this->id]; - - $delivery_option_list = array(); - $carriers_price = array(); - $carrier_collection = array(); - $package_list = $this->getPackageList($flush); - - // Foreach addresses - foreach ($package_list as $id_address => $packages) - { - // Initialize vars - $delivery_option_list[$id_address] = array(); - $carriers_price[$id_address] = array(); - $common_carriers = null; - $best_price_carriers = array(); - $best_grade_carriers = array(); - $carriers_instance = array(); - - // Get country - if ($id_address) - { - $address = new Address($id_address); - $country = new Country($address->id_country); - } - else - $country = $default_country; - - // Foreach packages, get the carriers with best price, best position and best grade - foreach ($packages as $id_package => $package) - { - // No carriers available - if (count($packages) == 1 && count($package['carrier_list']) == 1 && current($package['carrier_list']) == 0) - { - $cache[$this->id] = array(); - return $cache[$this->id]; - } - - $carriers_price[$id_address][$id_package] = array(); - - // Get all common carriers for each packages to the same address - if (is_null($common_carriers)) - $common_carriers = $package['carrier_list']; - else - $common_carriers = array_intersect($common_carriers, $package['carrier_list']); - - $best_price = null; - $best_price_carrier = null; - $best_grade = null; - $best_grade_carrier = null; - - // Foreach carriers of the package, calculate his price, check if it the best price, position and grade - foreach ($package['carrier_list'] as $id_carrier) - { - if (!isset($carriers_instance[$id_carrier])) - $carriers_instance[$id_carrier] = new Carrier($id_carrier); - - $price_with_tax = $this->getPackageShippingCost($id_carrier, true, $country, $package['product_list']); - $price_without_tax = $this->getPackageShippingCost($id_carrier, false, $country, $package['product_list']); - if (is_null($best_price) || $price_with_tax < $best_price) - { - $best_price = $price_with_tax; - $best_price_carrier = $id_carrier; - } - $carriers_price[$id_address][$id_package][$id_carrier] = array( - 'without_tax' => $price_without_tax, - 'with_tax' => $price_with_tax); - - $grade = $carriers_instance[$id_carrier]->grade; - if (is_null($best_grade) || $grade > $best_grade) - { - $best_grade = $grade; - $best_grade_carrier = $id_carrier; - } - } - - $best_price_carriers[$id_package] = $best_price_carrier; - $best_grade_carriers[$id_package] = $best_grade_carrier; - } - - // Reset $best_price_carrier, it's now an array - $best_price_carrier = array(); - $key = ''; - - // Get the delivery option with the lower price - foreach ($best_price_carriers as $id_package => $id_carrier) - { - $key .= $id_carrier.','; - if (!isset($best_price_carrier[$id_carrier])) - $best_price_carrier[$id_carrier] = array( - 'price_with_tax' => 0, - 'price_without_tax' => 0, - 'package_list' => array(), - 'product_list' => array(), - ); - $best_price_carrier[$id_carrier]['price_with_tax'] += $carriers_price[$id_address][$id_package][$id_carrier]['with_tax']; - $best_price_carrier[$id_carrier]['price_without_tax'] += $carriers_price[$id_address][$id_package][$id_carrier]['without_tax']; - $best_price_carrier[$id_carrier]['package_list'][] = $id_package; - $best_price_carrier[$id_carrier]['product_list'] = array_merge($best_price_carrier[$id_carrier]['product_list'], $packages[$id_package]['product_list']); - $best_price_carrier[$id_carrier]['instance'] = $carriers_instance[$id_carrier]; - $real_best_price = !isset($real_best_price) || $real_best_price > $carriers_price[$id_address][$id_package][$id_carrier]['with_tax'] ? - $carriers_price[$id_address][$id_package][$id_carrier]['with_tax'] : $real_best_price; - $real_best_price_wt = !isset($real_best_price_wt) || $real_best_price_wt > $carriers_price[$id_address][$id_package][$id_carrier]['without_tax'] ? - $carriers_price[$id_address][$id_package][$id_carrier]['without_tax'] : $real_best_price_wt; - } - - // Add the delivery option with best price as best price - $delivery_option_list[$id_address][$key] = array( - 'carrier_list' => $best_price_carrier, - 'is_best_price' => true, - 'is_best_grade' => false, - 'unique_carrier' => (count($best_price_carrier) <= 1) - ); - - // Reset $best_grade_carrier, it's now an array - $best_grade_carrier = array(); - $key = ''; - - // Get the delivery option with the best grade - foreach ($best_grade_carriers as $id_package => $id_carrier) - { - $key .= $id_carrier.','; - if (!isset($best_grade_carrier[$id_carrier])) - $best_grade_carrier[$id_carrier] = array( - 'price_with_tax' => 0, - 'price_without_tax' => 0, - 'package_list' => array(), - 'product_list' => array(), - ); - $best_grade_carrier[$id_carrier]['price_with_tax'] += $carriers_price[$id_address][$id_package][$id_carrier]['with_tax']; - $best_grade_carrier[$id_carrier]['price_without_tax'] += $carriers_price[$id_address][$id_package][$id_carrier]['without_tax']; - $best_grade_carrier[$id_carrier]['package_list'][] = $id_package; - $best_grade_carrier[$id_carrier]['product_list'] = array_merge($best_grade_carrier[$id_carrier]['product_list'], $packages[$id_package]['product_list']); - $best_grade_carrier[$id_carrier]['instance'] = $carriers_instance[$id_carrier]; - } - - // Add the delivery option with best grade as best grade - if (!isset($delivery_option_list[$id_address][$key])) - $delivery_option_list[$id_address][$key] = array( - 'carrier_list' => $best_grade_carrier, - 'is_best_price' => false, - 'unique_carrier' => (count($best_grade_carrier) <= 1) - ); - $delivery_option_list[$id_address][$key]['is_best_grade'] = true; - - // Get all delivery options with a unique carrier - foreach ($common_carriers as $id_carrier) - { - $key = ''; - $package_list = array(); - $product_list = array(); - $price_with_tax = 0; - $price_without_tax = 0; - - foreach ($packages as $id_package => $package) - { - $key .= $id_carrier.','; - $price_with_tax += $carriers_price[$id_address][$id_package][$id_carrier]['with_tax']; - $price_without_tax += $carriers_price[$id_address][$id_package][$id_carrier]['without_tax']; - $package_list[] = $id_package; - $product_list = array_merge($product_list, $package['product_list']); - } - - if (!isset($delivery_option_list[$id_address][$key])) - $delivery_option_list[$id_address][$key] = array( - 'is_best_price' => false, - 'is_best_grade' => false, - 'unique_carrier' => true, - 'carrier_list' => array( - $id_carrier => array( - 'price_with_tax' => $price_with_tax, - 'price_without_tax' => $price_without_tax, - 'instance' => $carriers_instance[$id_carrier], - 'package_list' => $package_list, - 'product_list' => $product_list, - ) - ) - ); - else - $delivery_option_list[$id_address][$key]['unique_carrier'] = (count($delivery_option_list[$id_address][$key]['carrier_list']) <= 1); - } - } - - $cart_rules = CartRule::getCustomerCartRules(Context::getContext()->cookie->id_lang, Context::getContext()->cookie->id_customer, true, true, false, $this, true); - - $result = false; - if ($this->id) - $result = Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'cart_cart_rule WHERE id_cart = '.(int)$this->id); - - $cart_rules_in_cart = array(); - - if (is_array($result)) - foreach ($result as $row) - $cart_rules_in_cart[] = $row['id_cart_rule']; - - $total_products_wt = $this->getOrderTotal(true, Cart::ONLY_PRODUCTS); - $total_products = $this->getOrderTotal(false, Cart::ONLY_PRODUCTS); - - $free_carriers_rules = array(); - - $context = Context::getContext(); - foreach ($cart_rules as $cart_rule) - { - $total_price = $cart_rule['minimum_amount_tax'] ? $total_products_wt : $total_products; - $total_price += $cart_rule['minimum_amount_tax'] && $cart_rule['minimum_amount_shipping'] ? $real_best_price : 0; - $total_price += !$cart_rule['minimum_amount_tax'] && $cart_rule['minimum_amount_shipping'] ? $real_best_price_wt : 0; - if ($cart_rule['free_shipping'] && $cart_rule['carrier_restriction'] - && in_array($cart_rule['id_cart_rule'], $cart_rules_in_cart) - && $cart_rule['minimum_amount'] <= $total_price) - { - $cr = new CartRule((int)$cart_rule['id_cart_rule']); - if (Validate::isLoadedObject($cr) && - $cr->checkValidity($context, in_array((int)$cart_rule['id_cart_rule'], $cart_rules_in_cart), false, false)) - { - $carriers = $cr->getAssociatedRestrictions('carrier', true, false); - if (is_array($carriers) && count($carriers) && isset($carriers['selected'])) - foreach ($carriers['selected'] as $carrier) - if (isset($carrier['id_carrier']) && $carrier['id_carrier']) - $free_carriers_rules[] = (int)$carrier['id_carrier']; - } - } - } - - // For each delivery options : - // - Set the carrier list - // - Calculate the price - // - Calculate the average position - foreach ($delivery_option_list as $id_address => $delivery_option) - foreach ($delivery_option as $key => $value) - { - $total_price_with_tax = 0; - $total_price_without_tax = 0; - $position = 0; - foreach ($value['carrier_list'] as $id_carrier => $data) - { - $total_price_with_tax += $data['price_with_tax']; - $total_price_without_tax += $data['price_without_tax']; - $total_price_without_tax_with_rules = (in_array($id_carrier, $free_carriers_rules)) ? 0 : $total_price_without_tax; - - if (!isset($carrier_collection[$id_carrier])) - $carrier_collection[$id_carrier] = new Carrier($id_carrier); - $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['instance'] = $carrier_collection[$id_carrier]; - - if (file_exists(_PS_SHIP_IMG_DIR_.$id_carrier.'.jpg')) - $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['logo'] = _THEME_SHIP_DIR_.$id_carrier.'.jpg'; - else - $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['logo'] = false; - - $position += $carrier_collection[$id_carrier]->position; - } - $delivery_option_list[$id_address][$key]['total_price_with_tax'] = $total_price_with_tax; - $delivery_option_list[$id_address][$key]['total_price_without_tax'] = $total_price_without_tax; - $delivery_option_list[$id_address][$key]['is_free'] = !$total_price_without_tax_with_rules ? true : false; - $delivery_option_list[$id_address][$key]['position'] = $position / count($value['carrier_list']); - } - - // Sort delivery option list - foreach ($delivery_option_list as &$array) - uasort ($array, array('Cart', 'sortDeliveryOptionList')); - - $cache[$this->id] = $delivery_option_list; - return $cache[$this->id]; - } - - /** - * - * Sort list of option delivery by parameters define in the BO - * @param $option1 - * @param $option2 - * @return int -1 if $option 1 must be placed before and 1 if the $option1 must be placed after the $option2 - */ - public static function sortDeliveryOptionList($option1, $option2) - { - static $order_by_price = null; - static $order_way = null; - if (is_null($order_by_price)) - $order_by_price = !Configuration::get('PS_CARRIER_DEFAULT_SORT'); - if (is_null($order_way)) - $order_way = Configuration::get('PS_CARRIER_DEFAULT_ORDER'); - - if ($order_by_price) - if ($order_way) - return ($option1['total_price_with_tax'] < $option2['total_price_with_tax']) * 2 - 1; // return -1 or 1 - else - return ($option1['total_price_with_tax'] >= $option2['total_price_with_tax']) * 2 - 1; // return -1 or 1 - else - if ($order_way) - return ($option1['position'] < $option2['position']) * 2 - 1; // return -1 or 1 - else - return ($option1['position'] >= $option2['position']) * 2 - 1; // return -1 or 1 - } - - public function carrierIsSelected($id_carrier, $id_address) - { - $delivery_option = $this->getDeliveryOption(); - $delivery_option_list = $this->getDeliveryOptionList(); - - if (!isset($delivery_option[$id_address])) - return false; - - if (!isset($delivery_option_list[$id_address][$delivery_option[$id_address]])) - return false; - - if (!in_array($id_carrier, array_keys($delivery_option_list[$id_address][$delivery_option[$id_address]]['carrier_list']))) - return false; - - return true; - } - - /** - * Get all deliveries options available for the current cart formated like Carriers::getCarriersForOrder - * This method was wrote for retrocompatibility with 1.4 theme - * New theme need to use Cart::getDeliveryOptionList() to generate carriers option in the checkout process - * - * @since 1.5.0 - * - * @param Country $default_country - * @param bool $flush Force flushing cache - * - */ - public function simulateCarriersOutput(Country $default_country = null, $flush = false) - { - $delivery_option_list = $this->getDeliveryOptionList($default_country, $flush); - - // This method cannot work if there is multiple address delivery - if (count($delivery_option_list) > 1 || empty($delivery_option_list)) - return array(); - - $carriers = array(); - foreach (reset($delivery_option_list) as $key => $option) - { - $price = $option['total_price_with_tax']; - $price_tax_exc = $option['total_price_without_tax']; - - if ($option['unique_carrier']) - { - $carrier = reset($option['carrier_list']); - $name = $carrier['instance']->name; - $img = $carrier['logo']; - $delay = $carrier['instance']->delay; - $delay = isset($delay[Context::getContext()->language->id]) ? $delay[Context::getContext()->language->id] : $delay[(int)Configuration::get('PS_LANG_DEFAULT')]; - } - else - { - $nameList = array(); - foreach ($option['carrier_list'] as $carrier) - $nameList[] = $carrier['instance']->name; - $name = join(' -', $nameList); - $img = ''; // No images if multiple carriers - $delay = ''; - } - $carriers[] = array( - 'name' => $name, - 'img' => $img, - 'delay' => $delay, - 'price' => $price, - 'price_tax_exc' => $price_tax_exc, - 'id_carrier' => Cart::intifier($key), // Need to translate to an integer for retrocompatibility reason, in 1.4 template we used intval - 'is_module' => false, - ); - } - return $carriers; - } - - public function simulateCarrierSelectedOutput($use_cache = true) - { - $delivery_option = $this->getDeliveryOption(null, false, $use_cache); - - if (count($delivery_option) > 1 || empty($delivery_option)) - return 0; - - return Cart::intifier(reset($delivery_option)); - } - - /** - * Translate a string option_delivery identifier ('24,3,') in a int (3240002000) - * - * The option_delivery identifier is a list of integers separated by a ','. - * This method replace the delimiter by a sequence of '0'. - * The size of this sequence is fixed by the first digit of the return - * - * @return int - */ - public static function intifier($string, $delimiter = ',') - { - $elm = explode($delimiter, $string); - $max = max($elm); - return strlen($max).implode(str_repeat('0', strlen($max) + 1), $elm); - } - - /** - * Translate a int option_delivery identifier (3240002000) in a string ('24,3,') - */ - public static function desintifier($int, $delimiter = ',') - { - $delimiter_len = $int[0]; - $int = strrev(substr($int, 1)); - $elm = explode(str_repeat('0', $delimiter_len + 1), $int); - return strrev(implode($delimiter, $elm)); - } - - /** - * Does the cart use multiple address - * @return bool - */ - public function isMultiAddressDelivery() - { - static $cache = array(); - - if (!isset($cache[$this->id])) - { - $sql = new DbQuery(); - $sql->select('count(distinct id_address_delivery)'); - $sql->from('cart_product', 'cp'); - $sql->where('id_cart = '.(int)$this->id); - - $cache[$this->id] = Db::getInstance()->getValue($sql) > 1; - } - return $cache[$this->id]; - } - - /** - * Get all delivery addresses object for the current cart - */ - public function getAddressCollection() - { - $collection = array(); - $cache_id = 'Cart::getAddressCollection'.(int)$this->id; - if (!Cache::isStored($cache_id)) - { - $result = Db::getInstance()->executeS( - 'SELECT DISTINCT `id_address_delivery` + ); + } + + return true; + } + + public static function getTotalCart($id_cart, $use_tax_display = false, $type = Cart::BOTH) + { + $cart = new Cart($id_cart); + if (!Validate::isLoadedObject($cart)) { + die(Tools::displayError()); + } + + $with_taxes = $use_tax_display ? $cart->_taxCalculationMethod != PS_TAX_EXC : true; + return Tools::displayPrice($cart->getOrderTotal($with_taxes, $type), Currency::getCurrencyInstance((int)$cart->id_currency), false); + } + + + public static function getOrderTotalUsingTaxCalculationMethod($id_cart) + { + return Cart::getTotalCart($id_cart, true); + } + + /** + * This function returns the total cart amount + * + * Possible values for $type: + * Cart::ONLY_PRODUCTS + * Cart::ONLY_DISCOUNTS + * Cart::BOTH + * Cart::BOTH_WITHOUT_SHIPPING + * Cart::ONLY_SHIPPING + * Cart::ONLY_WRAPPING + * Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING + * Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING + * + * @param bool $withTaxes With or without taxes + * @param int $type Total type + * @param bool $use_cache Allow using cache of the method CartRule::getContextualValue + * @return float Order total + */ + public function getOrderTotal($with_taxes = true, $type = Cart::BOTH, $products = null, $id_carrier = null, $use_cache = true) + { + // Dependencies + $address_factory = Adapter_ServiceLocator::get('Adapter_AddressFactory'); + $price_calculator = Adapter_ServiceLocator::get('Adapter_ProductPriceCalculator'); + $configuration = Adapter_ServiceLocator::get('Core_Business_ConfigurationInterface'); + + $ps_tax_address_type = $configuration->get('PS_TAX_ADDRESS_TYPE'); + $ps_use_ecotax = $configuration->get('PS_USE_ECOTAX'); + $ps_round_type = $configuration->get('PS_ROUND_TYPE'); + $ps_ecotax_tax_rules_group_id = $configuration->get('PS_ECOTAX_TAX_RULES_GROUP_ID'); + $compute_precision = $configuration->get('_PS_PRICE_COMPUTE_PRECISION_'); + + if (!$this->id) { + return 0; + } + + $type = (int)$type; + $array_type = array( + Cart::ONLY_PRODUCTS, + Cart::ONLY_DISCOUNTS, + Cart::BOTH, + Cart::BOTH_WITHOUT_SHIPPING, + Cart::ONLY_SHIPPING, + Cart::ONLY_WRAPPING, + Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING, + Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING, + ); + + // Define virtual context to prevent case where the cart is not the in the global context + $virtual_context = Context::getContext()->cloneContext(); + $virtual_context->cart = $this; + + if (!in_array($type, $array_type)) { + die(Tools::displayError()); + } + + $with_shipping = in_array($type, array(Cart::BOTH, Cart::ONLY_SHIPPING)); + + // if cart rules are not used + if ($type == Cart::ONLY_DISCOUNTS && !CartRule::isFeatureActive()) { + return 0; + } + + // no shipping cost if is a cart with only virtuals products + $virtual = $this->isVirtualCart(); + if ($virtual && $type == Cart::ONLY_SHIPPING) { + return 0; + } + + if ($virtual && $type == Cart::BOTH) { + $type = Cart::BOTH_WITHOUT_SHIPPING; + } + + if ($with_shipping || $type == Cart::ONLY_DISCOUNTS) { + if (is_null($products) && is_null($id_carrier)) { + $shipping_fees = $this->getTotalShippingCost(null, (bool)$with_taxes); + } else { + $shipping_fees = $this->getPackageShippingCost($id_carrier, (bool)$with_taxes, null, $products); + } + } else { + $shipping_fees = 0; + } + + if ($type == Cart::ONLY_SHIPPING) { + return $shipping_fees; + } + + if ($type == Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING) { + $type = Cart::ONLY_PRODUCTS; + } + + $param_product = true; + if (is_null($products)) { + $param_product = false; + $products = $this->getProducts(); + } + + if ($type == Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING) { + foreach ($products as $key => $product) { + if ($product['is_virtual']) { + unset($products[$key]); + } + } + $type = Cart::ONLY_PRODUCTS; + } + + $order_total = 0; + if (Tax::excludeTaxeOption()) { + $with_taxes = false; + } + + $products_total = array(); + $ecotax_total = 0; + + foreach ($products as $product) { + // products refer to the cart details + + if ($virtual_context->shop->id != $product['id_shop']) { + $virtual_context->shop = new Shop((int)$product['id_shop']); + } + + if ($ps_tax_address_type == 'id_address_invoice') { + $id_address = (int)$this->id_address_invoice; + } else { + $id_address = (int)$product['id_address_delivery']; + } // Get delivery address of the product from the cart + if (!$address_factory->addressExists($id_address)) { + $id_address = null; + } + + // The $null variable below is not used, + // but it is necessary to pass it to getProductPrice because + // it expects a reference. + $null = null; + $price = $price_calculator->getProductPrice( + (int)$product['id_product'], + $with_taxes, + (int)$product['id_product_attribute'], + 6, + null, + false, + true, + $product['cart_quantity'], + false, + (int)$this->id_customer ? (int)$this->id_customer : null, + (int)$this->id, + $id_address, + $null, + $ps_use_ecotax, + true, + $virtual_context + ); + + $address = $address_factory->findOrCreate($id_address, true); + + if ($with_taxes) { + $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int)$product['id_product'], $virtual_context); + $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator(); + } else { + $id_tax_rules_group = 0; + } + + if (in_array($ps_round_type, array(Order::ROUND_ITEM, Order::ROUND_LINE))) { + if (!isset($products_total[$id_tax_rules_group])) { + $products_total[$id_tax_rules_group] = 0; + } + } elseif (!isset($products_total[$id_tax_rules_group.'_'.$id_address])) { + $products_total[$id_tax_rules_group.'_'.$id_address] = 0; + } + + switch ($ps_round_type) { + case Order::ROUND_TOTAL: + $products_total[$id_tax_rules_group.'_'.$id_address] += $price * (int)$product['cart_quantity']; + break; + + case Order::ROUND_LINE: + $product_price = $price * $product['cart_quantity']; + $products_total[$id_tax_rules_group] += Tools::ps_round($product_price, $compute_precision); + break; + + case Order::ROUND_ITEM: + default: + $product_price = /*$with_taxes ? $tax_calculator->addTaxes($price) : */$price; + $products_total[$id_tax_rules_group] += Tools::ps_round($product_price, $compute_precision) * (int)$product['cart_quantity']; + break; + } + } + + foreach ($products_total as $key => $price) { + $order_total += $price; + } + + $order_total_products = $order_total; + + if ($type == Cart::ONLY_DISCOUNTS) { + $order_total = 0; + } + + // Wrapping Fees + $wrapping_fees = 0; + + // With PS_ATCP_SHIPWRAP on the gift wrapping cost computation calls getOrderTotal with $type === Cart::ONLY_PRODUCTS, so the flag below prevents an infinite recursion. + $include_gift_wrapping = (!$configuration->get('PS_ATCP_SHIPWRAP') || $type !== Cart::ONLY_PRODUCTS); + + if ($this->gift && $include_gift_wrapping) { + $wrapping_fees = Tools::convertPrice(Tools::ps_round($this->getGiftWrappingPrice($with_taxes), $compute_precision), Currency::getCurrencyInstance((int)$this->id_currency)); + } + if ($type == Cart::ONLY_WRAPPING) { + return $wrapping_fees; + } + + $order_total_discount = 0; + $order_shipping_discount = 0; + if (!in_array($type, array(Cart::ONLY_SHIPPING, Cart::ONLY_PRODUCTS)) && CartRule::isFeatureActive()) { + // First, retrieve the cart rules associated to this "getOrderTotal" + if ($with_shipping || $type == Cart::ONLY_DISCOUNTS) { + $cart_rules = $this->getCartRules(CartRule::FILTER_ACTION_ALL); + } else { + $cart_rules = $this->getCartRules(CartRule::FILTER_ACTION_REDUCTION); + // Cart Rules array are merged manually in order to avoid doubles + foreach ($this->getCartRules(CartRule::FILTER_ACTION_GIFT) as $tmp_cart_rule) { + $flag = false; + foreach ($cart_rules as $cart_rule) { + if ($tmp_cart_rule['id_cart_rule'] == $cart_rule['id_cart_rule']) { + $flag = true; + } + } + if (!$flag) { + $cart_rules[] = $tmp_cart_rule; + } + } + } + + $id_address_delivery = 0; + if (isset($products[0])) { + $id_address_delivery = (is_null($products) ? $this->id_address_delivery : $products[0]['id_address_delivery']); + } + $package = array('id_carrier' => $id_carrier, 'id_address' => $id_address_delivery, 'products' => $products); + + // Then, calculate the contextual value for each one + $flag = false; + foreach ($cart_rules as $cart_rule) { + // If the cart rule offers free shipping, add the shipping cost + if (($with_shipping || $type == Cart::ONLY_DISCOUNTS) && $cart_rule['obj']->free_shipping && !$flag) { + $order_shipping_discount = (float)Tools::ps_round($cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_SHIPPING, ($param_product ? $package : null), $use_cache), $compute_precision); + $flag = true; + } + + // If the cart rule is a free gift, then add the free gift value only if the gift is in this package + if ((int)$cart_rule['obj']->gift_product) { + $in_order = false; + if (is_null($products)) { + $in_order = true; + } else { + foreach ($products as $product) { + if ($cart_rule['obj']->gift_product == $product['id_product'] && $cart_rule['obj']->gift_product_attribute == $product['id_product_attribute']) { + $in_order = true; + } + } + } + + if ($in_order) { + $order_total_discount += $cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_GIFT, $package, $use_cache); + } + } + + // If the cart rule offers a reduction, the amount is prorated (with the products in the package) + if ($cart_rule['obj']->reduction_percent > 0 || $cart_rule['obj']->reduction_amount > 0) { + $order_total_discount += Tools::ps_round($cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_REDUCTION, $package, $use_cache), $compute_precision); + } + } + $order_total_discount = min(Tools::ps_round($order_total_discount, 2), (float)$order_total_products) + (float)$order_shipping_discount; + $order_total -= $order_total_discount; + } + + if ($type == Cart::BOTH) { + $order_total += $shipping_fees + $wrapping_fees; + } + + if ($order_total < 0 && $type != Cart::ONLY_DISCOUNTS) { + return 0; + } + + if ($type == Cart::ONLY_DISCOUNTS) { + return $order_total_discount; + } + + return Tools::ps_round((float)$order_total, $compute_precision); + } + + /** + * Get the gift wrapping price + * @param bool $with_taxes With or without taxes + * @return float wrapping price + */ + public function getGiftWrappingPrice($with_taxes = true, $id_address = null) + { + static $address = array(); + + $wrapping_fees = (float)Configuration::get('PS_GIFT_WRAPPING_PRICE'); + + if ($wrapping_fees <= 0) { + return $wrapping_fees; + } + + if ($with_taxes) { + if (Configuration::get('PS_ATCP_SHIPWRAP')) { + // With PS_ATCP_SHIPWRAP, wrapping fee is by default tax included + // so nothing to do here. + } else { + if (!isset($address[$this->id])) { + if ($id_address === null) { + $id_address = (int)$this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; + } + try { + $address[$this->id] = Address::initialize($id_address); + } catch (Exception $e) { + $address[$this->id] = new Address(); + $address[$this->id]->id_country = Configuration::get('PS_COUNTRY_DEFAULT'); + } + } + + $tax_manager = TaxManagerFactory::getManager($address[$this->id], (int)Configuration::get('PS_GIFT_WRAPPING_TAX_RULES_GROUP')); + $tax_calculator = $tax_manager->getTaxCalculator(); + $wrapping_fees = $tax_calculator->addTaxes($wrapping_fees); + } + } elseif (Configuration::get('PS_ATCP_SHIPWRAP')) { + // With PS_ATCP_SHIPWRAP, wrapping fee is by default tax included, so we convert it + // when asked for the pre tax price. + $wrapping_fees = Tools::ps_round( + $wrapping_fees / (1 + $this->getAverageProductsTaxRate()), + _PS_PRICE_COMPUTE_PRECISION_ + ); + } + + return $wrapping_fees; + } + + /** + * Get the number of packages + * + * @return int number of packages + */ + public function getNbOfPackages() + { + static $nb_packages = array(); + + if (!isset($nb_packages[$this->id])) { + $nb_packages[$this->id] = 0; + foreach ($this->getPackageList() as $by_address) { + $nb_packages[$this->id] += count($by_address); + } + } + + return $nb_packages[$this->id]; + } + + /** + * Get products grouped by package and by addresses to be sent individualy (one package = one shipping cost). + * + * @return array array( + * 0 => array( // First address + * 0 => array( // First package + * 'product_list' => array(...), + * 'carrier_list' => array(...), + * 'id_warehouse' => array(...), + * ), + * ), + * ); + * @todo Add avaibility check + */ + public function getPackageList($flush = false) + { + static $cache = array(); + $cache_key = (int)$this->id.'_'.(int)$this->id_address_delivery; + if (isset($cache[$cache_key]) && $cache[$cache_key] !== false && !$flush) { + return $cache[$cache_key]; + } + + $product_list = $this->getProducts($flush); + // Step 1 : Get product informations (warehouse_list and carrier_list), count warehouse + // Determine the best warehouse to determine the packages + // For that we count the number of time we can use a warehouse for a specific delivery address + $warehouse_count_by_address = array(); + + $stock_management_active = Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'); + + foreach ($product_list as &$product) { + if ((int)$product['id_address_delivery'] == 0) { + $product['id_address_delivery'] = (int)$this->id_address_delivery; + } + + if (!isset($warehouse_count_by_address[$product['id_address_delivery']])) { + $warehouse_count_by_address[$product['id_address_delivery']] = array(); + } + + $product['warehouse_list'] = array(); + + if ($stock_management_active && + (int)$product['advanced_stock_management'] == 1) { + $warehouse_list = Warehouse::getProductWarehouseList($product['id_product'], $product['id_product_attribute'], $this->id_shop); + if (count($warehouse_list) == 0) { + $warehouse_list = Warehouse::getProductWarehouseList($product['id_product'], $product['id_product_attribute']); + } + // Does the product is in stock ? + // If yes, get only warehouse where the product is in stock + + $warehouse_in_stock = array(); + $manager = StockManagerFactory::getManager(); + + foreach ($warehouse_list as $key => $warehouse) { + $product_real_quantities = $manager->getProductRealQuantities( + $product['id_product'], + $product['id_product_attribute'], + array($warehouse['id_warehouse']), + true + ); + + if ($product_real_quantities > 0 || Pack::isPack((int)$product['id_product'])) { + $warehouse_in_stock[] = $warehouse; + } + } + + if (!empty($warehouse_in_stock)) { + $warehouse_list = $warehouse_in_stock; + $product['in_stock'] = true; + } else { + $product['in_stock'] = false; + } + } else { + //simulate default warehouse + $warehouse_list = array(0 => array('id_warehouse' => 0)); + $product['in_stock'] = StockAvailable::getQuantityAvailableByProduct($product['id_product'], $product['id_product_attribute']) > 0; + } + + foreach ($warehouse_list as $warehouse) { + $product['warehouse_list'][$warehouse['id_warehouse']] = $warehouse['id_warehouse']; + if (!isset($warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']])) { + $warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']] = 0; + } + + $warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']]++; + } + } + unset($product); + + arsort($warehouse_count_by_address); + + // Step 2 : Group product by warehouse + $grouped_by_warehouse = array(); + + foreach ($product_list as &$product) { + if (!isset($grouped_by_warehouse[$product['id_address_delivery']])) { + $grouped_by_warehouse[$product['id_address_delivery']] = array( + 'in_stock' => array(), + 'out_of_stock' => array(), + ); + } + + $product['carrier_list'] = array(); + $id_warehouse = 0; + foreach ($warehouse_count_by_address[$product['id_address_delivery']] as $id_war => $val) { + if (array_key_exists((int)$id_war, $product['warehouse_list'])) { + $product['carrier_list'] = Tools::array_replace($product['carrier_list'], Carrier::getAvailableCarrierList(new Product($product['id_product']), $id_war, $product['id_address_delivery'], null, $this)); + if (!$id_warehouse) { + $id_warehouse = (int)$id_war; + } + } + } + + if (!isset($grouped_by_warehouse[$product['id_address_delivery']]['in_stock'][$id_warehouse])) { + $grouped_by_warehouse[$product['id_address_delivery']]['in_stock'][$id_warehouse] = array(); + $grouped_by_warehouse[$product['id_address_delivery']]['out_of_stock'][$id_warehouse] = array(); + } + + if (!$this->allow_seperated_package) { + $key = 'in_stock'; + } else { + $key = $product['in_stock'] ? 'in_stock' : 'out_of_stock'; + $product_quantity_in_stock = StockAvailable::getQuantityAvailableByProduct($product['id_product'], $product['id_product_attribute']); + if ($product['in_stock'] && $product['cart_quantity'] > $product_quantity_in_stock) { + $out_stock_part = $product['cart_quantity'] - $product_quantity_in_stock; + $product_bis = $product; + $product_bis['cart_quantity'] = $out_stock_part; + $product_bis['in_stock'] = 0; + $product['cart_quantity'] -= $out_stock_part; + $grouped_by_warehouse[$product['id_address_delivery']]['out_of_stock'][$id_warehouse][] = $product_bis; + } + } + + if (empty($product['carrier_list'])) { + $product['carrier_list'] = array(0 => 0); + } + + $grouped_by_warehouse[$product['id_address_delivery']][$key][$id_warehouse][] = $product; + } + unset($product); + + // Step 3 : grouped product from grouped_by_warehouse by available carriers + $grouped_by_carriers = array(); + foreach ($grouped_by_warehouse as $id_address_delivery => $products_in_stock_list) { + if (!isset($grouped_by_carriers[$id_address_delivery])) { + $grouped_by_carriers[$id_address_delivery] = array( + 'in_stock' => array(), + 'out_of_stock' => array(), + ); + } + foreach ($products_in_stock_list as $key => $warehouse_list) { + if (!isset($grouped_by_carriers[$id_address_delivery][$key])) { + $grouped_by_carriers[$id_address_delivery][$key] = array(); + } + foreach ($warehouse_list as $id_warehouse => $product_list) { + if (!isset($grouped_by_carriers[$id_address_delivery][$key][$id_warehouse])) { + $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse] = array(); + } + foreach ($product_list as $product) { + $package_carriers_key = implode(',', $product['carrier_list']); + + if (!isset($grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key])) { + $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key] = array( + 'product_list' => array(), + 'carrier_list' => $product['carrier_list'], + 'warehouse_list' => $product['warehouse_list'] + ); + } + + $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key]['product_list'][] = $product; + } + } + } + } + + $package_list = array(); + // Step 4 : merge product from grouped_by_carriers into $package to minimize the number of package + foreach ($grouped_by_carriers as $id_address_delivery => $products_in_stock_list) { + if (!isset($package_list[$id_address_delivery])) { + $package_list[$id_address_delivery] = array( + 'in_stock' => array(), + 'out_of_stock' => array(), + ); + } + + foreach ($products_in_stock_list as $key => $warehouse_list) { + if (!isset($package_list[$id_address_delivery][$key])) { + $package_list[$id_address_delivery][$key] = array(); + } + // Count occurance of each carriers to minimize the number of packages + $carrier_count = array(); + foreach ($warehouse_list as $id_warehouse => $products_grouped_by_carriers) { + foreach ($products_grouped_by_carriers as $data) { + foreach ($data['carrier_list'] as $id_carrier) { + if (!isset($carrier_count[$id_carrier])) { + $carrier_count[$id_carrier] = 0; + } + $carrier_count[$id_carrier]++; + } + } + } + arsort($carrier_count); + foreach ($warehouse_list as $id_warehouse => $products_grouped_by_carriers) { + if (!isset($package_list[$id_address_delivery][$key][$id_warehouse])) { + $package_list[$id_address_delivery][$key][$id_warehouse] = array(); + } + foreach ($products_grouped_by_carriers as $data) { + foreach ($carrier_count as $id_carrier => $rate) { + if (array_key_exists($id_carrier, $data['carrier_list'])) { + if (!isset($package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier])) { + $package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier] = array( + 'carrier_list' => $data['carrier_list'], + 'warehouse_list' => $data['warehouse_list'], + 'product_list' => array(), + ); + } + $package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['carrier_list'] = + array_intersect($package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['carrier_list'], $data['carrier_list']); + $package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['product_list'] = + array_merge($package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['product_list'], $data['product_list']); + + break; + } + } + } + } + } + } + + // Step 5 : Reduce depth of $package_list + $final_package_list = array(); + foreach ($package_list as $id_address_delivery => $products_in_stock_list) { + if (!isset($final_package_list[$id_address_delivery])) { + $final_package_list[$id_address_delivery] = array(); + } + + foreach ($products_in_stock_list as $key => $warehouse_list) { + foreach ($warehouse_list as $id_warehouse => $products_grouped_by_carriers) { + foreach ($products_grouped_by_carriers as $data) { + $final_package_list[$id_address_delivery][] = array( + 'product_list' => $data['product_list'], + 'carrier_list' => $data['carrier_list'], + 'warehouse_list' => $data['warehouse_list'], + 'id_warehouse' => $id_warehouse, + ); + } + } + } + } + $cache[$cache_key] = $final_package_list; + return $final_package_list; + } + + public function getPackageIdWarehouse($package, $id_carrier = null) + { + if ($id_carrier === null) { + if (isset($package['id_carrier'])) { + $id_carrier = (int)$package['id_carrier']; + } + } + + if ($id_carrier == null) { + return $package['id_warehouse']; + } + + foreach ($package['warehouse_list'] as $id_warehouse) { + $warehouse = new Warehouse((int)$id_warehouse); + $available_warehouse_carriers = $warehouse->getCarriers(); + if (in_array($id_carrier, $available_warehouse_carriers)) { + return (int)$id_warehouse; + } + } + return 0; + } + + /** + * Get all deliveries options available for the current cart + * @param Country $default_country + * @param bool $flush Force flushing cache + * + * @return array array( + * 0 => array( // First address + * '12,' => array( // First delivery option available for this address + * carrier_list => array( + * 12 => array( // First carrier for this option + * 'instance' => Carrier Object, + * 'logo' => , + * 'price_with_tax' => 12.4, + * 'price_without_tax' => 12.4, + * 'package_list' => array( + * 1, + * 3, + * ), + * ), + * ), + * is_best_grade => true, // Does this option have the biggest grade (quick shipping) for this shipping address + * is_best_price => true, // Does this option have the lower price for this shipping address + * unique_carrier => true, // Does this option use a unique carrier + * total_price_with_tax => 12.5, + * total_price_without_tax => 12.5, + * position => 5, // Average of the carrier position + * ), + * ), + * ); + * If there are no carriers available for an address, return an empty array + */ + public function getDeliveryOptionList(Country $default_country = null, $flush = false) + { + static $cache = array(); + if (isset($cache[$this->id]) && !$flush) { + return $cache[$this->id]; + } + + $delivery_option_list = array(); + $carriers_price = array(); + $carrier_collection = array(); + $package_list = $this->getPackageList($flush); + + // Foreach addresses + foreach ($package_list as $id_address => $packages) { + // Initialize vars + $delivery_option_list[$id_address] = array(); + $carriers_price[$id_address] = array(); + $common_carriers = null; + $best_price_carriers = array(); + $best_grade_carriers = array(); + $carriers_instance = array(); + + // Get country + if ($id_address) { + $address = new Address($id_address); + $country = new Country($address->id_country); + } else { + $country = $default_country; + } + + // Foreach packages, get the carriers with best price, best position and best grade + foreach ($packages as $id_package => $package) { + // No carriers available + if (count($packages) == 1 && count($package['carrier_list']) == 1 && current($package['carrier_list']) == 0) { + $cache[$this->id] = array(); + return $cache[$this->id]; + } + + $carriers_price[$id_address][$id_package] = array(); + + // Get all common carriers for each packages to the same address + if (is_null($common_carriers)) { + $common_carriers = $package['carrier_list']; + } else { + $common_carriers = array_intersect($common_carriers, $package['carrier_list']); + } + + $best_price = null; + $best_price_carrier = null; + $best_grade = null; + $best_grade_carrier = null; + + // Foreach carriers of the package, calculate his price, check if it the best price, position and grade + foreach ($package['carrier_list'] as $id_carrier) { + if (!isset($carriers_instance[$id_carrier])) { + $carriers_instance[$id_carrier] = new Carrier($id_carrier); + } + + $price_with_tax = $this->getPackageShippingCost($id_carrier, true, $country, $package['product_list']); + $price_without_tax = $this->getPackageShippingCost($id_carrier, false, $country, $package['product_list']); + if (is_null($best_price) || $price_with_tax < $best_price) { + $best_price = $price_with_tax; + $best_price_carrier = $id_carrier; + } + $carriers_price[$id_address][$id_package][$id_carrier] = array( + 'without_tax' => $price_without_tax, + 'with_tax' => $price_with_tax); + + $grade = $carriers_instance[$id_carrier]->grade; + if (is_null($best_grade) || $grade > $best_grade) { + $best_grade = $grade; + $best_grade_carrier = $id_carrier; + } + } + + $best_price_carriers[$id_package] = $best_price_carrier; + $best_grade_carriers[$id_package] = $best_grade_carrier; + } + + // Reset $best_price_carrier, it's now an array + $best_price_carrier = array(); + $key = ''; + + // Get the delivery option with the lower price + foreach ($best_price_carriers as $id_package => $id_carrier) { + $key .= $id_carrier.','; + if (!isset($best_price_carrier[$id_carrier])) { + $best_price_carrier[$id_carrier] = array( + 'price_with_tax' => 0, + 'price_without_tax' => 0, + 'package_list' => array(), + 'product_list' => array(), + ); + } + $best_price_carrier[$id_carrier]['price_with_tax'] += $carriers_price[$id_address][$id_package][$id_carrier]['with_tax']; + $best_price_carrier[$id_carrier]['price_without_tax'] += $carriers_price[$id_address][$id_package][$id_carrier]['without_tax']; + $best_price_carrier[$id_carrier]['package_list'][] = $id_package; + $best_price_carrier[$id_carrier]['product_list'] = array_merge($best_price_carrier[$id_carrier]['product_list'], $packages[$id_package]['product_list']); + $best_price_carrier[$id_carrier]['instance'] = $carriers_instance[$id_carrier]; + $real_best_price = !isset($real_best_price) || $real_best_price > $carriers_price[$id_address][$id_package][$id_carrier]['with_tax'] ? + $carriers_price[$id_address][$id_package][$id_carrier]['with_tax'] : $real_best_price; + $real_best_price_wt = !isset($real_best_price_wt) || $real_best_price_wt > $carriers_price[$id_address][$id_package][$id_carrier]['without_tax'] ? + $carriers_price[$id_address][$id_package][$id_carrier]['without_tax'] : $real_best_price_wt; + } + + // Add the delivery option with best price as best price + $delivery_option_list[$id_address][$key] = array( + 'carrier_list' => $best_price_carrier, + 'is_best_price' => true, + 'is_best_grade' => false, + 'unique_carrier' => (count($best_price_carrier) <= 1) + ); + + // Reset $best_grade_carrier, it's now an array + $best_grade_carrier = array(); + $key = ''; + + // Get the delivery option with the best grade + foreach ($best_grade_carriers as $id_package => $id_carrier) { + $key .= $id_carrier.','; + if (!isset($best_grade_carrier[$id_carrier])) { + $best_grade_carrier[$id_carrier] = array( + 'price_with_tax' => 0, + 'price_without_tax' => 0, + 'package_list' => array(), + 'product_list' => array(), + ); + } + $best_grade_carrier[$id_carrier]['price_with_tax'] += $carriers_price[$id_address][$id_package][$id_carrier]['with_tax']; + $best_grade_carrier[$id_carrier]['price_without_tax'] += $carriers_price[$id_address][$id_package][$id_carrier]['without_tax']; + $best_grade_carrier[$id_carrier]['package_list'][] = $id_package; + $best_grade_carrier[$id_carrier]['product_list'] = array_merge($best_grade_carrier[$id_carrier]['product_list'], $packages[$id_package]['product_list']); + $best_grade_carrier[$id_carrier]['instance'] = $carriers_instance[$id_carrier]; + } + + // Add the delivery option with best grade as best grade + if (!isset($delivery_option_list[$id_address][$key])) { + $delivery_option_list[$id_address][$key] = array( + 'carrier_list' => $best_grade_carrier, + 'is_best_price' => false, + 'unique_carrier' => (count($best_grade_carrier) <= 1) + ); + } + $delivery_option_list[$id_address][$key]['is_best_grade'] = true; + + // Get all delivery options with a unique carrier + foreach ($common_carriers as $id_carrier) { + $key = ''; + $package_list = array(); + $product_list = array(); + $price_with_tax = 0; + $price_without_tax = 0; + + foreach ($packages as $id_package => $package) { + $key .= $id_carrier.','; + $price_with_tax += $carriers_price[$id_address][$id_package][$id_carrier]['with_tax']; + $price_without_tax += $carriers_price[$id_address][$id_package][$id_carrier]['without_tax']; + $package_list[] = $id_package; + $product_list = array_merge($product_list, $package['product_list']); + } + + if (!isset($delivery_option_list[$id_address][$key])) { + $delivery_option_list[$id_address][$key] = array( + 'is_best_price' => false, + 'is_best_grade' => false, + 'unique_carrier' => true, + 'carrier_list' => array( + $id_carrier => array( + 'price_with_tax' => $price_with_tax, + 'price_without_tax' => $price_without_tax, + 'instance' => $carriers_instance[$id_carrier], + 'package_list' => $package_list, + 'product_list' => $product_list, + ) + ) + ); + } else { + $delivery_option_list[$id_address][$key]['unique_carrier'] = (count($delivery_option_list[$id_address][$key]['carrier_list']) <= 1); + } + } + } + + $cart_rules = CartRule::getCustomerCartRules(Context::getContext()->cookie->id_lang, Context::getContext()->cookie->id_customer, true, true, false, $this, true); + + $result = false; + if ($this->id) { + $result = Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'cart_cart_rule WHERE id_cart = '.(int)$this->id); + } + + $cart_rules_in_cart = array(); + + if (is_array($result)) { + foreach ($result as $row) { + $cart_rules_in_cart[] = $row['id_cart_rule']; + } + } + + $total_products_wt = $this->getOrderTotal(true, Cart::ONLY_PRODUCTS); + $total_products = $this->getOrderTotal(false, Cart::ONLY_PRODUCTS); + + $free_carriers_rules = array(); + + $context = Context::getContext(); + foreach ($cart_rules as $cart_rule) { + $total_price = $cart_rule['minimum_amount_tax'] ? $total_products_wt : $total_products; + $total_price += $cart_rule['minimum_amount_tax'] && $cart_rule['minimum_amount_shipping'] ? $real_best_price : 0; + $total_price += !$cart_rule['minimum_amount_tax'] && $cart_rule['minimum_amount_shipping'] ? $real_best_price_wt : 0; + if ($cart_rule['free_shipping'] && $cart_rule['carrier_restriction'] + && in_array($cart_rule['id_cart_rule'], $cart_rules_in_cart) + && $cart_rule['minimum_amount'] <= $total_price) { + $cr = new CartRule((int)$cart_rule['id_cart_rule']); + if (Validate::isLoadedObject($cr) && + $cr->checkValidity($context, in_array((int)$cart_rule['id_cart_rule'], $cart_rules_in_cart), false, false)) { + $carriers = $cr->getAssociatedRestrictions('carrier', true, false); + if (is_array($carriers) && count($carriers) && isset($carriers['selected'])) { + foreach ($carriers['selected'] as $carrier) { + if (isset($carrier['id_carrier']) && $carrier['id_carrier']) { + $free_carriers_rules[] = (int)$carrier['id_carrier']; + } + } + } + } + } + } + + // For each delivery options : + // - Set the carrier list + // - Calculate the price + // - Calculate the average position + foreach ($delivery_option_list as $id_address => $delivery_option) { + foreach ($delivery_option as $key => $value) { + $total_price_with_tax = 0; + $total_price_without_tax = 0; + $position = 0; + foreach ($value['carrier_list'] as $id_carrier => $data) { + $total_price_with_tax += $data['price_with_tax']; + $total_price_without_tax += $data['price_without_tax']; + $total_price_without_tax_with_rules = (in_array($id_carrier, $free_carriers_rules)) ? 0 : $total_price_without_tax; + + if (!isset($carrier_collection[$id_carrier])) { + $carrier_collection[$id_carrier] = new Carrier($id_carrier); + } + $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['instance'] = $carrier_collection[$id_carrier]; + + if (file_exists(_PS_SHIP_IMG_DIR_.$id_carrier.'.jpg')) { + $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['logo'] = _THEME_SHIP_DIR_.$id_carrier.'.jpg'; + } else { + $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['logo'] = false; + } + + $position += $carrier_collection[$id_carrier]->position; + } + $delivery_option_list[$id_address][$key]['total_price_with_tax'] = $total_price_with_tax; + $delivery_option_list[$id_address][$key]['total_price_without_tax'] = $total_price_without_tax; + $delivery_option_list[$id_address][$key]['is_free'] = !$total_price_without_tax_with_rules ? true : false; + $delivery_option_list[$id_address][$key]['position'] = $position / count($value['carrier_list']); + } + } + + // Sort delivery option list + foreach ($delivery_option_list as &$array) { + uasort($array, array('Cart', 'sortDeliveryOptionList')); + } + + $cache[$this->id] = $delivery_option_list; + return $cache[$this->id]; + } + + /** + * + * Sort list of option delivery by parameters define in the BO + * @param $option1 + * @param $option2 + * @return int -1 if $option 1 must be placed before and 1 if the $option1 must be placed after the $option2 + */ + public static function sortDeliveryOptionList($option1, $option2) + { + static $order_by_price = null; + static $order_way = null; + if (is_null($order_by_price)) { + $order_by_price = !Configuration::get('PS_CARRIER_DEFAULT_SORT'); + } + if (is_null($order_way)) { + $order_way = Configuration::get('PS_CARRIER_DEFAULT_ORDER'); + } + + if ($order_by_price) { + if ($order_way) { + return ($option1['total_price_with_tax'] < $option2['total_price_with_tax']) * 2 - 1; + } // return -1 or 1 + else { + return ($option1['total_price_with_tax'] >= $option2['total_price_with_tax']) * 2 - 1; + } + } // return -1 or 1 + elseif ($order_way) { + return ($option1['position'] < $option2['position']) * 2 - 1; + } // return -1 or 1 + else { + return ($option1['position'] >= $option2['position']) * 2 - 1; + } // return -1 or 1 + } + + public function carrierIsSelected($id_carrier, $id_address) + { + $delivery_option = $this->getDeliveryOption(); + $delivery_option_list = $this->getDeliveryOptionList(); + + if (!isset($delivery_option[$id_address])) { + return false; + } + + if (!isset($delivery_option_list[$id_address][$delivery_option[$id_address]])) { + return false; + } + + if (!in_array($id_carrier, array_keys($delivery_option_list[$id_address][$delivery_option[$id_address]]['carrier_list']))) { + return false; + } + + return true; + } + + /** + * Get all deliveries options available for the current cart formated like Carriers::getCarriersForOrder + * This method was wrote for retrocompatibility with 1.4 theme + * New theme need to use Cart::getDeliveryOptionList() to generate carriers option in the checkout process + * + * @since 1.5.0 + * + * @param Country $default_country + * @param bool $flush Force flushing cache + * + */ + public function simulateCarriersOutput(Country $default_country = null, $flush = false) + { + $delivery_option_list = $this->getDeliveryOptionList($default_country, $flush); + + // This method cannot work if there is multiple address delivery + if (count($delivery_option_list) > 1 || empty($delivery_option_list)) { + return array(); + } + + $carriers = array(); + foreach (reset($delivery_option_list) as $key => $option) { + $price = $option['total_price_with_tax']; + $price_tax_exc = $option['total_price_without_tax']; + $name = $img = $delay = ''; + + if ($option['unique_carrier']) { + $carrier = reset($option['carrier_list']); + if (isset($carrier['instance'])) { + $name = $carrier['instance']->name; + $delay = $carrier['instance']->delay; + $delay = isset($delay[Context::getContext()->language->id]) ? + $delay[Context::getContext()->language->id] : $delay[(int)Configuration::get('PS_LANG_DEFAULT')]; + } + if (isset($carrier['logo'])) { + $img = $carrier['logo']; + } + } else { + $nameList = array(); + foreach ($option['carrier_list'] as $carrier) { + $nameList[] = $carrier['instance']->name; + } + $name = join(' -', $nameList); + $img = ''; // No images if multiple carriers + $delay = ''; + } + $carriers[] = array( + 'name' => $name, + 'img' => $img, + 'delay' => $delay, + 'price' => $price, + 'price_tax_exc' => $price_tax_exc, + 'id_carrier' => Cart::intifier($key), // Need to translate to an integer for retrocompatibility reason, in 1.4 template we used intval + 'is_module' => false, + ); + } + return $carriers; + } + + public function simulateCarrierSelectedOutput($use_cache = true) + { + $delivery_option = $this->getDeliveryOption(null, false, $use_cache); + + if (count($delivery_option) > 1 || empty($delivery_option)) { + return 0; + } + + return Cart::intifier(reset($delivery_option)); + } + + /** + * Translate a string option_delivery identifier ('24,3,') in a int (3240002000) + * + * The option_delivery identifier is a list of integers separated by a ','. + * This method replace the delimiter by a sequence of '0'. + * The size of this sequence is fixed by the first digit of the return + * + * @return int + */ + public static function intifier($string, $delimiter = ',') + { + $elm = explode($delimiter, $string); + $max = max($elm); + return strlen($max).implode(str_repeat('0', strlen($max) + 1), $elm); + } + + /** + * Translate a int option_delivery identifier (3240002000) in a string ('24,3,') + */ + public static function desintifier($int, $delimiter = ',') + { + $delimiter_len = $int[0]; + $int = strrev(substr($int, 1)); + $elm = explode(str_repeat('0', $delimiter_len + 1), $int); + return strrev(implode($delimiter, $elm)); + } + + /** + * Does the cart use multiple address + * @return bool + */ + public function isMultiAddressDelivery() + { + static $cache = array(); + + if (!isset($cache[$this->id])) { + $sql = new DbQuery(); + $sql->select('count(distinct id_address_delivery)'); + $sql->from('cart_product', 'cp'); + $sql->where('id_cart = '.(int)$this->id); + + $cache[$this->id] = Db::getInstance()->getValue($sql) > 1; + } + return $cache[$this->id]; + } + + /** + * Get all delivery addresses object for the current cart + */ + public function getAddressCollection() + { + $collection = array(); + $cache_id = 'Cart::getAddressCollection'.(int)$this->id; + if (!Cache::isStored($cache_id)) { + $result = Db::getInstance()->executeS( + 'SELECT DISTINCT `id_address_delivery` FROM `'._DB_PREFIX_.'cart_product` WHERE id_cart = '.(int)$this->id - ); - Cache::store($cache_id, $result); - } - else - $result = Cache::retrieve($cache_id); - - $result[] = array('id_address_delivery' => (int)$this->id_address_delivery); - - foreach ($result as $row) - if ((int)$row['id_address_delivery'] != 0) - $collection[(int)$row['id_address_delivery']] = new Address((int)$row['id_address_delivery']); - return $collection; - } - - /** - * Set the delivery option and id_carrier, if there is only one carrier - */ - public function setDeliveryOption($delivery_option = null) - { - if (empty($delivery_option) || count($delivery_option) == 0) - { - $this->delivery_option = ''; - $this->id_carrier = 0; - return; - } - Cache::clean('getContextualValue_*'); - $delivery_option_list = $this->getDeliveryOptionList(null, true); - - foreach ($delivery_option_list as $id_address => $options) - if (!isset($delivery_option[$id_address])) - foreach ($options as $key => $option) - if ($option['is_best_price']) - { - $delivery_option[$id_address] = $key; - break; - } - - if (count($delivery_option) == 1) - $this->id_carrier = $this->getIdCarrierFromDeliveryOption($delivery_option); - - $this->delivery_option = serialize($delivery_option); - } - - protected function getIdCarrierFromDeliveryOption($delivery_option) - { - $delivery_option_list = $this->getDeliveryOptionList(); - foreach ($delivery_option as $key => $value) - if (isset($delivery_option_list[$key]) && isset($delivery_option_list[$key][$value])) - if (count($delivery_option_list[$key][$value]['carrier_list']) == 1) - return current(array_keys($delivery_option_list[$key][$value]['carrier_list'])); - - return 0; - } - - /** - * Get the delivery option selected, or if no delivery option was selected, - * the cheapest option for each address - * - * @param Country|null $default_country - * @param bool $dontAutoSelectOptions - * @param bool $use_cache - * - * @return array|bool|mixed Delivery option - */ - public function getDeliveryOption($default_country = null, $dontAutoSelectOptions = false, $use_cache = true) - { - static $cache = array(); - $cache_id = (int)(is_object($default_country) ? $default_country->id : 0).'-'.(int)$dontAutoSelectOptions; - if (isset($cache[$cache_id]) && $use_cache) - return $cache[$cache_id]; - - $delivery_option_list = $this->getDeliveryOptionList($default_country); - - // The delivery option was selected - if (isset($this->delivery_option) && $this->delivery_option != '') - { - $delivery_option = Tools::unSerialize($this->delivery_option); - $validated = true; - foreach ($delivery_option as $id_address => $key) - if (!isset($delivery_option_list[$id_address][$key])) - { - $validated = false; - break; - } - - if ($validated) - { - $cache[$cache_id] = $delivery_option; - return $delivery_option; - } - } - - if ($dontAutoSelectOptions) - return false; - - // No delivery option selected or delivery option selected is not valid, get the better for all options - $delivery_option = array(); - foreach ($delivery_option_list as $id_address => $options) - { - foreach ($options as $key => $option) - if (Configuration::get('PS_CARRIER_DEFAULT') == -1 && $option['is_best_price']) - { - $delivery_option[$id_address] = $key; - break; - } - elseif (Configuration::get('PS_CARRIER_DEFAULT') == -2 && $option['is_best_grade']) - { - $delivery_option[$id_address] = $key; - break; - } - elseif ($option['unique_carrier'] && in_array(Configuration::get('PS_CARRIER_DEFAULT'), array_keys($option['carrier_list']))) - { - $delivery_option[$id_address] = $key; - break; - } - - reset($options); - if (!isset($delivery_option[$id_address])) - $delivery_option[$id_address] = key($options); - } - - $cache[$cache_id] = $delivery_option; - - return $delivery_option; - } - - /** - * Return shipping total for the cart - * - * @param array|null $delivery_option Array of the delivery option for each address - * @param bool $use_tax - * @param Country|null $default_country - * @return float Shipping total - */ - public function getTotalShippingCost($delivery_option = null, $use_tax = true, Country $default_country = null) - { - if (isset(Context::getContext()->cookie->id_country)) - $default_country = new Country(Context::getContext()->cookie->id_country); - if (is_null($delivery_option)) - $delivery_option = $this->getDeliveryOption($default_country, false, false); - - $total_shipping = 0; - $delivery_option_list = $this->getDeliveryOptionList($default_country); - foreach ($delivery_option as $id_address => $key) - { - if (!isset($delivery_option_list[$id_address]) || !isset($delivery_option_list[$id_address][$key])) - continue; - if ($delivery_option_list[$id_address][$key]['is_free']) - $total_shipping += 0; - elseif ($use_tax) - $total_shipping += $delivery_option_list[$id_address][$key]['total_price_with_tax']; - else - $total_shipping += $delivery_option_list[$id_address][$key]['total_price_without_tax']; - } - - return $total_shipping; - } - - /** - * Return shipping total of a specific carriers for the cart - * - * @param int $id_carrier - * @param array $delivery_option Array of the delivery option for each address - * @param bool $useTax - * @param Country|null $default_country - * @param array|null $delivery_option - * @return float Shipping total - */ - public function getCarrierCost($id_carrier, $useTax = true, Country $default_country = null, $delivery_option = null) - { - if (is_null($delivery_option)) - $delivery_option = $this->getDeliveryOption($default_country); - - $total_shipping = 0; - $delivery_option_list = $this->getDeliveryOptionList(); - - - foreach ($delivery_option as $id_address => $key) - { - if (!isset($delivery_option_list[$id_address]) || !isset($delivery_option_list[$id_address][$key])) - continue; - if (isset($delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier])) - { - if ($useTax) - $total_shipping += $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['price_with_tax']; - else - $total_shipping += $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['price_without_tax']; - } - } - - return $total_shipping; - } - - /** - * @deprecated 1.5.0, use Cart->getPackageShippingCost() - */ - public function getOrderShippingCost($id_carrier = null, $use_tax = true, Country $default_country = null, $product_list = null) - { - Tools::displayAsDeprecated(); - return $this->getPackageShippingCost($id_carrier, $use_tax, $default_country, $product_list); - } - - /** - * Return package shipping cost - * - * @param int $id_carrier Carrier ID (default : current carrier) - * @param bool $use_tax - * @param Country|null $default_country - * @param array|null $product_list List of product concerned by the shipping. - * If null, all the product of the cart are used to calculate the shipping cost - * @param int|null $id_zone - * - * @return float Shipping total - */ - public function getPackageShippingCost($id_carrier = null, $use_tax = true, Country $default_country = null, $product_list = null, $id_zone = null) - { - if ($this->isVirtualCart()) - return 0; - - if (!$default_country) - $default_country = Context::getContext()->country; - - if (!is_null($product_list)) - foreach ($product_list as $key => $value) - if ($value['is_virtual'] == 1) - unset($product_list[$key]); - - if (is_null($product_list)) - $products = $this->getProducts(); - else - $products = $product_list; - - if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_invoice') - $address_id = (int)$this->id_address_invoice; - elseif (count($product_list)) - { - $prod = current($product_list); - $address_id = (int)$prod['id_address_delivery']; - } - else - $address_id = null; - if (!Address::addressExists($address_id)) - $address_id = null; - - $cache_id = 'getPackageShippingCost_'.(int)$this->id.'_'.(int)$address_id.'_'.(int)$id_carrier.'_'.(int)$use_tax.'_'.(int)$default_country->id; - if ($products) - foreach ($products as $product) - $cache_id .= '_'.(int)$product['id_product'].'_'.(int)$product['id_product_attribute']; - - if (Cache::isStored($cache_id)) - return Cache::retrieve($cache_id); - - // Order total in default currency without fees - $order_total = $this->getOrderTotal(true, Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING, $product_list); - - // Start with shipping cost at 0 - $shipping_cost = 0; - // If no product added, return 0 - if (!count($products)) - { - Cache::store($cache_id, $shipping_cost); - return $shipping_cost; - } - - if (!isset($id_zone)) - { - // Get id zone - if (!$this->isMultiAddressDelivery() - && isset($this->id_address_delivery) // Be carefull, id_address_delivery is not usefull one 1.5 - && $this->id_address_delivery - && Customer::customerHasAddress($this->id_customer, $this->id_address_delivery - )) - $id_zone = Address::getZoneById((int)$this->id_address_delivery); - else - { - if (!Validate::isLoadedObject($default_country)) - $default_country = new Country(Configuration::get('PS_COUNTRY_DEFAULT'), Configuration::get('PS_LANG_DEFAULT')); - - $id_zone = (int)$default_country->id_zone; - } - } - - if ($id_carrier && !$this->isCarrierInRange((int)$id_carrier, (int)$id_zone)) - $id_carrier = ''; - - if (empty($id_carrier) && $this->isCarrierInRange((int)Configuration::get('PS_CARRIER_DEFAULT'), (int)$id_zone)) - $id_carrier = (int)Configuration::get('PS_CARRIER_DEFAULT'); - - $total_package_without_shipping_tax_inc = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, $product_list); - if (empty($id_carrier)) - { - if ((int)$this->id_customer) - { - $customer = new Customer((int)$this->id_customer); - $result = Carrier::getCarriers((int)Configuration::get('PS_LANG_DEFAULT'), true, false, (int)$id_zone, $customer->getGroups()); - unset($customer); - } - else - $result = Carrier::getCarriers((int)Configuration::get('PS_LANG_DEFAULT'), true, false, (int)$id_zone); - - foreach ($result as $k => $row) - { - if ($row['id_carrier'] == Configuration::get('PS_CARRIER_DEFAULT')) - continue; - - if (!isset(self::$_carriers[$row['id_carrier']])) - self::$_carriers[$row['id_carrier']] = new Carrier((int)$row['id_carrier']); - - /** @var Carrier $carrier */ - $carrier = self::$_carriers[$row['id_carrier']]; - - $shipping_method = $carrier->getShippingMethod(); - // Get only carriers that are compliant with shipping method - if (($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && $carrier->getMaxDeliveryPriceByWeight((int)$id_zone) === false) - || ($shipping_method == Carrier::SHIPPING_METHOD_PRICE && $carrier->getMaxDeliveryPriceByPrice((int)$id_zone) === false)) - { - unset($result[$k]); - continue; - } - - // If out-of-range behavior carrier is set on "Desactivate carrier" - if ($row['range_behavior']) - { - $check_delivery_price_by_weight = Carrier::checkDeliveryPriceByWeight($row['id_carrier'], $this->getTotalWeight(), (int)$id_zone); - - $total_order = $total_package_without_shipping_tax_inc; - $check_delivery_price_by_price = Carrier::checkDeliveryPriceByPrice($row['id_carrier'], $total_order, (int)$id_zone, (int)$this->id_currency); - - // Get only carriers that have a range compatible with cart - if (($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && !$check_delivery_price_by_weight) - || ($shipping_method == Carrier::SHIPPING_METHOD_PRICE && !$check_delivery_price_by_price)) - { - unset($result[$k]); - continue; - } - } - - if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) - $shipping = $carrier->getDeliveryPriceByWeight($this->getTotalWeight($product_list), (int)$id_zone); - else - $shipping = $carrier->getDeliveryPriceByPrice($order_total, (int)$id_zone, (int)$this->id_currency); - - if (!isset($min_shipping_price)) - $min_shipping_price = $shipping; - - if ($shipping <= $min_shipping_price) - { - $id_carrier = (int)$row['id_carrier']; - $min_shipping_price = $shipping; - } - } - } - - if (empty($id_carrier)) - $id_carrier = Configuration::get('PS_CARRIER_DEFAULT'); - - if (!isset(self::$_carriers[$id_carrier])) - self::$_carriers[$id_carrier] = new Carrier((int)$id_carrier, Configuration::get('PS_LANG_DEFAULT')); - - $carrier = self::$_carriers[$id_carrier]; - - // No valid Carrier or $id_carrier <= 0 ? - if (!Validate::isLoadedObject($carrier)) - { - Cache::store($cache_id, 0); - return 0; - } - $shipping_method = $carrier->getShippingMethod(); - - if (!$carrier->active) - { - Cache::store($cache_id, $shipping_cost); - return $shipping_cost; - } - - // Free fees if free carrier - if ($carrier->is_free == 1) - { - Cache::store($cache_id, 0); - return 0; - } - - // Select carrier tax - if ($use_tax && !Tax::excludeTaxeOption()) - { - $address = Address::initialize((int)$address_id); - - if (Configuration::get('PS_ATCP_SHIPWRAP')) - { - // With PS_ATCP_SHIPWRAP, pre-tax price is deduced - // from post tax price, so no $carrier_tax here - // even though it sounds weird. - $carrier_tax = 0; - } - else - { - $carrier_tax = $carrier->getTaxesRate($address); - } - - } - - $configuration = Configuration::getMultiple(array( - 'PS_SHIPPING_FREE_PRICE', - 'PS_SHIPPING_HANDLING', - 'PS_SHIPPING_METHOD', - 'PS_SHIPPING_FREE_WEIGHT' - )); - - // Free fees - $free_fees_price = 0; - if (isset($configuration['PS_SHIPPING_FREE_PRICE'])) - $free_fees_price = Tools::convertPrice((float)$configuration['PS_SHIPPING_FREE_PRICE'], Currency::getCurrencyInstance((int)$this->id_currency)); - $orderTotalwithDiscounts = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, null, null, false); - if ($orderTotalwithDiscounts >= (float)($free_fees_price) && (float)($free_fees_price) > 0) - { - Cache::store($cache_id, $shipping_cost); - return $shipping_cost; - } - - if (isset($configuration['PS_SHIPPING_FREE_WEIGHT']) - && $this->getTotalWeight() >= (float)$configuration['PS_SHIPPING_FREE_WEIGHT'] - && (float)$configuration['PS_SHIPPING_FREE_WEIGHT'] > 0) - { - Cache::store($cache_id, $shipping_cost); - return $shipping_cost; - } - - // Get shipping cost using correct method - if ($carrier->range_behavior) - { - if (!isset($id_zone)) - { - // Get id zone - if (isset($this->id_address_delivery) - && $this->id_address_delivery - && Customer::customerHasAddress($this->id_customer, $this->id_address_delivery)) - $id_zone = Address::getZoneById((int)$this->id_address_delivery); - else - $id_zone = (int)$default_country->id_zone; - } - - if (($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && !Carrier::checkDeliveryPriceByWeight($carrier->id, $this->getTotalWeight(), (int)$id_zone)) - || ($shipping_method == Carrier::SHIPPING_METHOD_PRICE && !Carrier::checkDeliveryPriceByPrice($carrier->id, $total_package_without_shipping_tax_inc, $id_zone, (int)$this->id_currency) - )) - $shipping_cost += 0; - else - { - if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) - $shipping_cost += $carrier->getDeliveryPriceByWeight($this->getTotalWeight($product_list), $id_zone); - else // by price - $shipping_cost += $carrier->getDeliveryPriceByPrice($order_total, $id_zone, (int)$this->id_currency); - } - } - else - { - if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) - $shipping_cost += $carrier->getDeliveryPriceByWeight($this->getTotalWeight($product_list), $id_zone); - else - $shipping_cost += $carrier->getDeliveryPriceByPrice($order_total, $id_zone, (int)$this->id_currency); - - } - // Adding handling charges - if (isset($configuration['PS_SHIPPING_HANDLING']) && $carrier->shipping_handling) - $shipping_cost += (float)$configuration['PS_SHIPPING_HANDLING']; - - // Additional Shipping Cost per product - foreach ($products as $product) - if (!$product['is_virtual']) - $shipping_cost += $product['additional_shipping_cost'] * $product['cart_quantity']; - - $shipping_cost = Tools::convertPrice($shipping_cost, Currency::getCurrencyInstance((int)$this->id_currency)); - - //get external shipping cost from module - if ($carrier->shipping_external) - { - $module_name = $carrier->external_module_name; - - /** @var CarrierModule $module */ - $module = Module::getInstanceByName($module_name); - - if (Validate::isLoadedObject($module)) - { - if (array_key_exists('id_carrier', $module)) - $module->id_carrier = $carrier->id; - if ($carrier->need_range) - if (method_exists($module, 'getPackageShippingCost')) - $shipping_cost = $module->getPackageShippingCost($this, $shipping_cost, $products); - else - $shipping_cost = $module->getOrderShippingCost($this, $shipping_cost); - else - $shipping_cost = $module->getOrderShippingCostExternal($this); - - // Check if carrier is available - if ($shipping_cost === false) - { - Cache::store($cache_id, false); - return false; - } - } - else - { - Cache::store($cache_id, false); - return false; - } - } - - if (Configuration::get('PS_ATCP_SHIPWRAP')) - { - if (!$use_tax) - { - // With PS_ATCP_SHIPWRAP, we deduce the pre-tax price from the post-tax - // price. This is on purpose and required in Germany. - $shipping_cost /= (1 + $this->getAverageProductsTaxRate()); - } - } - else - { - // Apply tax - if ($use_tax && isset($carrier_tax)) - $shipping_cost *= 1 + ($carrier_tax / 100); - } - - $shipping_cost = (float)Tools::ps_round((float)$shipping_cost, 2); - Cache::store($cache_id, $shipping_cost); - - return $shipping_cost; - } - - /** - * Return cart weight - * @return float Cart weight - */ - public function getTotalWeight($products = null) - { - if (!is_null($products)) - { - $total_weight = 0; - foreach ($products as $product) - { - if (!isset($product['weight_attribute']) || is_null($product['weight_attribute'])) - $total_weight += $product['weight'] * $product['cart_quantity']; - else - $total_weight += $product['weight_attribute'] * $product['cart_quantity']; - } - return $total_weight; - } - - if (!isset(self::$_totalWeight[$this->id])) - { - if (Combination::isFeatureActive()) - $weight_product_with_attribute = Db::getInstance()->getValue(' + ); + Cache::store($cache_id, $result); + } else { + $result = Cache::retrieve($cache_id); + } + + $result[] = array('id_address_delivery' => (int)$this->id_address_delivery); + + foreach ($result as $row) { + if ((int)$row['id_address_delivery'] != 0) { + $collection[(int)$row['id_address_delivery']] = new Address((int)$row['id_address_delivery']); + } + } + return $collection; + } + + /** + * Set the delivery option and id_carrier, if there is only one carrier + */ + public function setDeliveryOption($delivery_option = null) + { + if (empty($delivery_option) || count($delivery_option) == 0) { + $this->delivery_option = ''; + $this->id_carrier = 0; + return; + } + Cache::clean('getContextualValue_*'); + $delivery_option_list = $this->getDeliveryOptionList(null, true); + + foreach ($delivery_option_list as $id_address => $options) { + if (!isset($delivery_option[$id_address])) { + foreach ($options as $key => $option) { + if ($option['is_best_price']) { + $delivery_option[$id_address] = $key; + break; + } + } + } + } + + if (count($delivery_option) == 1) { + $this->id_carrier = $this->getIdCarrierFromDeliveryOption($delivery_option); + } + + $this->delivery_option = serialize($delivery_option); + } + + protected function getIdCarrierFromDeliveryOption($delivery_option) + { + $delivery_option_list = $this->getDeliveryOptionList(); + foreach ($delivery_option as $key => $value) { + if (isset($delivery_option_list[$key]) && isset($delivery_option_list[$key][$value])) { + if (count($delivery_option_list[$key][$value]['carrier_list']) == 1) { + return current(array_keys($delivery_option_list[$key][$value]['carrier_list'])); + } + } + } + + return 0; + } + + /** + * Get the delivery option selected, or if no delivery option was selected, + * the cheapest option for each address + * + * @param Country|null $default_country + * @param bool $dontAutoSelectOptions + * @param bool $use_cache + * + * @return array|bool|mixed Delivery option + */ + public function getDeliveryOption($default_country = null, $dontAutoSelectOptions = false, $use_cache = true) + { + static $cache = array(); + $cache_id = (int)(is_object($default_country) ? $default_country->id : 0).'-'.(int)$dontAutoSelectOptions; + if (isset($cache[$cache_id]) && $use_cache) { + return $cache[$cache_id]; + } + + $delivery_option_list = $this->getDeliveryOptionList($default_country); + + // The delivery option was selected + if (isset($this->delivery_option) && $this->delivery_option != '') { + $delivery_option = Tools::unSerialize($this->delivery_option); + $validated = true; + foreach ($delivery_option as $id_address => $key) { + if (!isset($delivery_option_list[$id_address][$key])) { + $validated = false; + break; + } + } + + if ($validated) { + $cache[$cache_id] = $delivery_option; + return $delivery_option; + } + } + + if ($dontAutoSelectOptions) { + return false; + } + + // No delivery option selected or delivery option selected is not valid, get the better for all options + $delivery_option = array(); + foreach ($delivery_option_list as $id_address => $options) { + foreach ($options as $key => $option) { + if (Configuration::get('PS_CARRIER_DEFAULT') == -1 && $option['is_best_price']) { + $delivery_option[$id_address] = $key; + break; + } elseif (Configuration::get('PS_CARRIER_DEFAULT') == -2 && $option['is_best_grade']) { + $delivery_option[$id_address] = $key; + break; + } elseif ($option['unique_carrier'] && in_array(Configuration::get('PS_CARRIER_DEFAULT'), array_keys($option['carrier_list']))) { + $delivery_option[$id_address] = $key; + break; + } + } + + reset($options); + if (!isset($delivery_option[$id_address])) { + $delivery_option[$id_address] = key($options); + } + } + + $cache[$cache_id] = $delivery_option; + + return $delivery_option; + } + + /** + * Return shipping total for the cart + * + * @param array|null $delivery_option Array of the delivery option for each address + * @param bool $use_tax + * @param Country|null $default_country + * @return float Shipping total + */ + public function getTotalShippingCost($delivery_option = null, $use_tax = true, Country $default_country = null) + { + if (isset(Context::getContext()->cookie->id_country)) { + $default_country = new Country(Context::getContext()->cookie->id_country); + } + if (is_null($delivery_option)) { + $delivery_option = $this->getDeliveryOption($default_country, false, false); + } + + $total_shipping = 0; + $delivery_option_list = $this->getDeliveryOptionList($default_country); + foreach ($delivery_option as $id_address => $key) { + if (!isset($delivery_option_list[$id_address]) || !isset($delivery_option_list[$id_address][$key])) { + continue; + } + if ($use_tax) { + $total_shipping += $delivery_option_list[$id_address][$key]['total_price_with_tax']; + } else { + $total_shipping += $delivery_option_list[$id_address][$key]['total_price_without_tax']; + } + } + + return $total_shipping; + } + + /** + * Return shipping total of a specific carriers for the cart + * + * @param int $id_carrier + * @param array $delivery_option Array of the delivery option for each address + * @param bool $useTax + * @param Country|null $default_country + * @param array|null $delivery_option + * @return float Shipping total + */ + public function getCarrierCost($id_carrier, $useTax = true, Country $default_country = null, $delivery_option = null) + { + if (is_null($delivery_option)) { + $delivery_option = $this->getDeliveryOption($default_country); + } + + $total_shipping = 0; + $delivery_option_list = $this->getDeliveryOptionList(); + + + foreach ($delivery_option as $id_address => $key) { + if (!isset($delivery_option_list[$id_address]) || !isset($delivery_option_list[$id_address][$key])) { + continue; + } + if (isset($delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier])) { + if ($useTax) { + $total_shipping += $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['price_with_tax']; + } else { + $total_shipping += $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['price_without_tax']; + } + } + } + + return $total_shipping; + } + + /** + * @deprecated 1.5.0, use Cart->getPackageShippingCost() + */ + public function getOrderShippingCost($id_carrier = null, $use_tax = true, Country $default_country = null, $product_list = null) + { + Tools::displayAsDeprecated(); + return $this->getPackageShippingCost($id_carrier, $use_tax, $default_country, $product_list); + } + + /** + * Return package shipping cost + * + * @param int $id_carrier Carrier ID (default : current carrier) + * @param bool $use_tax + * @param Country|null $default_country + * @param array|null $product_list List of product concerned by the shipping. + * If null, all the product of the cart are used to calculate the shipping cost + * @param int|null $id_zone + * + * @return float Shipping total + */ + public function getPackageShippingCost($id_carrier = null, $use_tax = true, Country $default_country = null, $product_list = null, $id_zone = null) + { + if ($this->isVirtualCart()) { + return 0; + } + + if (!$default_country) { + $default_country = Context::getContext()->country; + } + + if (!is_null($product_list)) { + foreach ($product_list as $key => $value) { + if ($value['is_virtual'] == 1) { + unset($product_list[$key]); + } + } + } + + if (is_null($product_list)) { + $products = $this->getProducts(); + } else { + $products = $product_list; + } + + if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_invoice') { + $address_id = (int)$this->id_address_invoice; + } elseif (count($product_list)) { + $prod = current($product_list); + $address_id = (int)$prod['id_address_delivery']; + } else { + $address_id = null; + } + if (!Address::addressExists($address_id)) { + $address_id = null; + } + + $cache_id = 'getPackageShippingCost_'.(int)$this->id.'_'.(int)$address_id.'_'.(int)$id_carrier.'_'.(int)$use_tax.'_'.(int)$default_country->id; + if ($products) { + foreach ($products as $product) { + $cache_id .= '_'.(int)$product['id_product'].'_'.(int)$product['id_product_attribute']; + } + } + + if (Cache::isStored($cache_id)) { + return Cache::retrieve($cache_id); + } + + // Order total in default currency without fees + $order_total = $this->getOrderTotal(true, Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING, $product_list); + + // Start with shipping cost at 0 + $shipping_cost = 0; + // If no product added, return 0 + if (!count($products)) { + Cache::store($cache_id, $shipping_cost); + return $shipping_cost; + } + + if (!isset($id_zone)) { + // Get id zone + if (!$this->isMultiAddressDelivery() + && isset($this->id_address_delivery) // Be carefull, id_address_delivery is not usefull one 1.5 + && $this->id_address_delivery + && Customer::customerHasAddress($this->id_customer, $this->id_address_delivery + )) { + $id_zone = Address::getZoneById((int)$this->id_address_delivery); + } else { + if (!Validate::isLoadedObject($default_country)) { + $default_country = new Country(Configuration::get('PS_COUNTRY_DEFAULT'), Configuration::get('PS_LANG_DEFAULT')); + } + + $id_zone = (int)$default_country->id_zone; + } + } + + if ($id_carrier && !$this->isCarrierInRange((int)$id_carrier, (int)$id_zone)) { + $id_carrier = ''; + } + + if (empty($id_carrier) && $this->isCarrierInRange((int)Configuration::get('PS_CARRIER_DEFAULT'), (int)$id_zone)) { + $id_carrier = (int)Configuration::get('PS_CARRIER_DEFAULT'); + } + + $total_package_without_shipping_tax_inc = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, $product_list); + if (empty($id_carrier)) { + if ((int)$this->id_customer) { + $customer = new Customer((int)$this->id_customer); + $result = Carrier::getCarriers((int)Configuration::get('PS_LANG_DEFAULT'), true, false, (int)$id_zone, $customer->getGroups()); + unset($customer); + } else { + $result = Carrier::getCarriers((int)Configuration::get('PS_LANG_DEFAULT'), true, false, (int)$id_zone); + } + + foreach ($result as $k => $row) { + if ($row['id_carrier'] == Configuration::get('PS_CARRIER_DEFAULT')) { + continue; + } + + if (!isset(self::$_carriers[$row['id_carrier']])) { + self::$_carriers[$row['id_carrier']] = new Carrier((int)$row['id_carrier']); + } + + /** @var Carrier $carrier */ + $carrier = self::$_carriers[$row['id_carrier']]; + + $shipping_method = $carrier->getShippingMethod(); + // Get only carriers that are compliant with shipping method + if (($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && $carrier->getMaxDeliveryPriceByWeight((int)$id_zone) === false) + || ($shipping_method == Carrier::SHIPPING_METHOD_PRICE && $carrier->getMaxDeliveryPriceByPrice((int)$id_zone) === false)) { + unset($result[$k]); + continue; + } + + // If out-of-range behavior carrier is set on "Desactivate carrier" + if ($row['range_behavior']) { + $check_delivery_price_by_weight = Carrier::checkDeliveryPriceByWeight($row['id_carrier'], $this->getTotalWeight(), (int)$id_zone); + + $total_order = $total_package_without_shipping_tax_inc; + $check_delivery_price_by_price = Carrier::checkDeliveryPriceByPrice($row['id_carrier'], $total_order, (int)$id_zone, (int)$this->id_currency); + + // Get only carriers that have a range compatible with cart + if (($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && !$check_delivery_price_by_weight) + || ($shipping_method == Carrier::SHIPPING_METHOD_PRICE && !$check_delivery_price_by_price)) { + unset($result[$k]); + continue; + } + } + + if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) { + $shipping = $carrier->getDeliveryPriceByWeight($this->getTotalWeight($product_list), (int)$id_zone); + } else { + $shipping = $carrier->getDeliveryPriceByPrice($order_total, (int)$id_zone, (int)$this->id_currency); + } + + if (!isset($min_shipping_price)) { + $min_shipping_price = $shipping; + } + + if ($shipping <= $min_shipping_price) { + $id_carrier = (int)$row['id_carrier']; + $min_shipping_price = $shipping; + } + } + } + + if (empty($id_carrier)) { + $id_carrier = Configuration::get('PS_CARRIER_DEFAULT'); + } + + if (!isset(self::$_carriers[$id_carrier])) { + self::$_carriers[$id_carrier] = new Carrier((int)$id_carrier, Configuration::get('PS_LANG_DEFAULT')); + } + + $carrier = self::$_carriers[$id_carrier]; + + // No valid Carrier or $id_carrier <= 0 ? + if (!Validate::isLoadedObject($carrier)) { + Cache::store($cache_id, 0); + return 0; + } + $shipping_method = $carrier->getShippingMethod(); + + if (!$carrier->active) { + Cache::store($cache_id, $shipping_cost); + return $shipping_cost; + } + + // Free fees if free carrier + if ($carrier->is_free == 1) { + Cache::store($cache_id, 0); + return 0; + } + + // Select carrier tax + if ($use_tax && !Tax::excludeTaxeOption()) { + $address = Address::initialize((int)$address_id); + + if (Configuration::get('PS_ATCP_SHIPWRAP')) { + // With PS_ATCP_SHIPWRAP, pre-tax price is deduced + // from post tax price, so no $carrier_tax here + // even though it sounds weird. + $carrier_tax = 0; + } else { + $carrier_tax = $carrier->getTaxesRate($address); + } + } + + $configuration = Configuration::getMultiple(array( + 'PS_SHIPPING_FREE_PRICE', + 'PS_SHIPPING_HANDLING', + 'PS_SHIPPING_METHOD', + 'PS_SHIPPING_FREE_WEIGHT' + )); + + // Free fees + $free_fees_price = 0; + if (isset($configuration['PS_SHIPPING_FREE_PRICE'])) { + $free_fees_price = Tools::convertPrice((float)$configuration['PS_SHIPPING_FREE_PRICE'], Currency::getCurrencyInstance((int)$this->id_currency)); + } + $orderTotalwithDiscounts = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, null, null, false); + if ($orderTotalwithDiscounts >= (float)($free_fees_price) && (float)($free_fees_price) > 0) { + Cache::store($cache_id, $shipping_cost); + return $shipping_cost; + } + + if (isset($configuration['PS_SHIPPING_FREE_WEIGHT']) + && $this->getTotalWeight() >= (float)$configuration['PS_SHIPPING_FREE_WEIGHT'] + && (float)$configuration['PS_SHIPPING_FREE_WEIGHT'] > 0) { + Cache::store($cache_id, $shipping_cost); + return $shipping_cost; + } + + // Get shipping cost using correct method + if ($carrier->range_behavior) { + if (!isset($id_zone)) { + // Get id zone + if (isset($this->id_address_delivery) + && $this->id_address_delivery + && Customer::customerHasAddress($this->id_customer, $this->id_address_delivery)) { + $id_zone = Address::getZoneById((int)$this->id_address_delivery); + } else { + $id_zone = (int)$default_country->id_zone; + } + } + + if (($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && !Carrier::checkDeliveryPriceByWeight($carrier->id, $this->getTotalWeight(), (int)$id_zone)) + || ($shipping_method == Carrier::SHIPPING_METHOD_PRICE && !Carrier::checkDeliveryPriceByPrice($carrier->id, $total_package_without_shipping_tax_inc, $id_zone, (int)$this->id_currency) + )) { + $shipping_cost += 0; + } else { + if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) { + $shipping_cost += $carrier->getDeliveryPriceByWeight($this->getTotalWeight($product_list), $id_zone); + } else { // by price + $shipping_cost += $carrier->getDeliveryPriceByPrice($order_total, $id_zone, (int)$this->id_currency); + } + } + } else { + if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) { + $shipping_cost += $carrier->getDeliveryPriceByWeight($this->getTotalWeight($product_list), $id_zone); + } else { + $shipping_cost += $carrier->getDeliveryPriceByPrice($order_total, $id_zone, (int)$this->id_currency); + } + } + // Adding handling charges + if (isset($configuration['PS_SHIPPING_HANDLING']) && $carrier->shipping_handling) { + $shipping_cost += (float)$configuration['PS_SHIPPING_HANDLING']; + } + + // Additional Shipping Cost per product + foreach ($products as $product) { + if (!$product['is_virtual']) { + $shipping_cost += $product['additional_shipping_cost'] * $product['cart_quantity']; + } + } + + $shipping_cost = Tools::convertPrice($shipping_cost, Currency::getCurrencyInstance((int)$this->id_currency)); + + //get external shipping cost from module + if ($carrier->shipping_external) { + $module_name = $carrier->external_module_name; + + /** @var CarrierModule $module */ + $module = Module::getInstanceByName($module_name); + + if (Validate::isLoadedObject($module)) { + if (array_key_exists('id_carrier', $module)) { + $module->id_carrier = $carrier->id; + } + if ($carrier->need_range) { + if (method_exists($module, 'getPackageShippingCost')) { + $shipping_cost = $module->getPackageShippingCost($this, $shipping_cost, $products); + } else { + $shipping_cost = $module->getOrderShippingCost($this, $shipping_cost); + } + } else { + $shipping_cost = $module->getOrderShippingCostExternal($this); + } + + // Check if carrier is available + if ($shipping_cost === false) { + Cache::store($cache_id, false); + return false; + } + } else { + Cache::store($cache_id, false); + return false; + } + } + + if (Configuration::get('PS_ATCP_SHIPWRAP')) { + if (!$use_tax) { + // With PS_ATCP_SHIPWRAP, we deduce the pre-tax price from the post-tax + // price. This is on purpose and required in Germany. + $shipping_cost /= (1 + $this->getAverageProductsTaxRate()); + } + } else { + // Apply tax + if ($use_tax && isset($carrier_tax)) { + $shipping_cost *= 1 + ($carrier_tax / 100); + } + } + + $shipping_cost = (float)Tools::ps_round((float)$shipping_cost, 2); + Cache::store($cache_id, $shipping_cost); + + return $shipping_cost; + } + + /** + * Return cart weight + * @return float Cart weight + */ + public function getTotalWeight($products = null) + { + if (!is_null($products)) { + $total_weight = 0; + foreach ($products as $product) { + if (!isset($product['weight_attribute']) || is_null($product['weight_attribute'])) { + $total_weight += $product['weight'] * $product['cart_quantity']; + } else { + $total_weight += $product['weight_attribute'] * $product['cart_quantity']; + } + } + return $total_weight; + } + + if (!isset(self::$_totalWeight[$this->id])) { + if (Combination::isFeatureActive()) { + $weight_product_with_attribute = Db::getInstance()->getValue(' SELECT SUM((p.`weight` + pa.`weight`) * cp.`quantity`) as nb FROM `'._DB_PREFIX_.'cart_product` cp LEFT JOIN `'._DB_PREFIX_.'product` p ON (cp.`id_product` = p.`id_product`) LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (cp.`id_product_attribute` = pa.`id_product_attribute`) WHERE (cp.`id_product_attribute` IS NOT NULL AND cp.`id_product_attribute` != 0) AND cp.`id_cart` = '.(int)$this->id); - else - $weight_product_with_attribute = 0; + } else { + $weight_product_with_attribute = 0; + } - $weight_product_without_attribute = Db::getInstance()->getValue(' + $weight_product_without_attribute = Db::getInstance()->getValue(' SELECT SUM(p.`weight` * cp.`quantity`) as nb FROM `'._DB_PREFIX_.'cart_product` cp LEFT JOIN `'._DB_PREFIX_.'product` p ON (cp.`id_product` = p.`id_product`) WHERE (cp.`id_product_attribute` IS NULL OR cp.`id_product_attribute` = 0) AND cp.`id_cart` = '.(int)$this->id); - self::$_totalWeight[$this->id] = round((float)$weight_product_with_attribute + (float)$weight_product_without_attribute, 3); - } + self::$_totalWeight[$this->id] = round((float)$weight_product_with_attribute + (float)$weight_product_without_attribute, 3); + } - return self::$_totalWeight[$this->id]; - } + return self::$_totalWeight[$this->id]; + } - /** - * @deprecated 1.5.0 - * @param CartRule $obj - * @return bool|string - */ - public function checkDiscountValidity($obj, $discounts, $order_total, $products, $check_cart_discount = false) - { - Tools::displayAsDeprecated(); - $context = Context::getContext()->cloneContext(); - $context->cart = $this; + /** + * @deprecated 1.5.0 + * @param CartRule $obj + * @return bool|string + */ + public function checkDiscountValidity($obj, $discounts, $order_total, $products, $check_cart_discount = false) + { + Tools::displayAsDeprecated(); + $context = Context::getContext()->cloneContext(); + $context->cart = $this; - return $obj->checkValidity($context); - } + return $obj->checkValidity($context); + } - /** - * Return useful informations for cart - * - * @return array Cart details - */ - public function getSummaryDetails($id_lang = null, $refresh = false) - { - $context = Context::getContext(); - if (!$id_lang) - $id_lang = $context->language->id; + /** + * Return useful informations for cart + * + * @return array Cart details + */ + public function getSummaryDetails($id_lang = null, $refresh = false) + { + $context = Context::getContext(); + if (!$id_lang) { + $id_lang = $context->language->id; + } - $delivery = new Address((int)$this->id_address_delivery); - $invoice = new Address((int)$this->id_address_invoice); + $delivery = new Address((int)$this->id_address_delivery); + $invoice = new Address((int)$this->id_address_invoice); - // New layout system with personalization fields - $formatted_addresses = array( - 'delivery' => AddressFormat::getFormattedLayoutData($delivery), - 'invoice' => AddressFormat::getFormattedLayoutData($invoice) - ); + // New layout system with personalization fields + $formatted_addresses = array( + 'delivery' => AddressFormat::getFormattedLayoutData($delivery), + 'invoice' => AddressFormat::getFormattedLayoutData($invoice) + ); - $base_total_tax_inc = $this->getOrderTotal(true); - $base_total_tax_exc = $this->getOrderTotal(false); + $base_total_tax_inc = $this->getOrderTotal(true); + $base_total_tax_exc = $this->getOrderTotal(false); - $total_tax = $base_total_tax_inc - $base_total_tax_exc; + $total_tax = $base_total_tax_inc - $base_total_tax_exc; - if ($total_tax < 0) - $total_tax = 0; + if ($total_tax < 0) { + $total_tax = 0; + } - $currency = new Currency($this->id_currency); + $currency = new Currency($this->id_currency); - $products = $this->getProducts($refresh); + $products = $this->getProducts($refresh); - foreach ($products as $key => &$product) - { - $product['price_without_quantity_discount'] = Product::getPriceStatic( - $product['id_product'], - !Product::getTaxCalculationMethod(), - $product['id_product_attribute'], - 6, - null, - false, - false - ); + foreach ($products as $key => &$product) { + $product['price_without_quantity_discount'] = Product::getPriceStatic( + $product['id_product'], + !Product::getTaxCalculationMethod(), + $product['id_product_attribute'], + 6, + null, + false, + false + ); - if ($product['reduction_type'] == 'amount') - { - $reduction = (float)$product['price_wt'] - (float)$product['price_without_quantity_discount']; - $product['reduction_formatted'] = Tools::displayPrice($reduction); - } - } + if ($product['reduction_type'] == 'amount') { + $reduction = (!Product::getTaxCalculationMethod() ? (float)$product['price_wt'] : (float)$product['price']) - (float)$product['price_without_quantity_discount']; + $product['reduction_formatted'] = Tools::displayPrice($reduction); + } + } - $gift_products = array(); - $cart_rules = $this->getCartRules(); - $total_shipping = $this->getTotalShippingCost(); - $total_shipping_tax_exc = $this->getTotalShippingCost(null, false); - $total_products_wt = $this->getOrderTotal(true, Cart::ONLY_PRODUCTS); - $total_products = $this->getOrderTotal(false, Cart::ONLY_PRODUCTS); - $total_discounts = $this->getOrderTotal(true, Cart::ONLY_DISCOUNTS); - $total_discounts_tax_exc = $this->getOrderTotal(false, Cart::ONLY_DISCOUNTS); + $gift_products = array(); + $cart_rules = $this->getCartRules(); + $total_shipping = $this->getTotalShippingCost(); + $total_shipping_tax_exc = $this->getTotalShippingCost(null, false); + $total_products_wt = $this->getOrderTotal(true, Cart::ONLY_PRODUCTS); + $total_products = $this->getOrderTotal(false, Cart::ONLY_PRODUCTS); + $total_discounts = $this->getOrderTotal(true, Cart::ONLY_DISCOUNTS); + $total_discounts_tax_exc = $this->getOrderTotal(false, Cart::ONLY_DISCOUNTS); - // The cart content is altered for display - foreach ($cart_rules as &$cart_rule) - { - // If the cart rule is automatic (wihtout any code) and include free shipping, it should not be displayed as a cart rule but only set the shipping cost to 0 - if ($cart_rule['free_shipping'] && (empty($cart_rule['code']) || preg_match('/^'.CartRule::BO_ORDER_CODE_PREFIX.'[0-9]+/', $cart_rule['code']))) - { - $cart_rule['value_real'] -= $total_shipping; - $cart_rule['value_tax_exc'] -= $total_shipping_tax_exc; - $cart_rule['value_real'] = Tools::ps_round($cart_rule['value_real'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); - $cart_rule['value_tax_exc'] = Tools::ps_round($cart_rule['value_tax_exc'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); - if ($total_discounts > $cart_rule['value_real']) - $total_discounts -= $total_shipping; - if ($total_discounts_tax_exc > $cart_rule['value_tax_exc']) - $total_discounts_tax_exc -= $total_shipping_tax_exc; + // The cart content is altered for display + foreach ($cart_rules as &$cart_rule) { + // If the cart rule is automatic (wihtout any code) and include free shipping, it should not be displayed as a cart rule but only set the shipping cost to 0 + if ($cart_rule['free_shipping'] && (empty($cart_rule['code']) || preg_match('/^'.CartRule::BO_ORDER_CODE_PREFIX.'[0-9]+/', $cart_rule['code']))) { - // Update total shipping - $total_shipping = 0; - $total_shipping_tax_exc = 0; - } - if ($cart_rule['gift_product']) - { - foreach ($products as $key => &$product) - if (empty($product['gift']) && $product['id_product'] == $cart_rule['gift_product'] && $product['id_product_attribute'] == $cart_rule['gift_product_attribute']) - { - // Update total products - $total_products_wt = Tools::ps_round($total_products_wt - $product['price_wt'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); - $total_products = Tools::ps_round($total_products - $product['price'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); + $cart_rule['value_real'] -= $total_shipping; + $cart_rule['value_tax_exc'] -= $total_shipping_tax_exc; + $cart_rule['value_real'] = Tools::ps_round($cart_rule['value_real'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); + $cart_rule['value_tax_exc'] = Tools::ps_round($cart_rule['value_tax_exc'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); + if ($total_discounts > $cart_rule['value_real']) { + $total_discounts -= $total_shipping; + } + if ($total_discounts_tax_exc > $cart_rule['value_tax_exc']) { + $total_discounts_tax_exc -= $total_shipping_tax_exc; + } - // Update total discounts - $total_discounts = Tools::ps_round($total_discounts - $product['price_wt'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); - $total_discounts_tax_exc = Tools::ps_round($total_discounts_tax_exc - $product['price'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); + // Update total shipping + $total_shipping = 0; + $total_shipping_tax_exc = 0; + } - // Update cart rule value - $cart_rule['value_real'] = Tools::ps_round($cart_rule['value_real'] - $product['price_wt'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); - $cart_rule['value_tax_exc'] = Tools::ps_round($cart_rule['value_tax_exc'] - $product['price'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); + if ($cart_rule['gift_product']) { + foreach ($products as $key => &$product) { + if (empty($product['gift']) && $product['id_product'] == $cart_rule['gift_product'] && $product['id_product_attribute'] == $cart_rule['gift_product_attribute']) { + // Update total products + $total_products_wt = Tools::ps_round($total_products_wt - $product['price_wt'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); + $total_products = Tools::ps_round($total_products - $product['price'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); - // Update product quantity - $product['total_wt'] = Tools::ps_round($product['total_wt'] - $product['price_wt'], (int)$currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); - $product['total'] = Tools::ps_round($product['total'] - $product['price'], (int)$currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); - $product['cart_quantity']--; + // Update total discounts + $total_discounts = Tools::ps_round($total_discounts - $product['price_wt'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); + $total_discounts_tax_exc = Tools::ps_round($total_discounts_tax_exc - $product['price'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); - if (!$product['cart_quantity']) - unset($products[$key]); + // Update cart rule value + $cart_rule['value_real'] = Tools::ps_round($cart_rule['value_real'] - $product['price_wt'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); + $cart_rule['value_tax_exc'] = Tools::ps_round($cart_rule['value_tax_exc'] - $product['price'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); - // Add a new product line - $gift_product = $product; - $gift_product['cart_quantity'] = 1; - $gift_product['price'] = 0; - $gift_product['price_wt'] = 0; - $gift_product['total_wt'] = 0; - $gift_product['total'] = 0; - $gift_product['gift'] = true; - $gift_products[] = $gift_product; + // Update product quantity + $product['total_wt'] = Tools::ps_round($product['total_wt'] - $product['price_wt'], (int)$currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); + $product['total'] = Tools::ps_round($product['total'] - $product['price'], (int)$currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); + $product['cart_quantity']--; - break; // One gift product per cart rule - } - } - } + if (!$product['cart_quantity']) { + unset($products[$key]); + } - foreach ($cart_rules as $key => &$cart_rule) - { - if ((float)$cart_rule['value_real'] == 0 && (int)$cart_rule['free_shipping'] == 0) - unset($cart_rules[$key]); - } + // Add a new product line + $gift_product = $product; + $gift_product['cart_quantity'] = 1; + $gift_product['price'] = 0; + $gift_product['price_wt'] = 0; + $gift_product['total_wt'] = 0; + $gift_product['total'] = 0; + $gift_product['gift'] = true; + $gift_products[] = $gift_product; - $summary = array( - 'delivery' => $delivery, - 'delivery_state' => State::getNameById($delivery->id_state), - 'invoice' => $invoice, - 'invoice_state' => State::getNameById($invoice->id_state), - 'formattedAddresses' => $formatted_addresses, - 'products' => array_values($products), - 'gift_products' => $gift_products, - 'discounts' => array_values($cart_rules), - 'is_virtual_cart' => (int)$this->isVirtualCart(), - 'total_discounts' => $total_discounts, - 'total_discounts_tax_exc' => $total_discounts_tax_exc, - 'total_wrapping' => $this->getOrderTotal(true, Cart::ONLY_WRAPPING), - 'total_wrapping_tax_exc' => $this->getOrderTotal(false, Cart::ONLY_WRAPPING), - 'total_shipping' => $total_shipping, - 'total_shipping_tax_exc' => $total_shipping_tax_exc, - 'total_products_wt' => $total_products_wt, - 'total_products' => $total_products, - 'total_price' => $base_total_tax_inc, - 'total_tax' => $total_tax, - 'total_price_without_tax' => $base_total_tax_exc, - 'is_multi_address_delivery' => $this->isMultiAddressDelivery() || ((int)Tools::getValue('multi-shipping') == 1), - 'free_ship' => $total_shipping ? 0 : 1, - 'carrier' => new Carrier($this->id_carrier, $id_lang), - ); + break; // One gift product per cart rule + } + } + } + } - $hook = Hook::exec('actionCartSummary', $summary, null, true); - if (is_array($hook)) - $summary = array_merge($summary, array_shift($hook)); + foreach ($cart_rules as $key => &$cart_rule) { + if (((float)$cart_rule['value_real'] == 0 && (int)$cart_rule['free_shipping'] == 0)) { + unset($cart_rules[$key]); + } + } - return $summary; - } + $summary = array( + 'delivery' => $delivery, + 'delivery_state' => State::getNameById($delivery->id_state), + 'invoice' => $invoice, + 'invoice_state' => State::getNameById($invoice->id_state), + 'formattedAddresses' => $formatted_addresses, + 'products' => array_values($products), + 'gift_products' => $gift_products, + 'discounts' => array_values($cart_rules), + 'is_virtual_cart' => (int)$this->isVirtualCart(), + 'total_discounts' => $total_discounts, + 'total_discounts_tax_exc' => $total_discounts_tax_exc, + 'total_wrapping' => $this->getOrderTotal(true, Cart::ONLY_WRAPPING), + 'total_wrapping_tax_exc' => $this->getOrderTotal(false, Cart::ONLY_WRAPPING), + 'total_shipping' => $total_shipping, + 'total_shipping_tax_exc' => $total_shipping_tax_exc, + 'total_products_wt' => $total_products_wt, + 'total_products' => $total_products, + 'total_price' => $base_total_tax_inc, + 'total_tax' => $total_tax, + 'total_price_without_tax' => $base_total_tax_exc, + 'is_multi_address_delivery' => $this->isMultiAddressDelivery() || ((int)Tools::getValue('multi-shipping') == 1), + 'free_ship' =>!$total_shipping && !count($this->getDeliveryAddressesWithoutCarriers(true, $errors)), + 'carrier' => new Carrier($this->id_carrier, $id_lang), + ); - public function checkQuantities($return_product = false) - { - if (Configuration::get('PS_CATALOG_MODE') && !defined('_PS_ADMIN_DIR_')) - return false; + $hook = Hook::exec('actionCartSummary', $summary, null, true); + if (is_array($hook)) { + $summary = array_merge($summary, array_shift($hook)); + } - foreach ($this->getProducts() as $product) - { - if (!$this->allow_seperated_package && !$product['allow_oosp'] && StockAvailable::dependsOnStock($product['id_product']) && - $product['advanced_stock_management'] && (bool)Context::getContext()->customer->isLogged() && ($delivery = $this->getDeliveryOption()) && !empty($delivery)) - $product['stock_quantity'] = StockManager::getStockByCarrier((int)$product['id_product'], (int)$product['id_product_attribute'], $delivery); - if (!$product['active'] || !$product['available_for_order'] - || (!$product['allow_oosp'] && $product['stock_quantity'] < $product['cart_quantity'])) - return $return_product ? $product : false; - } + return $summary; + } - return true; - } + public function checkQuantities($return_product = false) + { + if (Configuration::get('PS_CATALOG_MODE') && !defined('_PS_ADMIN_DIR_')) { + return false; + } - public function checkProductsAccess() - { - if (Configuration::get('PS_CATALOG_MODE')) - return true; + foreach ($this->getProducts() as $product) { + if (!$this->allow_seperated_package && !$product['allow_oosp'] && StockAvailable::dependsOnStock($product['id_product']) && + $product['advanced_stock_management'] && (bool)Context::getContext()->customer->isLogged() && ($delivery = $this->getDeliveryOption()) && !empty($delivery)) { + $product['stock_quantity'] = StockManager::getStockByCarrier((int)$product['id_product'], (int)$product['id_product_attribute'], $delivery); + } + if (!$product['active'] || !$product['available_for_order'] + || (!$product['allow_oosp'] && $product['stock_quantity'] < $product['cart_quantity'])) { + return $return_product ? $product : false; + } + } - foreach ($this->getProducts() as $product) - if (!Product::checkAccessStatic($product['id_product'], $this->id_customer)) - return $product['id_product']; + return true; + } - return false; - } + public function checkProductsAccess() + { + if (Configuration::get('PS_CATALOG_MODE')) { + return true; + } + + foreach ($this->getProducts() as $product) { + if (!Product::checkAccessStatic($product['id_product'], $this->id_customer)) { + return $product['id_product']; + } + } + + return false; + } - public static function lastNoneOrderedCart($id_customer) - { - $sql = 'SELECT c.`id_cart` + public static function lastNoneOrderedCart($id_customer) + { + $sql = 'SELECT c.`id_cart` FROM '._DB_PREFIX_.'cart c WHERE NOT EXISTS (SELECT 1 FROM '._DB_PREFIX_.'orders o WHERE o.`id_cart` = c.`id_cart` AND o.`id_customer` = '.(int)$id_customer.') @@ -3239,111 +3302,115 @@ class CartCore extends ObjectModel '.Shop::addSqlRestriction(Shop::SHARE_ORDER, 'c').' ORDER BY c.`date_upd` DESC'; - if (!$id_cart = Db::getInstance()->getValue($sql)) - return false; + if (!$id_cart = Db::getInstance()->getValue($sql)) { + return false; + } - return (int)$id_cart; - } + return (int)$id_cart; + } - /** - * Check if cart contains only virtual products - * - * @return bool true if is a virtual cart or false - */ - public function isVirtualCart($strict = false) - { - if (!ProductDownload::isFeatureActive()) - return false; + /** + * Check if cart contains only virtual products + * + * @return bool true if is a virtual cart or false + */ + public function isVirtualCart($strict = false) + { + if (!ProductDownload::isFeatureActive()) { + return false; + } - if (!isset(self::$_isVirtualCart[$this->id])) - { - $products = $this->getProducts(); - if (!count($products)) - return false; + if (!isset(self::$_isVirtualCart[$this->id])) { + $products = $this->getProducts(); + if (!count($products)) { + return false; + } - $is_virtual = 1; - foreach ($products as $product) - { - if (empty($product['is_virtual'])) - $is_virtual = 0; - } - self::$_isVirtualCart[$this->id] = (int)$is_virtual; - } + $is_virtual = 1; + foreach ($products as $product) { + if (empty($product['is_virtual'])) { + $is_virtual = 0; + } + } + self::$_isVirtualCart[$this->id] = (int)$is_virtual; + } - return self::$_isVirtualCart[$this->id]; - } + return self::$_isVirtualCart[$this->id]; + } - /** - * Build cart object from provided id_order - * - * @param int $id_order - * @return Cart|bool - */ - public static function getCartByOrderId($id_order) - { - if ($id_cart = Cart::getCartIdByOrderId($id_order)) - return new Cart((int)$id_cart); + /** + * Build cart object from provided id_order + * + * @param int $id_order + * @return Cart|bool + */ + public static function getCartByOrderId($id_order) + { + if ($id_cart = Cart::getCartIdByOrderId($id_order)) { + return new Cart((int)$id_cart); + } - return false; - } + return false; + } - public static function getCartIdByOrderId($id_order) - { - $result = Db::getInstance()->getRow('SELECT `id_cart` FROM '._DB_PREFIX_.'orders WHERE `id_order` = '.(int)$id_order); - if (!$result || empty($result) || !array_key_exists('id_cart', $result)) - return false; - return $result['id_cart']; - } + public static function getCartIdByOrderId($id_order) + { + $result = Db::getInstance()->getRow('SELECT `id_cart` FROM '._DB_PREFIX_.'orders WHERE `id_order` = '.(int)$id_order); + if (!$result || empty($result) || !array_key_exists('id_cart', $result)) { + return false; + } + return $result['id_cart']; + } - /** - * Add customer's text - * - * @params int $id_product - * @params int $index - * @params int $type - * @params string $textValue - * - * @return bool Always true - */ - public function addTextFieldToProduct($id_product, $index, $type, $text_value) - { - return $this->_addCustomization($id_product, 0, $index, $type, $text_value, 0); - } + /** + * Add customer's text + * + * @params int $id_product + * @params int $index + * @params int $type + * @params string $textValue + * + * @return bool Always true + */ + public function addTextFieldToProduct($id_product, $index, $type, $text_value) + { + return $this->_addCustomization($id_product, 0, $index, $type, $text_value, 0); + } - /** - * Add customer's pictures - * - * @return bool Always true - */ - public function addPictureToProduct($id_product, $index, $type, $file) - { - return $this->_addCustomization($id_product, 0, $index, $type, $file, 0); - } + /** + * Add customer's pictures + * + * @return bool Always true + */ + public function addPictureToProduct($id_product, $index, $type, $file) + { + return $this->_addCustomization($id_product, 0, $index, $type, $file, 0); + } - /** - * @deprecated 1.5.5.0 - * @param int $id_product - * @param $index - * @return bool - */ - public function deletePictureToProduct($id_product, $index) - { - Tools::displayAsDeprecated(); - return $this->deleteCustomizationToProduct($id_product, 0); - } + /** + * @deprecated 1.5.5.0 + * @param int $id_product + * @param $index + * @return bool + */ + public function deletePictureToProduct($id_product, $index) + { + Tools::displayAsDeprecated(); + return $this->deleteCustomizationToProduct($id_product, 0); + } - /** - * Remove a customer's customization - * - * @param int $id_product - * @param int $index - * @return bool - */ - public function deleteCustomizationToProduct($id_product, $index) - { - $result = true; + /** + * Remove a customer's customization + * + * @param int $id_product + * @param int $index + * @return bool + */ + public function deleteCustomizationToProduct($id_product, $index) + { + $result = true; - $cust_data = Db::getInstance()->getRow(' + $cust_data = Db::getInstance()->getRow(' SELECT cu.`id_customization`, cd.`index`, cd.`value`, cd.`type` FROM `'._DB_PREFIX_.'customization` cu LEFT JOIN `'._DB_PREFIX_.'customized_data` cd ON cu.`id_customization` = cd.`id_customization` @@ -3351,236 +3418,247 @@ class CartCore extends ObjectModel AND cu.`id_product` = '.(int)$id_product.' AND `index` = '.(int)$index.' AND `in_cart` = 0' - ); + ); - // Delete customization picture if necessary - if ($cust_data['type'] == 0) - $result &= (@unlink(_PS_UPLOAD_DIR_.$cust_data['value']) && @unlink(_PS_UPLOAD_DIR_.$cust_data['value'].'_small')); + // Delete customization picture if necessary + if ($cust_data['type'] == 0) { + $result &= (@unlink(_PS_UPLOAD_DIR_.$cust_data['value']) && @unlink(_PS_UPLOAD_DIR_.$cust_data['value'].'_small')); + } - $result &= Db::getInstance()->execute('DELETE + $result &= Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'customized_data` WHERE `id_customization` = '.(int)$cust_data['id_customization'].' AND `index` = '.(int)$index - ); - return $result; - } + ); + return $result; + } - /** - * Return custom pictures in this cart for a specified product - * - * @param int $id_product - * @param int $type only return customization of this type - * @param bool $not_in_cart only return customizations that are not in cart already - * @return array result rows - */ - public function getProductCustomization($id_product, $type = null, $not_in_cart = false) - { - if (!Customization::isFeatureActive()) - return array(); + /** + * Return custom pictures in this cart for a specified product + * + * @param int $id_product + * @param int $type only return customization of this type + * @param bool $not_in_cart only return customizations that are not in cart already + * @return array result rows + */ + public function getProductCustomization($id_product, $type = null, $not_in_cart = false) + { + if (!Customization::isFeatureActive()) { + return array(); + } - $result = Db::getInstance()->executeS(' + $result = Db::getInstance()->executeS(' SELECT cu.id_customization, cd.index, cd.value, cd.type, cu.in_cart, cu.quantity FROM `'._DB_PREFIX_.'customization` cu LEFT JOIN `'._DB_PREFIX_.'customized_data` cd ON (cu.`id_customization` = cd.`id_customization`) WHERE cu.id_cart = '.(int)$this->id.' AND cu.id_product = '.(int)$id_product. - ($type === Product::CUSTOMIZE_FILE ? ' AND type = '.(int)Product::CUSTOMIZE_FILE : ''). - ($type === Product::CUSTOMIZE_TEXTFIELD ? ' AND type = '.(int)Product::CUSTOMIZE_TEXTFIELD : ''). - ($not_in_cart ? ' AND in_cart = 0' : '') - ); - return $result; - } + ($type === Product::CUSTOMIZE_FILE ? ' AND type = '.(int)Product::CUSTOMIZE_FILE : ''). + ($type === Product::CUSTOMIZE_TEXTFIELD ? ' AND type = '.(int)Product::CUSTOMIZE_TEXTFIELD : ''). + ($not_in_cart ? ' AND in_cart = 0' : '') + ); + return $result; + } - public static function getCustomerCarts($id_customer, $with_order = true) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getCustomerCarts($id_customer, $with_order = true) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM '._DB_PREFIX_.'cart c WHERE c.`id_customer` = '.(int)$id_customer.' '.(!$with_order ? 'AND NOT EXISTS (SELECT 1 FROM '._DB_PREFIX_.'orders o WHERE o.`id_cart` = c.`id_cart`)' : '').' ORDER BY c.`date_add` DESC'); - } + } - public static function replaceZeroByShopName($echo, $tr) - { - return ($echo == '0' ? Carrier::getCarrierNameFromShopName() : $echo); - } + public static function replaceZeroByShopName($echo, $tr) + { + return ($echo == '0' ? Carrier::getCarrierNameFromShopName() : $echo); + } - public function duplicate() - { - if (!Validate::isLoadedObject($this)) - return false; + public function duplicate() + { + if (!Validate::isLoadedObject($this)) { + return false; + } - $cart = new Cart($this->id); - $cart->id = null; - $cart->id_shop = $this->id_shop; - $cart->id_shop_group = $this->id_shop_group; + $cart = new Cart($this->id); + $cart->id = null; + $cart->id_shop = $this->id_shop; + $cart->id_shop_group = $this->id_shop_group; - if (!Customer::customerHasAddress((int)$cart->id_customer, (int)$cart->id_address_delivery)) - $cart->id_address_delivery = (int)Address::getFirstCustomerAddressId((int)$cart->id_customer); + if (!Customer::customerHasAddress((int)$cart->id_customer, (int)$cart->id_address_delivery)) { + $cart->id_address_delivery = (int)Address::getFirstCustomerAddressId((int)$cart->id_customer); + } - if (!Customer::customerHasAddress((int)$cart->id_customer, (int)$cart->id_address_invoice)) - $cart->id_address_invoice = (int)Address::getFirstCustomerAddressId((int)$cart->id_customer); + if (!Customer::customerHasAddress((int)$cart->id_customer, (int)$cart->id_address_invoice)) { + $cart->id_address_invoice = (int)Address::getFirstCustomerAddressId((int)$cart->id_customer); + } - if ($cart->id_customer) - $cart->secure_key = Cart::$_customer->secure_key; + if ($cart->id_customer) { + $cart->secure_key = Cart::$_customer->secure_key; + } - $cart->add(); + $cart->add(); - if (!Validate::isLoadedObject($cart)) - return false; + if (!Validate::isLoadedObject($cart)) { + return false; + } - $success = true; - $products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT * FROM `'._DB_PREFIX_.'cart_product` WHERE `id_cart` = '.(int)$this->id); + $success = true; + $products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT * FROM `'._DB_PREFIX_.'cart_product` WHERE `id_cart` = '.(int)$this->id); - $product_gift = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT cr.`gift_product`, cr.`gift_product_attribute` FROM `'._DB_PREFIX_.'cart_rule` cr LEFT JOIN `'._DB_PREFIX_.'order_cart_rule` ocr ON (ocr.`id_order` = '.(int)$this->id.') WHERE ocr.`id_cart_rule` = cr.`id_cart_rule`'); + $product_gift = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT cr.`gift_product`, cr.`gift_product_attribute` FROM `'._DB_PREFIX_.'cart_rule` cr LEFT JOIN `'._DB_PREFIX_.'order_cart_rule` ocr ON (ocr.`id_order` = '.(int)$this->id.') WHERE ocr.`id_cart_rule` = cr.`id_cart_rule`'); - $id_address_delivery = Configuration::get('PS_ALLOW_MULTISHIPPING') ? $cart->id_address_delivery : 0; + $id_address_delivery = Configuration::get('PS_ALLOW_MULTISHIPPING') ? $cart->id_address_delivery : 0; - foreach ($products as $product) - { - if ($id_address_delivery) - if (Customer::customerHasAddress((int)$cart->id_customer, $product['id_address_delivery'])) - $id_address_delivery = $product['id_address_delivery']; + foreach ($products as $product) { + if ($id_address_delivery) { + if (Customer::customerHasAddress((int)$cart->id_customer, $product['id_address_delivery'])) { + $id_address_delivery = $product['id_address_delivery']; + } + } - foreach ($product_gift as $gift) - if (isset($gift['gift_product']) && isset($gift['gift_product_attribute']) && (int)$gift['gift_product'] == (int)$product['id_product'] && (int)$gift['gift_product_attribute'] == (int)$product['id_product_attribute']) - $product['quantity'] = (int)$product['quantity'] - 1; + foreach ($product_gift as $gift) { + if (isset($gift['gift_product']) && isset($gift['gift_product_attribute']) && (int)$gift['gift_product'] == (int)$product['id_product'] && (int)$gift['gift_product_attribute'] == (int)$product['id_product_attribute']) { + $product['quantity'] = (int)$product['quantity'] - 1; + } + } - $success &= $cart->updateQty( - (int)$product['quantity'], - (int)$product['id_product'], - (int)$product['id_product_attribute'], - null, - 'up', - (int)$id_address_delivery, - new Shop((int)$cart->id_shop), - false - ); - } + $success &= $cart->updateQty( + (int)$product['quantity'], + (int)$product['id_product'], + (int)$product['id_product_attribute'], + null, + 'up', + (int)$id_address_delivery, + new Shop((int)$cart->id_shop), + false + ); + } - // Customized products - $customs = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + // Customized products + $customs = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM '._DB_PREFIX_.'customization c LEFT JOIN '._DB_PREFIX_.'customized_data cd ON cd.id_customization = c.id_customization WHERE c.id_cart = '.(int)$this->id - ); + ); - // Get datas from customization table - $customs_by_id = array(); - foreach ($customs as $custom) - { - if (!isset($customs_by_id[$custom['id_customization']])) - $customs_by_id[$custom['id_customization']] = array( - 'id_product_attribute' => $custom['id_product_attribute'], - 'id_product' => $custom['id_product'], - 'quantity' => $custom['quantity'] - ); - } + // Get datas from customization table + $customs_by_id = array(); + foreach ($customs as $custom) { + if (!isset($customs_by_id[$custom['id_customization']])) { + $customs_by_id[$custom['id_customization']] = array( + 'id_product_attribute' => $custom['id_product_attribute'], + 'id_product' => $custom['id_product'], + 'quantity' => $custom['quantity'] + ); + } + } - // Insert new customizations - $custom_ids = array(); - foreach ($customs_by_id as $customization_id => $val) - { - Db::getInstance()->execute(' + // Insert new customizations + $custom_ids = array(); + foreach ($customs_by_id as $customization_id => $val) { + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'customization` (id_cart, id_product_attribute, id_product, `id_address_delivery`, quantity, `quantity_refunded`, `quantity_returned`, `in_cart`) VALUES('.(int)$cart->id.', '.(int)$val['id_product_attribute'].', '.(int)$val['id_product'].', '.(int)$id_address_delivery.', '.(int)$val['quantity'].', 0, 0, 1)' - ); - $custom_ids[$customization_id] = Db::getInstance(_PS_USE_SQL_SLAVE_)->Insert_ID(); - } + ); + $custom_ids[$customization_id] = Db::getInstance(_PS_USE_SQL_SLAVE_)->Insert_ID(); + } - // Insert customized_data - if (count($customs)) - { - $first = true; - $sql_custom_data = 'INSERT INTO '._DB_PREFIX_.'customized_data (`id_customization`, `type`, `index`, `value`) VALUES '; - foreach ($customs as $custom) - { - if (!$first) - $sql_custom_data .= ','; - else - $first = false; + // Insert customized_data + if (count($customs)) { + $first = true; + $sql_custom_data = 'INSERT INTO '._DB_PREFIX_.'customized_data (`id_customization`, `type`, `index`, `value`) VALUES '; + foreach ($customs as $custom) { + if (!$first) { + $sql_custom_data .= ','; + } else { + $first = false; + } - $sql_custom_data .= '('.(int)$custom_ids[$custom['id_customization']].', '.(int)$custom['type'].', '. - (int)$custom['index'].', \''.pSQL($custom['value']).'\')'; - } - Db::getInstance()->execute($sql_custom_data); - } + $sql_custom_data .= '('.(int)$custom_ids[$custom['id_customization']].', '.(int)$custom['type'].', '. + (int)$custom['index'].', \''.pSQL($custom['value']).'\')'; + } + Db::getInstance()->execute($sql_custom_data); + } - return array('cart' => $cart, 'success' => $success); - } + return array('cart' => $cart, 'success' => $success); + } - public function getWsCartRows() - { - return Db::getInstance()->executeS(' + public function getWsCartRows() + { + return Db::getInstance()->executeS(' SELECT id_product, id_product_attribute, quantity, id_address_delivery FROM `'._DB_PREFIX_.'cart_product` WHERE id_cart = '.(int)$this->id.' AND id_shop = '.(int)Context::getContext()->shop->id - ); - } + ); + } - public function setWsCartRows($values) - { - if ($this->deleteAssociations()) - { - $query = 'INSERT INTO `'._DB_PREFIX_.'cart_product`(`id_cart`, `id_product`, `id_product_attribute`, `id_address_delivery`, `quantity`, `date_add`, `id_shop`) VALUES '; + public function setWsCartRows($values) + { + if ($this->deleteAssociations()) { + $query = 'INSERT INTO `'._DB_PREFIX_.'cart_product`(`id_cart`, `id_product`, `id_product_attribute`, `id_address_delivery`, `quantity`, `date_add`, `id_shop`) VALUES '; - foreach ($values as $value) - $query .= '('.(int)$this->id.', '.(int)$value['id_product'].', '. - (isset($value['id_product_attribute']) ? (int)$value['id_product_attribute'] : 'NULL').', '. - (isset($value['id_address_delivery']) ? (int)$value['id_address_delivery'] : 0).', '. - (int)$value['quantity'].', NOW(), '.(int)Context::getContext()->shop->id.'),'; + foreach ($values as $value) { + $query .= '('.(int)$this->id.', '.(int)$value['id_product'].', '. + (isset($value['id_product_attribute']) ? (int)$value['id_product_attribute'] : 'NULL').', '. + (isset($value['id_address_delivery']) ? (int)$value['id_address_delivery'] : 0).', '. + (int)$value['quantity'].', NOW(), '.(int)Context::getContext()->shop->id.'),'; + } - Db::getInstance()->execute(rtrim($query, ',')); - } + Db::getInstance()->execute(rtrim($query, ',')); + } - return true; - } + return true; + } - public function setProductAddressDelivery($id_product, $id_product_attribute, $old_id_address_delivery, $new_id_address_delivery) - { - // Check address is linked with the customer - if (!Customer::customerHasAddress(Context::getContext()->customer->id, $new_id_address_delivery)) - return false; + public function setProductAddressDelivery($id_product, $id_product_attribute, $old_id_address_delivery, $new_id_address_delivery) + { + // Check address is linked with the customer + if (!Customer::customerHasAddress(Context::getContext()->customer->id, $new_id_address_delivery)) { + return false; + } - if ($new_id_address_delivery == $old_id_address_delivery) - return false; + if ($new_id_address_delivery == $old_id_address_delivery) { + return false; + } - // Checking if the product with the old address delivery exists - $sql = new DbQuery(); - $sql->select('count(*)'); - $sql->from('cart_product', 'cp'); - $sql->where('id_product = '.(int)$id_product); - $sql->where('id_product_attribute = '.(int)$id_product_attribute); - $sql->where('id_address_delivery = '.(int)$old_id_address_delivery); - $sql->where('id_cart = '.(int)$this->id); - $result = Db::getInstance()->getValue($sql); + // Checking if the product with the old address delivery exists + $sql = new DbQuery(); + $sql->select('count(*)'); + $sql->from('cart_product', 'cp'); + $sql->where('id_product = '.(int)$id_product); + $sql->where('id_product_attribute = '.(int)$id_product_attribute); + $sql->where('id_address_delivery = '.(int)$old_id_address_delivery); + $sql->where('id_cart = '.(int)$this->id); + $result = Db::getInstance()->getValue($sql); - if ($result == 0) - return false; + if ($result == 0) { + return false; + } - // Checking if there is no others similar products with this new address delivery - $sql = new DbQuery(); - $sql->select('sum(quantity) as qty'); - $sql->from('cart_product', 'cp'); - $sql->where('id_product = '.(int)$id_product); - $sql->where('id_product_attribute = '.(int)$id_product_attribute); - $sql->where('id_address_delivery = '.(int)$new_id_address_delivery); - $sql->where('id_cart = '.(int)$this->id); - $result = Db::getInstance()->getValue($sql); + // Checking if there is no others similar products with this new address delivery + $sql = new DbQuery(); + $sql->select('sum(quantity) as qty'); + $sql->from('cart_product', 'cp'); + $sql->where('id_product = '.(int)$id_product); + $sql->where('id_product_attribute = '.(int)$id_product_attribute); + $sql->where('id_address_delivery = '.(int)$new_id_address_delivery); + $sql->where('id_cart = '.(int)$this->id); + $result = Db::getInstance()->getValue($sql); - // Removing similar products with this new address delivery - $sql = 'DELETE FROM '._DB_PREFIX_.'cart_product + // Removing similar products with this new address delivery + $sql = 'DELETE FROM '._DB_PREFIX_.'cart_product WHERE id_product = '.(int)$id_product.' AND id_product_attribute = '.(int)$id_product_attribute.' AND id_address_delivery = '.(int)$new_id_address_delivery.' AND id_cart = '.(int)$this->id.' LIMIT 1'; - Db::getInstance()->execute($sql); + Db::getInstance()->execute($sql); - // Changing the address - $sql = 'UPDATE '._DB_PREFIX_.'cart_product + // Changing the address + $sql = 'UPDATE '._DB_PREFIX_.'cart_product SET `id_address_delivery` = '.(int)$new_id_address_delivery.', `quantity` = `quantity` + '.(int)$result.' WHERE id_product = '.(int)$id_product.' @@ -3588,42 +3666,44 @@ class CartCore extends ObjectModel AND id_address_delivery = '.(int)$old_id_address_delivery.' AND id_cart = '.(int)$this->id.' LIMIT 1'; - Db::getInstance()->execute($sql); + Db::getInstance()->execute($sql); - // Changing the address of the customizations - $sql = 'UPDATE '._DB_PREFIX_.'customization + // Changing the address of the customizations + $sql = 'UPDATE '._DB_PREFIX_.'customization SET `id_address_delivery` = '.(int)$new_id_address_delivery.' WHERE id_product = '.(int)$id_product.' AND id_product_attribute = '.(int)$id_product_attribute.' AND id_address_delivery = '.(int)$old_id_address_delivery.' AND id_cart = '.(int)$this->id; - Db::getInstance()->execute($sql); + Db::getInstance()->execute($sql); - return true; - } + return true; + } - public function duplicateProduct($id_product, $id_product_attribute, $id_address_delivery, - $new_id_address_delivery, $quantity = 1, $keep_quantity = false) - { - // Check address is linked with the customer - if (!Customer::customerHasAddress(Context::getContext()->customer->id, $new_id_address_delivery)) - return false; + public function duplicateProduct($id_product, $id_product_attribute, $id_address_delivery, + $new_id_address_delivery, $quantity = 1, $keep_quantity = false) + { + // Check address is linked with the customer + if (!Customer::customerHasAddress(Context::getContext()->customer->id, $new_id_address_delivery)) { + return false; + } - // Checking the product do not exist with the new address - $sql = new DbQuery(); - $sql->select('count(*)'); - $sql->from('cart_product', 'c'); - $sql->where('id_product = '.(int)$id_product); - $sql->where('id_product_attribute = '.(int)$id_product_attribute); - $sql->where('id_address_delivery = '.(int)$new_id_address_delivery); - $sql->where('id_cart = '.(int)$this->id); - $result = Db::getInstance()->getValue($sql); + // Checking the product do not exist with the new address + $sql = new DbQuery(); + $sql->select('count(*)'); + $sql->from('cart_product', 'c'); + $sql->where('id_product = '.(int)$id_product); + $sql->where('id_product_attribute = '.(int)$id_product_attribute); + $sql->where('id_address_delivery = '.(int)$new_id_address_delivery); + $sql->where('id_cart = '.(int)$this->id); + $result = Db::getInstance()->getValue($sql); - if ($result > 0) - return false; + if ($result > 0) { + return false; + } - // Duplicating cart_product line - $sql = 'INSERT INTO '._DB_PREFIX_.'cart_product + // Duplicating cart_product line + $sql = 'INSERT INTO '._DB_PREFIX_.'cart_product (`id_cart`, `id_product`, `id_shop`, `id_product_attribute`, `quantity`, `date_add`, `id_address_delivery`) values( '.(int)$this->id.', @@ -3634,46 +3714,43 @@ class CartCore extends ObjectModel NOW(), '.(int)$new_id_address_delivery.')'; - Db::getInstance()->execute($sql); + Db::getInstance()->execute($sql); - if (!$keep_quantity) - { - $sql = new DbQuery(); - $sql->select('quantity'); - $sql->from('cart_product', 'c'); - $sql->where('id_product = '.(int)$id_product); - $sql->where('id_product_attribute = '.(int)$id_product_attribute); - $sql->where('id_address_delivery = '.(int)$id_address_delivery); - $sql->where('id_cart = '.(int)$this->id); - $duplicatedQuantity = Db::getInstance()->getValue($sql); + if (!$keep_quantity) { + $sql = new DbQuery(); + $sql->select('quantity'); + $sql->from('cart_product', 'c'); + $sql->where('id_product = '.(int)$id_product); + $sql->where('id_product_attribute = '.(int)$id_product_attribute); + $sql->where('id_address_delivery = '.(int)$id_address_delivery); + $sql->where('id_cart = '.(int)$this->id); + $duplicatedQuantity = Db::getInstance()->getValue($sql); - if ($duplicatedQuantity > $quantity) - { - $sql = 'UPDATE '._DB_PREFIX_.'cart_product + if ($duplicatedQuantity > $quantity) { + $sql = 'UPDATE '._DB_PREFIX_.'cart_product SET `quantity` = `quantity` - '.(int)$quantity.' WHERE id_cart = '.(int)$this->id.' AND id_product = '.(int)$id_product.' AND id_shop = '.(int)$this->id_shop.' AND id_product_attribute = '.(int)$id_product_attribute.' AND id_address_delivery = '.(int)$id_address_delivery; - Db::getInstance()->execute($sql); - } - } + Db::getInstance()->execute($sql); + } + } - // Checking if there is customizations - $sql = new DbQuery(); - $sql->select('*'); - $sql->from('customization', 'c'); - $sql->where('id_product = '.(int)$id_product); - $sql->where('id_product_attribute = '.(int)$id_product_attribute); - $sql->where('id_address_delivery = '.(int)$id_address_delivery); - $sql->where('id_cart = '.(int)$this->id); - $results = Db::getInstance()->executeS($sql); + // Checking if there is customizations + $sql = new DbQuery(); + $sql->select('*'); + $sql->from('customization', 'c'); + $sql->where('id_product = '.(int)$id_product); + $sql->where('id_product_attribute = '.(int)$id_product_attribute); + $sql->where('id_address_delivery = '.(int)$id_address_delivery); + $sql->where('id_cart = '.(int)$this->id); + $results = Db::getInstance()->executeS($sql); - foreach ($results as $customization) - { - // Duplicate customization - $sql = 'INSERT INTO '._DB_PREFIX_.'customization + foreach ($results as $customization) { + // Duplicate customization + $sql = 'INSERT INTO '._DB_PREFIX_.'customization (`id_product_attribute`, `id_address_delivery`, `id_cart`, `id_product`, `quantity`, `in_cart`) VALUES ( '.(int)$customization['id_product_attribute'].', @@ -3683,70 +3760,67 @@ class CartCore extends ObjectModel '.(int)$quantity.', '.(int)$customization['in_cart'].')'; - Db::getInstance()->execute($sql); + Db::getInstance()->execute($sql); - // Save last insert ID before doing another query - $last_id = (int)Db::getInstance()->Insert_ID(); + // Save last insert ID before doing another query + $last_id = (int)Db::getInstance()->Insert_ID(); - // Get data from duplicated customizations - $sql = new DbQuery(); - $sql->select('`type`, `index`, `value`'); - $sql->from('customized_data'); - $sql->where('id_customization = '.$customization['id_customization']); - $last_row = Db::getInstance()->getRow($sql); + // Get data from duplicated customizations + $sql = new DbQuery(); + $sql->select('`type`, `index`, `value`'); + $sql->from('customized_data'); + $sql->where('id_customization = '.$customization['id_customization']); + $last_row = Db::getInstance()->getRow($sql); - // Insert new copied data with new customization ID into customized_data table - $last_row['id_customization'] = $last_id; - Db::getInstance()->insert('customized_data', $last_row); + // Insert new copied data with new customization ID into customized_data table + $last_row['id_customization'] = $last_id; + Db::getInstance()->insert('customized_data', $last_row); + } - } - - $customization_count = count($results); - if ($customization_count > 0) - { - $sql = 'UPDATE '._DB_PREFIX_.'cart_product + $customization_count = count($results); + if ($customization_count > 0) { + $sql = 'UPDATE '._DB_PREFIX_.'cart_product SET `quantity` = `quantity` + '.(int)$customization_count * $quantity.' WHERE id_cart = '.(int)$this->id.' AND id_product = '.(int)$id_product.' AND id_shop = '.(int)$this->id_shop.' AND id_product_attribute = '.(int)$id_product_attribute.' AND id_address_delivery = '.(int)$new_id_address_delivery; - Db::getInstance()->execute($sql); - } + Db::getInstance()->execute($sql); + } - return true; - } + return true; + } - /** - * Update products cart address delivery with the address delivery of the cart - */ - public function setNoMultishipping() - { - $emptyCache = false; - if (Configuration::get('PS_ALLOW_MULTISHIPPING')) - { - // Upgrading quantities - $sql = 'SELECT sum(`quantity`) as quantity, id_product, id_product_attribute, count(*) as count + /** + * Update products cart address delivery with the address delivery of the cart + */ + public function setNoMultishipping() + { + $emptyCache = false; + if (Configuration::get('PS_ALLOW_MULTISHIPPING')) { + // Upgrading quantities + $sql = 'SELECT sum(`quantity`) as quantity, id_product, id_product_attribute, count(*) as count FROM `'._DB_PREFIX_.'cart_product` WHERE `id_cart` = '.(int)$this->id.' AND `id_shop` = '.(int)$this->id_shop.' GROUP BY id_product, id_product_attribute HAVING count > 1'; - foreach (Db::getInstance()->executeS($sql) as $product) - { - $sql = 'UPDATE `'._DB_PREFIX_.'cart_product` + foreach (Db::getInstance()->executeS($sql) as $product) { + $sql = 'UPDATE `'._DB_PREFIX_.'cart_product` SET `quantity` = '.$product['quantity'].' WHERE `id_cart` = '.(int)$this->id.' AND `id_shop` = '.(int)$this->id_shop.' AND id_product = '.$product['id_product'].' AND id_product_attribute = '.$product['id_product_attribute']; - if (Db::getInstance()->execute($sql)) - $emptyCache = true; - } + if (Db::getInstance()->execute($sql)) { + $emptyCache = true; + } + } - // Merging multiple lines - $sql = 'DELETE cp1 + // Merging multiple lines + $sql = 'DELETE cp1 FROM `'._DB_PREFIX_.'cart_product` cp1 INNER JOIN `'._DB_PREFIX_.'cart_product` cp2 ON ( @@ -3756,11 +3830,11 @@ class CartCore extends ObjectModel AND (cp1.id_address_delivery <> cp2.id_address_delivery) AND (cp1.date_add > cp2.date_add) )'; - Db::getInstance()->execute($sql); - } + Db::getInstance()->execute($sql); + } - // Update delivery address for each product line - $sql = 'UPDATE `'._DB_PREFIX_.'cart_product` + // Update delivery address for each product line + $sql = 'UPDATE `'._DB_PREFIX_.'cart_product` SET `id_address_delivery` = ( SELECT `id_address_delivery` FROM `'._DB_PREFIX_.'cart` WHERE `id_cart` = '.(int)$this->id.' AND `id_shop` = '.(int)$this->id_shop.' @@ -3768,211 +3842,218 @@ class CartCore extends ObjectModel WHERE `id_cart` = '.(int)$this->id.' '.(Configuration::get('PS_ALLOW_MULTISHIPPING') ? ' AND `id_shop` = '.(int)$this->id_shop : ''); - $cache_id = 'Cart::setNoMultishipping'.(int)$this->id.'-'.(int)$this->id_shop.((isset($this->id_address_delivery) && $this->id_address_delivery) ? '-'.(int)$this->id_address_delivery : ''); - if (!Cache::isStored($cache_id)) - { - if ($result = (bool)Db::getInstance()->execute($sql)) - $emptyCache = true; - Cache::store($cache_id, $result); - } + $cache_id = 'Cart::setNoMultishipping'.(int)$this->id.'-'.(int)$this->id_shop.((isset($this->id_address_delivery) && $this->id_address_delivery) ? '-'.(int)$this->id_address_delivery : ''); + if (!Cache::isStored($cache_id)) { + if ($result = (bool)Db::getInstance()->execute($sql)) { + $emptyCache = true; + } + Cache::store($cache_id, $result); + } - if (Customization::isFeatureActive()) - Db::getInstance()->execute(' + if (Customization::isFeatureActive()) { + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'customization` SET `id_address_delivery` = ( SELECT `id_address_delivery` FROM `'._DB_PREFIX_.'cart` WHERE `id_cart` = '.(int)$this->id.' ) WHERE `id_cart` = '.(int)$this->id); + } - if ($emptyCache) - $this->_products = null; - } + if ($emptyCache) { + $this->_products = null; + } + } - /** - * Set an address to all products on the cart without address delivery - */ - public function autosetProductAddress() - { - $id_address_delivery = 0; - // Get the main address of the customer - if ((int)$this->id_address_delivery > 0) - $id_address_delivery = (int)$this->id_address_delivery; - else - $id_address_delivery = (int)Address::getFirstCustomerAddressId(Context::getContext()->customer->id); + /** + * Set an address to all products on the cart without address delivery + */ + public function autosetProductAddress() + { + $id_address_delivery = 0; + // Get the main address of the customer + if ((int)$this->id_address_delivery > 0) { + $id_address_delivery = (int)$this->id_address_delivery; + } else { + $id_address_delivery = (int)Address::getFirstCustomerAddressId(Context::getContext()->customer->id); + } - if (!$id_address_delivery) - return; + if (!$id_address_delivery) { + return; + } - // Update - $sql = 'UPDATE `'._DB_PREFIX_.'cart_product` + // Update + $sql = 'UPDATE `'._DB_PREFIX_.'cart_product` SET `id_address_delivery` = '.(int)$id_address_delivery.' WHERE `id_cart` = '.(int)$this->id.' AND (`id_address_delivery` = 0 OR `id_address_delivery` IS NULL) AND `id_shop` = '.(int)$this->id_shop; - Db::getInstance()->execute($sql); + Db::getInstance()->execute($sql); - $sql = 'UPDATE `'._DB_PREFIX_.'customization` + $sql = 'UPDATE `'._DB_PREFIX_.'customization` SET `id_address_delivery` = '.(int)$id_address_delivery.' WHERE `id_cart` = '.(int)$this->id.' AND (`id_address_delivery` = 0 OR `id_address_delivery` IS NULL)'; - Db::getInstance()->execute($sql); - } + Db::getInstance()->execute($sql); + } - public function deleteAssociations() - { - return (Db::getInstance()->execute(' + public function deleteAssociations() + { + return (Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'cart_product` WHERE `id_cart` = '.(int)$this->id) !== false); - } + } - /** - * isGuestCartByCartId - * - * @param int $id_cart - * @return bool true if cart has been made by a guest customer - */ - public static function isGuestCartByCartId($id_cart) - { - if (!(int)$id_cart) - return false; - return (bool)Db::getInstance()->getValue(' + /** + * isGuestCartByCartId + * + * @param int $id_cart + * @return bool true if cart has been made by a guest customer + */ + public static function isGuestCartByCartId($id_cart) + { + if (!(int)$id_cart) { + return false; + } + return (bool)Db::getInstance()->getValue(' SELECT `is_guest` FROM `'._DB_PREFIX_.'customer` cu LEFT JOIN `'._DB_PREFIX_.'cart` ca ON (ca.`id_customer` = cu.`id_customer`) WHERE ca.`id_cart` = '.(int)$id_cart); - } + } - /** - * isCarrierInRange - * - * Check if the specified carrier is in range - * - * @id_carrier int - * @id_zone int - */ - public function isCarrierInRange($id_carrier, $id_zone) - { - $carrier = new Carrier((int)$id_carrier, Configuration::get('PS_LANG_DEFAULT')); - $shipping_method = $carrier->getShippingMethod(); - if (!$carrier->range_behavior) - return true; + /** + * isCarrierInRange + * + * Check if the specified carrier is in range + * + * @id_carrier int + * @id_zone int + */ + public function isCarrierInRange($id_carrier, $id_zone) + { + $carrier = new Carrier((int)$id_carrier, Configuration::get('PS_LANG_DEFAULT')); + $shipping_method = $carrier->getShippingMethod(); + if (!$carrier->range_behavior) { + return true; + } - if ($shipping_method == Carrier::SHIPPING_METHOD_FREE) - return true; + if ($shipping_method == Carrier::SHIPPING_METHOD_FREE) { + return true; + } - $check_delivery_price_by_weight = Carrier::checkDeliveryPriceByWeight( - (int)$id_carrier, - $this->getTotalWeight(), - $id_zone - ); - if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && $check_delivery_price_by_weight) - return true; + $check_delivery_price_by_weight = Carrier::checkDeliveryPriceByWeight( + (int)$id_carrier, + $this->getTotalWeight(), + $id_zone + ); + if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && $check_delivery_price_by_weight) { + return true; + } - $check_delivery_price_by_price = Carrier::checkDeliveryPriceByPrice( - (int)$id_carrier, - $this->getOrderTotal( - true, - Cart::BOTH_WITHOUT_SHIPPING - ), - $id_zone, - (int)$this->id_currency - ); - if ($shipping_method == Carrier::SHIPPING_METHOD_PRICE && $check_delivery_price_by_price) - return true; + $check_delivery_price_by_price = Carrier::checkDeliveryPriceByPrice( + (int)$id_carrier, + $this->getOrderTotal( + true, + Cart::BOTH_WITHOUT_SHIPPING + ), + $id_zone, + (int)$this->id_currency + ); + if ($shipping_method == Carrier::SHIPPING_METHOD_PRICE && $check_delivery_price_by_price) { + return true; + } - return false; - } + return false; + } - /** - * @param bool $ignore_virtual Ignore virtual product - * @param bool $exclusive If true, the validation is exclusive : it must be present product in stock and out of stock - * @since 1.5.0 - * - * @return bool false is some products from the cart are out of stock - */ - public function isAllProductsInStock($ignore_virtual = false, $exclusive = false) - { - $product_out_of_stock = 0; - $product_in_stock = 0; - foreach ($this->getProducts() as $product) - { - if (!$exclusive) - { - if (((int)$product['quantity_available'] - (int)$product['cart_quantity']) <= 0 - && (!$ignore_virtual || !$product['is_virtual'])) - return false; - } - else - { - if ((int)$product['quantity_available'] <= 0 - && (!$ignore_virtual || !$product['is_virtual'])) - $product_out_of_stock++; - if ((int)$product['quantity_available'] > 0 - && (!$ignore_virtual || !$product['is_virtual'])) - $product_in_stock++; + /** + * @param bool $ignore_virtual Ignore virtual product + * @param bool $exclusive If true, the validation is exclusive : it must be present product in stock and out of stock + * @since 1.5.0 + * + * @return bool false is some products from the cart are out of stock + */ + public function isAllProductsInStock($ignore_virtual = false, $exclusive = false) + { + $product_out_of_stock = 0; + $product_in_stock = 0; + foreach ($this->getProducts() as $product) { + if (!$exclusive) { + if (((int)$product['quantity_available'] - (int)$product['cart_quantity']) <= 0 + && (!$ignore_virtual || !$product['is_virtual'])) { + return false; + } + } else { + if ((int)$product['quantity_available'] <= 0 + && (!$ignore_virtual || !$product['is_virtual'])) { + $product_out_of_stock++; + } + if ((int)$product['quantity_available'] > 0 + && (!$ignore_virtual || !$product['is_virtual'])) { + $product_in_stock++; + } - if ($product_in_stock > 0 && $product_out_of_stock > 0) - return false; - } - } - return true; - } + if ($product_in_stock > 0 && $product_out_of_stock > 0) { + return false; + } + } + } + return true; + } - /** - * - * Execute hook displayCarrierList (extraCarrier) and merge theme to the $array - * @param array $array - */ - public static function addExtraCarriers(&$array) - { - $first = true; - $hook_extracarrier_addr = array(); - foreach (Context::getContext()->cart->getAddressCollection() as $address) - { - $hook = Hook::exec('displayCarrierList', array('address' => $address)); - $hook_extracarrier_addr[$address->id] = $hook; + /** + * + * Execute hook displayCarrierList (extraCarrier) and merge theme to the $array + * @param array $array + */ + public static function addExtraCarriers(&$array) + { + $first = true; + $hook_extracarrier_addr = array(); + foreach (Context::getContext()->cart->getAddressCollection() as $address) { + $hook = Hook::exec('displayCarrierList', array('address' => $address)); + $hook_extracarrier_addr[$address->id] = $hook; - if ($first) - { - $array = array_merge( - $array, - array('HOOK_EXTRACARRIER' => $hook) - ); - $first = false; - } - $array = array_merge( - $array, - array('HOOK_EXTRACARRIER_ADDR' => $hook_extracarrier_addr) - ); - } - } + if ($first) { + $array = array_merge( + $array, + array('HOOK_EXTRACARRIER' => $hook) + ); + $first = false; + } + $array = array_merge( + $array, + array('HOOK_EXTRACARRIER_ADDR' => $hook_extracarrier_addr) + ); + } + } - /** - * Get all the ids of the delivery addresses without carriers - * - * @param bool $return_collection Return a collection - * @param array &$error contain an error message if an error occurs - * @return array Array of address id or of address object - */ - public function getDeliveryAddressesWithoutCarriers($return_collection = false, &$error = array()) - { - $addresses_without_carriers = array(); - foreach ($this->getProducts() as $product) - { - if (!in_array($product['id_address_delivery'], $addresses_without_carriers) - && !count(Carrier::getAvailableCarrierList(new Product($product['id_product']), null, $product['id_address_delivery'], null, null, $error))) - $addresses_without_carriers[] = $product['id_address_delivery']; - } - if (!$return_collection) - return $addresses_without_carriers; - else - { - $addresses_instance_without_carriers = array(); - foreach ($addresses_without_carriers as $id_address) - $addresses_instance_without_carriers[] = new Address($id_address); - return $addresses_instance_without_carriers; - } - } + /** + * Get all the ids of the delivery addresses without carriers + * + * @param bool $return_collection Return a collection + * @param array &$error contain an error message if an error occurs + * @return array Array of address id or of address object + */ + public function getDeliveryAddressesWithoutCarriers($return_collection = false, &$error = array()) + { + $addresses_without_carriers = array(); + foreach ($this->getProducts() as $product) { + if (!in_array($product['id_address_delivery'], $addresses_without_carriers) + && !count(Carrier::getAvailableCarrierList(new Product($product['id_product']), null, $product['id_address_delivery'], null, null, $error))) { + $addresses_without_carriers[] = $product['id_address_delivery']; + } + } + if (!$return_collection) { + return $addresses_without_carriers; + } else { + $addresses_instance_without_carriers = array(); + foreach ($addresses_without_carriers as $id_address) { + $addresses_instance_without_carriers[] = new Address($id_address); + } + return $addresses_instance_without_carriers; + } + } } diff --git a/classes/CartRule.php b/classes/CartRule.php index ff3410fb..60941a3d 100644 --- a/classes/CartRule.php +++ b/classes/CartRule.php @@ -26,470 +26,491 @@ class CartRuleCore extends ObjectModel { - /* Filters used when retrieving the cart rules applied to a cart of when calculating the value of a reduction */ - const FILTER_ACTION_ALL = 1; - const FILTER_ACTION_SHIPPING = 2; - const FILTER_ACTION_REDUCTION = 3; - const FILTER_ACTION_GIFT = 4; - const FILTER_ACTION_ALL_NOCAP = 5; + /* Filters used when retrieving the cart rules applied to a cart of when calculating the value of a reduction */ + const FILTER_ACTION_ALL = 1; + const FILTER_ACTION_SHIPPING = 2; + const FILTER_ACTION_REDUCTION = 3; + const FILTER_ACTION_GIFT = 4; + const FILTER_ACTION_ALL_NOCAP = 5; - const BO_ORDER_CODE_PREFIX = 'BO_ORDER_'; + const BO_ORDER_CODE_PREFIX = 'BO_ORDER_'; - /* This variable controls that a free gift is offered only once, even when multi-shippping is activated and the same product is delivered in both addresses */ - protected static $only_one_gift = array(); + /* This variable controls that a free gift is offered only once, even when multi-shippping is activated and the same product is delivered in both addresses */ + protected static $only_one_gift = array(); - public $id; - public $name; - public $id_customer; - public $date_from; - public $date_to; - public $description; - public $quantity = 1; - public $quantity_per_user = 1; - public $priority = 1; - public $partial_use = 1; - public $code; - public $minimum_amount; - public $minimum_amount_tax; - public $minimum_amount_currency; - public $minimum_amount_shipping; - public $country_restriction; - public $carrier_restriction; - public $group_restriction; - public $cart_rule_restriction; - public $product_restriction; - public $shop_restriction; - public $free_shipping; - public $reduction_percent; - public $reduction_amount; - public $reduction_tax; - public $reduction_currency; - public $reduction_product; - public $gift_product; - public $gift_product_attribute; - public $highlight; - public $active = 1; - public $date_add; - public $date_upd; + public $id; + public $name; + public $id_customer; + public $date_from; + public $date_to; + public $description; + public $quantity = 1; + public $quantity_per_user = 1; + public $priority = 1; + public $partial_use = 1; + public $code; + public $minimum_amount; + public $minimum_amount_tax; + public $minimum_amount_currency; + public $minimum_amount_shipping; + public $country_restriction; + public $carrier_restriction; + public $group_restriction; + public $cart_rule_restriction; + public $product_restriction; + public $shop_restriction; + public $free_shipping; + public $reduction_percent; + public $reduction_amount; + public $reduction_tax; + public $reduction_currency; + public $reduction_product; + public $gift_product; + public $gift_product_attribute; + public $highlight; + public $active = 1; + public $date_add; + public $date_upd; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'cart_rule', - 'primary' => 'id_cart_rule', - 'multilang' => true, - 'fields' => array( - 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'date_from' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), - 'date_to' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), - 'description' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 65534), - 'quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'quantity_per_user' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'priority' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'partial_use' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'code' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 254), - 'minimum_amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'minimum_amount_tax' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'minimum_amount_currency' =>array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'minimum_amount_shipping' =>array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'country_restriction' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'carrier_restriction' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'group_restriction' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'cart_rule_restriction' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'product_restriction' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'shop_restriction' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'free_shipping' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'reduction_percent' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPercentage'), - 'reduction_amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'reduction_tax' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'reduction_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'reduction_product' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'gift_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'gift_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'highlight' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'cart_rule', + 'primary' => 'id_cart_rule', + 'multilang' => true, + 'fields' => array( + 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'date_from' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), + 'date_to' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), + 'description' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 65534), + 'quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'quantity_per_user' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'priority' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'partial_use' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'code' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 254), + 'minimum_amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'minimum_amount_tax' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'minimum_amount_currency' =>array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'minimum_amount_shipping' =>array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'country_restriction' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'carrier_restriction' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'group_restriction' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'cart_rule_restriction' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'product_restriction' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'shop_restriction' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'free_shipping' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'reduction_percent' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPercentage'), + 'reduction_amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'reduction_tax' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'reduction_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'reduction_product' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'gift_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'gift_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'highlight' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCleanHtml', 'required' => true, 'size' => 254), - ), - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCleanHtml', 'required' => true, 'size' => 254), + ), + ); - /** - * @see ObjectModel::add() - */ - public function add($autodate = true, $null_values = false) - { - if (!$this->reduction_currency) - $this->reduction_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT'); + /** + * @see ObjectModel::add() + */ + public function add($autodate = true, $null_values = false) + { + if (!$this->reduction_currency) { + $this->reduction_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT'); + } - if (!parent::add($autodate, $null_values)) - return false; + if (!parent::add($autodate, $null_values)) { + return false; + } - Configuration::updateGlobalValue('PS_CART_RULE_FEATURE_ACTIVE', '1'); - return true; - } + Configuration::updateGlobalValue('PS_CART_RULE_FEATURE_ACTIVE', '1'); + return true; + } - public function update($null_values = false) - { - Cache::clean('getContextualValue_'.$this->id.'_*'); + public function update($null_values = false) + { + Cache::clean('getContextualValue_'.$this->id.'_*'); - if (!$this->reduction_currency) - $this->reduction_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT'); + if (!$this->reduction_currency) { + $this->reduction_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT'); + } - return parent::update($null_values); - } + return parent::update($null_values); + } - /** - * @see ObjectModel::delete() - */ - public function delete() - { - if (!parent::delete()) - return false; + /** + * @see ObjectModel::delete() + */ + public function delete() + { + if (!parent::delete()) { + return false; + } - Configuration::updateGlobalValue('PS_CART_RULE_FEATURE_ACTIVE', CartRule::isCurrentlyUsed($this->def['table'], true)); + Configuration::updateGlobalValue('PS_CART_RULE_FEATURE_ACTIVE', CartRule::isCurrentlyUsed($this->def['table'], true)); - $r = Db::getInstance()->delete('cart_cart_rule', '`id_cart_rule` = '.(int)$this->id); - $r &= Db::getInstance()->delete('cart_rule_carrier', '`id_cart_rule` = '.(int)$this->id); - $r &= Db::getInstance()->delete('cart_rule_shop', '`id_cart_rule` = '.(int)$this->id); - $r &= Db::getInstance()->delete('cart_rule_group', '`id_cart_rule` = '.(int)$this->id); - $r &= Db::getInstance()->delete('cart_rule_country', '`id_cart_rule` = '.(int)$this->id); - $r &= Db::getInstance()->delete('cart_rule_combination', '`id_cart_rule_1` = '.(int)$this->id.' OR `id_cart_rule_2` = '.(int)$this->id); - $r &= Db::getInstance()->delete('cart_rule_product_rule_group', '`id_cart_rule` = '.(int)$this->id); - $r &= Db::getInstance()->delete('cart_rule_product_rule', 'NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'cart_rule_product_rule_group` + $r = Db::getInstance()->delete('cart_cart_rule', '`id_cart_rule` = '.(int)$this->id); + $r &= Db::getInstance()->delete('cart_rule_carrier', '`id_cart_rule` = '.(int)$this->id); + $r &= Db::getInstance()->delete('cart_rule_shop', '`id_cart_rule` = '.(int)$this->id); + $r &= Db::getInstance()->delete('cart_rule_group', '`id_cart_rule` = '.(int)$this->id); + $r &= Db::getInstance()->delete('cart_rule_country', '`id_cart_rule` = '.(int)$this->id); + $r &= Db::getInstance()->delete('cart_rule_combination', '`id_cart_rule_1` = '.(int)$this->id.' OR `id_cart_rule_2` = '.(int)$this->id); + $r &= Db::getInstance()->delete('cart_rule_product_rule_group', '`id_cart_rule` = '.(int)$this->id); + $r &= Db::getInstance()->delete('cart_rule_product_rule', 'NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'cart_rule_product_rule_group` WHERE `'._DB_PREFIX_.'cart_rule_product_rule`.`id_product_rule_group` = `'._DB_PREFIX_.'cart_rule_product_rule_group`.`id_product_rule_group`)'); - $r &= Db::getInstance()->delete('cart_rule_product_rule_value', 'NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'cart_rule_product_rule` + $r &= Db::getInstance()->delete('cart_rule_product_rule_value', 'NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'cart_rule_product_rule` WHERE `'._DB_PREFIX_.'cart_rule_product_rule_value`.`id_product_rule` = `'._DB_PREFIX_.'cart_rule_product_rule`.`id_product_rule`)'); - return $r; - } + return $r; + } - /** - * Copy conditions from one cart rule to an other - * - * @param int $id_cart_rule_source - * @param int $id_cart_rule_destination - */ - public static function copyConditions($id_cart_rule_source, $id_cart_rule_destination) - { - Db::getInstance()->execute(' + /** + * Copy conditions from one cart rule to an other + * + * @param int $id_cart_rule_source + * @param int $id_cart_rule_destination + */ + public static function copyConditions($id_cart_rule_source, $id_cart_rule_destination) + { + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'cart_rule_shop` (`id_cart_rule`, `id_shop`) (SELECT '.(int)$id_cart_rule_destination.', id_shop FROM `'._DB_PREFIX_.'cart_rule_shop` WHERE `id_cart_rule` = '.(int)$id_cart_rule_source.')'); - Db::getInstance()->execute(' + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'cart_rule_carrier` (`id_cart_rule`, `id_carrier`) (SELECT '.(int)$id_cart_rule_destination.', id_carrier FROM `'._DB_PREFIX_.'cart_rule_carrier` WHERE `id_cart_rule` = '.(int)$id_cart_rule_source.')'); - Db::getInstance()->execute(' + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'cart_rule_group` (`id_cart_rule`, `id_group`) (SELECT '.(int)$id_cart_rule_destination.', id_group FROM `'._DB_PREFIX_.'cart_rule_group` WHERE `id_cart_rule` = '.(int)$id_cart_rule_source.')'); - Db::getInstance()->execute(' + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'cart_rule_country` (`id_cart_rule`, `id_country`) (SELECT '.(int)$id_cart_rule_destination.', id_country FROM `'._DB_PREFIX_.'cart_rule_country` WHERE `id_cart_rule` = '.(int)$id_cart_rule_source.')'); - Db::getInstance()->execute(' + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'cart_rule_combination` (`id_cart_rule_1`, `id_cart_rule_2`) (SELECT '.(int)$id_cart_rule_destination.', IF(id_cart_rule_1 != '.(int)$id_cart_rule_source.', id_cart_rule_1, id_cart_rule_2) FROM `'._DB_PREFIX_.'cart_rule_combination` WHERE `id_cart_rule_1` = '.(int)$id_cart_rule_source.' OR `id_cart_rule_2` = '.(int)$id_cart_rule_source.')'); - // Todo : should be changed soon, be must be copied too - // Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cart_rule_product_rule` WHERE `id_cart_rule` = '.(int)$this->id); - // Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cart_rule_product_rule_value` WHERE `id_product_rule` NOT IN (SELECT `id_product_rule` FROM `'._DB_PREFIX_.'cart_rule_product_rule`)'); + // Todo : should be changed soon, be must be copied too + // Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cart_rule_product_rule` WHERE `id_cart_rule` = '.(int)$this->id); + // Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cart_rule_product_rule_value` WHERE `id_product_rule` NOT IN (SELECT `id_product_rule` FROM `'._DB_PREFIX_.'cart_rule_product_rule`)'); - // Copy products/category filters - $products_rules_group_source = Db::getInstance()->ExecuteS(' + // Copy products/category filters + $products_rules_group_source = Db::getInstance()->ExecuteS(' SELECT id_product_rule_group,quantity FROM `'._DB_PREFIX_.'cart_rule_product_rule_group` WHERE `id_cart_rule` = '.(int)$id_cart_rule_source.' '); - foreach ($products_rules_group_source as $product_rule_group_source) - { - Db::getInstance()->execute(' + foreach ($products_rules_group_source as $product_rule_group_source) { + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'cart_rule_product_rule_group` (`id_cart_rule`, `quantity`) VALUES ('.(int)$id_cart_rule_destination.','.(int)$product_rule_group_source['quantity'].')'); - $id_product_rule_group_destination = Db::getInstance()->Insert_ID(); + $id_product_rule_group_destination = Db::getInstance()->Insert_ID(); - $products_rules_source = Db::getInstance()->ExecuteS(' + $products_rules_source = Db::getInstance()->ExecuteS(' SELECT id_product_rule,type FROM `'._DB_PREFIX_.'cart_rule_product_rule` WHERE `id_product_rule_group` = '.(int)$product_rule_group_source['id_product_rule_group'].' '); - foreach ($products_rules_source as $product_rule_source) - { - Db::getInstance()->execute(' + foreach ($products_rules_source as $product_rule_source) { + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'cart_rule_product_rule` (`id_product_rule_group`, `type`) VALUES ('.(int)$id_product_rule_group_destination.',"'.pSQL($product_rule_source['type']).'")'); - $id_product_rule_destination = Db::getInstance()->Insert_ID(); + $id_product_rule_destination = Db::getInstance()->Insert_ID(); - $products_rules_values_source = Db::getInstance()->ExecuteS(' + $products_rules_values_source = Db::getInstance()->ExecuteS(' SELECT id_item FROM `'._DB_PREFIX_.'cart_rule_product_rule_value` WHERE `id_product_rule` = '.(int)$product_rule_source['id_product_rule'].' '); - foreach ($products_rules_values_source as $product_rule_value_source) - Db::getInstance()->execute(' + foreach ($products_rules_values_source as $product_rule_value_source) { + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'cart_rule_product_rule_value` (`id_product_rule`, `id_item`) VALUES ('.(int)$id_product_rule_destination.','.(int)$product_rule_value_source['id_item'].')'); - } - } - } + } + } + } + } - /** - * Retrieves the id associated to the given code - * - * @param string $code - * @return int|bool - */ - public static function getIdByCode($code) - { - if (!Validate::isCleanHtml($code)) - return false; - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT `id_cart_rule` FROM `'._DB_PREFIX_.'cart_rule` WHERE `code` = \''.pSQL($code).'\''); - } + /** + * Retrieves the id associated to the given code + * + * @param string $code + * @return int|bool + */ + public static function getIdByCode($code) + { + if (!Validate::isCleanHtml($code)) { + return false; + } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT `id_cart_rule` FROM `'._DB_PREFIX_.'cart_rule` WHERE `code` = \''.pSQL($code).'\''); + } - /** - * @param $id_lang - * @param $id_customer - * @param bool $active - * @param bool $includeGeneric - * @param bool $inStock - * @param Cart|null $cart - * @param bool $free_shipping_only - * @param bool $highlight_only - * @return array - * @throws PrestaShopDatabaseException - */ - public static function getCustomerCartRules($id_lang, $id_customer, $active = false, $includeGeneric = true, $inStock = false, Cart $cart = null, $free_shipping_only = false, $highlight_only = false) - { - if (!CartRule::isFeatureActive()) - return array(); + /** + * @param $id_lang + * @param $id_customer + * @param bool $active + * @param bool $includeGeneric + * @param bool $inStock + * @param Cart|null $cart + * @param bool $free_shipping_only + * @param bool $highlight_only + * @return array + * @throws PrestaShopDatabaseException + */ + public static function getCustomerCartRules($id_lang, $id_customer, $active = false, $includeGeneric = true, $inStock = false, Cart $cart = null, $free_shipping_only = false, $highlight_only = false) + { + if (!CartRule::isFeatureActive()) { + return array(); + } - $sql_part1 = '* FROM `'._DB_PREFIX_.'cart_rule` cr + $sql_part1 = '* FROM `'._DB_PREFIX_.'cart_rule` cr LEFT JOIN `'._DB_PREFIX_.'cart_rule_lang` crl ON (cr.`id_cart_rule` = crl.`id_cart_rule` AND crl.`id_lang` = '.(int)$id_lang.')'; - $sql_part2 = ' AND cr.date_from < "'.date('Y-m-d H:i:s').'" + $sql_part2 = ' AND cr.date_from < "'.date('Y-m-d H:i:s').'" AND cr.date_to > "'.date('Y-m-d H:i:s').'" '.($active ? 'AND cr.`active` = 1' : '').' '.($inStock ? 'AND cr.`quantity` > 0' : ''); - if ($free_shipping_only) - $sql_part2 .= ' AND free_shipping = 1 AND carrier_restriction = 1'; + if ($free_shipping_only) { + $sql_part2 .= ' AND free_shipping = 1 AND carrier_restriction = 1'; + } - if ($highlight_only) - $sql_part2 .= ' AND highlight = 1 AND code NOT LIKE "'.pSQL(CartRule::BO_ORDER_CODE_PREFIX).'%"'; + if ($highlight_only) { + $sql_part2 .= ' AND highlight = 1 AND code NOT LIKE "'.pSQL(CartRule::BO_ORDER_CODE_PREFIX).'%"'; + } - $sql = '(SELECT SQL_NO_CACHE '.$sql_part1.' WHERE cr.`id_customer` = '.(int)$id_customer.' '.$sql_part2.')'; - $sql .= ' UNION (SELECT '.$sql_part1.' WHERE cr.`group_restriction` = 1 '.$sql_part2.')'; - if ($includeGeneric && (int)$id_customer != 0) - $sql .= ' UNION (SELECT '.$sql_part1.' WHERE cr.`id_customer` = 0 '.$sql_part2.')'; + $sql = '(SELECT SQL_NO_CACHE '.$sql_part1.' WHERE cr.`id_customer` = '.(int)$id_customer.' '.$sql_part2.')'; + $sql .= ' UNION (SELECT '.$sql_part1.' WHERE cr.`group_restriction` = 1 '.$sql_part2.')'; + if ($includeGeneric && (int)$id_customer != 0) { + $sql .= ' UNION (SELECT '.$sql_part1.' WHERE cr.`id_customer` = 0 '.$sql_part2.')'; + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false); - if (empty($result)) - return array(); + if (empty($result)) { + return array(); + } - // Remove cart rule that does not match the customer groups - $customerGroups = Customer::getGroupsStatic($id_customer); + // Remove cart rule that does not match the customer groups + $customerGroups = Customer::getGroupsStatic($id_customer); - foreach ($result as $key => $cart_rule) - if ($cart_rule['group_restriction']) - { - $cartRuleGroups = Db::getInstance()->executeS('SELECT id_group FROM '._DB_PREFIX_.'cart_rule_group WHERE id_cart_rule = '.(int)$cart_rule['id_cart_rule']); - foreach ($cartRuleGroups as $cartRuleGroup) - if (in_array($cartRuleGroup['id_group'], $customerGroups)) - continue 2; - unset($result[$key]); - } + foreach ($result as $key => $cart_rule) { + if ($cart_rule['group_restriction']) { + $cartRuleGroups = Db::getInstance()->executeS('SELECT id_group FROM '._DB_PREFIX_.'cart_rule_group WHERE id_cart_rule = '.(int)$cart_rule['id_cart_rule']); + foreach ($cartRuleGroups as $cartRuleGroup) { + if (in_array($cartRuleGroup['id_group'], $customerGroups)) { + continue 2; + } + } + unset($result[$key]); + } + } - foreach ($result as &$cart_rule) - if ($cart_rule['quantity_per_user']) - { - $quantity_used = Order::getDiscountsCustomer((int)$id_customer, (int)$cart_rule['id_cart_rule']); - if (isset($cart) && isset($cart->id)) - $quantity_used += $cart->getDiscountsCustomer((int)$cart_rule['id_cart_rule']); - $cart_rule['quantity_for_user'] = $cart_rule['quantity_per_user'] - $quantity_used; - } - else - $cart_rule['quantity_for_user'] = 0; - unset($cart_rule); + foreach ($result as &$cart_rule) { + if ($cart_rule['quantity_per_user']) { + $quantity_used = Order::getDiscountsCustomer((int)$id_customer, (int)$cart_rule['id_cart_rule']); + if (isset($cart) && isset($cart->id)) { + $quantity_used += $cart->getDiscountsCustomer((int)$cart_rule['id_cart_rule']); + } + $cart_rule['quantity_for_user'] = $cart_rule['quantity_per_user'] - $quantity_used; + } else { + $cart_rule['quantity_for_user'] = 0; + } + } + unset($cart_rule); - foreach ($result as $key => $cart_rule) - if ($cart_rule['shop_restriction']) - { - $cartRuleShops = Db::getInstance()->executeS('SELECT id_shop FROM '._DB_PREFIX_.'cart_rule_shop WHERE id_cart_rule = '.(int)$cart_rule['id_cart_rule']); - foreach ($cartRuleShops as $cartRuleShop) - if (Shop::isFeatureActive() && ($cartRuleShop['id_shop'] == Context::getContext()->shop->id)) - continue 2; - unset($result[$key]); - } + foreach ($result as $key => $cart_rule) { + if ($cart_rule['shop_restriction']) { + $cartRuleShops = Db::getInstance()->executeS('SELECT id_shop FROM '._DB_PREFIX_.'cart_rule_shop WHERE id_cart_rule = '.(int)$cart_rule['id_cart_rule']); + foreach ($cartRuleShops as $cartRuleShop) { + if (Shop::isFeatureActive() && ($cartRuleShop['id_shop'] == Context::getContext()->shop->id)) { + continue 2; + } + } + unset($result[$key]); + } + } - if (isset($cart) && isset($cart->id)) - foreach ($result as $key => $cart_rule) - if ($cart_rule['product_restriction']) - { - $cr = new CartRule((int)$cart_rule['id_cart_rule']); - $r = $cr->checkProductRestrictions(Context::getContext(), false, false); - if ($r !== false) - continue; - unset($result[$key]); - } + if (isset($cart) && isset($cart->id)) { + foreach ($result as $key => $cart_rule) { + if ($cart_rule['product_restriction']) { + $cr = new CartRule((int)$cart_rule['id_cart_rule']); + $r = $cr->checkProductRestrictions(Context::getContext(), false, false); + if ($r !== false) { + continue; + } + unset($result[$key]); + } + } + } - foreach ($result as $key => $cart_rule) - if ($cart_rule['country_restriction']) - { - $countries = Db::getInstance()->ExecuteS(' + foreach ($result as $key => $cart_rule) { + if ($cart_rule['country_restriction']) { + $countries = Db::getInstance()->ExecuteS(' SELECT `id_country` FROM `'._DB_PREFIX_.'address` WHERE `id_customer` = '.(int)$id_customer.' AND `deleted` = 0' - ); + ); - if (is_array($countries) && count($countries)) - foreach ($countries as $country) - { - $id_cart_rule = (bool)Db::getInstance()->getValue(' + if (is_array($countries) && count($countries)) { + foreach ($countries as $country) { + $id_cart_rule = (bool)Db::getInstance()->getValue(' SELECT crc.id_cart_rule FROM '._DB_PREFIX_.'cart_rule_country crc WHERE crc.id_cart_rule = '.(int)$cart_rule['id_cart_rule'].' AND crc.id_country = '.(int)$country['id_country']); - if (!$id_cart_rule) - unset($result[$key]); - } - } + if (!$id_cart_rule) { + unset($result[$key]); + } + } + } + } + } - // Retrocompatibility with 1.4 discounts - foreach ($result as &$cart_rule) - { - $cart_rule['value'] = 0; - $cart_rule['minimal'] = Tools::convertPriceFull($cart_rule['minimum_amount'], new Currency($cart_rule['minimum_amount_currency']), Context::getContext()->currency); - $cart_rule['cumulable'] = !$cart_rule['cart_rule_restriction']; - $cart_rule['id_discount_type'] = false; - if ($cart_rule['free_shipping']) - $cart_rule['id_discount_type'] = Discount::FREE_SHIPPING; - elseif ($cart_rule['reduction_percent'] > 0) - { - $cart_rule['id_discount_type'] = Discount::PERCENT; - $cart_rule['value'] = $cart_rule['reduction_percent']; - } - elseif ($cart_rule['reduction_amount'] > 0) - { - $cart_rule['id_discount_type'] = Discount::AMOUNT; - $cart_rule['value'] = $cart_rule['reduction_amount']; - } - } - unset($cart_rule); + // Retrocompatibility with 1.4 discounts + foreach ($result as &$cart_rule) { + $cart_rule['value'] = 0; + $cart_rule['minimal'] = Tools::convertPriceFull($cart_rule['minimum_amount'], new Currency($cart_rule['minimum_amount_currency']), Context::getContext()->currency); + $cart_rule['cumulable'] = !$cart_rule['cart_rule_restriction']; + $cart_rule['id_discount_type'] = false; + if ($cart_rule['free_shipping']) { + $cart_rule['id_discount_type'] = Discount::FREE_SHIPPING; + } elseif ($cart_rule['reduction_percent'] > 0) { + $cart_rule['id_discount_type'] = Discount::PERCENT; + $cart_rule['value'] = $cart_rule['reduction_percent']; + } elseif ($cart_rule['reduction_amount'] > 0) { + $cart_rule['id_discount_type'] = Discount::AMOUNT; + $cart_rule['value'] = $cart_rule['reduction_amount']; + } + } + unset($cart_rule); - return $result; - } + return $result; + } - /** - * @param $id_customer - * @return bool - */ - public function usedByCustomer($id_customer) - { - return (bool)Db::getInstance()->getValue(' + /** + * @param $id_customer + * @return bool + */ + public function usedByCustomer($id_customer) + { + return (bool)Db::getInstance()->getValue(' SELECT id_cart_rule FROM `'._DB_PREFIX_.'order_cart_rule` ocr LEFT JOIN `'._DB_PREFIX_.'orders` o ON ocr.`id_order` = o.`id_order` WHERE ocr.`id_cart_rule` = '.(int)$this->id.' AND o.`id_customer` = '.(int)$id_customer); - } + } - /** - * @param $name - * @return bool - */ - public static function cartRuleExists($name) - { - if (!CartRule::isFeatureActive()) - return false; + /** + * @param $name + * @return bool + */ + public static function cartRuleExists($name) + { + if (!CartRule::isFeatureActive()) { + return false; + } - return (bool)Db::getInstance()->getValue(' + return (bool)Db::getInstance()->getValue(' SELECT `id_cart_rule` FROM `'._DB_PREFIX_.'cart_rule` WHERE `code` = \''.pSQL($name).'\''); - } + } - /** - * @param $id_customer - * @return bool - */ - public static function deleteByIdCustomer($id_customer) - { - $return = true; - $cart_rules = new PrestaShopCollection('CartRule'); - $cart_rules->where('id_customer', '=', $id_customer); - foreach ($cart_rules as $cart_rule) - $return &= $cart_rule->delete(); - return $return; - } + /** + * @param $id_customer + * @return bool + */ + public static function deleteByIdCustomer($id_customer) + { + $return = true; + $cart_rules = new PrestaShopCollection('CartRule'); + $cart_rules->where('id_customer', '=', $id_customer); + foreach ($cart_rules as $cart_rule) { + $return &= $cart_rule->delete(); + } + return $return; + } - /** - * @return array - */ - public function getProductRuleGroups() - { - if (!Validate::isLoadedObject($this) || $this->product_restriction == 0) - return array(); + /** + * @return array + */ + public function getProductRuleGroups() + { + if (!Validate::isLoadedObject($this) || $this->product_restriction == 0) { + return array(); + } - $productRuleGroups = array(); - $result = Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'cart_rule_product_rule_group WHERE id_cart_rule = '.(int)$this->id); - foreach ($result as $row) - { - if (!isset($productRuleGroups[$row['id_product_rule_group']])) - $productRuleGroups[$row['id_product_rule_group']] = array('id_product_rule_group' => $row['id_product_rule_group'], 'quantity' => $row['quantity']); - $productRuleGroups[$row['id_product_rule_group']]['product_rules'] = $this->getProductRules($row['id_product_rule_group']); - } - return $productRuleGroups; - } + $productRuleGroups = array(); + $result = Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'cart_rule_product_rule_group WHERE id_cart_rule = '.(int)$this->id); + foreach ($result as $row) { + if (!isset($productRuleGroups[$row['id_product_rule_group']])) { + $productRuleGroups[$row['id_product_rule_group']] = array('id_product_rule_group' => $row['id_product_rule_group'], 'quantity' => $row['quantity']); + } + $productRuleGroups[$row['id_product_rule_group']]['product_rules'] = $this->getProductRules($row['id_product_rule_group']); + } + return $productRuleGroups; + } - /** - * @param $id_product_rule_group - * @return array ('type' => ? , 'values' => ?) - */ - public function getProductRules($id_product_rule_group) - { - if (!Validate::isLoadedObject($this) || $this->product_restriction == 0) - return array(); + /** + * @param $id_product_rule_group + * @return array ('type' => ? , 'values' => ?) + */ + public function getProductRules($id_product_rule_group) + { + if (!Validate::isLoadedObject($this) || $this->product_restriction == 0) { + return array(); + } - $productRules = array(); - $results = Db::getInstance()->executeS(' + $productRules = array(); + $results = Db::getInstance()->executeS(' SELECT * FROM '._DB_PREFIX_.'cart_rule_product_rule pr LEFT JOIN '._DB_PREFIX_.'cart_rule_product_rule_value prv ON pr.id_product_rule = prv.id_product_rule WHERE pr.id_product_rule_group = '.(int)$id_product_rule_group); - foreach ($results as $row) - { - if (!isset($productRules[$row['id_product_rule']])) - $productRules[$row['id_product_rule']] = array('type' => $row['type'], 'values' => array()); - $productRules[$row['id_product_rule']]['values'][] = $row['id_item']; - } - return $productRules; - } + foreach ($results as $row) { + if (!isset($productRules[$row['id_product_rule']])) { + $productRules[$row['id_product_rule']] = array('type' => $row['type'], 'values' => array()); + } + $productRules[$row['id_product_rule']]['values'][] = $row['id_item']; + } + return $productRules; + } - /** - * Check if this cart rule can be applied - * - * @param Context $context - * @param bool $alreadyInCart Check if the voucher is already on the cart - * @param bool $display_error Display error - * @return bool|mixed|string - */ - public function checkValidity(Context $context, $alreadyInCart = false, $display_error = true, $check_carrier = true) - { - if (!CartRule::isFeatureActive()) - return false; + /** + * Check if this cart rule can be applied + * + * @param Context $context + * @param bool $alreadyInCart Check if the voucher is already on the cart + * @param bool $display_error Display error + * @return bool|mixed|string + */ + public function checkValidity(Context $context, $alreadyInCart = false, $display_error = true, $check_carrier = true) + { + if (!CartRule::isFeatureActive()) { + return false; + } - if (!$this->active) - return (!$display_error) ? false : Tools::displayError('This voucher is disabled'); - if (!$this->quantity) - return (!$display_error) ? false : Tools::displayError('This voucher has already been used'); - if (strtotime($this->date_from) > time()) - return (!$display_error) ? false : Tools::displayError('This voucher is not valid yet'); - if (strtotime($this->date_to) < time()) - return (!$display_error) ? false : Tools::displayError('This voucher has expired'); + if (!$this->active) { + return (!$display_error) ? false : Tools::displayError('This voucher is disabled'); + } + if (!$this->quantity) { + return (!$display_error) ? false : Tools::displayError('This voucher has already been used'); + } + if (strtotime($this->date_from) > time()) { + return (!$display_error) ? false : Tools::displayError('This voucher is not valid yet'); + } + if (strtotime($this->date_to) < time()) { + return (!$display_error) ? false : Tools::displayError('This voucher has expired'); + } - if ($context->cart->id_customer) - { - $quantityUsed = Db::getInstance()->getValue(' + if ($context->cart->id_customer) { + $quantityUsed = Db::getInstance()->getValue(' SELECT count(*) FROM '._DB_PREFIX_.'orders o LEFT JOIN '._DB_PREFIX_.'order_cart_rule od ON o.id_order = od.id_order @@ -497,613 +518,642 @@ class CartRuleCore extends ObjectModel AND od.id_cart_rule = '.(int)$this->id.' AND '.(int)Configuration::get('PS_OS_ERROR').' != o.current_state '); - if ($quantityUsed + 1 > $this->quantity_per_user) - return (!$display_error) ? false : Tools::displayError('You cannot use this voucher anymore (usage limit reached)'); - } + if ($quantityUsed + 1 > $this->quantity_per_user) { + return (!$display_error) ? false : Tools::displayError('You cannot use this voucher anymore (usage limit reached)'); + } + } - // Get an intersection of the customer groups and the cart rule groups (if the customer is not logged in, the default group is Visitors) - if ($this->group_restriction) - { - $id_cart_rule = (int)Db::getInstance()->getValue(' + // Get an intersection of the customer groups and the cart rule groups (if the customer is not logged in, the default group is Visitors) + if ($this->group_restriction) { + $id_cart_rule = (int)Db::getInstance()->getValue(' SELECT crg.id_cart_rule FROM '._DB_PREFIX_.'cart_rule_group crg WHERE crg.id_cart_rule = '.(int)$this->id.' AND crg.id_group '.($context->cart->id_customer ? 'IN (SELECT cg.id_group FROM '._DB_PREFIX_.'customer_group cg WHERE cg.id_customer = '.(int)$context->cart->id_customer.')' : '= '.(int)Configuration::get('PS_UNIDENTIFIED_GROUP'))); - if (!$id_cart_rule) - return (!$display_error) ? false : Tools::displayError('You cannot use this voucher'); - } + if (!$id_cart_rule) { + return (!$display_error) ? false : Tools::displayError('You cannot use this voucher'); + } + } - // Check if the customer delivery address is usable with the cart rule - if ($this->country_restriction) - { - if (!$context->cart->id_address_delivery) - return (!$display_error) ? false : Tools::displayError('You must choose a delivery address before applying this voucher to your order'); - $id_cart_rule = (int)Db::getInstance()->getValue(' + // Check if the customer delivery address is usable with the cart rule + if ($this->country_restriction) { + if (!$context->cart->id_address_delivery) { + return (!$display_error) ? false : Tools::displayError('You must choose a delivery address before applying this voucher to your order'); + } + $id_cart_rule = (int)Db::getInstance()->getValue(' SELECT crc.id_cart_rule FROM '._DB_PREFIX_.'cart_rule_country crc WHERE crc.id_cart_rule = '.(int)$this->id.' AND crc.id_country = (SELECT a.id_country FROM '._DB_PREFIX_.'address a WHERE a.id_address = '.(int)$context->cart->id_address_delivery.' LIMIT 1)'); - if (!$id_cart_rule) - return (!$display_error) ? false : Tools::displayError('You cannot use this voucher in your country of delivery'); - } + if (!$id_cart_rule) { + return (!$display_error) ? false : Tools::displayError('You cannot use this voucher in your country of delivery'); + } + } - // Check if the carrier chosen by the customer is usable with the cart rule - if ($this->carrier_restriction && $check_carrier) - { - if (!$context->cart->id_carrier) - return (!$display_error) ? false : Tools::displayError('You must choose a carrier before applying this voucher to your order'); - $id_cart_rule = (int)Db::getInstance()->getValue(' + // Check if the carrier chosen by the customer is usable with the cart rule + if ($this->carrier_restriction && $check_carrier) { + if (!$context->cart->id_carrier) { + return (!$display_error) ? false : Tools::displayError('You must choose a carrier before applying this voucher to your order'); + } + $id_cart_rule = (int)Db::getInstance()->getValue(' SELECT crc.id_cart_rule FROM '._DB_PREFIX_.'cart_rule_carrier crc INNER JOIN '._DB_PREFIX_.'carrier c ON (c.id_reference = crc.id_carrier AND c.deleted = 0) WHERE crc.id_cart_rule = '.(int)$this->id.' AND c.id_carrier = '.(int)$context->cart->id_carrier); - if (!$id_cart_rule) - return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with this carrier'); - } + if (!$id_cart_rule) { + return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with this carrier'); + } + } - // Check if the cart rules appliy to the shop browsed by the customer - if ($this->shop_restriction && $context->shop->id && Shop::isFeatureActive()) - { - $id_cart_rule = (int)Db::getInstance()->getValue(' + // Check if the cart rules appliy to the shop browsed by the customer + if ($this->shop_restriction && $context->shop->id && Shop::isFeatureActive()) { + $id_cart_rule = (int)Db::getInstance()->getValue(' SELECT crs.id_cart_rule FROM '._DB_PREFIX_.'cart_rule_shop crs WHERE crs.id_cart_rule = '.(int)$this->id.' AND crs.id_shop = '.(int)$context->shop->id); - if (!$id_cart_rule) - return (!$display_error) ? false : Tools::displayError('You cannot use this voucher'); - } + if (!$id_cart_rule) { + return (!$display_error) ? false : Tools::displayError('You cannot use this voucher'); + } + } - // Check if the products chosen by the customer are usable with the cart rule - if ($this->product_restriction) - { - $r = $this->checkProductRestrictions($context, false, $display_error, $alreadyInCart); - if ($r !== false && $display_error) - return $r; - elseif (!$r && !$display_error) - return false; - } + // Check if the products chosen by the customer are usable with the cart rule + if ($this->product_restriction) { + $r = $this->checkProductRestrictions($context, false, $display_error, $alreadyInCart); + if ($r !== false && $display_error) { + return $r; + } elseif (!$r && !$display_error) { + return false; + } + } - // Check if the cart rule is only usable by a specific customer, and if the current customer is the right one - if ($this->id_customer && $context->cart->id_customer != $this->id_customer) - { - if (!Context::getContext()->customer->isLogged()) - return (!$display_error) ? false : (Tools::displayError('You cannot use this voucher').' - '.Tools::displayError('Please log in first')); - return (!$display_error) ? false : Tools::displayError('You cannot use this voucher'); - } + // Check if the cart rule is only usable by a specific customer, and if the current customer is the right one + if ($this->id_customer && $context->cart->id_customer != $this->id_customer) { + if (!Context::getContext()->customer->isLogged()) { + return (!$display_error) ? false : (Tools::displayError('You cannot use this voucher').' - '.Tools::displayError('Please log in first')); + } + return (!$display_error) ? false : Tools::displayError('You cannot use this voucher'); + } - if ($this->minimum_amount && $check_carrier) - { - // Minimum amount is converted to the contextual currency - $minimum_amount = $this->minimum_amount; - if ($this->minimum_amount_currency != Context::getContext()->currency->id) - $minimum_amount = Tools::convertPriceFull($minimum_amount, new Currency($this->minimum_amount_currency), Context::getContext()->currency); + if ($this->minimum_amount && $check_carrier) { + // Minimum amount is converted to the contextual currency + $minimum_amount = $this->minimum_amount; + if ($this->minimum_amount_currency != Context::getContext()->currency->id) { + $minimum_amount = Tools::convertPriceFull($minimum_amount, new Currency($this->minimum_amount_currency), Context::getContext()->currency); + } - $cartTotal = $context->cart->getOrderTotal($this->minimum_amount_tax, Cart::ONLY_PRODUCTS); - if ($this->minimum_amount_shipping) - $cartTotal += $context->cart->getOrderTotal($this->minimum_amount_tax, Cart::ONLY_SHIPPING); - $products = $context->cart->getProducts(); - $cart_rules = $context->cart->getCartRules(); + $cartTotal = $context->cart->getOrderTotal($this->minimum_amount_tax, Cart::ONLY_PRODUCTS); + if ($this->minimum_amount_shipping) { + $cartTotal += $context->cart->getOrderTotal($this->minimum_amount_tax, Cart::ONLY_SHIPPING); + } + $products = $context->cart->getProducts(); + $cart_rules = $context->cart->getCartRules(); - foreach ($cart_rules as &$cart_rule) - if ($cart_rule['gift_product']) - foreach ($products as $key => &$product) - if (empty($product['gift']) && $product['id_product'] == $cart_rule['gift_product'] && $product['id_product_attribute'] == $cart_rule['gift_product_attribute']) - $cartTotal = Tools::ps_round($cartTotal - $product[$this->minimum_amount_tax ? 'price_wt' : 'price'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); + foreach ($cart_rules as &$cart_rule) { + if ($cart_rule['gift_product']) { + foreach ($products as $key => &$product) { + if (empty($product['gift']) && $product['id_product'] == $cart_rule['gift_product'] && $product['id_product_attribute'] == $cart_rule['gift_product_attribute']) { + $cartTotal = Tools::ps_round($cartTotal - $product[$this->minimum_amount_tax ? 'price_wt' : 'price'], (int)$context->currency->decimals * _PS_PRICE_COMPUTE_PRECISION_); + } + } + } + } - if ($cartTotal < $minimum_amount) - return (!$display_error) ? false : Tools::displayError('You have not reached the minimum amount required to use this voucher'); - } + if ($cartTotal < $minimum_amount) { + return (!$display_error) ? false : Tools::displayError('You have not reached the minimum amount required to use this voucher'); + } + } - /* This loop checks: - - if the voucher is already in the cart - - if a non compatible voucher is in the cart - - if there are products in the cart (gifts excluded) - Important note: this MUST be the last check, because if the tested cart rule has priority over a non combinable one in the cart, we will switch them - */ - $nb_products = Cart::getNbProducts($context->cart->id); - $otherCartRules = array(); - if ($check_carrier) - $otherCartRules = $context->cart->getCartRules(); - if (count($otherCartRules)) - foreach ($otherCartRules as $otherCartRule) - { - if ($otherCartRule['id_cart_rule'] == $this->id && !$alreadyInCart) - return (!$display_error) ? false : Tools::displayError('This voucher is already in your cart'); - if ($otherCartRule['gift_product']) - --$nb_products; + /* This loop checks: + - if the voucher is already in the cart + - if a non compatible voucher is in the cart + - if there are products in the cart (gifts excluded) + Important note: this MUST be the last check, because if the tested cart rule has priority over a non combinable one in the cart, we will switch them + */ + $nb_products = Cart::getNbProducts($context->cart->id); + $otherCartRules = array(); + if ($check_carrier) { + $otherCartRules = $context->cart->getCartRules(); + } + if (count($otherCartRules)) { + foreach ($otherCartRules as $otherCartRule) { + if ($otherCartRule['id_cart_rule'] == $this->id && !$alreadyInCart) { + return (!$display_error) ? false : Tools::displayError('This voucher is already in your cart'); + } + if ($otherCartRule['gift_product']) { + --$nb_products; + } - if ($this->cart_rule_restriction && $otherCartRule['cart_rule_restriction'] && $otherCartRule['id_cart_rule'] != $this->id) - { - $combinable = Db::getInstance()->getValue(' + if ($this->cart_rule_restriction && $otherCartRule['cart_rule_restriction'] && $otherCartRule['id_cart_rule'] != $this->id) { + $combinable = Db::getInstance()->getValue(' SELECT id_cart_rule_1 FROM '._DB_PREFIX_.'cart_rule_combination WHERE (id_cart_rule_1 = '.(int)$this->id.' AND id_cart_rule_2 = '.(int)$otherCartRule['id_cart_rule'].') OR (id_cart_rule_2 = '.(int)$this->id.' AND id_cart_rule_1 = '.(int)$otherCartRule['id_cart_rule'].')'); - if (!$combinable) - { - $cart_rule = new CartRule((int)$otherCartRule['id_cart_rule'], $context->cart->id_lang); - // The cart rules are not combinable and the cart rule currently in the cart has priority over the one tested - if ($cart_rule->priority <= $this->priority) - return (!$display_error) ? false : Tools::displayError('This voucher is not combinable with an other voucher already in your cart:').' '.$cart_rule->name; - // But if the cart rule that is tested has priority over the one in the cart, we remove the one in the cart and keep this new one - else - $context->cart->removeCartRule($cart_rule->id); - } - } - } + if (!$combinable) { + $cart_rule = new CartRule((int)$otherCartRule['id_cart_rule'], $context->cart->id_lang); + // The cart rules are not combinable and the cart rule currently in the cart has priority over the one tested + if ($cart_rule->priority <= $this->priority) { + return (!$display_error) ? false : Tools::displayError('This voucher is not combinable with an other voucher already in your cart:').' '.$cart_rule->name; + } + // But if the cart rule that is tested has priority over the one in the cart, we remove the one in the cart and keep this new one + else { + $context->cart->removeCartRule($cart_rule->id); + } + } + } + } + } - if (!$nb_products) - return (!$display_error) ? false : Tools::displayError('Cart is empty'); + if (!$nb_products) { + return (!$display_error) ? false : Tools::displayError('Cart is empty'); + } - if (!$display_error) - return true; - } + if (!$display_error) { + return true; + } + } - protected function checkProductRestrictions(Context $context, $return_products = false, $display_error = true, $already_in_cart = false) - { - $selected_products = array(); + protected function checkProductRestrictions(Context $context, $return_products = false, $display_error = true, $already_in_cart = false) + { + $selected_products = array(); - // Check if the products chosen by the customer are usable with the cart rule - if ($this->product_restriction) - { - $product_rule_groups = $this->getProductRuleGroups(); - foreach ($product_rule_groups as $id_product_rule_group => $product_rule_group) - { - $eligible_products_list = array(); - if (isset($context->cart) && is_object($context->cart) && is_array($products = $context->cart->getProducts())) - foreach ($products as $product) - $eligible_products_list[] = (int)$product['id_product'].'-'.(int)$product['id_product_attribute']; - if (!count($eligible_products_list)) - return (!$display_error) ? false : Tools::displayError('You cannot use this voucher in an empty cart'); + // Check if the products chosen by the customer are usable with the cart rule + if ($this->product_restriction) { + $product_rule_groups = $this->getProductRuleGroups(); + foreach ($product_rule_groups as $id_product_rule_group => $product_rule_group) { + $eligible_products_list = array(); + if (isset($context->cart) && is_object($context->cart) && is_array($products = $context->cart->getProducts())) { + foreach ($products as $product) { + $eligible_products_list[] = (int)$product['id_product'].'-'.(int)$product['id_product_attribute']; + } + } + if (!count($eligible_products_list)) { + return (!$display_error) ? false : Tools::displayError('You cannot use this voucher in an empty cart'); + } - $product_rules = $this->getProductRules($id_product_rule_group); - foreach ($product_rules as $product_rule) - { - switch ($product_rule['type']) - { - case 'attributes': - $cart_attributes = Db::getInstance()->executeS(' + $product_rules = $this->getProductRules($id_product_rule_group); + foreach ($product_rules as $product_rule) { + switch ($product_rule['type']) { + case 'attributes': + $cart_attributes = Db::getInstance()->executeS(' SELECT cp.quantity, cp.`id_product`, pac.`id_attribute`, cp.`id_product_attribute` FROM `'._DB_PREFIX_.'cart_product` cp LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON cp.id_product_attribute = pac.id_product_attribute WHERE cp.`id_cart` = '.(int)$context->cart->id.' AND cp.`id_product` IN ('.implode(',', array_map('intval', $eligible_products_list)).') AND cp.id_product_attribute > 0'); - $count_matching_products = 0; - $matching_products_list = array(); - foreach ($cart_attributes as $cart_attribute) - if (in_array($cart_attribute['id_attribute'], $product_rule['values'])) - { - $count_matching_products += $cart_attribute['quantity']; - if ($already_in_cart && $this->gift_product == $cart_attribute['id_product'] - && $this->gift_product_attribute == $cart_attribute['id_product_attribute']) - --$count_matching_products; - $matching_products_list[] = $cart_attribute['id_product'].'-'.$cart_attribute['id_product_attribute']; - } - if ($count_matching_products < $product_rule_group['quantity']) - return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products'); - $eligible_products_list = CartRule::array_uintersect($eligible_products_list, $matching_products_list); - break; - case 'products': - $cart_products = Db::getInstance()->executeS(' + $count_matching_products = 0; + $matching_products_list = array(); + foreach ($cart_attributes as $cart_attribute) { + if (in_array($cart_attribute['id_attribute'], $product_rule['values'])) { + $count_matching_products += $cart_attribute['quantity']; + if ($already_in_cart && $this->gift_product == $cart_attribute['id_product'] + && $this->gift_product_attribute == $cart_attribute['id_product_attribute']) { + --$count_matching_products; + } + $matching_products_list[] = $cart_attribute['id_product'].'-'.$cart_attribute['id_product_attribute']; + } + } + if ($count_matching_products < $product_rule_group['quantity']) { + return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products'); + } + $eligible_products_list = CartRule::array_uintersect($eligible_products_list, $matching_products_list); + break; + case 'products': + $cart_products = Db::getInstance()->executeS(' SELECT cp.quantity, cp.`id_product` FROM `'._DB_PREFIX_.'cart_product` cp WHERE cp.`id_cart` = '.(int)$context->cart->id.' AND cp.`id_product` IN ('.implode(',', array_map('intval', $eligible_products_list)).')'); - $count_matching_products = 0; - $matching_products_list = array(); - foreach ($cart_products as $cart_product) - if (in_array($cart_product['id_product'], $product_rule['values'])) - { - $count_matching_products += $cart_product['quantity']; - if ($already_in_cart && $this->gift_product == $cart_product['id_product']) - --$count_matching_products; - $matching_products_list[] = $cart_product['id_product'].'-0'; - } - if ($count_matching_products < $product_rule_group['quantity']) - return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products'); - $eligible_products_list = CartRule::array_uintersect($eligible_products_list, $matching_products_list); - break; - case 'categories': - $cart_categories = Db::getInstance()->executeS(' + $count_matching_products = 0; + $matching_products_list = array(); + foreach ($cart_products as $cart_product) { + if (in_array($cart_product['id_product'], $product_rule['values'])) { + $count_matching_products += $cart_product['quantity']; + if ($already_in_cart && $this->gift_product == $cart_product['id_product']) { + --$count_matching_products; + } + $matching_products_list[] = $cart_product['id_product'].'-0'; + } + } + if ($count_matching_products < $product_rule_group['quantity']) { + return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products'); + } + $eligible_products_list = CartRule::array_uintersect($eligible_products_list, $matching_products_list); + break; + case 'categories': + $cart_categories = Db::getInstance()->executeS(' SELECT cp.quantity, cp.`id_product`, cp.`id_product_attribute`, catp.`id_category` FROM `'._DB_PREFIX_.'cart_product` cp LEFT JOIN `'._DB_PREFIX_.'category_product` catp ON cp.id_product = catp.id_product WHERE cp.`id_cart` = '.(int)$context->cart->id.' AND cp.`id_product` IN ('.implode(',', array_map('intval', $eligible_products_list)).') AND cp.`id_product` <> '.(int)$this->gift_product); - $count_matching_products = 0; - $matching_products_list = array(); - foreach ($cart_categories as $cart_category) - if (in_array($cart_category['id_category'], $product_rule['values']) - /** - * We also check that the product is not already in the matching product list, - * because there are doubles in the query results (when the product is in multiple categories) - */ - && !in_array($cart_category['id_product'].'-'.$cart_category['id_product_attribute'], $matching_products_list)) - { - $count_matching_products += $cart_category['quantity']; - $matching_products_list[] = $cart_category['id_product'].'-'.$cart_category['id_product_attribute']; - } - if ($count_matching_products < $product_rule_group['quantity']) - return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products'); - // Attribute id is not important for this filter in the global list, so the ids are replaced by 0 - foreach ($matching_products_list as &$matching_product) - $matching_product = preg_replace('/^([0-9]+)-[0-9]+$/', '$1-0', $matching_product); - $eligible_products_list = CartRule::array_uintersect($eligible_products_list, $matching_products_list); - break; - case 'manufacturers': - $cart_manufacturers = Db::getInstance()->executeS(' + $count_matching_products = 0; + $matching_products_list = array(); + foreach ($cart_categories as $cart_category) { + if (in_array($cart_category['id_category'], $product_rule['values']) + /** + * We also check that the product is not already in the matching product list, + * because there are doubles in the query results (when the product is in multiple categories) + */ + && !in_array($cart_category['id_product'].'-'.$cart_category['id_product_attribute'], $matching_products_list)) { + $count_matching_products += $cart_category['quantity']; + $matching_products_list[] = $cart_category['id_product'].'-'.$cart_category['id_product_attribute']; + } + } + if ($count_matching_products < $product_rule_group['quantity']) { + return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products'); + } + // Attribute id is not important for this filter in the global list, so the ids are replaced by 0 + foreach ($matching_products_list as &$matching_product) { + $matching_product = preg_replace('/^([0-9]+)-[0-9]+$/', '$1-0', $matching_product); + } + $eligible_products_list = CartRule::array_uintersect($eligible_products_list, $matching_products_list); + break; + case 'manufacturers': + $cart_manufacturers = Db::getInstance()->executeS(' SELECT cp.quantity, cp.`id_product`, p.`id_manufacturer` FROM `'._DB_PREFIX_.'cart_product` cp LEFT JOIN `'._DB_PREFIX_.'product` p ON cp.id_product = p.id_product WHERE cp.`id_cart` = '.(int)$context->cart->id.' AND cp.`id_product` IN ('.implode(',', array_map('intval', $eligible_products_list)).')'); - $count_matching_products = 0; - $matching_products_list = array(); - foreach ($cart_manufacturers as $cart_manufacturer) - if (in_array($cart_manufacturer['id_manufacturer'], $product_rule['values'])) - { - $count_matching_products += $cart_manufacturer['quantity']; - $matching_products_list[] = $cart_manufacturer['id_product'].'-0'; - } - if ($count_matching_products < $product_rule_group['quantity']) - return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products'); - $eligible_products_list = CartRule::array_uintersect($eligible_products_list, $matching_products_list); - break; - case 'suppliers': - $cart_suppliers = Db::getInstance()->executeS(' + $count_matching_products = 0; + $matching_products_list = array(); + foreach ($cart_manufacturers as $cart_manufacturer) { + if (in_array($cart_manufacturer['id_manufacturer'], $product_rule['values'])) { + $count_matching_products += $cart_manufacturer['quantity']; + $matching_products_list[] = $cart_manufacturer['id_product'].'-0'; + } + } + if ($count_matching_products < $product_rule_group['quantity']) { + return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products'); + } + $eligible_products_list = CartRule::array_uintersect($eligible_products_list, $matching_products_list); + break; + case 'suppliers': + $cart_suppliers = Db::getInstance()->executeS(' SELECT cp.quantity, cp.`id_product`, p.`id_supplier` FROM `'._DB_PREFIX_.'cart_product` cp LEFT JOIN `'._DB_PREFIX_.'product` p ON cp.id_product = p.id_product WHERE cp.`id_cart` = '.(int)$context->cart->id.' AND cp.`id_product` IN ('.implode(',', array_map('intval', $eligible_products_list)).')'); - $count_matching_products = 0; - $matching_products_list = array(); - foreach ($cart_suppliers as $cart_supplier) - if (in_array($cart_supplier['id_supplier'], $product_rule['values'])) - { - $count_matching_products += $cart_supplier['quantity']; - $matching_products_list[] = $cart_supplier['id_product'].'-0'; - } - if ($count_matching_products < $product_rule_group['quantity']) - return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products'); - $eligible_products_list = CartRule::array_uintersect($eligible_products_list, $matching_products_list); - break; - } + $count_matching_products = 0; + $matching_products_list = array(); + foreach ($cart_suppliers as $cart_supplier) { + if (in_array($cart_supplier['id_supplier'], $product_rule['values'])) { + $count_matching_products += $cart_supplier['quantity']; + $matching_products_list[] = $cart_supplier['id_product'].'-0'; + } + } + if ($count_matching_products < $product_rule_group['quantity']) { + return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products'); + } + $eligible_products_list = CartRule::array_uintersect($eligible_products_list, $matching_products_list); + break; + } - if (!count($eligible_products_list)) - return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products'); - } - $selected_products = array_merge($selected_products, $eligible_products_list); - } - } + if (!count($eligible_products_list)) { + return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products'); + } + } + $selected_products = array_merge($selected_products, $eligible_products_list); + } + } - if ($return_products) - return $selected_products; - return (!$display_error) ? true : false; - } + if ($return_products) { + return $selected_products; + } + return (!$display_error) ? true : false; + } - protected static function array_uintersect($array1, $array2) - { - $intersection = array(); - foreach ($array1 as $value1) - foreach ($array2 as $value2) - if (CartRule::array_uintersect_compare($value1, $value2) == 0) - { - $intersection[] = $value1; - break 1; - } - return $intersection; - } + protected static function array_uintersect($array1, $array2) + { + $intersection = array(); + foreach ($array1 as $value1) { + foreach ($array2 as $value2) { + if (CartRule::array_uintersect_compare($value1, $value2) == 0) { + $intersection[] = $value1; + break 1; + } + } + } + return $intersection; + } - protected static function array_uintersect_compare($a, $b) - { - if ($a == $b) - return 0; + protected static function array_uintersect_compare($a, $b) + { + if ($a == $b) { + return 0; + } - $asplit = explode('-', $a); - $bsplit = explode('-', $b); - if ($asplit[0] == $bsplit[0] && (!(int)$asplit[1] || !(int)$bsplit[1])) - return 0; + $asplit = explode('-', $a); + $bsplit = explode('-', $b); + if ($asplit[0] == $bsplit[0] && (!(int)$asplit[1] || !(int)$bsplit[1])) { + return 0; + } - return 1; - } + return 1; + } - /** - * The reduction value is POSITIVE - * - * @param bool $use_tax - * @param Context $context - * @param bool $use_cache Allow using cache to avoid multiple free gift using multishipping - * @return float|int|string - */ - public function getContextualValue($use_tax, Context $context = null, $filter = null, $package = null, $use_cache = true) - { - if (!CartRule::isFeatureActive()) - return 0; - if (!$context) - $context = Context::getContext(); - if (!$filter) - $filter = CartRule::FILTER_ACTION_ALL; + /** + * The reduction value is POSITIVE + * + * @param bool $use_tax + * @param Context $context + * @param bool $use_cache Allow using cache to avoid multiple free gift using multishipping + * @return float|int|string + */ + public function getContextualValue($use_tax, Context $context = null, $filter = null, $package = null, $use_cache = true) + { + if (!CartRule::isFeatureActive()) { + return 0; + } + if (!$context) { + $context = Context::getContext(); + } + if (!$filter) { + $filter = CartRule::FILTER_ACTION_ALL; + } - $all_products = $context->cart->getProducts(); - $package_products = (is_null($package) ? $all_products : $package['products']); + $all_products = $context->cart->getProducts(); + $package_products = (is_null($package) ? $all_products : $package['products']); - $all_cart_rules_ids = $context->cart->getOrderedCartRulesIds(); + $all_cart_rules_ids = $context->cart->getOrderedCartRulesIds(); - $cart_amount_ti = $context->cart->getOrderTotal(true, Cart::ONLY_PRODUCTS); - $cart_amount_te = $context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS); + $cart_amount_ti = $context->cart->getOrderTotal(true, Cart::ONLY_PRODUCTS); + $cart_amount_te = $context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS); - $reduction_value = 0; + $reduction_value = 0; - $cache_id = 'getContextualValue_'.(int)$this->id.'_'.(int)$use_tax.'_'.(int)$context->cart->id.'_'.(int)$filter; - foreach ($package_products as $product) - $cache_id .= '_'.(int)$product['id_product'].'_'.(int)$product['id_product_attribute'].(isset($product['in_stock']) ? '_'.(int)$product['in_stock'] : ''); + $cache_id = 'getContextualValue_'.(int)$this->id.'_'.(int)$use_tax.'_'.(int)$context->cart->id.'_'.(int)$filter; + foreach ($package_products as $product) { + $cache_id .= '_'.(int)$product['id_product'].'_'.(int)$product['id_product_attribute'].(isset($product['in_stock']) ? '_'.(int)$product['in_stock'] : ''); + } - if (Cache::isStored($cache_id)) - return Cache::retrieve($cache_id); + if (Cache::isStored($cache_id)) { + return Cache::retrieve($cache_id); + } - // Free shipping on selected carriers - if ($this->free_shipping && in_array($filter, array(CartRule::FILTER_ACTION_ALL, CartRule::FILTER_ACTION_ALL_NOCAP, CartRule::FILTER_ACTION_SHIPPING))) - { - if (!$this->carrier_restriction) - $reduction_value += $context->cart->getOrderTotal($use_tax, Cart::ONLY_SHIPPING, is_null($package) ? null : $package['products'], is_null($package) ? null : $package['id_carrier']); - else - { - $data = Db::getInstance()->executeS(' + // Free shipping on selected carriers + if ($this->free_shipping && in_array($filter, array(CartRule::FILTER_ACTION_ALL, CartRule::FILTER_ACTION_ALL_NOCAP, CartRule::FILTER_ACTION_SHIPPING))) { + if (!$this->carrier_restriction) { + $reduction_value += $context->cart->getOrderTotal($use_tax, Cart::ONLY_SHIPPING, is_null($package) ? null : $package['products'], is_null($package) ? null : $package['id_carrier']); + } else { + $data = Db::getInstance()->executeS(' SELECT crc.id_cart_rule, c.id_carrier FROM '._DB_PREFIX_.'cart_rule_carrier crc INNER JOIN '._DB_PREFIX_.'carrier c ON (c.id_reference = crc.id_carrier AND c.deleted = 0) WHERE crc.id_cart_rule = '.(int)$this->id.' AND c.id_carrier = '.(int)$context->cart->id_carrier); - if ($data) - foreach ($data as $cart_rule) - $reduction_value += $context->cart->getCarrierCost((int)$cart_rule['id_carrier'], $use_tax, $context->country); - } - } + if ($data) { + foreach ($data as $cart_rule) { + $reduction_value += $context->cart->getCarrierCost((int)$cart_rule['id_carrier'], $use_tax, $context->country); + } + } + } + } - if (in_array($filter, array(CartRule::FILTER_ACTION_ALL, CartRule::FILTER_ACTION_ALL_NOCAP, CartRule::FILTER_ACTION_REDUCTION))) - { - // Discount (%) on the whole order - if ($this->reduction_percent && $this->reduction_product == 0) - { - // Do not give a reduction on free products! - $order_total = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS, $package_products); - foreach ($context->cart->getCartRules(CartRule::FILTER_ACTION_GIFT) as $cart_rule) - $order_total -= Tools::ps_round($cart_rule['obj']->getContextualValue($use_tax, $context, CartRule::FILTER_ACTION_GIFT, $package), _PS_PRICE_COMPUTE_PRECISION_); + if (in_array($filter, array(CartRule::FILTER_ACTION_ALL, CartRule::FILTER_ACTION_ALL_NOCAP, CartRule::FILTER_ACTION_REDUCTION))) { + // Discount (%) on the whole order + if ($this->reduction_percent && $this->reduction_product == 0) { + // Do not give a reduction on free products! + $order_total = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS, $package_products); + foreach ($context->cart->getCartRules(CartRule::FILTER_ACTION_GIFT) as $cart_rule) { + $order_total -= Tools::ps_round($cart_rule['obj']->getContextualValue($use_tax, $context, CartRule::FILTER_ACTION_GIFT, $package), _PS_PRICE_COMPUTE_PRECISION_); + } - $reduction_value += $order_total * $this->reduction_percent / 100; - } + $reduction_value += $order_total * $this->reduction_percent / 100; + } - // Discount (%) on a specific product - if ($this->reduction_percent && $this->reduction_product > 0) - { - foreach ($package_products as $product) - if ($product['id_product'] == $this->reduction_product) - $reduction_value += ($use_tax ? $product['total_wt'] : $product['total']) * $this->reduction_percent / 100; - } + // Discount (%) on a specific product + if ($this->reduction_percent && $this->reduction_product > 0) { + foreach ($package_products as $product) { + if ($product['id_product'] == $this->reduction_product) { + $reduction_value += ($use_tax ? $product['total_wt'] : $product['total']) * $this->reduction_percent / 100; + } + } + } - // Discount (%) on the cheapest product - if ($this->reduction_percent && $this->reduction_product == -1) - { - $minPrice = false; - $cheapest_product = null; - foreach ($all_products as $product) - { - $price = $product['price']; - if ($use_tax) - { - // since later on we won't be able to know the product the cart rule was applied to, - // use average cart VAT for price_wt - $price *= (1 + $context->cart->getAverageProductsTaxRate()); - } + // Discount (%) on the cheapest product + if ($this->reduction_percent && $this->reduction_product == -1) { + $minPrice = false; + $cheapest_product = null; + foreach ($all_products as $product) { + $price = $product['price']; + if ($use_tax) { + // since later on we won't be able to know the product the cart rule was applied to, + // use average cart VAT for price_wt + $price *= (1 + $context->cart->getAverageProductsTaxRate()); + } - if ($price > 0 && ($minPrice === false || $minPrice > $price)) - { - $minPrice = $price; - $cheapest_product = $product['id_product'].'-'.$product['id_product_attribute']; - } - } + if ($price > 0 && ($minPrice === false || $minPrice > $price)) { + $minPrice = $price; + $cheapest_product = $product['id_product'].'-'.$product['id_product_attribute']; + } + } - // Check if the cheapest product is in the package - $in_package = false; - foreach ($package_products as $product) - if ($product['id_product'].'-'.$product['id_product_attribute'] == $cheapest_product || $product['id_product'].'-0' == $cheapest_product) - $in_package = true; - if ($in_package) - $reduction_value += $minPrice * $this->reduction_percent / 100; - } + // Check if the cheapest product is in the package + $in_package = false; + foreach ($package_products as $product) { + if ($product['id_product'].'-'.$product['id_product_attribute'] == $cheapest_product || $product['id_product'].'-0' == $cheapest_product) { + $in_package = true; + } + } + if ($in_package) { + $reduction_value += $minPrice * $this->reduction_percent / 100; + } + } - // Discount (%) on the selection of products - if ($this->reduction_percent && $this->reduction_product == -2) - { - $selected_products_reduction = 0; - $selected_products = $this->checkProductRestrictions($context, true); - if (is_array($selected_products)) - foreach ($package_products as $product) - if (in_array($product['id_product'].'-'.$product['id_product_attribute'], $selected_products) - || in_array($product['id_product'].'-0', $selected_products)) - { - $price = $product['price']; - if ($use_tax) - $price *= (1 + $context->cart->getAverageProductsTaxRate()); + // Discount (%) on the selection of products + if ($this->reduction_percent && $this->reduction_product == -2) { + $selected_products_reduction = 0; + $selected_products = $this->checkProductRestrictions($context, true); + if (is_array($selected_products)) { + foreach ($package_products as $product) { + if (in_array($product['id_product'].'-'.$product['id_product_attribute'], $selected_products) + || in_array($product['id_product'].'-0', $selected_products)) { + $price = $product['price']; + if ($use_tax) { + $price *= (1 + $context->cart->getAverageProductsTaxRate()); + } - $selected_products_reduction += $price * $product['cart_quantity']; - } - $reduction_value += $selected_products_reduction * $this->reduction_percent / 100; - } + $selected_products_reduction += $price * $product['cart_quantity']; + } + } + } + $reduction_value += $selected_products_reduction * $this->reduction_percent / 100; + } - // Discount (¤) - if ((float)$this->reduction_amount > 0) - { - $prorata = 1; - if (!is_null($package) && count($all_products)) - { - $total_products = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS); - if ($total_products) - $prorata = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS, $package['products']) / $total_products; - } + // Discount (¤) + if ((float)$this->reduction_amount > 0) { + $prorata = 1; + if (!is_null($package) && count($all_products)) { + $total_products = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS); + if ($total_products) { + $prorata = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS, $package['products']) / $total_products; + } + } - $reduction_amount = $this->reduction_amount; - // If we need to convert the voucher value to the cart currency - if (isset($context->currency) && $this->reduction_currency != $context->currency->id) - { - $voucherCurrency = new Currency($this->reduction_currency); + $reduction_amount = $this->reduction_amount; + // If we need to convert the voucher value to the cart currency + if (isset($context->currency) && $this->reduction_currency != $context->currency->id) { + $voucherCurrency = new Currency($this->reduction_currency); - // First we convert the voucher value to the default currency - if ($reduction_amount == 0 || $voucherCurrency->conversion_rate == 0) - $reduction_amount = 0; - else - $reduction_amount /= $voucherCurrency->conversion_rate; + // First we convert the voucher value to the default currency + if ($reduction_amount == 0 || $voucherCurrency->conversion_rate == 0) { + $reduction_amount = 0; + } else { + $reduction_amount /= $voucherCurrency->conversion_rate; + } - // Then we convert the voucher value in the default currency into the cart currency - $reduction_amount *= $context->currency->conversion_rate; - $reduction_amount = Tools::ps_round($reduction_amount, _PS_PRICE_COMPUTE_PRECISION_); - } + // Then we convert the voucher value in the default currency into the cart currency + $reduction_amount *= $context->currency->conversion_rate; + $reduction_amount = Tools::ps_round($reduction_amount, _PS_PRICE_COMPUTE_PRECISION_); + } - // If it has the same tax application that you need, then it's the right value, whatever the product! - if ($this->reduction_tax == $use_tax) - { - // The reduction cannot exceed the products total, except when we do not want it to be limited (for the partial use calculation) - if ($filter != CartRule::FILTER_ACTION_ALL_NOCAP) - { - $cart_amount = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS); - $reduction_amount = min($reduction_amount, $cart_amount); - } - $reduction_value += $prorata * $reduction_amount; - } - else - { - if ($this->reduction_product > 0) - { - foreach ($context->cart->getProducts() as $product) - if ($product['id_product'] == $this->reduction_product) - { - $product_price_ti = $product['price_wt']; - $product_price_te = $product['price']; - $product_vat_amount = $product_price_ti - $product_price_te; + // If it has the same tax application that you need, then it's the right value, whatever the product! + if ($this->reduction_tax == $use_tax) { + // The reduction cannot exceed the products total, except when we do not want it to be limited (for the partial use calculation) + if ($filter != CartRule::FILTER_ACTION_ALL_NOCAP) { + $cart_amount = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS); + $reduction_amount = min($reduction_amount, $cart_amount); + } + $reduction_value += $prorata * $reduction_amount; + } else { + if ($this->reduction_product > 0) { + foreach ($context->cart->getProducts() as $product) { + if ($product['id_product'] == $this->reduction_product) { + $product_price_ti = $product['price_wt']; + $product_price_te = $product['price']; + $product_vat_amount = $product_price_ti - $product_price_te; - if ($product_vat_amount == 0 || $product_price_te == 0) - $product_vat_rate = 0; - else - $product_vat_rate = $product_vat_amount / $product_price_te; + if ($product_vat_amount == 0 || $product_price_te == 0) { + $product_vat_rate = 0; + } else { + $product_vat_rate = $product_vat_amount / $product_price_te; + } - if ($this->reduction_tax && !$use_tax) - $reduction_value += $prorata * $reduction_amount / (1 + $product_vat_rate); - elseif (!$this->reduction_tax && $use_tax) - $reduction_value += $prorata * $reduction_amount * (1 + $product_vat_rate); - } - } - // Discount (¤) on the whole order - elseif ($this->reduction_product == 0) - { - $cart_amount_te = null; - $cart_amount_ti = null; - $cart_average_vat_rate = $context->cart->getAverageProductsTaxRate($cart_amount_te, $cart_amount_ti); + if ($this->reduction_tax && !$use_tax) { + $reduction_value += $prorata * $reduction_amount / (1 + $product_vat_rate); + } elseif (!$this->reduction_tax && $use_tax) { + $reduction_value += $prorata * $reduction_amount * (1 + $product_vat_rate); + } + } + } + } + // Discount (¤) on the whole order + elseif ($this->reduction_product == 0) { + $cart_amount_te = null; + $cart_amount_ti = null; + $cart_average_vat_rate = $context->cart->getAverageProductsTaxRate($cart_amount_te, $cart_amount_ti); - // The reduction cannot exceed the products total, except when we do not want it to be limited (for the partial use calculation) - if ($filter != CartRule::FILTER_ACTION_ALL_NOCAP) - $reduction_amount = min($reduction_amount, $this->reduction_tax ? $cart_amount_ti : $cart_amount_te); + // The reduction cannot exceed the products total, except when we do not want it to be limited (for the partial use calculation) + if ($filter != CartRule::FILTER_ACTION_ALL_NOCAP) { + $reduction_amount = min($reduction_amount, $this->reduction_tax ? $cart_amount_ti : $cart_amount_te); + } - if ($this->reduction_tax && !$use_tax) - $reduction_value += $prorata * $reduction_amount / (1 + $cart_average_vat_rate); - elseif (!$this->reduction_tax && $use_tax) - $reduction_value += $prorata * $reduction_amount * (1 + $cart_average_vat_rate); - } - /* - * Reduction on the cheapest or on the selection is not really meaningful and has been disabled in the backend - * Please keep this code, so it won't be considered as a bug - * elseif ($this->reduction_product == -1) - * elseif ($this->reduction_product == -2) - */ - } + if ($this->reduction_tax && !$use_tax) { + $reduction_value += $prorata * $reduction_amount / (1 + $cart_average_vat_rate); + } elseif (!$this->reduction_tax && $use_tax) { + $reduction_value += $prorata * $reduction_amount * (1 + $cart_average_vat_rate); + } + } + /* + * Reduction on the cheapest or on the selection is not really meaningful and has been disabled in the backend + * Please keep this code, so it won't be considered as a bug + * elseif ($this->reduction_product == -1) + * elseif ($this->reduction_product == -2) + */ + } - // Take care of the other cart rules values if the filter allow it - if ($filter != CartRule::FILTER_ACTION_ALL_NOCAP) - { - // Cart values - $cart = Context::getContext()->cart; + // Take care of the other cart rules values if the filter allow it + if ($filter != CartRule::FILTER_ACTION_ALL_NOCAP) { + // Cart values + $cart = Context::getContext()->cart; - if (!Validate::isLoadedObject($cart)) - $cart = new Cart(); + if (!Validate::isLoadedObject($cart)) { + $cart = new Cart(); + } - $cart_average_vat_rate = $cart->getAverageProductsTaxRate(); - $current_cart_amount = $use_tax ? $cart_amount_ti : $cart_amount_te; + $cart_average_vat_rate = $cart->getAverageProductsTaxRate(); + $current_cart_amount = $use_tax ? $cart_amount_ti : $cart_amount_te; - foreach ($all_cart_rules_ids as $current_cart_rule_id) - { - if ((int)$current_cart_rule_id['id_cart_rule'] == (int)$this->id) - break; + foreach ($all_cart_rules_ids as $current_cart_rule_id) { + if ((int)$current_cart_rule_id['id_cart_rule'] == (int)$this->id) { + break; + } - $previous_cart_rule = new CartRule((int)$current_cart_rule_id['id_cart_rule']); - $previous_reduction_amount = $previous_cart_rule->reduction_amount; + $previous_cart_rule = new CartRule((int)$current_cart_rule_id['id_cart_rule']); + $previous_reduction_amount = $previous_cart_rule->reduction_amount; - if ($previous_cart_rule->reduction_tax && !$use_tax) - $previous_reduction_amount = $prorata * $previous_reduction_amount / (1 + $cart_average_vat_rate); - elseif (!$previous_cart_rule->reduction_tax && $use_tax) - $previous_reduction_amount = $prorata * $previous_reduction_amount * (1 + $cart_average_vat_rate); + if ($previous_cart_rule->reduction_tax && !$use_tax) { + $previous_reduction_amount = $prorata * $previous_reduction_amount / (1 + $cart_average_vat_rate); + } elseif (!$previous_cart_rule->reduction_tax && $use_tax) { + $previous_reduction_amount = $prorata * $previous_reduction_amount * (1 + $cart_average_vat_rate); + } - $current_cart_amount = max($current_cart_amount - (float)$previous_reduction_amount, 0); - } + $current_cart_amount = max($current_cart_amount - (float)$previous_reduction_amount, 0); + } - $reduction_value = min($reduction_value, $current_cart_amount); - } - } - } + $reduction_value = min($reduction_value, $current_cart_amount); + } + } + } - // Free gift - if ((int)$this->gift_product && in_array($filter, array(CartRule::FILTER_ACTION_ALL, CartRule::FILTER_ACTION_ALL_NOCAP, CartRule::FILTER_ACTION_GIFT))) - { - $id_address = (is_null($package) ? 0 : $package['id_address']); - foreach ($package_products as $product) - if ($product['id_product'] == $this->gift_product && ($product['id_product_attribute'] == $this->gift_product_attribute || !(int)$this->gift_product_attribute)) - { - // The free gift coupon must be applied to one product only (needed for multi-shipping which manage multiple product lists) - if (!isset(CartRule::$only_one_gift[$this->id.'-'.$this->gift_product]) - || CartRule::$only_one_gift[$this->id.'-'.$this->gift_product] == $id_address - || CartRule::$only_one_gift[$this->id.'-'.$this->gift_product] == 0 - || $id_address == 0 - || !$use_cache) - { - $reduction_value += ($use_tax ? $product['price_wt'] : $product['price']); - if ($use_cache && (!isset(CartRule::$only_one_gift[$this->id.'-'.$this->gift_product]) || CartRule::$only_one_gift[$this->id.'-'.$this->gift_product] == 0)) - CartRule::$only_one_gift[$this->id.'-'.$this->gift_product] = $id_address; - break; - } - } - } + // Free gift + if ((int)$this->gift_product && in_array($filter, array(CartRule::FILTER_ACTION_ALL, CartRule::FILTER_ACTION_ALL_NOCAP, CartRule::FILTER_ACTION_GIFT))) { + $id_address = (is_null($package) ? 0 : $package['id_address']); + foreach ($package_products as $product) { + if ($product['id_product'] == $this->gift_product && ($product['id_product_attribute'] == $this->gift_product_attribute || !(int)$this->gift_product_attribute)) { + // The free gift coupon must be applied to one product only (needed for multi-shipping which manage multiple product lists) + if (!isset(CartRule::$only_one_gift[$this->id.'-'.$this->gift_product]) + || CartRule::$only_one_gift[$this->id.'-'.$this->gift_product] == $id_address + || CartRule::$only_one_gift[$this->id.'-'.$this->gift_product] == 0 + || $id_address == 0 + || !$use_cache) { + $reduction_value += ($use_tax ? $product['price_wt'] : $product['price']); + if ($use_cache && (!isset(CartRule::$only_one_gift[$this->id.'-'.$this->gift_product]) || CartRule::$only_one_gift[$this->id.'-'.$this->gift_product] == 0)) { + CartRule::$only_one_gift[$this->id.'-'.$this->gift_product] = $id_address; + } + break; + } + } + } + } - Cache::store($cache_id, $reduction_value); - return $reduction_value; - } + Cache::store($cache_id, $reduction_value); + return $reduction_value; + } - /** - * Make sure caches are empty - * Must be called before calling multiple time getContextualValue() - */ - public static function cleanCache() - { - self::$only_one_gift = array(); - } + /** + * Make sure caches are empty + * Must be called before calling multiple time getContextualValue() + */ + public static function cleanCache() + { + self::$only_one_gift = array(); + } - /** - * @param int $offset - * @param int $limit - * @param string $search - * @return array - */ - protected function getCartRuleCombinations($offset = null, $limit = null, $search = '') - { - $array = array(); - if ($offset !== null && $limit !== null) - $sql_limit = ' LIMIT '.(int)$offset.', '.(int)($limit+1); - else - $sql_limit = ''; + /** + * @param int $offset + * @param int $limit + * @param string $search + * @return array + */ + protected function getCartRuleCombinations($offset = null, $limit = null, $search = '') + { + $array = array(); + if ($offset !== null && $limit !== null) { + $sql_limit = ' LIMIT '.(int)$offset.', '.(int)($limit+1); + } else { + $sql_limit = ''; + } - $array['selected'] = Db::getInstance()->executeS(' + $array['selected'] = Db::getInstance()->executeS(' SELECT cr.*, crl.*, 1 as selected FROM '._DB_PREFIX_.'cart_rule cr LEFT JOIN '._DB_PREFIX_.'cart_rule_lang crl ON (cr.id_cart_rule = crl.id_cart_rule AND crl.id_lang = '.(int)Context::getContext()->language->id.') @@ -1122,7 +1172,7 @@ class CartRuleCore extends ObjectModel ) ) ORDER BY cr.id_cart_rule'.$sql_limit); - $array['unselected'] = Db::getInstance()->executeS(' + $array['unselected'] = Db::getInstance()->executeS(' SELECT cr.*, crl.*, 1 as selected FROM '._DB_PREFIX_.'cart_rule cr INNER JOIN '._DB_PREFIX_.'cart_rule_lang crl ON (cr.id_cart_rule = crl.id_cart_rule AND crl.id_lang = '.(int)Context::getContext()->language->id.') @@ -1132,42 +1182,43 @@ class CartRuleCore extends ObjectModel AND cr.id_cart_rule != '.(int)$this->id.($search ? ' AND crl.name LIKE "%'.pSQL($search).'%"' : '').' AND crc1.id_cart_rule_1 IS NULL AND crc2.id_cart_rule_1 IS NULL ORDER BY cr.id_cart_rule'.$sql_limit); - return $array; - } + return $array; + } - /** - * @param string $type - * @param bool $active_only - * @param bool $i18n - * @param int $offset - * @param int $limit - * @param string $search_cart_rule_name - * @return array|bool - * @throws PrestaShopDatabaseException - */ - public function getAssociatedRestrictions($type, $active_only, $i18n, $offset = null, $limit = null, $search_cart_rule_name = '') - { - $array = array('selected' => array(), 'unselected' => array()); + /** + * @param string $type + * @param bool $active_only + * @param bool $i18n + * @param int $offset + * @param int $limit + * @param string $search_cart_rule_name + * @return array|bool + * @throws PrestaShopDatabaseException + */ + public function getAssociatedRestrictions($type, $active_only, $i18n, $offset = null, $limit = null, $search_cart_rule_name = '') + { + $array = array('selected' => array(), 'unselected' => array()); - if (!in_array($type, array('country', 'carrier', 'group', 'cart_rule', 'shop'))) - return false; + if (!in_array($type, array('country', 'carrier', 'group', 'cart_rule', 'shop'))) { + return false; + } - $shop_list = ''; - if ($type == 'shop') - { - $shops = Context::getContext()->employee->getAssociatedShops(); - if (count($shops)) - $shop_list = ' AND t.id_shop IN ('.implode(array_map('intval', $shops), ',').') '; - } + $shop_list = ''; + if ($type == 'shop') { + $shops = Context::getContext()->employee->getAssociatedShops(); + if (count($shops)) { + $shop_list = ' AND t.id_shop IN ('.implode(array_map('intval', $shops), ',').') '; + } + } - if ($offset !== null && $limit !== null) - $sql_limit = ' LIMIT '.(int)$offset.', '.(int)($limit+1); - else - $sql_limit = ''; + if ($offset !== null && $limit !== null) { + $sql_limit = ' LIMIT '.(int)$offset.', '.(int)($limit+1); + } else { + $sql_limit = ''; + } - if (!Validate::isLoadedObject($this) || $this->{$type.'_restriction'} == 0) - { - $array['selected'] = Db::getInstance()->executeS(' + if (!Validate::isLoadedObject($this) || $this->{$type.'_restriction'} == 0) { + $array['selected'] = Db::getInstance()->executeS(' SELECT t.*'.($i18n ? ', tl.*' : '').', 1 as selected FROM `'._DB_PREFIX_.$type.'` t '.($i18n ? 'LEFT JOIN `'._DB_PREFIX_.$type.'_lang` tl ON (t.id_'.$type.' = tl.id_'.$type.' AND tl.id_lang = '.(int)Context::getContext()->language->id.')' : '').' @@ -1175,68 +1226,68 @@ class CartRuleCore extends ObjectModel '.($active_only ? 'AND t.active = 1' : '').' '.(in_array($type, array('carrier', 'shop')) ? ' AND t.deleted = 0' : '').' '.($type == 'cart_rule' ? 'AND t.id_cart_rule != '.(int)$this->id : ''). - $shop_list. - (in_array($type, array('carrier', 'shop')) ? ' ORDER BY t.name ASC ' : ''). - (in_array($type, array('country', 'group', 'cart_rule')) && $i18n ? ' ORDER BY tl.name ASC ' : ''). - $sql_limit); - } - else - { - if ($type == 'cart_rule') - $array = $this->getCartRuleCombinations($offset, $limit, $search_cart_rule_name); - else - { - $resource = Db::getInstance()->query(' + $shop_list. + (in_array($type, array('carrier', 'shop')) ? ' ORDER BY t.name ASC ' : ''). + (in_array($type, array('country', 'group', 'cart_rule')) && $i18n ? ' ORDER BY tl.name ASC ' : ''). + $sql_limit); + } else { + if ($type == 'cart_rule') { + $array = $this->getCartRuleCombinations($offset, $limit, $search_cart_rule_name); + } else { + $resource = Db::getInstance()->query(' SELECT t.*'.($i18n ? ', tl.*' : '').', IF(crt.id_'.$type.' IS NULL, 0, 1) as selected FROM `'._DB_PREFIX_.$type.'` t '.($i18n ? 'LEFT JOIN `'._DB_PREFIX_.$type.'_lang` tl ON (t.id_'.$type.' = tl.id_'.$type.' AND tl.id_lang = '.(int)Context::getContext()->language->id.')' : '').' LEFT JOIN (SELECT id_'.$type.' FROM `'._DB_PREFIX_.'cart_rule_'.$type.'` WHERE id_cart_rule = '.(int)$this->id.') crt ON t.id_'.($type == 'carrier' ? 'reference' : $type).' = crt.id_'.$type.' WHERE 1 '.($active_only ? ' AND t.active = 1' : ''). - $shop_list - .(in_array($type, array('carrier', 'shop')) ? ' AND t.deleted = 0' : ''). - (in_array($type, array('carrier', 'shop')) ? ' ORDER BY t.name ASC ' : ''). - (in_array($type, array('country', 'group', 'cart_rule')) && $i18n ? ' ORDER BY tl.name ASC ' : ''). - $sql_limit, - false); - while ($row = Db::getInstance()->nextRow($resource)) - $array[($row['selected'] || $this->{$type.'_restriction'} == 0) ? 'selected' : 'unselected'][] = $row; - } - } - return $array; - } + $shop_list + .(in_array($type, array('carrier', 'shop')) ? ' AND t.deleted = 0' : ''). + (in_array($type, array('carrier', 'shop')) ? ' ORDER BY t.name ASC ' : ''). + (in_array($type, array('country', 'group', 'cart_rule')) && $i18n ? ' ORDER BY tl.name ASC ' : ''). + $sql_limit, + false); + while ($row = Db::getInstance()->nextRow($resource)) { + $array[($row['selected'] || $this->{$type.'_restriction'} == 0) ? 'selected' : 'unselected'][] = $row; + } + } + } + return $array; + } - public static function autoRemoveFromCart($context = null) - { - if (!$context) - $context = Context::getContext(); - if (!CartRule::isFeatureActive() || !Validate::isLoadedObject($context->cart)) - return array(); + public static function autoRemoveFromCart($context = null) + { + if (!$context) { + $context = Context::getContext(); + } + if (!CartRule::isFeatureActive() || !Validate::isLoadedObject($context->cart)) { + return array(); + } - static $errors = array(); - foreach ($context->cart->getCartRules() as $cart_rule) - { - if ($error = $cart_rule['obj']->checkValidity($context, true)) - { - $context->cart->removeCartRule($cart_rule['obj']->id); - $context->cart->update(); - $errors[] = $error; - } - } - return $errors; - } + static $errors = array(); + foreach ($context->cart->getCartRules() as $cart_rule) { + if ($error = $cart_rule['obj']->checkValidity($context, true)) { + $context->cart->removeCartRule($cart_rule['obj']->id); + $context->cart->update(); + $errors[] = $error; + } + } + return $errors; + } - /** - * @param Context|null $context - * @return mixed - */ - public static function autoAddToCart(Context $context = null) - { - if ($context === null) - $context = Context::getContext(); - if (!CartRule::isFeatureActive() || !Validate::isLoadedObject($context->cart)) - return; + /** + * @param Context|null $context + * @return mixed + */ + public static function autoAddToCart(Context $context = null) + { + if ($context === null) { + $context = Context::getContext(); + } + if (!CartRule::isFeatureActive() || !Validate::isLoadedObject($context->cart)) { + return; + } - $sql = ' + $sql = ' SELECT SQL_NO_CACHE cr.* FROM '._DB_PREFIX_.'cart_rule cr LEFT JOIN '._DB_PREFIX_.'cart_rule_shop crs ON cr.id_cart_rule = crs.id_cart_rule @@ -1283,83 +1334,90 @@ class CartRuleCore extends ObjectModel AND NOT EXISTS (SELECT 1 FROM '._DB_PREFIX_.'cart_cart_rule WHERE cr.id_cart_rule = '._DB_PREFIX_.'cart_cart_rule.id_cart_rule AND id_cart = '.(int)$context->cart->id.') ORDER BY priority'; - $result = Db::getInstance()->executeS($sql, true, false); - if ($result) - { - $cart_rules = ObjectModel::hydrateCollection('CartRule', $result); - if ($cart_rules) - foreach ($cart_rules as $cart_rule) - { - /** @var CartRule $cart_rule */ - if ($cart_rule->checkValidity($context, false, false)) - $context->cart->addCartRule($cart_rule->id); - } - } - } + $result = Db::getInstance()->executeS($sql, true, false); + if ($result) { + $cart_rules = ObjectModel::hydrateCollection('CartRule', $result); + if ($cart_rules) { + foreach ($cart_rules as $cart_rule) { + /** @var CartRule $cart_rule */ + if ($cart_rule->checkValidity($context, false, false)) { + $context->cart->addCartRule($cart_rule->id); + } + } + } + } + } - /** - * @return bool - */ - public static function isFeatureActive() - { - static $is_feature_active = null; - if ($is_feature_active === null) - $is_feature_active = (bool)Configuration::get('PS_CART_RULE_FEATURE_ACTIVE'); - return $is_feature_active; - } + /** + * @return bool + */ + public static function isFeatureActive() + { + static $is_feature_active = null; + if ($is_feature_active === null) { + $is_feature_active = (bool)Configuration::get('PS_CART_RULE_FEATURE_ACTIVE'); + } + return $is_feature_active; + } - /* When an entity associated to a product rule (product, category, attribute, supplier, manufacturer...) is deleted, the product rules must be updated */ - public static function cleanProductRuleIntegrity($type, $list) - { - // Type must be available in the 'type' enum of the table cart_rule_product_rule - if (!in_array($type, array('products', 'categories', 'attributes', 'manufacturers', 'suppliers'))) - return false; + /* When an entity associated to a product rule (product, category, attribute, supplier, manufacturer...) is deleted, the product rules must be updated */ + public static function cleanProductRuleIntegrity($type, $list) + { + // Type must be available in the 'type' enum of the table cart_rule_product_rule + if (!in_array($type, array('products', 'categories', 'attributes', 'manufacturers', 'suppliers'))) { + return false; + } - // This check must not be removed because this var is used a few lines below - $list = (is_array($list) ? implode(',', array_map('intval', $list)) : (int)$list); - if (!preg_match('/^[0-9,]+$/', $list)) - return false; + // This check must not be removed because this var is used a few lines below + $list = (is_array($list) ? implode(',', array_map('intval', $list)) : (int)$list); + if (!preg_match('/^[0-9,]+$/', $list)) { + return false; + } - // Delete associated restrictions on cart rules - Db::getInstance()->execute(' + // Delete associated restrictions on cart rules + Db::getInstance()->execute(' DELETE crprv FROM `'._DB_PREFIX_.'cart_rule_product_rule` crpr LEFT JOIN `'._DB_PREFIX_.'cart_rule_product_rule_value` crprv ON crpr.`id_product_rule` = crprv.`id_product_rule` WHERE crpr.`type` = "'.pSQL($type).'" AND crprv.`id_item` IN ('.$list.')'); // $list is checked a few lines above - // Delete the product rules that does not have any values - if (Db::getInstance()->Affected_Rows() > 0) - Db::getInstance()->delete('cart_rule_product_rule', 'NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'cart_rule_product_rule_value` + // Delete the product rules that does not have any values + if (Db::getInstance()->Affected_Rows() > 0) { + Db::getInstance()->delete('cart_rule_product_rule', 'NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'cart_rule_product_rule_value` WHERE `cart_rule_product_rule`.`id_product_rule` = `cart_rule_product_rule_value`.`id_product_rule`)'); - // If the product rules were the only conditions of a product rule group, delete the product rule group - if (Db::getInstance()->Affected_Rows() > 0) - Db::getInstance()->delete('cart_rule_product_rule_group', 'NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'cart_rule_product_rule` + } + // If the product rules were the only conditions of a product rule group, delete the product rule group + if (Db::getInstance()->Affected_Rows() > 0) { + Db::getInstance()->delete('cart_rule_product_rule_group', 'NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'cart_rule_product_rule` WHERE `cart_rule_product_rule`.`id_product_rule_group` = `cart_rule_product_rule_group`.`id_product_rule_group`)'); + } - // If the product rule group were the only restrictions of a cart rule, update de cart rule restriction cache - if (Db::getInstance()->Affected_Rows() > 0) - Db::getInstance()->execute(' + // If the product rule group were the only restrictions of a cart rule, update de cart rule restriction cache + if (Db::getInstance()->Affected_Rows() > 0) { + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'cart_rule` cr LEFT JOIN `'._DB_PREFIX_.'cart_rule_product_rule_group` crprg ON cr.id_cart_rule = crprg.id_cart_rule SET product_restriction = IF(crprg.id_product_rule_group IS NULL, 0, 1)'); + } - return true; - } + return true; + } - /** - * @param $name - * @param $id_lang - * @return array - */ - public static function getCartsRuleByCode($name, $id_lang, $extended = false) - { - $sql_base = 'SELECT cr.*, crl.* + /** + * @param $name + * @param $id_lang + * @return array + */ + public static function getCartsRuleByCode($name, $id_lang, $extended = false) + { + $sql_base = 'SELECT cr.*, crl.* FROM '._DB_PREFIX_.'cart_rule cr LEFT JOIN '._DB_PREFIX_.'cart_rule_lang crl ON (cr.id_cart_rule = crl.id_cart_rule AND crl.id_lang = '.(int)$id_lang.')'; - if ($extended) - return Db::getInstance()->executeS('('.$sql_base.' WHERE code LIKE \'%'.pSQL($name).'%\') UNION ('.$sql_base.' WHERE name LIKE \'%'.pSQL($name).'%\')'); - else - return Db::getInstance()->executeS($sql_base.' WHERE code LIKE \'%'.pSQL($name).'%\''); - } + if ($extended) { + return Db::getInstance()->executeS('('.$sql_base.' WHERE code LIKE \'%'.pSQL($name).'%\') UNION ('.$sql_base.' WHERE name LIKE \'%'.pSQL($name).'%\')'); + } else { + return Db::getInstance()->executeS($sql_base.' WHERE code LIKE \'%'.pSQL($name).'%\''); + } + } } diff --git a/classes/Category.php b/classes/Category.php index ca18a54f..77047023 100644 --- a/classes/Category.php +++ b/classes/Category.php @@ -26,445 +26,463 @@ class CategoryCore extends ObjectModel { - public $id; + public $id; - /** @var int category ID */ - public $id_category; + /** @var int category ID */ + public $id_category; - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var bool Status for display */ - public $active = 1; + /** @var bool Status for display */ + public $active = 1; - /** @var int category position */ - public $position; + /** @var int category position */ + public $position; - /** @var string Description */ - public $description; + /** @var string Description */ + public $description; - /** @var int Parent category ID */ - public $id_parent; + /** @var int Parent category ID */ + public $id_parent; - /** @var int default Category id */ - public $id_category_default; + /** @var int default Category id */ + public $id_category_default; - /** @var int Parents number */ - public $level_depth; + /** @var int Parents number */ + public $level_depth; - /** @var int Nested tree model "left" value */ - public $nleft; + /** @var int Nested tree model "left" value */ + public $nleft; - /** @var int Nested tree model "right" value */ - public $nright; + /** @var int Nested tree model "right" value */ + public $nright; - /** @var string string used in rewrited URL */ - public $link_rewrite; + /** @var string string used in rewrited URL */ + public $link_rewrite; - /** @var string Meta title */ - public $meta_title; + /** @var string Meta title */ + public $meta_title; - /** @var string Meta keywords */ - public $meta_keywords; + /** @var string Meta keywords */ + public $meta_keywords; - /** @var string Meta description */ - public $meta_description; + /** @var string Meta description */ + public $meta_description; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** @var string Object last modification date */ - public $date_upd; + /** @var string Object last modification date */ + public $date_upd; - /** @var bool is Category Root */ - public $is_root_category; + /** @var bool is Category Root */ + public $is_root_category; - /** @var int */ - public $id_shop_default; + /** @var int */ + public $id_shop_default; - public $groupBox; + public $groupBox; - protected static $_links = array(); + protected static $_links = array(); - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'category', - 'primary' => 'id_category', - 'multilang' => true, - 'multilang_shop' => true, - 'fields' => array( - 'nleft' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'nright' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'level_depth' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), - 'id_parent' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'id_shop_default' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'is_root_category' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'position' => array('type' => self::TYPE_INT), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCatalogName', 'required' => true, 'size' => 128), - 'link_rewrite' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isLinkRewrite', 'required' => true, 'size' => 128), - 'description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), - 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), - 'meta_description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - 'meta_keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'category', + 'primary' => 'id_category', + 'multilang' => true, + 'multilang_shop' => true, + 'fields' => array( + 'nleft' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'nright' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'level_depth' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), + 'id_parent' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'id_shop_default' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'is_root_category' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'position' => array('type' => self::TYPE_INT), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCatalogName', 'required' => true, 'size' => 128), + 'link_rewrite' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isLinkRewrite', 'required' => true, 'size' => 128), + 'description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), + 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), + 'meta_description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + 'meta_keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + ), + ); - /** @var string id_image is the category ID when an image exists and 'default' otherwise */ - public $id_image = 'default'; + /** @var string id_image is the category ID when an image exists and 'default' otherwise */ + public $id_image = 'default'; - protected $webserviceParameters = array( - 'objectsNodeName' => 'categories', - 'hidden_fields' => array('nleft', 'nright', 'groupBox'), - 'fields' => array( - 'id_parent' => array('xlink_resource'=> 'categories'), - 'level_depth' => array('setter' => false), - 'nb_products_recursive' => array('getter' => 'getWsNbProductsRecursive', 'setter' => false), - ), - 'associations' => array( - 'categories' => array('getter' => 'getChildrenWs', 'resource' => 'category', ), - 'products' => array('getter' => 'getProductsWs', 'resource' => 'product', ), - ), - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'categories', + 'hidden_fields' => array('nleft', 'nright', 'groupBox'), + 'fields' => array( + 'id_parent' => array('xlink_resource'=> 'categories'), + 'level_depth' => array('setter' => false), + 'nb_products_recursive' => array('getter' => 'getWsNbProductsRecursive', 'setter' => false), + ), + 'associations' => array( + 'categories' => array('getter' => 'getChildrenWs', 'resource' => 'category', ), + 'products' => array('getter' => 'getProductsWs', 'resource' => 'product', ), + ), + ); - public function __construct($id_category = null, $id_lang = null, $id_shop = null) - { - parent::__construct($id_category, $id_lang, $id_shop); - $this->id_image = ($this->id && file_exists(_PS_CAT_IMG_DIR_.(int)$this->id.'.jpg')) ? (int)$this->id : false; - $this->image_dir = _PS_CAT_IMG_DIR_; - } + public function __construct($id_category = null, $id_lang = null, $id_shop = null) + { + parent::__construct($id_category, $id_lang, $id_shop); + $this->id_image = ($this->id && file_exists(_PS_CAT_IMG_DIR_.(int)$this->id.'.jpg')) ? (int)$this->id : false; + $this->image_dir = _PS_CAT_IMG_DIR_; + } - public static function getDescriptionClean($description) - { - return Tools::getDescriptionClean($description); - } + public static function getDescriptionClean($description) + { + return Tools::getDescriptionClean($description); + } - public function add($autodate = true, $null_values = false) - { - if (!isset($this->level_depth)) - $this->level_depth = $this->calcLevelDepth(); + public function add($autodate = true, $null_values = false) + { + if (!isset($this->level_depth)) { + $this->level_depth = $this->calcLevelDepth(); + } - if ($this->is_root_category && ($id_root_category = (int)Configuration::get('PS_ROOT_CATEGORY'))) - $this->id_parent = $id_root_category; + if ($this->is_root_category && ($id_root_category = (int)Configuration::get('PS_ROOT_CATEGORY'))) { + $this->id_parent = $id_root_category; + } - $ret = parent::add($autodate, $null_values); - if (Tools::isSubmit('checkBoxShopAsso_category')) - foreach (Tools::getValue('checkBoxShopAsso_category') as $id_shop => $value) - { - $position = (int)Category::getLastPosition((int)$this->id_parent, $id_shop); - $this->addPosition($position, $id_shop); - } - else - foreach (Shop::getShops(true) as $shop) - { - $position = (int)Category::getLastPosition((int)$this->id_parent, $shop['id_shop']); - $this->addPosition($position, $shop['id_shop']); - } - if (!isset($this->doNotRegenerateNTree) || !$this->doNotRegenerateNTree) - Category::regenerateEntireNtree(); - $this->updateGroup($this->groupBox); - Hook::exec('actionCategoryAdd', array('category' => $this)); - return $ret; - } + $ret = parent::add($autodate, $null_values); + if (Tools::isSubmit('checkBoxShopAsso_category')) { + foreach (Tools::getValue('checkBoxShopAsso_category') as $id_shop => $value) { + $position = (int)Category::getLastPosition((int)$this->id_parent, $id_shop); + $this->addPosition($position, $id_shop); + } + } else { + foreach (Shop::getShops(true) as $shop) { + $position = (int)Category::getLastPosition((int)$this->id_parent, $shop['id_shop']); + $this->addPosition($position, $shop['id_shop']); + } + } + if (!isset($this->doNotRegenerateNTree) || !$this->doNotRegenerateNTree) { + Category::regenerateEntireNtree(); + } + $this->updateGroup($this->groupBox); + Hook::exec('actionCategoryAdd', array('category' => $this)); + return $ret; + } - /** - * update category positions in parent - * - * @param mixed $null_values - * @return bool - */ - public function update($null_values = false) - { - if ($this->id_parent == $this->id) - throw new PrestaShopException('a category cannot be its own parent'); + /** + * update category positions in parent + * + * @param mixed $null_values + * @return bool + */ + public function update($null_values = false) + { + if ($this->id_parent == $this->id) { + throw new PrestaShopException('a category cannot be its own parent'); + } - if ($this->is_root_category && $this->id_parent != (int)Configuration::get('PS_ROOT_CATEGORY')) - $this->is_root_category = 0; + if ($this->is_root_category && $this->id_parent != (int)Configuration::get('PS_ROOT_CATEGORY')) { + $this->is_root_category = 0; + } - // Update group selection - $this->updateGroup($this->groupBox); + // Update group selection + $this->updateGroup($this->groupBox); - if ($this->level_depth != $this->calcLevelDepth()) - { - $this->level_depth = $this->calcLevelDepth(); - $changed = true; - } + if ($this->level_depth != $this->calcLevelDepth()) { + $this->level_depth = $this->calcLevelDepth(); + $changed = true; + } - // If the parent category was changed, we don't want to have 2 categories with the same position - if (!isset($changed)) - $changed = $this->getDuplicatePosition(); - if ($changed) - { - if (Tools::isSubmit('checkBoxShopAsso_category')) - foreach (Tools::getValue('checkBoxShopAsso_category') as $id_asso_object => $row) - foreach ($row as $id_shop => $value) - $this->addPosition((int)Category::getLastPosition((int)$this->id_parent, (int)$id_shop), (int)$id_shop); - else - foreach (Shop::getShops(true) as $shop) - $this->addPosition((int)Category::getLastPosition((int)$this->id_parent, $shop['id_shop']), $shop['id_shop']); - } + // If the parent category was changed, we don't want to have 2 categories with the same position + if (!isset($changed)) { + $changed = $this->getDuplicatePosition(); + } + if ($changed) { + if (Tools::isSubmit('checkBoxShopAsso_category')) { + foreach (Tools::getValue('checkBoxShopAsso_category') as $id_asso_object => $row) { + foreach ($row as $id_shop => $value) { + $this->addPosition((int)Category::getLastPosition((int)$this->id_parent, (int)$id_shop), (int)$id_shop); + } + } + } else { + foreach (Shop::getShops(true) as $shop) { + $this->addPosition((int)Category::getLastPosition((int)$this->id_parent, $shop['id_shop']), $shop['id_shop']); + } + } + } - $ret = parent::update($null_values); - if ($changed && (!isset($this->doNotRegenerateNTree) || !$this->doNotRegenerateNTree)) - { - $this->cleanPositions((int)$this->id_parent); - Category::regenerateEntireNtree(); - $this->recalculateLevelDepth($this->id); - } - Hook::exec('actionCategoryUpdate', array('category' => $this)); - return $ret; - } + $ret = parent::update($null_values); + if ($changed && (!isset($this->doNotRegenerateNTree) || !$this->doNotRegenerateNTree)) { + $this->cleanPositions((int)$this->id_parent); + Category::regenerateEntireNtree(); + $this->recalculateLevelDepth($this->id); + } + Hook::exec('actionCategoryUpdate', array('category' => $this)); + return $ret; + } - /** - * @see ObjectModel::toggleStatus() - */ - public function toggleStatus() - { - $result = parent::toggleStatus(); - Hook::exec('actionCategoryUpdate'); - return $result; - } + /** + * @see ObjectModel::toggleStatus() + */ + public function toggleStatus() + { + $result = parent::toggleStatus(); + Hook::exec('actionCategoryUpdate'); + return $result; + } - /** - * Recursive scan of subcategories - * - * @param int $max_depth Maximum depth of the tree (i.e. 2 => 3 levels depth) - * @param int $current_depth specify the current depth in the tree (don't use it, only for rucursivity!) - * @param int $id_lang Specify the id of the language used - * @param array $excluded_ids_array specify a list of ids to exclude of results - * - * @return array Subcategories lite tree - */ - public function recurseLiteCategTree($max_depth = 3, $current_depth = 0, $id_lang = null, $excluded_ids_array = null) - { - $id_lang = is_null($id_lang) ? Context::getContext()->language->id : (int)$id_lang; + /** + * Recursive scan of subcategories + * + * @param int $max_depth Maximum depth of the tree (i.e. 2 => 3 levels depth) + * @param int $current_depth specify the current depth in the tree (don't use it, only for rucursivity!) + * @param int $id_lang Specify the id of the language used + * @param array $excluded_ids_array specify a list of ids to exclude of results + * + * @return array Subcategories lite tree + */ + public function recurseLiteCategTree($max_depth = 3, $current_depth = 0, $id_lang = null, $excluded_ids_array = null) + { + $id_lang = is_null($id_lang) ? Context::getContext()->language->id : (int)$id_lang; - $children = array(); - $subcats = $this->getSubCategories($id_lang, true); - if (($max_depth == 0 || $current_depth < $max_depth) && $subcats && count($subcats)) - foreach ($subcats as &$subcat) - { - if (!$subcat['id_category']) - break; - elseif (!is_array($excluded_ids_array) || !in_array($subcat['id_category'], $excluded_ids_array)) - { - $categ = new Category($subcat['id_category'], $id_lang); - $children[] = $categ->recurseLiteCategTree($max_depth, $current_depth + 1, $id_lang, $excluded_ids_array); - } - } + $children = array(); + $subcats = $this->getSubCategories($id_lang, true); + if (($max_depth == 0 || $current_depth < $max_depth) && $subcats && count($subcats)) { + foreach ($subcats as &$subcat) { + if (!$subcat['id_category']) { + break; + } elseif (!is_array($excluded_ids_array) || !in_array($subcat['id_category'], $excluded_ids_array)) { + $categ = new Category($subcat['id_category'], $id_lang); + $children[] = $categ->recurseLiteCategTree($max_depth, $current_depth + 1, $id_lang, $excluded_ids_array); + } + } + } - if (is_array($this->description)) - foreach ($this->description as $lang => $description) - $this->description[$lang] = Category::getDescriptionClean($description); - else - $this->description = Category::getDescriptionClean($this->description); + if (is_array($this->description)) { + foreach ($this->description as $lang => $description) { + $this->description[$lang] = Category::getDescriptionClean($description); + } + } else { + $this->description = Category::getDescriptionClean($this->description); + } - return array( - 'id' => (int)$this->id, - 'link' => Context::getContext()->link->getCategoryLink($this->id, $this->link_rewrite), - 'name' => $this->name, - 'desc'=> $this->description, - 'children' => $children - ); - } + return array( + 'id' => (int)$this->id, + 'link' => Context::getContext()->link->getCategoryLink($this->id, $this->link_rewrite), + 'name' => $this->name, + 'desc'=> $this->description, + 'children' => $children + ); + } - public static function recurseCategory($categories, $current, $id_category = null, $id_selected = 1) - { - if (!$id_category) - $id_category = (int)Configuration::get('PS_ROOT_CATEGORY'); + public static function recurseCategory($categories, $current, $id_category = null, $id_selected = 1) + { + if (!$id_category) { + $id_category = (int)Configuration::get('PS_ROOT_CATEGORY'); + } - echo ''; - if (isset($categories[$id_category])) - foreach (array_keys($categories[$id_category]) as $key) - Category::recurseCategory($categories, $categories[$id_category][$key], $key, $id_selected); - } + echo ''; + if (isset($categories[$id_category])) { + foreach (array_keys($categories[$id_category]) as $key) { + Category::recurseCategory($categories, $categories[$id_category][$key], $key, $id_selected); + } + } + } - /** - * Recursively add specified category childs to $to_delete array - * - * @param array &$to_delete Array reference where categories ID will be saved - * @param int $id_category Parent category ID - */ - protected function recursiveDelete(&$to_delete, $id_category) - { - if (!is_array($to_delete) || !$id_category) - die(Tools::displayError()); + /** + * Recursively add specified category childs to $to_delete array + * + * @param array &$to_delete Array reference where categories ID will be saved + * @param int $id_category Parent category ID + */ + protected function recursiveDelete(&$to_delete, $id_category) + { + if (!is_array($to_delete) || !$id_category) { + die(Tools::displayError()); + } - $result = Db::getInstance()->executeS(' + $result = Db::getInstance()->executeS(' SELECT `id_category` FROM `'._DB_PREFIX_.'category` WHERE `id_parent` = '.(int)$id_category); - foreach ($result as $row) - { - $to_delete[] = (int)$row['id_category']; - $this->recursiveDelete($to_delete, (int)$row['id_category']); - } - } + foreach ($result as $row) { + $to_delete[] = (int)$row['id_category']; + $this->recursiveDelete($to_delete, (int)$row['id_category']); + } + } - public function deleteLite() - { - // Directly call the parent of delete, in order to avoid recursion - return parent::delete(); - } + public function deleteLite() + { + // Directly call the parent of delete, in order to avoid recursion + return parent::delete(); + } - public function delete() - { - if ((int)$this->id === 0 || (int)$this->id === (int)Configuration::get('PS_ROOT_CATEGORY')) - return false; + public function delete() + { + if ((int)$this->id === 0 || (int)$this->id === (int)Configuration::get('PS_ROOT_CATEGORY')) { + return false; + } - $this->clearCache(); + $this->clearCache(); - $all_cat = $this->getAllChildren(); - $all_cat[] = $this; - foreach ($all_cat as $cat) - { - /** @var Category $cat */ - $cat->deleteLite(); - if (!$this->hasMultishopEntries()) - { - $cat->deleteImage(); - $cat->cleanGroups(); - $cat->cleanAssoProducts(); - // Delete associated restrictions on cart rules - CartRule::cleanProductRuleIntegrity('categories', array($cat->id)); - Category::cleanPositions($cat->id_parent); - /* Delete Categories in GroupReduction */ - if (GroupReduction::getGroupsReductionByCategoryId((int)$cat->id)) - GroupReduction::deleteCategory($cat->id); - } - } + $deleted_children = $all_cat = $this->getAllChildren(); + $all_cat[] = $this; + foreach ($all_cat as $cat) { + /** @var Category $cat */ + $cat->deleteLite(); + if (!$this->hasMultishopEntries()) { + $cat->deleteImage(); + $cat->cleanGroups(); + $cat->cleanAssoProducts(); + // Delete associated restrictions on cart rules + CartRule::cleanProductRuleIntegrity('categories', array($cat->id)); + Category::cleanPositions($cat->id_parent); + /* Delete Categories in GroupReduction */ + if (GroupReduction::getGroupsReductionByCategoryId((int)$cat->id)) { + GroupReduction::deleteCategory($cat->id); + } + } + } - /* Rebuild the nested tree */ - if (!$this->hasMultishopEntries() && (!isset($this->doNotRegenerateNTree) || !$this->doNotRegenerateNTree)) - Category::regenerateEntireNtree(); + /* Rebuild the nested tree */ + if (!$this->hasMultishopEntries() && (!isset($this->doNotRegenerateNTree) || !$this->doNotRegenerateNTree)) { + Category::regenerateEntireNtree(); + } - Hook::exec('actionCategoryDelete', array('category' => $this)); + Hook::exec('actionCategoryDelete', array('category' => $this, 'deleted_children' => $deleted_children)); - return true; - } + return true; + } - /** - * Delete several categories from database - * - * return boolean Deletion result - */ - public function deleteSelection($categories) - { - $return = 1; - foreach ($categories as $id_category) - { - $category = new Category($id_category); - if ($category->isRootCategoryForAShop()) - return false; - else - $return &= $category->delete(); - } - return $return; - } + /** + * Delete several categories from database + * + * return boolean Deletion result + */ + public function deleteSelection($categories) + { + $return = 1; + foreach ($categories as $id_category) { + $category = new Category($id_category); + if ($category->isRootCategoryForAShop()) { + return false; + } else { + $return &= $category->delete(); + } + } + return $return; + } - /** - * Get the depth level for the category - * - * @return int Depth level - */ - public function calcLevelDepth() - { - /* Root category */ - if (!$this->id_parent) - return 0; + /** + * Get the depth level for the category + * + * @return int Depth level + */ + public function calcLevelDepth() + { + /* Root category */ + if (!$this->id_parent) { + return 0; + } - $parent_category = new Category((int)$this->id_parent); - if (!Validate::isLoadedObject($parent_category)) - throw new PrestaShopException('Parent category does not exist'); - return $parent_category->level_depth + 1; - } + $parent_category = new Category((int)$this->id_parent); + if (!Validate::isLoadedObject($parent_category)) { + throw new PrestaShopException('Parent category does not exist'); + } + return $parent_category->level_depth + 1; + } - /** - * Re-calculate the values of all branches of the nested tree - */ - public static function regenerateEntireNtree() - { - $id = Context::getContext()->shop->id; - $id_shop = $id ? $id: Configuration::get('PS_SHOP_DEFAULT'); - $categories = Db::getInstance()->executeS(' + /** + * Re-calculate the values of all branches of the nested tree + */ + public static function regenerateEntireNtree() + { + $id = Context::getContext()->shop->id; + $id_shop = $id ? $id: Configuration::get('PS_SHOP_DEFAULT'); + $categories = Db::getInstance()->executeS(' SELECT c.`id_category`, c.`id_parent` FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_shop` cs ON (c.`id_category` = cs.`id_category` AND cs.`id_shop` = '.(int)$id_shop.') ORDER BY c.`id_parent`, cs.`position` ASC'); - $categories_array = array(); - foreach ($categories as $category) - $categories_array[$category['id_parent']]['subcategories'][] = $category['id_category']; - $n = 1; + $categories_array = array(); + foreach ($categories as $category) { + $categories_array[$category['id_parent']]['subcategories'][] = $category['id_category']; + } + $n = 1; - if (isset($categories_array[0]) && $categories_array[0]['subcategories']) - Category::_subTree($categories_array, $categories_array[0]['subcategories'][0], $n); - } + if (isset($categories_array[0]) && $categories_array[0]['subcategories']) { + Category::_subTree($categories_array, $categories_array[0]['subcategories'][0], $n); + } + } - protected static function _subTree(&$categories, $id_category, &$n) - { - $left = $n++; - if (isset($categories[(int)$id_category]['subcategories'])) - foreach ($categories[(int)$id_category]['subcategories'] as $id_subcategory) - Category::_subTree($categories, (int)$id_subcategory, $n); - $right = (int)$n++; + protected static function _subTree(&$categories, $id_category, &$n) + { + $left = $n++; + if (isset($categories[(int)$id_category]['subcategories'])) { + foreach ($categories[(int)$id_category]['subcategories'] as $id_subcategory) { + Category::_subTree($categories, (int)$id_subcategory, $n); + } + } + $right = (int)$n++; - Db::getInstance()->execute(' + Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'category SET nleft = '.(int)$left.', nright = '.(int)$right.' WHERE id_category = '.(int)$id_category.' LIMIT 1'); - } + } - /** - * Updates level_depth for all children of the given id_category - * - * @param int $id_category parent category - */ - public function recalculateLevelDepth($id_category) - { - if (!is_numeric($id_category)) - throw new PrestaShopException('id category is not numeric'); - /* Gets all children */ - $categories = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * Updates level_depth for all children of the given id_category + * + * @param int $id_category parent category + */ + public function recalculateLevelDepth($id_category) + { + if (!is_numeric($id_category)) { + throw new PrestaShopException('id category is not numeric'); + } + /* Gets all children */ + $categories = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT id_category, id_parent, level_depth FROM '._DB_PREFIX_.'category WHERE id_parent = '.(int)$id_category); - /* Gets level_depth */ - $level = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + /* Gets level_depth */ + $level = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT level_depth FROM '._DB_PREFIX_.'category WHERE id_category = '.(int)$id_category); - /* Updates level_depth for all children */ - foreach ($categories as $sub_category) - { - Db::getInstance()->execute(' + /* Updates level_depth for all children */ + foreach ($categories as $sub_category) { + Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'category SET level_depth = '.(int)($level['level_depth'] + 1).' WHERE id_category = '.(int)$sub_category['id_category']); - /* Recursive call */ - $this->recalculateLevelDepth($sub_category['id_category']); - } - } + /* Recursive call */ + $this->recalculateLevelDepth($sub_category['id_category']); + } + } - /** - * Return available categories - * - * @param int $id_lang Language ID - * @param bool $active return only active categories - * @return array Categories - */ - public static function getCategories($id_lang = false, $active = true, $order = true, $sql_filter = '', $sql_sort = '', $sql_limit = '') - { - if (!Validate::isBool($active)) - die(Tools::displayError()); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * Return available categories + * + * @param int $id_lang Language ID + * @param bool $active return only active categories + * @return array Categories + */ + public static function getCategories($id_lang = false, $active = true, $order = true, $sql_filter = '', $sql_sort = '', $sql_limit = '') + { + if (!Validate::isBool($active)) { + die(Tools::displayError()); + } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'category` c '.Shop::addSqlAssociation('category', 'c').' @@ -474,36 +492,40 @@ class CategoryCore extends ObjectModel '.(!$id_lang ? 'GROUP BY c.id_category' : '').' '.($sql_sort != '' ? $sql_sort : 'ORDER BY c.`level_depth` ASC, category_shop.`position` ASC').' '.($sql_limit != '' ? $sql_limit : '') - ); + ); - if (!$order) - return $result; + if (!$order) { + return $result; + } - $categories = array(); - foreach ($result as $row) - $categories[$row['id_parent']][$row['id_category']]['infos'] = $row; + $categories = array(); + foreach ($result as $row) { + $categories[$row['id_parent']][$row['id_category']]['infos'] = $row; + } - return $categories; - } + return $categories; + } - public static function getAllCategoriesName($root_category = null, $id_lang = false, $active = true, $groups = null, - $use_shop_restriction = true, $sql_filter = '', $sql_sort = '', $sql_limit = '') - { - if (isset($root_category) && !Validate::isInt($root_category)) - die(Tools::displayError()); + public static function getAllCategoriesName($root_category = null, $id_lang = false, $active = true, $groups = null, + $use_shop_restriction = true, $sql_filter = '', $sql_sort = '', $sql_limit = '') + { + if (isset($root_category) && !Validate::isInt($root_category)) { + die(Tools::displayError()); + } - if (!Validate::isBool($active)) - die(Tools::displayError()); + if (!Validate::isBool($active)) { + die(Tools::displayError()); + } - if (isset($groups) && Group::isFeatureActive() && !is_array($groups)) - $groups = (array)$groups; + if (isset($groups) && Group::isFeatureActive() && !is_array($groups)) { + $groups = (array)$groups; + } - $cache_id = 'Category::getAllCategoriesName_'.md5((int)$root_category.(int)$id_lang.(int)$active.(int)$use_shop_restriction - .(isset($groups) && Group::isFeatureActive() ? implode('', $groups) : '')); + $cache_id = 'Category::getAllCategoriesName_'.md5((int)$root_category.(int)$id_lang.(int)$active.(int)$use_shop_restriction + .(isset($groups) && Group::isFeatureActive() ? implode('', $groups) : '')); - if (!Cache::isStored($cache_id)) - { - $result = Db::getInstance()->executeS(' + if (!Cache::isStored($cache_id)) { + $result = Db::getInstance()->executeS(' SELECT c.id_category, cl.name FROM `'._DB_PREFIX_.'category` c '.($use_shop_restriction ? Shop::addSqlAssociation('category', 'c') : '').' @@ -517,34 +539,36 @@ class CategoryCore extends ObjectModel '.($sql_sort != '' ? $sql_sort : ' ORDER BY c.`level_depth` ASC').' '.($sql_sort == '' && $use_shop_restriction ? ', category_shop.`position` ASC' : '').' '.($sql_limit != '' ? $sql_limit : '') - ); + ); - Cache::store($cache_id, $result); - } - else - $result = Cache::retrieve($cache_id); + Cache::store($cache_id, $result); + } else { + $result = Cache::retrieve($cache_id); + } - return $result; - } + return $result; + } - public static function getNestedCategories($root_category = null, $id_lang = false, $active = true, $groups = null, - $use_shop_restriction = true, $sql_filter = '', $sql_sort = '', $sql_limit = '') - { - if (isset($root_category) && !Validate::isInt($root_category)) - die(Tools::displayError()); + public static function getNestedCategories($root_category = null, $id_lang = false, $active = true, $groups = null, + $use_shop_restriction = true, $sql_filter = '', $sql_sort = '', $sql_limit = '') + { + if (isset($root_category) && !Validate::isInt($root_category)) { + die(Tools::displayError()); + } - if (!Validate::isBool($active)) - die(Tools::displayError()); + if (!Validate::isBool($active)) { + die(Tools::displayError()); + } - if (isset($groups) && Group::isFeatureActive() && !is_array($groups)) - $groups = (array)$groups; + if (isset($groups) && Group::isFeatureActive() && !is_array($groups)) { + $groups = (array)$groups; + } - $cache_id = 'Category::getNestedCategories_'.md5((int)$root_category.(int)$id_lang.(int)$active.(int)$use_shop_restriction - .(isset($groups) && Group::isFeatureActive() ? implode('', $groups) : '')); + $cache_id = 'Category::getNestedCategories_'.md5((int)$root_category.(int)$id_lang.(int)$active.(int)$use_shop_restriction + .(isset($groups) && Group::isFeatureActive() ? implode('', $groups) : '')); - if (!Cache::isStored($cache_id)) - { - $result = Db::getInstance()->executeS(' + if (!Cache::isStored($cache_id)) { + $result = Db::getInstance()->executeS(' SELECT c.*, cl.* FROM `'._DB_PREFIX_.'category` c '.($use_shop_restriction ? Shop::addSqlAssociation('category', 'c') : '').' @@ -558,36 +582,37 @@ class CategoryCore extends ObjectModel '.($sql_sort != '' ? $sql_sort : ' ORDER BY c.`level_depth` ASC').' '.($sql_sort == '' && $use_shop_restriction ? ', category_shop.`position` ASC' : '').' '.($sql_limit != '' ? $sql_limit : '') - ); + ); - $categories = array(); - $buff = array(); + $categories = array(); + $buff = array(); - if (!isset($root_category)) - $root_category = Category::getRootCategory()->id; + if (!isset($root_category)) { + $root_category = Category::getRootCategory()->id; + } - foreach ($result as $row) - { - $current = &$buff[$row['id_category']]; - $current = $row; + foreach ($result as $row) { + $current = &$buff[$row['id_category']]; + $current = $row; - if ($row['id_category'] == $root_category) - $categories[$row['id_category']] = &$current; - else - $buff[$row['id_parent']]['children'][$row['id_category']] = &$current; - } + if ($row['id_category'] == $root_category) { + $categories[$row['id_category']] = &$current; + } else { + $buff[$row['id_parent']]['children'][$row['id_category']] = &$current; + } + } - Cache::store($cache_id, $categories); - } - else - $categories = Cache::retrieve($cache_id); + Cache::store($cache_id, $categories); + } else { + $categories = Cache::retrieve($cache_id); + } - return $categories; - } + return $categories; + } - public static function getSimpleCategories($id_lang) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getSimpleCategories($id_lang) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT c.`id_category`, cl.`name` FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category`'.Shop::addSqlRestrictionOnLang('cl').') @@ -596,32 +621,31 @@ class CategoryCore extends ObjectModel AND c.`id_category` != '.Configuration::get('PS_ROOT_CATEGORY').' GROUP BY c.id_category ORDER BY c.`id_category`, category_shop.`position`'); - } + } - public function getShopID() - { - return $this->id_shop; - } + public function getShopID() + { + return $this->id_shop; + } - /** - * Return current category childs - * - * @param int $id_lang Language ID - * @param bool $active return only active categories - * @return array Categories - */ - public function getSubCategories($id_lang, $active = true) - { - $sql_groups_where = ''; - $sql_groups_join = ''; - if (Group::isFeatureActive()) - { - $sql_groups_join = 'LEFT JOIN `'._DB_PREFIX_.'category_group` cg ON (cg.`id_category` = c.`id_category`)'; - $groups = FrontController::getCurrentCustomerGroups(); - $sql_groups_where = 'AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '='.(int)Group::getCurrent()->id); - } + /** + * Return current category childs + * + * @param int $id_lang Language ID + * @param bool $active return only active categories + * @return array Categories + */ + public function getSubCategories($id_lang, $active = true) + { + $sql_groups_where = ''; + $sql_groups_join = ''; + if (Group::isFeatureActive()) { + $sql_groups_join = 'LEFT JOIN `'._DB_PREFIX_.'category_group` cg ON (cg.`id_category` = c.`id_category`)'; + $groups = FrontController::getCurrentCustomerGroups(); + $sql_groups_where = 'AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '='.(int)Group::getCurrent()->id); + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT c.*, cl.id_lang, cl.name, cl.description, cl.link_rewrite, cl.meta_title, cl.meta_keywords, cl.meta_description FROM `'._DB_PREFIX_.'category` c '.Shop::addSqlAssociation('category', 'c').' @@ -633,87 +657,89 @@ class CategoryCore extends ObjectModel GROUP BY c.`id_category` ORDER BY `level_depth` ASC, category_shop.`position` ASC'); - foreach ($result as &$row) - { - $row['id_image'] = Tools::file_exists_cache(_PS_CAT_IMG_DIR_.$row['id_category'].'.jpg') ? (int)$row['id_category'] : Language::getIsoById($id_lang).'-default'; - $row['legend'] = 'no picture'; - } - return $result; - } + foreach ($result as &$row) { + $row['id_image'] = Tools::file_exists_cache(_PS_CAT_IMG_DIR_.$row['id_category'].'.jpg') ? (int)$row['id_category'] : Language::getIsoById($id_lang).'-default'; + $row['legend'] = 'no picture'; + } + return $result; + } - /** - * Returns category products - * - * @param int $id_lang Language ID - * @param int $p Page number - * @param int $n Number of products per page - * @param string|null $order_by ORDER BY column - * @param string|null $order_way Order way - * @param bool $get_total If set to true, returns the total number of results only - * @param bool $active If set to true, finds only active products - * @param bool $random If true, sets a random filter for returned products - * @param int $random_number_products Number of products to return if random is activated - * @param bool $check_access If set tot rue, check if the current customer - * can see products from this category - * @param Context|null $context - * - * @return array|int|false Products, number of products or false (no access) - * @throws PrestaShopDatabaseException - */ - public function getProducts($id_lang, $p, $n, $order_by = null, $order_way = null, $get_total = false, $active = true, $random = false, $random_number_products = 1, $check_access = true, Context $context = null) - { - if (!$context) - $context = Context::getContext(); + /** + * Returns category products + * + * @param int $id_lang Language ID + * @param int $p Page number + * @param int $n Number of products per page + * @param string|null $order_by ORDER BY column + * @param string|null $order_way Order way + * @param bool $get_total If set to true, returns the total number of results only + * @param bool $active If set to true, finds only active products + * @param bool $random If true, sets a random filter for returned products + * @param int $random_number_products Number of products to return if random is activated + * @param bool $check_access If set tot rue, check if the current customer + * can see products from this category + * @param Context|null $context + * + * @return array|int|false Products, number of products or false (no access) + * @throws PrestaShopDatabaseException + */ + public function getProducts($id_lang, $p, $n, $order_by = null, $order_way = null, $get_total = false, $active = true, $random = false, $random_number_products = 1, $check_access = true, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } - if ($check_access && !$this->checkAccess($context->customer->id)) - return false; + if ($check_access && !$this->checkAccess($context->customer->id)) { + return false; + } - $front = in_array($context->controller->controller_type, array('front', 'modulefront')); - $id_supplier = (int)Tools::getValue('id_supplier'); + $front = in_array($context->controller->controller_type, array('front', 'modulefront')); + $id_supplier = (int)Tools::getValue('id_supplier'); - /** Return only the number of products */ - if ($get_total) - { - $sql = 'SELECT COUNT(cp.`id_product`) AS total + /** Return only the number of products */ + if ($get_total) { + $sql = 'SELECT COUNT(cp.`id_product`) AS total FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON p.`id_product` = cp.`id_product` WHERE cp.`id_category` = '.(int)$this->id. - ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : ''). - ($active ? ' AND product_shop.`active` = 1' : ''). - ($id_supplier ? 'AND p.id_supplier = '.(int)$id_supplier : ''); + ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : ''). + ($active ? ' AND product_shop.`active` = 1' : ''). + ($id_supplier ? 'AND p.id_supplier = '.(int)$id_supplier : ''); - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); - } + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); + } - if ($p < 1) - $p = 1; + if ($p < 1) { + $p = 1; + } - /** Tools::strtolower is a fix for all modules which are now using lowercase values for 'orderBy' parameter */ - $order_by = Validate::isOrderBy($order_by) ? Tools::strtolower($order_by) : 'position'; - $order_way = Validate::isOrderWay($order_way) ? Tools::strtoupper($order_way) : 'ASC'; + /** Tools::strtolower is a fix for all modules which are now using lowercase values for 'orderBy' parameter */ + $order_by = Validate::isOrderBy($order_by) ? Tools::strtolower($order_by) : 'position'; + $order_way = Validate::isOrderWay($order_way) ? Tools::strtoupper($order_way) : 'ASC'; - $order_by_prefix = false; - if ($order_by == 'id_product' || $order_by == 'date_add' || $order_by == 'date_upd') - $order_by_prefix = 'p'; - elseif ($order_by == 'name') - $order_by_prefix = 'pl'; - elseif ($order_by == 'manufacturer' || $order_by == 'manufacturer_name') - { - $order_by_prefix = 'm'; - $order_by = 'name'; - } - elseif ($order_by == 'position') - $order_by_prefix = 'cp'; + $order_by_prefix = false; + if ($order_by == 'id_product' || $order_by == 'date_add' || $order_by == 'date_upd') { + $order_by_prefix = 'p'; + } elseif ($order_by == 'name') { + $order_by_prefix = 'pl'; + } elseif ($order_by == 'manufacturer' || $order_by == 'manufacturer_name') { + $order_by_prefix = 'm'; + $order_by = 'name'; + } elseif ($order_by == 'position') { + $order_by_prefix = 'cp'; + } - if ($order_by == 'price') - $order_by = 'orderprice'; + if ($order_by == 'price') { + $order_by = 'orderprice'; + } - $nb_days_new_product = Configuration::get('PS_NB_DAYS_NEW_PRODUCT'); - if (!Validate::isUnsignedInt($nb_days_new_product)) - $nb_days_new_product = 20; + $nb_days_new_product = Configuration::get('PS_NB_DAYS_NEW_PRODUCT'); + if (!Validate::isUnsignedInt($nb_days_new_product)) { + $nb_days_new_product = 20; + } - $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) AS quantity'.(Combination::isFeatureActive() ? ', IFNULL(product_attribute_shop.id_product_attribute, 0) AS id_product_attribute, + $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) AS quantity'.(Combination::isFeatureActive() ? ', IFNULL(product_attribute_shop.id_product_attribute, 0) AS id_product_attribute, product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity' : '').', pl.`description`, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, image_shop.`id_image` id_image, il.`legend` as legend, m.`name` AS manufacturer_name, cl.`name` AS category_default, @@ -723,7 +749,7 @@ class CategoryCore extends ObjectModel LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = cp.`id_product` '.Shop::addSqlAssociation('product', 'p'). - (Combination::isFeatureActive() ? ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop + (Combination::isFeatureActive() ? ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop ON (p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='.(int)$context->shop->id.')':'').' '.Product::sqlStock('p', 0).' LEFT JOIN `'._DB_PREFIX_.'category_lang` cl @@ -741,79 +767,86 @@ class CategoryCore extends ObjectModel ON m.`id_manufacturer` = p.`id_manufacturer` WHERE product_shop.`id_shop` = '.(int)$context->shop->id.' AND cp.`id_category` = '.(int)$this->id - .($active ? ' AND product_shop.`active` = 1' : '') - .($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '') - .($id_supplier ? ' AND p.id_supplier = '.(int)$id_supplier : '') - .' GROUP BY cp.id_product'; + .($active ? ' AND product_shop.`active` = 1' : '') + .($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '') + .($id_supplier ? ' AND p.id_supplier = '.(int)$id_supplier : '') + .' GROUP BY cp.id_product'; - if ($random === true) - $sql .= ' ORDER BY RAND() LIMIT '.(int)$random_number_products; - else - $sql .= ' ORDER BY '.(!empty($order_by_prefix) ? $order_by_prefix.'.' : '').'`'.bqSQL($order_by).'` '.pSQL($order_way).' + if ($random === true) { + $sql .= ' ORDER BY RAND() LIMIT '.(int)$random_number_products; + } else { + $sql .= ' ORDER BY '.(!empty($order_by_prefix) ? $order_by_prefix.'.' : '').'`'.bqSQL($order_by).'` '.pSQL($order_way).' LIMIT '.(((int)$p - 1) * (int)$n).','.(int)$n; + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false); - if (!$result) - return array(); + if (!$result) { + return array(); + } - if ($order_by == 'orderprice') - Tools::orderbyPrice($result, $order_way); + if ($order_by == 'orderprice') { + Tools::orderbyPrice($result, $order_way); + } - /** Modify SQL result */ - return Product::getProductsProperties($id_lang, $result); - } + /** Modify SQL result */ + return Product::getProductsProperties($id_lang, $result); + } - /** - * Return main categories - * - * @param int $id_lang Language ID - * @param bool $active return only active categories - * @return array categories - */ - public static function getHomeCategories($id_lang, $active = true, $id_shop = false) - { - return self::getChildren(Configuration::get('PS_HOME_CATEGORY'), $id_lang, $active, $id_shop); - } + /** + * Return main categories + * + * @param int $id_lang Language ID + * @param bool $active return only active categories + * @return array categories + */ + public static function getHomeCategories($id_lang, $active = true, $id_shop = false) + { + return self::getChildren(Configuration::get('PS_HOME_CATEGORY'), $id_lang, $active, $id_shop); + } - public static function getRootCategory($id_lang = null, Shop $shop = null) - { - $context = Context::getContext(); - if (is_null($id_lang)) - $id_lang = $context->language->id; - if (!$shop) - if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) - $shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); - else - $shop = $context->shop; - else - return new Category($shop->getCategory(), $id_lang); - $is_more_than_one_root_category = count(Category::getCategoriesWithoutParent()) > 1; - if (Shop::isFeatureActive() && $is_more_than_one_root_category && Shop::getContext() != Shop::CONTEXT_SHOP) - $category = Category::getTopCategory($id_lang); - else - $category = new Category($shop->getCategory(), $id_lang); + public static function getRootCategory($id_lang = null, Shop $shop = null) + { + $context = Context::getContext(); + if (is_null($id_lang)) { + $id_lang = $context->language->id; + } + if (!$shop) { + if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) { + $shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); + } else { + $shop = $context->shop; + } + } else { + return new Category($shop->getCategory(), $id_lang); + } + $is_more_than_one_root_category = count(Category::getCategoriesWithoutParent()) > 1; + if (Shop::isFeatureActive() && $is_more_than_one_root_category && Shop::getContext() != Shop::CONTEXT_SHOP) { + $category = Category::getTopCategory($id_lang); + } else { + $category = new Category($shop->getCategory(), $id_lang); + } - return $category; - } + return $category; + } - /** - * - * @param int $id_parent - * @param int $id_lang - * @param bool $active - * @param bool $id_shop - * @return array - */ - public static function getChildren($id_parent, $id_lang, $active = true, $id_shop = false) - { - if (!Validate::isBool($active)) - die(Tools::displayError()); + /** + * + * @param int $id_parent + * @param int $id_lang + * @param bool $active + * @param bool $id_shop + * @return array + */ + public static function getChildren($id_parent, $id_lang, $active = true, $id_shop = false) + { + if (!Validate::isBool($active)) { + die(Tools::displayError()); + } - $cache_id = 'Category::getChildren_'.(int)$id_parent.'-'.(int)$id_lang.'-'.(bool)$active.'-'.(int)$id_shop; - if (!Cache::isStored($cache_id)) - { - $query = 'SELECT c.`id_category`, cl.`name`, cl.`link_rewrite`, category_shop.`id_shop` + $cache_id = 'Category::getChildren_'.(int)$id_parent.'-'.(int)$id_lang.'-'.(bool)$active.'-'.(int)$id_shop; + if (!Cache::isStored($cache_id)) { + $query = 'SELECT c.`id_category`, cl.`name`, cl.`link_rewrite`, category_shop.`id_shop` FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category`'.Shop::addSqlRestrictionOnLang('cl').') '.Shop::addSqlAssociation('category', 'c').' @@ -822,93 +855,96 @@ class CategoryCore extends ObjectModel '.($active ? 'AND `active` = 1' : '').' GROUP BY c.`id_category` ORDER BY category_shop.`position` ASC'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * - * @param int $id_parent - * @param int $id_lang - * @param bool $active - * @param bool $id_shop - * @return array - */ - public static function hasChildren($id_parent, $id_lang, $active = true, $id_shop = false) - { - if (!Validate::isBool($active)) - die(Tools::displayError()); + /** + * + * @param int $id_parent + * @param int $id_lang + * @param bool $active + * @param bool $id_shop + * @return array + */ + public static function hasChildren($id_parent, $id_lang, $active = true, $id_shop = false) + { + if (!Validate::isBool($active)) { + die(Tools::displayError()); + } - $cache_id = 'Category::hasChildren_'.(int)$id_parent.'-'.(int)$id_lang.'-'.(bool)$active.'-'.(int)$id_shop; - if (!Cache::isStored($cache_id)) - { - $query = 'SELECT c.id_category, "" as name + $cache_id = 'Category::hasChildren_'.(int)$id_parent.'-'.(int)$id_lang.'-'.(bool)$active.'-'.(int)$id_shop; + if (!Cache::isStored($cache_id)) { + $query = 'SELECT c.id_category, "" as name FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category`'.Shop::addSqlRestrictionOnLang('cl').') '.Shop::addSqlAssociation('category', 'c').' WHERE `id_lang` = '.(int)$id_lang.' AND c.`id_parent` = '.(int)$id_parent.' '.($active ? 'AND `active` = 1' : '').' LIMIT 1'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Return an array of all children of the current category - * - * @param int $id_lang - * @return PrestaShopCollection Collection of Category - */ - public function getAllChildren($id_lang = null) - { - if (is_null($id_lang)) - $id_lang = Context::getContext()->language->id; + /** + * Return an array of all children of the current category + * + * @param int $id_lang + * @return PrestaShopCollection Collection of Category + */ + public function getAllChildren($id_lang = null) + { + if (is_null($id_lang)) { + $id_lang = Context::getContext()->language->id; + } - $categories = new PrestaShopCollection('Category', $id_lang); - $categories->where('nleft', '>', $this->nleft); - $categories->where('nright', '<', $this->nright); - return $categories; - } + $categories = new PrestaShopCollection('Category', $id_lang); + $categories->where('nleft', '>', $this->nleft); + $categories->where('nright', '<', $this->nright); + return $categories; + } - /** - * Return an array of all parents of the current category - * - * @param int $id_lang - * @return PrestaShopCollection Collection of Category - */ - public function getAllParents($id_lang = null) - { - if (is_null($id_lang)) - $id_lang = Context::getContext()->language->id; + /** + * Return an array of all parents of the current category + * + * @param int $id_lang + * @return PrestaShopCollection Collection of Category + */ + public function getAllParents($id_lang = null) + { + if (is_null($id_lang)) { + $id_lang = Context::getContext()->language->id; + } - $categories = new PrestaShopCollection('Category', $id_lang); - $categories->where('nleft', '<', $this->nleft); - $categories->where('nright', '>', $this->nright); - return $categories; - } + $categories = new PrestaShopCollection('Category', $id_lang); + $categories->where('nleft', '<', $this->nleft); + $categories->where('nright', '>', $this->nright); + return $categories; + } - /** - * This method allow to return children categories with the number of sub children selected for a product - * - * @param int $id_parent - * @param int $id_product - * @param int $id_lang - * @return array - */ - public static function getChildrenWithNbSelectedSubCat($id_parent, $selected_cat, $id_lang, Shop $shop = null, $use_shop_context = true) - { - if (!$shop) - $shop = Context::getContext()->shop; + /** + * This method allow to return children categories with the number of sub children selected for a product + * + * @param int $id_parent + * @param int $id_product + * @param int $id_lang + * @return array + */ + public static function getChildrenWithNbSelectedSubCat($id_parent, $selected_cat, $id_lang, Shop $shop = null, $use_shop_context = true) + { + if (!$shop) { + $shop = Context::getContext()->shop; + } - $id_shop = $shop->id ? $shop->id : Configuration::get('PS_SHOP_DEFAULT'); - $selected_cat = explode(',', str_replace(' ', '', $selected_cat)); - $sql = ' + $id_shop = $shop->id ? $shop->id : Configuration::get('PS_SHOP_DEFAULT'); + $selected_cat = explode(',', str_replace(' ', '', $selected_cat)); + $sql = ' SELECT c.`id_category`, c.`level_depth`, cl.`name`, IF(( SELECT COUNT(*) @@ -927,155 +963,171 @@ class CategoryCore extends ObjectModel LEFT JOIN `'._DB_PREFIX_.'category_shop` cs ON (c.`id_category` = cs.`id_category` AND cs.`id_shop` = '.(int)$id_shop.') WHERE `id_lang` = '.(int)$id_lang.' AND c.`id_parent` = '.(int)$id_parent; - if (Shop::getContext() == Shop::CONTEXT_SHOP && $use_shop_context) - $sql .= ' AND cs.`id_shop` = '.(int)$shop->id; - if (!Shop::isFeatureActive() || Shop::getContext() == Shop::CONTEXT_SHOP && $use_shop_context) - $sql .= ' ORDER BY cs.`position` ASC'; + if (Shop::getContext() == Shop::CONTEXT_SHOP && $use_shop_context) { + $sql .= ' AND cs.`id_shop` = '.(int)$shop->id; + } + if (!Shop::isFeatureActive() || Shop::getContext() == Shop::CONTEXT_SHOP && $use_shop_context) { + $sql .= ' ORDER BY cs.`position` ASC'; + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + } - /** - * Copy products from a category to another - * - * @param int $id_old Source category ID - * @param bool $id_new Destination category ID - * @return bool Duplication result - */ - public static function duplicateProductCategories($id_old, $id_new) - { - $sql = 'SELECT `id_category` + /** + * Copy products from a category to another + * + * @param int $id_old Source category ID + * @param bool $id_new Destination category ID + * @return bool Duplication result + */ + public static function duplicateProductCategories($id_old, $id_new) + { + $sql = 'SELECT `id_category` FROM `'._DB_PREFIX_.'category_product` WHERE `id_product` = '.(int)$id_old; - $result = Db::getInstance()->executeS($sql); + $result = Db::getInstance()->executeS($sql); - $row = array(); - if ($result) - foreach ($result as $i) - $row[] = '('.implode(', ', array((int)$id_new, $i['id_category'], '(SELECT tmp.max + 1 FROM ( + $row = array(); + if ($result) { + foreach ($result as $i) { + $row[] = '('.implode(', ', array((int)$id_new, $i['id_category'], '(SELECT tmp.max + 1 FROM ( SELECT MAX(cp.`position`) AS max FROM `'._DB_PREFIX_.'category_product` cp WHERE cp.`id_category`='.(int)$i['id_category'].') AS tmp)' - )).')'; + )).')'; + } + } - $flag = Db::getInstance()->execute(' + $flag = Db::getInstance()->execute(' INSERT IGNORE INTO `'._DB_PREFIX_.'category_product` (`id_product`, `id_category`, `position`) VALUES '.implode(',', $row) - ); - return $flag; - } + ); + return $flag; + } - /** - * Check if category can be moved in another one. - * The category cannot be moved in a child category. - * - * @param int $id_category current category - * @param int $id_parent Parent candidate - * @return bool Parent validity - */ - public static function checkBeforeMove($id_category, $id_parent) - { - if ($id_category == $id_parent) return false; - if ($id_parent == Configuration::get('PS_HOME_CATEGORY')) return true; - $i = (int)$id_parent; + /** + * Check if category can be moved in another one. + * The category cannot be moved in a child category. + * + * @param int $id_category current category + * @param int $id_parent Parent candidate + * @return bool Parent validity + */ + public static function checkBeforeMove($id_category, $id_parent) + { + if ($id_category == $id_parent) { + return false; + } + if ($id_parent == Configuration::get('PS_HOME_CATEGORY')) { + return true; + } + $i = (int)$id_parent; - while (42) - { - $result = Db::getInstance()->getRow('SELECT `id_parent` FROM `'._DB_PREFIX_.'category` WHERE `id_category` = '.(int)$i); - if (!isset($result['id_parent'])) return false; - if ($result['id_parent'] == $id_category) return false; - if ($result['id_parent'] == Configuration::get('PS_HOME_CATEGORY')) return true; - $i = $result['id_parent']; - } - } + while (42) { + $result = Db::getInstance()->getRow('SELECT `id_parent` FROM `'._DB_PREFIX_.'category` WHERE `id_category` = '.(int)$i); + if (!isset($result['id_parent'])) { + return false; + } + if ($result['id_parent'] == $id_category) { + return false; + } + if ($result['id_parent'] == Configuration::get('PS_HOME_CATEGORY')) { + return true; + } + $i = $result['id_parent']; + } + } - public static function getLinkRewrite($id_category, $id_lang) - { - if (!Validate::isUnsignedId($id_category) || !Validate::isUnsignedId($id_lang)) - return false; + public static function getLinkRewrite($id_category, $id_lang) + { + if (!Validate::isUnsignedId($id_category) || !Validate::isUnsignedId($id_lang)) { + return false; + } - if (!isset(self::$_links[$id_category.'-'.$id_lang])) - self::$_links[$id_category.'-'.$id_lang] = Db::getInstance()->getValue(' + if (!isset(self::$_links[$id_category.'-'.$id_lang])) { + self::$_links[$id_category.'-'.$id_lang] = Db::getInstance()->getValue(' SELECT cl.`link_rewrite` FROM `'._DB_PREFIX_.'category_lang` cl WHERE `id_lang` = '.(int)$id_lang.' '.Shop::addSqlRestrictionOnLang('cl').' AND cl.`id_category` = '.(int)$id_category); - return self::$_links[$id_category.'-'.$id_lang]; - } + } + return self::$_links[$id_category.'-'.$id_lang]; + } - public function getLink(Link $link = null, $id_lang = null) - { - if (!$link) - $link = Context::getContext()->link; + public function getLink(Link $link = null, $id_lang = null) + { + if (!$link) { + $link = Context::getContext()->link; + } - if (!$id_lang && is_array($this->link_rewrite)) - $id_lang = Context::getContext()->language->id; + if (!$id_lang && is_array($this->link_rewrite)) { + $id_lang = Context::getContext()->language->id; + } - return $link->getCategoryLink($this, - is_array($this->link_rewrite) ? $this->link_rewrite[$id_lang] : $this->link_rewrite, $id_lang); - } + return $link->getCategoryLink($this, + is_array($this->link_rewrite) ? $this->link_rewrite[$id_lang] : $this->link_rewrite, $id_lang); + } - public function getName($id_lang = null) - { - if (!$id_lang) - { - if (isset($this->name[Context::getContext()->language->id])) - $id_lang = Context::getContext()->language->id; - else - $id_lang = (int)Configuration::get('PS_LANG_DEFAULT'); - } - return isset($this->name[$id_lang]) ? $this->name[$id_lang] : ''; - } + public function getName($id_lang = null) + { + if (!$id_lang) { + if (isset($this->name[Context::getContext()->language->id])) { + $id_lang = Context::getContext()->language->id; + } else { + $id_lang = (int)Configuration::get('PS_LANG_DEFAULT'); + } + } + return isset($this->name[$id_lang]) ? $this->name[$id_lang] : ''; + } - /** - * Light back office search for categories - * - * @param int $id_lang Language ID - * @param string $query Searched string - * @param bool $unrestricted allows search without lang and includes first category and exact match - * @param bool $skip_cache - * @return array Corresponding categories - * @throws PrestaShopDatabaseException - */ - public static function searchByName($id_lang, $query, $unrestricted = false, $skip_cache = false) - { - if ($unrestricted === true) - { - $key = 'Category::searchByName_'.$query; - if ($skip_cache || !Cache::isStored($key)) - { - $categories = Db::getInstance()->getRow(' + /** + * Light back office search for categories + * + * @param int $id_lang Language ID + * @param string $query Searched string + * @param bool $unrestricted allows search without lang and includes first category and exact match + * @param bool $skip_cache + * @return array Corresponding categories + * @throws PrestaShopDatabaseException + */ + public static function searchByName($id_lang, $query, $unrestricted = false, $skip_cache = false) + { + if ($unrestricted === true) { + $key = 'Category::searchByName_'.$query; + if ($skip_cache || !Cache::isStored($key)) { + $categories = Db::getInstance()->getRow(' SELECT c.*, cl.* FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category` '.Shop::addSqlRestrictionOnLang('cl').') WHERE `name` = \''.pSQL($query).'\''); - if (!$skip_cache) - Cache::store($key, $categories); - return $categories; - } - return Cache::retrieve($key); - } - else - return Db::getInstance()->executeS(' + if (!$skip_cache) { + Cache::store($key, $categories); + } + return $categories; + } + return Cache::retrieve($key); + } else { + return Db::getInstance()->executeS(' SELECT c.*, cl.* FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category` AND `id_lang` = '.(int)$id_lang.' '.Shop::addSqlRestrictionOnLang('cl').') WHERE `name` LIKE \'%'.pSQL($query).'%\' AND c.`id_category` != '.(int)Configuration::get('PS_HOME_CATEGORY')); - } + } + } - /** - * Retrieve category by name and parent category id - * - * @param int $id_lang Language ID - * @param string $category_name Searched category name - * @param int $id_parent_category parent category ID - * @return array Corresponding category - */ - public static function searchByNameAndParentCategoryId($id_lang, $category_name, $id_parent_category) - { - return Db::getInstance()->getRow(' + /** + * Retrieve category by name and parent category id + * + * @param int $id_lang Language ID + * @param string $category_name Searched category name + * @param int $id_parent_category parent category ID + * @return array Corresponding category + */ + public static function searchByNameAndParentCategoryId($id_lang, $category_name, $id_parent_category) + { + return Db::getInstance()->getRow(' SELECT c.*, cl.* FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_lang` cl @@ -1084,395 +1136,415 @@ class CategoryCore extends ObjectModel WHERE `name` = \''.pSQL($category_name).'\' AND c.`id_category` != '.(int)Configuration::get('PS_HOME_CATEGORY').' AND c.`id_parent` = '.(int)$id_parent_category); - } + } - /** - * Search with Pathes for categories - * - * @param int $id_lang Language ID - * @param string $path of category - * @param bool $object_to_create a category + /** + * Search with Pathes for categories + * + * @param int $id_lang Language ID + * @param string $path of category + * @param bool $object_to_create a category * * @param bool $method_to_create a category - * @return array Corresponding categories - */ - public static function searchByPath($id_lang, $path, $object_to_create = false, $method_to_create = false) - { - $categories = explode('/', trim($path)); - $category = $id_parent_category = false; + * @return array Corresponding categories + */ + public static function searchByPath($id_lang, $path, $object_to_create = false, $method_to_create = false) + { + $categories = explode('/', trim($path)); + $category = $id_parent_category = false; - if (is_array($categories) && count($categories)) - foreach ($categories as $category_name) - { - if ($id_parent_category) - $category = Category::searchByNameAndParentCategoryId($id_lang, $category_name, $id_parent_category); - else - $category = Category::searchByName($id_lang, $category_name, true, true); + if (is_array($categories) && count($categories)) { + foreach ($categories as $category_name) { + if ($id_parent_category) { + $category = Category::searchByNameAndParentCategoryId($id_lang, $category_name, $id_parent_category); + } else { + $category = Category::searchByName($id_lang, $category_name, true, true); + } - if (!$category && $object_to_create && $method_to_create) - { - call_user_func_array(array($object_to_create, $method_to_create), array($id_lang, $category_name , $id_parent_category)); - $category = Category::searchByPath($id_lang, $category_name); - } - if (isset($category['id_category']) && $category['id_category']) - $id_parent_category = (int)$category['id_category']; - } - return $category; - } + if (!$category && $object_to_create && $method_to_create) { + call_user_func_array(array($object_to_create, $method_to_create), array($id_lang, $category_name, $id_parent_category)); + $category = Category::searchByPath($id_lang, $category_name); + } + if (isset($category['id_category']) && $category['id_category']) { + $id_parent_category = (int)$category['id_category']; + } + } + } + return $category; + } - /** - * Get Each parent category of this category until the root category - * - * @param int $id_lang Language ID - * @return array Corresponding categories - */ - public function getParentsCategories($id_lang = null) - { - $context = Context::getContext()->cloneContext(); - $context->shop = clone($context->shop); + /** + * Get Each parent category of this category until the root category + * + * @param int $id_lang Language ID + * @return array Corresponding categories + */ + public function getParentsCategories($id_lang = null) + { + $context = Context::getContext()->cloneContext(); + $context->shop = clone($context->shop); - if (is_null($id_lang)) - $id_lang = $context->language->id; + if (is_null($id_lang)) { + $id_lang = $context->language->id; + } - $categories = null; - $id_current = $this->id; - if (count(Category::getCategoriesWithoutParent()) > 1 && Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && count(Shop::getShops(true, null, true)) != 1) - $context->shop->id_category = (int)Configuration::get('PS_ROOT_CATEGORY'); - elseif (!$context->shop->id) - $context->shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); - $id_shop = $context->shop->id; - while (true) - { - $sql = ' + $categories = null; + $id_current = $this->id; + if (count(Category::getCategoriesWithoutParent()) > 1 && Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && count(Shop::getShops(true, null, true)) != 1) { + $context->shop->id_category = (int)Configuration::get('PS_ROOT_CATEGORY'); + } elseif (!$context->shop->id) { + $context->shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); + } + $id_shop = $context->shop->id; + while (true) { + $sql = ' SELECT c.*, cl.* FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category` AND `id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('cl').')'; - if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) - $sql .= ' LEFT JOIN `'._DB_PREFIX_.'category_shop` cs ON (c.`id_category` = cs.`id_category` AND cs.`id_shop` = '.(int)$id_shop.')'; - $sql .= ' WHERE c.`id_category` = '.(int)$id_current; - if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) - $sql .= ' AND cs.`id_shop` = '.(int)$context->shop->id; - $root_category = Category::getRootCategory(); - if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP - && (!Tools::isSubmit('id_category') || (int)Tools::getValue('id_category') == (int)$root_category->id || (int)$root_category->id == (int)$context->shop->id_category)) - $sql .= ' AND c.`id_parent` != 0'; + if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) { + $sql .= ' LEFT JOIN `'._DB_PREFIX_.'category_shop` cs ON (c.`id_category` = cs.`id_category` AND cs.`id_shop` = '.(int)$id_shop.')'; + } + $sql .= ' WHERE c.`id_category` = '.(int)$id_current; + if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP) { + $sql .= ' AND cs.`id_shop` = '.(int)$context->shop->id; + } + $root_category = Category::getRootCategory(); + if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP + && (!Tools::isSubmit('id_category') || (int)Tools::getValue('id_category') == (int)$root_category->id || (int)$root_category->id == (int)$context->shop->id_category)) { + $sql .= ' AND c.`id_parent` != 0'; + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); - if ($result) - $categories[] = $result; - elseif (!$categories) - $categories = array(); - if (!$result || ($result['id_category'] == $context->shop->id_category)) - return $categories; - $id_current = $result['id_parent']; - } - } - /** - * Specify if a category already in base - * - * @param int $id_category Category id - * @return bool - */ - public static function categoryExists($id_category) - { - $row = Db::getInstance()->getRow(' + if ($result) { + $categories[] = $result; + } elseif (!$categories) { + $categories = array(); + } + if (!$result || ($result['id_category'] == $context->shop->id_category)) { + return $categories; + } + $id_current = $result['id_parent']; + } + } + /** + * Specify if a category already in base + * + * @param int $id_category Category id + * @return bool + */ + public static function categoryExists($id_category) + { + $row = Db::getInstance()->getRow(' SELECT `id_category` FROM '._DB_PREFIX_.'category c WHERE c.`id_category` = '.(int)$id_category); - return isset($row['id_category']); - } + return isset($row['id_category']); + } - public function cleanGroups() - { - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'category_group` WHERE `id_category` = '.(int)$this->id); - } + public function cleanGroups() + { + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'category_group` WHERE `id_category` = '.(int)$this->id); + } - public function cleanAssoProducts() - { - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'category_product` WHERE `id_category` = '.(int)$this->id); - } + public function cleanAssoProducts() + { + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'category_product` WHERE `id_category` = '.(int)$this->id); + } - public function addGroups($groups) - { - foreach ($groups as $group) - if ($group !== false) - Db::getInstance()->insert('category_group', array('id_category' => (int)$this->id, 'id_group' => (int)$group)); - } + public function addGroups($groups) + { + foreach ($groups as $group) { + if ($group !== false) { + Db::getInstance()->insert('category_group', array('id_category' => (int)$this->id, 'id_group' => (int)$group)); + } + } + } - public function getGroups() - { - $cache_id = 'Category::getGroups_'.(int)$this->id; - if (!Cache::isStored($cache_id)) - { - $result = Db::getInstance()->executeS(' + public function getGroups() + { + $cache_id = 'Category::getGroups_'.(int)$this->id; + if (!Cache::isStored($cache_id)) { + $result = Db::getInstance()->executeS(' SELECT cg.`id_group` FROM '._DB_PREFIX_.'category_group cg WHERE cg.`id_category` = '.(int)$this->id); - $groups = array(); - foreach ($result as $group) - $groups[] = $group['id_group']; - Cache::store($cache_id, $groups); - return $groups; - } - return Cache::retrieve($cache_id); - } + $groups = array(); + foreach ($result as $group) { + $groups[] = $group['id_group']; + } + Cache::store($cache_id, $groups); + return $groups; + } + return Cache::retrieve($cache_id); + } - public function addGroupsIfNoExist($id_group) - { - $groups = $this->getGroups(); - if (!in_array((int)$id_group, $groups)) - return $this->addGroups(array((int)$id_group)); - return false; - } + public function addGroupsIfNoExist($id_group) + { + $groups = $this->getGroups(); + if (!in_array((int)$id_group, $groups)) { + return $this->addGroups(array((int)$id_group)); + } + return false; + } - /** - * checkAccess return true if id_customer is in a group allowed to see this category. - * - * @param mixed $id_customer - * @access public - * @return bool true if access allowed for customer $id_customer - */ - public function checkAccess($id_customer) - { - $cache_id = 'Category::checkAccess_'.(int)$this->id.'-'.$id_customer.(!$id_customer ? '-'.(int)Group::getCurrent()->id : ''); - if (!Cache::isStored($cache_id)) - { - if (!$id_customer) - $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * checkAccess return true if id_customer is in a group allowed to see this category. + * + * @param mixed $id_customer + * @access public + * @return bool true if access allowed for customer $id_customer + */ + public function checkAccess($id_customer) + { + $cache_id = 'Category::checkAccess_'.(int)$this->id.'-'.$id_customer.(!$id_customer ? '-'.(int)Group::getCurrent()->id : ''); + if (!Cache::isStored($cache_id)) { + if (!$id_customer) { + $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT ctg.`id_group` FROM '._DB_PREFIX_.'category_group ctg WHERE ctg.`id_category` = '.(int)$this->id.' AND ctg.`id_group` = '.(int)Group::getCurrent()->id); - else - $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + } else { + $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT ctg.`id_group` FROM '._DB_PREFIX_.'category_group ctg INNER JOIN '._DB_PREFIX_.'customer_group cg on (cg.`id_group` = ctg.`id_group` AND cg.`id_customer` = '.(int)$id_customer.') WHERE ctg.`id_category` = '.(int)$this->id); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Update customer groups associated to the object - * - * @param array $list groups - */ - public function updateGroup($list) - { - $this->cleanGroups(); - if (empty($list)) - $list = array(Configuration::get('PS_UNIDENTIFIED_GROUP'), Configuration::get('PS_GUEST_GROUP'), Configuration::get('PS_CUSTOMER_GROUP')); - $this->addGroups($list); - } + /** + * Update customer groups associated to the object + * + * @param array $list groups + */ + public function updateGroup($list) + { + $this->cleanGroups(); + if (empty($list)) { + $list = array(Configuration::get('PS_UNIDENTIFIED_GROUP'), Configuration::get('PS_GUEST_GROUP'), Configuration::get('PS_CUSTOMER_GROUP')); + } + $this->addGroups($list); + } - public static function setNewGroupForHome($id_group) - { - if (!(int)$id_group) - return false; + public static function setNewGroupForHome($id_group) + { + if (!(int)$id_group) { + return false; + } - return Db::getInstance()->execute(' + return Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'category_group` (`id_category`, `id_group`) VALUES ('.(int)Context::getContext()->shop->getCategory().', '.(int)$id_group.')'); - } + } - public function updatePosition($way, $position) - { - if (!$res = Db::getInstance()->executeS(' + public function updatePosition($way, $position) + { + if (!$res = Db::getInstance()->executeS(' SELECT cp.`id_category`, category_shop.`position`, cp.`id_parent` FROM `'._DB_PREFIX_.'category` cp '.Shop::addSqlAssociation('category', 'cp').' WHERE cp.`id_parent` = '.(int)$this->id_parent.' ORDER BY category_shop.`position` ASC' - )) - return false; + )) { + return false; + } - $moved_category = false; - foreach ($res as $category) - if ((int)$category['id_category'] == (int)$this->id) - $moved_category = $category; + $moved_category = false; + foreach ($res as $category) { + if ((int)$category['id_category'] == (int)$this->id) { + $moved_category = $category; + } + } - if ($moved_category === false || !$position) - return false; - // < and > statements rather than BETWEEN operator - // since BETWEEN is treated differently according to databases - $result = (Db::getInstance()->execute(' + if ($moved_category === false) { + return false; + } + // < and > statements rather than BETWEEN operator + // since BETWEEN is treated differently according to databases + $result = (Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'category` c '.Shop::addSqlAssociation('category', 'c').' SET category_shop.`position`= category_shop.`position` '.($way ? '- 1' : '+ 1').' WHERE category_shop.`position` '.($way - ? '> '.(int)$moved_category['position'].' AND category_shop.`position` <= '.(int)$position - : '< '.(int)$moved_category['position'].' AND category_shop.`position` >= '.(int)$position).' + ? '> '.(int)$moved_category['position'].' AND category_shop.`position` <= '.(int)$position + : '< '.(int)$moved_category['position'].' AND category_shop.`position` >= '.(int)$position).' AND c.`id_parent`='.(int)$moved_category['id_parent']) - && Db::getInstance()->execute(' + && Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'category` c '.Shop::addSqlAssociation('category', 'c').' SET category_shop.`position` = '.(int)$position.' WHERE c.`id_parent` = '.(int)$moved_category['id_parent'].' AND c.`id_category`='.(int)$moved_category['id_category'])); - Hook::exec('actionCategoryUpdate'); - return $result; - } + Hook::exec('actionCategoryUpdate'); + return $result; + } - /** - * cleanPositions keep order of category in $id_category_parent, - * but remove duplicate position. Should not be used if positions - * are clean at the beginning ! - * - * @param mixed $id_category_parent - * @return bool true if succeed - */ - public static function cleanPositions($id_category_parent = null) - { - if ($id_category_parent === null) - return; + /** + * cleanPositions keep order of category in $id_category_parent, + * but remove duplicate position. Should not be used if positions + * are clean at the beginning ! + * + * @param mixed $id_category_parent + * @return bool true if succeed + */ + public static function cleanPositions($id_category_parent = null) + { + if ($id_category_parent === null) { + return; + } - $return = true; - $result = Db::getInstance()->executeS(' + $return = true; + $result = Db::getInstance()->executeS(' SELECT c.`id_category` FROM `'._DB_PREFIX_.'category` c '.Shop::addSqlAssociation('category', 'c').' WHERE c.`id_parent` = '.(int)$id_category_parent.' ORDER BY category_shop.`position`'); - $count = count($result); - for ($i = 0; $i < $count; $i++) - { - $return &= Db::getInstance()->execute(' + $count = count($result); + for ($i = 0; $i < $count; $i++) { + $return &= Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'category` c '.Shop::addSqlAssociation('category', 'c').' SET category_shop.`position` = '.(int)($i).' WHERE c.`id_parent` = '.(int)$id_category_parent.' AND c.`id_category` = '.(int)$result[$i]['id_category']); - } - return $return; - } + } + return $return; + } - /** this function return the number of category + 1 having $id_category_parent as parent. - * - * @todo rename that function to make it understandable (getNewLastPosition for example) - * @param int $id_category_parent the parent category - * @param int $id_shop - * @return int - */ - public static function getLastPosition($id_category_parent, $id_shop) - { - if ((int)Db::getInstance()->getValue(' + /** this function return the number of category + 1 having $id_category_parent as parent. + * + * @todo rename that function to make it understandable (getNewLastPosition for example) + * @param int $id_category_parent the parent category + * @param int $id_shop + * @return int + */ + public static function getLastPosition($id_category_parent, $id_shop) + { + if ((int)Db::getInstance()->getValue(' SELECT COUNT(c.`id_category`) FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_shop` cs ON (c.`id_category` = cs.`id_category` AND cs.`id_shop` = '.(int)$id_shop.') - WHERE c.`id_parent` = '.(int)$id_category_parent) === 1) - return 0; - else - return (1 + (int)Db::getInstance()->getValue(' + WHERE c.`id_parent` = '.(int)$id_category_parent) === 1) { + return 0; + } else { + return (1 + (int)Db::getInstance()->getValue(' SELECT MAX(cs.`position`) FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_shop` cs ON (c.`id_category` = cs.`id_category` AND cs.`id_shop` = '.(int)$id_shop.') WHERE c.`id_parent` = '.(int)$id_category_parent)); - } + } + } - public static function getUrlRewriteInformations($id_category) - { - return Db::getInstance()->executeS(' + public static function getUrlRewriteInformations($id_category) + { + return Db::getInstance()->executeS(' SELECT l.`id_lang`, c.`link_rewrite` FROM `'._DB_PREFIX_.'category_lang` AS c LEFT JOIN `'._DB_PREFIX_.'lang` AS l ON c.`id_lang` = l.`id_lang` WHERE c.`id_category` = '.(int)$id_category.' AND l.`active` = 1' - ); - } + ); + } - /** - * Return nleft and nright fields for a given category - * - * @since 1.5.0 - * @param int $id - * @return array - */ - public static function getInterval($id) - { - $cache_id = 'Category::getInterval_'.(int)$id; - if (!Cache::isStored($cache_id)) - { - $result = Db::getInstance()->getRow(' + /** + * Return nleft and nright fields for a given category + * + * @since 1.5.0 + * @param int $id + * @return array + */ + public static function getInterval($id) + { + $cache_id = 'Category::getInterval_'.(int)$id; + if (!Cache::isStored($cache_id)) { + $result = Db::getInstance()->getRow(' SELECT nleft, nright, level_depth FROM '._DB_PREFIX_.'category WHERE id_category = '.(int)$id); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Check if current category is a child of shop root category - * - * @since 1.5.0 - * @param Shop $shop - * @return bool - */ - public function inShop(Shop $shop = null) - { - if (!$shop) - $shop = Context::getContext()->shop; + /** + * Check if current category is a child of shop root category + * + * @since 1.5.0 + * @param Shop $shop + * @return bool + */ + public function inShop(Shop $shop = null) + { + if (!$shop) { + $shop = Context::getContext()->shop; + } - if (!$interval = Category::getInterval($shop->getCategory())) - return false; - return ($this->nleft >= $interval['nleft'] && $this->nright <= $interval['nright']); - } + if (!$interval = Category::getInterval($shop->getCategory())) { + return false; + } + return ($this->nleft >= $interval['nleft'] && $this->nright <= $interval['nright']); + } - public static function inShopStatic($id_category, Shop $shop = null) - { - if (!$shop || !is_object($shop)) - $shop = Context::getContext()->shop; + public static function inShopStatic($id_category, Shop $shop = null) + { + if (!$shop || !is_object($shop)) { + $shop = Context::getContext()->shop; + } - if (!$interval = Category::getInterval($shop->getCategory())) - return false; - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('SELECT nleft, nright FROM `'._DB_PREFIX_.'category` WHERE id_category = '.(int)$id_category); - return ($row['nleft'] >= $interval['nleft'] && $row['nright'] <= $interval['nright']); - } + if (!$interval = Category::getInterval($shop->getCategory())) { + return false; + } + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('SELECT nleft, nright FROM `'._DB_PREFIX_.'category` WHERE id_category = '.(int)$id_category); + return ($row['nleft'] >= $interval['nleft'] && $row['nright'] <= $interval['nright']); + } - public function getChildrenWs() - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public function getChildrenWs() + { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT c.`id_category` as id FROM `'._DB_PREFIX_.'category` c '.Shop::addSqlAssociation('category', 'c').' WHERE c.`id_parent` = '.(int)$this->id.' AND c.`active` = 1 ORDER BY category_shop.`position` ASC'); - return $result; - } + return $result; + } - public function getProductsWs() - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public function getProductsWs() + { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT cp.`id_product` as id FROM `'._DB_PREFIX_.'category_product` cp WHERE cp.`id_category` = '.(int)$this->id.' ORDER BY `position` ASC'); - return $result; - } + return $result; + } - /** - * Search for another category with the same parent and the same position - * - * @return array first category found - */ - public function getDuplicatePosition() - { - return Db::getInstance()->getValue(' + /** + * Search for another category with the same parent and the same position + * + * @return array first category found + */ + public function getDuplicatePosition() + { + return Db::getInstance()->getValue(' SELECT c.`id_category` FROM `'._DB_PREFIX_.'category` c '.Shop::addSqlAssociation('category', 'c').' WHERE c.`id_parent` = '.(int)$this->id_parent.' AND category_shop.`position` = '.(int)$this->position.' AND c.`id_category` != '.(int)$this->id); - } + } - public function getWsNbProductsRecursive() - { - $nb_product_recursive = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public function getWsNbProductsRecursive() + { + $nb_product_recursive = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(distinct(id_product)) FROM `'._DB_PREFIX_.'category_product` WHERE id_category = '.(int)$this->id.' OR @@ -1486,27 +1558,30 @@ class CategoryCore extends ObjectModel AND c2.active = 1 ) '); - if (!$nb_product_recursive) - return -1; - return $nb_product_recursive; - } + if (!$nb_product_recursive) { + return -1; + } + return $nb_product_recursive; + } - /** - * - * @param Array $ids_category - * @param int $id_lang - * @return Array - */ - public static function getCategoryInformations($ids_category, $id_lang = null) - { - if ($id_lang === null) - $id_lang = Context::getContext()->language->id; + /** + * + * @param Array $ids_category + * @param int $id_lang + * @return Array + */ + public static function getCategoryInformations($ids_category, $id_lang = null) + { + if ($id_lang === null) { + $id_lang = Context::getContext()->language->id; + } - if (!is_array($ids_category) || !count($ids_category)) - return; + if (!is_array($ids_category) || !count($ids_category)) { + return; + } - $categories = array(); - $results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $categories = array(); + $results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT c.`id_category`, cl.`name`, cl.`link_rewrite`, cl.`id_lang` FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category`'.Shop::addSqlRestrictionOnLang('cl').') @@ -1514,230 +1589,231 @@ class CategoryCore extends ObjectModel WHERE cl.`id_lang` = '.(int)$id_lang.' AND c.`id_category` IN ('.implode(',', array_map('intval', $ids_category)).')'); - foreach ($results as $category) - $categories[$category['id_category']] = $category; + foreach ($results as $category) { + $categories[$category['id_category']] = $category; + } - return $categories; - } + return $categories; + } - /** - * @param $id_shop - * @return bool - */ - public function isParentCategoryAvailable($id_shop) - { - $id = Context::getContext()->shop->id; - $id_shop = $id ? $id : Configuration::get('PS_SHOP_DEFAULT'); - return (bool)Db::getInstance()->getValue(' + /** + * @param $id_shop + * @return bool + */ + public function isParentCategoryAvailable($id_shop) + { + $id = Context::getContext()->shop->id; + $id_shop = $id ? $id : Configuration::get('PS_SHOP_DEFAULT'); + return (bool)Db::getInstance()->getValue(' SELECT c.`id_category` FROM `'._DB_PREFIX_.'category` c '.Shop::addSqlAssociation('category', 'c').' WHERE category_shop.`id_shop` = '.(int)$id_shop.' AND c.`id_parent` = '.(int)$this->id_parent); - } + } - /** - * Add association between shop and categories - * @param int $id_shop - * @return bool - */ - public function addShop($id_shop) - { - $data = array(); - if (!$id_shop) - { - foreach (Shop::getShops(false) as $shop) - if (!$this->existsInShop($shop['id_shop'])) - $data[] = array( - 'id_category' => (int)$this->id, - 'id_shop' => (int)$shop['id_shop'], - ); - } - elseif (!$this->existsInShop($id_shop)) - $data[] = array( - 'id_category' => (int)$this->id, - 'id_shop' => (int)$id_shop, - ); + /** + * Add association between shop and categories + * @param int $id_shop + * @return bool + */ + public function addShop($id_shop) + { + $data = array(); + if (!$id_shop) { + foreach (Shop::getShops(false) as $shop) { + if (!$this->existsInShop($shop['id_shop'])) { + $data[] = array( + 'id_category' => (int)$this->id, + 'id_shop' => (int)$shop['id_shop'], + ); + } + } + } elseif (!$this->existsInShop($id_shop)) { + $data[] = array( + 'id_category' => (int)$this->id, + 'id_shop' => (int)$id_shop, + ); + } - return Db::getInstance()->insert('category_shop', $data); - } + return Db::getInstance()->insert('category_shop', $data); + } - public static function getRootCategories($id_lang = null, $active = true) - { - if (!$id_lang) - $id_lang = Context::getContext()->language->id; + public static function getRootCategories($id_lang = null, $active = true) + { + if (!$id_lang) { + $id_lang = Context::getContext()->language->id; + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT DISTINCT(c.`id_category`), cl.`name` FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (cl.`id_category` = c.`id_category` AND cl.`id_lang`='.(int)$id_lang.') WHERE `is_root_category` = 1 '.($active ? 'AND `active` = 1': '')); - } + } - public static function getCategoriesWithoutParent() - { - $cache_id = 'Category::getCategoriesWithoutParent_'.(int)Context::getContext()->language->id; - if (!Cache::isStored($cache_id)) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getCategoriesWithoutParent() + { + $cache_id = 'Category::getCategoriesWithoutParent_'.(int)Context::getContext()->language->id; + if (!Cache::isStored($cache_id)) { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT DISTINCT c.* FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category` AND cl.`id_lang` = '.(int)Context::getContext()->language->id.') WHERE `level_depth` = 1'); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - public function isRootCategoryForAShop() - { - return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public function isRootCategoryForAShop() + { + return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_shop` FROM `'._DB_PREFIX_.'shop` WHERE `id_category` = '.(int)$this->id); - } + } - /** - * @param null $id_lang - * @return Category - */ - public static function getTopCategory($id_lang = null) - { - if (is_null($id_lang)) - $id_lang = (int)Context::getContext()->language->id; - $cache_id = 'Category::getTopCategory_'.(int)$id_lang; - if (!Cache::isStored($cache_id)) - { - $id_category = (int)Db::getInstance()->getValue(' + /** + * @param null $id_lang + * @return Category + */ + public static function getTopCategory($id_lang = null) + { + if (is_null($id_lang)) { + $id_lang = (int)Context::getContext()->language->id; + } + $cache_id = 'Category::getTopCategory_'.(int)$id_lang; + if (!Cache::isStored($cache_id)) { + $id_category = (int)Db::getInstance()->getValue(' SELECT `id_category` FROM `'._DB_PREFIX_.'category` WHERE `id_parent` = 0'); - $category = new Category($id_category, $id_lang); - Cache::store($cache_id, $category); - return $category; - } - return Cache::retrieve($cache_id); - } + $category = new Category($id_category, $id_lang); + Cache::store($cache_id, $category); + return $category; + } + return Cache::retrieve($cache_id); + } - public function addPosition($position, $id_shop = null) - { - $return = true; - if (is_null($id_shop)) - { - if (Shop::getContext() != Shop::CONTEXT_SHOP) - foreach (Shop::getContextListShopID() as $id_shop) - $return &= Db::getInstance()->execute(' + public function addPosition($position, $id_shop = null) + { + $return = true; + if (is_null($id_shop)) { + if (Shop::getContext() != Shop::CONTEXT_SHOP) { + foreach (Shop::getContextListShopID() as $id_shop) { + $return &= Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'category_shop` (`id_category`, `id_shop`, `position`) VALUES ('.(int)$this->id.', '.(int)$id_shop.', '.(int)$position.') ON DUPLICATE KEY UPDATE `position` = '.(int)$position); - else - { - $id = Context::getContext()->shop->id; - $id_shop = $id ? $id : Configuration::get('PS_SHOP_DEFAULT'); - $return &= Db::getInstance()->execute(' + } + } else { + $id = Context::getContext()->shop->id; + $id_shop = $id ? $id : Configuration::get('PS_SHOP_DEFAULT'); + $return &= Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'category_shop` (`id_category`, `id_shop`, `position`) VALUES ('.(int)$this->id.', '.(int)$id_shop.', '.(int)$position.') ON DUPLICATE KEY UPDATE `position` = '.(int)$position); - } - } - else - $return &= Db::getInstance()->execute(' + } + } else { + $return &= Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'category_shop` (`id_category`, `id_shop`, `position`) VALUES ('.(int)$this->id.', '.(int)$id_shop.', '.(int)$position.') ON DUPLICATE KEY UPDATE `position` = '.(int)$position); + } - return $return; - } + return $return; + } - public static function getShopsByCategory($id_category) - { - return Db::getInstance()->executeS(' + public static function getShopsByCategory($id_category) + { + return Db::getInstance()->executeS(' SELECT `id_shop` FROM `'._DB_PREFIX_.'category_shop` WHERE `id_category` = '.(int)$id_category); - } + } - /** - * Update categories for a shop - * - * @param string $categories Categories list to associate a shop - * @param string $id_shop Categories list to associate a shop - * @return array Update/insertion result - */ - public static function updateFromShop($categories, $id_shop) - { - $shop = new Shop($id_shop); - // if array is empty or if the default category is not selected, return false - if (!is_array($categories) || !count($categories) || !in_array($shop->id_category, $categories)) - return false; + /** + * Update categories for a shop + * + * @param string $categories Categories list to associate a shop + * @param string $id_shop Categories list to associate a shop + * @return array Update/insertion result + */ + public static function updateFromShop($categories, $id_shop) + { + $shop = new Shop($id_shop); + // if array is empty or if the default category is not selected, return false + if (!is_array($categories) || !count($categories) || !in_array($shop->id_category, $categories)) { + return false; + } - // delete categories for this shop - Category::deleteCategoriesFromShop($id_shop); + // delete categories for this shop + Category::deleteCategoriesFromShop($id_shop); - // and add $categories to this shop - return Category::addToShop($categories, $id_shop); - } + // and add $categories to this shop + return Category::addToShop($categories, $id_shop); + } - /** - * Delete category from shop $id_shop - * @param int $id_shop - * @return bool - */ - public function deleteFromShop($id_shop) - { - return Db::getInstance()->execute(' + /** + * Delete category from shop $id_shop + * @param int $id_shop + * @return bool + */ + public function deleteFromShop($id_shop) + { + return Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'category_shop` WHERE `id_shop` = '.(int)$id_shop.' AND id_category = '.(int)$this->id); - } + } - /** - * Delete every categories - * @return bool - */ - public static function deleteCategoriesFromShop($id_shop) - { - return Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'category_shop` WHERE `id_shop` = '.(int)$id_shop); - } + /** + * Delete every categories + * @return bool + */ + public static function deleteCategoriesFromShop($id_shop) + { + return Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'category_shop` WHERE `id_shop` = '.(int)$id_shop); + } - /** - * Add some categories to a shop - * @param array $categories - * @return bool - */ - public static function addToShop(array $categories, $id_shop) - { - if (!is_array($categories)) - return false; - $sql = 'INSERT INTO `'._DB_PREFIX_.'category_shop` (`id_category`, `id_shop`) VALUES'; - $tab_categories = array(); - foreach ($categories as $id_category) - { - $tab_categories[] = new Category($id_category); - $sql .= '("'.(int)$id_category.'", "'.(int)$id_shop.'"),'; - } - // removing last comma to avoid SQL error - $sql = substr($sql, 0, strlen($sql) - 1); + /** + * Add some categories to a shop + * @param array $categories + * @return bool + */ + public static function addToShop(array $categories, $id_shop) + { + if (!is_array($categories)) { + return false; + } + $sql = 'INSERT INTO `'._DB_PREFIX_.'category_shop` (`id_category`, `id_shop`) VALUES'; + $tab_categories = array(); + foreach ($categories as $id_category) { + $tab_categories[] = new Category($id_category); + $sql .= '("'.(int)$id_category.'", "'.(int)$id_shop.'"),'; + } + // removing last comma to avoid SQL error + $sql = substr($sql, 0, strlen($sql) - 1); - $return = Db::getInstance()->execute($sql); - // we have to update position for every new entries - foreach ($tab_categories as $category) - { - /** @var Category $category */ - $category->addPosition(Category::getLastPosition($category->id_parent, $id_shop), $id_shop); - } + $return = Db::getInstance()->execute($sql); + // we have to update position for every new entries + foreach ($tab_categories as $category) { + /** @var Category $category */ + $category->addPosition(Category::getLastPosition($category->id_parent, $id_shop), $id_shop); + } - return $return; - } + return $return; + } - public function existsInShop($id_shop) - { - return (bool)Db::getInstance()->getValue(' + public function existsInShop($id_shop) + { + return (bool)Db::getInstance()->getValue(' SELECT `id_category` FROM `'._DB_PREFIX_.'category_shop` WHERE `id_category` = '.(int)$this->id.' AND `id_shop` = '.(int)$id_shop); - } + } } diff --git a/classes/Chart.php b/classes/Chart.php index df496d0d..04dd3eb2 100644 --- a/classes/Chart.php +++ b/classes/Chart.php @@ -26,156 +26,169 @@ class ChartCore { - protected static $poolId = 0; + protected static $poolId = 0; - protected $width = 600; - protected $height = 300; + protected $width = 600; + protected $height = 300; - /* Time mode */ - protected $timeMode = false; - protected $from; - protected $to; - protected $format; - protected $granularity; + /* Time mode */ + protected $timeMode = false; + protected $from; + protected $to; + protected $format; + protected $granularity; - protected $curves = array(); + protected $curves = array(); - /** @prototype void public static function init(void) */ - public static function init() - { - if (!self::$poolId) - { - ++self::$poolId; - return true; - } - } + /** @prototype void public static function init(void) */ + public static function init() + { + if (!self::$poolId) { + ++self::$poolId; + return true; + } + } - /** @prototype void public function __construct() */ - public function __construct() - { - ++self::$poolId; - } + /** @prototype void public function __construct() */ + public function __construct() + { + ++self::$poolId; + } - /** @prototype void public function setSize(int $width, int $height) */ - public function setSize($width, $height) - { - $this->width = (int)$width; - $this->height = (int)$height; - } + /** @prototype void public function setSize(int $width, int $height) */ + public function setSize($width, $height) + { + $this->width = (int)$width; + $this->height = (int)$height; + } - /** @prototype void public function setTimeMode($from, $to, $granularity) */ - public function setTimeMode($from, $to, $granularity) - { - $this->granularity = $granularity; + /** @prototype void public function setTimeMode($from, $to, $granularity) */ + public function setTimeMode($from, $to, $granularity) + { + $this->granularity = $granularity; - if (Validate::isDate($from)) - $from = strtotime($from); - $this->from = $from; - if (Validate::isDate($to)) - $to = strtotime($to); - $this->to = $to; + if (Validate::isDate($from)) { + $from = strtotime($from); + } + $this->from = $from; + if (Validate::isDate($to)) { + $to = strtotime($to); + } + $this->to = $to; - if ($granularity == 'd') - $this->format = '%d/%m/%y'; - if ($granularity == 'w') - $this->format = '%d/%m/%y'; - if ($granularity == 'm') - $this->format = '%m/%y'; - if ($granularity == 'y') - $this->format = '%y'; + if ($granularity == 'd') { + $this->format = '%d/%m/%y'; + } + if ($granularity == 'w') { + $this->format = '%d/%m/%y'; + } + if ($granularity == 'm') { + $this->format = '%m/%y'; + } + if ($granularity == 'y') { + $this->format = '%y'; + } - $this->timeMode = true; - } + $this->timeMode = true; + } - public function getCurve($i) - { - if (!array_key_exists($i, $this->curves)) - $this->curves[$i] = new Curve(); - return $this->curves[$i]; - } + public function getCurve($i) + { + if (!array_key_exists($i, $this->curves)) { + $this->curves[$i] = new Curve(); + } + return $this->curves[$i]; + } - /** @prototype void public function display() */ - public function display() - { - echo $this->fetch(); - } + /** @prototype void public function display() */ + public function display() + { + echo $this->fetch(); + } - public function fetch() - { - if ($this->timeMode) - { - $options = 'xaxis:{mode:"time",timeformat:\''.addslashes($this->format).'\',min:'.$this->from.'000,max:'.$this->to.'000}'; - if ($this->granularity == 'd') - foreach ($this->curves as $curve) - { - /** @var Curve $curve */ - for ($i = $this->from; $i <= $this->to; $i = strtotime('+1 day', $i)) - if (!$curve->getPoint($i)) - $curve->setPoint($i, 0); - } - } + public function fetch() + { + if ($this->timeMode) { + $options = 'xaxis:{mode:"time",timeformat:\''.addslashes($this->format).'\',min:'.$this->from.'000,max:'.$this->to.'000}'; + if ($this->granularity == 'd') { + foreach ($this->curves as $curve) { + /** @var Curve $curve */ + for ($i = $this->from; $i <= $this->to; $i = strtotime('+1 day', $i)) { + if (!$curve->getPoint($i)) { + $curve->setPoint($i, 0); + } + } + } + } + } - $jsCurves = array(); - foreach ($this->curves as $curve) - $jsCurves[] = $curve->getValues($this->timeMode); + $jsCurves = array(); + foreach ($this->curves as $curve) { + $jsCurves[] = $curve->getValues($this->timeMode); + } - if (count($jsCurves)) - return ' + if (count($jsCurves)) { + return '
'; - else - return ErrorFacade::Display(PS_ERROR_UNDEFINED, 'No values for this chart.'); - } + } else { + return ErrorFacade::Display(PS_ERROR_UNDEFINED, 'No values for this chart.'); + } + } } class Curve { - protected $values = array(); - protected $label; - protected $type; + protected $values = array(); + protected $label; + protected $type; - /** @prototype void public function setValues($values) */ - public function setValues($values) - { - $this->values = $values; - } + /** @prototype void public function setValues($values) */ + public function setValues($values) + { + $this->values = $values; + } - public function getValues($time_mode = false) - { - ksort($this->values); - $string = ''; - foreach ($this->values as $key => $value) - $string .= '['.addslashes((string)$key).($time_mode ? '000' : '').','.(float)$value.'],'; - return '{data:['.rtrim($string, ',').']'.(!empty($this->label) ? ',label:"'.$this->label.'"' : '').''.(!empty($this->type) ? ','.$this->type : '').'}'; - } + public function getValues($time_mode = false) + { + ksort($this->values); + $string = ''; + foreach ($this->values as $key => $value) { + $string .= '['.addslashes((string)$key).($time_mode ? '000' : '').','.(float)$value.'],'; + } + return '{data:['.rtrim($string, ',').']'.(!empty($this->label) ? ',label:"'.$this->label.'"' : '').''.(!empty($this->type) ? ','.$this->type : '').'}'; + } - /** @prototype void public function setPoint(float $x, float $y) */ - public function setPoint($x, $y) - { - $this->values[(string)$x] = (float)$y; - } + /** @prototype void public function setPoint(float $x, float $y) */ + public function setPoint($x, $y) + { + $this->values[(string)$x] = (float)$y; + } - public function setLabel($label) - { - $this->label = $label; - } + public function setLabel($label) + { + $this->label = $label; + } - public function setType($type) - { - $this->type = ''; - if ($type == 'bars') - $this->type = 'bars:{show:true,lineWidth:10}'; - if ($type == 'steps') - $this->type = 'lines:{show:true,steps:true}'; - } + public function setType($type) + { + $this->type = ''; + if ($type == 'bars') { + $this->type = 'bars:{show:true,lineWidth:10}'; + } + if ($type == 'steps') { + $this->type = 'lines:{show:true,steps:true}'; + } + } - public function getPoint($x) - { - if (array_key_exists((string)$x, $this->values)) - return $this->values[(string)$x]; - } + public function getPoint($x) + { + if (array_key_exists((string)$x, $this->values)) { + return $this->values[(string)$x]; + } + } } diff --git a/classes/Combination.php b/classes/Combination.php index becf93a3..05f128ca 100644 --- a/classes/Combination.php +++ b/classes/Combination.php @@ -26,308 +26,320 @@ class CombinationCore extends ObjectModel { - public $id_product; + public $id_product; - public $reference; + public $reference; - public $supplier_reference; + public $supplier_reference; - public $location; + public $location; - public $ean13; + public $ean13; - public $upc; + public $upc; - public $wholesale_price; + public $wholesale_price; - public $price; + public $price; - public $unit_price_impact; + public $unit_price_impact; - public $ecotax; + public $ecotax; - public $minimal_quantity = 1; + public $minimal_quantity = 1; - public $quantity; + public $quantity; - public $weight; + public $weight; - public $default_on; + public $default_on; - public $available_date = '0000-00-00'; + public $available_date = '0000-00-00'; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'product_attribute', - 'primary' => 'id_product_attribute', - 'fields' => array( - 'id_product' => array('type' => self::TYPE_INT, 'shop' => 'both', 'validate' => 'isUnsignedId', 'required' => true), - 'location' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 64), - 'ean13' => array('type' => self::TYPE_STRING, 'validate' => 'isEan13', 'size' => 13), - 'upc' => array('type' => self::TYPE_STRING, 'validate' => 'isUpc', 'size' => 12), - 'quantity' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'size' => 10), - 'reference' => array('type' => self::TYPE_STRING, 'size' => 32), - 'supplier_reference' => array('type' => self::TYPE_STRING, 'size' => 32), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'product_attribute', + 'primary' => 'id_product_attribute', + 'fields' => array( + 'id_product' => array('type' => self::TYPE_INT, 'shop' => 'both', 'validate' => 'isUnsignedId', 'required' => true), + 'location' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 64), + 'ean13' => array('type' => self::TYPE_STRING, 'validate' => 'isEan13', 'size' => 13), + 'upc' => array('type' => self::TYPE_STRING, 'validate' => 'isUpc', 'size' => 12), + 'quantity' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'size' => 10), + 'reference' => array('type' => self::TYPE_STRING, 'size' => 32), + 'supplier_reference' => array('type' => self::TYPE_STRING, 'size' => 32), - /* Shop fields */ - 'wholesale_price' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice', 'size' => 27), - 'price' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isNegativePrice', 'size' => 20), - 'ecotax' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice', 'size' => 20), - 'weight' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isFloat'), - 'unit_price_impact' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isNegativePrice', 'size' => 20), - 'minimal_quantity' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedId', 'required' => true), - 'default_on' => array('type' => self::TYPE_BOOL, 'allow_null' => true, 'shop' => true, 'validate' => 'isBool'), - 'available_date' => array('type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDateFormat'), - ), - ); + /* Shop fields */ + 'wholesale_price' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice', 'size' => 27), + 'price' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isNegativePrice', 'size' => 20), + 'ecotax' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice', 'size' => 20), + 'weight' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isFloat'), + 'unit_price_impact' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isNegativePrice', 'size' => 20), + 'minimal_quantity' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedId', 'required' => true), + 'default_on' => array('type' => self::TYPE_BOOL, 'allow_null' => true, 'shop' => true, 'validate' => 'isBool'), + 'available_date' => array('type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDateFormat'), + ), + ); - protected $webserviceParameters = array( - 'objectNodeName' => 'combination', - 'objectsNodeName' => 'combinations', - 'fields' => array( - 'id_product' => array('required' => true, 'xlink_resource'=> 'products'), - ), - 'associations' => array( - 'product_option_values' => array('resource' => 'product_option_value'), - 'images' => array('resource' => 'image', 'api' => 'images/products'), - ), - ); + protected $webserviceParameters = array( + 'objectNodeName' => 'combination', + 'objectsNodeName' => 'combinations', + 'fields' => array( + 'id_product' => array('required' => true, 'xlink_resource'=> 'products'), + ), + 'associations' => array( + 'product_option_values' => array('resource' => 'product_option_value'), + 'images' => array('resource' => 'image', 'api' => 'images/products'), + ), + ); - public function delete() - { - if (!parent::delete()) - return false; + public function delete() + { + if (!parent::delete()) { + return false; + } - // Removes the product from StockAvailable, for the current shop - StockAvailable::removeProductFromStockAvailable((int)$this->id_product, (int)$this->id); + // Removes the product from StockAvailable, for the current shop + StockAvailable::removeProductFromStockAvailable((int)$this->id_product, (int)$this->id); - if ($specific_prices = SpecificPrice::getByProductId((int)$this->id_product, (int)$this->id)) - foreach ($specific_prices as $specific_price) - { - $price = new SpecificPrice((int)$specific_price['id_specific_price']); - $price->delete(); - } + if ($specific_prices = SpecificPrice::getByProductId((int)$this->id_product, (int)$this->id)) { + foreach ($specific_prices as $specific_price) { + $price = new SpecificPrice((int)$specific_price['id_specific_price']); + $price->delete(); + } + } - if (!$this->hasMultishopEntries() && !$this->deleteAssociations()) - return false; + if (!$this->hasMultishopEntries() && !$this->deleteAssociations()) { + return false; + } - $this->deleteFromSupplier($this->id_product); - Product::updateDefaultAttribute($this->id_product); + $this->deleteFromSupplier($this->id_product); + Product::updateDefaultAttribute($this->id_product); - return true; - } + return true; + } - public function deleteFromSupplier($id_product) - { - return Db::getInstance()->delete('product_supplier', 'id_product = '.(int)$id_product - .' AND id_product_attribute = '.(int)$this->id); - } + public function deleteFromSupplier($id_product) + { + return Db::getInstance()->delete('product_supplier', 'id_product = '.(int)$id_product + .' AND id_product_attribute = '.(int)$this->id); + } - public function add($autodate = true, $null_values = false) - { - if ($this->default_on) - $this->default_on = 1; - else - $this->default_on = null; + public function add($autodate = true, $null_values = false) + { + if ($this->default_on) { + $this->default_on = 1; + } else { + $this->default_on = null; + } - if (!parent::add($autodate, $null_values)) - return false; + if (!parent::add($autodate, $null_values)) { + return false; + } - $product = new Product((int)$this->id_product); - if ($product->getType() == Product::PTYPE_VIRTUAL) - StockAvailable::setProductOutOfStock((int)$this->id_product, 1, null, (int)$this->id); - else - StockAvailable::setProductOutOfStock((int)$this->id_product, StockAvailable::outOfStock((int)$this->id_product), null, $this->id); + $product = new Product((int)$this->id_product); + if ($product->getType() == Product::PTYPE_VIRTUAL) { + StockAvailable::setProductOutOfStock((int)$this->id_product, 1, null, (int)$this->id); + } else { + StockAvailable::setProductOutOfStock((int)$this->id_product, StockAvailable::outOfStock((int)$this->id_product), null, $this->id); + } - SpecificPriceRule::applyAllRules(array((int)$this->id_product)); + SpecificPriceRule::applyAllRules(array((int)$this->id_product)); - Product::updateDefaultAttribute($this->id_product); + Product::updateDefaultAttribute($this->id_product); - return true; - } + return true; + } - public function update($null_values = false) - { - if ($this->default_on) - $this->default_on = 1; - else - $this->default_on = null; + public function update($null_values = false) + { + if ($this->default_on) { + $this->default_on = 1; + } else { + $this->default_on = null; + } - $return = parent::update($null_values); - Product::updateDefaultAttribute($this->id_product); + $return = parent::update($null_values); + Product::updateDefaultAttribute($this->id_product); - return $return; - } + return $return; + } - public function deleteAssociations() - { - $result = Db::getInstance()->delete('product_attribute_combination', '`id_product_attribute` = '.(int)$this->id); - $result &= Db::getInstance()->delete('cart_product', '`id_product_attribute` = '.(int)$this->id); - $result &= Db::getInstance()->delete('product_attribute_image', '`id_product_attribute` = '.(int)$this->id); + public function deleteAssociations() + { + $result = Db::getInstance()->delete('product_attribute_combination', '`id_product_attribute` = '.(int)$this->id); + $result &= Db::getInstance()->delete('cart_product', '`id_product_attribute` = '.(int)$this->id); + $result &= Db::getInstance()->delete('product_attribute_image', '`id_product_attribute` = '.(int)$this->id); - return $result; - } + return $result; + } - public function setAttributes($ids_attribute) - { - $result = $this->deleteAssociations(); - if ($result && !empty($ids_attribute)) - { - $sql_values = array(); - foreach ($ids_attribute as $value) - $sql_values[] = '('.(int)$value.', '.(int)$this->id.')'; + public function setAttributes($ids_attribute) + { + $result = $this->deleteAssociations(); + if ($result && !empty($ids_attribute)) { + $sql_values = array(); + foreach ($ids_attribute as $value) { + $sql_values[] = '('.(int)$value.', '.(int)$this->id.')'; + } - $result = Db::getInstance()->execute(' + $result = Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'product_attribute_combination` (`id_attribute`, `id_product_attribute`) VALUES '.implode(',', $sql_values) - ); - } - return $result; - } + ); + } + return $result; + } - public function setWsProductOptionValues($values) - { - $ids_attributes = array(); - foreach ($values as $value) - $ids_attributes[] = $value['id']; - return $this->setAttributes($ids_attributes); - } + public function setWsProductOptionValues($values) + { + $ids_attributes = array(); + foreach ($values as $value) { + $ids_attributes[] = $value['id']; + } + return $this->setAttributes($ids_attributes); + } - public function getWsProductOptionValues() - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public function getWsProductOptionValues() + { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT a.id_attribute AS id FROM `'._DB_PREFIX_.'product_attribute_combination` a '.Shop::addSqlAssociation('attribute', 'a').' WHERE a.id_product_attribute = '.(int)$this->id); - return $result; - } + return $result; + } - public function getWsImages() - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public function getWsImages() + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT a.`id_image` as id FROM `'._DB_PREFIX_.'product_attribute_image` a '.Shop::addSqlAssociation('product_attribute', 'a').' WHERE a.`id_product_attribute` = '.(int)$this->id.' '); - } + } - public function setImages($ids_image) - { - if (Db::getInstance()->execute(' + public function setImages($ids_image) + { + if (Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'product_attribute_image` - WHERE `id_product_attribute` = '.(int)$this->id) === false) - return false; + WHERE `id_product_attribute` = '.(int)$this->id) === false) { + return false; + } - if (is_array($ids_image) && count($ids_image)) - { - $sql_values = array(); + if (is_array($ids_image) && count($ids_image)) { + $sql_values = array(); - foreach ($ids_image as $value) - $sql_values[] = '('.(int)$this->id.', '.(int)$value.')'; + foreach ($ids_image as $value) { + $sql_values[] = '('.(int)$this->id.', '.(int)$value.')'; + } - if (is_array($sql_values) && count($sql_values)) - Db::getInstance()->execute(' + if (is_array($sql_values) && count($sql_values)) { + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'product_attribute_image` (`id_product_attribute`, `id_image`) VALUES '.implode(',', $sql_values) - ); - } - return true; - } + ); + } + } + return true; + } - public function setWsImages($values) - { - $ids_images = array(); - foreach ($values as $value) - $ids_images[] = (int)$value['id']; - return $this->setImages($ids_images); - } + public function setWsImages($values) + { + $ids_images = array(); + foreach ($values as $value) { + $ids_images[] = (int)$value['id']; + } + return $this->setImages($ids_images); + } - public function getAttributesName($id_lang) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public function getAttributesName($id_lang) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT al.* FROM '._DB_PREFIX_.'product_attribute_combination pac JOIN '._DB_PREFIX_.'attribute_lang al ON (pac.id_attribute = al.id_attribute AND al.id_lang='.(int)$id_lang.') WHERE pac.id_product_attribute='.(int)$this->id); - } + } - /** - * This method is allow to know if a feature is active - * @since 1.5.0.1 - * @return bool - */ - public static function isFeatureActive() - { - static $feature_active = null; + /** + * This method is allow to know if a feature is active + * @since 1.5.0.1 + * @return bool + */ + public static function isFeatureActive() + { + static $feature_active = null; - if ($feature_active === null) - $feature_active = Configuration::get('PS_COMBINATION_FEATURE_ACTIVE'); - return $feature_active; - } + if ($feature_active === null) { + $feature_active = Configuration::get('PS_COMBINATION_FEATURE_ACTIVE'); + } + return $feature_active; + } - /** - * This method is allow to know if a Combination entity is currently used - * @since 1.5.0.1 - * @param $table - * @param $has_active_column - * @return bool - */ - public static function isCurrentlyUsed($table = null, $has_active_column = false) - { - return parent::isCurrentlyUsed('product_attribute'); - } + /** + * This method is allow to know if a Combination entity is currently used + * @since 1.5.0.1 + * @param $table + * @param $has_active_column + * @return bool + */ + public static function isCurrentlyUsed($table = null, $has_active_column = false) + { + return parent::isCurrentlyUsed('product_attribute'); + } - /** - * For a given product_attribute reference, returns the corresponding id - * - * @param int $id_product - * @param string $reference - * @return int id - */ - public static function getIdByReference($id_product, $reference) - { - if (empty($reference)) - return 0; + /** + * For a given product_attribute reference, returns the corresponding id + * + * @param int $id_product + * @param string $reference + * @return int id + */ + public static function getIdByReference($id_product, $reference) + { + if (empty($reference)) { + return 0; + } - $query = new DbQuery(); - $query->select('pa.id_product_attribute'); - $query->from('product_attribute', 'pa'); - $query->where('pa.reference LIKE \'%'.pSQL($reference).'%\''); - $query->where('pa.id_product = '.(int)$id_product); + $query = new DbQuery(); + $query->select('pa.id_product_attribute'); + $query->from('product_attribute', 'pa'); + $query->where('pa.reference LIKE \'%'.pSQL($reference).'%\''); + $query->where('pa.id_product = '.(int)$id_product); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } - public function getColorsAttributes() - { - return Db::getInstance()->executeS(' + public function getColorsAttributes() + { + return Db::getInstance()->executeS(' SELECT a.id_attribute FROM '._DB_PREFIX_.'product_attribute_combination pac JOIN '._DB_PREFIX_.'attribute a ON (pac.id_attribute = a.id_attribute) JOIN '._DB_PREFIX_.'attribute_group ag ON (ag.id_attribute_group = a.id_attribute_group) WHERE pac.id_product_attribute='.(int)$this->id.' AND ag.is_color_group = 1 '); - } + } - /** - * Retrive the price of combination - * - * @since 1.5.0 - * @param int $id_product_attribute - * @return float mixed - */ - public static function getPrice($id_product_attribute) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Retrive the price of combination + * + * @since 1.5.0 + * @param int $id_product_attribute + * @return float mixed + */ + public static function getPrice($id_product_attribute) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT product_attribute_shop.`price` FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE pa.`id_product_attribute` = '.(int)$id_product_attribute - ); - } + ); + } } diff --git a/classes/CompareProduct.php b/classes/CompareProduct.php index c8591256..8fc05d94 100644 --- a/classes/CompareProduct.php +++ b/classes/CompareProduct.php @@ -26,144 +26,145 @@ class CompareProductCore extends ObjectModel { - public $id_compare; + public $id_compare; - public $id_customer; + public $id_customer; - public $date_add; + public $date_add; - public $date_upd; + public $date_upd; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'compare', - 'primary' => 'id_compare', - 'fields' => array( - 'id_compare' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), - 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'compare', + 'primary' => 'id_compare', + 'fields' => array( + 'id_compare' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), + 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), + ), + ); - /** - * Get all compare products of the customer - * @param int $id_customer - * @return array - */ - public static function getCompareProducts($id_compare) - { - $results = Db::getInstance()->executeS(' + /** + * Get all compare products of the customer + * @param int $id_customer + * @return array + */ + public static function getCompareProducts($id_compare) + { + $results = Db::getInstance()->executeS(' SELECT DISTINCT `id_product` FROM `'._DB_PREFIX_.'compare` c LEFT JOIN `'._DB_PREFIX_.'compare_product` cp ON (cp.`id_compare` = c.`id_compare`) WHERE cp.`id_compare` = '.(int)($id_compare)); - $compareProducts = null; + $compareProducts = null; - if ($results) - foreach ($results as $result) - $compareProducts[] = (int)$result['id_product']; + if ($results) { + foreach ($results as $result) { + $compareProducts[] = (int)$result['id_product']; + } + } - return $compareProducts; - } + return $compareProducts; + } - /** - * Add a compare product for the customer - * @param int $id_customer, int $id_product - * @return bool - */ - public static function addCompareProduct($id_compare, $id_product) - { - // Check if compare row exists - $id_compare = Db::getInstance()->getValue(' + /** + * Add a compare product for the customer + * @param int $id_customer, int $id_product + * @return bool + */ + public static function addCompareProduct($id_compare, $id_product) + { + // Check if compare row exists + $id_compare = Db::getInstance()->getValue(' SELECT `id_compare` FROM `'._DB_PREFIX_.'compare` WHERE `id_compare` = '.(int)$id_compare); - if (!$id_compare) - { - $id_customer = false; - if (Context::getContext()->customer) - $id_customer = Context::getContext()->customer->id; - $sql = Db::getInstance()->execute(' + if (!$id_compare) { + $id_customer = false; + if (Context::getContext()->customer) { + $id_customer = Context::getContext()->customer->id; + } + $sql = Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'compare` (`id_compare`, `id_customer`) VALUES (NULL, "'.($id_customer ? $id_customer: '0').'")'); - if ($sql) - { - $id_compare = Db::getInstance()->getValue('SELECT MAX(`id_compare`) FROM `'._DB_PREFIX_.'compare`'); - Context::getContext()->cookie->id_compare = $id_compare; - } - } + if ($sql) { + $id_compare = Db::getInstance()->getValue('SELECT MAX(`id_compare`) FROM `'._DB_PREFIX_.'compare`'); + Context::getContext()->cookie->id_compare = $id_compare; + } + } - return Db::getInstance()->execute(' + return Db::getInstance()->execute(' INSERT IGNORE INTO `'._DB_PREFIX_.'compare_product` (`id_compare`, `id_product`, `date_add`, `date_upd`) VALUES ('.(int)($id_compare).', '.(int)($id_product).', NOW(), NOW())'); - } + } - /** - * Remove a compare product for the customer - * @param int $id_compare - * @param int $id_product - * @return bool - */ - public static function removeCompareProduct($id_compare, $id_product) - { - return Db::getInstance()->execute(' + /** + * Remove a compare product for the customer + * @param int $id_compare + * @param int $id_product + * @return bool + */ + public static function removeCompareProduct($id_compare, $id_product) + { + return Db::getInstance()->execute(' DELETE cp FROM `'._DB_PREFIX_.'compare_product` cp, `'._DB_PREFIX_.'compare` c WHERE cp.`id_compare`=c.`id_compare` AND cp.`id_product` = '.(int)$id_product.' AND c.`id_compare` = '.(int)$id_compare); - } + } - /** - * Get the number of compare products of the customer - * @param int $id_compare - * @return int - */ - public static function getNumberProducts($id_compare) - { - return (int)(Db::getInstance()->getValue(' + /** + * Get the number of compare products of the customer + * @param int $id_compare + * @return int + */ + public static function getNumberProducts($id_compare) + { + return (int)(Db::getInstance()->getValue(' SELECT count(`id_compare`) FROM `'._DB_PREFIX_.'compare_product` WHERE `id_compare` = '.(int)($id_compare))); - } + } - /** - * Clean entries which are older than the period - * @param string $period - * @return void - */ - public static function cleanCompareProducts($period = 'week') - { - if ($period === 'week') - $interval = '1 WEEK'; - elseif ($period === 'month') - $interval = '1 MONTH'; - elseif ($period === 'year') - $interval = '1 YEAR'; - else - return; + /** + * Clean entries which are older than the period + * @param string $period + * @return void + */ + public static function cleanCompareProducts($period = 'week') + { + if ($period === 'week') { + $interval = '1 WEEK'; + } elseif ($period === 'month') { + $interval = '1 MONTH'; + } elseif ($period === 'year') { + $interval = '1 YEAR'; + } else { + return; + } - if ($interval != null) - { - Db::getInstance()->execute(' + if ($interval != null) { + Db::getInstance()->execute(' DELETE cp, c FROM `'._DB_PREFIX_.'compare_product` cp, `'._DB_PREFIX_.'compare` c WHERE cp.date_upd < DATE_SUB(NOW(), INTERVAL 1 WEEK) AND c.`id_compare`=cp.`id_compare`'); - } - } + } + } - /** - * Get the id_compare by id_customer - * @param int $id_customer - * @return int $id_compare - */ - public static function getIdCompareByIdCustomer($id_customer) - { - return (int)Db::getInstance()->getValue(' + /** + * Get the id_compare by id_customer + * @param int $id_customer + * @return int $id_compare + */ + public static function getIdCompareByIdCustomer($id_customer) + { + return (int)Db::getInstance()->getValue(' SELECT `id_compare` FROM `'._DB_PREFIX_.'compare` WHERE `id_customer`= '.(int)$id_customer); - } + } } diff --git a/classes/Configuration.php b/classes/Configuration.php index ebdcf9c6..f123b094 100644 --- a/classes/Configuration.php +++ b/classes/Configuration.php @@ -26,573 +26,597 @@ class ConfigurationCore extends ObjectModel { - public $id; - - /** @var string Key */ - public $name; - - public $id_shop_group; - public $id_shop; - - /** @var string Value */ - public $value; - - /** @var string Object creation date */ - public $date_add; - - /** @var string Object last modification date */ - public $date_upd; - - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'configuration', - 'primary' => 'id_configuration', - 'multilang' => true, - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isConfigName', 'required' => true, 'size' => 254), - 'id_shop_group' => array('type' => self::TYPE_NOTHING, 'validate' => 'isUnsignedId'), - 'id_shop' => array('type' => self::TYPE_NOTHING, 'validate' => 'isUnsignedId'), - 'value' => array('type' => self::TYPE_STRING), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); - - /** @var array Configuration cache */ - protected static $_cache = array(); - - /** @var array Vars types */ - protected static $types = array(); - - protected $webserviceParameters = array( - 'fields' => array( - 'value' => array(), - ) - ); - - /** - * @see ObjectModel::getFieldsLang() - * @return bool|array Multilingual fields - */ - public function getFieldsLang() - { - if (!is_array($this->value)) - return true; - return parent::getFieldsLang(); - } - - /** - * Return ID a configuration key - * - * @param string $key - * @param int $id_shop_group - * @param int $id_shop - * @return int Configuration key ID - */ - public static function getIdByName($key, $id_shop_group = null, $id_shop = null) - { - if ($id_shop === null) - $id_shop = Shop::getContextShopID(true); - if ($id_shop_group === null) - $id_shop_group = Shop::getContextShopGroupID(true); - - $sql = 'SELECT `'.bqSQL(self::$definition['primary']).'` - FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` - WHERE name = \''.pSQL($key).'\' - '.Configuration::sqlRestriction($id_shop_group, $id_shop); - return (int)Db::getInstance()->getValue($sql); - } - - public static function configurationIsLoaded() - { - static $loaded = null; - - if ($loaded !== null) - return $loaded; - - if (isset(self::$_cache) && isset(self::$_cache[self::$definition['table']]) && count(self::$_cache[self::$definition['table']])) - { - $loaded = true; - return $loaded; - } - - return false; - } - - /** - * WARNING: For testing only. Do NOT rely on this method, it may be removed at any time. - * @todo Delegate static calls from Configuration to an instance - * of a class to be created. - */ - public static function clearConfigurationCacheForTesting() - { - self::$_cache = array(); - } - - /** - * Load all configuration data - */ - public static function loadConfiguration() - { - self::$_cache[self::$definition['table']] = array(); - - $sql = 'SELECT c.`name`, cl.`id_lang`, IF(cl.`id_lang` IS NULL, c.`value`, cl.`value`) AS value, c.id_shop_group, c.id_shop - FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` c - LEFT JOIN `'._DB_PREFIX_.bqSQL(self::$definition['table']).'_lang` cl ON (c.`'.bqSQL(self::$definition['primary']).'` = cl.`'.bqSQL(self::$definition['primary']).'`)'; - $db = Db::getInstance(); - $result = $db->executeS($sql, false); - while ($row = $db->nextRow($result)) - { - $lang = ($row['id_lang']) ? $row['id_lang'] : 0; - self::$types[$row['name']] = ($lang) ? 'lang' : 'normal'; - if (!isset(self::$_cache[self::$definition['table']][$lang])) - self::$_cache[self::$definition['table']][$lang] = array( - 'global' => array(), - 'group' => array(), - 'shop' => array(), - ); - - if ($row['id_shop']) - self::$_cache[self::$definition['table']][$lang]['shop'][$row['id_shop']][$row['name']] = $row['value']; - elseif ($row['id_shop_group']) - self::$_cache[self::$definition['table']][$lang]['group'][$row['id_shop_group']][$row['name']] = $row['value']; - else - self::$_cache[self::$definition['table']][$lang]['global'][$row['name']] = $row['value']; - } - } - - /** - * Get a single configuration value (in one language only) - * - * @param string $key Key wanted - * @param int $id_lang Language ID - * @return string Value - */ - public static function get($key, $id_lang = null, $id_shop_group = null, $id_shop = null) - { - if (defined('_PS_DO_NOT_LOAD_CONFIGURATION_') && _PS_DO_NOT_LOAD_CONFIGURATION_) - return false; - - // If conf if not initialized, try manual query - if (!isset(self::$_cache[self::$definition['table']])) - { - Configuration::loadConfiguration(); - if (!self::$_cache[self::$definition['table']]) - return Db::getInstance()->getValue('SELECT `value` FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` WHERE `name` = "'.pSQL($key).'"'); - } - $id_lang = (int)$id_lang; - if ($id_shop === null || !Shop::isFeatureActive()) - $id_shop = Shop::getContextShopID(true); - if ($id_shop_group === null || !Shop::isFeatureActive()) - $id_shop_group = Shop::getContextShopGroupID(true); - - if (!isset(self::$_cache[self::$definition['table']][$id_lang])) - $id_lang = 0; - - if ($id_shop && Configuration::hasKey($key, $id_lang, null, $id_shop)) - return self::$_cache[self::$definition['table']][$id_lang]['shop'][$id_shop][$key]; - elseif ($id_shop_group && Configuration::hasKey($key, $id_lang, $id_shop_group)) - return self::$_cache[self::$definition['table']][$id_lang]['group'][$id_shop_group][$key]; - elseif (Configuration::hasKey($key, $id_lang)) - return self::$_cache[self::$definition['table']][$id_lang]['global'][$key]; - return false; - } - - public static function getGlobalValue($key, $id_lang = null) - { - return Configuration::get($key, $id_lang, 0, 0); - } - - /** - * Get a single configuration value (in multiple languages) - * - * @param string $key Key wanted - * @param int $id_shop_group - * @param int $id_shop - * @return array Values in multiple languages - */ - public static function getInt($key, $id_shop_group = null, $id_shop = null) - { - $results_array = array(); - foreach (Language::getIDs() as $id_lang) - $results_array[$id_lang] = Configuration::get($key, $id_lang, $id_shop_group, $id_shop); - - return $results_array; - } - - /** - * Get a single configuration value for all shops - * - * @param string $key Key wanted - * @param int $id_lang - * @return array Values for all shops - */ - public static function getMultiShopValues($key, $id_lang = null) - { - $shops = Shop::getShops(false, null, true); - $resultsArray = array(); - foreach ($shops as $id_shop) - $resultsArray[$id_shop] = Configuration::get($key, $id_lang, null, $id_shop); - return $resultsArray; - } - - - /** - * Get several configuration values (in one language only) - * - * @throws PrestaShopException - * @param array $keys Keys wanted - * @param int $id_lang Language ID - * @param int $id_shop_group - * @param int $id_shop - * @return array Values - */ - public static function getMultiple($keys, $id_lang = null, $id_shop_group = null, $id_shop = null) - { - if (!is_array($keys)) - throw new PrestaShopException('keys var is not an array'); - - $id_lang = (int)$id_lang; - if ($id_shop === null) - $id_shop = Shop::getContextShopID(true); - if ($id_shop_group === null) - $id_shop_group = Shop::getContextShopGroupID(true); - - $results = array(); - foreach ($keys as $key) - $results[$key] = Configuration::get($key, $id_lang, $id_shop_group, $id_shop); - return $results; - } - - /** - * Check if key exists in configuration - * - * @param string $key - * @param int $id_lang - * @param int $id_shop_group - * @param int $id_shop - * @return bool - */ - public static function hasKey($key, $id_lang = null, $id_shop_group = null, $id_shop = null) - { - if (!is_int($key) && !is_string($key)) - return false; - - $id_lang = (int)$id_lang; - - if ($id_shop) - return isset(self::$_cache[self::$definition['table']][$id_lang]['shop'][$id_shop]) - && (isset(self::$_cache[self::$definition['table']][$id_lang]['shop'][$id_shop][$key]) - || array_key_exists($key, self::$_cache[self::$definition['table']][$id_lang]['shop'][$id_shop])); - elseif ($id_shop_group) - return isset(self::$_cache[self::$definition['table']][$id_lang]['group'][$id_shop_group]) - && (isset(self::$_cache[self::$definition['table']][$id_lang]['group'][$id_shop_group][$key]) - || array_key_exists($key, self::$_cache[self::$definition['table']][$id_lang]['group'][$id_shop_group])); - - return isset(self::$_cache[self::$definition['table']][$id_lang]['global']) - && (isset(self::$_cache[self::$definition['table']][$id_lang]['global'][$key]) - || array_key_exists($key, self::$_cache[self::$definition['table']][$id_lang]['global'])); - } - - /** - * Set TEMPORARY a single configuration value (in one language only) - * - * @param string $key Key wanted - * @param mixed $values $values is an array if the configuration is multilingual, a single string else. - * @param int $id_shop_group - * @param int $id_shop - */ - public static function set($key, $values, $id_shop_group = null, $id_shop = null) - { - if (!Validate::isConfigName($key)) - die(sprintf(Tools::displayError('[%s] is not a valid configuration key'), $key)); - - if ($id_shop === null) - $id_shop = Shop::getContextShopID(true); - if ($id_shop_group === null) - $id_shop_group = Shop::getContextShopGroupID(true); - - if (!is_array($values)) - $values = array($values); - - foreach ($values as $lang => $value) - { - if ($id_shop) - self::$_cache[self::$definition['table']][$lang]['shop'][$id_shop][$key] = $value; - elseif ($id_shop_group) - self::$_cache[self::$definition['table']][$lang]['group'][$id_shop_group][$key] = $value; - else - self::$_cache[self::$definition['table']][$lang]['global'][$key] = $value; - } - } - - /** - * Update configuration key for global context only - * - * @param string $key - * @param mixed $values - * @param bool $html - * @return bool - */ - public static function updateGlobalValue($key, $values, $html = false) - { - return Configuration::updateValue($key, $values, $html, 0, 0); - } - - /** - * Update configuration key and value into database (automatically insert if key does not exist) - * - * @param string $key Key - * @param mixed $values $values is an array if the configuration is multilingual, a single string else. - * @param bool $html Specify if html is authorized in value - * @param int $id_shop_group - * @param int $id_shop - * @return bool Update result - */ - public static function updateValue($key, $values, $html = false, $id_shop_group = null, $id_shop = null) - { - if (!Validate::isConfigName($key)) - die(sprintf(Tools::displayError('[%s] is not a valid configuration key'), $key)); - - if ($id_shop === null || !Shop::isFeatureActive()) - $id_shop = Shop::getContextShopID(true); - if ($id_shop_group === null || !Shop::isFeatureActive()) - $id_shop_group = Shop::getContextShopGroupID(true); - - if (!is_array($values)) - $values = array($values); - - if ($html) - { - foreach ($values as &$value) - $value = Tools::purifyHTML($value); - unset($value); - } - - $result = true; - foreach ($values as $lang => $value) - { - $stored_value = Configuration::get($key, $lang, $id_shop_group, $id_shop); - // if there isn't a $stored_value, we must insert $value - if ((!is_numeric($value) && $value === $stored_value) || (is_numeric($value) && $value == $stored_value && Configuration::hasKey($key, $lang))) - continue; - - // If key already exists, update value - if (Configuration::hasKey($key, $lang, $id_shop_group, $id_shop)) - { - if (!$lang) - { - // Update config not linked to lang - $result &= Db::getInstance()->update(self::$definition['table'], array( - 'value' => pSQL($value, $html), - 'date_upd' => date('Y-m-d H:i:s'), - ), '`name` = \''.pSQL($key).'\''.Configuration::sqlRestriction($id_shop_group, $id_shop), 1, true); - } - else - { - // Update multi lang - $sql = 'UPDATE `'._DB_PREFIX_.bqSQL(self::$definition['table']).'_lang` cl - SET cl.value = \''.pSQL($value, $html).'\', - cl.date_upd = NOW() - WHERE cl.id_lang = '.(int)$lang.' - AND cl.`'.bqSQL(self::$definition['primary']).'` = ( - SELECT c.`'.bqSQL(self::$definition['primary']).'` - FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` c - WHERE c.name = \''.pSQL($key).'\'' - .Configuration::sqlRestriction($id_shop_group, $id_shop) - .')'; - $result &= Db::getInstance()->execute($sql); - } - } - // If key does not exists, create it - else - { - if (!$configID = Configuration::getIdByName($key, $id_shop_group, $id_shop)) - { - $newConfig = new Configuration(); - $newConfig->name = $key; - if ($id_shop) - $newConfig->id_shop = (int)$id_shop; - if ($id_shop_group) - $newConfig->id_shop_group = (int)$id_shop_group; - if (!$lang) - $newConfig->value = $value; - $result &= $newConfig->add(true, true); - $configID = $newConfig->id; - } - - if ($lang) - { - $result &= Db::getInstance()->insert(self::$definition['table'].'_lang', array( - self::$definition['primary'] => $configID, - 'id_lang' => (int)$lang, - 'value' => pSQL($value, $html), - 'date_upd' => date('Y-m-d H:i:s'), - )); - } - } - } - - Configuration::set($key, $values, $id_shop_group, $id_shop); - - return $result; - } - - /** - * Delete a configuration key in database (with or without language management) - * - * @param string $key Key to delete - * @return bool Deletion result - */ - public static function deleteByName($key) - { - if (!Validate::isConfigName($key)) - return false; - - $result = Db::getInstance()->execute(' - DELETE FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'_lang` - WHERE `'.bqSQL(self::$definition['primary']).'` IN ( - SELECT `'.bqSQL(self::$definition['primary']).'` - FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` - WHERE `name` = "'.pSQL($key).'" - )'); - - $result2 = Db::getInstance()->execute(' - DELETE FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` - WHERE `name` = "'.pSQL($key).'"'); - - self::$_cache[self::$definition['table']] = null; - - return ($result && $result2); - } - - /** - * Delete configuration key from current context. - * - * @param string $key - */ - public static function deleteFromContext($key) - { - if (Shop::getContext() == Shop::CONTEXT_ALL) - return; - - $id_shop = null; - $id_shop_group = Shop::getContextShopGroupID(true); - if (Shop::getContext() == Shop::CONTEXT_SHOP) - $id_shop = Shop::getContextShopID(true); - - $id = Configuration::getIdByName($key, $id_shop_group, $id_shop); - Db::getInstance()->execute(' - DELETE FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` - WHERE `'.bqSQL(self::$definition['primary']).'` = '.(int)$id); - Db::getInstance()->execute(' - DELETE FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'_lang` - WHERE `'.bqSQL(self::$definition['primary']).'` = '.(int)$id); - - self::$_cache[self::$definition['table']] = null; - } - - /** - * Check if configuration var is defined in given context - * - * @param string $key - * @param int $id_lang - * @param int $context - */ - public static function hasContext($key, $id_lang, $context) - { - if (Shop::getContext() == Shop::CONTEXT_ALL) - $id_shop = $id_shop_group = null; - elseif (Shop::getContext() == Shop::CONTEXT_GROUP) - { - $id_shop_group = Shop::getContextShopGroupID(true); - $id_shop = null; - } - else - { - $id_shop_group = Shop::getContextShopGroupID(true); - $id_shop = Shop::getContextShopID(true); - } - - if ($context == Shop::CONTEXT_SHOP && Configuration::hasKey($key, $id_lang, null, $id_shop)) - return true; - elseif ($context == Shop::CONTEXT_GROUP && Configuration::hasKey($key, $id_lang, $id_shop_group)) - return true; - elseif ($context == Shop::CONTEXT_ALL && Configuration::hasKey($key, $id_lang)) - return true; - return false; - } - - public static function isOverridenByCurrentContext($key) - { - if (Configuration::isLangKey($key)) - { - $testContext = false; - foreach (Language::getIDs(false) as $id_lang) - if ((Shop::getContext() == Shop::CONTEXT_SHOP && Configuration::hasContext($key, $id_lang, Shop::CONTEXT_SHOP)) - || (Shop::getContext() == Shop::CONTEXT_GROUP && Configuration::hasContext($key, $id_lang, Shop::CONTEXT_GROUP))) - $testContext = true; - } - else - { - $testContext = ((Shop::getContext() == Shop::CONTEXT_SHOP && Configuration::hasContext($key, null, Shop::CONTEXT_SHOP)) - || (Shop::getContext() == Shop::CONTEXT_GROUP && Configuration::hasContext($key, null, Shop::CONTEXT_GROUP))) ? true : false; - } - - return (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL && $testContext); - } - - /** - * Check if a key was loaded as multi lang - * - * @param string $key - * @return bool - */ - public static function isLangKey($key) - { - return (isset(self::$types[$key]) && self::$types[$key] == 'lang') ? true : false; - } - - /** - * Add SQL restriction on shops for configuration table - * - * @param int $id_shop_group - * @param int $id_shop - * @return string - */ - protected static function sqlRestriction($id_shop_group, $id_shop) - { - if ($id_shop) - return ' AND id_shop = '.(int)$id_shop; - elseif ($id_shop_group) - return ' AND id_shop_group = '.(int)$id_shop_group.' AND (id_shop IS NULL OR id_shop = 0)'; - else - return ' AND (id_shop_group IS NULL OR id_shop_group = 0) AND (id_shop IS NULL OR id_shop = 0)'; - } - - /** - * This method is override to allow TranslatedConfiguration entity - * - * @param $sql_join - * @param $sql_filter - * @param $sql_sort - * @param $sql_limit - * @return array - */ - public function getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit) - { - $query = ' - SELECT DISTINCT main.`'.bqSQL($this->def['primary']).'` - FROM `'._DB_PREFIX_.bqSQL($this->def['table']).'` main - '.$sql_join.' - WHERE id_configuration NOT IN ( - SELECT id_configuration - FROM '._DB_PREFIX_.bqSQL($this->def['table']).'_lang - ) '.$sql_filter.' - '.($sql_sort != '' ? $sql_sort : '').' - '.($sql_limit != '' ? $sql_limit : ''); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + public $id; + + /** @var string Key */ + public $name; + + public $id_shop_group; + public $id_shop; + + /** @var string Value */ + public $value; + + /** @var string Object creation date */ + public $date_add; + + /** @var string Object last modification date */ + public $date_upd; + + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'configuration', + 'primary' => 'id_configuration', + 'multilang' => true, + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isConfigName', 'required' => true, 'size' => 254), + 'id_shop_group' => array('type' => self::TYPE_NOTHING, 'validate' => 'isUnsignedId'), + 'id_shop' => array('type' => self::TYPE_NOTHING, 'validate' => 'isUnsignedId'), + 'value' => array('type' => self::TYPE_STRING), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); + + /** @var array Configuration cache */ + protected static $_cache = array(); + + /** @var array Vars types */ + protected static $types = array(); + + protected $webserviceParameters = array( + 'fields' => array( + 'value' => array(), + ) + ); + + /** + * @see ObjectModel::getFieldsLang() + * @return bool|array Multilingual fields + */ + public function getFieldsLang() + { + if (!is_array($this->value)) { + return true; + } + return parent::getFieldsLang(); + } + + /** + * Return ID a configuration key + * + * @param string $key + * @param int $id_shop_group + * @param int $id_shop + * @return int Configuration key ID + */ + public static function getIdByName($key, $id_shop_group = null, $id_shop = null) + { + if ($id_shop === null) { + $id_shop = Shop::getContextShopID(true); + } + if ($id_shop_group === null) { + $id_shop_group = Shop::getContextShopGroupID(true); + } + + $sql = 'SELECT `'.bqSQL(self::$definition['primary']).'` + FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` + WHERE name = \''.pSQL($key).'\' + '.Configuration::sqlRestriction($id_shop_group, $id_shop); + return (int)Db::getInstance()->getValue($sql); + } + + public static function configurationIsLoaded() + { + static $loaded = null; + + if ($loaded !== null) { + return $loaded; + } + + if (isset(self::$_cache) && isset(self::$_cache[self::$definition['table']]) && count(self::$_cache[self::$definition['table']])) { + $loaded = true; + return $loaded; + } + + return false; + } + + /** + * WARNING: For testing only. Do NOT rely on this method, it may be removed at any time. + * @todo Delegate static calls from Configuration to an instance + * of a class to be created. + */ + public static function clearConfigurationCacheForTesting() + { + self::$_cache = array(); + } + + /** + * Load all configuration data + */ + public static function loadConfiguration() + { + self::$_cache[self::$definition['table']] = array(); + + $sql = 'SELECT c.`name`, cl.`id_lang`, IF(cl.`id_lang` IS NULL, c.`value`, cl.`value`) AS value, c.id_shop_group, c.id_shop + FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` c + LEFT JOIN `'._DB_PREFIX_.bqSQL(self::$definition['table']).'_lang` cl ON (c.`'.bqSQL(self::$definition['primary']).'` = cl.`'.bqSQL(self::$definition['primary']).'`)'; + $db = Db::getInstance(); + $result = $db->executeS($sql, false); + while ($row = $db->nextRow($result)) { + $lang = ($row['id_lang']) ? $row['id_lang'] : 0; + self::$types[$row['name']] = ($lang) ? 'lang' : 'normal'; + if (!isset(self::$_cache[self::$definition['table']][$lang])) { + self::$_cache[self::$definition['table']][$lang] = array( + 'global' => array(), + 'group' => array(), + 'shop' => array(), + ); + } + + if ($row['id_shop']) { + self::$_cache[self::$definition['table']][$lang]['shop'][$row['id_shop']][$row['name']] = $row['value']; + } elseif ($row['id_shop_group']) { + self::$_cache[self::$definition['table']][$lang]['group'][$row['id_shop_group']][$row['name']] = $row['value']; + } else { + self::$_cache[self::$definition['table']][$lang]['global'][$row['name']] = $row['value']; + } + } + } + + /** + * Get a single configuration value (in one language only) + * + * @param string $key Key wanted + * @param int $id_lang Language ID + * @return string Value + */ + public static function get($key, $id_lang = null, $id_shop_group = null, $id_shop = null) + { + if (defined('_PS_DO_NOT_LOAD_CONFIGURATION_') && _PS_DO_NOT_LOAD_CONFIGURATION_) { + return false; + } + + // If conf if not initialized, try manual query + if (!isset(self::$_cache[self::$definition['table']])) { + Configuration::loadConfiguration(); + if (!self::$_cache[self::$definition['table']]) { + return Db::getInstance()->getValue('SELECT `value` FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` WHERE `name` = "'.pSQL($key).'"'); + } + } + $id_lang = (int)$id_lang; + if ($id_shop === null || !Shop::isFeatureActive()) { + $id_shop = Shop::getContextShopID(true); + } + if ($id_shop_group === null || !Shop::isFeatureActive()) { + $id_shop_group = Shop::getContextShopGroupID(true); + } + + if (!isset(self::$_cache[self::$definition['table']][$id_lang])) { + $id_lang = 0; + } + + if ($id_shop && Configuration::hasKey($key, $id_lang, null, $id_shop)) { + return self::$_cache[self::$definition['table']][$id_lang]['shop'][$id_shop][$key]; + } elseif ($id_shop_group && Configuration::hasKey($key, $id_lang, $id_shop_group)) { + return self::$_cache[self::$definition['table']][$id_lang]['group'][$id_shop_group][$key]; + } elseif (Configuration::hasKey($key, $id_lang)) { + return self::$_cache[self::$definition['table']][$id_lang]['global'][$key]; + } + return false; + } + + public static function getGlobalValue($key, $id_lang = null) + { + return Configuration::get($key, $id_lang, 0, 0); + } + + /** + * Get a single configuration value (in multiple languages) + * + * @param string $key Key wanted + * @param int $id_shop_group + * @param int $id_shop + * @return array Values in multiple languages + */ + public static function getInt($key, $id_shop_group = null, $id_shop = null) + { + $results_array = array(); + foreach (Language::getIDs() as $id_lang) { + $results_array[$id_lang] = Configuration::get($key, $id_lang, $id_shop_group, $id_shop); + } + + return $results_array; + } + + /** + * Get a single configuration value for all shops + * + * @param string $key Key wanted + * @param int $id_lang + * @return array Values for all shops + */ + public static function getMultiShopValues($key, $id_lang = null) + { + $shops = Shop::getShops(false, null, true); + $resultsArray = array(); + foreach ($shops as $id_shop) { + $resultsArray[$id_shop] = Configuration::get($key, $id_lang, null, $id_shop); + } + return $resultsArray; + } + + + /** + * Get several configuration values (in one language only) + * + * @throws PrestaShopException + * @param array $keys Keys wanted + * @param int $id_lang Language ID + * @param int $id_shop_group + * @param int $id_shop + * @return array Values + */ + public static function getMultiple($keys, $id_lang = null, $id_shop_group = null, $id_shop = null) + { + if (!is_array($keys)) { + throw new PrestaShopException('keys var is not an array'); + } + + $id_lang = (int)$id_lang; + if ($id_shop === null) { + $id_shop = Shop::getContextShopID(true); + } + if ($id_shop_group === null) { + $id_shop_group = Shop::getContextShopGroupID(true); + } + + $results = array(); + foreach ($keys as $key) { + $results[$key] = Configuration::get($key, $id_lang, $id_shop_group, $id_shop); + } + return $results; + } + + /** + * Check if key exists in configuration + * + * @param string $key + * @param int $id_lang + * @param int $id_shop_group + * @param int $id_shop + * @return bool + */ + public static function hasKey($key, $id_lang = null, $id_shop_group = null, $id_shop = null) + { + if (!is_int($key) && !is_string($key)) { + return false; + } + + $id_lang = (int)$id_lang; + + if ($id_shop) { + return isset(self::$_cache[self::$definition['table']][$id_lang]['shop'][$id_shop]) + && (isset(self::$_cache[self::$definition['table']][$id_lang]['shop'][$id_shop][$key]) + || array_key_exists($key, self::$_cache[self::$definition['table']][$id_lang]['shop'][$id_shop])); + } elseif ($id_shop_group) { + return isset(self::$_cache[self::$definition['table']][$id_lang]['group'][$id_shop_group]) + && (isset(self::$_cache[self::$definition['table']][$id_lang]['group'][$id_shop_group][$key]) + || array_key_exists($key, self::$_cache[self::$definition['table']][$id_lang]['group'][$id_shop_group])); + } + + return isset(self::$_cache[self::$definition['table']][$id_lang]['global']) + && (isset(self::$_cache[self::$definition['table']][$id_lang]['global'][$key]) + || array_key_exists($key, self::$_cache[self::$definition['table']][$id_lang]['global'])); + } + + /** + * Set TEMPORARY a single configuration value (in one language only) + * + * @param string $key Key wanted + * @param mixed $values $values is an array if the configuration is multilingual, a single string else. + * @param int $id_shop_group + * @param int $id_shop + */ + public static function set($key, $values, $id_shop_group = null, $id_shop = null) + { + if (!Validate::isConfigName($key)) { + die(sprintf(Tools::displayError('[%s] is not a valid configuration key'), $key)); + } + + if ($id_shop === null) { + $id_shop = Shop::getContextShopID(true); + } + if ($id_shop_group === null) { + $id_shop_group = Shop::getContextShopGroupID(true); + } + + if (!is_array($values)) { + $values = array($values); + } + + foreach ($values as $lang => $value) { + if ($id_shop) { + self::$_cache[self::$definition['table']][$lang]['shop'][$id_shop][$key] = $value; + } elseif ($id_shop_group) { + self::$_cache[self::$definition['table']][$lang]['group'][$id_shop_group][$key] = $value; + } else { + self::$_cache[self::$definition['table']][$lang]['global'][$key] = $value; + } + } + } + + /** + * Update configuration key for global context only + * + * @param string $key + * @param mixed $values + * @param bool $html + * @return bool + */ + public static function updateGlobalValue($key, $values, $html = false) + { + return Configuration::updateValue($key, $values, $html, 0, 0); + } + + /** + * Update configuration key and value into database (automatically insert if key does not exist) + * + * Values are inserted/updated directly using SQL, because using (Configuration) ObjectModel + * may not insert values correctly (for example, HTML is escaped, when it should not be). + * @TODO Fix saving HTML values in Configuration model + * + * @param string $key Key + * @param mixed $values $values is an array if the configuration is multilingual, a single string else. + * @param bool $html Specify if html is authorized in value + * @param int $id_shop_group + * @param int $id_shop + * @return bool Update result + */ + public static function updateValue($key, $values, $html = false, $id_shop_group = null, $id_shop = null) + { + if (!Validate::isConfigName($key)) { + die(sprintf(Tools::displayError('[%s] is not a valid configuration key'), $key)); + } + + if ($id_shop === null || !Shop::isFeatureActive()) { + $id_shop = Shop::getContextShopID(true); + } + if ($id_shop_group === null || !Shop::isFeatureActive()) { + $id_shop_group = Shop::getContextShopGroupID(true); + } + + if (!is_array($values)) { + $values = array($values); + } + + if ($html) { + foreach ($values as &$value) { + $value = Tools::purifyHTML($value); + } + unset($value); + } + + $result = true; + foreach ($values as $lang => $value) { + $stored_value = Configuration::get($key, $lang, $id_shop_group, $id_shop); + // if there isn't a $stored_value, we must insert $value + if ((!is_numeric($value) && $value === $stored_value) || (is_numeric($value) && $value == $stored_value && Configuration::hasKey($key, $lang))) { + continue; + } + + // If key already exists, update value + if (Configuration::hasKey($key, $lang, $id_shop_group, $id_shop)) { + if (!$lang) { + // Update config not linked to lang + $result &= Db::getInstance()->update(self::$definition['table'], array( + 'value' => pSQL($value, $html), + 'date_upd' => date('Y-m-d H:i:s'), + ), '`name` = \''.pSQL($key).'\''.Configuration::sqlRestriction($id_shop_group, $id_shop), 1, true); + } else { + // Update multi lang + $sql = 'UPDATE `'._DB_PREFIX_.bqSQL(self::$definition['table']).'_lang` cl + SET cl.value = \''.pSQL($value, $html).'\', + cl.date_upd = NOW() + WHERE cl.id_lang = '.(int)$lang.' + AND cl.`'.bqSQL(self::$definition['primary']).'` = ( + SELECT c.`'.bqSQL(self::$definition['primary']).'` + FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` c + WHERE c.name = \''.pSQL($key).'\'' + .Configuration::sqlRestriction($id_shop_group, $id_shop) + .')'; + $result &= Db::getInstance()->execute($sql); + } + } + // If key does not exists, create it + else { + if (!$configID = Configuration::getIdByName($key, $id_shop_group, $id_shop)) { + $now = date('Y-m-d H:i:s'); + $data = array( + 'id_shop_group' => $id_shop_group ? (int)$id_shop_group : null, + 'id_shop' => $id_shop ? (int)$id_shop : null, + 'name' => pSQL($key), + 'value' => $lang ? null : pSQL($value, $html), + 'date_add' => $now, + 'date_upd' => $now, + ); + $result &= Db::getInstance()->insert('configuration', $data, true); + $configID = Db::getInstance()->Insert_ID(); + } + + if ($lang) { + $result &= Db::getInstance()->insert(self::$definition['table'].'_lang', array( + self::$definition['primary'] => $configID, + 'id_lang' => (int)$lang, + 'value' => pSQL($value, $html), + 'date_upd' => date('Y-m-d H:i:s'), + )); + } + } + } + + Configuration::set($key, $values, $id_shop_group, $id_shop); + + return $result; + } + + /** + * Delete a configuration key in database (with or without language management) + * + * @param string $key Key to delete + * @return bool Deletion result + */ + public static function deleteByName($key) + { + if (!Validate::isConfigName($key)) { + return false; + } + + $result = Db::getInstance()->execute(' + DELETE FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'_lang` + WHERE `'.bqSQL(self::$definition['primary']).'` IN ( + SELECT `'.bqSQL(self::$definition['primary']).'` + FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` + WHERE `name` = "'.pSQL($key).'" + )'); + + $result2 = Db::getInstance()->execute(' + DELETE FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` + WHERE `name` = "'.pSQL($key).'"'); + + self::$_cache[self::$definition['table']] = null; + + return ($result && $result2); + } + + /** + * Delete configuration key from current context. + * + * @param string $key + */ + public static function deleteFromContext($key) + { + if (Shop::getContext() == Shop::CONTEXT_ALL) { + return; + } + + $id_shop = null; + $id_shop_group = Shop::getContextShopGroupID(true); + if (Shop::getContext() == Shop::CONTEXT_SHOP) { + $id_shop = Shop::getContextShopID(true); + } + + $id = Configuration::getIdByName($key, $id_shop_group, $id_shop); + Db::getInstance()->execute(' + DELETE FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'` + WHERE `'.bqSQL(self::$definition['primary']).'` = '.(int)$id); + Db::getInstance()->execute(' + DELETE FROM `'._DB_PREFIX_.bqSQL(self::$definition['table']).'_lang` + WHERE `'.bqSQL(self::$definition['primary']).'` = '.(int)$id); + + self::$_cache[self::$definition['table']] = null; + } + + /** + * Check if configuration var is defined in given context + * + * @param string $key + * @param int $id_lang + * @param int $context + */ + public static function hasContext($key, $id_lang, $context) + { + if (Shop::getContext() == Shop::CONTEXT_ALL) { + $id_shop = $id_shop_group = null; + } elseif (Shop::getContext() == Shop::CONTEXT_GROUP) { + $id_shop_group = Shop::getContextShopGroupID(true); + $id_shop = null; + } else { + $id_shop_group = Shop::getContextShopGroupID(true); + $id_shop = Shop::getContextShopID(true); + } + + if ($context == Shop::CONTEXT_SHOP && Configuration::hasKey($key, $id_lang, null, $id_shop)) { + return true; + } elseif ($context == Shop::CONTEXT_GROUP && Configuration::hasKey($key, $id_lang, $id_shop_group)) { + return true; + } elseif ($context == Shop::CONTEXT_ALL && Configuration::hasKey($key, $id_lang)) { + return true; + } + return false; + } + + public static function isOverridenByCurrentContext($key) + { + if (Configuration::isLangKey($key)) { + $testContext = false; + foreach (Language::getIDs(false) as $id_lang) { + if ((Shop::getContext() == Shop::CONTEXT_SHOP && Configuration::hasContext($key, $id_lang, Shop::CONTEXT_SHOP)) + || (Shop::getContext() == Shop::CONTEXT_GROUP && Configuration::hasContext($key, $id_lang, Shop::CONTEXT_GROUP))) { + $testContext = true; + } + } + } else { + $testContext = ((Shop::getContext() == Shop::CONTEXT_SHOP && Configuration::hasContext($key, null, Shop::CONTEXT_SHOP)) + || (Shop::getContext() == Shop::CONTEXT_GROUP && Configuration::hasContext($key, null, Shop::CONTEXT_GROUP))) ? true : false; + } + + return (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL && $testContext); + } + + /** + * Check if a key was loaded as multi lang + * + * @param string $key + * @return bool + */ + public static function isLangKey($key) + { + return (isset(self::$types[$key]) && self::$types[$key] == 'lang') ? true : false; + } + + /** + * Add SQL restriction on shops for configuration table + * + * @param int $id_shop_group + * @param int $id_shop + * @return string + */ + protected static function sqlRestriction($id_shop_group, $id_shop) + { + if ($id_shop) { + return ' AND id_shop = '.(int)$id_shop; + } elseif ($id_shop_group) { + return ' AND id_shop_group = '.(int)$id_shop_group.' AND (id_shop IS NULL OR id_shop = 0)'; + } else { + return ' AND (id_shop_group IS NULL OR id_shop_group = 0) AND (id_shop IS NULL OR id_shop = 0)'; + } + } + + /** + * This method is override to allow TranslatedConfiguration entity + * + * @param $sql_join + * @param $sql_filter + * @param $sql_sort + * @param $sql_limit + * @return array + */ + public function getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit) + { + $query = ' + SELECT DISTINCT main.`'.bqSQL($this->def['primary']).'` + FROM `'._DB_PREFIX_.bqSQL($this->def['table']).'` main + '.$sql_join.' + WHERE id_configuration NOT IN ( + SELECT id_configuration + FROM '._DB_PREFIX_.bqSQL($this->def['table']).'_lang + ) '.$sql_filter.' + '.($sql_sort != '' ? $sql_sort : '').' + '.($sql_limit != '' ? $sql_limit : ''); + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } } diff --git a/classes/ConfigurationKPI.php b/classes/ConfigurationKPI.php index 68807bd9..cbc39c84 100644 --- a/classes/ConfigurationKPI.php +++ b/classes/ConfigurationKPI.php @@ -26,145 +26,145 @@ class ConfigurationKPICore extends Configuration { - public static $definition_backup; + public static $definition_backup; - public static function setKpiDefinition() - { - ConfigurationKPI::$definition_backup = Configuration::$definition; - Configuration::$definition['table'] = 'configuration_kpi'; - Configuration::$definition['primary'] = 'id_configuration_kpi'; - } + public static function setKpiDefinition() + { + ConfigurationKPI::$definition_backup = Configuration::$definition; + Configuration::$definition['table'] = 'configuration_kpi'; + Configuration::$definition['primary'] = 'id_configuration_kpi'; + } - public static function unsetKpiDefinition() - { - Configuration::$definition = ConfigurationKPI::$definition_backup; - } + public static function unsetKpiDefinition() + { + Configuration::$definition = ConfigurationKPI::$definition_backup; + } - public static function getIdByName($key, $id_shop_group = null, $id_shop = null) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::getIdByName($key, $id_shop_group, $id_shop); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function getIdByName($key, $id_shop_group = null, $id_shop = null) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::getIdByName($key, $id_shop_group, $id_shop); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function loadConfiguration() - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::loadConfiguration(); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function loadConfiguration() + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::loadConfiguration(); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function get($key, $id_lang = null, $id_shop_group = null, $id_shop = null) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::get($key, $id_lang, $id_shop_group, $id_shop); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function get($key, $id_lang = null, $id_shop_group = null, $id_shop = null) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::get($key, $id_lang, $id_shop_group, $id_shop); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function getGlobalValue($key, $id_lang = null) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::getGlobalValue($key, $id_lang); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function getGlobalValue($key, $id_lang = null) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::getGlobalValue($key, $id_lang); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function getInt($key, $id_shop_group = null, $id_shop = null) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::getInt($key, $id_shop_group, $id_shop); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function getInt($key, $id_shop_group = null, $id_shop = null) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::getInt($key, $id_shop_group, $id_shop); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function getMultiple($keys, $id_lang = null, $id_shop_group = null, $id_shop = null) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::getMultiple($keys, $id_lang, $id_shop_group, $id_shop); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function getMultiple($keys, $id_lang = null, $id_shop_group = null, $id_shop = null) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::getMultiple($keys, $id_lang, $id_shop_group, $id_shop); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function hasKey($key, $id_lang = null, $id_shop_group = null, $id_shop = null) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::hasKey($key, $id_lang, $id_shop_group, $id_shop); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function hasKey($key, $id_lang = null, $id_shop_group = null, $id_shop = null) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::hasKey($key, $id_lang, $id_shop_group, $id_shop); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function set($key, $values, $id_shop_group = null, $id_shop = null) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::set($key, $values, $id_shop_group, $id_shop); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function set($key, $values, $id_shop_group = null, $id_shop = null) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::set($key, $values, $id_shop_group, $id_shop); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function updateGlobalValue($key, $values, $html = false) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::updateGlobalValue($key, $values, $html); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function updateGlobalValue($key, $values, $html = false) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::updateGlobalValue($key, $values, $html); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function updateValue($key, $values, $html = false, $id_shop_group = null, $id_shop = null) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::updateValue($key, $values, $html, $id_shop_group, $id_shop); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function updateValue($key, $values, $html = false, $id_shop_group = null, $id_shop = null) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::updateValue($key, $values, $html, $id_shop_group, $id_shop); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function deleteByName($key) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::deleteByName($key); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function deleteByName($key) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::deleteByName($key); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function deleteFromContext($key) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::deleteFromContext($key); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function deleteFromContext($key) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::deleteFromContext($key); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function hasContext($key, $id_lang, $context) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::hasContext($key, $id_lang, $context); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function hasContext($key, $id_lang, $context) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::hasContext($key, $id_lang, $context); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function isOverridenByCurrentContext($key) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::isOverridenByCurrentContext($key); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function isOverridenByCurrentContext($key) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::isOverridenByCurrentContext($key); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - public static function isLangKey($key) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::isLangKey($key); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } + public static function isLangKey($key) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::isLangKey($key); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } - protected static function sqlRestriction($id_shop_group, $id_shop) - { - ConfigurationKPI::setKpiDefinition(); - $r = parent::sqlRestriction($id_shop_group, $id_shop); - ConfigurationKPI::unsetKpiDefinition(); - return $r; - } -} \ No newline at end of file + protected static function sqlRestriction($id_shop_group, $id_shop) + { + ConfigurationKPI::setKpiDefinition(); + $r = parent::sqlRestriction($id_shop_group, $id_shop); + ConfigurationKPI::unsetKpiDefinition(); + return $r; + } +} diff --git a/classes/ConfigurationTest.php b/classes/ConfigurationTest.php index b1f627a5..d174f304 100644 --- a/classes/ConfigurationTest.php +++ b/classes/ConfigurationTest.php @@ -26,350 +26,360 @@ class ConfigurationTestCore { + public static $test_files = array( + '/cache/smarty/compile/index.php', + '/classes/log/index.php', + '/classes/cache/index.php', + '/config/index.php', + '/tools/tar/Archive_Tar.php', + '/tools/pear/PEAR.php', + '/controllers/admin/AdminLoginController.php', + '/css/index.php', + '/download/index.php', + '/img/404.gif', + '/js/tools.js', + '/js/jquery/plugins/fancybox/jquery.fancybox.js', + '/localization/fr.xml', + '/mails/index.php', + '/modules/index.php', + '/override/controllers/front/index.php', + '/pdf/order-return.tpl', + '/themes/default-bootstrap/css/global.css', + '/translations/export/index.php', + '/webservice/dispatcher.php', + '/upload/index.php', + '/index.php' + ); - public static $test_files = array( - '/cache/smarty/compile/index.php', - '/classes/log/index.php', - '/classes/cache/index.php', - '/config/index.php', - '/tools/tar/Archive_Tar.php', - '/tools/pear/PEAR.php', - '/controllers/admin/AdminLoginController.php', - '/css/index.php', - '/download/index.php', - '/img/404.gif', - '/js/tools.js', - '/js/jquery/plugins/fancybox/jquery.fancybox.js', - '/localization/fr.xml', - '/mails/index.php', - '/modules/index.php', - '/override/controllers/front/index.php', - '/pdf/order-return.tpl', - '/themes/default-bootstrap/css/global.css', - '/translations/export/index.php', - '/webservice/dispatcher.php', - '/upload/index.php', - '/index.php' - ); + /** + * getDefaultTests return an array of tests to executes. + * key are method name, value are parameters (false for no parameter) + * all path are _PS_ROOT_DIR_ related + * + * @return array + */ + public static function getDefaultTests() + { + $tests = array( + 'upload' => false, + 'cache_dir' => 'cache', + 'log_dir' => 'log', + 'img_dir' => 'img', + 'module_dir' => 'modules', + 'theme_lang_dir' => 'themes/'._THEME_NAME_.'/lang/', + 'theme_pdf_lang_dir' => 'themes/'._THEME_NAME_.'/pdf/lang/', + 'theme_cache_dir' => 'themes/'._THEME_NAME_.'/cache/', + 'translations_dir' => 'translations', + 'customizable_products_dir' => 'upload', + 'virtual_products_dir' => 'download' + ); - /** - * getDefaultTests return an array of tests to executes. - * key are method name, value are parameters (false for no parameter) - * all path are _PS_ROOT_DIR_ related - * - * @return array - */ - public static function getDefaultTests() - { - $tests = array( - 'upload' => false, - 'cache_dir' => 'cache', - 'log_dir' => 'log', - 'img_dir' => 'img', - 'module_dir' => 'modules', - 'theme_lang_dir' => 'themes/'._THEME_NAME_.'/lang/', - 'theme_pdf_lang_dir' => 'themes/'._THEME_NAME_.'/pdf/lang/', - 'theme_cache_dir' => 'themes/'._THEME_NAME_.'/cache/', - 'translations_dir' => 'translations', - 'customizable_products_dir' => 'upload', - 'virtual_products_dir' => 'download' - ); + if (!defined('_PS_HOST_MODE_')) { + $tests = array_merge($tests, array( + 'system' => array( + 'fopen', 'fclose', 'fread', 'fwrite', + 'rename', 'file_exists', 'unlink', 'rmdir', 'mkdir', + 'getcwd', 'chdir', 'chmod' + ), + 'phpversion' => false, + 'gd' => false, + 'mysql_support' => false, + 'config_dir' => 'config', + 'files' => false, + 'mails_dir' => 'mails', + )); + } - if (!defined('_PS_HOST_MODE_')) - $tests = array_merge($tests, array( - 'system' => array( - 'fopen', 'fclose', 'fread', 'fwrite', - 'rename', 'file_exists', 'unlink', 'rmdir', 'mkdir', - 'getcwd', 'chdir', 'chmod' - ), - 'phpversion' => false, - 'gd' => false, - 'mysql_support' => false, - 'config_dir' => 'config', - 'files' => false, - 'mails_dir' => 'mails', - )); + return $tests; + } - return $tests; - } + /** + * getDefaultTestsOp return an array of tests to executes. + * key are method name, value are parameters (false for no parameter) + * + * @return array + */ + public static function getDefaultTestsOp() + { + return array( + 'new_phpversion' => false, + 'fopen' => false, + 'register_globals' => false, + 'gz' => false, + 'mcrypt' => false, + 'mbstring' => false, + 'magicquotes' => false, + 'dom' => false, + 'pdo_mysql' => false, + ); + } - /** - * getDefaultTestsOp return an array of tests to executes. - * key are method name, value are parameters (false for no parameter) - * - * @return array - */ - public static function getDefaultTestsOp() - { - return array( - 'new_phpversion' => false, - 'fopen' => false, - 'register_globals' => false, - 'gz' => false, - 'mcrypt' => false, - 'mbstring' => false, - 'magicquotes' => false, - 'dom' => false, - 'pdo_mysql' => false, - ); - } + /** + * run all test defined in $tests + * + * @param array $tests + * @return array results of tests + */ + public static function check($tests) + { + $res = array(); + foreach ($tests as $key => $test) { + $res[$key] = ConfigurationTest::run($key, $test); + } + return $res; + } - /** - * run all test defined in $tests - * - * @param array $tests - * @return array results of tests - */ - public static function check($tests) - { - $res = array(); - foreach ($tests as $key => $test) - $res[$key] = ConfigurationTest::run($key, $test); - return $res; - } + public static function run($ptr, $arg = 0) + { + if (call_user_func(array('ConfigurationTest', 'test_'.$ptr), $arg)) { + return 'ok'; + } + return 'fail'; + } - public static function run($ptr, $arg = 0) - { - if (call_user_func(array('ConfigurationTest', 'test_'.$ptr), $arg)) - return 'ok'; - return 'fail'; - } + public static function test_phpversion() + { + return version_compare(substr(phpversion(), 0, 5), '5.2.0', '>='); + } - public static function test_phpversion() - { - return version_compare(substr(phpversion(), 0, 5), '5.2.0', '>='); - } + public static function test_new_phpversion() + { + return version_compare(substr(phpversion(), 0, 5), '5.4.0', '>='); + } - public static function test_new_phpversion() - { - return version_compare(substr(phpversion(), 0, 5), '5.4.0', '>='); - } + public static function test_mysql_support() + { + return extension_loaded('mysql') || extension_loaded('mysqli') || extension_loaded('pdo_mysql'); + } - public static function test_mysql_support() - { - return extension_loaded('mysql') || extension_loaded('mysqli') || extension_loaded('pdo_mysql'); - } + public static function test_pdo_mysql() + { + return extension_loaded('pdo_mysql'); + } - public static function test_pdo_mysql() - { - return extension_loaded('pdo_mysql'); - } + public static function test_magicquotes() + { + return !get_magic_quotes_gpc(); + } - public static function test_magicquotes() - { - return !get_magic_quotes_gpc(); - } + public static function test_upload() + { + return ini_get('file_uploads'); + } - public static function test_upload() - { - return ini_get('file_uploads'); - } + public static function test_fopen() + { + return ini_get('allow_url_fopen'); + } - public static function test_fopen() - { - return ini_get('allow_url_fopen'); - } + public static function test_system($funcs) + { + foreach ($funcs as $func) { + if (!function_exists($func)) { + return false; + } + } + return true; + } - public static function test_system($funcs) - { - foreach ($funcs as $func) - if (!function_exists($func)) - return false; - return true; - } + public static function test_gd() + { + return function_exists('imagecreatetruecolor'); + } - public static function test_gd() - { - return function_exists('imagecreatetruecolor'); - } + public static function test_register_globals() + { + return !ini_get('register_globals'); + } - public static function test_register_globals() - { - return !ini_get('register_globals'); - } + public static function test_gz() + { + if (function_exists('gzencode')) { + return @gzencode('dd') !== false; + } + return false; + } - public static function test_gz() - { - if (function_exists('gzencode')) - return @gzencode('dd') !== false; - return false; - } + public static function test_dir($relative_dir, $recursive = false, &$full_report = null) + { + $dir = rtrim(_PS_ROOT_DIR_, '\\/').DIRECTORY_SEPARATOR.trim($relative_dir, '\\/'); + if (!file_exists($dir) || !$dh = @opendir($dir)) { + $full_report = sprintf('Directory %s does not exist or is not writable', $dir); // sprintf for future translation + return false; + } + $dummy = rtrim($dir, '\\/').DIRECTORY_SEPARATOR.uniqid(); + if (@file_put_contents($dummy, 'test')) { + @unlink($dummy); + if (!$recursive) { + closedir($dh); + return true; + } + } elseif (!is_writable($dir)) { + $full_report = sprintf('Directory %s is not writable', $dir); // sprintf for future translation + return false; + } - public static function test_dir($relative_dir, $recursive = false, &$full_report = null) - { - $dir = rtrim(_PS_ROOT_DIR_, '\\/').DIRECTORY_SEPARATOR.trim($relative_dir, '\\/'); - if (!file_exists($dir) || !$dh = @opendir($dir)) - { - $full_report = sprintf('Directory %s does not exist or is not writable', $dir); // sprintf for future translation - return false; - } - $dummy = rtrim($dir, '\\/').DIRECTORY_SEPARATOR.uniqid(); - if (@file_put_contents($dummy, 'test')) - { - @unlink($dummy); - if (!$recursive) - { - closedir($dh); - return true; - } - } - elseif (!is_writable($dir)) - { - $full_report = sprintf('Directory %s is not writable', $dir); // sprintf for future translation - return false; - } + if ($recursive) { + while (($file = readdir($dh)) !== false) { + if (is_dir($dir.DIRECTORY_SEPARATOR.$file) && $file != '.' && $file != '..' && $file != '.svn') { + if (!ConfigurationTest::test_dir($relative_dir.DIRECTORY_SEPARATOR.$file, $recursive, $full_report)) { + return false; + } + } + } + } - if ($recursive) - while (($file = readdir($dh)) !== false) - if (is_dir($dir.DIRECTORY_SEPARATOR.$file) && $file != '.' && $file != '..' && $file != '.svn') - if (!ConfigurationTest::test_dir($relative_dir.DIRECTORY_SEPARATOR.$file, $recursive, $full_report)) - return false; + closedir($dh); + return true; + } - closedir($dh); - return true; - } + public static function test_file($file_relative) + { + $file = _PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$file_relative; + return (file_exists($file) && is_writable($file)); + } - public static function test_file($file_relative) - { - $file = _PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$file_relative; - return (file_exists($file) && is_writable($file)); - } + public static function test_config_dir($dir) + { + return ConfigurationTest::test_dir($dir); + } - public static function test_config_dir($dir) - { - return ConfigurationTest::test_dir($dir); - } + public static function test_sitemap($dir) + { + return ConfigurationTest::test_file($dir); + } - public static function test_sitemap($dir) - { - return ConfigurationTest::test_file($dir); - } + public static function test_root_dir($dir) + { + return ConfigurationTest::test_dir($dir); + } - public static function test_root_dir($dir) - { - return ConfigurationTest::test_dir($dir); - } + public static function test_log_dir($dir) + { + return ConfigurationTest::test_dir($dir); + } - public static function test_log_dir($dir) - { - return ConfigurationTest::test_dir($dir); - } + public static function test_admin_dir($dir) + { + return ConfigurationTest::test_dir($dir); + } - public static function test_admin_dir($dir) - { - return ConfigurationTest::test_dir($dir); - } + public static function test_img_dir($dir) + { + return ConfigurationTest::test_dir($dir, true); + } - public static function test_img_dir($dir) - { - return ConfigurationTest::test_dir($dir, true); - } + public static function test_module_dir($dir) + { + return ConfigurationTest::test_dir($dir, true); + } - public static function test_module_dir($dir) - { - return ConfigurationTest::test_dir($dir, true); - } + public static function test_cache_dir($dir) + { + return ConfigurationTest::test_dir($dir, true); + } - public static function test_cache_dir($dir) - { - return ConfigurationTest::test_dir($dir, true); - } + public static function test_tools_v2_dir($dir) + { + return ConfigurationTest::test_dir($dir); + } - public static function test_tools_v2_dir($dir) - { - return ConfigurationTest::test_dir($dir); - } + public static function test_cache_v2_dir($dir) + { + return ConfigurationTest::test_dir($dir); + } - public static function test_cache_v2_dir($dir) - { - return ConfigurationTest::test_dir($dir); - } + public static function test_download_dir($dir) + { + return ConfigurationTest::test_dir($dir); + } - public static function test_download_dir($dir) - { - return ConfigurationTest::test_dir($dir); - } + public static function test_mails_dir($dir) + { + return ConfigurationTest::test_dir($dir, true); + } - public static function test_mails_dir($dir) - { - return ConfigurationTest::test_dir($dir, true); - } + public static function test_translations_dir($dir) + { + return ConfigurationTest::test_dir($dir, true); + } - public static function test_translations_dir($dir) - { - return ConfigurationTest::test_dir($dir, true); - } + public static function test_theme_lang_dir($dir) + { + $absoluteDir = rtrim(_PS_ROOT_DIR_, '\\/').DIRECTORY_SEPARATOR.trim($dir, '\\/'); + if (!file_exists($absoluteDir)) { + return true; + } + return ConfigurationTest::test_dir($dir, true); + } - public static function test_theme_lang_dir($dir) - { - $absoluteDir = rtrim(_PS_ROOT_DIR_, '\\/').DIRECTORY_SEPARATOR.trim($dir, '\\/'); - if (!file_exists($absoluteDir)) - return true; - return ConfigurationTest::test_dir($dir, true); - } + public static function test_theme_pdf_lang_dir($dir) + { + $absoluteDir = rtrim(_PS_ROOT_DIR_, '\\/').DIRECTORY_SEPARATOR.trim($dir, '\\/'); + if (!file_exists($absoluteDir)) { + return true; + } + return ConfigurationTest::test_dir($dir, true); + } - public static function test_theme_pdf_lang_dir($dir) - { - $absoluteDir = rtrim(_PS_ROOT_DIR_, '\\/').DIRECTORY_SEPARATOR.trim($dir, '\\/'); - if (!file_exists($absoluteDir)) - return true; - return ConfigurationTest::test_dir($dir, true); - } + public static function test_theme_cache_dir($dir) + { + $absoluteDir = rtrim(_PS_ROOT_DIR_, '\\/').DIRECTORY_SEPARATOR.trim($dir, '\\/'); + if (!file_exists($absoluteDir)) { + return true; + } + return ConfigurationTest::test_dir($dir, true); + } - public static function test_theme_cache_dir($dir) - { - $absoluteDir = rtrim(_PS_ROOT_DIR_, '\\/').DIRECTORY_SEPARATOR.trim($dir, '\\/'); - if (!file_exists($absoluteDir)) - return true; - return ConfigurationTest::test_dir($dir, true); - } + public static function test_customizable_products_dir($dir) + { + return ConfigurationTest::test_dir($dir); + } - public static function test_customizable_products_dir($dir) - { - return ConfigurationTest::test_dir($dir); - } + public static function test_virtual_products_dir($dir) + { + return ConfigurationTest::test_dir($dir); + } - public static function test_virtual_products_dir($dir) - { - return ConfigurationTest::test_dir($dir); - } + public static function test_mbstring() + { + return function_exists('mb_strtolower'); + } - public static function test_mbstring() - { - return function_exists('mb_strtolower'); - } + public static function test_mcrypt() + { + return function_exists('mcrypt_encrypt'); + } - public static function test_mcrypt() - { - return function_exists('mcrypt_encrypt'); - } + public static function test_sessions() + { + if (!$path = @ini_get('session.save_path')) { + return true; + } - public static function test_sessions() - { - if (!$path = @ini_get('session.save_path')) - return true; + return is_writable($path); + } + public static function test_dom() + { + return extension_loaded('Dom'); + } - return is_writable($path); - } - public static function test_dom() - { - return extension_loaded('Dom'); - } + public static function test_files($full = false) + { + $return = array(); + foreach (ConfigurationTest::$test_files as $file) { + if (!file_exists(rtrim(_PS_ROOT_DIR_, DIRECTORY_SEPARATOR).str_replace('/', DIRECTORY_SEPARATOR, $file))) { + if ($full) { + array_push($return, $file); + } else { + return false; + } + } + } - public static function test_files($full = false) - { - $return = array(); - foreach (ConfigurationTest::$test_files as $file) - if (!file_exists(rtrim(_PS_ROOT_DIR_, DIRECTORY_SEPARATOR).str_replace('/', DIRECTORY_SEPARATOR, $file))) - { - if ($full) - array_push($return, $file); - else - return false; - } - - if ($full) - return $return; - return true; - } + if ($full) { + return $return; + } + return true; + } } diff --git a/classes/Connection.php b/classes/Connection.php index ef58377a..3594248f 100644 --- a/classes/Connection.php +++ b/classes/Connection.php @@ -26,174 +26,180 @@ class ConnectionCore extends ObjectModel { - /** @var int */ - public $id_guest; + /** @var int */ + public $id_guest; - /** @var int */ - public $id_page; + /** @var int */ + public $id_page; - /** @var string */ - public $ip_address; + /** @var string */ + public $ip_address; - /** @var string */ - public $http_referer; + /** @var string */ + public $http_referer; - /** @var int */ - public $id_shop; + /** @var int */ + public $id_shop; - /** @var int */ - public $id_shop_group; + /** @var int */ + public $id_shop_group; - /** @var string */ - public $date_add; + /** @var string */ + public $date_add; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'connections', - 'primary' => 'id_connections', - 'fields' => array( - 'id_guest' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_page' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'ip_address' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'http_referer' => array('type' => self::TYPE_STRING, 'validate' => 'isAbsoluteUrl'), - 'id_shop' => array('type' => self::TYPE_INT, 'required' => true), - 'id_shop_group' => array('type' => self::TYPE_INT, 'required' => true), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate') - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'connections', + 'primary' => 'id_connections', + 'fields' => array( + 'id_guest' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_page' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'ip_address' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'http_referer' => array('type' => self::TYPE_STRING, 'validate' => 'isAbsoluteUrl'), + 'id_shop' => array('type' => self::TYPE_INT, 'required' => true), + 'id_shop_group' => array('type' => self::TYPE_INT, 'required' => true), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate') + ), + ); - /** - * @see ObjectModel::getFields() - * @return array - */ - public function getFields() - { - if (!$this->id_shop_group) - $this->id_shop_group = Context::getContext()->shop->id_shop_group; + /** + * @see ObjectModel::getFields() + * @return array + */ + public function getFields() + { + if (!$this->id_shop_group) { + $this->id_shop_group = Context::getContext()->shop->id_shop_group; + } - $fields = parent::getFields(); - return $fields; - } + $fields = parent::getFields(); + return $fields; + } - public static function setPageConnection($cookie, $full = true) - { - $id_page = false; - // The connection is created if it does not exist yet and we get the current page id - if (!isset($cookie->id_connections) || !strstr(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '', Tools::getHttpHost(false, false))) - $id_page = Connection::setNewConnection($cookie); - // If we do not track the pages, no need to get the page id - if (!Configuration::get('PS_STATSDATA_PAGESVIEWS') && !Configuration::get('PS_STATSDATA_CUSTOMER_PAGESVIEWS')) - return array(); - if (!$id_page) - $id_page = Page::getCurrentId(); - // If we do not track the page views by customer, the id_page is the only information needed - if (!Configuration::get('PS_STATSDATA_CUSTOMER_PAGESVIEWS')) - return array('id_page' => $id_page); + public static function setPageConnection($cookie, $full = true) + { + $id_page = false; + // The connection is created if it does not exist yet and we get the current page id + if (!isset($cookie->id_connections) || !strstr(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '', Tools::getHttpHost(false, false))) { + $id_page = Connection::setNewConnection($cookie); + } + // If we do not track the pages, no need to get the page id + if (!Configuration::get('PS_STATSDATA_PAGESVIEWS') && !Configuration::get('PS_STATSDATA_CUSTOMER_PAGESVIEWS')) { + return array(); + } + if (!$id_page) { + $id_page = Page::getCurrentId(); + } + // If we do not track the page views by customer, the id_page is the only information needed + if (!Configuration::get('PS_STATSDATA_CUSTOMER_PAGESVIEWS')) { + return array('id_page' => $id_page); + } - // The ending time will be updated by an ajax request when the guest will close the page - $time_start = date('Y-m-d H:i:s'); - Db::getInstance()->insert('connections_page', array( - 'id_connections' => (int)$cookie->id_connections, - 'id_page' => (int)$id_page, - 'time_start' => $time_start - ), false, true, Db::INSERT_IGNORE); + // The ending time will be updated by an ajax request when the guest will close the page + $time_start = date('Y-m-d H:i:s'); + Db::getInstance()->insert('connections_page', array( + 'id_connections' => (int)$cookie->id_connections, + 'id_page' => (int)$id_page, + 'time_start' => $time_start + ), false, true, Db::INSERT_IGNORE); - // This array is serialized and used by the ajax request to identify the page - return array( - 'id_connections' => (int)$cookie->id_connections, - 'id_page' => (int)$id_page, - 'time_start' => $time_start); - } + // This array is serialized and used by the ajax request to identify the page + return array( + 'id_connections' => (int)$cookie->id_connections, + 'id_page' => (int)$id_page, + 'time_start' => $time_start); + } - public static function setNewConnection($cookie) - { - if (isset($_SERVER['HTTP_USER_AGENT']) - && preg_match('/BotLink|ahoy|AlkalineBOT|anthill|appie|arale|araneo|AraybOt|ariadne|arks|ATN_Worldwide|Atomz|bbot|Bjaaland|Ukonline|borg\-bot\/0\.9|boxseabot|bspider|calif|christcrawler|CMC\/0\.01|combine|confuzzledbot|CoolBot|cosmos|Internet Cruiser Robot|cusco|cyberspyder|cydralspider|desertrealm, desert realm|digger|DIIbot|grabber|downloadexpress|DragonBot|dwcp|ecollector|ebiness|elfinbot|esculapio|esther|fastcrawler|FDSE|FELIX IDE|ESI|fido|H�m�h�kki|KIT\-Fireball|fouineur|Freecrawl|gammaSpider|gazz|gcreep|golem|googlebot|griffon|Gromit|gulliver|gulper|hambot|havIndex|hotwired|htdig|iajabot|INGRID\/0\.1|Informant|InfoSpiders|inspectorwww|irobot|Iron33|JBot|jcrawler|Teoma|Jeeves|jobo|image\.kapsi\.net|KDD\-Explorer|ko_yappo_robot|label\-grabber|larbin|legs|Linkidator|linkwalker|Lockon|logo_gif_crawler|marvin|mattie|mediafox|MerzScope|NEC\-MeshExplorer|MindCrawler|udmsearch|moget|Motor|msnbot|muncher|muninn|MuscatFerret|MwdSearch|sharp\-info\-agent|WebMechanic|NetScoop|newscan\-online|ObjectsSearch|Occam|Orbsearch\/1\.0|packrat|pageboy|ParaSite|patric|pegasus|perlcrawler|phpdig|piltdownman|Pimptrain|pjspider|PlumtreeWebAccessor|PortalBSpider|psbot|Getterrobo\-Plus|Raven|RHCS|RixBot|roadrunner|Robbie|robi|RoboCrawl|robofox|Scooter|Search\-AU|searchprocess|Senrigan|Shagseeker|sift|SimBot|Site Valet|skymob|SLCrawler\/2\.0|slurp|ESI|snooper|solbot|speedy|spider_monkey|SpiderBot\/1\.0|spiderline|nil|suke|http:\/\/www\.sygol\.com|tach_bw|TechBOT|templeton|titin|topiclink|UdmSearch|urlck|Valkyrie libwww\-perl|verticrawl|Victoria|void\-bot|Voyager|VWbot_K|crawlpaper|wapspider|WebBandit\/1\.0|webcatcher|T\-H\-U\-N\-D\-E\-R\-S\-T\-O\-N\-E|WebMoose|webquest|webreaper|webs|webspider|WebWalker|wget|winona|whowhere|wlm|WOLP|WWWC|none|XGET|Nederland\.zoek|AISearchBot|woriobot|NetSeer|Nutch/i', $_SERVER['HTTP_USER_AGENT'])) - { - // This is a bot and we have to retrieve its connection ID - $sql = 'SELECT SQL_NO_CACHE `id_connections` FROM `'._DB_PREFIX_.'connections` + public static function setNewConnection($cookie) + { + if (isset($_SERVER['HTTP_USER_AGENT']) + && preg_match('/BotLink|ahoy|AlkalineBOT|anthill|appie|arale|araneo|AraybOt|ariadne|arks|ATN_Worldwide|Atomz|bbot|Bjaaland|Ukonline|borg\-bot\/0\.9|boxseabot|bspider|calif|christcrawler|CMC\/0\.01|combine|confuzzledbot|CoolBot|cosmos|Internet Cruiser Robot|cusco|cyberspyder|cydralspider|desertrealm, desert realm|digger|DIIbot|grabber|downloadexpress|DragonBot|dwcp|ecollector|ebiness|elfinbot|esculapio|esther|fastcrawler|FDSE|FELIX IDE|ESI|fido|H�m�h�kki|KIT\-Fireball|fouineur|Freecrawl|gammaSpider|gazz|gcreep|golem|googlebot|griffon|Gromit|gulliver|gulper|hambot|havIndex|hotwired|htdig|iajabot|INGRID\/0\.1|Informant|InfoSpiders|inspectorwww|irobot|Iron33|JBot|jcrawler|Teoma|Jeeves|jobo|image\.kapsi\.net|KDD\-Explorer|ko_yappo_robot|label\-grabber|larbin|legs|Linkidator|linkwalker|Lockon|logo_gif_crawler|marvin|mattie|mediafox|MerzScope|NEC\-MeshExplorer|MindCrawler|udmsearch|moget|Motor|msnbot|muncher|muninn|MuscatFerret|MwdSearch|sharp\-info\-agent|WebMechanic|NetScoop|newscan\-online|ObjectsSearch|Occam|Orbsearch\/1\.0|packrat|pageboy|ParaSite|patric|pegasus|perlcrawler|phpdig|piltdownman|Pimptrain|pjspider|PlumtreeWebAccessor|PortalBSpider|psbot|Getterrobo\-Plus|Raven|RHCS|RixBot|roadrunner|Robbie|robi|RoboCrawl|robofox|Scooter|Search\-AU|searchprocess|Senrigan|Shagseeker|sift|SimBot|Site Valet|skymob|SLCrawler\/2\.0|slurp|ESI|snooper|solbot|speedy|spider_monkey|SpiderBot\/1\.0|spiderline|nil|suke|http:\/\/www\.sygol\.com|tach_bw|TechBOT|templeton|titin|topiclink|UdmSearch|urlck|Valkyrie libwww\-perl|verticrawl|Victoria|void\-bot|Voyager|VWbot_K|crawlpaper|wapspider|WebBandit\/1\.0|webcatcher|T\-H\-U\-N\-D\-E\-R\-S\-T\-O\-N\-E|WebMoose|webquest|webreaper|webs|webspider|WebWalker|wget|winona|whowhere|wlm|WOLP|WWWC|none|XGET|Nederland\.zoek|AISearchBot|woriobot|NetSeer|Nutch|YandexBot/i', $_SERVER['HTTP_USER_AGENT'])) { + // This is a bot and we have to retrieve its connection ID + $sql = 'SELECT SQL_NO_CACHE `id_connections` FROM `'._DB_PREFIX_.'connections` WHERE ip_address = '.(int)ip2long(Tools::getRemoteAddr()).' AND `date_add` > \''.pSQL(date('Y-m-d H:i:00', time() - 1800)).'\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).' ORDER BY `date_add` DESC'; - if ($id_connections = Db::getInstance()->getValue($sql, false)) - { - $cookie->id_connections = (int)$id_connections; - return Page::getCurrentId(); - } - } + if ($id_connections = Db::getInstance()->getValue($sql, false)) { + $cookie->id_connections = (int)$id_connections; + return Page::getCurrentId(); + } + } - // A new connection is created if the guest made no actions during 30 minutes - $sql = 'SELECT SQL_NO_CACHE `id_guest` + // A new connection is created if the guest made no actions during 30 minutes + $sql = 'SELECT SQL_NO_CACHE `id_guest` FROM `'._DB_PREFIX_.'connections` WHERE `id_guest` = '.(int)$cookie->id_guest.' AND `date_add` > \''.pSQL(date('Y-m-d H:i:00', time() - 1800)).'\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).' ORDER BY `date_add` DESC'; - $result = Db::getInstance()->getRow($sql, false); - if (!$result['id_guest'] && (int)$cookie->id_guest) - { - // The old connections details are removed from the database in order to spare some memory - Connection::cleanConnectionsPages(); + $result = Db::getInstance()->getRow($sql, false); + if (!$result['id_guest'] && (int)$cookie->id_guest) { + // The old connections details are removed from the database in order to spare some memory + Connection::cleanConnectionsPages(); - $referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''; - $array_url = parse_url($referer); - if (!isset($array_url['host']) || preg_replace('/^www./', '', $array_url['host']) == preg_replace('/^www./', '', Tools::getHttpHost(false, false))) - $referer = ''; - $connection = new Connection(); - $connection->id_guest = (int)$cookie->id_guest; - $connection->id_page = Page::getCurrentId(); - $connection->ip_address = Tools::getRemoteAddr() ? (int)ip2long(Tools::getRemoteAddr()) : ''; - $connection->id_shop = Context::getContext()->shop->id; - $connection->id_shop_group = Context::getContext()->shop->id_shop_group; - $connection->date_add = $cookie->date_add; - if (Validate::isAbsoluteUrl($referer)) - $connection->http_referer = substr($referer, 0, 254); - $connection->add(); - $cookie->id_connections = $connection->id; - return $connection->id_page; - } - } + $referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''; + $array_url = parse_url($referer); + if (!isset($array_url['host']) || preg_replace('/^www./', '', $array_url['host']) == preg_replace('/^www./', '', Tools::getHttpHost(false, false))) { + $referer = ''; + } + $connection = new Connection(); + $connection->id_guest = (int)$cookie->id_guest; + $connection->id_page = Page::getCurrentId(); + $connection->ip_address = Tools::getRemoteAddr() ? (int)ip2long(Tools::getRemoteAddr()) : ''; + $connection->id_shop = Context::getContext()->shop->id; + $connection->id_shop_group = Context::getContext()->shop->id_shop_group; + $connection->date_add = $cookie->date_add; + if (Validate::isAbsoluteUrl($referer)) { + $connection->http_referer = substr($referer, 0, 254); + } + $connection->add(); + $cookie->id_connections = $connection->id; + return $connection->id_page; + } + } - public static function setPageTime($id_connections, $id_page, $time_start, $time) - { - if (!Validate::isUnsignedId($id_connections) - || !Validate::isUnsignedId($id_page) - || !Validate::isDate($time_start)) - return; + public static function setPageTime($id_connections, $id_page, $time_start, $time) + { + if (!Validate::isUnsignedId($id_connections) + || !Validate::isUnsignedId($id_page) + || !Validate::isDate($time_start)) { + return; + } - // Limited to 5 minutes because more than 5 minutes is considered as an error - if ($time > 300000) - $time = 300000; - Db::getInstance()->execute(' + // Limited to 5 minutes because more than 5 minutes is considered as an error + if ($time > 300000) { + $time = 300000; + } + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'connections_page` SET `time_end` = `time_start` + INTERVAL '.(int)($time / 1000).' SECOND WHERE `id_connections` = '.(int)$id_connections.' AND `id_page` = '.(int)$id_page.' AND `time_start` = \''.pSQL($time_start).'\''); - } + } - public static function cleanConnectionsPages() - { - $period = Configuration::get('PS_STATS_OLD_CONNECT_AUTO_CLEAN'); + public static function cleanConnectionsPages() + { + $period = Configuration::get('PS_STATS_OLD_CONNECT_AUTO_CLEAN'); - if ($period === 'week') - $interval = '1 WEEK'; - elseif ($period === 'month') - $interval = '1 MONTH'; - elseif ($period === 'year') - $interval = '1 YEAR'; - else - return; + if ($period === 'week') { + $interval = '1 WEEK'; + } elseif ($period === 'month') { + $interval = '1 MONTH'; + } elseif ($period === 'year') { + $interval = '1 YEAR'; + } else { + return; + } - if ($interval != null) - { - // Records of connections details older than the beginning of the specified interval are deleted - Db::getInstance()->execute(' + if ($interval != null) { + // Records of connections details older than the beginning of the specified interval are deleted + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'connections_page` WHERE time_start < LAST_DAY(DATE_SUB(NOW(), INTERVAL '.$interval.'))'); - } - } -} \ No newline at end of file + } + } +} diff --git a/classes/ConnectionsSource.php b/classes/ConnectionsSource.php index a16bde44..a8eb10df 100644 --- a/classes/ConnectionsSource.php +++ b/classes/ConnectionsSource.php @@ -26,81 +26,88 @@ class ConnectionsSourceCore extends ObjectModel { - public $id_connections; - public $http_referer; - public $request_uri; - public $keywords; - public $date_add; - public static $uri_max_size = 255; + public $id_connections; + public $http_referer; + public $request_uri; + public $keywords; + public $date_add; + public static $uri_max_size = 255; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'connections_source', - 'primary' => 'id_connections_source', - 'fields' => array( - 'id_connections' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'http_referer' => array('type' => self::TYPE_STRING, 'validate' => 'isAbsoluteUrl'), - 'request_uri' => array('type' => self::TYPE_STRING, 'validate' => 'isUrl'), - 'keywords' => array('type' => self::TYPE_STRING, 'validate' => 'isMessage'), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'connections_source', + 'primary' => 'id_connections_source', + 'fields' => array( + 'id_connections' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'http_referer' => array('type' => self::TYPE_STRING, 'validate' => 'isAbsoluteUrl'), + 'request_uri' => array('type' => self::TYPE_STRING, 'validate' => 'isUrl'), + 'keywords' => array('type' => self::TYPE_STRING, 'validate' => 'isMessage'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), + ), + ); - public function add($autodate = true, $nullValues = false) - { - if ($result = parent::add($autodate, $nullValues)) - Referrer::cacheNewSource($this->id); - return $result; - } + public function add($autodate = true, $nullValues = false) + { + if ($result = parent::add($autodate, $nullValues)) { + Referrer::cacheNewSource($this->id); + } + return $result; + } - public static function logHttpReferer(Cookie $cookie = null) - { - if (!$cookie) - $cookie = Context::getContext()->cookie; - if (!isset($cookie->id_connections) || !Validate::isUnsignedId($cookie->id_connections)) - return false; + public static function logHttpReferer(Cookie $cookie = null) + { + if (!$cookie) { + $cookie = Context::getContext()->cookie; + } + if (!isset($cookie->id_connections) || !Validate::isUnsignedId($cookie->id_connections)) { + return false; + } - // If the referrer is not correct, we drop the connection - if (isset($_SERVER['HTTP_REFERER']) && !Validate::isAbsoluteUrl($_SERVER['HTTP_REFERER'])) - return false; - // If there is no referrer and we do not want to save direct traffic (as opposed to referral traffic), we drop the connection - if (!isset($_SERVER['HTTP_REFERER']) && !Configuration::get('TRACKING_DIRECT_TRAFFIC')) - return false; + // If the referrer is not correct, we drop the connection + if (isset($_SERVER['HTTP_REFERER']) && !Validate::isAbsoluteUrl($_SERVER['HTTP_REFERER'])) { + return false; + } + // If there is no referrer and we do not want to save direct traffic (as opposed to referral traffic), we drop the connection + if (!isset($_SERVER['HTTP_REFERER']) && !Configuration::get('TRACKING_DIRECT_TRAFFIC')) { + return false; + } - $source = new ConnectionsSource(); + $source = new ConnectionsSource(); - // There are a few more operations if there is a referrer - if (isset($_SERVER['HTTP_REFERER'])) - { - // If the referrer is internal (i.e. from your own website), then we drop the connection - $parsed = parse_url($_SERVER['HTTP_REFERER']); - $parsed_host = parse_url(Tools::getProtocol().Tools::getHttpHost(false, false).__PS_BASE_URI__); - if ((!isset($parsed['path']) || !isset($parsed_host['path'])) || (preg_replace('/^www./', '', $parsed['host']) == preg_replace('/^www./', '', Tools::getHttpHost(false, false))) && !strncmp($parsed['path'], $parsed_host['path'], strlen(__PS_BASE_URI__))) - return false; + // There are a few more operations if there is a referrer + if (isset($_SERVER['HTTP_REFERER'])) { + // If the referrer is internal (i.e. from your own website), then we drop the connection + $parsed = parse_url($_SERVER['HTTP_REFERER']); + $parsed_host = parse_url(Tools::getProtocol().Tools::getHttpHost(false, false).__PS_BASE_URI__); + if ((!isset($parsed['path']) || !isset($parsed_host['path'])) || (preg_replace('/^www./', '', $parsed['host']) == preg_replace('/^www./', '', Tools::getHttpHost(false, false))) && !strncmp($parsed['path'], $parsed_host['path'], strlen(__PS_BASE_URI__))) { + return false; + } - $source->http_referer = substr($_SERVER['HTTP_REFERER'], 0, ConnectionsSource::$uri_max_size); - $source->keywords = substr(trim(SearchEngine::getKeywords($_SERVER['HTTP_REFERER'])), 0, ConnectionsSource::$uri_max_size); - } + $source->http_referer = substr($_SERVER['HTTP_REFERER'], 0, ConnectionsSource::$uri_max_size); + $source->keywords = substr(trim(SearchEngine::getKeywords($_SERVER['HTTP_REFERER'])), 0, ConnectionsSource::$uri_max_size); + } - $source->id_connections = (int)$cookie->id_connections; - $source->request_uri = Tools::getHttpHost(false, false); + $source->id_connections = (int)$cookie->id_connections; + $source->request_uri = Tools::getHttpHost(false, false); - if (isset($_SERVER['REQUEST_URI'])) - $source->request_uri .= $_SERVER['REQUEST_URI']; - elseif (isset($_SERVER['REDIRECT_URL'])) - $source->request_uri .= $_SERVER['REDIRECT_URL']; + if (isset($_SERVER['REQUEST_URI'])) { + $source->request_uri .= $_SERVER['REQUEST_URI']; + } elseif (isset($_SERVER['REDIRECT_URL'])) { + $source->request_uri .= $_SERVER['REDIRECT_URL']; + } - if (!Validate::isUrl($source->request_uri)) - $source->request_uri = ''; - $source->request_uri = substr($source->request_uri, 0, ConnectionsSource::$uri_max_size); - return $source->add(); - } + if (!Validate::isUrl($source->request_uri)) { + $source->request_uri = ''; + } + $source->request_uri = substr($source->request_uri, 0, ConnectionsSource::$uri_max_size); + return $source->add(); + } - public static function getOrderSources($id_order) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getOrderSources($id_order) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT cos.http_referer, cos.request_uri, cos.keywords, cos.date_add FROM '._DB_PREFIX_.'orders o INNER JOIN '._DB_PREFIX_.'guest g ON g.id_customer = o.id_customer @@ -108,5 +115,5 @@ class ConnectionsSourceCore extends ObjectModel INNER JOIN '._DB_PREFIX_.'connections_source cos ON cos.id_connections = co.id_connections WHERE id_order = '.(int)($id_order).' ORDER BY cos.date_add DESC'); - } -} \ No newline at end of file + } +} diff --git a/classes/Contact.php b/classes/Contact.php index f7502f2a..70a8feeb 100644 --- a/classes/Contact.php +++ b/classes/Contact.php @@ -26,47 +26,47 @@ class ContactCore extends ObjectModel { - public $id; + public $id; - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var string e-mail */ - public $email; + /** @var string e-mail */ + public $email; - /** @var string Detailed description */ - public $description; + /** @var string Detailed description */ + public $description; - public $customer_service; + public $customer_service; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'contact', - 'primary' => 'id_contact', - 'multilang' => true, - 'fields' => array( - 'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'size' => 128), - 'customer_service' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'contact', + 'primary' => 'id_contact', + 'multilang' => true, + 'fields' => array( + 'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'size' => 128), + 'customer_service' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), - 'description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCleanHtml'), - ), - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), + 'description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCleanHtml'), + ), + ); - /** - * Return available contacts - * - * @param int $id_lang Language ID - * @param Context - * @return array Contacts - */ - public static function getContacts($id_lang) - { - $shop_ids = Shop::getContextListShopID(); - $sql = 'SELECT * + /** + * Return available contacts + * + * @param int $id_lang Language ID + * @param Context + * @return array Contacts + */ + public static function getContacts($id_lang) + { + $shop_ids = Shop::getContextListShopID(); + $sql = 'SELECT * FROM `'._DB_PREFIX_.'contact` c '.Shop::addSqlAssociation('contact', 'c', false).' LEFT JOIN `'._DB_PREFIX_.'contact_lang` cl ON (c.`id_contact` = cl.`id_contact`) @@ -74,17 +74,17 @@ class ContactCore extends ObjectModel AND contact_shop.`id_shop` IN ('.implode(', ', array_map('intval', $shop_ids)).') GROUP BY c.`id_contact` ORDER BY `name` ASC'; - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + } - /** - * Return available categories contacts - * @return array Contacts - */ - public static function getCategoriesContacts() - { - $shop_ids = Shop::getContextListShopID(); - return Db::getInstance()->executeS(' + /** + * Return available categories contacts + * @return array Contacts + */ + public static function getCategoriesContacts() + { + $shop_ids = Shop::getContextListShopID(); + return Db::getInstance()->executeS(' SELECT cl.* FROM '._DB_PREFIX_.'contact ct '.Shop::addSqlAssociation('contact', 'ct', false).' @@ -94,5 +94,5 @@ class ContactCore extends ObjectModel AND contact_shop.`id_shop` IN ('.implode(', ', array_map('intval', $shop_ids)).') GROUP BY ct.`id_contact` '); - } -} \ No newline at end of file + } +} diff --git a/classes/Context.php b/classes/Context.php index caabc758..da70a018 100644 --- a/classes/Context.php +++ b/classes/Context.php @@ -31,269 +31,261 @@ */ class ContextCore { - /* @var Context */ - protected static $instance; + /* @var Context */ + protected static $instance; - /** @var Cart */ - public $cart; + /** @var Cart */ + public $cart; - /** @var Customer */ - public $customer; + /** @var Customer */ + public $customer; - /** @var Cookie */ - public $cookie; + /** @var Cookie */ + public $cookie; - /** @var Link */ - public $link; + /** @var Link */ + public $link; - /** @var Country */ - public $country; + /** @var Country */ + public $country; - /** @var Employee */ - public $employee; + /** @var Employee */ + public $employee; - /** @var AdminController|FrontController */ - public $controller; + /** @var AdminController|FrontController */ + public $controller; - /** @var string */ - public $override_controller_name_for_translations; + /** @var string */ + public $override_controller_name_for_translations; - /** @var Language */ - public $language; + /** @var Language */ + public $language; - /** @var Currency */ - public $currency; + /** @var Currency */ + public $currency; - /** @var AdminTab */ - public $tab; + /** @var AdminTab */ + public $tab; - /** @var Shop */ - public $shop; + /** @var Shop */ + public $shop; - /** @var Theme */ - public $theme; + /** @var Theme */ + public $theme; - /** @var Smarty */ - public $smarty; + /** @var Smarty */ + public $smarty; - /** @var Mobile_Detect */ - public $mobile_detect; + /** @var Mobile_Detect */ + public $mobile_detect; - /** @var int */ - public $mode; + /** @var int */ + public $mode; - /** - * Mobile device of the customer - * - * @var bool|null - */ - protected $mobile_device = null; + /** + * Mobile device of the customer + * + * @var bool|null + */ + protected $mobile_device = null; - /** @var bool|null */ - protected $is_mobile = null; + /** @var bool|null */ + protected $is_mobile = null; - /** @var bool|null */ - protected $is_tablet = null; + /** @var bool|null */ + protected $is_tablet = null; - /** @var int */ - const DEVICE_COMPUTER = 1; + /** @var int */ + const DEVICE_COMPUTER = 1; - /** @var int */ - const DEVICE_TABLET = 2; + /** @var int */ + const DEVICE_TABLET = 2; - /** @var int */ - const DEVICE_MOBILE = 4; + /** @var int */ + const DEVICE_MOBILE = 4; - /** @var int */ - const MODE_STD = 1; + /** @var int */ + const MODE_STD = 1; - /** @var int */ - const MODE_STD_CONTRIB = 2; + /** @var int */ + const MODE_STD_CONTRIB = 2; - /** @var int */ - const MODE_HOST_CONTRIB = 4; + /** @var int */ + const MODE_HOST_CONTRIB = 4; - /** @var int */ - const MODE_HOST = 8; + /** @var int */ + const MODE_HOST = 8; - /** - * Sets Mobile_Detect tool object - * - * @return Mobile_Detect - */ - public function getMobileDetect() - { - if ($this->mobile_detect === null) - { - require_once(_PS_TOOL_DIR_.'mobile_Detect/Mobile_Detect.php'); - $this->mobile_detect = new Mobile_Detect(); - } - return $this->mobile_detect; - } + /** + * Sets Mobile_Detect tool object + * + * @return Mobile_Detect + */ + public function getMobileDetect() + { + if ($this->mobile_detect === null) { + require_once(_PS_TOOL_DIR_.'mobile_Detect/Mobile_Detect.php'); + $this->mobile_detect = new Mobile_Detect(); + } + return $this->mobile_detect; + } - /** - * Checks if visitor's device is a mobile device - * - * @return bool - */ - public function isMobile() - { - if ($this->is_mobile === null) - { - $mobile_detect = $this->getMobileDetect(); - $this->is_mobile = $mobile_detect->isMobile(); - } - return $this->is_mobile; - } + /** + * Checks if visitor's device is a mobile device + * + * @return bool + */ + public function isMobile() + { + if ($this->is_mobile === null) { + $mobile_detect = $this->getMobileDetect(); + $this->is_mobile = $mobile_detect->isMobile(); + } + return $this->is_mobile; + } - /** - * Checks if visitor's device is a tablet device - * - * @return bool - */ - public function isTablet() - { - if ($this->is_tablet === null) - { - $mobile_detect = $this->getMobileDetect(); - $this->is_tablet = $mobile_detect->isTablet(); - } - return $this->is_tablet; - } + /** + * Checks if visitor's device is a tablet device + * + * @return bool + */ + public function isTablet() + { + if ($this->is_tablet === null) { + $mobile_detect = $this->getMobileDetect(); + $this->is_tablet = $mobile_detect->isTablet(); + } + return $this->is_tablet; + } - /** - * Sets mobile_device context variable - * - * @return bool - */ - public function getMobileDevice() - { - if ($this->mobile_device === null) - { - $this->mobile_device = false; - if ($this->checkMobileContext()) - { - if (isset(Context::getContext()->cookie->no_mobile) && Context::getContext()->cookie->no_mobile == false && (int)Configuration::get('PS_ALLOW_MOBILE_DEVICE') != 0) - $this->mobile_device = true; - else - { - switch ((int)Configuration::get('PS_ALLOW_MOBILE_DEVICE')) - { - case 1: // Only for mobile device - if ($this->isMobile() && !$this->isTablet()) - $this->mobile_device = true; - break; - case 2: // Only for touchpads - if ($this->isTablet() && !$this->isMobile()) - $this->mobile_device = true; - break; - case 3: // For touchpad or mobile devices - if ($this->isMobile() || $this->isTablet()) - $this->mobile_device = true; - break; - } - } - } - } - return $this->mobile_device; - } + /** + * Sets mobile_device context variable + * + * @return bool + */ + public function getMobileDevice() + { + if ($this->mobile_device === null) { + $this->mobile_device = false; + if ($this->checkMobileContext()) { + if (isset(Context::getContext()->cookie->no_mobile) && Context::getContext()->cookie->no_mobile == false && (int)Configuration::get('PS_ALLOW_MOBILE_DEVICE') != 0) { + $this->mobile_device = true; + } else { + switch ((int)Configuration::get('PS_ALLOW_MOBILE_DEVICE')) { + case 1: // Only for mobile device + if ($this->isMobile() && !$this->isTablet()) { + $this->mobile_device = true; + } + break; + case 2: // Only for touchpads + if ($this->isTablet() && !$this->isMobile()) { + $this->mobile_device = true; + } + break; + case 3: // For touchpad or mobile devices + if ($this->isMobile() || $this->isTablet()) { + $this->mobile_device = true; + } + break; + } + } + } + } + return $this->mobile_device; + } - /** - * Returns mobile device type - * - * @return int - */ - public function getDevice() - { - static $device = null; + /** + * Returns mobile device type + * + * @return int + */ + public function getDevice() + { + static $device = null; - if ($device === null) - { - if ($this->isTablet()) - $device = Context::DEVICE_TABLET; - elseif ($this->isMobile()) - $device = Context::DEVICE_MOBILE; - else - $device = Context::DEVICE_COMPUTER; - } + if ($device === null) { + if ($this->isTablet()) { + $device = Context::DEVICE_TABLET; + } elseif ($this->isMobile()) { + $device = Context::DEVICE_MOBILE; + } else { + $device = Context::DEVICE_COMPUTER; + } + } - return $device; - } + return $device; + } - /** - * Checks if mobile context is possible - * - * @return bool - * @throws PrestaShopException - */ - protected function checkMobileContext() - { - // Check mobile context - if (Tools::isSubmit('no_mobile_theme')) - { - Context::getContext()->cookie->no_mobile = true; - if (Context::getContext()->cookie->id_guest) - { - $guest = new Guest(Context::getContext()->cookie->id_guest); - $guest->mobile_theme = false; - $guest->update(); - } - } - elseif (Tools::isSubmit('mobile_theme_ok')) - { - Context::getContext()->cookie->no_mobile = false; - if (Context::getContext()->cookie->id_guest) - { - $guest = new Guest(Context::getContext()->cookie->id_guest); - $guest->mobile_theme = true; - $guest->update(); - } - } + /** + * Checks if mobile context is possible + * + * @return bool + * @throws PrestaShopException + */ + protected function checkMobileContext() + { + // Check mobile context + if (Tools::isSubmit('no_mobile_theme')) { + Context::getContext()->cookie->no_mobile = true; + if (Context::getContext()->cookie->id_guest) { + $guest = new Guest(Context::getContext()->cookie->id_guest); + $guest->mobile_theme = false; + $guest->update(); + } + } elseif (Tools::isSubmit('mobile_theme_ok')) { + Context::getContext()->cookie->no_mobile = false; + if (Context::getContext()->cookie->id_guest) { + $guest = new Guest(Context::getContext()->cookie->id_guest); + $guest->mobile_theme = true; + $guest->update(); + } + } - return isset($_SERVER['HTTP_USER_AGENT']) - && isset(Context::getContext()->cookie) - && (bool)Configuration::get('PS_ALLOW_MOBILE_DEVICE') - && @filemtime(_PS_THEME_MOBILE_DIR_) - && !Context::getContext()->cookie->no_mobile; - } + return isset($_SERVER['HTTP_USER_AGENT']) + && isset(Context::getContext()->cookie) + && (bool)Configuration::get('PS_ALLOW_MOBILE_DEVICE') + && @filemtime(_PS_THEME_MOBILE_DIR_) + && !Context::getContext()->cookie->no_mobile; + } - /** - * Get a singleton instance of Context object - * - * @return Context - */ - public static function getContext() - { - if (!isset(self::$instance)) - self::$instance = new Context(); + /** + * Get a singleton instance of Context object + * + * @return Context + */ + public static function getContext() + { + if (!isset(self::$instance)) { + self::$instance = new Context(); + } - return self::$instance; - } + return self::$instance; + } - /** - * @param $test_instance Context - * Unit testing purpose only - */ - public static function setInstanceForTesting($test_instance) - { - self::$instance = $test_instance; - } + /** + * @param $test_instance Context + * Unit testing purpose only + */ + public static function setInstanceForTesting($test_instance) + { + self::$instance = $test_instance; + } - /** - * Unit testing purpose only - */ - public static function deleteTestingInstance() - { - self::$instance = null; - } + /** + * Unit testing purpose only + */ + public static function deleteTestingInstance() + { + self::$instance = null; + } - /** - * Clone current context object - * - * @return Context - */ - public function cloneContext() - { - return clone($this); - } + /** + * Clone current context object + * + * @return Context + */ + public function cloneContext() + { + return clone($this); + } } diff --git a/classes/ControllerFactory.php b/classes/ControllerFactory.php index e35063d0..dee934fe 100644 --- a/classes/ControllerFactory.php +++ b/classes/ControllerFactory.php @@ -31,35 +31,34 @@ */ class ControllerFactoryCore { - /** - * @deprecated since 1.5.0 - */ - public static function includeController($className) - { - Tools::displayAsDeprecated(); + /** + * @deprecated since 1.5.0 + */ + public static function includeController($className) + { + Tools::displayAsDeprecated(); - if (!class_exists($className, false)) - { - require_once(_PS_CORE_DIR_.'/controllers/'.$className.'.php'); - if (file_exists(_PS_ROOT_DIR_.'/override/controllers/'.$className.'.php')) - require_once(_PS_ROOT_DIR_.'/override/controllers/'.$className.'.php'); - else - { - $coreClass = new ReflectionClass($className.'Core'); - if ($coreClass->isAbstract()) - eval('abstract class '.$className.' extends '.$className.'Core {}'); - else - eval('class '.$className.' extends '.$className.'Core {}'); - } - } - } + if (!class_exists($className, false)) { + require_once(_PS_CORE_DIR_.'/controllers/'.$className.'.php'); + if (file_exists(_PS_ROOT_DIR_.'/override/controllers/'.$className.'.php')) { + require_once(_PS_ROOT_DIR_.'/override/controllers/'.$className.'.php'); + } else { + $coreClass = new ReflectionClass($className.'Core'); + if ($coreClass->isAbstract()) { + eval('abstract class '.$className.' extends '.$className.'Core {}'); + } else { + eval('class '.$className.' extends '.$className.'Core {}'); + } + } + } + } - /** - * @deprecated since 1.5.0 - */ - public static function getController($className, $auth = false, $ssl = false) - { - ControllerFactory::includeController($className); - return new $className($auth, $ssl); - } -} \ No newline at end of file + /** + * @deprecated since 1.5.0 + */ + public static function getController($className, $auth = false, $ssl = false) + { + ControllerFactory::includeController($className); + return new $className($auth, $ssl); + } +} diff --git a/classes/Cookie.php b/classes/Cookie.php index 81922896..6089c984 100644 --- a/classes/Cookie.php +++ b/classes/Cookie.php @@ -26,387 +26,404 @@ class CookieCore { - /** @var array Contain cookie content in a key => value format */ - protected $_content; + /** @var array Contain cookie content in a key => value format */ + protected $_content; - /** @var array Crypted cookie name for setcookie() */ - protected $_name; + /** @var array Crypted cookie name for setcookie() */ + protected $_name; - /** @var array expiration date for setcookie() */ - protected $_expire; + /** @var array expiration date for setcookie() */ + protected $_expire; - /** @var array Website domain for setcookie() */ - protected $_domain; + /** @var array Website domain for setcookie() */ + protected $_domain; - /** @var array Path for setcookie() */ - protected $_path; + /** @var array Path for setcookie() */ + protected $_path; - /** @var array cipher tool instance */ - protected $_cipherTool; + /** @var array cipher tool instance */ + protected $_cipherTool; - protected $_modified = false; + protected $_modified = false; - protected $_allow_writing; + protected $_allow_writing; - protected $_salt; + protected $_salt; - protected $_standalone; + protected $_standalone; - protected $_secure = false; + protected $_secure = false; - /** - * Get data if the cookie exists and else initialize an new one - * - * @param $name string Cookie name before encrypting - * @param $path string - */ - public function __construct($name, $path = '', $expire = null, $shared_urls = null, $standalone = false, $secure = false) - { - $this->_content = array(); - $this->_standalone = $standalone; - $this->_expire = is_null($expire) ? time() + 1728000 : (int)$expire; - $this->_path = trim(($this->_standalone ? '' : Context::getContext()->shop->physical_uri).$path, '/\\').'/'; - if ($this->_path{0} != '/') $this->_path = '/'.$this->_path; - $this->_path = rawurlencode($this->_path); - $this->_path = str_replace('%2F', '/', $this->_path); - $this->_path = str_replace('%7E', '~', $this->_path); - $this->_domain = $this->getDomain($shared_urls); - $this->_name = 'PrestaShop-'.md5(($this->_standalone ? '' : _PS_VERSION_).$name.$this->_domain); - $this->_allow_writing = true; - $this->_salt = $this->_standalone ? str_pad('', 8, md5('ps'.__FILE__)) : _COOKIE_IV_; - if ($this->_standalone) - $this->_cipherTool = new Blowfish(str_pad('', 56, md5('ps'.__FILE__)), str_pad('', 56, md5('iv'.__FILE__))); - elseif (!Configuration::get('PS_CIPHER_ALGORITHM') || !defined('_RIJNDAEL_KEY_')) - $this->_cipherTool = new Blowfish(_COOKIE_KEY_, _COOKIE_IV_); - else - $this->_cipherTool = new Rijndael(_RIJNDAEL_KEY_, _RIJNDAEL_IV_); - $this->_secure = (bool)$secure; + /** + * Get data if the cookie exists and else initialize an new one + * + * @param $name string Cookie name before encrypting + * @param $path string + */ + public function __construct($name, $path = '', $expire = null, $shared_urls = null, $standalone = false, $secure = false) + { + $this->_content = array(); + $this->_standalone = $standalone; + $this->_expire = is_null($expire) ? time() + 1728000 : (int)$expire; + $this->_path = trim(($this->_standalone ? '' : Context::getContext()->shop->physical_uri).$path, '/\\').'/'; + if ($this->_path{0} != '/') { + $this->_path = '/'.$this->_path; + } + $this->_path = rawurlencode($this->_path); + $this->_path = str_replace('%2F', '/', $this->_path); + $this->_path = str_replace('%7E', '~', $this->_path); + $this->_domain = $this->getDomain($shared_urls); + $this->_name = 'PrestaShop-'.md5(($this->_standalone ? '' : _PS_VERSION_).$name.$this->_domain); + $this->_allow_writing = true; + $this->_salt = $this->_standalone ? str_pad('', 8, md5('ps'.__FILE__)) : _COOKIE_IV_; + if ($this->_standalone) { + $this->_cipherTool = new Blowfish(str_pad('', 56, md5('ps'.__FILE__)), str_pad('', 56, md5('iv'.__FILE__))); + } elseif (!Configuration::get('PS_CIPHER_ALGORITHM') || !defined('_RIJNDAEL_KEY_')) { + $this->_cipherTool = new Blowfish(_COOKIE_KEY_, _COOKIE_IV_); + } else { + $this->_cipherTool = new Rijndael(_RIJNDAEL_KEY_, _RIJNDAEL_IV_); + } + $this->_secure = (bool)$secure; - $this->update(); - } + $this->update(); + } - public function disallowWriting() - { - $this->_allow_writing = false; - } + public function disallowWriting() + { + $this->_allow_writing = false; + } - protected function getDomain($shared_urls = null) - { - $r = '!(?:(\w+)://)?(?:(\w+)\:(\w+)@)?([^/:]+)?(?:\:(\d*))?([^#?]+)?(?:\?([^#]+))?(?:#(.+$))?!i'; + protected function getDomain($shared_urls = null) + { + $r = '!(?:(\w+)://)?(?:(\w+)\:(\w+)@)?([^/:]+)?(?:\:(\d*))?([^#?]+)?(?:\?([^#]+))?(?:#(.+$))?!i'; - if (!preg_match ($r, Tools::getHttpHost(false, false), $out) || !isset($out[4])) - return false; + if (!preg_match($r, Tools::getHttpHost(false, false), $out) || !isset($out[4])) { + return false; + } - if (preg_match('/^(((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]{1}[0-9]|[1-9]).)'. - '{1}((25[0-5]|2[0-4][0-9]|[1]{1}[0-9]{2}|[1-9]{1}[0-9]|[0-9]).)'. - '{2}((25[0-5]|2[0-4][0-9]|[1]{1}[0-9]{2}|[1-9]{1}[0-9]|[0-9]){1}))$/', $out[4])) - return false; - if (!strstr(Tools::getHttpHost(false, false), '.')) - return false; + if (preg_match('/^(((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]{1}[0-9]|[1-9]).)'. + '{1}((25[0-5]|2[0-4][0-9]|[1]{1}[0-9]{2}|[1-9]{1}[0-9]|[0-9]).)'. + '{2}((25[0-5]|2[0-4][0-9]|[1]{1}[0-9]{2}|[1-9]{1}[0-9]|[0-9]){1}))$/', $out[4])) { + return false; + } + if (!strstr(Tools::getHttpHost(false, false), '.')) { + return false; + } - $domain = false; - if ($shared_urls !== null) - { - foreach ($shared_urls as $shared_url) - { - if ($shared_url != $out[4]) - continue; - if (preg_match('/^(?:.*\.)?([^.]*(?:.{2,4})?\..{2,3})$/Ui', $shared_url, $res)) - { - $domain = '.'.$res[1]; - break; - } - } - } - if (!$domain) - $domain = $out[4]; - return $domain; - } + $domain = false; + if ($shared_urls !== null) { + foreach ($shared_urls as $shared_url) { + if ($shared_url != $out[4]) { + continue; + } + if (preg_match('/^(?:.*\.)?([^.]*(?:.{2,4})?\..{2,3})$/Ui', $shared_url, $res)) { + $domain = '.'.$res[1]; + break; + } + } + } + if (!$domain) { + $domain = $out[4]; + } + return $domain; + } - /** - * Set expiration date - * - * @param int $expire Expiration time from now - */ - public function setExpire($expire) - { - $this->_expire = (int)($expire); - } + /** + * Set expiration date + * + * @param int $expire Expiration time from now + */ + public function setExpire($expire) + { + $this->_expire = (int)($expire); + } - /** - * Magic method wich return cookie data from _content array - * - * @param string $key key wanted - * @return string value corresponding to the key - */ - public function __get($key) - { - return isset($this->_content[$key]) ? $this->_content[$key] : false; - } + /** + * Magic method wich return cookie data from _content array + * + * @param string $key key wanted + * @return string value corresponding to the key + */ + public function __get($key) + { + return isset($this->_content[$key]) ? $this->_content[$key] : false; + } - /** - * Magic method which check if key exists in the cookie - * - * @param string $key key wanted - * @return bool key existence - */ - public function __isset($key) - { - return isset($this->_content[$key]); - } + /** + * Magic method which check if key exists in the cookie + * + * @param string $key key wanted + * @return bool key existence + */ + public function __isset($key) + { + return isset($this->_content[$key]); + } - /** - * Magic method which adds data into _content array - * - * @param string $key Access key for the value - * @param mixed $value Value corresponding to the key - * @throws Exception - */ - public function __set($key, $value) - { - if (is_array($value)) - die(Tools::displayError()); - if (preg_match('/¤|\|/', $key.$value)) - throw new Exception('Forbidden chars in cookie'); - if (!$this->_modified && (!isset($this->_content[$key]) || (isset($this->_content[$key]) && $this->_content[$key] != $value))) - $this->_modified = true; - $this->_content[$key] = $value; - } + /** + * Magic method which adds data into _content array + * + * @param string $key Access key for the value + * @param mixed $value Value corresponding to the key + * @throws Exception + */ + public function __set($key, $value) + { + if (is_array($value)) { + die(Tools::displayError()); + } + if (preg_match('/¤|\|/', $key.$value)) { + throw new Exception('Forbidden chars in cookie'); + } + if (!$this->_modified && (!isset($this->_content[$key]) || (isset($this->_content[$key]) && $this->_content[$key] != $value))) { + $this->_modified = true; + } + $this->_content[$key] = $value; + } - /** - * Magic method wich delete data into _content array - * - * @param string $key key wanted - */ - public function __unset($key) - { - if (isset($this->_content[$key])) - $this->_modified = true; - unset($this->_content[$key]); - } + /** + * Magic method wich delete data into _content array + * + * @param string $key key wanted + */ + public function __unset($key) + { + if (isset($this->_content[$key])) { + $this->_modified = true; + } + unset($this->_content[$key]); + } - /** - * Check customer informations saved into cookie and return customer validity - * - * @deprecated as of version 1.5 use Customer::isLogged() instead - * @return bool customer validity - */ - public function isLogged($withGuest = false) - { - Tools::displayAsDeprecated(); - if (!$withGuest && $this->is_guest == 1) - return false; + /** + * Check customer informations saved into cookie and return customer validity + * + * @deprecated as of version 1.5 use Customer::isLogged() instead + * @return bool customer validity + */ + public function isLogged($withGuest = false) + { + Tools::displayAsDeprecated(); + if (!$withGuest && $this->is_guest == 1) { + return false; + } - /* Customer is valid only if it can be load and if cookie password is the same as database one */ - if ($this->logged == 1 && $this->id_customer && Validate::isUnsignedId($this->id_customer) && Customer::checkPassword((int)($this->id_customer), $this->passwd)) - return true; - return false; - } + /* Customer is valid only if it can be load and if cookie password is the same as database one */ + if ($this->logged == 1 && $this->id_customer && Validate::isUnsignedId($this->id_customer) && Customer::checkPassword((int)($this->id_customer), $this->passwd)) { + return true; + } + return false; + } - /** - * Check employee informations saved into cookie and return employee validity - * - * @deprecated as of version 1.5 use Employee::isLoggedBack() instead - * @return bool employee validity - */ - public function isLoggedBack() - { - Tools::displayAsDeprecated(); - /* Employee is valid only if it can be load and if cookie password is the same as database one */ - return ($this->id_employee - && Validate::isUnsignedId($this->id_employee) - && Employee::checkPassword((int)$this->id_employee, $this->passwd) - && (!isset($this->_content['remote_addr']) || $this->_content['remote_addr'] == ip2long(Tools::getRemoteAddr()) || !Configuration::get('PS_COOKIE_CHECKIP')) - ); - } + /** + * Check employee informations saved into cookie and return employee validity + * + * @deprecated as of version 1.5 use Employee::isLoggedBack() instead + * @return bool employee validity + */ + public function isLoggedBack() + { + Tools::displayAsDeprecated(); + /* Employee is valid only if it can be load and if cookie password is the same as database one */ + return ($this->id_employee + && Validate::isUnsignedId($this->id_employee) + && Employee::checkPassword((int)$this->id_employee, $this->passwd) + && (!isset($this->_content['remote_addr']) || $this->_content['remote_addr'] == ip2long(Tools::getRemoteAddr()) || !Configuration::get('PS_COOKIE_CHECKIP')) + ); + } - /** - * Delete cookie - * As of version 1.5 don't call this function, use Customer::logout() or Employee::logout() instead; - */ - public function logout() - { - $this->_content = array(); - $this->_setcookie(); - unset($_COOKIE[$this->_name]); - $this->_modified = true; - } + /** + * Delete cookie + * As of version 1.5 don't call this function, use Customer::logout() or Employee::logout() instead; + */ + public function logout() + { + $this->_content = array(); + $this->_setcookie(); + unset($_COOKIE[$this->_name]); + $this->_modified = true; + } - /** - * Soft logout, delete everything links to the customer - * but leave there affiliate's informations. - * As of version 1.5 don't call this function, use Customer::mylogout() instead; - */ - public function mylogout() - { - unset($this->_content['id_compare']); - unset($this->_content['id_customer']); - unset($this->_content['id_guest']); - unset($this->_content['is_guest']); - unset($this->_content['id_connections']); - unset($this->_content['customer_lastname']); - unset($this->_content['customer_firstname']); - unset($this->_content['passwd']); - unset($this->_content['logged']); - unset($this->_content['email']); - unset($this->_content['id_cart']); - unset($this->_content['id_address_invoice']); - unset($this->_content['id_address_delivery']); - $this->_modified = true; - } + /** + * Soft logout, delete everything links to the customer + * but leave there affiliate's informations. + * As of version 1.5 don't call this function, use Customer::mylogout() instead; + */ + public function mylogout() + { + unset($this->_content['id_compare']); + unset($this->_content['id_customer']); + unset($this->_content['id_guest']); + unset($this->_content['is_guest']); + unset($this->_content['id_connections']); + unset($this->_content['customer_lastname']); + unset($this->_content['customer_firstname']); + unset($this->_content['passwd']); + unset($this->_content['logged']); + unset($this->_content['email']); + unset($this->_content['id_cart']); + unset($this->_content['id_address_invoice']); + unset($this->_content['id_address_delivery']); + $this->_modified = true; + } - public function makeNewLog() - { - unset($this->_content['id_customer']); - unset($this->_content['id_guest']); - Guest::setNewGuest($this); - $this->_modified = true; - } + public function makeNewLog() + { + unset($this->_content['id_customer']); + unset($this->_content['id_guest']); + Guest::setNewGuest($this); + $this->_modified = true; + } - /** - * Get cookie content - */ - public function update($nullValues = false) - { - if (isset($_COOKIE[$this->_name])) - { - /* Decrypt cookie content */ - $content = $this->_cipherTool->decrypt($_COOKIE[$this->_name]); - //printf("\$content = %s
", $content); + /** + * Get cookie content + */ + public function update($nullValues = false) + { + if (isset($_COOKIE[$this->_name])) { + /* Decrypt cookie content */ + $content = $this->_cipherTool->decrypt($_COOKIE[$this->_name]); + //printf("\$content = %s
", $content); - /* Get cookie checksum */ - $tmpTab = explode('¤', $content); - array_pop($tmpTab); - $content_for_checksum = implode('¤', $tmpTab).'¤'; - $checksum = crc32($this->_salt.$content_for_checksum); - //printf("\$checksum = %s
", $checksum); + /* Get cookie checksum */ + $tmpTab = explode('¤', $content); + array_pop($tmpTab); + $content_for_checksum = implode('¤', $tmpTab).'¤'; + $checksum = crc32($this->_salt.$content_for_checksum); + //printf("\$checksum = %s
", $checksum); - /* Unserialize cookie content */ - $tmpTab = explode('¤', $content); - foreach ($tmpTab as $keyAndValue) - { - $tmpTab2 = explode('|', $keyAndValue); - if (count($tmpTab2) == 2) - $this->_content[$tmpTab2[0]] = $tmpTab2[1]; - } - /* Blowfish fix */ - if (isset($this->_content['checksum'])) - $this->_content['checksum'] = (int)($this->_content['checksum']); - //printf("\$this->_content['checksum'] = %s
", $this->_content['checksum']); - //die(); - /* Check if cookie has not been modified */ - if (!isset($this->_content['checksum']) || $this->_content['checksum'] != $checksum) - $this->logout(); + /* Unserialize cookie content */ + $tmpTab = explode('¤', $content); + foreach ($tmpTab as $keyAndValue) { + $tmpTab2 = explode('|', $keyAndValue); + if (count($tmpTab2) == 2) { + $this->_content[$tmpTab2[0]] = $tmpTab2[1]; + } + } + /* Blowfish fix */ + if (isset($this->_content['checksum'])) { + $this->_content['checksum'] = (int)($this->_content['checksum']); + } + //printf("\$this->_content['checksum'] = %s
", $this->_content['checksum']); + //die(); + /* Check if cookie has not been modified */ + if (!isset($this->_content['checksum']) || $this->_content['checksum'] != $checksum) { + $this->logout(); + } - if (!isset($this->_content['date_add'])) - $this->_content['date_add'] = date('Y-m-d H:i:s'); - } - else - $this->_content['date_add'] = date('Y-m-d H:i:s'); + if (!isset($this->_content['date_add'])) { + $this->_content['date_add'] = date('Y-m-d H:i:s'); + } + } else { + $this->_content['date_add'] = date('Y-m-d H:i:s'); + } - //checks if the language exists, if not choose the default language - if (!$this->_standalone && !Language::getLanguage((int)$this->id_lang)) - { - $this->id_lang = Configuration::get('PS_LANG_DEFAULT'); - // set detect_language to force going through Tools::setCookieLanguage to figure out browser lang - $this->detect_language = true; - } + //checks if the language exists, if not choose the default language + if (!$this->_standalone && !Language::getLanguage((int)$this->id_lang)) { + $this->id_lang = Configuration::get('PS_LANG_DEFAULT'); + // set detect_language to force going through Tools::setCookieLanguage to figure out browser lang + $this->detect_language = true; + } + } - } + /** + * Setcookie according to php version + */ + protected function _setcookie($cookie = null) + { + if ($cookie) { + $content = $this->_cipherTool->encrypt($cookie); + $time = $this->_expire; + } else { + $content = 0; + $time = 1; + } + if (PHP_VERSION_ID <= 50200) { /* PHP version > 5.2.0 */ + return setcookie($this->_name, $content, $time, $this->_path, $this->_domain, $this->_secure); + } else { + return setcookie($this->_name, $content, $time, $this->_path, $this->_domain, $this->_secure, true); + } + } - /** - * Setcookie according to php version - */ - protected function _setcookie($cookie = null) - { - if ($cookie) - { - $content = $this->_cipherTool->encrypt($cookie); - $time = $this->_expire; - } - else - { - $content = 0; - $time = 1; - } - if (PHP_VERSION_ID <= 50200) /* PHP version > 5.2.0 */ - return setcookie($this->_name, $content, $time, $this->_path, $this->_domain, $this->_secure); - else - return setcookie($this->_name, $content, $time, $this->_path, $this->_domain, $this->_secure, true); - } + public function __destruct() + { + $this->write(); + } - public function __destruct() - { - $this->write(); - } + /** + * Save cookie with setcookie() + */ + public function write() + { + if (!$this->_modified || headers_sent() || !$this->_allow_writing) { + return; + } - /** - * Save cookie with setcookie() - */ - public function write() - { - if (!$this->_modified || headers_sent() || !$this->_allow_writing) - return; + $cookie = ''; - $cookie = ''; + /* Serialize cookie content */ + if (isset($this->_content['checksum'])) { + unset($this->_content['checksum']); + } + foreach ($this->_content as $key => $value) { + $cookie .= $key.'|'.$value.'¤'; + } - /* Serialize cookie content */ - if (isset($this->_content['checksum'])) unset($this->_content['checksum']); - foreach ($this->_content as $key => $value) - $cookie .= $key.'|'.$value.'¤'; + /* Add checksum to cookie */ + $cookie .= 'checksum|'.crc32($this->_salt.$cookie); + $this->_modified = false; + /* Cookies are encrypted for evident security reasons */ + return $this->_setcookie($cookie); + } - /* Add checksum to cookie */ - $cookie .= 'checksum|'.crc32($this->_salt.$cookie); - $this->_modified = false; - /* Cookies are encrypted for evident security reasons */ - return $this->_setcookie($cookie); - } + /** + * Get a family of variables (e.g. "filter_") + */ + public function getFamily($origin) + { + $result = array(); + if (count($this->_content) == 0) { + return $result; + } + foreach ($this->_content as $key => $value) { + if (strncmp($key, $origin, strlen($origin)) == 0) { + $result[$key] = $value; + } + } + return $result; + } - /** - * Get a family of variables (e.g. "filter_") - */ - public function getFamily($origin) - { - $result = array(); - if (count($this->_content) == 0) - return $result; - foreach ($this->_content as $key => $value) - if (strncmp($key, $origin, strlen($origin)) == 0) - $result[$key] = $value; - return $result; - } + /** + * + */ + public function unsetFamily($origin) + { + $family = $this->getFamily($origin); + foreach (array_keys($family) as $member) { + unset($this->$member); + } + } - /** - * - */ - public function unsetFamily($origin) - { - $family = $this->getFamily($origin); - foreach (array_keys($family) as $member) - unset($this->$member); - } + public function getAll() + { + return $this->_content; + } - public function getAll() - { - return $this->_content; - } + /** + * @return String name of cookie + */ + public function getName() + { + return $this->_name; + } - /** - * @return String name of cookie - */ - public function getName() - { - return $this->_name; - } - - /** - * Check if the cookie exists - * - * @since 1.5.0 - * @return bool - */ - public function exists() - { - return isset($_COOKIE[$this->_name]); - } + /** + * Check if the cookie exists + * + * @since 1.5.0 + * @return bool + */ + public function exists() + { + return isset($_COOKIE[$this->_name]); + } } diff --git a/classes/Country.php b/classes/Country.php index 30abd84f..a33a5d96 100644 --- a/classes/Country.php +++ b/classes/Country.php @@ -26,362 +26,397 @@ class CountryCore extends ObjectModel { - public $id; + public $id; - /** @var int Zone id which country belongs */ - public $id_zone; + /** @var int Zone id which country belongs */ + public $id_zone; - /** @var int Currency id which country belongs */ - public $id_currency; + /** @var int Currency id which country belongs */ + public $id_currency; - /** @var string 2 letters iso code */ - public $iso_code; + /** @var string 2 letters iso code */ + public $iso_code; - /** @var int international call prefix */ - public $call_prefix; + /** @var int international call prefix */ + public $call_prefix; - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var bool Contain states */ - public $contains_states; + /** @var bool Contain states */ + public $contains_states; - /** @var bool Need identification number dni/nif/nie */ - public $need_identification_number; + /** @var bool Need identification number dni/nif/nie */ + public $need_identification_number; - /** @var bool Need Zip Code */ - public $need_zip_code; + /** @var bool Need Zip Code */ + public $need_zip_code; - /** @var string Zip Code Format */ - public $zip_code_format; + /** @var string Zip Code Format */ + public $zip_code_format; - /** @var bool Display or not the tax incl./tax excl. mention in the front office */ - public $display_tax_label = true; + /** @var bool Display or not the tax incl./tax excl. mention in the front office */ + public $display_tax_label = true; - /** @var bool Status for delivery */ - public $active = true; + /** @var bool Status for delivery */ + public $active = true; - protected static $_idZones = array(); + protected static $_idZones = array(); - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'country', - 'primary' => 'id_country', - 'multilang' => true, - 'fields' => array( - 'id_zone' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'call_prefix' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'iso_code' => array('type' => self::TYPE_STRING, 'validate' => 'isLanguageIsoCode', 'required' => true, 'size' => 3), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'contains_states' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), - 'need_identification_number' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), - 'need_zip_code' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'zip_code_format' => array('type' => self::TYPE_STRING, 'validate' => 'isZipCodeFormat'), - 'display_tax_label' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'country', + 'primary' => 'id_country', + 'multilang' => true, + 'fields' => array( + 'id_zone' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'call_prefix' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'iso_code' => array('type' => self::TYPE_STRING, 'validate' => 'isLanguageIsoCode', 'required' => true, 'size' => 3), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'contains_states' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), + 'need_identification_number' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), + 'need_zip_code' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'zip_code_format' => array('type' => self::TYPE_STRING, 'validate' => 'isZipCodeFormat'), + 'display_tax_label' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), - ), - 'associations' => array( - 'zone' => array('type' => self::HAS_ONE), - 'currency' => array('type' => self::HAS_ONE), - ) - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), + ), + 'associations' => array( + 'zone' => array('type' => self::HAS_ONE), + 'currency' => array('type' => self::HAS_ONE), + ) + ); - protected static $cache_iso_by_id = array(); + protected static $cache_iso_by_id = array(); - protected $webserviceParameters = array( - 'objectsNodeName' => 'countries', - 'fields' => array( - 'id_zone' => array('xlink_resource'=> 'zones'), - 'id_currency' => array('xlink_resource'=> 'currencies'), - ), - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'countries', + 'fields' => array( + 'id_zone' => array('xlink_resource'=> 'zones'), + 'id_currency' => array('xlink_resource'=> 'currencies'), + ), + ); - public function delete() - { - if (!parent::delete()) - return false; - return Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'cart_rule_country WHERE id_country = '.(int)$this->id); - } + public function delete() + { + if (!parent::delete()) { + return false; + } + return Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'cart_rule_country WHERE id_country = '.(int)$this->id); + } - /** - * @brief Return available countries - * - * @param int $id_lang Language ID - * @param bool $active return only active coutries - * @param bool $contain_states return only country with states - * @param bool $list_states Include the states list with the returned list - * - * @return Array Countries and corresponding zones - */ - public static function getCountries($id_lang, $active = false, $contain_states = false, $list_states = true) - { - $countries = array(); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' + /** + * @brief Return available countries + * + * @param int $id_lang Language ID + * @param bool $active return only active coutries + * @param bool $contain_states return only country with states + * @param bool $list_states Include the states list with the returned list + * + * @return Array Countries and corresponding zones + */ + public static function getCountries($id_lang, $active = false, $contain_states = false, $list_states = true) + { + $countries = array(); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT cl.*,c.*, cl.`name` country, z.`name` zone FROM `'._DB_PREFIX_.'country` c '.Shop::addSqlAssociation('country', 'c').' LEFT JOIN `'._DB_PREFIX_.'country_lang` cl ON (c.`id_country` = cl.`id_country` AND cl.`id_lang` = '.(int)$id_lang.') LEFT JOIN `'._DB_PREFIX_.'zone` z ON (z.`id_zone` = c.`id_zone`) WHERE 1'.($active ? ' AND c.active = 1' : '').($contain_states ? ' AND c.`contains_states` = '.(int)$contain_states : '').' ORDER BY cl.name ASC'); - foreach ($result as $row) - $countries[$row['id_country']] = $row; + foreach ($result as $row) { + $countries[$row['id_country']] = $row; + } - if ($list_states) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('SELECT * FROM `'._DB_PREFIX_.'state` ORDER BY `name` ASC'); - foreach ($result as $row) - if (isset($countries[$row['id_country']]) && $row['active'] == 1) /* Does not keep the state if its country has been disabled and not selected */ - $countries[$row['id_country']]['states'][] = $row; - } - return $countries; - } + if ($list_states) { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('SELECT * FROM `'._DB_PREFIX_.'state` ORDER BY `name` ASC'); + foreach ($result as $row) { + if (isset($countries[$row['id_country']]) && $row['active'] == 1) { /* Does not keep the state if its country has been disabled and not selected */ + $countries[$row['id_country']]['states'][] = $row; + } + } + } + return $countries; + } - public static function getCountriesByIdShop($id_shop, $id_lang) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' + public static function getCountriesByIdShop($id_shop, $id_lang) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT * FROM `'._DB_PREFIX_.'country` c LEFT JOIN `'._DB_PREFIX_.'country_shop` cs ON (cs.`id_country`= c.`id_country`) LEFT JOIN `'._DB_PREFIX_.'country_lang` cl ON (c.`id_country` = cl.`id_country` AND cl.`id_lang` = '.(int)$id_lang.') WHERE `id_shop` = '.(int)$id_shop); - } + } - /** - * Get a country ID with its iso code - * - * @param string $iso_code Country iso code - * @param bool $active return only active coutries - * @return int Country ID - */ - public static function getByIso($iso_code, $active = false) - { - if (!Validate::isLanguageIsoCode($iso_code)) - die(Tools::displayError()); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + /** + * Get a country ID with its iso code + * + * @param string $iso_code Country iso code + * @param bool $active return only active coutries + * @return int Country ID + */ + public static function getByIso($iso_code, $active = false) + { + if (!Validate::isLanguageIsoCode($iso_code)) { + die(Tools::displayError()); + } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT `id_country` FROM `'._DB_PREFIX_.'country` WHERE `iso_code` = \''.pSQL(strtoupper($iso_code)).'\'' - .($active ? ' AND active = 1' : '') - ); - return (int)$result['id_country']; - } + .($active ? ' AND active = 1' : '') + ); - public static function getIdZone($id_country) - { - if (!Validate::isUnsignedId($id_country)) - die(Tools::displayError()); + if (isset($result['id_country'])) + { + return (int)$result['id_country']; + } + return false; + } - if (isset(self::$_idZones[$id_country])) - return self::$_idZones[$id_country]; + public static function getIdZone($id_country) + { + if (!Validate::isUnsignedId($id_country)) { + die(Tools::displayError()); + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + if (isset(self::$_idZones[$id_country])) { + return (int)self::$_idZones[$id_country]; + } + + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT `id_zone` FROM `'._DB_PREFIX_.'country` WHERE `id_country` = '.(int)$id_country); - self::$_idZones[$id_country] = $result['id_zone']; - return (int)$result['id_zone']; - } + if (isset($result['id_zone'])) + { + self::$_idZones[$id_country] = (int)$result['id_zone']; + return (int)$result['id_zone']; + } + return false; + } - /** - * Get a country name with its ID - * - * @param int $id_lang Language ID - * @param int $id_country Country ID - * @return string Country name - */ - public static function getNameById($id_lang, $id_country) - { - $key = 'country_getNameById_'.$id_country.'_'.$id_lang; - if (!Cache::isStored($key)) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Get a country name with its ID + * + * @param int $id_lang Language ID + * @param int $id_country Country ID + * @return string Country name + */ + public static function getNameById($id_lang, $id_country) + { + $key = 'country_getNameById_'.$id_country.'_'.$id_lang; + if (!Cache::isStored($key)) { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `name` FROM `'._DB_PREFIX_.'country_lang` WHERE `id_lang` = '.(int)$id_lang.' AND `id_country` = '.(int)$id_country - ); - Cache::store($key, $result); - return $result; - } - return Cache::retrieve($key); - } + ); + Cache::store($key, $result); + return $result; + } + return Cache::retrieve($key); + } - /** - * Get a country iso with its ID - * - * @param int $id_country Country ID - * @return string Country iso - */ - public static function getIsoById($id_country) - { - if (!isset(Country::$cache_iso_by_id[$id_country])) - { - Country::$cache_iso_by_id[$id_country] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Get a country iso with its ID + * + * @param int $id_country Country ID + * @return string Country iso + */ + public static function getIsoById($id_country) + { + if (!isset(Country::$cache_iso_by_id[$id_country])) { + Country::$cache_iso_by_id[$id_country] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `iso_code` FROM `'._DB_PREFIX_.'country` WHERE `id_country` = '.(int)$id_country); - } + } + if (isset(Country::$cache_iso_by_id[$id_country])) + { + return Country::$cache_iso_by_id[$id_country]; + } + return false; + } - return Country::$cache_iso_by_id[$id_country]; - } - - /** - * Get a country id with its name - * - * @param int $id_lang Language ID - * @param string $country Country Name - * @return int Country ID - */ - public static function getIdByName($id_lang = null, $country) - { - $sql = ' + /** + * Get a country id with its name + * + * @param int $id_lang Language ID + * @param string $country Country Name + * @return int Country ID + */ + public static function getIdByName($id_lang = null, $country) + { + $sql = ' SELECT `id_country` FROM `'._DB_PREFIX_.'country_lang` WHERE `name` = \''.pSQL($country).'\''; - if ($id_lang) - $sql .= ' AND `id_lang` = '.(int)$id_lang; + if ($id_lang) { + $sql .= ' AND `id_lang` = '.(int)$id_lang; + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); - return (int)$result['id_country']; - } + if (isset($result['id_country'])) + { + return (int)$result['id_country']; + } + return false; + } - public static function getNeedZipCode($id_country) - { - if (!(int)$id_country) - return false; + public static function getNeedZipCode($id_country) + { + if (!(int)$id_country) { + return false; + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `need_zip_code` FROM `'._DB_PREFIX_.'country` WHERE `id_country` = '.(int)$id_country); - } + } - public static function getZipCodeFormat($id_country) - { - if (!(int)$id_country) - return false; + public static function getZipCodeFormat($id_country) + { + if (!(int)$id_country) { + return false; + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + $zip_code_format = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `zip_code_format` FROM `'._DB_PREFIX_.'country` WHERE `id_country` = '.(int)$id_country); - } - /** - * Returns the default country Id - * - * @deprecated as of 1.5 use $context->country->id instead - * @return int default country id - */ - public static function getDefaultCountryId() - { - Tools::displayAsDeprecated(); - return Context::getContext()->country->id; - } + if (isset($zip_code_format) && $zip_code_format) + { + return $zip_code_format; + } + return false; + } - public static function getCountriesByZoneId($id_zone, $id_lang) - { - if (empty($id_zone) || empty($id_lang)) - die(Tools::displayError()); + /** + * Returns the default country Id + * + * @deprecated as of 1.5 use $context->country->id instead + * @return int default country id + */ + public static function getDefaultCountryId() + { + Tools::displayAsDeprecated(); + return Context::getContext()->country->id; + } - $sql = ' SELECT DISTINCT c.*, cl.* + public static function getCountriesByZoneId($id_zone, $id_lang) + { + if (empty($id_zone) || empty($id_lang)) { + die(Tools::displayError()); + } + + $sql = ' SELECT DISTINCT c.*, cl.* FROM `'._DB_PREFIX_.'country` c '.Shop::addSqlAssociation('country', 'c', false).' LEFT JOIN `'._DB_PREFIX_.'state` s ON (s.`id_country` = c.`id_country`) LEFT JOIN `'._DB_PREFIX_.'country_lang` cl ON (c.`id_country` = cl.`id_country`) WHERE (c.`id_zone` = '.(int)$id_zone.' OR s.`id_zone` = '.(int)$id_zone.') AND `id_lang` = '.(int)$id_lang; - return Db::getInstance()->executeS($sql); - } + return Db::getInstance()->executeS($sql); + } - public function isNeedDni() - { - return Country::isNeedDniByCountryId($this->id); - } + public function isNeedDni() + { + return Country::isNeedDniByCountryId($this->id); + } - public static function isNeedDniByCountryId($id_country) - { - return (bool)Db::getInstance()->getValue(' + public static function isNeedDniByCountryId($id_country) + { + return (bool)Db::getInstance()->getValue(' SELECT `need_identification_number` FROM `'._DB_PREFIX_.'country` WHERE `id_country` = '.(int)$id_country); - } + } - public static function containsStates($id_country) - { - return (bool)Db::getInstance()->getValue(' + public static function containsStates($id_country) + { + return (bool)Db::getInstance()->getValue(' SELECT `contains_states` FROM `'._DB_PREFIX_.'country` WHERE `id_country` = '.(int)$id_country); - } + } - /** - * @param $ids_countries - * @param $id_zone - * @return bool - */ - public function affectZoneToSelection($ids_countries, $id_zone) - { - // cast every array values to int (security) - $ids_countries = array_map('intval', $ids_countries); - return Db::getInstance()->execute(' + /** + * @param $ids_countries + * @param $id_zone + * @return bool + */ + public function affectZoneToSelection($ids_countries, $id_zone) + { + // cast every array values to int (security) + $ids_countries = array_map('intval', $ids_countries); + return Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'country` SET `id_zone` = '.(int)$id_zone.' WHERE `id_country` IN ('.implode(',', $ids_countries).') '); - } + } - /** - * Replace letters of zip code format And check this format on the zip code - * @param $zip_code - * @return (bool) - */ - public function checkZipCode($zip_code) - { - $zip_regexp = '/^'.$this->zip_code_format.'$/ui'; - $zip_regexp = str_replace(' ', '( |)', $zip_regexp); - $zip_regexp = str_replace('-', '(-|)', $zip_regexp); - $zip_regexp = str_replace('N', '[0-9]', $zip_regexp); - $zip_regexp = str_replace('L', '[a-zA-Z]', $zip_regexp); - $zip_regexp = str_replace('C', $this->iso_code, $zip_regexp); + /** + * Replace letters of zip code format And check this format on the zip code + * @param $zip_code + * @return (bool) + */ + public function checkZipCode($zip_code) + { + $zip_regexp = '/^'.$this->zip_code_format.'$/ui'; + $zip_regexp = str_replace(' ', '( |)', $zip_regexp); + $zip_regexp = str_replace('-', '(-|)', $zip_regexp); + $zip_regexp = str_replace('N', '[0-9]', $zip_regexp); + $zip_regexp = str_replace('L', '[a-zA-Z]', $zip_regexp); + $zip_regexp = str_replace('C', $this->iso_code, $zip_regexp); - return (bool)preg_match($zip_regexp, $zip_code); - } + return (bool)preg_match($zip_regexp, $zip_code); + } - public static function addModuleRestrictions(array $shops = array(), array $countries = array(), array $modules = array()) - { - if (!count($shops)) - $shops = Shop::getShops(true, null, true); + public static function addModuleRestrictions(array $shops = array(), array $countries = array(), array $modules = array()) + { + if (!count($shops)) { + $shops = Shop::getShops(true, null, true); + } - if (!count($countries)) - $countries = Country::getCountries((int)Context::getContext()->cookie->id_lang); + if (!count($countries)) { + $countries = Country::getCountries((int)Context::getContext()->cookie->id_lang); + } - if (!count($modules)) - $modules = Module::getPaymentModules(); + if (!count($modules)) { + $modules = Module::getPaymentModules(); + } - $sql = false; - foreach ($shops as $id_shop) - foreach ($countries as $country) - foreach ($modules as $module) - $sql .= '('.(int)$module['id_module'].', '.(int)$id_shop.', '.(int)$country['id_country'].'),'; + $sql = false; + foreach ($shops as $id_shop) { + foreach ($countries as $country) { + foreach ($modules as $module) { + $sql .= '('.(int)$module['id_module'].', '.(int)$id_shop.', '.(int)$country['id_country'].'),'; + } + } + } - if ($sql) - { - $sql = 'INSERT IGNORE INTO `'._DB_PREFIX_.'module_country` (`id_module`, `id_shop`, `id_country`) VALUES '.rtrim($sql, ','); - return Db::getInstance()->execute($sql); - } - else - return true; - } + if ($sql) { + $sql = 'INSERT IGNORE INTO `'._DB_PREFIX_.'module_country` (`id_module`, `id_shop`, `id_country`) VALUES '.rtrim($sql, ','); + return Db::getInstance()->execute($sql); + } else { + return true; + } + } - public function add($autodate = true, $null_values = false) - { - $return = parent::add($autodate, $null_values) && self::addModuleRestrictions(array(), array(array('id_country' => $this->id)), array()); - return $return; - } -} \ No newline at end of file + public function add($autodate = true, $null_values = false) + { + $return = parent::add($autodate, $null_values) && self::addModuleRestrictions(array(), array(array('id_country' => $this->id)), array()); + return $return; + } +} diff --git a/classes/County.php b/classes/County.php index ba8eaefb..8cba80d5 100644 --- a/classes/County.php +++ b/classes/County.php @@ -30,129 +30,129 @@ */ class CountyCore extends ObjectModel { - public $id; - public $name; - public $id_state; - public $active; + public $id; + public $name; + public $id_state; + public $active; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'county', - 'primary' => 'id_county', - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), - 'id_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'county', + 'primary' => 'id_county', + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), + 'id_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + ), + ); - protected static $_cache_get_counties = array(); - protected static $_cache_county_zipcode = array(); + protected static $_cache_get_counties = array(); + protected static $_cache_county_zipcode = array(); - const USE_BOTH_TAX = 0; - const USE_COUNTY_TAX = 1; - const USE_STATE_TAX = 2; + const USE_BOTH_TAX = 0; + const USE_COUNTY_TAX = 1; + const USE_STATE_TAX = 2; - protected $webserviceParameters = array( - 'fields' => array( - 'id_state' => array('xlink_resource'=> 'states'), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_state' => array('xlink_resource'=> 'states'), + ), + ); - public function delete() - { - return true; - } + public function delete() + { + return true; + } - /** - * @deprecated since 1.5 - */ - public static function getCounties($id_state) - { - Tools::displayAsDeprecated(); - return false; - } + /** + * @deprecated since 1.5 + */ + public static function getCounties($id_state) + { + Tools::displayAsDeprecated(); + return false; + } - /** - * @deprecated since 1.5 - */ - public function getZipCodes() - { - Tools::displayAsDeprecated(); - return false; - } + /** + * @deprecated since 1.5 + */ + public function getZipCodes() + { + Tools::displayAsDeprecated(); + return false; + } - /** - * @deprecated since 1.5 - */ - public function addZipCodes($zip_codes) - { - Tools::displayAsDeprecated(); - return true; - } + /** + * @deprecated since 1.5 + */ + public function addZipCodes($zip_codes) + { + Tools::displayAsDeprecated(); + return true; + } - /** - * @deprecated since 1.5 - */ - public function removeZipCodes($zip_codes) - { - Tools::displayAsDeprecated(); - return true; - } + /** + * @deprecated since 1.5 + */ + public function removeZipCodes($zip_codes) + { + Tools::displayAsDeprecated(); + return true; + } - /** - * @deprecated since 1.5 - */ - public function breakDownZipCode($zip_codes) - { - Tools::displayAsDeprecated(); - return array(0,0); - } + /** + * @deprecated since 1.5 + */ + public function breakDownZipCode($zip_codes) + { + Tools::displayAsDeprecated(); + return array(0,0); + } - /** - * @deprecated since 1.5 - */ - public static function getIdCountyByZipCode($id_state, $zip_code) - { - Tools::displayAsDeprecated(); - return false; - } + /** + * @deprecated since 1.5 + */ + public static function getIdCountyByZipCode($id_state, $zip_code) + { + Tools::displayAsDeprecated(); + return false; + } - /** - * @deprecated since 1.5 - */ - public function isZipCodeRangePresent($zip_codes) - { - Tools::displayAsDeprecated(); - return false; - } + /** + * @deprecated since 1.5 + */ + public function isZipCodeRangePresent($zip_codes) + { + Tools::displayAsDeprecated(); + return false; + } - /** - * @deprecated since 1.5 - */ - public function isZipCodePresent($zip_code) - { - Tools::displayAsDeprecated(); - return false; - } + /** + * @deprecated since 1.5 + */ + public function isZipCodePresent($zip_code) + { + Tools::displayAsDeprecated(); + return false; + } - /** - * @deprecated since 1.5 - */ - public static function deleteZipCodeByIdCounty($id_county) - { - Tools::displayAsDeprecated(); - return true; - } + /** + * @deprecated since 1.5 + */ + public static function deleteZipCodeByIdCounty($id_county) + { + Tools::displayAsDeprecated(); + return true; + } - /** - * @deprecated since 1.5 - */ - public static function getIdCountyByNameAndIdState($name, $id_state) - { - Tools::displayAsDeprecated(); - return false; - } -} \ No newline at end of file + /** + * @deprecated since 1.5 + */ + public static function getIdCountyByNameAndIdState($name, $id_state) + { + Tools::displayAsDeprecated(); + return false; + } +} diff --git a/classes/Currency.php b/classes/Currency.php index 27b839d8..27e7ada8 100644 --- a/classes/Currency.php +++ b/classes/Currency.php @@ -26,235 +26,248 @@ class CurrencyCore extends ObjectModel { - public $id; + public $id; - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var string Iso code */ - public $iso_code; + /** @var string Iso code */ + public $iso_code; - /** @var string Iso code numeric */ - public $iso_code_num; + /** @var string Iso code numeric */ + public $iso_code_num; - /** @var string Symbol for short display */ - public $sign; + /** @var string Symbol for short display */ + public $sign; - /** @var int bool used for displaying blank between sign and price */ - public $blank; + /** @var int bool used for displaying blank between sign and price */ + public $blank; - /** @var string exchange rate from euros */ - public $conversion_rate; + /** @var string exchange rate from euros */ + public $conversion_rate; - /** @var bool True if currency has been deleted (staying in database as deleted) */ - public $deleted = 0; + /** @var bool True if currency has been deleted (staying in database as deleted) */ + public $deleted = 0; - /** @var int ID used for displaying prices */ - public $format; + /** @var int ID used for displaying prices */ + public $format; - /** @var int bool Display decimals on prices */ - public $decimals; + /** @var int bool Display decimals on prices */ + public $decimals; - /** @var int bool active */ - public $active; + /** @var int bool active */ + public $active; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'currency', - 'primary' => 'id_currency', - 'multilang_shop' => true, - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), - 'iso_code' => array('type' => self::TYPE_STRING, 'validate' => 'isLanguageIsoCode', 'required' => true, 'size' => 3), - 'iso_code_num' => array('type' => self::TYPE_STRING, 'validate' => 'isNumericIsoCode', 'size' => 3), - 'blank' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'sign' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 8), - 'format' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'decimals' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), - 'conversion_rate' =>array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => true, 'shop' => true), - 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'currency', + 'primary' => 'id_currency', + 'multilang_shop' => true, + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), + 'iso_code' => array('type' => self::TYPE_STRING, 'validate' => 'isLanguageIsoCode', 'required' => true, 'size' => 3), + 'iso_code_num' => array('type' => self::TYPE_STRING, 'validate' => 'isNumericIsoCode', 'size' => 3), + 'blank' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'sign' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 8), + 'format' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'decimals' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), + 'conversion_rate' =>array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => true, 'shop' => true), + 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + ), + ); - /** @var array Currency cache */ - static protected $currencies = array(); - protected static $countActiveCurrencies = array(); + /** @var array Currency cache */ + protected static $currencies = array(); + protected static $countActiveCurrencies = array(); - protected $webserviceParameters = array( - 'objectsNodeName' => 'currencies', - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'currencies', + ); - /** - * contains the sign to display before price, according to its format - * @var string - */ - public $prefix = null; - /** - * contains the sign to display after price, according to its format - * @var string - */ - public $suffix = null; + /** + * contains the sign to display before price, according to its format + * @var string + */ + public $prefix = null; + /** + * contains the sign to display after price, according to its format + * @var string + */ + public $suffix = null; - public function __construct($id = null, $id_lang = null, $id_shop = null) - { - parent::__construct($id, $id_lang, $id_shop); - // prefix and suffix are convenient shortcut for displaying - // price sign before or after the price number - $this->prefix = $this->format % 2 != 0 ? $this->sign.' ' : ''; - $this->suffix = $this->format % 2 == 0 ? ' '.$this->sign : ''; - if (!$this->conversion_rate) - $this->conversion_rate = 1; - } - /** - * Overriding check if currency rate is not empty and if currency with the same iso code already exists. - * If it's true, currency is not added. - * - * @see ObjectModelCore::add() - */ - public function add($autodate = true, $nullValues = false) - { - if ((float)$this->conversion_rate <= 0) - return false; - return Currency::exists($this->iso_code, $this->iso_code_num) ? false : parent::add($autodate, $nullValues); - } + public function __construct($id = null, $id_lang = null, $id_shop = null) + { + parent::__construct($id, $id_lang, $id_shop); + // prefix and suffix are convenient shortcut for displaying + // price sign before or after the price number + $this->prefix = $this->format % 2 != 0 ? $this->sign.' ' : ''; + $this->suffix = $this->format % 2 == 0 ? ' '.$this->sign : ''; + if (!$this->conversion_rate) { + $this->conversion_rate = 1; + } + } + /** + * Overriding check if currency rate is not empty and if currency with the same iso code already exists. + * If it's true, currency is not added. + * + * @see ObjectModelCore::add() + */ + public function add($autodate = true, $nullValues = false) + { + if ((float)$this->conversion_rate <= 0) { + return false; + } + return Currency::exists($this->iso_code, $this->iso_code_num) ? false : parent::add($autodate, $nullValues); + } - public function update($autodate = true, $nullValues = false) - { - if ((float)$this->conversion_rate <= 0) - return false; - return parent::update($autodate, $nullValues); - } + public function update($autodate = true, $nullValues = false) + { + if ((float)$this->conversion_rate <= 0) { + return false; + } + return parent::update($autodate, $nullValues); + } - /** - * Check if a curency already exists. - * - * @param int|string $iso_code int for iso code number string for iso code - * @return bool - */ - public static function exists($iso_code, $iso_code_num, $id_shop = 0) - { - if (is_int($iso_code)) - $id_currency_exists = Currency::getIdByIsoCodeNum((int)$iso_code_num, (int)$id_shop); - else - $id_currency_exists = Currency::getIdByIsoCode($iso_code, (int)$id_shop); + /** + * Check if a curency already exists. + * + * @param int|string $iso_code int for iso code number string for iso code + * @return bool + */ + public static function exists($iso_code, $iso_code_num, $id_shop = 0) + { + if (is_int($iso_code)) { + $id_currency_exists = Currency::getIdByIsoCodeNum((int)$iso_code_num, (int)$id_shop); + } else { + $id_currency_exists = Currency::getIdByIsoCode($iso_code, (int)$id_shop); + } - if ($id_currency_exists) - return true; - else - return false; - } + if ($id_currency_exists) { + return true; + } else { + return false; + } + } - public function deleteSelection($selection) - { - if (!is_array($selection)) - return false; + public function deleteSelection($selection) + { + if (!is_array($selection)) { + return false; + } - $res = array(); - foreach ($selection as $id) - { - $obj = new Currency((int)$id); - $res[$id] = $obj->delete(); - } + $res = array(); + foreach ($selection as $id) { + $obj = new Currency((int)$id); + $res[$id] = $obj->delete(); + } - foreach ($res as $value) - if (!$value) - return false; - return true; - } + foreach ($res as $value) { + if (!$value) { + return false; + } + } + return true; + } - public function delete() - { - if ($this->id == Configuration::get('PS_CURRENCY_DEFAULT')) - { - $result = Db::getInstance()->getRow('SELECT `id_currency` FROM '._DB_PREFIX_.'currency WHERE `id_currency` != '.(int)($this->id).' AND `deleted` = 0'); - if (!$result['id_currency']) - return false; - Configuration::updateValue('PS_CURRENCY_DEFAULT', $result['id_currency']); - } - $this->deleted = 1; - return $this->update(); - } + public function delete() + { + if ($this->id == Configuration::get('PS_CURRENCY_DEFAULT')) { + $result = Db::getInstance()->getRow('SELECT `id_currency` FROM '._DB_PREFIX_.'currency WHERE `id_currency` != '.(int)($this->id).' AND `deleted` = 0'); + if (!$result['id_currency']) { + return false; + } + Configuration::updateValue('PS_CURRENCY_DEFAULT', $result['id_currency']); + } + $this->deleted = 1; + return $this->update(); + } - /** - * Return formated sign - * - * @param string $side left or right - * @return string formated sign - */ - public function getSign($side = null) - { - if (!$side) - return $this->sign; - $formated_strings = array( - 'left' => $this->sign.' ', - 'right' => ' '.$this->sign - ); + /** + * Return formated sign + * + * @param string $side left or right + * @return string formated sign + */ + public function getSign($side = null) + { + if (!$side) { + return $this->sign; + } + $formated_strings = array( + 'left' => $this->sign.' ', + 'right' => ' '.$this->sign + ); - $formats = array( - 1 => array('left' => &$formated_strings['left'], 'right' => ''), - 2 => array('left' => '', 'right' => &$formated_strings['right']), - 3 => array('left' => &$formated_strings['left'], 'right' => ''), - 4 => array('left' => '', 'right' => &$formated_strings['right']), - 5 => array('left' => '', 'right' => &$formated_strings['right']) - ); - if (isset($formats[$this->format][$side])) - return ($formats[$this->format][$side]); - return $this->sign; - } + $formats = array( + 1 => array('left' => &$formated_strings['left'], 'right' => ''), + 2 => array('left' => '', 'right' => &$formated_strings['right']), + 3 => array('left' => &$formated_strings['left'], 'right' => ''), + 4 => array('left' => '', 'right' => &$formated_strings['right']), + 5 => array('left' => '', 'right' => &$formated_strings['right']) + ); + if (isset($formats[$this->format][$side])) { + return ($formats[$this->format][$side]); + } + return $this->sign; + } - /** - * Return available currencies - * - * @return array Currencies - */ - public static function getCurrencies($object = false, $active = true, $group_by = false) - { - $tab = Db::getInstance()->executeS(' + /** + * Return available currencies + * + * @return array Currencies + */ + public static function getCurrencies($object = false, $active = true, $group_by = false) + { + $tab = Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'currency` c '.Shop::addSqlAssociation('currency', 'c'). - ' WHERE `deleted` = 0'. - ($active ? ' AND c.`active` = 1' : ''). - ($group_by ? ' GROUP BY c.`id_currency`' : ''). - ' ORDER BY `name` ASC'); - if ($object) - foreach ($tab as $key => $currency) - $tab[$key] = Currency::getCurrencyInstance($currency['id_currency']); - return $tab; - } + ' WHERE `deleted` = 0'. + ($active ? ' AND c.`active` = 1' : ''). + ($group_by ? ' GROUP BY c.`id_currency`' : ''). + ' ORDER BY `name` ASC'); + if ($object) { + foreach ($tab as $key => $currency) { + $tab[$key] = Currency::getCurrencyInstance($currency['id_currency']); + } + } + return $tab; + } - public static function getCurrenciesByIdShop($id_shop = 0) - { - return Db::getInstance()->executeS(' + public static function getCurrenciesByIdShop($id_shop = 0) + { + return Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'currency` c LEFT JOIN `'._DB_PREFIX_.'currency_shop` cs ON (cs.`id_currency` = c.`id_currency`) '.($id_shop ? ' WHERE cs.`id_shop` = '.(int)$id_shop : '').' ORDER BY `name` ASC'); - } + } - public static function getPaymentCurrenciesSpecial($id_module, $id_shop = null) - { - if (is_null($id_shop)) - $id_shop = Context::getContext()->shop->id; + public static function getPaymentCurrenciesSpecial($id_module, $id_shop = null) + { + if (is_null($id_shop)) { + $id_shop = Context::getContext()->shop->id; + } - $sql = 'SELECT * + $sql = 'SELECT * FROM '._DB_PREFIX_.'module_currency WHERE id_module = '.(int)$id_module.' AND id_shop ='.(int)$id_shop; - return Db::getInstance()->getRow($sql); - } + return Db::getInstance()->getRow($sql); + } - public static function getPaymentCurrencies($id_module, $id_shop = null) - { - if (is_null($id_shop)) - $id_shop = Context::getContext()->shop->id; + public static function getPaymentCurrencies($id_module, $id_shop = null) + { + if (is_null($id_shop)) { + $id_shop = Context::getContext()->shop->id; + } - $sql = 'SELECT c.* + $sql = 'SELECT c.* FROM `'._DB_PREFIX_.'module_currency` mc LEFT JOIN `'._DB_PREFIX_.'currency` c ON c.`id_currency` = mc.`id_currency` WHERE c.`deleted` = 0 @@ -262,202 +275,207 @@ class CurrencyCore extends ObjectModel AND c.`active` = 1 AND mc.id_shop = '.(int)$id_shop.' ORDER BY c.`name` ASC'; - return Db::getInstance()->executeS($sql); - } + return Db::getInstance()->executeS($sql); + } - public static function checkPaymentCurrencies($id_module, $id_shop = null) - { - if (empty($id_module)) - return false; + public static function checkPaymentCurrencies($id_module, $id_shop = null) + { + if (empty($id_module)) { + return false; + } - if (is_null($id_shop)) - $id_shop = Context::getContext()->shop->id; + if (is_null($id_shop)) { + $id_shop = Context::getContext()->shop->id; + } - $sql = 'SELECT * + $sql = 'SELECT * FROM `'._DB_PREFIX_.'module_currency` WHERE `id_module` = '.(int)$id_module.' AND `id_shop` = '.(int)$id_shop; - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + } - public static function getCurrency($id_currency) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + public static function getCurrency($id_currency) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT * FROM `'._DB_PREFIX_.'currency` WHERE `deleted` = 0 AND `id_currency` = '.(int)($id_currency)); - } + } - /** - * @param $iso_code - * @param int $id_shop - * @return int - */ - public static function getIdByIsoCode($iso_code, $id_shop = 0) - { - $cache_id = 'Currency::getIdByIsoCode_'.pSQL($iso_code).'-'.(int)$id_shop; - if (!Cache::isStored($cache_id)) - { - $query = Currency::getIdByQuery($id_shop); - $query->where('iso_code = \''.pSQL($iso_code).'\''); + /** + * @param $iso_code + * @param int $id_shop + * @return int + */ + public static function getIdByIsoCode($iso_code, $id_shop = 0) + { + $cache_id = 'Currency::getIdByIsoCode_'.pSQL($iso_code).'-'.(int)$id_shop; + if (!Cache::isStored($cache_id)) { + $query = Currency::getIdByQuery($id_shop); + $query->where('iso_code = \''.pSQL($iso_code).'\''); - $result = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query->build()); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + $result = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query->build()); + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * @param $iso_code_num - * @param int $id_shop - * @return int - */ - public static function getIdByIsoCodeNum($iso_code_num, $id_shop = 0) - { - $query = Currency::getIdByQuery($id_shop); - $query->where('iso_code_num = \''.pSQL($iso_code_num).'\''); + /** + * @param $iso_code_num + * @param int $id_shop + * @return int + */ + public static function getIdByIsoCodeNum($iso_code_num, $id_shop = 0) + { + $query = Currency::getIdByQuery($id_shop); + $query->where('iso_code_num = \''.pSQL($iso_code_num).'\''); - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query->build()); - } + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query->build()); + } - /** - * @param int $id_shop - * @return DbQuery - */ - public static function getIdByQuery($id_shop = 0) - { - $query = new DbQuery(); - $query->select('c.id_currency'); - $query->from('currency', 'c'); - $query->where('deleted = 0'); + /** + * @param int $id_shop + * @return DbQuery + */ + public static function getIdByQuery($id_shop = 0) + { + $query = new DbQuery(); + $query->select('c.id_currency'); + $query->from('currency', 'c'); + $query->where('deleted = 0'); - if (Shop::isFeatureActive() && $id_shop > 0) - { - $query->leftJoin('currency_shop', 'cs', 'cs.id_currency = c.id_currency'); - $query->where('id_shop = '.(int)$id_shop); - } - return $query; - } + if (Shop::isFeatureActive() && $id_shop > 0) { + $query->leftJoin('currency_shop', 'cs', 'cs.id_currency = c.id_currency'); + $query->where('id_shop = '.(int)$id_shop); + } + return $query; + } - /** - * Refresh the currency exchange rate - * The XML file define exchange rate for each from a default currency ($isoCodeSource). - * - * @param SimpleXMLElement $data XML content which contains all the exchange rates - * @param string $isoCodeSource The default currency used in the XML file - * @param Currency $defaultCurrency The default currency object - */ - public function refreshCurrency($data, $isoCodeSource, $defaultCurrency) - { - // fetch the exchange rate of the default currency - $exchange_rate = 1; - $tmp = $this->conversion_rate; - if ($defaultCurrency->iso_code != $isoCodeSource) - { - foreach ($data->currency as $currency) - if ($currency['iso_code'] == $defaultCurrency->iso_code) - { - $exchange_rate = round((float)$currency['rate'], 6); - break; - } - } + /** + * Refresh the currency exchange rate + * The XML file define exchange rate for each from a default currency ($isoCodeSource). + * + * @param SimpleXMLElement $data XML content which contains all the exchange rates + * @param string $isoCodeSource The default currency used in the XML file + * @param Currency $defaultCurrency The default currency object + */ + public function refreshCurrency($data, $isoCodeSource, $defaultCurrency) + { + // fetch the exchange rate of the default currency + $exchange_rate = 1; + $tmp = $this->conversion_rate; + if ($defaultCurrency->iso_code != $isoCodeSource) { + foreach ($data->currency as $currency) { + if ($currency['iso_code'] == $defaultCurrency->iso_code) { + $exchange_rate = round((float)$currency['rate'], 6); + break; + } + } + } - if ($defaultCurrency->iso_code == $this->iso_code) - $this->conversion_rate = 1; - else - { - if ($this->iso_code == $isoCodeSource) - $rate = 1; - else - { - foreach ($data->currency as $obj) - if ($this->iso_code == strval($obj['iso_code'])) - { - $rate = (float)$obj['rate']; - break; - } - } + if ($defaultCurrency->iso_code == $this->iso_code) { + $this->conversion_rate = 1; + } else { + if ($this->iso_code == $isoCodeSource) { + $rate = 1; + } else { + foreach ($data->currency as $obj) { + if ($this->iso_code == strval($obj['iso_code'])) { + $rate = (float)$obj['rate']; + break; + } + } + } - if (isset($rate)) - $this->conversion_rate = round($rate / $exchange_rate, 6); - } + if (isset($rate)) { + $this->conversion_rate = round($rate / $exchange_rate, 6); + } + } - if ($tmp != $this->conversion_rate) - $this->update(); - } + if ($tmp != $this->conversion_rate) { + $this->update(); + } + } - public static function getDefaultCurrency() - { - $id_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT'); - if ($id_currency == 0) - return false; + public static function getDefaultCurrency() + { + $id_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT'); + if ($id_currency == 0) { + return false; + } - return new Currency($id_currency); - } + return new Currency($id_currency); + } - public static function refreshCurrencies() - { - // Parse - if (!$feed = Tools::simplexml_load_file(_PS_CURRENCY_FEED_URL_)) - return Tools::displayError('Cannot parse feed.'); + public static function refreshCurrencies() + { + // Parse + if (!$feed = Tools::simplexml_load_file(_PS_CURRENCY_FEED_URL_)) { + return Tools::displayError('Cannot parse feed.'); + } - // Default feed currency (EUR) - $isoCodeSource = strval($feed->source['iso_code']); + // Default feed currency (EUR) + $isoCodeSource = strval($feed->source['iso_code']); - if (!$default_currency = Currency::getDefaultCurrency()) - return Tools::displayError('No default currency'); + if (!$default_currency = Currency::getDefaultCurrency()) { + return Tools::displayError('No default currency'); + } - $currencies = Currency::getCurrencies(true, false, true); - foreach ($currencies as $currency) - { - /** @var Currency $currency */ - if ($currency->id != $default_currency->id) - $currency->refreshCurrency($feed->list, $isoCodeSource, $default_currency); - } - } + $currencies = Currency::getCurrencies(true, false, true); + foreach ($currencies as $currency) { + /** @var Currency $currency */ + if ($currency->id != $default_currency->id) { + $currency->refreshCurrency($feed->list, $isoCodeSource, $default_currency); + } + } + } - /** - * Get current currency - * - * @deprecated as of 1.5 use $context->currency instead - * @return Currency - */ - public static function getCurrent() - { - Tools::displayAsDeprecated(); - return Context::getContext()->currency; - } + /** + * Get current currency + * + * @deprecated as of 1.5 use $context->currency instead + * @return Currency + */ + public static function getCurrent() + { + Tools::displayAsDeprecated(); + return Context::getContext()->currency; + } - public static function getCurrencyInstance($id) - { - if (!isset(self::$currencies[$id])) - self::$currencies[(int)($id)] = new Currency($id); - return self::$currencies[(int)($id)]; - } + public static function getCurrencyInstance($id) + { + if (!isset(self::$currencies[$id])) { + self::$currencies[(int)($id)] = new Currency($id); + } + return self::$currencies[(int)($id)]; + } - public function getConversationRate() - { - return $this->id != (int)Configuration::get('PS_CURRENCY_DEFAULT') ? $this->conversion_rate : 1; - } + public function getConversationRate() + { + return $this->id != (int)Configuration::get('PS_CURRENCY_DEFAULT') ? $this->conversion_rate : 1; + } - public static function countActiveCurrencies($id_shop = null) - { - if ($id_shop === null) - $id_shop = (int)Context::getContext()->shop->id; + public static function countActiveCurrencies($id_shop = null) + { + if ($id_shop === null) { + $id_shop = (int)Context::getContext()->shop->id; + } - if (!isset(self::$countActiveCurrencies[$id_shop])) - self::$countActiveCurrencies[$id_shop] = Db::getInstance()->getValue(' + if (!isset(self::$countActiveCurrencies[$id_shop])) { + self::$countActiveCurrencies[$id_shop] = Db::getInstance()->getValue(' SELECT COUNT(DISTINCT c.id_currency) FROM `'._DB_PREFIX_.'currency` c LEFT JOIN '._DB_PREFIX_.'currency_shop cs ON (cs.id_currency = c.id_currency AND cs.id_shop = '.(int)$id_shop.') WHERE c.`active` = 1 '); - return self::$countActiveCurrencies[$id_shop]; - } + } + return self::$countActiveCurrencies[$id_shop]; + } - public static function isMultiCurrencyActivated($id_shop = null) - { - return (Currency::countActiveCurrencies($id_shop) > 1); - } + public static function isMultiCurrencyActivated($id_shop = null) + { + return (Currency::countActiveCurrencies($id_shop) > 1); + } } diff --git a/classes/Customer.php b/classes/Customer.php index f1c1675e..9438e0c1 100644 --- a/classes/Customer.php +++ b/classes/Customer.php @@ -26,296 +26,299 @@ class CustomerCore extends ObjectModel { - public $id; + public $id; - public $id_shop; + public $id_shop; - public $id_shop_group; + public $id_shop_group; - /** @var string Secure key */ - public $secure_key; + /** @var string Secure key */ + public $secure_key; - /** @var string protected note */ - public $note; + /** @var string protected note */ + public $note; - /** @var int Gender ID */ - public $id_gender = 0; + /** @var int Gender ID */ + public $id_gender = 0; - /** @var int Default group ID */ - public $id_default_group; + /** @var int Default group ID */ + public $id_default_group; - /** @var int Current language used by the customer */ - public $id_lang; + /** @var int Current language used by the customer */ + public $id_lang; - /** @var string Lastname */ - public $lastname; + /** @var string Lastname */ + public $lastname; - /** @var string Firstname */ - public $firstname; + /** @var string Firstname */ + public $firstname; - /** @var string Birthday (yyyy-mm-dd) */ - public $birthday = null; + /** @var string Birthday (yyyy-mm-dd) */ + public $birthday = null; - /** @var string e-mail */ - public $email; + /** @var string e-mail */ + public $email; - /** @var bool Newsletter subscription */ - public $newsletter; + /** @var bool Newsletter subscription */ + public $newsletter; - /** @var string Newsletter ip registration */ - public $ip_registration_newsletter; + /** @var string Newsletter ip registration */ + public $ip_registration_newsletter; - /** @var string Newsletter ip registration */ - public $newsletter_date_add; + /** @var string Newsletter ip registration */ + public $newsletter_date_add; - /** @var bool Opt-in subscription */ - public $optin; + /** @var bool Opt-in subscription */ + public $optin; - /** @var string WebSite **/ - public $website; + /** @var string WebSite **/ + public $website; - /** @var string Company */ - public $company; + /** @var string Company */ + public $company; - /** @var string SIRET */ - public $siret; + /** @var string SIRET */ + public $siret; - /** @var string APE */ - public $ape; + /** @var string APE */ + public $ape; - /** @var float Outstanding allow amount (B2B opt) */ - public $outstanding_allow_amount = 0; + /** @var float Outstanding allow amount (B2B opt) */ + public $outstanding_allow_amount = 0; - /** @var int Show public prices (B2B opt) */ - public $show_public_prices = 0; + /** @var int Show public prices (B2B opt) */ + public $show_public_prices = 0; - /** @var int Risk ID (B2B opt) */ - public $id_risk; + /** @var int Risk ID (B2B opt) */ + public $id_risk; - /** @var int Max payment day */ - public $max_payment_days = 0; + /** @var int Max payment day */ + public $max_payment_days = 0; - /** @var int Password */ - public $passwd; + /** @var int Password */ + public $passwd; - /** @var string Datetime Password */ - public $last_passwd_gen; + /** @var string Datetime Password */ + public $last_passwd_gen; - /** @var bool Status */ - public $active = true; + /** @var bool Status */ + public $active = true; - /** @var bool Status */ - public $is_guest = 0; + /** @var bool Status */ + public $is_guest = 0; - /** @var bool True if carrier has been deleted (staying in database as deleted) */ - public $deleted = 0; + /** @var bool True if carrier has been deleted (staying in database as deleted) */ + public $deleted = 0; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** @var string Object last modification date */ - public $date_upd; + /** @var string Object last modification date */ + public $date_upd; - public $years; - public $days; - public $months; + public $years; + public $days; + public $months; - /** @var int customer id_country as determined by geolocation */ - public $geoloc_id_country; - /** @var int customer id_state as determined by geolocation */ - public $geoloc_id_state; - /** @var string customer postcode as determined by geolocation */ - public $geoloc_postcode; + /** @var int customer id_country as determined by geolocation */ + public $geoloc_id_country; + /** @var int customer id_state as determined by geolocation */ + public $geoloc_id_state; + /** @var string customer postcode as determined by geolocation */ + public $geoloc_postcode; - /** @var bool is the customer logged in */ - public $logged = 0; + /** @var bool is the customer logged in */ + public $logged = 0; - /** @var int id_guest meaning the guest table, not the guest customer */ - public $id_guest; + /** @var int id_guest meaning the guest table, not the guest customer */ + public $id_guest; - public $groupBox; + public $groupBox; - protected $webserviceParameters = array( - 'fields' => array( - 'id_default_group' => array('xlink_resource' => 'groups'), - 'id_lang' => array('xlink_resource' => 'languages'), - 'newsletter_date_add' => array(), - 'ip_registration_newsletter' => array(), - 'last_passwd_gen' => array('setter' => null), - 'secure_key' => array('setter' => null), - 'deleted' => array(), - 'passwd' => array('setter' => 'setWsPasswd'), - ), - 'associations' => array( - 'groups' => array('resource' => 'group'), - ) - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_default_group' => array('xlink_resource' => 'groups'), + 'id_lang' => array('xlink_resource' => 'languages'), + 'newsletter_date_add' => array(), + 'ip_registration_newsletter' => array(), + 'last_passwd_gen' => array('setter' => null), + 'secure_key' => array('setter' => null), + 'deleted' => array(), + 'passwd' => array('setter' => 'setWsPasswd'), + ), + 'associations' => array( + 'groups' => array('resource' => 'group'), + ) + ); - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'customer', - 'primary' => 'id_customer', - 'fields' => array( - 'secure_key' => array('type' => self::TYPE_STRING, 'validate' => 'isMd5', 'copy_post' => false), - 'lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName', 'required' => true, 'size' => 32), - 'firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName', 'required' => true, 'size' => 32), - 'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'required' => true, 'size' => 128), - 'passwd' => array('type' => self::TYPE_STRING, 'validate' => 'isPasswd', 'required' => true, 'size' => 32), - 'last_passwd_gen' => array('type' => self::TYPE_STRING, 'copy_post' => false), - 'id_gender' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'birthday' => array('type' => self::TYPE_DATE, 'validate' => 'isBirthDate'), - 'newsletter' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'newsletter_date_add' => array('type' => self::TYPE_DATE,'copy_post' => false), - 'ip_registration_newsletter' => array('type' => self::TYPE_STRING, 'copy_post' => false), - 'optin' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'website' => array('type' => self::TYPE_STRING, 'validate' => 'isUrl'), - 'company' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'), - 'siret' => array('type' => self::TYPE_STRING, 'validate' => 'isSiret'), - 'ape' => array('type' => self::TYPE_STRING, 'validate' => 'isApe'), - 'outstanding_allow_amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'copy_post' => false), - 'show_public_prices' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'copy_post' => false), - 'id_risk' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'copy_post' => false), - 'max_payment_days' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'copy_post' => false), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'copy_post' => false), - 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'copy_post' => false), - 'note' => array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml', 'size' => 65000, 'copy_post' => false), - 'is_guest' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'copy_post' => false), - 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'copy_post' => false), - 'id_shop_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'copy_post' => false), - 'id_default_group' => array('type' => self::TYPE_INT, 'copy_post' => false), - 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'copy_post' => false), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'copy_post' => false), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'copy_post' => false), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'customer', + 'primary' => 'id_customer', + 'fields' => array( + 'secure_key' => array('type' => self::TYPE_STRING, 'validate' => 'isMd5', 'copy_post' => false), + 'lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName', 'required' => true, 'size' => 32), + 'firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName', 'required' => true, 'size' => 32), + 'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'required' => true, 'size' => 128), + 'passwd' => array('type' => self::TYPE_STRING, 'validate' => 'isPasswd', 'required' => true, 'size' => 32), + 'last_passwd_gen' => array('type' => self::TYPE_STRING, 'copy_post' => false), + 'id_gender' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'birthday' => array('type' => self::TYPE_DATE, 'validate' => 'isBirthDate'), + 'newsletter' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'newsletter_date_add' => array('type' => self::TYPE_DATE,'copy_post' => false), + 'ip_registration_newsletter' => array('type' => self::TYPE_STRING, 'copy_post' => false), + 'optin' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'website' => array('type' => self::TYPE_STRING, 'validate' => 'isUrl'), + 'company' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'), + 'siret' => array('type' => self::TYPE_STRING, 'validate' => 'isSiret'), + 'ape' => array('type' => self::TYPE_STRING, 'validate' => 'isApe'), + 'outstanding_allow_amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'copy_post' => false), + 'show_public_prices' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'copy_post' => false), + 'id_risk' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'copy_post' => false), + 'max_payment_days' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'copy_post' => false), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'copy_post' => false), + 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'copy_post' => false), + 'note' => array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml', 'size' => 65000, 'copy_post' => false), + 'is_guest' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'copy_post' => false), + 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'copy_post' => false), + 'id_shop_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'copy_post' => false), + 'id_default_group' => array('type' => self::TYPE_INT, 'copy_post' => false), + 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'copy_post' => false), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'copy_post' => false), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'copy_post' => false), + ), + ); - protected static $_defaultGroupId = array(); - protected static $_customerHasAddress = array(); - protected static $_customer_groups = array(); + protected static $_defaultGroupId = array(); + protected static $_customerHasAddress = array(); + protected static $_customer_groups = array(); - public function __construct($id = null) - { - $this->id_default_group = (int)Configuration::get('PS_CUSTOMER_GROUP'); - parent::__construct($id); - } + public function __construct($id = null) + { + $this->id_default_group = (int)Configuration::get('PS_CUSTOMER_GROUP'); + parent::__construct($id); + } - public function add($autodate = true, $null_values = true) - { - $this->id_shop = ($this->id_shop) ? $this->id_shop : Context::getContext()->shop->id; - $this->id_shop_group = ($this->id_shop_group) ? $this->id_shop_group : Context::getContext()->shop->id_shop_group; - $this->id_lang = ($this->id_lang) ? $this->id_lang : Context::getContext()->language->id; - $this->birthday = (empty($this->years) ? $this->birthday : (int)$this->years.'-'.(int)$this->months.'-'.(int)$this->days); - $this->secure_key = md5(uniqid(rand(), true)); - $this->last_passwd_gen = date('Y-m-d H:i:s', strtotime('-'.Configuration::get('PS_PASSWD_TIME_FRONT').'minutes')); + public function add($autodate = true, $null_values = true) + { + $this->id_shop = ($this->id_shop) ? $this->id_shop : Context::getContext()->shop->id; + $this->id_shop_group = ($this->id_shop_group) ? $this->id_shop_group : Context::getContext()->shop->id_shop_group; + $this->id_lang = ($this->id_lang) ? $this->id_lang : Context::getContext()->language->id; + $this->birthday = (empty($this->years) ? $this->birthday : (int)$this->years.'-'.(int)$this->months.'-'.(int)$this->days); + $this->secure_key = md5(uniqid(rand(), true)); + $this->last_passwd_gen = date('Y-m-d H:i:s', strtotime('-'.Configuration::get('PS_PASSWD_TIME_FRONT').'minutes')); - if ($this->newsletter && !Validate::isDate($this->newsletter_date_add)) - $this->newsletter_date_add = date('Y-m-d H:i:s'); + if ($this->newsletter && !Validate::isDate($this->newsletter_date_add)) { + $this->newsletter_date_add = date('Y-m-d H:i:s'); + } - if ($this->id_default_group == Configuration::get('PS_CUSTOMER_GROUP')) - if ($this->is_guest) - $this->id_default_group = (int)Configuration::get('PS_GUEST_GROUP'); - else - $this->id_default_group = (int)Configuration::get('PS_CUSTOMER_GROUP'); + if ($this->id_default_group == Configuration::get('PS_CUSTOMER_GROUP')) { + if ($this->is_guest) { + $this->id_default_group = (int)Configuration::get('PS_GUEST_GROUP'); + } else { + $this->id_default_group = (int)Configuration::get('PS_CUSTOMER_GROUP'); + } + } - /* Can't create a guest customer, if this feature is disabled */ - if ($this->is_guest && !Configuration::get('PS_GUEST_CHECKOUT_ENABLED')) - return false; - $success = parent::add($autodate, $null_values); - $this->updateGroup($this->groupBox); - return $success; - } + /* Can't create a guest customer, if this feature is disabled */ + if ($this->is_guest && !Configuration::get('PS_GUEST_CHECKOUT_ENABLED')) { + return false; + } + $success = parent::add($autodate, $null_values); + $this->updateGroup($this->groupBox); + return $success; + } - public function update($nullValues = false) - { - $this->birthday = (empty($this->years) ? $this->birthday : (int)$this->years.'-'.(int)$this->months.'-'.(int)$this->days); + public function update($nullValues = false) + { + $this->birthday = (empty($this->years) ? $this->birthday : (int)$this->years.'-'.(int)$this->months.'-'.(int)$this->days); - if ($this->newsletter && !Validate::isDate($this->newsletter_date_add)) - $this->newsletter_date_add = date('Y-m-d H:i:s'); - if (isset(Context::getContext()->controller) && Context::getContext()->controller->controller_type == 'admin') - $this->updateGroup($this->groupBox); + if ($this->newsletter && !Validate::isDate($this->newsletter_date_add)) { + $this->newsletter_date_add = date('Y-m-d H:i:s'); + } + if (isset(Context::getContext()->controller) && Context::getContext()->controller->controller_type == 'admin') { + $this->updateGroup($this->groupBox); + } - if ($this->deleted) - { - $addresses = $this->getAddresses((int)Configuration::get('PS_LANG_DEFAULT')); - foreach ($addresses as $address) - { - $obj = new Address((int)$address['id_address']); - $obj->delete(); - } - } + if ($this->deleted) { + $addresses = $this->getAddresses((int)Configuration::get('PS_LANG_DEFAULT')); + foreach ($addresses as $address) { + $obj = new Address((int)$address['id_address']); + $obj->delete(); + } + } - return parent::update(true); - } + return parent::update(true); + } - public function delete() - { - if (!count(Order::getCustomerOrders((int)$this->id))) - { - $addresses = $this->getAddresses((int)Configuration::get('PS_LANG_DEFAULT')); - foreach ($addresses as $address) - { - $obj = new Address((int)$address['id_address']); - $obj->delete(); - } - } - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'customer_group` WHERE `id_customer` = '.(int)$this->id); - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'message WHERE id_customer='.(int)$this->id); - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'specific_price WHERE id_customer='.(int)$this->id); - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'compare WHERE id_customer='.(int)$this->id); + public function delete() + { + if (!count(Order::getCustomerOrders((int)$this->id))) { + $addresses = $this->getAddresses((int)Configuration::get('PS_LANG_DEFAULT')); + foreach ($addresses as $address) { + $obj = new Address((int)$address['id_address']); + $obj->delete(); + } + } + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'customer_group` WHERE `id_customer` = '.(int)$this->id); + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'message WHERE id_customer='.(int)$this->id); + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'specific_price WHERE id_customer='.(int)$this->id); + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'compare WHERE id_customer='.(int)$this->id); - $carts = Db::getInstance()->executes('SELECT id_cart + $carts = Db::getInstance()->executes('SELECT id_cart FROM '._DB_PREFIX_.'cart WHERE id_customer='.(int)$this->id); - if ($carts) - foreach ($carts as $cart) - { - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'cart WHERE id_cart='.(int)$cart['id_cart']); - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'cart_product WHERE id_cart='.(int)$cart['id_cart']); - } + if ($carts) { + foreach ($carts as $cart) { + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'cart WHERE id_cart='.(int)$cart['id_cart']); + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'cart_product WHERE id_cart='.(int)$cart['id_cart']); + } + } - $cts = Db::getInstance()->executes('SELECT id_customer_thread + $cts = Db::getInstance()->executes('SELECT id_customer_thread FROM '._DB_PREFIX_.'customer_thread WHERE id_customer='.(int)$this->id); - if ($cts) - foreach ($cts as $ct) - { - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'customer_thread WHERE id_customer_thread='.(int)$ct['id_customer_thread']); - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'customer_message WHERE id_customer_thread='.(int)$ct['id_customer_thread']); - } + if ($cts) { + foreach ($cts as $ct) { + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'customer_thread WHERE id_customer_thread='.(int)$ct['id_customer_thread']); + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'customer_message WHERE id_customer_thread='.(int)$ct['id_customer_thread']); + } + } - CartRule::deleteByIdCustomer((int)$this->id); - return parent::delete(); - } + CartRule::deleteByIdCustomer((int)$this->id); + return parent::delete(); + } - /** - * Return customers list - * - * @return array Customers - */ - public static function getCustomers() - { - $sql = 'SELECT `id_customer`, `email`, `firstname`, `lastname` + /** + * Return customers list + * + * @return array Customers + */ + public static function getCustomers() + { + $sql = 'SELECT `id_customer`, `email`, `firstname`, `lastname` FROM `'._DB_PREFIX_.'customer` WHERE 1 '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).' ORDER BY `id_customer` ASC'; - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + } - /** - * Return customer instance from its e-mail (optionnaly check password) - * - * @param string $email e-mail - * @param string $passwd Password is also checked if specified - * @return Customer instance - */ - public function getByEmail($email, $passwd = null, $ignore_guest = true) - { - if (!Validate::isEmail($email) || ($passwd && !Validate::isPasswd($passwd))) - die (Tools::displayError()); + /** + * Return customer instance from its e-mail (optionnaly check password) + * + * @param string $email e-mail + * @param string $passwd Password is also checked if specified + * @return Customer instance + */ + public function getByEmail($email, $passwd = null, $ignore_guest = true) + { + if (!Validate::isEmail($email) || ($passwd && !Validate::isPasswd($passwd))) { + die(Tools::displayError()); + } - $result = Db::getInstance()->getRow(' + $result = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.'customer` WHERE `email` = \''.pSQL($email).'\' @@ -324,124 +327,126 @@ class CustomerCore extends ObjectModel AND `deleted` = 0 '.($ignore_guest ? ' AND `is_guest` = 0' : '')); - if (!$result) - return false; - $this->id = $result['id_customer']; - foreach ($result as $key => $value) - if (property_exists($this, $key)) - $this->{$key} = $value; - return $this; - } + if (!$result) { + return false; + } + $this->id = $result['id_customer']; + foreach ($result as $key => $value) { + if (property_exists($this, $key)) { + $this->{$key} = $value; + } + } + return $this; + } - /** - * Retrieve customers by email address - * - * @param $email - * @return array - */ - public static function getCustomersByEmail($email) - { - $sql = 'SELECT * + /** + * Retrieve customers by email address + * + * @param $email + * @return array + */ + public static function getCustomersByEmail($email) + { + $sql = 'SELECT * FROM `'._DB_PREFIX_.'customer` WHERE `email` = \''.pSQL($email).'\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER); - return Db::getInstance()->ExecuteS($sql); - } + return Db::getInstance()->ExecuteS($sql); + } - /** - * Check id the customer is active or not - * - * @return bool customer validity - */ - public static function isBanned($id_customer) - { - if (!Validate::isUnsignedId($id_customer)) - return true; - $cache_id = 'Customer::isBanned_'.(int)$id_customer; - if (!Cache::isStored($cache_id)) - { - $result = (bool)!Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + /** + * Check id the customer is active or not + * + * @return bool customer validity + */ + public static function isBanned($id_customer) + { + if (!Validate::isUnsignedId($id_customer)) { + return true; + } + $cache_id = 'Customer::isBanned_'.(int)$id_customer; + if (!Cache::isStored($cache_id)) { + $result = (bool)!Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT `id_customer` FROM `'._DB_PREFIX_.'customer` WHERE `id_customer` = \''.(int)$id_customer.'\' AND active = 1 AND `deleted` = 0'); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Check if e-mail is already registered in database - * - * @param string $email e-mail - * @param $return_id boolean - * @param $ignore_guest boolean, to exclude guest customer - * @return Customer ID if found, false otherwise - */ - public static function customerExists($email, $return_id = false, $ignore_guest = true) - { - if (!Validate::isEmail($email)) - { - if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_) - die (Tools::displayError('Invalid email')); - return false; - } + /** + * Check if e-mail is already registered in database + * + * @param string $email e-mail + * @param $return_id boolean + * @param $ignore_guest boolean, to exclude guest customer + * @return Customer ID if found, false otherwise + */ + public static function customerExists($email, $return_id = false, $ignore_guest = true) + { + if (!Validate::isEmail($email)) { + if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_) { + die(Tools::displayError('Invalid email')); + } + return false; + } - $result = Db::getInstance()->getValue(' + $result = Db::getInstance()->getValue(' SELECT `id_customer` FROM `'._DB_PREFIX_.'customer` WHERE `email` = \''.pSQL($email).'\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).' '.($ignore_guest ? ' AND `is_guest` = 0' : '')); - return ($return_id ? (int)$result : (bool)$result); - } + return ($return_id ? (int)$result : (bool)$result); + } - /** - * Check if an address is owned by a customer - * - * @param int $id_customer Customer ID - * @param int $id_address Address ID - * @return bool result - */ - public static function customerHasAddress($id_customer, $id_address) - { - $key = (int)$id_customer.'-'.(int)$id_address; - if (!array_key_exists($key, self::$_customerHasAddress)) - { - self::$_customerHasAddress[$key] = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Check if an address is owned by a customer + * + * @param int $id_customer Customer ID + * @param int $id_address Address ID + * @return bool result + */ + public static function customerHasAddress($id_customer, $id_address) + { + $key = (int)$id_customer.'-'.(int)$id_address; + if (!array_key_exists($key, self::$_customerHasAddress)) { + self::$_customerHasAddress[$key] = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_address` FROM `'._DB_PREFIX_.'address` WHERE `id_customer` = '.(int)$id_customer.' AND `id_address` = '.(int)$id_address.' AND `deleted` = 0'); - } - return self::$_customerHasAddress[$key]; - } + } + return self::$_customerHasAddress[$key]; + } - public static function resetAddressCache($id_customer, $id_address) - { - $key = (int)$id_customer.'-'.(int)$id_address; - if (array_key_exists($key, self::$_customerHasAddress)) - unset(self::$_customerHasAddress[$key]); - } + public static function resetAddressCache($id_customer, $id_address) + { + $key = (int)$id_customer.'-'.(int)$id_address; + if (array_key_exists($key, self::$_customerHasAddress)) { + unset(self::$_customerHasAddress[$key]); + } + } - /** - * Return customer addresses - * - * @param int $id_lang Language ID - * @return array Addresses - */ - public function getAddresses($id_lang) - { - $share_order = (bool)Context::getContext()->shop->getGroup()->share_order; - $cache_id = 'Customer::getAddresses'.(int)$this->id.'-'.(int)$id_lang.'-'.$share_order; - if (!Cache::isStored($cache_id)) - { - $sql = 'SELECT DISTINCT a.*, cl.`name` AS country, s.name AS state, s.iso_code AS state_iso + /** + * Return customer addresses + * + * @param int $id_lang Language ID + * @return array Addresses + */ + public function getAddresses($id_lang) + { + $share_order = (bool)Context::getContext()->shop->getGroup()->share_order; + $cache_id = 'Customer::getAddresses'.(int)$this->id.'-'.(int)$id_lang.'-'.$share_order; + if (!Cache::isStored($cache_id)) { + $sql = 'SELECT DISTINCT a.*, cl.`name` AS country, s.name AS state, s.iso_code AS state_iso FROM `'._DB_PREFIX_.'address` a LEFT JOIN `'._DB_PREFIX_.'country` c ON (a.`id_country` = c.`id_country`) LEFT JOIN `'._DB_PREFIX_.'country_lang` cl ON (c.`id_country` = cl.`id_country`) @@ -449,139 +454,142 @@ class CustomerCore extends ObjectModel '.($share_order ? '' : Shop::addSqlAssociation('country', 'c')).' WHERE `id_lang` = '.(int)$id_lang.' AND `id_customer` = '.(int)$this->id.' AND a.`deleted` = 0'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Count the number of addresses for a customer - * - * @param int $id_customer Customer ID - * @return int Number of addresses - */ - public static function getAddressesTotalById($id_customer) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Count the number of addresses for a customer + * + * @param int $id_customer Customer ID + * @return int Number of addresses + */ + public static function getAddressesTotalById($id_customer) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(`id_address`) FROM `'._DB_PREFIX_.'address` WHERE `id_customer` = '.(int)$id_customer.' AND `deleted` = 0' - ); - } + ); + } - /** - * Check if customer password is the right one - * - * @param string $passwd Password - * @return bool result - */ - public static function checkPassword($id_customer, $passwd) - { - if (!Validate::isUnsignedId($id_customer) || !Validate::isMd5($passwd)) - die (Tools::displayError()); - $cache_id = 'Customer::checkPassword'.(int)$id_customer.'-'.$passwd; - if (!Cache::isStored($cache_id)) - { - $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Check if customer password is the right one + * + * @param string $passwd Password + * @return bool result + */ + public static function checkPassword($id_customer, $passwd) + { + if (!Validate::isUnsignedId($id_customer) || !Validate::isMd5($passwd)) { + die(Tools::displayError()); + } + $cache_id = 'Customer::checkPassword'.(int)$id_customer.'-'.$passwd; + if (!Cache::isStored($cache_id)) { + $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_customer` FROM `'._DB_PREFIX_.'customer` WHERE `id_customer` = '.(int)$id_customer.' AND `passwd` = \''.pSQL($passwd).'\''); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Light back office search for customers - * - * @param string $query Searched string - * @param null|int $limit Limit query results - * @return array|false|mysqli_result|null|PDOStatement|resource Corresponding customers - * @throws PrestaShopDatabaseException - */ - public static function searchByName($query, $limit = null) - { - $sql_base = 'SELECT * + /** + * Light back office search for customers + * + * @param string $query Searched string + * @param null|int $limit Limit query results + * @return array|false|mysqli_result|null|PDOStatement|resource Corresponding customers + * @throws PrestaShopDatabaseException + */ + public static function searchByName($query, $limit = null) + { + $sql_base = 'SELECT * FROM `'._DB_PREFIX_.'customer`'; - $sql = '('.$sql_base.' WHERE `email` LIKE \'%'.pSQL($query).'%\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).')'; - $sql .= ' UNION ('.$sql_base.' WHERE `id_customer` = '.(int)$query.' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).')'; - $sql .= ' UNION ('.$sql_base.' WHERE `lastname` LIKE \'%'.pSQL($query).'%\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).')'; - $sql .= ' UNION ('.$sql_base.' WHERE `firstname` LIKE \'%'.pSQL($query).'%\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).')'; + $sql = '('.$sql_base.' WHERE `email` LIKE \'%'.pSQL($query).'%\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).')'; + $sql .= ' UNION ('.$sql_base.' WHERE `id_customer` = '.(int)$query.' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).')'; + $sql .= ' UNION ('.$sql_base.' WHERE `lastname` LIKE \'%'.pSQL($query).'%\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).')'; + $sql .= ' UNION ('.$sql_base.' WHERE `firstname` LIKE \'%'.pSQL($query).'%\' '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).')'; - if ($limit) - $sql .= ' LIMIT 0, '.(int)$limit; + if ($limit) { + $sql .= ' LIMIT 0, '.(int)$limit; + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + } - /** - * Search for customers by ip address - * - * @param string $ip Searched string - */ - public static function searchByIp($ip) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * Search for customers by ip address + * + * @param string $ip Searched string + */ + public static function searchByIp($ip) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT DISTINCT c.* FROM `'._DB_PREFIX_.'customer` c LEFT JOIN `'._DB_PREFIX_.'guest` g ON g.id_customer = c.id_customer LEFT JOIN `'._DB_PREFIX_.'connections` co ON g.id_guest = co.id_guest WHERE co.`ip_address` = \''.(int)ip2long(trim($ip)).'\''); - } + } - /** - * Return several useful statistics about customer - * - * @return array Stats - */ - public function getStats() - { - $result = Db::getInstance()->getRow(' + /** + * Return several useful statistics about customer + * + * @return array Stats + */ + public function getStats() + { + $result = Db::getInstance()->getRow(' SELECT COUNT(`id_order`) AS nb_orders, SUM(`total_paid` / o.`conversion_rate`) AS total_orders FROM `'._DB_PREFIX_.'orders` o WHERE o.`id_customer` = '.(int)$this->id.' AND o.valid = 1'); - $result2 = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + $result2 = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT MAX(c.`date_add`) AS last_visit FROM `'._DB_PREFIX_.'guest` g LEFT JOIN `'._DB_PREFIX_.'connections` c ON c.id_guest = g.id_guest WHERE g.`id_customer` = '.(int)$this->id); - $result3 = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + $result3 = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT (YEAR(CURRENT_DATE)-YEAR(c.`birthday`)) - (RIGHT(CURRENT_DATE, 5)id) - return array(); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public function getLastEmails() + { + if (!$this->id) { + return array(); + } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT m.*, l.name as language FROM `'._DB_PREFIX_.'mail` m LEFT JOIN `'._DB_PREFIX_.'lang` l ON m.id_lang = l.id_lang WHERE `recipient` = "'.pSQL($this->email).'" ORDER BY m.date_add DESC LIMIT 10'); - } + } - public function getLastConnections() - { - if (!$this->id) - return array(); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public function getLastConnections() + { + if (!$this->id) { + return array(); + } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT c.date_add, COUNT(cp.id_page) AS pages, TIMEDIFF(MAX(cp.time_end), c.date_add) as time, http_referer,INET_NTOA(ip_address) as ipaddress FROM `'._DB_PREFIX_.'guest` g LEFT JOIN `'._DB_PREFIX_.'connections` c ON c.id_guest = g.id_guest @@ -590,309 +598,329 @@ class CustomerCore extends ObjectModel GROUP BY c.`id_connections` ORDER BY c.date_add DESC LIMIT 10'); - } + } - /* - * Specify if a customer already in base - * - * @param $id_customer Customer id - * @return bool - */ - /* DEPRECATED */ - public function customerIdExists($id_customer) - { - return Customer::customerIdExistsStatic((int)$id_customer); - } + /* + * Specify if a customer already in base + * + * @param $id_customer Customer id + * @return bool + */ + /* DEPRECATED */ + public function customerIdExists($id_customer) + { + return Customer::customerIdExistsStatic((int)$id_customer); + } - public static function customerIdExistsStatic($id_customer) - { - $cache_id = 'Customer::customerIdExistsStatic'.(int)$id_customer; - if (!Cache::isStored($cache_id)) - { - $result = (int)Db::getInstance()->getValue(' + public static function customerIdExistsStatic($id_customer) + { + $cache_id = 'Customer::customerIdExistsStatic'.(int)$id_customer; + if (!Cache::isStored($cache_id)) { + $result = (int)Db::getInstance()->getValue(' SELECT `id_customer` FROM '._DB_PREFIX_.'customer c WHERE c.`id_customer` = '.(int)$id_customer); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Update customer groups associated to the object - * - * @param array $list groups - */ - public function updateGroup($list) - { - if ($list && !empty($list)) - { - $this->cleanGroups(); - $this->addGroups($list); - } - else - $this->addGroups(array($this->id_default_group)); - } + /** + * Update customer groups associated to the object + * + * @param array $list groups + */ + public function updateGroup($list) + { + if ($list && !empty($list)) { + $this->cleanGroups(); + $this->addGroups($list); + } else { + $this->addGroups(array($this->id_default_group)); + } + } - public function cleanGroups() - { - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'customer_group` WHERE `id_customer` = '.(int)$this->id); - } + public function cleanGroups() + { + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'customer_group` WHERE `id_customer` = '.(int)$this->id); + } - public function addGroups($groups) - { - foreach ($groups as $group) - { - $row = array('id_customer' => (int)$this->id, 'id_group' => (int)$group); - Db::getInstance()->insert('customer_group', $row, false, true, Db::INSERT_IGNORE); - } - } + public function addGroups($groups) + { + foreach ($groups as $group) { + $row = array('id_customer' => (int)$this->id, 'id_group' => (int)$group); + Db::getInstance()->insert('customer_group', $row, false, true, Db::INSERT_IGNORE); + } + } - public static function getGroupsStatic($id_customer) - { - if (!Group::isFeatureActive()) - return array(Configuration::get('PS_CUSTOMER_GROUP')); + public static function getGroupsStatic($id_customer) + { + if (!Group::isFeatureActive()) { + return array(Configuration::get('PS_CUSTOMER_GROUP')); + } - if ($id_customer == 0) - self::$_customer_groups[$id_customer] = array((int)Configuration::get('PS_UNIDENTIFIED_GROUP')); + if ($id_customer == 0) { + self::$_customer_groups[$id_customer] = array((int)Configuration::get('PS_UNIDENTIFIED_GROUP')); + } - if (!isset(self::$_customer_groups[$id_customer])) - { - self::$_customer_groups[$id_customer] = array(); - $result = Db::getInstance()->executeS(' + if (!isset(self::$_customer_groups[$id_customer])) { + self::$_customer_groups[$id_customer] = array(); + $result = Db::getInstance()->executeS(' SELECT cg.`id_group` FROM '._DB_PREFIX_.'customer_group cg WHERE cg.`id_customer` = '.(int)$id_customer); - foreach ($result as $group) - self::$_customer_groups[$id_customer][] = (int)$group['id_group']; - } - return self::$_customer_groups[$id_customer]; - } + foreach ($result as $group) { + self::$_customer_groups[$id_customer][] = (int)$group['id_group']; + } + } + return self::$_customer_groups[$id_customer]; + } - public function getGroups() - { - return Customer::getGroupsStatic((int)$this->id); - } + public function getGroups() + { + return Customer::getGroupsStatic((int)$this->id); + } - /** - * @deprecated since 1.5 - */ - public function isUsed() - { - Tools::displayAsDeprecated(); - return false; - } + /** + * @deprecated since 1.5 + */ + public function isUsed() + { + Tools::displayAsDeprecated(); + return false; + } - public function getBoughtProducts() - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public function getBoughtProducts() + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'orders` o LEFT JOIN `'._DB_PREFIX_.'order_detail` od ON o.id_order = od.id_order WHERE o.valid = 1 AND o.`id_customer` = '.(int)$this->id); - } + } - public static function getDefaultGroupId($id_customer) - { - if (!Group::isFeatureActive()) - { - static $ps_customer_group = null; - if ($ps_customer_group === null) - $ps_customer_group = Configuration::get('PS_CUSTOMER_GROUP'); - return $ps_customer_group; - } + public static function getDefaultGroupId($id_customer) + { + if (!Group::isFeatureActive()) { + static $ps_customer_group = null; + if ($ps_customer_group === null) { + $ps_customer_group = Configuration::get('PS_CUSTOMER_GROUP'); + } + return $ps_customer_group; + } - if (!isset(self::$_defaultGroupId[(int)$id_customer])) - self::$_defaultGroupId[(int)$id_customer] = Db::getInstance()->getValue(' + if (!isset(self::$_defaultGroupId[(int)$id_customer])) { + self::$_defaultGroupId[(int)$id_customer] = Db::getInstance()->getValue(' SELECT `id_default_group` FROM `'._DB_PREFIX_.'customer` WHERE `id_customer` = '.(int)$id_customer - ); - return self::$_defaultGroupId[(int)$id_customer]; - } + ); + } + return self::$_defaultGroupId[(int)$id_customer]; + } - public static function getCurrentCountry($id_customer, Cart $cart = null) - { - if (!$cart) - $cart = Context::getContext()->cart; - if (!$cart || !$cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) - $id_address = (int)Db::getInstance()->getValue(' + public static function getCurrentCountry($id_customer, Cart $cart = null) + { + if (!$cart) { + $cart = Context::getContext()->cart; + } + if (!$cart || !$cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) { + $id_address = (int)Db::getInstance()->getValue(' SELECT `id_address` FROM `'._DB_PREFIX_.'address` WHERE `id_customer` = '.(int)$id_customer.' AND `deleted` = 0 ORDER BY `id_address`' - ); - else - $id_address = $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; - $ids = Address::getCountryAndState($id_address); - return (int)$ids['id_country'] ? $ids['id_country'] : Configuration::get('PS_COUNTRY_DEFAULT'); - } + ); + } else { + $id_address = $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; + } + $ids = Address::getCountryAndState($id_address); + return (int)$ids['id_country'] ? $ids['id_country'] : Configuration::get('PS_COUNTRY_DEFAULT'); + } - public function toggleStatus() - { - parent::toggleStatus(); + public function toggleStatus() + { + parent::toggleStatus(); - /* Change status to active/inactive */ - return Db::getInstance()->execute(' + /* Change status to active/inactive */ + return Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.bqSQL($this->def['table']).'` SET `date_upd` = NOW() WHERE `'.bqSQL($this->def['primary']).'` = '.(int)$this->id); - } + } - public function isGuest() - { - return (bool)$this->is_guest; - } + public function isGuest() + { + return (bool)$this->is_guest; + } - public function transformToCustomer($id_lang, $password = null) - { - if (!$this->isGuest()) - return false; - if (empty($password)) - $password = Tools::passwdGen(8, 'RANDOM'); - if (!Validate::isPasswd($password)) - return false; + public function transformToCustomer($id_lang, $password = null) + { + if (!$this->isGuest()) { + return false; + } + if (empty($password)) { + $password = Tools::passwdGen(8, 'RANDOM'); + } + if (!Validate::isPasswd($password)) { + return false; + } - $this->is_guest = 0; - $this->passwd = Tools::encrypt($password); - $this->cleanGroups(); - $this->addGroups(array(Configuration::get('PS_CUSTOMER_GROUP'))); // add default customer group - if ($this->update()) - { - $vars = array( - '{firstname}' => $this->firstname, - '{lastname}' => $this->lastname, - '{email}' => $this->email, - '{passwd}' => $password - ); + $this->is_guest = 0; + $this->passwd = Tools::encrypt($password); + $this->cleanGroups(); + $this->addGroups(array(Configuration::get('PS_CUSTOMER_GROUP'))); // add default customer group + if ($this->update()) { + $vars = array( + '{firstname}' => $this->firstname, + '{lastname}' => $this->lastname, + '{email}' => $this->email, + '{passwd}' => $password + ); - Mail::Send( - (int)$id_lang, - 'guest_to_customer', - Mail::l('Your guest account has been transformed into a customer account', (int)$id_lang), - $vars, - $this->email, - $this->firstname.' '.$this->lastname, - null, - null, - null, - null, - _PS_MAIL_DIR_, - false, - (int)$this->id_shop - ); - return true; - } - return false; - } + Mail::Send( + (int)$id_lang, + 'guest_to_customer', + Mail::l('Your guest account has been transformed into a customer account', (int)$id_lang), + $vars, + $this->email, + $this->firstname.' '.$this->lastname, + null, + null, + null, + null, + _PS_MAIL_DIR_, + false, + (int)$this->id_shop + ); + return true; + } + return false; + } - public function setWsPasswd($passwd) - { - if ($this->id == 0 || $this->passwd != $passwd) - $this->passwd = Tools::encrypt($passwd); - return true; - } + public function setWsPasswd($passwd) + { + if ($this->id == 0 || $this->passwd != $passwd) { + $this->passwd = Tools::encrypt($passwd); + } + return true; + } - /** - * Check customer informations and return customer validity - * - * @since 1.5.0 - * @param bool $with_guest - * @return bool customer validity - */ - public function isLogged($with_guest = false) - { - if (!$with_guest && $this->is_guest == 1) - return false; + /** + * Check customer informations and return customer validity + * + * @since 1.5.0 + * @param bool $with_guest + * @return bool customer validity + */ + public function isLogged($with_guest = false) + { + if (!$with_guest && $this->is_guest == 1) { + return false; + } - /* Customer is valid only if it can be load and if object password is the same as database one */ - return ($this->logged == 1 && $this->id && Validate::isUnsignedId($this->id) && Customer::checkPassword($this->id, $this->passwd)); - } + /* Customer is valid only if it can be load and if object password is the same as database one */ + return ($this->logged == 1 && $this->id && Validate::isUnsignedId($this->id) && Customer::checkPassword($this->id, $this->passwd)); + } - /** - * Logout - * - * @since 1.5.0 - */ - public function logout() - { - if (isset(Context::getContext()->cookie)) - Context::getContext()->cookie->logout(); - $this->logged = 0; - } + /** + * Logout + * + * @since 1.5.0 + */ + public function logout() + { + Hook::exec('actionCustomerLogoutBefore', array('customer' => $this)); - /** - * Soft logout, delete everything links to the customer - * but leave there affiliate's informations - * - * @since 1.5.0 - */ - public function mylogout() - { - if (isset(Context::getContext()->cookie)) - Context::getContext()->cookie->mylogout(); - $this->logged = 0; - } + if (isset(Context::getContext()->cookie)) { + Context::getContext()->cookie->logout(); + } - public function getLastCart($with_order = true) - { - $carts = Cart::getCustomerCarts((int)$this->id, $with_order); - if (!count($carts)) - return false; - $cart = array_shift($carts); - $cart = new Cart((int)$cart['id_cart']); - return ($cart->nbProducts() === 0 ? (int)$cart->id : false); - } + $this->logged = 0; - public function getOutstanding() - { - $query = new DbQuery(); - $query->select('SUM(oi.total_paid_tax_incl)'); - $query->from('order_invoice', 'oi'); - $query->leftJoin('orders', 'o', 'oi.id_order = o.id_order'); - $query->groupBy('o.id_customer'); - $query->where('o.id_customer = '.(int)$this->id); - $total_paid = (float)Db::getInstance()->getValue($query->build()); + Hook::exec('actionCustomerLogoutAfter', array('customer' => $this)); + } - $query = new DbQuery(); - $query->select('SUM(op.amount)'); - $query->from('order_payment', 'op'); - $query->leftJoin('order_invoice_payment', 'oip', 'op.id_order_payment = oip.id_order_payment'); - $query->leftJoin('orders', 'o', 'oip.id_order = o.id_order'); - $query->groupBy('o.id_customer'); - $query->where('o.id_customer = '.(int)$this->id); - $total_rest = (float)Db::getInstance()->getValue($query->build()); + /** + * Soft logout, delete everything links to the customer + * but leave there affiliate's informations + * + * @since 1.5.0 + */ + public function mylogout() + { + Hook::exec('actionCustomerLogoutBefore', array('customer' => $this)); - return $total_paid - $total_rest; - } + if (isset(Context::getContext()->cookie)) { + Context::getContext()->cookie->mylogout(); + } - public function getWsGroups() - { - return Db::getInstance()->executeS(' + $this->logged = 0; + + Hook::exec('actionCustomerLogoutAfter', array('customer' => $this)); + } + + public function getLastCart($with_order = true) + { + $carts = Cart::getCustomerCarts((int)$this->id, $with_order); + if (!count($carts)) { + return false; + } + $cart = array_shift($carts); + $cart = new Cart((int)$cart['id_cart']); + return ($cart->nbProducts() === 0 ? (int)$cart->id : false); + } + + public function getOutstanding() + { + $query = new DbQuery(); + $query->select('SUM(oi.total_paid_tax_incl)'); + $query->from('order_invoice', 'oi'); + $query->leftJoin('orders', 'o', 'oi.id_order = o.id_order'); + $query->groupBy('o.id_customer'); + $query->where('o.id_customer = '.(int)$this->id); + $total_paid = (float)Db::getInstance()->getValue($query->build()); + + $query = new DbQuery(); + $query->select('SUM(op.amount)'); + $query->from('order_payment', 'op'); + $query->leftJoin('order_invoice_payment', 'oip', 'op.id_order_payment = oip.id_order_payment'); + $query->leftJoin('orders', 'o', 'oip.id_order = o.id_order'); + $query->groupBy('o.id_customer'); + $query->where('o.id_customer = '.(int)$this->id); + $total_rest = (float)Db::getInstance()->getValue($query->build()); + + return $total_paid - $total_rest; + } + + public function getWsGroups() + { + return Db::getInstance()->executeS(' SELECT cg.`id_group` as id FROM '._DB_PREFIX_.'customer_group cg '.Shop::addSqlAssociation('group', 'cg').' WHERE cg.`id_customer` = '.(int)$this->id - ); - } + ); + } - public function setWsGroups($result) - { - $groups = array(); - foreach ($result as $row) - $groups[] = $row['id']; - $this->cleanGroups(); - $this->addGroups($groups); - return true; - } + public function setWsGroups($result) + { + $groups = array(); + foreach ($result as $row) { + $groups[] = $row['id']; + } + $this->cleanGroups(); + $this->addGroups($groups); + return true; + } - /** - * @see ObjectModel::getWebserviceObjectList() - */ - public function getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit) - { - $sql_filter .= Shop::addSqlRestriction(Shop::SHARE_CUSTOMER, 'main'); - return parent::getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit); - } + /** + * @see ObjectModel::getWebserviceObjectList() + */ + public function getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit) + { + $sql_filter .= Shop::addSqlRestriction(Shop::SHARE_CUSTOMER, 'main'); + return parent::getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit); + } } diff --git a/classes/CustomerMessage.php b/classes/CustomerMessage.php index 939ee341..3152f02f 100644 --- a/classes/CustomerMessage.php +++ b/classes/CustomerMessage.php @@ -26,52 +26,52 @@ class CustomerMessageCore extends ObjectModel { - public $id; - public $id_customer_thread; - public $id_employee; - public $message; - public $file_name; - public $ip_address; - public $user_agent; - public $private; - public $date_add; - public $date_upd; - public $read; + public $id; + public $id_customer_thread; + public $id_employee; + public $message; + public $file_name; + public $ip_address; + public $user_agent; + public $private; + public $date_add; + public $date_upd; + public $read; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'customer_message', - 'primary' => 'id_customer_message', - 'fields' => array( - 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_customer_thread' => array('type' => self::TYPE_INT), - 'ip_address' => array('type' => self::TYPE_STRING, 'validate' => 'isIp2Long', 'size' => 15), - 'message' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'required' => true, 'size' => 65000), - 'file_name' => array('type' => self::TYPE_STRING), - 'user_agent' => array('type' => self::TYPE_STRING), - 'private' => array('type' => self::TYPE_INT), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'read' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool') - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'customer_message', + 'primary' => 'id_customer_message', + 'fields' => array( + 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_customer_thread' => array('type' => self::TYPE_INT), + 'ip_address' => array('type' => self::TYPE_STRING, 'validate' => 'isIp2Long', 'size' => 15), + 'message' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'required' => true, 'size' => 16777216), + 'file_name' => array('type' => self::TYPE_STRING), + 'user_agent' => array('type' => self::TYPE_STRING), + 'private' => array('type' => self::TYPE_INT), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'read' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool') + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_employee' => array( - 'xlink_resource' => 'employees' - ), - 'id_customer_thread' => array( - 'xlink_resource' => 'customer_threads' - ), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_employee' => array( + 'xlink_resource' => 'employees' + ), + 'id_customer_thread' => array( + 'xlink_resource' => 'customer_threads' + ), + ), + ); - public static function getMessagesByOrderId($id_order, $private = true) - { - return Db::getInstance()->executeS(' + public static function getMessagesByOrderId($id_order, $private = true) + { + return Db::getInstance()->executeS(' SELECT cm.*, c.`firstname` AS cfirstname, c.`lastname` AS clastname, @@ -90,30 +90,32 @@ class CustomerMessageCore extends ObjectModel GROUP BY cm.id_customer_message ORDER BY cm.date_add DESC '); - } + } - public static function getTotalCustomerMessages($where = null) - { - if (is_null($where)) - return (int)Db::getInstance()->getValue(' + public static function getTotalCustomerMessages($where = null) + { + if (is_null($where)) { + return (int)Db::getInstance()->getValue(' SELECT COUNT(*) FROM '._DB_PREFIX_.'customer_message LEFT JOIN `'._DB_PREFIX_.'customer_thread` ct ON (cm.`id_customer_thread` = ct.`id_customer_thread`) WHERE 1'.Shop::addSqlRestriction() - ); - else - return (int)Db::getInstance()->getValue(' + ); + } else { + return (int)Db::getInstance()->getValue(' SELECT COUNT(*) FROM '._DB_PREFIX_.'customer_message cm LEFT JOIN `'._DB_PREFIX_.'customer_thread` ct ON (cm.`id_customer_thread` = ct.`id_customer_thread`) WHERE '.$where.Shop::addSqlRestriction() - ); - } + ); + } + } - public function delete() - { - if (!empty($this->file_name)) - @unlink(_PS_UPLOAD_DIR_.$this->file_name); - return parent::delete(); - } -} \ No newline at end of file + public function delete() + { + if (!empty($this->file_name)) { + @unlink(_PS_UPLOAD_DIR_.$this->file_name); + } + return parent::delete(); + } +} diff --git a/classes/CustomerThread.php b/classes/CustomerThread.php index 053d4887..a8ea5dcf 100644 --- a/classes/CustomerThread.php +++ b/classes/CustomerThread.php @@ -26,130 +26,132 @@ class CustomerThreadCore extends ObjectModel { - public $id; - public $id_shop; - public $id_lang; - public $id_contact; - public $id_customer; - public $id_order; - public $id_product; - public $status; - public $email; - public $token; - public $date_add; - public $date_upd; + public $id; + public $id_shop; + public $id_lang; + public $id_contact; + public $id_customer; + public $id_order; + public $id_product; + public $status; + public $email; + public $token; + public $date_add; + public $date_upd; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'customer_thread', - 'primary' => 'id_customer_thread', - 'fields' => array( - 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_contact' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_customer' =>array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'size' => 254), - 'token' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true), - 'status' => array('type' => self::TYPE_STRING), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'customer_thread', + 'primary' => 'id_customer_thread', + 'fields' => array( + 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_contact' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_customer' =>array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'size' => 254), + 'token' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true), + 'status' => array('type' => self::TYPE_STRING), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_lang' => array( - 'xlink_resource' => 'languages' - ), - 'id_shop' => array( - 'xlink_resource' => 'shops' - ), - 'id_customer' => array( - 'xlink_resource' => 'customers' - ), - 'id_order' => array( - 'xlink_resource' => 'orders' - ), - 'id_product' => array( - 'xlink_resource' => 'products' - ), - ), - 'associations' => array( - 'customer_messages' => array( - 'resource' => 'customer_message', - 'id' => array('required' => true)), - ) - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_lang' => array( + 'xlink_resource' => 'languages' + ), + 'id_shop' => array( + 'xlink_resource' => 'shops' + ), + 'id_customer' => array( + 'xlink_resource' => 'customers' + ), + 'id_order' => array( + 'xlink_resource' => 'orders' + ), + 'id_product' => array( + 'xlink_resource' => 'products' + ), + ), + 'associations' => array( + 'customer_messages' => array( + 'resource' => 'customer_message', + 'id' => array('required' => true)), + ) + ); - public function getWsCustomerMessages() - { - return Db::getInstance()->executeS(' + public function getWsCustomerMessages() + { + return Db::getInstance()->executeS(' SELECT `id_customer_message` id FROM `'._DB_PREFIX_.'customer_message` WHERE `id_customer_thread` = '.(int)$this->id); - } + } - public function delete() - { - if (!Validate::isUnsignedId($this->id)) - return false; + public function delete() + { + if (!Validate::isUnsignedId($this->id)) { + return false; + } - $return = true; - $result = Db::getInstance()->executeS(' + $return = true; + $result = Db::getInstance()->executeS(' SELECT `id_customer_message` FROM `'._DB_PREFIX_.'customer_message` WHERE `id_customer_thread` = '.(int)$this->id - ); + ); - if (count($result)) - { - foreach ($result as $res) - { - $message = new CustomerMessage((int)$res['id_customer_message']); - if (!Validate::isLoadedObject($message)) - $return = false; - else - $return &= $message->delete(); - } - } - $return &= parent::delete(); - return $return; - } + if (count($result)) { + foreach ($result as $res) { + $message = new CustomerMessage((int)$res['id_customer_message']); + if (!Validate::isLoadedObject($message)) { + $return = false; + } else { + $return &= $message->delete(); + } + } + } + $return &= parent::delete(); + return $return; + } - public static function getCustomerMessages($id_customer, $read = null, $id_order = null) - { - $sql = 'SELECT * + public static function getCustomerMessages($id_customer, $read = null, $id_order = null) + { + $sql = 'SELECT * FROM '._DB_PREFIX_.'customer_thread ct LEFT JOIN '._DB_PREFIX_.'customer_message cm ON ct.id_customer_thread = cm.id_customer_thread WHERE id_customer = '.(int)$id_customer; - if ($read !== null) - $sql .= ' AND cm.`read` = '.(int)$read; - if ($id_order !== null) - $sql .= ' AND ct.`id_order` = '.(int)$id_order; + if ($read !== null) { + $sql .= ' AND cm.`read` = '.(int)$read; + } + if ($id_order !== null) { + $sql .= ' AND ct.`id_order` = '.(int)$id_order; + } - return Db::getInstance()->executeS($sql); - } + return Db::getInstance()->executeS($sql); + } - public static function getIdCustomerThreadByEmailAndIdOrder($email, $id_order) - { - return Db::getInstance()->getValue(' + public static function getIdCustomerThreadByEmailAndIdOrder($email, $id_order) + { + return Db::getInstance()->getValue(' SELECT cm.id_customer_thread FROM '._DB_PREFIX_.'customer_thread cm WHERE cm.email = \''.pSQL($email).'\' AND cm.id_shop = '.(int)Context::getContext()->shop->id.' AND cm.id_order = '.(int)$id_order - ); - } + ); + } - public static function getContacts() - { - return Db::getInstance()->executeS(' + public static function getContacts() + { + return Db::getInstance()->executeS(' SELECT cl.*, COUNT(*) as total, ( SELECT id_customer_thread FROM '._DB_PREFIX_.'customer_thread ct2 @@ -167,27 +169,28 @@ class CustomerThreadCore extends ObjectModel '.Shop::addSqlRestriction().' GROUP BY ct.id_contact HAVING COUNT(*) > 0 '); - } + } - public static function getTotalCustomerThreads($where = null) - { - if (is_null($where)) - return (int)Db::getInstance()->getValue(' + public static function getTotalCustomerThreads($where = null) + { + if (is_null($where)) { + return (int)Db::getInstance()->getValue(' SELECT COUNT(*) FROM '._DB_PREFIX_.'customer_thread WHERE 1 '.Shop::addSqlRestriction() - ); - else - return (int)Db::getInstance()->getValue(' + ); + } else { + return (int)Db::getInstance()->getValue(' SELECT COUNT(*) FROM '._DB_PREFIX_.'customer_thread WHERE '.$where.Shop::addSqlRestriction() - ); - } + ); + } + } - public static function getMessageCustomerThreads($id_customer_thread) - { - return Db::getInstance()->executeS(' + public static function getMessageCustomerThreads($id_customer_thread) + { + return Db::getInstance()->executeS(' SELECT ct.*, cm.*, cl.name subject, CONCAT(e.firstname, \' \', e.lastname) employee_name, CONCAT(c.firstname, \' \', c.lastname) customer_name, c.firstname FROM '._DB_PREFIX_.'customer_thread ct @@ -202,12 +205,12 @@ class CustomerThreadCore extends ObjectModel WHERE ct.id_customer_thread = '.(int)$id_customer_thread.' ORDER BY cm.date_add ASC '); - } + } - public static function getNextThread($id_customer_thread) - { - $context = Context::getContext(); - return Db::getInstance()->getValue(' + public static function getNextThread($id_customer_thread) + { + $context = Context::getContext(); + return Db::getInstance()->getValue(' SELECT id_customer_thread FROM '._DB_PREFIX_.'customer_thread ct WHERE ct.status = "open" @@ -218,10 +221,10 @@ class CustomerThreadCore extends ObjectModel ORDER BY date_add DESC LIMIT 1 ) '.($context->cookie->{'customer_threadFilter_cl!id_contact'} ? - 'AND ct.id_contact = '.(int)$context->cookie->{'customer_threadFilter_cl!id_contact'} : '').' + 'AND ct.id_contact = '.(int)$context->cookie->{'customer_threadFilter_cl!id_contact'} : '').' '.($context->cookie->{'customer_threadFilter_l!id_lang'} ? - 'AND ct.id_lang = '.(int)$context->cookie->{'customer_threadFilter_l!id_lang'} : ''). - ' ORDER BY ct.date_upd ASC + 'AND ct.id_lang = '.(int)$context->cookie->{'customer_threadFilter_l!id_lang'} : ''). + ' ORDER BY ct.date_upd ASC '); - } -} \ No newline at end of file + } +} diff --git a/classes/Customization.php b/classes/Customization.php index f02f82ad..5d04c63d 100644 --- a/classes/Customization.php +++ b/classes/Customization.php @@ -26,233 +26,243 @@ class CustomizationCore extends ObjectModel { - /** @var int */ - public $id_product_attribute; - /** @var int */ - public $id_address_delivery; - /** @var int */ - public $id_cart; - /** @var int */ - public $id_product; - /** @var int */ - public $quantity; - /** @var int */ - public $quantity_refunded; - /** @var int */ - public $quantity_returned; - /** @var bool */ - public $in_cart; + /** @var int */ + public $id_product_attribute; + /** @var int */ + public $id_address_delivery; + /** @var int */ + public $id_cart; + /** @var int */ + public $id_product; + /** @var int */ + public $quantity; + /** @var int */ + public $quantity_refunded; + /** @var int */ + public $quantity_returned; + /** @var bool */ + public $in_cart; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'customization', - 'primary' => 'id_customization', - 'fields' => array( - /* Classic fields */ - 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_address_delivery' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_cart' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'quantity_refunded' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'quantity_returned' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'in_cart' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), - ), - ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_address_delivery' => array( - 'xlink_resource' => array( - 'resourceName' => 'addresses' - ) - ), - 'id_cart' => array( - 'xlink_resource' => array( - 'resourceName' => 'carts' - ) - ), - 'id_product' => array( - 'xlink_resource' => array( - 'resourceName' => 'products' - ) - ), - ), - 'associations' => array( - 'customized_data_text_fields' => array('resource' => 'customized_data_text_field', 'virtual_entity' => true, 'fields' => array( - 'id_customization_field' => array('required' => true, 'xlink_resource' => 'product_customization_fields'), - 'value' => array(), - ) - ), - 'customized_data_images' => array('resource' => 'customized_data_image', 'virtual_entity' => true, 'setter' => false, 'fields' => array( - 'id_customization_field' => array('xlink_resource' => 'product_customization_fields'), - 'value' => array(), - ) - ), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'customization', + 'primary' => 'id_customization', + 'fields' => array( + /* Classic fields */ + 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_address_delivery' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_cart' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'quantity_refunded' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'quantity_returned' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'in_cart' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), + ), + ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_address_delivery' => array( + 'xlink_resource' => array( + 'resourceName' => 'addresses' + ) + ), + 'id_cart' => array( + 'xlink_resource' => array( + 'resourceName' => 'carts' + ) + ), + 'id_product' => array( + 'xlink_resource' => array( + 'resourceName' => 'products' + ) + ), + ), + 'associations' => array( + 'customized_data_text_fields' => array('resource' => 'customized_data_text_field', 'virtual_entity' => true, 'fields' => array( + 'id_customization_field' => array('required' => true, 'xlink_resource' => 'product_customization_fields'), + 'value' => array(), + ) + ), + 'customized_data_images' => array('resource' => 'customized_data_image', 'virtual_entity' => true, 'setter' => false, 'fields' => array( + 'id_customization_field' => array('xlink_resource' => 'product_customization_fields'), + 'value' => array(), + ) + ), + ), + ); - public static function getReturnedCustomizations($id_order) - { - if (($result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getReturnedCustomizations($id_order) + { + if (($result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT ore.`id_order_return`, ord.`id_order_detail`, ord.`id_customization`, ord.`product_quantity` FROM `'._DB_PREFIX_.'order_return` ore INNER JOIN `'._DB_PREFIX_.'order_return_detail` ord ON (ord.`id_order_return` = ore.`id_order_return`) - WHERE ore.`id_order` = '.(int)($id_order).' AND ord.`id_customization` != 0')) === false) - return false; - $customizations = array(); - foreach ($result as $row) - $customizations[(int)($row['id_customization'])] = $row; - return $customizations; - } + WHERE ore.`id_order` = '.(int)($id_order).' AND ord.`id_customization` != 0')) === false) { + return false; + } + $customizations = array(); + foreach ($result as $row) { + $customizations[(int)($row['id_customization'])] = $row; + } + return $customizations; + } - public static function getOrderedCustomizations($id_cart) - { - if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT `id_customization`, `quantity` FROM `'._DB_PREFIX_.'customization` WHERE `id_cart` = '.(int)($id_cart))) - return false; - $customizations = array(); - foreach ($result as $row) - $customizations[(int)($row['id_customization'])] = $row; - return $customizations; - } + public static function getOrderedCustomizations($id_cart) + { + if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT `id_customization`, `quantity` FROM `'._DB_PREFIX_.'customization` WHERE `id_cart` = '.(int)($id_cart))) { + return false; + } + $customizations = array(); + foreach ($result as $row) { + $customizations[(int)($row['id_customization'])] = $row; + } + return $customizations; + } - public static function countCustomizationQuantityByProduct($customizations) - { - $total = array(); - foreach ($customizations as $customization) - $total[(int)$customization['id_order_detail']] = !isset($total[(int)$customization['id_order_detail']]) ? (int)$customization['quantity'] : $total[(int)$customization['id_order_detail']] + (int)$customization['quantity']; - return $total; - } + public static function countCustomizationQuantityByProduct($customizations) + { + $total = array(); + foreach ($customizations as $customization) { + $total[(int)$customization['id_order_detail']] = !isset($total[(int)$customization['id_order_detail']]) ? (int)$customization['quantity'] : $total[(int)$customization['id_order_detail']] + (int)$customization['quantity']; + } + return $total; + } - public static function getLabel($id_customization, $id_lang, $id_shop = null) - { - if (!$id_customization || !$id_lang) - return false; - if (Shop::isFeatureActive() && !$id_shop) - $id_shop = (int)Context::getContext()->shop->id; + public static function getLabel($id_customization, $id_lang, $id_shop = null) + { + if (!$id_customization || !$id_lang) { + return false; + } + if (Shop::isFeatureActive() && !$id_shop) { + $id_shop = (int)Context::getContext()->shop->id; + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT `name` FROM `'._DB_PREFIX_.'customization_field_lang` WHERE `id_customization_field` = '.(int)($id_customization).($id_shop ? ' AND cfl.`id_shop` = '.$id_shop : '').' AND `id_lang` = '.(int)($id_lang) - ); + ); - return $result['name']; - } + return $result['name']; + } - public static function retrieveQuantitiesFromIds($ids_customizations) - { - $quantities = array(); + public static function retrieveQuantitiesFromIds($ids_customizations) + { + $quantities = array(); - $in_values = ''; - foreach ($ids_customizations as $key => $id_customization) - { - if ($key > 0) $in_values .= ','; - $in_values .= (int)($id_customization); - } + $in_values = ''; + foreach ($ids_customizations as $key => $id_customization) { + if ($key > 0) { + $in_values .= ','; + } + $in_values .= (int)($id_customization); + } - if (!empty($in_values)) - { - $results = Db::getInstance()->executeS( - 'SELECT `id_customization`, `id_product`, `quantity`, `quantity_refunded`, `quantity_returned` + if (!empty($in_values)) { + $results = Db::getInstance()->executeS( + 'SELECT `id_customization`, `id_product`, `quantity`, `quantity_refunded`, `quantity_returned` FROM `'._DB_PREFIX_.'customization` WHERE `id_customization` IN ('.$in_values.')'); - foreach ($results as $row) - $quantities[$row['id_customization']] = $row; - } + foreach ($results as $row) { + $quantities[$row['id_customization']] = $row; + } + } - return $quantities; - } + return $quantities; + } - public static function countQuantityByCart($id_cart) - { - $quantity = array(); + public static function countQuantityByCart($id_cart) + { + $quantity = array(); - $results = Db::getInstance()->executeS(' + $results = Db::getInstance()->executeS(' SELECT `id_product`, `id_product_attribute`, SUM(`quantity`) AS quantity FROM `'._DB_PREFIX_.'customization` WHERE `id_cart` = '.(int)$id_cart.' GROUP BY `id_cart`, `id_product`, `id_product_attribute` '); - foreach ($results as $row) - $quantity[$row['id_product']][$row['id_product_attribute']] = $row['quantity']; + foreach ($results as $row) { + $quantity[$row['id_product']][$row['id_product_attribute']] = $row['quantity']; + } - return $quantity; - } + return $quantity; + } - /** - * This method is allow to know if a feature is used or active - * @since 1.5.0.1 - * @return bool - */ - public static function isFeatureActive() - { - return Configuration::get('PS_CUSTOMIZATION_FEATURE_ACTIVE'); - } + /** + * This method is allow to know if a feature is used or active + * @since 1.5.0.1 + * @return bool + */ + public static function isFeatureActive() + { + return Configuration::get('PS_CUSTOMIZATION_FEATURE_ACTIVE'); + } - /** - * This method is allow to know if a Customization entity is currently used - * @since 1.5.0.1 - * @param $table - * @param $has_active_column - * @return bool - */ - public static function isCurrentlyUsed($table = null, $has_active_column = false) - { - return (bool)Db::getInstance()->getValue(' + /** + * This method is allow to know if a Customization entity is currently used + * @since 1.5.0.1 + * @param $table + * @param $has_active_column + * @return bool + */ + public static function isCurrentlyUsed($table = null, $has_active_column = false) + { + return (bool)Db::getInstance()->getValue(' SELECT `id_customization_field` FROM `'._DB_PREFIX_.'customization_field` '); - } + } - public function getWsCustomizedDataTextFields() - { - if (!$results = Db::getInstance()->executeS(' + public function getWsCustomizedDataTextFields() + { + if (!$results = Db::getInstance()->executeS(' SELECT id_customization_field, value FROM `'._DB_PREFIX_.'customization_field` cf LEFT JOIN `'._DB_PREFIX_.'customized_data` cd ON (cf.id_customization_field = cd.index) WHERE `id_product` = '.(int)$this->id_product.' - AND cf.type = 1')) - return array(); - return $results; - } + AND cf.type = 1')) { + return array(); + } + return $results; + } - public function getWsCustomizedDataImages() - { - if (!$results = Db::getInstance()->executeS(' + public function getWsCustomizedDataImages() + { + if (!$results = Db::getInstance()->executeS(' SELECT id_customization_field, value FROM `'._DB_PREFIX_.'customization_field` cf LEFT JOIN `'._DB_PREFIX_.'customized_data` cd ON (cf.id_customization_field = cd.index) WHERE `id_product` = '.(int)$this->id_product.' - AND cf.type = 0')) - return array(); - return $results; - } + AND cf.type = 0')) { + return array(); + } + return $results; + } - public function setWsCustomizedDataTextFields($values) - { - $cart = new Cart($this->id_cart); - if (!Validate::isLoadedObject($cart)) - { - WebserviceRequest::getInstance()->setError(500, Tools::displayError('Could not load cart id='.$this->id_cart), 137); - return false; - } - Db::getInstance()->execute(' + public function setWsCustomizedDataTextFields($values) + { + $cart = new Cart($this->id_cart); + if (!Validate::isLoadedObject($cart)) { + WebserviceRequest::getInstance()->setError(500, Tools::displayError('Could not load cart id='.$this->id_cart), 137); + return false; + } + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'customized_data` WHERE id_customization = '.(int)$this->id.' AND type = 1'); - foreach ($values as $value) - { - $query = 'INSERT INTO `'._DB_PREFIX_.'customized_data` (`id_customization`, `type`, `index`, `value`) + foreach ($values as $value) { + $query = 'INSERT INTO `'._DB_PREFIX_.'customized_data` (`id_customization`, `type`, `index`, `value`) VALUES ('.(int)$this->id.', 1, '.(int)$value['id_customization_field'].', \''.pSQL($value['value']).'\')'; - if (!Db::getInstance()->execute($query)) - return false; - } - return true; - } + if (!Db::getInstance()->execute($query)) { + return false; + } + } + return true; + } } diff --git a/classes/CustomizationField.php b/classes/CustomizationField.php index 3f38b0f8..3fd897e9 100644 --- a/classes/CustomizationField.php +++ b/classes/CustomizationField.php @@ -26,40 +26,40 @@ class CustomizationFieldCore extends ObjectModel { - /** @var int */ - public $id_product; - /** @var int Customization type (0 File, 1 Textfield) (See Product class) */ - public $type; - /** @var bool Field is required */ - public $required; - /** @var string Label for customized field */ - public $name; + /** @var int */ + public $id_product; + /** @var int Customization type (0 File, 1 Textfield) (See Product class) */ + public $type; + /** @var bool Field is required */ + public $required; + /** @var string Label for customized field */ + public $name; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'customization_field', - 'primary' => 'id_customization_field', - 'multilang' => true, - 'multilang_shop' => true, - 'fields' => array( - /* Classic fields */ - 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'type' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'required' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'customization_field', + 'primary' => 'id_customization_field', + 'multilang' => true, + 'multilang_shop' => true, + 'fields' => array( + /* Classic fields */ + 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'type' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'required' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'required' => true, 'size' => 255), - ), - ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_product' => array( - 'xlink_resource' => array( - 'resourceName' => 'products' - ) - ), - ), - ); -} \ No newline at end of file + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'required' => true, 'size' => 255), + ), + ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_product' => array( + 'xlink_resource' => array( + 'resourceName' => 'products' + ) + ), + ), + ); +} diff --git a/classes/DateRange.php b/classes/DateRange.php index 8a629c59..e8c9bb2a 100644 --- a/classes/DateRange.php +++ b/classes/DateRange.php @@ -26,37 +26,36 @@ class DateRangeCore extends ObjectModel { - public $time_start; - public $time_end; + public $time_start; + public $time_end; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'date_range', - 'primary' => 'id_date_range', - 'fields' => array( - 'time_start' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), - 'time_end' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'date_range', + 'primary' => 'id_date_range', + 'fields' => array( + 'time_start' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), + 'time_end' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), + ), + ); - public static function getCurrentRange() - { - $result = Db::getInstance()->getRow(' + public static function getCurrentRange() + { + $result = Db::getInstance()->getRow(' SELECT `id_date_range`, `time_end` FROM `'._DB_PREFIX_.'date_range` WHERE `time_end` = (SELECT MAX(`time_end`) FROM `'._DB_PREFIX_.'date_range`)'); - if (!$result['id_date_range'] || strtotime($result['time_end']) < strtotime(date('Y-m-d H:i:s'))) - { - // The default range is set to 1 day less 1 second (in seconds) - $rangeSize = 86399; - $dateRange = new DateRange(); - $dateRange->time_start = date('Y-m-d'); - $dateRange->time_end = strftime('%Y-%m-%d %H:%M:%S', strtotime($dateRange->time_start) + $rangeSize); - $dateRange->add(); - return $dateRange->id; - } - return $result['id_date_range']; - } -} \ No newline at end of file + if (!$result['id_date_range'] || strtotime($result['time_end']) < strtotime(date('Y-m-d H:i:s'))) { + // The default range is set to 1 day less 1 second (in seconds) + $rangeSize = 86399; + $dateRange = new DateRange(); + $dateRange->time_start = date('Y-m-d'); + $dateRange->time_end = strftime('%Y-%m-%d %H:%M:%S', strtotime($dateRange->time_start) + $rangeSize); + $dateRange->add(); + return $dateRange->id; + } + return $result['id_date_range']; + } +} diff --git a/classes/Delivery.php b/classes/Delivery.php index 3013382b..b1cddb21 100644 --- a/classes/Delivery.php +++ b/classes/Delivery.php @@ -26,72 +26,74 @@ class DeliveryCore extends ObjectModel { - /** @var int */ - public $id_delivery; + /** @var int */ + public $id_delivery; - /** @var int **/ - public $id_shop; + /** @var int **/ + public $id_shop; - /** @var int **/ - public $id_shop_group; + /** @var int **/ + public $id_shop_group; - /** @var int */ - public $id_carrier; + /** @var int */ + public $id_carrier; - /** @var int */ - public $id_range_price; + /** @var int */ + public $id_range_price; - /** @var int */ - public $id_range_weight; + /** @var int */ + public $id_range_weight; - /** @var int */ - public $id_zone; + /** @var int */ + public $id_zone; - /** @var float */ - public $price; + /** @var float */ + public $price; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'delivery', - 'primary' => 'id_delivery', - 'fields' => array( - 'id_carrier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_range_price' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_range_weight' =>array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_zone' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_shop' => array('type' => self::TYPE_INT), - 'id_shop_group' => array('type' => self::TYPE_INT), - 'price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'delivery', + 'primary' => 'id_delivery', + 'fields' => array( + 'id_carrier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_range_price' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_range_weight' =>array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_zone' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_shop' => array('type' => self::TYPE_INT), + 'id_shop_group' => array('type' => self::TYPE_INT), + 'price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + ), + ); - protected $webserviceParameters = array( - 'objectsNodeName' => 'deliveries', - 'fields' => array( - 'id_carrier' => array('xlink_resource' => 'carriers'), - 'id_range_price' => array('xlink_resource' => 'price_ranges'), - 'id_range_weight' => array('xlink_resource' => 'weight_ranges'), - 'id_zone' => array('xlink_resource' => 'zones'), - ) - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'deliveries', + 'fields' => array( + 'id_carrier' => array('xlink_resource' => 'carriers'), + 'id_range_price' => array('xlink_resource' => 'price_ranges'), + 'id_range_weight' => array('xlink_resource' => 'weight_ranges'), + 'id_zone' => array('xlink_resource' => 'zones'), + ) + ); - public function getFields() - { - $fields = parent::getFields(); + public function getFields() + { + $fields = parent::getFields(); - // @todo add null management in definitions - if ($this->id_shop) - $fields['id_shop'] = (int)$this->id_shop; - else - $fields['id_shop'] = null; + // @todo add null management in definitions + if ($this->id_shop) { + $fields['id_shop'] = (int)$this->id_shop; + } else { + $fields['id_shop'] = null; + } - if ($this->id_shop_group) - $fields['id_shop_group'] = (int)$this->id_shop_group; - else - $fields['id_shop_group'] = null; + if ($this->id_shop_group) { + $fields['id_shop_group'] = (int)$this->id_shop_group; + } else { + $fields['id_shop_group'] = null; + } - return $fields; - } -} \ No newline at end of file + return $fields; + } +} diff --git a/classes/Discount.php b/classes/Discount.php index 6132189f..71c21d74 100644 --- a/classes/Discount.php +++ b/classes/Discount.php @@ -29,239 +29,261 @@ */ class DiscountCore extends CartRule { - const PERCENT = 1; - const AMOUNT = 2; - const FREE_SHIPPING = 3; + const PERCENT = 1; + const AMOUNT = 2; + const FREE_SHIPPING = 3; - public function __get($key) - { - Tools::displayAsDeprecated(); + public function __get($key) + { + Tools::displayAsDeprecated(); - if ($key == 'id_group') - return 0; - if ($key == 'id_discount_type') - { - if ($this->free_shipping) - return Discount::FREE_SHIPPING; - if ($this->reduction_percent > 0) - return Discount::PERCENT; - if ($this->reduction_amount > 0) - return Discount::AMOUNT; - } - if ($key == 'name') - return $this->code; - if ($key == 'value') - { - if ($this->reduction_percent > 0) - return $this->reduction_percent; - if ($this->reduction_amount > 0) - return $this->reduction_amount; - } - if ($key == 'cumulable') - return $this->cart_rule_restriction; - if ($key == 'cumulable_reduction') - return false; - if ($key == 'minimal') - return $this->minimum_amount; - if ($key == 'include_tax') - return $this->reduction_tax; - if ($key == 'behavior_not_exhausted') - return $this->partial_use; - if ($key == 'cart_display') - return true; + if ($key == 'id_group') { + return 0; + } + if ($key == 'id_discount_type') { + if ($this->free_shipping) { + return Discount::FREE_SHIPPING; + } + if ($this->reduction_percent > 0) { + return Discount::PERCENT; + } + if ($this->reduction_amount > 0) { + return Discount::AMOUNT; + } + } + if ($key == 'name') { + return $this->code; + } + if ($key == 'value') { + if ($this->reduction_percent > 0) { + return $this->reduction_percent; + } + if ($this->reduction_amount > 0) { + return $this->reduction_amount; + } + } + if ($key == 'cumulable') { + return $this->cart_rule_restriction; + } + if ($key == 'cumulable_reduction') { + return false; + } + if ($key == 'minimal') { + return $this->minimum_amount; + } + if ($key == 'include_tax') { + return $this->reduction_tax; + } + if ($key == 'behavior_not_exhausted') { + return $this->partial_use; + } + if ($key == 'cart_display') { + return true; + } - return $this->{$key}; - } + return $this->{$key}; + } - public function __set($key, $value) - { - Tools::displayAsDeprecated(); + public function __set($key, $value) + { + Tools::displayAsDeprecated(); - if ($key == 'id_discount_type') - { - if ($value == Discount::FREE_SHIPPING) - { - $this->free_shipping = true; - $this->reduction_percent = false; - $this->reduction_amount = false; - } - if ($value == Discount::PERCENT) - { - $this->free_shipping = false; - $this->reduction_percent = true; - $this->reduction_amount = false; - } - if ($value == Discount::AMOUNT) - { - $this->free_shipping = false; - $this->reduction_percent = false; - $this->reduction_amount = true; - } - } + if ($key == 'id_discount_type') { + if ($value == Discount::FREE_SHIPPING) { + $this->free_shipping = true; + $this->reduction_percent = false; + $this->reduction_amount = false; + } + if ($value == Discount::PERCENT) { + $this->free_shipping = false; + $this->reduction_percent = true; + $this->reduction_amount = false; + } + if ($value == Discount::AMOUNT) { + $this->free_shipping = false; + $this->reduction_percent = false; + $this->reduction_amount = true; + } + } - if ($key == 'code') - $this->name[Configuration::get('PS_LANG_DEFAULT')] = $value; + if ($key == 'code') { + $this->name[Configuration::get('PS_LANG_DEFAULT')] = $value; + } - if ($key == 'value') - { - if ($this->reduction_percent) - $this->reduction_percent = $value; - if ($this->reduction_amount) - $this->reduction_amount = $value; - } - if ($key == 'cumulable') - $this->cart_rule_restriction = 1; - if ($key == 'minimal') - $this->minimum_amount = $value; - if ($key == 'include_tax') - $this->reduction_tax = $value; - if ($key == 'behavior_not_exhausted') - $this->partial_use = $value; + if ($key == 'value') { + if ($this->reduction_percent) { + $this->reduction_percent = $value; + } + if ($this->reduction_amount) { + $this->reduction_amount = $value; + } + } + if ($key == 'cumulable') { + $this->cart_rule_restriction = 1; + } + if ($key == 'minimal') { + $this->minimum_amount = $value; + } + if ($key == 'include_tax') { + $this->reduction_tax = $value; + } + if ($key == 'behavior_not_exhausted') { + $this->partial_use = $value; + } - $this->{$key} = $value; - } + $this->{$key} = $value; + } - public function __call($method, $args) - { - Tools::displayAsDeprecated(); - $obj = $this->parent; - if (in_array($method, array('add', 'update', 'getIdByName', 'getCustomerDiscounts', 'getValue', 'discountExists', 'createOrderDiscount', 'getVouchersToCartDisplay', 'display'))) - $obj = $this; - return call_user_func_array(array($obj, $method), $args); - } + public function __call($method, $args) + { + Tools::displayAsDeprecated(); + $obj = $this->parent; + if (in_array($method, array('add', 'update', 'getIdByName', 'getCustomerDiscounts', 'getValue', 'discountExists', 'createOrderDiscount', 'getVouchersToCartDisplay', 'display'))) { + $obj = $this; + } + return call_user_func_array(array($obj, $method), $args); + } - /** - * @deprecated 1.5.0.1 - */ - public function add($autodate = true, $nullValues = false, $categories = null) - { - $r = parent::add($autodate, $nullValues); - // Todo : manage categories - return $r; - } + /** + * @deprecated 1.5.0.1 + */ + public function add($autodate = true, $nullValues = false, $categories = null) + { + $r = parent::add($autodate, $nullValues); + // Todo : manage categories + return $r; + } - /** - * @deprecated 1.5.0.1 - */ - public function update($autodate = true, $nullValues = false, $categories = null) - { - $r = parent::update($autodate, $nullValues); - // Todo : manage categories - return $r; - } + /** + * @deprecated 1.5.0.1 + */ + public function update($autodate = true, $nullValues = false, $categories = null) + { + $r = parent::update($autodate, $nullValues); + // Todo : manage categories + return $r; + } - /** - * @deprecated 1.5.0.1 - */ - public static function getIdByName($code) - { - return parent::getIdByCode($code); - } + /** + * @deprecated 1.5.0.1 + */ + public static function getIdByName($code) + { + return parent::getIdByCode($code); + } - /** - * @deprecated 1.5.0.1 - */ - public static function getCustomerDiscounts($id_lang, $id_customer, $active = false, $includeGenericOnes = true, $hasStock = false, Cart $cart = null) - { - return parent::getCustomerCartRules($id_lang, $id_customer, $active, $includeGenericOnes, $hasStock, $cart); - } + /** + * @deprecated 1.5.0.1 + */ + public static function getCustomerDiscounts($id_lang, $id_customer, $active = false, $includeGenericOnes = true, $hasStock = false, Cart $cart = null) + { + return parent::getCustomerCartRules($id_lang, $id_customer, $active, $includeGenericOnes, $hasStock, $cart); + } - /** - * @deprecated 1.5.0.1 - */ - public static function getVouchersToCartDisplay($id_lang, $id_customer) - { - return CartRule::getCustomerCartRules($id_lang, $id_customer); - } + /** + * @deprecated 1.5.0.1 + */ + public static function getVouchersToCartDisplay($id_lang, $id_customer) + { + return CartRule::getCustomerCartRules($id_lang, $id_customer); + } - /** - * @deprecated 1.5.0.1 - */ - public function getValue($nb_discounts = 0, $order_total_products = 0, $shipping_fees = 0, $id_cart = false, $useTax = true, Currency $currency = null, Shop $shop = null) - { - $context = Context::getContext(); - if ((int)$id_cart) - $context->cart = new Cart($id_cart); - if (Validate::isLoadedObject($currency)) - $context->currency = $currency; - if (Validate::isLoadedObject($shop)) - $context->shop = $shop; - return parent::getContextualValue($useTax, $context); - } + /** + * @deprecated 1.5.0.1 + */ + public function getValue($nb_discounts = 0, $order_total_products = 0, $shipping_fees = 0, $id_cart = false, $useTax = true, Currency $currency = null, Shop $shop = null) + { + $context = Context::getContext(); + if ((int)$id_cart) { + $context->cart = new Cart($id_cart); + } + if (Validate::isLoadedObject($currency)) { + $context->currency = $currency; + } + if (Validate::isLoadedObject($shop)) { + $context->shop = $shop; + } + return parent::getContextualValue($useTax, $context); + } - /** - * @deprecated 1.5.0.1 - */ - public static function discountExists($discountName, $id_discount = 0) - { - return parent::cartRuleExists($discountName); - } + /** + * @deprecated 1.5.0.1 + */ + public static function discountExists($discountName, $id_discount = 0) + { + return parent::cartRuleExists($discountName); + } - /** - * @deprecated 1.5.0.1 - * @param Order $order - * @return Discount - */ - public static function createOrderDiscount($order, $productList, $qtyList, $name, $shipping_cost = false, $id_category = 0, $subcategory = 0) - { - $products = $order->getProducts(false, $productList, $qtyList); + /** + * @deprecated 1.5.0.1 + * @param Order $order + * @return Discount + */ + public static function createOrderDiscount($order, $productList, $qtyList, $name, $shipping_cost = false, $id_category = 0, $subcategory = 0) + { + $products = $order->getProducts(false, $productList, $qtyList); - // Totals are stored in the order currency (or at least should be) - $total = $order->getTotalProductsWithTaxes($products); - $discounts = $order->getDiscounts(true); - $total_tmp = $total; - foreach ($discounts as $discount) - { - if ($discount['id_discount_type'] == Discount::PERCENT) - $total -= $total_tmp * ($discount['value'] / 100); - elseif ($discount['id_discount_type'] == Discount::AMOUNT) - $total -= ($discount['value'] * ($total_tmp / $order->total_products_wt)); - } - if ($shipping_cost) - $total += $order->total_shipping; + // Totals are stored in the order currency (or at least should be) + $total = $order->getTotalProductsWithTaxes($products); + $discounts = $order->getDiscounts(true); + $total_tmp = $total; + foreach ($discounts as $discount) { + if ($discount['id_discount_type'] == Discount::PERCENT) { + $total -= $total_tmp * ($discount['value'] / 100); + } elseif ($discount['id_discount_type'] == Discount::AMOUNT) { + $total -= ($discount['value'] * ($total_tmp / $order->total_products_wt)); + } + } + if ($shipping_cost) { + $total += $order->total_shipping; + } - // create discount - $voucher = new Discount(); - $voucher->id_discount_type = Discount::AMOUNT; - foreach (Language::getIDs((bool)$order) as $id_lang) - $voucher->description[$id_lang] = strval($name).(int)($order->id); - $voucher->value = (float)($total); - $voucher->name = 'V0C'.(int)($order->id_customer).'O'.(int)($order->id); - $voucher->id_customer = (int)($order->id_customer); - $voucher->id_currency = (int)($order->id_currency); - $voucher->quantity = 1; - $voucher->quantity_per_user = 1; - $voucher->cumulable = 1; - $voucher->cumulable_reduction = 1; - $voucher->minimal = (float)($voucher->value); - $voucher->active = 1; - $voucher->cart_display = 1; + // create discount + $voucher = new Discount(); + $voucher->id_discount_type = Discount::AMOUNT; + foreach (Language::getIDs((bool)$order) as $id_lang) { + $voucher->description[$id_lang] = strval($name).(int)($order->id); + } + $voucher->value = (float)($total); + $voucher->name = 'V0C'.(int)($order->id_customer).'O'.(int)($order->id); + $voucher->id_customer = (int)($order->id_customer); + $voucher->id_currency = (int)($order->id_currency); + $voucher->quantity = 1; + $voucher->quantity_per_user = 1; + $voucher->cumulable = 1; + $voucher->cumulable_reduction = 1; + $voucher->minimal = (float)($voucher->value); + $voucher->active = 1; + $voucher->cart_display = 1; - $now = time(); - $voucher->date_from = date('Y-m-d H:i:s', $now); - $voucher->date_to = date('Y-m-d H:i:s', $now + (3600 * 24 * 365.25)); /* 1 year */ - if (!$voucher->validateFieldsLang(false) || !$voucher->add()) - return false; - // set correct name - $voucher->name = 'V'.(int)($voucher->id).'C'.(int)($order->id_customer).'O'.$order->id; - if (!$voucher->update()) - return false; + $now = time(); + $voucher->date_from = date('Y-m-d H:i:s', $now); + $voucher->date_to = date('Y-m-d H:i:s', $now + (3600 * 24 * 365.25)); /* 1 year */ + if (!$voucher->validateFieldsLang(false) || !$voucher->add()) { + return false; + } + // set correct name + $voucher->name = 'V'.(int)($voucher->id).'C'.(int)($order->id_customer).'O'.$order->id; + if (!$voucher->update()) { + return false; + } - return $voucher; - } + return $voucher; + } - /** - * @deprecated 1.5.0.1 - */ - public static function display($value, $type, $currency = null) - { - if ((float)$value && (int)$type) - { - if ($type == 1) - return $value.chr(37); // ASCII #37 --> % (percent) - elseif ($type == 2) - return Tools::displayPrice($value, $currency); - } - return ''; // return a string because it's a display method - } -} \ No newline at end of file + /** + * @deprecated 1.5.0.1 + */ + public static function display($value, $type, $currency = null) + { + if ((float)$value && (int)$type) { + if ($type == 1) { + return $value.chr(37); + } // ASCII #37 --> % (percent) + elseif ($type == 2) { + return Tools::displayPrice($value, $currency); + } + } + return ''; // return a string because it's a display method + } +} diff --git a/classes/Dispatcher.php b/classes/Dispatcher.php index f690ecc9..c6e3b30a 100644 --- a/classes/Dispatcher.php +++ b/classes/Dispatcher.php @@ -29,844 +29,863 @@ */ class DispatcherCore { - /** - * List of available front controllers types - */ - const FC_FRONT = 1; - const FC_ADMIN = 2; - const FC_MODULE = 3; + /** + * List of available front controllers types + */ + const FC_FRONT = 1; + const FC_ADMIN = 2; + const FC_MODULE = 3; - /** - * @var Dispatcher - */ - public static $instance = null; + /** + * @var Dispatcher + */ + public static $instance = null; - /** - * @var array List of default routes - */ - public $default_routes = array( - 'category_rule' => array( - 'controller' => 'category', - 'rule' => '{id}-{rewrite}', - 'keywords' => array( - 'id' => array('regexp' => '[0-9]+', 'param' => 'id_category'), - 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), - 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - ), - ), - 'supplier_rule' => array( - 'controller' => 'supplier', - 'rule' => '{id}__{rewrite}', - 'keywords' => array( - 'id' => array('regexp' => '[0-9]+', 'param' => 'id_supplier'), - 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), - 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - ), - ), - 'manufacturer_rule' => array( - 'controller' => 'manufacturer', - 'rule' => '{id}_{rewrite}', - 'keywords' => array( - 'id' => array('regexp' => '[0-9]+', 'param' => 'id_manufacturer'), - 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), - 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - ), - ), - 'cms_rule' => array( - 'controller' => 'cms', - 'rule' => 'content/{id}-{rewrite}', - 'keywords' => array( - 'id' => array('regexp' => '[0-9]+', 'param' => 'id_cms'), - 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), - 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - ), - ), - 'cms_category_rule' => array( - 'controller' => 'cms', - 'rule' => 'content/category/{id}-{rewrite}', - 'keywords' => array( - 'id' => array('regexp' => '[0-9]+', 'param' => 'id_cms_category'), - 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), - 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - ), - ), - 'module' => array( - 'controller' => null, - 'rule' => 'module/{module}{/:controller}', - 'keywords' => array( - 'module' => array('regexp' => '[_a-zA-Z0-9_-]+', 'param' => 'module'), - 'controller' => array('regexp' => '[_a-zA-Z0-9_-]+', 'param' => 'controller'), - ), - 'params' => array( - 'fc' => 'module', - ), - ), - 'product_rule' => array( - 'controller' => 'product', - 'rule' => '{category:/}{id}-{rewrite}{-:ean13}.html', - 'keywords' => array( - 'id' => array('regexp' => '[0-9]+', 'param' => 'id_product'), - 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), - 'ean13' => array('regexp' => '[0-9\pL]*'), - 'category' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - 'categories' => array('regexp' => '[/_a-zA-Z0-9-\pL]*'), - 'reference' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - 'manufacturer' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - 'supplier' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - 'price' => array('regexp' => '[0-9\.,]*'), - 'tags' => array('regexp' => '[a-zA-Z0-9-\pL]*'), - ), - ), - /* Must be after the product and category rules in order to avoid conflict */ - 'layered_rule' => array( - 'controller' => 'category', - 'rule' => '{id}-{rewrite}{/:selected_filters}', - 'keywords' => array( - 'id' => array('regexp' => '[0-9]+', 'param' => 'id_category'), - /* Selected filters is used by the module blocklayered */ - 'selected_filters' => array('regexp' => '.*', 'param' => 'selected_filters'), - 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), - 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), - ), - ), - ); + /** + * @var array List of default routes + */ + public $default_routes = array( + 'category_rule' => array( + 'controller' => 'category', + 'rule' => '{id}-{rewrite}', + 'keywords' => array( + 'id' => array('regexp' => '[0-9]+', 'param' => 'id_category'), + 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), + 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + ), + ), + 'supplier_rule' => array( + 'controller' => 'supplier', + 'rule' => '{id}__{rewrite}', + 'keywords' => array( + 'id' => array('regexp' => '[0-9]+', 'param' => 'id_supplier'), + 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), + 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + ), + ), + 'manufacturer_rule' => array( + 'controller' => 'manufacturer', + 'rule' => '{id}_{rewrite}', + 'keywords' => array( + 'id' => array('regexp' => '[0-9]+', 'param' => 'id_manufacturer'), + 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), + 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + ), + ), + 'cms_rule' => array( + 'controller' => 'cms', + 'rule' => 'content/{id}-{rewrite}', + 'keywords' => array( + 'id' => array('regexp' => '[0-9]+', 'param' => 'id_cms'), + 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), + 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + ), + ), + 'cms_category_rule' => array( + 'controller' => 'cms', + 'rule' => 'content/category/{id}-{rewrite}', + 'keywords' => array( + 'id' => array('regexp' => '[0-9]+', 'param' => 'id_cms_category'), + 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), + 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + ), + ), + 'module' => array( + 'controller' => null, + 'rule' => 'module/{module}{/:controller}', + 'keywords' => array( + 'module' => array('regexp' => '[_a-zA-Z0-9_-]+', 'param' => 'module'), + 'controller' => array('regexp' => '[_a-zA-Z0-9_-]+', 'param' => 'controller'), + ), + 'params' => array( + 'fc' => 'module', + ), + ), + 'product_rule' => array( + 'controller' => 'product', + 'rule' => '{category:/}{id}-{rewrite}{-:ean13}.html', + 'keywords' => array( + 'id' => array('regexp' => '[0-9]+', 'param' => 'id_product'), + 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), + 'ean13' => array('regexp' => '[0-9\pL]*'), + 'category' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + 'categories' => array('regexp' => '[/_a-zA-Z0-9-\pL]*'), + 'reference' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + 'manufacturer' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + 'supplier' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + 'price' => array('regexp' => '[0-9\.,]*'), + 'tags' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + ), + ), + /* Must be after the product and category rules in order to avoid conflict */ + 'layered_rule' => array( + 'controller' => 'category', + 'rule' => '{id}-{rewrite}{/:selected_filters}', + 'keywords' => array( + 'id' => array('regexp' => '[0-9]+', 'param' => 'id_category'), + /* Selected filters is used by the module blocklayered */ + 'selected_filters' => array('regexp' => '.*', 'param' => 'selected_filters'), + 'rewrite' => array('regexp' => '[_a-zA-Z0-9\pL\pS-]*'), + 'meta_keywords' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + 'meta_title' => array('regexp' => '[_a-zA-Z0-9-\pL]*'), + ), + ), + ); - /** - * @var bool If true, use routes to build URL (mod rewrite must be activated) - */ - protected $use_routes = false; + /** + * @var bool If true, use routes to build URL (mod rewrite must be activated) + */ + protected $use_routes = false; - protected $multilang_activated = false; + protected $multilang_activated = false; - /** - * @var array List of loaded routes - */ - protected $routes = array(); + /** + * @var array List of loaded routes + */ + protected $routes = array(); - /** - * @var string Current controller name - */ - protected $controller; + /** + * @var string Current controller name + */ + protected $controller; - /** - * @var string Current request uri - */ - protected $request_uri; + /** + * @var string Current request uri + */ + protected $request_uri; - /** - * @var array Store empty route (a route with an empty rule) - */ - protected $empty_route; + /** + * @var array Store empty route (a route with an empty rule) + */ + protected $empty_route; - /** - * @var string Set default controller, which will be used if http parameter 'controller' is empty - */ - protected $default_controller; - protected $use_default_controller = false; + /** + * @var string Set default controller, which will be used if http parameter 'controller' is empty + */ + protected $default_controller; + protected $use_default_controller = false; - /** - * @var string Controller to use if found controller doesn't exist - */ - protected $controller_not_found = 'pagenotfound'; + /** + * @var string Controller to use if found controller doesn't exist + */ + protected $controller_not_found = 'pagenotfound'; - /** - * @var string Front controller to use - */ - protected $front_controller = self::FC_FRONT; + /** + * @var string Front controller to use + */ + protected $front_controller = self::FC_FRONT; - /** - * Get current instance of dispatcher (singleton) - * - * @return Dispatcher - */ - public static function getInstance() - { - if (!self::$instance) - self::$instance = new Dispatcher(); - return self::$instance; - } + /** + * Get current instance of dispatcher (singleton) + * + * @return Dispatcher + */ + public static function getInstance() + { + if (!self::$instance) { + self::$instance = new Dispatcher(); + } + return self::$instance; + } - /** - * Need to be instancied from getInstance() method - */ - protected function __construct() - { - $this->use_routes = (bool)Configuration::get('PS_REWRITING_SETTINGS'); + /** + * Need to be instancied from getInstance() method + */ + protected function __construct() + { + $this->use_routes = (bool)Configuration::get('PS_REWRITING_SETTINGS'); - // Select right front controller - if (defined('_PS_ADMIN_DIR_')) - { - $this->front_controller = self::FC_ADMIN; - $this->controller_not_found = 'adminnotfound'; - } - elseif (Tools::getValue('fc') == 'module') - { - $this->front_controller = self::FC_MODULE; - $this->controller_not_found = 'pagenotfound'; - } - else - { - $this->front_controller = self::FC_FRONT; - $this->controller_not_found = 'pagenotfound'; - } + // Select right front controller + if (defined('_PS_ADMIN_DIR_')) { + $this->front_controller = self::FC_ADMIN; + $this->controller_not_found = 'adminnotfound'; + } elseif (Tools::getValue('fc') == 'module') { + $this->front_controller = self::FC_MODULE; + $this->controller_not_found = 'pagenotfound'; + } else { + $this->front_controller = self::FC_FRONT; + $this->controller_not_found = 'pagenotfound'; + } - $this->setRequestUri(); + $this->setRequestUri(); - // Switch language if needed (only on front) - if (in_array($this->front_controller, array(self::FC_FRONT, self::FC_MODULE))) - Tools::switchLanguage(); + // Switch language if needed (only on front) + if (in_array($this->front_controller, array(self::FC_FRONT, self::FC_MODULE))) { + Tools::switchLanguage(); + } - if (Language::isMultiLanguageActivated()) - $this->multilang_activated = true; + if (Language::isMultiLanguageActivated()) { + $this->multilang_activated = true; + } - $this->loadRoutes(); - } + $this->loadRoutes(); + } - public function useDefaultController() - { - $this->use_default_controller = true; - if ($this->default_controller === null) - { - if (defined('_PS_ADMIN_DIR_')) - { - if (isset(Context::getContext()->employee) && Validate::isLoadedObject(Context::getContext()->employee) && isset(Context::getContext()->employee->default_tab)) - $this->default_controller = Tab::getClassNameById((int)Context::getContext()->employee->default_tab); - if (empty($this->default_controller)) - $this->default_controller = 'AdminDashboard'; - } - elseif (Tools::getValue('fc') == 'module') - $this->default_controller = 'default'; - else - $this->default_controller = 'index'; - } - return $this->default_controller; - } + public function useDefaultController() + { + $this->use_default_controller = true; + if ($this->default_controller === null) { + if (defined('_PS_ADMIN_DIR_')) { + if (isset(Context::getContext()->employee) && Validate::isLoadedObject(Context::getContext()->employee) && isset(Context::getContext()->employee->default_tab)) { + $this->default_controller = Tab::getClassNameById((int)Context::getContext()->employee->default_tab); + } + if (empty($this->default_controller)) { + $this->default_controller = 'AdminDashboard'; + } + } elseif (Tools::getValue('fc') == 'module') { + $this->default_controller = 'default'; + } else { + $this->default_controller = 'index'; + } + } + return $this->default_controller; + } - /** - * Find the controller and instantiate it - */ - public function dispatch() - { - $controller_class = ''; + /** + * Find the controller and instantiate it + */ + public function dispatch() + { + $controller_class = ''; - // Get current controller - $this->getController(); - if (!$this->controller) - $this->controller = $this->useDefaultController(); - // Dispatch with right front controller - switch ($this->front_controller) - { - // Dispatch front office controller - case self::FC_FRONT : - $controllers = Dispatcher::getControllers(array(_PS_FRONT_CONTROLLER_DIR_, _PS_OVERRIDE_DIR_.'controllers/front/')); - $controllers['index'] = 'IndexController'; - if (isset($controllers['auth'])) - $controllers['authentication'] = $controllers['auth']; - if (isset($controllers['compare'])) - $controllers['productscomparison'] = $controllers['compare']; - if (isset($controllers['contact'])) - $controllers['contactform'] = $controllers['contact']; + // Get current controller + $this->getController(); + if (!$this->controller) { + $this->controller = $this->useDefaultController(); + } + // Dispatch with right front controller + switch ($this->front_controller) { + // Dispatch front office controller + case self::FC_FRONT : + $controllers = Dispatcher::getControllers(array(_PS_FRONT_CONTROLLER_DIR_, _PS_OVERRIDE_DIR_.'controllers/front/')); + $controllers['index'] = 'IndexController'; + if (isset($controllers['auth'])) { + $controllers['authentication'] = $controllers['auth']; + } + if (isset($controllers['compare'])) { + $controllers['productscomparison'] = $controllers['compare']; + } + if (isset($controllers['contact'])) { + $controllers['contactform'] = $controllers['contact']; + } - if (!isset($controllers[strtolower($this->controller)])) - $this->controller = $this->controller_not_found; - $controller_class = $controllers[strtolower($this->controller)]; - $params_hook_action_dispatcher = array('controller_type' => self::FC_FRONT, 'controller_class' => $controller_class, 'is_module' => 0); - break; + if (!isset($controllers[strtolower($this->controller)])) { + $this->controller = $this->controller_not_found; + } + $controller_class = $controllers[strtolower($this->controller)]; + $params_hook_action_dispatcher = array('controller_type' => self::FC_FRONT, 'controller_class' => $controller_class, 'is_module' => 0); + break; - // Dispatch module controller for front office - case self::FC_MODULE : - $module_name = Validate::isModuleName(Tools::getValue('module')) ? Tools::getValue('module') : ''; - $module = Module::getInstanceByName($module_name); - $controller_class = 'PageNotFoundController'; - if (Validate::isLoadedObject($module) && $module->active) - { - $controllers = Dispatcher::getControllers(_PS_MODULE_DIR_.$module_name.'/controllers/front/'); - if (isset($controllers[strtolower($this->controller)])) - { - include_once(_PS_MODULE_DIR_.$module_name.'/controllers/front/'.$this->controller.'.php'); - $controller_class = $module_name.$this->controller.'ModuleFrontController'; - } - } - $params_hook_action_dispatcher = array('controller_type' => self::FC_FRONT, 'controller_class' => $controller_class, 'is_module' => 1); - break; + // Dispatch module controller for front office + case self::FC_MODULE : + $module_name = Validate::isModuleName(Tools::getValue('module')) ? Tools::getValue('module') : ''; + $module = Module::getInstanceByName($module_name); + $controller_class = 'PageNotFoundController'; + if (Validate::isLoadedObject($module) && $module->active) { + $controllers = Dispatcher::getControllers(_PS_MODULE_DIR_.$module_name.'/controllers/front/'); + if (isset($controllers[strtolower($this->controller)])) { + include_once(_PS_MODULE_DIR_.$module_name.'/controllers/front/'.$this->controller.'.php'); + $controller_class = $module_name.$this->controller.'ModuleFrontController'; + } + } + $params_hook_action_dispatcher = array('controller_type' => self::FC_FRONT, 'controller_class' => $controller_class, 'is_module' => 1); + break; - // Dispatch back office controller + module back office controller - case self::FC_ADMIN : - if ($this->use_default_controller && !Tools::getValue('token') && Validate::isLoadedObject(Context::getContext()->employee) && Context::getContext()->employee->isLoggedBack()) - Tools::redirectAdmin('index.php?controller='.$this->controller.'&token='.Tools::getAdminTokenLite($this->controller)); + // Dispatch back office controller + module back office controller + case self::FC_ADMIN : + if ($this->use_default_controller && !Tools::getValue('token') && Validate::isLoadedObject(Context::getContext()->employee) && Context::getContext()->employee->isLoggedBack()) { + Tools::redirectAdmin('index.php?controller='.$this->controller.'&token='.Tools::getAdminTokenLite($this->controller)); + } - $tab = Tab::getInstanceFromClassName($this->controller, Configuration::get('PS_LANG_DEFAULT')); - $retrocompatibility_admin_tab = null; + $tab = Tab::getInstanceFromClassName($this->controller, Configuration::get('PS_LANG_DEFAULT')); + $retrocompatibility_admin_tab = null; - if ($tab->module) - { - if (file_exists(_PS_MODULE_DIR_.$tab->module.'/'.$tab->class_name.'.php')) - $retrocompatibility_admin_tab = _PS_MODULE_DIR_.$tab->module.'/'.$tab->class_name.'.php'; - else - { - $controllers = Dispatcher::getControllers(_PS_MODULE_DIR_.$tab->module.'/controllers/admin/'); - if (!isset($controllers[strtolower($this->controller)])) - { - $this->controller = $this->controller_not_found; - $controller_class = 'AdminNotFoundController'; - } - else - { - // Controllers in modules can be named AdminXXX.php or AdminXXXController.php - include_once(_PS_MODULE_DIR_.$tab->module.'/controllers/admin/'.$controllers[strtolower($this->controller)].'.php'); - $controller_class = $controllers[strtolower($this->controller)].(strpos($controllers[strtolower($this->controller)], 'Controller') ? '' : 'Controller'); - } - } - $params_hook_action_dispatcher = array('controller_type' => self::FC_ADMIN, 'controller_class' => $controller_class, 'is_module' => 1); - } - else - { - $controllers = Dispatcher::getControllers(array(_PS_ADMIN_DIR_.'/tabs/', _PS_ADMIN_CONTROLLER_DIR_, _PS_OVERRIDE_DIR_.'controllers/admin/')); - if (!isset($controllers[strtolower($this->controller)])) - { - // If this is a parent tab, load the first child - if (Validate::isLoadedObject($tab) && $tab->id_parent == 0 && ($tabs = Tab::getTabs(Context::getContext()->language->id, $tab->id)) && isset($tabs[0])) - Tools::redirectAdmin(Context::getContext()->link->getAdminLink($tabs[0]['class_name'])); - $this->controller = $this->controller_not_found; - } + if ($tab->module) { + if (file_exists(_PS_MODULE_DIR_.$tab->module.'/'.$tab->class_name.'.php')) { + $retrocompatibility_admin_tab = _PS_MODULE_DIR_.$tab->module.'/'.$tab->class_name.'.php'; + } else { + $controllers = Dispatcher::getControllers(_PS_MODULE_DIR_.$tab->module.'/controllers/admin/'); + if (!isset($controllers[strtolower($this->controller)])) { + $this->controller = $this->controller_not_found; + $controller_class = 'AdminNotFoundController'; + } else { + // Controllers in modules can be named AdminXXX.php or AdminXXXController.php + include_once(_PS_MODULE_DIR_.$tab->module.'/controllers/admin/'.$controllers[strtolower($this->controller)].'.php'); + $controller_class = $controllers[strtolower($this->controller)].(strpos($controllers[strtolower($this->controller)], 'Controller') ? '' : 'Controller'); + } + } + $params_hook_action_dispatcher = array('controller_type' => self::FC_ADMIN, 'controller_class' => $controller_class, 'is_module' => 1); + } else { + $controllers = Dispatcher::getControllers(array(_PS_ADMIN_DIR_.'/tabs/', _PS_ADMIN_CONTROLLER_DIR_, _PS_OVERRIDE_DIR_.'controllers/admin/')); + if (!isset($controllers[strtolower($this->controller)])) { + // If this is a parent tab, load the first child + if (Validate::isLoadedObject($tab) && $tab->id_parent == 0 && ($tabs = Tab::getTabs(Context::getContext()->language->id, $tab->id)) && isset($tabs[0])) { + Tools::redirectAdmin(Context::getContext()->link->getAdminLink($tabs[0]['class_name'])); + } + $this->controller = $this->controller_not_found; + } - $controller_class = $controllers[strtolower($this->controller)]; - $params_hook_action_dispatcher = array('controller_type' => self::FC_ADMIN, 'controller_class' => $controller_class, 'is_module' => 0); + $controller_class = $controllers[strtolower($this->controller)]; + $params_hook_action_dispatcher = array('controller_type' => self::FC_ADMIN, 'controller_class' => $controller_class, 'is_module' => 0); - if (file_exists(_PS_ADMIN_DIR_.'/tabs/'.$controller_class.'.php')) - $retrocompatibility_admin_tab = _PS_ADMIN_DIR_.'/tabs/'.$controller_class.'.php'; - } + if (file_exists(_PS_ADMIN_DIR_.'/tabs/'.$controller_class.'.php')) { + $retrocompatibility_admin_tab = _PS_ADMIN_DIR_.'/tabs/'.$controller_class.'.php'; + } + } - // @retrocompatibility with admin/tabs/ old system - if ($retrocompatibility_admin_tab) - { - include_once($retrocompatibility_admin_tab); - include_once(_PS_ADMIN_DIR_.'/functions.php'); - runAdminTab($this->controller, !empty($_REQUEST['ajaxMode'])); - return; - } - break; + // @retrocompatibility with admin/tabs/ old system + if ($retrocompatibility_admin_tab) { + include_once($retrocompatibility_admin_tab); + include_once(_PS_ADMIN_DIR_.'/functions.php'); + runAdminTab($this->controller, !empty($_REQUEST['ajaxMode'])); + return; + } + break; - default : - throw new PrestaShopException('Bad front controller chosen'); - } + default : + throw new PrestaShopException('Bad front controller chosen'); + } - // Instantiate controller - try - { - // Loading controller - $controller = Controller::getController($controller_class); + // Instantiate controller + try { + // Loading controller + $controller = Controller::getController($controller_class); - // Execute hook dispatcher - if (isset($params_hook_action_dispatcher)) - Hook::exec('actionDispatcher', $params_hook_action_dispatcher); + // Execute hook dispatcher + if (isset($params_hook_action_dispatcher)) { + Hook::exec('actionDispatcher', $params_hook_action_dispatcher); + } - // Running controller - $controller->run(); - } - catch (PrestaShopException $e) - { - $e->displayMessage(); - } - } + // Running controller + $controller->run(); + } catch (PrestaShopException $e) { + $e->displayMessage(); + } + } - /** - * Set request uri and iso lang - */ - protected function setRequestUri() - { - // Get request uri (HTTP_X_REWRITE_URL is used by IIS) - if (isset($_SERVER['REQUEST_URI'])) - $this->request_uri = $_SERVER['REQUEST_URI']; - elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) - $this->request_uri = $_SERVER['HTTP_X_REWRITE_URL']; - $this->request_uri = rawurldecode($this->request_uri); + /** + * Set request uri and iso lang + */ + protected function setRequestUri() + { + // Get request uri (HTTP_X_REWRITE_URL is used by IIS) + if (isset($_SERVER['REQUEST_URI'])) { + $this->request_uri = $_SERVER['REQUEST_URI']; + } elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) { + $this->request_uri = $_SERVER['HTTP_X_REWRITE_URL']; + } + $this->request_uri = rawurldecode($this->request_uri); - if (isset(Context::getContext()->shop) && is_object(Context::getContext()->shop)) - $this->request_uri = preg_replace('#^'.preg_quote(Context::getContext()->shop->getBaseURI(), '#').'#i', '/', $this->request_uri); + if (isset(Context::getContext()->shop) && is_object(Context::getContext()->shop)) { + $this->request_uri = preg_replace('#^'.preg_quote(Context::getContext()->shop->getBaseURI(), '#').'#i', '/', $this->request_uri); + } - // If there are several languages, get language from uri - if ($this->use_routes && Language::isMultiLanguageActivated()) - if (preg_match('#^/([a-z]{2})(?:/.*)?$#', $this->request_uri, $m)) - { - $_GET['isolang'] = $m[1]; - $this->request_uri = substr($this->request_uri, 3); - } - } + // If there are several languages, get language from uri + if ($this->use_routes && Language::isMultiLanguageActivated()) { + if (preg_match('#^/([a-z]{2})(?:/.*)?$#', $this->request_uri, $m)) { + $_GET['isolang'] = $m[1]; + $this->request_uri = substr($this->request_uri, 3); + } + } + } - /** - * Load default routes group by languages - */ - protected function loadRoutes($id_shop = null) - { - $context = Context::getContext(); + /** + * Load default routes group by languages + */ + protected function loadRoutes($id_shop = null) + { + $context = Context::getContext(); - // Load custom routes from modules - $modules_routes = Hook::exec('moduleRoutes', array('id_shop' => $id_shop), null, true, false); - if (is_array($modules_routes) && count($modules_routes)) - foreach ($modules_routes as $module_route) - { - if (is_array($module_route) && count($module_route)) - foreach ($module_route as $route => $route_details) - if (array_key_exists('controller', $route_details) && array_key_exists('rule', $route_details) - && array_key_exists('keywords', $route_details) && array_key_exists('params', $route_details)) - { - if (!isset($this->default_routes[$route])) - $this->default_routes[$route] = array(); - $this->default_routes[$route] = array_merge($this->default_routes[$route], $route_details); - } - } + // Load custom routes from modules + $modules_routes = Hook::exec('moduleRoutes', array('id_shop' => $id_shop), null, true, false); + if (is_array($modules_routes) && count($modules_routes)) { + foreach ($modules_routes as $module_route) { + if (is_array($module_route) && count($module_route)) { + foreach ($module_route as $route => $route_details) { + if (array_key_exists('controller', $route_details) && array_key_exists('rule', $route_details) + && array_key_exists('keywords', $route_details) && array_key_exists('params', $route_details)) { + if (!isset($this->default_routes[$route])) { + $this->default_routes[$route] = array(); + } + $this->default_routes[$route] = array_merge($this->default_routes[$route], $route_details); + } + } + } + } + } - $language_ids = Language::getIDs(); + $language_ids = Language::getIDs(); - if (isset($context->language) && !in_array($context->language->id, $language_ids)) - $language_ids[] = (int)$context->language->id; + if (isset($context->language) && !in_array($context->language->id, $language_ids)) { + $language_ids[] = (int)$context->language->id; + } - // Set default routes - foreach ($language_ids as $id_lang) - foreach ($this->default_routes as $id => $route) - $this->addRoute( - $id, - $route['rule'], - $route['controller'], - $id_lang, - $route['keywords'], - isset($route['params']) ? $route['params'] : array(), - $id_shop - ); + // Set default routes + foreach ($language_ids as $id_lang) { + foreach ($this->default_routes as $id => $route) { + $this->addRoute( + $id, + $route['rule'], + $route['controller'], + $id_lang, + $route['keywords'], + isset($route['params']) ? $route['params'] : array(), + $id_shop + ); + } + } - // Load the custom routes prior the defaults to avoid infinite loops - if ($this->use_routes) - { - // Load routes from meta table - $sql = 'SELECT m.page, ml.url_rewrite, ml.id_lang + // Load the custom routes prior the defaults to avoid infinite loops + if ($this->use_routes) { + // Load routes from meta table + $sql = 'SELECT m.page, ml.url_rewrite, ml.id_lang FROM `'._DB_PREFIX_.'meta` m LEFT JOIN `'._DB_PREFIX_.'meta_lang` ml ON (m.id_meta = ml.id_meta'.Shop::addSqlRestrictionOnLang('ml', $id_shop).') ORDER BY LENGTH(ml.url_rewrite) DESC'; - if ($results = Db::getInstance()->executeS($sql)) - foreach ($results as $row) - { - if ($row['url_rewrite']) - $this->addRoute($row['page'], $row['url_rewrite'], $row['page'], $row['id_lang'], array(), array(), $id_shop); - } + if ($results = Db::getInstance()->executeS($sql)) { + foreach ($results as $row) { + if ($row['url_rewrite']) { + $this->addRoute($row['page'], $row['url_rewrite'], $row['page'], $row['id_lang'], array(), array(), $id_shop); + } + } + } - // Set default empty route if no empty route (that's weird I know) - if (!$this->empty_route) - $this->empty_route = array( - 'routeID' => 'index', - 'rule' => '', - 'controller' => 'index', - ); + // Set default empty route if no empty route (that's weird I know) + if (!$this->empty_route) { + $this->empty_route = array( + 'routeID' => 'index', + 'rule' => '', + 'controller' => 'index', + ); + } - // Load custom routes - foreach ($this->default_routes as $route_id => $route_data) - if ($custom_route = Configuration::get('PS_ROUTE_'.$route_id, null, null, $id_shop)) - { - if (isset($context->language) && !in_array($context->language->id, $language_ids)) - $language_ids[] = (int)$context->language->id; + // Load custom routes + foreach ($this->default_routes as $route_id => $route_data) { + if ($custom_route = Configuration::get('PS_ROUTE_'.$route_id, null, null, $id_shop)) { + if (isset($context->language) && !in_array($context->language->id, $language_ids)) { + $language_ids[] = (int)$context->language->id; + } - foreach ($language_ids as $id_lang) - $this->addRoute( - $route_id, - $custom_route, - $route_data['controller'], - $id_lang, - $route_data['keywords'], - isset($route_data['params']) ? $route_data['params'] : array(), - $id_shop - ); - } - } - } + foreach ($language_ids as $id_lang) { + $this->addRoute( + $route_id, + $custom_route, + $route_data['controller'], + $id_lang, + $route_data['keywords'], + isset($route_data['params']) ? $route_data['params'] : array(), + $id_shop + ); + } + } + } + } + } - /** - * - * @param string $route_id Name of the route (need to be uniq, a second route with same name will override the first) - * @param string $rule Url rule - * @param string $controller Controller to call if request uri match the rule - * @param int $id_lang - * @param int $id_shop - */ - public function addRoute($route_id, $rule, $controller, $id_lang = null, array $keywords = array(), array $params = array(), $id_shop = null) - { - if (isset(Context::getContext()->language) && $id_lang === null) - $id_lang = (int)Context::getContext()->language->id; + /** + * + * @param string $route_id Name of the route (need to be uniq, a second route with same name will override the first) + * @param string $rule Url rule + * @param string $controller Controller to call if request uri match the rule + * @param int $id_lang + * @param int $id_shop + */ + public function addRoute($route_id, $rule, $controller, $id_lang = null, array $keywords = array(), array $params = array(), $id_shop = null) + { + if (isset(Context::getContext()->language) && $id_lang === null) { + $id_lang = (int)Context::getContext()->language->id; + } - if (isset(Context::getContext()->shop) && $id_shop === null) - $id_shop = (int)Context::getContext()->shop->id; + if (isset(Context::getContext()->shop) && $id_shop === null) { + $id_shop = (int)Context::getContext()->shop->id; + } - $regexp = preg_quote($rule, '#'); - if ($keywords) - { - $transform_keywords = array(); - preg_match_all('#\\\{(([^{}]*)\\\:)?('.implode('|', array_keys($keywords)).')(\\\:([^{}]*))?\\\}#', $regexp, $m); - for ($i = 0, $total = count($m[0]); $i < $total; $i++) - { - $prepend = $m[2][$i]; - $keyword = $m[3][$i]; - $append = $m[5][$i]; - $transform_keywords[$keyword] = array( - 'required' => isset($keywords[$keyword]['param']), - 'prepend' => stripslashes($prepend), - 'append' => stripslashes($append), - ); + $regexp = preg_quote($rule, '#'); + if ($keywords) { + $transform_keywords = array(); + preg_match_all('#\\\{(([^{}]*)\\\:)?('.implode('|', array_keys($keywords)).')(\\\:([^{}]*))?\\\}#', $regexp, $m); + for ($i = 0, $total = count($m[0]); $i < $total; $i++) { + $prepend = $m[2][$i]; + $keyword = $m[3][$i]; + $append = $m[5][$i]; + $transform_keywords[$keyword] = array( + 'required' => isset($keywords[$keyword]['param']), + 'prepend' => stripslashes($prepend), + 'append' => stripslashes($append), + ); - $prepend_regexp = $append_regexp = ''; - if ($prepend || $append) - { - $prepend_regexp = '('.preg_quote($prepend); - $append_regexp = preg_quote($append).')?'; - } + $prepend_regexp = $append_regexp = ''; + if ($prepend || $append) { + $prepend_regexp = '('.preg_quote($prepend); + $append_regexp = preg_quote($append).')?'; + } - if (isset($keywords[$keyword]['param'])) - $regexp = str_replace($m[0][$i], $prepend_regexp.'(?P<'.$keywords[$keyword]['param'].'>'.$keywords[$keyword]['regexp'].')'.$append_regexp, $regexp); - else - $regexp = str_replace($m[0][$i], $prepend_regexp.'('.$keywords[$keyword]['regexp'].')'.$append_regexp, $regexp); + if (isset($keywords[$keyword]['param'])) { + $regexp = str_replace($m[0][$i], $prepend_regexp.'(?P<'.$keywords[$keyword]['param'].'>'.$keywords[$keyword]['regexp'].')'.$append_regexp, $regexp); + } else { + $regexp = str_replace($m[0][$i], $prepend_regexp.'('.$keywords[$keyword]['regexp'].')'.$append_regexp, $regexp); + } + } + $keywords = $transform_keywords; + } - } - $keywords = $transform_keywords; - } + $regexp = '#^/'.$regexp.'$#u'; + if (!isset($this->routes[$id_shop])) { + $this->routes[$id_shop] = array(); + } + if (!isset($this->routes[$id_shop][$id_lang])) { + $this->routes[$id_shop][$id_lang] = array(); + } - $regexp = '#^/'.$regexp.'$#u'; - if (!isset($this->routes[$id_shop])) - $this->routes[$id_shop] = array(); - if (!isset($this->routes[$id_shop][$id_lang])) - $this->routes[$id_shop][$id_lang] = array(); + $this->routes[$id_shop][$id_lang][$route_id] = array( + 'rule' => $rule, + 'regexp' => $regexp, + 'controller' => $controller, + 'keywords' => $keywords, + 'params' => $params, + ); + } - $this->routes[$id_shop][$id_lang][$route_id] = array( - 'rule' => $rule, - 'regexp' => $regexp, - 'controller' => $controller, - 'keywords' => $keywords, - 'params' => $params, - ); - } + /** + * Check if a route exists + * + * @param string $route_id + * @param int $id_lang + * @param int $id_shop + * @return bool + */ + public function hasRoute($route_id, $id_lang = null, $id_shop = null) + { + if (isset(Context::getContext()->language) && $id_lang === null) { + $id_lang = (int)Context::getContext()->language->id; + } + if (isset(Context::getContext()->shop) && $id_shop === null) { + $id_shop = (int)Context::getContext()->shop->id; + } - /** - * Check if a route exists - * - * @param string $route_id - * @param int $id_lang - * @param int $id_shop - * @return bool - */ - public function hasRoute($route_id, $id_lang = null, $id_shop = null) - { - if (isset(Context::getContext()->language) && $id_lang === null) - $id_lang = (int)Context::getContext()->language->id; - if (isset(Context::getContext()->shop) && $id_shop === null) - $id_shop = (int)Context::getContext()->shop->id; + return isset($this->routes[$id_shop]) && isset($this->routes[$id_shop][$id_lang]) && isset($this->routes[$id_shop][$id_lang][$route_id]); + } - return isset($this->routes[$id_shop]) && isset($this->routes[$id_shop][$id_lang]) && isset($this->routes[$id_shop][$id_lang][$route_id]); - } + /** + * Check if a keyword is written in a route rule + * + * @param string $route_id + * @param int $id_lang + * @param string $keyword + * @param int $id_shop + * @return bool + */ + public function hasKeyword($route_id, $id_lang, $keyword, $id_shop = null) + { + if ($id_shop === null) { + $id_shop = (int)Context::getContext()->shop->id; + } - /** - * Check if a keyword is written in a route rule - * - * @param string $route_id - * @param int $id_lang - * @param string $keyword - * @param int $id_shop - * @return bool - */ - public function hasKeyword($route_id, $id_lang, $keyword, $id_shop = null) - { - if ($id_shop === null) - $id_shop = (int)Context::getContext()->shop->id; + if (!isset($this->routes[$id_shop])) { + $this->loadRoutes($id_shop); + } - if (!isset($this->routes[$id_shop])) - $this->loadRoutes($id_shop); + if (!isset($this->routes[$id_shop]) || !isset($this->routes[$id_shop][$id_lang]) || !isset($this->routes[$id_shop][$id_lang][$route_id])) { + return false; + } - if (!isset($this->routes[$id_shop]) || !isset($this->routes[$id_shop][$id_lang]) || !isset($this->routes[$id_shop][$id_lang][$route_id])) - return false; + return preg_match('#\{([^{}]*:)?'.preg_quote($keyword, '#').'(:[^{}]*)?\}#', $this->routes[$id_shop][$id_lang][$route_id]['rule']); + } - return preg_match('#\{([^{}]*:)?'.preg_quote($keyword, '#').'(:[^{}]*)?\}#', $this->routes[$id_shop][$id_lang][$route_id]['rule']); - } + /** + * Check if a route rule contain all required keywords of default route definition + * + * @param string $route_id + * @param string $rule Rule to verify + * @param array $errors List of missing keywords + */ + public function validateRoute($route_id, $rule, &$errors = array()) + { + $errors = array(); + if (!isset($this->default_routes[$route_id])) { + return false; + } - /** - * Check if a route rule contain all required keywords of default route definition - * - * @param string $route_id - * @param string $rule Rule to verify - * @param array $errors List of missing keywords - */ - public function validateRoute($route_id, $rule, &$errors = array()) - { - $errors = array(); - if (!isset($this->default_routes[$route_id])) - return false; + foreach ($this->default_routes[$route_id]['keywords'] as $keyword => $data) { + if (isset($data['param']) && !preg_match('#\{([^{}]*:)?'.$keyword.'(:[^{}]*)?\}#', $rule)) { + $errors[] = $keyword; + } + } - foreach ($this->default_routes[$route_id]['keywords'] as $keyword => $data) - if (isset($data['param']) && !preg_match('#\{([^{}]*:)?'.$keyword.'(:[^{}]*)?\}#', $rule)) - $errors[] = $keyword; + return (count($errors)) ? false : true; + } - return (count($errors)) ? false : true; - } + /** + * Create an url from + * + * @param string $route_id Name the route + * @param int $id_lang + * @param array $params + * @param bool $use_routes If false, don't use to create this url + * @param string $anchor Optional anchor to add at the end of this url + */ + public function createUrl($route_id, $id_lang = null, array $params = array(), $force_routes = false, $anchor = '', $id_shop = null) + { + if ($id_lang === null) { + $id_lang = (int)Context::getContext()->language->id; + } + if ($id_shop === null) { + $id_shop = (int)Context::getContext()->shop->id; + } - /** - * Create an url from - * - * @param string $route_id Name the route - * @param int $id_lang - * @param array $params - * @param bool $use_routes If false, don't use to create this url - * @param string $anchor Optional anchor to add at the end of this url - */ - public function createUrl($route_id, $id_lang = null, array $params = array(), $force_routes = false, $anchor = '', $id_shop = null) - { - if ($id_lang === null) - $id_lang = (int)Context::getContext()->language->id; - if ($id_shop === null) - $id_shop = (int)Context::getContext()->shop->id; + if (!isset($this->routes[$id_shop])) { + $this->loadRoutes($id_shop); + } - if (!isset($this->routes[$id_shop])) - $this->loadRoutes($id_shop); + if (!isset($this->routes[$id_shop][$id_lang][$route_id])) { + $query = http_build_query($params, '', '&'); + $index_link = $this->use_routes ? '' : 'index.php'; + return ($route_id == 'index') ? $index_link.(($query) ? '?'.$query : '') : ((trim($route_id) == '') ? '' : 'index.php?controller='.$route_id).(($query) ? '&'.$query : '').$anchor; + } + $route = $this->routes[$id_shop][$id_lang][$route_id]; + // Check required fields + $query_params = isset($route['params']) ? $route['params'] : array(); + foreach ($route['keywords'] as $key => $data) { + if (!$data['required']) { + continue; + } - if (!isset($this->routes[$id_shop][$id_lang][$route_id])) - { - $query = http_build_query($params, '', '&'); - $index_link = $this->use_routes ? '' : 'index.php'; - return ($route_id == 'index') ? $index_link.(($query) ? '?'.$query : '') : ((trim($route_id) == '') ? '' : 'index.php?controller='.$route_id).(($query) ? '&'.$query : '').$anchor; - } - $route = $this->routes[$id_shop][$id_lang][$route_id]; - // Check required fields - $query_params = isset($route['params']) ? $route['params'] : array(); - foreach ($route['keywords'] as $key => $data) - { - if (!$data['required']) - continue; + if (!array_key_exists($key, $params)) { + throw new PrestaShopException('Dispatcher::createUrl() miss required parameter "'.$key.'" for route "'.$route_id.'"'); + } + if (isset($this->default_routes[$route_id])) { + $query_params[$this->default_routes[$route_id]['keywords'][$key]['param']] = $params[$key]; + } + } - if (!array_key_exists($key, $params)) - throw new PrestaShopException('Dispatcher::createUrl() miss required parameter "'.$key.'" for route "'.$route_id.'"'); - if (isset($this->default_routes[$route_id])) - $query_params[$this->default_routes[$route_id]['keywords'][$key]['param']] = $params[$key]; - } + // Build an url which match a route + if ($this->use_routes || $force_routes) { + $url = $route['rule']; + $add_param = array(); - // Build an url which match a route - if ($this->use_routes || $force_routes) - { + foreach ($params as $key => $value) { + if (!isset($route['keywords'][$key])) { + if (!isset($this->default_routes[$route_id]['keywords'][$key])) { + $add_param[$key] = $value; + } + } else { + if ($params[$key]) { + $replace = $route['keywords'][$key]['prepend'].$params[$key].$route['keywords'][$key]['append']; + } else { + $replace = ''; + } + $url = preg_replace('#\{([^{}]*:)?'.$key.'(:[^{}]*)?\}#', $replace, $url); + } + } + $url = preg_replace('#\{([^{}]*:)?[a-z0-9_]+?(:[^{}]*)?\}#', '', $url); + if (count($add_param)) { + $url .= '?'.http_build_query($add_param, '', '&'); + } + } + // Build a classic url index.php?controller=foo&... + else { + $add_params = array(); + foreach ($params as $key => $value) { + if (!isset($route['keywords'][$key]) && !isset($this->default_routes[$route_id]['keywords'][$key])) { + $add_params[$key] = $value; + } + } - $url = $route['rule']; - $add_param = array(); + if (!empty($route['controller'])) { + $query_params['controller'] = $route['controller']; + } + $query = http_build_query(array_merge($add_params, $query_params), '', '&'); + if ($this->multilang_activated) { + $query .= (!empty($query) ? '&' : '').'id_lang='.(int)$id_lang; + } + $url = 'index.php?'.$query; + } - foreach ($params as $key => $value) - { - if (!isset($route['keywords'][$key])) - { - if (!isset($this->default_routes[$route_id]['keywords'][$key])) - $add_param[$key] = $value; - } - else - { - if ($params[$key]) - $replace = $route['keywords'][$key]['prepend'].$params[$key].$route['keywords'][$key]['append']; - else - $replace = ''; - $url = preg_replace('#\{([^{}]*:)?'.$key.'(:[^{}]*)?\}#', $replace, $url); - } - } - $url = preg_replace('#\{([^{}]*:)?[a-z0-9_]+?(:[^{}]*)?\}#', '', $url); - if (count($add_param)) - $url .= '?'.http_build_query($add_param, '', '&'); - } - // Build a classic url index.php?controller=foo&... - else - { - $add_params = array(); - foreach ($params as $key => $value) - if (!isset($route['keywords'][$key]) && !isset($this->default_routes[$route_id]['keywords'][$key])) - $add_params[$key] = $value; + return $url.$anchor; + } - if (!empty($route['controller'])) - $query_params['controller'] = $route['controller']; - $query = http_build_query(array_merge($add_params, $query_params), '', '&'); - if ($this->multilang_activated) - $query .= (!empty($query) ? '&' : '').'id_lang='.(int)$id_lang; - $url = 'index.php?'.$query; + /** + * Retrieve the controller from url or request uri if routes are activated + * + * @return string + */ + public function getController($id_shop = null) + { + if (defined('_PS_ADMIN_DIR_')) { + $_GET['controllerUri'] = Tools::getvalue('controller'); + } + if ($this->controller) { + $_GET['controller'] = $this->controller; + return $this->controller; + } - } + if (isset(Context::getContext()->shop) && $id_shop === null) { + $id_shop = (int)Context::getContext()->shop->id; + } - return $url.$anchor; - } + $controller = Tools::getValue('controller'); - /** - * Retrieve the controller from url or request uri if routes are activated - * - * @return string - */ - public function getController($id_shop = null) - { - if (defined('_PS_ADMIN_DIR_')) - $_GET['controllerUri'] = Tools::getvalue('controller'); - if ($this->controller) - { - $_GET['controller'] = $this->controller; - return $this->controller; - } + if (isset($controller) && is_string($controller) && preg_match('/^([0-9a-z_-]+)\?(.*)=(.*)$/Ui', $controller, $m)) { + $controller = $m[1]; + if (isset($_GET['controller'])) { + $_GET[$m[2]] = $m[3]; + } elseif (isset($_POST['controller'])) { + $_POST[$m[2]] = $m[3]; + } + } - if (isset(Context::getContext()->shop) && $id_shop === null) - $id_shop = (int)Context::getContext()->shop->id; + if (!Validate::isControllerName($controller)) { + $controller = false; + } - $controller = Tools::getValue('controller'); + // Use routes ? (for url rewriting) + if ($this->use_routes && !$controller && !defined('_PS_ADMIN_DIR_')) { + if (!$this->request_uri) { + return strtolower($this->controller_not_found); + } + $controller = $this->controller_not_found; + $test_request_uri = preg_replace('/(=http:\/\/)/', '=', $this->request_uri); - if (isset($controller) && is_string($controller) && preg_match('/^([0-9a-z_-]+)\?(.*)=(.*)$/Ui', $controller, $m)) - { - $controller = $m[1]; - if (isset($_GET['controller'])) - $_GET[$m[2]] = $m[3]; - elseif (isset($_POST['controller'])) - $_POST[$m[2]] = $m[3]; - } + // If the request_uri matches a static file, then there is no need to check the routes, we keep "controller_not_found" (a static file should not go through the dispatcher) + if (!preg_match('/\.(gif|jpe?g|png|css|js|ico)$/i', parse_url($test_request_uri, PHP_URL_PATH))) { + // Add empty route as last route to prevent this greedy regexp to match request uri before right time + if ($this->empty_route) { + $this->addRoute($this->empty_route['routeID'], $this->empty_route['rule'], $this->empty_route['controller'], Context::getContext()->language->id, array(), array(), $id_shop); + } - if (!Validate::isControllerName($controller)) - $controller = false; + list($uri) = explode('?', $this->request_uri); - // Use routes ? (for url rewriting) - if ($this->use_routes && !$controller && !defined('_PS_ADMIN_DIR_')) - { - if (!$this->request_uri) - return strtolower($this->controller_not_found); - $controller = $this->controller_not_found; - $test_request_uri = preg_replace('/(=http:\/\/)/', '=', $this->request_uri); + if (isset($this->routes[$id_shop][Context::getContext()->language->id])) { + foreach ($this->routes[$id_shop][Context::getContext()->language->id] as $route) { + if (preg_match($route['regexp'], $uri, $m)) { + // Route found ! Now fill $_GET with parameters of uri + foreach ($m as $k => $v) { + if (!is_numeric($k)) { + $_GET[$k] = $v; + } + } - // If the request_uri matches a static file, then there is no need to check the routes, we keep "controller_not_found" (a static file should not go through the dispatcher) - if (!preg_match('/\.(gif|jpe?g|png|css|js|ico)$/i', parse_url($test_request_uri, PHP_URL_PATH))) - { - // Add empty route as last route to prevent this greedy regexp to match request uri before right time - if ($this->empty_route) - $this->addRoute($this->empty_route['routeID'], $this->empty_route['rule'], $this->empty_route['controller'], Context::getContext()->language->id, array(), array(), $id_shop); + $controller = $route['controller'] ? $route['controller'] : $_GET['controller']; + if (!empty($route['params'])) { + foreach ($route['params'] as $k => $v) { + $_GET[$k] = $v; + } + } - list($uri) = explode('?', $this->request_uri); + // A patch for module friendly urls + if (preg_match('#module-([a-z0-9_-]+)-([a-z0-9_]+)$#i', $controller, $m)) { + $_GET['module'] = $m[1]; + $_GET['fc'] = 'module'; + $controller = $m[2]; + } - if (isset($this->routes[$id_shop][Context::getContext()->language->id])) - foreach ($this->routes[$id_shop][Context::getContext()->language->id] as $route) - if (preg_match($route['regexp'], $uri, $m)) - { - // Route found ! Now fill $_GET with parameters of uri - foreach ($m as $k => $v) - if (!is_numeric($k)) - $_GET[$k] = $v; + if (isset($_GET['fc']) && $_GET['fc'] == 'module') { + $this->front_controller = self::FC_MODULE; + } + break; + } + } + } + } - $controller = $route['controller'] ? $route['controller'] : $_GET['controller']; - if (!empty($route['params'])) - foreach ($route['params'] as $k => $v) - $_GET[$k] = $v; + if ($controller == 'index' || preg_match('/^\/index.php(?:\?.*)?$/', $this->request_uri)) { + $controller = $this->useDefaultController(); + } + } - // A patch for module friendly urls - if (preg_match('#module-([a-z0-9_-]+)-([a-z0-9_]+)$#i', $controller, $m)) - { - $_GET['module'] = $m[1]; - $_GET['fc'] = 'module'; - $controller = $m[2]; - } + $this->controller = str_replace('-', '', $controller); + $_GET['controller'] = $this->controller; + return $this->controller; + } - if (isset($_GET['fc']) && $_GET['fc'] == 'module') - $this->front_controller = self::FC_MODULE; - break; - } - } + /** + * Get list of all available FO controllers + * + * @var mixed $dirs + * @return array + */ + public static function getControllers($dirs) + { + if (!is_array($dirs)) { + $dirs = array($dirs); + } - if ($controller == 'index' || preg_match('/^\/index.php(?:\?.*)?$/', $this->request_uri)) - $controller = $this->useDefaultController(); - } + $controllers = array(); + foreach ($dirs as $dir) { + $controllers = array_merge($controllers, Dispatcher::getControllersInDirectory($dir)); + } + return $controllers; + } - $this->controller = str_replace('-', '', $controller); - $_GET['controller'] = $this->controller; - return $this->controller; - } + /** + * Get list of all available Module Front controllers + * + * @return array + */ + public static function getModuleControllers($type = 'all', $module = null) + { + $modules_controllers = array(); + if (is_null($module)) { + $modules = Module::getModulesOnDisk(true); + } elseif (!is_array($module)) { + $modules = array(Module::getInstanceByName($module)); + } else { + $modules = array(); + foreach ($module as $_mod) { + $modules[] = Module::getInstanceByName($_mod); + } + } - /** - * Get list of all available FO controllers - * - * @var mixed $dirs - * @return array - */ - public static function getControllers($dirs) - { - if (!is_array($dirs)) - $dirs = array($dirs); + foreach ($modules as $mod) { + foreach (Dispatcher::getControllersInDirectory(_PS_MODULE_DIR_.$mod->name.'/controllers/') as $controller) { + if ($type == 'admin') { + if (strpos($controller, 'Admin') !== false) { + $modules_controllers[$mod->name][] = $controller; + } + } elseif ($type == 'front') { + if (strpos($controller, 'Admin') === false) { + $modules_controllers[$mod->name][] = $controller; + } + } else { + $modules_controllers[$mod->name][] = $controller; + } + } + } + return $modules_controllers; + } - $controllers = array(); - foreach ($dirs as $dir) - $controllers = array_merge($controllers, Dispatcher::getControllersInDirectory($dir)); - return $controllers; - } + /** + * Get list of available controllers from the specified dir + * + * @param string $dir Directory to scan (recursively) + * @return array + */ + public static function getControllersInDirectory($dir) + { + if (!is_dir($dir)) { + return array(); + } - /** - * Get list of all available Module Front controllers - * - * @return array - */ - public static function getModuleControllers($type = 'all', $module = null) - { - $modules_controllers = array(); - if (is_null($module)) - $modules = Module::getModulesOnDisk(true); - elseif (!is_array($module)) - $modules = array(Module::getInstanceByName($module)); - else - { - $modules = array(); - foreach ($module as $_mod) - $modules[] = Module::getInstanceByName($_mod); - } + $controllers = array(); + $controller_files = scandir($dir); + foreach ($controller_files as $controller_filename) { + if ($controller_filename[0] != '.') { + if (!strpos($controller_filename, '.php') && is_dir($dir.$controller_filename)) { + $controllers += Dispatcher::getControllersInDirectory($dir.$controller_filename.DIRECTORY_SEPARATOR); + } elseif ($controller_filename != 'index.php') { + $key = str_replace(array('controller.php', '.php'), '', strtolower($controller_filename)); + $controllers[$key] = basename($controller_filename, '.php'); + } + } + } - foreach ($modules as $mod) - { - foreach (Dispatcher::getControllersInDirectory(_PS_MODULE_DIR_.$mod->name.'/controllers/') as $controller) - { - if ($type == 'admin') - { - if (strpos($controller, 'Admin') !== false) - $modules_controllers[$mod->name][] = $controller; - } - elseif ($type == 'front') - { - if (strpos($controller, 'Admin') === false) - $modules_controllers[$mod->name][] = $controller; - } - else - $modules_controllers[$mod->name][] = $controller; - } - } - return $modules_controllers; - } - - /** - * Get list of available controllers from the specified dir - * - * @param string $dir Directory to scan (recursively) - * @return array - */ - public static function getControllersInDirectory($dir) - { - if (!is_dir($dir)) - return array(); - - $controllers = array(); - $controller_files = scandir($dir); - foreach ($controller_files as $controller_filename) - { - if ($controller_filename[0] != '.') - { - if (!strpos($controller_filename, '.php') && is_dir($dir.$controller_filename)) - $controllers += Dispatcher::getControllersInDirectory($dir.$controller_filename.DIRECTORY_SEPARATOR); - elseif ($controller_filename != 'index.php') - { - $key = str_replace(array('controller.php', '.php'), '', strtolower($controller_filename)); - $controllers[$key] = basename($controller_filename, '.php'); - } - } - } - - return $controllers; - } + return $controllers; + } } diff --git a/classes/Employee.php b/classes/Employee.php index 58ed4551..dadb9e60 100644 --- a/classes/Employee.php +++ b/classes/Employee.php @@ -26,443 +26,471 @@ class EmployeeCore extends ObjectModel { - public $id; + public $id; - /** @var string Determine employee profile */ - public $id_profile; + /** @var string Determine employee profile */ + public $id_profile; - /** @var string employee language */ - public $id_lang; + /** @var string employee language */ + public $id_lang; - /** @var string Lastname */ - public $lastname; + /** @var string Lastname */ + public $lastname; - /** @var string Firstname */ - public $firstname; + /** @var string Firstname */ + public $firstname; - /** @var string e-mail */ - public $email; + /** @var string e-mail */ + public $email; - /** @var string Password */ - public $passwd; + /** @var string Password */ + public $passwd; - /** @var datetime Password */ - public $last_passwd_gen; + /** @var datetime Password */ + public $last_passwd_gen; - public $stats_date_from; - public $stats_date_to; + public $stats_date_from; + public $stats_date_to; - public $stats_compare_from; - public $stats_compare_to; - public $stats_compare_option = 1; + public $stats_compare_from; + public $stats_compare_to; + public $stats_compare_option = 1; - public $preselect_date_range; + public $preselect_date_range; - /** @var string Display back office background in the specified color */ - public $bo_color; + /** @var string Display back office background in the specified color */ + public $bo_color; - public $default_tab; + public $default_tab; - /** @var string employee's chosen theme */ - public $bo_theme; + /** @var string employee's chosen theme */ + public $bo_theme; - /** @var string employee's chosen css file */ - public $bo_css = 'admin-theme.css'; + /** @var string employee's chosen css file */ + public $bo_css = 'admin-theme.css'; - /** @var int employee desired screen width */ - public $bo_width; + /** @var int employee desired screen width */ + public $bo_width; - /** @var bool, false */ - public $bo_menu = 1; + /** @var bool, false */ + public $bo_menu = 1; - /* Deprecated */ - public $bo_show_screencast = false; + /* Deprecated */ + public $bo_show_screencast = false; - /** @var bool Status */ - public $active = 1; + /** @var bool Status */ + public $active = 1; - /** @var bool Optin status */ - public $optin = 1; + /** @var bool Optin status */ + public $optin = 1; - public $remote_addr; + public $remote_addr; - /* employee notifications */ - public $id_last_order; - public $id_last_customer_message; - public $id_last_customer; + /* employee notifications */ + public $id_last_order; + public $id_last_customer_message; + public $id_last_customer; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'employee', - 'primary' => 'id_employee', - 'fields' => array( - 'lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName', 'required' => true, 'size' => 32), - 'firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName', 'required' => true, 'size' => 32), - 'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'required' => true, 'size' => 128), - 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), - 'passwd' => array('type' => self::TYPE_STRING, 'validate' => 'isPasswdAdmin', 'required' => true, 'size' => 32), - 'last_passwd_gen' => array('type' => self::TYPE_STRING), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'optin' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'id_profile' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), - 'bo_color' => array('type' => self::TYPE_STRING, 'validate' => 'isColor', 'size' => 32), - 'default_tab' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'bo_theme' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 32), - 'bo_css' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 64), - 'bo_width' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'bo_menu' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'stats_date_from' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'stats_date_to' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'stats_compare_from' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'stats_compare_to' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'stats_compare_option' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'preselect_date_range' => array('type' => self::TYPE_STRING, 'size' => 32), - 'id_last_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'id_last_customer_message' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'id_last_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'employee', + 'primary' => 'id_employee', + 'fields' => array( + 'lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName', 'required' => true, 'size' => 32), + 'firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName', 'required' => true, 'size' => 32), + 'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'required' => true, 'size' => 128), + 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), + 'passwd' => array('type' => self::TYPE_STRING, 'validate' => 'isPasswdAdmin', 'required' => true, 'size' => 32), + 'last_passwd_gen' => array('type' => self::TYPE_STRING), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'optin' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'id_profile' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), + 'bo_color' => array('type' => self::TYPE_STRING, 'validate' => 'isColor', 'size' => 32), + 'default_tab' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'bo_theme' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 32), + 'bo_css' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 64), + 'bo_width' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'bo_menu' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'stats_date_from' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'stats_date_to' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'stats_compare_from' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'stats_compare_to' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'stats_compare_option' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'preselect_date_range' => array('type' => self::TYPE_STRING, 'size' => 32), + 'id_last_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'id_last_customer_message' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'id_last_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_lang' => array('xlink_resource' => 'languages'), - 'last_passwd_gen' => array('setter' => null), - 'stats_date_from' => array('setter' => null), - 'stats_date_to' => array('setter' => null), - 'stats_compare_from' => array('setter' => null), - 'stats_compare_to' => array('setter' => null), - 'passwd' => array('setter' => 'setWsPasswd'), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_lang' => array('xlink_resource' => 'languages'), + 'last_passwd_gen' => array('setter' => null), + 'stats_date_from' => array('setter' => null), + 'stats_date_to' => array('setter' => null), + 'stats_compare_from' => array('setter' => null), + 'stats_compare_to' => array('setter' => null), + 'passwd' => array('setter' => 'setWsPasswd'), + ), + ); - protected $associated_shops = array(); + protected $associated_shops = array(); - public function __construct($id = null, $id_lang = null, $id_shop = null) - { - parent::__construct($id, null, $id_shop); + public function __construct($id = null, $id_lang = null, $id_shop = null) + { + parent::__construct($id, null, $id_shop); - if (!is_null($id_lang)) - $this->id_lang = (int)(Language::getLanguage($id_lang) !== false) ? $id_lang : Configuration::get('PS_LANG_DEFAULT'); + if (!is_null($id_lang)) { + $this->id_lang = (int)(Language::getLanguage($id_lang) !== false) ? $id_lang : Configuration::get('PS_LANG_DEFAULT'); + } - if ($this->id) - $this->associated_shops = $this->getAssociatedShops(); + if ($this->id) { + $this->associated_shops = $this->getAssociatedShops(); + } - $this->image_dir = _PS_EMPLOYEE_IMG_DIR_; - } + $this->image_dir = _PS_EMPLOYEE_IMG_DIR_; + } - /** - * @see ObjectModel::getFields() - * @return array - */ - public function getFields() - { - if (empty($this->stats_date_from) || $this->stats_date_from == '0000-00-00') - $this->stats_date_from = date('Y-m-d', strtotime('-1 month')); + /** + * @see ObjectModel::getFields() + * @return array + */ + public function getFields() + { + if (empty($this->stats_date_from) || $this->stats_date_from == '0000-00-00') { + $this->stats_date_from = date('Y-m-d', strtotime('-1 month')); + } - if (empty($this->stats_compare_from) || $this->stats_compare_from == '0000-00-00') - $this->stats_compare_from = null; + if (empty($this->stats_compare_from) || $this->stats_compare_from == '0000-00-00') { + $this->stats_compare_from = null; + } - if (empty($this->stats_date_to) || $this->stats_date_to == '0000-00-00') - $this->stats_date_to = date('Y-m-d'); + if (empty($this->stats_date_to) || $this->stats_date_to == '0000-00-00') { + $this->stats_date_to = date('Y-m-d'); + } - if (empty($this->stats_compare_to) || $this->stats_compare_to == '0000-00-00') - $this->stats_compare_to = null; + if (empty($this->stats_compare_to) || $this->stats_compare_to == '0000-00-00') { + $this->stats_compare_to = null; + } - return parent::getFields(); - } + return parent::getFields(); + } - public function add($autodate = true, $null_values = true) - { - $this->last_passwd_gen = date('Y-m-d H:i:s', strtotime('-'.Configuration::get('PS_PASSWD_TIME_BACK').'minutes')); - $this->saveOptin(); - $this->updateTextDirection(); - return parent::add($autodate, $null_values); - } + public function add($autodate = true, $null_values = true) + { + $this->last_passwd_gen = date('Y-m-d H:i:s', strtotime('-'.Configuration::get('PS_PASSWD_TIME_BACK').'minutes')); + $this->saveOptin(); + $this->updateTextDirection(); + return parent::add($autodate, $null_values); + } - public function update($null_values = false) - { - if (empty($this->stats_date_from) || $this->stats_date_from == '0000-00-00') - $this->stats_date_from = date('Y-m-d'); - if (empty($this->stats_date_to) || $this->stats_date_to == '0000-00-00') - $this->stats_date_to = date('Y-m-d'); - $this->saveOptin(); - $this->updateTextDirection(); - return parent::update($null_values); - } + public function update($null_values = false) + { + if (empty($this->stats_date_from) || $this->stats_date_from == '0000-00-00') { + $this->stats_date_from = date('Y-m-d'); + } - protected function updateTextDirection() - { - if (!defined('_PS_ADMIN_DIR_')) - return; - $path = _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes'.DIRECTORY_SEPARATOR.$this->bo_theme.DIRECTORY_SEPARATOR.'css'.DIRECTORY_SEPARATOR; - $language = new Language($this->id_lang); - if ($language->is_rtl && !strpos($this->bo_css, '_rtl')) - { - $bo_css = preg_replace('/^(.*)\.css$/', '$1_rtl.css', $this->bo_css); - if (file_exists($path.$bo_css)) - $this->bo_css = $bo_css; - } - elseif (!$language->is_rtl && strpos($this->bo_css, '_rtl')) - { - $bo_css = preg_replace('/^(.*)_rtl\.css$/', '$1.css', $this->bo_css); - if (file_exists($path.$bo_css)) - $this->bo_css = $bo_css; - } - } + if (empty($this->stats_date_to) || $this->stats_date_to == '0000-00-00') { + $this->stats_date_to = date('Y-m-d'); + } - protected function saveOptin() - { - if ($this->optin && !defined('PS_INSTALLATION_IN_PROGRESS')) - { - $language = new Language($this->id_lang); - $params = http_build_query(array( - 'email' => $this->email, - 'method' => 'addMemberToNewsletter', - 'language' => $language->iso_code, - 'visitorType' => 1, - 'source' => 'backoffice' - )); - Tools::file_get_contents('http://www.prestashop.com/ajax/controller.php?'.$params); - } - } + $currentEmployee = new Employee((int)$this->id); - /** - * Return list of employees - * - * @param bool $active_only Filter employee by active status - * @return array|false Employees or false - */ - public static function getEmployees($active_only = true) - { - return Db::getInstance()->executeS(' + if ($currentEmployee->optin != $this->optin) { + $this->saveOptin(); + } + + $this->updateTextDirection(); + return parent::update($null_values); + } + + protected function updateTextDirection() + { + if (!defined('_PS_ADMIN_DIR_')) { + return; + } + + $path = _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes'.DIRECTORY_SEPARATOR.$this->bo_theme.DIRECTORY_SEPARATOR.'css'.DIRECTORY_SEPARATOR; + $language = new Language($this->id_lang); + + if ($language->is_rtl && !strpos($this->bo_css, '_rtl')) { + $bo_css = preg_replace('/^(.*)\.css$/', '$1_rtl.css', $this->bo_css); + + if (file_exists($path.$bo_css)) { + $this->bo_css = $bo_css; + } + } elseif (!$language->is_rtl && strpos($this->bo_css, '_rtl')) { + $bo_css = preg_replace('/^(.*)_rtl\.css$/', '$1.css', $this->bo_css); + + if (file_exists($path.$bo_css)) { + $this->bo_css = $bo_css; + } + } + } + + protected function saveOptin() + { + if ($this->optin && !defined('PS_INSTALLATION_IN_PROGRESS')) { + $language = new Language($this->id_lang); + $params = http_build_query(array( + 'email' => $this->email, + 'method' => 'addMemberToNewsletter', + 'language' => $language->iso_code, + 'visitorType' => 1, + 'source' => 'backoffice' + )); + Tools::file_get_contents('http://www.prestashop.com/ajax/controller.php?'.$params); + } + } + + /** + * Return list of employees + * + * @param bool $active_only Filter employee by active status + * @return array|false Employees or false + */ + public static function getEmployees($active_only = true) + { + return Db::getInstance()->executeS(' SELECT `id_employee`, `firstname`, `lastname` FROM `'._DB_PREFIX_.'employee` '.($active_only ? ' WHERE `active` = 1' : '').' ORDER BY `lastname` ASC '); - } + } - /** - * Return employee instance from its e-mail (optionnaly check password) - * - * @param string $email e-mail - * @param string $passwd Password is also checked if specified - * @param bool $active_only Filter employee by active status - * @return Employee instance - */ - public function getByEmail($email, $passwd = null, $active_only = true) - { - if (!Validate::isEmail($email) || ($passwd != null && !Validate::isPasswd($passwd))) - die(Tools::displayError()); + /** + * Return employee instance from its e-mail (optionnaly check password) + * + * @param string $email e-mail + * @param string $passwd Password is also checked if specified + * @param bool $active_only Filter employee by active status + * @return Employee instance + */ + public function getByEmail($email, $passwd = null, $active_only = true) + { + if (!Validate::isEmail($email) || ($passwd != null && !Validate::isPasswd($passwd))) { + die(Tools::displayError()); + } - $result = Db::getInstance()->getRow(' + $result = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.'employee` WHERE `email` = \''.pSQL($email).'\' - '.($active_only ? ' AND active = 1' : '') - .($passwd !== null ? ' AND `passwd` = \''.Tools::encrypt($passwd).'\'' : '')); - if (!$result) - return false; - $this->id = $result['id_employee']; - $this->id_profile = $result['id_profile']; - foreach ($result as $key => $value) - if (property_exists($this, $key)) - $this->{$key} = $value; - return $this; - } + '.($active_only ? ' AND `active` = 1' : '') + .($passwd !== null ? ' AND `passwd` = \''.Tools::encrypt($passwd).'\'' : '')); + if (!$result) { + return false; + } + $this->id = $result['id_employee']; + $this->id_profile = $result['id_profile']; + foreach ($result as $key => $value) { + if (property_exists($this, $key)) { + $this->{$key} = $value; + } + } + return $this; + } - public static function employeeExists($email) - { - if (!Validate::isEmail($email)) - die (Tools::displayError()); + public static function employeeExists($email) + { + if (!Validate::isEmail($email)) { + die(Tools::displayError()); + } - return (bool)Db::getInstance()->getValue(' + return (bool)Db::getInstance()->getValue(' SELECT `id_employee` FROM `'._DB_PREFIX_.'employee` WHERE `email` = \''.pSQL($email).'\''); - } + } - /** - * Check if employee password is the right one - * - * @param string $passwd Password - * @return bool result - */ - public static function checkPassword($id_employee, $passwd) - { - if (!Validate::isUnsignedId($id_employee) || !Validate::isPasswd($passwd, 8)) - die (Tools::displayError()); + /** + * Check if employee password is the right one + * + * @param string $passwd Password + * @return bool result + */ + public static function checkPassword($id_employee, $passwd) + { + if (!Validate::isUnsignedId($id_employee) || !Validate::isPasswd($passwd, 8)) { + die(Tools::displayError()); + } - return Db::getInstance()->getValue(' + return Db::getInstance()->getValue(' SELECT `id_employee` FROM `'._DB_PREFIX_.'employee` WHERE `id_employee` = '.(int)$id_employee.' AND `passwd` = \''.pSQL($passwd).'\' - AND active = 1'); - } + AND `active` = 1'); + } - public static function countProfile($id_profile, $active_only = false) - { - return Db::getInstance()->getValue(' + public static function countProfile($id_profile, $active_only = false) + { + return Db::getInstance()->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'employee` WHERE `id_profile` = '.(int)$id_profile.' '.($active_only ? ' AND `active` = 1' : '')); - } + } - public function isLastAdmin() - { - return ($this->isSuperAdmin() - && Employee::countProfile($this->id_profile, true) == 1 - && $this->active - ); - } + public function isLastAdmin() + { + return ($this->isSuperAdmin() + && Employee::countProfile($this->id_profile, true) == 1 + && $this->active + ); + } - public function setWsPasswd($passwd) - { - if ($this->id != 0) - { - if ($this->passwd != $passwd) - $this->passwd = Tools::encrypt($passwd); - } - else - $this->passwd = Tools::encrypt($passwd); - return true; - } + public function setWsPasswd($passwd) + { + if ($this->id != 0) { + if ($this->passwd != $passwd) { + $this->passwd = Tools::encrypt($passwd); + } + } else { + $this->passwd = Tools::encrypt($passwd); + } + return true; + } - /** - * Check employee informations saved into cookie and return employee validity - * - * @return bool employee validity - */ - public function isLoggedBack() - { - if (!Cache::isStored('isLoggedBack'.$this->id)) - { - /* Employee is valid only if it can be load and if cookie password is the same as database one */ - $result = ( - $this->id && Validate::isUnsignedId($this->id) && Employee::checkPassword($this->id, Context::getContext()->cookie->passwd) - && (!isset(Context::getContext()->cookie->remote_addr) || Context::getContext()->cookie->remote_addr == ip2long(Tools::getRemoteAddr()) || !Configuration::get('PS_COOKIE_CHECKIP')) - ); - Cache::store('isLoggedBack'.$this->id, $result); - return $result; - } - return Cache::retrieve('isLoggedBack'.$this->id); - } + /** + * Check employee informations saved into cookie and return employee validity + * + * @return bool employee validity + */ + public function isLoggedBack() + { + if (!Cache::isStored('isLoggedBack'.$this->id)) { + /* Employee is valid only if it can be load and if cookie password is the same as database one */ + $result = ( + $this->id && Validate::isUnsignedId($this->id) && Employee::checkPassword($this->id, Context::getContext()->cookie->passwd) + && (!isset(Context::getContext()->cookie->remote_addr) || Context::getContext()->cookie->remote_addr == ip2long(Tools::getRemoteAddr()) || !Configuration::get('PS_COOKIE_CHECKIP')) + ); + Cache::store('isLoggedBack'.$this->id, $result); + return $result; + } + return Cache::retrieve('isLoggedBack'.$this->id); + } - /** - * Logout - */ - public function logout() - { - if (isset(Context::getContext()->cookie)) - { - Context::getContext()->cookie->logout(); - Context::getContext()->cookie->write(); - } - $this->id = null; - } + /** + * Logout + */ + public function logout() + { + if (isset(Context::getContext()->cookie)) { + Context::getContext()->cookie->logout(); + Context::getContext()->cookie->write(); + } + $this->id = null; + } - public function favoriteModulesList() - { - return Db::getInstance()->executeS(' - SELECT module + public function favoriteModulesList() + { + return Db::getInstance()->executeS(' + SELECT `module` FROM `'._DB_PREFIX_.'module_preference` WHERE `id_employee` = '.(int)$this->id.' AND `favorite` = 1 AND (`interest` = 1 OR `interest` IS NULL)' - ); - } + ); + } - /** - * Check if the employee is associated to a specific shop - * - * @since 1.5.0 - * @param int $id_shop - * @return bool - */ - public function hasAuthOnShop($id_shop) - { - return $this->isSuperAdmin() || in_array($id_shop, $this->associated_shops); - } + /** + * Check if the employee is associated to a specific shop + * + * @since 1.5.0 + * @param int $id_shop + * @return bool + */ + public function hasAuthOnShop($id_shop) + { + return $this->isSuperAdmin() || in_array($id_shop, $this->associated_shops); + } - /** - * Check if the employee is associated to a specific shop group - * - * @since 1.5.0 - * @param int $id_shop_shop - * @return bool - */ - public function hasAuthOnShopGroup($id_shop_group) - { - if ($this->isSuperAdmin()) - return true; + /** + * Check if the employee is associated to a specific shop group + * + * @since 1.5.0 + * @param int $id_shop_shop + * @return bool + */ + public function hasAuthOnShopGroup($id_shop_group) + { + if ($this->isSuperAdmin()) { + return true; + } - foreach ($this->associated_shops as $id_shop) - if ($id_shop_group == Shop::getGroupFromShop($id_shop, true)) - return true; - return false; - } + foreach ($this->associated_shops as $id_shop) { + if ($id_shop_group == Shop::getGroupFromShop($id_shop, true)) { + return true; + } + } + return false; + } - /** - * Get default id_shop with auth for current employee - * - * @since 1.5.0 - * @return int - */ - public function getDefaultShopID() - { - if ($this->isSuperAdmin() || in_array(Configuration::get('PS_SHOP_DEFAULT'), $this->associated_shops)) - return Configuration::get('PS_SHOP_DEFAULT'); - return $this->associated_shops[0]; - } + /** + * Get default id_shop with auth for current employee + * + * @since 1.5.0 + * @return int + */ + public function getDefaultShopID() + { + if ($this->isSuperAdmin() || in_array(Configuration::get('PS_SHOP_DEFAULT'), $this->associated_shops)) { + return Configuration::get('PS_SHOP_DEFAULT'); + } + return $this->associated_shops[0]; + } - public static function getEmployeesByProfile($id_profile, $active_only = false) - { - return Db::getInstance()->executeS(' + public static function getEmployeesByProfile($id_profile, $active_only = false) + { + return Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'employee` WHERE `id_profile` = '.(int)$id_profile.' '.($active_only ? ' AND `active` = 1' : '')); - } + } - /** - * Check if current employee is super administrator - * - * @return bool - */ - public function isSuperAdmin() - { - return $this->id_profile == _PS_ADMIN_PROFILE_; - } + /** + * Check if current employee is super administrator + * + * @return bool + */ + public function isSuperAdmin() + { + return $this->id_profile == _PS_ADMIN_PROFILE_; + } - public function getImage() - { - if (!Validate::isLoadedObject($this)) - return Tools::getAdminImageUrl('prestashop-avatar.png'); - return Tools::getShopProtocol().'profile.prestashop.com/'.urlencode($this->email).'.jpg'; - } + public function getImage() + { + if (!Validate::isLoadedObject($this)) { + return Tools::getAdminImageUrl('prestashop-avatar.png'); + } + return Tools::getShopProtocol().'profile.prestashop.com/'.urlencode($this->email).'.jpg'; + } - public function getLastElementsForNotify($element) - { - $element = bqSQL($element); - $max = Db::getInstance()->getValue(' + public function getLastElementsForNotify($element) + { + $element = bqSQL($element); + $max = Db::getInstance()->getValue(' SELECT MAX(`id_'.$element.'`) as `id_'.$element.'` FROM `'._DB_PREFIX_.$element.($element == 'order' ? 's': '').'`'); - // if no rows in table, set max to 0 - if ((int)$max < 1) - $max = 0; + // if no rows in table, set max to 0 + if ((int)$max < 1) { + $max = 0; + } - return (int)$max; - } + return (int)$max; + } - public static function setLastConnectionDate($id_employee) - { - return Db::getInstance()->execute(' + public static function setLastConnectionDate($id_employee) + { + return Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'employee` SET `last_connection_date` = CURRENT_DATE() WHERE `id_employee` = '.(int)$id_employee.' AND `last_connection_date`< CURRENT_DATE() '); - } + } } diff --git a/classes/Feature.php b/classes/Feature.php index 3f8af275..c67c0971 100644 --- a/classes/Feature.php +++ b/classes/Feature.php @@ -26,98 +26,99 @@ class FeatureCore extends ObjectModel { - /** @var string Name */ - public $name; - public $position; + /** @var string Name */ + public $name; + public $position; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'feature', - 'primary' => 'id_feature', - 'multilang' => true, - 'fields' => array( - 'position' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'feature', + 'primary' => 'id_feature', + 'multilang' => true, + 'fields' => array( + 'position' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), - ), - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), + ), + ); - protected $webserviceParameters = array( - 'objectsNodeName' => 'product_features', - 'objectNodeName' => 'product_feature', - 'fields' => array(), - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'product_features', + 'objectNodeName' => 'product_feature', + 'fields' => array(), + ); - /** - * Get a feature data for a given id_feature and id_lang - * - * @param int $id_lang Language id - * @param int $id_feature Feature id - * @return array Array with feature's data - */ - public static function getFeature($id_lang, $id_feature) - { - return Db::getInstance()->getRow(' + /** + * Get a feature data for a given id_feature and id_lang + * + * @param int $id_lang Language id + * @param int $id_feature Feature id + * @return array Array with feature's data + */ + public static function getFeature($id_lang, $id_feature) + { + return Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.'feature` f LEFT JOIN `'._DB_PREFIX_.'feature_lang` fl ON ( f.`id_feature` = fl.`id_feature` AND fl.`id_lang` = '.(int)$id_lang.') WHERE f.`id_feature` = '.(int)$id_feature - ); - } + ); + } - /** - * Get all features for a given language - * - * @param int $id_lang Language id - * @return array Multiple arrays with feature's data - */ - public static function getFeatures($id_lang, $with_shop = true) - { - return Db::getInstance()->executeS(' + /** + * Get all features for a given language + * + * @param int $id_lang Language id + * @return array Multiple arrays with feature's data + */ + public static function getFeatures($id_lang, $with_shop = true) + { + return Db::getInstance()->executeS(' SELECT DISTINCT f.id_feature, f.*, fl.* FROM `'._DB_PREFIX_.'feature` f '.($with_shop ? Shop::addSqlAssociation('feature', 'f') : '').' LEFT JOIN `'._DB_PREFIX_.'feature_lang` fl ON (f.`id_feature` = fl.`id_feature` AND fl.`id_lang` = '.(int)$id_lang.') ORDER BY f.`position` ASC'); - } + } - /** - * Delete several objects from database - * - * @param array $selection Array with items to delete - * @return bool Deletion result - */ - public function deleteSelection($selection) - { - /* Also delete Attributes */ - foreach ($selection as $value) - { - $obj = new Feature($value); - if (!$obj->delete()) - return false; - } - return true; - } + /** + * Delete several objects from database + * + * @param array $selection Array with items to delete + * @return bool Deletion result + */ + public function deleteSelection($selection) + { + /* Also delete Attributes */ + foreach ($selection as $value) { + $obj = new Feature($value); + if (!$obj->delete()) { + return false; + } + } + return true; + } - public function add($autodate = true, $nullValues = false) - { - if ($this->position <= 0) - $this->position = Feature::getHigherPosition() + 1; + public function add($autodate = true, $nullValues = false) + { + if ($this->position <= 0) { + $this->position = Feature::getHigherPosition() + 1; + } - $return = parent::add($autodate, true); - Hook::exec('actionFeatureSave', array('id_feature' => $this->id)); - return $return; - } + $return = parent::add($autodate, true); + Hook::exec('actionFeatureSave', array('id_feature' => $this->id)); + return $return; + } - public function delete() - { - /* Also delete related attributes */ - Db::getInstance()->execute(' + public function delete() + { + /* Also delete related attributes */ + Db::getInstance()->execute(' DELETE `'._DB_PREFIX_.'feature_value_lang` FROM @@ -127,124 +128,127 @@ class FeatureCore extends ObjectModel WHERE `'._DB_PREFIX_.'feature_value`.`id_feature` = '.(int)$this->id.' '); - Db::getInstance()->execute(' + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'feature_value` WHERE `id_feature` = '.(int)$this->id - ); - /* Also delete related products */ - Db::getInstance()->execute(' + ); + /* Also delete related products */ + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'feature_product` WHERE `id_feature` = '.(int)$this->id - ); + ); - $return = parent::delete(); - if ($return) - Hook::exec('actionFeatureDelete', array('id_feature' => $this->id)); + $return = parent::delete(); + if ($return) { + Hook::exec('actionFeatureDelete', array('id_feature' => $this->id)); + } - /* Reinitializing position */ - $this->cleanPositions(); + /* Reinitializing position */ + $this->cleanPositions(); - return $return; - } + return $return; + } - public function update($nullValues = false) - { - $this->clearCache(); + public function update($nullValues = false) + { + $this->clearCache(); - $result = 1; - $fields = $this->getFieldsLang(); - foreach ($fields as $field) - { - foreach (array_keys($field) as $key) - if (!Validate::isTableOrIdentifier($key)) - die(Tools::displayError()); + $result = 1; + $fields = $this->getFieldsLang(); + foreach ($fields as $field) { + foreach (array_keys($field) as $key) { + if (!Validate::isTableOrIdentifier($key)) { + die(Tools::displayError()); + } + } - $sql = 'SELECT `id_lang` FROM `'.pSQL(_DB_PREFIX_.$this->def['table']).'_lang` + $sql = 'SELECT `id_lang` FROM `'.pSQL(_DB_PREFIX_.$this->def['table']).'_lang` WHERE `'.$this->def['primary'].'` = '.(int)$this->id.' AND `id_lang` = '.(int)$field['id_lang']; - $mode = Db::getInstance()->getRow($sql); - $result &= (!$mode) ? Db::getInstance()->insert($this->def['table'].'_lang', $field) : - Db::getInstance()->update( - $this->def['table'].'_lang', - $field, - '`'.$this->def['primary'].'` = '.(int)$this->id.' AND `id_lang` = '.(int)$field['id_lang'] - ); - } - Hook::exec('actionFeatureSave', array('id_feature' => $this->id)); - return $result; - } + $mode = Db::getInstance()->getRow($sql); + $result &= (!$mode) ? Db::getInstance()->insert($this->def['table'].'_lang', $field) : + Db::getInstance()->update( + $this->def['table'].'_lang', + $field, + '`'.$this->def['primary'].'` = '.(int)$this->id.' AND `id_lang` = '.(int)$field['id_lang'] + ); + } + Hook::exec('actionFeatureSave', array('id_feature' => $this->id)); + return $result; + } - /** - * Count number of features for a given language - * - * @param int $id_lang Language id - * @return int Number of feature - */ - public static function nbFeatures($id_lang) - { - return Db::getInstance()->getValue(' + /** + * Count number of features for a given language + * + * @param int $id_lang Language id + * @return int Number of feature + */ + public static function nbFeatures($id_lang) + { + return Db::getInstance()->getValue(' SELECT COUNT(*) as nb FROM `'._DB_PREFIX_.'feature` ag LEFT JOIN `'._DB_PREFIX_.'feature_lang` agl ON (ag.`id_feature` = agl.`id_feature` AND `id_lang` = '.(int)$id_lang.') '); - } + } - /** - * Create a feature from import - * - * @param int $id_feature Feature id - * @param int $id_product Product id - * @param array $value Feature Value - */ - public static function addFeatureImport($name, $position = false) - { - $rq = Db::getInstance()->getRow(' + /** + * Create a feature from import + * + * @param int $id_feature Feature id + * @param int $id_product Product id + * @param array $value Feature Value + */ + public static function addFeatureImport($name, $position = false) + { + $rq = Db::getInstance()->getRow(' SELECT `id_feature` FROM '._DB_PREFIX_.'feature_lang WHERE `name` = \''.pSQL($name).'\' GROUP BY `id_feature` '); - if (empty($rq)) - { - // Feature doesn't exist, create it - $feature = new Feature(); - $feature->name = array_fill_keys(Language::getIDs(), (string)$name); - if ($position) - $feature->position = (int)$position; - else - $feature->position = Feature::getHigherPosition() + 1; - $feature->add(); - return $feature->id; - } - elseif (isset($rq['id_feature']) && $rq['id_feature']) - { - if (is_numeric($position) && $feature = new Feature((int)$rq['id_feature'])) - { - $feature->position = (int)$position; - if (Validate::isLoadedObject($feature)) - $feature->update(); - } + if (empty($rq)) { + // Feature doesn't exist, create it + $feature = new Feature(); + $feature->name = array_fill_keys(Language::getIDs(), (string)$name); + if ($position) { + $feature->position = (int)$position; + } else { + $feature->position = Feature::getHigherPosition() + 1; + } + $feature->add(); + return $feature->id; + } elseif (isset($rq['id_feature']) && $rq['id_feature']) { + if (is_numeric($position) && $feature = new Feature((int)$rq['id_feature'])) { + $feature->position = (int)$position; + if (Validate::isLoadedObject($feature)) { + $feature->update(); + } + } - return (int)$rq['id_feature']; - } - } + return (int)$rq['id_feature']; + } + } - public static function getFeaturesForComparison($list_ids_product, $id_lang) - { - if (!Feature::isFeatureActive()) - return false; + public static function getFeaturesForComparison($list_ids_product, $id_lang) + { + if (!Feature::isFeatureActive()) { + return false; + } - $ids = ''; - foreach ($list_ids_product as $id) - $ids .= (int)$id.','; + $ids = ''; + foreach ($list_ids_product as $id) { + $ids .= (int)$id.','; + } - $ids = rtrim($ids, ','); + $ids = rtrim($ids, ','); - if (empty($ids)) - return false; + if (empty($ids)) { + return false; + } - return Db::getInstance()->executeS(' + return Db::getInstance()->executeS(' SELECT f.*, fl.* FROM `'._DB_PREFIX_.'feature` f LEFT JOIN `'._DB_PREFIX_.'feature_product` fp @@ -256,80 +260,85 @@ class FeatureCore extends ObjectModel GROUP BY f.`id_feature` ORDER BY f.`position` ASC '); - } + } - /** - * This metohd is allow to know if a feature is used or active - * @since 1.5.0.1 - * @return bool - */ - public static function isFeatureActive() - { - return Configuration::get('PS_FEATURE_FEATURE_ACTIVE'); - } + /** + * This metohd is allow to know if a feature is used or active + * @since 1.5.0.1 + * @return bool + */ + public static function isFeatureActive() + { + return Configuration::get('PS_FEATURE_FEATURE_ACTIVE'); + } - /** - * Move a feature - * @param bool $way Up (1) or Down (0) - * @param int $position - * @return bool Update result - */ - public function updatePosition($way, $position, $id_feature = null) - { - if (!$res = Db::getInstance()->executeS(' + /** + * Move a feature + * @param bool $way Up (1) or Down (0) + * @param int $position + * @return bool Update result + */ + public function updatePosition($way, $position, $id_feature = null) + { + if (!$res = Db::getInstance()->executeS(' SELECT `position`, `id_feature` FROM `'._DB_PREFIX_.'feature` WHERE `id_feature` = '.(int)($id_feature ? $id_feature : $this->id).' ORDER BY `position` ASC' - )) - return false; + )) { + return false; + } - foreach ($res as $feature) - if ((int)$feature['id_feature'] == (int)$this->id) - $moved_feature = $feature; + foreach ($res as $feature) { + if ((int)$feature['id_feature'] == (int)$this->id) { + $moved_feature = $feature; + } + } - if (!isset($moved_feature) || !isset($position)) - return false; + if (!isset($moved_feature) || !isset($position)) { + return false; + } - // < and > statements rather than BETWEEN operator - // since BETWEEN is treated differently according to databases - return (Db::getInstance()->execute(' + // < and > statements rather than BETWEEN operator + // since BETWEEN is treated differently according to databases + return (Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'feature` SET `position`= `position` '.($way ? '- 1' : '+ 1').' WHERE `position` '.($way - ? '> '.(int)$moved_feature['position'].' AND `position` <= '.(int)$position - : '< '.(int)$moved_feature['position'].' AND `position` >= '.(int)$position)) - && Db::getInstance()->execute(' + ? '> '.(int)$moved_feature['position'].' AND `position` <= '.(int)$position + : '< '.(int)$moved_feature['position'].' AND `position` >= '.(int)$position)) + && Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'feature` SET `position` = '.(int)$position.' WHERE `id_feature`='.(int)$moved_feature['id_feature'])); - } + } - /** - * Reorder feature position - * Call it after deleting a feature. - * - * @return bool $return - */ - public static function cleanPositions() - { - $sql = 'SET @i = -1; UPDATE `'._DB_PREFIX_.'feature` SET `position` = @i:=@i+1 ORDER BY `position` ASC'; - return (bool)Db::getInstance()->execute($sql); - } + /** + * Reorder feature position + * Call it after deleting a feature. + * + * @return bool $return + */ + public static function cleanPositions() + { + Db::getInstance()->execute('SET @i = -1', false); + $sql = 'UPDATE `'._DB_PREFIX_.'feature` SET `position` = @i:=@i+1 ORDER BY `position` ASC'; + return (bool)Db::getInstance()->execute($sql); + } - /** - * getHigherPosition - * - * Get the higher feature position - * - * @return int $position - */ - public static function getHigherPosition() - { - $sql = 'SELECT MAX(`position`) + /** + * getHigherPosition + * + * Get the higher feature position + * + * @return int $position + */ + public static function getHigherPosition() + { + $sql = 'SELECT MAX(`position`) FROM `'._DB_PREFIX_.'feature`'; - $position = DB::getInstance()->getValue($sql); - return (is_numeric($position)) ? $position : - 1; - } -} \ No newline at end of file + $position = DB::getInstance()->getValue($sql); + return (is_numeric($position)) ? $position : - 1; + } +} diff --git a/classes/FeatureValue.php b/classes/FeatureValue.php index 29f8ce4e..0e2d132c 100644 --- a/classes/FeatureValue.php +++ b/classes/FeatureValue.php @@ -26,64 +26,64 @@ class FeatureValueCore extends ObjectModel { - /** @var int Group id which attribute belongs */ - public $id_feature; + /** @var int Group id which attribute belongs */ + public $id_feature; - /** @var string Name */ - public $value; + /** @var string Name */ + public $value; - /** @var bool Custom */ - public $custom = 0; + /** @var bool Custom */ + public $custom = 0; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'feature_value', - 'primary' => 'id_feature_value', - 'multilang' => true, - 'fields' => array( - 'id_feature' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'custom' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'feature_value', + 'primary' => 'id_feature_value', + 'multilang' => true, + 'fields' => array( + 'id_feature' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'custom' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - /* Lang fields */ - 'value' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 255), - ), - ); + /* Lang fields */ + 'value' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 255), + ), + ); - protected $webserviceParameters = array( - 'objectsNodeName' => 'product_feature_values', - 'objectNodeName' => 'product_feature_value', - 'fields' => array( - 'id_feature' => array('xlink_resource'=> 'product_features'), - ), - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'product_feature_values', + 'objectNodeName' => 'product_feature_value', + 'fields' => array( + 'id_feature' => array('xlink_resource'=> 'product_features'), + ), + ); - /** - * Get all values for a given feature - * - * @param bool $id_feature Feature id - * @return array Array with feature's values - */ - public static function getFeatureValues($id_feature) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * Get all values for a given feature + * + * @param bool $id_feature Feature id + * @return array Array with feature's values + */ + public static function getFeatureValues($id_feature) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'feature_value` WHERE `id_feature` = '.(int)$id_feature - ); - } + ); + } - /** - * Get all values for a given feature and language - * - * @param int $id_lang Language id - * @param bool $id_feature Feature id - * @return array Array with feature's values - */ - public static function getFeatureValuesWithLang($id_lang, $id_feature, $custom = false) - { - return Db::getInstance()->executeS(' + /** + * Get all values for a given feature and language + * + * @param int $id_lang Language id + * @param bool $id_feature Feature id + * @return array Array with feature's values + */ + public static function getFeatureValuesWithLang($id_lang, $id_feature, $custom = false) + { + return Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'feature_value` v LEFT JOIN `'._DB_PREFIX_.'feature_value_lang` vl @@ -92,44 +92,45 @@ class FeatureValueCore extends ObjectModel '.(!$custom ? 'AND (v.`custom` IS NULL OR v.`custom` = 0)' : '').' ORDER BY vl.`value` ASC '); - } + } - /** - * Get all language for a given value - * - * @param bool $id_feature_value Feature value id - * @return array Array with value's languages - */ - public static function getFeatureValueLang($id_feature_value) - { - return Db::getInstance()->executeS(' + /** + * Get all language for a given value + * + * @param bool $id_feature_value Feature value id + * @return array Array with value's languages + */ + public static function getFeatureValueLang($id_feature_value) + { + return Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'feature_value_lang` WHERE `id_feature_value` = '.(int)$id_feature_value.' ORDER BY `id_lang` '); - } + } - /** - * Select the good lang in tab - * - * @param array $lang Array with all language - * @param int $id_lang Language id - * @return string String value name selected - */ - public static function selectLang($lang, $id_lang) - { - foreach ($lang as $tab) - if ($tab['id_lang'] == $id_lang) - return $tab['value']; - } + /** + * Select the good lang in tab + * + * @param array $lang Array with all language + * @param int $id_lang Language id + * @return string String value name selected + */ + public static function selectLang($lang, $id_lang) + { + foreach ($lang as $tab) { + if ($tab['id_lang'] == $id_lang) { + return $tab['value']; + } + } + } - public static function addFeatureValueImport($id_feature, $value, $id_product = null, $id_lang = null, $custom = false) - { - $id_feature_value = false; - if (!is_null($id_product) && $id_product) - { - $id_feature_value = Db::getInstance()->getValue(' + public static function addFeatureValueImport($id_feature, $value, $id_product = null, $id_lang = null, $custom = false) + { + $id_feature_value = false; + if (!is_null($id_product) && $id_product) { + $id_feature_value = Db::getInstance()->getValue(' SELECT fp.`id_feature_value` FROM '._DB_PREFIX_.'feature_product fp INNER JOIN '._DB_PREFIX_.'feature_value fv USING (`id_feature_value`) @@ -137,17 +138,18 @@ class FeatureValueCore extends ObjectModel AND fv.`custom` = '.(int)$custom.' AND fp.`id_product` = '.(int)$id_product); - if ($custom && $id_feature_value && !is_null($id_lang) && $id_lang) - Db::getInstance()->execute(' + if ($custom && $id_feature_value && !is_null($id_lang) && $id_lang) { + Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'feature_value_lang SET `value` = \''.pSQL($value).'\' WHERE `id_feature_value` = '.(int)$id_feature_value.' AND `value` != \''.pSQL($value).'\' AND `id_lang` = '.(int)$id_lang); - } + } + } - if (!$custom) - $id_feature_value = Db::getInstance()->getValue(' + if (!$custom) { + $id_feature_value = Db::getInstance()->getValue(' SELECT fv.`id_feature_value` FROM '._DB_PREFIX_.'feature_value fv LEFT JOIN '._DB_PREFIX_.'feature_value_lang fvl ON (fvl.`id_feature_value` = fv.`id_feature_value` AND fvl.`id_lang` = '.(int)$id_lang.') @@ -155,47 +157,52 @@ class FeatureValueCore extends ObjectModel AND fv.`id_feature` = '.(int)$id_feature.' AND fv.`custom` = 0 GROUP BY fv.`id_feature_value`'); + } - if ($id_feature_value) - return (int)$id_feature_value; + if ($id_feature_value) { + return (int)$id_feature_value; + } - // Feature doesn't exist, create it - $feature_value = new FeatureValue(); - $feature_value->id_feature = (int)$id_feature; - $feature_value->custom = (bool)$custom; - $feature_value->value = array_fill_keys(Language::getIDs(false), $value); - $feature_value->add(); + // Feature doesn't exist, create it + $feature_value = new FeatureValue(); + $feature_value->id_feature = (int)$id_feature; + $feature_value->custom = (bool)$custom; + $feature_value->value = array_fill_keys(Language::getIDs(false), $value); + $feature_value->add(); - return (int)$feature_value->id; - } + return (int)$feature_value->id; + } - public function add($autodate = true, $nullValues = false) - { - $return = parent::add($autodate, $nullValues); - if ($return) - Hook::exec('actionFeatureValueSave', array('id_feature_value' => $this->id)); - return $return; - } + public function add($autodate = true, $nullValues = false) + { + $return = parent::add($autodate, $nullValues); + if ($return) { + Hook::exec('actionFeatureValueSave', array('id_feature_value' => $this->id)); + } + return $return; + } - public function delete() - { - /* Also delete related products */ - Db::getInstance()->execute(' + public function delete() + { + /* Also delete related products */ + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'feature_product` WHERE `id_feature_value` = '.(int)$this->id - ); - $return = parent::delete(); + ); + $return = parent::delete(); - if ($return) - Hook::exec('actionFeatureValueDelete', array('id_feature_value' => $this->id)); - return $return; - } + if ($return) { + Hook::exec('actionFeatureValueDelete', array('id_feature_value' => $this->id)); + } + return $return; + } - public function update($nullValues = false) - { - $return = parent::update($nullValues); - if ($return) - Hook::exec('actionFeatureValueSave', array('id_feature_value' => $this->id)); - return $return; - } + public function update($nullValues = false) + { + $return = parent::update($nullValues); + if ($return) { + Hook::exec('actionFeatureValueSave', array('id_feature_value' => $this->id)); + } + return $return; + } } diff --git a/classes/FileUploader.php b/classes/FileUploader.php index 5f45f035..78aeed37 100644 --- a/classes/FileUploader.php +++ b/classes/FileUploader.php @@ -26,243 +26,260 @@ class FileUploaderCore { - protected $allowedExtensions = array(); + protected $allowedExtensions = array(); - /** @var QqUploadedFileXhr|QqUploadedFileForm|false */ - protected $file; - protected $sizeLimit; + /** @var QqUploadedFileXhr|QqUploadedFileForm|false */ + protected $file; + protected $sizeLimit; - public function __construct(array $allowedExtensions = array(), $sizeLimit = 10485760) - { - $allowedExtensions = array_map('strtolower', $allowedExtensions); + public function __construct(array $allowedExtensions = array(), $sizeLimit = 10485760) + { + $allowedExtensions = array_map('strtolower', $allowedExtensions); - $this->allowedExtensions = $allowedExtensions; - $this->sizeLimit = $sizeLimit; + $this->allowedExtensions = $allowedExtensions; + $this->sizeLimit = $sizeLimit; - if (isset($_GET['qqfile'])) - $this->file = new QqUploadedFileXhr(); - elseif (isset($_FILES['qqfile'])) - $this->file = new QqUploadedFileForm(); - else - $this->file = false; - } + if (isset($_GET['qqfile'])) { + $this->file = new QqUploadedFileXhr(); + } elseif (isset($_FILES['qqfile'])) { + $this->file = new QqUploadedFileForm(); + } else { + $this->file = false; + } + } - protected function toBytes($str) - { - $val = trim($str); - $last = strtolower($str[strlen($str) - 1]); - switch ($last) - { - case 'g': $val *= 1024; - case 'm': $val *= 1024; - case 'k': $val *= 1024; - } - return $val; - } + protected function toBytes($str) + { + $val = trim($str); + $last = strtolower($str[strlen($str) - 1]); + switch ($last) { + case 'g': $val *= 1024; + case 'm': $val *= 1024; + case 'k': $val *= 1024; + } + return $val; + } - /** - * Returns array('success'=>true) or array('error'=>'error message') - */ - public function handleUpload() - { - if (!$this->file) - return array('error' => Tools::displayError('No files were uploaded.')); + /** + * Returns array('success'=>true) or array('error'=>'error message') + */ + public function handleUpload() + { + if (!$this->file) { + return array('error' => Tools::displayError('No files were uploaded.')); + } - $size = $this->file->getSize(); + $size = $this->file->getSize(); - if ($size == 0) - return array('error' => Tools::displayError('File is empty')); - if ($size > $this->sizeLimit) - return array('error' => Tools::displayError('File is too large')); + if ($size == 0) { + return array('error' => Tools::displayError('File is empty')); + } + if ($size > $this->sizeLimit) { + return array('error' => Tools::displayError('File is too large')); + } - $pathinfo = pathinfo($this->file->getName()); - $these = implode(', ', $this->allowedExtensions); - if (!isset($pathinfo['extension'])) - return array('error' => sprintf(Tools::displayError('File has an invalid extension, it should be one of these: %s.'), $these)); - $ext = $pathinfo['extension']; - if ($this->allowedExtensions && !in_array(strtolower($ext), $this->allowedExtensions)) - return array('error' => sprintf(Tools::displayError('File has an invalid extension, it should be one of these: %s.'), $these)); + $pathinfo = pathinfo($this->file->getName()); + $these = implode(', ', $this->allowedExtensions); + if (!isset($pathinfo['extension'])) { + return array('error' => sprintf(Tools::displayError('File has an invalid extension, it should be one of these: %s.'), $these)); + } + $ext = $pathinfo['extension']; + if ($this->allowedExtensions && !in_array(strtolower($ext), $this->allowedExtensions)) { + return array('error' => sprintf(Tools::displayError('File has an invalid extension, it should be one of these: %s.'), $these)); + } - return $this->file->save(); - - } + return $this->file->save(); + } } class QqUploadedFileForm { - /** - * Save the file to the specified path - * @return bool TRUE on success - */ - public function save() - { - $product = new Product($_GET['id_product']); - if (!Validate::isLoadedObject($product)) - return array('error' => Tools::displayError('Cannot add image because product creation failed.')); - else - { - $image = new Image(); - $image->id_product = (int)$product->id; - $image->position = Image::getHighestPosition($product->id) + 1; - $legends = Tools::getValue('legend'); - if (is_array($legends)) - foreach ($legends as $key => $legend) - if (Validate::isGenericName($legend)) - $image->legend[(int)$key] = $legend; - else - return array('error' => sprintf(Tools::displayError('Error on image caption: "%1s" is not a valid caption.'), Tools::safeOutput($legend))); - if (!Image::getCover($image->id_product)) - $image->cover = 1; - else - $image->cover = 0; + /** + * Save the file to the specified path + * @return bool TRUE on success + */ + public function save() + { + $product = new Product($_GET['id_product']); + if (!Validate::isLoadedObject($product)) { + return array('error' => Tools::displayError('Cannot add image because product creation failed.')); + } else { + $image = new Image(); + $image->id_product = (int)$product->id; + $image->position = Image::getHighestPosition($product->id) + 1; + $legends = Tools::getValue('legend'); + if (is_array($legends)) { + foreach ($legends as $key => $legend) { + if (Validate::isGenericName($legend)) { + $image->legend[(int)$key] = $legend; + } else { + return array('error' => sprintf(Tools::displayError('Error on image caption: "%1s" is not a valid caption.'), Tools::safeOutput($legend))); + } + } + } + if (!Image::getCover($image->id_product)) { + $image->cover = 1; + } else { + $image->cover = 0; + } - if (($validate = $image->validateFieldsLang(false, true)) !== true) - return array('error' => Tools::displayError($validate)); - if (!$image->add()) - return array('error' => Tools::displayError('Error while creating additional image')); - else - return $this->copyImage($product->id, $image->id); - } - } + if (($validate = $image->validateFieldsLang(false, true)) !== true) { + return array('error' => Tools::displayError($validate)); + } + if (!$image->add()) { + return array('error' => Tools::displayError('Error while creating additional image')); + } else { + return $this->copyImage($product->id, $image->id); + } + } + } - public function copyImage($id_product, $id_image, $method = 'auto') - { - $image = new Image($id_image); - if (!$new_path = $image->getPathForCreation()) - return array('error' => Tools::displayError('An error occurred during new folder creation')); - if (!($tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES['qqfile']['tmp_name'], $tmpName)) - return array('error' => Tools::displayError('An error occurred during the image upload')); - elseif (!ImageManager::resize($tmpName, $new_path.'.'.$image->image_format)) - return array('error' => Tools::displayError('An error occurred while copying image.')); - elseif ($method == 'auto') - { - $imagesTypes = ImageType::getImagesTypes('products'); - foreach ($imagesTypes as $imageType) - { - if (!ImageManager::resize($tmpName, $new_path.'-'.stripslashes($imageType['name']).'.'.$image->image_format, $imageType['width'], $imageType['height'], $image->image_format)) - return array('error' => Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name'])); - } - } - unlink($tmpName); - Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_product)); + public function copyImage($id_product, $id_image, $method = 'auto') + { + $image = new Image($id_image); + if (!$new_path = $image->getPathForCreation()) { + return array('error' => Tools::displayError('An error occurred during new folder creation')); + } + if (!($tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES['qqfile']['tmp_name'], $tmpName)) { + return array('error' => Tools::displayError('An error occurred during the image upload')); + } elseif (!ImageManager::resize($tmpName, $new_path.'.'.$image->image_format)) { + return array('error' => Tools::displayError('An error occurred while copying image.')); + } elseif ($method == 'auto') { + $imagesTypes = ImageType::getImagesTypes('products'); + foreach ($imagesTypes as $imageType) { + if (!ImageManager::resize($tmpName, $new_path.'-'.stripslashes($imageType['name']).'.'.$image->image_format, $imageType['width'], $imageType['height'], $image->image_format)) { + return array('error' => Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name'])); + } + } + } + unlink($tmpName); + Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_product)); - if (!$image->update()) - return array('error' => Tools::displayError('Error while updating status')); - $img = array('id_image' => $image->id, 'position' => $image->position, 'cover' => $image->cover, 'name' => $this->getName(), 'legend' => $image->legend); - return array('success' => $img); - } + if (!$image->update()) { + return array('error' => Tools::displayError('Error while updating status')); + } + $img = array('id_image' => $image->id, 'position' => $image->position, 'cover' => $image->cover, 'name' => $this->getName(), 'legend' => $image->legend); + return array('success' => $img); + } - public function getName() - { - return $_FILES['qqfile']['name']; - } + public function getName() + { + return $_FILES['qqfile']['name']; + } - public function getSize() - { - return $_FILES['qqfile']['size']; - } + public function getSize() + { + return $_FILES['qqfile']['size']; + } } /** * Handle file uploads via XMLHttpRequest */ class QqUploadedFileXhr { - /** - * Save the file to the specified path - * @return bool TRUE on success - */ - public function upload($path) - { - $input = fopen('php://input', 'r'); - $target = fopen($path, 'w'); + /** + * Save the file to the specified path + * @return bool TRUE on success + */ + public function upload($path) + { + $input = fopen('php://input', 'r'); + $target = fopen($path, 'w'); - $realSize = stream_copy_to_stream($input, $target); - if ($realSize != $this->getSize()) - return false; + $realSize = stream_copy_to_stream($input, $target); + if ($realSize != $this->getSize()) { + return false; + } - fclose($input); - fclose($target); + fclose($input); + fclose($target); - return true; - } + return true; + } - public function save() - { - $product = new Product($_GET['id_product']); - if (!Validate::isLoadedObject($product)) - return array('error' => Tools::displayError('Cannot add image because product creation failed.')); - else - { - $image = new Image(); - $image->id_product = (int)($product->id); - $image->position = Image::getHighestPosition($product->id) + 1; - $legends = Tools::getValue('legend'); - if (is_array($legends)) - foreach ($legends as $key => $legend) - if (Validate::isGenericName($legend)) - $image->legend[(int)$key] = $legend; - else - return array('error' => sprintf(Tools::displayError('Error on image caption: "%1s" is not a valid caption.'), Tools::safeOutput($legend))); - if (!Image::getCover($image->id_product)) - $image->cover = 1; - else - $image->cover = 0; + public function save() + { + $product = new Product($_GET['id_product']); + if (!Validate::isLoadedObject($product)) { + return array('error' => Tools::displayError('Cannot add image because product creation failed.')); + } else { + $image = new Image(); + $image->id_product = (int)($product->id); + $image->position = Image::getHighestPosition($product->id) + 1; + $legends = Tools::getValue('legend'); + if (is_array($legends)) { + foreach ($legends as $key => $legend) { + if (Validate::isGenericName($legend)) { + $image->legend[(int)$key] = $legend; + } else { + return array('error' => sprintf(Tools::displayError('Error on image caption: "%1s" is not a valid caption.'), Tools::safeOutput($legend))); + } + } + } + if (!Image::getCover($image->id_product)) { + $image->cover = 1; + } else { + $image->cover = 0; + } - if (($validate = $image->validateFieldsLang(false, true)) !== true) - return array('error' => Tools::displayError($validate)); - if (!$image->add()) - return array('error' => Tools::displayError('Error while creating additional image')); - else - return $this->copyImage($product->id, $image->id); - } - } + if (($validate = $image->validateFieldsLang(false, true)) !== true) { + return array('error' => Tools::displayError($validate)); + } + if (!$image->add()) { + return array('error' => Tools::displayError('Error while creating additional image')); + } else { + return $this->copyImage($product->id, $image->id); + } + } + } - public function copyImage($id_product, $id_image, $method = 'auto') - { - $image = new Image($id_image); - if (!$new_path = $image->getPathForCreation()) - return array('error' => Tools::displayError('An error occurred during new folder creation')); - if (!($tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !$this->upload($tmpName)) - return array('error' => Tools::displayError('An error occurred during the image upload')); - elseif (!ImageManager::resize($tmpName, $new_path.'.'.$image->image_format)) - return array('error' => Tools::displayError('An error occurred while copying image.')); - elseif ($method == 'auto') - { - $imagesTypes = ImageType::getImagesTypes('products'); - foreach ($imagesTypes as $imageType) - { - /* - $theme = (Shop::isFeatureActive() ? '-'.$imageType['id_theme'] : ''); - if (!ImageManager::resize($tmpName, $new_path.'-'.stripslashes($imageType['name']).$theme.'.'.$image->image_format, $imageType['width'], $imageType['height'], $image->image_format)) - return array('error' => Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name'])); - */ - if (!ImageManager::resize($tmpName, $new_path.'-'.stripslashes($imageType['name']).'.'.$image->image_format, $imageType['width'], $imageType['height'], $image->image_format)) - return array('error' => Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name'])); - } - } - unlink($tmpName); - Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_product)); + public function copyImage($id_product, $id_image, $method = 'auto') + { + $image = new Image($id_image); + if (!$new_path = $image->getPathForCreation()) { + return array('error' => Tools::displayError('An error occurred during new folder creation')); + } + if (!($tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !$this->upload($tmpName)) { + return array('error' => Tools::displayError('An error occurred during the image upload')); + } elseif (!ImageManager::resize($tmpName, $new_path.'.'.$image->image_format)) { + return array('error' => Tools::displayError('An error occurred while copying image.')); + } elseif ($method == 'auto') { + $imagesTypes = ImageType::getImagesTypes('products'); + foreach ($imagesTypes as $imageType) { + /* + $theme = (Shop::isFeatureActive() ? '-'.$imageType['id_theme'] : ''); + if (!ImageManager::resize($tmpName, $new_path.'-'.stripslashes($imageType['name']).$theme.'.'.$image->image_format, $imageType['width'], $imageType['height'], $image->image_format)) + return array('error' => Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name'])); + */ + if (!ImageManager::resize($tmpName, $new_path.'-'.stripslashes($imageType['name']).'.'.$image->image_format, $imageType['width'], $imageType['height'], $image->image_format)) { + return array('error' => Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name'])); + } + } + } + unlink($tmpName); + Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_product)); - if (!$image->update()) - return array('error' => Tools::displayError('Error while updating status')); - $img = array('id_image' => $image->id, 'position' => $image->position, 'cover' => $image->cover, 'name' => $this->getName(), 'legend' => $image->legend); - return array('success' => $img); - } + if (!$image->update()) { + return array('error' => Tools::displayError('Error while updating status')); + } + $img = array('id_image' => $image->id, 'position' => $image->position, 'cover' => $image->cover, 'name' => $this->getName(), 'legend' => $image->legend); + return array('success' => $img); + } - public function getName() - { - return $_GET['qqfile']; - } + public function getName() + { + return $_GET['qqfile']; + } - public function getSize() - { - if (isset($_SERVER['CONTENT_LENGTH']) || isset($_SERVER['HTTP_CONTENT_LENGTH'])) - { - if (isset($_SERVER['HTTP_CONTENT_LENGTH'])) - return (int)$_SERVER['HTTP_CONTENT_LENGTH']; - else - return (int)$_SERVER['CONTENT_LENGTH']; - } - return false; - } + public function getSize() + { + if (isset($_SERVER['CONTENT_LENGTH']) || isset($_SERVER['HTTP_CONTENT_LENGTH'])) { + if (isset($_SERVER['HTTP_CONTENT_LENGTH'])) { + return (int)$_SERVER['HTTP_CONTENT_LENGTH']; + } else { + return (int)$_SERVER['CONTENT_LENGTH']; + } + } + return false; + } } diff --git a/classes/Gender.php b/classes/Gender.php index 490faff7..b1eade75 100644 --- a/classes/Gender.php +++ b/classes/Gender.php @@ -29,45 +29,47 @@ */ class GenderCore extends ObjectModel { - public $id_gender; - public $name; - public $type; + public $id_gender; + public $name; + public $type; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'gender', - 'primary' => 'id_gender', - 'multilang' => true, - 'fields' => array( - 'type' => array('type' => self::TYPE_INT, 'required' => true), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'gender', + 'primary' => 'id_gender', + 'multilang' => true, + 'fields' => array( + 'type' => array('type' => self::TYPE_INT, 'required' => true), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isString', 'required' => true, 'size' => 20), - ), - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isString', 'required' => true, 'size' => 20), + ), + ); - public function __construct($id = null, $id_lang = null, $id_shop = null) - { - parent::__construct($id, $id_lang, $id_shop); + public function __construct($id = null, $id_lang = null, $id_shop = null) + { + parent::__construct($id, $id_lang, $id_shop); - $this->image_dir = _PS_GENDERS_DIR_; - } + $this->image_dir = _PS_GENDERS_DIR_; + } - public static function getGenders($id_lang = null) - { - if (is_null($id_lang)) - $id_lang = Context::getContext()->language->id; + public static function getGenders($id_lang = null) + { + if (is_null($id_lang)) { + $id_lang = Context::getContext()->language->id; + } - $genders = new PrestaShopCollection('Gender', $id_lang); - return $genders; - } + $genders = new PrestaShopCollection('Gender', $id_lang); + return $genders; + } - public function getImage($use_unknown = false) - { - if (!isset($this->id) || empty($this->id) || !file_exists(_PS_GENDERS_DIR_.$this->id.'.jpg')) - return _THEME_GENDERS_DIR_.'Unknown.jpg'; - return _THEME_GENDERS_DIR_.$this->id.'.jpg'; - } -} \ No newline at end of file + public function getImage($use_unknown = false) + { + if (!isset($this->id) || empty($this->id) || !file_exists(_PS_GENDERS_DIR_.$this->id.'.jpg')) { + return _THEME_GENDERS_DIR_.'Unknown.jpg'; + } + return _THEME_GENDERS_DIR_.$this->id.'.jpg'; + } +} diff --git a/classes/Group.php b/classes/Group.php index 8b47b35c..f39b786a 100644 --- a/classes/Group.php +++ b/classes/Group.php @@ -26,82 +26,85 @@ class GroupCore extends ObjectModel { - public $id; + public $id; - /** @var string Lastname */ - public $name; + /** @var string Lastname */ + public $name; - /** @var string Reduction */ - public $reduction; + /** @var string Reduction */ + public $reduction; - /** @var int Price display method (tax inc/tax exc) */ - public $price_display_method; + /** @var int Price display method (tax inc/tax exc) */ + public $price_display_method; - /** @var bool Show prices */ - public $show_prices = 1; + /** @var bool Show prices */ + public $show_prices = 1; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** @var string Object last modification date */ - public $date_upd; + /** @var string Object last modification date */ + public $date_upd; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'group', - 'primary' => 'id_group', - 'multilang' => true, - 'fields' => array( - 'reduction' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'price_display_method' => array('type' => self::TYPE_INT, 'validate' => 'isPriceDisplayMethod', 'required' => true), - 'show_prices' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'group', + 'primary' => 'id_group', + 'multilang' => true, + 'fields' => array( + 'reduction' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'price_display_method' => array('type' => self::TYPE_INT, 'validate' => 'isPriceDisplayMethod', 'required' => true), + 'show_prices' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), - ), - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), + ), + ); - protected static $cache_reduction = array(); - protected static $group_price_display_method = array(); + protected static $cache_reduction = array(); + protected static $group_price_display_method = array(); - protected $webserviceParameters = array(); + protected $webserviceParameters = array(); - public function __construct($id = null, $id_lang = null, $id_shop = null) - { - parent::__construct($id, $id_lang, $id_shop); - if ($this->id && !isset(Group::$group_price_display_method[$this->id])) - self::$group_price_display_method[$this->id] = $this->price_display_method; - } + public function __construct($id = null, $id_lang = null, $id_shop = null) + { + parent::__construct($id, $id_lang, $id_shop); + if ($this->id && !isset(Group::$group_price_display_method[$this->id])) { + self::$group_price_display_method[$this->id] = $this->price_display_method; + } + } - public static function getGroups($id_lang, $id_shop = false) - { - $shop_criteria = ''; - if ($id_shop) - $shop_criteria = Shop::addSqlAssociation('group', 'g'); + public static function getGroups($id_lang, $id_shop = false) + { + $shop_criteria = ''; + if ($id_shop) { + $shop_criteria = Shop::addSqlAssociation('group', 'g'); + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT DISTINCT g.`id_group`, g.`reduction`, g.`price_display_method`, gl.`name` FROM `'._DB_PREFIX_.'group` g LEFT JOIN `'._DB_PREFIX_.'group_lang` AS gl ON (g.`id_group` = gl.`id_group` AND gl.`id_lang` = '.(int)$id_lang.') '.$shop_criteria.' ORDER BY g.`id_group` ASC'); - } + } - public function getCustomers($count = false, $start = 0, $limit = 0, $shop_filtering = false) - { - if ($count) - return Db::getInstance()->getValue(' + public function getCustomers($count = false, $start = 0, $limit = 0, $shop_filtering = false) + { + if ($count) { + return Db::getInstance()->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'customer_group` cg LEFT JOIN `'._DB_PREFIX_.'customer` c ON (cg.`id_customer` = c.`id_customer`) WHERE cg.`id_group` = '.(int)$this->id.' '.($shop_filtering ? Shop::addSqlRestriction(Shop::SHARE_CUSTOMER) : '').' AND c.`deleted` != 1'); - return Db::getInstance()->executeS(' + } + return Db::getInstance()->executeS(' SELECT cg.`id_customer`, c.* FROM `'._DB_PREFIX_.'customer_group` cg LEFT JOIN `'._DB_PREFIX_.'customer` c ON (cg.`id_customer` = c.`id_customer`) @@ -110,87 +113,86 @@ class GroupCore extends ObjectModel '.($shop_filtering ? Shop::addSqlRestriction(Shop::SHARE_CUSTOMER) : '').' ORDER BY cg.`id_customer` ASC '.($limit > 0 ? 'LIMIT '.(int)$start.', '.(int)$limit : '')); - } + } - public static function getReduction($id_customer = null) - { - if (!isset(self::$cache_reduction['customer'][(int)$id_customer])) - { - $id_group = $id_customer ? Customer::getDefaultGroupId((int)$id_customer) : (int)Group::getCurrent()->id; - self::$cache_reduction['customer'][(int)$id_customer] = Group::getReductionByIdGroup($id_group); - } - return self::$cache_reduction['customer'][(int)$id_customer]; - } + public static function getReduction($id_customer = null) + { + if (!isset(self::$cache_reduction['customer'][(int)$id_customer])) { + $id_group = $id_customer ? Customer::getDefaultGroupId((int)$id_customer) : (int)Group::getCurrent()->id; + self::$cache_reduction['customer'][(int)$id_customer] = Group::getReductionByIdGroup($id_group); + } + return self::$cache_reduction['customer'][(int)$id_customer]; + } - public static function getReductionByIdGroup($id_group) - { - if (!isset(self::$cache_reduction['group'][$id_group])) - { - self::$cache_reduction['group'][$id_group] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getReductionByIdGroup($id_group) + { + if (!isset(self::$cache_reduction['group'][$id_group])) { + self::$cache_reduction['group'][$id_group] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `reduction` FROM `'._DB_PREFIX_.'group` WHERE `id_group` = '.(int)$id_group); - } - return self::$cache_reduction['group'][$id_group]; - } + } + return self::$cache_reduction['group'][$id_group]; + } - public static function getPriceDisplayMethod($id_group) - { - if (!isset(Group::$group_price_display_method[$id_group])) - self::$group_price_display_method[$id_group] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getPriceDisplayMethod($id_group) + { + if (!isset(Group::$group_price_display_method[$id_group])) { + self::$group_price_display_method[$id_group] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `price_display_method` FROM `'._DB_PREFIX_.'group` WHERE `id_group` = '.(int)$id_group); - return self::$group_price_display_method[$id_group]; - } + } + return self::$group_price_display_method[$id_group]; + } - public static function getDefaultPriceDisplayMethod() - { - return Group::getPriceDisplayMethod((int)Configuration::get('PS_CUSTOMER_GROUP')); - } + public static function getDefaultPriceDisplayMethod() + { + return Group::getPriceDisplayMethod((int)Configuration::get('PS_CUSTOMER_GROUP')); + } - public function add($autodate = true, $null_values = false) - { - Configuration::updateGlobalValue('PS_GROUP_FEATURE_ACTIVE', '1'); - if (parent::add($autodate, $null_values)) - { - Category::setNewGroupForHome((int)$this->id); - Carrier::assignGroupToAllCarriers((int)$this->id); - return true; - } - return false; - } + public function add($autodate = true, $null_values = false) + { + Configuration::updateGlobalValue('PS_GROUP_FEATURE_ACTIVE', '1'); + if (parent::add($autodate, $null_values)) { + Category::setNewGroupForHome((int)$this->id); + Carrier::assignGroupToAllCarriers((int)$this->id); + return true; + } + return false; + } - public function update($autodate = true, $null_values = false) - { - if (!Configuration::getGlobalValue('PS_GROUP_FEATURE_ACTIVE') && $this->reduction > 0) - Configuration::updateGlobalValue('PS_GROUP_FEATURE_ACTIVE', 1); - return parent::update($autodate, $null_values); - } + public function update($autodate = true, $null_values = false) + { + if (!Configuration::getGlobalValue('PS_GROUP_FEATURE_ACTIVE') && $this->reduction > 0) { + Configuration::updateGlobalValue('PS_GROUP_FEATURE_ACTIVE', 1); + } + return parent::update($autodate, $null_values); + } - public function delete() - { - if ($this->id == (int)Configuration::get('PS_CUSTOMER_GROUP')) - return false; - if (parent::delete()) - { - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cart_rule_group` WHERE `id_group` = '.(int)$this->id); - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'customer_group` WHERE `id_group` = '.(int)$this->id); - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'category_group` WHERE `id_group` = '.(int)$this->id); - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'group_reduction` WHERE `id_group` = '.(int)$this->id); - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'product_group_reduction_cache` WHERE `id_group` = '.(int)$this->id); - $this->truncateModulesRestrictions($this->id); + public function delete() + { + if ($this->id == (int)Configuration::get('PS_CUSTOMER_GROUP')) { + return false; + } + if (parent::delete()) { + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'cart_rule_group` WHERE `id_group` = '.(int)$this->id); + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'customer_group` WHERE `id_group` = '.(int)$this->id); + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'category_group` WHERE `id_group` = '.(int)$this->id); + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'group_reduction` WHERE `id_group` = '.(int)$this->id); + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'product_group_reduction_cache` WHERE `id_group` = '.(int)$this->id); + $this->truncateModulesRestrictions($this->id); - // Add default group (id 3) to customers without groups - Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'customer_group` ( + // Add default group (id 3) to customers without groups + Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'customer_group` ( SELECT c.id_customer, '.(int)Configuration::get('PS_CUSTOMER_GROUP').' FROM `'._DB_PREFIX_.'customer` c LEFT JOIN `'._DB_PREFIX_.'customer_group` cg ON cg.id_customer = c.id_customer WHERE cg.id_customer IS NULL)'); - // Set to the customer the default group - // Select the minimal id from customer_group - Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'customer` cg + // Set to the customer the default group + // Select the minimal id from customer_group + Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'customer` cg SET id_default_group = IFNULL(( SELECT min(id_group) FROM `'._DB_PREFIX_.'customer_group` @@ -198,158 +200,168 @@ class GroupCore extends ObjectModel '.(int)Configuration::get('PS_CUSTOMER_GROUP').') WHERE `id_default_group` = '.(int)$this->id); - return true; - } - return false; - } + return true; + } + return false; + } - /** - * This method is allow to know if a feature is used or active - * @since 1.5.0.1 - * @return bool - */ - public static function isFeatureActive() - { - static $ps_group_feature_active = null; - if ($ps_group_feature_active === null) - $ps_group_feature_active = Configuration::get('PS_GROUP_FEATURE_ACTIVE'); - return $ps_group_feature_active; - } + /** + * This method is allow to know if a feature is used or active + * @since 1.5.0.1 + * @return bool + */ + public static function isFeatureActive() + { + static $ps_group_feature_active = null; + if ($ps_group_feature_active === null) { + $ps_group_feature_active = Configuration::get('PS_GROUP_FEATURE_ACTIVE'); + } + return $ps_group_feature_active; + } - /** - * This method is allow to know if there are other groups than the default ones - * @since 1.5.0.1 - * @param $table - * @param $has_active_column - * @return bool - */ - public static function isCurrentlyUsed($table = null, $has_active_column = false) - { - return (bool)(Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'group`') > 3); - } + /** + * This method is allow to know if there are other groups than the default ones + * @since 1.5.0.1 + * @param $table + * @param $has_active_column + * @return bool + */ + public static function isCurrentlyUsed($table = null, $has_active_column = false) + { + return (bool)(Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'group`') > 3); + } - /** - * Truncate all modules restrictions for the group - * - * @param int $id_group - * @return bool - */ - public static function truncateModulesRestrictions($id_group) - { - return Db::getInstance()->execute(' + /** + * Truncate all modules restrictions for the group + * + * @param int $id_group + * @return bool + */ + public static function truncateModulesRestrictions($id_group) + { + return Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'module_group` WHERE `id_group` = '.(int)$id_group); - } + } - /** - * Truncate all restrictions by module - * - * @param int $id_module - * @return bool - */ - public static function truncateRestrictionsByModule($id_module) - { - return Db::getInstance()->execute(' + /** + * Truncate all restrictions by module + * + * @param int $id_module + * @return bool + */ + public static function truncateRestrictionsByModule($id_module) + { + return Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'module_group` WHERE `id_module` = '.(int)$id_module); - } + } - /** - * Adding restrictions modules to the group with id $id_group - * @param $id_group - * @param $modules - * @param array $shops - * @return bool - */ - public static function addModulesRestrictions($id_group, $modules, $shops = array(1)) - { - if (!is_array($modules) || !count($modules) || !is_array($shops) || !count($shops)) - return false; + /** + * Adding restrictions modules to the group with id $id_group + * @param $id_group + * @param $modules + * @param array $shops + * @return bool + */ + public static function addModulesRestrictions($id_group, $modules, $shops = array(1)) + { + if (!is_array($modules) || !count($modules) || !is_array($shops) || !count($shops)) { + return false; + } - // Delete all record for this group - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module_group` WHERE `id_group` = '.(int)$id_group); + // Delete all record for this group + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module_group` WHERE `id_group` = '.(int)$id_group); - $sql = 'INSERT INTO `'._DB_PREFIX_.'module_group` (`id_module`, `id_shop`, `id_group`) VALUES '; - foreach ($modules as $module) - foreach ($shops as $shop) - $sql .= '("'.(int)$module.'", "'.(int)$shop.'", "'.(int)$id_group.'"),'; - $sql = rtrim($sql, ','); + $sql = 'INSERT INTO `'._DB_PREFIX_.'module_group` (`id_module`, `id_shop`, `id_group`) VALUES '; + foreach ($modules as $module) { + foreach ($shops as $shop) { + $sql .= '("'.(int)$module.'", "'.(int)$shop.'", "'.(int)$id_group.'"),'; + } + } + $sql = rtrim($sql, ','); - return (bool)Db::getInstance()->execute($sql); - } + return (bool)Db::getInstance()->execute($sql); + } - /** - * Add restrictions for a new module. - * We authorize every groups to the new module - * - * @param int $id_module - * @param array $shops - * @return bool - */ - public static function addRestrictionsForModule($id_module, $shops = array(1)) - { - if (!is_array($shops) || !count($shops)) - return false; + /** + * Add restrictions for a new module. + * We authorize every groups to the new module + * + * @param int $id_module + * @param array $shops + * @return bool + */ + public static function addRestrictionsForModule($id_module, $shops = array(1)) + { + if (!is_array($shops) || !count($shops)) { + return false; + } - $res = true; - foreach ($shops as $shop) - $res &= Db::getInstance()->execute(' + $res = true; + foreach ($shops as $shop) { + $res &= Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'module_group` (`id_module`, `id_shop`, `id_group`) (SELECT '.(int)$id_module.', '.(int)$shop.', id_group FROM `'._DB_PREFIX_.'group`)'); - return $res; - } + } + return $res; + } - /** - * Return current group object - * Use context - * - * @return Group Group object - */ - public static function getCurrent() - { - static $groups = array(); - static $ps_unidentified_group = null; - static $ps_customer_group = null; + /** + * Return current group object + * Use context + * + * @return Group Group object + */ + public static function getCurrent() + { + static $groups = array(); + static $ps_unidentified_group = null; + static $ps_customer_group = null; - if ($ps_unidentified_group === null) - $ps_unidentified_group = Configuration::get('PS_UNIDENTIFIED_GROUP'); + if ($ps_unidentified_group === null) { + $ps_unidentified_group = Configuration::get('PS_UNIDENTIFIED_GROUP'); + } - if ($ps_customer_group === null) - $ps_customer_group = Configuration::get('PS_CUSTOMER_GROUP'); + if ($ps_customer_group === null) { + $ps_customer_group = Configuration::get('PS_CUSTOMER_GROUP'); + } - $customer = Context::getContext()->customer; - if (Validate::isLoadedObject($customer)) - $id_group = (int)$customer->id_default_group; - else - $id_group = (int)$ps_unidentified_group; + $customer = Context::getContext()->customer; + if (Validate::isLoadedObject($customer)) { + $id_group = (int)$customer->id_default_group; + } else { + $id_group = (int)$ps_unidentified_group; + } - if (!isset($groups[$id_group])) - $groups[$id_group] = new Group($id_group); + if (!isset($groups[$id_group])) { + $groups[$id_group] = new Group($id_group); + } - if (!$groups[$id_group]->isAssociatedToShop(Context::getContext()->shop->id)) - { - $id_group = (int)$ps_customer_group; - if (!isset($groups[$id_group])) - $groups[$id_group] = new Group($id_group); - } + if (!$groups[$id_group]->isAssociatedToShop(Context::getContext()->shop->id)) { + $id_group = (int)$ps_customer_group; + if (!isset($groups[$id_group])) { + $groups[$id_group] = new Group($id_group); + } + } - return $groups[$id_group]; - } + return $groups[$id_group]; + } - /** - * Light back office search for Group - * - * @param string $query Searched string - * @return array Corresponding groups - */ - public static function searchByName($query) - { - return Db::getInstance()->getRow(' + /** + * Light back office search for Group + * + * @param string $query Searched string + * @return array Corresponding groups + */ + public static function searchByName($query) + { + return Db::getInstance()->getRow(' SELECT g.*, gl.* FROM `'._DB_PREFIX_.'group` g LEFT JOIN `'._DB_PREFIX_.'group_lang` gl ON (g.`id_group` = gl.`id_group`) WHERE `name` = \''.pSQL($query).'\' '); - } -} \ No newline at end of file + } +} diff --git a/classes/GroupReduction.php b/classes/GroupReduction.php index 1261d170..9959364d 100644 --- a/classes/GroupReduction.php +++ b/classes/GroupReduction.php @@ -26,239 +26,245 @@ class GroupReductionCore extends ObjectModel { - public $id_group; - public $id_category; - public $reduction; + public $id_group; + public $id_category; + public $reduction; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'group_reduction', - 'primary' => 'id_group_reduction', - 'fields' => array( - 'id_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_category' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'reduction' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'group_reduction', + 'primary' => 'id_group_reduction', + 'fields' => array( + 'id_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_category' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'reduction' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + ), + ); - protected static $reduction_cache = array(); + protected static $reduction_cache = array(); - public function add($autodate = true, $null_values = false) - { - return (parent::add($autodate, $null_values) && $this->_setCache()); - } + public function add($autodate = true, $null_values = false) + { + return (parent::add($autodate, $null_values) && $this->_setCache()); + } - public function update($null_values = false) - { - return (parent::update($null_values) && $this->_updateCache()); - } + public function update($null_values = false) + { + return (parent::update($null_values) && $this->_updateCache()); + } - public function delete() - { - $products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public function delete() + { + $products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT cp.`id_product` FROM `'._DB_PREFIX_.'category_product` cp WHERE cp.`id_category` = '.(int)$this->id_category - ); + ); - $ids = array(); - foreach ($products as $row) - $ids[] = $row['id_product']; + $ids = array(); + foreach ($products as $row) { + $ids[] = $row['id_product']; + } - if ($ids) - Db::getInstance()->delete('product_group_reduction_cache', 'id_product IN ('.implode(', ', $ids).')'); - return (parent::delete()); - } + if ($ids) { + Db::getInstance()->delete('product_group_reduction_cache', 'id_product IN ('.implode(', ', $ids).')'); + } + return (parent::delete()); + } - protected function _clearCache() - { - return Db::getInstance()->delete('product_group_reduction_cache', 'id_group = '.(int)$this->id_group); - } + protected function _clearCache() + { + return Db::getInstance()->delete('product_group_reduction_cache', 'id_group = '.(int)$this->id_group); + } - protected function _setCache() - { - $products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + protected function _setCache() + { + $products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT cp.`id_product` FROM `'._DB_PREFIX_.'category_product` cp WHERE cp.`id_category` = '.(int)$this->id_category - ); + ); - $values = array(); - foreach ($products as $row) - $values[] = '('.(int)$row['id_product'].', '.(int)$this->id_group.', '.(float)$this->reduction.')'; + $values = array(); + foreach ($products as $row) { + $values[] = '('.(int)$row['id_product'].', '.(int)$this->id_group.', '.(float)$this->reduction.')'; + } - if (count($values)) - { - $query = 'INSERT INTO `'._DB_PREFIX_.'product_group_reduction_cache` (`id_product`, `id_group`, `reduction`) + if (count($values)) { + $query = 'INSERT INTO `'._DB_PREFIX_.'product_group_reduction_cache` (`id_product`, `id_group`, `reduction`) VALUES '.implode(', ', $values).' ON DUPLICATE KEY UPDATE `reduction` = IF(VALUES(`reduction`) > `reduction`, VALUES(`reduction`), `reduction`)'; - return (Db::getInstance()->execute($query)); - } + return (Db::getInstance()->execute($query)); + } - return true; - } + return true; + } - protected function _updateCache() - { - $products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + protected function _updateCache() + { + $products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT cp.`id_product` FROM `'._DB_PREFIX_.'category_product` cp WHERE cp.`id_category` = '.(int)$this->id_category, - false); + false); - $ids = array(); - foreach ($products as $product) - $ids[] = $product['id_product']; + $ids = array(); + foreach ($products as $product) { + $ids[] = $product['id_product']; + } - $result = true; - if ($ids) - $result &= Db::getInstance()->update('product_group_reduction_cache', array( - 'reduction' => (float)$this->reduction, - ), 'id_product IN('.implode(', ', $ids).') AND id_group = '.(int)$this->id_group); + $result = true; + if ($ids) { + $result &= Db::getInstance()->update('product_group_reduction_cache', array( + 'reduction' => (float)$this->reduction, + ), 'id_product IN('.implode(', ', $ids).') AND id_group = '.(int)$this->id_group); + } - return $result; - } + return $result; + } - public static function getGroupReductions($id_group, $id_lang) - { - $lang = $id_lang.Shop::addSqlRestrictionOnLang('cl'); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getGroupReductions($id_group, $id_lang) + { + $lang = $id_lang.Shop::addSqlRestrictionOnLang('cl'); + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT gr.`id_group_reduction`, gr.`id_group`, gr.`id_category`, gr.`reduction`, cl.`name` AS category_name FROM `'._DB_PREFIX_.'group_reduction` gr LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (cl.`id_category` = gr.`id_category` AND cl.`id_lang` = '.(int)$lang.') WHERE `id_group` = '.(int)$id_group - ); - } + ); + } - public static function getValueForProduct($id_product, $id_group) - { - if (!Group::isFeatureActive()) - return 0; + public static function getValueForProduct($id_product, $id_group) + { + if (!Group::isFeatureActive()) { + return 0; + } - if (!isset(self::$reduction_cache[$id_product.'-'.$id_group])) - self::$reduction_cache[$id_product.'-'.$id_group] = Db::getInstance()->getValue(' + if (!isset(self::$reduction_cache[$id_product.'-'.$id_group])) { + self::$reduction_cache[$id_product.'-'.$id_group] = Db::getInstance()->getValue(' SELECT `reduction` FROM `'._DB_PREFIX_.'product_group_reduction_cache` WHERE `id_product` = '.(int)$id_product.' AND `id_group` = '.(int)$id_group); - // Should return string (decimal in database) and not a float - return self::$reduction_cache[$id_product.'-'.$id_group]; - } + } + // Should return string (decimal in database) and not a float + return self::$reduction_cache[$id_product.'-'.$id_group]; + } - public static function doesExist($id_group, $id_category) - { - return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function doesExist($id_group, $id_category) + { + return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_group` FROM `'._DB_PREFIX_.'group_reduction` WHERE `id_group` = '.(int)$id_group.' AND `id_category` = '.(int)$id_category); - } + } - public static function getGroupsByCategoryId($id_category) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getGroupsByCategoryId($id_category) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT gr.`id_group` as id_group, gr.`reduction` as reduction, id_group_reduction FROM `'._DB_PREFIX_.'group_reduction` gr WHERE `id_category` = '.(int)$id_category - ); - } + ); + } - /** - * @deprecated 1.5.3.0 - * @param int $id_category - * @return array|null - */ - public static function getGroupByCategoryId($id_category) - { - Tools::displayAsDeprecated('Use GroupReduction::getGroupsByCategoryId($id_category)'); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + /** + * @deprecated 1.5.3.0 + * @param int $id_category + * @return array|null + */ + public static function getGroupByCategoryId($id_category) + { + Tools::displayAsDeprecated('Use GroupReduction::getGroupsByCategoryId($id_category)'); + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT gr.`id_group` as id_group, gr.`reduction` as reduction, id_group_reduction FROM `'._DB_PREFIX_.'group_reduction` gr - WHERE `id_category` = '.(int)$id_category - , false); - } + WHERE `id_category` = '.(int)$id_category, false); + } - public static function getGroupsReductionByCategoryId($id_category) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getGroupsReductionByCategoryId($id_category) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT gr.`id_group_reduction` as id_group_reduction, id_group FROM `'._DB_PREFIX_.'group_reduction` gr WHERE `id_category` = '.(int)$id_category - ); - } + ); + } - /** - * @deprecated 1.5.3.0 - * @param int $id_category - * @return array|null - */ - public static function getGroupReductionByCategoryId($id_category) - { - Tools::displayAsDeprecated('Use GroupReduction::getGroupsByCategoryId($id_category)'); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + /** + * @deprecated 1.5.3.0 + * @param int $id_category + * @return array|null + */ + public static function getGroupReductionByCategoryId($id_category) + { + Tools::displayAsDeprecated('Use GroupReduction::getGroupsByCategoryId($id_category)'); + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT gr.`id_group_reduction` as id_group_reduction FROM `'._DB_PREFIX_.'group_reduction` gr - WHERE `id_category` = '.(int)$id_category - , false); - } + WHERE `id_category` = '.(int)$id_category, false); + } - public static function setProductReduction($id_product, $id_group = null, $id_category = null, $reduction = null) - { - $res = true; - GroupReduction::deleteProductReduction((int)$id_product); + public static function setProductReduction($id_product, $id_group = null, $id_category = null, $reduction = null) + { + $res = true; + GroupReduction::deleteProductReduction((int)$id_product); - $categories = Product::getProductCategories((int)$id_product); + $categories = Product::getProductCategories((int)$id_product); - if ($categories) - foreach ($categories as $category) - { - $reductions = GroupReduction::getGroupsByCategoryId((int)$category); - if ($reductions) - foreach ($reductions as $reduction) - { - $current_group_reduction = new GroupReduction((int)$reduction['id_group_reduction']); - $res &= $current_group_reduction->_setCache(); - } - } + if ($categories) { + foreach ($categories as $category) { + $reductions = GroupReduction::getGroupsByCategoryId((int)$category); + if ($reductions) { + foreach ($reductions as $reduction) { + $current_group_reduction = new GroupReduction((int)$reduction['id_group_reduction']); + $res &= $current_group_reduction->_setCache(); + } + } + } + } - return $res; - } + return $res; + } - public static function deleteProductReduction($id_product) - { - $query = 'DELETE FROM `'._DB_PREFIX_.'product_group_reduction_cache` WHERE `id_product` = '.(int)$id_product; - if (Db::getInstance()->execute($query) === false) - return false; - return true; - } + public static function deleteProductReduction($id_product) + { + $query = 'DELETE FROM `'._DB_PREFIX_.'product_group_reduction_cache` WHERE `id_product` = '.(int)$id_product; + if (Db::getInstance()->execute($query) === false) { + return false; + } + return true; + } - public static function duplicateReduction($id_product_old, $id_product) - { - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executes(' + public static function duplicateReduction($id_product_old, $id_product) + { + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executes(' SELECT pgr.`id_product`, pgr.`id_group`, pgr.`reduction` FROM `'._DB_PREFIX_.'product_group_reduction_cache` pgr WHERE pgr.`id_product` = '.(int)$id_product_old - ); + ); - if (!$res) - return true; + if (!$res) { + return true; + } - $query = ''; + $query = ''; - foreach ($res as $row) - { - $query .= 'INSERT INTO `'._DB_PREFIX_.'product_group_reduction_cache` (`id_product`, `id_group`, `reduction`) VALUES '; - $query .= '('.(int)$id_product.', '.(int)$row['id_group'].', '.(float)$row['reduction'].') ON DUPLICATE KEY UPDATE `reduction` = '.(float)$row['reduction'].';'; - } + foreach ($res as $row) { + $query .= 'INSERT INTO `'._DB_PREFIX_.'product_group_reduction_cache` (`id_product`, `id_group`, `reduction`) VALUES '; + $query .= '('.(int)$id_product.', '.(int)$row['id_group'].', '.(float)$row['reduction'].') ON DUPLICATE KEY UPDATE `reduction` = '.(float)$row['reduction'].';'; + } - return Db::getInstance()->execute($query); - } + return Db::getInstance()->execute($query); + } - public static function deleteCategory($id_category) - { - $query = 'DELETE FROM `'._DB_PREFIX_.'group_reduction` WHERE `id_category` = '.(int)$id_category; - if (Db::getInstance()->Execute($query) === false) - return false; - return true; - } + public static function deleteCategory($id_category) + { + $query = 'DELETE FROM `'._DB_PREFIX_.'group_reduction` WHERE `id_category` = '.(int)$id_category; + if (Db::getInstance()->Execute($query) === false) { + return false; + } + return true; + } } diff --git a/classes/Guest.php b/classes/Guest.php index b2d33f90..73ca3fe0 100644 --- a/classes/Guest.php +++ b/classes/Guest.php @@ -26,169 +26,171 @@ class GuestCore extends ObjectModel { - public $id_operating_system; - public $id_web_browser; - public $id_customer; - public $javascript; - public $screen_resolution_x; - public $screen_resolution_y; - public $screen_color; - public $sun_java; - public $adobe_flash; - public $adobe_director; - public $apple_quicktime; - public $real_player; - public $windows_media; - public $accept_language; - public $mobile_theme; + public $id_operating_system; + public $id_web_browser; + public $id_customer; + public $javascript; + public $screen_resolution_x; + public $screen_resolution_y; + public $screen_color; + public $sun_java; + public $adobe_flash; + public $adobe_director; + public $apple_quicktime; + public $real_player; + public $windows_media; + public $accept_language; + public $mobile_theme; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'guest', - 'primary' => 'id_guest', - 'fields' => array( - 'id_operating_system' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_web_browser' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'javascript' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'screen_resolution_x' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'screen_resolution_y' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'screen_color' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'sun_java' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'adobe_flash' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'adobe_director' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'apple_quicktime' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'real_player' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'windows_media' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'accept_language' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 8), - 'mobile_theme' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'guest', + 'primary' => 'id_guest', + 'fields' => array( + 'id_operating_system' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_web_browser' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'javascript' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'screen_resolution_x' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'screen_resolution_y' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'screen_color' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'sun_java' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'adobe_flash' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'adobe_director' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'apple_quicktime' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'real_player' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'windows_media' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'accept_language' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 8), + 'mobile_theme' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_customer' => array('xlink_resource' => 'customers'), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_customer' => array('xlink_resource' => 'customers'), + ), + ); - public function userAgent() - { - $userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; - $acceptLanguage = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : ''; - $this->accept_language = $this->getLanguage($acceptLanguage); - $this->id_operating_system = $this->getOs($userAgent); - $this->id_web_browser = $this->getBrowser($userAgent); - $this->mobile_theme = Context::getContext()->getMobileDevice(); - } + public function userAgent() + { + $userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; + $acceptLanguage = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : ''; + $this->accept_language = $this->getLanguage($acceptLanguage); + $this->id_operating_system = $this->getOs($userAgent); + $this->id_web_browser = $this->getBrowser($userAgent); + $this->mobile_theme = Context::getContext()->getMobileDevice(); + } - protected function getLanguage($acceptLanguage) - { - // $langsArray is filled with all the languages accepted, ordered by priority - $langsArray = array(); - preg_match_all('/([a-z]{2}(-[a-z]{2})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/', $acceptLanguage, $array); - if (count($array[1])) - { - $langsArray = array_combine($array[1], $array[4]); - foreach ($langsArray as $lang => $val) - if ($val === '') - $langsArray[$lang] = 1; - arsort($langsArray, SORT_NUMERIC); - } + protected function getLanguage($acceptLanguage) + { + // $langsArray is filled with all the languages accepted, ordered by priority + $langsArray = array(); + preg_match_all('/([a-z]{2}(-[a-z]{2})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/', $acceptLanguage, $array); + if (count($array[1])) { + $langsArray = array_combine($array[1], $array[4]); + foreach ($langsArray as $lang => $val) { + if ($val === '') { + $langsArray[$lang] = 1; + } + } + arsort($langsArray, SORT_NUMERIC); + } - // Only the first language is returned - return (count($langsArray) ? key($langsArray) : ''); - } + // Only the first language is returned + return (count($langsArray) ? key($langsArray) : ''); + } - protected function getBrowser($userAgent) - { - $browserArray = array( - 'Chrome' => 'Chrome/', - 'Safari' => 'Safari', - 'Safari iPad' => 'iPad', - 'Firefox' => 'Firefox/', - 'Opera' => 'Opera', - 'IE 11' => 'Trident', - 'IE 10' => 'MSIE 10', - 'IE 9' => 'MSIE 9', - 'IE 8' => 'MSIE 8', - 'IE 7' => 'MSIE 7', - 'IE 6' => 'MSIE 6' - ); - foreach ($browserArray as $k => $value) - if (strstr($userAgent, $value)) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + protected function getBrowser($userAgent) + { + $browserArray = array( + 'Chrome' => 'Chrome/', + 'Safari' => 'Safari', + 'Safari iPad' => 'iPad', + 'Firefox' => 'Firefox/', + 'Opera' => 'Opera', + 'IE 11' => 'Trident', + 'IE 10' => 'MSIE 10', + 'IE 9' => 'MSIE 9', + 'IE 8' => 'MSIE 8', + 'IE 7' => 'MSIE 7', + 'IE 6' => 'MSIE 6' + ); + foreach ($browserArray as $k => $value) { + if (strstr($userAgent, $value)) { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT `id_web_browser` FROM `'._DB_PREFIX_.'web_browser` wb WHERE wb.`name` = \''.pSQL($k).'\''); - return $result['id_web_browser']; - } - return null; - } + return $result['id_web_browser']; + } + } + return null; + } - protected function getOs($userAgent) - { - $osArray = array( - 'Windows 8' => 'Windows NT 6.2', - 'Windows 7' => 'Windows NT 6.1', - 'Windows Vista' => 'Windows NT 6.0', - 'Windows XP' => 'Windows NT 5', - 'MacOsX' => 'Mac OS X', - 'Android' => 'Android', - 'Linux' => 'X11' - ); + protected function getOs($userAgent) + { + $osArray = array( + 'Windows 8' => 'Windows NT 6.2', + 'Windows 7' => 'Windows NT 6.1', + 'Windows Vista' => 'Windows NT 6.0', + 'Windows XP' => 'Windows NT 5', + 'MacOsX' => 'Mac OS X', + 'Android' => 'Android', + 'Linux' => 'X11' + ); - foreach ($osArray as $k => $value) - if (strstr($userAgent, $value)) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + foreach ($osArray as $k => $value) { + if (strstr($userAgent, $value)) { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT `id_operating_system` FROM `'._DB_PREFIX_.'operating_system` os WHERE os.`name` = \''.pSQL($k).'\''); - return $result['id_operating_system']; - } - return null; - } + return $result['id_operating_system']; + } + } + return null; + } - public static function getFromCustomer($id_customer) - { - if (!Validate::isUnsignedId($id_customer)) - return false; - $result = Db::getInstance()->getRow(' + public static function getFromCustomer($id_customer) + { + if (!Validate::isUnsignedId($id_customer)) { + return false; + } + $result = Db::getInstance()->getRow(' SELECT `id_guest` FROM `'._DB_PREFIX_.'guest` WHERE `id_customer` = '.(int)($id_customer)); - return $result['id_guest']; - } + return $result['id_guest']; + } - public function mergeWithCustomer($id_guest, $id_customer) - { - // Since the guests are merged, the guest id in the connections table must be changed too - Db::getInstance()->execute(' + public function mergeWithCustomer($id_guest, $id_customer) + { + // Since the guests are merged, the guest id in the connections table must be changed too + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'connections` c SET c.`id_guest` = '.(int)($id_guest).' WHERE c.`id_guest` = '.(int)($this->id)); - // The current guest is removed from the database - $this->delete(); + // The current guest is removed from the database + $this->delete(); - // $this is still filled with values, so it's id is changed for the old guest - $this->id = (int)($id_guest); - $this->id_customer = (int)($id_customer); + // $this is still filled with values, so it's id is changed for the old guest + $this->id = (int)($id_guest); + $this->id_customer = (int)($id_customer); - // $this is now the old guest but filled with the most up to date values - $this->update(); - } + // $this is now the old guest but filled with the most up to date values + $this->update(); + } - public static function setNewGuest($cookie) - { - $guest = new Guest(isset($cookie->id_customer) ? Guest::getFromCustomer((int)($cookie->id_customer)) : null); - $guest->userAgent(); - $guest->save(); - $cookie->id_guest = (int)($guest->id); - } -} \ No newline at end of file + public static function setNewGuest($cookie) + { + $guest = new Guest(isset($cookie->id_customer) ? Guest::getFromCustomer((int)($cookie->id_customer)) : null); + $guest->userAgent(); + $guest->save(); + $cookie->id_guest = (int)($guest->id); + } +} diff --git a/classes/Hook.php b/classes/Hook.php index fa7cc4c2..67fc631d 100644 --- a/classes/Hook.php +++ b/classes/Hook.php @@ -26,816 +26,836 @@ class HookCore extends ObjectModel { - /** - * @var string Hook name identifier - */ - public $name; + /** + * @var string Hook name identifier + */ + public $name; - /** - * @var string Hook title (displayed in BO) - */ - public $title; + /** + * @var string Hook title (displayed in BO) + */ + public $title; - /** - * @var string Hook description - */ - public $description; + /** + * @var string Hook description + */ + public $description; - /** - * @var bool - */ - public $position = false; + /** + * @var bool + */ + public $position = false; - /** - * @var bool Is this hook usable with live edit ? - */ - public $live_edit = false; + /** + * @var bool Is this hook usable with live edit ? + */ + public $live_edit = false; - /** - * @var array List of executed hooks on this page - */ - public static $executed_hooks = array(); + /** + * @var array List of executed hooks on this page + */ + public static $executed_hooks = array(); - public static $native_module; + public static $native_module; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'hook', - 'primary' => 'id_hook', - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isHookName', 'required' => true, 'size' => 64), - 'title' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'), - 'description' => array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'), - 'position' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'live_edit' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'hook', + 'primary' => 'id_hook', + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isHookName', 'required' => true, 'size' => 64), + 'title' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'), + 'description' => array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'), + 'position' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'live_edit' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + ), + ); - /** - * @deprecated 1.5.0 - */ - protected static $_hook_modules_cache = null; + /** + * @deprecated 1.5.0 + */ + protected static $_hook_modules_cache = null; - /** - * @deprecated 1.5.0 - */ - protected static $_hook_modules_cache_exec = null; + /** + * @deprecated 1.5.0 + */ + protected static $_hook_modules_cache_exec = null; - public function add($autodate = true, $null_values = false) - { - Cache::clean('hook_idsbyname'); - return parent::add($autodate, $null_values); - } + public function add($autodate = true, $null_values = false) + { + Cache::clean('hook_idsbyname'); + return parent::add($autodate, $null_values); + } - /** - * Return Hooks List - * - * @param bool $position - * @return array Hooks List - */ - public static function getHooks($position = false) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * Return Hooks List + * + * @param bool $position + * @return array Hooks List + */ + public static function getHooks($position = false) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'hook` h '.($position ? 'WHERE h.`position` = 1' : '').' ORDER BY `name`' - ); - } + ); + } - /** - * Return hook ID from name - * - * @param string $hook_name Hook name - * @return int Hook ID - */ - public static function getIdByName($hook_name) - { - $hook_name = strtolower($hook_name); - if (!Validate::isHookName($hook_name)) - return false; + /** + * Return hook ID from name + * + * @param string $hook_name Hook name + * @return int Hook ID + */ + public static function getIdByName($hook_name) + { + $hook_name = strtolower($hook_name); + if (!Validate::isHookName($hook_name)) { + return false; + } - $cache_id = 'hook_idsbyname'; - if (!Cache::isStored($cache_id)) - { - // Get all hook ID by name and alias - $hook_ids = array(); - $db = Db::getInstance(); - $result = $db->ExecuteS(' + $cache_id = 'hook_idsbyname'; + if (!Cache::isStored($cache_id)) { + // Get all hook ID by name and alias + $hook_ids = array(); + $db = Db::getInstance(); + $result = $db->ExecuteS(' SELECT `id_hook`, `name` FROM `'._DB_PREFIX_.'hook` UNION SELECT `id_hook`, ha.`alias` as name FROM `'._DB_PREFIX_.'hook_alias` ha INNER JOIN `'._DB_PREFIX_.'hook` h ON ha.name = h.name', false); - while ($row = $db->nextRow($result)) - $hook_ids[strtolower($row['name'])] = $row['id_hook']; - Cache::store($cache_id, $hook_ids); - } - else - $hook_ids = Cache::retrieve($cache_id); + while ($row = $db->nextRow($result)) { + $hook_ids[strtolower($row['name'])] = $row['id_hook']; + } + Cache::store($cache_id, $hook_ids); + } else { + $hook_ids = Cache::retrieve($cache_id); + } - return (isset($hook_ids[$hook_name]) ? $hook_ids[$hook_name] : false); - } + return (isset($hook_ids[$hook_name]) ? $hook_ids[$hook_name] : false); + } - /** - * Return hook ID from name - */ - public static function getNameById($hook_id) - { - $cache_id = 'hook_namebyid_'.$hook_id; - if (!Cache::isStored($cache_id)) - { - $result = Db::getInstance()->getValue(' + /** + * Return hook ID from name + */ + public static function getNameById($hook_id) + { + $cache_id = 'hook_namebyid_'.$hook_id; + if (!Cache::isStored($cache_id)) { + $result = Db::getInstance()->getValue(' SELECT `name` FROM `'._DB_PREFIX_.'hook` WHERE `id_hook` = '.(int)$hook_id); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Return hook live edit bool from ID - */ - public static function getLiveEditById($hook_id) { - $cache_id = 'hook_live_editbyid_'.$hook_id; - if (!Cache::isStored($cache_id)) - { - $result = Db::getInstance()->getValue(' + /** + * Return hook live edit bool from ID + */ + public static function getLiveEditById($hook_id) + { + $cache_id = 'hook_live_editbyid_'.$hook_id; + if (!Cache::isStored($cache_id)) { + $result = Db::getInstance()->getValue(' SELECT `live_edit` FROM `'._DB_PREFIX_.'hook` WHERE `id_hook` = '.(int)$hook_id); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Get list of hook alias - * - * @since 1.5.0 - * @return array - */ - public static function getHookAliasList() - { - $cache_id = 'hook_alias'; - if (!Cache::isStored($cache_id)) - { - $hook_alias_list = Db::getInstance()->executeS('SELECT * FROM `'._DB_PREFIX_.'hook_alias`'); - $hook_alias = array(); - if ($hook_alias_list) - foreach ($hook_alias_list as $ha) - $hook_alias[strtolower($ha['alias'])] = $ha['name']; - Cache::store($cache_id, $hook_alias); - return $hook_alias; - } - return Cache::retrieve($cache_id); - } + /** + * Get list of hook alias + * + * @since 1.5.0 + * @return array + */ + public static function getHookAliasList() + { + $cache_id = 'hook_alias'; + if (!Cache::isStored($cache_id)) { + $hook_alias_list = Db::getInstance()->executeS('SELECT * FROM `'._DB_PREFIX_.'hook_alias`'); + $hook_alias = array(); + if ($hook_alias_list) { + foreach ($hook_alias_list as $ha) { + $hook_alias[strtolower($ha['alias'])] = $ha['name']; + } + } + Cache::store($cache_id, $hook_alias); + return $hook_alias; + } + return Cache::retrieve($cache_id); + } - /** - * Return backward compatibility hook name - * - * @since 1.5.0 - * @param string $hook_name Hook name - * @return int Hook ID - */ - public static function getRetroHookName($hook_name) - { - $alias_list = Hook::getHookAliasList(); - if (isset($alias_list[strtolower($hook_name)])) - return $alias_list[strtolower($hook_name)]; + /** + * Return backward compatibility hook name + * + * @since 1.5.0 + * @param string $hook_name Hook name + * @return int Hook ID + */ + public static function getRetroHookName($hook_name) + { + $alias_list = Hook::getHookAliasList(); + if (isset($alias_list[strtolower($hook_name)])) { + return $alias_list[strtolower($hook_name)]; + } - $retro_hook_name = array_search($hook_name, $alias_list); - if ($retro_hook_name === false) - return ''; - return $retro_hook_name; - } + $retro_hook_name = array_search($hook_name, $alias_list); + if ($retro_hook_name === false) { + return ''; + } + return $retro_hook_name; + } - /** - * Get list of all registered hooks with modules - * - * @since 1.5.0 - * @return array - */ - public static function getHookModuleList() - { - $cache_id = 'hook_module_list'; - if (!Cache::isStored($cache_id)) - { - $results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * Get list of all registered hooks with modules + * + * @since 1.5.0 + * @return array + */ + public static function getHookModuleList() + { + $cache_id = 'hook_module_list'; + if (!Cache::isStored($cache_id)) { + $results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT h.id_hook, h.name as h_name, title, description, h.position, live_edit, hm.position as hm_position, m.id_module, m.name, active FROM `'._DB_PREFIX_.'hook_module` hm STRAIGHT_JOIN `'._DB_PREFIX_.'hook` h ON (h.id_hook = hm.id_hook AND hm.id_shop = '.(int)Context::getContext()->shop->id.') STRAIGHT_JOIN `'._DB_PREFIX_.'module` as m ON (m.id_module = hm.id_module) ORDER BY hm.position'); - $list = array(); - foreach ($results as $result) - { - if (!isset($list[$result['id_hook']])) - $list[$result['id_hook']] = array(); + $list = array(); + foreach ($results as $result) { + if (!isset($list[$result['id_hook']])) { + $list[$result['id_hook']] = array(); + } - $list[$result['id_hook']][$result['id_module']] = array( - 'id_hook' => $result['id_hook'], - 'title' => $result['title'], - 'description' => $result['description'], - 'hm.position' => $result['position'], - 'live_edit' => $result['live_edit'], - 'm.position' => $result['hm_position'], - 'id_module' => $result['id_module'], - 'name' => $result['name'], - 'active' => $result['active'], - ); - } - Cache::store($cache_id, $list); + $list[$result['id_hook']][$result['id_module']] = array( + 'id_hook' => $result['id_hook'], + 'title' => $result['title'], + 'description' => $result['description'], + 'hm.position' => $result['position'], + 'live_edit' => $result['live_edit'], + 'm.position' => $result['hm_position'], + 'id_module' => $result['id_module'], + 'name' => $result['name'], + 'active' => $result['active'], + ); + } + Cache::store($cache_id, $list); - // @todo remove this in 1.6, we keep it in 1.5 for retrocompatibility - Hook::$_hook_modules_cache = $list; - return $list; - } + // @todo remove this in 1.6, we keep it in 1.5 for retrocompatibility + Hook::$_hook_modules_cache = $list; + return $list; + } - return Cache::retrieve($cache_id); - } + return Cache::retrieve($cache_id); + } - /** - * Return Hooks List - * - * @since 1.5.0 - * @param int $id_hook - * @param int $id_module - * @return array Modules List - */ - public static function getModulesFromHook($id_hook, $id_module = null) - { - $hm_list = Hook::getHookModuleList(); - $module_list = (isset($hm_list[$id_hook])) ? $hm_list[$id_hook] : array(); + /** + * Return Hooks List + * + * @since 1.5.0 + * @param int $id_hook + * @param int $id_module + * @return array Modules List + */ + public static function getModulesFromHook($id_hook, $id_module = null) + { + $hm_list = Hook::getHookModuleList(); + $module_list = (isset($hm_list[$id_hook])) ? $hm_list[$id_hook] : array(); - if ($id_module) - return (isset($module_list[$id_module])) ? array($module_list[$id_module]) : array(); - return $module_list; - } + if ($id_module) { + return (isset($module_list[$id_module])) ? array($module_list[$id_module]) : array(); + } + return $module_list; + } - /** - * Get list of modules we can execute per hook - * - * @since 1.5.0 - * @param string $hook_name Get list of modules for this hook if given - * @return array - */ - public static function getHookModuleExecList($hook_name = null) - { - $context = Context::getContext(); - $cache_id = 'hook_module_exec_list_'.(isset($context->shop->id) ? '_'.$context->shop->id : '' ).((isset($context->customer)) ? '_'.$context->customer->id : ''); - if (!Cache::isStored($cache_id) || $hook_name == 'displayPayment' || $hook_name == 'displayBackOfficeHeader') - { - $frontend = true; - $groups = array(); - $use_groups = Group::isFeatureActive(); - if (isset($context->employee)) - $frontend = false; - else - { - // Get groups list - if ($use_groups) - { - if (isset($context->customer) && $context->customer->isLogged()) - $groups = $context->customer->getGroups(); - elseif (isset($context->customer) && $context->customer->isLogged(true)) - $groups = array((int)Configuration::get('PS_GUEST_GROUP')); - else - $groups = array((int)Configuration::get('PS_UNIDENTIFIED_GROUP')); - } - } + /** + * Get list of modules we can execute per hook + * + * @since 1.5.0 + * @param string $hook_name Get list of modules for this hook if given + * @return array + */ + public static function getHookModuleExecList($hook_name = null) + { + $context = Context::getContext(); + $cache_id = 'hook_module_exec_list_'.(isset($context->shop->id) ? '_'.$context->shop->id : '').((isset($context->customer)) ? '_'.$context->customer->id : ''); + if (!Cache::isStored($cache_id) || $hook_name == 'displayPayment' || $hook_name == 'displayBackOfficeHeader') { + $frontend = true; + $groups = array(); + $use_groups = Group::isFeatureActive(); + if (isset($context->employee)) { + $frontend = false; + } else { + // Get groups list + if ($use_groups) { + if (isset($context->customer) && $context->customer->isLogged()) { + $groups = $context->customer->getGroups(); + } elseif (isset($context->customer) && $context->customer->isLogged(true)) { + $groups = array((int)Configuration::get('PS_GUEST_GROUP')); + } else { + $groups = array((int)Configuration::get('PS_UNIDENTIFIED_GROUP')); + } + } + } - // SQL Request - $sql = new DbQuery(); - $sql->select('h.`name` as hook, m.`id_module`, h.`id_hook`, m.`name` as module, h.`live_edit`'); - $sql->from('module', 'm'); - if ($hook_name != 'displayBackOfficeHeader') - { - $sql->join(Shop::addSqlAssociation('module', 'm', true, 'module_shop.enable_device & '.(int)Context::getContext()->getDevice())); - $sql->innerJoin('module_shop', 'ms', 'ms.`id_module` = m.`id_module`'); - } - $sql->innerJoin('hook_module', 'hm', 'hm.`id_module` = m.`id_module`'); - $sql->innerJoin('hook', 'h', 'hm.`id_hook` = h.`id_hook`'); - if ($hook_name != 'displayPayment') - $sql->where('h.name != "displayPayment"'); - // For payment modules, we check that they are available in the contextual country - elseif ($frontend) - { - if (Validate::isLoadedObject($context->country)) - $sql->where('(h.name = "displayPayment" AND (SELECT id_country FROM '._DB_PREFIX_.'module_country mc WHERE mc.id_module = m.id_module AND id_country = '.(int)$context->country->id.' AND id_shop = '.(int)$context->shop->id.' LIMIT 1) = '.(int)$context->country->id.')'); - if (Validate::isLoadedObject($context->currency)) - $sql->where('(h.name = "displayPayment" AND (SELECT id_currency FROM '._DB_PREFIX_.'module_currency mcr WHERE mcr.id_module = m.id_module AND id_currency IN ('.(int)$context->currency->id.', -1, -2) LIMIT 1) IN ('.(int)$context->currency->id.', -1, -2))'); - } - if (Validate::isLoadedObject($context->shop)) - $sql->where('hm.id_shop = '.(int)$context->shop->id); + // SQL Request + $sql = new DbQuery(); + $sql->select('h.`name` as hook, m.`id_module`, h.`id_hook`, m.`name` as module, h.`live_edit`'); + $sql->from('module', 'm'); + if ($hook_name != 'displayBackOfficeHeader') { + $sql->join(Shop::addSqlAssociation('module', 'm', true, 'module_shop.enable_device & '.(int)Context::getContext()->getDevice())); + $sql->innerJoin('module_shop', 'ms', 'ms.`id_module` = m.`id_module`'); + } + $sql->innerJoin('hook_module', 'hm', 'hm.`id_module` = m.`id_module`'); + $sql->innerJoin('hook', 'h', 'hm.`id_hook` = h.`id_hook`'); + if ($hook_name != 'displayPayment') { + $sql->where('h.name != "displayPayment"'); + } + // For payment modules, we check that they are available in the contextual country + elseif ($frontend) { + if (Validate::isLoadedObject($context->country)) { + $sql->where('(h.name = "displayPayment" AND (SELECT id_country FROM '._DB_PREFIX_.'module_country mc WHERE mc.id_module = m.id_module AND id_country = '.(int)$context->country->id.' AND id_shop = '.(int)$context->shop->id.' LIMIT 1) = '.(int)$context->country->id.')'); + } + if (Validate::isLoadedObject($context->currency)) { + $sql->where('(h.name = "displayPayment" AND (SELECT id_currency FROM '._DB_PREFIX_.'module_currency mcr WHERE mcr.id_module = m.id_module AND id_currency IN ('.(int)$context->currency->id.', -1, -2) LIMIT 1) IN ('.(int)$context->currency->id.', -1, -2))'); + } + } + if (Validate::isLoadedObject($context->shop)) { + $sql->where('hm.id_shop = '.(int)$context->shop->id); + } - if ($frontend) - { - if ($use_groups) - { - $sql->leftJoin('module_group', 'mg', 'mg.`id_module` = m.`id_module`'); - if (Validate::isLoadedObject($context->shop)) - $sql->where('mg.id_shop = '.((int)$context->shop->id).(count($groups) ? ' AND mg.`id_group` IN ('.implode(', ', $groups).')' : '')); - elseif (count($groups)) - $sql->where('mg.`id_group` IN ('.implode(', ', $groups).')'); - } - } + if ($frontend) { + if ($use_groups) { + $sql->leftJoin('module_group', 'mg', 'mg.`id_module` = m.`id_module`'); + if (Validate::isLoadedObject($context->shop)) { + $sql->where('mg.id_shop = '.((int)$context->shop->id).(count($groups) ? ' AND mg.`id_group` IN ('.implode(', ', $groups).')' : '')); + } elseif (count($groups)) { + $sql->where('mg.`id_group` IN ('.implode(', ', $groups).')'); + } + } + } - $sql->groupBy('hm.id_hook, hm.id_module'); - $sql->orderBy('hm.`position`'); + $sql->groupBy('hm.id_hook, hm.id_module'); + $sql->orderBy('hm.`position`'); - $list = array(); - if ($result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql)) - foreach ($result as $row) - { - $row['hook'] = strtolower($row['hook']); - if (!isset($list[$row['hook']])) - $list[$row['hook']] = array(); + $list = array(); + if ($result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql)) { + foreach ($result as $row) { + $row['hook'] = strtolower($row['hook']); + if (!isset($list[$row['hook']])) { + $list[$row['hook']] = array(); + } - $list[$row['hook']][] = array( - 'id_hook' => $row['id_hook'], - 'module' => $row['module'], - 'id_module' => $row['id_module'], - 'live_edit' => $row['live_edit'], - ); - } - if ($hook_name != 'displayPayment' && $hook_name != 'displayBackOfficeHeader') - { - Cache::store($cache_id, $list); - // @todo remove this in 1.6, we keep it in 1.5 for backward compatibility - self::$_hook_modules_cache_exec = $list; - } - } - else - $list = Cache::retrieve($cache_id); + $list[$row['hook']][] = array( + 'id_hook' => $row['id_hook'], + 'module' => $row['module'], + 'id_module' => $row['id_module'], + 'live_edit' => $row['live_edit'], + ); + } + } + if ($hook_name != 'displayPayment' && $hook_name != 'displayBackOfficeHeader') { + Cache::store($cache_id, $list); + // @todo remove this in 1.6, we keep it in 1.5 for backward compatibility + self::$_hook_modules_cache_exec = $list; + } + } else { + $list = Cache::retrieve($cache_id); + } - // If hook_name is given, just get list of modules for this hook - if ($hook_name) - { - $retro_hook_name = strtolower(Hook::getRetroHookName($hook_name)); - $hook_name = strtolower($hook_name); + // If hook_name is given, just get list of modules for this hook + if ($hook_name) { + $retro_hook_name = strtolower(Hook::getRetroHookName($hook_name)); + $hook_name = strtolower($hook_name); - $return = array(); - $inserted_modules = array(); - if (isset($list[$hook_name])) - $return = $list[$hook_name]; - foreach ($return as $module) - $inserted_modules[] = $module['id_module']; - if (isset($list[$retro_hook_name])) - foreach ($list[$retro_hook_name] as $retro_module_call) - if (!in_array($retro_module_call['id_module'], $inserted_modules)) - $return[] = $retro_module_call; + $return = array(); + $inserted_modules = array(); + if (isset($list[$hook_name])) { + $return = $list[$hook_name]; + } + foreach ($return as $module) { + $inserted_modules[] = $module['id_module']; + } + if (isset($list[$retro_hook_name])) { + foreach ($list[$retro_hook_name] as $retro_module_call) { + if (!in_array($retro_module_call['id_module'], $inserted_modules)) { + $return[] = $retro_module_call; + } + } + } - return (count($return) > 0 ? $return : false); - } - else - return $list; - } + return (count($return) > 0 ? $return : false); + } else { + return $list; + } + } - /** - * Execute modules for specified hook - * - * @param string $hook_name Hook Name - * @param array $hook_args Parameters for the functions - * @param int $id_module Execute hook for this module only - * @param bool $array_return If specified, module output will be set by name in an array - * @param bool $check_exceptions Check permission exceptions - * @param bool $use_push Force change to be refreshed on Dashboard widgets - * @param int $id_shop If specified, hook will be execute the shop with this ID - * - * @throws PrestaShopException - * - * @return string/array modules output - */ - public static function exec($hook_name, $hook_args = array(), $id_module = null, $array_return = false, $check_exceptions = true, - $use_push = false, $id_shop = null) - { - if (defined('PS_INSTALLATION_IN_PROGRESS')) - return; + /** + * Execute modules for specified hook + * + * @param string $hook_name Hook Name + * @param array $hook_args Parameters for the functions + * @param int $id_module Execute hook for this module only + * @param bool $array_return If specified, module output will be set by name in an array + * @param bool $check_exceptions Check permission exceptions + * @param bool $use_push Force change to be refreshed on Dashboard widgets + * @param int $id_shop If specified, hook will be execute the shop with this ID + * + * @throws PrestaShopException + * + * @return string/array modules output + */ + public static function exec($hook_name, $hook_args = array(), $id_module = null, $array_return = false, $check_exceptions = true, + $use_push = false, $id_shop = null) + { + if (defined('PS_INSTALLATION_IN_PROGRESS')) { + return; + } - static $disable_non_native_modules = null; - if ($disable_non_native_modules === null) - $disable_non_native_modules = (bool)Configuration::get('PS_DISABLE_NON_NATIVE_MODULE'); + static $disable_non_native_modules = null; + if ($disable_non_native_modules === null) { + $disable_non_native_modules = (bool)Configuration::get('PS_DISABLE_NON_NATIVE_MODULE'); + } - // Check arguments validity - if (($id_module && !is_numeric($id_module)) || !Validate::isHookName($hook_name)) - throw new PrestaShopException('Invalid id_module or hook_name'); + // Check arguments validity + if (($id_module && !is_numeric($id_module)) || !Validate::isHookName($hook_name)) { + throw new PrestaShopException('Invalid id_module or hook_name'); + } - // If no modules associated to hook_name or recompatible hook name, we stop the function + // If no modules associated to hook_name or recompatible hook name, we stop the function - if (!$module_list = Hook::getHookModuleExecList($hook_name)) - return ''; + if (!$module_list = Hook::getHookModuleExecList($hook_name)) { + return ''; + } - // Check if hook exists - if (!$id_hook = Hook::getIdByName($hook_name)) - return false; + // Check if hook exists + if (!$id_hook = Hook::getIdByName($hook_name)) { + return false; + } - // Store list of executed hooks on this page - Hook::$executed_hooks[$id_hook] = $hook_name; + // Store list of executed hooks on this page + Hook::$executed_hooks[$id_hook] = $hook_name; - $live_edit = false; - $context = Context::getContext(); - if (!isset($hook_args['cookie']) || !$hook_args['cookie']) - $hook_args['cookie'] = $context->cookie; - if (!isset($hook_args['cart']) || !$hook_args['cart']) - $hook_args['cart'] = $context->cart; + $live_edit = false; + $context = Context::getContext(); + if (!isset($hook_args['cookie']) || !$hook_args['cookie']) { + $hook_args['cookie'] = $context->cookie; + } + if (!isset($hook_args['cart']) || !$hook_args['cart']) { + $hook_args['cart'] = $context->cart; + } - $retro_hook_name = Hook::getRetroHookName($hook_name); + $retro_hook_name = Hook::getRetroHookName($hook_name); - // Look on modules list - $altern = 0; - $output = ''; + // Look on modules list + $altern = 0; + $output = ''; - if ($disable_non_native_modules && !isset(Hook::$native_module)) - Hook::$native_module = Module::getNativeModuleList(); + if ($disable_non_native_modules && !isset(Hook::$native_module)) { + Hook::$native_module = Module::getNativeModuleList(); + } - $different_shop = false; - if ($id_shop !== null && Validate::isUnsignedId($id_shop) && $id_shop != $context->shop->getContextShopID()) - { - $old_context = $context->shop->getContext(); - $old_shop = clone $context->shop; - $shop = new Shop((int)$id_shop); - if (Validate::isLoadedObject($shop)) - { - $context->shop = $shop; - $context->shop->setContext(Shop::CONTEXT_SHOP, $shop->id); - $different_shop = true; - } - } + $different_shop = false; + if ($id_shop !== null && Validate::isUnsignedId($id_shop) && $id_shop != $context->shop->getContextShopID()) { + $old_context = $context->shop->getContext(); + $old_shop = clone $context->shop; + $shop = new Shop((int)$id_shop); + if (Validate::isLoadedObject($shop)) { + $context->shop = $shop; + $context->shop->setContext(Shop::CONTEXT_SHOP, $shop->id); + $different_shop = true; + } + } - foreach ($module_list as $array) - { - // Check errors - if ($id_module && $id_module != $array['id_module']) - continue; + foreach ($module_list as $array) { + // Check errors + if ($id_module && $id_module != $array['id_module']) { + continue; + } - if ((bool)$disable_non_native_modules && Hook::$native_module && count(Hook::$native_module) && !in_array($array['module'], self::$native_module)) - continue; + if ((bool)$disable_non_native_modules && Hook::$native_module && count(Hook::$native_module) && !in_array($array['module'], self::$native_module)) { + continue; + } - // Check permissions - if ($check_exceptions) - { - $exceptions = Module::getExceptionsStatic($array['id_module'], $array['id_hook']); + // Check permissions + if ($check_exceptions) { + $exceptions = Module::getExceptionsStatic($array['id_module'], $array['id_hook']); - $controller = Dispatcher::getInstance()->getController(); - $controller_obj = Context::getContext()->controller; + $controller = Dispatcher::getInstance()->getController(); + $controller_obj = Context::getContext()->controller; - //check if current controller is a module controller - if (isset($controller_obj->module) && Validate::isLoadedObject($controller_obj->module)) - $controller = 'module-'.$controller_obj->module->name.'-'.$controller; + //check if current controller is a module controller + if (isset($controller_obj->module) && Validate::isLoadedObject($controller_obj->module)) { + $controller = 'module-'.$controller_obj->module->name.'-'.$controller; + } - if (in_array($controller, $exceptions)) - continue; + if (in_array($controller, $exceptions)) { + continue; + } - //Backward compatibility of controller names - $matching_name = array( - 'authentication' => 'auth', - 'productscomparison' => 'compare' - ); - if (isset($matching_name[$controller]) && in_array($matching_name[$controller], $exceptions)) - continue; - if (Validate::isLoadedObject($context->employee) && !Module::getPermissionStatic($array['id_module'], 'view', $context->employee)) - continue; - } + //Backward compatibility of controller names + $matching_name = array( + 'authentication' => 'auth', + 'productscomparison' => 'compare' + ); + if (isset($matching_name[$controller]) && in_array($matching_name[$controller], $exceptions)) { + continue; + } + if (Validate::isLoadedObject($context->employee) && !Module::getPermissionStatic($array['id_module'], 'view', $context->employee)) { + continue; + } + } - if (!($moduleInstance = Module::getInstanceByName($array['module']))) - continue; + if (!($moduleInstance = Module::getInstanceByName($array['module']))) { + continue; + } - if ($use_push && !$moduleInstance->allow_push) - continue; - // Check which / if method is callable - $hook_callable = is_callable(array($moduleInstance, 'hook'.$hook_name)); - $hook_retro_callable = is_callable(array($moduleInstance, 'hook'.$retro_hook_name)); + if ($use_push && !$moduleInstance->allow_push) { + continue; + } + // Check which / if method is callable + $hook_callable = is_callable(array($moduleInstance, 'hook'.$hook_name)); + $hook_retro_callable = is_callable(array($moduleInstance, 'hook'.$retro_hook_name)); - if (($hook_callable || $hook_retro_callable) && Module::preCall($moduleInstance->name)) - { - $hook_args['altern'] = ++$altern; + if (($hook_callable || $hook_retro_callable) && Module::preCall($moduleInstance->name)) { + $hook_args['altern'] = ++$altern; - if ($use_push && isset($moduleInstance->push_filename) && file_exists($moduleInstance->push_filename)) - Tools::waitUntilFileIsModified($moduleInstance->push_filename, $moduleInstance->push_time_limit); + if ($use_push && isset($moduleInstance->push_filename) && file_exists($moduleInstance->push_filename)) { + Tools::waitUntilFileIsModified($moduleInstance->push_filename, $moduleInstance->push_time_limit); + } - // Call hook method - if ($hook_callable) - $display = Hook::coreCallHook($moduleInstance, 'hook'.$hook_name, $hook_args); - elseif ($hook_retro_callable) - $display = Hook::coreCallHook($moduleInstance, 'hook'.$retro_hook_name, $hook_args); + // Call hook method + if ($hook_callable) { + $display = Hook::coreCallHook($moduleInstance, 'hook'.$hook_name, $hook_args); + } elseif ($hook_retro_callable) { + $display = Hook::coreCallHook($moduleInstance, 'hook'.$retro_hook_name, $hook_args); + } - // Live edit - if (!$array_return && $array['live_edit'] && Tools::isSubmit('live_edit') && Tools::getValue('ad') - && Tools::getValue('liveToken') == Tools::getAdminToken('AdminModulesPositions' - .(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee'))) - { - $live_edit = true; - $output .= self::wrapLiveEdit($display, $moduleInstance, $array['id_hook']); - } - elseif ($array_return) - $output[$moduleInstance->name] = $display; - else - $output .= $display; - } - } + // Live edit + if (!$array_return && $array['live_edit'] && Tools::isSubmit('live_edit') && Tools::getValue('ad') + && Tools::getValue('liveToken') == Tools::getAdminToken('AdminModulesPositions' + .(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee'))) { + $live_edit = true; + $output .= self::wrapLiveEdit($display, $moduleInstance, $array['id_hook']); + } elseif ($array_return) { + $output[$moduleInstance->name] = $display; + } else { + $output .= $display; + } + } + } - if ($different_shop) - { - $context->shop = $old_shop; - $context->shop->setContext($old_context, $shop->id); - } + if ($different_shop) { + $context->shop = $old_shop; + $context->shop->setContext($old_context, $shop->id); + } - if ($array_return) - return $output; - else - return ($live_edit ? ' -
' : '').$output.($live_edit ? '
' : '');// Return html string - } + if ($array_return) { + return $output; + } else { + return ($live_edit ? ' +
' : '').$output.($live_edit ? '
' : ''); + }// Return html string + } - public static function coreCallHook($module, $method, $params) - { - // Define if we will log modules performances for this session - if (Module::$_log_modules_perfs === null) - { - $modulo = _PS_DEBUG_PROFILING_ ? 1 : Configuration::get('PS_log_modules_perfs_MODULO'); - Module::$_log_modules_perfs = ($modulo && mt_rand(0, $modulo - 1) == 0); - if (Module::$_log_modules_perfs) - Module::$_log_modules_perfs_session = mt_rand(); - } + public static function coreCallHook($module, $method, $params) + { + // Define if we will log modules performances for this session + if (Module::$_log_modules_perfs === null) { + $modulo = _PS_DEBUG_PROFILING_ ? 1 : Configuration::get('PS_log_modules_perfs_MODULO'); + Module::$_log_modules_perfs = ($modulo && mt_rand(0, $modulo - 1) == 0); + if (Module::$_log_modules_perfs) { + Module::$_log_modules_perfs_session = mt_rand(); + } + } - // Immediately return the result if we do not log performances - if (!Module::$_log_modules_perfs) - return $module->{$method}($params); + // Immediately return the result if we do not log performances + if (!Module::$_log_modules_perfs) { + return $module->{$method}($params); + } - // Store time and memory before and after hook call and save the result in the database - $time_start = microtime(true); - $memory_start = memory_get_usage(true); + // Store time and memory before and after hook call and save the result in the database + $time_start = microtime(true); + $memory_start = memory_get_usage(true); - // Call hook - $r = $module->{$method}($params); + // Call hook + $r = $module->{$method}($params); - $time_end = microtime(true); - $memory_end = memory_get_usage(true); + $time_end = microtime(true); + $memory_end = memory_get_usage(true); - Db::getInstance()->execute(' + Db::getInstance()->execute(' INSERT INTO '._DB_PREFIX_.'modules_perfs (session, module, method, time_start, time_end, memory_start, memory_end) VALUES ('.(int)Module::$_log_modules_perfs_session.', "'.pSQL($module->name).'", "'.pSQL($method).'", "'.pSQL($time_start).'", "'.pSQL($time_end).'", '.(int)$memory_start.', '.(int)$memory_end.')'); - return $r; - } + return $r; + } - public static function wrapLiveEdit($display, $moduleInstance, $id_hook) - { - return ' + public static function wrapLiveEdit($display, $moduleInstance, $id_hook) + { + return '
' - .Tools::safeOutput($moduleInstance->displayName).' + .Tools::safeOutput($moduleInstance->displayName).' '.$display.'
'; - } + } - /** - * @deprecated 1.5.0 - */ - public static function updateOrderStatus($new_order_status_id, $id_order) - { - Tools::displayAsDeprecated(); - $order = new Order((int)$id_order); - $new_os = new OrderState((int)$new_order_status_id, $order->id_lang); + /** + * @deprecated 1.5.0 + */ + public static function updateOrderStatus($new_order_status_id, $id_order) + { + Tools::displayAsDeprecated(); + $order = new Order((int)$id_order); + $new_os = new OrderState((int)$new_order_status_id, $order->id_lang); - $return = ((int)$new_os->id == Configuration::get('PS_OS_PAYMENT')) ? Hook::exec('paymentConfirm', array('id_order' => (int)($order->id))) : true; - $return = Hook::exec('updateOrderStatus', array('newOrderStatus' => $new_os, 'id_order' => (int)($order->id))) && $return; - return $return; - } + $return = ((int)$new_os->id == Configuration::get('PS_OS_PAYMENT')) ? Hook::exec('paymentConfirm', array('id_order' => (int)($order->id))) : true; + $return = Hook::exec('updateOrderStatus', array('newOrderStatus' => $new_os, 'id_order' => (int)($order->id))) && $return; + return $return; + } - /** - * @deprecated 1.5.0 - */ - public static function postUpdateOrderStatus($new_order_status_id, $id_order) - { - Tools::displayAsDeprecated(); - $order = new Order((int)$id_order); - $new_os = new OrderState((int)$new_order_status_id, $order->id_lang); - $return = Hook::exec('postUpdateOrderStatus', array('newOrderStatus' => $new_os, 'id_order' => (int)($order->id))); - return $return; - } + /** + * @deprecated 1.5.0 + */ + public static function postUpdateOrderStatus($new_order_status_id, $id_order) + { + Tools::displayAsDeprecated(); + $order = new Order((int)$id_order); + $new_os = new OrderState((int)$new_order_status_id, $order->id_lang); + $return = Hook::exec('postUpdateOrderStatus', array('newOrderStatus' => $new_os, 'id_order' => (int)($order->id))); + return $return; + } - /** - * @deprecated 1.5.0 - */ - public static function orderConfirmation($id_order) - { - Tools::displayAsDeprecated(); - if (Validate::isUnsignedId($id_order)) - { - $params = array(); - $order = new Order((int)$id_order); - $currency = new Currency((int)$order->id_currency); + /** + * @deprecated 1.5.0 + */ + public static function orderConfirmation($id_order) + { + Tools::displayAsDeprecated(); + if (Validate::isUnsignedId($id_order)) { + $params = array(); + $order = new Order((int)$id_order); + $currency = new Currency((int)$order->id_currency); - if (Validate::isLoadedObject($order)) - { - $cart = new Cart((int)$order->id_cart); - $params['total_to_pay'] = $cart->getOrderTotal(); - $params['currency'] = $currency->sign; - $params['objOrder'] = $order; - $params['currencyObj'] = $currency; + if (Validate::isLoadedObject($order)) { + $cart = new Cart((int)$order->id_cart); + $params['total_to_pay'] = $cart->getOrderTotal(); + $params['currency'] = $currency->sign; + $params['objOrder'] = $order; + $params['currencyObj'] = $currency; - return Hook::exec('orderConfirmation', $params); - } - } - return false; - } + return Hook::exec('orderConfirmation', $params); + } + } + return false; + } - /** - * @deprecated 1.5.0 - */ - public static function paymentReturn($id_order, $id_module) - { - Tools::displayAsDeprecated(); - if (Validate::isUnsignedId($id_order) && Validate::isUnsignedId($id_module)) - { - $params = array(); - $order = new Order((int)($id_order)); - $currency = new Currency((int)($order->id_currency)); + /** + * @deprecated 1.5.0 + */ + public static function paymentReturn($id_order, $id_module) + { + Tools::displayAsDeprecated(); + if (Validate::isUnsignedId($id_order) && Validate::isUnsignedId($id_module)) { + $params = array(); + $order = new Order((int)($id_order)); + $currency = new Currency((int)($order->id_currency)); - if (Validate::isLoadedObject($order)) - { - $cart = new Cart((int)$order->id_cart); - $params['total_to_pay'] = $cart->getOrderTotal(); - $params['currency'] = $currency->sign; - $params['objOrder'] = $order; - $params['currencyObj'] = $currency; + if (Validate::isLoadedObject($order)) { + $cart = new Cart((int)$order->id_cart); + $params['total_to_pay'] = $cart->getOrderTotal(); + $params['currency'] = $currency->sign; + $params['objOrder'] = $order; + $params['currencyObj'] = $currency; - return Hook::exec('paymentReturn', $params, (int)($id_module)); - } - } - return false; - } + return Hook::exec('paymentReturn', $params, (int)($id_module)); + } + } + return false; + } - /** - * @deprecated 1.5.0 - */ - public static function PDFInvoice($pdf, $id_order) - { - Tools::displayAsDeprecated(); - if (!is_object($pdf) || !Validate::isUnsignedId($id_order)) - return false; - return Hook::exec('PDFInvoice', array('pdf' => $pdf, 'id_order' => $id_order)); - } + /** + * @deprecated 1.5.0 + */ + public static function PDFInvoice($pdf, $id_order) + { + Tools::displayAsDeprecated(); + if (!is_object($pdf) || !Validate::isUnsignedId($id_order)) { + return false; + } + return Hook::exec('PDFInvoice', array('pdf' => $pdf, 'id_order' => $id_order)); + } - /** - * @deprecated 1.5.0 - */ - public static function backBeforePayment($module) - { - Tools::displayAsDeprecated(); - if ($module) - return Hook::exec('backBeforePayment', array('module' => strval($module))); - } + /** + * @deprecated 1.5.0 + */ + public static function backBeforePayment($module) + { + Tools::displayAsDeprecated(); + if ($module) { + return Hook::exec('backBeforePayment', array('module' => strval($module))); + } + } - /** - * @deprecated 1.5.0 - */ - public static function updateCarrier($id_carrier, $carrier) - { - Tools::displayAsDeprecated(); - if (!Validate::isUnsignedId($id_carrier) || !is_object($carrier)) - return false; - return Hook::exec('updateCarrier', array('id_carrier' => $id_carrier, 'carrier' => $carrier)); - } + /** + * @deprecated 1.5.0 + */ + public static function updateCarrier($id_carrier, $carrier) + { + Tools::displayAsDeprecated(); + if (!Validate::isUnsignedId($id_carrier) || !is_object($carrier)) { + return false; + } + return Hook::exec('updateCarrier', array('id_carrier' => $id_carrier, 'carrier' => $carrier)); + } - /** - * Preload hook modules cache - * - * @deprecated 1.5.0 use Hook::getHookModuleList() instead - * - * @return bool preload_needed - */ - public static function preloadHookModulesCache() - { - Tools::displayAsDeprecated(); + /** + * Preload hook modules cache + * + * @deprecated 1.5.0 use Hook::getHookModuleList() instead + * + * @return bool preload_needed + */ + public static function preloadHookModulesCache() + { + Tools::displayAsDeprecated(); - if (!is_null(self::$_hook_modules_cache)) - return false; + if (!is_null(self::$_hook_modules_cache)) { + return false; + } - self::$_hook_modules_cache = Hook::getHookModuleList(); - return true; - } + self::$_hook_modules_cache = Hook::getHookModuleList(); + return true; + } - /** - * Return hook ID from name - * - * @param string $hook_name Hook name - * @return int Hook ID - * - * @deprecated since 1.5.0 use Hook::getIdByName() instead - */ - public static function get($hook_name) - { - Tools::displayAsDeprecated(); - if (!Validate::isHookName($hook_name)) - die(Tools::displayError()); + /** + * Return hook ID from name + * + * @param string $hook_name Hook name + * @return int Hook ID + * + * @deprecated since 1.5.0 use Hook::getIdByName() instead + */ + public static function get($hook_name) + { + Tools::displayAsDeprecated(); + if (!Validate::isHookName($hook_name)) { + die(Tools::displayError()); + } - $result = Db::getInstance()->getRow(' + $result = Db::getInstance()->getRow(' SELECT `id_hook`, `name` FROM `'._DB_PREFIX_.'hook` WHERE `name` = \''.pSQL($hook_name).'\''); - return ($result ? $result['id_hook'] : false); - } + return ($result ? $result['id_hook'] : false); + } - /** - * Called when quantity of a product is updated. - * - * @deprecated 1.5.3.0 - * - * @param Cart $cart - * @param Order $order - * @param Customer $customer - * @param Currency $currency - * @param $orderStatus - * - * @throws PrestaShopException - * - * @return string - */ - public static function newOrder($cart, $order, $customer, $currency, $order_status) - { - Tools::displayAsDeprecated(); - return Hook::exec('newOrder', array( - 'cart' => $cart, - 'order' => $order, - 'customer' => $customer, - 'currency' => $currency, - 'orderStatus' => $order_status)); - } + /** + * Called when quantity of a product is updated. + * + * @deprecated 1.5.3.0 + * + * @param Cart $cart + * @param Order $order + * @param Customer $customer + * @param Currency $currency + * @param $orderStatus + * + * @throws PrestaShopException + * + * @return string + */ + public static function newOrder($cart, $order, $customer, $currency, $order_status) + { + Tools::displayAsDeprecated(); + return Hook::exec('newOrder', array( + 'cart' => $cart, + 'order' => $order, + 'customer' => $customer, + 'currency' => $currency, + 'orderStatus' => $order_status)); + } - /** - * @deprecated 1.5.0 - */ - public static function updateQuantity($product, $order = null) - { - Tools::displayAsDeprecated(); - return Hook::exec('updateQuantity', array('product' => $product, 'order' => $order)); - } + /** + * @deprecated 1.5.0 + */ + public static function updateQuantity($product, $order = null) + { + Tools::displayAsDeprecated(); + return Hook::exec('updateQuantity', array('product' => $product, 'order' => $order)); + } - /** - * @deprecated 1.5.0 - */ - public static function productFooter($product, $category) - { - Tools::displayAsDeprecated(); - return Hook::exec('productFooter', array('product' => $product, 'category' => $category)); - } + /** + * @deprecated 1.5.0 + */ + public static function productFooter($product, $category) + { + Tools::displayAsDeprecated(); + return Hook::exec('productFooter', array('product' => $product, 'category' => $category)); + } - /** - * @deprecated 1.5.0 - */ - public static function productOutOfStock($product) - { - Tools::displayAsDeprecated(); - return Hook::exec('productOutOfStock', array('product' => $product)); - } + /** + * @deprecated 1.5.0 + */ + public static function productOutOfStock($product) + { + Tools::displayAsDeprecated(); + return Hook::exec('productOutOfStock', array('product' => $product)); + } - /** - * @deprecated 1.5.0 - */ - public static function addProduct($product) - { - Tools::displayAsDeprecated(); - return Hook::exec('addProduct', array('product' => $product)); - } + /** + * @deprecated 1.5.0 + */ + public static function addProduct($product) + { + Tools::displayAsDeprecated(); + return Hook::exec('addProduct', array('product' => $product)); + } - /** - * @deprecated 1.5.0 - */ - public static function updateProduct($product) - { - Tools::displayAsDeprecated(); - return Hook::exec('updateProduct', array('product' => $product)); - } + /** + * @deprecated 1.5.0 + */ + public static function updateProduct($product) + { + Tools::displayAsDeprecated(); + return Hook::exec('updateProduct', array('product' => $product)); + } - /** - * @deprecated 1.5.0 - */ - public static function deleteProduct($product) - { - Tools::displayAsDeprecated(); - return Hook::exec('deleteProduct', array('product' => $product)); - } + /** + * @deprecated 1.5.0 + */ + public static function deleteProduct($product) + { + Tools::displayAsDeprecated(); + return Hook::exec('deleteProduct', array('product' => $product)); + } - /** - * @deprecated 1.5.0 - */ - public static function updateProductAttribute($id_product_attribute) - { - Tools::displayAsDeprecated(); - return Hook::exec('updateProductAttribute', array('id_product_attribute' => $id_product_attribute)); - } + /** + * @deprecated 1.5.0 + */ + public static function updateProductAttribute($id_product_attribute) + { + Tools::displayAsDeprecated(); + return Hook::exec('updateProductAttribute', array('id_product_attribute' => $id_product_attribute)); + } } diff --git a/classes/Image.php b/classes/Image.php index 58fed2e5..61bfc840 100644 --- a/classes/Image.php +++ b/classes/Image.php @@ -26,121 +26,126 @@ class ImageCore extends ObjectModel { - public $id; + public $id; - /** @var int Image ID */ - public $id_image; + /** @var int Image ID */ + public $id_image; - /** @var int Product ID */ - public $id_product; + /** @var int Product ID */ + public $id_product; - /** @var int Position used to order images of the same product */ - public $position; + /** @var int Position used to order images of the same product */ + public $position; - /** @var bool Image is cover */ - public $cover; + /** @var bool Image is cover */ + public $cover; - /** @var string Legend */ - public $legend; + /** @var string Legend */ + public $legend; - /** @var string image extension */ - public $image_format = 'jpg'; + /** @var string image extension */ + public $image_format = 'jpg'; - /** @var string path to index.php file to be copied to new image folders */ - public $source_index; + /** @var string path to index.php file to be copied to new image folders */ + public $source_index; - /** @var string image folder */ - protected $folder; + /** @var string image folder */ + protected $folder; - /** @var string image path without extension */ - protected $existing_path; + /** @var string image path without extension */ + protected $existing_path; - /** @var int access rights of created folders (octal) */ - protected static $access_rights = 0775; + /** @var int access rights of created folders (octal) */ + protected static $access_rights = 0775; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'image', - 'primary' => 'id_image', - 'multilang' => true, - 'fields' => array( - 'id_product' => array('type' => self::TYPE_INT, 'shop' => 'both', 'validate' => 'isUnsignedId', 'required' => true), - 'position' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'cover' => array('type' => self::TYPE_BOOL, 'allow_null' => true, 'validate' => 'isBool', 'shop' => true), - 'legend' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'image', + 'primary' => 'id_image', + 'multilang' => true, + 'fields' => array( + 'id_product' => array('type' => self::TYPE_INT, 'shop' => 'both', 'validate' => 'isUnsignedId', 'required' => true), + 'position' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'cover' => array('type' => self::TYPE_BOOL, 'allow_null' => true, 'validate' => 'isBool', 'shop' => true), + 'legend' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), + ), + ); - protected static $_cacheGetSize = array(); + protected static $_cacheGetSize = array(); - public function __construct($id = null, $id_lang = null) - { - parent::__construct($id, $id_lang); - $this->image_dir = _PS_PROD_IMG_DIR_; - $this->source_index = _PS_PROD_IMG_DIR_.'index.php'; - } + public function __construct($id = null, $id_lang = null) + { + parent::__construct($id, $id_lang); + $this->image_dir = _PS_PROD_IMG_DIR_; + $this->source_index = _PS_PROD_IMG_DIR_.'index.php'; + } - public function add($autodate = true, $null_values = false) - { - if ($this->position <= 0) - $this->position = Image::getHighestPosition($this->id_product) + 1; + public function add($autodate = true, $null_values = false) + { + if ($this->position <= 0) { + $this->position = Image::getHighestPosition($this->id_product) + 1; + } - if ($this->cover) - $this->cover = 1; - else - $this->cover = null; + if ($this->cover) { + $this->cover = 1; + } else { + $this->cover = null; + } - return parent::add($autodate, $null_values); - } + return parent::add($autodate, $null_values); + } - public function update($null_values = false) - { - if ($this->cover) - $this->cover = 1; - else - $this->cover = null; + public function update($null_values = false) + { + if ($this->cover) { + $this->cover = 1; + } else { + $this->cover = null; + } - return parent::update($null_values); - } + return parent::update($null_values); + } - public function delete() - { - if (!parent::delete()) - return false; + public function delete() + { + if (!parent::delete()) { + return false; + } - if ($this->hasMultishopEntries()) - return true; + if ($this->hasMultishopEntries()) { + return true; + } - if (!$this->deleteProductAttributeImage() || !$this->deleteImage()) - return false; + if (!$this->deleteProductAttributeImage() || !$this->deleteImage()) { + return false; + } - // update positions - Db::getInstance()->execute('SET @position:=0', false); - Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'image` SET position=(@position:=@position+1) + // update positions + Db::getInstance()->execute('SET @position:=0', false); + Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'image` SET position=(@position:=@position+1) WHERE `id_product` = '.(int)$this->id_product.' ORDER BY position ASC'); - return true; - } + return true; + } - /** - * Return first image (by position) associated with a product attribute - * - * @param int $id_shop Shop ID - * @param int $id_lang Language ID - * @param int $id_product Product ID - * @param int $id_product_attribute Product Attribute ID - * @return array - */ - public static function getBestImageAttribute($id_shop, $id_lang, $id_product, $id_product_attribute) - { - $cache_id = 'Image::getBestImageAttribute'.'-'.(int)$id_product.'-'.(int)$id_product_attribute.'-'.(int)$id_lang.'-'.(int)$id_shop; + /** + * Return first image (by position) associated with a product attribute + * + * @param int $id_shop Shop ID + * @param int $id_lang Language ID + * @param int $id_product Product ID + * @param int $id_product_attribute Product Attribute ID + * @return array + */ + public static function getBestImageAttribute($id_shop, $id_lang, $id_product, $id_product_attribute) + { + $cache_id = 'Image::getBestImageAttribute'.'-'.(int)$id_product.'-'.(int)$id_product_attribute.'-'.(int)$id_lang.'-'.(int)$id_shop; - if (!Cache::isStored($cache_id)) - { - $row = Db::getInstance()->getRow(' + if (!Cache::isStored($cache_id)) { + $row = Db::getInstance()->getRow(' SELECT image_shop.`id_image` id_image, il.`legend` FROM `'._DB_PREFIX_.'image` i INNER JOIN `'._DB_PREFIX_.'image_shop` image_shop @@ -151,622 +156,648 @@ class ImageCore extends ObjectModel ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.') WHERE i.`id_product` = '.(int)$id_product.' ORDER BY i.`position` ASC'); - Cache::store($cache_id, $row); - } - else - $row = Cache::retrieve($cache_id); - return $row; - } + Cache::store($cache_id, $row); + } else { + $row = Cache::retrieve($cache_id); + } + return $row; + } - /** - * Return available images for a product - * - * @param int $id_lang Language ID - * @param int $id_product Product ID - * @param int $id_product_attribute Product Attribute ID - * @return array Images - */ - public static function getImages($id_lang, $id_product, $id_product_attribute = null) - { - $attribute_filter = ($id_product_attribute ? ' AND ai.`id_product_attribute` = '.(int)$id_product_attribute : ''); - $sql = 'SELECT * + /** + * Return available images for a product + * + * @param int $id_lang Language ID + * @param int $id_product Product ID + * @param int $id_product_attribute Product Attribute ID + * @return array Images + */ + public static function getImages($id_lang, $id_product, $id_product_attribute = null) + { + $attribute_filter = ($id_product_attribute ? ' AND ai.`id_product_attribute` = '.(int)$id_product_attribute : ''); + $sql = 'SELECT * FROM `'._DB_PREFIX_.'image` i LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image`)'; - if ($id_product_attribute) - $sql .= ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_image` ai ON (i.`id_image` = ai.`id_image`)'; + if ($id_product_attribute) { + $sql .= ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_image` ai ON (i.`id_image` = ai.`id_image`)'; + } - $sql .= ' WHERE i.`id_product` = '.(int)$id_product.' AND il.`id_lang` = '.(int)$id_lang.$attribute_filter.' + $sql .= ' WHERE i.`id_product` = '.(int)$id_product.' AND il.`id_lang` = '.(int)$id_lang.$attribute_filter.' ORDER BY i.`position` ASC'; - return Db::getInstance()->executeS($sql); - } + return Db::getInstance()->executeS($sql); + } - /** - * Check if a product has an image available - * - * @param int $id_lang Language ID - * @param int $id_product Product ID - * @param int $id_product_attribute Product Attribute ID - * @return bool - */ - public static function hasImages($id_lang, $id_product, $id_product_attribute = null) - { - $attribute_filter = ($id_product_attribute ? ' AND ai.`id_product_attribute` = '.(int)$id_product_attribute : ''); - $sql = 'SELECT 1 + /** + * Check if a product has an image available + * + * @param int $id_lang Language ID + * @param int $id_product Product ID + * @param int $id_product_attribute Product Attribute ID + * @return bool + */ + public static function hasImages($id_lang, $id_product, $id_product_attribute = null) + { + $attribute_filter = ($id_product_attribute ? ' AND ai.`id_product_attribute` = '.(int)$id_product_attribute : ''); + $sql = 'SELECT 1 FROM `'._DB_PREFIX_.'image` i LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image`)'; - if ($id_product_attribute) - $sql .= ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_image` ai ON (i.`id_image` = ai.`id_image`)'; + if ($id_product_attribute) { + $sql .= ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_image` ai ON (i.`id_image` = ai.`id_image`)'; + } - $sql .= ' WHERE i.`id_product` = '.(int)$id_product.' AND il.`id_lang` = '.(int)$id_lang.$attribute_filter; - return (bool)Db::getInstance()->getValue($sql); - } + $sql .= ' WHERE i.`id_product` = '.(int)$id_product.' AND il.`id_lang` = '.(int)$id_lang.$attribute_filter; + return (bool)Db::getInstance()->getValue($sql); + } - /** - * Return Images - * - * @return array Images - */ - public static function getAllImages() - { - return Db::getInstance()->executeS(' + /** + * Return Images + * + * @return array Images + */ + public static function getAllImages() + { + return Db::getInstance()->executeS(' SELECT `id_image`, `id_product` FROM `'._DB_PREFIX_.'image` ORDER BY `id_image` ASC'); - } + } - /** - * Return number of images for a product - * - * @param int $id_product Product ID - * @return int number of images - */ - public static function getImagesTotal($id_product) - { - $result = Db::getInstance()->getRow(' + /** + * Return number of images for a product + * + * @param int $id_product Product ID + * @return int number of images + */ + public static function getImagesTotal($id_product) + { + $result = Db::getInstance()->getRow(' SELECT COUNT(`id_image`) AS total FROM `'._DB_PREFIX_.'image` WHERE `id_product` = '.(int)$id_product); - return $result['total']; - } + return $result['total']; + } - /** - * Return highest position of images for a product - * - * @param int $id_product Product ID - * @return int highest position of images - */ - public static function getHighestPosition($id_product) - { - $result = Db::getInstance()->getRow(' + /** + * Return highest position of images for a product + * + * @param int $id_product Product ID + * @return int highest position of images + */ + public static function getHighestPosition($id_product) + { + $result = Db::getInstance()->getRow(' SELECT MAX(`position`) AS max FROM `'._DB_PREFIX_.'image` WHERE `id_product` = '.(int)$id_product); - return $result['max']; - } + return $result['max']; + } - /** - * Delete product cover - * - * @param int $id_product Product ID - * @return bool result - */ - public static function deleteCover($id_product) - { - if (!Validate::isUnsignedId($id_product)) - die(Tools::displayError()); + /** + * Delete product cover + * + * @param int $id_product Product ID + * @return bool result + */ + public static function deleteCover($id_product) + { + if (!Validate::isUnsignedId($id_product)) { + die(Tools::displayError()); + } - if (file_exists(_PS_TMP_IMG_DIR_.'product_'.$id_product.'.jpg')) - unlink(_PS_TMP_IMG_DIR_.'product_'.$id_product.'.jpg'); + if (file_exists(_PS_TMP_IMG_DIR_.'product_'.$id_product.'.jpg')) { + unlink(_PS_TMP_IMG_DIR_.'product_'.$id_product.'.jpg'); + } - return (Db::getInstance()->execute(' + return (Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'image` SET `cover` = NULL WHERE `id_product` = '.(int)$id_product - ) && - Db::getInstance()->execute(' + ) && + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'image` i, `'._DB_PREFIX_.'image_shop` image_shop SET image_shop.`cover` = NULL WHERE image_shop.id_shop IN ('.implode(',', array_map('intval', Shop::getContextListShopID())).') AND image_shop.id_image = i.id_image AND i.`id_product` = '.(int)$id_product - )); - } + )); + } - /** - *Get product cover - * - * @param int $id_product Product ID - * @return bool result - */ - public static function getCover($id_product) - { - return Db::getInstance()->getRow(' + /** + *Get product cover + * + * @param int $id_product Product ID + * @return bool result + */ + public static function getCover($id_product) + { + return Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.'image` i'. - Shop::addSqlAssociation('image', 'i').' + Shop::addSqlAssociation('image', 'i').' WHERE i.`id_product` = '.(int)$id_product.' AND image_shop.`cover`= 1'); - } + } - /** - * Copy images from a product to another - * - * @param int $id_product_old Source product ID - * @param bool $id_product_new Destination product ID - */ - public static function duplicateProductImages($id_product_old, $id_product_new, $combination_images) - { - $images_types = ImageType::getImagesTypes('products'); - $result = Db::getInstance()->executeS(' + /** + * Copy images from a product to another + * + * @param int $id_product_old Source product ID + * @param bool $id_product_new Destination product ID + */ + public static function duplicateProductImages($id_product_old, $id_product_new, $combination_images) + { + $images_types = ImageType::getImagesTypes('products'); + $result = Db::getInstance()->executeS(' SELECT `id_image` FROM `'._DB_PREFIX_.'image` WHERE `id_product` = '.(int)$id_product_old); - foreach ($result as $row) - { - $image_old = new Image($row['id_image']); - $image_new = clone $image_old; - unset($image_new->id); - $image_new->id_product = (int)$id_product_new; + foreach ($result as $row) { + $image_old = new Image($row['id_image']); + $image_new = clone $image_old; + unset($image_new->id); + $image_new->id_product = (int)$id_product_new; - // A new id is generated for the cloned image when calling add() - if ($image_new->add()) - { - $new_path = $image_new->getPathForCreation(); - foreach ($images_types as $image_type) - { - if (file_exists(_PS_PROD_IMG_DIR_.$image_old->getExistingImgPath().'-'.$image_type['name'].'.jpg')) - { - if (!Configuration::get('PS_LEGACY_IMAGES')) - $image_new->createImgFolder(); - copy(_PS_PROD_IMG_DIR_.$image_old->getExistingImgPath().'-'.$image_type['name'].'.jpg', - $new_path.'-'.$image_type['name'].'.jpg'); - if (Configuration::get('WATERMARK_HASH')) - copy(_PS_PROD_IMG_DIR_.$image_old->getExistingImgPath().'-'.$image_type['name'].'-'.Configuration::get('WATERMARK_HASH').'.jpg', - $new_path.'-'.$image_type['name'].'-'.Configuration::get('WATERMARK_HASH').'.jpg'); - } - } + // A new id is generated for the cloned image when calling add() + if ($image_new->add()) { + $new_path = $image_new->getPathForCreation(); + foreach ($images_types as $image_type) { + if (file_exists(_PS_PROD_IMG_DIR_.$image_old->getExistingImgPath().'-'.$image_type['name'].'.jpg')) { + if (!Configuration::get('PS_LEGACY_IMAGES')) { + $image_new->createImgFolder(); + } + copy(_PS_PROD_IMG_DIR_.$image_old->getExistingImgPath().'-'.$image_type['name'].'.jpg', + $new_path.'-'.$image_type['name'].'.jpg'); + if (Configuration::get('WATERMARK_HASH')) { + copy(_PS_PROD_IMG_DIR_.$image_old->getExistingImgPath().'-'.$image_type['name'].'-'.Configuration::get('WATERMARK_HASH').'.jpg', + $new_path.'-'.$image_type['name'].'-'.Configuration::get('WATERMARK_HASH').'.jpg'); + } + } + } - if (file_exists(_PS_PROD_IMG_DIR_.$image_old->getExistingImgPath().'.jpg')) - copy(_PS_PROD_IMG_DIR_.$image_old->getExistingImgPath().'.jpg', $new_path.'.jpg'); + if (file_exists(_PS_PROD_IMG_DIR_.$image_old->getExistingImgPath().'.jpg')) { + copy(_PS_PROD_IMG_DIR_.$image_old->getExistingImgPath().'.jpg', $new_path.'.jpg'); + } - Image::replaceAttributeImageAssociationId($combination_images, (int)$image_old->id, (int)$image_new->id); + Image::replaceAttributeImageAssociationId($combination_images, (int)$image_old->id, (int)$image_new->id); - // Duplicate shop associations for images - $image_new->duplicateShops($id_product_old); - } - else - return false; - } - return Image::duplicateAttributeImageAssociations($combination_images); - } + // Duplicate shop associations for images + $image_new->duplicateShops($id_product_old); + } else { + return false; + } + } + return Image::duplicateAttributeImageAssociations($combination_images); + } - protected static function replaceAttributeImageAssociationId(&$combination_images, $saved_id, $id_image) - { - if (!isset($combination_images['new']) || !is_array($combination_images['new'])) - return; - foreach ($combination_images['new'] as $id_product_attribute => $image_ids) - foreach ($image_ids as $key => $image_id) - if ((int)$image_id == (int)$saved_id) - $combination_images['new'][$id_product_attribute][$key] = (int)$id_image; - } + protected static function replaceAttributeImageAssociationId(&$combination_images, $saved_id, $id_image) + { + if (!isset($combination_images['new']) || !is_array($combination_images['new'])) { + return; + } + foreach ($combination_images['new'] as $id_product_attribute => $image_ids) { + foreach ($image_ids as $key => $image_id) { + if ((int)$image_id == (int)$saved_id) { + $combination_images['new'][$id_product_attribute][$key] = (int)$id_image; + } + } + } + } - /** - * Duplicate product attribute image associations - * @param int $id_product_attribute_old - * @return bool - */ - public static function duplicateAttributeImageAssociations($combination_images) - { - if (!isset($combination_images['new']) || !is_array($combination_images['new'])) - return true; - $query = 'INSERT INTO `'._DB_PREFIX_.'product_attribute_image` (`id_product_attribute`, `id_image`) VALUES '; - foreach ($combination_images['new'] as $id_product_attribute => $image_ids) - foreach ($image_ids as $image_id) - $query .= '('.(int)$id_product_attribute.', '.(int)$image_id.'), '; - $query = rtrim($query, ', '); - return DB::getInstance()->execute($query); - } + /** + * Duplicate product attribute image associations + * @param int $id_product_attribute_old + * @return bool + */ + public static function duplicateAttributeImageAssociations($combination_images) + { + if (!isset($combination_images['new']) || !is_array($combination_images['new'])) { + return true; + } + $query = 'INSERT INTO `'._DB_PREFIX_.'product_attribute_image` (`id_product_attribute`, `id_image`) VALUES '; + foreach ($combination_images['new'] as $id_product_attribute => $image_ids) { + foreach ($image_ids as $image_id) { + $query .= '('.(int)$id_product_attribute.', '.(int)$image_id.'), '; + } + } + $query = rtrim($query, ', '); + return DB::getInstance()->execute($query); + } - /** - * Reposition image - * - * @param int $position Position - * @param bool $direction Direction - * @deprecated since version 1.5.0.1 use Image::updatePosition() instead - */ - public function positionImage($position, $direction) - { - Tools::displayAsDeprecated(); + /** + * Reposition image + * + * @param int $position Position + * @param bool $direction Direction + * @deprecated since version 1.5.0.1 use Image::updatePosition() instead + */ + public function positionImage($position, $direction) + { + Tools::displayAsDeprecated(); - $position = (int)$position; - $direction = (int)$direction; + $position = (int)$position; + $direction = (int)$direction; - // temporary position - $high_position = Image::getHighestPosition($this->id_product) + 1; + // temporary position + $high_position = Image::getHighestPosition($this->id_product) + 1; - Db::getInstance()->execute(' + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'image` SET `position` = '.(int)$high_position.' WHERE `id_product` = '.(int)$this->id_product.' AND `position` = '.($direction ? $position - 1 : $position + 1)); - Db::getInstance()->execute(' + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'image` SET `position` = `position`'.($direction ? '-1' : '+1').' WHERE `id_image` = '.(int)$this->id); - Db::getInstance()->execute(' + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'image` SET `position` = '.$this->position.' WHERE `id_product` = '.(int)$this->id_product.' AND `position` = '.(int)$high_position); - } + } - /** - * Change an image position and update relative positions - * - * @param int $way position is moved up if 0, moved down if 1 - * @param int $position new position of the moved image - * @return int success - */ - public function updatePosition($way, $position) - { - if (!isset($this->id) || !$position) - return false; + /** + * Change an image position and update relative positions + * + * @param int $way position is moved up if 0, moved down if 1 + * @param int $position new position of the moved image + * @return int success + */ + public function updatePosition($way, $position) + { + if (!isset($this->id) || !$position) { + return false; + } - // < and > statements rather than BETWEEN operator - // since BETWEEN is treated differently according to databases - $result = (Db::getInstance()->execute(' + // < and > statements rather than BETWEEN operator + // since BETWEEN is treated differently according to databases + $result = (Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'image` SET `position`= `position` '.($way ? '- 1' : '+ 1').' WHERE `position` '.($way - ? '> '.(int)$this->position.' AND `position` <= '.(int)$position - : '< '.(int)$this->position.' AND `position` >= '.(int)$position).' + ? '> '.(int)$this->position.' AND `position` <= '.(int)$position + : '< '.(int)$this->position.' AND `position` >= '.(int)$position).' AND `id_product`='.(int)$this->id_product) - && Db::getInstance()->execute(' + && Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'image` SET `position` = '.(int)$position.' WHERE `id_image` = '.(int)$this->id_image)); - return $result; - } + return $result; + } - public static function getSize($type) - { - if (!isset(self::$_cacheGetSize[$type]) || self::$_cacheGetSize[$type] === null) - self::$_cacheGetSize[$type] = Db::getInstance()->getRow(' + public static function getSize($type) + { + if (!isset(self::$_cacheGetSize[$type]) || self::$_cacheGetSize[$type] === null) { + self::$_cacheGetSize[$type] = Db::getInstance()->getRow(' SELECT `width`, `height` FROM '._DB_PREFIX_.'image_type WHERE `name` = \''.pSQL($type).'\' '); - return self::$_cacheGetSize[$type]; - } + } + return self::$_cacheGetSize[$type]; + } - public static function getWidth($params, &$smarty) - { - $result = self::getSize($params['type']); - return $result['width']; - } + public static function getWidth($params, &$smarty) + { + $result = self::getSize($params['type']); + return $result['width']; + } - public static function getHeight($params, &$smarty) - { - $result = self::getSize($params['type']); - return $result['height']; - } + public static function getHeight($params, &$smarty) + { + $result = self::getSize($params['type']); + return $result['height']; + } - /** - * Clear all images in tmp dir - */ - public static function clearTmpDir() - { - foreach (scandir(_PS_TMP_IMG_DIR_) as $d) - if (preg_match('/(.*)\.jpg$/', $d)) - unlink(_PS_TMP_IMG_DIR_.$d); - } - /** - * Delete Image - Product attribute associations for this image - */ - public function deleteProductAttributeImage() - { - return Db::getInstance()->execute(' + /** + * Clear all images in tmp dir + */ + public static function clearTmpDir() + { + foreach (scandir(_PS_TMP_IMG_DIR_) as $d) { + if (preg_match('/(.*)\.jpg$/', $d)) { + unlink(_PS_TMP_IMG_DIR_.$d); + } + } + } + /** + * Delete Image - Product attribute associations for this image + */ + public function deleteProductAttributeImage() + { + return Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'product_attribute_image` WHERE `id_image` = '.(int)$this->id - ); - } + ); + } - /** - * Delete the product image from disk and remove the containing folder if empty - * Handles both legacy and new image filesystems - */ - public function deleteImage($force_delete = false) - { - if (!$this->id) - return false; + /** + * Delete the product image from disk and remove the containing folder if empty + * Handles both legacy and new image filesystems + */ + public function deleteImage($force_delete = false) + { + if (!$this->id) { + return false; + } - // Delete base image - if (file_exists($this->image_dir.$this->getExistingImgPath().'.'.$this->image_format)) - unlink($this->image_dir.$this->getExistingImgPath().'.'.$this->image_format); - else - return false; + // Delete base image + if (file_exists($this->image_dir.$this->getExistingImgPath().'.'.$this->image_format)) { + unlink($this->image_dir.$this->getExistingImgPath().'.'.$this->image_format); + } else { + return false; + } - $files_to_delete = array(); + $files_to_delete = array(); - // Delete auto-generated images - $image_types = ImageType::getImagesTypes(); - foreach ($image_types as $image_type) - { - $files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-'.$image_type['name'].'.'.$this->image_format; - if (Configuration::get('WATERMARK_HASH')) - $files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-'.$image_type['name'].'-'.Configuration::get('WATERMARK_HASH').'.'.$this->image_format; - } + // Delete auto-generated images + $image_types = ImageType::getImagesTypes(); + foreach ($image_types as $image_type) { + $files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-'.$image_type['name'].'.'.$this->image_format; + if (Configuration::get('WATERMARK_HASH')) { + $files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-'.$image_type['name'].'-'.Configuration::get('WATERMARK_HASH').'.'.$this->image_format; + } + } - // Delete watermark image - $files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-watermark.'.$this->image_format; - // delete index.php - $files_to_delete[] = $this->image_dir.$this->getImgFolder().'index.php'; - // Delete tmp images - $files_to_delete[] = _PS_TMP_IMG_DIR_.'product_'.$this->id_product.'.'.$this->image_format; - $files_to_delete[] = _PS_TMP_IMG_DIR_.'product_mini_'.$this->id_product.'.'.$this->image_format; + // Delete watermark image + $files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-watermark.'.$this->image_format; + // delete index.php + $files_to_delete[] = $this->image_dir.$this->getImgFolder().'index.php'; + // Delete tmp images + $files_to_delete[] = _PS_TMP_IMG_DIR_.'product_'.$this->id_product.'.'.$this->image_format; + $files_to_delete[] = _PS_TMP_IMG_DIR_.'product_mini_'.$this->id_product.'.'.$this->image_format; - foreach ($files_to_delete as $file) - if (file_exists($file) && !@unlink($file)) - return false; + foreach ($files_to_delete as $file) { + if (file_exists($file) && !@unlink($file)) { + return false; + } + } - // Can we delete the image folder? - if (is_dir($this->image_dir.$this->getImgFolder())) - { - $delete_folder = true; - foreach (scandir($this->image_dir.$this->getImgFolder()) as $file) - if (($file != '.' && $file != '..')) - { - $delete_folder = false; - break; - } - } - if (isset($delete_folder) && $delete_folder) - @rmdir($this->image_dir.$this->getImgFolder()); + // Can we delete the image folder? + if (is_dir($this->image_dir.$this->getImgFolder())) { + $delete_folder = true; + foreach (scandir($this->image_dir.$this->getImgFolder()) as $file) { + if (($file != '.' && $file != '..')) { + $delete_folder = false; + break; + } + } + } + if (isset($delete_folder) && $delete_folder) { + @rmdir($this->image_dir.$this->getImgFolder()); + } - return true; - } + return true; + } - /** - * Recursively deletes all product images in the given folder tree and removes empty folders. - * - * @param string $path folder containing the product images to delete - * @param string $format image format - * @return bool success - */ - public static function deleteAllImages($path, $format = 'jpg') - { - if (!$path || !$format || !is_dir($path)) - return false; - foreach (scandir($path) as $file) - { - if (preg_match('/^[0-9]+(\-(.*))?\.'.$format.'$/', $file)) - unlink($path.$file); - elseif (is_dir($path.$file) && (preg_match('/^[0-9]$/', $file))) - Image::deleteAllImages($path.$file.'/', $format); - } + /** + * Recursively deletes all product images in the given folder tree and removes empty folders. + * + * @param string $path folder containing the product images to delete + * @param string $format image format + * @return bool success + */ + public static function deleteAllImages($path, $format = 'jpg') + { + if (!$path || !$format || !is_dir($path)) { + return false; + } + foreach (scandir($path) as $file) { + if (preg_match('/^[0-9]+(\-(.*))?\.'.$format.'$/', $file)) { + unlink($path.$file); + } elseif (is_dir($path.$file) && (preg_match('/^[0-9]$/', $file))) { + Image::deleteAllImages($path.$file.'/', $format); + } + } - // Can we remove the image folder? - if (is_numeric(basename($path))) - { - $remove_folder = true; - foreach (scandir($path) as $file) - if (($file != '.' && $file != '..' && $file != 'index.php')) - { - $remove_folder = false; - break; - } + // Can we remove the image folder? + if (is_numeric(basename($path))) { + $remove_folder = true; + foreach (scandir($path) as $file) { + if (($file != '.' && $file != '..' && $file != 'index.php')) { + $remove_folder = false; + break; + } + } - if ($remove_folder) - { - // we're only removing index.php if it's a folder we want to delete - if (file_exists($path.'index.php')) - @unlink ($path.'index.php'); - @rmdir($path); - } - } + if ($remove_folder) { + // we're only removing index.php if it's a folder we want to delete + if (file_exists($path.'index.php')) { + @unlink($path.'index.php'); + } + @rmdir($path); + } + } - return true; - } + return true; + } - /** - * Returns image path in the old or in the new filesystem - * - * @ returns string image path - */ - public function getExistingImgPath() - { - if (!$this->id) - return false; + /** + * Returns image path in the old or in the new filesystem + * + * @ returns string image path + */ + public function getExistingImgPath() + { + if (!$this->id) { + return false; + } - if (!$this->existing_path) - { - if (Configuration::get('PS_LEGACY_IMAGES') && file_exists(_PS_PROD_IMG_DIR_.$this->id_product.'-'.$this->id.'.'.$this->image_format)) - $this->existing_path = $this->id_product.'-'.$this->id; - else - $this->existing_path = $this->getImgPath(); - } + if (!$this->existing_path) { + if (Configuration::get('PS_LEGACY_IMAGES') && file_exists(_PS_PROD_IMG_DIR_.$this->id_product.'-'.$this->id.'.'.$this->image_format)) { + $this->existing_path = $this->id_product.'-'.$this->id; + } else { + $this->existing_path = $this->getImgPath(); + } + } - return $this->existing_path; - } + return $this->existing_path; + } - /** - * Returns the path to the folder containing the image in the new filesystem - * - * @return string path to folder - */ - public function getImgFolder() - { - if (!$this->id) - return false; + /** + * Returns the path to the folder containing the image in the new filesystem + * + * @return string path to folder + */ + public function getImgFolder() + { + if (!$this->id) { + return false; + } - if (!$this->folder) - $this->folder = Image::getImgFolderStatic($this->id); + if (!$this->folder) { + $this->folder = Image::getImgFolderStatic($this->id); + } - return $this->folder; - } + return $this->folder; + } - /** - * Create parent folders for the image in the new filesystem - * - * @return bool success - */ - public function createImgFolder() - { - if (!$this->id) - return false; + /** + * Create parent folders for the image in the new filesystem + * + * @return bool success + */ + public function createImgFolder() + { + if (!$this->id) { + return false; + } - if (!file_exists(_PS_PROD_IMG_DIR_.$this->getImgFolder())) - { - // Apparently sometimes mkdir cannot set the rights, and sometimes chmod can't. Trying both. - $success = @mkdir(_PS_PROD_IMG_DIR_.$this->getImgFolder(), self::$access_rights, true); - $chmod = @chmod(_PS_PROD_IMG_DIR_.$this->getImgFolder(), self::$access_rights); + if (!file_exists(_PS_PROD_IMG_DIR_.$this->getImgFolder())) { + // Apparently sometimes mkdir cannot set the rights, and sometimes chmod can't. Trying both. + $success = @mkdir(_PS_PROD_IMG_DIR_.$this->getImgFolder(), self::$access_rights, true); + $chmod = @chmod(_PS_PROD_IMG_DIR_.$this->getImgFolder(), self::$access_rights); - // Create an index.php file in the new folder - if (($success || $chmod) - && !file_exists(_PS_PROD_IMG_DIR_.$this->getImgFolder().'index.php') - && file_exists($this->source_index)) - return @copy($this->source_index, _PS_PROD_IMG_DIR_.$this->getImgFolder().'index.php'); - } - return true; - } + // Create an index.php file in the new folder + if (($success || $chmod) + && !file_exists(_PS_PROD_IMG_DIR_.$this->getImgFolder().'index.php') + && file_exists($this->source_index)) { + return @copy($this->source_index, _PS_PROD_IMG_DIR_.$this->getImgFolder().'index.php'); + } + } + return true; + } - /** - * Returns the path to the image without file extension - * - * @return string path - */ - public function getImgPath() - { - if (!$this->id) - return false; + /** + * Returns the path to the image without file extension + * + * @return string path + */ + public function getImgPath() + { + if (!$this->id) { + return false; + } - $path = $this->getImgFolder().$this->id; - return $path; - } + $path = $this->getImgFolder().$this->id; + return $path; + } - /** - * Returns the path to the folder containing the image in the new filesystem - * - * @param mixed $id_image - * @return string path to folder - */ - public static function getImgFolderStatic($id_image) - { - if (!is_numeric($id_image)) - return false; - $folders = str_split((string)$id_image); - return implode('/', $folders).'/'; - } + /** + * Returns the path to the folder containing the image in the new filesystem + * + * @param mixed $id_image + * @return string path to folder + */ + public static function getImgFolderStatic($id_image) + { + if (!is_numeric($id_image)) { + return false; + } + $folders = str_split((string)$id_image); + return implode('/', $folders).'/'; + } - /** - * Move all legacy product image files from the image folder root to their subfolder in the new filesystem. - * If max_execution_time is provided, stops before timeout and returns string "timeout". - * If any image cannot be moved, stops and returns "false" - * - * @param int $max_execution_time - * @return mixed success or timeout - */ - public static function moveToNewFileSystem($max_execution_time = 0) - { - $start_time = time(); - $image = null; - $tmp_folder = 'duplicates/'; - foreach (scandir(_PS_PROD_IMG_DIR_) as $file) - { - // matches the base product image or the thumbnails - if (preg_match('/^([0-9]+\-)([0-9]+)(\-(.*))?\.jpg$/', $file, $matches)) - { - // don't recreate an image object for each image type - if (!$image || $image->id !== (int)$matches[2]) - $image = new Image((int)$matches[2]); - // image exists in DB and with the correct product? - if (Validate::isLoadedObject($image) && $image->id_product == (int)rtrim($matches[1], '-')) - { - // create the new folder if it does not exist - if (!$image->createImgFolder()) - return false; + /** + * Move all legacy product image files from the image folder root to their subfolder in the new filesystem. + * If max_execution_time is provided, stops before timeout and returns string "timeout". + * If any image cannot be moved, stops and returns "false" + * + * @param int $max_execution_time + * @return mixed success or timeout + */ + public static function moveToNewFileSystem($max_execution_time = 0) + { + $start_time = time(); + $image = null; + $tmp_folder = 'duplicates/'; + foreach (scandir(_PS_PROD_IMG_DIR_) as $file) { + // matches the base product image or the thumbnails + if (preg_match('/^([0-9]+\-)([0-9]+)(\-(.*))?\.jpg$/', $file, $matches)) { + // don't recreate an image object for each image type + if (!$image || $image->id !== (int)$matches[2]) { + $image = new Image((int)$matches[2]); + } + // image exists in DB and with the correct product? + if (Validate::isLoadedObject($image) && $image->id_product == (int)rtrim($matches[1], '-')) { + // create the new folder if it does not exist + if (!$image->createImgFolder()) { + return false; + } - // if there's already a file at the new image path, move it to a dump folder - // most likely the preexisting image is a demo image not linked to a product and it's ok to replace it - $new_path = _PS_PROD_IMG_DIR_.$image->getImgPath().(isset($matches[3]) ? $matches[3] : '').'.jpg'; - if (file_exists($new_path)) - { - if (!file_exists(_PS_PROD_IMG_DIR_.$tmp_folder)) - { - @mkdir(_PS_PROD_IMG_DIR_.$tmp_folder, self::$access_rights); - @chmod(_PS_PROD_IMG_DIR_.$tmp_folder, self::$access_rights); - } - $tmp_path = _PS_PROD_IMG_DIR_.$tmp_folder.basename($file); - if (!@rename($new_path, $tmp_path) || !file_exists($tmp_path)) - return false; - } - // move the image - if (!@rename(_PS_PROD_IMG_DIR_.$file, $new_path) || !file_exists($new_path)) - return false; - } - } - if ((int)$max_execution_time != 0 && (time() - $start_time > (int)$max_execution_time - 4)) - return 'timeout'; - } - return true; - } + // if there's already a file at the new image path, move it to a dump folder + // most likely the preexisting image is a demo image not linked to a product and it's ok to replace it + $new_path = _PS_PROD_IMG_DIR_.$image->getImgPath().(isset($matches[3]) ? $matches[3] : '').'.jpg'; + if (file_exists($new_path)) { + if (!file_exists(_PS_PROD_IMG_DIR_.$tmp_folder)) { + @mkdir(_PS_PROD_IMG_DIR_.$tmp_folder, self::$access_rights); + @chmod(_PS_PROD_IMG_DIR_.$tmp_folder, self::$access_rights); + } + $tmp_path = _PS_PROD_IMG_DIR_.$tmp_folder.basename($file); + if (!@rename($new_path, $tmp_path) || !file_exists($tmp_path)) { + return false; + } + } + // move the image + if (!@rename(_PS_PROD_IMG_DIR_.$file, $new_path) || !file_exists($new_path)) { + return false; + } + } + } + if ((int)$max_execution_time != 0 && (time() - $start_time > (int)$max_execution_time - 4)) { + return 'timeout'; + } + } + return true; + } - /** - * Try to create and delete some folders to check if moving images to new file system will be possible - * - * @return bool success - */ - public static function testFileSystem() - { - $safe_mode = Tools::getSafeModeStatus(); - if ($safe_mode) - return false; - $folder1 = _PS_PROD_IMG_DIR_.'testfilesystem/'; - $test_folder = $folder1.'testsubfolder/'; - // check if folders are already existing from previous failed test - if (file_exists($test_folder)) - { - @rmdir($test_folder); - @rmdir($folder1); - } - if (file_exists($test_folder)) - return false; + /** + * Try to create and delete some folders to check if moving images to new file system will be possible + * + * @return bool success + */ + public static function testFileSystem() + { + $safe_mode = Tools::getSafeModeStatus(); + if ($safe_mode) { + return false; + } + $folder1 = _PS_PROD_IMG_DIR_.'testfilesystem/'; + $test_folder = $folder1.'testsubfolder/'; + // check if folders are already existing from previous failed test + if (file_exists($test_folder)) { + @rmdir($test_folder); + @rmdir($folder1); + } + if (file_exists($test_folder)) { + return false; + } - @mkdir($test_folder, self::$access_rights, true); - @chmod($test_folder, self::$access_rights); - if (!is_writeable($test_folder)) - return false; - @rmdir($test_folder); - @rmdir($folder1); - if (file_exists($folder1)) - return false; - return true; - } + @mkdir($test_folder, self::$access_rights, true); + @chmod($test_folder, self::$access_rights); + if (!is_writeable($test_folder)) { + return false; + } + @rmdir($test_folder); + @rmdir($folder1); + if (file_exists($folder1)) { + return false; + } + return true; + } - /** - * Returns the path where a product image should be created (without file format) - * - * @return string path - */ - public function getPathForCreation() - { - if (!$this->id) - return false; - if (Configuration::get('PS_LEGACY_IMAGES')) - { - if (!$this->id_product) - return false; - $path = $this->id_product.'-'.$this->id; - } - else - { - $path = $this->getImgPath(); - $this->createImgFolder(); - } - return _PS_PROD_IMG_DIR_.$path; - } + /** + * Returns the path where a product image should be created (without file format) + * + * @return string path + */ + public function getPathForCreation() + { + if (!$this->id) { + return false; + } + if (Configuration::get('PS_LEGACY_IMAGES')) { + if (!$this->id_product) { + return false; + } + $path = $this->id_product.'-'.$this->id; + } else { + $path = $this->getImgPath(); + $this->createImgFolder(); + } + return _PS_PROD_IMG_DIR_.$path; + } } diff --git a/classes/ImageManager.php b/classes/ImageManager.php index a4388f5a..5f000c38 100644 --- a/classes/ImageManager.php +++ b/classes/ImageManager.php @@ -31,540 +31,548 @@ */ class ImageManagerCore { - const ERROR_FILE_NOT_EXIST = 1; - const ERROR_FILE_WIDTH = 2; - const ERROR_MEMORY_LIMIT = 3; + const ERROR_FILE_NOT_EXIST = 1; + const ERROR_FILE_WIDTH = 2; + const ERROR_MEMORY_LIMIT = 3; - /** - * Generate a cached thumbnail for object lists (eg. carrier, order statuses...etc) - * - * @param string $image Real image filename - * @param string $cache_image Cached filename - * @param int $size Desired size - * @param string $image_type Image type - * @param bool $disable_cache When turned on a timestamp will be added to the image URI to disable the HTTP cache - * @param bool $regenerate When turned on and the file already exist, the file will be regenerated - * @return string - */ - public static function thumbnail($image, $cache_image, $size, $image_type = 'jpg', $disable_cache = true, $regenerate = false) - { - if (!file_exists($image)) - return ''; + /** + * Generate a cached thumbnail for object lists (eg. carrier, order statuses...etc) + * + * @param string $image Real image filename + * @param string $cache_image Cached filename + * @param int $size Desired size + * @param string $image_type Image type + * @param bool $disable_cache When turned on a timestamp will be added to the image URI to disable the HTTP cache + * @param bool $regenerate When turned on and the file already exist, the file will be regenerated + * @return string + */ + public static function thumbnail($image, $cache_image, $size, $image_type = 'jpg', $disable_cache = true, $regenerate = false) + { + if (!file_exists($image)) { + return ''; + } - if (file_exists(_PS_TMP_IMG_DIR_.$cache_image) && $regenerate) - @unlink(_PS_TMP_IMG_DIR_.$cache_image); + if (file_exists(_PS_TMP_IMG_DIR_.$cache_image) && $regenerate) { + @unlink(_PS_TMP_IMG_DIR_.$cache_image); + } - if ($regenerate || !file_exists(_PS_TMP_IMG_DIR_.$cache_image)) - { - $infos = getimagesize($image); + if ($regenerate || !file_exists(_PS_TMP_IMG_DIR_.$cache_image)) { + $infos = getimagesize($image); - // Evaluate the memory required to resize the image: if it's too much, you can't resize it. - if (!ImageManager::checkImageMemoryLimit($image)) - return false; + // Evaluate the memory required to resize the image: if it's too much, you can't resize it. + if (!ImageManager::checkImageMemoryLimit($image)) { + return false; + } - $x = $infos[0]; - $y = $infos[1]; - $max_x = $size * 3; + $x = $infos[0]; + $y = $infos[1]; + $max_x = $size * 3; - // Size is already ok - if ($y < $size && $x <= $max_x) - copy($image, _PS_TMP_IMG_DIR_.$cache_image); - // We need to resize */ - else - { - $ratio_x = $x / ($y / $size); - if ($ratio_x > $max_x) - { - $ratio_x = $max_x; - $size = $y / ($x / $max_x); - } + // Size is already ok + if ($y < $size && $x <= $max_x) { + copy($image, _PS_TMP_IMG_DIR_.$cache_image); + } + // We need to resize */ + else { + $ratio_x = $x / ($y / $size); + if ($ratio_x > $max_x) { + $ratio_x = $max_x; + $size = $y / ($x / $max_x); + } - ImageManager::resize($image, _PS_TMP_IMG_DIR_.$cache_image, $ratio_x, $size, $image_type); - } - } - // Relative link will always work, whatever the base uri set in the admin - if (Context::getContext()->controller->controller_type == 'admin') - return ''; - else - return ''; - } + ImageManager::resize($image, _PS_TMP_IMG_DIR_.$cache_image, $ratio_x, $size, $image_type); + } + } + // Relative link will always work, whatever the base uri set in the admin + if (Context::getContext()->controller->controller_type == 'admin') { + return ''; + } else { + return ''; + } + } - /** - * Check if memory limit is too long or not - * - * @param $image - * @return bool - */ - public static function checkImageMemoryLimit($image) - { - $infos = @getimagesize($image); + /** + * Check if memory limit is too long or not + * + * @param $image + * @return bool + */ + public static function checkImageMemoryLimit($image) + { + $infos = @getimagesize($image); - if (!is_array($infos) || !isset($infos['bits'])) - return true; + if (!is_array($infos) || !isset($infos['bits'])) { + return true; + } - $memory_limit = Tools::getMemoryLimit(); - // memory_limit == -1 => unlimited memory - if (function_exists('memory_get_usage') && (int)$memory_limit != -1) - { - $current_memory = memory_get_usage(); - $channel = isset($infos['channels']) ? ($infos['channels'] / 8) : 1; + $memory_limit = Tools::getMemoryLimit(); + // memory_limit == -1 => unlimited memory + if (function_exists('memory_get_usage') && (int)$memory_limit != -1) { + $current_memory = memory_get_usage(); + $channel = isset($infos['channels']) ? ($infos['channels'] / 8) : 1; - // Evaluate the memory required to resize the image: if it's too much, you can't resize it. - if (($infos[0] * $infos[1] * $infos['bits'] * $channel + pow(2, 16)) * 1.8 + $current_memory > $memory_limit - 1024 * 1024) - return false; - } + // Evaluate the memory required to resize the image: if it's too much, you can't resize it. + // For perfs, avoid computing static maths formulas in the code. pow(2, 16) = 65536 ; 1024 * 1024 = 1048576 + if (($infos[0] * $infos[1] * $infos['bits'] * $channel + 65536) * 1.8 + $current_memory > $memory_limit - 1048576) { + return false; + } + } - return true; - } + return true; + } - /** - * Resize, cut and optimize image - * - * @param string $src_file Image object from $_FILE - * @param string $dst_file Destination filename - * @param int $dst_width Desired width (optional) - * @param int $dst_height Desired height (optional) - * @param string $file_type - * @param bool $force_type - * @param int $error - * @param int $tgt_width - * @param int $tgt_height - * @param int $quality - * @param int $src_width - * @param int $src_height - * @return bool Operation result - */ - public static function resize($src_file, $dst_file, $dst_width = null, $dst_height = null, $file_type = 'jpg', - $force_type = false, &$error = 0, &$tgt_width = null, &$tgt_height = null, $quality = 5, - &$src_width = null, &$src_height = null) - { - if (PHP_VERSION_ID < 50300) - clearstatcache(); - else - clearstatcache(true, $src_file); + /** + * Resize, cut and optimize image + * + * @param string $src_file Image object from $_FILE + * @param string $dst_file Destination filename + * @param int $dst_width Desired width (optional) + * @param int $dst_height Desired height (optional) + * @param string $file_type + * @param bool $force_type + * @param int $error + * @param int $tgt_width + * @param int $tgt_height + * @param int $quality + * @param int $src_width + * @param int $src_height + * @return bool Operation result + */ + public static function resize($src_file, $dst_file, $dst_width = null, $dst_height = null, $file_type = 'jpg', + $force_type = false, &$error = 0, &$tgt_width = null, &$tgt_height = null, $quality = 5, + &$src_width = null, &$src_height = null) + { + if (PHP_VERSION_ID < 50300) { + clearstatcache(); + } else { + clearstatcache(true, $src_file); + } - if (!file_exists($src_file) || !filesize($src_file)) - return !($error = self::ERROR_FILE_NOT_EXIST); + if (!file_exists($src_file) || !filesize($src_file)) { + return !($error = self::ERROR_FILE_NOT_EXIST); + } - list($tmp_width, $tmp_height, $type) = getimagesize($src_file); - $rotate = 0; - if (function_exists('exif_read_data') && function_exists('mb_strtolower')) - { - $exif = @exif_read_data($src_file); + list($tmp_width, $tmp_height, $type) = getimagesize($src_file); + $rotate = 0; + if (function_exists('exif_read_data') && function_exists('mb_strtolower')) { + $exif = @exif_read_data($src_file); - if ($exif && isset($exif['Orientation'])) - { - switch ($exif['Orientation']) - { - case 3: - $src_width = $tmp_width; - $src_height = $tmp_height; - $rotate = 180; - break; + if ($exif && isset($exif['Orientation'])) { + switch ($exif['Orientation']) { + case 3: + $src_width = $tmp_width; + $src_height = $tmp_height; + $rotate = 180; + break; - case 6: - $src_width = $tmp_height; - $src_height = $tmp_width; - $rotate = -90; - break; + case 6: + $src_width = $tmp_height; + $src_height = $tmp_width; + $rotate = -90; + break; - case 8: - $src_width = $tmp_height; - $src_height = $tmp_width; - $rotate = 90; - break; + case 8: + $src_width = $tmp_height; + $src_height = $tmp_width; + $rotate = 90; + break; - default: - $src_width = $tmp_width; - $src_height = $tmp_height; - } - } - else - { - $src_width = $tmp_width; - $src_height = $tmp_height; - } - } - else - { - $src_width = $tmp_width; - $src_height = $tmp_height; - } + default: + $src_width = $tmp_width; + $src_height = $tmp_height; + } + } else { + $src_width = $tmp_width; + $src_height = $tmp_height; + } + } else { + $src_width = $tmp_width; + $src_height = $tmp_height; + } - // If PS_IMAGE_QUALITY is activated, the generated image will be a PNG with .jpg as a file extension. - // This allow for higher quality and for transparency. JPG source files will also benefit from a higher quality - // because JPG reencoding by GD, even with max quality setting, degrades the image. - if (Configuration::get('PS_IMAGE_QUALITY') == 'png_all' - || (Configuration::get('PS_IMAGE_QUALITY') == 'png' && $type == IMAGETYPE_PNG) && !$force_type) - $file_type = 'png'; + // If PS_IMAGE_QUALITY is activated, the generated image will be a PNG with .jpg as a file extension. + // This allow for higher quality and for transparency. JPG source files will also benefit from a higher quality + // because JPG reencoding by GD, even with max quality setting, degrades the image. + if (Configuration::get('PS_IMAGE_QUALITY') == 'png_all' + || (Configuration::get('PS_IMAGE_QUALITY') == 'png' && $type == IMAGETYPE_PNG) && !$force_type) { + $file_type = 'png'; + } - if (!$src_width) - return !($error = self::ERROR_FILE_WIDTH); - if (!$dst_width) - $dst_width = $src_width; - if (!$dst_height) - $dst_height = $src_height; + if (!$src_width) { + return !($error = self::ERROR_FILE_WIDTH); + } + if (!$dst_width) { + $dst_width = $src_width; + } + if (!$dst_height) { + $dst_height = $src_height; + } - $width_diff = $dst_width / $src_width; - $height_diff = $dst_height / $src_height; + $width_diff = $dst_width / $src_width; + $height_diff = $dst_height / $src_height; - $ps_image_generation_method = Configuration::get('PS_IMAGE_GENERATION_METHOD'); - if ($width_diff > 1 && $height_diff > 1) - { - $next_width = $src_width; - $next_height = $src_height; - } - else - { - if ($ps_image_generation_method == 2 || (!$ps_image_generation_method && $width_diff > $height_diff)) - { - $next_height = $dst_height; - $next_width = round(($src_width * $next_height) / $src_height); - $dst_width = (int)(!$ps_image_generation_method ? $dst_width : $next_width); - } - else - { - $next_width = $dst_width; - $next_height = round($src_height * $dst_width / $src_width); - $dst_height = (int)(!$ps_image_generation_method ? $dst_height : $next_height); - } - } + $ps_image_generation_method = Configuration::get('PS_IMAGE_GENERATION_METHOD'); + if ($width_diff > 1 && $height_diff > 1) { + $next_width = $src_width; + $next_height = $src_height; + } else { + if ($ps_image_generation_method == 2 || (!$ps_image_generation_method && $width_diff > $height_diff)) { + $next_height = $dst_height; + $next_width = round(($src_width * $next_height) / $src_height); + $dst_width = (int)(!$ps_image_generation_method ? $dst_width : $next_width); + } else { + $next_width = $dst_width; + $next_height = round($src_height * $dst_width / $src_width); + $dst_height = (int)(!$ps_image_generation_method ? $dst_height : $next_height); + } + } - if (!ImageManager::checkImageMemoryLimit($src_file)) - return !($error = self::ERROR_MEMORY_LIMIT); + if (!ImageManager::checkImageMemoryLimit($src_file)) { + return !($error = self::ERROR_MEMORY_LIMIT); + } - $tgt_width = $dst_width; - $tgt_height = $dst_height; + $tgt_width = $dst_width; + $tgt_height = $dst_height; - $dest_image = imagecreatetruecolor($dst_width, $dst_height); + $dest_image = imagecreatetruecolor($dst_width, $dst_height); - // If image is a PNG and the output is PNG, fill with transparency. Else fill with white background. - if ($file_type == 'png' && $type == IMAGETYPE_PNG) - { - imagealphablending($dest_image, false); - imagesavealpha($dest_image, true); - $transparent = imagecolorallocatealpha($dest_image, 255, 255, 255, 127); - imagefilledrectangle($dest_image, 0, 0, $dst_width, $dst_height, $transparent); - } - else - { - $white = imagecolorallocate($dest_image, 255, 255, 255); - imagefilledrectangle ($dest_image, 0, 0, $dst_width, $dst_height, $white); - } + // If image is a PNG and the output is PNG, fill with transparency. Else fill with white background. + if ($file_type == 'png' && $type == IMAGETYPE_PNG) { + imagealphablending($dest_image, false); + imagesavealpha($dest_image, true); + $transparent = imagecolorallocatealpha($dest_image, 255, 255, 255, 127); + imagefilledrectangle($dest_image, 0, 0, $dst_width, $dst_height, $transparent); + } else { + $white = imagecolorallocate($dest_image, 255, 255, 255); + imagefilledrectangle($dest_image, 0, 0, $dst_width, $dst_height, $white); + } - $src_image = ImageManager::create($type, $src_file); - if ($rotate) - $src_image = imagerotate($src_image, $rotate, 0); + $src_image = ImageManager::create($type, $src_file); + if ($rotate) { + $src_image = imagerotate($src_image, $rotate, 0); + } - if ($dst_width >= $src_width && $dst_height >= $src_height) - imagecopyresized($dest_image, $src_image, (int)(($dst_width - $next_width) / 2), (int)(($dst_height - $next_height) / 2), 0, 0, $next_width, $next_height, $src_width, $src_height); - else - ImageManager::imagecopyresampled($dest_image, $src_image, (int)(($dst_width - $next_width) / 2), (int)(($dst_height - $next_height) / 2), 0, 0, $next_width, $next_height, $src_width, $src_height, $quality); - $write_file = ImageManager::write($file_type, $dest_image, $dst_file); - @imagedestroy($src_image); - return $write_file; - } + if ($dst_width >= $src_width && $dst_height >= $src_height) { + imagecopyresized($dest_image, $src_image, (int)(($dst_width - $next_width) / 2), (int)(($dst_height - $next_height) / 2), 0, 0, $next_width, $next_height, $src_width, $src_height); + } else { + ImageManager::imagecopyresampled($dest_image, $src_image, (int)(($dst_width - $next_width) / 2), (int)(($dst_height - $next_height) / 2), 0, 0, $next_width, $next_height, $src_width, $src_height, $quality); + } + $write_file = ImageManager::write($file_type, $dest_image, $dst_file); + @imagedestroy($src_image); + return $write_file; + } - public static function imagecopyresampled(&$dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h, $quality = 3) - { - // Plug-and-Play fastimagecopyresampled function replaces much slower imagecopyresampled. - // Just include this function and change all "imagecopyresampled" references to "fastimagecopyresampled". - // Typically from 30 to 60 times faster when reducing high resolution images down to thumbnail size using the default quality setting. - // Author: Tim Eckel - Date: 09/07/07 - Version: 1.1 - Project: FreeRingers.net - Freely distributable - These comments must remain. - // - // Optional "quality" parameter (defaults is 3). Fractional values are allowed, for example 1.5. Must be greater than zero. - // Between 0 and 1 = Fast, but mosaic results, closer to 0 increases the mosaic effect. - // 1 = Up to 350 times faster. Poor results, looks very similar to imagecopyresized. - // 2 = Up to 95 times faster. Images appear a little sharp, some prefer this over a quality of 3. - // 3 = Up to 60 times faster. Will give high quality smooth results very close to imagecopyresampled, just faster. - // 4 = Up to 25 times faster. Almost identical to imagecopyresampled for most images. - // 5 = No speedup. Just uses imagecopyresampled, no advantage over imagecopyresampled. + public static function imagecopyresampled(&$dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h, $quality = 3) + { + // Plug-and-Play fastimagecopyresampled function replaces much slower imagecopyresampled. + // Just include this function and change all "imagecopyresampled" references to "fastimagecopyresampled". + // Typically from 30 to 60 times faster when reducing high resolution images down to thumbnail size using the default quality setting. + // Author: Tim Eckel - Date: 09/07/07 - Version: 1.1 - Project: FreeRingers.net - Freely distributable - These comments must remain. + // + // Optional "quality" parameter (defaults is 3). Fractional values are allowed, for example 1.5. Must be greater than zero. + // Between 0 and 1 = Fast, but mosaic results, closer to 0 increases the mosaic effect. + // 1 = Up to 350 times faster. Poor results, looks very similar to imagecopyresized. + // 2 = Up to 95 times faster. Images appear a little sharp, some prefer this over a quality of 3. + // 3 = Up to 60 times faster. Will give high quality smooth results very close to imagecopyresampled, just faster. + // 4 = Up to 25 times faster. Almost identical to imagecopyresampled for most images. + // 5 = No speedup. Just uses imagecopyresampled, no advantage over imagecopyresampled. - if (empty($src_image) || empty($dst_image) || $quality <= 0) - return false; - if ($quality < 5 && (($dst_w * $quality) < $src_w || ($dst_h * $quality) < $src_h)) - { - $temp = imagecreatetruecolor ($dst_w * $quality + 1, $dst_h * $quality + 1); - imagecopyresized ($temp, $src_image, 0, 0, $src_x, $src_y, $dst_w * $quality + 1, $dst_h * $quality + 1, $src_w, $src_h); - imagecopyresampled ($dst_image, $temp, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $dst_w * $quality, $dst_h * $quality); - imagedestroy ($temp); - } - else - imagecopyresampled ($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); - return true; - } + if (empty($src_image) || empty($dst_image) || $quality <= 0) { + return false; + } + if ($quality < 5 && (($dst_w * $quality) < $src_w || ($dst_h * $quality) < $src_h)) { + $temp = imagecreatetruecolor($dst_w * $quality + 1, $dst_h * $quality + 1); + imagecopyresized($temp, $src_image, 0, 0, $src_x, $src_y, $dst_w * $quality + 1, $dst_h * $quality + 1, $src_w, $src_h); + imagecopyresampled($dst_image, $temp, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $dst_w * $quality, $dst_h * $quality); + imagedestroy($temp); + } else { + imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); + } + return true; + } - /** - * Check if file is a real image - * - * @param string $filename File path to check - * @param string $file_mime_type File known mime type (generally from $_FILES) - * @param array $mime_type_list Allowed MIME types - * @return bool - */ - public static function isRealImage($filename, $file_mime_type = null, $mime_type_list = null) - { - // Detect mime content type - $mime_type = false; - if (!$mime_type_list) - $mime_type_list = array('image/gif', 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png'); + /** + * Check if file is a real image + * + * @param string $filename File path to check + * @param string $file_mime_type File known mime type (generally from $_FILES) + * @param array $mime_type_list Allowed MIME types + * @return bool + */ + public static function isRealImage($filename, $file_mime_type = null, $mime_type_list = null) + { + // Detect mime content type + $mime_type = false; + if (!$mime_type_list) { + $mime_type_list = array('image/gif', 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png'); + } - // Try 4 different methods to determine the mime type - if (function_exists('getimagesize')) - { - $image_info = @getimagesize($filename); + // Try 4 different methods to determine the mime type + if (function_exists('getimagesize')) { + $image_info = @getimagesize($filename); - if ($image_info) - $mime_type = $image_info['mime']; - else - $file_mime_type = false; - } - elseif (function_exists('finfo_open')) - { - $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME; - $finfo = finfo_open($const); - $mime_type = finfo_file($finfo, $filename); - finfo_close($finfo); - } - elseif (function_exists('mime_content_type')) - $mime_type = mime_content_type($filename); - elseif (function_exists('exec')) - { - $mime_type = trim(exec('file -b --mime-type '.escapeshellarg($filename))); - if (!$mime_type) - $mime_type = trim(exec('file --mime '.escapeshellarg($filename))); - if (!$mime_type) - $mime_type = trim(exec('file -bi '.escapeshellarg($filename))); - } + if ($image_info) { + $mime_type = $image_info['mime']; + } else { + $file_mime_type = false; + } + } elseif (function_exists('finfo_open')) { + $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME; + $finfo = finfo_open($const); + $mime_type = finfo_file($finfo, $filename); + finfo_close($finfo); + } elseif (function_exists('mime_content_type')) { + $mime_type = mime_content_type($filename); + } elseif (function_exists('exec')) { + $mime_type = trim(exec('file -b --mime-type '.escapeshellarg($filename))); + if (!$mime_type) { + $mime_type = trim(exec('file --mime '.escapeshellarg($filename))); + } + if (!$mime_type) { + $mime_type = trim(exec('file -bi '.escapeshellarg($filename))); + } + } - if ($file_mime_type && (empty($mime_type) || $mime_type == 'regular file' || $mime_type == 'text/plain')) - $mime_type = $file_mime_type; + if ($file_mime_type && (empty($mime_type) || $mime_type == 'regular file' || $mime_type == 'text/plain')) { + $mime_type = $file_mime_type; + } - // For each allowed MIME type, we are looking for it inside the current MIME type - foreach ($mime_type_list as $type) - if (strstr($mime_type, $type)) - return true; + // For each allowed MIME type, we are looking for it inside the current MIME type + foreach ($mime_type_list as $type) { + if (strstr($mime_type, $type)) { + return true; + } + } - return false; - } + return false; + } - /** - * Check if image file extension is correct - * - * @param string $filename Real filename - * @param array|null $authorized_extensions - * @return bool True if it's correct - */ - public static function isCorrectImageFileExt($filename, $authorized_extensions = null) - { - // Filter on file extension - if ($authorized_extensions === null) - $authorized_extensions = array('gif', 'jpg', 'jpeg', 'jpe', 'png'); - $name_explode = explode('.', $filename); - if (count($name_explode) >= 2) - { - $current_extension = strtolower($name_explode[count($name_explode) - 1]); - if (!in_array($current_extension, $authorized_extensions)) - return false; - } - else - return false; + /** + * Check if image file extension is correct + * + * @param string $filename Real filename + * @param array|null $authorized_extensions + * @return bool True if it's correct + */ + public static function isCorrectImageFileExt($filename, $authorized_extensions = null) + { + // Filter on file extension + if ($authorized_extensions === null) { + $authorized_extensions = array('gif', 'jpg', 'jpeg', 'jpe', 'png'); + } + $name_explode = explode('.', $filename); + if (count($name_explode) >= 2) { + $current_extension = strtolower($name_explode[count($name_explode) - 1]); + if (!in_array($current_extension, $authorized_extensions)) { + return false; + } + } else { + return false; + } - return true; - } + return true; + } - /** - * Validate image upload (check image type and weight) - * - * @param array $file Upload $_FILE value - * @param int $max_file_size Maximum upload size - * @return bool|string Return false if no error encountered - */ - public static function validateUpload($file, $max_file_size = 0, $types = null) - { - if ((int)$max_file_size > 0 && $file['size'] > (int)$max_file_size) - return sprintf(Tools::displayError('Image is too large (%1$d kB). Maximum allowed: %2$d kB'), $file['size'] / 1024, $max_file_size / 1024); - if (!ImageManager::isRealImage($file['tmp_name'], $file['type']) || !ImageManager::isCorrectImageFileExt($file['name'], $types) || preg_match('/\%00/', $file['name'])) - return Tools::displayError('Image format not recognized, allowed formats are: .gif, .jpg, .png'); - if ($file['error']) - return sprintf(Tools::displayError('Error while uploading image; please change your server\'s settings. (Error code: %s)'), $file['error']); - return false; - } + /** + * Validate image upload (check image type and weight) + * + * @param array $file Upload $_FILE value + * @param int $max_file_size Maximum upload size + * @return bool|string Return false if no error encountered + */ + public static function validateUpload($file, $max_file_size = 0, $types = null) + { + if ((int)$max_file_size > 0 && $file['size'] > (int)$max_file_size) { + return sprintf(Tools::displayError('Image is too large (%1$d kB). Maximum allowed: %2$d kB'), $file['size'] / 1024, $max_file_size / 1024); + } + if (!ImageManager::isRealImage($file['tmp_name'], $file['type']) || !ImageManager::isCorrectImageFileExt($file['name'], $types) || preg_match('/\%00/', $file['name'])) { + return Tools::displayError('Image format not recognized, allowed formats are: .gif, .jpg, .png'); + } + if ($file['error']) { + return sprintf(Tools::displayError('Error while uploading image; please change your server\'s settings. (Error code: %s)'), $file['error']); + } + return false; + } - /** - * Validate icon upload - * - * @param array $file Upload $_FILE value - * @param int $max_file_size Maximum upload size - * @return bool|string Return false if no error encountered - */ - public static function validateIconUpload($file, $max_file_size = 0) - { - if ((int)$max_file_size > 0 && $file['size'] > $max_file_size) - return sprintf( - Tools::displayError('Image is too large (%1$d kB). Maximum allowed: %2$d kB'), - $file['size'] / 1000, - $max_file_size / 1000 - ); - if (substr($file['name'], -4) != '.ico') - return Tools::displayError('Image format not recognized, allowed formats are: .ico'); - if ($file['error']) - return Tools::displayError('Error while uploading image; please change your server\'s settings.'); - return false; - } + /** + * Validate icon upload + * + * @param array $file Upload $_FILE value + * @param int $max_file_size Maximum upload size + * @return bool|string Return false if no error encountered + */ + public static function validateIconUpload($file, $max_file_size = 0) + { + if ((int)$max_file_size > 0 && $file['size'] > $max_file_size) { + return sprintf( + Tools::displayError('Image is too large (%1$d kB). Maximum allowed: %2$d kB'), + $file['size'] / 1000, + $max_file_size / 1000 + ); + } + if (substr($file['name'], -4) != '.ico') { + return Tools::displayError('Image format not recognized, allowed formats are: .ico'); + } + if ($file['error']) { + return Tools::displayError('Error while uploading image; please change your server\'s settings.'); + } + return false; + } - /** - * Cut image - * - * @param array $src_file Origin filename - * @param string $dst_file Destination filename - * @param int $dst_width Desired width - * @param int $dst_height Desired height - * @param string $file_type - * @param int $dst_x - * @param int $dst_y - * - * @return bool Operation result - */ - public static function cut($src_file, $dst_file, $dst_width = null, $dst_height = null, $file_type = 'jpg', $dst_x = 0, $dst_y = 0) - { - if (!file_exists($src_file)) - return false; + /** + * Cut image + * + * @param array $src_file Origin filename + * @param string $dst_file Destination filename + * @param int $dst_width Desired width + * @param int $dst_height Desired height + * @param string $file_type + * @param int $dst_x + * @param int $dst_y + * + * @return bool Operation result + */ + public static function cut($src_file, $dst_file, $dst_width = null, $dst_height = null, $file_type = 'jpg', $dst_x = 0, $dst_y = 0) + { + if (!file_exists($src_file)) { + return false; + } - // Source information - $src_info = getimagesize($src_file); - $src = array( - 'width' => $src_info[0], - 'height' => $src_info[1], - 'ressource' => ImageManager::create($src_info[2], $src_file), - ); + // Source information + $src_info = getimagesize($src_file); + $src = array( + 'width' => $src_info[0], + 'height' => $src_info[1], + 'ressource' => ImageManager::create($src_info[2], $src_file), + ); - // Destination information - $dest = array(); - $dest['x'] = $dst_x; - $dest['y'] = $dst_y; - $dest['width'] = !is_null($dst_width) ? $dst_width : $src['width']; - $dest['height'] = !is_null($dst_height) ? $dst_height : $src['height']; - $dest['ressource'] = ImageManager::createWhiteImage($dest['width'], $dest['height']); + // Destination information + $dest = array(); + $dest['x'] = $dst_x; + $dest['y'] = $dst_y; + $dest['width'] = !is_null($dst_width) ? $dst_width : $src['width']; + $dest['height'] = !is_null($dst_height) ? $dst_height : $src['height']; + $dest['ressource'] = ImageManager::createWhiteImage($dest['width'], $dest['height']); - $white = imagecolorallocate($dest['ressource'], 255, 255, 255); - imagecopyresampled($dest['ressource'], $src['ressource'], 0, 0, $dest['x'], $dest['y'], $dest['width'], $dest['height'], $dest['width'], $dest['height']); - imagecolortransparent($dest['ressource'], $white); - $return = ImageManager::write($file_type, $dest['ressource'], $dst_file); - @imagedestroy($src['ressource']); - return $return; - } + $white = imagecolorallocate($dest['ressource'], 255, 255, 255); + imagecopyresampled($dest['ressource'], $src['ressource'], 0, 0, $dest['x'], $dest['y'], $dest['width'], $dest['height'], $dest['width'], $dest['height']); + imagecolortransparent($dest['ressource'], $white); + $return = ImageManager::write($file_type, $dest['ressource'], $dst_file); + @imagedestroy($src['ressource']); + return $return; + } - /** - * Create an image with GD extension from a given type - * - * @param string $type - * @param string $filename - * @return resource - */ - public static function create($type, $filename) - { - switch ($type) - { - case IMAGETYPE_GIF : - return imagecreatefromgif($filename); - break; + /** + * Create an image with GD extension from a given type + * + * @param string $type + * @param string $filename + * @return resource + */ + public static function create($type, $filename) + { + switch ($type) { + case IMAGETYPE_GIF : + return imagecreatefromgif($filename); + break; - case IMAGETYPE_PNG : - return imagecreatefrompng($filename); - break; + case IMAGETYPE_PNG : + return imagecreatefrompng($filename); + break; - case IMAGETYPE_JPEG : - default: - return imagecreatefromjpeg($filename); - break; - } - } + case IMAGETYPE_JPEG : + default: + return imagecreatefromjpeg($filename); + break; + } + } - /** - * Create an empty image with white background - * - * @param int $width - * @param int $height - * @return resource - */ - public static function createWhiteImage($width, $height) - { - $image = imagecreatetruecolor($width, $height); - $white = imagecolorallocate($image, 255, 255, 255); - imagefill($image, 0, 0, $white); - return $image; - } + /** + * Create an empty image with white background + * + * @param int $width + * @param int $height + * @return resource + */ + public static function createWhiteImage($width, $height) + { + $image = imagecreatetruecolor($width, $height); + $white = imagecolorallocate($image, 255, 255, 255); + imagefill($image, 0, 0, $white); + return $image; + } - /** - * Generate and write image - * - * @param string $type - * @param resource $resource - * @param string $filename - * @return bool - */ - public static function write($type, $resource, $filename) - { - static $ps_png_quality = null; - static $ps_jpeg_quality = null; + /** + * Generate and write image + * + * @param string $type + * @param resource $resource + * @param string $filename + * @return bool + */ + public static function write($type, $resource, $filename) + { + static $ps_png_quality = null; + static $ps_jpeg_quality = null; - if ($ps_png_quality === null) - $ps_png_quality = Configuration::get('PS_PNG_QUALITY'); + if ($ps_png_quality === null) { + $ps_png_quality = Configuration::get('PS_PNG_QUALITY'); + } - if ($ps_jpeg_quality === null) - $ps_jpeg_quality = Configuration::get('PS_JPEG_QUALITY'); + if ($ps_jpeg_quality === null) { + $ps_jpeg_quality = Configuration::get('PS_JPEG_QUALITY'); + } - switch ($type) - { - case 'gif': - $success = imagegif($resource, $filename); - break; + switch ($type) { + case 'gif': + $success = imagegif($resource, $filename); + break; - case 'png': - $quality = ($ps_png_quality === false ? 7 : $ps_png_quality); - $success = imagepng($resource, $filename, (int)$quality); - break; + case 'png': + $quality = ($ps_png_quality === false ? 7 : $ps_png_quality); + $success = imagepng($resource, $filename, (int)$quality); + break; - case 'jpg': - case 'jpeg': - default: - $quality = ($ps_jpeg_quality === false ? 90 : $ps_jpeg_quality); - imageinterlace($resource, 1); /// make it PROGRESSIVE - $success = imagejpeg($resource, $filename, (int)$quality); - break; - } - imagedestroy($resource); - @chmod($filename, 0664); - return $success; - } + case 'jpg': + case 'jpeg': + default: + $quality = ($ps_jpeg_quality === false ? 90 : $ps_jpeg_quality); + imageinterlace($resource, 1); /// make it PROGRESSIVE + $success = imagejpeg($resource, $filename, (int)$quality); + break; + } + imagedestroy($resource); + @chmod($filename, 0664); + return $success; + } - /** - * Return the mime type by the file extension - * - * @param string $file_name - * @return string - */ - public static function getMimeTypeByExtension($file_name) - { - $types = array( - 'image/gif' => array('gif'), - 'image/jpeg' => array('jpg', 'jpeg'), - 'image/png' => array('png') - ); - $extension = substr($file_name, strrpos($file_name, '.') + 1); + /** + * Return the mime type by the file extension + * + * @param string $file_name + * @return string + */ + public static function getMimeTypeByExtension($file_name) + { + $types = array( + 'image/gif' => array('gif'), + 'image/jpeg' => array('jpg', 'jpeg'), + 'image/png' => array('png') + ); + $extension = substr($file_name, strrpos($file_name, '.') + 1); - $mime_type = null; - foreach ($types as $mime => $exts) - if (in_array($extension, $exts)) - { - $mime_type = $mime; - break; - } + $mime_type = null; + foreach ($types as $mime => $exts) { + if (in_array($extension, $exts)) { + $mime_type = $mime; + break; + } + } - if ($mime_type === null) - $mime_type = 'image/jpeg'; + if ($mime_type === null) { + $mime_type = 'image/jpeg'; + } - return $mime_type; - } + return $mime_type; + } } diff --git a/classes/ImageType.php b/classes/ImageType.php index 9ba016e3..5ccbc36c 100644 --- a/classes/ImageType.php +++ b/classes/ImageType.php @@ -26,152 +26,157 @@ class ImageTypeCore extends ObjectModel { - public $id; + public $id; - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var int Width */ - public $width; + /** @var int Width */ + public $width; - /** @var int Height */ - public $height; + /** @var int Height */ + public $height; - /** @var bool Apply to products */ - public $products; + /** @var bool Apply to products */ + public $products; - /** @var int Apply to categories */ - public $categories; + /** @var int Apply to categories */ + public $categories; - /** @var int Apply to manufacturers */ - public $manufacturers; + /** @var int Apply to manufacturers */ + public $manufacturers; - /** @var int Apply to suppliers */ - public $suppliers; + /** @var int Apply to suppliers */ + public $suppliers; - /** @var int Apply to scenes */ - public $scenes; + /** @var int Apply to scenes */ + public $scenes; - /** @var int Apply to store */ - public $stores; + /** @var int Apply to store */ + public $stores; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'image_type', - 'primary' => 'id_image_type', - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isImageTypeName', 'required' => true, 'size' => 64), - 'width' => array('type' => self::TYPE_INT, 'validate' => 'isImageSize', 'required' => true), - 'height' => array('type' => self::TYPE_INT, 'validate' => 'isImageSize', 'required' => true), - 'categories' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'products' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'manufacturers' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'suppliers' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'scenes' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'stores' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'image_type', + 'primary' => 'id_image_type', + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isImageTypeName', 'required' => true, 'size' => 64), + 'width' => array('type' => self::TYPE_INT, 'validate' => 'isImageSize', 'required' => true), + 'height' => array('type' => self::TYPE_INT, 'validate' => 'isImageSize', 'required' => true), + 'categories' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'products' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'manufacturers' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'suppliers' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'scenes' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'stores' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + ), + ); - /** - * @var array Image types cache - */ - protected static $images_types_cache = array(); + /** + * @var array Image types cache + */ + protected static $images_types_cache = array(); - protected static $images_types_name_cache = array(); + protected static $images_types_name_cache = array(); - protected $webserviceParameters = array(); + protected $webserviceParameters = array(); - /** - * Returns image type definitions - * - * @param string|null Image type - * @param bool $order_by_size - * @return array Image type definitions - * @throws PrestaShopDatabaseException - */ - public static function getImagesTypes($type = null, $order_by_size = false) - { - if (!isset(self::$images_types_cache[$type])) - { - $where = 'WHERE 1'; - if (!empty($type)) - $where .= ' AND `'.bqSQL($type).'` = 1 '; + /** + * Returns image type definitions + * + * @param string|null Image type + * @param bool $order_by_size + * @return array Image type definitions + * @throws PrestaShopDatabaseException + */ + public static function getImagesTypes($type = null, $order_by_size = false) + { + if (!isset(self::$images_types_cache[$type])) { + $where = 'WHERE 1'; + if (!empty($type)) { + $where .= ' AND `'.bqSQL($type).'` = 1 '; + } - if ($order_by_size) - $query = 'SELECT * FROM `'._DB_PREFIX_.'image_type` '.$where.' ORDER BY `width` DESC, `height` DESC, `name`ASC'; - else - $query = 'SELECT * FROM `'._DB_PREFIX_.'image_type` '.$where.' ORDER BY `name` ASC'; + if ($order_by_size) { + $query = 'SELECT * FROM `'._DB_PREFIX_.'image_type` '.$where.' ORDER BY `width` DESC, `height` DESC, `name`ASC'; + } else { + $query = 'SELECT * FROM `'._DB_PREFIX_.'image_type` '.$where.' ORDER BY `name` ASC'; + } - self::$images_types_cache[$type] = Db::getInstance()->executeS($query); - } - return self::$images_types_cache[$type]; - } + self::$images_types_cache[$type] = Db::getInstance()->executeS($query); + } + return self::$images_types_cache[$type]; + } - /** - * Check if type already is already registered in database - * - * @param string $typeName Name - * @return int Number of results found - */ - public static function typeAlreadyExists($type_name) - { - if (!Validate::isImageTypeName($type_name)) - die(Tools::displayError()); + /** + * Check if type already is already registered in database + * + * @param string $typeName Name + * @return int Number of results found + */ + public static function typeAlreadyExists($type_name) + { + if (!Validate::isImageTypeName($type_name)) { + die(Tools::displayError()); + } - Db::getInstance()->executeS(' + Db::getInstance()->executeS(' SELECT `id_image_type` FROM `'._DB_PREFIX_.'image_type` WHERE `name` = \''.pSQL($type_name).'\''); - return Db::getInstance()->NumRows(); - } + return Db::getInstance()->NumRows(); + } - /** - * Finds image type definition by name and type - * @param string $name - * @param string $type - */ - public static function getByNameNType($name, $type = null, $order = 0) - { - static $is_passed = false; + /** + * Finds image type definition by name and type + * @param string $name + * @param string $type + */ + public static function getByNameNType($name, $type = null, $order = 0) + { + static $is_passed = false; - if (!isset(self::$images_types_name_cache[$name.'_'.$type.'_'.$order]) && !$is_passed) - { - $results = Db::getInstance()->ExecuteS('SELECT * FROM `'._DB_PREFIX_.'image_type`'); + if (!isset(self::$images_types_name_cache[$name.'_'.$type.'_'.$order]) && !$is_passed) { + $results = Db::getInstance()->ExecuteS('SELECT * FROM `'._DB_PREFIX_.'image_type`'); - $types = array('products', 'categories', 'manufacturers', 'suppliers', 'scenes', 'stores'); - $total = count($types); + $types = array('products', 'categories', 'manufacturers', 'suppliers', 'scenes', 'stores'); + $total = count($types); - foreach ($results as $result) - foreach ($result as $value) - for ($i = 0; $i < $total; ++$i) - self::$images_types_name_cache[$result['name'].'_'.$types[$i].'_'.$value] = $result; + foreach ($results as $result) { + foreach ($result as $value) { + for ($i = 0; $i < $total; ++$i) { + self::$images_types_name_cache[$result['name'].'_'.$types[$i].'_'.$value] = $result; + } + } + } - $is_passed = true; - } + $is_passed = true; + } - $return = false; - if (isset(self::$images_types_name_cache[$name.'_'.$type.'_'.$order])) - $return = self::$images_types_name_cache[$name.'_'.$type.'_'.$order]; - return $return; - } + $return = false; + if (isset(self::$images_types_name_cache[$name.'_'.$type.'_'.$order])) { + $return = self::$images_types_name_cache[$name.'_'.$type.'_'.$order]; + } + return $return; + } - public static function getFormatedName($name) - { - $theme_name = Context::getContext()->shop->theme_name; - $name_without_theme_name = str_replace(array('_'.$theme_name, $theme_name.'_'), '', $name); - - //check if the theme name is already in $name if yes only return $name - if (strstr($name, $theme_name) && self::getByNameNType($name)) - return $name; - elseif (self::getByNameNType($name_without_theme_name.'_'.$theme_name)) - return $name_without_theme_name.'_'.$theme_name; - elseif (self::getByNameNType($theme_name.'_'.$name_without_theme_name)) - return $theme_name.'_'.$name_without_theme_name; - else - return $name_without_theme_name.'_default'; - } + public static function getFormatedName($name) + { + $theme_name = Context::getContext()->shop->theme_name; + $name_without_theme_name = str_replace(array('_'.$theme_name, $theme_name.'_'), '', $name); + //check if the theme name is already in $name if yes only return $name + if (strstr($name, $theme_name) && self::getByNameNType($name)) { + return $name; + } elseif (self::getByNameNType($name_without_theme_name.'_'.$theme_name)) { + return $name_without_theme_name.'_'.$theme_name; + } elseif (self::getByNameNType($theme_name.'_'.$name_without_theme_name)) { + return $theme_name.'_'.$name_without_theme_name; + } else { + return $name_without_theme_name.'_default'; + } + } } diff --git a/classes/Language.php b/classes/Language.php index bfc4ca9c..5ae6ed1d 100644 --- a/classes/Language.php +++ b/classes/Language.php @@ -26,962 +26,1020 @@ class LanguageCore extends ObjectModel { - public $id; + public $id; - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var string 2-letter iso code */ - public $iso_code; + /** @var string 2-letter iso code */ + public $iso_code; - /** @var string 5-letter iso code */ - public $language_code; + /** @var string 5-letter iso code */ + public $language_code; - /** @var string date format http://http://php.net/manual/en/function.date.php with the date only */ - public $date_format_lite = 'Y-m-d'; + /** @var string date format http://http://php.net/manual/en/function.date.php with the date only */ + public $date_format_lite = 'Y-m-d'; - /** @var string date format http://http://php.net/manual/en/function.date.php with hours and minutes */ - public $date_format_full = 'Y-m-d H:i:s'; + /** @var string date format http://http://php.net/manual/en/function.date.php with hours and minutes */ + public $date_format_full = 'Y-m-d H:i:s'; - /** @var bool true if this language is right to left language */ - public $is_rtl = false; + /** @var bool true if this language is right to left language */ + public $is_rtl = false; - /** @var bool Status */ - public $active = true; + /** @var bool Status */ + public $active = true; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'lang', - 'primary' => 'id_lang', - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), - 'iso_code' => array('type' => self::TYPE_STRING, 'validate' => 'isLanguageIsoCode', 'required' => true, 'size' => 2), - 'language_code' => array('type' => self::TYPE_STRING, 'validate' => 'isLanguageCode', 'size' => 5), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'is_rtl' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'date_format_lite' => array('type' => self::TYPE_STRING, 'validate' => 'isPhpDateFormat', 'required' => true, 'size' => 32), - 'date_format_full' => array('type' => self::TYPE_STRING, 'validate' => 'isPhpDateFormat', 'required' => true, 'size' => 32), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'lang', + 'primary' => 'id_lang', + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), + 'iso_code' => array('type' => self::TYPE_STRING, 'validate' => 'isLanguageIsoCode', 'required' => true, 'size' => 2), + 'language_code' => array('type' => self::TYPE_STRING, 'validate' => 'isLanguageCode', 'size' => 5), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'is_rtl' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'date_format_lite' => array('type' => self::TYPE_STRING, 'validate' => 'isPhpDateFormat', 'required' => true, 'size' => 32), + 'date_format_full' => array('type' => self::TYPE_STRING, 'validate' => 'isPhpDateFormat', 'required' => true, 'size' => 32), + ), + ); - /** @var array Languages cache */ - protected static $_checkedLangs; - protected static $_LANGUAGES; - protected static $countActiveLanguages = array(); + /** @var array Languages cache */ + protected static $_checkedLangs; + protected static $_LANGUAGES; + protected static $countActiveLanguages = array(); - protected $webserviceParameters = array( - 'objectNodeName' => 'language', - 'objectsNodeName' => 'languages', - ); + protected $webserviceParameters = array( + 'objectNodeName' => 'language', + 'objectsNodeName' => 'languages', + ); - protected $translationsFilesAndVars = array( - 'fields' => '_FIELDS', - 'errors' => '_ERRORS', - 'admin' => '_LANGADM', - 'pdf' => '_LANGPDF', - 'tabs' => 'tabs', - ); + protected $translationsFilesAndVars = array( + 'fields' => '_FIELDS', + 'errors' => '_ERRORS', + 'admin' => '_LANGADM', + 'pdf' => '_LANGPDF', + 'tabs' => 'tabs', + ); - public function __construct($id = null, $id_lang = null) - { - parent::__construct($id); - } + public function __construct($id = null, $id_lang = null) + { + parent::__construct($id); + } - /** - * @see ObjectModel::getFields() - * @return array - */ - public function getFields() - { - $this->iso_code = strtolower($this->iso_code); - if (empty($this->language_code)) - $this->language_code = $this->iso_code; + /** + * @see ObjectModel::getFields() + * @return array + */ + public function getFields() + { + $this->iso_code = strtolower($this->iso_code); + if (empty($this->language_code)) { + $this->language_code = $this->iso_code; + } - return parent::getFields(); - } + return parent::getFields(); + } - /** - * Generate translations files - * - */ - protected function _generateFiles($newIso = null) - { - $iso_code = $newIso ? $newIso : $this->iso_code; + /** + * Generate translations files + * + */ + protected function _generateFiles($newIso = null) + { + $iso_code = $newIso ? $newIso : $this->iso_code; - if (!file_exists(_PS_TRANSLATIONS_DIR_.$iso_code)) - { - if (@mkdir(_PS_TRANSLATIONS_DIR_.$iso_code)) - @chmod(_PS_TRANSLATIONS_DIR_.$iso_code, 0777); - } + if (!file_exists(_PS_TRANSLATIONS_DIR_.$iso_code)) { + if (@mkdir(_PS_TRANSLATIONS_DIR_.$iso_code)) { + @chmod(_PS_TRANSLATIONS_DIR_.$iso_code, 0777); + } + } - foreach ($this->translationsFilesAndVars as $file => $var) - { - $path_file = _PS_TRANSLATIONS_DIR_.$iso_code.'/'.$file.'.php'; - if (!file_exists($path_file)) - if ($file != 'tabs') - @file_put_contents($path_file, 'translationsFilesAndVars as $file => $var) { + $path_file = _PS_TRANSLATIONS_DIR_.$iso_code.'/'.$file.'.php'; + if (!file_exists($path_file)) { + if ($file != 'tabs') { + @file_put_contents($path_file, ''); - else - @file_put_contents($path_file, ''); + } + } - @chmod($path_file, 0777); - } - } + @chmod($path_file, 0777); + } + } - /** - * Move translations files after editing language iso code - */ - public function moveToIso($newIso) - { - if ($newIso == $this->iso_code) - return true; + /** + * Move translations files after editing language iso code + */ + public function moveToIso($newIso) + { + if ($newIso == $this->iso_code) { + return true; + } - if (file_exists(_PS_TRANSLATIONS_DIR_.$this->iso_code)) - rename(_PS_TRANSLATIONS_DIR_.$this->iso_code, _PS_TRANSLATIONS_DIR_.$newIso); + if (file_exists(_PS_TRANSLATIONS_DIR_.$this->iso_code)) { + rename(_PS_TRANSLATIONS_DIR_.$this->iso_code, _PS_TRANSLATIONS_DIR_.$newIso); + } - if (file_exists(_PS_MAIL_DIR_.$this->iso_code)) - rename(_PS_MAIL_DIR_.$this->iso_code, _PS_MAIL_DIR_.$newIso); + if (file_exists(_PS_MAIL_DIR_.$this->iso_code)) { + rename(_PS_MAIL_DIR_.$this->iso_code, _PS_MAIL_DIR_.$newIso); + } - $modulesList = Module::getModulesDirOnDisk(); - foreach ($modulesList as $moduleDir) - { - if (file_exists(_PS_MODULE_DIR_.$moduleDir.'/mails/'.$this->iso_code)) - rename(_PS_MODULE_DIR_.$moduleDir.'/mails/'.$this->iso_code, _PS_MODULE_DIR_.$moduleDir.'/mails/'.$newIso); + $modulesList = Module::getModulesDirOnDisk(); + foreach ($modulesList as $moduleDir) { + if (file_exists(_PS_MODULE_DIR_.$moduleDir.'/mails/'.$this->iso_code)) { + rename(_PS_MODULE_DIR_.$moduleDir.'/mails/'.$this->iso_code, _PS_MODULE_DIR_.$moduleDir.'/mails/'.$newIso); + } - if (file_exists(_PS_MODULE_DIR_.$moduleDir.'/'.$this->iso_code.'.php')) - rename(_PS_MODULE_DIR_.$moduleDir.'/'.$this->iso_code.'.php', _PS_MODULE_DIR_.$moduleDir.'/'.$newIso.'.php'); - } + if (file_exists(_PS_MODULE_DIR_.$moduleDir.'/'.$this->iso_code.'.php')) { + rename(_PS_MODULE_DIR_.$moduleDir.'/'.$this->iso_code.'.php', _PS_MODULE_DIR_.$moduleDir.'/'.$newIso.'.php'); + } + } - foreach (Theme::getThemes() as $theme) - { - /** @var Theme $theme */ - $theme_dir = $theme->directory; - if (file_exists(_PS_ALL_THEMES_DIR_.$theme_dir.'/lang/'.$this->iso_code.'.php')) - rename(_PS_ALL_THEMES_DIR_.$theme_dir.'/lang/'.$this->iso_code.'.php', _PS_ALL_THEMES_DIR_.$theme_dir.'/lang/'.$newIso.'.php'); + foreach (Theme::getThemes() as $theme) { + /** @var Theme $theme */ + $theme_dir = $theme->directory; + if (file_exists(_PS_ALL_THEMES_DIR_.$theme_dir.'/lang/'.$this->iso_code.'.php')) { + rename(_PS_ALL_THEMES_DIR_.$theme_dir.'/lang/'.$this->iso_code.'.php', _PS_ALL_THEMES_DIR_.$theme_dir.'/lang/'.$newIso.'.php'); + } - if (file_exists(_PS_ALL_THEMES_DIR_.$theme_dir.'/mails/'.$this->iso_code)) - rename(_PS_ALL_THEMES_DIR_.$theme_dir.'/mails/'.$this->iso_code, _PS_ALL_THEMES_DIR_.$theme_dir.'/mails/'.$newIso); + if (file_exists(_PS_ALL_THEMES_DIR_.$theme_dir.'/mails/'.$this->iso_code)) { + rename(_PS_ALL_THEMES_DIR_.$theme_dir.'/mails/'.$this->iso_code, _PS_ALL_THEMES_DIR_.$theme_dir.'/mails/'.$newIso); + } - foreach ($modulesList as $module) - if (file_exists(_PS_ALL_THEMES_DIR_.$theme_dir.'/modules/'.$module.'/'.$this->iso_code.'.php')) - rename(_PS_ALL_THEMES_DIR_.$theme_dir.'/modules/'.$module.'/'.$this->iso_code.'.php', _PS_ALL_THEMES_DIR_.$theme_dir.'/modules/'.$module.'/'.$newIso.'.php'); - } - } + foreach ($modulesList as $module) { + if (file_exists(_PS_ALL_THEMES_DIR_.$theme_dir.'/modules/'.$module.'/'.$this->iso_code.'.php')) { + rename(_PS_ALL_THEMES_DIR_.$theme_dir.'/modules/'.$module.'/'.$this->iso_code.'.php', _PS_ALL_THEMES_DIR_.$theme_dir.'/modules/'.$module.'/'.$newIso.'.php'); + } + } + } + } - /** - * Return an array of theme - * - * @return array([theme dir] => array('name' => [theme name])) - * @deprecated 1.5.5.0 - */ - protected function _getThemesList() - { - Tools::displayAsDeprecated(); + /** + * Return an array of theme + * + * @return array([theme dir] => array('name' => [theme name])) + * @deprecated 1.5.5.0 + */ + protected function _getThemesList() + { + Tools::displayAsDeprecated(); - static $themes = array(); + static $themes = array(); - if (empty($themes)) - { - $installed_themes = Theme::getThemes(); - foreach ($installed_themes as $theme) - { - /** @var Theme $theme */ - $themes[$theme->directory] = array('name' => $theme->name); - } - } - return $themes; - } + if (empty($themes)) { + $installed_themes = Theme::getThemes(); + foreach ($installed_themes as $theme) { + /** @var Theme $theme */ + $themes[$theme->directory] = array('name' => $theme->name); + } + } + return $themes; + } - public function add($autodate = true, $nullValues = false, $only_add = false) - { - if (!parent::add($autodate, $nullValues)) - return false; + public function add($autodate = true, $nullValues = false, $only_add = false) + { + if (!parent::add($autodate, $nullValues)) { + return false; + } - if ($only_add) - return true; + if ($only_add) { + return true; + } - // create empty files if they not exists - $this->_generateFiles(); + // create empty files if they not exists + $this->_generateFiles(); - // @todo Since a lot of modules are not in right format with their primary keys name, just get true ... - $this->loadUpdateSQL(); + // @todo Since a lot of modules are not in right format with their primary keys name, just get true ... + $this->loadUpdateSQL(); - return true; - } + return true; + } - public function checkFiles() - { - return Language::checkFilesWithIsoCode($this->iso_code); - } + public function checkFiles() + { + return Language::checkFilesWithIsoCode($this->iso_code); + } - /** - * This functions checks if every files exists for the language $iso_code. - * Concerned files are those located in translations/$iso_code/ - * and translations/mails/$iso_code . - * - * @param mixed $iso_code - * @returntrue if all files exists - */ - public static function checkFilesWithIsoCode($iso_code) - { - if (isset(self::$_checkedLangs[$iso_code]) && self::$_checkedLangs[$iso_code]) - return true; + /** + * This functions checks if every files exists for the language $iso_code. + * Concerned files are those located in translations/$iso_code/ + * and translations/mails/$iso_code . + * + * @param mixed $iso_code + * @returntrue if all files exists + */ + public static function checkFilesWithIsoCode($iso_code) + { + if (isset(self::$_checkedLangs[$iso_code]) && self::$_checkedLangs[$iso_code]) { + return true; + } - foreach (array_keys(Language::getFilesList($iso_code, _THEME_NAME_, false, false, false, true)) as $key) - if (!file_exists($key)) - return false; - self::$_checkedLangs[$iso_code] = true; - return true; - } + foreach (array_keys(Language::getFilesList($iso_code, _THEME_NAME_, false, false, false, true)) as $key) { + if (!file_exists($key)) { + return false; + } + } + self::$_checkedLangs[$iso_code] = true; + return true; + } - public static function getFilesList($iso_from, $theme_from, $iso_to = false, $theme_to = false, $select = false, $check = false, $modules = false) - { - if (empty($iso_from)) - die(Tools::displayError()); + public static function getFilesList($iso_from, $theme_from, $iso_to = false, $theme_to = false, $select = false, $check = false, $modules = false) + { + if (empty($iso_from)) { + die(Tools::displayError()); + } - $copy = ($iso_to && $theme_to) ? true : false; + $copy = ($iso_to && $theme_to) ? true : false; - $lPath_from = _PS_TRANSLATIONS_DIR_.(string)$iso_from.'/'; - $tPath_from = _PS_ROOT_DIR_.'/themes/'.(string)$theme_from.'/'; - $pPath_from = _PS_ROOT_DIR_.'/themes/'.(string)$theme_from.'/pdf/'; - $mPath_from = _PS_MAIL_DIR_.(string)$iso_from.'/'; + $lPath_from = _PS_TRANSLATIONS_DIR_.(string)$iso_from.'/'; + $tPath_from = _PS_ROOT_DIR_.'/themes/'.(string)$theme_from.'/'; + $pPath_from = _PS_ROOT_DIR_.'/themes/'.(string)$theme_from.'/pdf/'; + $mPath_from = _PS_MAIL_DIR_.(string)$iso_from.'/'; - if ($copy) - { - $lPath_to = _PS_TRANSLATIONS_DIR_.(string)$iso_to.'/'; - $tPath_to = _PS_ROOT_DIR_.'/themes/'.(string)$theme_to.'/'; - $pPath_to = _PS_ROOT_DIR_.'/themes/'.(string)$theme_to.'/pdf/'; - $mPath_to = _PS_MAIL_DIR_.(string)$iso_to.'/'; - } + if ($copy) { + $lPath_to = _PS_TRANSLATIONS_DIR_.(string)$iso_to.'/'; + $tPath_to = _PS_ROOT_DIR_.'/themes/'.(string)$theme_to.'/'; + $pPath_to = _PS_ROOT_DIR_.'/themes/'.(string)$theme_to.'/pdf/'; + $mPath_to = _PS_MAIL_DIR_.(string)$iso_to.'/'; + } - $lFiles = array('admin.php', 'errors.php', 'fields.php', 'pdf.php', 'tabs.php'); + $lFiles = array('admin.php', 'errors.php', 'fields.php', 'pdf.php', 'tabs.php'); - // Added natives mails files - $mFiles = array( - 'account.html', 'account.txt', - 'backoffice_order.html', 'backoffice_order.txt', - 'bankwire.html', 'bankwire.txt', - 'cheque.html', 'cheque.txt', - 'contact.html', 'contact.txt', - 'contact_form.html', 'contact_form.txt', - 'credit_slip.html', 'credit_slip.txt', - 'download_product.html', 'download_product.txt', - 'employee_password.html', 'employee_password.txt', - 'forward_msg.html', 'forward_msg.txt', - 'guest_to_customer.html', 'guest_to_customer.txt', - 'in_transit.html', 'in_transit.txt', - 'log_alert.html', 'log_alert.txt', - 'newsletter.html', 'newsletter.txt', - 'order_canceled.html', 'order_canceled.txt', - 'order_conf.html', 'order_conf.txt', - 'order_customer_comment.html', 'order_customer_comment.txt', - 'order_merchant_comment.html', 'order_merchant_comment.txt', - 'order_return_state.html', 'order_return_state.txt', - 'outofstock.html', 'outofstock.txt', - 'password.html', 'password.txt', - 'password_query.html', 'password_query.txt', - 'payment.html', 'payment.txt', - 'payment_error.html', 'payment_error.txt', - 'preparation.html', 'preparation.txt', - 'refund.html', 'refund.txt', - 'reply_msg.html', 'reply_msg.txt', - 'shipped.html', 'shipped.txt', - 'test.html', 'test.txt', - 'voucher.html', 'voucher.txt', - 'voucher_new.html', 'voucher_new.txt', - 'order_changed.html', 'order_changed.txt' - ); + // Added natives mails files + $mFiles = array( + 'account.html', 'account.txt', + 'backoffice_order.html', 'backoffice_order.txt', + 'bankwire.html', 'bankwire.txt', + 'cheque.html', 'cheque.txt', + 'contact.html', 'contact.txt', + 'contact_form.html', 'contact_form.txt', + 'credit_slip.html', 'credit_slip.txt', + 'download_product.html', 'download_product.txt', + 'employee_password.html', 'employee_password.txt', + 'forward_msg.html', 'forward_msg.txt', + 'guest_to_customer.html', 'guest_to_customer.txt', + 'in_transit.html', 'in_transit.txt', + 'log_alert.html', 'log_alert.txt', + 'newsletter.html', 'newsletter.txt', + 'order_canceled.html', 'order_canceled.txt', + 'order_conf.html', 'order_conf.txt', + 'order_customer_comment.html', 'order_customer_comment.txt', + 'order_merchant_comment.html', 'order_merchant_comment.txt', + 'order_return_state.html', 'order_return_state.txt', + 'outofstock.html', 'outofstock.txt', + 'password.html', 'password.txt', + 'password_query.html', 'password_query.txt', + 'payment.html', 'payment.txt', + 'payment_error.html', 'payment_error.txt', + 'preparation.html', 'preparation.txt', + 'refund.html', 'refund.txt', + 'reply_msg.html', 'reply_msg.txt', + 'shipped.html', 'shipped.txt', + 'test.html', 'test.txt', + 'voucher.html', 'voucher.txt', + 'voucher_new.html', 'voucher_new.txt', + 'order_changed.html', 'order_changed.txt' + ); - $number = -1; + $number = -1; - $files = array(); - $files_tr = array(); - $files_theme = array(); - $files_mail = array(); - $files_modules = array(); + $files = array(); + $files_tr = array(); + $files_theme = array(); + $files_mail = array(); + $files_modules = array(); - // When a copy is made from a theme in specific language - // to an other theme for the same language, - // it's avoid to copy Translations, Mails files - // and modules files which are not override by theme. - if (!$copy || $iso_from != $iso_to) - { - // Translations files - if (!$check || ($check && (string)$iso_from != 'en')) - foreach ($lFiles as $file) - $files_tr[$lPath_from.$file] = ($copy ? $lPath_to.$file : ++$number); - if ($select == 'tr') - return $files_tr; - $files = array_merge($files, $files_tr); + // When a copy is made from a theme in specific language + // to an other theme for the same language, + // it's avoid to copy Translations, Mails files + // and modules files which are not override by theme. + if (!$copy || $iso_from != $iso_to) { + // Translations files + if (!$check || ($check && (string)$iso_from != 'en')) { + foreach ($lFiles as $file) { + $files_tr[$lPath_from.$file] = ($copy ? $lPath_to.$file : ++$number); + } + } + if ($select == 'tr') { + return $files_tr; + } + $files = array_merge($files, $files_tr); - // Mail files - if (!$check || ($check && (string)$iso_from != 'en')) - $files_mail[$mPath_from.'lang.php'] = ($copy ? $mPath_to.'lang.php' : ++$number); - foreach ($mFiles as $file) - $files_mail[$mPath_from.$file] = ($copy ? $mPath_to.$file : ++$number); - if ($select == 'mail') - return $files_mail; - $files = array_merge($files, $files_mail); + // Mail files + if (!$check || ($check && (string)$iso_from != 'en')) { + $files_mail[$mPath_from.'lang.php'] = ($copy ? $mPath_to.'lang.php' : ++$number); + } + foreach ($mFiles as $file) { + $files_mail[$mPath_from.$file] = ($copy ? $mPath_to.$file : ++$number); + } + if ($select == 'mail') { + return $files_mail; + } + $files = array_merge($files, $files_mail); - // Modules - if ($modules) - { - $modList = Module::getModulesDirOnDisk(); - foreach ($modList as $mod) - { - $modDir = _PS_MODULE_DIR_.$mod; - // Lang file - if (file_exists($modDir.'/translations/'.(string)$iso_from.'.php')) - $files_modules[$modDir.'/translations/'.(string)$iso_from.'.php'] = ($copy ? $modDir.'/translations/'.(string)$iso_to.'.php' : ++$number); - elseif (file_exists($modDir.'/'.(string)$iso_from.'.php')) - $files_modules[$modDir.'/'.(string)$iso_from.'.php'] = ($copy ? $modDir.'/'.(string)$iso_to.'.php' : ++$number); - // Mails files - $modMailDirFrom = $modDir.'/mails/'.(string)$iso_from; - $modMailDirTo = $modDir.'/mails/'.(string)$iso_to; - if (file_exists($modMailDirFrom)) - { - $dirFiles = scandir($modMailDirFrom); - foreach ($dirFiles as $file) - if (file_exists($modMailDirFrom.'/'.$file) && $file != '.' && $file != '..' && $file != '.svn') - $files_modules[$modMailDirFrom.'/'.$file] = ($copy ? $modMailDirTo.'/'.$file : ++$number); - } - } - if ($select == 'modules') - return $files_modules; - $files = array_merge($files, $files_modules); - } - } - elseif ($select == 'mail' || $select == 'tr') - return $files; + // Modules + if ($modules) { + $modList = Module::getModulesDirOnDisk(); + foreach ($modList as $mod) { + $modDir = _PS_MODULE_DIR_.$mod; + // Lang file + if (file_exists($modDir.'/translations/'.(string)$iso_from.'.php')) { + $files_modules[$modDir.'/translations/'.(string)$iso_from.'.php'] = ($copy ? $modDir.'/translations/'.(string)$iso_to.'.php' : ++$number); + } elseif (file_exists($modDir.'/'.(string)$iso_from.'.php')) { + $files_modules[$modDir.'/'.(string)$iso_from.'.php'] = ($copy ? $modDir.'/'.(string)$iso_to.'.php' : ++$number); + } + // Mails files + $modMailDirFrom = $modDir.'/mails/'.(string)$iso_from; + $modMailDirTo = $modDir.'/mails/'.(string)$iso_to; + if (file_exists($modMailDirFrom)) { + $dirFiles = scandir($modMailDirFrom); + foreach ($dirFiles as $file) { + if (file_exists($modMailDirFrom.'/'.$file) && $file != '.' && $file != '..' && $file != '.svn') { + $files_modules[$modMailDirFrom.'/'.$file] = ($copy ? $modMailDirTo.'/'.$file : ++$number); + } + } + } + } + if ($select == 'modules') { + return $files_modules; + } + $files = array_merge($files, $files_modules); + } + } elseif ($select == 'mail' || $select == 'tr') { + return $files; + } - // Theme files - if (!$check || ($check && (string)$iso_from != 'en')) - { - $files_theme[$tPath_from.'lang/'.(string)$iso_from.'.php'] = ($copy ? $tPath_to.'lang/'.(string)$iso_to.'.php' : ++$number); + // Theme files + if (!$check || ($check && (string)$iso_from != 'en')) { + $files_theme[$tPath_from.'lang/'.(string)$iso_from.'.php'] = ($copy ? $tPath_to.'lang/'.(string)$iso_to.'.php' : ++$number); - // Override for pdf files in the theme - if (file_exists($pPath_from.'lang/'.(string)$iso_from.'.php')) - $files_theme[$pPath_from.'lang/'.(string)$iso_from.'.php'] = ($copy ? $pPath_to.'lang/'.(string)$iso_to.'.php' : ++$number); + // Override for pdf files in the theme + if (file_exists($pPath_from.'lang/'.(string)$iso_from.'.php')) { + $files_theme[$pPath_from.'lang/'.(string)$iso_from.'.php'] = ($copy ? $pPath_to.'lang/'.(string)$iso_to.'.php' : ++$number); + } - $module_theme_files = (file_exists($tPath_from.'modules/') ? scandir($tPath_from.'modules/') : array()); - foreach ($module_theme_files as $module) - if ($module !== '.' && $module != '..' && $module !== '.svn' && file_exists($tPath_from.'modules/'.$module.'/translations/'.(string)$iso_from.'.php')) - $files_theme[$tPath_from.'modules/'.$module.'/translations/'.(string)$iso_from.'.php'] = ($copy ? $tPath_to.'modules/'.$module.'/translations/'.(string)$iso_to.'.php' : ++$number); - } - if ($select == 'theme') - return $files_theme; - $files = array_merge($files, $files_theme); + $module_theme_files = (file_exists($tPath_from.'modules/') ? scandir($tPath_from.'modules/') : array()); + foreach ($module_theme_files as $module) { + if ($module !== '.' && $module != '..' && $module !== '.svn' && file_exists($tPath_from.'modules/'.$module.'/translations/'.(string)$iso_from.'.php')) { + $files_theme[$tPath_from.'modules/'.$module.'/translations/'.(string)$iso_from.'.php'] = ($copy ? $tPath_to.'modules/'.$module.'/translations/'.(string)$iso_to.'.php' : ++$number); + } + } + } + if ($select == 'theme') { + return $files_theme; + } + $files = array_merge($files, $files_theme); - // Return - return $files; - } + // Return + return $files; + } - /** - * loadUpdateSQL will create default lang values when you create a new lang, based on default id lang - * - * @return bool true if succeed - */ - public function loadUpdateSQL() - { - $tables = Db::getInstance()->executeS('SHOW TABLES LIKE \''.str_replace('_', '\\_', _DB_PREFIX_).'%\_lang\' '); - $langTables = array(); + /** + * loadUpdateSQL will create default lang values when you create a new lang, based on default id lang + * + * @return bool true if succeed + */ + public function loadUpdateSQL() + { + $tables = Db::getInstance()->executeS('SHOW TABLES LIKE \''.str_replace('_', '\\_', _DB_PREFIX_).'%\_lang\' '); + $langTables = array(); - foreach ($tables as $table) - foreach ($table as $t) - if ($t != _DB_PREFIX_.'configuration_lang') - $langTables[] = $t; + foreach ($tables as $table) { + foreach ($table as $t) { + if ($t != _DB_PREFIX_.'configuration_lang') { + $langTables[] = $t; + } + } + } - $return = true; + $return = true; - $shops = Shop::getShopsCollection(false); - foreach ($shops as $shop) - { - /** @var Shop $shop */ - $id_lang_default = Configuration::get('PS_LANG_DEFAULT', null, $shop->id_shop_group, $shop->id); + $shops = Shop::getShopsCollection(false); + foreach ($shops as $shop) { + /** @var Shop $shop */ + $id_lang_default = Configuration::get('PS_LANG_DEFAULT', null, $shop->id_shop_group, $shop->id); - foreach ($langTables as $name) - { - preg_match('#^'.preg_quote(_DB_PREFIX_).'(.+)_lang$#i', $name, $m); - $identifier = 'id_'.$m[1]; + foreach ($langTables as $name) { + preg_match('#^'.preg_quote(_DB_PREFIX_).'(.+)_lang$#i', $name, $m); + $identifier = 'id_'.$m[1]; - $fields = ''; - // We will check if the table contains a column "id_shop" - // If yes, we will add "id_shop" as a WHERE condition in queries copying data from default language - $shop_field_exists = $primary_key_exists = false; - $columns = Db::getInstance()->executeS('SHOW COLUMNS FROM `'.$name.'`'); - foreach ($columns as $column) - { - $fields .= $column['Field'].', '; - if ($column['Field'] == 'id_shop') - $shop_field_exists = true; - if ($column['Field'] == $identifier) - $primary_key_exists = true; - } - $fields = rtrim($fields, ', '); + $fields = ''; + // We will check if the table contains a column "id_shop" + // If yes, we will add "id_shop" as a WHERE condition in queries copying data from default language + $shop_field_exists = $primary_key_exists = false; + $columns = Db::getInstance()->executeS('SHOW COLUMNS FROM `'.$name.'`'); + foreach ($columns as $column) { + $fields .= $column['Field'].', '; + if ($column['Field'] == 'id_shop') { + $shop_field_exists = true; + } + if ($column['Field'] == $identifier) { + $primary_key_exists = true; + } + } + $fields = rtrim($fields, ', '); - if (!$primary_key_exists) - continue; + if (!$primary_key_exists) { + continue; + } - $sql = 'INSERT IGNORE INTO `'.$name.'` ('.$fields.') (SELECT '; + $sql = 'INSERT IGNORE INTO `'.$name.'` ('.$fields.') (SELECT '; - // For each column, copy data from default language - reset($columns); - foreach ($columns as $column) - { - if ($identifier != $column['Field'] && $column['Field'] != 'id_lang') - { - $sql .= '( + // For each column, copy data from default language + reset($columns); + foreach ($columns as $column) { + if ($identifier != $column['Field'] && $column['Field'] != 'id_lang') { + $sql .= '( SELECT `'.bqSQL($column['Field']).'` FROM `'.bqSQL($name).'` tl WHERE tl.`id_lang` = '.(int)$id_lang_default.' '.($shop_field_exists ? ' AND tl.`id_shop` = '.(int)$shop->id : '').' AND tl.`'.bqSQL($identifier).'` = `'.bqSQL(str_replace('_lang', '', $name)).'`.`'.bqSQL($identifier).'` ),'; - } - else - $sql .= '`'.bqSQL($column['Field']).'`,'; - } - $sql = rtrim($sql, ', '); - $sql .= ' FROM `'._DB_PREFIX_.'lang` CROSS JOIN `'.bqSQL(str_replace('_lang', '', $name)).'`)'; - $return &= Db::getInstance()->execute($sql); - } - } - return $return; - } + } else { + $sql .= '`'.bqSQL($column['Field']).'`,'; + } + } + $sql = rtrim($sql, ', '); + $sql .= ' FROM `'._DB_PREFIX_.'lang` CROSS JOIN `'.bqSQL(str_replace('_lang', '', $name)).'`)'; + $return &= Db::getInstance()->execute($sql); + } + } + return $return; + } - public static function recurseDeleteDir($dir) - { - if (!is_dir($dir)) - return false; - if ($handle = @opendir($dir)) - { - while (false !== ($file = readdir($handle))) - if ($file != '.' && $file != '..') - { - if (is_dir($dir.'/'.$file)) - Language::recurseDeleteDir($dir.'/'.$file); - elseif (file_exists($dir.'/'.$file)) - @unlink($dir.'/'.$file); - } - closedir($handle); - } - if (is_writable($dir)) - rmdir($dir); - } + public static function recurseDeleteDir($dir) + { + if (!is_dir($dir)) { + return false; + } + if ($handle = @opendir($dir)) { + while (false !== ($file = readdir($handle))) { + if ($file != '.' && $file != '..') { + if (is_dir($dir.'/'.$file)) { + Language::recurseDeleteDir($dir.'/'.$file); + } elseif (file_exists($dir.'/'.$file)) { + @unlink($dir.'/'.$file); + } + } + } + closedir($handle); + } + if (is_writable($dir)) { + rmdir($dir); + } + } - public function delete() - { - if (!$this->hasMultishopEntries() || Shop::getContext() == Shop::CONTEXT_ALL) - { - if (empty($this->iso_code)) - $this->iso_code = Language::getIsoById($this->id); + public function delete() + { + if (!$this->hasMultishopEntries() || Shop::getContext() == Shop::CONTEXT_ALL) { + if (empty($this->iso_code)) { + $this->iso_code = Language::getIsoById($this->id); + } - // Database translations deletion - $result = Db::getInstance()->executeS('SHOW TABLES FROM `'._DB_NAME_.'`'); - foreach ($result as $row) - if (isset($row['Tables_in_'._DB_NAME_]) && !empty($row['Tables_in_'._DB_NAME_]) && preg_match('/'.preg_quote(_DB_PREFIX_).'_lang/', $row['Tables_in_'._DB_NAME_])) - if (!Db::getInstance()->execute('DELETE FROM `'.$row['Tables_in_'._DB_NAME_].'` WHERE `id_lang` = '.(int)$this->id)) - return false; + // Database translations deletion + $result = Db::getInstance()->executeS('SHOW TABLES FROM `'._DB_NAME_.'`'); + foreach ($result as $row) { + if (isset($row['Tables_in_'._DB_NAME_]) && !empty($row['Tables_in_'._DB_NAME_]) && preg_match('/'.preg_quote(_DB_PREFIX_).'_lang/', $row['Tables_in_'._DB_NAME_])) { + if (!Db::getInstance()->execute('DELETE FROM `'.$row['Tables_in_'._DB_NAME_].'` WHERE `id_lang` = '.(int)$this->id)) { + return false; + } + } + } - // Delete tags - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'tag WHERE id_lang = '.(int)$this->id); + // Delete tags + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'tag WHERE id_lang = '.(int)$this->id); - // Delete search words - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'search_word WHERE id_lang = '.(int)$this->id); + // Delete search words + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'search_word WHERE id_lang = '.(int)$this->id); - // Files deletion - foreach (Language::getFilesList($this->iso_code, _THEME_NAME_, false, false, false, true, true) as $key => $file) - if (file_exists($key)) - unlink($key); + // Files deletion + foreach (Language::getFilesList($this->iso_code, _THEME_NAME_, false, false, false, true, true) as $key => $file) { + if (file_exists($key)) { + unlink($key); + } + } - $modList = scandir(_PS_MODULE_DIR_); - foreach ($modList as $mod) - { - Language::recurseDeleteDir(_PS_MODULE_DIR_.$mod.'/mails/'.$this->iso_code); - $files = @scandir(_PS_MODULE_DIR_.$mod.'/mails/'); - if (count($files) <= 2) - Language::recurseDeleteDir(_PS_MODULE_DIR_.$mod.'/mails/'); + $modList = scandir(_PS_MODULE_DIR_); + foreach ($modList as $mod) { + Language::recurseDeleteDir(_PS_MODULE_DIR_.$mod.'/mails/'.$this->iso_code); + $files = @scandir(_PS_MODULE_DIR_.$mod.'/mails/'); + if (count($files) <= 2) { + Language::recurseDeleteDir(_PS_MODULE_DIR_.$mod.'/mails/'); + } - if (file_exists(_PS_MODULE_DIR_.$mod.'/'.$this->iso_code.'.php')) - { - unlink(_PS_MODULE_DIR_.$mod.'/'.$this->iso_code.'.php'); - $files = @scandir(_PS_MODULE_DIR_.$mod); - if (count($files) <= 2) - Language::recurseDeleteDir(_PS_MODULE_DIR_.$mod); - } - } + if (file_exists(_PS_MODULE_DIR_.$mod.'/'.$this->iso_code.'.php')) { + unlink(_PS_MODULE_DIR_.$mod.'/'.$this->iso_code.'.php'); + $files = @scandir(_PS_MODULE_DIR_.$mod); + if (count($files) <= 2) { + Language::recurseDeleteDir(_PS_MODULE_DIR_.$mod); + } + } + } - if (file_exists(_PS_MAIL_DIR_.$this->iso_code)) - Language::recurseDeleteDir(_PS_MAIL_DIR_.$this->iso_code); - if (file_exists(_PS_TRANSLATIONS_DIR_.$this->iso_code)) - Language::recurseDeleteDir(_PS_TRANSLATIONS_DIR_.$this->iso_code); + if (file_exists(_PS_MAIL_DIR_.$this->iso_code)) { + Language::recurseDeleteDir(_PS_MAIL_DIR_.$this->iso_code); + } + if (file_exists(_PS_TRANSLATIONS_DIR_.$this->iso_code)) { + Language::recurseDeleteDir(_PS_TRANSLATIONS_DIR_.$this->iso_code); + } - $images = array( - '.jpg', - '-default-'.ImageType::getFormatedName('thickbox').'.jpg', - '-default-'.ImageType::getFormatedName('home').'.jpg', - '-default-'.ImageType::getFormatedName('large').'.jpg', - '-default-'.ImageType::getFormatedName('medium').'.jpg', - '-default-'.ImageType::getFormatedName('small').'.jpg' - ); - $images_directories = array(_PS_CAT_IMG_DIR_, _PS_MANU_IMG_DIR_, _PS_PROD_IMG_DIR_, _PS_SUPP_IMG_DIR_); - foreach ($images_directories as $image_directory) - foreach ($images as $image) - { - if (file_exists($image_directory.$this->iso_code.$image)) - unlink($image_directory.$this->iso_code.$image); - if (file_exists(_PS_ROOT_DIR_.'/img/l/'.$this->id.'.jpg')) - unlink(_PS_ROOT_DIR_.'/img/l/'.$this->id.'.jpg'); - } - } + $images = array( + '.jpg', + '-default-'.ImageType::getFormatedName('thickbox').'.jpg', + '-default-'.ImageType::getFormatedName('home').'.jpg', + '-default-'.ImageType::getFormatedName('large').'.jpg', + '-default-'.ImageType::getFormatedName('medium').'.jpg', + '-default-'.ImageType::getFormatedName('small').'.jpg' + ); + $images_directories = array(_PS_CAT_IMG_DIR_, _PS_MANU_IMG_DIR_, _PS_PROD_IMG_DIR_, _PS_SUPP_IMG_DIR_); + foreach ($images_directories as $image_directory) { + foreach ($images as $image) { + if (file_exists($image_directory.$this->iso_code.$image)) { + unlink($image_directory.$this->iso_code.$image); + } + if (file_exists(_PS_ROOT_DIR_.'/img/l/'.$this->id.'.jpg')) { + unlink(_PS_ROOT_DIR_.'/img/l/'.$this->id.'.jpg'); + } + } + } + } - if (!parent::delete()) - return false; + if (!parent::delete()) { + return false; + } - return true; - } + return true; + } - public function deleteSelection($selection) - { - if (!is_array($selection)) - die(Tools::displayError()); + public function deleteSelection($selection) + { + if (!is_array($selection)) { + die(Tools::displayError()); + } - $result = true; - foreach ($selection as $id) - { - $language = new Language($id); - $result = $result && $language->delete(); - } + $result = true; + foreach ($selection as $id) { + $language = new Language($id); + $result = $result && $language->delete(); + } - return $result; - } + return $result; + } - /** - * Returns available languages - * - * @param bool $active Select only active languages - * @param int|bool $id_shop Shop ID - * @param bool $ids_only If true, returns an array of language IDs - * - * @return array Languages - */ - public static function getLanguages($active = true, $id_shop = false, $ids_only = false) - { - if (!self::$_LANGUAGES) - Language::loadLanguages(); + /** + * Returns available languages + * + * @param bool $active Select only active languages + * @param int|bool $id_shop Shop ID + * @param bool $ids_only If true, returns an array of language IDs + * + * @return array Languages + */ + public static function getLanguages($active = true, $id_shop = false, $ids_only = false) + { + if (!self::$_LANGUAGES) { + Language::loadLanguages(); + } - $languages = array(); - foreach (self::$_LANGUAGES as $language) - { - if ($active && !$language['active'] || ($id_shop && !isset($language['shops'][(int)$id_shop]))) - continue; + $languages = array(); + foreach (self::$_LANGUAGES as $language) { + if ($active && !$language['active'] || ($id_shop && !isset($language['shops'][(int)$id_shop]))) { + continue; + } - $languages[] = $ids_only ? $language['id_lang'] : $language; - } + $languages[] = $ids_only ? $language['id_lang'] : $language; + } - return $languages; - } + return $languages; + } - /** - * Returns an array of language IDs - * - * @param bool $active Select only active languages - * @param int|bool $id_shop Shop ID - * - * @return array - */ - public static function getIDs($active = true, $id_shop = false) - { - return self::getLanguages($active, $id_shop, true); - } + /** + * Returns an array of language IDs + * + * @param bool $active Select only active languages + * @param int|bool $id_shop Shop ID + * + * @return array + */ + public static function getIDs($active = true, $id_shop = false) + { + return self::getLanguages($active, $id_shop, true); + } - public static function getLanguage($id_lang) - { - if (!array_key_exists((int)$id_lang, self::$_LANGUAGES)) - return false; - return self::$_LANGUAGES[(int)($id_lang)]; - } + public static function getLanguage($id_lang) + { + if (!array_key_exists((int)$id_lang, self::$_LANGUAGES)) { + return false; + } + return self::$_LANGUAGES[(int)($id_lang)]; + } - /** - * Return iso code from id - * - * @param int $id_lang Language ID - * @return string Iso code - */ - public static function getIsoById($id_lang) - { - if (isset(self::$_LANGUAGES[(int)$id_lang]['iso_code'])) - return self::$_LANGUAGES[(int)$id_lang]['iso_code']; - return false; - } + /** + * Return iso code from id + * + * @param int $id_lang Language ID + * @return string Iso code + */ + public static function getIsoById($id_lang) + { + if (isset(self::$_LANGUAGES[(int)$id_lang]['iso_code'])) { + return self::$_LANGUAGES[(int)$id_lang]['iso_code']; + } + return false; + } - /** - * Return id from iso code - * - * @param string $iso_code Iso code - * @param bool $no_cache - * @return false|null|string - */ - public static function getIdByIso($iso_code, $no_cache = false) - { - if (!Validate::isLanguageIsoCode($iso_code)) - die(Tools::displayError('Fatal error: ISO code is not correct').' '.Tools::safeOutput($iso_code)); + /** + * Return id from iso code + * + * @param string $iso_code Iso code + * @param bool $no_cache + * @return false|null|string + */ + public static function getIdByIso($iso_code, $no_cache = false) + { + if (!Validate::isLanguageIsoCode($iso_code)) { + die(Tools::displayError('Fatal error: ISO code is not correct').' '.Tools::safeOutput($iso_code)); + } - $key = 'Language::getIdByIso_'.$iso_code; - if ($no_cache || !Cache::isStored($key)) - { - $id_lang = Db::getInstance()->getValue('SELECT `id_lang` FROM `'._DB_PREFIX_.'lang` WHERE `iso_code` = \''.pSQL(strtolower($iso_code)).'\''); + $key = 'Language::getIdByIso_'.$iso_code; + if ($no_cache || !Cache::isStored($key)) { + $id_lang = Db::getInstance()->getValue('SELECT `id_lang` FROM `'._DB_PREFIX_.'lang` WHERE `iso_code` = \''.pSQL(strtolower($iso_code)).'\''); - Cache::store($key, $id_lang); - return $id_lang; - } - return Cache::retrieve($key); - } + Cache::store($key, $id_lang); + return $id_lang; + } + return Cache::retrieve($key); + } - public static function getLanguageCodeByIso($iso_code) - { - if (!Validate::isLanguageIsoCode($iso_code)) - die(Tools::displayError('Fatal error: ISO code is not correct').' '.Tools::safeOutput($iso_code)); + public static function getLanguageCodeByIso($iso_code) + { + if (!Validate::isLanguageIsoCode($iso_code)) { + die(Tools::displayError('Fatal error: ISO code is not correct').' '.Tools::safeOutput($iso_code)); + } - return Db::getInstance()->getValue('SELECT `language_code` FROM `'._DB_PREFIX_.'lang` WHERE `iso_code` = \''.pSQL(strtolower($iso_code)).'\''); - } + return Db::getInstance()->getValue('SELECT `language_code` FROM `'._DB_PREFIX_.'lang` WHERE `iso_code` = \''.pSQL(strtolower($iso_code)).'\''); + } - public static function getLanguageByIETFCode($code) - { - if (!Validate::isLanguageCode($code)) - die(sprintf(Tools::displayError('Fatal error: IETF code %s is not correct'), Tools::safeOutput($code))); + public static function getLanguageByIETFCode($code) + { + if (!Validate::isLanguageCode($code)) { + die(sprintf(Tools::displayError('Fatal error: IETF code %s is not correct'), Tools::safeOutput($code))); + } - // $code is in the form of 'xx-YY' where xx is the language code - // and 'YY' a country code identifying a variant of the language. - $lang_country = explode('-', $code); - // Get the language component of the code - $lang = $lang_country[0]; + // $code is in the form of 'xx-YY' where xx is the language code + // and 'YY' a country code identifying a variant of the language. + $lang_country = explode('-', $code); + // Get the language component of the code + $lang = $lang_country[0]; - // Find the id_lang of the language. - // We look for anything with the correct language code - // and sort on equality with the exact IETF code wanted. - // That way using only one query we get either the exact wanted language - // or a close match. - $id_lang = Db::getInstance()->getValue( - 'SELECT `id_lang`, IF(language_code = \''.pSQL($code).'\', 0, LENGTH(language_code)) as found + // Find the id_lang of the language. + // We look for anything with the correct language code + // and sort on equality with the exact IETF code wanted. + // That way using only one query we get either the exact wanted language + // or a close match. + $id_lang = Db::getInstance()->getValue( + 'SELECT `id_lang`, IF(language_code = \''.pSQL($code).'\', 0, LENGTH(language_code)) as found FROM `'._DB_PREFIX_.'lang` WHERE LEFT(`language_code`,2) = \''.pSQL($lang).'\' ORDER BY found ASC' - ); + ); - // Instantiate the Language object if we found it. - if ($id_lang) - return new Language($id_lang); - else - return false; - } + // Instantiate the Language object if we found it. + if ($id_lang) { + return new Language($id_lang); + } else { + return false; + } + } - /** - * Return array (id_lang, iso_code) - * - * @param string $iso_code Iso code - * @return array Language (id_lang, iso_code) - */ - public static function getIsoIds($active = true) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT `id_lang`, `iso_code` FROM `'._DB_PREFIX_.'lang` '.($active ? 'WHERE active = 1' : '')); - } + /** + * Return array (id_lang, iso_code) + * + * @param string $iso_code Iso code + * @return array Language (id_lang, iso_code) + */ + public static function getIsoIds($active = true) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT `id_lang`, `iso_code` FROM `'._DB_PREFIX_.'lang` '.($active ? 'WHERE active = 1' : '')); + } - public static function copyLanguageData($from, $to) - { - $result = Db::getInstance()->executeS('SHOW TABLES FROM `'._DB_NAME_.'`'); - foreach ($result as $row) - if (preg_match('/_lang/', $row['Tables_in_'._DB_NAME_]) && $row['Tables_in_'._DB_NAME_] != _DB_PREFIX_.'lang') - { - $result2 = Db::getInstance()->executeS('SELECT * FROM `'.$row['Tables_in_'._DB_NAME_].'` WHERE `id_lang` = '.(int)$from); - if (!count($result2)) - continue; - Db::getInstance()->execute('DELETE FROM `'.$row['Tables_in_'._DB_NAME_].'` WHERE `id_lang` = '.(int)$to); - $query = 'INSERT INTO `'.$row['Tables_in_'._DB_NAME_].'` VALUES '; - foreach ($result2 as $row2) - { - $query .= '('; - $row2['id_lang'] = $to; - foreach ($row2 as $field) - $query .= (!is_string($field) && $field == null) ? 'NULL,' : '\''.pSQL($field, true).'\','; - $query = rtrim($query, ',').'),'; - } - $query = rtrim($query, ','); - Db::getInstance()->execute($query); - } - return true; - } + public static function copyLanguageData($from, $to) + { + $result = Db::getInstance()->executeS('SHOW TABLES FROM `'._DB_NAME_.'`'); + foreach ($result as $row) { + if (preg_match('/_lang/', $row['Tables_in_'._DB_NAME_]) && $row['Tables_in_'._DB_NAME_] != _DB_PREFIX_.'lang') { + $result2 = Db::getInstance()->executeS('SELECT * FROM `'.$row['Tables_in_'._DB_NAME_].'` WHERE `id_lang` = '.(int)$from); + if (!count($result2)) { + continue; + } + Db::getInstance()->execute('DELETE FROM `'.$row['Tables_in_'._DB_NAME_].'` WHERE `id_lang` = '.(int)$to); + $query = 'INSERT INTO `'.$row['Tables_in_'._DB_NAME_].'` VALUES '; + foreach ($result2 as $row2) { + $query .= '('; + $row2['id_lang'] = $to; + foreach ($row2 as $field) { + $query .= (!is_string($field) && $field == null) ? 'NULL,' : '\''.pSQL($field, true).'\','; + } + $query = rtrim($query, ',').'),'; + } + $query = rtrim($query, ','); + Db::getInstance()->execute($query); + } + } + return true; + } - /** - * Load all languages in memory for caching - */ - public static function loadLanguages() - { - self::$_LANGUAGES = array(); + /** + * Load all languages in memory for caching + */ + public static function loadLanguages() + { + self::$_LANGUAGES = array(); - $sql = 'SELECT l.*, ls.`id_shop` + $sql = 'SELECT l.*, ls.`id_shop` FROM `'._DB_PREFIX_.'lang` l LEFT JOIN `'._DB_PREFIX_.'lang_shop` ls ON (l.id_lang = ls.id_lang)'; - $result = Db::getInstance()->executeS($sql); - foreach ($result as $row) - { - if (!isset(self::$_LANGUAGES[(int)$row['id_lang']])) - self::$_LANGUAGES[(int)$row['id_lang']] = $row; - self::$_LANGUAGES[(int)$row['id_lang']]['shops'][(int)$row['id_shop']] = true; - } - } + $result = Db::getInstance()->executeS($sql); + foreach ($result as $row) { + if (!isset(self::$_LANGUAGES[(int)$row['id_lang']])) { + self::$_LANGUAGES[(int)$row['id_lang']] = $row; + } + self::$_LANGUAGES[(int)$row['id_lang']]['shops'][(int)$row['id_shop']] = true; + } + } - public static function checkAndAddLanguage($iso_code, $lang_pack = false, $only_add = false, $params_lang = null) - { - if (Language::getIdByIso($iso_code)) - return true; + public static function checkAndAddLanguage($iso_code, $lang_pack = false, $only_add = false, $params_lang = null) + { + if (Language::getIdByIso($iso_code)) { + return true; + } - // Initialize the language - $lang = new Language(); - $lang->iso_code = Tools::strtolower($iso_code); - $lang->language_code = $iso_code; // Rewritten afterwards if the language code is available - $lang->active = true; + // Initialize the language + $lang = new Language(); + $lang->iso_code = Tools::strtolower($iso_code); + $lang->language_code = $iso_code; // Rewritten afterwards if the language code is available + $lang->active = true; - // If the language pack has not been provided, retrieve it from prestashop.com - if (!$lang_pack) - $lang_pack = Tools::jsonDecode(Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/get_language_pack.php?version='._PS_VERSION_.'&iso_lang='.$iso_code)); + // If the language pack has not been provided, retrieve it from prestashop.com + if (!$lang_pack) { + $lang_pack = Tools::jsonDecode(Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/get_language_pack.php?version='._PS_VERSION_.'&iso_lang='.$iso_code)); + } - // If a language pack has been found or provided, prefill the language object with the value - if ($lang_pack) - foreach (get_object_vars($lang_pack) as $key => $value) - if ($key != 'iso_code' && isset(Language::$definition['fields'][$key])) - $lang->$key = $value; + // If a language pack has been found or provided, prefill the language object with the value + if ($lang_pack) { + foreach (get_object_vars($lang_pack) as $key => $value) { + if ($key != 'iso_code' && isset(Language::$definition['fields'][$key])) { + $lang->$key = $value; + } + } + } - // Use the values given in parameters to override the data retrieved automatically - if ($params_lang !== null && is_array($params_lang)) - foreach ($params_lang as $key => $value) - if ($key != 'iso_code' && isset(Language::$definition['fields'][$key])) - $lang->$key = $value; + // Use the values given in parameters to override the data retrieved automatically + if ($params_lang !== null && is_array($params_lang)) { + foreach ($params_lang as $key => $value) { + if ($key != 'iso_code' && isset(Language::$definition['fields'][$key])) { + $lang->$key = $value; + } + } + } - if (!$lang->name && $lang->iso_code) - $lang->name = $lang->iso_code; + if (!$lang->name && $lang->iso_code) { + $lang->name = $lang->iso_code; + } - if (!$lang->validateFields() || !$lang->validateFieldsLang() || !$lang->add(true, false, $only_add)) - return false; + if (!$lang->validateFields() || !$lang->validateFieldsLang() || !$lang->add(true, false, $only_add)) { + return false; + } - if (isset($params_lang['allow_accented_chars_url']) && in_array($params_lang['allow_accented_chars_url'], array('1', 'true'))) - Configuration::updateGlobalValue('PS_ALLOW_ACCENTED_CHARS_URL', 1); + if (isset($params_lang['allow_accented_chars_url']) && in_array($params_lang['allow_accented_chars_url'], array('1', 'true'))) { + Configuration::updateGlobalValue('PS_ALLOW_ACCENTED_CHARS_URL', 1); + } - $flag = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/flags/jpeg/'.$iso_code.'.jpg'); - if ($flag != null && !preg_match('//', $flag)) - { - $file = fopen(_PS_ROOT_DIR_.'/img/l/'.(int)$lang->id.'.jpg', 'w'); - if ($file) - { - fwrite($file, $flag); - fclose($file); - } - else - Language::_copyNoneFlag((int)$lang->id); - } - else - Language::_copyNoneFlag((int)$lang->id); + $flag = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/flags/jpeg/'.$iso_code.'.jpg'); + if ($flag != null && !preg_match('//', $flag)) { + $file = fopen(_PS_ROOT_DIR_.'/img/l/'.(int)$lang->id.'.jpg', 'w'); + if ($file) { + fwrite($file, $flag); + fclose($file); + } else { + Language::_copyNoneFlag((int)$lang->id); + } + } else { + Language::_copyNoneFlag((int)$lang->id); + } - $files_copy = array( - '/en.jpg', - '/en-default-'.ImageType::getFormatedName('thickbox').'.jpg', - '/en-default-'.ImageType::getFormatedName('home').'.jpg', - '/en-default-'.ImageType::getFormatedName('large').'.jpg', - '/en-default-'.ImageType::getFormatedName('medium').'.jpg', - '/en-default-'.ImageType::getFormatedName('small').'.jpg', - '/en-default-'.ImageType::getFormatedName('scene').'.jpg' - ); + $files_copy = array( + '/en.jpg', + '/en-default-'.ImageType::getFormatedName('thickbox').'.jpg', + '/en-default-'.ImageType::getFormatedName('home').'.jpg', + '/en-default-'.ImageType::getFormatedName('large').'.jpg', + '/en-default-'.ImageType::getFormatedName('medium').'.jpg', + '/en-default-'.ImageType::getFormatedName('small').'.jpg', + '/en-default-'.ImageType::getFormatedName('scene').'.jpg' + ); - foreach (array(_PS_CAT_IMG_DIR_, _PS_MANU_IMG_DIR_, _PS_PROD_IMG_DIR_, _PS_SUPP_IMG_DIR_) as $to) - foreach ($files_copy as $file) - @copy(_PS_ROOT_DIR_.'/img/l'.$file, $to.str_replace('/en', '/'.$iso_code, $file)); + foreach (array(_PS_CAT_IMG_DIR_, _PS_MANU_IMG_DIR_, _PS_PROD_IMG_DIR_, _PS_SUPP_IMG_DIR_) as $to) { + foreach ($files_copy as $file) { + @copy(_PS_ROOT_DIR_.'/img/l'.$file, $to.str_replace('/en', '/'.$iso_code, $file)); + } + } - return true; - } + return true; + } - protected static function _copyNoneFlag($id) - { - return copy(_PS_ROOT_DIR_.'/img/l/none.jpg', _PS_ROOT_DIR_.'/img/l/'.$id.'.jpg'); - } + protected static function _copyNoneFlag($id) + { + return copy(_PS_ROOT_DIR_.'/img/l/none.jpg', _PS_ROOT_DIR_.'/img/l/'.$id.'.jpg'); + } - protected static $_cache_language_installation = null; - public static function isInstalled($iso_code) - { - if (self::$_cache_language_installation === null) - { - self::$_cache_language_installation = array(); - $result = Db::getInstance()->executeS('SELECT `id_lang`, `iso_code` FROM `'._DB_PREFIX_.'lang`'); - foreach ($result as $row) - self::$_cache_language_installation[$row['iso_code']] = $row['id_lang']; - } - return (isset(self::$_cache_language_installation[$iso_code]) ? self::$_cache_language_installation[$iso_code] : false); - } + protected static $_cache_language_installation = null; + public static function isInstalled($iso_code) + { + if (self::$_cache_language_installation === null) { + self::$_cache_language_installation = array(); + $result = Db::getInstance()->executeS('SELECT `id_lang`, `iso_code` FROM `'._DB_PREFIX_.'lang`'); + foreach ($result as $row) { + self::$_cache_language_installation[$row['iso_code']] = $row['id_lang']; + } + } + return (isset(self::$_cache_language_installation[$iso_code]) ? self::$_cache_language_installation[$iso_code] : false); + } - public static function countActiveLanguages($id_shop = null) - { - if (isset(Context::getContext()->shop) && is_object(Context::getContext()->shop) && $id_shop === null) - $id_shop = (int)Context::getContext()->shop->id; + public static function countActiveLanguages($id_shop = null) + { + if (isset(Context::getContext()->shop) && is_object(Context::getContext()->shop) && $id_shop === null) { + $id_shop = (int)Context::getContext()->shop->id; + } - if (!isset(self::$countActiveLanguages[$id_shop])) - self::$countActiveLanguages[$id_shop] = Db::getInstance()->getValue(' + if (!isset(self::$countActiveLanguages[$id_shop])) { + self::$countActiveLanguages[$id_shop] = Db::getInstance()->getValue(' SELECT COUNT(DISTINCT l.id_lang) FROM `'._DB_PREFIX_.'lang` l JOIN '._DB_PREFIX_.'lang_shop lang_shop ON (lang_shop.id_lang = l.id_lang AND lang_shop.id_shop = '.(int)$id_shop.') WHERE l.`active` = 1 '); - return self::$countActiveLanguages[$id_shop]; - } + } + return self::$countActiveLanguages[$id_shop]; + } - public static function downloadAndInstallLanguagePack($iso, $version = null, $params = null, $install = true) - { - if (!Validate::isLanguageIsoCode((string)$iso)) - return false; + public static function downloadAndInstallLanguagePack($iso, $version = null, $params = null, $install = true) + { + if (!Validate::isLanguageIsoCode((string)$iso)) { + return false; + } - if ($version == null) - $version = _PS_VERSION_; + if ($version == null) { + $version = _PS_VERSION_; + } - $lang_pack = false; - $lang_pack_ok = false; - $errors = array(); - $file = _PS_TRANSLATIONS_DIR_.(string)$iso.'.gzip'; + $lang_pack = false; + $lang_pack_ok = false; + $errors = array(); + $file = _PS_TRANSLATIONS_DIR_.(string)$iso.'.gzip'; - if (!$lang_pack_link = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/get_language_pack.php?version='.$version.'&iso_lang='.Tools::strtolower((string)$iso))) - $errors[] = Tools::displayError('Archive cannot be downloaded from prestashop.com.'); - elseif (!$lang_pack = Tools::jsonDecode($lang_pack_link)) - $errors[] = Tools::displayError('Error occurred when language was checked according to your Prestashop version.'); - elseif (empty($lang_pack->error) && ($content = Tools::file_get_contents('http://translations.prestashop.com/download/lang_packs/gzip/'.$lang_pack->version.'/'.Tools::strtolower($lang_pack->iso_code.'.gzip')))) - if (!@file_put_contents($file, $content)) - { - if (is_writable(dirname($file))) - { - @unlink($file); - @file_put_contents($file, $content); - } - elseif (!is_writable($file)) - $errors[] = Tools::displayError('Server does not have permissions for writing.').' ('.$file.')'; - } + if (!$lang_pack_link = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/get_language_pack.php?version='.$version.'&iso_lang='.Tools::strtolower((string)$iso))) { + $errors[] = Tools::displayError('Archive cannot be downloaded from prestashop.com.'); + } elseif (!$lang_pack = Tools::jsonDecode($lang_pack_link)) { + $errors[] = Tools::displayError('Error occurred when language was checked according to your Prestashop version.'); + } elseif (empty($lang_pack->error) && ($content = Tools::file_get_contents('http://translations.prestashop.com/download/lang_packs/gzip/'.$lang_pack->version.'/'.Tools::strtolower($lang_pack->iso_code.'.gzip')))) { + if (!@file_put_contents($file, $content)) { + if (is_writable(dirname($file))) { + @unlink($file); + @file_put_contents($file, $content); + } elseif (!is_writable($file)) { + $errors[] = Tools::displayError('Server does not have permissions for writing.').' ('.$file.')'; + } + } + } - if (!file_exists($file)) - $errors[] = Tools::displayError('No language pack is available for your version.'); - elseif ($install) - { - require_once(_PS_TOOL_DIR_.'tar/Archive_Tar.php'); - $gz = new Archive_Tar($file, true); - $files_list = AdminTranslationsController::filterTranslationFiles(Language::getLanguagePackListContent((string)$iso, $gz)); - $files_paths = AdminTranslationsController::filesListToPaths($files_list); + if (!file_exists($file)) { + $errors[] = Tools::displayError('No language pack is available for your version.'); + } elseif ($install) { + require_once(_PS_TOOL_DIR_.'tar/Archive_Tar.php'); + $gz = new Archive_Tar($file, true); + $files_list = AdminTranslationsController::filterTranslationFiles(Language::getLanguagePackListContent((string)$iso, $gz)); + $files_paths = AdminTranslationsController::filesListToPaths($files_list); - $i = 0; - $tmp_array = array(); + $i = 0; + $tmp_array = array(); - foreach ($files_paths as $files_path) - { - $path = dirname($files_path); - if (is_dir(_PS_TRANSLATIONS_DIR_.'../'.$path) && !is_writable(_PS_TRANSLATIONS_DIR_.'../'.$path) && !in_array($path, $tmp_array)) - { - $errors[] = (!$i++? Tools::displayError('The archive cannot be extracted.').' ' : '').Tools::displayError('The server does not have permissions for writing.').' '.sprintf(Tools::displayError('Please check rights for %s'), $path); - $tmp_array[] = $path; - } - } + foreach ($files_paths as $files_path) { + $path = dirname($files_path); + if (is_dir(_PS_TRANSLATIONS_DIR_.'../'.$path) && !is_writable(_PS_TRANSLATIONS_DIR_.'../'.$path) && !in_array($path, $tmp_array)) { + $errors[] = (!$i++? Tools::displayError('The archive cannot be extracted.').' ' : '').Tools::displayError('The server does not have permissions for writing.').' '.sprintf(Tools::displayError('Please check rights for %s'), $path); + $tmp_array[] = $path; + } + } - if (defined('_PS_HOST_MODE_')) - { - $mails_files = array(); - $other_files = array(); + if (defined('_PS_HOST_MODE_')) { + $mails_files = array(); + $other_files = array(); - foreach ($files_list as $key => $data) - if (substr($data['filename'], 0, 5) == 'mails') - $mails_files[] = $data; - else - $other_files[] = $data; + foreach ($files_list as $key => $data) { + if (substr($data['filename'], 0, 5) == 'mails') { + $mails_files[] = $data; + } else { + $other_files[] = $data; + } + } - $files_list = $other_files; - } + $files_list = $other_files; + } - if (!$gz->extractList(AdminTranslationsController::filesListToPaths($files_list), _PS_TRANSLATIONS_DIR_.'../')) - $errors[] = sprintf(Tools::displayError('Cannot decompress the translation file for the following language: %s'), (string)$iso); + if (!$gz->extractList(AdminTranslationsController::filesListToPaths($files_list), _PS_TRANSLATIONS_DIR_.'../')) { + $errors[] = sprintf(Tools::displayError('Cannot decompress the translation file for the following language: %s'), (string)$iso); + } - // Clear smarty modules cache - Tools::clearCache(); + // Clear smarty modules cache + Tools::clearCache(); - if (!Language::checkAndAddLanguage((string)$iso, $lang_pack, false, $params)) - $errors[] = sprintf(Tools::displayError('An error occurred while creating the language: %s'), (string)$iso); - else - { - // Reset cache - Language::loadLanguages(); - AdminTranslationsController::checkAndAddMailsFiles((string)$iso, $files_list); - AdminTranslationsController::addNewTabs((string)$iso, $files_list); - } - } + if (!Language::checkAndAddLanguage((string)$iso, $lang_pack, false, $params)) { + $errors[] = sprintf(Tools::displayError('An error occurred while creating the language: %s'), (string)$iso); + } else { + // Reset cache + Language::loadLanguages(); + AdminTranslationsController::checkAndAddMailsFiles((string)$iso, $files_list); + AdminTranslationsController::addNewTabs((string)$iso, $files_list); + } + } - return count($errors) ? $errors : true; - } + return count($errors) ? $errors : true; + } - /** - * Check if more on than one language is activated - * - * @since 1.5.0 - * @return bool - */ - public static function isMultiLanguageActivated($id_shop = null) - { - return (Language::countActiveLanguages($id_shop) > 1); - } + /** + * Check if more on than one language is activated + * + * @since 1.5.0 + * @return bool + */ + public static function isMultiLanguageActivated($id_shop = null) + { + return (Language::countActiveLanguages($id_shop) > 1); + } - public static function getLanguagePackListContent($iso, $tar) - { - $key = 'Language::getLanguagePackListContent_'.$iso; - if (!Cache::isStored($key)) - { - if (!$tar instanceof Archive_Tar) - return false; - $result = $tar->listContent(); - Cache::store($key, $result); - return $result; - } - return Cache::retrieve($key); - } + public static function getLanguagePackListContent($iso, $tar) + { + $key = 'Language::getLanguagePackListContent_'.$iso; + if (!Cache::isStored($key)) { + if (!$tar instanceof Archive_Tar) { + return false; + } + $result = $tar->listContent(); + Cache::store($key, $result); + return $result; + } + return Cache::retrieve($key); + } - public static function updateModulesTranslations(Array $modules_list) - { - require_once(_PS_TOOL_DIR_.'tar/Archive_Tar.php'); + public static function updateModulesTranslations(Array $modules_list) + { + require_once(_PS_TOOL_DIR_.'tar/Archive_Tar.php'); - $languages = Language::getLanguages(false); - foreach ($languages as $lang) - { - $gz = false; - $files_listing = array(); - foreach ($modules_list as $module_name) - { - $filegz = _PS_TRANSLATIONS_DIR_.$lang['iso_code'].'.gzip'; + $languages = Language::getLanguages(false); + foreach ($languages as $lang) { + $gz = false; + $files_listing = array(); + foreach ($modules_list as $module_name) { + $filegz = _PS_TRANSLATIONS_DIR_.$lang['iso_code'].'.gzip'; - clearstatcache(); - if (@filemtime($filegz) < (time() - (24 * 3600))) - if (Language::downloadAndInstallLanguagePack($lang['iso_code'], null, null, false) !== true) - break; + clearstatcache(); + if (@filemtime($filegz) < (time() - (24 * 3600))) { + if (Language::downloadAndInstallLanguagePack($lang['iso_code'], null, null, false) !== true) { + break; + } + } - $gz = new Archive_Tar($filegz, true); - $files_list = Language::getLanguagePackListContent($lang['iso_code'], $gz); - foreach ($files_list as $i => $file) - if (strpos($file['filename'], 'modules/'.$module_name.'/') !== 0) - unset($files_list[$i]); + $gz = new Archive_Tar($filegz, true); + $files_list = Language::getLanguagePackListContent($lang['iso_code'], $gz); + foreach ($files_list as $i => $file) { + if (strpos($file['filename'], 'modules/'.$module_name.'/') !== 0) { + unset($files_list[$i]); + } + } - foreach ($files_list as $file) - if (isset($file['filename']) && is_string($file['filename'])) - $files_listing[] = $file['filename']; - } - if ($gz) - $gz->extractList($files_listing, _PS_TRANSLATIONS_DIR_.'../', ''); - } - } + foreach ($files_list as $file) { + if (isset($file['filename']) && is_string($file['filename'])) { + $files_listing[] = $file['filename']; + } + } + } + if ($gz) { + $gz->extractList($files_listing, _PS_TRANSLATIONS_DIR_.'../', ''); + } + } + } } diff --git a/classes/Link.php b/classes/Link.php index 0c7c2739..a96c28d1 100644 --- a/classes/Link.php +++ b/classes/Link.php @@ -26,651 +26,680 @@ class LinkCore { - /** @var bool Rewriting activation */ - protected $allow; - protected $url; - public static $cache = array('page' => array()); - - public $protocol_link; - public $protocol_content; - - protected $ssl_enable; - - protected static $category_disable_rewrite = null; - - /** - * Constructor (initialization only) - */ - public function __construct($protocol_link = null, $protocol_content = null) - { - $this->allow = (int)Configuration::get('PS_REWRITING_SETTINGS'); - $this->url = $_SERVER['SCRIPT_NAME']; - $this->protocol_link = $protocol_link; - $this->protocol_content = $protocol_content; - - if (!defined('_PS_BASE_URL_')) - define('_PS_BASE_URL_', Tools::getShopDomain(true)); - if (!defined('_PS_BASE_URL_SSL_')) - define('_PS_BASE_URL_SSL_', Tools::getShopDomainSsl(true)); - - if (Link::$category_disable_rewrite === null) - Link::$category_disable_rewrite = array(Configuration::get('PS_HOME_CATEGORY'), Configuration::get('PS_ROOT_CATEGORY')); - - $this->ssl_enable = Configuration::get('PS_SSL_ENABLED'); - } - - /** - * Create a link to delete a product - * - * @param mixed $product ID of the product OR a Product object - * @param int $id_picture ID of the picture to delete - * @return string - */ - public function getProductDeletePictureLink($product, $id_picture) - { - $url = $this->getProductLink($product); - return $url.((strpos($url, '?')) ? '&' : '?').'deletePicture='.$id_picture; - } - - /** - * Create a link to a product - * - * @param mixed $product Product object (can be an ID product, but deprecated) - * @param string $alias - * @param string $category - * @param string $ean13 - * @param int $id_lang - * @param int $id_shop (since 1.5.0) ID shop need to be used when we generate a product link for a product in a cart - * @param int $ipa ID product attribute - * @return string - */ - public function getProductLink($product, $alias = null, $category = null, $ean13 = null, $id_lang = null, $id_shop = null, $ipa = 0, $force_routes = false, $relative_protocol = false) - { - $dispatcher = Dispatcher::getInstance(); - - if (!$id_lang) - $id_lang = Context::getContext()->language->id; - - $url = $this->getBaseLink($id_shop, null, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); - - if (!is_object($product)) - { - if (is_array($product) && isset($product['id_product'])) - $product = new Product($product['id_product'], false, $id_lang, $id_shop); - elseif ((int)$product) - $product = new Product((int)$product, false, $id_lang, $id_shop); - else - throw new PrestaShopException('Invalid product vars'); - } - - // Set available keywords - $params = array(); - $params['id'] = $product->id; - $params['rewrite'] = (!$alias) ? $product->getFieldByLang('link_rewrite') : $alias; - - $params['ean13'] = (!$ean13) ? $product->ean13 : $ean13; - $params['meta_keywords'] = Tools::str2url($product->getFieldByLang('meta_keywords')); - $params['meta_title'] = Tools::str2url($product->getFieldByLang('meta_title')); - - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'manufacturer', $id_shop)) - $params['manufacturer'] = Tools::str2url($product->isFullyLoaded ? $product->manufacturer_name : Manufacturer::getNameById($product->id_manufacturer)); - - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'supplier', $id_shop)) - $params['supplier'] = Tools::str2url($product->isFullyLoaded ? $product->supplier_name : Supplier::getNameById($product->id_supplier)); - - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'price', $id_shop)) - $params['price'] = $product->isFullyLoaded ? $product->price : Product::getPriceStatic($product->id, false, null, 6, null, false, true, 1, false, null, null, null, $product->specificPrice); - - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'tags', $id_shop)) - $params['tags'] = Tools::str2url($product->getTags($id_lang)); - - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'category', $id_shop)) - $params['category'] = (!is_null($product->category) && !empty($product->category)) ? Tools::str2url($product->category) : Tools::str2url($category); - - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'reference', $id_shop)) - $params['reference'] = Tools::str2url($product->reference); - - if ($dispatcher->hasKeyword('product_rule', $id_lang, 'categories', $id_shop)) - { - $params['category'] = (!$category) ? $product->category : $category; - $cats = array(); - foreach ($product->getParentCategories($id_lang) as $cat) - if (!in_array($cat['id_category'], Link::$category_disable_rewrite))//remove root and home category from the URL - $cats[] = $cat['link_rewrite']; - $params['categories'] = implode('/', $cats); - } - $anchor = $ipa ? $product->getAnchor($ipa, $force_routes) : ''; - - return $url.$dispatcher->createUrl('product_rule', $id_lang, $params, $force_routes, $anchor, $id_shop); - } - - /** - * Create a link to a category - * - * @param mixed $category Category object (can be an ID category, but deprecated) - * @param string $alias - * @param int $id_lang - * @param string $selected_filters Url parameter to autocheck filters of the module blocklayered - * @return string - */ - public function getCategoryLink($category, $alias = null, $id_lang = null, $selected_filters = null, $id_shop = null, $relative_protocol = false) - { - if (!$id_lang) - $id_lang = Context::getContext()->language->id; - - $url = $this->getBaseLink($id_shop, null, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); - - if (!is_object($category)) - $category = new Category($category, $id_lang); - - // Set available keywords - $params = array(); - $params['id'] = $category->id; - $params['rewrite'] = (!$alias) ? $category->link_rewrite : $alias; - $params['meta_keywords'] = Tools::str2url($category->getFieldByLang('meta_keywords')); - $params['meta_title'] = Tools::str2url($category->getFieldByLang('meta_title')); - - // Selected filters is used by the module blocklayered - $selected_filters = is_null($selected_filters) ? '' : $selected_filters; - - if (empty($selected_filters)) - $rule = 'category_rule'; - else - { - $rule = 'layered_rule'; - $params['selected_filters'] = $selected_filters; - } - - return $url.Dispatcher::getInstance()->createUrl($rule, $id_lang, $params, $this->allow, '', $id_shop); - } - - /** - * Create a link to a CMS category - * - * @param mixed $category CMSCategory object (can be an ID category, but deprecated) - * @param string $alias - * @param int $id_lang - * @return string - */ - public function getCMSCategoryLink($cms_category, $alias = null, $id_lang = null, $id_shop = null, $relative_protocol = false) - { - if (!$id_lang) - $id_lang = Context::getContext()->language->id; - - $url = $this->getBaseLink($id_shop, null, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); - - $dispatcher = Dispatcher::getInstance(); - if (!is_object($cms_category)) - { - if ($alias !== null && !$dispatcher->hasKeyword('cms_category_rule', $id_lang, 'meta_keywords', $id_shop) && !$dispatcher->hasKeyword('cms_category_rule', $id_lang, 'meta_title', $id_shop)) - return $url.$dispatcher->createUrl('cms_category_rule', $id_lang, array('id' => (int)$cms_category, 'rewrite' => (string)$alias), $this->allow, '', $id_shop); - $cms_category = new CMSCategory($cms_category, $id_lang); - } - if (is_array($cms_category->link_rewrite) && isset($cms_category->link_rewrite[(int)$id_lang])) - $cms_category->link_rewrite = $cms_category->link_rewrite[(int)$id_lang]; - if (is_array($cms_category->meta_keywords) && isset($cms_category->meta_keywords[(int)$id_lang])) - $cms_category->meta_keywords = $cms_category->meta_keywords[(int)$id_lang]; - if (is_array($cms_category->meta_title) && isset($cms_category->meta_title[(int)$id_lang])) - $cms_category->meta_title = $cms_category->meta_title[(int)$id_lang]; - - // Set available keywords - $params = array(); - $params['id'] = $cms_category->id; - $params['rewrite'] = (!$alias) ? $cms_category->link_rewrite : $alias; - $params['meta_keywords'] = Tools::str2url($cms_category->meta_keywords); - $params['meta_title'] = Tools::str2url($cms_category->meta_title); - - return $url.$dispatcher->createUrl('cms_category_rule', $id_lang, $params, $this->allow, '', $id_shop); - } - - /** - * Create a link to a CMS page - * - * @param mixed $cms CMS object (can be an ID CMS, but deprecated) - * @param string $alias - * @param bool $ssl - * @param int $id_lang - * @return string - */ - public function getCMSLink($cms, $alias = null, $ssl = null, $id_lang = null, $id_shop = null, $relative_protocol = false) - { - if (!$id_lang) - $id_lang = Context::getContext()->language->id; - - $url = $this->getBaseLink($id_shop, $ssl, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); - - $dispatcher = Dispatcher::getInstance(); - if (!is_object($cms)) - { - if ($alias !== null && !$dispatcher->hasKeyword('cms_rule', $id_lang, 'meta_keywords', $id_shop) && !$dispatcher->hasKeyword('cms_rule', $id_lang, 'meta_title', $id_shop)) - return $url.$dispatcher->createUrl('cms_rule', $id_lang, array('id' => (int)$cms, 'rewrite' => (string)$alias), $this->allow, '', $id_shop); - $cms = new CMS($cms, $id_lang); - } - - // Set available keywords - $params = array(); - $params['id'] = $cms->id; - $params['rewrite'] = (!$alias) ? (is_array($cms->link_rewrite) ? $cms->link_rewrite[(int)$id_lang] : $cms->link_rewrite) : $alias; - - $params['meta_keywords'] = ''; - if (isset($cms->meta_keywords) && !empty($cms->meta_keywords)) - $params['meta_keywords'] = is_array($cms->meta_keywords) ? Tools::str2url($cms->meta_keywords[(int)$id_lang]) : Tools::str2url($cms->meta_keywords); - - $params['meta_title'] = ''; - if (isset($cms->meta_title) && !empty($cms->meta_title)) - $params['meta_title'] = is_array($cms->meta_title) ? Tools::str2url($cms->meta_title[(int)$id_lang]) : Tools::str2url($cms->meta_title); - - return $url.$dispatcher->createUrl('cms_rule', $id_lang, $params, $this->allow, '', $id_shop); - } - - /** - * Create a link to a supplier - * - * @param mixed $supplier Supplier object (can be an ID supplier, but deprecated) - * @param string $alias - * @param int $id_lang - * @return string - */ - public function getSupplierLink($supplier, $alias = null, $id_lang = null, $id_shop = null, $relative_protocol = false) - { - if (!$id_lang) - $id_lang = Context::getContext()->language->id; - - $url = $this->getBaseLink($id_shop, null, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); - - $dispatcher = Dispatcher::getInstance(); - if (!is_object($supplier)) - { - if ($alias !== null && !$dispatcher->hasKeyword('supplier_rule', $id_lang, 'meta_keywords', $id_shop) && !$dispatcher->hasKeyword('supplier_rule', $id_lang, 'meta_title', $id_shop)) - return $url.$dispatcher->createUrl('supplier_rule', $id_lang, array('id' => (int)$supplier, 'rewrite' => (string)$alias), $this->allow, '', $id_shop); - $supplier = new Supplier($supplier, $id_lang); - } - - // Set available keywords - $params = array(); - $params['id'] = $supplier->id; - $params['rewrite'] = (!$alias) ? $supplier->link_rewrite : $alias; - $params['meta_keywords'] = Tools::str2url($supplier->meta_keywords); - $params['meta_title'] = Tools::str2url($supplier->meta_title); - - return $url.$dispatcher->createUrl('supplier_rule', $id_lang, $params, $this->allow, '', $id_shop); - } - - /** - * Create a link to a manufacturer - * - * @param mixed $manufacturer Manufacturer object (can be an ID supplier, but deprecated) - * @param string $alias - * @param int $id_lang - * @return string - */ - public function getManufacturerLink($manufacturer, $alias = null, $id_lang = null, $id_shop = null, $relative_protocol = false) - { - if (!$id_lang) - $id_lang = Context::getContext()->language->id; - - $url = $this->getBaseLink($id_shop, null, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); - - $dispatcher = Dispatcher::getInstance(); - if (!is_object($manufacturer)) - { - if ($alias !== null && !$dispatcher->hasKeyword('manufacturer_rule', $id_lang, 'meta_keywords', $id_shop) && !$dispatcher->hasKeyword('manufacturer_rule', $id_lang, 'meta_title', $id_shop)) - return $url.$dispatcher->createUrl('manufacturer_rule', $id_lang, array('id' => (int)$manufacturer, 'rewrite' => (string)$alias), $this->allow, '', $id_shop); - $manufacturer = new Manufacturer($manufacturer, $id_lang); - } - - // Set available keywords - $params = array(); - $params['id'] = $manufacturer->id; - $params['rewrite'] = (!$alias) ? $manufacturer->link_rewrite : $alias; - $params['meta_keywords'] = Tools::str2url($manufacturer->meta_keywords); - $params['meta_title'] = Tools::str2url($manufacturer->meta_title); - - return $url.$dispatcher->createUrl('manufacturer_rule', $id_lang, $params, $this->allow, '', $id_shop); - } - - /** - * Create a link to a module - * - * @since 1.5.0 - * @param string $module Module name - * @param string $process Action name - * @param int $id_lang - * @return string - */ - public function getModuleLink($module, $controller = 'default', array $params = array(), $ssl = null, $id_lang = null, $id_shop = null, $relative_protocol = false) - { - if (!$id_lang) - $id_lang = Context::getContext()->language->id; - - $url = $this->getBaseLink($id_shop, $ssl, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); - - // Set available keywords - $params['module'] = $module; - $params['controller'] = $controller ? $controller : 'default'; - - // If the module has its own route ... just use it ! - if (Dispatcher::getInstance()->hasRoute('module-'.$module.'-'.$controller, $id_lang, $id_shop)) - return $this->getPageLink('module-'.$module.'-'.$controller, $ssl, $id_lang, $params); - else - return $url.Dispatcher::getInstance()->createUrl('module', $id_lang, $params, $this->allow, '', $id_shop); - } - - /** - * Use controller name to create a link - * - * @param string $controller - * @param bool $with_token include or not the token in the url - * @return string url - */ - public function getAdminLink($controller, $with_token = true) - { - $id_lang = Context::getContext()->language->id; - - $params = $with_token ? array('token' => Tools::getAdminTokenLite($controller)) : array(); - return Dispatcher::getInstance()->createUrl($controller, $id_lang, $params, false); - } - - /** - * Returns a link to a product image for display - * Note: the new image filesystem stores product images in subdirectories of img/p/ - * - * @param string $name rewrite link of the image - * @param string $ids id part of the image filename - can be "id_product-id_image" (legacy support, recommended) or "id_image" (new) - * @param string $type - */ - public function getImageLink($name, $ids, $type = null) - { - $not_default = false; - - // Check if module is installed, enabled, customer is logged in and watermark logged option is on - if (Configuration::get('WATERMARK_LOGGED') && (Module::isInstalled('watermark') && Module::isEnabled('watermark')) && isset(Context::getContext()->customer->id)) - $type .= '-'.Configuration::get('WATERMARK_HASH'); - - // legacy mode or default image - $theme = ((Shop::isFeatureActive() && file_exists(_PS_PROD_IMG_DIR_.$ids.($type ? '-'.$type : '').'-'.(int)Context::getContext()->shop->id_theme.'.jpg')) ? '-'.Context::getContext()->shop->id_theme : ''); - if ((Configuration::get('PS_LEGACY_IMAGES') - && (file_exists(_PS_PROD_IMG_DIR_.$ids.($type ? '-'.$type : '').$theme.'.jpg'))) - || ($not_default = strpos($ids, 'default') !== false)) - { - if ($this->allow == 1 && !$not_default) - $uri_path = __PS_BASE_URI__.$ids.($type ? '-'.$type : '').$theme.'/'.$name.'.jpg'; - else - $uri_path = _THEME_PROD_DIR_.$ids.($type ? '-'.$type : '').$theme.'.jpg'; - } - else - { - // if ids if of the form id_product-id_image, we want to extract the id_image part - $split_ids = explode('-', $ids); - $id_image = (isset($split_ids[1]) ? $split_ids[1] : $split_ids[0]); - $theme = ((Shop::isFeatureActive() && file_exists(_PS_PROD_IMG_DIR_.Image::getImgFolderStatic($id_image).$id_image.($type ? '-'.$type : '').'-'.(int)Context::getContext()->shop->id_theme.'.jpg')) ? '-'.Context::getContext()->shop->id_theme : ''); - if ($this->allow == 1) - $uri_path = __PS_BASE_URI__.$id_image.($type ? '-'.$type : '').$theme.'/'.$name.'.jpg'; - else - $uri_path = _THEME_PROD_DIR_.Image::getImgFolderStatic($id_image).$id_image.($type ? '-'.$type : '').$theme.'.jpg'; - } - - return $this->protocol_content.Tools::getMediaServer($uri_path).$uri_path; - } - - public function getMediaLink($filepath) - { - return $this->protocol_content.Tools::getMediaServer($filepath).$filepath; - } - - /** - * Create a simple link - * - * @param string $controller - * @param bool $ssl - * @param int $id_lang - * @param string|array $request - * @param bool $request_url_encode Use URL encode - * - * @return string Page link - */ - public function getPageLink($controller, $ssl = null, $id_lang = null, $request = null, $request_url_encode = false, $id_shop = null, $relative_protocol = false) - { - //If $controller contains '&' char, it means that $controller contains request data and must be parsed first - $p = strpos($controller, '&'); - if ($p !== false) - { - $request = substr($controller, $p + 1); - $request_url_encode = false; - $controller = substr($controller, 0, $p); - } - - $controller = Tools::strReplaceFirst('.php', '', $controller); - if (!$id_lang) - $id_lang = (int)Context::getContext()->language->id; - - //need to be unset because getModuleLink need those params when rewrite is enable - if (is_array($request)) - { - if (isset($request['module'])) - unset($request['module']); - if (isset($request['controller'])) - unset($request['controller']); - } - else - { - // @FIXME html_entity_decode has been added due to '&' => '%3B' ... - $request = html_entity_decode($request); - if ($request_url_encode) - $request = urlencode($request); - parse_str($request, $request); - } - - $uri_path = Dispatcher::getInstance()->createUrl($controller, $id_lang, $request, false, '', $id_shop); - - return $this->getBaseLink($id_shop, $ssl, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop).ltrim($uri_path, '/'); - } - - public function getCatImageLink($name, $id_category, $type = null) - { - if ($this->allow == 1 && $type) - $uri_path = __PS_BASE_URI__.'c/'.$id_category.'-'.$type.'/'.$name.'.jpg'; - else - $uri_path = _THEME_CAT_DIR_.$id_category.($type ? '-'.$type : '').'.jpg'; - return $this->protocol_content.Tools::getMediaServer($uri_path).$uri_path; - } - - /** - * Create link after language change, for the change language block - * - * @param int $id_lang Language ID - * @return string link - */ - public function getLanguageLink($id_lang, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - - $params = $_GET; - unset($params['isolang'], $params['controller']); - - if (!$this->allow) - $params['id_lang'] = $id_lang; - else - unset($params['id_lang']); - - $controller = Dispatcher::getInstance()->getController(); - - if (!empty($context->controller->php_self)) - $controller = $context->controller->php_self; - - if ($controller == 'product' && isset($params['id_product'])) - return $this->getProductLink((int)$params['id_product'], null, null, null, (int)$id_lang); - elseif ($controller == 'category' && isset($params['id_category'])) - return $this->getCategoryLink((int)$params['id_category'], null, (int)$id_lang); - elseif ($controller == 'supplier' && isset($params['id_supplier'])) - return $this->getSupplierLink((int)$params['id_supplier'], null, (int)$id_lang); - elseif ($controller == 'manufacturer' && isset($params['id_manufacturer'])) - return $this->getManufacturerLink((int)$params['id_manufacturer'], null, (int)$id_lang); - elseif ($controller == 'cms' && isset($params['id_cms'])) - return $this->getCMSLink((int)$params['id_cms'], null, false, (int)$id_lang); - elseif ($controller == 'cms' && isset($params['id_cms_category'])) - return $this->getCMSCategoryLink((int)$params['id_cms_category'], null, (int)$id_lang); - elseif (isset($params['fc']) && $params['fc'] == 'module') - { - $module = Validate::isModuleName(Tools::getValue('module')) ? Tools::getValue('module') : ''; - if (!empty($module)) - { - unset($params['fc'], $params['module']); - return $this->getModuleLink($module, $controller, $params, null, (int)$id_lang); - } - } - - return $this->getPageLink($controller, null, $id_lang, $params); - } - - public function goPage($url, $p) - { - $url = rtrim(str_replace('?&', '?', $url), '?'); - return $url.($p == 1 ? '' : (!strstr($url, '?') ? '?' : '&').'p='.(int)$p); - } - - /** - * Get pagination link - * - * @param string $type Controller name - * @param int $id_object - * @param bool $nb Show nb element per page attribute - * @param bool $sort Show sort attribute - * @param bool $pagination Show page number attribute - * @param bool $array If false return an url, if true return an array - */ - public function getPaginationLink($type, $id_object, $nb = false, $sort = false, $pagination = false, $array = false) - { - // If no parameter $type, try to get it by using the controller name - if (!$type && !$id_object) - { - $method_name = 'get'.Dispatcher::getInstance()->getController().'Link'; - if (method_exists($this, $method_name) && isset($_GET['id_'.Dispatcher::getInstance()->getController()])) - { - $type = Dispatcher::getInstance()->getController(); - $id_object = $_GET['id_'.$type]; - } - } - - if ($type && $id_object) - $url = $this->{'get'.$type.'Link'}($id_object, null); - else - { - if (isset(Context::getContext()->controller->php_self)) - $name = Context::getContext()->controller->php_self; - else - $name = Dispatcher::getInstance()->getController(); - $url = $this->getPageLink($name); - } - - $vars = array(); - $vars_nb = array('n'); - $vars_sort = array('orderby', 'orderway'); - $vars_pagination = array('p'); - - foreach ($_GET as $k => $value) - { - if ($k != 'id_'.$type && $k != 'controller') - { - if (Configuration::get('PS_REWRITING_SETTINGS') && ($k == 'isolang' || $k == 'id_lang')) - continue; - $if_nb = (!$nb || ($nb && !in_array($k, $vars_nb))); - $if_sort = (!$sort || ($sort && !in_array($k, $vars_sort))); - $if_pagination = (!$pagination || ($pagination && !in_array($k, $vars_pagination))); - if ($if_nb && $if_sort && $if_pagination) - { - if (!is_array($value)) - $vars[urlencode($k)] = $value; - else - { - foreach (explode('&', http_build_query(array($k => $value), '', '&')) as $key => $val) - { - $data = explode('=', $val); - $vars[urldecode($data[0])] = $data[1]; - } - } - } - } - } - - if (!$array) - if (count($vars)) - return $url.(!strstr($url, '?') && ($this->allow == 1 || $url == $this->url) ? '?' : '&').http_build_query($vars, '', '&'); - else - return $url; - - $vars['requestUrl'] = $url; - - if ($type && $id_object) - $vars['id_'.$type] = (is_object($id_object) ? (int)$id_object->id : (int)$id_object); - - if (!$this->allow == 1) - $vars['controller'] = Dispatcher::getInstance()->getController(); - return $vars; - } - - public function addSortDetails($url, $orderby, $orderway) - { - return $url.(!strstr($url, '?') ? '?' : '&').'orderby='.urlencode($orderby).'&orderway='.urlencode($orderway); - } - - protected function getLangLink($id_lang = null, Context $context = null, $id_shop = null) - { - if (!$context) - $context = Context::getContext(); - - if ((!$this->allow && in_array($id_shop, array($context->shop->id, null))) || !Language::isMultiLanguageActivated($id_shop) || !(int)Configuration::get('PS_REWRITING_SETTINGS', null, null, $id_shop)) - return ''; - - if (!$id_lang) - $id_lang = $context->language->id; - - return Language::getIsoById($id_lang).'/'; - } - - protected function getBaseLink($id_shop = null, $ssl = null, $relative_protocol = false) - { - static $force_ssl = null; - - if ($ssl === null) - { - if ($force_ssl === null) - $force_ssl = (Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE')); - $ssl = $force_ssl; - } - - if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && $id_shop !== null) - $shop = new Shop($id_shop); - else - $shop = Context::getContext()->shop; - - if ($relative_protocol) - $base = '//'.($ssl && $this->ssl_enable ? $shop->domain_ssl : $shop->domain); - else - $base = (($ssl && $this->ssl_enable) ? 'https://'.$shop->domain_ssl : 'http://'.$shop->domain); - - return $base.$shop->getBaseURI(); - } - - public static function getQuickLink($url) - { - $parsedUrl = parse_url($url); - $output = array(); - if (is_array($parsedUrl) && isset($parsedUrl['query'])) - { - parse_str($parsedUrl['query'], $output); - unset($output['token'], $output['conf'], $output['id_quick_access']); - } - return http_build_query($output); - } - - public function matchQuickLink($url) - { - $quicklink = $this->getQuickLink($url); - if (isset($quicklink) && $quicklink === ($this->getQuickLink($_SERVER['REQUEST_URI']))) - return true; - else - return false; - } + /** @var bool Rewriting activation */ + protected $allow; + protected $url; + public static $cache = array('page' => array()); + + public $protocol_link; + public $protocol_content; + + protected $ssl_enable; + + protected static $category_disable_rewrite = null; + + /** + * Constructor (initialization only) + */ + public function __construct($protocol_link = null, $protocol_content = null) + { + $this->allow = (int)Configuration::get('PS_REWRITING_SETTINGS'); + $this->url = $_SERVER['SCRIPT_NAME']; + $this->protocol_link = $protocol_link; + $this->protocol_content = $protocol_content; + + if (!defined('_PS_BASE_URL_')) { + define('_PS_BASE_URL_', Tools::getShopDomain(true)); + } + if (!defined('_PS_BASE_URL_SSL_')) { + define('_PS_BASE_URL_SSL_', Tools::getShopDomainSsl(true)); + } + + if (Link::$category_disable_rewrite === null) { + Link::$category_disable_rewrite = array(Configuration::get('PS_HOME_CATEGORY'), Configuration::get('PS_ROOT_CATEGORY')); + } + + $this->ssl_enable = Configuration::get('PS_SSL_ENABLED'); + } + + /** + * Create a link to delete a product + * + * @param mixed $product ID of the product OR a Product object + * @param int $id_picture ID of the picture to delete + * @return string + */ + public function getProductDeletePictureLink($product, $id_picture) + { + $url = $this->getProductLink($product); + return $url.((strpos($url, '?')) ? '&' : '?').'deletePicture='.$id_picture; + } + + /** + * Create a link to a product + * + * @param mixed $product Product object (can be an ID product, but deprecated) + * @param string $alias + * @param string $category + * @param string $ean13 + * @param int $id_lang + * @param int $id_shop (since 1.5.0) ID shop need to be used when we generate a product link for a product in a cart + * @param int $ipa ID product attribute + * @return string + */ + public function getProductLink($product, $alias = null, $category = null, $ean13 = null, $id_lang = null, $id_shop = null, $ipa = 0, $force_routes = false, $relative_protocol = false, $add_anchor = false) + { + $dispatcher = Dispatcher::getInstance(); + + if (!$id_lang) { + $id_lang = Context::getContext()->language->id; + } + + $url = $this->getBaseLink($id_shop, null, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); + + if (!is_object($product)) { + if (is_array($product) && isset($product['id_product'])) { + $product = new Product($product['id_product'], false, $id_lang, $id_shop); + } elseif ((int)$product) { + $product = new Product((int)$product, false, $id_lang, $id_shop); + } else { + throw new PrestaShopException('Invalid product vars'); + } + } + + // Set available keywords + $params = array(); + $params['id'] = $product->id; + $params['rewrite'] = (!$alias) ? $product->getFieldByLang('link_rewrite') : $alias; + + $params['ean13'] = (!$ean13) ? $product->ean13 : $ean13; + $params['meta_keywords'] = Tools::str2url($product->getFieldByLang('meta_keywords')); + $params['meta_title'] = Tools::str2url($product->getFieldByLang('meta_title')); + + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'manufacturer', $id_shop)) { + $params['manufacturer'] = Tools::str2url($product->isFullyLoaded ? $product->manufacturer_name : Manufacturer::getNameById($product->id_manufacturer)); + } + + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'supplier', $id_shop)) { + $params['supplier'] = Tools::str2url($product->isFullyLoaded ? $product->supplier_name : Supplier::getNameById($product->id_supplier)); + } + + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'price', $id_shop)) { + $params['price'] = $product->isFullyLoaded ? $product->price : Product::getPriceStatic($product->id, false, null, 6, null, false, true, 1, false, null, null, null, $product->specificPrice); + } + + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'tags', $id_shop)) { + $params['tags'] = Tools::str2url($product->getTags($id_lang)); + } + + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'category', $id_shop)) { + $params['category'] = (!is_null($product->category) && !empty($product->category)) ? Tools::str2url($product->category) : Tools::str2url($category); + } + + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'reference', $id_shop)) { + $params['reference'] = Tools::str2url($product->reference); + } + + if ($dispatcher->hasKeyword('product_rule', $id_lang, 'categories', $id_shop)) { + $params['category'] = (!$category) ? $product->category : $category; + $cats = array(); + foreach ($product->getParentCategories($id_lang) as $cat) { + if (!in_array($cat['id_category'], Link::$category_disable_rewrite)) { + //remove root and home category from the URL + $cats[] = $cat['link_rewrite']; + } + } + $params['categories'] = implode('/', $cats); + } + $anchor = $ipa ? $product->getAnchor((int)$ipa, (bool)$add_anchor) : ''; + + return $url.$dispatcher->createUrl('product_rule', $id_lang, $params, $force_routes, $anchor, $id_shop); + } + + /** + * Create a link to a category + * + * @param mixed $category Category object (can be an ID category, but deprecated) + * @param string $alias + * @param int $id_lang + * @param string $selected_filters Url parameter to autocheck filters of the module blocklayered + * @return string + */ + public function getCategoryLink($category, $alias = null, $id_lang = null, $selected_filters = null, $id_shop = null, $relative_protocol = false) + { + if (!$id_lang) { + $id_lang = Context::getContext()->language->id; + } + + $url = $this->getBaseLink($id_shop, null, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); + + if (!is_object($category)) { + $category = new Category($category, $id_lang); + } + + // Set available keywords + $params = array(); + $params['id'] = $category->id; + $params['rewrite'] = (!$alias) ? $category->link_rewrite : $alias; + $params['meta_keywords'] = Tools::str2url($category->getFieldByLang('meta_keywords')); + $params['meta_title'] = Tools::str2url($category->getFieldByLang('meta_title')); + + // Selected filters is used by the module blocklayered + $selected_filters = is_null($selected_filters) ? '' : $selected_filters; + + if (empty($selected_filters)) { + $rule = 'category_rule'; + } else { + $rule = 'layered_rule'; + $params['selected_filters'] = $selected_filters; + } + + return $url.Dispatcher::getInstance()->createUrl($rule, $id_lang, $params, $this->allow, '', $id_shop); + } + + /** + * Create a link to a CMS category + * + * @param mixed $category CMSCategory object (can be an ID category, but deprecated) + * @param string $alias + * @param int $id_lang + * @return string + */ + public function getCMSCategoryLink($cms_category, $alias = null, $id_lang = null, $id_shop = null, $relative_protocol = false) + { + if (!$id_lang) { + $id_lang = Context::getContext()->language->id; + } + + $url = $this->getBaseLink($id_shop, null, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); + + $dispatcher = Dispatcher::getInstance(); + if (!is_object($cms_category)) { + if ($alias !== null && !$dispatcher->hasKeyword('cms_category_rule', $id_lang, 'meta_keywords', $id_shop) && !$dispatcher->hasKeyword('cms_category_rule', $id_lang, 'meta_title', $id_shop)) { + return $url.$dispatcher->createUrl('cms_category_rule', $id_lang, array('id' => (int)$cms_category, 'rewrite' => (string)$alias), $this->allow, '', $id_shop); + } + $cms_category = new CMSCategory($cms_category, $id_lang); + } + if (is_array($cms_category->link_rewrite) && isset($cms_category->link_rewrite[(int)$id_lang])) { + $cms_category->link_rewrite = $cms_category->link_rewrite[(int)$id_lang]; + } + if (is_array($cms_category->meta_keywords) && isset($cms_category->meta_keywords[(int)$id_lang])) { + $cms_category->meta_keywords = $cms_category->meta_keywords[(int)$id_lang]; + } + if (is_array($cms_category->meta_title) && isset($cms_category->meta_title[(int)$id_lang])) { + $cms_category->meta_title = $cms_category->meta_title[(int)$id_lang]; + } + + // Set available keywords + $params = array(); + $params['id'] = $cms_category->id; + $params['rewrite'] = (!$alias) ? $cms_category->link_rewrite : $alias; + $params['meta_keywords'] = Tools::str2url($cms_category->meta_keywords); + $params['meta_title'] = Tools::str2url($cms_category->meta_title); + + return $url.$dispatcher->createUrl('cms_category_rule', $id_lang, $params, $this->allow, '', $id_shop); + } + + /** + * Create a link to a CMS page + * + * @param mixed $cms CMS object (can be an ID CMS, but deprecated) + * @param string $alias + * @param bool $ssl + * @param int $id_lang + * @return string + */ + public function getCMSLink($cms, $alias = null, $ssl = null, $id_lang = null, $id_shop = null, $relative_protocol = false) + { + if (!$id_lang) { + $id_lang = Context::getContext()->language->id; + } + + $url = $this->getBaseLink($id_shop, $ssl, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); + + $dispatcher = Dispatcher::getInstance(); + if (!is_object($cms)) { + if ($alias !== null && !$dispatcher->hasKeyword('cms_rule', $id_lang, 'meta_keywords', $id_shop) && !$dispatcher->hasKeyword('cms_rule', $id_lang, 'meta_title', $id_shop)) { + return $url.$dispatcher->createUrl('cms_rule', $id_lang, array('id' => (int)$cms, 'rewrite' => (string)$alias), $this->allow, '', $id_shop); + } + $cms = new CMS($cms, $id_lang); + } + + // Set available keywords + $params = array(); + $params['id'] = $cms->id; + $params['rewrite'] = (!$alias) ? (is_array($cms->link_rewrite) ? $cms->link_rewrite[(int)$id_lang] : $cms->link_rewrite) : $alias; + + $params['meta_keywords'] = ''; + if (isset($cms->meta_keywords) && !empty($cms->meta_keywords)) { + $params['meta_keywords'] = is_array($cms->meta_keywords) ? Tools::str2url($cms->meta_keywords[(int)$id_lang]) : Tools::str2url($cms->meta_keywords); + } + + $params['meta_title'] = ''; + if (isset($cms->meta_title) && !empty($cms->meta_title)) { + $params['meta_title'] = is_array($cms->meta_title) ? Tools::str2url($cms->meta_title[(int)$id_lang]) : Tools::str2url($cms->meta_title); + } + + return $url.$dispatcher->createUrl('cms_rule', $id_lang, $params, $this->allow, '', $id_shop); + } + + /** + * Create a link to a supplier + * + * @param mixed $supplier Supplier object (can be an ID supplier, but deprecated) + * @param string $alias + * @param int $id_lang + * @return string + */ + public function getSupplierLink($supplier, $alias = null, $id_lang = null, $id_shop = null, $relative_protocol = false) + { + if (!$id_lang) { + $id_lang = Context::getContext()->language->id; + } + + $url = $this->getBaseLink($id_shop, null, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); + + $dispatcher = Dispatcher::getInstance(); + if (!is_object($supplier)) { + if ($alias !== null && !$dispatcher->hasKeyword('supplier_rule', $id_lang, 'meta_keywords', $id_shop) && !$dispatcher->hasKeyword('supplier_rule', $id_lang, 'meta_title', $id_shop)) { + return $url.$dispatcher->createUrl('supplier_rule', $id_lang, array('id' => (int)$supplier, 'rewrite' => (string)$alias), $this->allow, '', $id_shop); + } + $supplier = new Supplier($supplier, $id_lang); + } + + // Set available keywords + $params = array(); + $params['id'] = $supplier->id; + $params['rewrite'] = (!$alias) ? $supplier->link_rewrite : $alias; + $params['meta_keywords'] = Tools::str2url($supplier->meta_keywords); + $params['meta_title'] = Tools::str2url($supplier->meta_title); + + return $url.$dispatcher->createUrl('supplier_rule', $id_lang, $params, $this->allow, '', $id_shop); + } + + /** + * Create a link to a manufacturer + * + * @param mixed $manufacturer Manufacturer object (can be an ID supplier, but deprecated) + * @param string $alias + * @param int $id_lang + * @return string + */ + public function getManufacturerLink($manufacturer, $alias = null, $id_lang = null, $id_shop = null, $relative_protocol = false) + { + if (!$id_lang) { + $id_lang = Context::getContext()->language->id; + } + + $url = $this->getBaseLink($id_shop, null, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); + + $dispatcher = Dispatcher::getInstance(); + if (!is_object($manufacturer)) { + if ($alias !== null && !$dispatcher->hasKeyword('manufacturer_rule', $id_lang, 'meta_keywords', $id_shop) && !$dispatcher->hasKeyword('manufacturer_rule', $id_lang, 'meta_title', $id_shop)) { + return $url.$dispatcher->createUrl('manufacturer_rule', $id_lang, array('id' => (int)$manufacturer, 'rewrite' => (string)$alias), $this->allow, '', $id_shop); + } + $manufacturer = new Manufacturer($manufacturer, $id_lang); + } + + // Set available keywords + $params = array(); + $params['id'] = $manufacturer->id; + $params['rewrite'] = (!$alias) ? $manufacturer->link_rewrite : $alias; + $params['meta_keywords'] = Tools::str2url($manufacturer->meta_keywords); + $params['meta_title'] = Tools::str2url($manufacturer->meta_title); + + return $url.$dispatcher->createUrl('manufacturer_rule', $id_lang, $params, $this->allow, '', $id_shop); + } + + /** + * Create a link to a module + * + * @since 1.5.0 + * @param string $module Module name + * @param string $process Action name + * @param int $id_lang + * @return string + */ + public function getModuleLink($module, $controller = 'default', array $params = array(), $ssl = null, $id_lang = null, $id_shop = null, $relative_protocol = false) + { + if (!$id_lang) { + $id_lang = Context::getContext()->language->id; + } + + $url = $this->getBaseLink($id_shop, $ssl, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop); + + // Set available keywords + $params['module'] = $module; + $params['controller'] = $controller ? $controller : 'default'; + + // If the module has its own route ... just use it ! + if (Dispatcher::getInstance()->hasRoute('module-'.$module.'-'.$controller, $id_lang, $id_shop)) { + return $this->getPageLink('module-'.$module.'-'.$controller, $ssl, $id_lang, $params); + } else { + return $url.Dispatcher::getInstance()->createUrl('module', $id_lang, $params, $this->allow, '', $id_shop); + } + } + + /** + * Use controller name to create a link + * + * @param string $controller + * @param bool $with_token include or not the token in the url + * @return string url + */ + public function getAdminLink($controller, $with_token = true) + { + $id_lang = Context::getContext()->language->id; + + $params = $with_token ? array('token' => Tools::getAdminTokenLite($controller)) : array(); + return Dispatcher::getInstance()->createUrl($controller, $id_lang, $params, false); + } + + /** + * Returns a link to a product image for display + * Note: the new image filesystem stores product images in subdirectories of img/p/ + * + * @param string $name rewrite link of the image + * @param string $ids id part of the image filename - can be "id_product-id_image" (legacy support, recommended) or "id_image" (new) + * @param string $type + */ + public function getImageLink($name, $ids, $type = null) + { + $not_default = false; + + // Check if module is installed, enabled, customer is logged in and watermark logged option is on + if (Configuration::get('WATERMARK_LOGGED') && (Module::isInstalled('watermark') && Module::isEnabled('watermark')) && isset(Context::getContext()->customer->id)) { + $type .= '-'.Configuration::get('WATERMARK_HASH'); + } + + // legacy mode or default image + $theme = ((Shop::isFeatureActive() && file_exists(_PS_PROD_IMG_DIR_.$ids.($type ? '-'.$type : '').'-'.(int)Context::getContext()->shop->id_theme.'.jpg')) ? '-'.Context::getContext()->shop->id_theme : ''); + if ((Configuration::get('PS_LEGACY_IMAGES') + && (file_exists(_PS_PROD_IMG_DIR_.$ids.($type ? '-'.$type : '').$theme.'.jpg'))) + || ($not_default = strpos($ids, 'default') !== false)) { + if ($this->allow == 1 && !$not_default) { + $uri_path = __PS_BASE_URI__.$ids.($type ? '-'.$type : '').$theme.'/'.$name.'.jpg'; + } else { + $uri_path = _THEME_PROD_DIR_.$ids.($type ? '-'.$type : '').$theme.'.jpg'; + } + } else { + // if ids if of the form id_product-id_image, we want to extract the id_image part + $split_ids = explode('-', $ids); + $id_image = (isset($split_ids[1]) ? $split_ids[1] : $split_ids[0]); + $theme = ((Shop::isFeatureActive() && file_exists(_PS_PROD_IMG_DIR_.Image::getImgFolderStatic($id_image).$id_image.($type ? '-'.$type : '').'-'.(int)Context::getContext()->shop->id_theme.'.jpg')) ? '-'.Context::getContext()->shop->id_theme : ''); + if ($this->allow == 1) { + $uri_path = __PS_BASE_URI__.$id_image.($type ? '-'.$type : '').$theme.'/'.$name.'.jpg'; + } else { + $uri_path = _THEME_PROD_DIR_.Image::getImgFolderStatic($id_image).$id_image.($type ? '-'.$type : '').$theme.'.jpg'; + } + } + + return $this->protocol_content.Tools::getMediaServer($uri_path).$uri_path; + } + + public function getMediaLink($filepath) + { + return $this->protocol_content.Tools::getMediaServer($filepath).$filepath; + } + + /** + * Create a simple link + * + * @param string $controller + * @param bool $ssl + * @param int $id_lang + * @param string|array $request + * @param bool $request_url_encode Use URL encode + * + * @return string Page link + */ + public function getPageLink($controller, $ssl = null, $id_lang = null, $request = null, $request_url_encode = false, $id_shop = null, $relative_protocol = false) + { + //If $controller contains '&' char, it means that $controller contains request data and must be parsed first + $p = strpos($controller, '&'); + if ($p !== false) { + $request = substr($controller, $p + 1); + $request_url_encode = false; + $controller = substr($controller, 0, $p); + } + + $controller = Tools::strReplaceFirst('.php', '', $controller); + if (!$id_lang) { + $id_lang = (int)Context::getContext()->language->id; + } + + //need to be unset because getModuleLink need those params when rewrite is enable + if (is_array($request)) { + if (isset($request['module'])) { + unset($request['module']); + } + if (isset($request['controller'])) { + unset($request['controller']); + } + } else { + // @FIXME html_entity_decode has been added due to '&' => '%3B' ... + $request = html_entity_decode($request); + if ($request_url_encode) { + $request = urlencode($request); + } + parse_str($request, $request); + } + + $uri_path = Dispatcher::getInstance()->createUrl($controller, $id_lang, $request, false, '', $id_shop); + + return $this->getBaseLink($id_shop, $ssl, $relative_protocol).$this->getLangLink($id_lang, null, $id_shop).ltrim($uri_path, '/'); + } + + public function getCatImageLink($name, $id_category, $type = null) + { + if ($this->allow == 1 && $type) { + $uri_path = __PS_BASE_URI__.'c/'.$id_category.'-'.$type.'/'.$name.'.jpg'; + } else { + $uri_path = _THEME_CAT_DIR_.$id_category.($type ? '-'.$type : '').'.jpg'; + } + return $this->protocol_content.Tools::getMediaServer($uri_path).$uri_path; + } + + /** + * Create link after language change, for the change language block + * + * @param int $id_lang Language ID + * @return string link + */ + public function getLanguageLink($id_lang, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + + $params = $_GET; + unset($params['isolang'], $params['controller']); + + if (!$this->allow) { + $params['id_lang'] = $id_lang; + } else { + unset($params['id_lang']); + } + + $controller = Dispatcher::getInstance()->getController(); + + if (!empty($context->controller->php_self)) { + $controller = $context->controller->php_self; + } + + if ($controller == 'product' && isset($params['id_product'])) { + return $this->getProductLink((int)$params['id_product'], null, null, null, (int)$id_lang); + } elseif ($controller == 'category' && isset($params['id_category'])) { + return $this->getCategoryLink((int)$params['id_category'], null, (int)$id_lang); + } elseif ($controller == 'supplier' && isset($params['id_supplier'])) { + return $this->getSupplierLink((int)$params['id_supplier'], null, (int)$id_lang); + } elseif ($controller == 'manufacturer' && isset($params['id_manufacturer'])) { + return $this->getManufacturerLink((int)$params['id_manufacturer'], null, (int)$id_lang); + } elseif ($controller == 'cms' && isset($params['id_cms'])) { + return $this->getCMSLink((int)$params['id_cms'], null, null, (int)$id_lang); + } elseif ($controller == 'cms' && isset($params['id_cms_category'])) { + return $this->getCMSCategoryLink((int)$params['id_cms_category'], null, (int)$id_lang); + } elseif (isset($params['fc']) && $params['fc'] == 'module') { + $module = Validate::isModuleName(Tools::getValue('module')) ? Tools::getValue('module') : ''; + if (!empty($module)) { + unset($params['fc'], $params['module']); + return $this->getModuleLink($module, $controller, $params, null, (int)$id_lang); + } + } + + return $this->getPageLink($controller, null, $id_lang, $params); + } + + public function goPage($url, $p) + { + $url = rtrim(str_replace('?&', '?', $url), '?'); + return $url.($p == 1 ? '' : (!strstr($url, '?') ? '?' : '&').'p='.(int)$p); + } + + /** + * Get pagination link + * + * @param string $type Controller name + * @param int $id_object + * @param bool $nb Show nb element per page attribute + * @param bool $sort Show sort attribute + * @param bool $pagination Show page number attribute + * @param bool $array If false return an url, if true return an array + */ + public function getPaginationLink($type, $id_object, $nb = false, $sort = false, $pagination = false, $array = false) + { + // If no parameter $type, try to get it by using the controller name + if (!$type && !$id_object) { + $method_name = 'get'.Dispatcher::getInstance()->getController().'Link'; + if (method_exists($this, $method_name) && isset($_GET['id_'.Dispatcher::getInstance()->getController()])) { + $type = Dispatcher::getInstance()->getController(); + $id_object = $_GET['id_'.$type]; + } + } + + if ($type && $id_object) { + $url = $this->{'get'.$type.'Link'}($id_object, null); + } else { + if (isset(Context::getContext()->controller->php_self)) { + $name = Context::getContext()->controller->php_self; + } else { + $name = Dispatcher::getInstance()->getController(); + } + $url = $this->getPageLink($name); + } + + $vars = array(); + $vars_nb = array('n'); + $vars_sort = array('orderby', 'orderway'); + $vars_pagination = array('p'); + + foreach ($_GET as $k => $value) { + if ($k != 'id_'.$type && $k != 'controller') { + if (Configuration::get('PS_REWRITING_SETTINGS') && ($k == 'isolang' || $k == 'id_lang')) { + continue; + } + $if_nb = (!$nb || ($nb && !in_array($k, $vars_nb))); + $if_sort = (!$sort || ($sort && !in_array($k, $vars_sort))); + $if_pagination = (!$pagination || ($pagination && !in_array($k, $vars_pagination))); + if ($if_nb && $if_sort && $if_pagination) { + if (!is_array($value)) { + $vars[urlencode($k)] = $value; + } else { + foreach (explode('&', http_build_query(array($k => $value), '', '&')) as $key => $val) { + $data = explode('=', $val); + $vars[urldecode($data[0])] = $data[1]; + } + } + } + } + } + + if (!$array) { + if (count($vars)) { + return $url.(!strstr($url, '?') && ($this->allow == 1 || $url == $this->url) ? '?' : '&').http_build_query($vars, '', '&'); + } else { + return $url; + } + } + + $vars['requestUrl'] = $url; + + if ($type && $id_object) { + $vars['id_'.$type] = (is_object($id_object) ? (int)$id_object->id : (int)$id_object); + } + + if (!$this->allow == 1) { + $vars['controller'] = Dispatcher::getInstance()->getController(); + } + return $vars; + } + + public function addSortDetails($url, $orderby, $orderway) + { + return $url.(!strstr($url, '?') ? '?' : '&').'orderby='.urlencode($orderby).'&orderway='.urlencode($orderway); + } + + protected function getLangLink($id_lang = null, Context $context = null, $id_shop = null) + { + if (!$context) { + $context = Context::getContext(); + } + + if ((!$this->allow && in_array($id_shop, array($context->shop->id, null))) || !Language::isMultiLanguageActivated($id_shop) || !(int)Configuration::get('PS_REWRITING_SETTINGS', null, null, $id_shop)) { + return ''; + } + + if (!$id_lang) { + $id_lang = $context->language->id; + } + + return Language::getIsoById($id_lang).'/'; + } + + protected function getBaseLink($id_shop = null, $ssl = null, $relative_protocol = false) + { + static $force_ssl = null; + + if ($ssl === null) { + if ($force_ssl === null) { + $force_ssl = (Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE')); + } + $ssl = $force_ssl; + } + + if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && $id_shop !== null) { + $shop = new Shop($id_shop); + } else { + $shop = Context::getContext()->shop; + } + + if ($relative_protocol) { + $base = '//'.($ssl && $this->ssl_enable ? $shop->domain_ssl : $shop->domain); + } else { + $base = (($ssl && $this->ssl_enable) ? 'https://'.$shop->domain_ssl : 'http://'.$shop->domain); + } + + return $base.$shop->getBaseURI(); + } + + public static function getQuickLink($url) + { + $parsedUrl = parse_url($url); + $output = array(); + if (is_array($parsedUrl) && isset($parsedUrl['query'])) { + parse_str($parsedUrl['query'], $output); + unset($output['token'], $output['conf'], $output['id_quick_access']); + } + return http_build_query($output); + } + + public function matchQuickLink($url) + { + $quicklink = $this->getQuickLink($url); + if (isset($quicklink) && $quicklink === ($this->getQuickLink($_SERVER['REQUEST_URI']))) { + return true; + } else { + return false; + } + } } diff --git a/classes/LocalizationPack.php b/classes/LocalizationPack.php index 5eaad330..fbf7f78c 100644 --- a/classes/LocalizationPack.php +++ b/classes/LocalizationPack.php @@ -26,469 +26,462 @@ class LocalizationPackCore { - public $name; - public $version; + public $name; + public $version; - protected $iso_code_lang; - protected $iso_currency; - protected $_errors = array(); + protected $iso_code_lang; + protected $iso_currency; + protected $_errors = array(); - public function loadLocalisationPack($file, $selection, $install_mode = false, $iso_localization_pack = null) - { - if (!$xml = simplexml_load_string($file)) - return false; - $main_attributes = $xml->attributes(); - $this->name = (string)$main_attributes['name']; - $this->version = (string)$main_attributes['version']; - if ($iso_localization_pack) - { + public function loadLocalisationPack($file, $selection, $install_mode = false, $iso_localization_pack = null) + { + if (!$xml = @simplexml_load_string($file)) { + return false; + } + libxml_clear_errors(); + $main_attributes = $xml->attributes(); + $this->name = (string)$main_attributes['name']; + $this->version = (string)$main_attributes['version']; + if ($iso_localization_pack) { + $id_country = (int)Country::getByIso($iso_localization_pack); - $id_country = Country::getByIso($iso_localization_pack); - $country = new Country($id_country); - if (!$country->active) - { - $country->active = 1; - if (!$country->update()) - $this->_errors[] = Tools::displayError('Cannot enable the associated country: ').$country->name; - } - } + if ($id_country) { + $country = new Country($id_country); + } + if (!$id_country || !Validate::isLoadedObject($country)) { + $this->_errors[] = Tools::displayError(sprintf('Cannot load country : %1d', $id_country)); + return false; + } + if (!$country->active) { + $country->active = 1; + if (!$country->update()) { + $this->_errors[] = Tools::displayError(sprintf('Cannot enable the associated country: %1s', $country->name)); + } + } + } - $res = true; + $res = true; - if (empty($selection)) - { - $res &= $this->_installStates($xml); - $res &= $this->_installTaxes($xml); - $res &= $this->_installCurrencies($xml, $install_mode); - $res &= $this->installConfiguration($xml); - $res &= $this->installModules($xml); - $res &= $this->updateDefaultGroupDisplayMethod($xml); + if (empty($selection)) { + $res &= $this->_installStates($xml); + $res &= $this->_installTaxes($xml); + $res &= $this->_installCurrencies($xml, $install_mode); + $res &= $this->installConfiguration($xml); + $res &= $this->installModules($xml); + $res &= $this->updateDefaultGroupDisplayMethod($xml); - if (($res || $install_mode) && isset($this->iso_code_lang)) - { - if (!($id_lang = (int)Language::getIdByIso($this->iso_code_lang, true))) - $id_lang = 1; - if (!$install_mode) - Configuration::updateValue('PS_LANG_DEFAULT', $id_lang); - } - elseif (!isset($this->iso_code_lang) && $install_mode) - $id_lang = 1; + if (($res || $install_mode) && isset($this->iso_code_lang)) { + if (!($id_lang = (int)Language::getIdByIso($this->iso_code_lang, true))) { + $id_lang = 1; + } + if (!$install_mode) { + Configuration::updateValue('PS_LANG_DEFAULT', $id_lang); + } + } elseif (!isset($this->iso_code_lang) && $install_mode) { + $id_lang = 1; + } - if (!Language::isInstalled(Language::getIsoById($id_lang))) - { - $res &= $this->_installLanguages($xml, $install_mode); - $res &= $this->_installUnits($xml); - } + if (!Language::isInstalled(Language::getIsoById($id_lang))) { + $res &= $this->_installLanguages($xml, $install_mode); + $res &= $this->_installUnits($xml); + } - if ($install_mode && $res && isset($this->iso_currency)) - { - Cache::clean('Currency::getIdByIsoCode_*'); - $res &= Configuration::updateValue('PS_CURRENCY_DEFAULT', (int)Currency::getIdByIsoCode($this->iso_currency)); - Currency::refreshCurrencies(); - } + if ($install_mode && $res && isset($this->iso_currency)) { + Cache::clean('Currency::getIdByIsoCode_*'); + $res &= Configuration::updateValue('PS_CURRENCY_DEFAULT', (int)Currency::getIdByIsoCode($this->iso_currency)); + Currency::refreshCurrencies(); + } + } else { + foreach ($selection as $selected) { + // No need to specify the install_mode because if the selection mode is used, then it's not the install + $res &= Validate::isLocalizationPackSelection($selected) ? $this->{'_install'.$selected}($xml) : false; + } + } - } - else - foreach ($selection as $selected) - // No need to specify the install_mode because if the selection mode is used, then it's not the install - $res &= Validate::isLocalizationPackSelection($selected) ? $this->{'_install'.$selected}($xml) : false; + return $res; + } - return $res; - } + /** + * @param SimpleXMLElement $xml + * @return bool + * @throws PrestaShopException + */ + protected function _installStates($xml) + { + if (isset($xml->states->state)) { + foreach ($xml->states->state as $data) { + /** @var SimpleXMLElement $data */ + $attributes = $data->attributes(); + $id_country = ($attributes['country']) ? (int)Country::getByIso(strval($attributes['country'])) : false; + $id_state = ($id_country) ? State::getIdByIso($attributes['iso_code'], $id_country) : State::getIdByName($attributes['name']); - /** - * @param SimpleXMLElement $xml - * @return bool - * @throws PrestaShopException - */ - protected function _installStates($xml) - { - if (isset($xml->states->state)) - foreach ($xml->states->state as $data) - { - /** @var SimpleXMLElement $data */ - $attributes = $data->attributes(); - $id_country = ($attributes['country']) ? (int)Country::getByIso(strval($attributes['country'])) : false; - $id_state = ($id_country) ? State::getIdByIso($attributes['iso_code'], $id_country) : State::getIdByName($attributes['name']); + if (!$id_state) { + $state = new State(); + $state->name = strval($attributes['name']); + $state->iso_code = strval($attributes['iso_code']); + $state->id_country = $id_country; - if (!$id_state) - { - $state = new State(); - $state->name = strval($attributes['name']); - $state->iso_code = strval($attributes['iso_code']); - $state->id_country = $id_country; + $id_zone = (int)Zone::getIdByName(strval($attributes['zone'])); + if (!$id_zone) { + $zone = new Zone(); + $zone->name = (string)$attributes['zone']; + $zone->active = true; - $id_zone = (int)Zone::getIdByName(strval($attributes['zone'])); - if (!$id_zone) - { - $zone = new Zone(); - $zone->name = (string)$attributes['zone']; - $zone->active = true; + if (!$zone->add()) { + $this->_errors[] = Tools::displayError('Invalid Zone name.'); + return false; + } - if (!$zone->add()) - { - $this->_errors[] = Tools::displayError('Invalid Zone name.'); - return false; - } + $id_zone = $zone->id; + } - $id_zone = $zone->id; - } + $state->id_zone = $id_zone; - $state->id_zone = $id_zone; + if (!$state->validateFields()) { + $this->_errors[] = Tools::displayError('Invalid state properties.'); + return false; + } - if (!$state->validateFields()) - { - $this->_errors[] = Tools::displayError('Invalid state properties.'); - return false; - } + $country = new Country($state->id_country); + if (!$country->contains_states) { + $country->contains_states = 1; + if (!$country->update()) { + $this->_errors[] = Tools::displayError('Cannot update the associated country: ').$country->name; + } + } - $country = new Country($state->id_country); - if (!$country->contains_states) - { - $country->contains_states = 1; - if (!$country->update()) - $this->_errors[] = Tools::displayError('Cannot update the associated country: ').$country->name; - } + if (!$state->add()) { + $this->_errors[] = Tools::displayError('An error occurred while adding the state.'); + return false; + } + } else { + $state = new State($id_state); + if (!Validate::isLoadedObject($state)) { + $this->_errors[] = Tools::displayError('An error occurred while fetching the state.'); + return false; + } + } + } + } - if (!$state->add()) - { - $this->_errors[] = Tools::displayError('An error occurred while adding the state.'); - return false; - } - } - else - { - $state = new State($id_state); - if (!Validate::isLoadedObject($state)) - { - $this->_errors[] = Tools::displayError('An error occurred while fetching the state.'); - return false; - } - } - } + return true; + } - return true; - } + /** + * @param SimpleXMLElement $xml + * @return bool + * @throws PrestaShopException + */ + protected function _installTaxes($xml) + { + if (isset($xml->taxes->tax)) { + $assoc_taxes = array(); + foreach ($xml->taxes->tax as $taxData) { + /** @var SimpleXMLElement $taxData */ + $attributes = $taxData->attributes(); + if (($id_tax = Tax::getTaxIdByName($attributes['name']))) { + $assoc_taxes[(int)$attributes['id']] = $id_tax; + continue; + } + $tax = new Tax(); + $tax->name[(int)Configuration::get('PS_LANG_DEFAULT')] = (string)$attributes['name']; + $tax->rate = (float)$attributes['rate']; + $tax->active = 1; - /** - * @param SimpleXMLElement $xml - * @return bool - * @throws PrestaShopException - */ - protected function _installTaxes($xml) - { - if (isset($xml->taxes->tax)) - { - $assoc_taxes = array(); - foreach ($xml->taxes->tax as $taxData) - { - /** @var SimpleXMLElement $taxData */ - $attributes = $taxData->attributes(); - if (($id_tax = Tax::getTaxIdByName($attributes['name']))) - { - $assoc_taxes[(int)$attributes['id']] = $id_tax; - continue; - } - $tax = new Tax(); - $tax->name[(int)Configuration::get('PS_LANG_DEFAULT')] = (string)$attributes['name']; - $tax->rate = (float)$attributes['rate']; - $tax->active = 1; + if (($error = $tax->validateFields(false, true)) !== true || ($error = $tax->validateFieldsLang(false, true)) !== true) { + $this->_errors[] = Tools::displayError('Invalid tax properties.').' '.$error; + return false; + } - if (($error = $tax->validateFields(false, true)) !== true || ($error = $tax->validateFieldsLang(false, true)) !== true) - { - $this->_errors[] = Tools::displayError('Invalid tax properties.').' '.$error; - return false; - } + if (!$tax->add()) { + $this->_errors[] = Tools::displayError('An error occurred while importing the tax: ').(string)$attributes['name']; + return false; + } - if (!$tax->add()) - { - $this->_errors[] = Tools::displayError('An error occurred while importing the tax: ').(string)$attributes['name']; - return false; - } + $assoc_taxes[(int)$attributes['id']] = $tax->id; + } - $assoc_taxes[(int)$attributes['id']] = $tax->id; - } + foreach ($xml->taxes->taxRulesGroup as $group) { + /** @var SimpleXMLElement $group */ + $group_attributes = $group->attributes(); + if (!Validate::isGenericName($group_attributes['name'])) { + continue; + } - foreach ($xml->taxes->taxRulesGroup as $group) - { - /** @var SimpleXMLElement $group */ - $group_attributes = $group->attributes(); - if (!Validate::isGenericName($group_attributes['name'])) - continue; + if (TaxRulesGroup::getIdByName($group['name'])) { + continue; + } - if (TaxRulesGroup::getIdByName($group['name'])) - continue; + $trg = new TaxRulesGroup(); + $trg->name = $group['name']; + $trg->active = 1; - $trg = new TaxRulesGroup(); - $trg->name = $group['name']; - $trg->active = 1; + if (!$trg->save()) { + $this->_errors[] = Tools::displayError('This tax rule cannot be saved.'); + return false; + } - if (!$trg->save()) - { - $this->_errors[] = Tools::displayError('This tax rule cannot be saved.'); - return false; - } + foreach ($group->taxRule as $rule) { + /** @var SimpleXMLElement $rule */ + $rule_attributes = $rule->attributes(); - foreach ($group->taxRule as $rule) - { - /** @var SimpleXMLElement $rule */ - $rule_attributes = $rule->attributes(); + // Validation + if (!isset($rule_attributes['iso_code_country'])) { + continue; + } - // Validation - if (!isset($rule_attributes['iso_code_country'])) - continue; + $id_country = (int)Country::getByIso(strtoupper($rule_attributes['iso_code_country'])); + if (!$id_country) { + continue; + } - $id_country = Country::getByIso(strtoupper($rule_attributes['iso_code_country'])); - if (!$id_country) - continue; + if (!isset($rule_attributes['id_tax']) || !array_key_exists(strval($rule_attributes['id_tax']), $assoc_taxes)) { + continue; + } - if (!isset($rule_attributes['id_tax']) || !array_key_exists(strval($rule_attributes['id_tax']), $assoc_taxes)) - continue; + // Default values + $id_state = (int)isset($rule_attributes['iso_code_state']) ? State::getIdByIso(strtoupper($rule_attributes['iso_code_state'])) : 0; + $id_county = 0; + $zipcode_from = 0; + $zipcode_to = 0; + $behavior = $rule_attributes['behavior']; - // Default values - $id_state = (int)isset($rule_attributes['iso_code_state']) ? State::getIdByIso(strtoupper($rule_attributes['iso_code_state'])) : 0; - $id_county = 0; - $zipcode_from = 0; - $zipcode_to = 0; - $behavior = $rule_attributes['behavior']; + if (isset($rule_attributes['zipcode_from'])) { + $zipcode_from = $rule_attributes['zipcode_from']; + if (isset($rule_attributes['zipcode_to'])) { + $zipcode_to = $rule_attributes['zipcode_to']; + } + } - if (isset($rule_attributes['zipcode_from'])) - { - $zipcode_from = $rule_attributes['zipcode_from']; - if (isset($rule_attributes['zipcode_to'])) - $zipcode_to = $rule_attributes['zipcode_to']; - } + // Creation + $tr = new TaxRule(); + $tr->id_tax_rules_group = $trg->id; + $tr->id_country = $id_country; + $tr->id_state = $id_state; + $tr->id_county = $id_county; + $tr->zipcode_from = $zipcode_from; + $tr->zipcode_to = $zipcode_to; + $tr->behavior = $behavior; + $tr->description = ''; + $tr->id_tax = $assoc_taxes[strval($rule_attributes['id_tax'])]; + $tr->save(); + } + } + } + return true; + } - // Creation - $tr = new TaxRule(); - $tr->id_tax_rules_group = $trg->id; - $tr->id_country = $id_country; - $tr->id_state = $id_state; - $tr->id_county = $id_county; - $tr->zipcode_from = $zipcode_from; - $tr->zipcode_to = $zipcode_to; - $tr->behavior = $behavior; - $tr->description = ''; - $tr->id_tax = $assoc_taxes[strval($rule_attributes['id_tax'])]; - $tr->save(); - } - } - } - return true; - } + /** + * @param SimpleXMLElement $xml + * @param bool $install_mode + * @return bool + * @throws PrestaShopException + */ + protected function _installCurrencies($xml, $install_mode = false) + { + if (isset($xml->currencies->currency)) { + foreach ($xml->currencies->currency as $data) { + /** @var SimpleXMLElement $data */ + $attributes = $data->attributes(); + if (Currency::exists($attributes['iso_code'], (int)$attributes['iso_code_num'])) { + continue; + } + $currency = new Currency(); + $currency->name = (string)$attributes['name']; + $currency->iso_code = (string)$attributes['iso_code']; + $currency->iso_code_num = (int)$attributes['iso_code_num']; + $currency->sign = (string)$attributes['sign']; + $currency->blank = (int)$attributes['blank']; + $currency->conversion_rate = 1; // This value will be updated if the store is online + $currency->format = (int)$attributes['format']; + $currency->decimals = (int)$attributes['decimals']; + $currency->active = true; + if (!$currency->validateFields()) { + $this->_errors[] = Tools::displayError('Invalid currency properties.'); + return false; + } + if (!Currency::exists($currency->iso_code, $currency->iso_code_num)) { + if (!$currency->add()) { + $this->_errors[] = Tools::displayError('An error occurred while importing the currency: ').strval($attributes['name']); + return false; + } - /** - * @param SimpleXMLElement $xml - * @param bool $install_mode - * @return bool - * @throws PrestaShopException - */ - protected function _installCurrencies($xml, $install_mode = false) - { - if (isset($xml->currencies->currency)) - { - foreach ($xml->currencies->currency as $data) - { - /** @var SimpleXMLElement $data */ - $attributes = $data->attributes(); - if (Currency::exists($attributes['iso_code'], (int)$attributes['iso_code_num'])) - continue; - $currency = new Currency(); - $currency->name = (string)$attributes['name']; - $currency->iso_code = (string)$attributes['iso_code']; - $currency->iso_code_num = (int)$attributes['iso_code_num']; - $currency->sign = (string)$attributes['sign']; - $currency->blank = (int)$attributes['blank']; - $currency->conversion_rate = 1; // This value will be updated if the store is online - $currency->format = (int)$attributes['format']; - $currency->decimals = (int)$attributes['decimals']; - $currency->active = true; - if (!$currency->validateFields()) - { - $this->_errors[] = Tools::displayError('Invalid currency properties.'); - return false; - } - if (!Currency::exists($currency->iso_code, $currency->iso_code_num)) - { - if (!$currency->add()) - { - $this->_errors[] = Tools::displayError('An error occurred while importing the currency: ').strval($attributes['name']); - return false; - } + PaymentModule::addCurrencyPermissions($currency->id); + } + } - PaymentModule::addCurrencyPermissions($currency->id); - } - } + if (($error = Currency::refreshCurrencies()) !== null) { + $this->_errors[] = $error; + } - if (($error = Currency::refreshCurrencies()) !== null) - $this->_errors[] = $error; + if (!count($this->_errors) && $install_mode && isset($attributes['iso_code']) && count($xml->currencies->currency) == 1) { + $this->iso_currency = $attributes['iso_code']; + } + } - if (!count($this->_errors) && $install_mode && isset($attributes['iso_code']) && count($xml->currencies->currency) == 1) - $this->iso_currency = $attributes['iso_code']; - } + return true; + } - return true; - } + /** + * @param SimpleXMLElement $xml + * @param bool $install_mode + * @return bool + */ + protected function _installLanguages($xml, $install_mode = false) + { + $attributes = array(); + if (isset($xml->languages->language)) { + foreach ($xml->languages->language as $data) { + /** @var SimpleXMLElement $data */ + $attributes = $data->attributes(); + // if we are not in an installation context or if the pack is not available in the local directory + if (Language::getIdByIso($attributes['iso_code']) && !$install_mode) { + continue; + } - /** - * @param SimpleXMLElement $xml - * @param bool $install_mode - * @return bool - */ - protected function _installLanguages($xml, $install_mode = false) - { - $attributes = array(); - if (isset($xml->languages->language)) - foreach ($xml->languages->language as $data) - { - /** @var SimpleXMLElement $data */ - $attributes = $data->attributes(); - // if we are not in an installation context or if the pack is not available in the local directory - if (Language::getIdByIso($attributes['iso_code']) && !$install_mode) - continue; + $errors = Language::downloadAndInstallLanguagePack($attributes['iso_code'], $attributes['version'], $attributes); + if ($errors !== true && is_array($errors)) { + $this->_errors = array_merge($this->_errors, $errors); + } + } + } - $errors = Language::downloadAndInstallLanguagePack($attributes['iso_code'], $attributes['version'], $attributes); - if ($errors !== true && is_array($errors)) - $this->_errors = array_merge($this->_errors, $errors); - } + // change the default language if there is only one language in the localization pack + if (!count($this->_errors) && $install_mode && isset($attributes['iso_code']) && count($xml->languages->language) == 1) { + $this->iso_code_lang = $attributes['iso_code']; + } - // change the default language if there is only one language in the localization pack - if (!count($this->_errors) && $install_mode && isset($attributes['iso_code']) && count($xml->languages->language) == 1) - $this->iso_code_lang = $attributes['iso_code']; + return !count($this->_errors); + } - return !count($this->_errors); - } + /** + * @param SimpleXMLElement $xml + * @return bool + */ + protected function _installUnits($xml) + { + $varNames = array('weight' => 'PS_WEIGHT_UNIT', 'volume' => 'PS_VOLUME_UNIT', 'short_distance' => 'PS_DIMENSION_UNIT', 'base_distance' => 'PS_BASE_DISTANCE_UNIT', 'long_distance' => 'PS_DISTANCE_UNIT'); + if (isset($xml->units->unit)) { + foreach ($xml->units->unit as $data) { + /** @var SimpleXMLElement $data */ + $attributes = $data->attributes(); + if (!isset($varNames[strval($attributes['type'])])) { + $this->_errors[] = Tools::displayError('Localization pack corrupted: wrong unit type.'); + return false; + } + if (!Configuration::updateValue($varNames[strval($attributes['type'])], strval($attributes['value']))) { + $this->_errors[] = Tools::displayError('An error occurred while setting the units.'); + return false; + } + } + } + return true; + } - /** - * @param SimpleXMLElement $xml - * @return bool - */ - protected function _installUnits($xml) - { - $varNames = array('weight' => 'PS_WEIGHT_UNIT', 'volume' => 'PS_VOLUME_UNIT', 'short_distance' => 'PS_DIMENSION_UNIT', 'base_distance' => 'PS_BASE_DISTANCE_UNIT', 'long_distance' => 'PS_DISTANCE_UNIT'); - if (isset($xml->units->unit)) - foreach ($xml->units->unit as $data) - { - /** @var SimpleXMLElement $data */ - $attributes = $data->attributes(); - if (!isset($varNames[strval($attributes['type'])])) - { - $this->_errors[] = Tools::displayError('Localization pack corrupted: wrong unit type.'); - return false; - } - if (!Configuration::updateValue($varNames[strval($attributes['type'])], strval($attributes['value']))) - { - $this->_errors[] = Tools::displayError('An error occurred while setting the units.'); - return false; - } - } - return true; - } + /** + * Install/Uninstall a module from a localization file + * + * + * + * @param SimpleXMLElement $xml + * @return bool + */ + protected function installModules($xml) + { + if (isset($xml->modules)) { + foreach ($xml->modules->module as $data) { + /** @var SimpleXMLElement $data */ + $attributes = $data->attributes(); + $name = (string)$attributes['name']; + if (isset($name) && $module = Module::getInstanceByName($name)) { + $install = ($attributes['install'] == 1) ? true : false; - /** - * Install/Uninstall a module from a localization file - * - * - * - * @param SimpleXMLElement $xml - * @return bool - */ - protected function installModules($xml) - { - if (isset($xml->modules)) - foreach ($xml->modules->module as $data) - { - /** @var SimpleXMLElement $data */ - $attributes = $data->attributes(); - $name = (string)$attributes['name']; - if (isset($name) && $module = Module::getInstanceByName($name)) - { - $install = ($attributes['install'] == 1) ? true : false; + if ($install) { + if (!Module::isInstalled($name)) { + if (!$module->install()) { + $this->_errors[] = Tools::displayError('An error occurred while installing the module:').$name; + } + } + } elseif (Module::isInstalled($name)) { + if (!$module->uninstall()) { + $this->_errors[] = Tools::displayError('An error occurred while uninstalling the module:').$name; + } + } - if ($install) - { - if (!Module::isInstalled($name)) - if (!$module->install()) - $this->_errors[] = Tools::displayError('An error occurred while installing the module:').$name; - } - else - if (Module::isInstalled($name)) - if (!$module->uninstall()) - $this->_errors[] = Tools::displayError('An error occurred while uninstalling the module:').$name; + unset($module); + } else { + $this->_errors[] = Tools::displayError('An error has occurred, this module does not exist:').$name; + } + } + } - unset($module); - } - else - $this->_errors[] = Tools::displayError('An error has occurred, this module does not exist:').$name; - } + return true; + } - return true; - } + /** + * Update a configuration variable from a localization file + * + * + * + * @param SimpleXMLElement $xml + * @return bool + */ + protected function installConfiguration($xml) + { + if (isset($xml->configurations)) { + foreach ($xml->configurations->configuration as $data) { + /** @var SimpleXMLElement $data */ + $attributes = $data->attributes(); + $name = (string)$attributes['name']; - /** - * Update a configuration variable from a localization file - * - * - * - * @param SimpleXMLElement $xml - * @return bool - */ - protected function installConfiguration($xml) - { - if (isset($xml->configurations)) - foreach ($xml->configurations->configuration as $data) - { - /** @var SimpleXMLElement $data */ - $attributes = $data->attributes(); - $name = (string)$attributes['name']; + if (isset($name) && isset($attributes['value']) && Configuration::get($name) !== false) { + if (!Configuration::updateValue($name, (string)$attributes['value'])) { + $this->_errors[] = Tools::displayError('An error occurred during the configuration setup: '.$name); + } + } + } + } - if (isset($name) && isset($attributes['value']) && Configuration::get($name) !== false) - if (!Configuration::updateValue($name, (string)$attributes['value'])) - $this->_errors[] = Tools::displayError('An error occurred during the configuration setup: '.$name); - } + return true; + } - return true; - } + /** + * @param SimpleXMLElement $xml + * @return bool + */ + protected function _installGroups($xml) + { + return $this->updateDefaultGroupDisplayMethod($xml); + } - /** - * @param SimpleXMLElement $xml - * @return bool - */ - protected function _installGroups($xml) - { - return $this->updateDefaultGroupDisplayMethod($xml); - } + /** + * @param SimpleXMLElement $xml + * @return bool + */ + protected function updateDefaultGroupDisplayMethod($xml) + { + if (isset($xml->group_default)) { + $attributes = $xml->group_default->attributes(); + if (isset($attributes['price_display_method']) && in_array((int)$attributes['price_display_method'], array(0, 1))) { + Configuration::updateValue('PRICE_DISPLAY_METHOD', (int)$attributes['price_display_method']); - /** - * @param SimpleXMLElement $xml - * @return bool - */ - protected function updateDefaultGroupDisplayMethod($xml) - { - if (isset($xml->group_default)) - { - $attributes = $xml->group_default->attributes(); - if (isset($attributes['price_display_method']) && in_array((int)$attributes['price_display_method'], array(0, 1))) - { - Configuration::updateValue('PRICE_DISPLAY_METHOD', (int)$attributes['price_display_method']); + foreach (array((int)Configuration::get('PS_CUSTOMER_GROUP'), (int)Configuration::get('PS_GUEST_GROUP'), (int)Configuration::get('PS_UNIDENTIFIED_GROUP')) as $id_group) { + $group = new Group((int)$id_group); + $group->price_display_method = (int)$attributes['price_display_method']; + if (!$group->save()) { + $this->_errors[] = Tools::displayError('An error occurred during the default group update'); + } + } + } else { + $this->_errors[] = Tools::displayError('An error has occurred during the default group update'); + } + } - foreach (array((int)Configuration::get('PS_CUSTOMER_GROUP'), (int)Configuration::get('PS_GUEST_GROUP'), (int)Configuration::get('PS_UNIDENTIFIED_GROUP')) as $id_group) - { - $group = new Group((int)$id_group); - $group->price_display_method = (int)$attributes['price_display_method']; - if (!$group->save()) - $this->_errors[] = Tools::displayError('An error occurred during the default group update'); - } - } - else - $this->_errors[] = Tools::displayError('An error has occurred during the default group update'); - } + return true; + } - return true; - } - - public function getErrors() - { - return $this->_errors; - } + public function getErrors() + { + return $this->_errors; + } } diff --git a/classes/Mail.php b/classes/Mail.php index a01b7bd8..7dba72b2 100644 --- a/classes/Mail.php +++ b/classes/Mail.php @@ -31,504 +31,513 @@ include_once(_PS_SWIFT_DIR_.'Swift/Plugin/Decorator.php'); class MailCore extends ObjectModel { - public $id; - - /** @var string Recipient */ - public $recipient; - - /** @var string Template */ - public $template; - - /** @var string Subject */ - public $subject; - - /** @var int Language ID */ - public $id_lang; - - /** @var int Timestamp */ - public $date_add; - - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'mail', - 'primary' => 'id_mail', - 'fields' => array( - 'recipient' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'copy_post' => false, 'required' => true, 'size' => 126), - 'template' => array('type' => self::TYPE_STRING, 'validate' => 'isTplName', 'copy_post' => false, 'required' => true, 'size' => 62), - 'subject' => array('type' => self::TYPE_STRING, 'validate' => 'isMailSubject', 'copy_post' => false, 'required' => true, 'size' => 254), - 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'copy_post' => false, 'required' => true), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'copy_post' => false, 'required' => true), - ), - ); - - const TYPE_HTML = 1; - const TYPE_TEXT = 2; - const TYPE_BOTH = 3; - - /** - * Send Email - * - * @param int $id_lang Language of the email (to translate the template) - * @param string $template Template: the name of template not be a var but a string ! - * @param string $subject - * @param string $template_vars - * @param string $to - * @param string $to_name - * @param string $from - * @param string $from_name - * @param array $file_attachment Array with three parameters (content, mime and name). You can use an array of array to attach multiple files - * @param bool $modeSMTP - * @param string $template_path - * @param bool $die - * @param string $bcc Bcc recipient - */ - public static function Send($id_lang, $template, $subject, $template_vars, $to, - $to_name = null, $from = null, $from_name = null, $file_attachment = null, $mode_smtp = null, - $template_path = _PS_MAIL_DIR_, $die = false, $id_shop = null, $bcc = null, $reply_to = null) - { - if (!$id_shop) - $id_shop = Context::getContext()->shop->id; - - $configuration = Configuration::getMultiple(array( - 'PS_SHOP_EMAIL', - 'PS_MAIL_METHOD', - 'PS_MAIL_SERVER', - 'PS_MAIL_USER', - 'PS_MAIL_PASSWD', - 'PS_SHOP_NAME', - 'PS_MAIL_SMTP_ENCRYPTION', - 'PS_MAIL_SMTP_PORT', - 'PS_MAIL_TYPE' - ), null, null, $id_shop); - - // Returns immediatly if emails are deactivated - if ($configuration['PS_MAIL_METHOD'] == 3) - return true; - - $theme_path = _PS_THEME_DIR_; - - // Get the path of theme by id_shop if exist - if (is_numeric($id_shop) && $id_shop) - { - $shop = new Shop((int)$id_shop); - $theme_name = $shop->getTheme(); - - if (_THEME_NAME_ != $theme_name) - $theme_path = _PS_ROOT_DIR_.'/themes/'.$theme_name.'/'; - } - - if (!isset($configuration['PS_MAIL_SMTP_ENCRYPTION'])) - $configuration['PS_MAIL_SMTP_ENCRYPTION'] = 'off'; - if (!isset($configuration['PS_MAIL_SMTP_PORT'])) - $configuration['PS_MAIL_SMTP_PORT'] = 'default'; - - // Sending an e-mail can be of vital importance for the merchant, when his password is lost for example, so we must not die but do our best to send the e-mail - - if (!isset($from) || !Validate::isEmail($from)) - $from = $configuration['PS_SHOP_EMAIL']; - - if (!Validate::isEmail($from)) - $from = null; - - // $from_name is not that important, no need to die if it is not valid - if (!isset($from_name) || !Validate::isMailName($from_name)) - $from_name = $configuration['PS_SHOP_NAME']; - if (!Validate::isMailName($from_name)) - $from_name = null; - - // It would be difficult to send an e-mail if the e-mail is not valid, so this time we can die if there is a problem - if (!is_array($to) && !Validate::isEmail($to)) - { - Tools::dieOrLog(Tools::displayError('Error: parameter "to" is corrupted'), $die); - return false; - } - - // if bcc is not null, make sure it's a vaild e-mail - if (!is_null($bcc) && !is_array($bcc) && !Validate::isEmail($bcc)) - { - Tools::dieOrLog(Tools::displayError('Error: parameter "bcc" is corrupted'), $die); - $bcc = null; - } - - if (!is_array($template_vars)) - $template_vars = array(); - - // Do not crash for this error, that may be a complicated customer name - if (is_string($to_name) && !empty($to_name) && !Validate::isMailName($to_name)) - $to_name = null; - - if (!Validate::isTplName($template)) - { - Tools::dieOrLog(Tools::displayError('Error: invalid e-mail template'), $die); - return false; - } - - if (!Validate::isMailSubject($subject)) - { - Tools::dieOrLog(Tools::displayError('Error: invalid e-mail subject'), $die); - return false; - } - - /* Construct multiple recipients list if needed */ - $to_list = new Swift_RecipientList(); - if (is_array($to) && isset($to)) - { - foreach ($to as $key => $addr) - { - $addr = trim($addr); - if (!Validate::isEmail($addr)) - { - Tools::dieOrLog(Tools::displayError('Error: invalid e-mail address'), $die); - return false; - } - - if (is_array($to_name) && $to_name && is_array($to_name) && Validate::isGenericName($to_name[$key])) - $to_name = $to_name[$key]; - - $to_name = (($to_name == null || $to_name == $addr) ? '' : self::mimeEncode($to_name)); - $to_list->addTo($addr, $to_name); - } - $to_plugin = $to[0]; - } - else - { - /* Simple recipient, one address */ - $to_plugin = $to; - $to_name = (($to_name == null || $to_name == $to) ? '' : self::mimeEncode($to_name)); - $to_list->addTo($to, $to_name); - } - if (isset($bcc)) - $to_list->addBcc($bcc); - - try { - /* Connect with the appropriate configuration */ - if ($configuration['PS_MAIL_METHOD'] == 2) - { - if (empty($configuration['PS_MAIL_SERVER']) || empty($configuration['PS_MAIL_SMTP_PORT'])) - { - Tools::dieOrLog(Tools::displayError('Error: invalid SMTP server or SMTP port'), $die); - return false; - } - $connection = new Swift_Connection_SMTP( - $configuration['PS_MAIL_SERVER'], - $configuration['PS_MAIL_SMTP_PORT'], - $configuration['PS_MAIL_SMTP_ENCRYPTION'] == 'ssl' ? Swift_Connection_SMTP::ENC_SSL : (($configuration['PS_MAIL_SMTP_ENCRYPTION'] == 'tls' ? Swift_Connection_SMTP::ENC_TLS : Swift_Connection_SMTP::ENC_OFF)) - ); - $connection->setTimeout(4); - if (!$connection) - return false; - if (!empty($configuration['PS_MAIL_USER'])) - $connection->setUsername($configuration['PS_MAIL_USER']); - if (!empty($configuration['PS_MAIL_PASSWD'])) - $connection->setPassword($configuration['PS_MAIL_PASSWD']); - } - else - $connection = new Swift_Connection_NativeMail(); - - if (!$connection) - return false; - $swift = new Swift($connection, Configuration::get('PS_MAIL_DOMAIN', null, null, $id_shop)); - /* Get templates content */ - $iso = Language::getIsoById((int)$id_lang); - if (!$iso) - { - Tools::dieOrLog(Tools::displayError('Error - No ISO code for email'), $die); - return false; - } - $iso_template = $iso.'/'.$template; - - $module_name = false; - $override_mail = false; - - // get templatePath - if (preg_match('#'.$shop->physical_uri.'modules/#', str_replace(DIRECTORY_SEPARATOR, '/', $template_path)) && preg_match('#modules/([a-z0-9_-]+)/#ui', str_replace(DIRECTORY_SEPARATOR, '/',$template_path), $res)) - $module_name = $res[1]; - - if ($module_name !== false && (file_exists($theme_path.'modules/'.$module_name.'/mails/'.$iso_template.'.txt') || - file_exists($theme_path.'modules/'.$module_name.'/mails/'.$iso_template.'.html'))) - $template_path = $theme_path.'modules/'.$module_name.'/mails/'; - elseif (file_exists($theme_path.'mails/'.$iso_template.'.txt') || file_exists($theme_path.'mails/'.$iso_template.'.html')) - { - $template_path = $theme_path.'mails/'; - $override_mail = true; - } - if (!file_exists($template_path.$iso_template.'.txt') && ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_TEXT)) - { - Tools::dieOrLog(Tools::displayError('Error - The following e-mail template is missing:').' '.$template_path.$iso_template.'.txt', $die); - return false; - } - elseif (!file_exists($template_path.$iso_template.'.html') && ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_HTML)) - { - Tools::dieOrLog(Tools::displayError('Error - The following e-mail template is missing:').' '.$template_path.$iso_template.'.html', $die); - return false; - } - $template_html = ''; - $template_txt = ''; - Hook::exec('actionEmailAddBeforeContent', array( - 'template' => $template, - 'template_html' => &$template_html, - 'template_txt' => &$template_txt, - 'id_lang' => (int)$id_lang - ), null, true); - $template_html .= file_get_contents($template_path.$iso_template.'.html'); - $template_txt .= strip_tags(html_entity_decode(file_get_contents($template_path.$iso_template.'.txt'), null, 'utf-8')); - Hook::exec('actionEmailAddAfterContent', array( - 'template' => $template, - 'template_html' => &$template_html, - 'template_txt' => &$template_txt, - 'id_lang' => (int)$id_lang - ), null, true); - if ($override_mail && file_exists($template_path.$iso.'/lang.php')) - include_once($template_path.$iso.'/lang.php'); - elseif ($module_name && file_exists($theme_path.'mails/'.$iso.'/lang.php')) - include_once($theme_path.'mails/'.$iso.'/lang.php'); - elseif (file_exists(_PS_MAIL_DIR_.$iso.'/lang.php')) - include_once(_PS_MAIL_DIR_.$iso.'/lang.php'); - else - { - Tools::dieOrLog(Tools::displayError('Error - The language file is missing for:').' '.$iso, $die); - return false; - } - - /* Create mail and attach differents parts */ - $subject = '['.Configuration::get('PS_SHOP_NAME', null, null, $id_shop).'] '.$subject; - $message = new Swift_Message($subject); - - $message->setCharset('utf-8'); - - /* Set Message-ID - getmypid() is blocked on some hosting */ - $message->setId(Mail::generateId()); - - $message->headers->setEncoding('Q'); - - if (!($reply_to && Validate::isEmail($reply_to))) - $reply_to = $from; - - if (isset($reply_to) && $reply_to) - $message->setReplyTo($reply_to); - - $template_vars = array_map(array('Tools', 'htmlentitiesDecodeUTF8'), $template_vars); - $template_vars = array_map(array('Tools', 'stripslashes'), $template_vars); - - if (Configuration::get('PS_LOGO_MAIL') !== false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_MAIL', null, null, $id_shop))) - $logo = _PS_IMG_DIR_.Configuration::get('PS_LOGO_MAIL', null, null, $id_shop); - else - { - if (file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO', null, null, $id_shop))) - $logo = _PS_IMG_DIR_.Configuration::get('PS_LOGO', null, null, $id_shop); - else - $template_vars['{shop_logo}'] = ''; - } - ShopUrl::cacheMainDomainForShop((int)$id_shop); - /* don't attach the logo as */ - if (isset($logo)) - $template_vars['{shop_logo}'] = $message->attach(new Swift_Message_EmbeddedFile(new Swift_File($logo), null, ImageManager::getMimeTypeByExtension($logo))); - - if ((Context::getContext()->link instanceof Link) === false) - Context::getContext()->link = new Link(); - - $template_vars['{shop_name}'] = Tools::safeOutput(Configuration::get('PS_SHOP_NAME', null, null, $id_shop)); - $template_vars['{shop_url}'] = Context::getContext()->link->getPageLink('index', true, Context::getContext()->language->id, null, false, $id_shop); - $template_vars['{my_account_url}'] = Context::getContext()->link->getPageLink('my-account', true, Context::getContext()->language->id, null, false, $id_shop); - $template_vars['{guest_tracking_url}'] = Context::getContext()->link->getPageLink('guest-tracking', true, Context::getContext()->language->id, null, false, $id_shop); - $template_vars['{history_url}'] = Context::getContext()->link->getPageLink('history', true, Context::getContext()->language->id, null, false, $id_shop); - $template_vars['{color}'] = Tools::safeOutput(Configuration::get('PS_MAIL_COLOR', null, null, $id_shop)); - // Get extra template_vars - $extra_template_vars = array(); - Hook::exec('actionGetExtraMailTemplateVars', array( - 'template' => $template, - 'template_vars' => $template_vars, - 'extra_template_vars' => &$extra_template_vars, - 'id_lang' => (int)$id_lang - ), null, true); - $template_vars = array_merge($template_vars, $extra_template_vars); - $swift->attachPlugin(new Swift_Plugin_Decorator(array($to_plugin => $template_vars)), 'decorator'); - if ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_TEXT) - $message->attach(new Swift_Message_Part($template_txt, 'text/plain', '8bit', 'utf-8')); - if ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_HTML) - $message->attach(new Swift_Message_Part($template_html, 'text/html', '8bit', 'utf-8')); - if ($file_attachment && !empty($file_attachment)) - { - // Multiple attachments? - if (!is_array(current($file_attachment))) - $file_attachment = array($file_attachment); - - foreach ($file_attachment as $attachment) - if (isset($attachment['content']) && isset($attachment['name']) && isset($attachment['mime'])) - $message->attach(new Swift_Message_Attachment($attachment['content'], $attachment['name'], $attachment['mime'])); - } - /* Send mail */ - $send = $swift->send($message, $to_list, new Swift_Address($from, $from_name)); - $swift->disconnect(); - - ShopUrl::resetMainDomainCache(); - - if ($send && Configuration::get('PS_LOG_EMAILS')) - { - $mail = new Mail(); - $mail->template = substr($template, 0, 62); - $mail->subject = substr($subject, 0, 254); - $mail->id_lang = (int)$id_lang; - foreach (array_merge($to_list->getTo(), $to_list->getCc(), $to_list->getBcc()) as $recipient) - { - /** @var Swift_Address $recipient */ - $mail->id = null; - $mail->recipient = substr($recipient->getAddress(), 0, 126); - $mail->add(); - } - } - - return $send; - } - catch (Swift_Exception $e) - { - PrestaShopLogger::addLog( - 'Swift Error: '.$e->getMessage(), - 3, - null, - 'Swift_Message' - ); - - return false; - } - } - - public static function eraseLog($id_mail) - { - return Db::getInstance()->delete('mail', 'id_mail = '.(int)$id_mail); - } - - public static function eraseAllLogs() - { - return Db::getInstance()->execute('TRUNCATE TABLE '._DB_PREFIX_.'mail'); - } - - public static function sendMailTest($smtpChecked, $smtpServer, $content, $subject, $type, $to, $from, $smtpLogin, $smtpPassword, $smtpPort = 25, $smtpEncryption) - { - $result = false; - try { - if ($smtpChecked) - { - $smtp = new Swift_Connection_SMTP($smtpServer, $smtpPort, ($smtpEncryption == 'off') ? - Swift_Connection_SMTP::ENC_OFF : (($smtpEncryption == 'tls') ? Swift_Connection_SMTP::ENC_TLS : Swift_Connection_SMTP::ENC_SSL)); - $smtp->setUsername($smtpLogin); - $smtp->setpassword($smtpPassword); - $smtp->setTimeout(5); - $swift = new Swift($smtp, Configuration::get('PS_MAIL_DOMAIN')); - } - else - $swift = new Swift(new Swift_Connection_NativeMail(), Configuration::get('PS_MAIL_DOMAIN')); - - $message = new Swift_Message($subject, $content, $type); - - if ($swift->send($message, $to, $from)) - $result = true; - - $swift->disconnect(); - } catch (Swift_ConnectionException $e) { - $result = $e->getMessage(); - } catch (Swift_Message_MimeException $e) { - $result = $e->getMessage(); - } - - return $result; - } - - /** - * This method is used to get the translation for email Object. - * For an object is forbidden to use htmlentities, - * we have to return a sentence with accents. - * - * @param string $string raw sentence (write directly in file) - */ - public static function l($string, $id_lang = null, Context $context = null) - { - global $_LANGMAIL; - - if (!$context) - $context = Context::getContext(); - if ($id_lang == null) - $id_lang = (!isset($context->language) || !is_object($context->language)) ? (int)Configuration::get('PS_LANG_DEFAULT') : (int)$context->language->id; - $iso_code = Language::getIsoById((int)$id_lang); - - $file_core = _PS_ROOT_DIR_.'/mails/'.$iso_code.'/lang.php'; - if (Tools::file_exists_cache($file_core) && empty($_LANGMAIL)) - include($file_core); - - $file_theme = _PS_THEME_DIR_.'mails/'.$iso_code.'/lang.php'; - if (Tools::file_exists_cache($file_theme)) - include($file_theme); - - if (!is_array($_LANGMAIL)) - return (str_replace('"', '"', $string)); - - $key = str_replace('\'', '\\\'', $string); - return str_replace('"', '"', stripslashes((array_key_exists($key, $_LANGMAIL) && !empty($_LANGMAIL[$key])) ? $_LANGMAIL[$key] : $string)); - } - - /* Rewrite of Swift_Message::generateId() without getmypid() */ - protected static function generateId($idstring = null) - { - $midparams = array( - 'utctime' => gmstrftime('%Y%m%d%H%M%S'), - 'randint' => mt_rand(), - 'customstr' => (preg_match("/^(? (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : php_uname('n')), - ); - return vsprintf("<%s.%d.%s@%s>", $midparams); - } - - public static function isMultibyte($data) - { - $length = strlen($data); - for ($i = 0; $i < $length; $i++) - if (ord(($data[$i])) > 128) - return true; - return false; - } - - public static function mimeEncode($string, $charset = 'UTF-8', $newline = "\r\n") - { - if (!self::isMultibyte($string) && strlen($string) < 75) - return $string; - - $charset = strtoupper($charset); - $start = '=?'.$charset.'?B?'; - $end = '?='; - $sep = $end.$newline.' '.$start; - $length = 75 - strlen($start) - strlen($end); - $length = $length - ($length % 4); - - if ($charset === 'UTF-8') - { - $parts = array(); - $maxchars = floor(($length * 3) / 4); - $stringLength = strlen($string); - - while ($stringLength > $maxchars) - { - $i = (int)$maxchars; - $result = ord($string[$i]); - - while ($result >= 128 && $result <= 191) - $result = ord($string[--$i]); - - $parts[] = base64_encode(substr($string, 0, $i)); - $string = substr($string, $i); - $stringLength = strlen($string); - } - - $parts[] = base64_encode($string); - $string = implode($sep, $parts); - } - else - { - $string = chunk_split(base64_encode($string), $length, $sep); - $string = preg_replace('/'.preg_quote($sep).'$/', '', $string); - } - - return $start.$string.$end; - } + public $id; + + /** @var string Recipient */ + public $recipient; + + /** @var string Template */ + public $template; + + /** @var string Subject */ + public $subject; + + /** @var int Language ID */ + public $id_lang; + + /** @var int Timestamp */ + public $date_add; + + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'mail', + 'primary' => 'id_mail', + 'fields' => array( + 'recipient' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'copy_post' => false, 'required' => true, 'size' => 126), + 'template' => array('type' => self::TYPE_STRING, 'validate' => 'isTplName', 'copy_post' => false, 'required' => true, 'size' => 62), + 'subject' => array('type' => self::TYPE_STRING, 'validate' => 'isMailSubject', 'copy_post' => false, 'required' => true, 'size' => 254), + 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'copy_post' => false, 'required' => true), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'copy_post' => false, 'required' => true), + ), + ); + + const TYPE_HTML = 1; + const TYPE_TEXT = 2; + const TYPE_BOTH = 3; + + /** + * Send Email + * + * @param int $id_lang Language of the email (to translate the template) + * @param string $template Template: the name of template not be a var but a string ! + * @param string $subject + * @param string $template_vars + * @param string $to + * @param string $to_name + * @param string $from + * @param string $from_name + * @param array $file_attachment Array with three parameters (content, mime and name). You can use an array of array to attach multiple files + * @param bool $modeSMTP + * @param string $template_path + * @param bool $die + * @param string $bcc Bcc recipient + */ + public static function Send($id_lang, $template, $subject, $template_vars, $to, + $to_name = null, $from = null, $from_name = null, $file_attachment = null, $mode_smtp = null, + $template_path = _PS_MAIL_DIR_, $die = false, $id_shop = null, $bcc = null, $reply_to = null) + { + if (!$id_shop) { + $id_shop = Context::getContext()->shop->id; + } + + $configuration = Configuration::getMultiple(array( + 'PS_SHOP_EMAIL', + 'PS_MAIL_METHOD', + 'PS_MAIL_SERVER', + 'PS_MAIL_USER', + 'PS_MAIL_PASSWD', + 'PS_SHOP_NAME', + 'PS_MAIL_SMTP_ENCRYPTION', + 'PS_MAIL_SMTP_PORT', + 'PS_MAIL_TYPE' + ), null, null, $id_shop); + + // Returns immediatly if emails are deactivated + if ($configuration['PS_MAIL_METHOD'] == 3) { + return true; + } + + $theme_path = _PS_THEME_DIR_; + + // Get the path of theme by id_shop if exist + if (is_numeric($id_shop) && $id_shop) { + $shop = new Shop((int)$id_shop); + $theme_name = $shop->getTheme(); + + if (_THEME_NAME_ != $theme_name) { + $theme_path = _PS_ROOT_DIR_.'/themes/'.$theme_name.'/'; + } + } + + if (!isset($configuration['PS_MAIL_SMTP_ENCRYPTION'])) { + $configuration['PS_MAIL_SMTP_ENCRYPTION'] = 'off'; + } + if (!isset($configuration['PS_MAIL_SMTP_PORT'])) { + $configuration['PS_MAIL_SMTP_PORT'] = 'default'; + } + + // Sending an e-mail can be of vital importance for the merchant, when his password is lost for example, so we must not die but do our best to send the e-mail + + if (!isset($from) || !Validate::isEmail($from)) { + $from = $configuration['PS_SHOP_EMAIL']; + } + + if (!Validate::isEmail($from)) { + $from = null; + } + + // $from_name is not that important, no need to die if it is not valid + if (!isset($from_name) || !Validate::isMailName($from_name)) { + $from_name = $configuration['PS_SHOP_NAME']; + } + if (!Validate::isMailName($from_name)) { + $from_name = null; + } + + // It would be difficult to send an e-mail if the e-mail is not valid, so this time we can die if there is a problem + if (!is_array($to) && !Validate::isEmail($to)) { + Tools::dieOrLog(Tools::displayError('Error: parameter "to" is corrupted'), $die); + return false; + } + + // if bcc is not null, make sure it's a vaild e-mail + if (!is_null($bcc) && !is_array($bcc) && !Validate::isEmail($bcc)) { + Tools::dieOrLog(Tools::displayError('Error: parameter "bcc" is corrupted'), $die); + $bcc = null; + } + + if (!is_array($template_vars)) { + $template_vars = array(); + } + + // Do not crash for this error, that may be a complicated customer name + if (is_string($to_name) && !empty($to_name) && !Validate::isMailName($to_name)) { + $to_name = null; + } + + if (!Validate::isTplName($template)) { + Tools::dieOrLog(Tools::displayError('Error: invalid e-mail template'), $die); + return false; + } + + if (!Validate::isMailSubject($subject)) { + Tools::dieOrLog(Tools::displayError('Error: invalid e-mail subject'), $die); + return false; + } + + /* Construct multiple recipients list if needed */ + $to_list = new Swift_RecipientList(); + if (is_array($to) && isset($to)) { + foreach ($to as $key => $addr) { + $addr = trim($addr); + if (!Validate::isEmail($addr)) { + Tools::dieOrLog(Tools::displayError('Error: invalid e-mail address'), $die); + return false; + } + + if (is_array($to_name) && $to_name && is_array($to_name) && Validate::isGenericName($to_name[$key])) { + $to_name = $to_name[$key]; + } + + $to_name = (($to_name == null || $to_name == $addr) ? '' : self::mimeEncode($to_name)); + $to_list->addTo($addr, $to_name); + } + $to_plugin = $to[0]; + } else { + /* Simple recipient, one address */ + $to_plugin = $to; + $to_name = (($to_name == null || $to_name == $to) ? '' : self::mimeEncode($to_name)); + $to_list->addTo($to, $to_name); + } + if (isset($bcc)) { + $to_list->addBcc($bcc); + } + + try { + /* Connect with the appropriate configuration */ + if ($configuration['PS_MAIL_METHOD'] == 2) { + if (empty($configuration['PS_MAIL_SERVER']) || empty($configuration['PS_MAIL_SMTP_PORT'])) { + Tools::dieOrLog(Tools::displayError('Error: invalid SMTP server or SMTP port'), $die); + return false; + } + $connection = new Swift_Connection_SMTP( + $configuration['PS_MAIL_SERVER'], + $configuration['PS_MAIL_SMTP_PORT'], + $configuration['PS_MAIL_SMTP_ENCRYPTION'] == 'ssl' ? Swift_Connection_SMTP::ENC_SSL : (($configuration['PS_MAIL_SMTP_ENCRYPTION'] == 'tls' ? Swift_Connection_SMTP::ENC_TLS : Swift_Connection_SMTP::ENC_OFF)) + ); + $connection->setTimeout(4); + if (!$connection) { + return false; + } + if (!empty($configuration['PS_MAIL_USER'])) { + $connection->setUsername($configuration['PS_MAIL_USER']); + } + if (!empty($configuration['PS_MAIL_PASSWD'])) { + $connection->setPassword($configuration['PS_MAIL_PASSWD']); + } + } else { + $connection = new Swift_Connection_NativeMail(); + } + + if (!$connection) { + return false; + } + $swift = new Swift($connection, Configuration::get('PS_MAIL_DOMAIN', null, null, $id_shop)); + /* Get templates content */ + $iso = Language::getIsoById((int)$id_lang); + if (!$iso) { + Tools::dieOrLog(Tools::displayError('Error - No ISO code for email'), $die); + return false; + } + $iso_template = $iso.'/'.$template; + + $module_name = false; + $override_mail = false; + + // get templatePath + if (preg_match('#'.$shop->physical_uri.'modules/#', str_replace(DIRECTORY_SEPARATOR, '/', $template_path)) && preg_match('#modules/([a-z0-9_-]+)/#ui', str_replace(DIRECTORY_SEPARATOR, '/', $template_path), $res)) { + $module_name = $res[1]; + } + + if ($module_name !== false && (file_exists($theme_path.'modules/'.$module_name.'/mails/'.$iso_template.'.txt') || + file_exists($theme_path.'modules/'.$module_name.'/mails/'.$iso_template.'.html'))) { + $template_path = $theme_path.'modules/'.$module_name.'/mails/'; + } elseif (file_exists($theme_path.'mails/'.$iso_template.'.txt') || file_exists($theme_path.'mails/'.$iso_template.'.html')) { + $template_path = $theme_path.'mails/'; + $override_mail = true; + } + if (!file_exists($template_path.$iso_template.'.txt') && ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_TEXT)) { + Tools::dieOrLog(Tools::displayError('Error - The following e-mail template is missing:').' '.$template_path.$iso_template.'.txt', $die); + return false; + } elseif (!file_exists($template_path.$iso_template.'.html') && ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_HTML)) { + Tools::dieOrLog(Tools::displayError('Error - The following e-mail template is missing:').' '.$template_path.$iso_template.'.html', $die); + return false; + } + $template_html = ''; + $template_txt = ''; + Hook::exec('actionEmailAddBeforeContent', array( + 'template' => $template, + 'template_html' => &$template_html, + 'template_txt' => &$template_txt, + 'id_lang' => (int)$id_lang + ), null, true); + $template_html .= file_get_contents($template_path.$iso_template.'.html'); + $template_txt .= strip_tags(html_entity_decode(file_get_contents($template_path.$iso_template.'.txt'), null, 'utf-8')); + Hook::exec('actionEmailAddAfterContent', array( + 'template' => $template, + 'template_html' => &$template_html, + 'template_txt' => &$template_txt, + 'id_lang' => (int)$id_lang + ), null, true); + if ($override_mail && file_exists($template_path.$iso.'/lang.php')) { + include_once($template_path.$iso.'/lang.php'); + } elseif ($module_name && file_exists($theme_path.'mails/'.$iso.'/lang.php')) { + include_once($theme_path.'mails/'.$iso.'/lang.php'); + } elseif (file_exists(_PS_MAIL_DIR_.$iso.'/lang.php')) { + include_once(_PS_MAIL_DIR_.$iso.'/lang.php'); + } else { + Tools::dieOrLog(Tools::displayError('Error - The language file is missing for:').' '.$iso, $die); + return false; + } + + /* Create mail and attach differents parts */ + $subject = '['.Configuration::get('PS_SHOP_NAME', null, null, $id_shop).'] '.$subject; + $message = new Swift_Message($subject); + + $message->setCharset('utf-8'); + + /* Set Message-ID - getmypid() is blocked on some hosting */ + $message->setId(Mail::generateId()); + + $message->headers->setEncoding('Q'); + + if (!($reply_to && Validate::isEmail($reply_to))) { + $reply_to = $from; + } + + if (isset($reply_to) && $reply_to) { + $message->setReplyTo($reply_to); + } + + $template_vars = array_map(array('Tools', 'htmlentitiesDecodeUTF8'), $template_vars); + $template_vars = array_map(array('Tools', 'stripslashes'), $template_vars); + + if (Configuration::get('PS_LOGO_MAIL') !== false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_MAIL', null, null, $id_shop))) { + $logo = _PS_IMG_DIR_.Configuration::get('PS_LOGO_MAIL', null, null, $id_shop); + } else { + if (file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO', null, null, $id_shop))) { + $logo = _PS_IMG_DIR_.Configuration::get('PS_LOGO', null, null, $id_shop); + } else { + $template_vars['{shop_logo}'] = ''; + } + } + ShopUrl::cacheMainDomainForShop((int)$id_shop); + /* don't attach the logo as */ + if (isset($logo)) { + $template_vars['{shop_logo}'] = $message->attach(new Swift_Message_EmbeddedFile(new Swift_File($logo), null, ImageManager::getMimeTypeByExtension($logo))); + } + + if ((Context::getContext()->link instanceof Link) === false) { + Context::getContext()->link = new Link(); + } + + $template_vars['{shop_name}'] = Tools::safeOutput(Configuration::get('PS_SHOP_NAME', null, null, $id_shop)); + $template_vars['{shop_url}'] = Context::getContext()->link->getPageLink('index', true, Context::getContext()->language->id, null, false, $id_shop); + $template_vars['{my_account_url}'] = Context::getContext()->link->getPageLink('my-account', true, Context::getContext()->language->id, null, false, $id_shop); + $template_vars['{guest_tracking_url}'] = Context::getContext()->link->getPageLink('guest-tracking', true, Context::getContext()->language->id, null, false, $id_shop); + $template_vars['{history_url}'] = Context::getContext()->link->getPageLink('history', true, Context::getContext()->language->id, null, false, $id_shop); + $template_vars['{color}'] = Tools::safeOutput(Configuration::get('PS_MAIL_COLOR', null, null, $id_shop)); + // Get extra template_vars + $extra_template_vars = array(); + Hook::exec('actionGetExtraMailTemplateVars', array( + 'template' => $template, + 'template_vars' => $template_vars, + 'extra_template_vars' => &$extra_template_vars, + 'id_lang' => (int)$id_lang + ), null, true); + $template_vars = array_merge($template_vars, $extra_template_vars); + $swift->attachPlugin(new Swift_Plugin_Decorator(array($to_plugin => $template_vars)), 'decorator'); + if ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_TEXT) { + $message->attach(new Swift_Message_Part($template_txt, 'text/plain', '8bit', 'utf-8')); + } + if ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_HTML) { + $message->attach(new Swift_Message_Part($template_html, 'text/html', '8bit', 'utf-8')); + } + if ($file_attachment && !empty($file_attachment)) { + // Multiple attachments? + if (!is_array(current($file_attachment))) { + $file_attachment = array($file_attachment); + } + + foreach ($file_attachment as $attachment) { + if (isset($attachment['content']) && isset($attachment['name']) && isset($attachment['mime'])) { + $message->attach(new Swift_Message_Attachment($attachment['content'], $attachment['name'], $attachment['mime'])); + } + } + } + /* Send mail */ + $send = $swift->send($message, $to_list, new Swift_Address($from, $from_name)); + $swift->disconnect(); + + ShopUrl::resetMainDomainCache(); + + if ($send && Configuration::get('PS_LOG_EMAILS')) { + $mail = new Mail(); + $mail->template = substr($template, 0, 62); + $mail->subject = substr($subject, 0, 254); + $mail->id_lang = (int)$id_lang; + foreach (array_merge($to_list->getTo(), $to_list->getCc(), $to_list->getBcc()) as $recipient) { + /** @var Swift_Address $recipient */ + $mail->id = null; + $mail->recipient = substr($recipient->getAddress(), 0, 126); + $mail->add(); + } + } + + return $send; + } catch (Swift_Exception $e) { + PrestaShopLogger::addLog( + 'Swift Error: '.$e->getMessage(), + 3, + null, + 'Swift_Message' + ); + + return false; + } + } + + public static function eraseLog($id_mail) + { + return Db::getInstance()->delete('mail', 'id_mail = '.(int)$id_mail); + } + + public static function eraseAllLogs() + { + return Db::getInstance()->execute('TRUNCATE TABLE '._DB_PREFIX_.'mail'); + } + + public static function sendMailTest($smtpChecked, $smtpServer, $content, $subject, $type, $to, $from, $smtpLogin, $smtpPassword, $smtpPort = 25, $smtpEncryption) + { + $result = false; + try { + if ($smtpChecked) { + $smtp = new Swift_Connection_SMTP($smtpServer, $smtpPort, ($smtpEncryption == 'off') ? + Swift_Connection_SMTP::ENC_OFF : (($smtpEncryption == 'tls') ? Swift_Connection_SMTP::ENC_TLS : Swift_Connection_SMTP::ENC_SSL)); + $smtp->setUsername($smtpLogin); + $smtp->setpassword($smtpPassword); + $smtp->setTimeout(5); + $swift = new Swift($smtp, Configuration::get('PS_MAIL_DOMAIN')); + } else { + $swift = new Swift(new Swift_Connection_NativeMail(), Configuration::get('PS_MAIL_DOMAIN')); + } + + $message = new Swift_Message($subject, $content, $type); + + if ($swift->send($message, $to, $from)) { + $result = true; + } + + $swift->disconnect(); + } catch (Swift_ConnectionException $e) { + $result = $e->getMessage(); + } catch (Swift_Message_MimeException $e) { + $result = $e->getMessage(); + } + + return $result; + } + + /** + * This method is used to get the translation for email Object. + * For an object is forbidden to use htmlentities, + * we have to return a sentence with accents. + * + * @param string $string raw sentence (write directly in file) + */ + public static function l($string, $id_lang = null, Context $context = null) + { + global $_LANGMAIL; + + if (!$context) { + $context = Context::getContext(); + } + if ($id_lang == null) { + $id_lang = (!isset($context->language) || !is_object($context->language)) ? (int)Configuration::get('PS_LANG_DEFAULT') : (int)$context->language->id; + } + $iso_code = Language::getIsoById((int)$id_lang); + + $file_core = _PS_ROOT_DIR_.'/mails/'.$iso_code.'/lang.php'; + if (Tools::file_exists_cache($file_core) && empty($_LANGMAIL)) { + include($file_core); + } + + $file_theme = _PS_THEME_DIR_.'mails/'.$iso_code.'/lang.php'; + if (Tools::file_exists_cache($file_theme)) { + include($file_theme); + } + + if (!is_array($_LANGMAIL)) { + return (str_replace('"', '"', $string)); + } + + $key = str_replace('\'', '\\\'', $string); + return str_replace('"', '"', stripslashes((array_key_exists($key, $_LANGMAIL) && !empty($_LANGMAIL[$key])) ? $_LANGMAIL[$key] : $string)); + } + + /* Rewrite of Swift_Message::generateId() without getmypid() */ + protected static function generateId($idstring = null) + { + $midparams = array( + 'utctime' => gmstrftime('%Y%m%d%H%M%S'), + 'randint' => mt_rand(), + 'customstr' => (preg_match("/^(? (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : php_uname('n')), + ); + return vsprintf("<%s.%d.%s@%s>", $midparams); + } + + public static function isMultibyte($data) + { + $length = strlen($data); + for ($i = 0; $i < $length; $i++) { + if (ord(($data[$i])) > 128) { + return true; + } + } + return false; + } + + public static function mimeEncode($string, $charset = 'UTF-8', $newline = "\r\n") + { + if (!self::isMultibyte($string) && strlen($string) < 75) { + return $string; + } + + $charset = strtoupper($charset); + $start = '=?'.$charset.'?B?'; + $end = '?='; + $sep = $end.$newline.' '.$start; + $length = 75 - strlen($start) - strlen($end); + $length = $length - ($length % 4); + + if ($charset === 'UTF-8') { + $parts = array(); + $maxchars = floor(($length * 3) / 4); + $stringLength = strlen($string); + + while ($stringLength > $maxchars) { + $i = (int)$maxchars; + $result = ord($string[$i]); + + while ($result >= 128 && $result <= 191) { + $result = ord($string[--$i]); + } + + $parts[] = base64_encode(substr($string, 0, $i)); + $string = substr($string, $i); + $stringLength = strlen($string); + } + + $parts[] = base64_encode($string); + $string = implode($sep, $parts); + } else { + $string = chunk_split(base64_encode($string), $length, $sep); + $string = preg_replace('/'.preg_quote($sep).'$/', '', $string); + } + + return $start.$string.$end; + } } diff --git a/classes/Manufacturer.php b/classes/Manufacturer.php index ff703c90..0ccfb3be 100644 --- a/classes/Manufacturer.php +++ b/classes/Manufacturer.php @@ -26,169 +26,171 @@ class ManufacturerCore extends ObjectModel { - public $id; + public $id; - /** @var int manufacturer ID //FIXME is it really usefull...? */ - public $id_manufacturer; + /** @var int manufacturer ID //FIXME is it really usefull...? */ + public $id_manufacturer; - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var string A description */ - public $description; + /** @var string A description */ + public $description; - /** @var string A short description */ - public $short_description; + /** @var string A short description */ + public $short_description; - /** @var int Address */ - public $id_address; + /** @var int Address */ + public $id_address; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** @var string Object last modification date */ - public $date_upd; + /** @var string Object last modification date */ + public $date_upd; - /** @var string Friendly URL */ - public $link_rewrite; + /** @var string Friendly URL */ + public $link_rewrite; - /** @var string Meta title */ - public $meta_title; + /** @var string Meta title */ + public $meta_title; - /** @var string Meta keywords */ - public $meta_keywords; + /** @var string Meta keywords */ + public $meta_keywords; - /** @var string Meta description */ - public $meta_description; + /** @var string Meta description */ + public $meta_description; - /** @var bool active */ - public $active; + /** @var bool active */ + public $active; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'manufacturer', - 'primary' => 'id_manufacturer', - 'multilang' => true, - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isCatalogName', 'required' => true, 'size' => 64), - 'active' => array('type' => self::TYPE_BOOL), - 'date_add' => array('type' => self::TYPE_DATE), - 'date_upd' => array('type' => self::TYPE_DATE), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'manufacturer', + 'primary' => 'id_manufacturer', + 'multilang' => true, + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isCatalogName', 'required' => true, 'size' => 64), + 'active' => array('type' => self::TYPE_BOOL), + 'date_add' => array('type' => self::TYPE_DATE), + 'date_upd' => array('type' => self::TYPE_DATE), - /* Lang fields */ - 'description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), - 'short_description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), - 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), - 'meta_description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - 'meta_keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName'), - ), - ); + /* Lang fields */ + 'description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), + 'short_description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), + 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), + 'meta_description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + 'meta_keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName'), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'active' => array(), - 'link_rewrite' => array('getter' => 'getLink', 'setter' => false), - ), - 'associations' => array( - 'addresses' => array('resource' => 'address', 'setter' => false, 'fields' => array( - 'id' => array('xlink_resource' => 'addresses'), - )), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'active' => array(), + 'link_rewrite' => array('getter' => 'getLink', 'setter' => false), + ), + 'associations' => array( + 'addresses' => array('resource' => 'address', 'setter' => false, 'fields' => array( + 'id' => array('xlink_resource' => 'addresses'), + )), + ), + ); - public function __construct($id = null, $id_lang = null) - { - parent::__construct($id, $id_lang); + public function __construct($id = null, $id_lang = null) + { + parent::__construct($id, $id_lang); - $this->link_rewrite = $this->getLink(); - $this->image_dir = _PS_MANU_IMG_DIR_; - } + $this->link_rewrite = $this->getLink(); + $this->image_dir = _PS_MANU_IMG_DIR_; + } - public function delete() - { - $address = new Address($this->id_address); + public function delete() + { + $address = new Address($this->id_address); - if (Validate::isLoadedObject($address) && !$address->delete()) - return false; + if (Validate::isLoadedObject($address) && !$address->delete()) { + return false; + } - if (parent::delete()) - { - CartRule::cleanProductRuleIntegrity('manufacturers', $this->id); - return $this->deleteImage(); - } - } + if (parent::delete()) { + CartRule::cleanProductRuleIntegrity('manufacturers', $this->id); + return $this->deleteImage(); + } + } - /** - * Delete several objects from database - * - * return boolean Deletion result - */ - public function deleteSelection($selection) - { - if (!is_array($selection)) - die(Tools::displayError()); + /** + * Delete several objects from database + * + * return boolean Deletion result + */ + public function deleteSelection($selection) + { + if (!is_array($selection)) { + die(Tools::displayError()); + } - $result = true; - foreach ($selection as $id) - { - $this->id = (int)$id; - $this->id_address = Manufacturer::getManufacturerAddress(); - $result = $result && $this->delete(); - } + $result = true; + foreach ($selection as $id) { + $this->id = (int)$id; + $this->id_address = Manufacturer::getManufacturerAddress(); + $result = $result && $this->delete(); + } - return $result; - } + return $result; + } - protected function getManufacturerAddress() - { - if (!(int)$this->id) - return false; + protected function getManufacturerAddress() + { + if (!(int)$this->id) { + return false; + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT `id_address` FROM '._DB_PREFIX_.'address WHERE `id_manufacturer` = '.(int)$this->id); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT `id_address` FROM '._DB_PREFIX_.'address WHERE `id_manufacturer` = '.(int)$this->id); + } - /** - * Return manufacturers - * - * @param bool $get_nb_products [optional] return products numbers for each - * @param int $id_lang - * @param bool $active - * @param int $p - * @param int $n - * @param bool $all_group - * @return array Manufacturers - */ - public static function getManufacturers($get_nb_products = false, $id_lang = 0, $active = true, $p = false, $n = false, $all_group = false, $group_by = false) - { - if (!$id_lang) - $id_lang = (int)Configuration::get('PS_LANG_DEFAULT'); - if (!Group::isFeatureActive()) - $all_group = true; + /** + * Return manufacturers + * + * @param bool $get_nb_products [optional] return products numbers for each + * @param int $id_lang + * @param bool $active + * @param int $p + * @param int $n + * @param bool $all_group + * @return array Manufacturers + */ + public static function getManufacturers($get_nb_products = false, $id_lang = 0, $active = true, $p = false, $n = false, $all_group = false, $group_by = false) + { + if (!$id_lang) { + $id_lang = (int)Configuration::get('PS_LANG_DEFAULT'); + } + if (!Group::isFeatureActive()) { + $all_group = true; + } - $manufacturers = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $manufacturers = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT m.*, ml.`description`, ml.`short_description` FROM `'._DB_PREFIX_.'manufacturer` m '.Shop::addSqlAssociation('manufacturer', 'm').' INNER JOIN `'._DB_PREFIX_.'manufacturer_lang` ml ON (m.`id_manufacturer` = ml.`id_manufacturer` AND ml.`id_lang` = '.(int)$id_lang.') '.($active ? 'WHERE m.`active` = 1' : '') - .($group_by ? ' GROUP BY m.`id_manufacturer`' : '' ).' + .($group_by ? ' GROUP BY m.`id_manufacturer`' : '').' ORDER BY m.`name` ASC '.($p ? ' LIMIT '.(((int)$p - 1) * (int)$n).','.(int)$n : '')); - if ($manufacturers === false) - return false; + if ($manufacturers === false) { + return false; + } - if ($get_nb_products) - { - $sql_groups = ''; - if (!$all_group) - { - $groups = FrontController::getCurrentCustomerGroups(); - $sql_groups = (count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); - } + if ($get_nb_products) { + $sql_groups = ''; + if (!$all_group) { + $groups = FrontController::getCurrentCustomerGroups(); + $sql_groups = (count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); + } - $results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT p.`id_manufacturer`, COUNT(DISTINCT p.`id_product`) as nb_products FROM `'._DB_PREFIX_.'product` p USE INDEX (product_manufacturer) '.Shop::addSqlAssociation('product', 'p').' @@ -202,133 +204,144 @@ class ManufacturerCore extends ObjectModel WHERE p.`id_product` = cp.`id_product` AND cg.`id_group` '.$sql_groups.' )').' GROUP BY p.`id_manufacturer`' - ); + ); - $counts = array(); - foreach ($results as $result) - $counts[(int)$result['id_manufacturer']] = (int)$result['nb_products']; + $counts = array(); + foreach ($results as $result) { + $counts[(int)$result['id_manufacturer']] = (int)$result['nb_products']; + } - if (count($counts)) - foreach ($manufacturers as $key => $manufacturer) - if (array_key_exists((int)$manufacturer['id_manufacturer'], $counts)) - $manufacturers[$key]['nb_products'] = $counts[(int)$manufacturer['id_manufacturer']]; - else - $manufacturers[$key]['nb_products'] = 0; - } + if (count($counts)) { + foreach ($manufacturers as $key => $manufacturer) { + if (array_key_exists((int)$manufacturer['id_manufacturer'], $counts)) { + $manufacturers[$key]['nb_products'] = $counts[(int)$manufacturer['id_manufacturer']]; + } else { + $manufacturers[$key]['nb_products'] = 0; + } + } + } + } - $total_manufacturers = count($manufacturers); - $rewrite_settings = (int)Configuration::get('PS_REWRITING_SETTINGS'); - for ($i = 0; $i < $total_manufacturers; $i++) - $manufacturers[$i]['link_rewrite'] = ($rewrite_settings ? Tools::link_rewrite($manufacturers[$i]['name']) : 0); - return $manufacturers; - } + $total_manufacturers = count($manufacturers); + $rewrite_settings = (int)Configuration::get('PS_REWRITING_SETTINGS'); + for ($i = 0; $i < $total_manufacturers; $i++) { + $manufacturers[$i]['link_rewrite'] = ($rewrite_settings ? Tools::link_rewrite($manufacturers[$i]['name']) : 0); + } + return $manufacturers; + } - /** - * Return name from id - * - * @param int $id_manufacturer Manufacturer ID - * @return string name - */ - static protected $cacheName = array(); - public static function getNameById($id_manufacturer) - { - if (!isset(self::$cacheName[$id_manufacturer])) - self::$cacheName[$id_manufacturer] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Return name from id + * + * @param int $id_manufacturer Manufacturer ID + * @return string name + */ + protected static $cacheName = array(); + public static function getNameById($id_manufacturer) + { + if (!isset(self::$cacheName[$id_manufacturer])) { + self::$cacheName[$id_manufacturer] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `name` FROM `'._DB_PREFIX_.'manufacturer` WHERE `id_manufacturer` = '.(int)$id_manufacturer.' AND `active` = 1' - ); + ); + } - return self::$cacheName[$id_manufacturer]; - } + return self::$cacheName[$id_manufacturer]; + } - public static function getIdByName($name) - { - $result = Db::getInstance()->getRow(' + public static function getIdByName($name) + { + $result = Db::getInstance()->getRow(' SELECT `id_manufacturer` FROM `'._DB_PREFIX_.'manufacturer` WHERE `name` = \''.pSQL($name).'\'' - ); + ); - if (isset($result['id_manufacturer'])) - return (int)$result['id_manufacturer']; + if (isset($result['id_manufacturer'])) { + return (int)$result['id_manufacturer']; + } - return false; - } + return false; + } - public function getLink() - { - return Tools::link_rewrite($this->name); - } + public function getLink() + { + return Tools::link_rewrite($this->name); + } - public static function getProducts($id_manufacturer, $id_lang, $p, $n, $order_by = null, $order_way = null, - $get_total = false, $active = true, $active_category = true, Context $context = null) - { - if (!$context) - $context = Context::getContext(); + public static function getProducts($id_manufacturer, $id_lang, $p, $n, $order_by = null, $order_way = null, + $get_total = false, $active = true, $active_category = true, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } - $front = true; - if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) - $front = false; + $front = true; + if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) { + $front = false; + } - if ($p < 1) - $p = 1; + if ($p < 1) { + $p = 1; + } - if (empty($order_by) || $order_by == 'position') - $order_by = 'name'; + if (empty($order_by) || $order_by == 'position') { + $order_by = 'name'; + } - if (empty($order_way)) $order_way = 'ASC'; + if (empty($order_way)) { + $order_way = 'ASC'; + } - if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) - die (Tools::displayError()); + if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) { + die(Tools::displayError()); + } - $groups = FrontController::getCurrentCustomerGroups(); - $sql_groups = count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'; + $groups = FrontController::getCurrentCustomerGroups(); + $sql_groups = count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'; - /* Return only the number of products */ - if ($get_total) - { - $sql = ' + /* Return only the number of products */ + if ($get_total) { + $sql = ' SELECT p.`id_product` FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' WHERE p.id_manufacturer = '.(int)$id_manufacturer - .($active ? ' AND product_shop.`active` = 1' : '').' + .($active ? ' AND product_shop.`active` = 1' : '').' '.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').' AND EXISTS ( SELECT 1 FROM `'._DB_PREFIX_.'category_group` cg LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON (cp.`id_category` = cg.`id_category`)'. - ($active_category ? ' INNER JOIN `'._DB_PREFIX_.'category` ca ON cp.`id_category` = ca.`id_category` AND ca.`active` = 1' : '').' + ($active_category ? ' INNER JOIN `'._DB_PREFIX_.'category` ca ON cp.`id_category` = ca.`id_category` AND ca.`active` = 1' : '').' WHERE p.`id_product` = cp.`id_product` AND cg.`id_group` '.$sql_groups.' )'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - return (int)count($result); - } - if (strpos($order_by, '.') > 0) - { - $order_by = explode('.', $order_by); - $order_by = pSQL($order_by[0]).'.`'.pSQL($order_by[1]).'`'; - } - $alias = ''; - if ($order_by == 'price') - $alias = 'product_shop.'; - elseif ($order_by == 'name') - $alias = 'pl.'; - elseif ($order_by == 'manufacturer_name') - { - $order_by = 'name'; - $alias = 'm.'; - } - elseif ($order_by == 'quantity') - $alias = 'stock.'; - else - $alias = 'p.'; + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + return (int)count($result); + } + if (strpos($order_by, '.') > 0) { + $order_by = explode('.', $order_by); + $order_by = pSQL($order_by[0]).'.`'.pSQL($order_by[1]).'`'; + } + $alias = ''; + if ($order_by == 'price') { + $alias = 'product_shop.'; + } elseif ($order_by == 'name') { + $alias = 'pl.'; + } elseif ($order_by == 'manufacturer_name') { + $order_by = 'name'; + $alias = 'm.'; + } elseif ($order_by == 'quantity') { + $alias = 'stock.'; + } else { + $alias = 'p.'; + } - $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity' - .(Combination::isFeatureActive() ? ', product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, IFNULL(product_attribute_shop.`id_product_attribute`,0) id_product_attribute' : '').' + $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity' + .(Combination::isFeatureActive() ? ', product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, IFNULL(product_attribute_shop.`id_product_attribute`,0) id_product_attribute' : '').' , pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, pl.`available_now`, pl.`available_later`, image_shop.`id_image` id_image, il.`legend`, m.`name` AS manufacturer_name, DATEDIFF( @@ -338,9 +351,9 @@ class ManufacturerCore extends ObjectModel INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY ) ) > 0 AS new' - .' FROM `'._DB_PREFIX_.'product` p + .' FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p'). - (Combination::isFeatureActive() ? 'LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop + (Combination::isFeatureActive() ? 'LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop ON (p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='.(int)$context->shop->id.')':'').' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').') @@ -352,16 +365,17 @@ class ManufacturerCore extends ObjectModel ON (m.`id_manufacturer` = p.`id_manufacturer`) '.Product::sqlStock('p', 0); - if (Group::isFeatureActive() || $active_category) - { - $sql .= 'JOIN `'._DB_PREFIX_.'category_product` cp ON (p.id_product = cp.id_product)'; - if (Group::isFeatureActive()) - $sql .= 'JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.`id_category` = cg.`id_category` AND cg.`id_group` '.$sql_groups.')'; - if ($active_category) - $sql .= 'JOIN `'._DB_PREFIX_.'category` ca ON cp.`id_category` = ca.`id_category` AND ca.`active` = 1'; - } + if (Group::isFeatureActive() || $active_category) { + $sql .= 'JOIN `'._DB_PREFIX_.'category_product` cp ON (p.id_product = cp.id_product)'; + if (Group::isFeatureActive()) { + $sql .= 'JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.`id_category` = cg.`id_category` AND cg.`id_group` '.$sql_groups.')'; + } + if ($active_category) { + $sql .= 'JOIN `'._DB_PREFIX_.'category` ca ON cp.`id_category` = ca.`id_category` AND ca.`active` = 1'; + } + } - $sql .= ' + $sql .= ' WHERE p.`id_manufacturer` = '.(int)$id_manufacturer.' '.($active ? ' AND product_shop.`active` = 1' : '').' '.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').' @@ -369,25 +383,28 @@ class ManufacturerCore extends ObjectModel ORDER BY '.$alias.'`'.bqSQL($order_by).'` '.pSQL($order_way).' LIMIT '.(((int)$p - 1) * (int)$n).','.(int)$n; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - if (!$result) - return false; + if (!$result) { + return false; + } - if ($order_by == 'price') - Tools::orderbyPrice($result, $order_way); + if ($order_by == 'price') { + Tools::orderbyPrice($result, $order_way); + } - return Product::getProductsProperties($id_lang, $result); - } + return Product::getProductsProperties($id_lang, $result); + } - public function getProductsLite($id_lang) - { - $context = Context::getContext(); - $front = true; - if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) - $front = false; + public function getProductsLite($id_lang) + { + $context = Context::getContext(); + $front = true; + if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) { + $front = false; + } - return Db::getInstance()->executeS(' + return Db::getInstance()->executeS(' SELECT p.`id_product`, pl.`name` FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' @@ -396,29 +413,29 @@ class ManufacturerCore extends ObjectModel AND pl.`id_lang` = '.(int)$id_lang.$context->shop->addSqlRestrictionOnLang('pl').' ) WHERE p.`id_manufacturer` = '.(int)$this->id. - ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '')); - } + ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '')); + } - /* - * Specify if a manufacturer already in base - * - * @param $id_manufacturer Manufacturer id - * @return bool - */ - public static function manufacturerExists($id_manufacturer) - { - $row = Db::getInstance()->getRow(' + /* + * Specify if a manufacturer already in base + * + * @param $id_manufacturer Manufacturer id + * @return bool + */ + public static function manufacturerExists($id_manufacturer) + { + $row = Db::getInstance()->getRow(' SELECT `id_manufacturer` FROM '._DB_PREFIX_.'manufacturer m WHERE m.`id_manufacturer` = '.(int)$id_manufacturer - ); + ); - return isset($row['id_manufacturer']); - } + return isset($row['id_manufacturer']); + } - public function getAddresses($id_lang) - { - return Db::getInstance()->executeS(' + public function getAddresses($id_lang) + { + return Db::getInstance()->executeS(' SELECT a.*, cl.name AS `country`, s.name AS `state` FROM `'._DB_PREFIX_.'address` AS a LEFT JOIN `'._DB_PREFIX_.'country_lang` AS cl ON ( @@ -428,43 +445,45 @@ class ManufacturerCore extends ObjectModel LEFT JOIN `'._DB_PREFIX_.'state` AS s ON (s.`id_state` = a.`id_state`) WHERE `id_manufacturer` = '.(int)$this->id.' AND a.`deleted` = 0' - ); - } + ); + } - public function getWsAddresses() - { - return Db::getInstance()->executeS(' + public function getWsAddresses() + { + return Db::getInstance()->executeS(' SELECT a.id_address as id FROM `'._DB_PREFIX_.'address` AS a '.Shop::addSqlAssociation('manufacturer', 'a').' WHERE a.`id_manufacturer` = '.(int)$this->id.' AND a.`deleted` = 0' - ); - } + ); + } - public function setWsAddresses($id_addresses) - { - $ids = array(); + public function setWsAddresses($id_addresses) + { + $ids = array(); - foreach ($id_addresses as $id) - $ids[] = (int)$id['id']; + foreach ($id_addresses as $id) { + $ids[] = (int)$id['id']; + } - $result1 = (Db::getInstance()->execute(' + $result1 = (Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'address` SET id_manufacturer = 0 WHERE id_manufacturer = '.(int)$this->id.' AND deleted = 0') !== false - ); + ); - $result2 = true; - if (count($ids)) - $result2 = (Db::getInstance()->execute(' + $result2 = true; + if (count($ids)) { + $result2 = (Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'address` SET id_customer = 0, id_supplier = 0, id_manufacturer = '.(int)$this->id.' WHERE id_address IN('.implode(',', $ids).') AND deleted = 0') !== false - ); + ); + } - return ($result1 && $result2); - } + return ($result1 && $result2); + } } diff --git a/classes/Media.php b/classes/Media.php index 0932e409..8775b381 100644 --- a/classes/Media.php +++ b/classes/Media.php @@ -26,821 +26,861 @@ class MediaCore { - public static $jquery_ui_dependencies = array( - 'ui.core' => array('fileName' => 'jquery.ui.core.min.js', 'dependencies' => array(), 'theme' => true), - 'ui.widget' => array('fileName' => 'jquery.ui.widget.min.js', 'dependencies' => array(), 'theme' => false), - 'ui.mouse' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => false), - 'ui.position' => array('fileName' => 'jquery.ui.position.min.js', 'dependencies' => array(), 'theme' => false), - 'ui.draggable' => array('fileName' => 'jquery.ui.draggable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => false), - 'ui.droppable' => array('fileName' => 'jquery.ui.droppable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse', 'ui.draggable'), 'theme' => false), - 'ui.resizable' => array('fileName' => 'jquery.ui.resizable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), - 'ui.selectable' => array('fileName' => 'jquery.ui.selectable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), - 'ui.sortable' => array('fileName' => 'jquery.ui.sortable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), - 'ui.autocomplete' => array('fileName' => 'jquery.ui.autocomplete.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.position', 'ui.menu'), 'theme' => true), - 'ui.button' => array('fileName' => 'jquery.ui.button.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), - 'ui.dialog' => array('fileName' => 'jquery.ui.dialog.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.position','ui.button'), 'theme' => true), - 'ui.menu' => array('fileName' => 'jquery.ui.menu.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.position'), 'theme' => true), - 'ui.slider' => array('fileName' => 'jquery.ui.slider.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), - 'ui.spinner' => array('fileName' => 'jquery.ui.spinner.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.button'), 'theme' => true), - 'ui.tabs' => array('fileName' => 'jquery.ui.tabs.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), - 'ui.datepicker' => array('fileName' => 'jquery.ui.datepicker.min.js', 'dependencies' => array('ui.core'), 'theme' => true), - 'ui.progressbar' => array('fileName' => 'jquery.ui.progressbar.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), - 'ui.tooltip' => array('fileName' => 'jquery.ui.tooltip.min.js', 'dependencies' => array('ui.core', 'ui.widget','ui.position','effects.core'), 'theme' => true), - 'ui.accordion' => array('fileName' => 'jquery.ui.accordion.min.js', 'dependencies' => array('ui.core', 'ui.widget','effects.core'), 'theme' => true), - 'effects.core' => array('fileName' => 'jquery.effects.core.min.js', 'dependencies' => array(), 'theme' => false), - 'effects.blind' => array('fileName' => 'jquery.effects.blind.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.bounce' => array('fileName' => 'jquery.effects.bounce.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.clip' => array('fileName' => 'jquery.effects.clip.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.drop' => array('fileName' => 'jquery.effects.drop.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.explode' => array('fileName' => 'jquery.effects.explode.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.fade' => array('fileName' => 'jquery.effects.fade.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.fold' => array('fileName' => 'jquery.effects.fold.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.highlight' => array('fileName' => 'jquery.effects.highlight.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.pulsate' => array('fileName' => 'jquery.effects.pulsate.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.scale' => array('fileName' => 'jquery.effects.scale.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.shake' => array('fileName' => 'jquery.effects.shake.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.slide' => array('fileName' => 'jquery.effects.slide.min.js', 'dependencies' => array('effects.core'), 'theme' => false), - 'effects.transfer' => array('fileName' => 'jquery.effects.transfer.min.js', 'dependencies' => array('effects.core'), 'theme' => false) - ); - - /** - * @var array list of javascript definitions - */ - protected static $js_def = array(); - - /** - * @var array list of javascript inline scripts - */ - protected static $inline_script = array(); - - /** - * @var array list of javascript external scripts - */ - protected static $inline_script_src = array(); - - /** - * @var string pattern used in packJSinHTML - */ - public static $pattern_js = '#\s*(<\s*script(?:\s[^>]*(?:javascript)[^>]*|)+>)(.*)(<\s*/script\s*[^>]*>)\s*#Uims'; - - public static function minifyHTML($html_content) - { - if (strlen($html_content) > 0) - { - //set an alphabetical order for args - // $html_content = preg_replace_callback( - // '/(<[a-zA-Z0-9]+)((\s*[a-zA-Z0-9]+=[\"\\\'][^\"\\\']*[\"\\\']\s*)*)>/', - // array('Media', 'minifyHTMLpregCallback'), - // $html_content, - // Media::getBackTrackLimit()); - - require_once(_PS_TOOL_DIR_.'minify_html/minify_html.class.php'); - $html_content = str_replace(chr(194).chr(160), ' ', $html_content); - if (trim($minified_content = Minify_HTML::minify($html_content, array('cssMinifier', 'jsMinifier'))) != '') - $html_content = $minified_content; - - return $html_content; - } - return false; - } - - public static function minifyHTMLpregCallback($preg_matches) - { - $args = array(); - preg_match_all('/[a-zA-Z0-9]+=[\"\\\'][^\"\\\']*[\"\\\']/is', $preg_matches[2], $args); - $args = $args[0]; - sort($args); - // if there is no args in the balise, we don't write a space (avoid previous : , now : <title>) - if (empty($args)) - $output = $preg_matches[1].'>'; - else - $output = $preg_matches[1].' '.implode(' ', $args).'>'; - return $output; - } - - public static function packJSinHTML($html_content) - { - if (strlen($html_content) > 0) - { - $html_content_copy = $html_content; - $html_content = preg_replace_callback( - Media::$pattern_js, - array('Media', 'packJSinHTMLpregCallback'), - $html_content, - Media::getBackTrackLimit()); - - // If the string is too big preg_replace return an error - // In this case, we don't compress the content - if (function_exists('preg_last_error') && preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR) - { - if (_PS_MODE_DEV_) - Tools::error_log('ERROR: PREG_BACKTRACK_LIMIT_ERROR in function packJSinHTML'); - return $html_content_copy; - } - return $html_content; - } - return false; - } - - public static function packJSinHTMLpregCallback($preg_matches) - { - if (!(trim($preg_matches[2]))) - return $preg_matches[0]; - $preg_matches[1] = $preg_matches[1].'/* <![CDATA[ */'; - $preg_matches[2] = Media::packJS($preg_matches[2]); - $preg_matches[count($preg_matches) - 1] = '/* ]]> */'.$preg_matches[count($preg_matches) - 1]; - unset($preg_matches[0]); - $output = implode('', $preg_matches); - return $output; - } - - public static function packJS($js_content) - { - if (!empty($js_content)) - { - require_once(_PS_TOOL_DIR_.'js_minify/jsmin.php'); - try - { - $js_content = JSMin::minify($js_content); - } - catch (Exception $e) - { - if (_PS_MODE_DEV_) - echo $e->getMessage(); - return ';'.trim($js_content, ';').';'; - } - } - return ';'.trim($js_content, ';').';'; - } - - public static function minifyCSS($css_content, $fileuri = false, &$import_url = array()) - { - global $current_css_file; - - $current_css_file = $fileuri; - if (strlen($css_content) > 0) - { - $limit = Media::getBackTrackLimit(); - $css_content = preg_replace('#/\*.*?\*/#s', '', $css_content, $limit); - $css_content = preg_replace_callback('#(url\((?![\'"]?(?:data:|//|https?:))(?:\'|")?)([^\)\'"]*)(?=[\'"]?\))#s', array('Tools', 'replaceByAbsoluteURL'), $css_content, $limit); - $css_content = preg_replace('#\s+#', ' ', $css_content, $limit); - $css_content = str_replace(array("\t", "\n", "\r"), '', $css_content); - $css_content = str_replace(array('; ', ': '), array(';', ':'), $css_content); - $css_content = str_replace(array(' {', '{ '), '{', $css_content); - $css_content = str_replace(', ', ',', $css_content); - $css_content = str_replace(array('} ', ' }', ';}'), '}', $css_content); - $css_content = str_replace(array(':0px', ':0em', ':0pt', ':0%'), ':0', $css_content); - $css_content = str_replace(array(' 0px', ' 0em', ' 0pt', ' 0%'), ' 0', $css_content); - $css_content = str_replace('\'images_ie/', '\'images/', $css_content); - $css_content = preg_replace_callback('#(AlphaImageLoader\(src=\')([^\']*\',)#s', array('Tools', 'replaceByAbsoluteURL'), $css_content); - // Store all import url - preg_match_all('#@(import|charset) .*?;#i', $css_content, $m); - for ($i = 0, $total = count($m[0]); $i < $total; $i++) - { - if (isset($m[1][$i]) && $m[1][$i] == 'import') - $import_url[] = $m[0][$i]; - $css_content = str_replace($m[0][$i], '', $css_content); - } - - return trim($css_content); - } - return false; - } - - /** - * addJS return javascript path - * - * @param mixed $js_uri - * - * @return string - */ - public static function getJSPath($js_uri) - { - return Media::getMediaPath($js_uri); - } - - /** - * addCSS return stylesheet path. - * - * @param mixed $css_uri - * @param string $css_media_type - * @param bool $need_rtl - * - * @return string - */ - public static function getCSSPath($css_uri, $css_media_type = 'all', $need_rtl = true) - { - // RTL Ready: search and load rtl css file if it's not originally rtl - if ($need_rtl && Context::getContext()->language->is_rtl) - { - $css_uri_rtl = preg_replace('/(^[^.].*)(\.css)$/', '$1_rtl.css', $css_uri); - $rtl_media = Media::getMediaPath($css_uri_rtl, $css_media_type); - if ($rtl_media != false) - return $rtl_media; - } - // End RTL - return Media::getMediaPath($css_uri, $css_media_type); - } - - public static function getMediaPath($media_uri, $css_media_type = null) - { - if (is_array($media_uri) || $media_uri === null || empty($media_uri)) - return false; - - $url_data = parse_url($media_uri); - if (!is_array($url_data)) - return false; - - $file_uri = ''; - if (!array_key_exists('host', $url_data)) - { - $media_uri_host_mode = '/'.ltrim(str_replace(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, _PS_CORE_DIR_), __PS_BASE_URI__, $media_uri), '/\\'); - $media_uri = '/'.ltrim(str_replace(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, _PS_ROOT_DIR_), __PS_BASE_URI__, $media_uri), '/\\'); - $url_data['path'] = $media_uri; - // remove PS_BASE_URI on _PS_ROOT_DIR_ for the following - $file_uri = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); - $file_uri_host_mode = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, Tools::str_replace_once(_PS_CORE_DIR_, '', $url_data['path'])); - } - - // check if css files exists - if (!array_key_exists('host', $url_data)) - { - if (!@filemtime($file_uri) || @filesize($file_uri) === 0) - { - if (!defined('_PS_HOST_MODE_')) - return false; - elseif (!@filemtime($file_uri_host_mode) || @filesize($file_uri_host_mode) === 0) - return false; - else - $media_uri = $media_uri_host_mode; - } - } - - if (!array_key_exists('host', $url_data)) - $media_uri = str_replace('//', '/', $media_uri); - - if ($css_media_type) - return array($media_uri => $css_media_type); - - return $media_uri; - } - - /** - * return jquery path. - * - * @param mixed $version - * - * @return string - */ - public static function getJqueryPath($version = null, $folder = null, $minifier = true) - { - $add_no_conflict = false; - if ($version === null) - $version = _PS_JQUERY_VERSION_; //set default version - elseif (preg_match('/^([0-9\.]+)$/Ui', $version)) - $add_no_conflict = true; - else - return false; - - if ($folder === null) - $folder = _PS_JS_DIR_.'jquery/'; //set default folder - //check if file exist - $file = $folder.'jquery-'.$version.($minifier ? '.min.js' : '.js'); - - // remove PS_BASE_URI on _PS_ROOT_DIR_ for the following - $url_data = parse_url($file); - $file_uri = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); - $file_uri_host_mode = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); - // check if js files exists, if not try to load query from ajax.googleapis.com - - $return = array(); - - if (@filemtime($file_uri) || (defined('_PS_HOST_MODE_') && @filemtime($file_uri_host_mode))) - $return[] = Media::getJSPath($file); - else - $return[] = Media::getJSPath(Tools::getCurrentUrlProtocolPrefix().'ajax.googleapis.com/ajax/libs/jquery/' - .$version.'/jquery'.($minifier ? '.min.js' : '.js')); - - if ($add_no_conflict) - $return[] = Media::getJSPath(Context::getContext()->shop->getBaseURL(true, false)._PS_JS_DIR_ - .'jquery/jquery.noConflict.php?version='.$version); - - //added query migrate for compatibility with new version of jquery will be removed in ps 1.6 - $return[] = Media::getJSPath(_PS_JS_DIR_.'jquery/jquery-migrate-1.2.1.min.js'); - - return $return; - } - - /** - * return jqueryUI component path. - * - * @param mixed $component - * - * @return string - */ - public static function getJqueryUIPath($component, $theme, $check_dependencies) - { - $ui_path = array('js' => array(), 'css' => array()); - $folder = _PS_JS_DIR_.'jquery/ui/'; - $file = 'jquery.'.$component.'.min.js'; - $url_data = parse_url($folder.$file); - $file_uri = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); - $file_uri_host_mode = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); - $ui_tmp = array(); - if (isset(Media::$jquery_ui_dependencies[$component]) && Media::$jquery_ui_dependencies[$component]['theme'] && $check_dependencies) - { - $theme_css = Media::getCSSPath($folder.'themes/'.$theme.'/jquery.ui.theme.css'); - $comp_css = Media::getCSSPath($folder.'themes/'.$theme.'/jquery.'.$component.'.css'); - if (!empty($theme_css) || $theme_css) - $ui_path['css'] = array_merge($ui_path['css'], $theme_css); - if (!empty($comp_css) || $comp_css) - $ui_path['css'] = array_merge($ui_path['css'], $comp_css); - } - if ($check_dependencies && array_key_exists($component, self::$jquery_ui_dependencies)) - { - foreach (self::$jquery_ui_dependencies[$component]['dependencies'] as $dependency) - { - $ui_tmp[] = Media::getJqueryUIPath($dependency, $theme, false); - if (self::$jquery_ui_dependencies[$dependency]['theme']) - $dep_css = Media::getCSSPath($folder.'themes/'.$theme.'/jquery.'.$dependency.'.css'); - - - if (isset($dep_css) && (!empty($dep_css) || $dep_css)) - $ui_path['css'] = array_merge($ui_path['css'], $dep_css); - } - } - if (@filemtime($file_uri) || (defined('_PS_HOST_MODE_') && @filemtime($file_uri_host_mode))) - { - if (!empty($ui_tmp)) - { - foreach ($ui_tmp as $ui) - { - if (!empty($ui['js'])) - $ui_path['js'][] = $ui['js']; - - if (!empty($ui['css'])) - $ui_path['css'][] = $ui['css']; - } - $ui_path['js'][] = Media::getJSPath($folder.$file); - } - else - $ui_path['js'] = Media::getJSPath($folder.$file); - } - - //add i18n file for datepicker - if ($component == 'ui.datepicker') - { - if (!is_array($ui_path['js'])) - $ui_path['js'] = array($ui_path['js']); - - $ui_path['js'][] = Media::getJSPath($folder.'i18n/jquery.ui.datepicker-'.Context::getContext()->language->iso_code.'.js'); - } - - return $ui_path; - } - - /** - * return jquery plugin path. - * - * @param mixed $name - * - * @return string|boolean - */ - public static function getJqueryPluginPath($name, $folder = null) - { - $plugin_path = array('js' => array(), 'css' => array()); - if ($folder === null) - $folder = _PS_JS_DIR_.'jquery/plugins/'; //set default folder - - $file = 'jquery.'.$name.'.js'; - $url_data = parse_url($folder); - $file_uri = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); - $file_uri_host_mode = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); - - if (@file_exists($file_uri.$file) || (defined('_PS_HOST_MODE_') && @file_exists($file_uri_host_mode.$file))) - $plugin_path['js'] = Media::getJSPath($folder.$file); - elseif (@file_exists($file_uri.$name.'/'.$file) || (defined('_PS_HOST_MODE_') && @file_exists($file_uri_host_mode.$name.'/'.$file))) - $plugin_path['js'] = Media::getJSPath($folder.$name.'/'.$file); - else - return false; - $plugin_path['css'] = Media::getJqueryPluginCSSPath($name, $folder); - - return $plugin_path; - } - - /** - * return jquery plugin css path if exist. - * - * @param mixed $name - * - * @return string|boolean - */ - public static function getJqueryPluginCSSPath($name, $folder = null) - { - if ($folder === null) - $folder = _PS_JS_DIR_.'jquery/plugins/'; //set default folder - $file = 'jquery.'.$name.'.css'; - $url_data = parse_url($folder); - $file_uri = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); - $file_uri_host_mode = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); - - if (@file_exists($file_uri.$file) || (defined('_PS_HOST_MODE_') && @file_exists($file_uri_host_mode.$file))) - return Media::getCSSPath($folder.$file); - elseif (@file_exists($file_uri.$name.'/'.$file) || (defined('_PS_HOST_MODE_') && @file_exists($file_uri_host_mode.$name.'/'.$file))) - return Media::getCSSPath($folder.$name.'/'.$file); - else - return false; - } - - /** - * Combine Compress and Cache CSS (ccc) calls - * - * @param array $css_files - * - * @return array processed css_files - */ - public static function cccCss($css_files) - { - //inits - $css_files_by_media = array(); - $external_css_files = array(); - $compressed_css_files = array(); - $compressed_css_files_not_found = array(); - $compressed_css_files_infos = array(); - $protocol_link = Tools::getCurrentUrlProtocolPrefix(); - $cache_path = _PS_THEME_DIR_.'cache/'; - - // group css files by media - foreach ($css_files as $filename => $media) - { - if (!array_key_exists($media, $css_files_by_media)) - $css_files_by_media[$media] = array(); - - $infos = array(); - $infos['uri'] = $filename; - $url_data = parse_url($filename); - - if (array_key_exists('host', $url_data)) - { - $external_css_files[$filename] = $media; - continue; - } - - $infos['path'] = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, '/', $url_data['path']); - - if (!@filemtime($infos['path'])) - $infos['path'] = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, '/', $url_data['path']); - - $css_files_by_media[$media]['files'][] = $infos; - if (!array_key_exists('date', $css_files_by_media[$media])) - $css_files_by_media[$media]['date'] = 0; - $css_files_by_media[$media]['date'] = max( - (int)@filemtime($infos['path']), - $css_files_by_media[$media]['date'] - ); - - if (!array_key_exists($media, $compressed_css_files_infos)) - $compressed_css_files_infos[$media] = array('key' => ''); - $compressed_css_files_infos[$media]['key'] .= $filename; - } - - // get compressed css file infos - $version = (int)Configuration::get('PS_CCCCSS_VERSION'); - foreach ($compressed_css_files_infos as $media => &$info) - { - $key = md5($info['key'].$protocol_link); - $filename = $cache_path.'v_'.$version.'_'.$key.'_'.$media.'.css'; - - $info = array( - 'key' => $key, - 'date' => (int)@filemtime($filename) - ); - } - - foreach ($css_files_by_media as $media => $media_infos) - { - if ($media_infos['date'] > $compressed_css_files_infos[$media]['date']) - { - if ($compressed_css_files_infos[$media]['date']) - { - Configuration::updateValue('PS_CCCCSS_VERSION', ++$version); - break; - } - } - } - - // aggregate and compress css files content, write new caches files - $import_url = array(); - foreach ($css_files_by_media as $media => $media_infos) - { - $cache_filename = $cache_path.'v_'.$version.'_'.$compressed_css_files_infos[$media]['key'].'_'.$media.'.css'; - if ($media_infos['date'] > $compressed_css_files_infos[$media]['date']) - { - $cache_filename = $cache_path.'v_'.$version.'_'.$compressed_css_files_infos[$media]['key'].'_'.$media.'.css'; - $compressed_css_files[$media] = ''; - foreach ($media_infos['files'] as $file_infos) - { - if (file_exists($file_infos['path'])) - $compressed_css_files[$media] .= Media::minifyCSS(file_get_contents($file_infos['path']), $file_infos['uri'], $import_url); - else - $compressed_css_files_not_found[] = $file_infos['path']; - } - if (!empty($compressed_css_files_not_found)) - $content = '/* WARNING ! file(s) not found : "'. - implode(',', $compressed_css_files_not_found). - '" */'."\n".$compressed_css_files[$media]; - else - $content = $compressed_css_files[$media]; - - $content = '@charset "UTF-8";'."\n".$content; - $content = implode('', $import_url).$content; - file_put_contents($cache_filename, $content); - chmod($cache_filename, 0777); - } - $compressed_css_files[$media] = $cache_filename; - } - - // rebuild the original css_files array - $css_files = array(); - foreach ($compressed_css_files as $media => $filename) - { - $url = str_replace(_PS_THEME_DIR_, _THEMES_DIR_._THEME_NAME_.'/', $filename); - $css_files[$protocol_link.Tools::getMediaServer($url).$url] = $media; - } - return array_merge($external_css_files, $css_files); - } - - public static function getBackTrackLimit() - { - static $limit = null; - if ($limit === null) - { - $limit = @ini_get('pcre.backtrack_limit'); - if (!$limit) - $limit = -1; - } - - return $limit; - } - - /** - * Combine Compress and Cache (ccc) JS calls - * - * @param array $js_files - * - * @return array processed js_files - */ - public static function cccJS($js_files) - { - //inits - $compressed_js_files_not_found = array(); - $js_files_infos = array(); - $js_files_date = 0; - $compressed_js_filename = ''; - $js_external_files = array(); - $protocol_link = Tools::getCurrentUrlProtocolPrefix(); - $cache_path = _PS_THEME_DIR_.'cache/'; - - // get js files infos - foreach ($js_files as $filename) - { - if (Validate::isAbsoluteUrl($filename)) - $js_external_files[] = $filename; - else - { - $infos = array(); - $infos['uri'] = $filename; - $url_data = parse_url($filename); - $infos['path'] = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, '/', $url_data['path']); - - if (!@filemtime($infos['path'])) - $infos['path'] = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, '/', $url_data['path']); - - $js_files_infos[] = $infos; - - $js_files_date = max( - (int)@filemtime($infos['path']), - $js_files_date - ); - $compressed_js_filename .= $filename; - } - } - - // get compressed js file infos - $compressed_js_filename = md5($compressed_js_filename); - $version = (int)Configuration::get('PS_CCCJS_VERSION'); - $compressed_js_path = $cache_path.'v_'.$version.'_'.$compressed_js_filename.'.js'; - $compressed_js_file_date = (int)@filemtime($compressed_js_path); - - // aggregate and compress js files content, write new caches files - if ($js_files_date > $compressed_js_file_date) - { - if ($compressed_js_file_date) - Configuration::updateValue('PS_CCCJS_VERSION', ++$version); - - $compressed_js_path = $cache_path.'v_'.$version.'_'.$compressed_js_filename.'.js'; - $content = ''; - foreach ($js_files_infos as $file_infos) - { - if (file_exists($file_infos['path'])) - { - $tmp_content = file_get_contents($file_infos['path']); - if (preg_match('@\.(min|pack)\.[^/]+$@', $file_infos['path'], $matches)) - $content .= preg_replace('/\/\/@\ssourceMappingURL\=[_a-zA-Z0-9-.]+\.'.$matches[1].'\.map\s+/', '', $tmp_content); - else - $content .= Media::packJS($tmp_content); - } - else - $compressed_js_files_not_found[] = $file_infos['path']; - } - - if (!empty($compressed_js_files_not_found)) - $content = '/* WARNING ! file(s) not found : "'. - implode(',', $compressed_js_files_not_found). - '" */'."\n".$content; - - file_put_contents($compressed_js_path, $content); - chmod($compressed_js_path, 0777); - } - - // rebuild the original js_files array - if (strpos($compressed_js_path, _PS_ROOT_DIR_) !== false) - $url = str_replace(_PS_ROOT_DIR_.'/', __PS_BASE_URI__, $compressed_js_path); - - if (strpos($compressed_js_path, _PS_CORE_DIR_) !== false) - $url = str_replace(_PS_CORE_DIR_.'/', __PS_BASE_URI__, $compressed_js_path); - - return array_merge(array($protocol_link.Tools::getMediaServer($url).$url), $js_external_files); - } - - /** - * Clear theme cache - * - * @return void - */ - public static function clearCache() - { - foreach (array(_PS_THEME_DIR_.'cache') as $dir) - if (file_exists($dir)) - foreach (scandir($dir) as $file) - if ($file[0] != '.' && $file != 'index.php') - Tools::deleteFile($dir.DIRECTORY_SEPARATOR.$file, array('index.php')); - - $version = (int)Configuration::get('PS_CCCJS_VERSION'); - Configuration::updateValue('PS_CCCJS_VERSION', ++$version); - $version = (int)Configuration::get('PS_CCCCSS_VERSION'); - Configuration::updateValue('PS_CCCCSS_VERSION', ++$version); - } - - /** - * Get JS definitions - * - * @return array JS definitions - */ - public static function getJsDef() - { - ksort(Media::$js_def); - return Media::$js_def; - } - - /** - * Get JS inline script - * - * @return array inline script - */ - public static function getInlineScript() - { - return Media::$inline_script; - } - - /** - * Add a new javascript definition at bottom of page - * - * @param mixed $js_def - * - * @return void - */ - public static function addJsDef($js_def) - { - if (is_array($js_def)) - foreach ($js_def as $key => $js) - Media::$js_def[$key] = $js; - elseif ($js_def) - Media::$js_def[] = $js_def; - } - - /** - * Add a new javascript definition from a capture at bottom of page - * - * @param mixed $params - * @param string $content - * @param Smarty $smarty - * @param bool $repeat - * - * @return void - */ - public static function addJsDefL($params, $content, $smarty = null, &$repeat = false) - { - if (!$repeat && isset($params) && Tools::strlen($content)) - { - if (!is_array($params)) - $params = (array)$params; - - foreach ($params as $param) - Media::$js_def[$param] = $content; - } - } - - public static function deferInlineScripts($output) - { - /* Try to enqueue in js_files inline scripts with src but without conditionnal comments */ - $dom = new DOMDocument(); - libxml_use_internal_errors(true); - @$dom->loadHTML(($output)); - libxml_use_internal_errors(false); - $scripts = $dom->getElementsByTagName('script'); - if (is_object($scripts) && $scripts->length) - foreach ($scripts as $script) - { - /** @var DOMElement $script */ - if ($src = $script->getAttribute('src')) - { - if (substr($src, 0, 2) == '//') - $src = Tools::getCurrentUrlProtocolPrefix().substr($src, 2); - - $patterns = array( - '#code\.jquery\.com/jquery-([0-9\.]+)(\.min)*\.js$#Ui', - '#ajax\.googleapis\.com/ajax/libs/jquery/([0-9\.]+)/jquery(\.min)*\.js$#Ui', - '#ajax\.aspnetcdn\.com/ajax/jquery/jquery-([0-9\.]+)(\.min)*\.js$#Ui', - '#cdnjs\.cloudflare\.com/ajax/libs/jquery/([0-9\.]+)/jquery(\.min)*\.js$#Ui', - '#/jquery-([0-9\.]+)(\.min)*\.js$#Ui' - ); - - foreach ($patterns as $pattern) - { - $matches = array(); - if (preg_match($pattern, $src, $matches)) - { - $minifier = $version = false; - if (isset($matches[2]) && $matches[2]) - $minifier = (bool)$matches[2]; - if (isset($matches[1]) && $matches[1]) - $version = $matches[1]; - if ($version) - { - if ($version != _PS_JQUERY_VERSION_) - Context::getContext()->controller->addJquery($version, null, $minifier); - array_push(Media::$inline_script_src, $src); - } - } - - } - if (!in_array($src, Media::$inline_script_src)) - Context::getContext()->controller->addJS($src); - } - } - $output = preg_replace_callback(Media::$pattern_js, array('Media', 'deferScript'), $output); - return $output; - } - - /** - * Get all JS scripts and place it to bottom - * To be used in callback with deferInlineScripts - * - * @param array $matches - * - * @return bool|string Empty string or original script lines - */ - public static function deferScript($matches) - { - if (!is_array($matches)) - return false; - $inline = ''; - - if (isset($matches[0])) - $original = trim($matches[0]); - - if (isset($matches[2])) - $inline = trim($matches[2]); - - /* This is an inline script, add its content to inline scripts stack then remove it from content */ - if (!empty($inline) && preg_match(Media::$pattern_js, $original) !== false && Media::$inline_script[] = $inline) - return ''; - - /* This is an external script, if it already belongs to js_files then remove it from content */ - preg_match('/src\s*=\s*["\']?([^"\']*)[^>]/ims', $original, $results); - if (array_key_exists(1, $results)) - { - if (substr($results[1], 0, 2) == '//') - { - $protocol_link = Tools::getCurrentUrlProtocolPrefix(); - $results[1] = $protocol_link.ltrim($results[1], '/'); - } - if (in_array($results[1], Context::getContext()->controller->js_files) || in_array($results[1], Media::$inline_script_src)) - return ''; - } - - /* return original string because no match was found */ - return $original; - } + public static $jquery_ui_dependencies = array( + 'ui.core' => array('fileName' => 'jquery.ui.core.min.js', 'dependencies' => array(), 'theme' => true), + 'ui.widget' => array('fileName' => 'jquery.ui.widget.min.js', 'dependencies' => array(), 'theme' => false), + 'ui.mouse' => array('fileName' => 'jquery.ui.mouse.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => false), + 'ui.position' => array('fileName' => 'jquery.ui.position.min.js', 'dependencies' => array(), 'theme' => false), + 'ui.draggable' => array('fileName' => 'jquery.ui.draggable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => false), + 'ui.droppable' => array('fileName' => 'jquery.ui.droppable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse', 'ui.draggable'), 'theme' => false), + 'ui.resizable' => array('fileName' => 'jquery.ui.resizable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), + 'ui.selectable' => array('fileName' => 'jquery.ui.selectable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), + 'ui.sortable' => array('fileName' => 'jquery.ui.sortable.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), + 'ui.autocomplete' => array('fileName' => 'jquery.ui.autocomplete.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.position', 'ui.menu'), 'theme' => true), + 'ui.button' => array('fileName' => 'jquery.ui.button.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), + 'ui.dialog' => array('fileName' => 'jquery.ui.dialog.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.position','ui.button'), 'theme' => true), + 'ui.menu' => array('fileName' => 'jquery.ui.menu.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.position'), 'theme' => true), + 'ui.slider' => array('fileName' => 'jquery.ui.slider.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.mouse'), 'theme' => true), + 'ui.spinner' => array('fileName' => 'jquery.ui.spinner.min.js', 'dependencies' => array('ui.core', 'ui.widget', 'ui.button'), 'theme' => true), + 'ui.tabs' => array('fileName' => 'jquery.ui.tabs.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), + 'ui.datepicker' => array('fileName' => 'jquery.ui.datepicker.min.js', 'dependencies' => array('ui.core'), 'theme' => true), + 'ui.progressbar' => array('fileName' => 'jquery.ui.progressbar.min.js', 'dependencies' => array('ui.core', 'ui.widget'), 'theme' => true), + 'ui.tooltip' => array('fileName' => 'jquery.ui.tooltip.min.js', 'dependencies' => array('ui.core', 'ui.widget','ui.position','effects.core'), 'theme' => true), + 'ui.accordion' => array('fileName' => 'jquery.ui.accordion.min.js', 'dependencies' => array('ui.core', 'ui.widget','effects.core'), 'theme' => true), + 'effects.core' => array('fileName' => 'jquery.effects.core.min.js', 'dependencies' => array(), 'theme' => false), + 'effects.blind' => array('fileName' => 'jquery.effects.blind.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.bounce' => array('fileName' => 'jquery.effects.bounce.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.clip' => array('fileName' => 'jquery.effects.clip.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.drop' => array('fileName' => 'jquery.effects.drop.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.explode' => array('fileName' => 'jquery.effects.explode.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.fade' => array('fileName' => 'jquery.effects.fade.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.fold' => array('fileName' => 'jquery.effects.fold.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.highlight' => array('fileName' => 'jquery.effects.highlight.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.pulsate' => array('fileName' => 'jquery.effects.pulsate.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.scale' => array('fileName' => 'jquery.effects.scale.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.shake' => array('fileName' => 'jquery.effects.shake.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.slide' => array('fileName' => 'jquery.effects.slide.min.js', 'dependencies' => array('effects.core'), 'theme' => false), + 'effects.transfer' => array('fileName' => 'jquery.effects.transfer.min.js', 'dependencies' => array('effects.core'), 'theme' => false) + ); + + /** + * @var array list of javascript definitions + */ + protected static $js_def = array(); + + /** + * @var array list of javascript inline scripts + */ + protected static $inline_script = array(); + + /** + * @var array list of javascript external scripts + */ + protected static $inline_script_src = array(); + + /** + * @var string pattern used in replaceByAbsoluteURL + */ + public static $pattern_callback = '#(url\((?![\'"]?(?:data:|//|https?:))(?:\'|")?)([^\)\'"]*)(?=[\'"]?\))#s'; + + /** + * @var string used for preg_replace_callback parameter (avoid global) + */ + protected static $current_css_file; + + /** + * @var string pattern used in packJSinHTML + */ + public static $pattern_js = '#\s*(<\s*script(?:\s[^>]*(?:javascript)[^>]*|)+>)(.*)(<\s*/script\s*[^>]*>)\s*#Uims'; + + public static function minifyHTML($html_content) + { + if (strlen($html_content) > 0) { + //set an alphabetical order for args + // $html_content = preg_replace_callback( + // '/(<[a-zA-Z0-9]+)((\s*[a-zA-Z0-9]+=[\"\\\'][^\"\\\']*[\"\\\']\s*)*)>/', + // array('Media', 'minifyHTMLpregCallback'), + // $html_content, + // Media::getBackTrackLimit()); + + require_once(_PS_TOOL_DIR_.'minify_html/minify_html.class.php'); + $html_content = str_replace(chr(194).chr(160), ' ', $html_content); + if (trim($minified_content = Minify_HTML::minify($html_content, array('cssMinifier', 'jsMinifier'))) != '') { + $html_content = $minified_content; + } + + return $html_content; + } + return false; + } + + public static function minifyHTMLpregCallback($preg_matches) + { + $args = array(); + preg_match_all('/[a-zA-Z0-9]+=[\"\\\'][^\"\\\']*[\"\\\']/is', $preg_matches[2], $args); + $args = $args[0]; + sort($args); + // if there is no args in the balise, we don't write a space (avoid previous : <title >, now : <title>) + if (empty($args)) { + $output = $preg_matches[1].'>'; + } else { + $output = $preg_matches[1].' '.implode(' ', $args).'>'; + } + return $output; + } + + public static function packJSinHTML($html_content) + { + if (strlen($html_content) > 0) { + $html_content_copy = $html_content; + $html_content = preg_replace_callback( + Media::$pattern_js, + array('Media', 'packJSinHTMLpregCallback'), + $html_content, + Media::getBackTrackLimit()); + + // If the string is too big preg_replace return an error + // In this case, we don't compress the content + if (function_exists('preg_last_error') && preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR) { + if (_PS_MODE_DEV_) { + Tools::error_log('ERROR: PREG_BACKTRACK_LIMIT_ERROR in function packJSinHTML'); + } + return $html_content_copy; + } + return $html_content; + } + return false; + } + + public static function packJSinHTMLpregCallback($preg_matches) + { + if (!(trim($preg_matches[2]))) { + return $preg_matches[0]; + } + $preg_matches[1] = $preg_matches[1].'/* <![CDATA[ */'; + $preg_matches[2] = Media::packJS($preg_matches[2]); + $preg_matches[count($preg_matches) - 1] = '/* ]]> */'.$preg_matches[count($preg_matches) - 1]; + unset($preg_matches[0]); + $output = implode('', $preg_matches); + return $output; + } + + public static function packJS($js_content) + { + if (!empty($js_content)) { + require_once(_PS_TOOL_DIR_.'js_minify/jsmin.php'); + try { + $js_content = JSMin::minify($js_content); + } catch (Exception $e) { + if (_PS_MODE_DEV_) { + echo $e->getMessage(); + } + return ';'.trim($js_content, ';').';'; + } + } + return ';'.trim($js_content, ';').';'; + } + + public static function minifyCSS($css_content, $fileuri = false, &$import_url = array()) + { + Media::$current_css_file = $fileuri; + + if (strlen($css_content) > 0) { + $limit = Media::getBackTrackLimit(); + $css_content = preg_replace('#/\*.*?\*/#s', '', $css_content, $limit); + $css_content = preg_replace_callback(Media::$pattern_callback, array('Media', 'replaceByAbsoluteURL'), $css_content, $limit); + $css_content = preg_replace('#\s+#', ' ', $css_content, $limit); + $css_content = str_replace(array("\t", "\n", "\r"), '', $css_content); + $css_content = str_replace(array('; ', ': '), array(';', ':'), $css_content); + $css_content = str_replace(array(' {', '{ '), '{', $css_content); + $css_content = str_replace(', ', ',', $css_content); + $css_content = str_replace(array('} ', ' }', ';}'), '}', $css_content); + $css_content = str_replace(array(':0px', ':0em', ':0pt', ':0%'), ':0', $css_content); + $css_content = str_replace(array(' 0px', ' 0em', ' 0pt', ' 0%'), ' 0', $css_content); + $css_content = str_replace('\'images_ie/', '\'images/', $css_content); + $css_content = preg_replace_callback('#(AlphaImageLoader\(src=\')([^\']*\',)#s', array('Tools', 'replaceByAbsoluteURL'), $css_content); + // Store all import url + preg_match_all('#@(import|charset) .*?;#i', $css_content, $m); + for ($i = 0, $total = count($m[0]); $i < $total; $i++) { + if (isset($m[1][$i]) && $m[1][$i] == 'import') { + $import_url[] = $m[0][$i]; + } + $css_content = str_replace($m[0][$i], '', $css_content); + } + + return trim($css_content); + } + return false; + } + + public static function replaceByAbsoluteURL($matches) + { + if (array_key_exists(1, $matches) && array_key_exists(2, $matches)) { + if (!preg_match('/^(?:https?:)?\/\//iUs', $matches[2])) { + $protocol_link = Tools::getCurrentUrlProtocolPrefix(); + $sep = '/'; + $tmp = $matches[2][0] == $sep ? $matches[2] : dirname(Media::$current_css_file).$sep.ltrim($matches[2], $sep); + $server = Tools::getMediaServer($tmp); + + return $matches[1].$protocol_link.$server.$tmp; + } else + return $matches[0]; + } + return false; + } + + /** + * addJS return javascript path + * + * @param mixed $js_uri + * + * @return string + */ + public static function getJSPath($js_uri) + { + return Media::getMediaPath($js_uri); + } + + /** + * addCSS return stylesheet path. + * + * @param mixed $css_uri + * @param string $css_media_type + * @param bool $need_rtl + * + * @return string + */ + public static function getCSSPath($css_uri, $css_media_type = 'all', $need_rtl = true) + { + // RTL Ready: search and load rtl css file if it's not originally rtl + if ($need_rtl && Context::getContext()->language->is_rtl) { + $css_uri_rtl = preg_replace('/(^[^.].*)(\.css)$/', '$1_rtl.css', $css_uri); + $rtl_media = Media::getMediaPath($css_uri_rtl, $css_media_type); + if ($rtl_media != false) { + return $rtl_media; + } + } + // End RTL + return Media::getMediaPath($css_uri, $css_media_type); + } + + public static function getMediaPath($media_uri, $css_media_type = null) + { + if (is_array($media_uri) || $media_uri === null || empty($media_uri)) { + return false; + } + + $url_data = parse_url($media_uri); + if (!is_array($url_data)) { + return false; + } + + $file_uri = ''; + if (!array_key_exists('host', $url_data)) { + $media_uri_host_mode = '/'.ltrim(str_replace(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, _PS_CORE_DIR_), __PS_BASE_URI__, $media_uri), '/\\'); + $media_uri = '/'.ltrim(str_replace(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, _PS_ROOT_DIR_), __PS_BASE_URI__, $media_uri), '/\\'); + $url_data['path'] = $media_uri; + // remove PS_BASE_URI on _PS_ROOT_DIR_ for the following + $file_uri = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); + $file_uri_host_mode = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, Tools::str_replace_once(_PS_CORE_DIR_, '', $url_data['path'])); + } + + // check if css files exists + if (!array_key_exists('host', $url_data)) { + if (!@filemtime($file_uri) || @filesize($file_uri) === 0) { + if (!defined('_PS_HOST_MODE_')) { + return false; + } elseif (!@filemtime($file_uri_host_mode) || @filesize($file_uri_host_mode) === 0) { + return false; + } else { + $media_uri = $media_uri_host_mode; + } + } + } + + if (!array_key_exists('host', $url_data)) { + $media_uri = str_replace('//', '/', $media_uri); + } + + if ($css_media_type) { + return array($media_uri => $css_media_type); + } + + return $media_uri; + } + + /** + * return jquery path. + * + * @param mixed $version + * + * @return string + */ + public static function getJqueryPath($version = null, $folder = null, $minifier = true) + { + $add_no_conflict = false; + if ($version === null) { + $version = _PS_JQUERY_VERSION_; + } //set default version + elseif (preg_match('/^([0-9\.]+)$/Ui', $version)) { + $add_no_conflict = true; + } else { + return false; + } + + if ($folder === null) { + $folder = _PS_JS_DIR_.'jquery/'; + } //set default folder + //check if file exist + $file = $folder.'jquery-'.$version.($minifier ? '.min.js' : '.js'); + + // remove PS_BASE_URI on _PS_ROOT_DIR_ for the following + $url_data = parse_url($file); + $file_uri = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); + $file_uri_host_mode = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); + // check if js files exists, if not try to load query from ajax.googleapis.com + + $return = array(); + + if (@filemtime($file_uri) || (defined('_PS_HOST_MODE_') && @filemtime($file_uri_host_mode))) { + $return[] = Media::getJSPath($file); + } else { + $return[] = Media::getJSPath(Tools::getCurrentUrlProtocolPrefix().'ajax.googleapis.com/ajax/libs/jquery/' + .$version.'/jquery'.($minifier ? '.min.js' : '.js')); + } + + if ($add_no_conflict) { + $return[] = Media::getJSPath(Context::getContext()->shop->getBaseURL(true, false)._PS_JS_DIR_ + .'jquery/jquery.noConflict.php?version='.$version); + } + + //added query migrate for compatibility with new version of jquery will be removed in ps 1.6 + $return[] = Media::getJSPath(_PS_JS_DIR_.'jquery/jquery-migrate-1.2.1.min.js'); + + return $return; + } + + /** + * return jqueryUI component path. + * + * @param mixed $component + * + * @return string + */ + public static function getJqueryUIPath($component, $theme, $check_dependencies) + { + $ui_path = array('js' => array(), 'css' => array()); + $folder = _PS_JS_DIR_.'jquery/ui/'; + $file = 'jquery.'.$component.'.min.js'; + $url_data = parse_url($folder.$file); + $file_uri = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); + $file_uri_host_mode = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); + $ui_tmp = array(); + if (isset(Media::$jquery_ui_dependencies[$component]) && Media::$jquery_ui_dependencies[$component]['theme'] && $check_dependencies) { + $theme_css = Media::getCSSPath($folder.'themes/'.$theme.'/jquery.ui.theme.css'); + $comp_css = Media::getCSSPath($folder.'themes/'.$theme.'/jquery.'.$component.'.css'); + if (!empty($theme_css) || $theme_css) { + $ui_path['css'] = array_merge($ui_path['css'], $theme_css); + } + if (!empty($comp_css) || $comp_css) { + $ui_path['css'] = array_merge($ui_path['css'], $comp_css); + } + } + if ($check_dependencies && array_key_exists($component, self::$jquery_ui_dependencies)) { + foreach (self::$jquery_ui_dependencies[$component]['dependencies'] as $dependency) { + $ui_tmp[] = Media::getJqueryUIPath($dependency, $theme, false); + if (self::$jquery_ui_dependencies[$dependency]['theme']) { + $dep_css = Media::getCSSPath($folder.'themes/'.$theme.'/jquery.'.$dependency.'.css'); + } + + + if (isset($dep_css) && (!empty($dep_css) || $dep_css)) { + $ui_path['css'] = array_merge($ui_path['css'], $dep_css); + } + } + } + if (@filemtime($file_uri) || (defined('_PS_HOST_MODE_') && @filemtime($file_uri_host_mode))) { + if (!empty($ui_tmp)) { + foreach ($ui_tmp as $ui) { + if (!empty($ui['js'])) { + $ui_path['js'][] = $ui['js']; + } + + if (!empty($ui['css'])) { + $ui_path['css'][] = $ui['css']; + } + } + $ui_path['js'][] = Media::getJSPath($folder.$file); + } else { + $ui_path['js'] = Media::getJSPath($folder.$file); + } + } + + //add i18n file for datepicker + if ($component == 'ui.datepicker') { + if (!is_array($ui_path['js'])) { + $ui_path['js'] = array($ui_path['js']); + } + + $ui_path['js'][] = Media::getJSPath($folder.'i18n/jquery.ui.datepicker-'.Context::getContext()->language->iso_code.'.js'); + } + + return $ui_path; + } + + /** + * return jquery plugin path. + * + * @param mixed $name + * + * @return string|boolean + */ + public static function getJqueryPluginPath($name, $folder = null) + { + $plugin_path = array('js' => array(), 'css' => array()); + if ($folder === null) { + $folder = _PS_JS_DIR_.'jquery/plugins/'; + } //set default folder + + $file = 'jquery.'.$name.'.js'; + $url_data = parse_url($folder); + $file_uri = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); + $file_uri_host_mode = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); + + if (@file_exists($file_uri.$file) || (defined('_PS_HOST_MODE_') && @file_exists($file_uri_host_mode.$file))) { + $plugin_path['js'] = Media::getJSPath($folder.$file); + } elseif (@file_exists($file_uri.$name.'/'.$file) || (defined('_PS_HOST_MODE_') && @file_exists($file_uri_host_mode.$name.'/'.$file))) { + $plugin_path['js'] = Media::getJSPath($folder.$name.'/'.$file); + } else { + return false; + } + $plugin_path['css'] = Media::getJqueryPluginCSSPath($name, $folder); + + return $plugin_path; + } + + /** + * return jquery plugin css path if exist. + * + * @param mixed $name + * + * @return string|boolean + */ + public static function getJqueryPluginCSSPath($name, $folder = null) + { + if ($folder === null) { + $folder = _PS_JS_DIR_.'jquery/plugins/'; + } //set default folder + $file = 'jquery.'.$name.'.css'; + $url_data = parse_url($folder); + $file_uri = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); + $file_uri_host_mode = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, DIRECTORY_SEPARATOR, $url_data['path']); + + if (@file_exists($file_uri.$file) || (defined('_PS_HOST_MODE_') && @file_exists($file_uri_host_mode.$file))) { + return Media::getCSSPath($folder.$file); + } elseif (@file_exists($file_uri.$name.'/'.$file) || (defined('_PS_HOST_MODE_') && @file_exists($file_uri_host_mode.$name.'/'.$file))) { + return Media::getCSSPath($folder.$name.'/'.$file); + } else { + return false; + } + } + + /** + * Combine Compress and Cache CSS (ccc) calls + * + * @param array $css_files + * + * @return array processed css_files + */ + public static function cccCss($css_files) + { + //inits + $css_files_by_media = array(); + $external_css_files = array(); + $compressed_css_files = array(); + $compressed_css_files_not_found = array(); + $compressed_css_files_infos = array(); + $protocol_link = Tools::getCurrentUrlProtocolPrefix(); + $cache_path = _PS_THEME_DIR_.'cache/'; + + // group css files by media + foreach ($css_files as $filename => $media) { + if (!array_key_exists($media, $css_files_by_media)) { + $css_files_by_media[$media] = array(); + } + + $infos = array(); + $infos['uri'] = $filename; + $url_data = parse_url($filename); + + if (array_key_exists('host', $url_data)) { + $external_css_files[$filename] = $media; + continue; + } + + $infos['path'] = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, '/', $url_data['path']); + + if (!@filemtime($infos['path'])) { + $infos['path'] = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, '/', $url_data['path']); + } + + $css_files_by_media[$media]['files'][] = $infos; + if (!array_key_exists('date', $css_files_by_media[$media])) { + $css_files_by_media[$media]['date'] = 0; + } + $css_files_by_media[$media]['date'] = max( + (int)@filemtime($infos['path']), + $css_files_by_media[$media]['date'] + ); + + if (!array_key_exists($media, $compressed_css_files_infos)) { + $compressed_css_files_infos[$media] = array('key' => ''); + } + $compressed_css_files_infos[$media]['key'] .= $filename; + } + + // get compressed css file infos + $version = (int)Configuration::get('PS_CCCCSS_VERSION'); + foreach ($compressed_css_files_infos as $media => &$info) { + $key = md5($info['key'].$protocol_link); + $filename = $cache_path.'v_'.$version.'_'.$key.'_'.$media.'.css'; + + $info = array( + 'key' => $key, + 'date' => (int)@filemtime($filename) + ); + } + + foreach ($css_files_by_media as $media => $media_infos) { + if ($media_infos['date'] > $compressed_css_files_infos[$media]['date']) { + if ($compressed_css_files_infos[$media]['date']) { + Configuration::updateValue('PS_CCCCSS_VERSION', ++$version); + break; + } + } + } + + // aggregate and compress css files content, write new caches files + $import_url = array(); + foreach ($css_files_by_media as $media => $media_infos) { + $cache_filename = $cache_path.'v_'.$version.'_'.$compressed_css_files_infos[$media]['key'].'_'.$media.'.css'; + if ($media_infos['date'] > $compressed_css_files_infos[$media]['date']) { + $cache_filename = $cache_path.'v_'.$version.'_'.$compressed_css_files_infos[$media]['key'].'_'.$media.'.css'; + $compressed_css_files[$media] = ''; + foreach ($media_infos['files'] as $file_infos) { + if (file_exists($file_infos['path'])) { + $compressed_css_files[$media] .= Media::minifyCSS(file_get_contents($file_infos['path']), $file_infos['uri'], $import_url); + } else { + $compressed_css_files_not_found[] = $file_infos['path']; + } + } + if (!empty($compressed_css_files_not_found)) { + $content = '/* WARNING ! file(s) not found : "'. + implode(',', $compressed_css_files_not_found). + '" */'."\n".$compressed_css_files[$media]; + } else { + $content = $compressed_css_files[$media]; + } + + $content = '@charset "UTF-8";'."\n".$content; + $content = implode('', $import_url).$content; + file_put_contents($cache_filename, $content); + chmod($cache_filename, 0777); + } + $compressed_css_files[$media] = $cache_filename; + } + + // rebuild the original css_files array + $css_files = array(); + foreach ($compressed_css_files as $media => $filename) { + $url = str_replace(_PS_THEME_DIR_, _THEMES_DIR_._THEME_NAME_.'/', $filename); + $css_files[$protocol_link.Tools::getMediaServer($url).$url] = $media; + } + return array_merge($external_css_files, $css_files); + } + + public static function getBackTrackLimit() + { + static $limit = null; + if ($limit === null) { + $limit = @ini_get('pcre.backtrack_limit'); + if (!$limit) { + $limit = -1; + } + } + + return $limit; + } + + /** + * Combine Compress and Cache (ccc) JS calls + * + * @param array $js_files + * + * @return array processed js_files + */ + public static function cccJS($js_files) + { + //inits + $compressed_js_files_not_found = array(); + $js_files_infos = array(); + $js_files_date = 0; + $compressed_js_filename = ''; + $js_external_files = array(); + $protocol_link = Tools::getCurrentUrlProtocolPrefix(); + $cache_path = _PS_THEME_DIR_.'cache/'; + + // get js files infos + foreach ($js_files as $filename) { + if (Validate::isAbsoluteUrl($filename)) { + $js_external_files[] = $filename; + } else { + $infos = array(); + $infos['uri'] = $filename; + $url_data = parse_url($filename); + $infos['path'] = _PS_ROOT_DIR_.Tools::str_replace_once(__PS_BASE_URI__, '/', $url_data['path']); + + if (!@filemtime($infos['path'])) { + $infos['path'] = _PS_CORE_DIR_.Tools::str_replace_once(__PS_BASE_URI__, '/', $url_data['path']); + } + + $js_files_infos[] = $infos; + + $js_files_date = max( + (int)@filemtime($infos['path']), + $js_files_date + ); + $compressed_js_filename .= $filename; + } + } + + // get compressed js file infos + $compressed_js_filename = md5($compressed_js_filename); + $version = (int)Configuration::get('PS_CCCJS_VERSION'); + $compressed_js_path = $cache_path.'v_'.$version.'_'.$compressed_js_filename.'.js'; + $compressed_js_file_date = (int)@filemtime($compressed_js_path); + + // aggregate and compress js files content, write new caches files + if ($js_files_date > $compressed_js_file_date) { + if ($compressed_js_file_date) { + Configuration::updateValue('PS_CCCJS_VERSION', ++$version); + } + + $compressed_js_path = $cache_path.'v_'.$version.'_'.$compressed_js_filename.'.js'; + $content = ''; + foreach ($js_files_infos as $file_infos) { + if (file_exists($file_infos['path'])) { + $tmp_content = file_get_contents($file_infos['path']); + if (preg_match('@\.(min|pack)\.[^/]+$@', $file_infos['path'], $matches)) { + $content .= preg_replace('/\/\/@\ssourceMappingURL\=[_a-zA-Z0-9-.]+\.'.$matches[1].'\.map\s+/', '', $tmp_content); + } else { + $content .= Media::packJS($tmp_content); + } + } else { + $compressed_js_files_not_found[] = $file_infos['path']; + } + } + + if (!empty($compressed_js_files_not_found)) { + $content = '/* WARNING ! file(s) not found : "'. + implode(',', $compressed_js_files_not_found). + '" */'."\n".$content; + } + + file_put_contents($compressed_js_path, $content); + chmod($compressed_js_path, 0777); + } + + // rebuild the original js_files array + if (strpos($compressed_js_path, _PS_ROOT_DIR_) !== false) { + $url = str_replace(_PS_ROOT_DIR_.'/', __PS_BASE_URI__, $compressed_js_path); + } + + if (strpos($compressed_js_path, _PS_CORE_DIR_) !== false) { + $url = str_replace(_PS_CORE_DIR_.'/', __PS_BASE_URI__, $compressed_js_path); + } + + return array_merge(array($protocol_link.Tools::getMediaServer($url).$url), $js_external_files); + } + + /** + * Clear theme cache + * + * @return void + */ + public static function clearCache() + { + foreach (array(_PS_THEME_DIR_.'cache') as $dir) { + if (file_exists($dir)) { + foreach (scandir($dir) as $file) { + if ($file[0] != '.' && $file != 'index.php') { + Tools::deleteFile($dir.DIRECTORY_SEPARATOR.$file, array('index.php')); + } + } + } + } + + $version = (int)Configuration::get('PS_CCCJS_VERSION'); + Configuration::updateValue('PS_CCCJS_VERSION', ++$version); + $version = (int)Configuration::get('PS_CCCCSS_VERSION'); + Configuration::updateValue('PS_CCCCSS_VERSION', ++$version); + } + + /** + * Get JS definitions + * + * @return array JS definitions + */ + public static function getJsDef() + { + ksort(Media::$js_def); + return Media::$js_def; + } + + /** + * Get JS inline script + * + * @return array inline script + */ + public static function getInlineScript() + { + return Media::$inline_script; + } + + /** + * Add a new javascript definition at bottom of page + * + * @param mixed $js_def + * + * @return void + */ + public static function addJsDef($js_def) + { + if (is_array($js_def)) { + foreach ($js_def as $key => $js) { + Media::$js_def[$key] = $js; + } + } elseif ($js_def) { + Media::$js_def[] = $js_def; + } + } + + /** + * Add a new javascript definition from a capture at bottom of page + * + * @param mixed $params + * @param string $content + * @param Smarty $smarty + * @param bool $repeat + * + * @return void + */ + public static function addJsDefL($params, $content, $smarty = null, &$repeat = false) + { + if (!$repeat && isset($params) && Tools::strlen($content)) { + if (!is_array($params)) { + $params = (array)$params; + } + + foreach ($params as $param) { + Media::$js_def[$param] = $content; + } + } + } + + public static function deferInlineScripts($output) + { + /* Try to enqueue in js_files inline scripts with src but without conditionnal comments */ + $dom = new DOMDocument(); + libxml_use_internal_errors(true); + @$dom->loadHTML(($output)); + libxml_use_internal_errors(false); + $scripts = $dom->getElementsByTagName('script'); + if (is_object($scripts) && $scripts->length) { + foreach ($scripts as $script) { + /** @var DOMElement $script */ + if ($src = $script->getAttribute('src')) { + if (substr($src, 0, 2) == '//') { + $src = Tools::getCurrentUrlProtocolPrefix().substr($src, 2); + } + + $patterns = array( + '#code\.jquery\.com/jquery-([0-9\.]+)(\.min)*\.js$#Ui', + '#ajax\.googleapis\.com/ajax/libs/jquery/([0-9\.]+)/jquery(\.min)*\.js$#Ui', + '#ajax\.aspnetcdn\.com/ajax/jquery/jquery-([0-9\.]+)(\.min)*\.js$#Ui', + '#cdnjs\.cloudflare\.com/ajax/libs/jquery/([0-9\.]+)/jquery(\.min)*\.js$#Ui', + '#/jquery-([0-9\.]+)(\.min)*\.js$#Ui' + ); + + foreach ($patterns as $pattern) { + $matches = array(); + if (preg_match($pattern, $src, $matches)) { + $minifier = $version = false; + if (isset($matches[2]) && $matches[2]) { + $minifier = (bool)$matches[2]; + } + if (isset($matches[1]) && $matches[1]) { + $version = $matches[1]; + } + if ($version) { + if ($version != _PS_JQUERY_VERSION_) { + Context::getContext()->controller->addJquery($version, null, $minifier); + } + array_push(Media::$inline_script_src, $src); + } + } + } + if (!in_array($src, Media::$inline_script_src)) { + Context::getContext()->controller->addJS($src); + } + } + } + } + $output = preg_replace_callback(Media::$pattern_js, array('Media', 'deferScript'), $output); + return $output; + } + + /** + * Get all JS scripts and place it to bottom + * To be used in callback with deferInlineScripts + * + * @param array $matches + * + * @return bool|string Empty string or original script lines + */ + public static function deferScript($matches) + { + if (!is_array($matches)) { + return false; + } + $inline = ''; + + if (isset($matches[0])) { + $original = trim($matches[0]); + } + + if (isset($matches[2])) { + $inline = trim($matches[2]); + } + + /* This is an inline script, add its content to inline scripts stack then remove it from content */ + if (!empty($inline) && preg_match(Media::$pattern_js, $original) !== false && Media::$inline_script[] = $inline) { + return ''; + } + + /* This is an external script, if it already belongs to js_files then remove it from content */ + preg_match('/src\s*=\s*["\']?([^"\']*)[^>]/ims', $original, $results); + if (array_key_exists(1, $results)) { + if (substr($results[1], 0, 2) == '//') { + $protocol_link = Tools::getCurrentUrlProtocolPrefix(); + $results[1] = $protocol_link.ltrim($results[1], '/'); + } + if (in_array($results[1], Context::getContext()->controller->js_files) || in_array($results[1], Media::$inline_script_src)) { + return ''; + } + } + + /* return original string because no match was found */ + return $original; + } } diff --git a/classes/Message.php b/classes/Message.php index 3adb7e5d..ff86f539 100644 --- a/classes/Message.php +++ b/classes/Message.php @@ -26,77 +26,79 @@ class MessageCore extends ObjectModel { - public $id; + public $id; - /** @var string message content */ - public $message; + /** @var string message content */ + public $message; - /** @var int Cart ID (if applicable) */ - public $id_cart; + /** @var int Cart ID (if applicable) */ + public $id_cart; - /** @var int Order ID (if applicable) */ - public $id_order; + /** @var int Order ID (if applicable) */ + public $id_order; - /** @var int Customer ID (if applicable) */ - public $id_customer; + /** @var int Customer ID (if applicable) */ + public $id_customer; - /** @var int Employee ID (if applicable) */ - public $id_employee; + /** @var int Employee ID (if applicable) */ + public $id_employee; - /** @var bool Message is not displayed to the customer */ - public $private; + /** @var bool Message is not displayed to the customer */ + public $private; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'message', - 'primary' => 'id_message', - 'fields' => array( - 'message' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'required' => true, 'size' => 1600), - 'id_cart' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'private' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'message', + 'primary' => 'id_message', + 'fields' => array( + 'message' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'required' => true, 'size' => 1600), + 'id_cart' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'private' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - /** - * Return the last message from cart - * - * @param int $id_cart Cart ID - * @return array Message - */ - public static function getMessageByCartId($id_cart) - { - return Db::getInstance()->getRow(' + /** + * Return the last message from cart + * + * @param int $id_cart Cart ID + * @return array Message + */ + public static function getMessageByCartId($id_cart) + { + return Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.'message` WHERE `id_cart` = '.(int)$id_cart - ); - } + ); + } - /** - * Return messages from Order ID - * - * @param int $id_order Order ID - * @param bool $private return WITH private messages - * @return array Messages - */ - public static function getMessagesByOrderId($id_order, $private = false, Context $context = null) - { - if (!Validate::isBool($private)) - die(Tools::displayError()); + /** + * Return messages from Order ID + * + * @param int $id_order Order ID + * @param bool $private return WITH private messages + * @return array Messages + */ + public static function getMessagesByOrderId($id_order, $private = false, Context $context = null) + { + if (!Validate::isBool($private)) { + die(Tools::displayError()); + } - if (!$context) - $context = Context::getContext(); + if (!$context) { + $context = Context::getContext(); + } - return Db::getInstance()->executeS(' + return Db::getInstance()->executeS(' SELECT m.*, c.`firstname` AS cfirstname, c.`lastname` AS clastname, e.`firstname` AS efirstname, e.`lastname` AS elastname, (COUNT(mr.id_message) = 0 AND m.id_customer != 0) AS is_new_for_me FROM `'._DB_PREFIX_.'message` m @@ -110,24 +112,26 @@ class MessageCore extends ObjectModel GROUP BY m.id_message ORDER BY m.date_add DESC '); - } + } - /** - * Return messages from Cart ID - * - * @param int $id_order Order ID - * @param bool $private return WITH private messages - * @return array Messages - */ - public static function getMessagesByCartId($id_cart, $private = false, Context $context = null) - { - if (!Validate::isBool($private)) - die(Tools::displayError()); + /** + * Return messages from Cart ID + * + * @param int $id_order Order ID + * @param bool $private return WITH private messages + * @return array Messages + */ + public static function getMessagesByCartId($id_cart, $private = false, Context $context = null) + { + if (!Validate::isBool($private)) { + die(Tools::displayError()); + } - if (!$context) - $context = Context::getContext(); + if (!$context) { + $context = Context::getContext(); + } - return Db::getInstance()->executeS(' + return Db::getInstance()->executeS(' SELECT m.*, c.`firstname` AS cfirstname, c.`lastname` AS clastname, e.`firstname` AS efirstname, e.`lastname` AS elastname, (COUNT(mr.id_message) = 0 AND m.id_customer != 0) AS is_new_for_me FROM `'._DB_PREFIX_.'message` m @@ -139,23 +143,24 @@ class MessageCore extends ObjectModel GROUP BY m.id_message ORDER BY m.date_add DESC '); - } + } - /** - * Registered a message 'readed' - * - * @param int $id_message Message ID - * @param int $id_emplyee Employee ID - */ - public static function markAsReaded($id_message, $id_employee) - { - if (!Validate::isUnsignedId($id_message) || !Validate::isUnsignedId($id_employee)) - die(Tools::displayError()); + /** + * Registered a message 'readed' + * + * @param int $id_message Message ID + * @param int $id_emplyee Employee ID + */ + public static function markAsReaded($id_message, $id_employee) + { + if (!Validate::isUnsignedId($id_message) || !Validate::isUnsignedId($id_employee)) { + die(Tools::displayError()); + } - $result = Db::getInstance()->execute(' + $result = Db::getInstance()->execute(' INSERT INTO '._DB_PREFIX_.'message_readed (id_message , id_employee , date_add) VALUES ('.(int)$id_message.', '.(int)$id_employee.', NOW()); '); - return $result; - } -} \ No newline at end of file + return $result; + } +} diff --git a/classes/Meta.php b/classes/Meta.php index 268c5a8c..fe32ea82 100644 --- a/classes/Meta.php +++ b/classes/Meta.php @@ -26,111 +26,118 @@ class MetaCore extends ObjectModel { - public $page; - public $configurable = 1; - public $title; - public $description; - public $keywords; - public $url_rewrite; + public $page; + public $configurable = 1; + public $title; + public $description; + public $keywords; + public $url_rewrite; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'meta', - 'primary' => 'id_meta', - 'multilang' => true, - 'multilang_shop' => true, - 'fields' => array( - 'page' => array('type' => self::TYPE_STRING, 'validate' => 'isFileName', 'required' => true, 'size' => 64), - 'configurable' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'meta', + 'primary' => 'id_meta', + 'multilang' => true, + 'multilang_shop' => true, + 'fields' => array( + 'page' => array('type' => self::TYPE_STRING, 'validate' => 'isFileName', 'required' => true, 'size' => 64), + 'configurable' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - /* Lang fields */ - 'title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), - 'description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - 'keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - 'url_rewrite' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isLinkRewrite', 'size' => 255), - ), - ); + /* Lang fields */ + 'title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), + 'description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + 'keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + 'url_rewrite' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isLinkRewrite', 'size' => 255), + ), + ); - public static function getPages($exclude_filled = false, $add_page = false) - { - $selected_pages = array(); - if (!$files = Tools::scandir(_PS_CORE_DIR_.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.'front'.DIRECTORY_SEPARATOR, 'php', '', true)) - die(Tools::displayError('Cannot scan root directory')); + public static function getPages($exclude_filled = false, $add_page = false) + { + $selected_pages = array(); + if (!$files = Tools::scandir(_PS_CORE_DIR_.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.'front'.DIRECTORY_SEPARATOR, 'php', '', true)) { + die(Tools::displayError('Cannot scan "root" directory')); + } - // Exclude pages forbidden - $exlude_pages = array( - 'category', 'changecurrency', 'cms', 'footer', 'header', - 'pagination', 'product', 'product-sort', 'statistics' - ); + if (!$override_files = Tools::scandir(_PS_CORE_DIR_.DIRECTORY_SEPARATOR . 'override' . DIRECTORY_SEPARATOR . 'controllers' . DIRECTORY_SEPARATOR . 'front' . DIRECTORY_SEPARATOR, 'php', '', true)) { + die(Tools::displayError('Cannot scan "override" directory')); + } - foreach ($files as $file) - { - if ($file != 'index.php' && !in_array(strtolower(str_replace('Controller.php', '', $file)), $exlude_pages)) - { - $class_name = str_replace('.php', '', $file); - $reflection = class_exists($class_name) ? new ReflectionClass(str_replace('.php', '', $file)) : false; - $properties = $reflection ? $reflection->getDefaultProperties() : array(); - if (isset($properties['php_self'])) - $selected_pages[$properties['php_self']] = $properties['php_self']; - elseif (preg_match('/^[a-z0-9_.-]*\.php$/i', $file)) - $selected_pages[strtolower(str_replace('Controller.php', '', $file))] = strtolower(str_replace('Controller.php', '', $file)); - elseif (preg_match('/^([a-z0-9_.-]*\/)?[a-z0-9_.-]*\.php$/i', $file)) - $selected_pages[strtolower(sprintf(Tools::displayError('%2$s (in %1$s)'), dirname($file), str_replace('Controller.php', '', basename($file))))] = strtolower(str_replace('Controller.php', '', basename($file))); - } - } + $files = array_values(array_unique(array_merge($files, $override_files))); - // Add modules controllers to list (this function is cool !) - foreach (glob(_PS_MODULE_DIR_.'*/controllers/front/*.php') as $file) - { - $filename = Tools::strtolower(basename($file, '.php')); - if ($filename == 'index') - continue; + // Exclude pages forbidden + $exlude_pages = array( + 'category', 'changecurrency', 'cms', 'footer', 'header', + 'pagination', 'product', 'product-sort', 'statistics' + ); - $module = Tools::strtolower(basename(dirname(dirname(dirname($file))))); - $selected_pages[$module.' - '.$filename] = 'module-'.$module.'-'.$filename; - } + foreach ($files as $file) { + if ($file != 'index.php' && !in_array(strtolower(str_replace('Controller.php', '', $file)), $exlude_pages)) { + $class_name = str_replace('.php', '', $file); + $reflection = class_exists($class_name) ? new ReflectionClass(str_replace('.php', '', $file)) : false; + $properties = $reflection ? $reflection->getDefaultProperties() : array(); + if (isset($properties['php_self'])) { + $selected_pages[$properties['php_self']] = $properties['php_self']; + } elseif (preg_match('/^[a-z0-9_.-]*\.php$/i', $file)) { + $selected_pages[strtolower(str_replace('Controller.php', '', $file))] = strtolower(str_replace('Controller.php', '', $file)); + } elseif (preg_match('/^([a-z0-9_.-]*\/)?[a-z0-9_.-]*\.php$/i', $file)) { + $selected_pages[strtolower(sprintf(Tools::displayError('%2$s (in %1$s)'), dirname($file), str_replace('Controller.php', '', basename($file))))] = strtolower(str_replace('Controller.php', '', basename($file))); + } + } + } - // Exclude page already filled - if ($exclude_filled) - { - $metas = Meta::getMetas(); - foreach ($metas as $meta) - if (in_array($meta['page'], $selected_pages)) - unset($selected_pages[array_search($meta['page'], $selected_pages)]); - } - // Add selected page - if ($add_page) - { - $name = $add_page; - if (preg_match('#module-([a-z0-9_-]+)-([a-z0-9]+)$#i', $add_page, $m)) - $add_page = $m[1].' - '.$m[2]; - $selected_pages[$add_page] = $name; - asort($selected_pages); - } - return $selected_pages; - } + // Add modules controllers to list (this function is cool !) + foreach (glob(_PS_MODULE_DIR_.'*/controllers/front/*.php') as $file) { + $filename = Tools::strtolower(basename($file, '.php')); + if ($filename == 'index') { + continue; + } - public static function getMetas() - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT * FROM '._DB_PREFIX_.'meta ORDER BY page ASC'); - } + $module = Tools::strtolower(basename(dirname(dirname(dirname($file))))); + $selected_pages[$module.' - '.$filename] = 'module-'.$module.'-'.$filename; + } - public static function getMetasByIdLang($id_lang) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + // Exclude page already filled + if ($exclude_filled) { + $metas = Meta::getMetas(); + foreach ($metas as $meta) { + if (in_array($meta['page'], $selected_pages)) { + unset($selected_pages[array_search($meta['page'], $selected_pages)]); + } + } + } + // Add selected page + if ($add_page) { + $name = $add_page; + if (preg_match('#module-([a-z0-9_-]+)-([a-z0-9]+)$#i', $add_page, $m)) { + $add_page = $m[1].' - '.$m[2]; + } + $selected_pages[$add_page] = $name; + asort($selected_pages); + } + return $selected_pages; + } + + public static function getMetas() + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT * FROM '._DB_PREFIX_.'meta ORDER BY page ASC'); + } + + public static function getMetasByIdLang($id_lang) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'meta` m LEFT JOIN `'._DB_PREFIX_.'meta_lang` ml ON m.`id_meta` = ml.`id_meta` WHERE ml.`id_lang` = '.(int)$id_lang - .Shop::addSqlRestrictionOnLang('ml'). - 'ORDER BY page ASC'); - } + .Shop::addSqlRestrictionOnLang('ml'). + 'ORDER BY page ASC'); + } - public static function getMetaByPage($page, $id_lang) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + public static function getMetaByPage($page, $id_lang) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT * FROM '._DB_PREFIX_.'meta m LEFT JOIN '._DB_PREFIX_.'meta_lang ml ON m.id_meta = ml.id_meta @@ -140,41 +147,43 @@ class MetaCore extends ObjectModel ) AND ml.id_lang = '.(int)$id_lang.' '.Shop::addSqlRestrictionOnLang('ml')); - } + } - public function update($null_values = false) - { - if (!parent::update($null_values)) - return false; + public function update($null_values = false) + { + if (!parent::update($null_values)) { + return false; + } - return Tools::generateHtaccess(); - } + return Tools::generateHtaccess(); + } - public function delete() - { - if (!parent::delete()) - return false; + public function delete() + { + if (!parent::delete()) { + return false; + } - return Tools::generateHtaccess(); - } + return Tools::generateHtaccess(); + } - public function deleteSelection($selection) - { - if (!is_array($selection)) - die(Tools::displayError()); - $result = true; - foreach ($selection as $id) - { - $this->id = (int)$id; - $result = $result && $this->delete(); - } + public function deleteSelection($selection) + { + if (!is_array($selection)) { + die(Tools::displayError()); + } + $result = true; + foreach ($selection as $id) { + $this->id = (int)$id; + $result = $result && $this->delete(); + } - return $result && Tools::generateHtaccess(); - } + return $result && Tools::generateHtaccess(); + } - public static function getEquivalentUrlRewrite($new_id_lang, $id_lang, $url_rewrite) - { - return Db::getInstance()->getValue(' + public static function getEquivalentUrlRewrite($new_id_lang, $id_lang, $url_rewrite) + { + return Db::getInstance()->getValue(' SELECT url_rewrite FROM `'._DB_PREFIX_.'meta_lang` WHERE id_meta = ( @@ -185,248 +194,253 @@ class MetaCore extends ObjectModel ) AND id_lang = '.(int)$new_id_lang.' AND id_shop = '.Context::getContext()->shop->id); - } + } - /** - * @since 1.5.0 - */ - public static function getMetaTags($id_lang, $page_name, $title = '') - { - global $maintenance; - if (!(isset($maintenance) && (!in_array(Tools::getRemoteAddr(), explode(',', Configuration::get('PS_MAINTENANCE_IP')))))) - { - if ($page_name == 'product' && ($id_product = Tools::getValue('id_product'))) - return Meta::getProductMetas($id_product, $id_lang, $page_name); - elseif ($page_name == 'category' && ($id_category = Tools::getValue('id_category'))) - return Meta::getCategoryMetas($id_category, $id_lang, $page_name, $title); - elseif ($page_name == 'manufacturer' && ($id_manufacturer = Tools::getValue('id_manufacturer'))) - return Meta::getManufacturerMetas($id_manufacturer, $id_lang, $page_name); - elseif ($page_name == 'supplier' && ($id_supplier = Tools::getValue('id_supplier'))) - return Meta::getSupplierMetas($id_supplier, $id_lang, $page_name); - elseif ($page_name == 'cms' && ($id_cms = Tools::getValue('id_cms'))) - return Meta::getCmsMetas($id_cms, $id_lang, $page_name); - elseif ($page_name == 'cms' && ($id_cms_category = Tools::getValue('id_cms_category'))) - return Meta::getCmsCategoryMetas($id_cms_category, $id_lang, $page_name); - } + /** + * @since 1.5.0 + */ + public static function getMetaTags($id_lang, $page_name, $title = '') + { + global $maintenance; + if (!(isset($maintenance) && (!in_array(Tools::getRemoteAddr(), explode(',', Configuration::get('PS_MAINTENANCE_IP')))))) { + if ($page_name == 'product' && ($id_product = Tools::getValue('id_product'))) { + return Meta::getProductMetas($id_product, $id_lang, $page_name); + } elseif ($page_name == 'category' && ($id_category = Tools::getValue('id_category'))) { + return Meta::getCategoryMetas($id_category, $id_lang, $page_name, $title); + } elseif ($page_name == 'manufacturer' && ($id_manufacturer = Tools::getValue('id_manufacturer'))) { + return Meta::getManufacturerMetas($id_manufacturer, $id_lang, $page_name); + } elseif ($page_name == 'supplier' && ($id_supplier = Tools::getValue('id_supplier'))) { + return Meta::getSupplierMetas($id_supplier, $id_lang, $page_name); + } elseif ($page_name == 'cms' && ($id_cms = Tools::getValue('id_cms'))) { + return Meta::getCmsMetas($id_cms, $id_lang, $page_name); + } elseif ($page_name == 'cms' && ($id_cms_category = Tools::getValue('id_cms_category'))) { + return Meta::getCmsCategoryMetas($id_cms_category, $id_lang, $page_name); + } + } - return Meta::getHomeMetas($id_lang, $page_name); - } + return Meta::getHomeMetas($id_lang, $page_name); + } - /** - * Get meta tags for a given page - * - * @since 1.5.0 - * @param int $id_lang - * @param string $page_name - * @return array Meta tags - */ - public static function getHomeMetas($id_lang, $page_name) - { - $metas = Meta::getMetaByPage($page_name, $id_lang); - $ret['meta_title'] = (isset($metas['title']) && $metas['title']) ? $metas['title'].' - '.Configuration::get('PS_SHOP_NAME') : Configuration::get('PS_SHOP_NAME'); - $ret['meta_description'] = (isset($metas['description']) && $metas['description']) ? $metas['description'] : ''; - $ret['meta_keywords'] = (isset($metas['keywords']) && $metas['keywords']) ? $metas['keywords'] : ''; - return $ret; - } + /** + * Get meta tags for a given page + * + * @since 1.5.0 + * @param int $id_lang + * @param string $page_name + * @return array Meta tags + */ + public static function getHomeMetas($id_lang, $page_name) + { + $metas = Meta::getMetaByPage($page_name, $id_lang); + $ret['meta_title'] = (isset($metas['title']) && $metas['title']) ? $metas['title'].' - '.Configuration::get('PS_SHOP_NAME') : Configuration::get('PS_SHOP_NAME'); + $ret['meta_description'] = (isset($metas['description']) && $metas['description']) ? $metas['description'] : ''; + $ret['meta_keywords'] = (isset($metas['keywords']) && $metas['keywords']) ? $metas['keywords'] : ''; + return $ret; + } - /** - * Get product meta tags - * - * @since 1.5.0 - * @param int $id_product - * @param int $id_lang - * @param string $page_name - * @return array - */ - public static function getProductMetas($id_product, $id_lang, $page_name) - { - $sql = 'SELECT `name`, `meta_title`, `meta_description`, `meta_keywords`, `description_short` + /** + * Get product meta tags + * + * @since 1.5.0 + * @param int $id_product + * @param int $id_lang + * @param string $page_name + * @return array + */ + public static function getProductMetas($id_product, $id_lang, $page_name) + { + $sql = 'SELECT `name`, `meta_title`, `meta_description`, `meta_keywords`, `description_short` FROM `'._DB_PREFIX_.'product` p LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (pl.`id_product` = p.`id_product`'.Shop::addSqlRestrictionOnLang('pl').') '.Shop::addSqlAssociation('product', 'p').' WHERE pl.id_lang = '.(int)$id_lang.' AND pl.id_product = '.(int)$id_product.' AND product_shop.active = 1'; - if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql)) - { - if (empty($row['meta_description'])) - $row['meta_description'] = strip_tags($row['description_short']); - return Meta::completeMetaTags($row, $row['name']); - } + if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql)) { + if (empty($row['meta_description'])) { + $row['meta_description'] = strip_tags($row['description_short']); + } + return Meta::completeMetaTags($row, $row['name']); + } - return Meta::getHomeMetas($id_lang, $page_name); - } + return Meta::getHomeMetas($id_lang, $page_name); + } - /** - * Get category meta tags - * - * @since 1.5.0 - * @param int $id_category - * @param int $id_lang - * @param string $page_name - * @return array - */ - public static function getCategoryMetas($id_category, $id_lang, $page_name, $title = '') - { - if (!empty($title)) - $title = ' - '.$title; - $page_number = (int)Tools::getValue('p'); - $sql = 'SELECT `name`, `meta_title`, `meta_description`, `meta_keywords`, `description` + /** + * Get category meta tags + * + * @since 1.5.0 + * @param int $id_category + * @param int $id_lang + * @param string $page_name + * @return array + */ + public static function getCategoryMetas($id_category, $id_lang, $page_name, $title = '') + { + if (!empty($title)) { + $title = ' - '.$title; + } + $page_number = (int)Tools::getValue('p'); + $sql = 'SELECT `name`, `meta_title`, `meta_description`, `meta_keywords`, `description` FROM `'._DB_PREFIX_.'category_lang` cl WHERE cl.`id_lang` = '.(int)$id_lang.' AND cl.`id_category` = '.(int)$id_category.Shop::addSqlRestrictionOnLang('cl'); - $cache_id = 'Meta::getCategoryMetas'.(int)$id_category.'-'.(int)$id_lang; - if (!Cache::isStored($cache_id)) - { - if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql)) - { - if (empty($row['meta_description'])) - $row['meta_description'] = strip_tags($row['description']); + $cache_id = 'Meta::getCategoryMetas'.(int)$id_category.'-'.(int)$id_lang; + if (!Cache::isStored($cache_id)) { + if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql)) { + if (empty($row['meta_description'])) { + $row['meta_description'] = strip_tags($row['description']); + } - // Paginate title - if (!empty($row['meta_title'])) - $row['meta_title'] = $title.$row['meta_title'].(!empty($page_number) ? ' ('.$page_number.')' : '').' - '.Configuration::get('PS_SHOP_NAME'); - else - $row['meta_title'] = $row['name'].(!empty($page_number) ? ' ('.$page_number.')' : '').' - '.Configuration::get('PS_SHOP_NAME'); + // Paginate title + if (!empty($row['meta_title'])) { + $row['meta_title'] = $title.$row['meta_title'].(!empty($page_number) ? ' ('.$page_number.')' : '').' - '.Configuration::get('PS_SHOP_NAME'); + } else { + $row['meta_title'] = $row['name'].(!empty($page_number) ? ' ('.$page_number.')' : '').' - '.Configuration::get('PS_SHOP_NAME'); + } - if (!empty($title)) - $row['meta_title'] = $title.(!empty($page_number) ? ' ('.$page_number.')' : '').' - '.Configuration::get('PS_SHOP_NAME'); + if (!empty($title)) { + $row['meta_title'] = $title.(!empty($page_number) ? ' ('.$page_number.')' : '').' - '.Configuration::get('PS_SHOP_NAME'); + } - $result = Meta::completeMetaTags($row, $row['name']); - } - else - $result = Meta::getHomeMetas($id_lang, $page_name); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + $result = Meta::completeMetaTags($row, $row['name']); + } else { + $result = Meta::getHomeMetas($id_lang, $page_name); + } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Get manufacturer meta tags - * - * @since 1.5.0 - * @param int $id_manufacturer - * @param int $id_lang - * @param string $page_name - * @return array - */ - public static function getManufacturerMetas($id_manufacturer, $id_lang, $page_name) - { - $page_number = (int)Tools::getValue('p'); - $sql = 'SELECT `name`, `meta_title`, `meta_description`, `meta_keywords` + /** + * Get manufacturer meta tags + * + * @since 1.5.0 + * @param int $id_manufacturer + * @param int $id_lang + * @param string $page_name + * @return array + */ + public static function getManufacturerMetas($id_manufacturer, $id_lang, $page_name) + { + $page_number = (int)Tools::getValue('p'); + $sql = 'SELECT `name`, `meta_title`, `meta_description`, `meta_keywords` FROM `'._DB_PREFIX_.'manufacturer_lang` ml LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (ml.`id_manufacturer` = m.`id_manufacturer`) WHERE ml.id_lang = '.(int)$id_lang.' AND ml.id_manufacturer = '.(int)$id_manufacturer; - if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql)) - { - if (!empty($row['meta_description'])) - $row['meta_description'] = strip_tags($row['meta_description']); - $row['meta_title'] = ($row['meta_title'] ? $row['meta_title'] : $row['name']).(!empty($page_number) ? ' ('.$page_number.')' : ''); - $row['meta_title'] .= ' - '.Configuration::get('PS_SHOP_NAME'); - return Meta::completeMetaTags($row, $row['meta_title']); - } + if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql)) { + if (!empty($row['meta_description'])) { + $row['meta_description'] = strip_tags($row['meta_description']); + } + $row['meta_title'] = ($row['meta_title'] ? $row['meta_title'] : $row['name']).(!empty($page_number) ? ' ('.$page_number.')' : ''); + $row['meta_title'] .= ' - '.Configuration::get('PS_SHOP_NAME'); + return Meta::completeMetaTags($row, $row['meta_title']); + } - return Meta::getHomeMetas($id_lang, $page_name); - } + return Meta::getHomeMetas($id_lang, $page_name); + } - /** - * Get supplier meta tags - * - * @since 1.5.0 - * @param int $id_supplier - * @param int $id_lang - * @param string $page_name - * @return array - */ - public static function getSupplierMetas($id_supplier, $id_lang, $page_name) - { - $sql = 'SELECT `name`, `meta_title`, `meta_description`, `meta_keywords` + /** + * Get supplier meta tags + * + * @since 1.5.0 + * @param int $id_supplier + * @param int $id_lang + * @param string $page_name + * @return array + */ + public static function getSupplierMetas($id_supplier, $id_lang, $page_name) + { + $sql = 'SELECT `name`, `meta_title`, `meta_description`, `meta_keywords` FROM `'._DB_PREFIX_.'supplier_lang` sl LEFT JOIN `'._DB_PREFIX_.'supplier` s ON (sl.`id_supplier` = s.`id_supplier`) WHERE sl.id_lang = '.(int)$id_lang.' AND sl.id_supplier = '.(int)$id_supplier; - if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql)) - { - if (!empty($row['meta_description'])) - $row['meta_description'] = strip_tags($row['meta_description']); - if (!empty($row['meta_title'])) - $row['meta_title'] = $row['meta_title'].' - '.Configuration::get('PS_SHOP_NAME'); - return Meta::completeMetaTags($row, $row['name']); - } + if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql)) { + if (!empty($row['meta_description'])) { + $row['meta_description'] = strip_tags($row['meta_description']); + } + if (!empty($row['meta_title'])) { + $row['meta_title'] = $row['meta_title'].' - '.Configuration::get('PS_SHOP_NAME'); + } + return Meta::completeMetaTags($row, $row['name']); + } - return Meta::getHomeMetas($id_lang, $page_name); - } + return Meta::getHomeMetas($id_lang, $page_name); + } - /** - * Get CMS meta tags - * - * @since 1.5.0 - * @param int $id_cms - * @param int $id_lang - * @param string $page_name - * @return array - */ - public static function getCmsMetas($id_cms, $id_lang, $page_name) - { - $sql = 'SELECT `meta_title`, `meta_description`, `meta_keywords` + /** + * Get CMS meta tags + * + * @since 1.5.0 + * @param int $id_cms + * @param int $id_lang + * @param string $page_name + * @return array + */ + public static function getCmsMetas($id_cms, $id_lang, $page_name) + { + $sql = 'SELECT `meta_title`, `meta_description`, `meta_keywords` FROM `'._DB_PREFIX_.'cms_lang` WHERE id_lang = '.(int)$id_lang.' AND id_cms = '.(int)$id_cms. - ((int)Context::getContext()->shop->id ? - ' AND id_shop = '.(int)Context::getContext()->shop->id : '' ); + ((int)Context::getContext()->shop->id ? + ' AND id_shop = '.(int)Context::getContext()->shop->id : ''); - if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql)) - { - $row['meta_title'] = $row['meta_title'].' - '.Configuration::get('PS_SHOP_NAME'); - return Meta::completeMetaTags($row, $row['meta_title']); - } + if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql)) { + $row['meta_title'] = $row['meta_title'].' - '.Configuration::get('PS_SHOP_NAME'); + return Meta::completeMetaTags($row, $row['meta_title']); + } - return Meta::getHomeMetas($id_lang, $page_name); - } + return Meta::getHomeMetas($id_lang, $page_name); + } - /** - * Get CMS category meta tags - * - * @since 1.5.0 - * @param int $id_cms_category - * @param int $id_lang - * @param string $page_name - * @return array - */ - public static function getCmsCategoryMetas($id_cms_category, $id_lang, $page_name) - { - $sql = 'SELECT `meta_title`, `meta_description`, `meta_keywords` + /** + * Get CMS category meta tags + * + * @since 1.5.0 + * @param int $id_cms_category + * @param int $id_lang + * @param string $page_name + * @return array + */ + public static function getCmsCategoryMetas($id_cms_category, $id_lang, $page_name) + { + $sql = 'SELECT `meta_title`, `meta_description`, `meta_keywords` FROM `'._DB_PREFIX_.'cms_category_lang` WHERE id_lang = '.(int)$id_lang.' AND id_cms_category = '.(int)$id_cms_category. - ((int)Context::getContext()->shop->id ? - ' AND id_shop = '.(int)Context::getContext()->shop->id : ''); - if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql)) - { - $row['meta_title'] = $row['meta_title'].' - '.Configuration::get('PS_SHOP_NAME'); - return Meta::completeMetaTags($row, $row['meta_title']); - } + ((int)Context::getContext()->shop->id ? + ' AND id_shop = '.(int)Context::getContext()->shop->id : ''); + if ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql)) { + $row['meta_title'] = $row['meta_title'].' - '.Configuration::get('PS_SHOP_NAME'); + return Meta::completeMetaTags($row, $row['meta_title']); + } - return Meta::getHomeMetas($id_lang, $page_name); - } + return Meta::getHomeMetas($id_lang, $page_name); + } - /** - * @since 1.5.0 - */ - public static function completeMetaTags($meta_tags, $default_value, Context $context = null) - { - if (!$context) - $context = Context::getContext(); + /** + * @since 1.5.0 + */ + public static function completeMetaTags($meta_tags, $default_value, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } - if (empty($meta_tags['meta_title'])) - $meta_tags['meta_title'] = $default_value.' - '.Configuration::get('PS_SHOP_NAME'); - if (empty($meta_tags['meta_description'])) - $meta_tags['meta_description'] = Configuration::get('PS_META_DESCRIPTION', $context->language->id) ? Configuration::get('PS_META_DESCRIPTION', $context->language->id) : ''; - if (empty($meta_tags['meta_keywords'])) - $meta_tags['meta_keywords'] = Configuration::get('PS_META_KEYWORDS', $context->language->id) ? Configuration::get('PS_META_KEYWORDS', $context->language->id) : ''; - return $meta_tags; - } + if (empty($meta_tags['meta_title'])) { + $meta_tags['meta_title'] = $default_value.' - '.Configuration::get('PS_SHOP_NAME'); + } + if (empty($meta_tags['meta_description'])) { + $meta_tags['meta_description'] = Configuration::get('PS_META_DESCRIPTION', $context->language->id) ? Configuration::get('PS_META_DESCRIPTION', $context->language->id) : ''; + } + if (empty($meta_tags['meta_keywords'])) { + $meta_tags['meta_keywords'] = Configuration::get('PS_META_KEYWORDS', $context->language->id) ? Configuration::get('PS_META_KEYWORDS', $context->language->id) : ''; + } + return $meta_tags; + } } diff --git a/classes/Notification.php b/classes/Notification.php index f39b704f..d7af3e6e 100644 --- a/classes/Notification.php +++ b/classes/Notification.php @@ -26,60 +26,60 @@ class NotificationCore { - public $types; + public $types; - public function __construct() - { - $this->types = array('order', 'customer_message', 'customer'); - } + public function __construct() + { + $this->types = array('order', 'customer_message', 'customer'); + } - /** - * getLastElements return all the notifications (new order, new customer registration, and new customer message) - * Get all the notifications - * - * @return array containing the notifications - */ - public function getLastElements() - { - global $cookie; + /** + * getLastElements return all the notifications (new order, new customer registration, and new customer message) + * Get all the notifications + * + * @return array containing the notifications + */ + public function getLastElements() + { + global $cookie; - $notifications = array(); - $employee_infos = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + $notifications = array(); + $employee_infos = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT id_last_order, id_last_customer_message, id_last_customer FROM `'._DB_PREFIX_.'employee` WHERE `id_employee` = '.(int)$cookie->id_employee); - foreach ($this->types as $type) - $notifications[$type] = Notification::getLastElementsIdsByType($type, $employee_infos['id_last_'.$type]); + foreach ($this->types as $type) { + $notifications[$type] = Notification::getLastElementsIdsByType($type, $employee_infos['id_last_'.$type]); + } - return $notifications; - } + return $notifications; + } - /** - * getLastElementsIdsByType return all the element ids to show (order, customer registration, and customer message) - * Get all the element ids - * - * @param string $type contains the field name of the Employee table - * @param int $id_last_element contains the id of the last seen element - * @return array containing the notifications - */ - public static function getLastElementsIdsByType($type, $id_last_element) - { - switch ($type) - { - case 'order': - $sql = ' + /** + * getLastElementsIdsByType return all the element ids to show (order, customer registration, and customer message) + * Get all the element ids + * + * @param string $type contains the field name of the Employee table + * @param int $id_last_element contains the id of the last seen element + * @return array containing the notifications + */ + public static function getLastElementsIdsByType($type, $id_last_element) + { + switch ($type) { + case 'order': + $sql = ' SELECT SQL_CALC_FOUND_ROWS o.`id_order`, o.`id_customer`, o.`total_paid`, o.`id_currency`, o.`date_upd`, c.`firstname`, c.`lastname` FROM `'._DB_PREFIX_.'orders` as o LEFT JOIN `'._DB_PREFIX_.'customer` as c ON (c.`id_customer` = o.`id_customer`) WHERE `id_order` > '.(int)$id_last_element. - Shop::addSqlRestriction(false, 'o').' + Shop::addSqlRestriction(false, 'o').' ORDER BY `id_order` DESC LIMIT 5'; - break; + break; - case 'customer_message': - $sql = ' + case 'customer_message': + $sql = ' SELECT SQL_CALC_FOUND_ROWS c.`id_customer_message`, ct.`id_customer`, ct.`id_customer_thread`, ct.`email`, c.`date_add` as date_upd FROM `'._DB_PREFIX_.'customer_message` as c LEFT JOIN `'._DB_PREFIX_.'customer_thread` as ct ON (c.`id_customer_thread` = ct.`id_customer_thread`) @@ -88,64 +88,65 @@ class NotificationCore AND ct.id_shop IN ('.implode(', ', Shop::getContextListShopID()).') ORDER BY c.`id_customer_message` DESC LIMIT 5'; - break; - default: - $sql = ' + break; + default: + $sql = ' SELECT SQL_CALC_FOUND_ROWS t.`id_'.bqSQL($type).'`, t.* FROM `'._DB_PREFIX_.bqSQL($type).'` t WHERE t.`deleted` = 0 AND t.`id_'.bqSQL($type).'` > '.(int)$id_last_element. - Shop::addSqlRestriction(false, 't').' + Shop::addSqlRestriction(false, 't').' ORDER BY t.`id_'.bqSQL($type).'` DESC LIMIT 5'; - break; - } + break; + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false); - $total = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT FOUND_ROWS()', false); - $json = array('total' => $total, 'results' => array()); - foreach ($result as $value) - { - $customer_name = ''; - if (isset($value['firstname']) && isset($value['lastname'])) - $customer_name = Tools::safeOutput($value['firstname'].' '.$value['lastname']); - elseif (isset($value['email'])) - $customer_name = Tools::safeOutput($value['email']); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false); + $total = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT FOUND_ROWS()', false); + $json = array('total' => $total, 'results' => array()); + foreach ($result as $value) { + $customer_name = ''; + if (isset($value['firstname']) && isset($value['lastname'])) { + $customer_name = Tools::safeOutput($value['firstname'].' '.$value['lastname']); + } elseif (isset($value['email'])) { + $customer_name = Tools::safeOutput($value['email']); + } - $json['results'][] = array( - 'id_order' => ((!empty($value['id_order'])) ? (int)$value['id_order'] : 0), - 'id_customer' => ((!empty($value['id_customer'])) ? (int)$value['id_customer'] : 0), - 'id_customer_message' => ((!empty($value['id_customer_message'])) ? (int)$value['id_customer_message'] : 0), - 'id_customer_thread' => ((!empty($value['id_customer_thread'])) ? (int)$value['id_customer_thread'] : 0), - 'total_paid' => ((!empty($value['total_paid'])) ? Tools::displayPrice((float)$value['total_paid'], (int)$value['id_currency'], false) : 0), - 'customer_name' => $customer_name, - // x1000 because of moment.js (see: http://momentjs.com/docs/#/parsing/unix-timestamp/) - 'update_date' => isset($value['date_upd']) ? (int)strtotime($value['date_upd']) * 1000 : 0, - ); - } + $json['results'][] = array( + 'id_order' => ((!empty($value['id_order'])) ? (int)$value['id_order'] : 0), + 'id_customer' => ((!empty($value['id_customer'])) ? (int)$value['id_customer'] : 0), + 'id_customer_message' => ((!empty($value['id_customer_message'])) ? (int)$value['id_customer_message'] : 0), + 'id_customer_thread' => ((!empty($value['id_customer_thread'])) ? (int)$value['id_customer_thread'] : 0), + 'total_paid' => ((!empty($value['total_paid'])) ? Tools::displayPrice((float)$value['total_paid'], (int)$value['id_currency'], false) : 0), + 'customer_name' => $customer_name, + // x1000 because of moment.js (see: http://momentjs.com/docs/#/parsing/unix-timestamp/) + 'update_date' => isset($value['date_upd']) ? (int)strtotime($value['date_upd']) * 1000 : 0, + ); + } - return $json; - } + return $json; + } - /** - * updateEmployeeLastElement return 0 if the field doesn't exists in Employee table. - * Updates the last seen element by the employee - * - * @param string $type contains the field name of the Employee table - * @return bool if type exists or not - */ - public function updateEmployeeLastElement($type) - { - global $cookie; + /** + * updateEmployeeLastElement return 0 if the field doesn't exists in Employee table. + * Updates the last seen element by the employee + * + * @param string $type contains the field name of the Employee table + * @return bool if type exists or not + */ + public function updateEmployeeLastElement($type) + { + global $cookie; - if (in_array($type, $this->types)) - // We update the last item viewed - return Db::getInstance()->execute(' + if (in_array($type, $this->types)) { + // We update the last item viewed + return Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'employee` SET `id_last_'.bqSQL($type).'` = ( SELECT IFNULL(MAX(`id_'.$type.'`), 0) FROM `'._DB_PREFIX_.(($type == 'order') ? bqSQL($type).'s' : bqSQL($type)).'` ) WHERE `id_employee` = '.(int)$cookie->id_employee); - return false; - } -} \ No newline at end of file + } + return false; + } +} diff --git a/classes/ObjectModel.php b/classes/ObjectModel.php index 8dafd4c5..2ef59613 100644 --- a/classes/ObjectModel.php +++ b/classes/ObjectModel.php @@ -26,1871 +26,1948 @@ abstract class ObjectModelCore implements Core_Foundation_Database_EntityInterface { - /** - * List of field types - */ - const TYPE_INT = 1; - const TYPE_BOOL = 2; - const TYPE_STRING = 3; - const TYPE_FLOAT = 4; - const TYPE_DATE = 5; - const TYPE_HTML = 6; - const TYPE_NOTHING = 7; - const TYPE_SQL = 8; - - /** - * List of data to format - */ - const FORMAT_COMMON = 1; - const FORMAT_LANG = 2; - const FORMAT_SHOP = 3; - - /** - * List of association types - */ - const HAS_ONE = 1; - const HAS_MANY = 2; - - /** @var int Object ID */ - public $id; - - /** @var int Language ID */ - protected $id_lang = null; - - /** @var int Shop ID */ - protected $id_shop = null; - - /** @var array|null List of shop IDs */ - public $id_shop_list = null; - - /** @var bool */ - protected $get_shop_from_context = true; - - /** @var array|null Holds required fields for each ObjectModel class */ - protected static $fieldsRequiredDatabase = null; - - /** - * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. - * @var string - */ - protected $table; - - /** - * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. - * @var string - */ - protected $identifier; - - /** - * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. - * @var array - */ - protected $fieldsRequired = array(); - - /** - * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. - * @var array - */ - protected $fieldsSize = array(); - - /** - * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. - * @var array - */ - protected $fieldsValidate = array(); - - /** - * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. - * @var array - */ - protected $fieldsRequiredLang = array(); - - /** - * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. - * @var array - */ - protected $fieldsSizeLang = array(); - - /** - * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. - * @var array - */ - protected $fieldsValidateLang = array(); - - /** - * @deprecated 1.5.0.1 - * @var array - */ - protected $tables = array(); - - /** @var array Tables */ - protected $webserviceParameters = array(); - - /** @var string Path to image directory. Used for image deletion. */ - protected $image_dir = null; - - /** @var String file type of image files. */ - protected $image_format = 'jpg'; - - /** - * @var array Contains object definition - * @since 1.5.0.1 - */ - public static $definition = array(); - - /** - * Holds compiled definitions of each ObjectModel class. - * Values are assigned during object initialization. - * - * @var array - */ - protected static $loaded_classes = array(); - - /** @var array Contains current object definition. */ - protected $def; - - /** @var array|null List of specific fields to update (all fields if null). */ - protected $update_fields = null; - - /** @var Db An instance of the db in order to avoid calling Db::getInstance() thousands of times. */ - protected static $db = false; - - /** @var bool Enables to define an ID before adding object. */ - public $force_id = false; - - /** - * @var bool If true, objects are cached in memory. - */ - protected static $cache_objects = true; - - public static function getRepositoryClassName() - { - return null; - } - - /** - * Returns object validation rules (fields validity) - * - * @param string $class Child class name for static use (optional) - * - * @return array Validation rules (fields validity) - */ - public static function getValidationRules($class = __CLASS__) - { - $object = new $class(); - return array( - 'required' => $object->fieldsRequired, - 'size' => $object->fieldsSize, - 'validate' => $object->fieldsValidate, - 'requiredLang' => $object->fieldsRequiredLang, - 'sizeLang' => $object->fieldsSizeLang, - 'validateLang' => $object->fieldsValidateLang, - ); - } - - /** - * Builds the object - * - * @param int|null $id If specified, loads and existing object from DB (optional). - * @param int|null $id_lang Required if object is multilingual (optional). - * @param int|null $id_shop ID shop for objects with multishop tables. - * - * @throws PrestaShopDatabaseException - * @throws PrestaShopException - */ - public function __construct($id = null, $id_lang = null, $id_shop = null) - { - $class_name = get_class($this); - if (!isset(ObjectModel::$loaded_classes[$class_name])) - { - $this->def = ObjectModel::getDefinition($class_name); - $this->setDefinitionRetrocompatibility(); - if (!Validate::isTableOrIdentifier($this->def['primary']) || !Validate::isTableOrIdentifier($this->def['table'])) - throw new PrestaShopException('Identifier or table format not valid for class '.$class_name); - - ObjectModel::$loaded_classes[$class_name] = get_object_vars($this); - } - else - foreach (ObjectModel::$loaded_classes[$class_name] as $key => $value) - $this->{$key} = $value; - - if ($id_lang !== null) - $this->id_lang = (Language::getLanguage($id_lang) !== false) ? $id_lang : Configuration::get('PS_LANG_DEFAULT'); - - if ($id_shop && $this->isMultishop()) - { - $this->id_shop = (int)$id_shop; - $this->get_shop_from_context = false; - } - - if ($this->isMultishop() && !$this->id_shop) - $this->id_shop = Context::getContext()->shop->id; - - if ($id) - { - $entity_mapper = Adapter_ServiceLocator::get("Adapter_EntityMapper"); - $entity_mapper->load($id, $id_lang, $this, $this->def, $this->id_shop, self::$cache_objects); - } - } - - /** - * Prepare fields for ObjectModel class (add, update) - * All fields are verified (pSQL, intval, ...) - * - * @return array All object fields - * @throws PrestaShopException - */ - public function getFields() - { - $this->validateFields(); - $fields = $this->formatFields(self::FORMAT_COMMON); - - // For retro compatibility - if (Shop::isTableAssociated($this->def['table'])) - $fields = array_merge($fields, $this->getFieldsShop()); - - // Ensure that we get something to insert - if (!$fields && isset($this->id) && Validate::isUnsignedId($this->id)) - $fields[$this->def['primary']] = $this->id; - - return $fields; - } - - /** - * Prepare fields for multishop - * Fields are not validated here, we consider they are already validated in getFields() method, - * this is not the best solution but this is the only one possible for retro compatibility. - * - * @since 1.5.0.1 - * @return array All object fields - */ - public function getFieldsShop() - { - $fields = $this->formatFields(self::FORMAT_SHOP); - if (!$fields && isset($this->id) && Validate::isUnsignedId($this->id)) - $fields[$this->def['primary']] = $this->id; - - return $fields; - } - - /** - * Prepare multilang fields - * - * @since 1.5.0.1 - * - * @return array - * @throws PrestaShopException - */ - public function getFieldsLang() - { - // Backward compatibility - if (method_exists($this, 'getTranslationsFieldsChild')) - return $this->getTranslationsFieldsChild(); - - $this->validateFieldsLang(); - $is_lang_multishop = $this->isLangMultishop(); - - $fields = array(); - if ($this->id_lang === null) - foreach (Language::getIDs(false) as $id_lang) - { - $fields[$id_lang] = $this->formatFields(self::FORMAT_LANG, $id_lang); - $fields[$id_lang]['id_lang'] = $id_lang; - if ($this->id_shop && $is_lang_multishop) - $fields[$id_lang]['id_shop'] = (int)$this->id_shop; - } - else - { - $fields = array($this->id_lang => $this->formatFields(self::FORMAT_LANG, $this->id_lang)); - $fields[$this->id_lang]['id_lang'] = $this->id_lang; - if ($this->id_shop && $is_lang_multishop) - $fields[$this->id_lang]['id_shop'] = (int)$this->id_shop; - } - - return $fields; - } - - /** - * Formats values of each fields. - * - * @since 1.5.0.1 - * @param int $type FORMAT_COMMON or FORMAT_LANG or FORMAT_SHOP - * @param int $id_lang If this parameter is given, only take lang fields - * - * @return array - */ - protected function formatFields($type, $id_lang = null) - { - $fields = array(); - - // Set primary key in fields - if (isset($this->id)) - $fields[$this->def['primary']] = $this->id; - - foreach ($this->def['fields'] as $field => $data) - { - // Only get fields we need for the type - // E.g. if only lang fields are filtered, ignore fields without lang => true - if (($type == self::FORMAT_LANG && empty($data['lang'])) - || ($type == self::FORMAT_SHOP && empty($data['shop'])) - || ($type == self::FORMAT_COMMON && ((!empty($data['shop']) && $data['shop'] != 'both') || !empty($data['lang'])))) - continue; - - if (is_array($this->update_fields)) - if ((!empty($data['lang']) || (!empty($data['shop']) && $data['shop'] != 'both')) && (empty($this->update_fields[$field]) || ($type == self::FORMAT_LANG && empty($this->update_fields[$field][$id_lang])))) - continue; - - // Get field value, if value is multilang and field is empty, use value from default lang - $value = $this->$field; - if ($type == self::FORMAT_LANG && $id_lang && is_array($value)) - { - if (!empty($value[$id_lang])) - $value = $value[$id_lang]; - elseif (!empty($data['required'])) - $value = $value[Configuration::get('PS_LANG_DEFAULT')]; - else - $value = ''; - } - - $purify = (isset($data['validate']) && Tools::strtolower($data['validate']) == 'iscleanhtml') ? true : false; - // Format field value - $fields[$field] = ObjectModel::formatValue($value, $data['type'], false, $purify, !empty($data['allow_null'])); - } - - return $fields; - } - - /** - * Formats a value - * - * @param mixed $value - * @param int $type - * @param bool $with_quotes - * @param bool $purify - * @param bool $allow_null - * @return mixed - */ - public static function formatValue($value, $type, $with_quotes = false, $purify = true, $allow_null = false) - { - if ($allow_null && $value === null) - return array('type' => 'sql', 'value' => 'NULL'); - - switch ($type) - { - case self::TYPE_INT: - return (int)$value; - - case self::TYPE_BOOL: - return (int)$value; - - case self::TYPE_FLOAT: - return (float)str_replace(',', '.', $value); - - case self::TYPE_DATE: - if (!$value) - return '0000-00-00'; - - if ($with_quotes) - return '\''.pSQL($value).'\''; - return pSQL($value); - - case self::TYPE_HTML: - if ($purify) - $value = Tools::purifyHTML($value); - if ($with_quotes) - return '\''.pSQL($value, true).'\''; - return pSQL($value, true); - - case self::TYPE_SQL: - if ($with_quotes) - return '\''.pSQL($value, true).'\''; - return pSQL($value, true); - - case self::TYPE_NOTHING: - return $value; - - case self::TYPE_STRING: - default : - if ($with_quotes) - return '\''.pSQL($value).'\''; - return pSQL($value); - } - } - - /** - * Saves current object to database (add or update) - * - * @param bool $null_values - * @param bool $auto_date - * - * @return bool Insertion result - * @throws PrestaShopException - */ - public function save($null_values = false, $auto_date = true) - { - return (int)$this->id > 0 ? $this->update($null_values) : $this->add($auto_date, $null_values); - } - - /** - * Adds current object to the database - * - * @param bool $auto_date - * @param bool $null_values - * - * @return bool Insertion result - * @throws PrestaShopDatabaseException - * @throws PrestaShopException - */ - public function add($auto_date = true, $null_values = false) - { - if (isset($this->id) && !$this->force_id) - unset($this->id); - - // @hook actionObject*AddBefore - Hook::exec('actionObjectAddBefore', array('object' => $this)); - Hook::exec('actionObject'.get_class($this).'AddBefore', array('object' => $this)); - - // Automatically fill dates - if ($auto_date && property_exists($this, 'date_add')) - $this->date_add = date('Y-m-d H:i:s'); - if ($auto_date && property_exists($this, 'date_upd')) - $this->date_upd = date('Y-m-d H:i:s'); - - if (Shop::isTableAssociated($this->def['table'])) - { - $id_shop_list = Shop::getContextListShopID(); - if (count($this->id_shop_list) > 0) - $id_shop_list = $this->id_shop_list; - } - - // Database insertion - if (Shop::checkIdShopDefault($this->def['table'])) - $this->id_shop_default = (in_array(Configuration::get('PS_SHOP_DEFAULT'), $id_shop_list) == true) ? Configuration::get('PS_SHOP_DEFAULT') : min($id_shop_list); - if (!$result = Db::getInstance()->insert($this->def['table'], $this->getFields(), $null_values)) - return false; - - // Get object id in database - $this->id = Db::getInstance()->Insert_ID(); - - // Database insertion for multishop fields related to the object - if (Shop::isTableAssociated($this->def['table'])) - { - $fields = $this->getFieldsShop(); - $fields[$this->def['primary']] = (int)$this->id; - - foreach ($id_shop_list as $id_shop) - { - $fields['id_shop'] = (int)$id_shop; - $result &= Db::getInstance()->insert($this->def['table'].'_shop', $fields, $null_values); - } - } - - if (!$result) - return false; - - // Database insertion for multilingual fields related to the object - if (!empty($this->def['multilang'])) - { - $fields = $this->getFieldsLang(); - if ($fields && is_array($fields)) - { - $shops = Shop::getCompleteListOfShopsID(); - $asso = Shop::getAssoTable($this->def['table'].'_lang'); - foreach ($fields as $field) - { - foreach (array_keys($field) as $key) - if (!Validate::isTableOrIdentifier($key)) - throw new PrestaShopException('key '.$key.' is not table or identifier'); - $field[$this->def['primary']] = (int)$this->id; - - if ($asso !== false && $asso['type'] == 'fk_shop') - { - foreach ($shops as $id_shop) - { - $field['id_shop'] = (int)$id_shop; - $result &= Db::getInstance()->insert($this->def['table'].'_lang', $field); - } - } - else - $result &= Db::getInstance()->insert($this->def['table'].'_lang', $field); - } - } - } - - // @hook actionObject*AddAfter - Hook::exec('actionObjectAddAfter', array('object' => $this)); - Hook::exec('actionObject'.get_class($this).'AddAfter', array('object' => $this)); - - return $result; - } - - /** - * Takes current object ID, gets its values from database, - * saves them in a new row and loads newly saved values as a new object. - * - * @return ObjectModel|false - * @throws PrestaShopDatabaseException - */ - public function duplicateObject() - { - $definition = ObjectModel::getDefinition($this); - - $res = Db::getInstance()->getRow(' + /** + * List of field types + */ + const TYPE_INT = 1; + const TYPE_BOOL = 2; + const TYPE_STRING = 3; + const TYPE_FLOAT = 4; + const TYPE_DATE = 5; + const TYPE_HTML = 6; + const TYPE_NOTHING = 7; + const TYPE_SQL = 8; + + /** + * List of data to format + */ + const FORMAT_COMMON = 1; + const FORMAT_LANG = 2; + const FORMAT_SHOP = 3; + + /** + * List of association types + */ + const HAS_ONE = 1; + const HAS_MANY = 2; + + /** @var int Object ID */ + public $id; + + /** @var int Language ID */ + protected $id_lang = null; + + /** @var int Shop ID */ + protected $id_shop = null; + + /** @var array|null List of shop IDs */ + public $id_shop_list = null; + + /** @var bool */ + protected $get_shop_from_context = true; + + /** @var array|null Holds required fields for each ObjectModel class */ + protected static $fieldsRequiredDatabase = null; + + /** + * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. + * @var string + */ + protected $table; + + /** + * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. + * @var string + */ + protected $identifier; + + /** + * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. + * @var array + */ + protected $fieldsRequired = array(); + + /** + * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. + * @var array + */ + protected $fieldsSize = array(); + + /** + * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. + * @var array + */ + protected $fieldsValidate = array(); + + /** + * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. + * @var array + */ + protected $fieldsRequiredLang = array(); + + /** + * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. + * @var array + */ + protected $fieldsSizeLang = array(); + + /** + * @deprecated 1.5.0.1 Define property using $definition['table'] property instead. + * @var array + */ + protected $fieldsValidateLang = array(); + + /** + * @deprecated 1.5.0.1 + * @var array + */ + protected $tables = array(); + + /** @var array Tables */ + protected $webserviceParameters = array(); + + /** @var string Path to image directory. Used for image deletion. */ + protected $image_dir = null; + + /** @var String file type of image files. */ + protected $image_format = 'jpg'; + + /** + * @var array Contains object definition + * @since 1.5.0.1 + */ + public static $definition = array(); + + /** + * Holds compiled definitions of each ObjectModel class. + * Values are assigned during object initialization. + * + * @var array + */ + protected static $loaded_classes = array(); + + /** @var array Contains current object definition. */ + protected $def; + + /** @var array|null List of specific fields to update (all fields if null). */ + protected $update_fields = null; + + /** @var Db An instance of the db in order to avoid calling Db::getInstance() thousands of times. */ + protected static $db = false; + + /** @var bool Enables to define an ID before adding object. */ + public $force_id = false; + + /** + * @var bool If true, objects are cached in memory. + */ + protected static $cache_objects = true; + + public static function getRepositoryClassName() + { + return null; + } + + /** + * Returns object validation rules (fields validity) + * + * @param string $class Child class name for static use (optional) + * + * @return array Validation rules (fields validity) + */ + public static function getValidationRules($class = __CLASS__) + { + $object = new $class(); + return array( + 'required' => $object->fieldsRequired, + 'size' => $object->fieldsSize, + 'validate' => $object->fieldsValidate, + 'requiredLang' => $object->fieldsRequiredLang, + 'sizeLang' => $object->fieldsSizeLang, + 'validateLang' => $object->fieldsValidateLang, + ); + } + + /** + * Builds the object + * + * @param int|null $id If specified, loads and existing object from DB (optional). + * @param int|null $id_lang Required if object is multilingual (optional). + * @param int|null $id_shop ID shop for objects with multishop tables. + * + * @throws PrestaShopDatabaseException + * @throws PrestaShopException + */ + public function __construct($id = null, $id_lang = null, $id_shop = null) + { + $class_name = get_class($this); + if (!isset(ObjectModel::$loaded_classes[$class_name])) { + $this->def = ObjectModel::getDefinition($class_name); + $this->setDefinitionRetrocompatibility(); + if (!Validate::isTableOrIdentifier($this->def['primary']) || !Validate::isTableOrIdentifier($this->def['table'])) { + throw new PrestaShopException('Identifier or table format not valid for class '.$class_name); + } + + ObjectModel::$loaded_classes[$class_name] = get_object_vars($this); + } else { + foreach (ObjectModel::$loaded_classes[$class_name] as $key => $value) { + $this->{$key} = $value; + } + } + + if ($id_lang !== null) { + $this->id_lang = (Language::getLanguage($id_lang) !== false) ? $id_lang : Configuration::get('PS_LANG_DEFAULT'); + } + + if ($id_shop && $this->isMultishop()) { + $this->id_shop = (int)$id_shop; + $this->get_shop_from_context = false; + } + + if ($this->isMultishop() && !$this->id_shop) { + $this->id_shop = Context::getContext()->shop->id; + } + + if ($id) { + $entity_mapper = Adapter_ServiceLocator::get("Adapter_EntityMapper"); + $entity_mapper->load($id, $id_lang, $this, $this->def, $this->id_shop, self::$cache_objects); + } + } + + /** + * Prepare fields for ObjectModel class (add, update) + * All fields are verified (pSQL, intval, ...) + * + * @return array All object fields + * @throws PrestaShopException + */ + public function getFields() + { + $this->validateFields(); + $fields = $this->formatFields(self::FORMAT_COMMON); + + // For retro compatibility + if (Shop::isTableAssociated($this->def['table'])) { + $fields = array_merge($fields, $this->getFieldsShop()); + } + + // Ensure that we get something to insert + if (!$fields && isset($this->id) && Validate::isUnsignedId($this->id)) { + $fields[$this->def['primary']] = $this->id; + } + + return $fields; + } + + /** + * Prepare fields for multishop + * Fields are not validated here, we consider they are already validated in getFields() method, + * this is not the best solution but this is the only one possible for retro compatibility. + * + * @since 1.5.0.1 + * @return array All object fields + */ + public function getFieldsShop() + { + $fields = $this->formatFields(self::FORMAT_SHOP); + if (!$fields && isset($this->id) && Validate::isUnsignedId($this->id)) { + $fields[$this->def['primary']] = $this->id; + } + + return $fields; + } + + /** + * Prepare multilang fields + * + * @since 1.5.0.1 + * + * @return array + * @throws PrestaShopException + */ + public function getFieldsLang() + { + // Backward compatibility + if (method_exists($this, 'getTranslationsFieldsChild')) { + return $this->getTranslationsFieldsChild(); + } + + $this->validateFieldsLang(); + $is_lang_multishop = $this->isLangMultishop(); + + $fields = array(); + if ($this->id_lang === null) { + foreach (Language::getIDs(false) as $id_lang) { + $fields[$id_lang] = $this->formatFields(self::FORMAT_LANG, $id_lang); + $fields[$id_lang]['id_lang'] = $id_lang; + if ($this->id_shop && $is_lang_multishop) { + $fields[$id_lang]['id_shop'] = (int)$this->id_shop; + } + } + } else { + $fields = array($this->id_lang => $this->formatFields(self::FORMAT_LANG, $this->id_lang)); + $fields[$this->id_lang]['id_lang'] = $this->id_lang; + if ($this->id_shop && $is_lang_multishop) { + $fields[$this->id_lang]['id_shop'] = (int)$this->id_shop; + } + } + + return $fields; + } + + /** + * Formats values of each fields. + * + * @since 1.5.0.1 + * @param int $type FORMAT_COMMON or FORMAT_LANG or FORMAT_SHOP + * @param int $id_lang If this parameter is given, only take lang fields + * + * @return array + */ + protected function formatFields($type, $id_lang = null) + { + $fields = array(); + + // Set primary key in fields + if (isset($this->id)) { + $fields[$this->def['primary']] = $this->id; + } + + foreach ($this->def['fields'] as $field => $data) { + // Only get fields we need for the type + // E.g. if only lang fields are filtered, ignore fields without lang => true + if (($type == self::FORMAT_LANG && empty($data['lang'])) + || ($type == self::FORMAT_SHOP && empty($data['shop'])) + || ($type == self::FORMAT_COMMON && ((!empty($data['shop']) && $data['shop'] != 'both') || !empty($data['lang'])))) { + continue; + } + + if (is_array($this->update_fields)) { + if ((!empty($data['lang']) || (!empty($data['shop']) && $data['shop'] != 'both')) && (empty($this->update_fields[$field]) || ($type == self::FORMAT_LANG && empty($this->update_fields[$field][$id_lang])))) { + continue; + } + } + + // Get field value, if value is multilang and field is empty, use value from default lang + $value = $this->$field; + if ($type == self::FORMAT_LANG && $id_lang && is_array($value)) { + if (!empty($value[$id_lang])) { + $value = $value[$id_lang]; + } elseif (!empty($data['required'])) { + $value = $value[Configuration::get('PS_LANG_DEFAULT')]; + } else { + $value = ''; + } + } + + $purify = (isset($data['validate']) && Tools::strtolower($data['validate']) == 'iscleanhtml') ? true : false; + // Format field value + $fields[$field] = ObjectModel::formatValue($value, $data['type'], false, $purify, !empty($data['allow_null'])); + } + + return $fields; + } + + /** + * Formats a value + * + * @param mixed $value + * @param int $type + * @param bool $with_quotes + * @param bool $purify + * @param bool $allow_null + * @return mixed + */ + public static function formatValue($value, $type, $with_quotes = false, $purify = true, $allow_null = false) + { + if ($allow_null && $value === null) { + return array('type' => 'sql', 'value' => 'NULL'); + } + + switch ($type) { + case self::TYPE_INT: + return (int)$value; + + case self::TYPE_BOOL: + return (int)$value; + + case self::TYPE_FLOAT: + return (float)str_replace(',', '.', $value); + + case self::TYPE_DATE: + if (!$value) { + return '0000-00-00'; + } + + if ($with_quotes) { + return '\''.pSQL($value).'\''; + } + return pSQL($value); + + case self::TYPE_HTML: + if ($purify) { + $value = Tools::purifyHTML($value); + } + if ($with_quotes) { + return '\''.pSQL($value, true).'\''; + } + return pSQL($value, true); + + case self::TYPE_SQL: + if ($with_quotes) { + return '\''.pSQL($value, true).'\''; + } + return pSQL($value, true); + + case self::TYPE_NOTHING: + return $value; + + case self::TYPE_STRING: + default : + if ($with_quotes) { + return '\''.pSQL($value).'\''; + } + return pSQL($value); + } + } + + /** + * Saves current object to database (add or update) + * + * @param bool $null_values + * @param bool $auto_date + * + * @return bool Insertion result + * @throws PrestaShopException + */ + public function save($null_values = false, $auto_date = true) + { + return (int)$this->id > 0 ? $this->update($null_values) : $this->add($auto_date, $null_values); + } + + /** + * Adds current object to the database + * + * @param bool $auto_date + * @param bool $null_values + * + * @return bool Insertion result + * @throws PrestaShopDatabaseException + * @throws PrestaShopException + */ + public function add($auto_date = true, $null_values = false) + { + if (isset($this->id) && !$this->force_id) { + unset($this->id); + } + + // @hook actionObject*AddBefore + Hook::exec('actionObjectAddBefore', array('object' => $this)); + Hook::exec('actionObject'.get_class($this).'AddBefore', array('object' => $this)); + + // Automatically fill dates + if ($auto_date && property_exists($this, 'date_add')) { + $this->date_add = date('Y-m-d H:i:s'); + } + if ($auto_date && property_exists($this, 'date_upd')) { + $this->date_upd = date('Y-m-d H:i:s'); + } + + if (Shop::isTableAssociated($this->def['table'])) { + $id_shop_list = Shop::getContextListShopID(); + if (count($this->id_shop_list) > 0) { + $id_shop_list = $this->id_shop_list; + } + } + + // Database insertion + if (Shop::checkIdShopDefault($this->def['table'])) { + $this->id_shop_default = (in_array(Configuration::get('PS_SHOP_DEFAULT'), $id_shop_list) == true) ? Configuration::get('PS_SHOP_DEFAULT') : min($id_shop_list); + } + if (!$result = Db::getInstance()->insert($this->def['table'], $this->getFields(), $null_values)) { + return false; + } + + // Get object id in database + $this->id = Db::getInstance()->Insert_ID(); + + // Database insertion for multishop fields related to the object + if (Shop::isTableAssociated($this->def['table'])) { + $fields = $this->getFieldsShop(); + $fields[$this->def['primary']] = (int)$this->id; + + foreach ($id_shop_list as $id_shop) { + $fields['id_shop'] = (int)$id_shop; + $result &= Db::getInstance()->insert($this->def['table'].'_shop', $fields, $null_values); + } + } + + if (!$result) { + return false; + } + + // Database insertion for multilingual fields related to the object + if (!empty($this->def['multilang'])) { + $fields = $this->getFieldsLang(); + if ($fields && is_array($fields)) { + $shops = Shop::getCompleteListOfShopsID(); + $asso = Shop::getAssoTable($this->def['table'].'_lang'); + foreach ($fields as $field) { + foreach (array_keys($field) as $key) { + if (!Validate::isTableOrIdentifier($key)) { + throw new PrestaShopException('key '.$key.' is not table or identifier'); + } + } + $field[$this->def['primary']] = (int)$this->id; + + if ($asso !== false && $asso['type'] == 'fk_shop') { + foreach ($shops as $id_shop) { + $field['id_shop'] = (int)$id_shop; + $result &= Db::getInstance()->insert($this->def['table'].'_lang', $field); + } + } else { + $result &= Db::getInstance()->insert($this->def['table'].'_lang', $field); + } + } + } + } + + // @hook actionObject*AddAfter + Hook::exec('actionObjectAddAfter', array('object' => $this)); + Hook::exec('actionObject'.get_class($this).'AddAfter', array('object' => $this)); + + return $result; + } + + /** + * Takes current object ID, gets its values from database, + * saves them in a new row and loads newly saved values as a new object. + * + * @return ObjectModel|false + * @throws PrestaShopDatabaseException + */ + public function duplicateObject() + { + $definition = ObjectModel::getDefinition($this); + + $res = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.bqSQL($definition['table']).'` WHERE `'.bqSQL($definition['primary']).'` = '.(int)$this->id - ); - if (!$res) - return false; + ); + if (!$res) { + return false; + } - unset($res[$definition['primary']]); - foreach ($res as $field => &$value) - if (isset($definition['fields'][$field])) - $value = ObjectModel::formatValue($value, $definition['fields'][$field]['type'], false, true, - !empty($definition['fields'][$field]['allow_null'])); + unset($res[$definition['primary']]); + foreach ($res as $field => &$value) { + if (isset($definition['fields'][$field])) { + $value = ObjectModel::formatValue($value, $definition['fields'][$field]['type'], false, true, + !empty($definition['fields'][$field]['allow_null'])); + } + } - if (!Db::getInstance()->insert($definition['table'], $res)) - return false; + if (!Db::getInstance()->insert($definition['table'], $res)) { + return false; + } - $object_id = Db::getInstance()->Insert_ID(); + $object_id = Db::getInstance()->Insert_ID(); - if (isset($definition['multilang']) && $definition['multilang']) - { - $result = Db::getInstance()->executeS(' + if (isset($definition['multilang']) && $definition['multilang']) { + $result = Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.bqSQL($definition['table']).'_lang` WHERE `'.bqSQL($definition['primary']).'` = '.(int)$this->id); - if (!$result) - return false; - - foreach ($result as &$row) - foreach ($row as $field => &$value) - if (isset($definition['fields'][$field])) - $value = ObjectModel::formatValue($value, $definition['fields'][$field]['type'], false, true, - !empty($definition['fields'][$field]['allow_null'])); - - // Keep $row2, you cannot use $row because there is an unexplicated conflict with the previous usage of this variable - foreach ($result as $row2) - { - $row2[$definition['primary']] = (int)$object_id; - if (!Db::getInstance()->insert($definition['table'].'_lang', $row2)) - return false; - } - } - - /** @var ObjectModel $object_duplicated */ - $object_duplicated = new $definition['classname']((int)$object_id); - $object_duplicated->duplicateShops((int)$this->id); - - return $object_duplicated; - } - - /** - * Updates the current object in the database - * - * @param bool $null_values - * - * @return bool - * @throws PrestaShopDatabaseException - * @throws PrestaShopException - */ - public function update($null_values = false) - { - // @hook actionObject*UpdateBefore - Hook::exec('actionObjectUpdateBefore', array('object' => $this)); - Hook::exec('actionObject'.get_class($this).'UpdateBefore', array('object' => $this)); - - $this->clearCache(); - - // Automatically fill dates - if (array_key_exists('date_upd', $this)) - { - $this->date_upd = date('Y-m-d H:i:s'); - if (isset($this->update_fields) && is_array($this->update_fields) && count($this->update_fields)) - $this->update_fields['date_upd'] = true; - } - - // Automatically fill dates - if (array_key_exists('date_add', $this) && $this->date_add == null) - { - $this->date_add = date('Y-m-d H:i:s'); - if (isset($this->update_fields) && is_array($this->update_fields) && count($this->update_fields)) - $this->update_fields['date_add'] = true; - } - - $id_shop_list = Shop::getContextListShopID(); - if (count($this->id_shop_list) > 0) - $id_shop_list = $this->id_shop_list; - - if (Shop::checkIdShopDefault($this->def['table']) && !$this->id_shop_default) - $this->id_shop_default = (in_array(Configuration::get('PS_SHOP_DEFAULT'), $id_shop_list) == true) ? Configuration::get('PS_SHOP_DEFAULT') : min($id_shop_list); - // Database update - if (!$result = Db::getInstance()->update($this->def['table'], $this->getFields(), '`'.pSQL($this->def['primary']).'` = '.(int)$this->id, 0, $null_values)) - return false; - - // Database insertion for multishop fields related to the object - if (Shop::isTableAssociated($this->def['table'])) - { - $fields = $this->getFieldsShop(); - $fields[$this->def['primary']] = (int)$this->id; - if (is_array($this->update_fields)) - { - $update_fields = $this->update_fields; - $this->update_fields = null; - $all_fields = $this->getFieldsShop(); - $all_fields[$this->def['primary']] = (int)$this->id; - $this->update_fields = $update_fields; - } - else - $all_fields = $fields; - - foreach ($id_shop_list as $id_shop) - { - $fields['id_shop'] = (int)$id_shop; - $all_fields['id_shop'] = (int)$id_shop; - $where = $this->def['primary'].' = '.(int)$this->id.' AND id_shop = '.(int)$id_shop; - - // A little explanation of what we do here : we want to create multishop entry when update is called, but - // only if we are in a shop context (if we are in all context, we just want to update entries that alread exists) - $shop_exists = Db::getInstance()->getValue('SELECT '.$this->def['primary'].' FROM '._DB_PREFIX_.$this->def['table'].'_shop WHERE '.$where); - if ($shop_exists) - $result &= Db::getInstance()->update($this->def['table'].'_shop', $fields, $where, 0, $null_values); - elseif (Shop::getContext() == Shop::CONTEXT_SHOP) - $result &= Db::getInstance()->insert($this->def['table'].'_shop', $all_fields, $null_values); - } - } - - // Database update for multilingual fields related to the object - if (isset($this->def['multilang']) && $this->def['multilang']) - { - $fields = $this->getFieldsLang(); - if (is_array($fields)) - { - foreach ($fields as $field) - { - foreach (array_keys($field) as $key) - if (!Validate::isTableOrIdentifier($key)) - throw new PrestaShopException('key '.$key.' is not a valid table or identifier'); - - // If this table is linked to multishop system, update / insert for all shops from context - if ($this->isLangMultishop()) - { - $id_shop_list = Shop::getContextListShopID(); - if (count($this->id_shop_list) > 0) - $id_shop_list = $this->id_shop_list; - foreach ($id_shop_list as $id_shop) - { - $field['id_shop'] = (int)$id_shop; - $where = pSQL($this->def['primary']).' = '.(int)$this->id - .' AND id_lang = '.(int)$field['id_lang'] - .' AND id_shop = '.(int)$id_shop; - - if (Db::getInstance()->getValue('SELECT COUNT(*) FROM '.pSQL(_DB_PREFIX_.$this->def['table']).'_lang WHERE '.$where)) - $result &= Db::getInstance()->update($this->def['table'].'_lang', $field, $where); - else - $result &= Db::getInstance()->insert($this->def['table'].'_lang', $field); - } - } - // If this table is not linked to multishop system ... - else - { - $where = pSQL($this->def['primary']).' = '.(int)$this->id - .' AND id_lang = '.(int)$field['id_lang']; - if (Db::getInstance()->getValue('SELECT COUNT(*) FROM '.pSQL(_DB_PREFIX_.$this->def['table']).'_lang WHERE '.$where)) - $result &= Db::getInstance()->update($this->def['table'].'_lang', $field, $where); - else - $result &= Db::getInstance()->insert($this->def['table'].'_lang', $field, $null_values); - } - } - } - } - - // @hook actionObject*UpdateAfter - Hook::exec('actionObjectUpdateAfter', array('object' => $this)); - Hook::exec('actionObject'.get_class($this).'UpdateAfter', array('object' => $this)); - - return $result; - } - - /** - * Deletes current object from database - * - * @return bool True if delete was successful - * @throws PrestaShopException - */ - public function delete() - { - // @hook actionObject*DeleteBefore - Hook::exec('actionObjectDeleteBefore', array('object' => $this)); - Hook::exec('actionObject'.get_class($this).'DeleteBefore', array('object' => $this)); - - $this->clearCache(); - $result = true; - // Remove association to multishop table - if (Shop::isTableAssociated($this->def['table'])) - { - $id_shop_list = Shop::getContextListShopID(); - if (count($this->id_shop_list)) - $id_shop_list = $this->id_shop_list; - - $result &= Db::getInstance()->delete($this->def['table'].'_shop', '`'.$this->def['primary'].'`='.(int)$this->id.' AND id_shop IN ('.implode(', ', $id_shop_list).')'); - } - - // Database deletion - $has_multishop_entries = $this->hasMultishopEntries(); - if ($result && !$has_multishop_entries) - $result &= Db::getInstance()->delete($this->def['table'], '`'.bqSQL($this->def['primary']).'` = '.(int)$this->id); - - if (!$result) - return false; - - // Database deletion for multilingual fields related to the object - if (!empty($this->def['multilang']) && !$has_multishop_entries) - $result &= Db::getInstance()->delete($this->def['table'].'_lang', '`'.bqSQL($this->def['primary']).'` = '.(int)$this->id); - - // @hook actionObject*DeleteAfter - Hook::exec('actionObjectDeleteAfter', array('object' => $this)); - Hook::exec('actionObject'.get_class($this).'DeleteAfter', array('object' => $this)); - - return $result; - } - - /** - * Deletes multiple objects from the database at once - * - * @param array $ids Array of objects IDs. - * - * @return bool - */ - public function deleteSelection($ids) - { - $result = true; - foreach ($ids as $id) - { - $this->id = (int)$id; - $result = $result && $this->delete(); - } - - return $result; - } - - /** - * Toggles object status in database - * - * @return bool Update result - * @throws PrestaShopException - */ - public function toggleStatus() - { - // Object must have a variable called 'active' - if (!array_key_exists('active', $this)) - throw new PrestaShopException('property "active" is missing in object '.get_class($this)); - - // Update only active field - $this->setFieldsToUpdate(array('active' => true)); - - // Update active status on object - $this->active = !(int)$this->active; - - // Change status to active/inactive - return $this->update(false); - } - - /** - * @deprecated 1.5.0.1 (use getFieldsLang()) - * @param array $fields_array - * - * @return array - * @throws PrestaShopException - */ - protected function getTranslationsFields($fields_array) - { - $fields = array(); - - if ($this->id_lang == null) - foreach (Language::getIDs(false) as $id_lang) - $this->makeTranslationFields($fields, $fields_array, $id_lang); - else - $this->makeTranslationFields($fields, $fields_array, $this->id_lang); - - return $fields; - } - - /** - * @deprecated 1.5.0.1 - * @param array $fields - * @param array $fields_array - * @param int $id_language - * - * @throws PrestaShopException - */ - protected function makeTranslationFields(&$fields, &$fields_array, $id_language) - { - $fields[$id_language]['id_lang'] = $id_language; - $fields[$id_language][$this->def['primary']] = (int)$this->id; - if ($this->id_shop && $this->isLangMultishop()) - $fields[$id_language]['id_shop'] = (int)$this->id_shop; - foreach ($fields_array as $k => $field) - { - $html = false; - $field_name = $field; - if (is_array($field)) - { - $field_name = $k; - $html = (isset($field['html'])) ? $field['html'] : false; - } - - /* Check fields validity */ - if (!Validate::isTableOrIdentifier($field_name)) - throw new PrestaShopException('identifier is not table or identifier : '.$field_name); - - // Copy the field, or the default language field if it's both required and empty - if ((!$this->id_lang && isset($this->{$field_name}[$id_language]) && !empty($this->{$field_name}[$id_language])) - || ($this->id_lang && isset($this->$field_name) && !empty($this->$field_name))) - $fields[$id_language][$field_name] = $this->id_lang ? pSQL($this->$field_name, $html) : pSQL($this->{$field_name}[$id_language], $html); - elseif (in_array($field_name, $this->fieldsRequiredLang)) - $fields[$id_language][$field_name] = pSQL($this->id_lang ? $this->$field_name : $this->{$field_name}[Configuration::get('PS_LANG_DEFAULT')], $html); - else - $fields[$id_language][$field_name] = ''; - } - } - - /** - * Checks if object field values are valid before database interaction - * - * @param bool $die - * @param bool $error_return - * - * @return bool|string True, false or error message. - * @throws PrestaShopException - */ - public function validateFields($die = true, $error_return = false) - { - foreach ($this->def['fields'] as $field => $data) - { - if (!empty($data['lang'])) - continue; - - if (is_array($this->update_fields) && empty($this->update_fields[$field])) - continue; - - $message = $this->validateField($field, $this->$field); - if ($message !== true) - { - if ($die) - throw new PrestaShopException($message); - return $error_return ? $message : false; - } - } - - return true; - } - - /** - * Checks if multilingual object field values are valid before database interaction. - * - * @param bool $die - * @param bool $error_return - * - * @return bool|string True, false or error message. - * @throws PrestaShopException - */ - public function validateFieldsLang($die = true, $error_return = false) - { - foreach ($this->def['fields'] as $field => $data) - { - if (empty($data['lang'])) - continue; - - $values = $this->$field; - - // If the object has not been loaded in multilanguage, then the value is the one for the current language of the object - if (!is_array($values)) - $values = array($this->id_lang => $values); - - // The value for the default must always be set, so we put an empty string if it does not exists - if (!isset($values[Configuration::get('PS_LANG_DEFAULT')])) - $values[Configuration::get('PS_LANG_DEFAULT')] = ''; - - foreach ($values as $id_lang => $value) - { - if (is_array($this->update_fields) && empty($this->update_fields[$field][$id_lang])) - continue; - - $message = $this->validateField($field, $value, $id_lang); - if ($message !== true) - { - if ($die) - throw new PrestaShopException($message); - return $error_return ? $message : false; - } - } - } - - return true; - } - - /** - * Validate a single field - * - * @since 1.5.0.1 - * @param string $field Field name - * @param mixed $value Field value - * @param int|null $id_lang Language ID - * @param array $skip Array of fields to skip. - * @param bool $human_errors If true, uses more descriptive, translatable error strings. - * - * @return true|string True or error message string. - * @throws PrestaShopException - */ - public function validateField($field, $value, $id_lang = null, $skip = array(), $human_errors = false) - { - static $ps_lang_default = null; - static $ps_allow_html_iframe = null; - - if ($ps_lang_default === null) - $ps_lang_default = Configuration::get('PS_LANG_DEFAULT'); - - if ($ps_allow_html_iframe === null) - $ps_allow_html_iframe = (int)Configuration::get('PS_ALLOW_HTML_IFRAME'); - - - $this->cacheFieldsRequiredDatabase(); - $data = $this->def['fields'][$field]; - - - - // Check if field is required - $required_fields = (isset(self::$fieldsRequiredDatabase[get_class($this)])) ? self::$fieldsRequiredDatabase[get_class($this)] : array(); - if (!$id_lang || $id_lang == $ps_lang_default) - if (!in_array('required', $skip) && (!empty($data['required']) || in_array($field, $required_fields))) - if (Tools::isEmpty($value)) - if ($human_errors) - return sprintf(Tools::displayError('The %s field is required.'), $this->displayFieldName($field, get_class($this))); - else - return 'Property '.get_class($this).'->'.$field.' is empty'; - - // Default value - if (!$value && !empty($data['default'])) - { - $value = $data['default']; - $this->$field = $value; - } - - // Check field values - if (!in_array('values', $skip) && !empty($data['values']) && is_array($data['values']) && !in_array($value, $data['values'])) - return 'Property '.get_class($this).'->'.$field.' has bad value (allowed values are: '.implode(', ', $data['values']).')'; - - // Check field size - if (!in_array('size', $skip) && !empty($data['size'])) - { - $size = $data['size']; - if (!is_array($data['size'])) - $size = array('min' => 0, 'max' => $data['size']); - - $length = Tools::strlen($value); - if ($length < $size['min'] || $length > $size['max']) - { - if ($human_errors) - { - if (isset($data['lang']) && $data['lang']) - { - $language = new Language((int)$id_lang); - return sprintf(Tools::displayError('The field %1$s (%2$s) is too long (%3$d chars max, html chars including).'), $this->displayFieldName($field, get_class($this)), $language->name, $size['max']); - } - else - return sprintf(Tools::displayError('The %1$s field is too long (%2$d chars max).'), $this->displayFieldName($field, get_class($this)), $size['max']); - } - else - return 'Property '.get_class($this).'->'.$field.' length ('.$length.') must be between '.$size['min'].' and '.$size['max']; - } - } - - // Check field validator - if (!in_array('validate', $skip) && !empty($data['validate'])) - { - if (!method_exists('Validate', $data['validate'])) - throw new PrestaShopException('Validation function not found. '.$data['validate']); - - if (!empty($value)) - { - $res = true; - if (Tools::strtolower($data['validate']) == 'iscleanhtml') - { - if (!call_user_func(array('Validate', $data['validate']), $value, $ps_allow_html_iframe)) - $res = false; - } - else - { - if (!call_user_func(array('Validate', $data['validate']), $value)) - $res = false; - } - if (!$res) - { - if ($human_errors) - return sprintf(Tools::displayError('The %s field is invalid.'), $this->displayFieldName($field, get_class($this))); - else - return 'Property '.get_class($this).'->'.$field.' is not valid'; - } - } - } - - return true; - } - - /** - * Returns field name translation - * - * @param string $field Field name - * @param string $class ObjectModel class name - * @param bool $htmlentities If true, applies htmlentities() to result string - * @param Context|null $context Context object - * - * @return string - */ - public static function displayFieldName($field, $class = __CLASS__, $htmlentities = true, Context $context = null) - { - global $_FIELDS; - - if (!isset($context)) - $context = Context::getContext(); - - if ($_FIELDS === null && file_exists(_PS_TRANSLATIONS_DIR_.$context->language->iso_code.'/fields.php')) - include_once(_PS_TRANSLATIONS_DIR_.$context->language->iso_code.'/fields.php'); - - $key = $class.'_'.md5($field); - return ((is_array($_FIELDS) && array_key_exists($key, $_FIELDS)) ? ($htmlentities ? htmlentities($_FIELDS[$key], ENT_QUOTES, 'utf-8') : $_FIELDS[$key]) : $field); - } - - /** - * @deprecated 1.5.0.1 Use validateController() instead - * @param bool $htmlentities - * - * @return array - */ - public function validateControler($htmlentities = true) - { - Tools::displayAsDeprecated(); - return $this->validateController($htmlentities); - } - - /** - * Validates submitted values and returns an array of errors, if any. - * - * @param bool $htmlentities If true, uses htmlentities() for field name translations in errors. - * - * @return array - */ - public function validateController($htmlentities = true) - { - $this->cacheFieldsRequiredDatabase(); - $errors = array(); - $required_fields_database = (isset(self::$fieldsRequiredDatabase[get_class($this)])) ? self::$fieldsRequiredDatabase[get_class($this)] : array(); - foreach ($this->def['fields'] as $field => $data) - { - $value = Tools::getValue($field, $this->{$field}); - // Check if field is required by user - if (in_array($field, $required_fields_database)) - $data['required'] = true; - - // Checking for required fields - if (isset($data['required']) && $data['required'] && empty($value) && $value !== '0') - if (!$this->id || $field != 'passwd') - $errors[$field] = '<b>'.self::displayFieldName($field, get_class($this), $htmlentities).'</b> '.Tools::displayError('is required.'); - - // Checking for maximum fields sizes - if (isset($data['size']) && !empty($value) && Tools::strlen($value) > $data['size']) - $errors[$field] = sprintf( - Tools::displayError('%1$s is too long. Maximum length: %2$d'), - self::displayFieldName($field, get_class($this), $htmlentities), - $data['size'] - ); - - // Checking for fields validity - // Hack for postcode required for country which does not have postcodes - if (!empty($value) || $value === '0' || ($field == 'postcode' && $value == '0')) - { - if (isset($data['validate']) && !Validate::$data['validate']($value) && (!empty($value) || $data['required'])) - $errors[$field] = '<b>'.self::displayFieldName($field, get_class($this), $htmlentities).'</b> '.Tools::displayError('is invalid.'); - else - { - if (isset($data['copy_post']) && !$data['copy_post']) - continue; - if ($field == 'passwd') - { - if ($value = Tools::getValue($field)) - $this->{$field} = Tools::encrypt($value); - } - else - $this->{$field} = $value; - } - } - } - - return $errors; - } - - /** - * Returns webservice parameters of this object. - * - * @param string|null $ws_params_attribute_name - * - * @return array - */ - public function getWebserviceParameters($ws_params_attribute_name = null) - { - $this->cacheFieldsRequiredDatabase(); - $default_resource_parameters = array( - 'objectSqlId' => $this->def['primary'], - 'retrieveData' => array( - 'className' => get_class($this), - 'retrieveMethod' => 'getWebserviceObjectList', - 'params' => array(), - 'table' => $this->def['table'], - ), - 'fields' => array( - 'id' => array('sqlId' => $this->def['primary'], 'i18n' => false), - ), - ); - - if ($ws_params_attribute_name === null) - $ws_params_attribute_name = 'webserviceParameters'; - - if (!isset($this->{$ws_params_attribute_name}['objectNodeName'])) - $default_resource_parameters['objectNodeName'] = $this->def['table']; - if (!isset($this->{$ws_params_attribute_name}['objectsNodeName'])) - $default_resource_parameters['objectsNodeName'] = $this->def['table'].'s'; - - if (isset($this->{$ws_params_attribute_name}['associations'])) - foreach ($this->{$ws_params_attribute_name}['associations'] as $assoc_name => &$association) - { - if (!array_key_exists('setter', $association) || (isset($association['setter']) && !$association['setter'])) - $association['setter'] = Tools::toCamelCase('set_ws_'.$assoc_name); - if (!array_key_exists('getter', $association)) - $association['getter'] = Tools::toCamelCase('get_ws_'.$assoc_name); - } - - if (isset($this->{$ws_params_attribute_name}['retrieveData']) && isset($this->{$ws_params_attribute_name}['retrieveData']['retrieveMethod'])) - unset($default_resource_parameters['retrieveData']['retrieveMethod']); - - $resource_parameters = array_merge_recursive($default_resource_parameters, $this->{$ws_params_attribute_name}); - - $required_fields = (isset(self::$fieldsRequiredDatabase[get_class($this)]) ? self::$fieldsRequiredDatabase[get_class($this)] : array()); - foreach ($this->def['fields'] as $field_name => $details) - { - if (!isset($resource_parameters['fields'][$field_name])) - $resource_parameters['fields'][$field_name] = array(); - $current_field = array(); - $current_field['sqlId'] = $field_name; - if (isset($details['size'])) - $current_field['maxSize'] = $details['size']; - if (isset($details['lang'])) - $current_field['i18n'] = $details['lang']; - else - $current_field['i18n'] = false; - if ((isset($details['required']) && $details['required'] === true) || in_array($field_name, $required_fields)) - $current_field['required'] = true; - else - $current_field['required'] = false; - if (isset($details['validate'])) - { - $current_field['validateMethod'] = ( - array_key_exists('validateMethod', $resource_parameters['fields'][$field_name]) ? - array_merge($resource_parameters['fields'][$field_name]['validateMethod'], array($details['validate'])) : - array($details['validate']) - ); - } - $resource_parameters['fields'][$field_name] = array_merge($resource_parameters['fields'][$field_name], $current_field); - - if (isset($details['ws_modifier'])) - $resource_parameters['fields'][$field_name]['modifier'] = $details['ws_modifier']; - } - if (isset($this->date_add)) - $resource_parameters['fields']['date_add']['setter'] = false; - if (isset($this->date_upd)) - $resource_parameters['fields']['date_upd']['setter'] = false; - foreach ($resource_parameters['fields'] as $key => $resource_parameters_field) - if (!isset($resource_parameters_field['sqlId'])) - $resource_parameters['fields'][$key]['sqlId'] = $key; - - return $resource_parameters; - } - - /** - * Returns webservice object list. - * - * @param string $sql_join - * @param string $sql_filter - * @param string $sql_sort - * @param string $sql_limit - * - * @return array|null - * @throws PrestaShopDatabaseException - */ - public function getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit) - { - $assoc = Shop::getAssoTable($this->def['table']); - $class_name = WebserviceRequest::$ws_current_classname; - $vars = get_class_vars($class_name); - if ($assoc !== false) - { - if ($assoc['type'] !== 'fk_shop') - { - $multi_shop_join = ' LEFT JOIN `'._DB_PREFIX_.bqSQL($this->def['table']).'_'.bqSQL($assoc['type']).'` + if (!$result) { + return false; + } + + foreach ($result as &$row) { + foreach ($row as $field => &$value) { + if (isset($definition['fields'][$field])) { + $value = ObjectModel::formatValue($value, $definition['fields'][$field]['type'], false, true, + !empty($definition['fields'][$field]['allow_null'])); + } + } + } + + // Keep $row2, you cannot use $row because there is an unexplicated conflict with the previous usage of this variable + foreach ($result as $row2) { + $row2[$definition['primary']] = (int)$object_id; + if (!Db::getInstance()->insert($definition['table'].'_lang', $row2)) { + return false; + } + } + } + + /** @var ObjectModel $object_duplicated */ + $object_duplicated = new $definition['classname']((int)$object_id); + $object_duplicated->duplicateShops((int)$this->id); + + return $object_duplicated; + } + + /** + * Updates the current object in the database + * + * @param bool $null_values + * + * @return bool + * @throws PrestaShopDatabaseException + * @throws PrestaShopException + */ + public function update($null_values = false) + { + // @hook actionObject*UpdateBefore + Hook::exec('actionObjectUpdateBefore', array('object' => $this)); + Hook::exec('actionObject'.get_class($this).'UpdateBefore', array('object' => $this)); + + $this->clearCache(); + + // Automatically fill dates + if (array_key_exists('date_upd', $this)) { + $this->date_upd = date('Y-m-d H:i:s'); + if (isset($this->update_fields) && is_array($this->update_fields) && count($this->update_fields)) { + $this->update_fields['date_upd'] = true; + } + } + + // Automatically fill dates + if (array_key_exists('date_add', $this) && $this->date_add == null) { + $this->date_add = date('Y-m-d H:i:s'); + if (isset($this->update_fields) && is_array($this->update_fields) && count($this->update_fields)) { + $this->update_fields['date_add'] = true; + } + } + + $id_shop_list = Shop::getContextListShopID(); + if (count($this->id_shop_list) > 0) { + $id_shop_list = $this->id_shop_list; + } + + if (Shop::checkIdShopDefault($this->def['table']) && !$this->id_shop_default) { + $this->id_shop_default = (in_array(Configuration::get('PS_SHOP_DEFAULT'), $id_shop_list) == true) ? Configuration::get('PS_SHOP_DEFAULT') : min($id_shop_list); + } + // Database update + if (!$result = Db::getInstance()->update($this->def['table'], $this->getFields(), '`'.pSQL($this->def['primary']).'` = '.(int)$this->id, 0, $null_values)) { + return false; + } + + // Database insertion for multishop fields related to the object + if (Shop::isTableAssociated($this->def['table'])) { + $fields = $this->getFieldsShop(); + $fields[$this->def['primary']] = (int)$this->id; + if (is_array($this->update_fields)) { + $update_fields = $this->update_fields; + $this->update_fields = null; + $all_fields = $this->getFieldsShop(); + $all_fields[$this->def['primary']] = (int)$this->id; + $this->update_fields = $update_fields; + } else { + $all_fields = $fields; + } + + foreach ($id_shop_list as $id_shop) { + $fields['id_shop'] = (int)$id_shop; + $all_fields['id_shop'] = (int)$id_shop; + $where = $this->def['primary'].' = '.(int)$this->id.' AND id_shop = '.(int)$id_shop; + + // A little explanation of what we do here : we want to create multishop entry when update is called, but + // only if we are in a shop context (if we are in all context, we just want to update entries that alread exists) + $shop_exists = Db::getInstance()->getValue('SELECT '.$this->def['primary'].' FROM '._DB_PREFIX_.$this->def['table'].'_shop WHERE '.$where); + if ($shop_exists) { + $result &= Db::getInstance()->update($this->def['table'].'_shop', $fields, $where, 0, $null_values); + } elseif (Shop::getContext() == Shop::CONTEXT_SHOP) { + $result &= Db::getInstance()->insert($this->def['table'].'_shop', $all_fields, $null_values); + } + } + } + + // Database update for multilingual fields related to the object + if (isset($this->def['multilang']) && $this->def['multilang']) { + $fields = $this->getFieldsLang(); + if (is_array($fields)) { + foreach ($fields as $field) { + foreach (array_keys($field) as $key) { + if (!Validate::isTableOrIdentifier($key)) { + throw new PrestaShopException('key '.$key.' is not a valid table or identifier'); + } + } + + // If this table is linked to multishop system, update / insert for all shops from context + if ($this->isLangMultishop()) { + $id_shop_list = Shop::getContextListShopID(); + if (count($this->id_shop_list) > 0) { + $id_shop_list = $this->id_shop_list; + } + foreach ($id_shop_list as $id_shop) { + $field['id_shop'] = (int)$id_shop; + $where = pSQL($this->def['primary']).' = '.(int)$this->id + .' AND id_lang = '.(int)$field['id_lang'] + .' AND id_shop = '.(int)$id_shop; + + if (Db::getInstance()->getValue('SELECT COUNT(*) FROM '.pSQL(_DB_PREFIX_.$this->def['table']).'_lang WHERE '.$where)) { + $result &= Db::getInstance()->update($this->def['table'].'_lang', $field, $where); + } else { + $result &= Db::getInstance()->insert($this->def['table'].'_lang', $field); + } + } + } + // If this table is not linked to multishop system ... + else { + $where = pSQL($this->def['primary']).' = '.(int)$this->id + .' AND id_lang = '.(int)$field['id_lang']; + if (Db::getInstance()->getValue('SELECT COUNT(*) FROM '.pSQL(_DB_PREFIX_.$this->def['table']).'_lang WHERE '.$where)) { + $result &= Db::getInstance()->update($this->def['table'].'_lang', $field, $where); + } else { + $result &= Db::getInstance()->insert($this->def['table'].'_lang', $field, $null_values); + } + } + } + } + } + + // @hook actionObject*UpdateAfter + Hook::exec('actionObjectUpdateAfter', array('object' => $this)); + Hook::exec('actionObject'.get_class($this).'UpdateAfter', array('object' => $this)); + + return $result; + } + + /** + * Deletes current object from database + * + * @return bool True if delete was successful + * @throws PrestaShopException + */ + public function delete() + { + // @hook actionObject*DeleteBefore + Hook::exec('actionObjectDeleteBefore', array('object' => $this)); + Hook::exec('actionObject'.get_class($this).'DeleteBefore', array('object' => $this)); + + $this->clearCache(); + $result = true; + // Remove association to multishop table + if (Shop::isTableAssociated($this->def['table'])) { + $id_shop_list = Shop::getContextListShopID(); + if (count($this->id_shop_list)) { + $id_shop_list = $this->id_shop_list; + } + + $result &= Db::getInstance()->delete($this->def['table'].'_shop', '`'.$this->def['primary'].'`='.(int)$this->id.' AND id_shop IN ('.implode(', ', $id_shop_list).')'); + } + + // Database deletion + $has_multishop_entries = $this->hasMultishopEntries(); + if ($result && !$has_multishop_entries) { + $result &= Db::getInstance()->delete($this->def['table'], '`'.bqSQL($this->def['primary']).'` = '.(int)$this->id); + } + + if (!$result) { + return false; + } + + // Database deletion for multilingual fields related to the object + if (!empty($this->def['multilang']) && !$has_multishop_entries) { + $result &= Db::getInstance()->delete($this->def['table'].'_lang', '`'.bqSQL($this->def['primary']).'` = '.(int)$this->id); + } + + // @hook actionObject*DeleteAfter + Hook::exec('actionObjectDeleteAfter', array('object' => $this)); + Hook::exec('actionObject'.get_class($this).'DeleteAfter', array('object' => $this)); + + return $result; + } + + /** + * Deletes multiple objects from the database at once + * + * @param array $ids Array of objects IDs. + * + * @return bool + */ + public function deleteSelection($ids) + { + $result = true; + foreach ($ids as $id) { + $this->id = (int)$id; + $result = $result && $this->delete(); + } + + return $result; + } + + /** + * Toggles object status in database + * + * @return bool Update result + * @throws PrestaShopException + */ + public function toggleStatus() + { + // Object must have a variable called 'active' + if (!array_key_exists('active', $this)) { + throw new PrestaShopException('property "active" is missing in object '.get_class($this)); + } + + // Update only active field + $this->setFieldsToUpdate(array('active' => true)); + + // Update active status on object + $this->active = !(int)$this->active; + + // Change status to active/inactive + return $this->update(false); + } + + /** + * @deprecated 1.5.0.1 (use getFieldsLang()) + * @param array $fields_array + * + * @return array + * @throws PrestaShopException + */ + protected function getTranslationsFields($fields_array) + { + $fields = array(); + + if ($this->id_lang == null) { + foreach (Language::getIDs(false) as $id_lang) { + $this->makeTranslationFields($fields, $fields_array, $id_lang); + } + } else { + $this->makeTranslationFields($fields, $fields_array, $this->id_lang); + } + + return $fields; + } + + /** + * @deprecated 1.5.0.1 + * @param array $fields + * @param array $fields_array + * @param int $id_language + * + * @throws PrestaShopException + */ + protected function makeTranslationFields(&$fields, &$fields_array, $id_language) + { + $fields[$id_language]['id_lang'] = $id_language; + $fields[$id_language][$this->def['primary']] = (int)$this->id; + if ($this->id_shop && $this->isLangMultishop()) { + $fields[$id_language]['id_shop'] = (int)$this->id_shop; + } + foreach ($fields_array as $k => $field) { + $html = false; + $field_name = $field; + if (is_array($field)) { + $field_name = $k; + $html = (isset($field['html'])) ? $field['html'] : false; + } + + /* Check fields validity */ + if (!Validate::isTableOrIdentifier($field_name)) { + throw new PrestaShopException('identifier is not table or identifier : '.$field_name); + } + + // Copy the field, or the default language field if it's both required and empty + if ((!$this->id_lang && isset($this->{$field_name}[$id_language]) && !empty($this->{$field_name}[$id_language])) + || ($this->id_lang && isset($this->$field_name) && !empty($this->$field_name))) { + $fields[$id_language][$field_name] = $this->id_lang ? pSQL($this->$field_name, $html) : pSQL($this->{$field_name}[$id_language], $html); + } elseif (in_array($field_name, $this->fieldsRequiredLang)) { + $fields[$id_language][$field_name] = pSQL($this->id_lang ? $this->$field_name : $this->{$field_name}[Configuration::get('PS_LANG_DEFAULT')], $html); + } else { + $fields[$id_language][$field_name] = ''; + } + } + } + + /** + * Checks if object field values are valid before database interaction + * + * @param bool $die + * @param bool $error_return + * + * @return bool|string True, false or error message. + * @throws PrestaShopException + */ + public function validateFields($die = true, $error_return = false) + { + foreach ($this->def['fields'] as $field => $data) { + if (!empty($data['lang'])) { + continue; + } + + if (is_array($this->update_fields) && empty($this->update_fields[$field])) { + continue; + } + + $message = $this->validateField($field, $this->$field); + if ($message !== true) { + if ($die) { + throw new PrestaShopException($message); + } + return $error_return ? $message : false; + } + } + + return true; + } + + /** + * Checks if multilingual object field values are valid before database interaction. + * + * @param bool $die + * @param bool $error_return + * + * @return bool|string True, false or error message. + * @throws PrestaShopException + */ + public function validateFieldsLang($die = true, $error_return = false) + { + foreach ($this->def['fields'] as $field => $data) { + if (empty($data['lang'])) { + continue; + } + + $values = $this->$field; + + // If the object has not been loaded in multilanguage, then the value is the one for the current language of the object + if (!is_array($values)) { + $values = array($this->id_lang => $values); + } + + // The value for the default must always be set, so we put an empty string if it does not exists + if (!isset($values[Configuration::get('PS_LANG_DEFAULT')])) { + $values[Configuration::get('PS_LANG_DEFAULT')] = ''; + } + + foreach ($values as $id_lang => $value) { + if (is_array($this->update_fields) && empty($this->update_fields[$field][$id_lang])) { + continue; + } + + $message = $this->validateField($field, $value, $id_lang); + if ($message !== true) { + if ($die) { + throw new PrestaShopException($message); + } + return $error_return ? $message : false; + } + } + } + + return true; + } + + /** + * Validate a single field + * + * @since 1.5.0.1 + * @param string $field Field name + * @param mixed $value Field value + * @param int|null $id_lang Language ID + * @param array $skip Array of fields to skip. + * @param bool $human_errors If true, uses more descriptive, translatable error strings. + * + * @return true|string True or error message string. + * @throws PrestaShopException + */ + public function validateField($field, $value, $id_lang = null, $skip = array(), $human_errors = false) + { + static $ps_lang_default = null; + static $ps_allow_html_iframe = null; + + if ($ps_lang_default === null) { + $ps_lang_default = Configuration::get('PS_LANG_DEFAULT'); + } + + if ($ps_allow_html_iframe === null) { + $ps_allow_html_iframe = (int)Configuration::get('PS_ALLOW_HTML_IFRAME'); + } + + + $this->cacheFieldsRequiredDatabase(); + $data = $this->def['fields'][$field]; + + + + // Check if field is required + $required_fields = (isset(self::$fieldsRequiredDatabase[get_class($this)])) ? self::$fieldsRequiredDatabase[get_class($this)] : array(); + if (!$id_lang || $id_lang == $ps_lang_default) { + if (!in_array('required', $skip) && (!empty($data['required']) || in_array($field, $required_fields))) { + if (Tools::isEmpty($value)) { + if ($human_errors) { + return sprintf(Tools::displayError('The %s field is required.'), $this->displayFieldName($field, get_class($this))); + } else { + return 'Property '.get_class($this).'->'.$field.' is empty'; + } + } + } + } + + // Default value + if (!$value && !empty($data['default'])) { + $value = $data['default']; + $this->$field = $value; + } + + // Check field values + if (!in_array('values', $skip) && !empty($data['values']) && is_array($data['values']) && !in_array($value, $data['values'])) { + return 'Property '.get_class($this).'->'.$field.' has bad value (allowed values are: '.implode(', ', $data['values']).')'; + } + + // Check field size + if (!in_array('size', $skip) && !empty($data['size'])) { + $size = $data['size']; + if (!is_array($data['size'])) { + $size = array('min' => 0, 'max' => $data['size']); + } + + $length = Tools::strlen($value); + if ($length < $size['min'] || $length > $size['max']) { + if ($human_errors) { + if (isset($data['lang']) && $data['lang']) { + $language = new Language((int)$id_lang); + return sprintf(Tools::displayError('The field %1$s (%2$s) is too long (%3$d chars max, html chars including).'), $this->displayFieldName($field, get_class($this)), $language->name, $size['max']); + } else { + return sprintf(Tools::displayError('The %1$s field is too long (%2$d chars max).'), $this->displayFieldName($field, get_class($this)), $size['max']); + } + } else { + return 'Property '.get_class($this).'->'.$field.' length ('.$length.') must be between '.$size['min'].' and '.$size['max']; + } + } + } + + // Check field validator + if (!in_array('validate', $skip) && !empty($data['validate'])) { + if (!method_exists('Validate', $data['validate'])) { + throw new PrestaShopException('Validation function not found. '.$data['validate']); + } + + if (!empty($value)) { + $res = true; + if (Tools::strtolower($data['validate']) == 'iscleanhtml') { + if (!call_user_func(array('Validate', $data['validate']), $value, $ps_allow_html_iframe)) { + $res = false; + } + } else { + if (!call_user_func(array('Validate', $data['validate']), $value)) { + $res = false; + } + } + if (!$res) { + if ($human_errors) { + return sprintf(Tools::displayError('The %s field is invalid.'), $this->displayFieldName($field, get_class($this))); + } else { + return 'Property '.get_class($this).'->'.$field.' is not valid'; + } + } + } + } + + return true; + } + + /** + * Returns field name translation + * + * @param string $field Field name + * @param string $class ObjectModel class name + * @param bool $htmlentities If true, applies htmlentities() to result string + * @param Context|null $context Context object + * + * @return string + */ + public static function displayFieldName($field, $class = __CLASS__, $htmlentities = true, Context $context = null) + { + global $_FIELDS; + + if (!isset($context)) { + $context = Context::getContext(); + } + + if ($_FIELDS === null && file_exists(_PS_TRANSLATIONS_DIR_.$context->language->iso_code.'/fields.php')) { + include_once(_PS_TRANSLATIONS_DIR_.$context->language->iso_code.'/fields.php'); + } + + $key = $class.'_'.md5($field); + return ((is_array($_FIELDS) && array_key_exists($key, $_FIELDS)) ? ($htmlentities ? htmlentities($_FIELDS[$key], ENT_QUOTES, 'utf-8') : $_FIELDS[$key]) : $field); + } + + /** + * @deprecated 1.5.0.1 Use validateController() instead + * @param bool $htmlentities + * + * @return array + */ + public function validateControler($htmlentities = true) + { + Tools::displayAsDeprecated(); + return $this->validateController($htmlentities); + } + + /** + * Validates submitted values and returns an array of errors, if any. + * + * @param bool $htmlentities If true, uses htmlentities() for field name translations in errors. + * + * @return array + */ + public function validateController($htmlentities = true) + { + $this->cacheFieldsRequiredDatabase(); + $errors = array(); + $required_fields_database = (isset(self::$fieldsRequiredDatabase[get_class($this)])) ? self::$fieldsRequiredDatabase[get_class($this)] : array(); + foreach ($this->def['fields'] as $field => $data) { + $value = Tools::getValue($field, $this->{$field}); + // Check if field is required by user + if (in_array($field, $required_fields_database)) { + $data['required'] = true; + } + + // Checking for required fields + if (isset($data['required']) && $data['required'] && empty($value) && $value !== '0') { + if (!$this->id || $field != 'passwd') { + $errors[$field] = '<b>'.self::displayFieldName($field, get_class($this), $htmlentities).'</b> '.Tools::displayError('is required.'); + } + } + + // Checking for maximum fields sizes + if (isset($data['size']) && !empty($value) && Tools::strlen($value) > $data['size']) { + $errors[$field] = sprintf( + Tools::displayError('%1$s is too long. Maximum length: %2$d'), + self::displayFieldName($field, get_class($this), $htmlentities), + $data['size'] + ); + } + + // Checking for fields validity + // Hack for postcode required for country which does not have postcodes + if (!empty($value) || $value === '0' || ($field == 'postcode' && $value == '0')) { + if (isset($data['validate']) && !Validate::$data['validate']($value) && (!empty($value) || $data['required'])) { + $errors[$field] = '<b>'.self::displayFieldName($field, get_class($this), $htmlentities).'</b> '.Tools::displayError('is invalid.'); + } else { + if (isset($data['copy_post']) && !$data['copy_post']) { + continue; + } + if ($field == 'passwd') { + if ($value = Tools::getValue($field)) { + $this->{$field} = Tools::encrypt($value); + } + } else { + $this->{$field} = $value; + } + } + } + } + + return $errors; + } + + /** + * Returns webservice parameters of this object. + * + * @param string|null $ws_params_attribute_name + * + * @return array + */ + public function getWebserviceParameters($ws_params_attribute_name = null) + { + $this->cacheFieldsRequiredDatabase(); + $default_resource_parameters = array( + 'objectSqlId' => $this->def['primary'], + 'retrieveData' => array( + 'className' => get_class($this), + 'retrieveMethod' => 'getWebserviceObjectList', + 'params' => array(), + 'table' => $this->def['table'], + ), + 'fields' => array( + 'id' => array('sqlId' => $this->def['primary'], 'i18n' => false), + ), + ); + + if ($ws_params_attribute_name === null) { + $ws_params_attribute_name = 'webserviceParameters'; + } + + if (!isset($this->{$ws_params_attribute_name}['objectNodeName'])) { + $default_resource_parameters['objectNodeName'] = $this->def['table']; + } + if (!isset($this->{$ws_params_attribute_name}['objectsNodeName'])) { + $default_resource_parameters['objectsNodeName'] = $this->def['table'].'s'; + } + + if (isset($this->{$ws_params_attribute_name}['associations'])) { + foreach ($this->{$ws_params_attribute_name}['associations'] as $assoc_name => &$association) { + if (!array_key_exists('setter', $association) || (isset($association['setter']) && !$association['setter'])) { + $association['setter'] = Tools::toCamelCase('set_ws_'.$assoc_name); + } + if (!array_key_exists('getter', $association)) { + $association['getter'] = Tools::toCamelCase('get_ws_'.$assoc_name); + } + } + } + + if (isset($this->{$ws_params_attribute_name}['retrieveData']) && isset($this->{$ws_params_attribute_name}['retrieveData']['retrieveMethod'])) { + unset($default_resource_parameters['retrieveData']['retrieveMethod']); + } + + $resource_parameters = array_merge_recursive($default_resource_parameters, $this->{$ws_params_attribute_name}); + + $required_fields = (isset(self::$fieldsRequiredDatabase[get_class($this)]) ? self::$fieldsRequiredDatabase[get_class($this)] : array()); + foreach ($this->def['fields'] as $field_name => $details) { + if (!isset($resource_parameters['fields'][$field_name])) { + $resource_parameters['fields'][$field_name] = array(); + } + $current_field = array(); + $current_field['sqlId'] = $field_name; + if (isset($details['size'])) { + $current_field['maxSize'] = $details['size']; + } + if (isset($details['lang'])) { + $current_field['i18n'] = $details['lang']; + } else { + $current_field['i18n'] = false; + } + if ((isset($details['required']) && $details['required'] === true) || in_array($field_name, $required_fields)) { + $current_field['required'] = true; + } else { + $current_field['required'] = false; + } + if (isset($details['validate'])) { + $current_field['validateMethod'] = ( + array_key_exists('validateMethod', $resource_parameters['fields'][$field_name]) ? + array_merge($resource_parameters['fields'][$field_name]['validateMethod'], array($details['validate'])) : + array($details['validate']) + ); + } + $resource_parameters['fields'][$field_name] = array_merge($resource_parameters['fields'][$field_name], $current_field); + + if (isset($details['ws_modifier'])) { + $resource_parameters['fields'][$field_name]['modifier'] = $details['ws_modifier']; + } + } + if (isset($this->date_add)) { + $resource_parameters['fields']['date_add']['setter'] = false; + } + if (isset($this->date_upd)) { + $resource_parameters['fields']['date_upd']['setter'] = false; + } + foreach ($resource_parameters['fields'] as $key => $resource_parameters_field) { + if (!isset($resource_parameters_field['sqlId'])) { + $resource_parameters['fields'][$key]['sqlId'] = $key; + } + } + + return $resource_parameters; + } + + /** + * Returns webservice object list. + * + * @param string $sql_join + * @param string $sql_filter + * @param string $sql_sort + * @param string $sql_limit + * + * @return array|null + * @throws PrestaShopDatabaseException + */ + public function getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit) + { + $assoc = Shop::getAssoTable($this->def['table']); + $class_name = WebserviceRequest::$ws_current_classname; + $vars = get_class_vars($class_name); + if ($assoc !== false) { + if ($assoc['type'] !== 'fk_shop') { + $multi_shop_join = ' LEFT JOIN `'._DB_PREFIX_.bqSQL($this->def['table']).'_'.bqSQL($assoc['type']).'` AS `multi_shop_'.bqSQL($this->def['table']).'` ON (main.`'.bqSQL($this->def['primary']).'` = `multi_shop_'.bqSQL($this->def['table']).'`.`'.bqSQL($this->def['primary']).'`)'; - $sql_filter = 'AND `multi_shop_'.bqSQL($this->def['table']).'`.id_shop = '.Context::getContext()->shop->id.' '.$sql_filter; - $sql_join = $multi_shop_join.' '.$sql_join; - } - else - { - $vars = get_class_vars($class_name); - foreach ($vars['shopIDs'] as $id_shop) - $or[] = '(main.id_shop = '.(int)$id_shop.(isset($this->def['fields']['id_shop_group']) ? ' OR (id_shop = 0 AND id_shop_group='.(int)Shop::getGroupFromShop((int)$id_shop).')' : '').')'; + $sql_filter = 'AND `multi_shop_'.bqSQL($this->def['table']).'`.id_shop = '.Context::getContext()->shop->id.' '.$sql_filter; + $sql_join = $multi_shop_join.' '.$sql_join; + } else { + $vars = get_class_vars($class_name); + foreach ($vars['shopIDs'] as $id_shop) { + $or[] = '(main.id_shop = '.(int)$id_shop.(isset($this->def['fields']['id_shop_group']) ? ' OR (id_shop = 0 AND id_shop_group='.(int)Shop::getGroupFromShop((int)$id_shop).')' : '').')'; + } - $prepend = ''; - if (count($or)) - $prepend = 'AND ('.implode('OR', $or).')'; - $sql_filter = $prepend.' '.$sql_filter; - } - } - $query = ' + $prepend = ''; + if (count($or)) { + $prepend = 'AND ('.implode('OR', $or).')'; + } + $sql_filter = $prepend.' '.$sql_filter; + } + } + $query = ' SELECT DISTINCT main.`'.bqSQL($this->def['primary']).'` FROM `'._DB_PREFIX_.bqSQL($this->def['table']).'` AS main '.$sql_join.' WHERE 1 '.$sql_filter.' '.($sql_sort != '' ? $sql_sort : '').' '.($sql_limit != '' ? $sql_limit : ''); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } - /** - * Validate required fields. - * - * @param bool $htmlentities - * - * @return array - * @throws PrestaShopException - */ - public function validateFieldsRequiredDatabase($htmlentities = true) - { - $this->cacheFieldsRequiredDatabase(); - $errors = array(); - $required_fields = (isset(self::$fieldsRequiredDatabase[get_class($this)])) ? self::$fieldsRequiredDatabase[get_class($this)] : array(); + /** + * Validate required fields. + * + * @param bool $htmlentities + * + * @return array + * @throws PrestaShopException + */ + public function validateFieldsRequiredDatabase($htmlentities = true) + { + $this->cacheFieldsRequiredDatabase(); + $errors = array(); + $required_fields = (isset(self::$fieldsRequiredDatabase[get_class($this)])) ? self::$fieldsRequiredDatabase[get_class($this)] : array(); - foreach ($this->def['fields'] as $field => $data) - { - if (!in_array($field, $required_fields)) - continue; + foreach ($this->def['fields'] as $field => $data) { + if (!in_array($field, $required_fields)) { + continue; + } - if (!method_exists('Validate', $data['validate'])) - throw new PrestaShopException('Validation function not found. '.$data['validate']); + if (!method_exists('Validate', $data['validate'])) { + throw new PrestaShopException('Validation function not found. '.$data['validate']); + } - $value = Tools::getValue($field); + $value = Tools::getValue($field); - if (empty($value)) - $errors[$field] = sprintf(Tools::displayError('The field %s is required.'), self::displayFieldName($field, get_class($this), $htmlentities)); - } + if (empty($value)) { + $errors[$field] = sprintf(Tools::displayError('The field %s is required.'), self::displayFieldName($field, get_class($this), $htmlentities)); + } + } - return $errors; - } + return $errors; + } - /** - * Returns an array of required fields - * - * @param bool $all If true, returns required fields of all object classes. - * - * @return array|null - * @throws PrestaShopDatabaseException - */ - public function getFieldsRequiredDatabase($all = false) - { - return Db::getInstance()->executeS(' + /** + * Returns an array of required fields + * + * @param bool $all If true, returns required fields of all object classes. + * + * @return array|null + * @throws PrestaShopDatabaseException + */ + public function getFieldsRequiredDatabase($all = false) + { + return Db::getInstance()->executeS(' SELECT id_required_field, object_name, field_name FROM '._DB_PREFIX_.'required_field '.(!$all ? 'WHERE object_name = \''.pSQL(get_class($this)).'\'' : '')); - } + } - /** - * Caches data about required objects fields in memory - * - * @param bool $all If true, caches required fields of all object classes. - */ - public function cacheFieldsRequiredDatabase($all = true) - { - if (!is_array(self::$fieldsRequiredDatabase)) - { - $fields = $this->getfieldsRequiredDatabase((bool)$all); - if ($fields) - foreach ($fields as $row) - self::$fieldsRequiredDatabase[$row['object_name']][(int)$row['id_required_field']] = pSQL($row['field_name']); - else - self::$fieldsRequiredDatabase = array(); - } - } + /** + * Caches data about required objects fields in memory + * + * @param bool $all If true, caches required fields of all object classes. + */ + public function cacheFieldsRequiredDatabase($all = true) + { + if (!is_array(self::$fieldsRequiredDatabase)) { + $fields = $this->getfieldsRequiredDatabase((bool)$all); + if ($fields) { + foreach ($fields as $row) { + self::$fieldsRequiredDatabase[$row['object_name']][(int)$row['id_required_field']] = pSQL($row['field_name']); + } + } else { + self::$fieldsRequiredDatabase = array(); + } + } + } - /** - * Sets required field for this class in the database. - * - * @param array $fields - * - * @return bool - * @throws PrestaShopDatabaseException - */ - public function addFieldsRequiredDatabase($fields) - { - if (!is_array($fields)) - return false; + /** + * Sets required field for this class in the database. + * + * @param array $fields + * + * @return bool + * @throws PrestaShopDatabaseException + */ + public function addFieldsRequiredDatabase($fields) + { + if (!is_array($fields)) { + return false; + } - if (!Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'required_field WHERE object_name = \''.get_class($this).'\'')) - return false; + if (!Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'required_field WHERE object_name = \''.get_class($this).'\'')) { + return false; + } - foreach ($fields as $field) - if (!Db::getInstance()->insert('required_field', array('object_name' => get_class($this), 'field_name' => pSQL($field)))) - return false; + foreach ($fields as $field) { + if (!Db::getInstance()->insert('required_field', array('object_name' => get_class($this), 'field_name' => pSQL($field)))) { + return false; + } + } - return true; - } + return true; + } - /** - * Clears cache entries that have this object's ID. - * - * @param bool $all If true, clears cache for all objects - */ - public function clearCache($all = false) - { - if ($all) - Cache::clean('objectmodel_'.$this->def['classname'].'_*'); - elseif ($this->id) - Cache::clean('objectmodel_'.$this->def['classname'].'_'.(int)$this->id.'_*'); - } + /** + * Clears cache entries that have this object's ID. + * + * @param bool $all If true, clears cache for all objects + */ + public function clearCache($all = false) + { + if ($all) { + Cache::clean('objectmodel_'.$this->def['classname'].'_*'); + } elseif ($this->id) { + Cache::clean('objectmodel_'.$this->def['classname'].'_'.(int)$this->id.'_*'); + } + } - /** - * Checks if current object is associated to a shop. - * - * @since 1.5.0.1 - * @param int|null $id_shop - * @return bool - */ - public function isAssociatedToShop($id_shop = null) - { - if ($id_shop === null) - $id_shop = Context::getContext()->shop->id; + /** + * Checks if current object is associated to a shop. + * + * @since 1.5.0.1 + * @param int|null $id_shop + * @return bool + */ + public function isAssociatedToShop($id_shop = null) + { + if ($id_shop === null) { + $id_shop = Context::getContext()->shop->id; + } - $cache_id = 'objectmodel_shop_'.$this->def['classname'].'_'.(int)$this->id.'-'.(int)$id_shop; - if (!ObjectModel::$cache_objects || !Cache::isStored($cache_id)) - { - $associated = (bool)Db::getInstance()->getValue(' + $cache_id = 'objectmodel_shop_'.$this->def['classname'].'_'.(int)$this->id.'-'.(int)$id_shop; + if (!ObjectModel::$cache_objects || !Cache::isStored($cache_id)) { + $associated = (bool)Db::getInstance()->getValue(' SELECT id_shop FROM `'.pSQL(_DB_PREFIX_.$this->def['table']).'_shop` WHERE `'.$this->def['primary'].'` = '.(int)$this->id.' AND id_shop = '.(int)$id_shop - ); + ); - if (!ObjectModel::$cache_objects) - return $associated; + if (!ObjectModel::$cache_objects) { + return $associated; + } - Cache::store($cache_id, $associated); - return $associated; - } + Cache::store($cache_id, $associated); + return $associated; + } - return Cache::retrieve($cache_id); - } + return Cache::retrieve($cache_id); + } - /** - * This function associate an item to its context - * - * @param int|array $id_shops - * - * @return bool|void - * @throws PrestaShopDatabaseException - */ - public function associateTo($id_shops) - { - if (!$this->id) - return; + /** + * This function associate an item to its context + * + * @param int|array $id_shops + * + * @return bool|void + * @throws PrestaShopDatabaseException + */ + public function associateTo($id_shops) + { + if (!$this->id) { + return; + } - if (!is_array($id_shops)) - $id_shops = array($id_shops); + if (!is_array($id_shops)) { + $id_shops = array($id_shops); + } - $data = array(); - foreach ($id_shops as $id_shop) - { - if (!$this->isAssociatedToShop($id_shop)) - $data[] = array( - $this->def['primary'] => (int)$this->id, - 'id_shop' => (int)$id_shop, - ); - } + $data = array(); + foreach ($id_shops as $id_shop) { + if (!$this->isAssociatedToShop($id_shop)) { + $data[] = array( + $this->def['primary'] => (int)$this->id, + 'id_shop' => (int)$id_shop, + ); + } + } - if ($data) - return Db::getInstance()->insert($this->def['table'].'_shop', $data); + if ($data) { + return Db::getInstance()->insert($this->def['table'].'_shop', $data); + } - return true; - } + return true; + } - /** - * Gets the list of associated shop IDs - * - * @since 1.5.0.1 - * - * @return array - * @throws PrestaShopDatabaseException - */ - public function getAssociatedShops() - { - if (!Shop::isTableAssociated($this->def['table'])) - return array(); + /** + * Gets the list of associated shop IDs + * + * @since 1.5.0.1 + * + * @return array + * @throws PrestaShopDatabaseException + */ + public function getAssociatedShops() + { + if (!Shop::isTableAssociated($this->def['table'])) { + return array(); + } - $list = array(); - $sql = 'SELECT id_shop FROM `'._DB_PREFIX_.$this->def['table'].'_shop` WHERE `'.$this->def['primary'].'` = '.(int)$this->id; - foreach (Db::getInstance()->executeS($sql) as $row) - $list[] = $row['id_shop']; + $list = array(); + $sql = 'SELECT id_shop FROM `'._DB_PREFIX_.$this->def['table'].'_shop` WHERE `'.$this->def['primary'].'` = '.(int)$this->id; + foreach (Db::getInstance()->executeS($sql) as $row) { + $list[] = $row['id_shop']; + } - return $list; - } + return $list; + } - /** - * Copies shop association data from object with specified ID. - * - * @since 1.5.0.1 - * @param $id - * - * @return bool|void - * @throws PrestaShopDatabaseException - */ - public function duplicateShops($id) - { - if (!Shop::isTableAssociated($this->def['table'])) - return false; + /** + * Copies shop association data from object with specified ID. + * + * @since 1.5.0.1 + * @param $id + * + * @return bool|void + * @throws PrestaShopDatabaseException + */ + public function duplicateShops($id) + { + if (!Shop::isTableAssociated($this->def['table'])) { + return false; + } - $sql = 'SELECT id_shop + $sql = 'SELECT id_shop FROM '._DB_PREFIX_.$this->def['table'].'_shop WHERE '.$this->def['primary'].' = '.(int)$id; - if ($results = Db::getInstance()->executeS($sql)) - { - $ids = array(); - foreach ($results as $row) - $ids[] = $row['id_shop']; - return $this->associateTo($ids); - } + if ($results = Db::getInstance()->executeS($sql)) { + $ids = array(); + foreach ($results as $row) { + $ids[] = $row['id_shop']; + } + return $this->associateTo($ids); + } - return false; - } + return false; + } - /** - * Checks if there is more than one entry in associated shop table for current object. - * - * @since 1.5.0.1 - * - * @return bool - */ - public function hasMultishopEntries() - { - if (!Shop::isTableAssociated($this->def['table']) || !Shop::isFeatureActive()) - return false; + /** + * Checks if there is more than one entry in associated shop table for current object. + * + * @since 1.5.0.1 + * + * @return bool + */ + public function hasMultishopEntries() + { + if (!Shop::isTableAssociated($this->def['table']) || !Shop::isFeatureActive()) { + return false; + } - return (bool)Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.$this->def['table'].'_shop` WHERE `'.$this->def['primary'].'` = '.(int)$this->id); - } + return (bool)Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.$this->def['table'].'_shop` WHERE `'.$this->def['primary'].'` = '.(int)$this->id); + } - /** - * Checks if object is multi-shop object. - * - * @return bool - */ - public function isMultishop() - { - return Shop::isTableAssociated($this->def['table']) || !empty($this->def['multilang_shop']); - } + /** + * Checks if object is multi-shop object. + * + * @return bool + */ + public function isMultishop() + { + return Shop::isTableAssociated($this->def['table']) || !empty($this->def['multilang_shop']); + } - /** - * Checks if a field is a multi-shop field. - * - * @param string $field - * - * @return bool - */ - public function isMultiShopField($field) - { - return (isset($this->def['fields'][$field]) && isset($this->def['fields'][$field]['shop']) && $this->def['fields'][$field]['shop']); - } + /** + * Checks if a field is a multi-shop field. + * + * @param string $field + * + * @return bool + */ + public function isMultiShopField($field) + { + return (isset($this->def['fields'][$field]) && isset($this->def['fields'][$field]['shop']) && $this->def['fields'][$field]['shop']); + } - /** - * Checks if the object is both multi-language and multi-shop. - * - * @return bool - */ - public function isLangMultishop() - { - return !empty($this->def['multilang']) && !empty($this->def['multilang_shop']); - } + /** + * Checks if the object is both multi-language and multi-shop. + * + * @return bool + */ + public function isLangMultishop() + { + return !empty($this->def['multilang']) && !empty($this->def['multilang_shop']); + } - /** - * Updates a table and splits the common datas and the shop datas. - * - * @since 1.5.0.1 - * @param string $classname - * @param array $data - * @param string $where - * @param string $specific_where Only executed for common table - * - * @return bool - */ - public static function updateMultishopTable($classname, $data, $where = '', $specific_where = '') - { - $def = ObjectModel::getDefinition($classname); - $update_data = array(); - foreach ($data as $field => $value) - { - if (!isset($def['fields'][$field])) - continue; + /** + * Updates a table and splits the common datas and the shop datas. + * + * @since 1.5.0.1 + * @param string $classname + * @param array $data + * @param string $where + * @param string $specific_where Only executed for common table + * + * @return bool + */ + public static function updateMultishopTable($classname, $data, $where = '', $specific_where = '') + { + $def = ObjectModel::getDefinition($classname); + $update_data = array(); + foreach ($data as $field => $value) { + if (!isset($def['fields'][$field])) { + continue; + } - if (!empty($def['fields'][$field]['shop'])) - { - if ($value === null && !empty($def['fields'][$field]['allow_null'])) - { - $update_data[] = "a.$field = NULL"; - $update_data[] = "{$def['table']}_shop.$field = NULL"; - } - else - { - $update_data[] = "a.$field = '$value'"; - $update_data[] = "{$def['table']}_shop.$field = '$value'"; - } - } - else - { - if ($value === null && !empty($def['fields'][$field]['allow_null'])) - $update_data[] = "a.$field = NULL"; - else - $update_data[] = "a.$field = '$value'"; - } - } + if (!empty($def['fields'][$field]['shop'])) { + if ($value === null && !empty($def['fields'][$field]['allow_null'])) { + $update_data[] = "a.$field = NULL"; + $update_data[] = "{$def['table']}_shop.$field = NULL"; + } else { + $update_data[] = "a.$field = '$value'"; + $update_data[] = "{$def['table']}_shop.$field = '$value'"; + } + } else { + if ($value === null && !empty($def['fields'][$field]['allow_null'])) { + $update_data[] = "a.$field = NULL"; + } else { + $update_data[] = "a.$field = '$value'"; + } + } + } - $sql = 'UPDATE '._DB_PREFIX_.$def['table'].' a + $sql = 'UPDATE '._DB_PREFIX_.$def['table'].' a '.Shop::addSqlAssociation($def['table'], 'a', true, null, true).' SET '.implode(', ', $update_data). - (!empty($where) ? ' WHERE '.$where : ''); + (!empty($where) ? ' WHERE '.$where : ''); - return Db::getInstance()->execute($sql); - } + return Db::getInstance()->execute($sql); + } - /** - * Delete images associated with the object - * - * @param bool $force_delete - * - * @return bool - */ - public function deleteImage($force_delete = false) - { - if (!$this->id) - return false; + /** + * Delete images associated with the object + * + * @param bool $force_delete + * + * @return bool + */ + public function deleteImage($force_delete = false) + { + if (!$this->id) { + return false; + } - if ($force_delete || !$this->hasMultishopEntries()) - { - /* Deleting object images and thumbnails (cache) */ - if ($this->image_dir) - { - if (file_exists($this->image_dir.$this->id.'.'.$this->image_format) - && !unlink($this->image_dir.$this->id.'.'.$this->image_format)) - return false; - } - if (file_exists(_PS_TMP_IMG_DIR_.$this->def['table'].'_'.$this->id.'.'.$this->image_format) - && !unlink(_PS_TMP_IMG_DIR_.$this->def['table'].'_'.$this->id.'.'.$this->image_format)) - return false; - if (file_exists(_PS_TMP_IMG_DIR_.$this->def['table'].'_mini_'.$this->id.'.'.$this->image_format) - && !unlink(_PS_TMP_IMG_DIR_.$this->def['table'].'_mini_'.$this->id.'.'.$this->image_format)) - return false; + if ($force_delete || !$this->hasMultishopEntries()) { + /* Deleting object images and thumbnails (cache) */ + if ($this->image_dir) { + if (file_exists($this->image_dir.$this->id.'.'.$this->image_format) + && !unlink($this->image_dir.$this->id.'.'.$this->image_format)) { + return false; + } + } + if (file_exists(_PS_TMP_IMG_DIR_.$this->def['table'].'_'.$this->id.'.'.$this->image_format) + && !unlink(_PS_TMP_IMG_DIR_.$this->def['table'].'_'.$this->id.'.'.$this->image_format)) { + return false; + } + if (file_exists(_PS_TMP_IMG_DIR_.$this->def['table'].'_mini_'.$this->id.'.'.$this->image_format) + && !unlink(_PS_TMP_IMG_DIR_.$this->def['table'].'_mini_'.$this->id.'.'.$this->image_format)) { + return false; + } - $types = ImageType::getImagesTypes(); - foreach ($types as $image_type) - if (file_exists($this->image_dir.$this->id.'-'.stripslashes($image_type['name']).'.'.$this->image_format) - && !unlink($this->image_dir.$this->id.'-'.stripslashes($image_type['name']).'.'.$this->image_format)) - return false; - } + $types = ImageType::getImagesTypes(); + foreach ($types as $image_type) { + if (file_exists($this->image_dir.$this->id.'-'.stripslashes($image_type['name']).'.'.$this->image_format) + && !unlink($this->image_dir.$this->id.'-'.stripslashes($image_type['name']).'.'.$this->image_format)) { + return false; + } + } + } - return true; - } + return true; + } - /** - * Checks if an object exists in database. - * - * @param int $id_entity - * @param string $table - * - * @return bool - */ - public static function existsInDatabase($id_entity, $table) - { - $row = Db::getInstance()->getRow(' + /** + * Checks if an object exists in database. + * + * @param int $id_entity + * @param string $table + * + * @return bool + */ + public static function existsInDatabase($id_entity, $table) + { + $row = Db::getInstance()->getRow(' SELECT `id_'.bqSQL($table).'` as id FROM `'._DB_PREFIX_.bqSQL($table).'` e WHERE e.`id_'.bqSQL($table).'` = '.(int)$id_entity, false - ); + ); - return isset($row['id']); - } + return isset($row['id']); + } - /** - * Checks if an object type exists in the database. - * - * @since 1.5.0.1 - * @param string|null $table Name of table linked to entity - * @param bool $has_active_column True if the table has an active column - * - * @return bool - */ - public static function isCurrentlyUsed($table = null, $has_active_column = false) - { - if ($table === null) - $table = self::$definition['table']; + /** + * Checks if an object type exists in the database. + * + * @since 1.5.0.1 + * @param string|null $table Name of table linked to entity + * @param bool $has_active_column True if the table has an active column + * + * @return bool + */ + public static function isCurrentlyUsed($table = null, $has_active_column = false) + { + if ($table === null) { + $table = self::$definition['table']; + } - $query = new DbQuery(); - $query->select('`id_'.bqSQL($table).'`'); - $query->from($table); - if ($has_active_column) - $query->where('`active` = 1'); + $query = new DbQuery(); + $query->select('`id_'.bqSQL($table).'`'); + $query->from($table); + if ($has_active_column) { + $query->where('`active` = 1'); + } - return (bool)Db::getInstance()->getValue($query); - } + return (bool)Db::getInstance()->getValue($query); + } - /** - * Fill an object with given data. Data must be an array with this syntax: - * array(objProperty => value, objProperty2 => value, etc.) - * - * @since 1.5.0.1 - * @param array $data - * @param int|null $id_lang - */ - public function hydrate(array $data, $id_lang = null) - { - $this->id_lang = $id_lang; - if (isset($data[$this->def['primary']])) - $this->id = $data[$this->def['primary']]; + /** + * Fill an object with given data. Data must be an array with this syntax: + * array(objProperty => value, objProperty2 => value, etc.) + * + * @since 1.5.0.1 + * @param array $data + * @param int|null $id_lang + */ + public function hydrate(array $data, $id_lang = null) + { + $this->id_lang = $id_lang; + if (isset($data[$this->def['primary']])) { + $this->id = $data[$this->def['primary']]; + } - foreach ($data as $key => $value) - if (array_key_exists($key, $this)) - $this->$key = $value; - } + foreach ($data as $key => $value) { + if (array_key_exists($key, $this)) { + $this->$key = $value; + } + } + } - /** - * Fill (hydrate) a list of objects in order to get a collection of these objects - * - * @since 1.5.0.1 - * @param string $class Class of objects to hydrate - * @param array $datas List of data (multi-dimensional array) - * @param int|null $id_lang - * - * @return array - * @throws PrestaShopException - */ - public static function hydrateCollection($class, array $datas, $id_lang = null) - { - if (!class_exists($class)) - throw new PrestaShopException("Class '$class' not found"); + /** + * Fill (hydrate) a list of objects in order to get a collection of these objects + * + * @since 1.5.0.1 + * @param string $class Class of objects to hydrate + * @param array $datas List of data (multi-dimensional array) + * @param int|null $id_lang + * + * @return array + * @throws PrestaShopException + */ + public static function hydrateCollection($class, array $datas, $id_lang = null) + { + if (!class_exists($class)) { + throw new PrestaShopException("Class '$class' not found"); + } - $collection = array(); - $rows = array(); - if ($datas) - { - $definition = ObjectModel::getDefinition($class); - if (!array_key_exists($definition['primary'], $datas[0])) - throw new PrestaShopException("Identifier '{$definition['primary']}' not found for class '$class'"); + $collection = array(); + $rows = array(); + if ($datas) { + $definition = ObjectModel::getDefinition($class); + if (!array_key_exists($definition['primary'], $datas[0])) { + throw new PrestaShopException("Identifier '{$definition['primary']}' not found for class '$class'"); + } - foreach ($datas as $row) - { - // Get object common properties - $id = $row[$definition['primary']]; - if (!isset($rows[$id])) - $rows[$id] = $row; + foreach ($datas as $row) { + // Get object common properties + $id = $row[$definition['primary']]; + if (!isset($rows[$id])) { + $rows[$id] = $row; + } - // Get object lang properties - if (isset($row['id_lang']) && !$id_lang) - foreach ($definition['fields'] as $field => $data) - if (!empty($data['lang'])) - { - if (!is_array($rows[$id][$field])) - $rows[$id][$field] = array(); - $rows[$id][$field][$row['id_lang']] = $row[$field]; - } - } - } + // Get object lang properties + if (isset($row['id_lang']) && !$id_lang) { + foreach ($definition['fields'] as $field => $data) { + if (!empty($data['lang'])) { + if (!is_array($rows[$id][$field])) { + $rows[$id][$field] = array(); + } + $rows[$id][$field][$row['id_lang']] = $row[$field]; + } + } + } + } + } - // Hydrate objects - foreach ($rows as $row) - { - /** @var ObjectModel $obj */ - $obj = new $class; - $obj->hydrate($row, $id_lang); - $collection[] = $obj; - } + // Hydrate objects + foreach ($rows as $row) { + /** @var ObjectModel $obj */ + $obj = new $class; + $obj->hydrate($row, $id_lang); + $collection[] = $obj; + } - return $collection; - } + return $collection; + } - /** - * Returns object definition - * - * @param string $class Name of object - * @param string|null $field Name of field if we want the definition of one field only - * - * @return array - */ - public static function getDefinition($class, $field = null) - { - if (is_object($class)) - $class = get_class($class); + /** + * Returns object definition + * + * @param string $class Name of object + * @param string|null $field Name of field if we want the definition of one field only + * + * @return array + */ + public static function getDefinition($class, $field = null) + { + if (is_object($class)) { + $class = get_class($class); + } - if ($field === null) - $cache_id = 'objectmodel_def_'.$class; + if ($field === null) { + $cache_id = 'objectmodel_def_'.$class; + } - if ($field !== null || !Cache::isStored($cache_id)) - { - $reflection = new ReflectionClass($class); - $definition = $reflection->getStaticPropertyValue('definition'); + if ($field !== null || !Cache::isStored($cache_id)) { + $reflection = new ReflectionClass($class); - $definition['classname'] = $class; + if (!$reflection->hasProperty('definition')) { + return false; + } - if (!empty($definition['multilang'])) - $definition['associations'][PrestaShopCollection::LANG_ALIAS] = array( - 'type' => self::HAS_MANY, - 'field' => $definition['primary'], - 'foreign_field' => $definition['primary'], - ); + $definition = $reflection->getStaticPropertyValue('definition'); - if ($field) - return isset($definition['fields'][$field]) ? $definition['fields'][$field] : null; + $definition['classname'] = $class; - Cache::store($cache_id, $definition); - return $definition; - } + if (!empty($definition['multilang'])) { + $definition['associations'][PrestaShopCollection::LANG_ALIAS] = array( + 'type' => self::HAS_MANY, + 'field' => $definition['primary'], + 'foreign_field' => $definition['primary'], + ); + } - return Cache::retrieve($cache_id); - } + if ($field) { + return isset($definition['fields'][$field]) ? $definition['fields'][$field] : null; + } - /** - * Retrocompatibility for classes without $definition static - * @TODO Remove this in 1.6 ! - * - * @since 1.5.0.1 - */ - protected function setDefinitionRetrocompatibility() - { - // Retrocompatibility with $table property ($definition['table']) - if (isset($this->def['table'])) - $this->table = $this->def['table']; - else - $this->def['table'] = $this->table; + Cache::store($cache_id, $definition); + return $definition; + } - // Retrocompatibility with $identifier property ($definition['primary']) - if (isset($this->def['primary'])) - $this->identifier = $this->def['primary']; - else - $this->def['primary'] = $this->identifier; + return Cache::retrieve($cache_id); + } - // Check multilang retrocompatibility - if (method_exists($this, 'getTranslationsFieldsChild')) - $this->def['multilang'] = true; + /** + * Retrocompatibility for classes without $definition static + * @TODO Remove this in 1.6 ! + * + * @since 1.5.0.1 + */ + protected function setDefinitionRetrocompatibility() + { + // Retrocompatibility with $table property ($definition['table']) + if (isset($this->def['table'])) { + $this->table = $this->def['table']; + } else { + $this->def['table'] = $this->table; + } - // Retrocompatibility with $fieldsValidate, $fieldsRequired and $fieldsSize properties ($definition['fields']) - if (isset($this->def['fields'])) - { - foreach ($this->def['fields'] as $field => $data) - { - $suffix = (isset($data['lang']) && $data['lang']) ? 'Lang' : ''; - if (isset($data['validate'])) - $this->{'fieldsValidate'.$suffix}[$field] = $data['validate']; - if (isset($data['required']) && $data['required']) - $this->{'fieldsRequired'.$suffix}[] = $field; - if (isset($data['size'])) - $this->{'fieldsSize'.$suffix}[$field] = $data['size']; - } - } - else - { - $this->def['fields'] = array(); - $suffixs = array('', 'Lang'); - foreach ($suffixs as $suffix) - { - foreach ($this->{'fieldsValidate'.$suffix} as $field => $validate) - { - $this->def['fields'][$field]['validate'] = $validate; - if ($suffix == 'Lang') - $this->def['fields'][$field]['lang'] = true; - } - foreach ($this->{'fieldsRequired'.$suffix} as $field) - { - $this->def['fields'][$field]['required'] = true; - if ($suffix == 'Lang') - $this->def['fields'][$field]['lang'] = true; - } - foreach ($this->{'fieldsSize'.$suffix} as $field => $size) - { - $this->def['fields'][$field]['size'] = $size; - if ($suffix == 'Lang') - $this->def['fields'][$field]['lang'] = true; - } - } - } - } + // Retrocompatibility with $identifier property ($definition['primary']) + if (isset($this->def['primary'])) { + $this->identifier = $this->def['primary']; + } else { + $this->def['primary'] = $this->identifier; + } - /** - * Return the field value for the specified language if the field is multilang, - * else the field value. - * - * @since 1.5.0.1 - * @param string $field_name - * @param int|null $id_lang - * - * @return mixed - * @throws PrestaShopException - */ - public function getFieldByLang($field_name, $id_lang = null) - { - $definition = ObjectModel::getDefinition($this); - // Is field in definition? - if ($definition && isset($definition['fields'][$field_name])) - { - $field = $definition['fields'][$field_name]; - // Is field multilang? - if (isset($field['lang']) && $field['lang']) - { - if (is_array($this->{$field_name})) - return $this->{$field_name}[$id_lang ? $id_lang : Context::getContext()->language->id]; - } - return $this->{$field_name}; - } - else - throw new PrestaShopException('Could not load field from definition.'); - } + // Check multilang retrocompatibility + if (method_exists($this, 'getTranslationsFieldsChild')) { + $this->def['multilang'] = true; + } - /** - * Set a list of specific fields to update - * array(field1 => true, field2 => false, - * langfield1 => array(1 => true, 2 => false)) - * - * @since 1.5.0.1 - * @param array $fields - */ - public function setFieldsToUpdate(array $fields) - { - $this->update_fields = $fields; - } + // Retrocompatibility with $fieldsValidate, $fieldsRequired and $fieldsSize properties ($definition['fields']) + if (isset($this->def['fields'])) { + foreach ($this->def['fields'] as $field => $data) { + $suffix = (isset($data['lang']) && $data['lang']) ? 'Lang' : ''; + if (isset($data['validate'])) { + $this->{'fieldsValidate'.$suffix}[$field] = $data['validate']; + } + if (isset($data['required']) && $data['required']) { + $this->{'fieldsRequired'.$suffix}[] = $field; + } + if (isset($data['size'])) { + $this->{'fieldsSize'.$suffix}[$field] = $data['size']; + } + } + } else { + $this->def['fields'] = array(); + $suffixs = array('', 'Lang'); + foreach ($suffixs as $suffix) { + foreach ($this->{'fieldsValidate'.$suffix} as $field => $validate) { + $this->def['fields'][$field]['validate'] = $validate; + if ($suffix == 'Lang') { + $this->def['fields'][$field]['lang'] = true; + } + } + foreach ($this->{'fieldsRequired'.$suffix} as $field) { + $this->def['fields'][$field]['required'] = true; + if ($suffix == 'Lang') { + $this->def['fields'][$field]['lang'] = true; + } + } + foreach ($this->{'fieldsSize'.$suffix} as $field => $size) { + $this->def['fields'][$field]['size'] = $size; + if ($suffix == 'Lang') { + $this->def['fields'][$field]['lang'] = true; + } + } + } + } + } - /** - * Enables object caching - */ - public static function enableCache() - { - ObjectModel::$cache_objects = true; - } + /** + * Return the field value for the specified language if the field is multilang, + * else the field value. + * + * @since 1.5.0.1 + * @param string $field_name + * @param int|null $id_lang + * + * @return mixed + * @throws PrestaShopException + */ + public function getFieldByLang($field_name, $id_lang = null) + { + $definition = ObjectModel::getDefinition($this); + // Is field in definition? + if ($definition && isset($definition['fields'][$field_name])) { + $field = $definition['fields'][$field_name]; + // Is field multilang? + if (isset($field['lang']) && $field['lang']) { + if (is_array($this->{$field_name})) { + return $this->{$field_name}[$id_lang ? $id_lang : Context::getContext()->language->id]; + } + } + return $this->{$field_name}; + } else { + throw new PrestaShopException('Could not load field from definition.'); + } + } - /** - * Disables object caching - */ - public static function disableCache() - { - ObjectModel::$cache_objects = false; - } + /** + * Set a list of specific fields to update + * array(field1 => true, field2 => false, + * langfield1 => array(1 => true, 2 => false)) + * + * @since 1.5.0.1 + * @param array $fields + */ + public function setFieldsToUpdate(array $fields) + { + $this->update_fields = $fields; + } + + /** + * Enables object caching + */ + public static function enableCache() + { + ObjectModel::$cache_objects = true; + } + + /** + * Disables object caching + */ + public static function disableCache() + { + ObjectModel::$cache_objects = false; + } } diff --git a/classes/Pack.php b/classes/Pack.php index 4b16aae6..8713ace2 100644 --- a/classes/Pack.php +++ b/classes/Pack.php @@ -26,92 +26,108 @@ class PackCore extends Product { - protected static $cachePackItems = array(); - protected static $cacheIsPack = array(); - protected static $cacheIsPacked = array(); + protected static $cachePackItems = array(); + protected static $cacheIsPack = array(); + protected static $cacheIsPacked = array(); - /** - * Is product a pack? - * - * @param $id_product - * @return bool - */ - public static function isPack($id_product) - { - if (!Pack::isFeatureActive()) - return false; + /** + * Is product a pack? + * + * @param $id_product + * @return bool + */ + public static function isPack($id_product) + { + if (!Pack::isFeatureActive()) { + return false; + } - if (!$id_product) - return false; + if (!$id_product) { + return false; + } - if (!array_key_exists($id_product, self::$cacheIsPack)) - { - $result = Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'pack` WHERE id_product_pack = '.(int)$id_product); - self::$cacheIsPack[$id_product] = ($result > 0); - } - return self::$cacheIsPack[$id_product]; - } + if (!array_key_exists($id_product, self::$cacheIsPack)) { + $result = Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'pack` WHERE id_product_pack = '.(int)$id_product); + self::$cacheIsPack[$id_product] = ($result > 0); + } + return self::$cacheIsPack[$id_product]; + } - /** - * Is product in a pack? - * - * @param $id_product - * @return bool - */ - public static function isPacked($id_product) - { - if (!Pack::isFeatureActive()) - return false; + /** + * Is product in a pack? + * If $id_product_attribute specified, then will restrict search on the given combination, + * else this method will match a product if at least one of all its combination is in a pack. + * + * @param $id_product + * @param $id_product_attribute Optional combination of the product + * @return bool + */ + public static function isPacked($id_product, $id_product_attribute = false) + { + + + if (!Pack::isFeatureActive()) { + return false; + } + if ($id_product_attribute === false) { + $cache_key = $id_product.'-0'; + if (!array_key_exists($cache_key, self::$cacheIsPacked)) { + $result = Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'pack` WHERE id_product_item = '.(int)$id_product); + self::$cacheIsPacked[$cache_key] = ($result > 0); + } + return self::$cacheIsPacked[$cache_key]; + } else { + $cache_key = $id_product.'-'.$id_product_attribute; + if (!array_key_exists($cache_key, self::$cacheIsPacked)) { + $result = Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'pack` WHERE id_product_item = '.((int)$id_product).' AND + id_product_attribute_item = '.((int)$id_product_attribute)); + self::$cacheIsPacked[$cache_key] = ($result > 0); + } + return self::$cacheIsPacked[$cache_key]; + } + } - if (!array_key_exists($id_product, self::$cacheIsPacked)) - { - $result = Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'pack` WHERE id_product_item = '.(int)$id_product); - self::$cacheIsPacked[$id_product] = ($result > 0); - } - return self::$cacheIsPacked[$id_product]; - } + public static function noPackPrice($id_product) + { + $sum = 0; + $price_display_method = !self::$_taxCalculationMethod; + $items = Pack::getItems($id_product, Configuration::get('PS_LANG_DEFAULT')); + foreach ($items as $item) { + /** @var Product $item */ + $sum += $item->getPrice($price_display_method) * $item->pack_quantity; + } - public static function noPackPrice($id_product) - { - $sum = 0; - $price_display_method = !self::$_taxCalculationMethod; - $items = Pack::getItems($id_product, Configuration::get('PS_LANG_DEFAULT')); - foreach ($items as $item) - { - /** @var Product $item */ - $sum += $item->getPrice($price_display_method) * $item->pack_quantity; - } + return $sum; + } - return $sum; - } + public static function noPackWholesalePrice($id_product) + { + $sum = 0; + $items = Pack::getItems($id_product, Configuration::get('PS_LANG_DEFAULT')); + foreach ($items as $item) { + $sum += $item->wholesale_price * $item->pack_quantity; + } + return $sum; + } - public static function noPackWholesalePrice($id_product) - { - $sum = 0; - $items = Pack::getItems($id_product, Configuration::get('PS_LANG_DEFAULT')); - foreach ($items as $item) - $sum += $item->wholesale_price * $item->pack_quantity; - return $sum; - } + public static function getItems($id_product, $id_lang) + { + if (!Pack::isFeatureActive()) { + return array(); + } - public static function getItems($id_product, $id_lang) - { - if (!Pack::isFeatureActive()) - return array(); - - if (array_key_exists($id_product, self::$cachePackItems)) - return self::$cachePackItems[$id_product]; - $result = Db::getInstance()->executeS('SELECT id_product_item, id_product_attribute_item, quantity FROM `'._DB_PREFIX_.'pack` where id_product_pack = '.(int)$id_product); - $array_result = array(); - foreach ($result as $row) - { - $p = new Product($row['id_product_item'], false, $id_lang); - $p->loadStockData(); - $p->pack_quantity = $row['quantity']; - $p->id_pack_product_attribute = (isset($row['id_product_attribute_item']) && $row['id_product_attribute_item'] ? $row['id_product_attribute_item'] : 0); - if (isset($row['id_product_attribute_item']) && $row['id_product_attribute_item']) - { - $sql = 'SELECT agl.`name` AS group_name, al.`name` AS attribute_name + if (array_key_exists($id_product, self::$cachePackItems)) { + return self::$cachePackItems[$id_product]; + } + $result = Db::getInstance()->executeS('SELECT id_product_item, id_product_attribute_item, quantity FROM `'._DB_PREFIX_.'pack` where id_product_pack = '.(int)$id_product); + $array_result = array(); + foreach ($result as $row) { + $p = new Product($row['id_product_item'], false, $id_lang); + $p->loadStockData(); + $p->pack_quantity = $row['quantity']; + $p->id_pack_product_attribute = (isset($row['id_product_attribute_item']) && $row['id_product_attribute_item'] ? $row['id_product_attribute_item'] : 0); + if (isset($row['id_product_attribute_item']) && $row['id_product_attribute_item']) { + $sql = 'SELECT agl.`name` AS group_name, al.`name` AS attribute_name FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON pac.`id_product_attribute` = pa.`id_product_attribute` @@ -123,41 +139,44 @@ class PackCore extends Product GROUP BY pa.`id_product_attribute`, ag.`id_attribute_group` ORDER BY pa.`id_product_attribute`'; - $combinations = Db::getInstance()->executeS($sql); - foreach ($combinations as $k => $combination) - $p->name .= ' '.$combination['group_name'].'-'.$combination['attribute_name']; - } - $array_result[] = $p; - } - self::$cachePackItems[$id_product] = $array_result; - return self::$cachePackItems[$id_product]; - } + $combinations = Db::getInstance()->executeS($sql); + foreach ($combinations as $k => $combination) { + $p->name .= ' '.$combination['group_name'].'-'.$combination['attribute_name']; + } + } + $array_result[] = $p; + } + self::$cachePackItems[$id_product] = $array_result; + return self::$cachePackItems[$id_product]; + } - public static function isInStock($id_product) - { - if (!Pack::isFeatureActive()) - return true; + public static function isInStock($id_product) + { + if (!Pack::isFeatureActive()) { + return true; + } - $items = Pack::getItems((int)$id_product, Configuration::get('PS_LANG_DEFAULT')); + $items = Pack::getItems((int)$id_product, Configuration::get('PS_LANG_DEFAULT')); - foreach ($items as $item) - { - /** @var Product $item */ - // Updated for 1.5.0 - if (Product::getQuantity($item->id) < $item->pack_quantity && !$item->isAvailableWhenOutOfStock((int)$item->out_of_stock)) - return false; - } - return true; - } + foreach ($items as $item) { + /** @var Product $item */ + // Updated for 1.5.0 + if (Product::getQuantity($item->id) < $item->pack_quantity && !$item->isAvailableWhenOutOfStock((int)$item->out_of_stock)) { + return false; + } + } + return true; + } - public static function getItemTable($id_product, $id_lang, $full = false) - { - if (!Pack::isFeatureActive()) - return array(); + public static function getItemTable($id_product, $id_lang, $full = false) + { + if (!Pack::isFeatureActive()) { + return array(); + } - $context = Context::getContext(); + $context = Context::getContext(); - $sql = 'SELECT p.*, product_shop.*, pl.*, image_shop.`id_image` id_image, il.`legend`, cl.`name` AS category_default, a.quantity AS pack_quantity, product_shop.`id_category_default`, a.id_product_pack, a.id_product_attribute_item + $sql = 'SELECT p.*, product_shop.*, pl.*, image_shop.`id_image` id_image, il.`legend`, cl.`name` AS category_default, a.quantity AS pack_quantity, product_shop.`id_category_default`, a.id_product_pack, a.id_product_attribute_item FROM `'._DB_PREFIX_.'pack` a LEFT JOIN `'._DB_PREFIX_.'product` p ON p.id_product = a.id_product_item LEFT JOIN `'._DB_PREFIX_.'product_lang` pl @@ -174,15 +193,13 @@ class PackCore extends Product AND a.`id_product_pack` = '.(int)$id_product.' GROUP BY a.`id_product_item`, a.`id_product_attribute_item`'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - foreach ($result as &$line) - { - if (Combination::isFeatureActive() && isset($line['id_product_attribute_item']) && $line['id_product_attribute_item']) - { - $line['cache_default_attribute'] = $line['id_product_attribute'] = $line['id_product_attribute_item']; + foreach ($result as &$line) { + if (Combination::isFeatureActive() && isset($line['id_product_attribute_item']) && $line['id_product_attribute_item']) { + $line['cache_default_attribute'] = $line['id_product_attribute'] = $line['id_product_attribute_item']; - $sql = 'SELECT agl.`name` AS group_name, al.`name` AS attribute_name, pai.`id_image` AS id_product_attribute_image + $sql = 'SELECT agl.`name` AS group_name, al.`name` AS attribute_name, pai.`id_image` AS id_product_attribute_image FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON pac.`id_product_attribute` = '.$line['id_product_attribute_item'].' @@ -195,46 +212,51 @@ class PackCore extends Product GROUP BY pa.`id_product_attribute`, ag.`id_attribute_group` ORDER BY pa.`id_product_attribute`'; - $attr_name = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + $attr_name = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - if (isset($attr_name[0]['id_product_attribute_image']) && $attr_name[0]['id_product_attribute_image']) - $line['id_image'] = $attr_name[0]['id_product_attribute_image']; - $line['name'] .= "\n"; - foreach ($attr_name as $value) - $line['name'] .= ' '.$value['group_name'].'-'.$value['attribute_name']; - } - $line = Product::getTaxesInformations($line); - } + if (isset($attr_name[0]['id_product_attribute_image']) && $attr_name[0]['id_product_attribute_image']) { + $line['id_image'] = $attr_name[0]['id_product_attribute_image']; + } + $line['name'] .= "\n"; + foreach ($attr_name as $value) { + $line['name'] .= ' '.$value['group_name'].'-'.$value['attribute_name']; + } + } + $line = Product::getTaxesInformations($line); + } - if (!$full) - return $result; + if (!$full) { + return $result; + } - $array_result = array(); - foreach ($result as $prow) - if (!Pack::isPack($prow['id_product'])) - { - $prow['id_product_attribute'] = (int)$prow['id_product_attribute_item']; - $array_result[] = Product::getProductProperties($id_lang, $prow); - } - return $array_result; - } + $array_result = array(); + foreach ($result as $prow) { + if (!Pack::isPack($prow['id_product'])) { + $prow['id_product_attribute'] = (int)$prow['id_product_attribute_item']; + $array_result[] = Product::getProductProperties($id_lang, $prow); + } + } + return $array_result; + } - public static function getPacksTable($id_product, $id_lang, $full = false, $limit = null) - { - if (!Pack::isFeatureActive()) - return array(); + public static function getPacksTable($id_product, $id_lang, $full = false, $limit = null) + { + if (!Pack::isFeatureActive()) { + return array(); + } - $packs = Db::getInstance()->getValue(' + $packs = Db::getInstance()->getValue(' SELECT GROUP_CONCAT(a.`id_product_pack`) FROM `'._DB_PREFIX_.'pack` a WHERE a.`id_product_item` = '.(int)$id_product); - if (!(int)$packs) - return array(); + if (!(int)$packs) { + return array(); + } - $context = Context::getContext(); + $context = Context::getContext(); - $sql = ' + $sql = ' SELECT p.*, product_shop.*, pl.*, image_shop.`id_image` id_image, il.`legend`, IFNULL(product_attribute_shop.id_product_attribute, 0) id_product_attribute FROM `'._DB_PREFIX_.'product` p NATURAL LEFT JOIN `'._DB_PREFIX_.'product_lang` pl @@ -248,125 +270,161 @@ class PackCore extends Product '.Shop::addSqlRestrictionOnLang('pl').' AND p.`id_product` IN ('.$packs.') GROUP BY p.id_product'; - if ($limit) - $sql .= ' LIMIT '.(int)$limit; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - if (!$full) - return $result; + if ($limit) { + $sql .= ' LIMIT '.(int)$limit; + } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + if (!$full) { + return $result; + } - $array_result = array(); - foreach ($result as $row) - if (!Pack::isPacked($row['id_product'])) - $array_result[] = Product::getProductProperties($id_lang, $row); - return $array_result; - } + $array_result = array(); + foreach ($result as $row) { + if (!Pack::isPacked($row['id_product'])) { + $array_result[] = Product::getProductProperties($id_lang, $row); + } + } + return $array_result; + } - public static function deleteItems($id_product) - { - return Db::getInstance()->update('product', array('cache_is_pack' => 0), 'id_product = '.(int)$id_product) && - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'pack` WHERE `id_product_pack` = '.(int)$id_product) && - Configuration::updateGlobalValue('PS_PACK_FEATURE_ACTIVE', Pack::isCurrentlyUsed()); - } + public static function deleteItems($id_product) + { + return Db::getInstance()->update('product', array('cache_is_pack' => 0), 'id_product = '.(int)$id_product) && + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'pack` WHERE `id_product_pack` = '.(int)$id_product) && + Configuration::updateGlobalValue('PS_PACK_FEATURE_ACTIVE', Pack::isCurrentlyUsed()); + } - /** - * Add an item to the pack - * - * @param int $id_product - * @param int $id_item - * @param int $qty - * @param int $id_attribute_item - * @return bool true if everything was fine - * @throws PrestaShopDatabaseException - */ - public static function addItem($id_product, $id_item, $qty, $id_attribute_item = 0) - { - $id_attribute_item = (int)$id_attribute_item ? (int)$id_attribute_item : Product::getDefaultAttribute((int)$id_item); - return Db::getInstance()->update('product', array('cache_is_pack' => 1), 'id_product = '.(int)$id_product) && - Db::getInstance()->insert('pack', array( - 'id_product_pack' => (int)$id_product, - 'id_product_item' => (int)$id_item, - 'id_product_attribute_item' => (int)$id_attribute_item, - 'quantity' => (int)$qty - )) - && Configuration::updateGlobalValue('PS_PACK_FEATURE_ACTIVE', '1'); - } + /** + * Add an item to the pack + * + * @param int $id_product + * @param int $id_item + * @param int $qty + * @param int $id_attribute_item + * @return bool true if everything was fine + * @throws PrestaShopDatabaseException + */ + public static function addItem($id_product, $id_item, $qty, $id_attribute_item = 0) + { + $id_attribute_item = (int)$id_attribute_item ? (int)$id_attribute_item : Product::getDefaultAttribute((int)$id_item); + return Db::getInstance()->update('product', array('cache_is_pack' => 1), 'id_product = '.(int)$id_product) && + Db::getInstance()->insert('pack', array( + 'id_product_pack' => (int)$id_product, + 'id_product_item' => (int)$id_item, + 'id_product_attribute_item' => (int)$id_attribute_item, + 'quantity' => (int)$qty + )) + && Configuration::updateGlobalValue('PS_PACK_FEATURE_ACTIVE', '1'); + } - public static function duplicate($id_product_old, $id_product_new) - { - Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'pack` (`id_product_pack`, `id_product_item`, `id_product_attribute_item`, `quantity`) + public static function duplicate($id_product_old, $id_product_new) + { + Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'pack` (`id_product_pack`, `id_product_item`, `id_product_attribute_item`, `quantity`) (SELECT '.(int)$id_product_new.', `id_product_item`, `id_product_attribute_item`, `quantity` FROM `'._DB_PREFIX_.'pack` WHERE `id_product_pack` = '.(int)$id_product_old.')'); - // If return query result, a non-pack product will return false - return true; - } + // If return query result, a non-pack product will return false + return true; + } - /** - * This method is allow to know if a feature is used or active - * @since 1.5.0.1 - * @return bool - */ - public static function isFeatureActive() - { - return Configuration::get('PS_PACK_FEATURE_ACTIVE'); - } + /** + * This method is allow to know if a feature is used or active + * @since 1.5.0.1 + * @return bool + */ + public static function isFeatureActive() + { + return Configuration::get('PS_PACK_FEATURE_ACTIVE'); + } - /** - * This method is allow to know if a Pack entity is currently used - * @since 1.5.0 - * @param $table - * @param $has_active_column - * @return bool - */ - public static function isCurrentlyUsed($table = null, $has_active_column = false) - { - // We dont't use the parent method because the identifier isn't id_pack - return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * This method is allow to know if a Pack entity is currently used + * @since 1.5.0 + * @param $table + * @param $has_active_column + * @return bool + */ + public static function isCurrentlyUsed($table = null, $has_active_column = false) + { + // We dont't use the parent method because the identifier isn't id_pack + return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_product_pack` FROM `'._DB_PREFIX_.'pack` '); - } + } - /** - * For a given pack, tells if it has at least one product using the advanced stock management - * - * @param int $id_product id_pack - * @return bool - */ - public static function usesAdvancedStockManagement($id_product) - { - if (!Pack::isPack($id_product)) - return false; + /** + * For a given pack, tells if it has at least one product using the advanced stock management + * + * @param int $id_product id_pack + * @return bool + */ + public static function usesAdvancedStockManagement($id_product) + { + if (!Pack::isPack($id_product)) { + return false; + } - $products = Pack::getItems($id_product, Configuration::get('PS_LANG_DEFAULT')); - foreach ($products as $product) - { - // if one product uses the advanced stock management - if ($product->advanced_stock_management == 1) - return true; - } - // not used - return false; - } + $products = Pack::getItems($id_product, Configuration::get('PS_LANG_DEFAULT')); + foreach ($products as $product) { + // if one product uses the advanced stock management + if ($product->advanced_stock_management == 1) { + return true; + } + } + // not used + return false; + } - /** - * For a given pack, tells if all products using the advanced stock management - * - * @param int $id_product id_pack - * @return bool - */ - public static function allUsesAdvancedStockManagement($id_product) - { - if (!Pack::isPack($id_product)) - return false; + /** + * For a given pack, tells if all products using the advanced stock management + * + * @param int $id_product id_pack + * @return bool + */ + public static function allUsesAdvancedStockManagement($id_product) + { + if (!Pack::isPack($id_product)) { + return false; + } - $products = Pack::getItems($id_product, Configuration::get('PS_LANG_DEFAULT')); - foreach ($products as $product) - { - // if one product uses the advanced stock management - if ($product->advanced_stock_management == 0) - return false; - } - // not used - return true; - } + $products = Pack::getItems($id_product, Configuration::get('PS_LANG_DEFAULT')); + foreach ($products as $product) { + // if one product uses the advanced stock management + if ($product->advanced_stock_management == 0) { + return false; + } + } + // not used + return true; + } + + /** + * Returns Packs that conatins the given product in the right declinaison. + * + * @param integer $id_item Product item id that could be contained in a|many pack(s) + * @param integer $id_attribute_item The declinaison of the product + * @param integer $id_lang + * @return array[Product] Packs that contains the given product + */ + public static function getPacksContainingItem($id_item, $id_attribute_item, $id_lang) + { + if (!Pack::isFeatureActive() || !$id_item) { + return array(); + } + + $query = 'SELECT `id_product_pack`, `quantity` FROM `'._DB_PREFIX_.'pack` + WHERE `id_product_item` = '.((int)$id_item); + if (Combination::isFeatureActive()) { + $query .= ' AND `id_product_attribute_item` = '.((int)$id_attribute_item); + } + $result = Db::getInstance()->executeS($query); + $array_result = array(); + foreach ($result as $row) { + $p = new Product($row['id_product_pack'], true, $id_lang); + $p->loadStockData(); + $p->pack_item_quantity = $row['quantity']; // Specific need from StockAvailable::updateQuantity() + $array_result[] = $p; + } + return $array_result; + } } diff --git a/classes/Page.php b/classes/Page.php index 1bcc97f9..c7d90932 100644 --- a/classes/Page.php +++ b/classes/Page.php @@ -26,104 +26,106 @@ class PageCore extends ObjectModel { - public $id_page_type; - public $id_object; + public $id_page_type; + public $id_object; - public $name; + public $name; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'page', - 'primary' => 'id_page', - 'fields' => array( - 'id_page_type' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_object' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'page', + 'primary' => 'id_page', + 'fields' => array( + 'id_page_type' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_object' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + ), + ); - /** - * @return int Current page ID - */ - public static function getCurrentId() - { - $controller = Dispatcher::getInstance()->getController(); - $page_type_id = Page::getPageTypeByName($controller); + /** + * @return int Current page ID + */ + public static function getCurrentId() + { + $controller = Dispatcher::getInstance()->getController(); + $page_type_id = Page::getPageTypeByName($controller); - // Some pages must be distinguished in order to record exactly what is being seen - // @todo dispatcher module - $special_array = array( - 'product' => 'id_product', - 'category' => 'id_category', - 'order' => 'step', - 'manufacturer' => 'id_manufacturer', - ); + // Some pages must be distinguished in order to record exactly what is being seen + // @todo dispatcher module + $special_array = array( + 'product' => 'id_product', + 'category' => 'id_category', + 'order' => 'step', + 'manufacturer' => 'id_manufacturer', + ); - $where = ''; - $insert_data = array( - 'id_page_type' => $page_type_id, - ); + $where = ''; + $insert_data = array( + 'id_page_type' => $page_type_id, + ); - if (array_key_exists($controller, $special_array)) - { - $object_id = Tools::getValue($special_array[$controller], null); - $where = ' AND `id_object` = '.(int)$object_id; - $insert_data['id_object'] = (int)$object_id; - } + if (array_key_exists($controller, $special_array)) { + $object_id = Tools::getValue($special_array[$controller], null); + $where = ' AND `id_object` = '.(int)$object_id; + $insert_data['id_object'] = (int)$object_id; + } - $sql = 'SELECT `id_page` + $sql = 'SELECT `id_page` FROM `'._DB_PREFIX_.'page` WHERE `id_page_type` = '.(int)$page_type_id.$where; - $result = Db::getInstance()->getRow($sql); - if ($result['id_page']) - return $result['id_page']; + $result = Db::getInstance()->getRow($sql); + if ($result['id_page']) { + return $result['id_page']; + } - Db::getInstance()->insert('page', $insert_data, true); - return Db::getInstance()->Insert_ID(); - } + Db::getInstance()->insert('page', $insert_data, true); + return Db::getInstance()->Insert_ID(); + } - /** - * Return page type ID from page name - * - * @param string $name Page name (E.g. product.php) - */ - public static function getPageTypeByName($name) - { - if ($value = Db::getInstance()->getValue(' + /** + * Return page type ID from page name + * + * @param string $name Page name (E.g. product.php) + */ + public static function getPageTypeByName($name) + { + if ($value = Db::getInstance()->getValue(' SELECT id_page_type FROM '._DB_PREFIX_.'page_type WHERE name = \''.pSQL($name).'\'' - ) - ) - return $value; + ) + ) { + return $value; + } - Db::getInstance()->insert('page_type', array('name' => pSQL($name))); + Db::getInstance()->insert('page_type', array('name' => pSQL($name))); - return Db::getInstance()->Insert_ID(); - } + return Db::getInstance()->Insert_ID(); + } - public static function setPageViewed($id_page) - { - $id_date_range = DateRange::getCurrentRange(); - $context = Context::getContext(); + public static function setPageViewed($id_page) + { + $id_date_range = DateRange::getCurrentRange(); + $context = Context::getContext(); - // Try to increment the visits counter - $sql = 'UPDATE `'._DB_PREFIX_.'page_viewed` + // Try to increment the visits counter + $sql = 'UPDATE `'._DB_PREFIX_.'page_viewed` SET `counter` = `counter` + 1 WHERE `id_date_range` = '.(int)$id_date_range.' AND `id_page` = '.(int)$id_page.' AND `id_shop` = '.(int)$context->shop->id; - Db::getInstance()->execute($sql); + Db::getInstance()->execute($sql); - // If no one has seen the page in this date range, it is added - if (Db::getInstance()->Affected_Rows() == 0) - Db::getInstance()->insert('page_viewed', array( - 'id_date_range' => (int)$id_date_range, - 'id_page' => (int)$id_page, - 'counter' => 1, - 'id_shop' => (int)$context->shop->id, - 'id_shop_group' => (int)$context->shop->id_shop_group, - )); - } + // If no one has seen the page in this date range, it is added + if (Db::getInstance()->Affected_Rows() == 0) { + Db::getInstance()->insert('page_viewed', array( + 'id_date_range' => (int)$id_date_range, + 'id_page' => (int)$id_page, + 'counter' => 1, + 'id_shop' => (int)$context->shop->id, + 'id_shop_group' => (int)$context->shop->id_shop_group, + )); + } + } } diff --git a/classes/PaymentCC.php b/classes/PaymentCC.php index 22635d4d..4761be28 100644 --- a/classes/PaymentCC.php +++ b/classes/PaymentCC.php @@ -32,49 +32,49 @@ */ class PaymentCCCore extends OrderPayment { - public $id_order; - public $id_currency; - public $amount; - public $transaction_id; - public $card_number; - public $card_brand; - public $card_expiration; - public $card_holder; - public $date_add; + public $id_order; + public $id_currency; + public $amount; + public $transaction_id; + public $card_number; + public $card_brand; + public $card_expiration; + public $card_holder; + public $date_add; - protected $fieldsRequired = array('id_currency', 'amount'); - protected $fieldsSize = array('transaction_id' => 254, 'card_number' => 254, 'card_brand' => 254, 'card_expiration' => 254, 'card_holder' => 254); - protected $fieldsValidate = array( - 'id_order' => 'isUnsignedId', 'id_currency' => 'isUnsignedId', 'amount' => 'isPrice', - 'transaction_id' => 'isAnything', 'card_number' => 'isAnything', 'card_brand' => 'isAnything', 'card_expiration' => 'isAnything', 'card_holder' => 'isAnything'); + protected $fieldsRequired = array('id_currency', 'amount'); + protected $fieldsSize = array('transaction_id' => 254, 'card_number' => 254, 'card_brand' => 254, 'card_expiration' => 254, 'card_holder' => 254); + protected $fieldsValidate = array( + 'id_order' => 'isUnsignedId', 'id_currency' => 'isUnsignedId', 'amount' => 'isPrice', + 'transaction_id' => 'isAnything', 'card_number' => 'isAnything', 'card_brand' => 'isAnything', 'card_expiration' => 'isAnything', 'card_holder' => 'isAnything'); - public static $definition = array( - 'table' => 'payment_cc', - 'primary' => 'id_payment_cc', - ); + public static $definition = array( + 'table' => 'payment_cc', + 'primary' => 'id_payment_cc', + ); - /** - * @deprecated 1.5.0.2 - * @see OrderPaymentCore - */ - public function add($autodate = true, $nullValues = false) - { - Tools::displayAsDeprecated(); - return parent::add($autodate, $nullValues); - } + /** + * @deprecated 1.5.0.2 + * @see OrderPaymentCore + */ + public function add($autodate = true, $nullValues = false) + { + Tools::displayAsDeprecated(); + return parent::add($autodate, $nullValues); + } - /** - * Get the detailed payment of an order - * @param int $id_order - * @return array - * @deprecated 1.5.0.1 - * @see OrderPaymentCore - */ - public static function getByOrderId($id_order) - { - Tools::displayAsDeprecated(); - $order = new Order($id_order); - return OrderPayment::getByOrderReference($order->reference); - } + /** + * Get the detailed payment of an order + * @param int $id_order + * @return array + * @deprecated 1.5.0.1 + * @see OrderPaymentCore + */ + public static function getByOrderId($id_order) + { + Tools::displayAsDeprecated(); + $order = new Order($id_order); + return OrderPayment::getByOrderReference($order->reference); + } } diff --git a/classes/PaymentModule.php b/classes/PaymentModule.php index 59ebd5a1..fd253ac7 100644 --- a/classes/PaymentModule.php +++ b/classes/PaymentModule.php @@ -26,979 +26,982 @@ abstract class PaymentModuleCore extends Module { - /** @var int Current order's id */ - public $currentOrder; - public $currencies = true; - public $currencies_mode = 'checkbox'; + /** @var int Current order's id */ + public $currentOrder; + public $currencies = true; + public $currencies_mode = 'checkbox'; - const DEBUG_MODE = false; + const DEBUG_MODE = false; - public function install() - { - if (!parent::install()) - return false; + public function install() + { + if (!parent::install()) { + return false; + } - // Insert currencies availability - if ($this->currencies_mode == 'checkbox') - { - if (!$this->addCheckboxCurrencyRestrictionsForModule()) - return false; - } - elseif ($this->currencies_mode == 'radio') - { - if (!$this->addRadioCurrencyRestrictionsForModule()) - return false; - } - else - Tools::displayError('No currency mode for payment module'); + // Insert currencies availability + if ($this->currencies_mode == 'checkbox') { + if (!$this->addCheckboxCurrencyRestrictionsForModule()) { + return false; + } + } elseif ($this->currencies_mode == 'radio') { + if (!$this->addRadioCurrencyRestrictionsForModule()) { + return false; + } + } else { + Tools::displayError('No currency mode for payment module'); + } - // Insert countries availability - $return = $this->addCheckboxCountryRestrictionsForModule(); + // Insert countries availability + $return = $this->addCheckboxCountryRestrictionsForModule(); - if (!Configuration::get('CONF_'.strtoupper($this->name).'_FIXED')) - Configuration::updateValue('CONF_'.strtoupper($this->name).'_FIXED', '0.2'); - if (!Configuration::get('CONF_'.strtoupper($this->name).'_VAR')) - Configuration::updateValue('CONF_'.strtoupper($this->name).'_VAR', '2'); - if (!Configuration::get('CONF_'.strtoupper($this->name).'_FIXED_FOREIGN')) - Configuration::updateValue('CONF_'.strtoupper($this->name).'_FIXED_FOREIGN', '0.2'); - if (!Configuration::get('CONF_'.strtoupper($this->name).'_VAR_FOREIGN')) - Configuration::updateValue('CONF_'.strtoupper($this->name).'_VAR_FOREIGN', '2'); + if (!Configuration::get('CONF_'.strtoupper($this->name).'_FIXED')) { + Configuration::updateValue('CONF_'.strtoupper($this->name).'_FIXED', '0.2'); + } + if (!Configuration::get('CONF_'.strtoupper($this->name).'_VAR')) { + Configuration::updateValue('CONF_'.strtoupper($this->name).'_VAR', '2'); + } + if (!Configuration::get('CONF_'.strtoupper($this->name).'_FIXED_FOREIGN')) { + Configuration::updateValue('CONF_'.strtoupper($this->name).'_FIXED_FOREIGN', '0.2'); + } + if (!Configuration::get('CONF_'.strtoupper($this->name).'_VAR_FOREIGN')) { + Configuration::updateValue('CONF_'.strtoupper($this->name).'_VAR_FOREIGN', '2'); + } - return $return; - } + return $return; + } - public function uninstall() - { - if (!Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module_country` WHERE id_module = '.(int)$this->id) - || !Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module_currency` WHERE id_module = '.(int)$this->id) - || !Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module_group` WHERE id_module = '.(int)$this->id)) - return false; - return parent::uninstall(); - } + public function uninstall() + { + if (!Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module_country` WHERE id_module = '.(int)$this->id) + || !Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module_currency` WHERE id_module = '.(int)$this->id) + || !Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module_group` WHERE id_module = '.(int)$this->id)) { + return false; + } + return parent::uninstall(); + } - /** - * Add checkbox currency restrictions for a new module - * @param array $shops - * - * @return bool - */ - public function addCheckboxCurrencyRestrictionsForModule(array $shops = array()) - { - if (!$shops) - $shops = Shop::getShops(true, null, true); + /** + * Add checkbox currency restrictions for a new module + * @param array $shops + * + * @return bool + */ + public function addCheckboxCurrencyRestrictionsForModule(array $shops = array()) + { + if (!$shops) { + $shops = Shop::getShops(true, null, true); + } - foreach ($shops as $s) - { - if (!Db::getInstance()->execute(' + foreach ($shops as $s) { + if (!Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'module_currency` (`id_module`, `id_shop`, `id_currency`) - SELECT '.(int)$this->id.', "'.(int)$s.'", `id_currency` FROM `'._DB_PREFIX_.'currency` WHERE deleted = 0')) - return false; - } - return true; - } - - /** - * Add radio currency restrictions for a new module - * @param array $shops - * - * @return bool - */ - public function addRadioCurrencyRestrictionsForModule(array $shops = array()) - { - if (!$shops) - $shops = Shop::getShops(true, null, true); - - foreach ($shops as $s) - if (!Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'module_currency` (`id_module`, `id_shop`, `id_currency`) - VALUES ('.(int)$this->id.', "'.(int)$s.'", -2)')) - return false; - return true; - } - - /** - * Add checkbox country restrictions for a new module - * @param array $shops - * - * @return bool - */ - public function addCheckboxCountryRestrictionsForModule(array $shops = array()) - { - $countries = Country::getCountries((int)Context::getContext()->language->id, true); //get only active country - $country_ids = array(); - foreach ($countries as $country) - $country_ids[] = $country['id_country']; - return Country::addModuleRestrictions($shops, $countries, array(array('id_module' => (int)$this->id))); - } - - /** - * Validate an order in database - * Function called from a payment module - * - * @param int $id_cart - * @param int $id_order_state - * @param float $amount_paid Amount really paid by customer (in the default currency) - * @param string $payment_method Payment method (eg. 'Credit card') - * @param null $message Message to attach to order - * @param array $extra_vars - * @param null $currency_special - * @param bool $dont_touch_amount - * @param bool $secure_key - * @param Shop $shop - * - * @return bool - * @throws PrestaShopException - */ - public function validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method = 'Unknown', - $message = null, $extra_vars = array(), $currency_special = null, $dont_touch_amount = false, - $secure_key = false, Shop $shop = null) - { - if (self::DEBUG_MODE) - PrestaShopLogger::addLog('PaymentModule::validateOrder - Function called', 1, null, 'Cart', (int)$id_cart, true); - - if (!isset($this->context)) - $this->context = Context::getContext(); - $this->context->cart = new Cart($id_cart); - $this->context->customer = new Customer($this->context->cart->id_customer); - // The tax cart is loaded before the customer so re-cache the tax calculation method - $this->context->cart->setTaxCalculationMethod(); - - $this->context->language = new Language($this->context->cart->id_lang); - $this->context->shop = ($shop ? $shop : new Shop($this->context->cart->id_shop)); - ShopUrl::resetMainDomainCache(); - $id_currency = $currency_special ? (int)$currency_special : (int)$this->context->cart->id_currency; - $this->context->currency = new Currency($id_currency, null, $this->context->shop->id); - if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') - $context_country = $this->context->country; - - $order_status = new OrderState((int)$id_order_state, (int)$this->context->language->id); - if (!Validate::isLoadedObject($order_status)) - { - PrestaShopLogger::addLog('PaymentModule::validateOrder - Order Status cannot be loaded', 3, null, 'Cart', (int)$id_cart, true); - throw new PrestaShopException('Can\'t load Order status'); - } - - if (!$this->active) - { - PrestaShopLogger::addLog('PaymentModule::validateOrder - Module is not active', 3, null, 'Cart', (int)$id_cart, true); - die(Tools::displayError()); - } - - // Does order already exists ? - if (Validate::isLoadedObject($this->context->cart) && $this->context->cart->OrderExists() == false) - { - if ($secure_key !== false && $secure_key != $this->context->cart->secure_key) - { - PrestaShopLogger::addLog('PaymentModule::validateOrder - Secure key does not match', 3, null, 'Cart', (int)$id_cart, true); - die(Tools::displayError()); - } - - // For each package, generate an order - $delivery_option_list = $this->context->cart->getDeliveryOptionList(); - $package_list = $this->context->cart->getPackageList(); - $cart_delivery_option = $this->context->cart->getDeliveryOption(); - - // If some delivery options are not defined, or not valid, use the first valid option - foreach ($delivery_option_list as $id_address => $package) - if (!isset($cart_delivery_option[$id_address]) || !array_key_exists($cart_delivery_option[$id_address], $package)) - foreach ($package as $key => $val) - { - $cart_delivery_option[$id_address] = $key; - break; - } - - $order_list = array(); - $order_detail_list = array(); - - do - $reference = Order::generateReference(); - while (Order::getByReference($reference)->count()); - - $this->currentOrderReference = $reference; - - $order_creation_failed = false; - $cart_total_paid = (float)Tools::ps_round((float)$this->context->cart->getOrderTotal(true, Cart::BOTH), 2); - - foreach ($cart_delivery_option as $id_address => $key_carriers) - foreach ($delivery_option_list[$id_address][$key_carriers]['carrier_list'] as $id_carrier => $data) - foreach ($data['package_list'] as $id_package) - { - // Rewrite the id_warehouse - $package_list[$id_address][$id_package]['id_warehouse'] = (int)$this->context->cart->getPackageIdWarehouse($package_list[$id_address][$id_package], (int)$id_carrier); - $package_list[$id_address][$id_package]['id_carrier'] = $id_carrier; - } - // Make sure CartRule caches are empty - CartRule::cleanCache(); - $cart_rules = $this->context->cart->getCartRules(); - foreach ($cart_rules as $cart_rule) - { - if (($rule = new CartRule((int)$cart_rule['obj']->id)) && Validate::isLoadedObject($rule)) - { - if ($error = $rule->checkValidity($this->context, true, true)) - { - $this->context->cart->removeCartRule((int)$rule->id); - if (isset($this->context->cookie) && isset($this->context->cookie->id_customer) && $this->context->cookie->id_customer && !empty($rule->code)) - { - if (Configuration::get('PS_ORDER_PROCESS_TYPE') == 1) - Tools::redirect('index.php?controller=order-opc&submitAddDiscount=1&discount_name='.urlencode($rule->code)); - Tools::redirect('index.php?controller=order&submitAddDiscount=1&discount_name='.urlencode($rule->code)); - } - else - { - $rule_name = isset($rule->name[(int)$this->context->cart->id_lang]) ? $rule->name[(int)$this->context->cart->id_lang] : $rule->code; - $error = sprintf(Tools::displayError('CartRule ID %1s (%2s) used in this cart is not valid and has been withdrawn from cart'), (int)$rule->id, $rule_name); - PrestaShopLogger::addLog($error, 3, '0000002', 'Cart', (int)$this->context->cart->id); - } - } - } - } - - foreach ($package_list as $id_address => $packageByAddress) - foreach ($packageByAddress as $id_package => $package) - { - /** @var Order $order */ - $order = new Order(); - $order->product_list = $package['product_list']; - - if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') - { - $address = new Address($id_address); - $this->context->country = new Country($address->id_country, $this->context->cart->id_lang); - if (!$this->context->country->active) - throw new PrestaShopException('The delivery address country is not active.'); - } - - $carrier = null; - if (!$this->context->cart->isVirtualCart() && isset($package['id_carrier'])) - { - $carrier = new Carrier($package['id_carrier'], $this->context->cart->id_lang); - $order->id_carrier = (int)$carrier->id; - $id_carrier = (int)$carrier->id; - } - else - { - $order->id_carrier = 0; - $id_carrier = 0; - } - - $order->id_customer = (int)$this->context->cart->id_customer; - $order->id_address_invoice = (int)$this->context->cart->id_address_invoice; - $order->id_address_delivery = (int)$id_address; - $order->id_currency = $this->context->currency->id; - $order->id_lang = (int)$this->context->cart->id_lang; - $order->id_cart = (int)$this->context->cart->id; - $order->reference = $reference; - $order->id_shop = (int)$this->context->shop->id; - $order->id_shop_group = (int)$this->context->shop->id_shop_group; - - $order->secure_key = ($secure_key ? pSQL($secure_key) : pSQL($this->context->customer->secure_key)); - $order->payment = $payment_method; - if (isset($this->name)) - $order->module = $this->name; - $order->recyclable = $this->context->cart->recyclable; - $order->gift = (int)$this->context->cart->gift; - $order->gift_message = $this->context->cart->gift_message; - $order->mobile_theme = $this->context->cart->mobile_theme; - $order->conversion_rate = $this->context->currency->conversion_rate; - $amount_paid = !$dont_touch_amount ? Tools::ps_round((float)$amount_paid, 2) : $amount_paid; - $order->total_paid_real = 0; - - $order->total_products = (float)$this->context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier); - $order->total_products_wt = (float)$this->context->cart->getOrderTotal(true, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier); - $order->total_discounts_tax_excl = (float)abs($this->context->cart->getOrderTotal(false, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier)); - $order->total_discounts_tax_incl = (float)abs($this->context->cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier)); - $order->total_discounts = $order->total_discounts_tax_incl; - - $order->total_shipping_tax_excl = (float)$this->context->cart->getPackageShippingCost((int)$id_carrier, false, null, $order->product_list); - $order->total_shipping_tax_incl = (float)$this->context->cart->getPackageShippingCost((int)$id_carrier, true, null, $order->product_list); - $order->total_shipping = $order->total_shipping_tax_incl; - - if (!is_null($carrier) && Validate::isLoadedObject($carrier)) - $order->carrier_tax_rate = $carrier->getTaxesRate(new Address($this->context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')})); - - $order->total_wrapping_tax_excl = (float)abs($this->context->cart->getOrderTotal(false, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier)); - $order->total_wrapping_tax_incl = (float)abs($this->context->cart->getOrderTotal(true, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier)); - $order->total_wrapping = $order->total_wrapping_tax_incl; - - $order->total_paid_tax_excl = (float)Tools::ps_round((float)$this->context->cart->getOrderTotal(false, Cart::BOTH, $order->product_list, $id_carrier), _PS_PRICE_COMPUTE_PRECISION_); - $order->total_paid_tax_incl = (float)Tools::ps_round((float)$this->context->cart->getOrderTotal(true, Cart::BOTH, $order->product_list, $id_carrier), _PS_PRICE_COMPUTE_PRECISION_); - $order->total_paid = $order->total_paid_tax_incl; - $order->round_mode = Configuration::get('PS_PRICE_ROUND_MODE'); - $order->round_type = Configuration::get('PS_ROUND_TYPE'); - - $order->invoice_date = '0000-00-00 00:00:00'; - $order->delivery_date = '0000-00-00 00:00:00'; - - if (self::DEBUG_MODE) - PrestaShopLogger::addLog('PaymentModule::validateOrder - Order is about to be added', 1, null, 'Cart', (int)$id_cart, true); - - // Creating order - $result = $order->add(); - - if (!$result) - { - PrestaShopLogger::addLog('PaymentModule::validateOrder - Order cannot be created', 3, null, 'Cart', (int)$id_cart, true); - throw new PrestaShopException('Can\'t save Order'); - } - - // Amount paid by customer is not the right one -> Status = payment error - // We don't use the following condition to avoid the float precision issues : http://www.php.net/manual/en/language.types.float.php - // if ($order->total_paid != $order->total_paid_real) - // We use number_format in order to compare two string - if ($order_status->logable && number_format($cart_total_paid, _PS_PRICE_COMPUTE_PRECISION_) != number_format($amount_paid, _PS_PRICE_COMPUTE_PRECISION_)) - $id_order_state = Configuration::get('PS_OS_ERROR'); - - $order_list[] = $order; - - if (self::DEBUG_MODE) - PrestaShopLogger::addLog('PaymentModule::validateOrder - OrderDetail is about to be added', 1, null, 'Cart', (int)$id_cart, true); - - // Insert new Order detail list using cart for the current order - $order_detail = new OrderDetail(null, null, $this->context); - $order_detail->createList($order, $this->context->cart, $id_order_state, $order->product_list, 0, true, $package_list[$id_address][$id_package]['id_warehouse']); - $order_detail_list[] = $order_detail; - - if (self::DEBUG_MODE) - PrestaShopLogger::addLog('PaymentModule::validateOrder - OrderCarrier is about to be added', 1, null, 'Cart', (int)$id_cart, true); - - // Adding an entry in order_carrier table - if (!is_null($carrier)) - { - $order_carrier = new OrderCarrier(); - $order_carrier->id_order = (int)$order->id; - $order_carrier->id_carrier = (int)$id_carrier; - $order_carrier->weight = (float)$order->getTotalWeight(); - $order_carrier->shipping_cost_tax_excl = (float)$order->total_shipping_tax_excl; - $order_carrier->shipping_cost_tax_incl = (float)$order->total_shipping_tax_incl; - $order_carrier->add(); - } - } - - // The country can only change if the address used for the calculation is the delivery address, and if multi-shipping is activated - if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') - $this->context->country = $context_country; - - if (!$this->context->country->active) - { - PrestaShopLogger::addLog('PaymentModule::validateOrder - Country is not active', 3, null, 'Cart', (int)$id_cart, true); - throw new PrestaShopException('The order address country is not active.'); - } - - if (self::DEBUG_MODE) - PrestaShopLogger::addLog('PaymentModule::validateOrder - Payment is about to be added', 1, null, 'Cart', (int)$id_cart, true); - - // Register Payment only if the order status validate the order - if ($order_status->logable) - { - // $order is the last order loop in the foreach - // The method addOrderPayment of the class Order make a create a paymentOrder - // linked to the order reference and not to the order id - if (isset($extra_vars['transaction_id'])) - $transaction_id = $extra_vars['transaction_id']; - else - $transaction_id = null; - - if (!$order->addOrderPayment($amount_paid, null, $transaction_id)) - { - PrestaShopLogger::addLog('PaymentModule::validateOrder - Cannot save Order Payment', 3, null, 'Cart', (int)$id_cart, true); - throw new PrestaShopException('Can\'t save Order Payment'); - } - } - - // Next ! - $only_one_gift = false; - $cart_rule_used = array(); - $products = $this->context->cart->getProducts(); - - // Make sure CartRule caches are empty - CartRule::cleanCache(); - foreach ($order_detail_list as $key => $order_detail) - { - /** @var OrderDetail $order_detail */ - - $order = $order_list[$key]; - if (!$order_creation_failed && isset($order->id)) - { - if (!$secure_key) - $message .= '<br />'.Tools::displayError('Warning: the secure key is empty, check your payment account before validation'); - // Optional message to attach to this order - if (isset($message) & !empty($message)) - { - $msg = new Message(); - $message = strip_tags($message, '<br>'); - if (Validate::isCleanHtml($message)) - { - if (self::DEBUG_MODE) - PrestaShopLogger::addLog('PaymentModule::validateOrder - Message is about to be added', 1, null, 'Cart', (int)$id_cart, true); - $msg->message = $message; - $msg->id_cart = (int)$id_cart; - $msg->id_customer = intval($order->id_customer); - $msg->id_order = intval($order->id); - $msg->private = 1; - $msg->add(); - } - } - - // Insert new Order detail list using cart for the current order - //$orderDetail = new OrderDetail(null, null, $this->context); - //$orderDetail->createList($order, $this->context->cart, $id_order_state); - - // Construct order detail table for the email - $products_list = ''; - $virtual_product = true; - - $product_var_tpl_list = array(); - foreach ($order->product_list as $product) - { - $price = Product::getPriceStatic((int)$product['id_product'], false, ($product['id_product_attribute'] ? (int)$product['id_product_attribute'] : null), 6, null, false, true, $product['cart_quantity'], false, (int)$order->id_customer, (int)$order->id_cart, (int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); - $price_wt = Product::getPriceStatic((int)$product['id_product'], true, ($product['id_product_attribute'] ? (int)$product['id_product_attribute'] : null), 2, null, false, true, $product['cart_quantity'], false, (int)$order->id_customer, (int)$order->id_cart, (int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); - - $product_price = Product::getTaxCalculationMethod() == PS_TAX_EXC ? Tools::ps_round($price, 2) : $price_wt; - - $product_var_tpl = array( - 'reference' => $product['reference'], - 'name' => $product['name'].(isset($product['attributes']) ? ' - '.$product['attributes'] : ''), - 'unit_price' => Tools::displayPrice($product_price, $this->context->currency, false), - 'price' => Tools::displayPrice($product_price * $product['quantity'], $this->context->currency, false), - 'quantity' => $product['quantity'], - 'customization' => array() - ); - - $customized_datas = Product::getAllCustomizedDatas((int)$order->id_cart); - if (isset($customized_datas[$product['id_product']][$product['id_product_attribute']])) - { - $product_var_tpl['customization'] = array(); - foreach ($customized_datas[$product['id_product']][$product['id_product_attribute']][$order->id_address_delivery] as $customization) - { - $customization_text = ''; - if (isset($customization['datas'][Product::CUSTOMIZE_TEXTFIELD])) - foreach ($customization['datas'][Product::CUSTOMIZE_TEXTFIELD] as $text) - $customization_text .= $text['name'].': '.$text['value'].'<br />'; - - if (isset($customization['datas'][Product::CUSTOMIZE_FILE])) - $customization_text .= sprintf(Tools::displayError('%d image(s)'), count($customization['datas'][Product::CUSTOMIZE_FILE])).'<br />'; - - $customization_quantity = (int)$product['customization_quantity']; - - $product_var_tpl['customization'][] = array( - 'customization_text' => $customization_text, - 'customization_quantity' => $customization_quantity, - 'quantity' => Tools::displayPrice($customization_quantity * $product_price, $this->context->currency, false) - ); - } - } - - $product_var_tpl_list[] = $product_var_tpl; - // Check if is not a virutal product for the displaying of shipping - if (!$product['is_virtual']) - $virtual_product &= false; - - } // end foreach ($products) - - $product_list_txt = ''; - $product_list_html = ''; - if (count($product_var_tpl_list) > 0) - { - $product_list_txt = $this->getEmailTemplateContent('order_conf_product_list.txt', Mail::TYPE_TEXT, $product_var_tpl_list); - $product_list_html = $this->getEmailTemplateContent('order_conf_product_list.tpl', Mail::TYPE_HTML, $product_var_tpl_list); - } - - $cart_rules_list = array(); - $total_reduction_value_ti = 0; - $total_reduction_value_tex = 0; - foreach ($cart_rules as $cart_rule) - { - $package = array('id_carrier' => $order->id_carrier, 'id_address' => $order->id_address_delivery, 'products' => $order->product_list); - $values = array( - 'tax_incl' => $cart_rule['obj']->getContextualValue(true, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package), - 'tax_excl' => $cart_rule['obj']->getContextualValue(false, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package) - ); - - // If the reduction is not applicable to this order, then continue with the next one - if (!$values['tax_excl']) - continue; - - // IF - // This is not multi-shipping - // The value of the voucher is greater than the total of the order - // Partial use is allowed - // This is an "amount" reduction, not a reduction in % or a gift - // THEN - // The voucher is cloned with a new value corresponding to the remainder - if (count($order_list) == 1 && $values['tax_incl'] > ($order->total_products_wt - $total_reduction_value_ti) && $cart_rule['obj']->partial_use == 1 && $cart_rule['obj']->reduction_amount > 0) - { - // Create a new voucher from the original - $voucher = new CartRule($cart_rule['obj']->id); // We need to instantiate the CartRule without lang parameter to allow saving it - unset($voucher->id); - - // Set a new voucher code - $voucher->code = empty($voucher->code) ? substr(md5($order->id.'-'.$order->id_customer.'-'.$cart_rule['obj']->id), 0, 16) : $voucher->code.'-2'; - if (preg_match('/\-([0-9]{1,2})\-([0-9]{1,2})$/', $voucher->code, $matches) && $matches[1] == $matches[2]) - $voucher->code = preg_replace('/'.$matches[0].'$/', '-'.(intval($matches[1]) + 1), $voucher->code); - - // Set the new voucher value - if ($voucher->reduction_tax) - { - $voucher->reduction_amount = ($total_reduction_value_ti + $values['tax_incl']) - $order->total_products_wt; - - // Add total shipping amout only if reduction amount > total shipping - if ($voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_incl) - $voucher->reduction_amount -= $order->total_shipping_tax_incl; - } - else - { - $voucher->reduction_amount = ($total_reduction_value_tex + $values['tax_excl']) - $order->total_products; - - // Add total shipping amout only if reduction amount > total shipping - if ($voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_excl) - $voucher->reduction_amount -= $order->total_shipping_tax_excl; - } - if ($voucher->reduction_amount <= 0) - continue; - - if ($this->context->customer->isGuest()) - $voucher->id_customer = 0; - else - $voucher->id_customer = $order->id_customer; - - $voucher->quantity = 1; - $voucher->quantity_per_user = 1; - $voucher->free_shipping = 0; - if ($voucher->add()) - { - // If the voucher has conditions, they are now copied to the new voucher - CartRule::copyConditions($cart_rule['obj']->id, $voucher->id); - - $params = array( - '{voucher_amount}' => Tools::displayPrice($voucher->reduction_amount, $this->context->currency, false), - '{voucher_num}' => $voucher->code, - '{firstname}' => $this->context->customer->firstname, - '{lastname}' => $this->context->customer->lastname, - '{id_order}' => $order->reference, - '{order_name}' => $order->getUniqReference() - ); - Mail::Send( - (int)$order->id_lang, - 'voucher', - sprintf(Mail::l('New voucher for your order %s', (int)$order->id_lang), $order->reference), - $params, - $this->context->customer->email, - $this->context->customer->firstname.' '.$this->context->customer->lastname, - null, null, null, null, _PS_MAIL_DIR_, false, (int)$order->id_shop - ); - } - - $values['tax_incl'] = $order->total_products_wt - $total_reduction_value_ti; - $values['tax_excl'] = $order->total_products - $total_reduction_value_tex; - - } - $total_reduction_value_ti += $values['tax_incl']; - $total_reduction_value_tex += $values['tax_excl']; - - $order->addCartRule($cart_rule['obj']->id, $cart_rule['obj']->name, $values, 0, $cart_rule['obj']->free_shipping); - - if ($id_order_state != Configuration::get('PS_OS_ERROR') && $id_order_state != Configuration::get('PS_OS_CANCELED') && !in_array($cart_rule['obj']->id, $cart_rule_used)) - { - $cart_rule_used[] = $cart_rule['obj']->id; - - // Create a new instance of Cart Rule without id_lang, in order to update its quantity - $cart_rule_to_update = new CartRule($cart_rule['obj']->id); - $cart_rule_to_update->quantity = max(0, $cart_rule_to_update->quantity - 1); - $cart_rule_to_update->update(); - } - - $cart_rules_list[] = array( - 'voucher_name' => $cart_rule['obj']->name, - 'voucher_reduction' => ($values['tax_incl'] != 0.00 ? '-' : '').Tools::displayPrice($values['tax_incl'], $this->context->currency, false) - ); - } - - $cart_rules_list_txt = ''; - $cart_rules_list_html = ''; - if (count($cart_rules_list) > 0) - { - $cart_rules_list_txt = $this->getEmailTemplateContent('order_conf_cart_rules.txt', Mail::TYPE_TEXT, $cart_rules_list); - $cart_rules_list_html = $this->getEmailTemplateContent('order_conf_cart_rules.tpl', Mail::TYPE_HTML, $cart_rules_list); - } - - // Specify order id for message - $old_message = Message::getMessageByCartId((int)$this->context->cart->id); - if ($old_message) - { - $update_message = new Message((int)$old_message['id_message']); - $update_message->id_order = (int)$order->id; - $update_message->update(); - - // Add this message in the customer thread - $customer_thread = new CustomerThread(); - $customer_thread->id_contact = 0; - $customer_thread->id_customer = (int)$order->id_customer; - $customer_thread->id_shop = (int)$this->context->shop->id; - $customer_thread->id_order = (int)$order->id; - $customer_thread->id_lang = (int)$this->context->language->id; - $customer_thread->email = $this->context->customer->email; - $customer_thread->status = 'open'; - $customer_thread->token = Tools::passwdGen(12); - $customer_thread->add(); - - $customer_message = new CustomerMessage(); - $customer_message->id_customer_thread = $customer_thread->id; - $customer_message->id_employee = 0; - $customer_message->message = $update_message->message; - $customer_message->private = 0; - - if (!$customer_message->add()) - $this->errors[] = Tools::displayError('An error occurred while saving message'); - } - - if (self::DEBUG_MODE) - PrestaShopLogger::addLog('PaymentModule::validateOrder - Hook validateOrder is about to be called', 1, null, 'Cart', (int)$id_cart, true); - - // Hook validate order - Hook::exec('actionValidateOrder', array( - 'cart' => $this->context->cart, - 'order' => $order, - 'customer' => $this->context->customer, - 'currency' => $this->context->currency, - 'orderStatus' => $order_status - )); - - foreach ($this->context->cart->getProducts() as $product) - if ($order_status->logable) - ProductSale::addProductSale((int)$product['id_product'], (int)$product['cart_quantity']); - - if (self::DEBUG_MODE) - PrestaShopLogger::addLog('PaymentModule::validateOrder - Order Status is about to be added', 1, null, 'Cart', (int)$id_cart, true); - - // Set the order status - $new_history = new OrderHistory(); - $new_history->id_order = (int)$order->id; - $new_history->changeIdOrderState((int)$id_order_state, $order, true); - $new_history->addWithemail(true, $extra_vars); - - // Switch to back order if needed - if (Configuration::get('PS_STOCK_MANAGEMENT') && $order_detail->getStockState()) - { - $history = new OrderHistory(); - $history->id_order = (int)$order->id; - $history->changeIdOrderState(Configuration::get($order->valid ? 'PS_OS_OUTOFSTOCK_PAID' : 'PS_OS_OUTOFSTOCK_UNPAID'), $order, true); - $history->addWithemail(); - } - - unset($order_detail); - - // Order is reloaded because the status just changed - $order = new Order($order->id); - - // Send an e-mail to customer (one order = one email) - if ($id_order_state != Configuration::get('PS_OS_ERROR') && $id_order_state != Configuration::get('PS_OS_CANCELED') && $this->context->customer->id) - { - $invoice = new Address($order->id_address_invoice); - $delivery = new Address($order->id_address_delivery); - $delivery_state = $delivery->id_state ? new State($delivery->id_state) : false; - $invoice_state = $invoice->id_state ? new State($invoice->id_state) : false; - - $data = array( - '{firstname}' => $this->context->customer->firstname, - '{lastname}' => $this->context->customer->lastname, - '{email}' => $this->context->customer->email, - '{delivery_block_txt}' => $this->_getFormatedAddress($delivery, "\n"), - '{invoice_block_txt}' => $this->_getFormatedAddress($invoice, "\n"), - '{delivery_block_html}' => $this->_getFormatedAddress($delivery, '<br />', array( - 'firstname' => '<span style="font-weight:bold;">%s</span>', - 'lastname' => '<span style="font-weight:bold;">%s</span>' - )), - '{invoice_block_html}' => $this->_getFormatedAddress($invoice, '<br />', array( - 'firstname' => '<span style="font-weight:bold;">%s</span>', - 'lastname' => '<span style="font-weight:bold;">%s</span>' - )), - '{delivery_company}' => $delivery->company, - '{delivery_firstname}' => $delivery->firstname, - '{delivery_lastname}' => $delivery->lastname, - '{delivery_address1}' => $delivery->address1, - '{delivery_address2}' => $delivery->address2, - '{delivery_city}' => $delivery->city, - '{delivery_postal_code}' => $delivery->postcode, - '{delivery_country}' => $delivery->country, - '{delivery_state}' => $delivery->id_state ? $delivery_state->name : '', - '{delivery_phone}' => ($delivery->phone) ? $delivery->phone : $delivery->phone_mobile, - '{delivery_other}' => $delivery->other, - '{invoice_company}' => $invoice->company, - '{invoice_vat_number}' => $invoice->vat_number, - '{invoice_firstname}' => $invoice->firstname, - '{invoice_lastname}' => $invoice->lastname, - '{invoice_address2}' => $invoice->address2, - '{invoice_address1}' => $invoice->address1, - '{invoice_city}' => $invoice->city, - '{invoice_postal_code}' => $invoice->postcode, - '{invoice_country}' => $invoice->country, - '{invoice_state}' => $invoice->id_state ? $invoice_state->name : '', - '{invoice_phone}' => ($invoice->phone) ? $invoice->phone : $invoice->phone_mobile, - '{invoice_other}' => $invoice->other, - '{order_name}' => $order->getUniqReference(), - '{date}' => Tools::displayDate(date('Y-m-d H:i:s'), null, 1), - '{carrier}' => ($virtual_product || !isset($carrier->name)) ? Tools::displayError('No carrier') : $carrier->name, - '{payment}' => Tools::substr($order->payment, 0, 32), - '{products}' => $product_list_html, - '{products_txt}' => $product_list_txt, - '{discounts}' => $cart_rules_list_html, - '{discounts_txt}' => $cart_rules_list_txt, - '{total_paid}' => Tools::displayPrice($order->total_paid, $this->context->currency, false), - '{total_products}' => Tools::displayPrice(Product::getTaxCalculationMethod() == PS_TAX_EXC ? $order->total_products : $order->total_products_wt, $this->context->currency, false), - '{total_discounts}' => Tools::displayPrice($order->total_discounts, $this->context->currency, false), - '{total_shipping}' => Tools::displayPrice($order->total_shipping, $this->context->currency, false), - '{total_wrapping}' => Tools::displayPrice($order->total_wrapping, $this->context->currency, false), - '{total_tax_paid}' => Tools::displayPrice(($order->total_products_wt - $order->total_products) + ($order->total_shipping_tax_incl - $order->total_shipping_tax_excl), $this->context->currency, false)); - - if (is_array($extra_vars)) - $data = array_merge($data, $extra_vars); - - // Join PDF invoice - if ((int)Configuration::get('PS_INVOICE') && $order_status->invoice && $order->invoice_number) - { - $order_invoice_list = $order->getInvoicesCollection(); - Hook::exec('actionPDFInvoiceRender', array('order_invoice_list' => $order_invoice_list)); - $pdf = new PDF($order_invoice_list, PDF::TEMPLATE_INVOICE, $this->context->smarty); - $file_attachement['content'] = $pdf->render(false); - $file_attachement['name'] = Configuration::get('PS_INVOICE_PREFIX', (int)$order->id_lang, null, $order->id_shop).sprintf('%06d', $order->invoice_number).'.pdf'; - $file_attachement['mime'] = 'application/pdf'; - } - else - $file_attachement = null; - - if (self::DEBUG_MODE) - PrestaShopLogger::addLog('PaymentModule::validateOrder - Mail is about to be sent', 1, null, 'Cart', (int)$id_cart, true); - - if (Validate::isEmail($this->context->customer->email)) - Mail::Send( - (int)$order->id_lang, - 'order_conf', - Mail::l('Order confirmation', (int)$order->id_lang), - $data, - $this->context->customer->email, - $this->context->customer->firstname.' '.$this->context->customer->lastname, - null, - null, - $file_attachement, - null, _PS_MAIL_DIR_, false, (int)$order->id_shop - ); - } - - // updates stock in shops - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $product_list = $order->getProducts(); - foreach ($product_list as $product) - { - // if the available quantities depends on the physical stock - if (StockAvailable::dependsOnStock($product['product_id'])) - { - // synchronizes - StockAvailable::synchronize($product['product_id'], $order->id_shop); - } - } - } - - $order->updateOrderDetailTax(); - } - else - { - $error = Tools::displayError('Order creation failed'); - PrestaShopLogger::addLog($error, 4, '0000002', 'Cart', intval($order->id_cart)); - die($error); - } - } // End foreach $order_detail_list - - // Use the last order as currentOrder - if (isset($order) && $order->id) - $this->currentOrder = (int)$order->id; - - if (self::DEBUG_MODE) - PrestaShopLogger::addLog('PaymentModule::validateOrder - End of validateOrder', 1, null, 'Cart', (int)$id_cart, true); - - return true; - } - else - { - $error = Tools::displayError('Cart cannot be loaded or an order has already been placed using this cart'); - PrestaShopLogger::addLog($error, 4, '0000001', 'Cart', intval($this->context->cart->id)); - die($error); - } - } - - /** - * @deprecated 1.6.0.7 - * @param mixed $content - * @return mixed - */ - public function formatProductAndVoucherForEmail($content) - { - Tools::displayAsDeprecated(); - return $content; - } - - /** - * @param Object Address $the_address that needs to be txt formated - * @return String the txt formated address block - */ - protected function _getTxtFormatedAddress($the_address) - { - $adr_fields = AddressFormat::getOrderedAddressFields($the_address->id_country, false, true); - $r_values = array(); - foreach ($adr_fields as $fields_line) - { - $tmp_values = array(); - foreach (explode(' ', $fields_line) as $field_item) - { - $field_item = trim($field_item); - $tmp_values[] = $the_address->{$field_item}; - } - $r_values[] = implode(' ', $tmp_values); - } - - $out = implode("\n", $r_values); - return $out; - } - - /** - * @param Object Address $the_address that needs to be txt formated - * @return String the txt formated address block - */ - - protected function _getFormatedAddress(Address $the_address, $line_sep, $fields_style = array()) - { - return AddressFormat::generateAddress($the_address, array('avoid' => array()), $line_sep, ' ', $fields_style); - } - - /** - * @param int $id_currency : this parameter is optionnal but on 1.5 version of Prestashop, it will be REQUIRED - * @return Currency - */ - public function getCurrency($current_id_currency = null) - { - if (!(int)$current_id_currency) - $current_id_currency = Context::getContext()->currency->id; - - if (!$this->currencies) - return false; - if ($this->currencies_mode == 'checkbox') - { - $currencies = Currency::getPaymentCurrencies($this->id); - return $currencies; - } - elseif ($this->currencies_mode == 'radio') - { - $currencies = Currency::getPaymentCurrenciesSpecial($this->id); - $currency = $currencies['id_currency']; - if ($currency == -1) - $id_currency = (int)$current_id_currency; - elseif ($currency == -2) - $id_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT'); - else - $id_currency = $currency; - } - if (!isset($id_currency) || empty($id_currency)) - return false; - $currency = new Currency($id_currency); - return $currency; - } - - /** - * Allows specified payment modules to be used by a specific currency - * - * @since 1.4.5 - * @param int $id_currency - * @param array $id_module_list - * @return bool - */ - public static function addCurrencyPermissions($id_currency, array $id_module_list = array()) - { - $values = ''; - if (count($id_module_list) == 0) - { - // fetch all installed module ids - $modules = PaymentModuleCore::getInstalledPaymentModules(); - foreach ($modules as $module) - $id_module_list[] = $module['id_module']; - } - - foreach ($id_module_list as $id_module) - $values .= '('.(int)$id_module.','.(int)$id_currency.'),'; - - if (!empty($values)) - { - return Db::getInstance()->execute(' + SELECT '.(int)$this->id.', "'.(int)$s.'", `id_currency` FROM `'._DB_PREFIX_.'currency` WHERE deleted = 0')) { + return false; + } + } + return true; + } + + /** + * Add radio currency restrictions for a new module + * @param array $shops + * + * @return bool + */ + public function addRadioCurrencyRestrictionsForModule(array $shops = array()) + { + if (!$shops) { + $shops = Shop::getShops(true, null, true); + } + + foreach ($shops as $s) { + if (!Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'module_currency` (`id_module`, `id_shop`, `id_currency`) + VALUES ('.(int)$this->id.', "'.(int)$s.'", -2)')) { + return false; + } + } + return true; + } + + /** + * Add checkbox country restrictions for a new module + * @param array $shops + * + * @return bool + */ + public function addCheckboxCountryRestrictionsForModule(array $shops = array()) + { + $countries = Country::getCountries((int)Context::getContext()->language->id, true); //get only active country + $country_ids = array(); + foreach ($countries as $country) { + $country_ids[] = $country['id_country']; + } + return Country::addModuleRestrictions($shops, $countries, array(array('id_module' => (int)$this->id))); + } + + /** + * Validate an order in database + * Function called from a payment module + * + * @param int $id_cart + * @param int $id_order_state + * @param float $amount_paid Amount really paid by customer (in the default currency) + * @param string $payment_method Payment method (eg. 'Credit card') + * @param null $message Message to attach to order + * @param array $extra_vars + * @param null $currency_special + * @param bool $dont_touch_amount + * @param bool $secure_key + * @param Shop $shop + * + * @return bool + * @throws PrestaShopException + */ + public function validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method = 'Unknown', + $message = null, $extra_vars = array(), $currency_special = null, $dont_touch_amount = false, + $secure_key = false, Shop $shop = null) + { + if (self::DEBUG_MODE) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - Function called', 1, null, 'Cart', (int)$id_cart, true); + } + + if (!isset($this->context)) { + $this->context = Context::getContext(); + } + $this->context->cart = new Cart($id_cart); + $this->context->customer = new Customer($this->context->cart->id_customer); + // The tax cart is loaded before the customer so re-cache the tax calculation method + $this->context->cart->setTaxCalculationMethod(); + + $this->context->language = new Language($this->context->cart->id_lang); + $this->context->shop = ($shop ? $shop : new Shop($this->context->cart->id_shop)); + ShopUrl::resetMainDomainCache(); + $id_currency = $currency_special ? (int)$currency_special : (int)$this->context->cart->id_currency; + $this->context->currency = new Currency($id_currency, null, $this->context->shop->id); + if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') { + $context_country = $this->context->country; + } + + $order_status = new OrderState((int)$id_order_state, (int)$this->context->language->id); + if (!Validate::isLoadedObject($order_status)) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - Order Status cannot be loaded', 3, null, 'Cart', (int)$id_cart, true); + throw new PrestaShopException('Can\'t load Order status'); + } + + if (!$this->active) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - Module is not active', 3, null, 'Cart', (int)$id_cart, true); + die(Tools::displayError()); + } + + // Does order already exists ? + if (Validate::isLoadedObject($this->context->cart) && $this->context->cart->OrderExists() == false) { + if ($secure_key !== false && $secure_key != $this->context->cart->secure_key) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - Secure key does not match', 3, null, 'Cart', (int)$id_cart, true); + die(Tools::displayError()); + } + + // For each package, generate an order + $delivery_option_list = $this->context->cart->getDeliveryOptionList(); + $package_list = $this->context->cart->getPackageList(); + $cart_delivery_option = $this->context->cart->getDeliveryOption(); + + // If some delivery options are not defined, or not valid, use the first valid option + foreach ($delivery_option_list as $id_address => $package) { + if (!isset($cart_delivery_option[$id_address]) || !array_key_exists($cart_delivery_option[$id_address], $package)) { + foreach ($package as $key => $val) { + $cart_delivery_option[$id_address] = $key; + break; + } + } + } + + $order_list = array(); + $order_detail_list = array(); + + do { + $reference = Order::generateReference(); + } while (Order::getByReference($reference)->count()); + + $this->currentOrderReference = $reference; + + $order_creation_failed = false; + $cart_total_paid = (float)Tools::ps_round((float)$this->context->cart->getOrderTotal(true, Cart::BOTH), 2); + + foreach ($cart_delivery_option as $id_address => $key_carriers) { + foreach ($delivery_option_list[$id_address][$key_carriers]['carrier_list'] as $id_carrier => $data) { + foreach ($data['package_list'] as $id_package) { + // Rewrite the id_warehouse + $package_list[$id_address][$id_package]['id_warehouse'] = (int)$this->context->cart->getPackageIdWarehouse($package_list[$id_address][$id_package], (int)$id_carrier); + $package_list[$id_address][$id_package]['id_carrier'] = $id_carrier; + } + } + } + // Make sure CartRule caches are empty + CartRule::cleanCache(); + $cart_rules = $this->context->cart->getCartRules(); + foreach ($cart_rules as $cart_rule) { + if (($rule = new CartRule((int)$cart_rule['obj']->id)) && Validate::isLoadedObject($rule)) { + if ($error = $rule->checkValidity($this->context, true, true)) { + $this->context->cart->removeCartRule((int)$rule->id); + if (isset($this->context->cookie) && isset($this->context->cookie->id_customer) && $this->context->cookie->id_customer && !empty($rule->code)) { + if (Configuration::get('PS_ORDER_PROCESS_TYPE') == 1) { + Tools::redirect('index.php?controller=order-opc&submitAddDiscount=1&discount_name='.urlencode($rule->code)); + } + Tools::redirect('index.php?controller=order&submitAddDiscount=1&discount_name='.urlencode($rule->code)); + } else { + $rule_name = isset($rule->name[(int)$this->context->cart->id_lang]) ? $rule->name[(int)$this->context->cart->id_lang] : $rule->code; + $error = sprintf(Tools::displayError('CartRule ID %1s (%2s) used in this cart is not valid and has been withdrawn from cart'), (int)$rule->id, $rule_name); + PrestaShopLogger::addLog($error, 3, '0000002', 'Cart', (int)$this->context->cart->id); + } + } + } + } + + foreach ($package_list as $id_address => $packageByAddress) { + foreach ($packageByAddress as $id_package => $package) { + /** @var Order $order */ + $order = new Order(); + $order->product_list = $package['product_list']; + + if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') { + $address = new Address($id_address); + $this->context->country = new Country($address->id_country, $this->context->cart->id_lang); + if (!$this->context->country->active) { + throw new PrestaShopException('The delivery address country is not active.'); + } + } + + $carrier = null; + if (!$this->context->cart->isVirtualCart() && isset($package['id_carrier'])) { + $carrier = new Carrier($package['id_carrier'], $this->context->cart->id_lang); + $order->id_carrier = (int)$carrier->id; + $id_carrier = (int)$carrier->id; + } else { + $order->id_carrier = 0; + $id_carrier = 0; + } + + $order->id_customer = (int)$this->context->cart->id_customer; + $order->id_address_invoice = (int)$this->context->cart->id_address_invoice; + $order->id_address_delivery = (int)$id_address; + $order->id_currency = $this->context->currency->id; + $order->id_lang = (int)$this->context->cart->id_lang; + $order->id_cart = (int)$this->context->cart->id; + $order->reference = $reference; + $order->id_shop = (int)$this->context->shop->id; + $order->id_shop_group = (int)$this->context->shop->id_shop_group; + + $order->secure_key = ($secure_key ? pSQL($secure_key) : pSQL($this->context->customer->secure_key)); + $order->payment = $payment_method; + if (isset($this->name)) { + $order->module = $this->name; + } + $order->recyclable = $this->context->cart->recyclable; + $order->gift = (int)$this->context->cart->gift; + $order->gift_message = $this->context->cart->gift_message; + $order->mobile_theme = $this->context->cart->mobile_theme; + $order->conversion_rate = $this->context->currency->conversion_rate; + $amount_paid = !$dont_touch_amount ? Tools::ps_round((float)$amount_paid, 2) : $amount_paid; + $order->total_paid_real = 0; + + $order->total_products = (float)$this->context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier); + $order->total_products_wt = (float)$this->context->cart->getOrderTotal(true, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier); + $order->total_discounts_tax_excl = (float)abs($this->context->cart->getOrderTotal(false, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier)); + $order->total_discounts_tax_incl = (float)abs($this->context->cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier)); + $order->total_discounts = $order->total_discounts_tax_incl; + + $order->total_shipping_tax_excl = (float)$this->context->cart->getPackageShippingCost((int)$id_carrier, false, null, $order->product_list); + $order->total_shipping_tax_incl = (float)$this->context->cart->getPackageShippingCost((int)$id_carrier, true, null, $order->product_list); + $order->total_shipping = $order->total_shipping_tax_incl; + + if (!is_null($carrier) && Validate::isLoadedObject($carrier)) { + $order->carrier_tax_rate = $carrier->getTaxesRate(new Address($this->context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')})); + } + + $order->total_wrapping_tax_excl = (float)abs($this->context->cart->getOrderTotal(false, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier)); + $order->total_wrapping_tax_incl = (float)abs($this->context->cart->getOrderTotal(true, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier)); + $order->total_wrapping = $order->total_wrapping_tax_incl; + + $order->total_paid_tax_excl = (float)Tools::ps_round((float)$this->context->cart->getOrderTotal(false, Cart::BOTH, $order->product_list, $id_carrier), _PS_PRICE_COMPUTE_PRECISION_); + $order->total_paid_tax_incl = (float)Tools::ps_round((float)$this->context->cart->getOrderTotal(true, Cart::BOTH, $order->product_list, $id_carrier), _PS_PRICE_COMPUTE_PRECISION_); + $order->total_paid = $order->total_paid_tax_incl; + $order->round_mode = Configuration::get('PS_PRICE_ROUND_MODE'); + $order->round_type = Configuration::get('PS_ROUND_TYPE'); + + $order->invoice_date = '0000-00-00 00:00:00'; + $order->delivery_date = '0000-00-00 00:00:00'; + + if (self::DEBUG_MODE) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - Order is about to be added', 1, null, 'Cart', (int)$id_cart, true); + } + + // Creating order + $result = $order->add(); + + if (!$result) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - Order cannot be created', 3, null, 'Cart', (int)$id_cart, true); + throw new PrestaShopException('Can\'t save Order'); + } + + // Amount paid by customer is not the right one -> Status = payment error + // We don't use the following condition to avoid the float precision issues : http://www.php.net/manual/en/language.types.float.php + // if ($order->total_paid != $order->total_paid_real) + // We use number_format in order to compare two string + if ($order_status->logable && number_format($cart_total_paid, _PS_PRICE_COMPUTE_PRECISION_) != number_format($amount_paid, _PS_PRICE_COMPUTE_PRECISION_)) { + $id_order_state = Configuration::get('PS_OS_ERROR'); + } + + $order_list[] = $order; + + if (self::DEBUG_MODE) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - OrderDetail is about to be added', 1, null, 'Cart', (int)$id_cart, true); + } + + // Insert new Order detail list using cart for the current order + $order_detail = new OrderDetail(null, null, $this->context); + $order_detail->createList($order, $this->context->cart, $id_order_state, $order->product_list, 0, true, $package_list[$id_address][$id_package]['id_warehouse']); + $order_detail_list[] = $order_detail; + + if (self::DEBUG_MODE) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - OrderCarrier is about to be added', 1, null, 'Cart', (int)$id_cart, true); + } + + // Adding an entry in order_carrier table + if (!is_null($carrier)) { + $order_carrier = new OrderCarrier(); + $order_carrier->id_order = (int)$order->id; + $order_carrier->id_carrier = (int)$id_carrier; + $order_carrier->weight = (float)$order->getTotalWeight(); + $order_carrier->shipping_cost_tax_excl = (float)$order->total_shipping_tax_excl; + $order_carrier->shipping_cost_tax_incl = (float)$order->total_shipping_tax_incl; + $order_carrier->add(); + } + } + } + + // The country can only change if the address used for the calculation is the delivery address, and if multi-shipping is activated + if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') { + $this->context->country = $context_country; + } + + if (!$this->context->country->active) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - Country is not active', 3, null, 'Cart', (int)$id_cart, true); + throw new PrestaShopException('The order address country is not active.'); + } + + if (self::DEBUG_MODE) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - Payment is about to be added', 1, null, 'Cart', (int)$id_cart, true); + } + + // Register Payment only if the order status validate the order + if ($order_status->logable) { + // $order is the last order loop in the foreach + // The method addOrderPayment of the class Order make a create a paymentOrder + // linked to the order reference and not to the order id + if (isset($extra_vars['transaction_id'])) { + $transaction_id = $extra_vars['transaction_id']; + } else { + $transaction_id = null; + } + + if (!$order->addOrderPayment($amount_paid, null, $transaction_id)) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - Cannot save Order Payment', 3, null, 'Cart', (int)$id_cart, true); + throw new PrestaShopException('Can\'t save Order Payment'); + } + } + + // Next ! + $only_one_gift = false; + $cart_rule_used = array(); + $products = $this->context->cart->getProducts(); + + // Make sure CartRule caches are empty + CartRule::cleanCache(); + foreach ($order_detail_list as $key => $order_detail) { + /** @var OrderDetail $order_detail */ + + $order = $order_list[$key]; + if (!$order_creation_failed && isset($order->id)) { + if (!$secure_key) { + $message .= '<br />'.Tools::displayError('Warning: the secure key is empty, check your payment account before validation'); + } + // Optional message to attach to this order + if (isset($message) & !empty($message)) { + $msg = new Message(); + $message = strip_tags($message, '<br>'); + if (Validate::isCleanHtml($message)) { + if (self::DEBUG_MODE) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - Message is about to be added', 1, null, 'Cart', (int)$id_cart, true); + } + $msg->message = $message; + $msg->id_cart = (int)$id_cart; + $msg->id_customer = intval($order->id_customer); + $msg->id_order = intval($order->id); + $msg->private = 1; + $msg->add(); + } + } + + // Insert new Order detail list using cart for the current order + //$orderDetail = new OrderDetail(null, null, $this->context); + //$orderDetail->createList($order, $this->context->cart, $id_order_state); + + // Construct order detail table for the email + $products_list = ''; + $virtual_product = true; + + $product_var_tpl_list = array(); + foreach ($order->product_list as $product) { + $price = Product::getPriceStatic((int)$product['id_product'], false, ($product['id_product_attribute'] ? (int)$product['id_product_attribute'] : null), 6, null, false, true, $product['cart_quantity'], false, (int)$order->id_customer, (int)$order->id_cart, (int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); + $price_wt = Product::getPriceStatic((int)$product['id_product'], true, ($product['id_product_attribute'] ? (int)$product['id_product_attribute'] : null), 2, null, false, true, $product['cart_quantity'], false, (int)$order->id_customer, (int)$order->id_cart, (int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); + + $product_price = Product::getTaxCalculationMethod() == PS_TAX_EXC ? Tools::ps_round($price, 2) : $price_wt; + + $product_var_tpl = array( + 'reference' => $product['reference'], + 'name' => $product['name'].(isset($product['attributes']) ? ' - '.$product['attributes'] : ''), + 'unit_price' => Tools::displayPrice($product_price, $this->context->currency, false), + 'price' => Tools::displayPrice($product_price * $product['quantity'], $this->context->currency, false), + 'quantity' => $product['quantity'], + 'customization' => array() + ); + + $customized_datas = Product::getAllCustomizedDatas((int)$order->id_cart); + if (isset($customized_datas[$product['id_product']][$product['id_product_attribute']])) { + $product_var_tpl['customization'] = array(); + foreach ($customized_datas[$product['id_product']][$product['id_product_attribute']][$order->id_address_delivery] as $customization) { + $customization_text = ''; + if (isset($customization['datas'][Product::CUSTOMIZE_TEXTFIELD])) { + foreach ($customization['datas'][Product::CUSTOMIZE_TEXTFIELD] as $text) { + $customization_text .= $text['name'].': '.$text['value'].'<br />'; + } + } + + if (isset($customization['datas'][Product::CUSTOMIZE_FILE])) { + $customization_text .= sprintf(Tools::displayError('%d image(s)'), count($customization['datas'][Product::CUSTOMIZE_FILE])).'<br />'; + } + + $customization_quantity = (int)$product['customization_quantity']; + + $product_var_tpl['customization'][] = array( + 'customization_text' => $customization_text, + 'customization_quantity' => $customization_quantity, + 'quantity' => Tools::displayPrice($customization_quantity * $product_price, $this->context->currency, false) + ); + } + } + + $product_var_tpl_list[] = $product_var_tpl; + // Check if is not a virutal product for the displaying of shipping + if (!$product['is_virtual']) { + $virtual_product &= false; + } + } // end foreach ($products) + + $product_list_txt = ''; + $product_list_html = ''; + if (count($product_var_tpl_list) > 0) { + $product_list_txt = $this->getEmailTemplateContent('order_conf_product_list.txt', Mail::TYPE_TEXT, $product_var_tpl_list); + $product_list_html = $this->getEmailTemplateContent('order_conf_product_list.tpl', Mail::TYPE_HTML, $product_var_tpl_list); + } + + $cart_rules_list = array(); + $total_reduction_value_ti = 0; + $total_reduction_value_tex = 0; + foreach ($cart_rules as $cart_rule) { + $package = array('id_carrier' => $order->id_carrier, 'id_address' => $order->id_address_delivery, 'products' => $order->product_list); + $values = array( + 'tax_incl' => $cart_rule['obj']->getContextualValue(true, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package), + 'tax_excl' => $cart_rule['obj']->getContextualValue(false, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package) + ); + + // If the reduction is not applicable to this order, then continue with the next one + if (!$values['tax_excl']) { + continue; + } + + // IF + // This is not multi-shipping + // The value of the voucher is greater than the total of the order + // Partial use is allowed + // This is an "amount" reduction, not a reduction in % or a gift + // THEN + // The voucher is cloned with a new value corresponding to the remainder + if (count($order_list) == 1 && $values['tax_incl'] > ($order->total_products_wt - $total_reduction_value_ti) && $cart_rule['obj']->partial_use == 1 && $cart_rule['obj']->reduction_amount > 0) { + // Create a new voucher from the original + $voucher = new CartRule($cart_rule['obj']->id); // We need to instantiate the CartRule without lang parameter to allow saving it + unset($voucher->id); + + // Set a new voucher code + $voucher->code = empty($voucher->code) ? substr(md5($order->id.'-'.$order->id_customer.'-'.$cart_rule['obj']->id), 0, 16) : $voucher->code.'-2'; + if (preg_match('/\-([0-9]{1,2})\-([0-9]{1,2})$/', $voucher->code, $matches) && $matches[1] == $matches[2]) { + $voucher->code = preg_replace('/'.$matches[0].'$/', '-'.(intval($matches[1]) + 1), $voucher->code); + } + + // Set the new voucher value + if ($voucher->reduction_tax) { + $voucher->reduction_amount = ($total_reduction_value_ti + $values['tax_incl']) - $order->total_products_wt; + + // Add total shipping amout only if reduction amount > total shipping + if ($voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_incl) { + $voucher->reduction_amount -= $order->total_shipping_tax_incl; + } + } else { + $voucher->reduction_amount = ($total_reduction_value_tex + $values['tax_excl']) - $order->total_products; + + // Add total shipping amout only if reduction amount > total shipping + if ($voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_excl) { + $voucher->reduction_amount -= $order->total_shipping_tax_excl; + } + } + if ($voucher->reduction_amount <= 0) { + continue; + } + + if ($this->context->customer->isGuest()) { + $voucher->id_customer = 0; + } else { + $voucher->id_customer = $order->id_customer; + } + + $voucher->quantity = 1; + $voucher->reduction_currency = $order->id_currency; + $voucher->quantity_per_user = 1; + $voucher->free_shipping = 0; + if ($voucher->add()) { + // If the voucher has conditions, they are now copied to the new voucher + CartRule::copyConditions($cart_rule['obj']->id, $voucher->id); + + $params = array( + '{voucher_amount}' => Tools::displayPrice($voucher->reduction_amount, $this->context->currency, false), + '{voucher_num}' => $voucher->code, + '{firstname}' => $this->context->customer->firstname, + '{lastname}' => $this->context->customer->lastname, + '{id_order}' => $order->reference, + '{order_name}' => $order->getUniqReference() + ); + Mail::Send( + (int)$order->id_lang, + 'voucher', + sprintf(Mail::l('New voucher for your order %s', (int)$order->id_lang), $order->reference), + $params, + $this->context->customer->email, + $this->context->customer->firstname.' '.$this->context->customer->lastname, + null, null, null, null, _PS_MAIL_DIR_, false, (int)$order->id_shop + ); + } + + $values['tax_incl'] = $order->total_products_wt - $total_reduction_value_ti; + $values['tax_excl'] = $order->total_products - $total_reduction_value_tex; + } + $total_reduction_value_ti += $values['tax_incl']; + $total_reduction_value_tex += $values['tax_excl']; + + $order->addCartRule($cart_rule['obj']->id, $cart_rule['obj']->name, $values, 0, $cart_rule['obj']->free_shipping); + + if ($id_order_state != Configuration::get('PS_OS_ERROR') && $id_order_state != Configuration::get('PS_OS_CANCELED') && !in_array($cart_rule['obj']->id, $cart_rule_used)) { + $cart_rule_used[] = $cart_rule['obj']->id; + + // Create a new instance of Cart Rule without id_lang, in order to update its quantity + $cart_rule_to_update = new CartRule($cart_rule['obj']->id); + $cart_rule_to_update->quantity = max(0, $cart_rule_to_update->quantity - 1); + $cart_rule_to_update->update(); + } + + $cart_rules_list[] = array( + 'voucher_name' => $cart_rule['obj']->name, + 'voucher_reduction' => ($values['tax_incl'] != 0.00 ? '-' : '').Tools::displayPrice($values['tax_incl'], $this->context->currency, false) + ); + } + + $cart_rules_list_txt = ''; + $cart_rules_list_html = ''; + if (count($cart_rules_list) > 0) { + $cart_rules_list_txt = $this->getEmailTemplateContent('order_conf_cart_rules.txt', Mail::TYPE_TEXT, $cart_rules_list); + $cart_rules_list_html = $this->getEmailTemplateContent('order_conf_cart_rules.tpl', Mail::TYPE_HTML, $cart_rules_list); + } + + // Specify order id for message + $old_message = Message::getMessageByCartId((int)$this->context->cart->id); + if ($old_message) { + $update_message = new Message((int)$old_message['id_message']); + $update_message->id_order = (int)$order->id; + $update_message->update(); + + // Add this message in the customer thread + $customer_thread = new CustomerThread(); + $customer_thread->id_contact = 0; + $customer_thread->id_customer = (int)$order->id_customer; + $customer_thread->id_shop = (int)$this->context->shop->id; + $customer_thread->id_order = (int)$order->id; + $customer_thread->id_lang = (int)$this->context->language->id; + $customer_thread->email = $this->context->customer->email; + $customer_thread->status = 'open'; + $customer_thread->token = Tools::passwdGen(12); + $customer_thread->add(); + + $customer_message = new CustomerMessage(); + $customer_message->id_customer_thread = $customer_thread->id; + $customer_message->id_employee = 0; + $customer_message->message = $update_message->message; + $customer_message->private = 0; + + if (!$customer_message->add()) { + $this->errors[] = Tools::displayError('An error occurred while saving message'); + } + } + + if (self::DEBUG_MODE) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - Hook validateOrder is about to be called', 1, null, 'Cart', (int)$id_cart, true); + } + + // Hook validate order + Hook::exec('actionValidateOrder', array( + 'cart' => $this->context->cart, + 'order' => $order, + 'customer' => $this->context->customer, + 'currency' => $this->context->currency, + 'orderStatus' => $order_status + )); + + foreach ($this->context->cart->getProducts() as $product) { + if ($order_status->logable) { + ProductSale::addProductSale((int)$product['id_product'], (int)$product['cart_quantity']); + } + } + + if (self::DEBUG_MODE) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - Order Status is about to be added', 1, null, 'Cart', (int)$id_cart, true); + } + + // Set the order status + $new_history = new OrderHistory(); + $new_history->id_order = (int)$order->id; + $new_history->changeIdOrderState((int)$id_order_state, $order, true); + $new_history->addWithemail(true, $extra_vars); + + // Switch to back order if needed + if (Configuration::get('PS_STOCK_MANAGEMENT') && ($order_detail->getStockState() || $order_detail->product_quantity_in_stock <= 0)) { + $history = new OrderHistory(); + $history->id_order = (int)$order->id; + $history->changeIdOrderState(Configuration::get($order->valid ? 'PS_OS_OUTOFSTOCK_PAID' : 'PS_OS_OUTOFSTOCK_UNPAID'), $order, true); + $history->addWithemail(); + } + + unset($order_detail); + + // Order is reloaded because the status just changed + $order = new Order($order->id); + + // Send an e-mail to customer (one order = one email) + if ($id_order_state != Configuration::get('PS_OS_ERROR') && $id_order_state != Configuration::get('PS_OS_CANCELED') && $this->context->customer->id) { + $invoice = new Address($order->id_address_invoice); + $delivery = new Address($order->id_address_delivery); + $delivery_state = $delivery->id_state ? new State($delivery->id_state) : false; + $invoice_state = $invoice->id_state ? new State($invoice->id_state) : false; + + $data = array( + '{firstname}' => $this->context->customer->firstname, + '{lastname}' => $this->context->customer->lastname, + '{email}' => $this->context->customer->email, + '{delivery_block_txt}' => $this->_getFormatedAddress($delivery, "\n"), + '{invoice_block_txt}' => $this->_getFormatedAddress($invoice, "\n"), + '{delivery_block_html}' => $this->_getFormatedAddress($delivery, '<br />', array( + 'firstname' => '<span style="font-weight:bold;">%s</span>', + 'lastname' => '<span style="font-weight:bold;">%s</span>' + )), + '{invoice_block_html}' => $this->_getFormatedAddress($invoice, '<br />', array( + 'firstname' => '<span style="font-weight:bold;">%s</span>', + 'lastname' => '<span style="font-weight:bold;">%s</span>' + )), + '{delivery_company}' => $delivery->company, + '{delivery_firstname}' => $delivery->firstname, + '{delivery_lastname}' => $delivery->lastname, + '{delivery_address1}' => $delivery->address1, + '{delivery_address2}' => $delivery->address2, + '{delivery_city}' => $delivery->city, + '{delivery_postal_code}' => $delivery->postcode, + '{delivery_country}' => $delivery->country, + '{delivery_state}' => $delivery->id_state ? $delivery_state->name : '', + '{delivery_phone}' => ($delivery->phone) ? $delivery->phone : $delivery->phone_mobile, + '{delivery_other}' => $delivery->other, + '{invoice_company}' => $invoice->company, + '{invoice_vat_number}' => $invoice->vat_number, + '{invoice_firstname}' => $invoice->firstname, + '{invoice_lastname}' => $invoice->lastname, + '{invoice_address2}' => $invoice->address2, + '{invoice_address1}' => $invoice->address1, + '{invoice_city}' => $invoice->city, + '{invoice_postal_code}' => $invoice->postcode, + '{invoice_country}' => $invoice->country, + '{invoice_state}' => $invoice->id_state ? $invoice_state->name : '', + '{invoice_phone}' => ($invoice->phone) ? $invoice->phone : $invoice->phone_mobile, + '{invoice_other}' => $invoice->other, + '{order_name}' => $order->getUniqReference(), + '{date}' => Tools::displayDate(date('Y-m-d H:i:s'), null, 1), + '{carrier}' => ($virtual_product || !isset($carrier->name)) ? Tools::displayError('No carrier') : $carrier->name, + '{payment}' => Tools::substr($order->payment, 0, 32), + '{products}' => $product_list_html, + '{products_txt}' => $product_list_txt, + '{discounts}' => $cart_rules_list_html, + '{discounts_txt}' => $cart_rules_list_txt, + '{total_paid}' => Tools::displayPrice($order->total_paid, $this->context->currency, false), + '{total_products}' => Tools::displayPrice(Product::getTaxCalculationMethod() == PS_TAX_EXC ? $order->total_products : $order->total_products_wt, $this->context->currency, false), + '{total_discounts}' => Tools::displayPrice($order->total_discounts, $this->context->currency, false), + '{total_shipping}' => Tools::displayPrice($order->total_shipping, $this->context->currency, false), + '{total_wrapping}' => Tools::displayPrice($order->total_wrapping, $this->context->currency, false), + '{total_tax_paid}' => Tools::displayPrice(($order->total_products_wt - $order->total_products) + ($order->total_shipping_tax_incl - $order->total_shipping_tax_excl), $this->context->currency, false)); + + if (is_array($extra_vars)) { + $data = array_merge($data, $extra_vars); + } + + // Join PDF invoice + if ((int)Configuration::get('PS_INVOICE') && $order_status->invoice && $order->invoice_number) { + $order_invoice_list = $order->getInvoicesCollection(); + Hook::exec('actionPDFInvoiceRender', array('order_invoice_list' => $order_invoice_list)); + $pdf = new PDF($order_invoice_list, PDF::TEMPLATE_INVOICE, $this->context->smarty); + $file_attachement['content'] = $pdf->render(false); + $file_attachement['name'] = Configuration::get('PS_INVOICE_PREFIX', (int)$order->id_lang, null, $order->id_shop).sprintf('%06d', $order->invoice_number).'.pdf'; + $file_attachement['mime'] = 'application/pdf'; + } else { + $file_attachement = null; + } + + if (self::DEBUG_MODE) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - Mail is about to be sent', 1, null, 'Cart', (int)$id_cart, true); + } + + if (Validate::isEmail($this->context->customer->email)) { + Mail::Send( + (int)$order->id_lang, + 'order_conf', + Mail::l('Order confirmation', (int)$order->id_lang), + $data, + $this->context->customer->email, + $this->context->customer->firstname.' '.$this->context->customer->lastname, + null, + null, + $file_attachement, + null, _PS_MAIL_DIR_, false, (int)$order->id_shop + ); + } + } + + // updates stock in shops + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $product_list = $order->getProducts(); + foreach ($product_list as $product) { + // if the available quantities depends on the physical stock + if (StockAvailable::dependsOnStock($product['product_id'])) { + // synchronizes + StockAvailable::synchronize($product['product_id'], $order->id_shop); + } + } + } + + $order->updateOrderDetailTax(); + } else { + $error = Tools::displayError('Order creation failed'); + PrestaShopLogger::addLog($error, 4, '0000002', 'Cart', intval($order->id_cart)); + die($error); + } + } // End foreach $order_detail_list + + // Use the last order as currentOrder + if (isset($order) && $order->id) { + $this->currentOrder = (int)$order->id; + } + + if (self::DEBUG_MODE) { + PrestaShopLogger::addLog('PaymentModule::validateOrder - End of validateOrder', 1, null, 'Cart', (int)$id_cart, true); + } + + return true; + } else { + $error = Tools::displayError('Cart cannot be loaded or an order has already been placed using this cart'); + PrestaShopLogger::addLog($error, 4, '0000001', 'Cart', intval($this->context->cart->id)); + die($error); + } + } + + /** + * @deprecated 1.6.0.7 + * @param mixed $content + * @return mixed + */ + public function formatProductAndVoucherForEmail($content) + { + Tools::displayAsDeprecated(); + return $content; + } + + /** + * @param Object Address $the_address that needs to be txt formated + * @return String the txt formated address block + */ + protected function _getTxtFormatedAddress($the_address) + { + $adr_fields = AddressFormat::getOrderedAddressFields($the_address->id_country, false, true); + $r_values = array(); + foreach ($adr_fields as $fields_line) { + $tmp_values = array(); + foreach (explode(' ', $fields_line) as $field_item) { + $field_item = trim($field_item); + $tmp_values[] = $the_address->{$field_item}; + } + $r_values[] = implode(' ', $tmp_values); + } + + $out = implode("\n", $r_values); + return $out; + } + + /** + * @param Object Address $the_address that needs to be txt formated + * @return String the txt formated address block + */ + + protected function _getFormatedAddress(Address $the_address, $line_sep, $fields_style = array()) + { + return AddressFormat::generateAddress($the_address, array('avoid' => array()), $line_sep, ' ', $fields_style); + } + + /** + * @param int $id_currency : this parameter is optionnal but on 1.5 version of Prestashop, it will be REQUIRED + * @return Currency + */ + public function getCurrency($current_id_currency = null) + { + if (!(int)$current_id_currency) { + $current_id_currency = Context::getContext()->currency->id; + } + + if (!$this->currencies) { + return false; + } + if ($this->currencies_mode == 'checkbox') { + $currencies = Currency::getPaymentCurrencies($this->id); + return $currencies; + } elseif ($this->currencies_mode == 'radio') { + $currencies = Currency::getPaymentCurrenciesSpecial($this->id); + $currency = $currencies['id_currency']; + if ($currency == -1) { + $id_currency = (int)$current_id_currency; + } elseif ($currency == -2) { + $id_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT'); + } else { + $id_currency = $currency; + } + } + if (!isset($id_currency) || empty($id_currency)) { + return false; + } + $currency = new Currency($id_currency); + return $currency; + } + + /** + * Allows specified payment modules to be used by a specific currency + * + * @since 1.4.5 + * @param int $id_currency + * @param array $id_module_list + * @return bool + */ + public static function addCurrencyPermissions($id_currency, array $id_module_list = array()) + { + $values = ''; + if (count($id_module_list) == 0) { + // fetch all installed module ids + $modules = PaymentModuleCore::getInstalledPaymentModules(); + foreach ($modules as $module) { + $id_module_list[] = $module['id_module']; + } + } + + foreach ($id_module_list as $id_module) { + $values .= '('.(int)$id_module.','.(int)$id_currency.'),'; + } + + if (!empty($values)) { + return Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'module_currency` (`id_module`, `id_currency`) VALUES '.rtrim($values, ',')); - } + } - return true; - } + return true; + } - /** - * List all installed and active payment modules - * @see Module::getPaymentModules() if you need a list of module related to the user context - * - * @since 1.4.5 - * @return array module informations - */ - public static function getInstalledPaymentModules() - { - $hook_payment = 'Payment'; - if (Db::getInstance()->getValue('SELECT `id_hook` FROM `'._DB_PREFIX_.'hook` WHERE `name` = \'displayPayment\'')) - $hook_payment = 'displayPayment'; + /** + * List all installed and active payment modules + * @see Module::getPaymentModules() if you need a list of module related to the user context + * + * @since 1.4.5 + * @return array module informations + */ + public static function getInstalledPaymentModules() + { + $hook_payment = 'Payment'; + if (Db::getInstance()->getValue('SELECT `id_hook` FROM `'._DB_PREFIX_.'hook` WHERE `name` = \'displayPayment\'')) { + $hook_payment = 'displayPayment'; + } - return Db::getInstance()->executeS(' + return Db::getInstance()->executeS(' SELECT DISTINCT m.`id_module`, h.`id_hook`, m.`name`, hm.`position` FROM `'._DB_PREFIX_.'module` m LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_module` = m.`id_module`' - .Shop::addSqlRestriction(false, 'hm').' + .Shop::addSqlRestriction(false, 'hm').' LEFT JOIN `'._DB_PREFIX_.'hook` h ON hm.`id_hook` = h.`id_hook` INNER JOIN `'._DB_PREFIX_.'module_shop` ms ON (m.`id_module` = ms.`id_module` AND ms.id_shop='.(int)Context::getContext()->shop->id.') WHERE h.`name` = \''.pSQL($hook_payment).'\''); - } + } - public static function preCall($module_name) - { - if (!parent::preCall($module_name)) - return false; + public static function preCall($module_name) + { + if (!parent::preCall($module_name)) { + return false; + } - if (($module_instance = Module::getInstanceByName($module_name))) - { - /** @var PaymentModule $module_instance */ - if (!$module_instance->currencies || ($module_instance->currencies && count(Currency::checkPaymentCurrencies($module_instance->id)))) - return true; - } + if (($module_instance = Module::getInstanceByName($module_name))) { + /** @var PaymentModule $module_instance */ + if (!$module_instance->currencies || ($module_instance->currencies && count(Currency::checkPaymentCurrencies($module_instance->id)))) { + return true; + } + } - return false; - } + return false; + } - /** - * Fetch the content of $template_name inside the folder current_theme/mails/current_iso_lang/ if found, otherwise in mails/current_iso_lang - * - * @param string $template_name template name with extension - * @param int $mail_type Mail::TYPE_HTML or Mail::TYPE_TXT - * @param array $var list send to smarty - * - * @return string - */ - protected function getEmailTemplateContent($template_name, $mail_type, $var) - { - $email_configuration = Configuration::get('PS_MAIL_TYPE'); - if ($email_configuration != $mail_type && $email_configuration != Mail::TYPE_BOTH) - return ''; + /** + * Fetch the content of $template_name inside the folder current_theme/mails/current_iso_lang/ if found, otherwise in mails/current_iso_lang + * + * @param string $template_name template name with extension + * @param int $mail_type Mail::TYPE_HTML or Mail::TYPE_TXT + * @param array $var list send to smarty + * + * @return string + */ + protected function getEmailTemplateContent($template_name, $mail_type, $var) + { + $email_configuration = Configuration::get('PS_MAIL_TYPE'); + if ($email_configuration != $mail_type && $email_configuration != Mail::TYPE_BOTH) { + return ''; + } - $theme_template_path = _PS_THEME_DIR_.'mails'.DIRECTORY_SEPARATOR.$this->context->language->iso_code.DIRECTORY_SEPARATOR.$template_name; - $default_mail_template_path = _PS_MAIL_DIR_.$this->context->language->iso_code.DIRECTORY_SEPARATOR.$template_name; + $theme_template_path = _PS_THEME_DIR_.'mails'.DIRECTORY_SEPARATOR.$this->context->language->iso_code.DIRECTORY_SEPARATOR.$template_name; + $default_mail_template_path = _PS_MAIL_DIR_.$this->context->language->iso_code.DIRECTORY_SEPARATOR.$template_name; - if (Tools::file_exists_cache($theme_template_path)) - $default_mail_template_path = $theme_template_path; + if (Tools::file_exists_cache($theme_template_path)) { + $default_mail_template_path = $theme_template_path; + } - if (Tools::file_exists_cache($default_mail_template_path)) - { - $this->context->smarty->assign('list', $var); - return $this->context->smarty->fetch($default_mail_template_path); - } - return ''; - } + if (Tools::file_exists_cache($default_mail_template_path)) { + $this->context->smarty->assign('list', $var); + return $this->context->smarty->fetch($default_mail_template_path); + } + return ''; + } } diff --git a/classes/PrestaShopAutoload.php b/classes/PrestaShopAutoload.php index a453977b..70bfed2a 100644 --- a/classes/PrestaShopAutoload.php +++ b/classes/PrestaShopAutoload.php @@ -29,195 +29,198 @@ */ class PrestaShopAutoload { - /** - * File where classes index is stored - */ - const INDEX_FILE = 'cache/class_index.php'; + /** + * File where classes index is stored + */ + const INDEX_FILE = 'cache/class_index.php'; - /** - * @var PrestaShopAutoload - */ - protected static $instance; + /** + * @var PrestaShopAutoload + */ + protected static $instance; - /** - * @var string Root directory - */ - protected $root_dir; + /** + * @var string Root directory + */ + protected $root_dir; - /** - * @var array array('classname' => 'path/to/override', 'classnamecore' => 'path/to/class/core') - */ - public $index = array(); + /** + * @var array array('classname' => 'path/to/override', 'classnamecore' => 'path/to/class/core') + */ + public $index = array(); - public $_include_override_path = true; + public $_include_override_path = true; - protected static $class_aliases = array( - 'Collection' => 'PrestaShopCollection', - 'Autoload' => 'PrestaShopAutoload', - 'Backup' => 'PrestaShopBackup', - 'Logger' => 'PrestaShopLogger' - ); + protected static $class_aliases = array( + 'Collection' => 'PrestaShopCollection', + 'Autoload' => 'PrestaShopAutoload', + 'Backup' => 'PrestaShopBackup', + 'Logger' => 'PrestaShopLogger' + ); - protected function __construct() - { - $this->root_dir = _PS_CORE_DIR_.'/'; - $file = $this->normalizeDirectory(_PS_ROOT_DIR_).PrestaShopAutoload::INDEX_FILE; - if (@filemtime($file) && is_readable($file)) - $this->index = include($file); - else - $this->generateIndex(); - } + protected function __construct() + { + $this->root_dir = _PS_CORE_DIR_.'/'; + $file = $this->normalizeDirectory(_PS_ROOT_DIR_).PrestaShopAutoload::INDEX_FILE; + if (@filemtime($file) && is_readable($file)) { + $this->index = include($file); + } else { + $this->generateIndex(); + } + } - /** - * Get instance of autoload (singleton) - * - * @return PrestaShopAutoload - */ - public static function getInstance() - { - if (!PrestaShopAutoload::$instance) - PrestaShopAutoload::$instance = new PrestaShopAutoload(); + /** + * Get instance of autoload (singleton) + * + * @return PrestaShopAutoload + */ + public static function getInstance() + { + if (!PrestaShopAutoload::$instance) { + PrestaShopAutoload::$instance = new PrestaShopAutoload(); + } - return PrestaShopAutoload::$instance; - } + return PrestaShopAutoload::$instance; + } - /** - * Retrieve informations about a class in classes index and load it - * - * @param string $classname - */ - public function load($classname) - { - // Retrocompatibility - if (isset(PrestaShopAutoload::$class_aliases[$classname]) && !interface_exists($classname, false) && !class_exists($classname, false)) - return eval('class '.$classname.' extends '.PrestaShopAutoload::$class_aliases[$classname].' {}'); + /** + * Retrieve informations about a class in classes index and load it + * + * @param string $classname + */ + public function load($classname) + { + // Retrocompatibility + if (isset(PrestaShopAutoload::$class_aliases[$classname]) && !interface_exists($classname, false) && !class_exists($classname, false)) { + return eval('class '.$classname.' extends '.PrestaShopAutoload::$class_aliases[$classname].' {}'); + } - // regenerate the class index if the requested file doesn't exists - if ((isset($this->index[$classname]) && $this->index[$classname]['path'] && !is_file($this->root_dir.$this->index[$classname]['path'])) - || (isset($this->index[$classname.'Core']) && $this->index[$classname.'Core']['path'] && !is_file($this->root_dir.$this->index[$classname.'Core']['path']))) - $this->generateIndex(); + // regenerate the class index if the requested file doesn't exists + if ((isset($this->index[$classname]) && $this->index[$classname]['path'] && !is_file($this->root_dir.$this->index[$classname]['path'])) + || (isset($this->index[$classname.'Core']) && $this->index[$classname.'Core']['path'] && !is_file($this->root_dir.$this->index[$classname.'Core']['path']))) { + $this->generateIndex(); + } - // If $classname has not core suffix (E.g. Shop, Product) - if (substr($classname, -4) != 'Core') - { - $class_dir = (isset($this->index[$classname]['override']) - && $this->index[$classname]['override'] === true) ? $this->normalizeDirectory(_PS_ROOT_DIR_) : $this->root_dir; + // If $classname has not core suffix (E.g. Shop, Product) + if (substr($classname, -4) != 'Core') { + $class_dir = (isset($this->index[$classname]['override']) + && $this->index[$classname]['override'] === true) ? $this->normalizeDirectory(_PS_ROOT_DIR_) : $this->root_dir; - // If requested class does not exist, load associated core class - if (isset($this->index[$classname]) && !$this->index[$classname]['path']) - { - require_once($class_dir.$this->index[$classname.'Core']['path']); + // If requested class does not exist, load associated core class + if (isset($this->index[$classname]) && !$this->index[$classname]['path']) { + require_once($class_dir.$this->index[$classname.'Core']['path']); - if ($this->index[$classname.'Core']['type'] != 'interface') - eval($this->index[$classname.'Core']['type'].' '.$classname.' extends '.$classname.'Core {}'); - } - else - { - // request a non Core Class load the associated Core class if exists - if (isset($this->index[$classname.'Core'])) - require_once($this->root_dir.$this->index[$classname.'Core']['path']); + if ($this->index[$classname.'Core']['type'] != 'interface') { + eval($this->index[$classname.'Core']['type'].' '.$classname.' extends '.$classname.'Core {}'); + } + } else { + // request a non Core Class load the associated Core class if exists + if (isset($this->index[$classname.'Core'])) { + require_once($this->root_dir.$this->index[$classname.'Core']['path']); + } - if (isset($this->index[$classname])) - require_once($class_dir.$this->index[$classname]['path']); - } - } - // Call directly ProductCore, ShopCore class - elseif (isset($this->index[$classname]['path']) && $this->index[$classname]['path']) - require_once($this->root_dir.$this->index[$classname]['path']); - } + if (isset($this->index[$classname])) { + require_once($class_dir.$this->index[$classname]['path']); + } + } + } + // Call directly ProductCore, ShopCore class + elseif (isset($this->index[$classname]['path']) && $this->index[$classname]['path']) { + require_once($this->root_dir.$this->index[$classname]['path']); + } + } - /** - * Generate classes index - */ - public function generateIndex() - { - $classes = array_merge( - $this->getClassesFromDir('classes/'), - $this->getClassesFromDir('controllers/'), - $this->getClassesFromDir('Adapter/'), - $this->getClassesFromDir('Core/') - ); + /** + * Generate classes index + */ + public function generateIndex() + { + $classes = array_merge( + $this->getClassesFromDir('classes/'), + $this->getClassesFromDir('controllers/'), + $this->getClassesFromDir('Adapter/'), + $this->getClassesFromDir('Core/') + ); - if ($this->_include_override_path) - $classes = array_merge( - $classes, - $this->getClassesFromDir('override/classes/', defined('_PS_HOST_MODE_')), - $this->getClassesFromDir('override/controllers/', defined('_PS_HOST_MODE_')) - ); + if ($this->_include_override_path) { + $classes = array_merge( + $classes, + $this->getClassesFromDir('override/classes/', defined('_PS_HOST_MODE_')), + $this->getClassesFromDir('override/controllers/', defined('_PS_HOST_MODE_')) + ); + } - ksort($classes); - $content = '<?php return '.var_export($classes, true).'; ?>'; + ksort($classes); + $content = '<?php return '.var_export($classes, true).'; ?>'; - // Write classes index on disc to cache it - $filename = $this->normalizeDirectory(_PS_ROOT_DIR_).PrestaShopAutoload::INDEX_FILE; - $filename_tmp = tempnam(dirname($filename), basename($filename.'.')); - if ($filename_tmp !== false && file_put_contents($filename_tmp, $content) !== false) - { - if (!@rename($filename_tmp, $filename)) - unlink($filename_tmp); - else - @chmod($filename, 0666); - } - // $filename_tmp couldn't be written. $filename should be there anyway (even if outdated), no need to die. - else - Tools::error_log('Cannot write temporary file '.$filename_tmp); - $this->index = $classes; - } + // Write classes index on disc to cache it + $filename = $this->normalizeDirectory(_PS_ROOT_DIR_).PrestaShopAutoload::INDEX_FILE; + $filename_tmp = tempnam(dirname($filename), basename($filename.'.')); + if ($filename_tmp !== false && file_put_contents($filename_tmp, $content) !== false) { + if (!@rename($filename_tmp, $filename)) { + unlink($filename_tmp); + } else { + @chmod($filename, 0666); + } + } + // $filename_tmp couldn't be written. $filename should be there anyway (even if outdated), no need to die. + else { + Tools::error_log('Cannot write temporary file '.$filename_tmp); + } + $this->index = $classes; + } - /** - * Retrieve recursively all classes in a directory and its subdirectories - * - * @param string $path Relativ path from root to the directory - * @return array - */ - protected function getClassesFromDir($path, $host_mode = false) - { - $classes = array(); - $root_dir = $host_mode ? $this->normalizeDirectory(_PS_ROOT_DIR_) : $this->root_dir; + /** + * Retrieve recursively all classes in a directory and its subdirectories + * + * @param string $path Relativ path from root to the directory + * @return array + */ + protected function getClassesFromDir($path, $host_mode = false) + { + $classes = array(); + $root_dir = $host_mode ? $this->normalizeDirectory(_PS_ROOT_DIR_) : $this->root_dir; - foreach (scandir($root_dir.$path) as $file) - { - if ($file[0] != '.') - { - if (is_dir($root_dir.$path.$file)) - $classes = array_merge($classes, $this->getClassesFromDir($path.$file.'/', $host_mode)); - elseif (substr($file, -4) == '.php') - { - $content = file_get_contents($root_dir.$path.$file); + foreach (scandir($root_dir.$path) as $file) { + if ($file[0] != '.') { + if (is_dir($root_dir.$path.$file)) { + $classes = array_merge($classes, $this->getClassesFromDir($path.$file.'/', $host_mode)); + } elseif (substr($file, -4) == '.php') { + $content = file_get_contents($root_dir.$path.$file); - $namespacePattern = '[\\a-z0-9_]*[\\]'; - $pattern = '#\W((abstract\s+)?class|interface)\s+(?P<classname>'.basename($file, '.php').'(?:Core)?)' - .'(?:\s+extends\s+'.$namespacePattern.'[a-z][a-z0-9_]*)?(?:\s+implements\s+'.$namespacePattern.'[a-z][\\a-z0-9_]*(?:\s*,\s*'.$namespacePattern.'[a-z][\\a-z0-9_]*)*)?\s*\{#i'; + $namespacePattern = '[\\a-z0-9_]*[\\]'; + $pattern = '#\W((abstract\s+)?class|interface)\s+(?P<classname>'.basename($file, '.php').'(?:Core)?)' + .'(?:\s+extends\s+'.$namespacePattern.'[a-z][a-z0-9_]*)?(?:\s+implements\s+'.$namespacePattern.'[a-z][\\a-z0-9_]*(?:\s*,\s*'.$namespacePattern.'[a-z][\\a-z0-9_]*)*)?\s*\{#i'; - if (preg_match($pattern, $content, $m)) - { - $classes[$m['classname']] = array( - 'path' => $path.$file, - 'type' => trim($m[1]), - 'override' => $host_mode - ); + if (preg_match($pattern, $content, $m)) { + $classes[$m['classname']] = array( + 'path' => $path.$file, + 'type' => trim($m[1]), + 'override' => $host_mode + ); - if (substr($m['classname'], -4) == 'Core') - $classes[substr($m['classname'], 0, -4)] = array( - 'path' => '', - 'type' => $classes[$m['classname']]['type'], - 'override' => $host_mode - ); - } - } - } - } + if (substr($m['classname'], -4) == 'Core') { + $classes[substr($m['classname'], 0, -4)] = array( + 'path' => '', + 'type' => $classes[$m['classname']]['type'], + 'override' => $host_mode + ); + } + } + } + } + } - return $classes; - } + return $classes; + } - public function getClassPath($classname) - { - return (isset($this->index[$classname]) && isset($this->index[$classname]['path'])) ? $this->index[$classname]['path'] : null; - } + public function getClassPath($classname) + { + return (isset($this->index[$classname]) && isset($this->index[$classname]['path'])) ? $this->index[$classname]['path'] : null; + } - private function normalizeDirectory($directory) - { - return rtrim($directory, '/\\').DIRECTORY_SEPARATOR; - } + private function normalizeDirectory($directory) + { + return rtrim($directory, '/\\').DIRECTORY_SEPARATOR; + } } diff --git a/classes/PrestaShopBackup.php b/classes/PrestaShopBackup.php index 56fb2be9..7b2075b6 100644 --- a/classes/PrestaShopBackup.php +++ b/classes/PrestaShopBackup.php @@ -26,287 +26,283 @@ class PrestaShopBackupCore { - /** @var int Object id */ - public $id; - /** @var string Last error messages */ - public $error; + /** @var int Object id */ + public $id; + /** @var string Last error messages */ + public $error; /** @var string default backup directory. */ - public static $backupDir = '/backups/'; - /** @var string custom backup directory. */ - public $customBackupDir = null; + public static $backupDir = '/backups/'; + /** @var string custom backup directory. */ + public $customBackupDir = null; - public $psBackupAll = true; - public $psBackupDropTable = true; + public $psBackupAll = true; + public $psBackupDropTable = true; - /** - * Creates a new backup object - * - * @param string $filename Filename of the backup file - */ - public function __construct($filename = null) - { - if ($filename) - $this->id = $this->getRealBackupPath($filename); + /** + * Creates a new backup object + * + * @param string $filename Filename of the backup file + */ + public function __construct($filename = null) + { + if ($filename) { + $this->id = $this->getRealBackupPath($filename); + } - $psBackupAll = Configuration::get('PS_BACKUP_ALL'); - $psBackupDropTable = Configuration::get('PS_BACKUP_DROP_TABLE'); - $this->psBackupAll = $psBackupAll !== false ? $psBackupAll : true; - $this->psBackupDropTable = $psBackupDropTable !== false ? $psBackupDropTable : true; - } + $psBackupAll = Configuration::get('PS_BACKUP_ALL'); + $psBackupDropTable = Configuration::get('PS_BACKUP_DROP_TABLE'); + $this->psBackupAll = $psBackupAll !== false ? $psBackupAll : true; + $this->psBackupDropTable = $psBackupDropTable !== false ? $psBackupDropTable : true; + } - /** - * you can set a different path with that function - * - * @TODO include the prefix name - * @param string $dir - * @return bool bo - */ - public function setCustomBackupPath($dir) - { - $custom_dir = DIRECTORY_SEPARATOR.trim($dir, '/').DIRECTORY_SEPARATOR; - if (is_dir((defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_ : _PS_ADMIN_DIR_).$custom_dir)) - $this->customBackupDir = $custom_dir; - else - return false; + /** + * you can set a different path with that function + * + * @TODO include the prefix name + * @param string $dir + * @return bool bo + */ + public function setCustomBackupPath($dir) + { + $custom_dir = DIRECTORY_SEPARATOR.trim($dir, '/').DIRECTORY_SEPARATOR; + if (is_dir((defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_ : _PS_ADMIN_DIR_).$custom_dir)) { + $this->customBackupDir = $custom_dir; + } else { + return false; + } - return true; - } + return true; + } - /** - * get the path to use for backup (customBackupDir if specified, or default) - * - * @param string $filename filename to use - * @return string full path - */ - public function getRealBackupPath($filename = null) - { - $backupDir = PrestaShopBackup::getBackupPath($filename); - if (!empty($this->customBackupDir)) - { - $backupDir = str_replace((defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_ : _PS_ADMIN_DIR_).self::$backupDir, - (defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_ : _PS_ADMIN_DIR_).$this->customBackupDir, $backupDir); + /** + * get the path to use for backup (customBackupDir if specified, or default) + * + * @param string $filename filename to use + * @return string full path + */ + public function getRealBackupPath($filename = null) + { + $backupDir = PrestaShopBackup::getBackupPath($filename); + if (!empty($this->customBackupDir)) { + $backupDir = str_replace((defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_ : _PS_ADMIN_DIR_).self::$backupDir, + (defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_ : _PS_ADMIN_DIR_).$this->customBackupDir, $backupDir); - if (strrpos($backupDir, DIRECTORY_SEPARATOR)) - $backupDir .= DIRECTORY_SEPARATOR; - } - return $backupDir; - } + if (strrpos($backupDir, DIRECTORY_SEPARATOR)) { + $backupDir .= DIRECTORY_SEPARATOR; + } + } + return $backupDir; + } - /** - * Get the full path of the backup file - * - * @param string $filename prefix of the backup file (datetime will be the second part) - * @return string The full path of the backup file, or false if the backup file does not exists - */ - public static function getBackupPath($filename = '') - { - $backupdir = realpath((defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_ : _PS_ADMIN_DIR_).self::$backupDir); + /** + * Get the full path of the backup file + * + * @param string $filename prefix of the backup file (datetime will be the second part) + * @return string The full path of the backup file, or false if the backup file does not exists + */ + public static function getBackupPath($filename = '') + { + $backupdir = realpath((defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_ : _PS_ADMIN_DIR_).self::$backupDir); - if ($backupdir === false) - die(Tools::displayError('"Backup" directory does not exist.')); + if ($backupdir === false) { + die(Tools::displayError('"Backup" directory does not exist.')); + } - // Check the realpath so we can validate the backup file is under the backup directory - if (!empty($filename)) - $backupfile = realpath($backupdir.DIRECTORY_SEPARATOR.$filename); - else - $backupfile = $backupdir.DIRECTORY_SEPARATOR; + // Check the realpath so we can validate the backup file is under the backup directory + if (!empty($filename)) { + $backupfile = realpath($backupdir.DIRECTORY_SEPARATOR.$filename); + } else { + $backupfile = $backupdir.DIRECTORY_SEPARATOR; + } - if ($backupfile === false || strncmp($backupdir, $backupfile, strlen($backupdir)) != 0) - die (Tools::displayError()); + if ($backupfile === false || strncmp($backupdir, $backupfile, strlen($backupdir)) != 0) { + die(Tools::displayError()); + } - return $backupfile; - } + return $backupfile; + } - /** - * Check if a backup file exist - * - * @param string $filename prefix of the backup file (datetime will be the second part) - * @return bool true if backup file exist - */ - public static function backupExist($filename) - { - $backupdir = realpath((defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_ : _PS_ADMIN_DIR_).self::$backupDir); + /** + * Check if a backup file exist + * + * @param string $filename prefix of the backup file (datetime will be the second part) + * @return bool true if backup file exist + */ + public static function backupExist($filename) + { + $backupdir = realpath((defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_ : _PS_ADMIN_DIR_).self::$backupDir); - if ($backupdir === false) - die(Tools::displayError('"Backup" directory does not exist.')); + if ($backupdir === false) { + die(Tools::displayError('"Backup" directory does not exist.')); + } - return @filemtime($backupdir.DIRECTORY_SEPARATOR.$filename); - } - /** - * Get the URL used to retrieve this backup file - * - * @return string The url used to request the backup file - */ - public function getBackupURL() - { - return __PS_BASE_URI__.basename(_PS_ADMIN_DIR_).'/backup.php?filename='.basename($this->id); - } + return @filemtime($backupdir.DIRECTORY_SEPARATOR.$filename); + } + /** + * Get the URL used to retrieve this backup file + * + * @return string The url used to request the backup file + */ + public function getBackupURL() + { + return __PS_BASE_URI__.basename(_PS_ADMIN_DIR_).'/backup.php?filename='.basename($this->id); + } - /** - * Delete the current backup file - * - * @return bool Deletion result, true on success - */ - public function delete() - { - if (!$this->id || !unlink($this->id)) - { - $this->error = Tools::displayError('Error deleting').' '.($this->id ? '"'.$this->id.'"' : - Tools::displayError('Invalid ID')); - return false; - } - return true; - } + /** + * Delete the current backup file + * + * @return bool Deletion result, true on success + */ + public function delete() + { + if (!$this->id || !unlink($this->id)) { + $this->error = Tools::displayError('Error deleting').' '.($this->id ? '"'.$this->id.'"' : + Tools::displayError('Invalid ID')); + return false; + } + return true; + } - /** - * Deletes a range of backup files - * - * @return bool True on success - */ - public function deleteSelection($list) - { - foreach ($list as $file) - { - $backup = new PrestaShopBackup($file); - if (!$backup->delete()) - { - $this->error = $backup->error; - return false; - } - } - return true; - } + /** + * Deletes a range of backup files + * + * @return bool True on success + */ + public function deleteSelection($list) + { + foreach ($list as $file) { + $backup = new PrestaShopBackup($file); + if (!$backup->delete()) { + $this->error = $backup->error; + return false; + } + } + return true; + } - /** - * Creates a new backup file - * - * @return bool true on successful backup - */ - public function add() - { - if (!$this->psBackupAll) - $ignore_insert_table = array(_DB_PREFIX_.'connections', _DB_PREFIX_.'connections_page', _DB_PREFIX_ - .'connections_source', _DB_PREFIX_.'guest', _DB_PREFIX_.'statssearch'); - else - $ignore_insert_table = array(); + /** + * Creates a new backup file + * + * @return bool true on successful backup + */ + public function add() + { + if (!$this->psBackupAll) { + $ignore_insert_table = array(_DB_PREFIX_.'connections', _DB_PREFIX_.'connections_page', _DB_PREFIX_ + .'connections_source', _DB_PREFIX_.'guest', _DB_PREFIX_.'statssearch'); + } else { + $ignore_insert_table = array(); + } - // Generate some random number, to make it extra hard to guess backup file names - $rand = dechex ( mt_rand(0, min(0xffffffff, mt_getrandmax() ) ) ); - $date = time(); - $backupfile = $this->getRealBackupPath().$date.'-'.$rand.'.sql'; + // Generate some random number, to make it extra hard to guess backup file names + $rand = dechex(mt_rand(0, min(0xffffffff, mt_getrandmax()))); + $date = time(); + $backupfile = $this->getRealBackupPath().$date.'-'.$rand.'.sql'; - // Figure out what compression is available and open the file - if (function_exists('bzopen')) - { - $backupfile .= '.bz2'; - $fp = @bzopen($backupfile, 'w'); - } - elseif (function_exists('gzopen')) - { - $backupfile .= '.gz'; - $fp = @gzopen($backupfile, 'w'); - } - else - $fp = @fopen($backupfile, 'w'); + // Figure out what compression is available and open the file + if (function_exists('bzopen')) { + $backupfile .= '.bz2'; + $fp = @bzopen($backupfile, 'w'); + } elseif (function_exists('gzopen')) { + $backupfile .= '.gz'; + $fp = @gzopen($backupfile, 'w'); + } else { + $fp = @fopen($backupfile, 'w'); + } - if ($fp === false) - { - echo Tools::displayError('Unable to create backup file').' "'.addslashes($backupfile).'"'; - return false; - } + if ($fp === false) { + echo Tools::displayError('Unable to create backup file').' "'.addslashes($backupfile).'"'; + return false; + } - $this->id = realpath($backupfile); + $this->id = realpath($backupfile); - fwrite($fp, '/* Backup for '.Tools::getHttpHost(false, false).__PS_BASE_URI__."\n * at ".date($date)."\n */\n"); - fwrite($fp, "\n".'SET NAMES \'utf8\';'."\n\n"); + fwrite($fp, '/* Backup for '.Tools::getHttpHost(false, false).__PS_BASE_URI__."\n * at ".date($date)."\n */\n"); + fwrite($fp, "\n".'SET NAMES \'utf8\';'."\n\n"); - // Find all tables - $tables = Db::getInstance()->executeS('SHOW TABLES'); - $found = 0; - foreach ($tables as $table) - { - $table = current($table); + // Find all tables + $tables = Db::getInstance()->executeS('SHOW TABLES'); + $found = 0; + foreach ($tables as $table) { + $table = current($table); - // Skip tables which do not start with _DB_PREFIX_ - if (strlen($table) < strlen(_DB_PREFIX_) || strncmp($table, _DB_PREFIX_, strlen(_DB_PREFIX_)) != 0) - continue; + // Skip tables which do not start with _DB_PREFIX_ + if (strlen($table) < strlen(_DB_PREFIX_) || strncmp($table, _DB_PREFIX_, strlen(_DB_PREFIX_)) != 0) { + continue; + } - // Export the table schema - $schema = Db::getInstance()->executeS('SHOW CREATE TABLE `'.$table.'`'); + // Export the table schema + $schema = Db::getInstance()->executeS('SHOW CREATE TABLE `'.$table.'`'); - if (count($schema) != 1 || !isset($schema[0]['Table']) || !isset($schema[0]['Create Table'])) - { - fclose($fp); - $this->delete(); - echo Tools::displayError('An error occurred while backing up. Unable to obtain the schema of').' "'.$table; - return false; - } + if (count($schema) != 1 || !isset($schema[0]['Table']) || !isset($schema[0]['Create Table'])) { + fclose($fp); + $this->delete(); + echo Tools::displayError('An error occurred while backing up. Unable to obtain the schema of').' "'.$table; + return false; + } - fwrite($fp, '/* Scheme for table '.$schema[0]['Table']." */\n"); + fwrite($fp, '/* Scheme for table '.$schema[0]['Table']." */\n"); - if ($this->psBackupDropTable) - fwrite($fp, 'DROP TABLE IF EXISTS `'.$schema[0]['Table'].'`;'."\n"); + if ($this->psBackupDropTable) { + fwrite($fp, 'DROP TABLE IF EXISTS `'.$schema[0]['Table'].'`;'."\n"); + } - fwrite($fp, $schema[0]['Create Table'].";\n\n"); + fwrite($fp, $schema[0]['Create Table'].";\n\n"); - if (!in_array($schema[0]['Table'], $ignore_insert_table)) - { - $data = Db::getInstance()->query('SELECT * FROM `'.$schema[0]['Table'].'`', false); - $sizeof = DB::getInstance()->NumRows(); - $lines = explode("\n", $schema[0]['Create Table']); + if (!in_array($schema[0]['Table'], $ignore_insert_table)) { + $data = Db::getInstance()->query('SELECT * FROM `'.$schema[0]['Table'].'`', false); + $sizeof = DB::getInstance()->NumRows(); + $lines = explode("\n", $schema[0]['Create Table']); - if ($data && $sizeof > 0) - { - // Export the table data - fwrite($fp, 'INSERT INTO `'.$schema[0]['Table']."` VALUES\n"); - $i = 1; - while ($row = DB::getInstance()->nextRow($data)) - { - $s = '('; + if ($data && $sizeof > 0) { + // Export the table data + fwrite($fp, 'INSERT INTO `'.$schema[0]['Table']."` VALUES\n"); + $i = 1; + while ($row = DB::getInstance()->nextRow($data)) { + $s = '('; - foreach ($row as $field => $value) - { - $tmp = "'".pSQL($value, true)."',"; - if ($tmp != "'',") - $s .= $tmp; - else - { - foreach ($lines as $line) - if (strpos($line, '`'.$field.'`') !== false) - { - if (preg_match('/(.*NOT NULL.*)/Ui', $line)) - $s .= "'',"; - else - $s .= 'NULL,'; - break; - } - } - } - $s = rtrim($s, ','); + foreach ($row as $field => $value) { + $tmp = "'".pSQL($value, true)."',"; + if ($tmp != "'',") { + $s .= $tmp; + } else { + foreach ($lines as $line) { + if (strpos($line, '`'.$field.'`') !== false) { + if (preg_match('/(.*NOT NULL.*)/Ui', $line)) { + $s .= "'',"; + } else { + $s .= 'NULL,'; + } + break; + } + } + } + } + $s = rtrim($s, ','); - if ($i % 200 == 0 && $i < $sizeof) - $s .= ");\nINSERT INTO `".$schema[0]['Table']."` VALUES\n"; - elseif ($i < $sizeof) - $s .= "),\n"; - else - $s .= ");\n"; + if ($i % 200 == 0 && $i < $sizeof) { + $s .= ");\nINSERT INTO `".$schema[0]['Table']."` VALUES\n"; + } elseif ($i < $sizeof) { + $s .= "),\n"; + } else { + $s .= ");\n"; + } - fwrite($fp, $s); - ++$i; - } - } - } - $found++; - } + fwrite($fp, $s); + ++$i; + } + } + } + $found++; + } - fclose($fp); - if ($found == 0) - { - $this->delete(); - echo Tools::displayError('No valid tables were found to backup.' ); - return false; - } + fclose($fp); + if ($found == 0) { + $this->delete(); + echo Tools::displayError('No valid tables were found to backup.'); + return false; + } - return true; - } -} \ No newline at end of file + return true; + } +} diff --git a/classes/PrestaShopCollection.php b/classes/PrestaShopCollection.php index f4edb8f5..646896f1 100644 --- a/classes/PrestaShopCollection.php +++ b/classes/PrestaShopCollection.php @@ -31,687 +31,696 @@ */ class PrestaShopCollectionCore implements Iterator, ArrayAccess, Countable { - const LEFT_JOIN = 1; - const INNER_JOIN = 2; - const LEFT_OUTER_JOIN = 3; - - /** - * @var string Object class name - */ - protected $classname; - - /** - * @var int - */ - protected $id_lang; - - /** - * @var array Object definition - */ - protected $definition = array(); - - /** - * @var DbQuery - */ - protected $query; - - /** - * @var array Collection of objects in an array - */ - protected $results = array(); - - /** - * @var bool Is current collection already hydrated - */ - protected $is_hydrated = false; - - /** - * @var int Collection iterator - */ - protected $iterator = 0; - - /** - * @var int Total of elements for iteration - */ - protected $total; - - /** - * @var int Page number - */ - protected $page_number = 0; - - /** - * @var int Size of a page - */ - protected $page_size = 0; - - protected $fields = array(); - protected $alias = array(); - protected $alias_iterator = 0; - protected $join_list = array(); - protected $association_definition = array(); - - const LANG_ALIAS = 'l'; - - /** - * @param string $classname - * @param int $id_lang - */ - public function __construct($classname, $id_lang = null) - { - $this->classname = $classname; - $this->id_lang = $id_lang; - - $this->definition = ObjectModel::getDefinition($this->classname); - if (!isset($this->definition['table'])) - throw new PrestaShopException('Miss table in definition for class '.$this->classname); - elseif (!isset($this->definition['primary'])) - throw new PrestaShopException('Miss primary in definition for class '.$this->classname); - - $this->query = new DbQuery(); - } - - /** - * Join current entity to an associated entity - * - * @param string $association Association name - * @param string $on - * @param int $type - * @return PrestaShopCollection - */ - public function join($association, $on = '', $type = null) - { - if (!$association) - return; - - if (!isset($this->join_list[$association])) - { - $definition = $this->getDefinition($association); - $on = '{'.$definition['asso']['complete_field'].'} = {'.$definition['asso']['complete_foreign_field'].'}'; - $type = self::LEFT_JOIN; - $this->join_list[$association] = array( - 'table' => ($definition['is_lang']) ? $definition['table'].'_lang' : $definition['table'], - 'alias' => $this->generateAlias($association), - 'on' => array(), - ); - } - - if ($on) - $this->join_list[$association]['on'][] = $this->parseFields($on); - - if ($type) - $this->join_list[$association]['type'] = $type; - - return $this; - } - - /** - * Add WHERE restriction on query - * - * @param string $field Field name - * @param string $operator List of operators : =, !=, <>, <, <=, >, >=, like, notlike, regexp, notregexp - * @param mixed $value - * @param string $type where|having - * @return PrestaShopCollection - */ - public function where($field, $operator, $value, $method = 'where') - { - if ($method != 'where' && $method != 'having') - throw new PrestaShopException('Bad method argument for where() method (should be "where" or "having")'); - - // Create WHERE clause with an array value (IN, NOT IN) - if (is_array($value)) - { - switch (strtolower($operator)) - { - case '=' : - case 'in' : - $this->query->$method($this->parseField($field).' IN('.implode(', ', $this->formatValue($value, $field)).')'); - break; - - case '!=' : - case '<>' : - case 'notin' : - $this->query->$method($this->parseField($field).' NOT IN('.implode(', ', $this->formatValue($value, $field)).')'); - break; - - default : - throw new PrestaShopException('Operator not supported for array value'); - } - } - // Create WHERE clause - else - { - switch (strtolower($operator)) - { - case '=' : - case '!=' : - case '<>' : - case '>' : - case '>=' : - case '<' : - case '<=' : - case 'like' : - case 'regexp' : - $this->query->$method($this->parseField($field).' '.$operator.' '.$this->formatValue($value, $field)); - break; - - case 'notlike' : - $this->query->$method($this->parseField($field).' NOT LIKE '.$this->formatValue($value, $field)); - break; - - case 'notregexp' : - $this->query->$method($this->parseField($field).' NOT REGEXP '.$this->formatValue($value, $field)); - break; - - default : - throw new PrestaShopException('Operator not supported'); - } - } - - return $this; - } - - /** - * Add WHERE restriction on query using real SQL syntax - * - * @param string $sql - * @return PrestaShopCollection - */ - public function sqlWhere($sql) - { - $this->query->where($this->parseFields($sql)); - return $this; - } - - /** - * Add HAVING restriction on query - * - * @param string $field Field name - * @param string $operator List of operators : =, !=, <>, <, <=, >, >=, like, notlike, regexp, notregexp - * @param mixed $value - * @return PrestaShopCollection - */ - public function having($field, $operator, $value) - { - return $this->where($field, $operator, $value, 'having'); - } - - /** - * Add HAVING restriction on query using real SQL syntax - * - * @param string $sql - * @return PrestaShopCollection - */ - public function sqlHaving($sql) - { - $this->query->having($this->parseFields($sql)); - return $this; - } - - /** - * Add ORDER BY restriction on query - * - * @param string $field Field name - * @param string $order asc|desc - * @return PrestaShopCollection - */ - public function orderBy($field, $order = 'asc') - { - $order = strtolower($order); - if ($order != 'asc' && $order != 'desc') - throw new PrestaShopException('Order must be asc or desc'); - $this->query->orderBy($this->parseField($field).' '.$order); - return $this; - } - - /** - * Add ORDER BY restriction on query using real SQL syntax - * - * @param string $sql - * @return PrestaShopCollection - */ - public function sqlOrderBy($sql) - { - $this->query->orderBy($this->parseFields($sql)); - return $this; - } - - /** - * Add GROUP BY restriction on query - * - * @param string $field Field name - * @return PrestaShopCollection - */ - public function groupBy($field) - { - $this->query->groupBy($this->parseField($field)); - return $this; - } - - /** - * Add GROUP BY restriction on query using real SQL syntax - * - * @param string $sql - * @return PrestaShopCollection - */ - public function sqlGroupBy($sql) - { - $this->query->groupBy($this->parseFields($sql)); - return $this; - } - - /** - * Launch sql query to create collection of objects - * - * @param bool $display_query If true, query will be displayed (for debug purpose) - * @return PrestaShopCollection - */ - public function getAll($display_query = false) - { - if ($this->is_hydrated) - return $this; - $this->is_hydrated = true; - - $alias = $this->generateAlias(); - //$this->query->select($alias.'.*'); - $this->query->from($this->definition['table'], $alias); - - // If multilang, create association to lang table - if (!empty($this->definition['multilang'])) - { - $this->join(self::LANG_ALIAS); - if ($this->id_lang) - $this->where(self::LANG_ALIAS.'.id_lang', '=', $this->id_lang); - } - - // Add join clause - foreach ($this->join_list as $data) - { - $on = '('.implode(') AND (', $data['on']).')'; - switch ($data['type']) - { - case self::LEFT_JOIN : - $this->query->leftJoin($data['table'], $data['alias'], $on); - break; - - case self::INNER_JOIN : - $this->query->innerJoin($data['table'], $data['alias'], $on); - break; - - case self::LEFT_OUTER_JOIN : - $this->query->leftOuterJoin($data['table'], $data['alias'], $on); - break; - } - } - - // All limit clause - if ($this->page_size) - $this->query->limit($this->page_size, $this->page_number * $this->page_size); - - // Shall we display query for debug ? - if ($display_query) - echo $this->query.'<br />'; - - $this->results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($this->query); - $this->results = ObjectModel::hydrateCollection($this->classname, $this->results, $this->id_lang); - - return $this; - } - - /** - * Retrieve the first result - * - * @return ObjectModel - */ - public function getFirst() - { - $this->getAll(); - if (!count($this)) - return false; - return $this[0]; - } - - /** - * Get results array - * - * @return array - */ - public function getResults() - { - $this->getAll(); - return $this->results; - } - - /** - * This method is called when a foreach begin - * - * @see Iterator::rewind() - */ - public function rewind() - { - $this->getAll(); - $this->results = array_merge($this->results); - $this->iterator = 0; - $this->total = count($this->results); - } - - /** - * Get current result - * - * @see Iterator::current() - * @return ObjectModel - */ - public function current() - { - return isset($this->results[$this->iterator]) ? $this->results[$this->iterator] : null; - } - - /** - * Check if there is a current result - * - * @see Iterator::valid() - * @return bool - */ - public function valid() - { - return $this->iterator < $this->total; - } - - /** - * Get current result index - * - * @see Iterator::key() - * @return int - */ - public function key() - { - return $this->iterator; - } - - /** - * Go to next result - * - * @see Iterator::next() - */ - public function next() - { - $this->iterator++; - } - - /** - * Get total of results - * - * @see Countable::count() - * @return int - */ - public function count() - { - $this->getAll(); - return count($this->results); - } - - /** - * Check if a result exist - * - * @see ArrayAccess::offsetExists() - * @param $offset - * @return bool - */ - public function offsetExists($offset) - { - $this->getAll(); - return isset($this->results[$offset]); - } - - /** - * Get a result by offset - * - * @see ArrayAccess::offsetGet() - * @param $offset - * @return ObjectModel - */ - public function offsetGet($offset) - { - $this->getAll(); - if (!isset($this->results[$offset])) - throw new PrestaShopException('Unknown offset '.$offset.' for collection '.$this->classname); - return $this->results[$offset]; - } - - /** - * Add an element in the collection - * - * @see ArrayAccess::offsetSet() - * @param $offset - * @param $value - */ - public function offsetSet($offset, $value) - { - if (!$value instanceof $this->classname) - throw new PrestaShopException('You cannot add an element which is not an instance of '.$this->classname); - - $this->getAll(); - if (is_null($offset)) - $this->results[] = $value; - else - $this->results[$offset] = $value; - } - - /** - * Delete an element from the collection - * - * @see ArrayAccess::offsetUnset() - * @param $offset - */ - public function offsetUnset($offset) - { - $this->getAll(); - unset($this->results[$offset]); - } - - /** - * Get definition of an association - * - * @param string $association - * @return array - */ - protected function getDefinition($association) - { - if (!$association) - return $this->definition; - - if (!isset($this->association_definition[$association])) - { - $definition = $this->definition; - $split = explode('.', $association); - $is_lang = false; - for ($i = 0, $total_association = count($split); $i < $total_association; $i++) - { - $asso = $split[$i]; - - // Check is current association exists in current definition - if (!isset($definition['associations'][$asso])) - throw new PrestaShopException('Association '.$asso.' not found for class '.$this->definition['classname']); - $current_def = $definition['associations'][$asso]; - - // Special case for lang alias - if ($asso == self::LANG_ALIAS) - { - $is_lang = true; - break; - } - - $classname = (isset($current_def['object'])) ? $current_def['object'] : Tools::toCamelCase($asso, true); - $definition = ObjectModel::getDefinition($classname); - } - - // Get definition of associated entity and add information on current association - $current_def['name'] = $asso; - if (!isset($current_def['object'])) - $current_def['object'] = Tools::toCamelCase($asso, true); - if (!isset($current_def['field'])) - $current_def['field'] = 'id_'.$asso; - if (!isset($current_def['foreign_field'])) - $current_def['foreign_field'] = 'id_'.$asso; - if ($total_association > 1) - { - unset($split[$total_association - 1]); - $current_def['complete_field'] = implode('.', $split).'.'.$current_def['field']; - } - else - $current_def['complete_field'] = $current_def['field']; - $current_def['complete_foreign_field'] = $association.'.'.$current_def['field']; - - $definition['is_lang'] = $is_lang; - $definition['asso'] = $current_def; - $this->association_definition[$association] = $definition; - } - else - $definition = $this->association_definition[$association]; - - return $definition; - } - - /** - * Parse all fields with {field} syntax in a string - * - * @param string $str - * @return string - */ - protected function parseFields($str) - { - preg_match_all('#\{(([a-z0-9_]+\.)*[a-z0-9_]+)\}#i', $str, $m); - for ($i = 0, $total = count($m[0]); $i < $total; $i++) - $str = str_replace($m[0][$i], $this->parseField($m[1][$i]), $str); - return $str; - } - - /** - * Replace a field with its SQL version (E.g. manufacturer.name with a2.name) - * - * @param string $field Field name - * @return string - */ - protected function parseField($field) - { - $info = $this->getFieldInfo($field); - return $info['alias'].'.`'.$info['name'].'`'; - } - - /** - * Format a value with the type of the given field - * - * @param mixed $value - * @param string $field Field name - * @return mixed - */ - protected function formatValue($value, $field) - { - $info = $this->getFieldInfo($field); - if (is_array($value)) - { - $results = array(); - foreach ($value as $item) - $results[] = ObjectModel::formatValue($item, $info['type'], true); - return $results; - } - return ObjectModel::formatValue($value, $info['type'], true); - } - - /** - * Obtain some information on a field (alias, name, type, etc.) - * - * @param string $field Field name - * @return array - */ - protected function getFieldInfo($field) - { - if (!isset($this->fields[$field])) - { - $split = explode('.', $field); - $total = count($split); - if ($total > 1) - { - $fieldname = $split[$total - 1]; - unset($split[$total - 1]); - $association = implode('.', $split); - } - else - { - $fieldname = $field; - $association = ''; - } - - $definition = $this->getDefinition($association); - if ($association && !isset($this->join_list[$association])) - $this->join($association); - - if ($fieldname == $definition['primary'] || (!empty($definition['is_lang']) && $fieldname == 'id_lang')) - $type = ObjectModel::TYPE_INT; - else - { - // Test if field exists - if (!isset($definition['fields'][$fieldname])) - throw new PrestaShopException('Field '.$fieldname.' not found in class '.$definition['classname']); - - // Test field validity for language fields - if (empty($definition['is_lang']) && !empty($definition['fields'][$fieldname]['lang'])) - throw new PrestaShopException('Field '.$fieldname.' is declared as lang field but is used in non multilang context'); - elseif (!empty($definition['is_lang']) && empty($definition['fields'][$fieldname]['lang'])) - throw new PrestaShopException('Field '.$fieldname.' is not declared as lang field but is used in multilang context'); - - $type = $definition['fields'][$fieldname]['type']; - } - - $this->fields[$field] = array( - 'name' => $fieldname, - 'association' => $association, - 'alias' => $this->generateAlias($association), - 'type' => $type, - ); - } - return $this->fields[$field]; - } - - /** - * Set the page number - * - * @param int $page_number - * @return PrestaShopCollection - */ - public function setPageNumber($page_number) - { - $page_number = (int)$page_number; - if ($page_number > 0) - $page_number--; - - $this->page_number = $page_number; - return $this; - } - - /** - * Set the nuber of item per page - * - * @param int $page_size - * @return PrestaShopCollection - */ - public function setPageSize($page_size) - { - $this->page_size = (int)$page_size; - return $this; - } - - /** - * Generate uniq alias from association name - * - * @param string $association Use empty association for alias on current table - * @return string - */ - protected function generateAlias($association = '') - { - if (!isset($this->alias[$association])) - $this->alias[$association] = 'a'.$this->alias_iterator++; - return $this->alias[$association]; - } -} \ No newline at end of file + const LEFT_JOIN = 1; + const INNER_JOIN = 2; + const LEFT_OUTER_JOIN = 3; + + /** + * @var string Object class name + */ + protected $classname; + + /** + * @var int + */ + protected $id_lang; + + /** + * @var array Object definition + */ + protected $definition = array(); + + /** + * @var DbQuery + */ + protected $query; + + /** + * @var array Collection of objects in an array + */ + protected $results = array(); + + /** + * @var bool Is current collection already hydrated + */ + protected $is_hydrated = false; + + /** + * @var int Collection iterator + */ + protected $iterator = 0; + + /** + * @var int Total of elements for iteration + */ + protected $total; + + /** + * @var int Page number + */ + protected $page_number = 0; + + /** + * @var int Size of a page + */ + protected $page_size = 0; + + protected $fields = array(); + protected $alias = array(); + protected $alias_iterator = 0; + protected $join_list = array(); + protected $association_definition = array(); + + const LANG_ALIAS = 'l'; + + /** + * @param string $classname + * @param int $id_lang + */ + public function __construct($classname, $id_lang = null) + { + $this->classname = $classname; + $this->id_lang = $id_lang; + + $this->definition = ObjectModel::getDefinition($this->classname); + if (!isset($this->definition['table'])) { + throw new PrestaShopException('Miss table in definition for class '.$this->classname); + } elseif (!isset($this->definition['primary'])) { + throw new PrestaShopException('Miss primary in definition for class '.$this->classname); + } + + $this->query = new DbQuery(); + } + + /** + * Join current entity to an associated entity + * + * @param string $association Association name + * @param string $on + * @param int $type + * @return PrestaShopCollection + */ + public function join($association, $on = '', $type = null) + { + if (!$association) { + return; + } + + if (!isset($this->join_list[$association])) { + $definition = $this->getDefinition($association); + $on = '{'.$definition['asso']['complete_field'].'} = {'.$definition['asso']['complete_foreign_field'].'}'; + $type = self::LEFT_JOIN; + $this->join_list[$association] = array( + 'table' => ($definition['is_lang']) ? $definition['table'].'_lang' : $definition['table'], + 'alias' => $this->generateAlias($association), + 'on' => array(), + ); + } + + if ($on) { + $this->join_list[$association]['on'][] = $this->parseFields($on); + } + + if ($type) { + $this->join_list[$association]['type'] = $type; + } + + return $this; + } + + /** + * Add WHERE restriction on query + * + * @param string $field Field name + * @param string $operator List of operators : =, !=, <>, <, <=, >, >=, like, notlike, regexp, notregexp + * @param mixed $value + * @param string $type where|having + * @return PrestaShopCollection + */ + public function where($field, $operator, $value, $method = 'where') + { + if ($method != 'where' && $method != 'having') { + throw new PrestaShopException('Bad method argument for where() method (should be "where" or "having")'); + } + + // Create WHERE clause with an array value (IN, NOT IN) + if (is_array($value)) { + switch (strtolower($operator)) { + case '=' : + case 'in' : + $this->query->$method($this->parseField($field).' IN('.implode(', ', $this->formatValue($value, $field)).')'); + break; + + case '!=' : + case '<>' : + case 'notin' : + $this->query->$method($this->parseField($field).' NOT IN('.implode(', ', $this->formatValue($value, $field)).')'); + break; + + default : + throw new PrestaShopException('Operator not supported for array value'); + } + } + // Create WHERE clause + else { + switch (strtolower($operator)) { + case '=' : + case '!=' : + case '<>' : + case '>' : + case '>=' : + case '<' : + case '<=' : + case 'like' : + case 'regexp' : + $this->query->$method($this->parseField($field).' '.$operator.' '.$this->formatValue($value, $field)); + break; + + case 'notlike' : + $this->query->$method($this->parseField($field).' NOT LIKE '.$this->formatValue($value, $field)); + break; + + case 'notregexp' : + $this->query->$method($this->parseField($field).' NOT REGEXP '.$this->formatValue($value, $field)); + break; + + default : + throw new PrestaShopException('Operator not supported'); + } + } + + return $this; + } + + /** + * Add WHERE restriction on query using real SQL syntax + * + * @param string $sql + * @return PrestaShopCollection + */ + public function sqlWhere($sql) + { + $this->query->where($this->parseFields($sql)); + return $this; + } + + /** + * Add HAVING restriction on query + * + * @param string $field Field name + * @param string $operator List of operators : =, !=, <>, <, <=, >, >=, like, notlike, regexp, notregexp + * @param mixed $value + * @return PrestaShopCollection + */ + public function having($field, $operator, $value) + { + return $this->where($field, $operator, $value, 'having'); + } + + /** + * Add HAVING restriction on query using real SQL syntax + * + * @param string $sql + * @return PrestaShopCollection + */ + public function sqlHaving($sql) + { + $this->query->having($this->parseFields($sql)); + return $this; + } + + /** + * Add ORDER BY restriction on query + * + * @param string $field Field name + * @param string $order asc|desc + * @return PrestaShopCollection + */ + public function orderBy($field, $order = 'asc') + { + $order = strtolower($order); + if ($order != 'asc' && $order != 'desc') { + throw new PrestaShopException('Order must be asc or desc'); + } + $this->query->orderBy($this->parseField($field).' '.$order); + return $this; + } + + /** + * Add ORDER BY restriction on query using real SQL syntax + * + * @param string $sql + * @return PrestaShopCollection + */ + public function sqlOrderBy($sql) + { + $this->query->orderBy($this->parseFields($sql)); + return $this; + } + + /** + * Add GROUP BY restriction on query + * + * @param string $field Field name + * @return PrestaShopCollection + */ + public function groupBy($field) + { + $this->query->groupBy($this->parseField($field)); + return $this; + } + + /** + * Add GROUP BY restriction on query using real SQL syntax + * + * @param string $sql + * @return PrestaShopCollection + */ + public function sqlGroupBy($sql) + { + $this->query->groupBy($this->parseFields($sql)); + return $this; + } + + /** + * Launch sql query to create collection of objects + * + * @param bool $display_query If true, query will be displayed (for debug purpose) + * @return PrestaShopCollection + */ + public function getAll($display_query = false) + { + if ($this->is_hydrated) { + return $this; + } + $this->is_hydrated = true; + + $alias = $this->generateAlias(); + //$this->query->select($alias.'.*'); + $this->query->from($this->definition['table'], $alias); + + // If multilang, create association to lang table + if (!empty($this->definition['multilang'])) { + $this->join(self::LANG_ALIAS); + if ($this->id_lang) { + $this->where(self::LANG_ALIAS.'.id_lang', '=', $this->id_lang); + } + } + + // Add join clause + foreach ($this->join_list as $data) { + $on = '('.implode(') AND (', $data['on']).')'; + switch ($data['type']) { + case self::LEFT_JOIN : + $this->query->leftJoin($data['table'], $data['alias'], $on); + break; + + case self::INNER_JOIN : + $this->query->innerJoin($data['table'], $data['alias'], $on); + break; + + case self::LEFT_OUTER_JOIN : + $this->query->leftOuterJoin($data['table'], $data['alias'], $on); + break; + } + } + + // All limit clause + if ($this->page_size) { + $this->query->limit($this->page_size, $this->page_number * $this->page_size); + } + + // Shall we display query for debug ? + if ($display_query) { + echo $this->query.'<br />'; + } + + $this->results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($this->query); + if ($this->results && is_array($this->results)) + $this->results = ObjectModel::hydrateCollection($this->classname, $this->results, $this->id_lang); + + return $this; + } + + /** + * Retrieve the first result + * + * @return ObjectModel + */ + public function getFirst() + { + $this->getAll(); + if (!count($this)) { + return false; + } + return $this[0]; + } + + /** + * Get results array + * + * @return array + */ + public function getResults() + { + $this->getAll(); + return $this->results; + } + + /** + * This method is called when a foreach begin + * + * @see Iterator::rewind() + */ + public function rewind() + { + $this->getAll(); + $this->results = array_merge($this->results); + $this->iterator = 0; + $this->total = count($this->results); + } + + /** + * Get current result + * + * @see Iterator::current() + * @return ObjectModel + */ + public function current() + { + return isset($this->results[$this->iterator]) ? $this->results[$this->iterator] : null; + } + + /** + * Check if there is a current result + * + * @see Iterator::valid() + * @return bool + */ + public function valid() + { + return $this->iterator < $this->total; + } + + /** + * Get current result index + * + * @see Iterator::key() + * @return int + */ + public function key() + { + return $this->iterator; + } + + /** + * Go to next result + * + * @see Iterator::next() + */ + public function next() + { + $this->iterator++; + } + + /** + * Get total of results + * + * @see Countable::count() + * @return int + */ + public function count() + { + $this->getAll(); + return count($this->results); + } + + /** + * Check if a result exist + * + * @see ArrayAccess::offsetExists() + * @param $offset + * @return bool + */ + public function offsetExists($offset) + { + $this->getAll(); + return isset($this->results[$offset]); + } + + /** + * Get a result by offset + * + * @see ArrayAccess::offsetGet() + * @param $offset + * @return ObjectModel + */ + public function offsetGet($offset) + { + $this->getAll(); + if (!isset($this->results[$offset])) { + throw new PrestaShopException('Unknown offset '.$offset.' for collection '.$this->classname); + } + return $this->results[$offset]; + } + + /** + * Add an element in the collection + * + * @see ArrayAccess::offsetSet() + * @param $offset + * @param $value + */ + public function offsetSet($offset, $value) + { + if (!$value instanceof $this->classname) { + throw new PrestaShopException('You cannot add an element which is not an instance of '.$this->classname); + } + + $this->getAll(); + if (is_null($offset)) { + $this->results[] = $value; + } else { + $this->results[$offset] = $value; + } + } + + /** + * Delete an element from the collection + * + * @see ArrayAccess::offsetUnset() + * @param $offset + */ + public function offsetUnset($offset) + { + $this->getAll(); + unset($this->results[$offset]); + } + + /** + * Get definition of an association + * + * @param string $association + * @return array + */ + protected function getDefinition($association) + { + if (!$association) { + return $this->definition; + } + + if (!isset($this->association_definition[$association])) { + $definition = $this->definition; + $split = explode('.', $association); + $is_lang = false; + for ($i = 0, $total_association = count($split); $i < $total_association; $i++) { + $asso = $split[$i]; + + // Check is current association exists in current definition + if (!isset($definition['associations'][$asso])) { + throw new PrestaShopException('Association '.$asso.' not found for class '.$this->definition['classname']); + } + $current_def = $definition['associations'][$asso]; + + // Special case for lang alias + if ($asso == self::LANG_ALIAS) { + $is_lang = true; + break; + } + + $classname = (isset($current_def['object'])) ? $current_def['object'] : Tools::toCamelCase($asso, true); + $definition = ObjectModel::getDefinition($classname); + } + + // Get definition of associated entity and add information on current association + $current_def['name'] = $asso; + if (!isset($current_def['object'])) { + $current_def['object'] = Tools::toCamelCase($asso, true); + } + if (!isset($current_def['field'])) { + $current_def['field'] = 'id_'.$asso; + } + if (!isset($current_def['foreign_field'])) { + $current_def['foreign_field'] = 'id_'.$asso; + } + if ($total_association > 1) { + unset($split[$total_association - 1]); + $current_def['complete_field'] = implode('.', $split).'.'.$current_def['field']; + } else { + $current_def['complete_field'] = $current_def['field']; + } + $current_def['complete_foreign_field'] = $association.'.'.$current_def['field']; + + $definition['is_lang'] = $is_lang; + $definition['asso'] = $current_def; + $this->association_definition[$association] = $definition; + } else { + $definition = $this->association_definition[$association]; + } + + return $definition; + } + + /** + * Parse all fields with {field} syntax in a string + * + * @param string $str + * @return string + */ + protected function parseFields($str) + { + preg_match_all('#\{(([a-z0-9_]+\.)*[a-z0-9_]+)\}#i', $str, $m); + for ($i = 0, $total = count($m[0]); $i < $total; $i++) { + $str = str_replace($m[0][$i], $this->parseField($m[1][$i]), $str); + } + return $str; + } + + /** + * Replace a field with its SQL version (E.g. manufacturer.name with a2.name) + * + * @param string $field Field name + * @return string + */ + protected function parseField($field) + { + $info = $this->getFieldInfo($field); + return $info['alias'].'.`'.$info['name'].'`'; + } + + /** + * Format a value with the type of the given field + * + * @param mixed $value + * @param string $field Field name + * @return mixed + */ + protected function formatValue($value, $field) + { + $info = $this->getFieldInfo($field); + if (is_array($value)) { + $results = array(); + foreach ($value as $item) { + $results[] = ObjectModel::formatValue($item, $info['type'], true); + } + return $results; + } + return ObjectModel::formatValue($value, $info['type'], true); + } + + /** + * Obtain some information on a field (alias, name, type, etc.) + * + * @param string $field Field name + * @return array + */ + protected function getFieldInfo($field) + { + if (!isset($this->fields[$field])) { + $split = explode('.', $field); + $total = count($split); + if ($total > 1) { + $fieldname = $split[$total - 1]; + unset($split[$total - 1]); + $association = implode('.', $split); + } else { + $fieldname = $field; + $association = ''; + } + + $definition = $this->getDefinition($association); + if ($association && !isset($this->join_list[$association])) { + $this->join($association); + } + + if ($fieldname == $definition['primary'] || (!empty($definition['is_lang']) && $fieldname == 'id_lang')) { + $type = ObjectModel::TYPE_INT; + } else { + // Test if field exists + if (!isset($definition['fields'][$fieldname])) { + throw new PrestaShopException('Field '.$fieldname.' not found in class '.$definition['classname']); + } + + // Test field validity for language fields + if (empty($definition['is_lang']) && !empty($definition['fields'][$fieldname]['lang'])) { + throw new PrestaShopException('Field '.$fieldname.' is declared as lang field but is used in non multilang context'); + } elseif (!empty($definition['is_lang']) && empty($definition['fields'][$fieldname]['lang'])) { + throw new PrestaShopException('Field '.$fieldname.' is not declared as lang field but is used in multilang context'); + } + + $type = $definition['fields'][$fieldname]['type']; + } + + $this->fields[$field] = array( + 'name' => $fieldname, + 'association' => $association, + 'alias' => $this->generateAlias($association), + 'type' => $type, + ); + } + return $this->fields[$field]; + } + + /** + * Set the page number + * + * @param int $page_number + * @return PrestaShopCollection + */ + public function setPageNumber($page_number) + { + $page_number = (int)$page_number; + if ($page_number > 0) { + $page_number--; + } + + $this->page_number = $page_number; + return $this; + } + + /** + * Set the nuber of item per page + * + * @param int $page_size + * @return PrestaShopCollection + */ + public function setPageSize($page_size) + { + $this->page_size = (int)$page_size; + return $this; + } + + /** + * Generate uniq alias from association name + * + * @param string $association Use empty association for alias on current table + * @return string + */ + protected function generateAlias($association = '') + { + if (!isset($this->alias[$association])) { + $this->alias[$association] = 'a'.$this->alias_iterator++; + } + return $this->alias[$association]; + } +} diff --git a/classes/PrestaShopLogger.php b/classes/PrestaShopLogger.php index 65b8a67d..0e4d06d2 100644 --- a/classes/PrestaShopLogger.php +++ b/classes/PrestaShopLogger.php @@ -24,147 +24,149 @@ * International Registered Trademark & Property of PrestaShop SA */ -class PrestaShopLoggerCore extends ObjectModel +class PrestaShopLoggerCore extends ObjectModel { - /** @var int Log id */ - public $id_log; + /** @var int Log id */ + public $id_log; - /** @var int Log severity */ - public $severity; + /** @var int Log severity */ + public $severity; - /** @var int Error code */ - public $error_code; + /** @var int Error code */ + public $error_code; - /** @var string Message */ - public $message; + /** @var string Message */ + public $message; - /** @var string Object type (eg. Order, Customer...) */ - public $object_type; + /** @var string Object type (eg. Order, Customer...) */ + public $object_type; - /** @var int Object ID */ - public $object_id; + /** @var int Object ID */ + public $object_id; - /** @var int Object ID */ - public $id_employee; + /** @var int Object ID */ + public $id_employee; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** @var string Object last modification date */ - public $date_upd; + /** @var string Object last modification date */ + public $date_upd; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'log', - 'primary' => 'id_log', - 'fields' => array( - 'severity' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), - 'error_code' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'message' => array('type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true), - 'object_id' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'object_type' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'log', + 'primary' => 'id_log', + 'fields' => array( + 'severity' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), + 'error_code' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'message' => array('type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true), + 'object_id' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'object_type' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - protected static $is_present = array(); + protected static $is_present = array(); - /** - * Send e-mail to the shop owner only if the minimal severity level has been reached - * - * @param Logger - * @param PrestaShopLogger $log - */ - public static function sendByMail($log) - { - if ((int)Configuration::get('PS_LOGS_BY_EMAIL') <= (int)$log->severity) - Mail::Send( - (int)Configuration::get('PS_LANG_DEFAULT'), - 'log_alert', - Mail::l('Log: You have a new alert from your shop', (int)Configuration::get('PS_LANG_DEFAULT')), - array(), - Configuration::get('PS_SHOP_EMAIL') - ); - } + /** + * Send e-mail to the shop owner only if the minimal severity level has been reached + * + * @param Logger + * @param PrestaShopLogger $log + */ + public static function sendByMail($log) + { + if ((int)Configuration::get('PS_LOGS_BY_EMAIL') <= (int)$log->severity) { + Mail::Send( + (int)Configuration::get('PS_LANG_DEFAULT'), + 'log_alert', + Mail::l('Log: You have a new alert from your shop', (int)Configuration::get('PS_LANG_DEFAULT')), + array(), + Configuration::get('PS_SHOP_EMAIL') + ); + } + } - /** - * add a log item to the database and send a mail if configured for this $severity - * - * @param string $message the log message - * @param int $severity - * @param int $error_code - * @param string $object_type - * @param int $object_id - * @param bool $allow_duplicate if set to true, can log several time the same information (not recommended) - * @return bool true if succeed - */ - public static function addLog($message, $severity = 1, $error_code = null, $object_type = null, $object_id = null, $allow_duplicate = false, $id_employee = null) - { - $log = new PrestaShopLogger(); - $log->severity = (int)$severity; - $log->error_code = (int)$error_code; - $log->message = pSQL($message); - $log->date_add = date('Y-m-d H:i:s'); - $log->date_upd = date('Y-m-d H:i:s'); + /** + * add a log item to the database and send a mail if configured for this $severity + * + * @param string $message the log message + * @param int $severity + * @param int $error_code + * @param string $object_type + * @param int $object_id + * @param bool $allow_duplicate if set to true, can log several time the same information (not recommended) + * @return bool true if succeed + */ + public static function addLog($message, $severity = 1, $error_code = null, $object_type = null, $object_id = null, $allow_duplicate = false, $id_employee = null) + { + $log = new PrestaShopLogger(); + $log->severity = (int)$severity; + $log->error_code = (int)$error_code; + $log->message = pSQL($message); + $log->date_add = date('Y-m-d H:i:s'); + $log->date_upd = date('Y-m-d H:i:s'); - if ($id_employee === null && isset(Context::getContext()->employee) && Validate::isLoadedObject(Context::getContext()->employee)) - $id_employee = Context::getContext()->employee->id; + if ($id_employee === null && isset(Context::getContext()->employee) && Validate::isLoadedObject(Context::getContext()->employee)) { + $id_employee = Context::getContext()->employee->id; + } - if ($id_employee !== null) - $log->id_employee = (int)$id_employee; + if ($id_employee !== null) { + $log->id_employee = (int)$id_employee; + } - if (!empty($object_type) && !empty($object_id)) - { - $log->object_type = pSQL($object_type); - $log->object_id = (int)$object_id; - } + if (!empty($object_type) && !empty($object_id)) { + $log->object_type = pSQL($object_type); + $log->object_id = (int)$object_id; + } - if ($object_type != 'Swift_Message') - PrestaShopLogger::sendByMail($log); + if ($object_type != 'Swift_Message') { + PrestaShopLogger::sendByMail($log); + } - if ($allow_duplicate || !$log->_isPresent()) - { - $res = $log->add(); - if ($res) - { - self::$is_present[$log->getHash()] = isset(self::$is_present[$log->getHash()])?self::$is_present[$log->getHash()] + 1:1; - return true; - } - } - return false; - } + if ($allow_duplicate || !$log->_isPresent()) { + $res = $log->add(); + if ($res) { + self::$is_present[$log->getHash()] = isset(self::$is_present[$log->getHash()])?self::$is_present[$log->getHash()] + 1:1; + return true; + } + } + return false; + } - /** - * this function md5($this->message.$this->severity.$this->error_code.$this->object_type.$this->object_id) - * - * @return string hash - */ - public function getHash() - { - if (empty($this->hash)) - $this->hash = md5($this->message.$this->severity.$this->error_code.$this->object_type.$this->object_id); + /** + * this function md5($this->message.$this->severity.$this->error_code.$this->object_type.$this->object_id) + * + * @return string hash + */ + public function getHash() + { + if (empty($this->hash)) { + $this->hash = md5($this->message.$this->severity.$this->error_code.$this->object_type.$this->object_id); + } - return $this->hash; - } + return $this->hash; + } - public static function eraseAllLogs() - { - return Db::getInstance()->execute('TRUNCATE TABLE '._DB_PREFIX_.'log'); - } + public static function eraseAllLogs() + { + return Db::getInstance()->execute('TRUNCATE TABLE '._DB_PREFIX_.'log'); + } - /** - * check if this log message already exists in database. - * - * @return true if exists - */ - protected function _isPresent() - { - if (!isset(self::$is_present[md5($this->message)])) - self::$is_present[$this->getHash()] = Db::getInstance()->getValue('SELECT COUNT(*) + /** + * check if this log message already exists in database. + * + * @return true if exists + */ + protected function _isPresent() + { + if (!isset(self::$is_present[md5($this->message)])) { + self::$is_present[$this->getHash()] = Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'log` WHERE `message` = \''.$this->message.'\' @@ -173,7 +175,8 @@ class PrestaShopLoggerCore extends ObjectModel AND `object_type` = \''.$this->object_type.'\' AND `object_id` = \''.$this->object_id.'\' '); + } - return self::$is_present[$this->getHash()]; - } -} \ No newline at end of file + return self::$is_present[$this->getHash()]; + } +} diff --git a/classes/Product.php b/classes/Product.php index 1f5fb2eb..e9b1d540 100644 --- a/classes/Product.php +++ b/classes/Product.php @@ -35,1151 +35,1204 @@ define('_CUSTOMIZE_TEXTFIELD_', 1); class ProductCore extends ObjectModel { - /** @var string Tax name */ - public $tax_name; + /** @var string Tax name */ + public $tax_name; - /** @var string Tax rate */ - public $tax_rate; + /** @var string Tax rate */ + public $tax_rate; - /** @var int Manufacturer id */ - public $id_manufacturer; + /** @var int Manufacturer id */ + public $id_manufacturer; - /** @var int Supplier id */ - public $id_supplier; + /** @var int Supplier id */ + public $id_supplier; - /** @var int default Category id */ - public $id_category_default; + /** @var int default Category id */ + public $id_category_default; - /** @var int default Shop id */ - public $id_shop_default; + /** @var int default Shop id */ + public $id_shop_default; - /** @var string Manufacturer name */ - public $manufacturer_name; + /** @var string Manufacturer name */ + public $manufacturer_name; - /** @var string Supplier name */ - public $supplier_name; + /** @var string Supplier name */ + public $supplier_name; - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var string Long description */ - public $description; + /** @var string Long description */ + public $description; - /** @var string Short description */ - public $description_short; + /** @var string Short description */ + public $description_short; - /** @var int Quantity available */ - public $quantity = 0; + /** @var int Quantity available */ + public $quantity = 0; - /** @var int Minimal quantity for add to cart */ - public $minimal_quantity = 1; + /** @var int Minimal quantity for add to cart */ + public $minimal_quantity = 1; - /** @var string available_now */ - public $available_now; + /** @var string available_now */ + public $available_now; - /** @var string available_later */ - public $available_later; + /** @var string available_later */ + public $available_later; - /** @var float Price in euros */ - public $price = 0; + /** @var float Price in euros */ + public $price = 0; - public $specificPrice = 0; + public $specificPrice = 0; - /** @var float Additional shipping cost */ - public $additional_shipping_cost = 0; + /** @var float Additional shipping cost */ + public $additional_shipping_cost = 0; - /** @var float Wholesale Price in euros */ - public $wholesale_price = 0; + /** @var float Wholesale Price in euros */ + public $wholesale_price = 0; - /** @var bool on_sale */ - public $on_sale = false; + /** @var bool on_sale */ + public $on_sale = false; - /** @var bool online_only */ - public $online_only = false; + /** @var bool online_only */ + public $online_only = false; - /** @var string unity */ - public $unity = null; + /** @var string unity */ + public $unity = null; - /** @var float price for product's unity */ - public $unit_price; + /** @var float price for product's unity */ + public $unit_price; - /** @var float price for product's unity ratio */ - public $unit_price_ratio = 0; + /** @var float price for product's unity ratio */ + public $unit_price_ratio = 0; - /** @var float Ecotax */ - public $ecotax = 0; + /** @var float Ecotax */ + public $ecotax = 0; - /** @var string Reference */ - public $reference; + /** @var string Reference */ + public $reference; - /** @var string Supplier Reference */ - public $supplier_reference; + /** @var string Supplier Reference */ + public $supplier_reference; - /** @var string Location */ - public $location; + /** @var string Location */ + public $location; - /** @var string Width in default width unit */ - public $width = 0; + /** @var string Width in default width unit */ + public $width = 0; - /** @var string Height in default height unit */ - public $height = 0; + /** @var string Height in default height unit */ + public $height = 0; - /** @var string Depth in default depth unit */ - public $depth = 0; + /** @var string Depth in default depth unit */ + public $depth = 0; - /** @var string Weight in default weight unit */ - public $weight = 0; + /** @var string Weight in default weight unit */ + public $weight = 0; - /** @var string Ean-13 barcode */ - public $ean13; + /** @var string Ean-13 barcode */ + public $ean13; - /** @var string Upc barcode */ - public $upc; + /** @var string Upc barcode */ + public $upc; - /** @var string Friendly URL */ - public $link_rewrite; + /** @var string Friendly URL */ + public $link_rewrite; - /** @var string Meta tag description */ - public $meta_description; + /** @var string Meta tag description */ + public $meta_description; - /** @var string Meta tag keywords */ - public $meta_keywords; + /** @var string Meta tag keywords */ + public $meta_keywords; - /** @var string Meta tag title */ - public $meta_title; + /** @var string Meta tag title */ + public $meta_title; - /** @var bool Product statuts */ - public $quantity_discount = 0; + /** @var bool Product statuts */ + public $quantity_discount = 0; - /** @var bool Product customization */ - public $customizable; + /** @var bool Product customization */ + public $customizable; - /** @var bool Product is new */ - public $new = null; + /** @var bool Product is new */ + public $new = null; - /** @var int Number of uploadable files (concerning customizable products) */ - public $uploadable_files; + /** @var int Number of uploadable files (concerning customizable products) */ + public $uploadable_files; - /** @var int Number of text fields */ - public $text_fields; + /** @var int Number of text fields */ + public $text_fields; - /** @var bool Product statuts */ - public $active = true; + /** @var bool Product statuts */ + public $active = true; - /** @var bool Product statuts */ - public $redirect_type = ''; + /** @var bool Product statuts */ + public $redirect_type = ''; - /** @var bool Product statuts */ - public $id_product_redirected = 0; + /** @var bool Product statuts */ + public $id_product_redirected = 0; - /** @var bool Product available for order */ - public $available_for_order = true; + /** @var bool Product available for order */ + public $available_for_order = true; - /** @var string Object available order date */ - public $available_date = '0000-00-00'; + /** @var string Object available order date */ + public $available_date = '0000-00-00'; - /** @var string Enumerated (enum) product condition (new, used, refurbished) */ - public $condition; + /** @var string Enumerated (enum) product condition (new, used, refurbished) */ + public $condition; - /** @var bool Show price of Product */ - public $show_price = true; + /** @var bool Show price of Product */ + public $show_price = true; - /** @var bool is the product indexed in the search index? */ - public $indexed = 0; + /** @var bool is the product indexed in the search index? */ + public $indexed = 0; - /** @var string ENUM('both', 'catalog', 'search', 'none') front office visibility */ - public $visibility; + /** @var string ENUM('both', 'catalog', 'search', 'none') front office visibility */ + public $visibility; - /** @var string Object creation date */ - public $date_add; - - /** @var string Object last modification date */ - public $date_upd; - - /*** @var array Tags */ - public $tags; - - /** - * @var float Base price of the product - * @deprecated 1.6.0.13 - */ - public $base_price; - - public $id_tax_rules_group = 1; - - /** - * We keep this variable for retrocompatibility for themes - * @deprecated 1.5.0 - */ - public $id_color_default = 0; - - /** - * @since 1.5.0 - * @var bool Tells if the product uses the advanced stock management - */ - public $advanced_stock_management = 0; - public $out_of_stock; - public $depends_on_stock; - - public $isFullyLoaded = false; - - public $cache_is_pack; - public $cache_has_attachments; - public $is_virtual; - public $id_pack_product_attribute; - public $cache_default_attribute; - - /** - * @var string If product is populated, this property contain the rewrite link of the default category - */ - public $category; - - /** - * @var int tell the type of stock management to apply on the pack - */ - public $pack_stock_type = 3; - - public static $_taxCalculationMethod = null; - protected static $_prices = array(); - protected static $_pricesLevel2 = array(); - protected static $_incat = array(); - - /** - * @since 1.5.6.1 - * @var array $_cart_quantity is deprecated since 1.5.6.1 - */ - protected static $_cart_quantity = array(); - - protected static $_tax_rules_group = array(); - protected static $_cacheFeatures = array(); - protected static $_frontFeaturesCache = array(); - protected static $producPropertiesCache = array(); - - /** @var array cache stock data in getStock() method */ - protected static $cacheStock = array(); - - public static $definition = array( - 'table' => 'product', - 'primary' => 'id_product', - 'multilang' => true, - 'multilang_shop' => true, - 'fields' => array( - /* Classic fields */ - 'id_shop_default' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_manufacturer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_supplier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference', 'size' => 32), - 'supplier_reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference', 'size' => 32), - 'location' => array('type' => self::TYPE_STRING, 'validate' => 'isReference', 'size' => 64), - 'width' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat'), - 'height' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat'), - 'depth' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat'), - 'weight' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat'), - 'quantity_discount' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'ean13' => array('type' => self::TYPE_STRING, 'validate' => 'isEan13', 'size' => 13), - 'upc' => array('type' => self::TYPE_STRING, 'validate' => 'isUpc', 'size' => 12), - 'cache_is_pack' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'cache_has_attachments' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'is_virtual' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - - /* Shop fields */ - 'id_category_default' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedId'), - 'id_tax_rules_group' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedId'), - 'on_sale' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), - 'online_only' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), - 'ecotax' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice'), - 'minimal_quantity' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'), - 'price' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice', 'required' => true), - 'wholesale_price' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice'), - 'unity' => array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isString'), - 'unit_price_ratio' => array('type' => self::TYPE_FLOAT, 'shop' => true), - 'additional_shipping_cost' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice'), - 'customizable' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'), - 'text_fields' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'), - 'uploadable_files' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'), - 'active' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), - 'redirect_type' => array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isString'), - 'id_product_redirected' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedId'), - 'available_for_order' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), - 'available_date' => array('type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDateFormat'), - 'condition' => array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isGenericName', 'values' => array('new', 'used', 'refurbished'), 'default' => 'new'), - 'show_price' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), - 'indexed' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), - 'visibility' => array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isProductVisibility', 'values' => array('both', 'catalog', 'search', 'none'), 'default' => 'both'), - 'cache_default_attribute' => array('type' => self::TYPE_INT, 'shop' => true), - 'advanced_stock_management' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), - 'date_add' => array('type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDate'), - 'pack_stock_type' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'), - - /* Lang fields */ - 'meta_description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - 'meta_keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), - 'link_rewrite' => array( - 'type' => self::TYPE_STRING, - 'lang' => true, - 'validate' => 'isLinkRewrite', - 'required' => true, - 'size' => 128, - 'ws_modifier' => array( - 'http_method' => WebserviceRequest::HTTP_POST, - 'modifier' => 'modifierWsLinkRewrite' - ) - ), - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCatalogName', 'required' => true, 'size' => 128), - 'description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), - 'description_short' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), - 'available_now' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - 'available_later' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'IsGenericName', 'size' => 255), - ), - 'associations' => array( - 'manufacturer' => array('type' => self::HAS_ONE), - 'supplier' => array('type' => self::HAS_ONE), - 'default_category' => array('type' => self::HAS_ONE, 'field' => 'id_category_default', 'object' => 'Category'), - 'tax_rules_group' => array('type' => self::HAS_ONE), - 'categories' => array('type' => self::HAS_MANY, 'field' => 'id_category', 'object' => 'Category', 'association' => 'category_product'), - 'stock_availables' => array('type' => self::HAS_MANY, 'field' => 'id_stock_available', 'object' => 'StockAvailable', 'association' => 'stock_availables'), - ), - ); - - protected $webserviceParameters = array( - 'objectMethods' => array( - 'add' => 'addWs', - 'update' => 'updateWs' - ), - 'objectNodeNames' => 'products', - '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' => 'products' - ) - ), - 'id_default_combination' => array( - 'getter' => 'getWsDefaultCombination', - 'setter' => 'setWsDefaultCombination', - 'xlink_resource' => array( - 'resourceName' => 'combinations' - ) - ), - '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()) - ), - 'combinations' => array( - 'resource' => 'combination', - 'fields' => array( - 'id' => array('required' => true), - ) - ), - 'product_option_values' => array( - 'resource' => 'product_option_value', - 'fields' => array( - 'id' => array('required' => true), - ) - ), - 'product_features' => array( - 'resource' => 'product_feature', - 'fields' => array( - 'id' => array('required' => true), - 'id_feature_value' => array( - 'required' => true, - 'xlink_resource' => 'product_feature_values' - ), - ) - ), - 'tags' => array('resource' => 'tag', - 'fields' => array( - 'id' => array('required' => true), - )), - 'stock_availables' => array('resource' => 'stock_available', - 'fields' => array( - 'id' => array('required' => true), - 'id_product_attribute' => array('required' => true), - ), - 'setter' => false - ), - 'accessories' => array( - 'resource' => 'product', - 'api' => 'products', - 'fields' => array( - 'id' => array( - 'required' => true, - 'xlink_resource' => 'product'), - ) - ), - 'product_bundle' => array( - 'resource' => 'product', - 'api' => 'products', - 'fields' => array( - 'id' => array('required' => true), - 'quantity' => array(), - ), - ), - ), - ); - - const CUSTOMIZE_FILE = 0; - const CUSTOMIZE_TEXTFIELD = 1; - - /** - * Note: prefix is "PTYPE" because TYPE_ is used in ObjectModel (definition) - */ - const PTYPE_SIMPLE = 0; - const PTYPE_PACK = 1; - const PTYPE_VIRTUAL = 2; - - public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, Context $context = null) - { - parent::__construct($id_product, $id_lang, $id_shop); - if ($full && $this->id) - { - if (!$context) - $context = Context::getContext(); - - $this->isFullyLoaded = $full; - $this->tax_name = 'deprecated'; // The applicable tax may be BOTH the product one AND the state one (moreover this variable is some deadcode) - $this->manufacturer_name = Manufacturer::getNameById((int)$this->id_manufacturer); - $this->supplier_name = Supplier::getNameById((int)$this->id_supplier); - $address = null; - if (is_object($context->cart) && $context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')} != null) - $address = $context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; - - $this->tax_rate = $this->getTaxesRate(new Address($address)); - - $this->new = $this->isNew(); - - // Keep base price - $this->base_price = $this->price; - - $this->price = Product::getPriceStatic((int)$this->id, false, null, 6, null, false, true, 1, false, null, null, null, $this->specificPrice); - $this->unit_price = ($this->unit_price_ratio != 0 ? $this->price / $this->unit_price_ratio : 0); - if ($this->id) - $this->tags = Tag::getProductTags((int)$this->id); - - $this->loadStockData(); - } - - if ($this->id_category_default) - $this->category = Category::getLinkRewrite((int)$this->id_category_default, (int)$id_lang); - } - - /** - * @see ObjectModel::getFieldsShop() - * @return array - */ - public function getFieldsShop() - { - $fields = parent::getFieldsShop(); - if (is_null($this->update_fields) || (!empty($this->update_fields['price']) && !empty($this->update_fields['unit_price']))) - $fields['unit_price_ratio'] = (float)$this->unit_price > 0 ? $this->price / $this->unit_price : 0; - $fields['unity'] = pSQL($this->unity); - - return $fields; - } - - public function add($autodate = true, $null_values = false) - { - if (!parent::add($autodate, $null_values)) - return false; - - $id_shop_list = Shop::getContextListShopID(); - if ($this->getType() == Product::PTYPE_VIRTUAL) - { - foreach ($id_shop_list as $value) - StockAvailable::setProductOutOfStock((int)$this->id, 1, $value); - - if ($this->active && !Configuration::get('PS_VIRTUAL_PROD_FEATURE_ACTIVE')) - Configuration::updateGlobalValue('PS_VIRTUAL_PROD_FEATURE_ACTIVE', '1'); - } - else - foreach ($id_shop_list as $value) - StockAvailable::setProductOutOfStock((int)$this->id, 2, $value); - - $this->setGroupReduction(); - Hook::exec('actionProductSave', array('id_product' => (int)$this->id, 'product' => $this)); - return true; - } - - public function update($null_values = false) - { - $return = parent::update($null_values); - $this->setGroupReduction(); - - // Sync stock Reference, EAN13 and UPC - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && StockAvailable::dependsOnStock($this->id, Context::getContext()->shop->id)) - Db::getInstance()->update('stock', array( - 'reference' => pSQL($this->reference), - 'ean13' => pSQL($this->ean13), - 'upc' => pSQL($this->upc), - ), 'id_product = '.(int)$this->id.' AND id_product_attribute = 0'); - - Hook::exec('actionProductSave', array('id_product' => (int)$this->id, 'product' => $this)); - Hook::exec('actionProductUpdate', array('id_product' => (int)$this->id, 'product' => $this)); - if ($this->getType() == Product::PTYPE_VIRTUAL && $this->active && !Configuration::get('PS_VIRTUAL_PROD_FEATURE_ACTIVE')) - Configuration::updateGlobalValue('PS_VIRTUAL_PROD_FEATURE_ACTIVE', '1'); - - return $return; - } - - public static function initPricesComputation($id_customer = null) - { - if ($id_customer) - { - $customer = new Customer((int)$id_customer); - if (!Validate::isLoadedObject($customer)) - die(Tools::displayError()); - self::$_taxCalculationMethod = Group::getPriceDisplayMethod((int)$customer->id_default_group); - $cur_cart = Context::getContext()->cart; - $id_address = 0; - if (Validate::isLoadedObject($cur_cart)) - $id_address = (int)$cur_cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; - $address_infos = Address::getCountryAndState($id_address); - - if (self::$_taxCalculationMethod != PS_TAX_EXC - && !empty($address_infos['vat_number']) - && $address_infos['id_country'] != Configuration::get('VATNUMBER_COUNTRY') - && Configuration::get('VATNUMBER_MANAGEMENT')) - self::$_taxCalculationMethod = PS_TAX_EXC; - } - else - self::$_taxCalculationMethod = Group::getPriceDisplayMethod(Group::getCurrent()->id); - } - - public static function getTaxCalculationMethod($id_customer = null) - { - if (self::$_taxCalculationMethod === null || $id_customer !== null) - Product::initPricesComputation($id_customer); - - return (int)self::$_taxCalculationMethod; - } - - /** - * Move a product inside its category - * @param bool $way Up (1) or Down (0) - * @param int $position - * return boolean Update result - */ - public function updatePosition($way, $position) - { - if (!$res = Db::getInstance()->executeS(' + /** @var string Object creation date */ + public $date_add; + + /** @var string Object last modification date */ + public $date_upd; + + /*** @var array Tags */ + public $tags; + + /** + * @var float Base price of the product + * @deprecated 1.6.0.13 + */ + public $base_price; + + public $id_tax_rules_group = 1; + + /** + * We keep this variable for retrocompatibility for themes + * @deprecated 1.5.0 + */ + public $id_color_default = 0; + + /** + * @since 1.5.0 + * @var bool Tells if the product uses the advanced stock management + */ + public $advanced_stock_management = 0; + public $out_of_stock; + public $depends_on_stock; + + public $isFullyLoaded = false; + + public $cache_is_pack; + public $cache_has_attachments; + public $is_virtual; + public $id_pack_product_attribute; + public $cache_default_attribute; + + /** + * @var string If product is populated, this property contain the rewrite link of the default category + */ + public $category; + + /** + * @var int tell the type of stock management to apply on the pack + */ + public $pack_stock_type = 3; + + public static $_taxCalculationMethod = null; + protected static $_prices = array(); + protected static $_pricesLevel2 = array(); + protected static $_incat = array(); + + /** + * @since 1.5.6.1 + * @var array $_cart_quantity is deprecated since 1.5.6.1 + */ + protected static $_cart_quantity = array(); + + protected static $_tax_rules_group = array(); + protected static $_cacheFeatures = array(); + protected static $_frontFeaturesCache = array(); + protected static $producPropertiesCache = array(); + + /** @var array cache stock data in getStock() method */ + protected static $cacheStock = array(); + + public static $definition = array( + 'table' => 'product', + 'primary' => 'id_product', + 'multilang' => true, + 'multilang_shop' => true, + 'fields' => array( + /* Classic fields */ + 'id_shop_default' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_manufacturer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_supplier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference', 'size' => 32), + 'supplier_reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference', 'size' => 32), + 'location' => array('type' => self::TYPE_STRING, 'validate' => 'isReference', 'size' => 64), + 'width' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat'), + 'height' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat'), + 'depth' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat'), + 'weight' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat'), + 'quantity_discount' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'ean13' => array('type' => self::TYPE_STRING, 'validate' => 'isEan13', 'size' => 13), + 'upc' => array('type' => self::TYPE_STRING, 'validate' => 'isUpc', 'size' => 12), + 'cache_is_pack' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'cache_has_attachments' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'is_virtual' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + + /* Shop fields */ + 'id_category_default' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedId'), + 'id_tax_rules_group' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedId'), + 'on_sale' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), + 'online_only' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), + 'ecotax' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice'), + 'minimal_quantity' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'), + 'price' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice', 'required' => true), + 'wholesale_price' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice'), + 'unity' => array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isString'), + 'unit_price_ratio' => array('type' => self::TYPE_FLOAT, 'shop' => true), + 'additional_shipping_cost' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice'), + 'customizable' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'), + 'text_fields' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'), + 'uploadable_files' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'), + 'active' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), + 'redirect_type' => array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isString'), + 'id_product_redirected' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedId'), + 'available_for_order' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), + 'available_date' => array('type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDateFormat'), + 'condition' => array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isGenericName', 'values' => array('new', 'used', 'refurbished'), 'default' => 'new'), + 'show_price' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), + 'indexed' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), + 'visibility' => array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isProductVisibility', 'values' => array('both', 'catalog', 'search', 'none'), 'default' => 'both'), + 'cache_default_attribute' => array('type' => self::TYPE_INT, 'shop' => true), + 'advanced_stock_management' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), + 'date_add' => array('type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDate'), + 'pack_stock_type' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'), + + /* Lang fields */ + 'meta_description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + 'meta_keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), + 'link_rewrite' => array( + 'type' => self::TYPE_STRING, + 'lang' => true, + 'validate' => 'isLinkRewrite', + 'required' => true, + 'size' => 128, + 'ws_modifier' => array( + 'http_method' => WebserviceRequest::HTTP_POST, + 'modifier' => 'modifierWsLinkRewrite' + ) + ), + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCatalogName', 'required' => true, 'size' => 128), + 'description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), + 'description_short' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), + 'available_now' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + 'available_later' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'IsGenericName', 'size' => 255), + ), + 'associations' => array( + 'manufacturer' => array('type' => self::HAS_ONE), + 'supplier' => array('type' => self::HAS_ONE), + 'default_category' => array('type' => self::HAS_ONE, 'field' => 'id_category_default', 'object' => 'Category'), + 'tax_rules_group' => array('type' => self::HAS_ONE), + 'categories' => array('type' => self::HAS_MANY, 'field' => 'id_category', 'object' => 'Category', 'association' => 'category_product'), + 'stock_availables' => array('type' => self::HAS_MANY, 'field' => 'id_stock_available', 'object' => 'StockAvailable', 'association' => 'stock_availables'), + ), + ); + + protected $webserviceParameters = array( + 'objectMethods' => array( + 'add' => 'addWs', + 'update' => 'updateWs' + ), + 'objectNodeNames' => 'products', + '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' => 'products' + ) + ), + 'id_default_combination' => array( + 'getter' => 'getWsDefaultCombination', + 'setter' => 'setWsDefaultCombination', + 'xlink_resource' => array( + 'resourceName' => 'combinations' + ) + ), + '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()) + ), + 'combinations' => array( + 'resource' => 'combination', + 'fields' => array( + 'id' => array('required' => true), + ) + ), + 'product_option_values' => array( + 'resource' => 'product_option_value', + 'fields' => array( + 'id' => array('required' => true), + ) + ), + 'product_features' => array( + 'resource' => 'product_feature', + 'fields' => array( + 'id' => array('required' => true), + 'id_feature_value' => array( + 'required' => true, + 'xlink_resource' => 'product_feature_values' + ), + ) + ), + 'tags' => array('resource' => 'tag', + 'fields' => array( + 'id' => array('required' => true), + )), + 'stock_availables' => array('resource' => 'stock_available', + 'fields' => array( + 'id' => array('required' => true), + 'id_product_attribute' => array('required' => true), + ), + 'setter' => false + ), + 'accessories' => array( + 'resource' => 'product', + 'api' => 'products', + 'fields' => array( + 'id' => array( + 'required' => true, + 'xlink_resource' => 'product'), + ) + ), + 'product_bundle' => array( + 'resource' => 'product', + 'api' => 'products', + 'fields' => array( + 'id' => array('required' => true), + 'quantity' => array(), + ), + ), + ), + ); + + const CUSTOMIZE_FILE = 0; + const CUSTOMIZE_TEXTFIELD = 1; + + /** + * Note: prefix is "PTYPE" because TYPE_ is used in ObjectModel (definition) + */ + const PTYPE_SIMPLE = 0; + const PTYPE_PACK = 1; + const PTYPE_VIRTUAL = 2; + + public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, Context $context = null) + { + parent::__construct($id_product, $id_lang, $id_shop); + if ($full && $this->id) { + if (!$context) { + $context = Context::getContext(); + } + + $this->isFullyLoaded = $full; + $this->tax_name = 'deprecated'; // The applicable tax may be BOTH the product one AND the state one (moreover this variable is some deadcode) + $this->manufacturer_name = Manufacturer::getNameById((int)$this->id_manufacturer); + $this->supplier_name = Supplier::getNameById((int)$this->id_supplier); + $address = null; + if (is_object($context->cart) && $context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')} != null) { + $address = $context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; + } + + $this->tax_rate = $this->getTaxesRate(new Address($address)); + + $this->new = $this->isNew(); + + // Keep base price + $this->base_price = $this->price; + + $this->price = Product::getPriceStatic((int)$this->id, false, null, 6, null, false, true, 1, false, null, null, null, $this->specificPrice); + $this->unit_price = ($this->unit_price_ratio != 0 ? $this->price / $this->unit_price_ratio : 0); + if ($this->id) { + $this->tags = Tag::getProductTags((int)$this->id); + } + + $this->loadStockData(); + } + + if ($this->id_category_default) { + $this->category = Category::getLinkRewrite((int)$this->id_category_default, (int)$id_lang); + } + } + + /** + * @see ObjectModel::getFieldsShop() + * @return array + */ + public function getFieldsShop() + { + $fields = parent::getFieldsShop(); + if (is_null($this->update_fields) || (!empty($this->update_fields['price']) && !empty($this->update_fields['unit_price']))) { + $fields['unit_price_ratio'] = (float)$this->unit_price > 0 ? $this->price / $this->unit_price : 0; + } + $fields['unity'] = pSQL($this->unity); + + return $fields; + } + + public function add($autodate = true, $null_values = false) + { + if (!parent::add($autodate, $null_values)) { + return false; + } + + $id_shop_list = Shop::getContextListShopID(); + if ($this->getType() == Product::PTYPE_VIRTUAL) { + foreach ($id_shop_list as $value) { + StockAvailable::setProductOutOfStock((int)$this->id, 1, $value); + } + + if ($this->active && !Configuration::get('PS_VIRTUAL_PROD_FEATURE_ACTIVE')) { + Configuration::updateGlobalValue('PS_VIRTUAL_PROD_FEATURE_ACTIVE', '1'); + } + } else { + foreach ($id_shop_list as $value) { + StockAvailable::setProductOutOfStock((int)$this->id, 2, $value); + } + } + + $this->setGroupReduction(); + Hook::exec('actionProductSave', array('id_product' => (int)$this->id, 'product' => $this)); + return true; + } + + public function update($null_values = false) + { + $return = parent::update($null_values); + $this->setGroupReduction(); + + // Sync stock Reference, EAN13 and UPC + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && StockAvailable::dependsOnStock($this->id, Context::getContext()->shop->id)) { + Db::getInstance()->update('stock', array( + 'reference' => pSQL($this->reference), + 'ean13' => pSQL($this->ean13), + 'upc' => pSQL($this->upc), + ), 'id_product = '.(int)$this->id.' AND id_product_attribute = 0'); + } + + Hook::exec('actionProductSave', array('id_product' => (int)$this->id, 'product' => $this)); + Hook::exec('actionProductUpdate', array('id_product' => (int)$this->id, 'product' => $this)); + if ($this->getType() == Product::PTYPE_VIRTUAL && $this->active && !Configuration::get('PS_VIRTUAL_PROD_FEATURE_ACTIVE')) { + Configuration::updateGlobalValue('PS_VIRTUAL_PROD_FEATURE_ACTIVE', '1'); + } + + return $return; + } + + public static function initPricesComputation($id_customer = null) + { + if ($id_customer) { + $customer = new Customer((int)$id_customer); + if (!Validate::isLoadedObject($customer)) { + die(Tools::displayError()); + } + self::$_taxCalculationMethod = Group::getPriceDisplayMethod((int)$customer->id_default_group); + $cur_cart = Context::getContext()->cart; + $id_address = 0; + if (Validate::isLoadedObject($cur_cart)) { + $id_address = (int)$cur_cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; + } + $address_infos = Address::getCountryAndState($id_address); + + if (self::$_taxCalculationMethod != PS_TAX_EXC + && !empty($address_infos['vat_number']) + && $address_infos['id_country'] != Configuration::get('VATNUMBER_COUNTRY') + && Configuration::get('VATNUMBER_MANAGEMENT')) { + self::$_taxCalculationMethod = PS_TAX_EXC; + } + } else { + self::$_taxCalculationMethod = Group::getPriceDisplayMethod(Group::getCurrent()->id); + } + } + + public static function getTaxCalculationMethod($id_customer = null) + { + if (self::$_taxCalculationMethod === null || $id_customer !== null) { + Product::initPricesComputation($id_customer); + } + + return (int)self::$_taxCalculationMethod; + } + + /** + * Move a product inside its category + * @param bool $way Up (1) or Down (0) + * @param int $position + * return boolean Update result + */ + public function updatePosition($way, $position) + { + if (!$res = Db::getInstance()->executeS(' SELECT cp.`id_product`, cp.`position`, cp.`id_category` FROM `'._DB_PREFIX_.'category_product` cp WHERE cp.`id_category` = '.(int)Tools::getValue('id_category', 1).' ORDER BY cp.`position` ASC' - )) - return false; + )) { + return false; + } - foreach ($res as $product) - if ((int)$product['id_product'] == (int)$this->id) - $moved_product = $product; + foreach ($res as $product) { + if ((int)$product['id_product'] == (int)$this->id) { + $moved_product = $product; + } + } - if (!isset($moved_product) || !isset($position)) - return false; + if (!isset($moved_product) || !isset($position)) { + return false; + } - // < and > statements rather than BETWEEN operator - // since BETWEEN is treated differently according to databases - return (Db::getInstance()->execute(' + // < and > statements rather than BETWEEN operator + // since BETWEEN is treated differently according to databases + return (Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'category_product` SET `position`= `position` '.($way ? '- 1' : '+ 1').' WHERE `position` '.($way - ? '> '.(int)$moved_product['position'].' AND `position` <= '.(int)$position - : '< '.(int)$moved_product['position'].' AND `position` >= '.(int)$position).' + ? '> '.(int)$moved_product['position'].' AND `position` <= '.(int)$position + : '< '.(int)$moved_product['position'].' AND `position` >= '.(int)$position).' AND `id_category`='.(int)$moved_product['id_category']) - && Db::getInstance()->execute(' + && Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'category_product` SET `position` = '.(int)$position.' WHERE `id_product` = '.(int)$moved_product['id_product'].' AND `id_category`='.(int)$moved_product['id_category'])); - } + } - /* - * Reorder product position in category $id_category. - * Call it after deleting a product from a category. - * - * @param int $id_category - */ - public static function cleanPositions($id_category, $position = 0) - { - $return = true; + /* + * Reorder product position in category $id_category. + * Call it after deleting a product from a category. + * + * @param int $id_category + */ + public static function cleanPositions($id_category, $position = 0) + { + $return = true; - if (!(int)$position) - { - - $result = Db::getInstance()->executeS(' + if (!(int)$position) { + $result = Db::getInstance()->executeS(' SELECT `id_product` FROM `'._DB_PREFIX_.'category_product` WHERE `id_category` = '.(int)$id_category.' ORDER BY `position` '); - $total = count($result); + $total = count($result); - for ($i = 0; $i < $total; $i++) - $return &= Db::getInstance()->update('category_product', array( - 'position' => $i, - ), '`id_category` = '.(int)$id_category.' AND `id_product` = '.(int)$result[$i]['id_product']); - } - else - $return &= Db::getInstance()->update('category_product', - array('position' => array('type' => 'sql', 'value' => '`position`-1')), - '`id_category` = '.(int)$id_category.' AND `position` > '.(int)$position); + for ($i = 0; $i < $total; $i++) { + $return &= Db::getInstance()->update('category_product', array( + 'position' => $i, + ), '`id_category` = '.(int)$id_category.' AND `id_product` = '.(int)$result[$i]['id_product']); + } + } else { + $return &= Db::getInstance()->update('category_product', + array('position' => array('type' => 'sql', 'value' => '`position`-1')), + '`id_category` = '.(int)$id_category.' AND `position` > '.(int)$position); + } - return $return; - } + return $return; + } - /** - * Get the default attribute for a product - * - * @return int Attributes list - */ - public static function getDefaultAttribute($id_product, $minimum_quantity = 0, $reset = false) - { - static $combinations = array(); + /** + * Get the default attribute for a product + * + * @return int Attributes list + */ + public static function getDefaultAttribute($id_product, $minimum_quantity = 0, $reset = false) + { + static $combinations = array(); - if (!Combination::isFeatureActive()) - return 0; + if (!Combination::isFeatureActive()) { + return 0; + } - if ($reset && isset($combinations[$id_product])) - unset($combinations[$id_product]); + if ($reset && isset($combinations[$id_product])) { + unset($combinations[$id_product]); + } - if (!isset($combinations[$id_product])) - $combinations[$id_product] = array(); - if (isset($combinations[$id_product][$minimum_quantity])) - return $combinations[$id_product][$minimum_quantity]; + if (!isset($combinations[$id_product])) { + $combinations[$id_product] = array(); + } + if (isset($combinations[$id_product][$minimum_quantity])) { + return $combinations[$id_product][$minimum_quantity]; + } - $sql = 'SELECT product_attribute_shop.id_product_attribute + $sql = 'SELECT product_attribute_shop.id_product_attribute FROM '._DB_PREFIX_.'product_attribute pa '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE pa.id_product = '.(int)$id_product; - $result_no_filter = Db::getInstance()->getValue($sql); - if (!$result_no_filter) - { - $combinations[$id_product][$minimum_quantity] = 0; - return 0; - } + $result_no_filter = Db::getInstance()->getValue($sql); + if (!$result_no_filter) { + $combinations[$id_product][$minimum_quantity] = 0; + return 0; + } - $sql = 'SELECT product_attribute_shop.id_product_attribute + $sql = 'SELECT product_attribute_shop.id_product_attribute FROM '._DB_PREFIX_.'product_attribute pa '.Shop::addSqlAssociation('product_attribute', 'pa').' '.($minimum_quantity > 0 ? Product::sqlStock('pa', 'pa') : ''). - ' WHERE product_attribute_shop.default_on = 1 ' - .($minimum_quantity > 0 ? ' AND IFNULL(stock.quantity, 0) >= '.(int)$minimum_quantity : ''). - ' AND pa.id_product = '.(int)$id_product; - $result = Db::getInstance()->getValue($sql); + ' WHERE product_attribute_shop.default_on = 1 ' + .($minimum_quantity > 0 ? ' AND IFNULL(stock.quantity, 0) >= '.(int)$minimum_quantity : ''). + ' AND pa.id_product = '.(int)$id_product; + $result = Db::getInstance()->getValue($sql); - if (!$result) - { - $sql = 'SELECT product_attribute_shop.id_product_attribute + if (!$result) { + $sql = 'SELECT product_attribute_shop.id_product_attribute FROM '._DB_PREFIX_.'product_attribute pa '.Shop::addSqlAssociation('product_attribute', 'pa').' '.($minimum_quantity > 0 ? Product::sqlStock('pa', 'pa') : ''). - ' WHERE pa.id_product = '.(int)$id_product - .($minimum_quantity > 0 ? ' AND IFNULL(stock.quantity, 0) >= '.(int)$minimum_quantity : ''); + ' WHERE pa.id_product = '.(int)$id_product + .($minimum_quantity > 0 ? ' AND IFNULL(stock.quantity, 0) >= '.(int)$minimum_quantity : ''); - $result = Db::getInstance()->getValue($sql); - } + $result = Db::getInstance()->getValue($sql); + } - if (!$result) - { - $sql = 'SELECT product_attribute_shop.id_product_attribute + if (!$result) { + $sql = 'SELECT product_attribute_shop.id_product_attribute FROM '._DB_PREFIX_.'product_attribute pa '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE product_attribute_shop.`default_on` = 1 AND pa.id_product = '.(int)$id_product; - $result = Db::getInstance()->getValue($sql); - } + $result = Db::getInstance()->getValue($sql); + } - if (!$result) - $result = $result_no_filter; + if (!$result) { + $result = $result_no_filter; + } - $combinations[$id_product][$minimum_quantity] = $result; - return $result; - } + $combinations[$id_product][$minimum_quantity] = $result; + return $result; + } - public function setAvailableDate($available_date = '0000-00-00') - { - if (Validate::isDateFormat($available_date) && $this->available_date != $available_date) - { - $this->available_date = $available_date; - return $this->update(); - } - return false; - } + public function setAvailableDate($available_date = '0000-00-00') + { + if (Validate::isDateFormat($available_date) && $this->available_date != $available_date) { + $this->available_date = $available_date; + return $this->update(); + } + return false; + } - /** - * For a given id_product and id_product_attribute, return available date - * - * @param int $id_product - * @param int $id_product_attribute Optional - * @return string/null - */ - public static function getAvailableDate($id_product, $id_product_attribute = null) - { - $sql = 'SELECT'; + /** + * For a given id_product and id_product_attribute, return available date + * + * @param int $id_product + * @param int $id_product_attribute Optional + * @return string/null + */ + public static function getAvailableDate($id_product, $id_product_attribute = null) + { + $sql = 'SELECT'; - if ($id_product_attribute === null) - $sql .= ' p.`available_date`'; - else - $sql .= ' IF(pa.`available_date` = "0000-00-00", p.`available_date`, pa.`available_date`) AS available_date'; + if ($id_product_attribute === null) { + $sql .= ' p.`available_date`'; + } else { + $sql .= ' IF(pa.`available_date` = "0000-00-00", p.`available_date`, pa.`available_date`) AS available_date'; + } - $sql .= ' FROM `'._DB_PREFIX_.'product` p'; + $sql .= ' FROM `'._DB_PREFIX_.'product` p'; - if ($id_product_attribute !== null) - $sql .= ' LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (pa.`id_product` = p.`id_product`)'; + if ($id_product_attribute !== null) { + $sql .= ' LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (pa.`id_product` = p.`id_product`)'; + } - $sql .= Shop::addSqlAssociation('product', 'p'); + $sql .= Shop::addSqlAssociation('product', 'p'); - if ($id_product_attribute !== null) - $sql .= Shop::addSqlAssociation('product_attribute', 'pa'); + if ($id_product_attribute !== null) { + $sql .= Shop::addSqlAssociation('product_attribute', 'pa'); + } - $sql .= ' WHERE p.`id_product` = '.(int)$id_product; + $sql .= ' WHERE p.`id_product` = '.(int)$id_product; - if ($id_product_attribute !== null) - $sql .= ' AND pa.`id_product` = '.(int)$id_product.' AND pa.`id_product_attribute` = '.(int)$id_product_attribute; + if ($id_product_attribute !== null) { + $sql .= ' AND pa.`id_product` = '.(int)$id_product.' AND pa.`id_product_attribute` = '.(int)$id_product_attribute; + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); - if ($result == '0000-00-00') - $result = null; + if ($result == '0000-00-00') { + $result = null; + } - return $result; - } + return $result; + } - public static function updateIsVirtual($id_product, $is_virtual = true) - { - Db::getInstance()->update('product', array( - 'is_virtual' => (bool)$is_virtual, - ), 'id_product = '.(int)$id_product); - } + public static function updateIsVirtual($id_product, $is_virtual = true) + { + Db::getInstance()->update('product', array( + 'is_virtual' => (bool)$is_virtual, + ), 'id_product = '.(int)$id_product); + } - /** - * @see ObjectModel::validateField() - */ - public function validateField($field, $value, $id_lang = null, $skip = array(), $human_errors = false) - { - if ($field == 'description_short') - { - $limit = (int)Configuration::get('PS_PRODUCT_SHORT_DESC_LIMIT'); - if ($limit <= 0) - $limit = 800; + /** + * @see ObjectModel::validateField() + */ + public function validateField($field, $value, $id_lang = null, $skip = array(), $human_errors = false) + { + if ($field == 'description_short') { + $limit = (int)Configuration::get('PS_PRODUCT_SHORT_DESC_LIMIT'); + if ($limit <= 0) { + $limit = 800; + } - $size_without_html = Tools::strlen(strip_tags($value)); - $size_with_html = Tools::strlen($value); - $this->def['fields']['description_short']['size'] = $limit + $size_with_html - $size_without_html; - } - return parent::validateField($field, $value, $id_lang, $skip, $human_errors); - } + $size_without_html = Tools::strlen(strip_tags($value)); + $size_with_html = Tools::strlen($value); + $this->def['fields']['description_short']['size'] = $limit + $size_with_html - $size_without_html; + } + return parent::validateField($field, $value, $id_lang, $skip, $human_errors); + } - public function toggleStatus() - { - //test if the product is active and if redirect_type is empty string and set default value to id_product_redirected & redirect_type - // /!\ after parent::toggleStatus() active will be false, that why we set 404 by default :p - if ($this->active) - { - //case where active will be false after parent::toggleStatus() - $this->id_product_redirected = 0; - $this->redirect_type = '404'; - } - else - { - //case where active will be true after parent::toggleStatus() - $this->id_product_redirected = 0; - $this->redirect_type = ''; - } - return parent::toggleStatus(); - } + public function toggleStatus() + { + //test if the product is active and if redirect_type is empty string and set default value to id_product_redirected & redirect_type + // /!\ after parent::toggleStatus() active will be false, that why we set 404 by default :p + if ($this->active) { + //case where active will be false after parent::toggleStatus() + $this->id_product_redirected = 0; + $this->redirect_type = '404'; + } else { + //case where active will be true after parent::toggleStatus() + $this->id_product_redirected = 0; + $this->redirect_type = ''; + } + return parent::toggleStatus(); + } - public function delete() - { - /* - * @since 1.5.0 - * It is NOT possible to delete a product if there are currently: - * - physical stock for this product - * - supply order(s) for this product - */ - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $this->advanced_stock_management) - { - $stock_manager = StockManagerFactory::getManager(); - $physical_quantity = $stock_manager->getProductPhysicalQuantities($this->id, 0); - $real_quantity = $stock_manager->getProductRealQuantities($this->id, 0); - if ($physical_quantity > 0) - return false; - if ($real_quantity > $physical_quantity) - return false; - } - $result = parent::delete(); + public function delete() + { + /* + * @since 1.5.0 + * It is NOT possible to delete a product if there are currently: + * - physical stock for this product + * - supply order(s) for this product + */ + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $this->advanced_stock_management) { + $stock_manager = StockManagerFactory::getManager(); + $physical_quantity = $stock_manager->getProductPhysicalQuantities($this->id, 0); + $real_quantity = $stock_manager->getProductRealQuantities($this->id, 0); + if ($physical_quantity > 0) { + return false; + } + if ($real_quantity > $physical_quantity) { + return false; + } - // Removes the product from StockAvailable, for the current shop - StockAvailable::removeProductFromStockAvailable($this->id); - $result &= ($this->deleteProductAttributes() && $this->deleteImages() && $this->deleteSceneProducts()); - // If there are still entries in product_shop, don't remove completly the product - if ($this->hasMultishopEntries()) - return true; + $warehouse_product_locations = Adapter_ServiceLocator::get('Core_Foundation_Database_EntityManager')->getRepository('WarehouseProductLocation')->findByIdProduct($this->id); + foreach ($warehouse_product_locations as $warehouse_product_location) { + $warehouse_product_location->delete(); + } - Hook::exec('actionProductDelete', array('id_product' => (int)$this->id, 'product' => $this)); - if (!$result || - !GroupReduction::deleteProductReduction($this->id) || - !$this->deleteCategories(true) || - !$this->deleteProductFeatures() || - !$this->deleteTags() || - !$this->deleteCartProducts() || - !$this->deleteAttributesImpacts() || - !$this->deleteAttachments(false) || - !$this->deleteCustomization() || - !SpecificPrice::deleteByProductId((int)$this->id) || - !$this->deletePack() || - !$this->deleteProductSale() || - !$this->deleteSearchIndexes() || - !$this->deleteAccessories() || - !$this->deleteFromAccessories() || - !$this->deleteFromSupplier() || - !$this->deleteDownload() || - !$this->deleteFromCartRules()) - return false; + $stocks = Adapter_ServiceLocator::get('Core_Foundation_Database_EntityManager')->getRepository('Stock')->findByIdProduct($this->id); + foreach ($stocks as $stock) { + $stock->delete(); + } + } + $result = parent::delete(); - return true; - } + // Removes the product from StockAvailable, for the current shop + StockAvailable::removeProductFromStockAvailable($this->id); + $result &= ($this->deleteProductAttributes() && $this->deleteImages() && $this->deleteSceneProducts()); + // If there are still entries in product_shop, don't remove completely the product + if ($this->hasMultishopEntries()) { + return true; + } - public function deleteSelection($products) - { - $return = 1; - if (is_array($products) && ($count = count($products))) - { - // Deleting products can be quite long on a cheap server. Let's say 1.5 seconds by product (I've seen it!). - if (intval(ini_get('max_execution_time')) < round($count * 1.5)) - ini_set('max_execution_time', round($count * 1.5)); + Hook::exec('actionProductDelete', array('id_product' => (int)$this->id, 'product' => $this)); + if (!$result || + !GroupReduction::deleteProductReduction($this->id) || + !$this->deleteCategories(true) || + !$this->deleteProductFeatures() || + !$this->deleteTags() || + !$this->deleteCartProducts() || + !$this->deleteAttributesImpacts() || + !$this->deleteAttachments(false) || + !$this->deleteCustomization() || + !SpecificPrice::deleteByProductId((int)$this->id) || + !$this->deletePack() || + !$this->deleteProductSale() || + !$this->deleteSearchIndexes() || + !$this->deleteAccessories() || + !$this->deleteFromAccessories() || + !$this->deleteFromSupplier() || + !$this->deleteDownload() || + !$this->deleteFromCartRules()) { + return false; + } - foreach ($products as $id_product) - { - $product = new Product((int)$id_product); - $return &= $product->delete(); - } - } - return $return; - } + return true; + } - public function deleteFromCartRules() - { - CartRule::cleanProductRuleIntegrity('products', $this->id); - return true; - } + public function deleteSelection($products) + { + $return = 1; + if (is_array($products) && ($count = count($products))) { + // Deleting products can be quite long on a cheap server. Let's say 1.5 seconds by product (I've seen it!). + if (intval(ini_get('max_execution_time')) < round($count * 1.5)) { + ini_set('max_execution_time', round($count * 1.5)); + } - public function deleteFromSupplier() - { - return Db::getInstance()->delete('product_supplier', 'id_product = '.(int)$this->id); - } + foreach ($products as $id_product) { + $product = new Product((int)$id_product); + $return &= $product->delete(); + } + } + return $return; + } - /** - * addToCategories add this product to the category/ies if not exists. - * - * @param mixed $categories id_category or array of id_category - * @return bool true if succeed - */ - public function addToCategories($categories = array()) - { - if (empty($categories)) - return false; + public function deleteFromCartRules() + { + CartRule::cleanProductRuleIntegrity('products', $this->id); + return true; + } - if (!is_array($categories)) - $categories = array($categories); + public function deleteFromSupplier() + { + return Db::getInstance()->delete('product_supplier', 'id_product = '.(int)$this->id); + } - if (!count($categories)) - return false; + /** + * addToCategories add this product to the category/ies if not exists. + * + * @param mixed $categories id_category or array of id_category + * @return bool true if succeed + */ + public function addToCategories($categories = array()) + { + if (empty($categories)) { + return false; + } - $categories = array_map('intval', $categories); + if (!is_array($categories)) { + $categories = array($categories); + } - $current_categories = $this->getCategories(); - $current_categories = array_map('intval', $current_categories); + if (!count($categories)) { + return false; + } - // for new categ, put product at last position - $res_categ_new_pos = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $categories = array_map('intval', $categories); + + $current_categories = $this->getCategories(); + $current_categories = array_map('intval', $current_categories); + + // for new categ, put product at last position + $res_categ_new_pos = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT id_category, MAX(position)+1 newPos FROM `'._DB_PREFIX_.'category_product` WHERE `id_category` IN('.implode(',', $categories).') GROUP BY id_category'); - foreach ($res_categ_new_pos as $array) - $new_categories[(int)$array['id_category']] = (int)$array['newPos']; + foreach ($res_categ_new_pos as $array) { + $new_categories[(int)$array['id_category']] = (int)$array['newPos']; + } - $new_categ_pos = array(); - foreach ($categories as $id_category) - $new_categ_pos[$id_category] = isset($new_categories[$id_category]) ? $new_categories[$id_category] : 0; + $new_categ_pos = array(); + foreach ($categories as $id_category) { + $new_categ_pos[$id_category] = isset($new_categories[$id_category]) ? $new_categories[$id_category] : 0; + } - $product_cats = array(); + $product_cats = array(); - foreach ($categories as $new_id_categ) - if (!in_array($new_id_categ, $current_categories)) - $product_cats[] = array( - 'id_category' => (int)$new_id_categ, - 'id_product' => (int)$this->id, - 'position' => (int)$new_categ_pos[$new_id_categ], - ); + foreach ($categories as $new_id_categ) { + if (!in_array($new_id_categ, $current_categories)) { + $product_cats[] = array( + 'id_category' => (int)$new_id_categ, + 'id_product' => (int)$this->id, + 'position' => (int)$new_categ_pos[$new_id_categ], + ); + } + } - Db::getInstance()->insert('category_product', $product_cats); - return true; - } + Db::getInstance()->insert('category_product', $product_cats); + return true; + } - /** - * Update categories to index product into - * - * @param string $productCategories Categories list to index product into - * @param bool $keeping_current_pos (deprecated, no more used) - * @return array Update/insertion result - */ - public function updateCategories($categories, $keeping_current_pos = false) - { - if (empty($categories)) - return false; + /** + * Update categories to index product into + * + * @param string $productCategories Categories list to index product into + * @param bool $keeping_current_pos (deprecated, no more used) + * @return array Update/insertion result + */ + public function updateCategories($categories, $keeping_current_pos = false) + { + if (empty($categories)) { + return false; + } - $result = Db::getInstance()->executeS(' + $result = Db::getInstance()->executeS(' SELECT c.`id_category` FROM `'._DB_PREFIX_.'category_product` cp LEFT JOIN `'._DB_PREFIX_.'category` c ON (c.`id_category` = cp.`id_category`) '.Shop::addSqlAssociation('category', 'c', true, null, true).' WHERE cp.`id_category` NOT IN ('.implode(',', array_map('intval', $categories)).') AND cp.id_product = '.$this->id - ); + ); - // if none are found, it's an error - if (!is_array($result)) - return false; + // if none are found, it's an error + if (!is_array($result)) { + return false; + } - foreach ($result as $categ_to_delete) - $this->deleteCategory($categ_to_delete['id_category']); + foreach ($result as $categ_to_delete) { + $this->deleteCategory($categ_to_delete['id_category']); + } - if (!$this->addToCategories($categories)) - return false; + if (!$this->addToCategories($categories)) { + return false; + } - SpecificPriceRule::applyAllRules(array((int)$this->id)); - return true; - } + SpecificPriceRule::applyAllRules(array((int)$this->id)); + return true; + } - /** - * deleteCategory delete this product from the category $id_category - * - * @param mixed $id_category - * @param mixed $clean_positions - * @return bool - */ - public function deleteCategory($id_category, $clean_positions = true) - { - $result = Db::getInstance()->executeS( - 'SELECT `id_category`, `position` + /** + * deleteCategory delete this product from the category $id_category + * + * @param mixed $id_category + * @param mixed $clean_positions + * @return bool + */ + public function deleteCategory($id_category, $clean_positions = true) + { + $result = Db::getInstance()->executeS( + 'SELECT `id_category`, `position` FROM `'._DB_PREFIX_.'category_product` WHERE `id_product` = '.(int)$this->id.' AND id_category = '.(int)$id_category.'' - ); + ); - $return = Db::getInstance()->delete('category_product', 'id_product = '.(int)$this->id.' AND id_category = '.(int)$id_category); - if ($clean_positions === true) - foreach ($result as $row) - $this->cleanPositions((int)$row['id_category'], (int)$row['position']); - SpecificPriceRule::applyAllRules(array((int)$this->id)); - return $return; - } + $return = Db::getInstance()->delete('category_product', 'id_product = '.(int)$this->id.' AND id_category = '.(int)$id_category); + if ($clean_positions === true) { + foreach ($result as $row) { + $this->cleanPositions((int)$row['id_category'], (int)$row['position']); + } + } + SpecificPriceRule::applyAllRules(array((int)$this->id)); + return $return; + } - /** - * Delete all association to category where product is indexed - * - * @param bool $clean_positions clean category positions after deletion - * @return array Deletion result - */ - public function deleteCategories($clean_positions = false) - { - if ($clean_positions === true) - $result = Db::getInstance()->executeS( - 'SELECT `id_category`, `position` + /** + * Delete all association to category where product is indexed + * + * @param bool $clean_positions clean category positions after deletion + * @return array Deletion result + */ + public function deleteCategories($clean_positions = false) + { + if ($clean_positions === true) { + $result = Db::getInstance()->executeS( + 'SELECT `id_category`, `position` FROM `'._DB_PREFIX_.'category_product` WHERE `id_product` = '.(int)$this->id - ); + ); + } - $return = Db::getInstance()->delete('category_product', 'id_product = '.(int)$this->id); - if ($clean_positions === true && is_array($result)) - foreach ($result as $row) - $return &= $this->cleanPositions((int)$row['id_category'], (int)$row['position']); + $return = Db::getInstance()->delete('category_product', 'id_product = '.(int)$this->id); + if ($clean_positions === true && is_array($result)) { + foreach ($result as $row) { + $return &= $this->cleanPositions((int)$row['id_category'], (int)$row['position']); + } + } - return $return; - } + return $return; + } - /** - * Delete products tags entries - * - * @return array Deletion result - */ - public function deleteTags() - { - return Db::getInstance()->delete('product_tag', 'id_product = '.(int)$this->id) - && Db::getInstance()->delete('tag', 'NOT EXISTS (SELECT 1 FROM '._DB_PREFIX_.'product_tag + /** + * Delete products tags entries + * + * @return array Deletion result + */ + public function deleteTags() + { + return Db::getInstance()->delete('product_tag', 'id_product = '.(int)$this->id) + && Db::getInstance()->delete('tag', 'NOT EXISTS (SELECT 1 FROM '._DB_PREFIX_.'product_tag WHERE '._DB_PREFIX_.'product_tag.id_tag = '._DB_PREFIX_.'tag.id_tag)'); - } + } - /** - * Delete product from cart - * - * @return array Deletion result - */ - public function deleteCartProducts() - { - return Db::getInstance()->delete('cart_product', 'id_product = '.(int)$this->id); - } + /** + * Delete product from cart + * + * @return array Deletion result + */ + public function deleteCartProducts() + { + return Db::getInstance()->delete('cart_product', 'id_product = '.(int)$this->id); + } - /** - * Delete product images from database - * - * @return bool success - */ - public function deleteImages() - { - $result = Db::getInstance()->executeS(' + /** + * Delete product images from database + * + * @return bool success + */ + public function deleteImages() + { + $result = Db::getInstance()->executeS(' SELECT `id_image` FROM `'._DB_PREFIX_.'image` WHERE `id_product` = '.(int)$this->id - ); + ); - $status = true; - if ($result) - foreach ($result as $row) - { - $image = new Image($row['id_image']); - $status &= $image->delete(); - } - return $status; - } + $status = true; + if ($result) { + foreach ($result as $row) { + $image = new Image($row['id_image']); + $status &= $image->delete(); + } + } + return $status; + } - /** - * @deprecated 1.5.0 Use Combination::getPrice() - */ - public static function getProductAttributePrice($id_product_attribute) - { - return Combination::getPrice($id_product_attribute); - } + /** + * @deprecated 1.5.0 Use Combination::getPrice() + */ + public static function getProductAttributePrice($id_product_attribute) + { + return Combination::getPrice($id_product_attribute); + } - /** - * Get all available products - * - * @param int $id_lang Language id - * @param int $start Start number - * @param int $limit Number of products to return - * @param string $order_by Field for ordering - * @param string $order_way Way for ordering (ASC or DESC) - * @return array Products details - */ - public static function getProducts($id_lang, $start, $limit, $order_by, $order_way, $id_category = false, - $only_active = false, Context $context = null) - { - if (!$context) - $context = Context::getContext(); + /** + * Get all available products + * + * @param int $id_lang Language id + * @param int $start Start number + * @param int $limit Number of products to return + * @param string $order_by Field for ordering + * @param string $order_way Way for ordering (ASC or DESC) + * @return array Products details + */ + public static function getProducts($id_lang, $start, $limit, $order_by, $order_way, $id_category = false, + $only_active = false, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } - $front = true; - if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) - $front = false; + $front = true; + if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) { + $front = false; + } - if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) - die (Tools::displayError()); - if ($order_by == 'id_product' || $order_by == 'price' || $order_by == 'date_add' || $order_by == 'date_upd') - $order_by_prefix = 'p'; - elseif ($order_by == 'name') - $order_by_prefix = 'pl'; - elseif ($order_by == 'position') - $order_by_prefix = 'c'; + if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) { + die(Tools::displayError()); + } + if ($order_by == 'id_product' || $order_by == 'price' || $order_by == 'date_add' || $order_by == 'date_upd') { + $order_by_prefix = 'p'; + } elseif ($order_by == 'name') { + $order_by_prefix = 'pl'; + } elseif ($order_by == 'position') { + $order_by_prefix = 'c'; + } - if (strpos($order_by, '.') > 0) - { - $order_by = explode('.', $order_by); - $order_by_prefix = $order_by[0]; - $order_by = $order_by[1]; - } - $sql = 'SELECT p.*, product_shop.*, pl.* , m.`name` AS manufacturer_name, s.`name` AS supplier_name + if (strpos($order_by, '.') > 0) { + $order_by = explode('.', $order_by); + $order_by_prefix = $order_by[0]; + $order_by = $order_by[1]; + } + $sql = 'SELECT p.*, product_shop.*, pl.* , m.`name` AS manufacturer_name, s.`name` AS supplier_name FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` '.Shop::addSqlRestrictionOnLang('pl').') LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`) LEFT JOIN `'._DB_PREFIX_.'supplier` s ON (s.`id_supplier` = p.`id_supplier`)'. - ($id_category ? 'LEFT JOIN `'._DB_PREFIX_.'category_product` c ON (c.`id_product` = p.`id_product`)' : '').' + ($id_category ? 'LEFT JOIN `'._DB_PREFIX_.'category_product` c ON (c.`id_product` = p.`id_product`)' : '').' WHERE pl.`id_lang` = '.(int)$id_lang. - ($id_category ? ' AND c.`id_category` = '.(int)$id_category : ''). - ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : ''). - ($only_active ? ' AND product_shop.`active` = 1' : '').' + ($id_category ? ' AND c.`id_category` = '.(int)$id_category : ''). + ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : ''). + ($only_active ? ' AND product_shop.`active` = 1' : '').' ORDER BY '.(isset($order_by_prefix) ? pSQL($order_by_prefix).'.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way). - ($limit > 0 ? ' LIMIT '.(int)$start.','.(int)$limit : ''); - $rq = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - if ($order_by == 'price') - Tools::orderbyPrice($rq, $order_way); + ($limit > 0 ? ' LIMIT '.(int)$start.','.(int)$limit : ''); + $rq = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + if ($order_by == 'price') { + Tools::orderbyPrice($rq, $order_way); + } - foreach ($rq as &$row) - $row = Product::getTaxesInformations($row); + foreach ($rq as &$row) { + $row = Product::getTaxesInformations($row); + } - return ($rq); - } + return ($rq); + } - public static function getSimpleProducts($id_lang, Context $context = null) - { - if (!$context) - $context = Context::getContext(); + public static function getSimpleProducts($id_lang, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } - $front = true; - if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) - $front = false; + $front = true; + if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) { + $front = false; + } - $sql = 'SELECT p.`id_product`, pl.`name` + $sql = 'SELECT p.`id_product`, pl.`name` FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` '.Shop::addSqlRestrictionOnLang('pl').') WHERE pl.`id_lang` = '.(int)$id_lang.' '.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').' ORDER BY pl.`name`'; - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + } - public function isNew() - { - $result = Db::getInstance()->executeS(' + public function isNew() + { + $result = Db::getInstance()->executeS(' SELECT p.id_product FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' @@ -1192,448 +1245,463 @@ class ProductCore extends ObjectModel ) ) > 0 ', true, false); - return count($result) > 0; - } + return count($result) > 0; + } - public function productAttributeExists($attributes_list, $current_product_attribute = false, Context $context = null, $all_shops = false, $return_id = false) - { - if (!Combination::isFeatureActive()) - return false; - if ($context === null) - $context = Context::getContext(); - $result = Db::getInstance()->executeS( - 'SELECT pac.`id_attribute`, pac.`id_product_attribute` + public function productAttributeExists($attributes_list, $current_product_attribute = false, Context $context = null, $all_shops = false, $return_id = false) + { + if (!Combination::isFeatureActive()) { + return false; + } + if ($context === null) { + $context = Context::getContext(); + } + $result = Db::getInstance()->executeS( + 'SELECT pac.`id_attribute`, pac.`id_product_attribute` FROM `'._DB_PREFIX_.'product_attribute` pa JOIN `'._DB_PREFIX_.'product_attribute_shop` pas ON (pas.id_product_attribute = pa.id_product_attribute) LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON (pac.`id_product_attribute` = pa.`id_product_attribute`) WHERE 1 '.(!$all_shops ? ' AND pas.id_shop ='.(int)$context->shop->id : '').' AND pa.`id_product` = '.(int)$this->id. - ($all_shops ? ' GROUP BY pac.id_attribute, pac.id_product_attribute ' : '') - ); + ($all_shops ? ' GROUP BY pac.id_attribute, pac.id_product_attribute ' : '') + ); - /* If something's wrong */ - if (!$result || empty($result)) - return false; - /* Product attributes simulation */ - $product_attributes = array(); - foreach ($result as $product_attribute) - $product_attributes[$product_attribute['id_product_attribute']][] = $product_attribute['id_attribute']; - /* Checking product's attribute existence */ - foreach ($product_attributes as $key => $product_attribute) - if (count($product_attribute) == count($attributes_list)) - { - $diff = false; - for ($i = 0; $diff == false && isset($product_attribute[$i]); $i++) - if (!in_array($product_attribute[$i], $attributes_list) || $key == $current_product_attribute) - $diff = true; - if (!$diff) - { - if ($return_id) - return $key; - return true; - } - } + /* If something's wrong */ + if (!$result || empty($result)) { + return false; + } + /* Product attributes simulation */ + $product_attributes = array(); + foreach ($result as $product_attribute) { + $product_attributes[$product_attribute['id_product_attribute']][] = $product_attribute['id_attribute']; + } + /* Checking product's attribute existence */ + foreach ($product_attributes as $key => $product_attribute) { + if (count($product_attribute) == count($attributes_list)) { + $diff = false; + for ($i = 0; $diff == false && isset($product_attribute[$i]); $i++) { + if (!in_array($product_attribute[$i], $attributes_list) || $key == $current_product_attribute) { + $diff = true; + } + } + if (!$diff) { + if ($return_id) { + return $key; + } + return true; + } + } + } - return false; - } + return false; + } - /** - * addProductAttribute is deprecated - * - * The quantity params now set StockAvailable for the current shop with the specified quantity - * The supplier_reference params now set the supplier reference of the default supplier of the product if possible - * - * @see StockManager if you want to manage real stock - * @see StockAvailable if you want to manage available quantities for sale on your shop(s) - * @see ProductSupplier for manage supplier reference(s) - * - * @deprecated since 1.5.0 - */ - public function addProductAttribute($price, $weight, $unit_impact, $ecotax, $quantity, $id_images, $reference, - $id_supplier = null, $ean13, $default, $location = null, $upc = null, $minimal_quantity = 1) - { - Tools::displayAsDeprecated(); + /** + * addProductAttribute is deprecated + * + * The quantity params now set StockAvailable for the current shop with the specified quantity + * The supplier_reference params now set the supplier reference of the default supplier of the product if possible + * + * @see StockManager if you want to manage real stock + * @see StockAvailable if you want to manage available quantities for sale on your shop(s) + * @see ProductSupplier for manage supplier reference(s) + * + * @deprecated since 1.5.0 + */ + public function addProductAttribute($price, $weight, $unit_impact, $ecotax, $quantity, $id_images, $reference, + $id_supplier = null, $ean13, $default, $location = null, $upc = null, $minimal_quantity = 1) + { + Tools::displayAsDeprecated(); - $id_product_attribute = $this->addAttribute( - $price, $weight, $unit_impact, $ecotax, $id_images, - $reference, $ean13, $default, $location, $upc, $minimal_quantity - ); + $id_product_attribute = $this->addAttribute( + $price, $weight, $unit_impact, $ecotax, $id_images, + $reference, $ean13, $default, $location, $upc, $minimal_quantity + ); - if (!$id_product_attribute) - return false; + if (!$id_product_attribute) { + return false; + } - StockAvailable::setQuantity($this->id, $id_product_attribute, $quantity); - //Try to set the default supplier reference - $this->addSupplierReference($id_supplier, $id_product_attribute); - return $id_product_attribute; - } + StockAvailable::setQuantity($this->id, $id_product_attribute, $quantity); + //Try to set the default supplier reference + $this->addSupplierReference($id_supplier, $id_product_attribute); + return $id_product_attribute; + } - public function generateMultipleCombinations($combinations, $attributes) - { - $res = true; - $default_on = 1; - foreach ($combinations as $key => $combination) - { - $id_combination = (int)$this->productAttributeExists($attributes[$key], false, null, true, true); - $obj = new Combination($id_combination); + public function generateMultipleCombinations($combinations, $attributes) + { + $res = true; + $default_on = 1; + foreach ($combinations as $key => $combination) { + $id_combination = (int)$this->productAttributeExists($attributes[$key], false, null, true, true); + $obj = new Combination($id_combination); - if ($id_combination) - { - $obj->minimal_quantity = 1; - $obj->available_date = '0000-00-00'; - } + if ($id_combination) { + $obj->minimal_quantity = 1; + $obj->available_date = '0000-00-00'; + } - foreach ($combination as $field => $value) - $obj->$field = $value; + foreach ($combination as $field => $value) { + $obj->$field = $value; + } - $obj->default_on = $default_on; - $default_on = 0; - $this->setAvailableDate(); + $obj->default_on = $default_on; + $default_on = 0; + $this->setAvailableDate(); - $obj->save(); + $obj->save(); - if (!$id_combination) - { - $attribute_list = array(); - foreach ($attributes[$key] as $id_attribute) - $attribute_list[] = array( - 'id_product_attribute' => (int)$obj->id, - 'id_attribute' => (int)$id_attribute - ); - $res &= Db::getInstance()->insert('product_attribute_combination', $attribute_list); - } - } + if (!$id_combination) { + $attribute_list = array(); + foreach ($attributes[$key] as $id_attribute) { + $attribute_list[] = array( + 'id_product_attribute' => (int)$obj->id, + 'id_attribute' => (int)$id_attribute + ); + } + $res &= Db::getInstance()->insert('product_attribute_combination', $attribute_list); + } + } - return $res; - } + return $res; + } - /** - * @param int $quantity DEPRECATED - * @param string $supplier_reference DEPRECATED - */ - public function addCombinationEntity($wholesale_price, $price, $weight, $unit_impact, $ecotax, $quantity, - $id_images, $reference, $id_supplier, $ean13, $default, $location = null, $upc = null, $minimal_quantity = 1, array $id_shop_list = array(), $available_date = null) - { - $id_product_attribute = $this->addAttribute( - $price, $weight, $unit_impact, $ecotax, $id_images, - $reference, $ean13, $default, $location, $upc, $minimal_quantity, $id_shop_list, $available_date); - $this->addSupplierReference($id_supplier, $id_product_attribute); - $result = ObjectModel::updateMultishopTable('Combination', array( - 'wholesale_price' => (float)$wholesale_price, - ), 'a.id_product_attribute = '.(int)$id_product_attribute); + /** + * @param int $quantity DEPRECATED + * @param string $supplier_reference DEPRECATED + */ + public function addCombinationEntity($wholesale_price, $price, $weight, $unit_impact, $ecotax, $quantity, + $id_images, $reference, $id_supplier, $ean13, $default, $location = null, $upc = null, $minimal_quantity = 1, array $id_shop_list = array(), $available_date = null) + { + $id_product_attribute = $this->addAttribute( + $price, $weight, $unit_impact, $ecotax, $id_images, + $reference, $ean13, $default, $location, $upc, $minimal_quantity, $id_shop_list, $available_date); + $this->addSupplierReference($id_supplier, $id_product_attribute); + $result = ObjectModel::updateMultishopTable('Combination', array( + 'wholesale_price' => (float)$wholesale_price, + ), 'a.id_product_attribute = '.(int)$id_product_attribute); - if (!$id_product_attribute || !$result) - return false; + if (!$id_product_attribute || !$result) { + return false; + } - return $id_product_attribute; - } + return $id_product_attribute; + } - /** - * @deprecated 1.5.5.0 - * @param $attributes - * @param bool $set_default - * @return array - */ - public function addProductAttributeMultiple($attributes, $set_default = true) - { - Tools::displayAsDeprecated(); - $return = array(); - $default_value = 1; - foreach ($attributes as &$attribute) - { - $obj = new Combination(); - foreach ($attribute as $key => $value) - $obj->$key = $value; + /** + * @deprecated 1.5.5.0 + * @param $attributes + * @param bool $set_default + * @return array + */ + public function addProductAttributeMultiple($attributes, $set_default = true) + { + Tools::displayAsDeprecated(); + $return = array(); + $default_value = 1; + foreach ($attributes as &$attribute) { + $obj = new Combination(); + foreach ($attribute as $key => $value) { + $obj->$key = $value; + } - if ($set_default) - { - $obj->default_on = $default_value; - $default_value = 0; - // if we add a combination for this shop and this product does not use the combination feature in other shop, - // we clone the default combination in every shop linked to this product - if (!$this->hasAttributesInOtherShops()) - { - $id_shop_list_array = Product::getShopsByProduct($this->id); - $id_shop_list = array(); - foreach ($id_shop_list_array as $array_shop) - $id_shop_list[] = $array_shop['id_shop']; - $obj->id_shop_list = $id_shop_list; - } - } - $obj->add(); - $return[] = $obj->id; - } + if ($set_default) { + $obj->default_on = $default_value; + $default_value = 0; + // if we add a combination for this shop and this product does not use the combination feature in other shop, + // we clone the default combination in every shop linked to this product + if (!$this->hasAttributesInOtherShops()) { + $id_shop_list_array = Product::getShopsByProduct($this->id); + $id_shop_list = array(); + foreach ($id_shop_list_array as $array_shop) { + $id_shop_list[] = $array_shop['id_shop']; + } + $obj->id_shop_list = $id_shop_list; + } + } + $obj->add(); + $return[] = $obj->id; + } - return $return; - } + return $return; + } - /** - * Del all default attributes for product - */ - public function deleteDefaultAttributes() - { - return ObjectModel::updateMultishopTable('Combination', array( - 'default_on' => null, - ), 'a.`id_product` = '.(int)$this->id); - } + /** + * Del all default attributes for product + */ + public function deleteDefaultAttributes() + { + return ObjectModel::updateMultishopTable('Combination', array( + 'default_on' => null, + ), 'a.`id_product` = '.(int)$this->id); + } - public function setDefaultAttribute($id_product_attribute) - { - $result = ObjectModel::updateMultishopTable('Combination', array( - 'default_on' => 1 - ), 'a.`id_product` = '.(int)$this->id.' AND a.`id_product_attribute` = '.(int)$id_product_attribute); + public function setDefaultAttribute($id_product_attribute) + { + $result = ObjectModel::updateMultishopTable('Combination', array( + 'default_on' => 1 + ), 'a.`id_product` = '.(int)$this->id.' AND a.`id_product_attribute` = '.(int)$id_product_attribute); - $result &= ObjectModel::updateMultishopTable('product', array( - 'cache_default_attribute' => (int)$id_product_attribute, - ), 'a.`id_product` = '.(int)$this->id); - $this->cache_default_attribute = (int)$id_product_attribute; - return $result; - } + $result &= ObjectModel::updateMultishopTable('product', array( + 'cache_default_attribute' => (int)$id_product_attribute, + ), 'a.`id_product` = '.(int)$this->id); + $this->cache_default_attribute = (int)$id_product_attribute; + return $result; + } - public static function updateDefaultAttribute($id_product) - { - $id_default_attribute = (int)Product::getDefaultAttribute($id_product); + public static function updateDefaultAttribute($id_product) + { + $id_default_attribute = (int)Product::getDefaultAttribute($id_product); - $result = Db::getInstance()->update('product_shop', array( - 'cache_default_attribute' => $id_default_attribute, - ), 'id_product = '.(int)$id_product.Shop::addSqlRestriction()); + $result = Db::getInstance()->update('product_shop', array( + 'cache_default_attribute' => $id_default_attribute, + ), 'id_product = '.(int)$id_product.Shop::addSqlRestriction()); - $result &= Db::getInstance()->update('product', array( - 'cache_default_attribute' => $id_default_attribute, - ), 'id_product = '.(int)$id_product); + $result &= Db::getInstance()->update('product', array( + 'cache_default_attribute' => $id_default_attribute, + ), 'id_product = '.(int)$id_product); - if ($result && $id_default_attribute) - return $id_default_attribute; - else - return $result; - } + if ($result && $id_default_attribute) { + return $id_default_attribute; + } else { + return $result; + } + } - /** - * Update a product attribute - * - * @deprecated since 1.5 - * @see updateAttribute() to use instead - * @see ProductSupplier for manage supplier reference(s) - * - */ - public function updateProductAttribute($id_product_attribute, $wholesale_price, $price, $weight, $unit, $ecotax, - $id_images, $reference, $id_supplier = null, $ean13, $default, $location = null, $upc = null, $minimal_quantity, $available_date) - { - Tools::displayAsDeprecated(); + /** + * Update a product attribute + * + * @deprecated since 1.5 + * @see updateAttribute() to use instead + * @see ProductSupplier for manage supplier reference(s) + * + */ + public function updateProductAttribute($id_product_attribute, $wholesale_price, $price, $weight, $unit, $ecotax, + $id_images, $reference, $id_supplier = null, $ean13, $default, $location = null, $upc = null, $minimal_quantity, $available_date) + { + Tools::displayAsDeprecated(); - $return = $this->updateAttribute( - $id_product_attribute, $wholesale_price, $price, $weight, $unit, $ecotax, - $id_images, $reference, $ean13, $default, $location = null, $upc = null, $minimal_quantity, $available_date - ); - $this->addSupplierReference($id_supplier, $id_product_attribute); + $return = $this->updateAttribute( + $id_product_attribute, $wholesale_price, $price, $weight, $unit, $ecotax, + $id_images, $reference, $ean13, $default, $location = null, $upc = null, $minimal_quantity, $available_date + ); + $this->addSupplierReference($id_supplier, $id_product_attribute); - return $return; - } + return $return; + } - /** - * Sets or updates Supplier Reference - * - * @param int $id_supplier - * @param int $id_product_attribute - * @param string $supplier_reference - * @param float $price - * @param int $id_currency - */ - public function addSupplierReference($id_supplier, $id_product_attribute, $supplier_reference = null, $price = null, $id_currency = null) - { - //in some case we need to add price without supplier reference - if ($supplier_reference === null) - $supplier_reference = ''; + /** + * Sets or updates Supplier Reference + * + * @param int $id_supplier + * @param int $id_product_attribute + * @param string $supplier_reference + * @param float $price + * @param int $id_currency + */ + public function addSupplierReference($id_supplier, $id_product_attribute, $supplier_reference = null, $price = null, $id_currency = null) + { + //in some case we need to add price without supplier reference + if ($supplier_reference === null) { + $supplier_reference = ''; + } - //Try to set the default supplier reference - if (($id_supplier > 0) && ($this->id > 0)) - { - $id_product_supplier = (int)ProductSupplier::getIdByProductAndSupplier($this->id, $id_product_attribute, $id_supplier); + //Try to set the default supplier reference + if (($id_supplier > 0) && ($this->id > 0)) { + $id_product_supplier = (int)ProductSupplier::getIdByProductAndSupplier($this->id, $id_product_attribute, $id_supplier); - $product_supplier = new ProductSupplier($id_product_supplier); + $product_supplier = new ProductSupplier($id_product_supplier); - if (!$id_product_supplier) - { - $product_supplier->id_product = (int)$this->id; - $product_supplier->id_product_attribute = (int)$id_product_attribute; - $product_supplier->id_supplier = (int)$id_supplier; - } + if (!$id_product_supplier) { + $product_supplier->id_product = (int)$this->id; + $product_supplier->id_product_attribute = (int)$id_product_attribute; + $product_supplier->id_supplier = (int)$id_supplier; + } - $product_supplier->product_supplier_reference = pSQL($supplier_reference); - $product_supplier->product_supplier_price_te = !is_null($price) ? (float)$price : (float)$product_supplier->product_supplier_price_te; - $product_supplier->id_currency = !is_null($id_currency) ? (int)$id_currency : (int)$product_supplier->id_currency; - $product_supplier->save(); - } - } + $product_supplier->product_supplier_reference = pSQL($supplier_reference); + $product_supplier->product_supplier_price_te = !is_null($price) ? (float)$price : (float)$product_supplier->product_supplier_price_te; + $product_supplier->id_currency = !is_null($id_currency) ? (int)$id_currency : (int)$product_supplier->id_currency; + $product_supplier->save(); + } + } - /** - * Update a product attribute - * - * @param int $id_product_attribute Product attribute id - * @param float $wholesale_price Wholesale price - * @param float $price Additional price - * @param float $weight Additional weight - * @param float $unit - * @param float $ecotax Additional ecotax - * @param int $id_image Image id - * @param string $reference Reference - * @param string $ean13 Ean-13 barcode - * @param int $default Default On - * @param string $upc Upc barcode - * @param string $minimal_quantity Minimal quantity - * @return array Update result - */ - public function updateAttribute($id_product_attribute, $wholesale_price, $price, $weight, $unit, $ecotax, - $id_images, $reference, $ean13, $default, $location = null, $upc = null, $minimal_quantity = null, $available_date = null, $update_all_fields = true, array $id_shop_list = array()) - { - $combination = new Combination($id_product_attribute); + /** + * Update a product attribute + * + * @param int $id_product_attribute Product attribute id + * @param float $wholesale_price Wholesale price + * @param float $price Additional price + * @param float $weight Additional weight + * @param float $unit + * @param float $ecotax Additional ecotax + * @param int $id_image Image id + * @param string $reference Reference + * @param string $ean13 Ean-13 barcode + * @param int $default Default On + * @param string $upc Upc barcode + * @param string $minimal_quantity Minimal quantity + * @return array Update result + */ + public function updateAttribute($id_product_attribute, $wholesale_price, $price, $weight, $unit, $ecotax, + $id_images, $reference, $ean13, $default, $location = null, $upc = null, $minimal_quantity = null, $available_date = null, $update_all_fields = true, array $id_shop_list = array()) + { + $combination = new Combination($id_product_attribute); - if (!$update_all_fields) - $combination->setFieldsToUpdate(array( - 'price' => !is_null($price), - 'wholesale_price' => !is_null($wholesale_price), - 'ecotax' => !is_null($ecotax), - 'weight' => !is_null($weight), - 'unit_price_impact' => !is_null($unit), - 'default_on' => !is_null($default), - 'minimal_quantity' => !is_null($minimal_quantity), - 'available_date' => !is_null($available_date), - )); + if (!$update_all_fields) { + $combination->setFieldsToUpdate(array( + 'price' => !is_null($price), + 'wholesale_price' => !is_null($wholesale_price), + 'ecotax' => !is_null($ecotax), + 'weight' => !is_null($weight), + 'unit_price_impact' => !is_null($unit), + 'default_on' => !is_null($default), + 'minimal_quantity' => !is_null($minimal_quantity), + 'available_date' => !is_null($available_date), + )); + } - $price = str_replace(',', '.', $price); - $weight = str_replace(',', '.', $weight); + $price = str_replace(',', '.', $price); + $weight = str_replace(',', '.', $weight); - $combination->price = (float)$price; - $combination->wholesale_price = (float)$wholesale_price; - $combination->ecotax = (float)$ecotax; - $combination->weight = (float)$weight; - $combination->unit_price_impact = (float)$unit; - $combination->reference = pSQL($reference); - $combination->location = pSQL($location); - $combination->ean13 = pSQL($ean13); - $combination->upc = pSQL($upc); - $combination->default_on = (int)$default; - $combination->minimal_quantity = (int)$minimal_quantity; - $combination->available_date = $available_date ? pSQL($available_date) : '0000-00-00'; + $combination->price = (float)$price; + $combination->wholesale_price = (float)$wholesale_price; + $combination->ecotax = (float)$ecotax; + $combination->weight = (float)$weight; + $combination->unit_price_impact = (float)$unit; + $combination->reference = pSQL($reference); + $combination->location = pSQL($location); + $combination->ean13 = pSQL($ean13); + $combination->upc = pSQL($upc); + $combination->default_on = (int)$default; + $combination->minimal_quantity = (int)$minimal_quantity; + $combination->available_date = $available_date ? pSQL($available_date) : '0000-00-00'; - if (count($id_shop_list)) - $combination->id_shop_list = $id_shop_list; + if (count($id_shop_list)) { + $combination->id_shop_list = $id_shop_list; + } - $combination->save(); + $combination->save(); - if (is_array($id_images) && count($id_images)) - $combination->setImages($id_images); + if (is_array($id_images) && count($id_images)) { + $combination->setImages($id_images); + } - $id_default_attribute = (int)Product::updateDefaultAttribute($this->id); - if ($id_default_attribute) - $this->cache_default_attribute = $id_default_attribute; + $id_default_attribute = (int)Product::updateDefaultAttribute($this->id); + if ($id_default_attribute) { + $this->cache_default_attribute = $id_default_attribute; + } - // Sync stock Reference, EAN13 and UPC for this attribute - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && StockAvailable::dependsOnStock($this->id, Context::getContext()->shop->id)) - Db::getInstance()->update('stock', array( - 'reference' => pSQL($reference), - 'ean13' => pSQL($ean13), - 'upc' => pSQL($upc), - ), 'id_product = '.$this->id.' AND id_product_attribute = '.(int)$id_product_attribute); + // Sync stock Reference, EAN13 and UPC for this attribute + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && StockAvailable::dependsOnStock($this->id, Context::getContext()->shop->id)) { + Db::getInstance()->update('stock', array( + 'reference' => pSQL($reference), + 'ean13' => pSQL($ean13), + 'upc' => pSQL($upc), + ), 'id_product = '.$this->id.' AND id_product_attribute = '.(int)$id_product_attribute); + } - Hook::exec('actionProductAttributeUpdate', array('id_product_attribute' => (int)$id_product_attribute)); - Tools::clearColorListCache($this->id); + Hook::exec('actionProductAttributeUpdate', array('id_product_attribute' => (int)$id_product_attribute)); + Tools::clearColorListCache($this->id); - return true; - } + return true; + } - /** - * Add a product attribute - * @since 1.5.0.1 - * - * @param float $price Additional price - * @param float $weight Additional weight - * @param float $ecotax Additional ecotax - * @param int $id_images Image ids - * @param string $reference Reference - * @param string $location Location - * @param string $ean13 Ean-13 barcode - * @param bool $default Is default attribute for product - * @param int $minimal_quantity Minimal quantity to add to cart - * @return mixed $id_product_attribute or false - */ - public function addAttribute($price, $weight, $unit_impact, $ecotax, $id_images, $reference, $ean13, - $default, $location = null, $upc = null, $minimal_quantity = 1, array $id_shop_list = array(), $available_date = null) - { - if (!$this->id) - return; + /** + * Add a product attribute + * @since 1.5.0.1 + * + * @param float $price Additional price + * @param float $weight Additional weight + * @param float $ecotax Additional ecotax + * @param int $id_images Image ids + * @param string $reference Reference + * @param string $location Location + * @param string $ean13 Ean-13 barcode + * @param bool $default Is default attribute for product + * @param int $minimal_quantity Minimal quantity to add to cart + * @return mixed $id_product_attribute or false + */ + public function addAttribute($price, $weight, $unit_impact, $ecotax, $id_images, $reference, $ean13, + $default, $location = null, $upc = null, $minimal_quantity = 1, array $id_shop_list = array(), $available_date = null) + { + if (!$this->id) { + return; + } - $price = str_replace(',', '.', $price); - $weight = str_replace(',', '.', $weight); + $price = str_replace(',', '.', $price); + $weight = str_replace(',', '.', $weight); - $combination = new Combination(); - $combination->id_product = (int)$this->id; - $combination->price = (float)$price; - $combination->ecotax = (float)$ecotax; - $combination->quantity = 0; - $combination->weight = (float)$weight; - $combination->unit_price_impact = (float)$unit_impact; - $combination->reference = pSQL($reference); - $combination->location = pSQL($location); - $combination->ean13 = pSQL($ean13); - $combination->upc = pSQL($upc); - $combination->default_on = (int)$default; - $combination->minimal_quantity = (int)$minimal_quantity; - $combination->available_date = $available_date; + $combination = new Combination(); + $combination->id_product = (int)$this->id; + $combination->price = (float)$price; + $combination->ecotax = (float)$ecotax; + $combination->quantity = 0; + $combination->weight = (float)$weight; + $combination->unit_price_impact = (float)$unit_impact; + $combination->reference = pSQL($reference); + $combination->location = pSQL($location); + $combination->ean13 = pSQL($ean13); + $combination->upc = pSQL($upc); + $combination->default_on = (int)$default; + $combination->minimal_quantity = (int)$minimal_quantity; + $combination->available_date = $available_date; - if (count($id_shop_list)) - $combination->id_shop_list = array_unique($id_shop_list); + if (count($id_shop_list)) { + $combination->id_shop_list = array_unique($id_shop_list); + } - $combination->add(); + $combination->add(); - if (!$combination->id) - return false; + if (!$combination->id) { + return false; + } - $total_quantity = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + $total_quantity = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT SUM(quantity) as quantity FROM '._DB_PREFIX_.'stock_available WHERE id_product = '.(int)$this->id.' AND id_product_attribute <> 0 ' - ); + ); - if (!$total_quantity) - Db::getInstance()->update('stock_available', array('quantity' => 0), '`id_product` = '.$this->id); + if (!$total_quantity) { + Db::getInstance()->update('stock_available', array('quantity' => 0), '`id_product` = '.$this->id); + } - $id_default_attribute = Product::updateDefaultAttribute($this->id); + $id_default_attribute = Product::updateDefaultAttribute($this->id); - if ($id_default_attribute) - { - $this->cache_default_attribute = $id_default_attribute; - if (!$combination->available_date) - $this->setAvailableDate(); - } + if ($id_default_attribute) { + $this->cache_default_attribute = $id_default_attribute; + if (!$combination->available_date) { + $this->setAvailableDate(); + } + } - if (!empty($id_images)) - $combination->setImages($id_images); + if (!empty($id_images)) { + $combination->setImages($id_images); + } - Tools::clearColorListCache($this->id); + Tools::clearColorListCache($this->id); - if (Configuration::get('PS_DEFAULT_WAREHOUSE_NEW_PRODUCT') != 0 && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $warehouse_location_entity = new WarehouseProductLocation(); - $warehouse_location_entity->id_product = $this->id; - $warehouse_location_entity->id_product_attribute = (int)$combination->id; - $warehouse_location_entity->id_warehouse = Configuration::get('PS_DEFAULT_WAREHOUSE_NEW_PRODUCT'); - $warehouse_location_entity->location = pSQL(''); - $warehouse_location_entity->save(); - } + if (Configuration::get('PS_DEFAULT_WAREHOUSE_NEW_PRODUCT') != 0 && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $warehouse_location_entity = new WarehouseProductLocation(); + $warehouse_location_entity->id_product = $this->id; + $warehouse_location_entity->id_product_attribute = (int)$combination->id; + $warehouse_location_entity->id_warehouse = Configuration::get('PS_DEFAULT_WAREHOUSE_NEW_PRODUCT'); + $warehouse_location_entity->location = pSQL(''); + $warehouse_location_entity->save(); + } - return (int)$combination->id; - } + return (int)$combination->id; + } - /** - * @deprecated since 1.5.0 - */ - public function updateQuantityProductWithAttributeQuantity() - { - Tools::displayAsDeprecated(); + /** + * @deprecated since 1.5.0 + */ + public function updateQuantityProductWithAttributeQuantity() + { + Tools::displayAsDeprecated(); - return Db::getInstance()->execute(' + return Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'product` SET `quantity` = IFNULL( ( @@ -1642,287 +1710,298 @@ class ProductCore extends ObjectModel WHERE `id_product` = '.(int)$this->id.' ), \'0\') WHERE `id_product` = '.(int)$this->id); - } - /** - * Delete product attributes - * - * @return array Deletion result - */ - public function deleteProductAttributes() - { - Hook::exec('actionProductAttributeDelete', array('id_product_attribute' => 0, 'id_product' => (int)$this->id, 'deleteAllAttributes' => true)); + } + /** + * Delete product attributes + * + * @return array Deletion result + */ + public function deleteProductAttributes() + { + Hook::exec('actionProductAttributeDelete', array('id_product_attribute' => 0, 'id_product' => (int)$this->id, 'deleteAllAttributes' => true)); - $result = true; - $combinations = new PrestaShopCollection('Combination'); - $combinations->where('id_product', '=', $this->id); - foreach ($combinations as $combination) - $result &= $combination->delete(); - SpecificPriceRule::applyAllRules(array((int)$this->id)); - Tools::clearColorListCache($this->id); - return $result; - } + $result = true; + $combinations = new PrestaShopCollection('Combination'); + $combinations->where('id_product', '=', $this->id); + foreach ($combinations as $combination) { + $result &= $combination->delete(); + } + SpecificPriceRule::applyAllRules(array((int)$this->id)); + Tools::clearColorListCache($this->id); + return $result; + } - /** - * Delete product attributes impacts - * - * @return bool - */ - public function deleteAttributesImpacts() - { - return Db::getInstance()->execute( - 'DELETE FROM `'._DB_PREFIX_.'attribute_impact` + /** + * Delete product attributes impacts + * + * @return bool + */ + public function deleteAttributesImpacts() + { + return Db::getInstance()->execute( + 'DELETE FROM `'._DB_PREFIX_.'attribute_impact` WHERE `id_product` = '.(int)$this->id - ); - } + ); + } - /** - * Delete product features - * - * @return array Deletion result - */ - public function deleteProductFeatures() - { - SpecificPriceRule::applyAllRules(array((int)$this->id)); - return $this->deleteFeatures(); - } + /** + * Delete product features + * + * @return array Deletion result + */ + public function deleteProductFeatures() + { + SpecificPriceRule::applyAllRules(array((int)$this->id)); + return $this->deleteFeatures(); + } - public static function updateCacheAttachment($id_product) - { - $value = (bool)Db::getInstance()->getValue(' + public static function updateCacheAttachment($id_product) + { + $value = (bool)Db::getInstance()->getValue(' SELECT id_attachment FROM '._DB_PREFIX_.'product_attachment WHERE id_product='.(int)$id_product); - return Db::getInstance()->update( - 'product', - array('cache_has_attachments' => (int)$value), - 'id_product = '.(int)$id_product - ); - } + return Db::getInstance()->update( + 'product', + array('cache_has_attachments' => (int)$value), + 'id_product = '.(int)$id_product + ); + } - /** - * Delete product attachments - * - * @param bool $update_cache If set to true attachment cache will be updated - * @return array Deletion result - */ - public function deleteAttachments($update_attachment_cache = true) - { - $res = Db::getInstance()->execute(' + /** + * Delete product attachments + * + * @param bool $update_cache If set to true attachment cache will be updated + * @return array Deletion result + */ + public function deleteAttachments($update_attachment_cache = true) + { + $res = Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'product_attachment` WHERE `id_product` = '.(int)$this->id - ); + ); - if (isset($update_attachment_cache) && (bool)$update_attachment_cache === true) - Product::updateCacheAttachment((int)$this->id); + if (isset($update_attachment_cache) && (bool)$update_attachment_cache === true) { + Product::updateCacheAttachment((int)$this->id); + } - return $res; - } + return $res; + } - /** - * Delete product customizations - * - * @return array Deletion result - */ - public function deleteCustomization() - { - return ( - Db::getInstance()->execute( - 'DELETE FROM `'._DB_PREFIX_.'customization_field` + /** + * Delete product customizations + * + * @return array Deletion result + */ + public function deleteCustomization() + { + return ( + Db::getInstance()->execute( + 'DELETE FROM `'._DB_PREFIX_.'customization_field` WHERE `id_product` = '.(int)$this->id - ) - && - Db::getInstance()->execute( - 'DELETE `'._DB_PREFIX_.'customization_field_lang` FROM `'._DB_PREFIX_.'customization_field_lang` LEFT JOIN `'._DB_PREFIX_.'customization_field` + ) + && + Db::getInstance()->execute( + 'DELETE `'._DB_PREFIX_.'customization_field_lang` FROM `'._DB_PREFIX_.'customization_field_lang` LEFT JOIN `'._DB_PREFIX_.'customization_field` ON ('._DB_PREFIX_.'customization_field.id_customization_field = '._DB_PREFIX_.'customization_field_lang.id_customization_field) WHERE '._DB_PREFIX_.'customization_field.id_customization_field IS NULL' - ) - ); - } + ) + ); + } - /** - * Delete product pack details - * - * @return array Deletion result - */ - public function deletePack() - { - return Db::getInstance()->execute( - 'DELETE FROM `'._DB_PREFIX_.'pack` + /** + * Delete product pack details + * + * @return array Deletion result + */ + public function deletePack() + { + return Db::getInstance()->execute( + 'DELETE FROM `'._DB_PREFIX_.'pack` WHERE `id_product_pack` = '.(int)$this->id.' OR `id_product_item` = '.(int)$this->id - ); - } + ); + } - /** - * Delete product sales - * - * @return array Deletion result - */ - public function deleteProductSale() - { - return Db::getInstance()->execute( - 'DELETE FROM `'._DB_PREFIX_.'product_sale` + /** + * Delete product sales + * + * @return array Deletion result + */ + public function deleteProductSale() + { + return Db::getInstance()->execute( + 'DELETE FROM `'._DB_PREFIX_.'product_sale` WHERE `id_product` = '.(int)$this->id - ); - } + ); + } - /** - * Delete product in its scenes - * - * @return array Deletion result - */ - public function deleteSceneProducts() - { - return Db::getInstance()->execute( - 'DELETE FROM `'._DB_PREFIX_.'scene_products` + /** + * Delete product in its scenes + * + * @return array Deletion result + */ + public function deleteSceneProducts() + { + return Db::getInstance()->execute( + 'DELETE FROM `'._DB_PREFIX_.'scene_products` WHERE `id_product` = '.(int)$this->id - ); - } + ); + } - /** - * Delete product indexed words - * - * @return array Deletion result - */ - public function deleteSearchIndexes() - { - return ( - Db::getInstance()->execute( - 'DELETE `'._DB_PREFIX_.'search_index`, `'._DB_PREFIX_.'search_word` + /** + * Delete product indexed words + * + * @return array Deletion result + */ + public function deleteSearchIndexes() + { + return ( + Db::getInstance()->execute( + 'DELETE `'._DB_PREFIX_.'search_index`, `'._DB_PREFIX_.'search_word` FROM `'._DB_PREFIX_.'search_index` JOIN `'._DB_PREFIX_.'search_word` WHERE `'._DB_PREFIX_.'search_index`.`id_product` = '.(int)$this->id.' AND `'._DB_PREFIX_.'search_word`.`id_word` = `'._DB_PREFIX_.'search_index`.id_word' - ) - ); - } + ) + ); + } - /** - * Add a product attributes combinaison - * - * @param int $id_product_attribute Product attribute id - * @param array $attributes Attributes to forge combinaison - * @return array Insertion result - * @deprecated since 1.5.0.7 - */ - public function addAttributeCombinaison($id_product_attribute, $attributes) - { - Tools::displayAsDeprecated(); - if (!is_array($attributes)) - die(Tools::displayError()); - if (!count($attributes)) - return false; + /** + * Add a product attributes combinaison + * + * @param int $id_product_attribute Product attribute id + * @param array $attributes Attributes to forge combinaison + * @return array Insertion result + * @deprecated since 1.5.0.7 + */ + public function addAttributeCombinaison($id_product_attribute, $attributes) + { + Tools::displayAsDeprecated(); + if (!is_array($attributes)) { + die(Tools::displayError()); + } + if (!count($attributes)) { + return false; + } - $combination = new Combination((int)$id_product_attribute); - return $combination->setAttributes($attributes); - } + $combination = new Combination((int)$id_product_attribute); + return $combination->setAttributes($attributes); + } - /** - * @deprecated 1.5.5.0 - * @param $id_attributes - * @param $combinations - * @return bool - * @throws PrestaShopDatabaseException - */ - public function addAttributeCombinationMultiple($id_attributes, $combinations) - { - Tools::displayAsDeprecated(); - $attributes_list = array(); - foreach ($id_attributes as $nb => $id_product_attribute) - if (isset($combinations[$nb])) - foreach ($combinations[$nb] as $id_attribute) - $attributes_list[] = array( - 'id_product_attribute' => (int)$id_product_attribute, - 'id_attribute' => (int)$id_attribute, - ); + /** + * @deprecated 1.5.5.0 + * @param $id_attributes + * @param $combinations + * @return bool + * @throws PrestaShopDatabaseException + */ + public function addAttributeCombinationMultiple($id_attributes, $combinations) + { + Tools::displayAsDeprecated(); + $attributes_list = array(); + foreach ($id_attributes as $nb => $id_product_attribute) { + if (isset($combinations[$nb])) { + foreach ($combinations[$nb] as $id_attribute) { + $attributes_list[] = array( + 'id_product_attribute' => (int)$id_product_attribute, + 'id_attribute' => (int)$id_attribute, + ); + } + } + } - return Db::getInstance()->insert('product_attribute_combination', $attributes_list); - } + return Db::getInstance()->insert('product_attribute_combination', $attributes_list); + } - /** - * Delete a product attributes combination - * - * @param int $id_product_attribute Product attribute id - * @return array Deletion result - */ - public function deleteAttributeCombination($id_product_attribute) - { - if (!$this->id || !$id_product_attribute || !is_numeric($id_product_attribute)) - return false; + /** + * Delete a product attributes combination + * + * @param int $id_product_attribute Product attribute id + * @return array Deletion result + */ + public function deleteAttributeCombination($id_product_attribute) + { + if (!$this->id || !$id_product_attribute || !is_numeric($id_product_attribute)) { + return false; + } - Hook::exec( - 'deleteProductAttribute', - array( - 'id_product_attribute' => $id_product_attribute, - 'id_product' => $this->id, - 'deleteAllAttributes' => false - ) - ); + Hook::exec( + 'deleteProductAttribute', + array( + 'id_product_attribute' => $id_product_attribute, + 'id_product' => $this->id, + 'deleteAllAttributes' => false + ) + ); - $combination = new Combination($id_product_attribute); - $res = $combination->delete(); - SpecificPriceRule::applyAllRules(array((int)$this->id)); - return $res; - } + $combination = new Combination($id_product_attribute); + $res = $combination->delete(); + SpecificPriceRule::applyAllRules(array((int)$this->id)); + return $res; + } - /** - * Delete features - * - */ - public function deleteFeatures() - { - // List products features - $features = Db::getInstance()->executeS(' + /** + * Delete features + * + */ + public function deleteFeatures() + { + // List products features + $features = Db::getInstance()->executeS(' SELECT p.*, f.* FROM `'._DB_PREFIX_.'feature_product` as p LEFT JOIN `'._DB_PREFIX_.'feature_value` as f ON (f.`id_feature_value` = p.`id_feature_value`) WHERE `id_product` = '.(int)$this->id); - foreach ($features as $tab) - // Delete product custom features - if ($tab['custom']) - { - Db::getInstance()->execute(' + foreach ($features as $tab) { + // Delete product custom features + if ($tab['custom']) { + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'feature_value` WHERE `id_feature_value` = '.(int)$tab['id_feature_value']); - Db::getInstance()->execute(' + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'feature_value_lang` WHERE `id_feature_value` = '.(int)$tab['id_feature_value']); - } - // Delete product features - $result = Db::getInstance()->execute(' + } + } + // Delete product features + $result = Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'feature_product` WHERE `id_product` = '.(int)$this->id); - SpecificPriceRule::applyAllRules(array((int)$this->id)); - return ($result); - } + SpecificPriceRule::applyAllRules(array((int)$this->id)); + return ($result); + } - /** - * Get all available product attributes resume - * - * @param int $id_lang Language id - * @return array Product attributes combinations - */ - public function getAttributesResume($id_lang, $attribute_value_separator = ' - ', $attribute_separator = ', ') - { - if (!Combination::isFeatureActive()) - return array(); + /** + * Get all available product attributes resume + * + * @param int $id_lang Language id + * @return array Product attributes combinations + */ + public function getAttributesResume($id_lang, $attribute_value_separator = ' - ', $attribute_separator = ', ') + { + if (!Combination::isFeatureActive()) { + return array(); + } - $combinations = Db::getInstance()->executeS('SELECT pa.*, product_attribute_shop.* + $combinations = Db::getInstance()->executeS('SELECT pa.*, product_attribute_shop.* FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE pa.`id_product` = '.(int)$this->id.' GROUP BY pa.`id_product_attribute`'); - if (!$combinations) - return false; + if (!$combinations) { + return false; + } - $product_attributes = array(); - foreach ($combinations as $combination) - $product_attributes[] = (int)$combination['id_product_attribute']; + $product_attributes = array(); + foreach ($combinations as $combination) { + $product_attributes[] = (int)$combination['id_product_attribute']; + } - $lang = Db::getInstance()->executeS('SELECT pac.id_product_attribute, GROUP_CONCAT(agl.`name`, \''.pSQL($attribute_value_separator).'\',al.`name` ORDER BY agl.`id_attribute_group` SEPARATOR \''.pSQL($attribute_separator).'\') as attribute_designation + $lang = Db::getInstance()->executeS('SELECT pac.id_product_attribute, GROUP_CONCAT(agl.`name`, \''.pSQL($attribute_value_separator).'\',al.`name` ORDER BY agl.`id_attribute_group` SEPARATOR \''.pSQL($attribute_separator).'\') as attribute_designation FROM `'._DB_PREFIX_.'product_attribute_combination` pac LEFT JOIN `'._DB_PREFIX_.'attribute` a ON a.`id_attribute` = pac.`id_attribute` LEFT JOIN `'._DB_PREFIX_.'attribute_group` ag ON ag.`id_attribute_group` = a.`id_attribute_group` @@ -1931,42 +2010,42 @@ class ProductCore extends ObjectModel WHERE pac.id_product_attribute IN ('.implode(',', $product_attributes).') GROUP BY pac.id_product_attribute'); - foreach ($lang as $k => $row) - $combinations[$k]['attribute_designation'] = $row['attribute_designation']; + foreach ($lang as $k => $row) { + $combinations[$k]['attribute_designation'] = $row['attribute_designation']; + } - //Get quantity of each variations - foreach ($combinations as $key => $row) - { - $cache_key = $row['id_product'].'_'.$row['id_product_attribute'].'_quantity'; + //Get quantity of each variations + foreach ($combinations as $key => $row) { + $cache_key = $row['id_product'].'_'.$row['id_product_attribute'].'_quantity'; - if (!Cache::isStored($cache_key)) - { - $result = StockAvailable::getQuantityAvailableByProduct($row['id_product'], $row['id_product_attribute']); - Cache::store( - $cache_key, - $result - ); - $combinations[$key]['quantity'] = $result; - } - else - $combinations[$key]['quantity'] = Cache::retrieve($cache_key); - } + if (!Cache::isStored($cache_key)) { + $result = StockAvailable::getQuantityAvailableByProduct($row['id_product'], $row['id_product_attribute']); + Cache::store( + $cache_key, + $result + ); + $combinations[$key]['quantity'] = $result; + } else { + $combinations[$key]['quantity'] = Cache::retrieve($cache_key); + } + } - return $combinations; - } + return $combinations; + } - /** - * Get all available product attributes combinations - * - * @param int $id_lang Language id - * @return array Product attributes combinations - */ - public function getAttributeCombinations($id_lang) - { - if (!Combination::isFeatureActive()) - return array(); + /** + * Get all available product attributes combinations + * + * @param int $id_lang Language id + * @return array Product attributes combinations + */ + public function getAttributeCombinations($id_lang) + { + if (!Combination::isFeatureActive()) { + return array(); + } - $sql = 'SELECT pa.*, product_attribute_shop.*, ag.`id_attribute_group`, ag.`is_color_group`, agl.`name` AS group_name, al.`name` AS attribute_name, + $sql = 'SELECT pa.*, product_attribute_shop.*, ag.`id_attribute_group`, ag.`is_color_group`, agl.`name` AS group_name, al.`name` AS attribute_name, a.`id_attribute` FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' @@ -1979,37 +2058,38 @@ class ProductCore extends ObjectModel GROUP BY pa.`id_product_attribute`, ag.`id_attribute_group` ORDER BY pa.`id_product_attribute`'; - $res = Db::getInstance()->executeS($sql); + $res = Db::getInstance()->executeS($sql); - //Get quantity of each variations - foreach ($res as $key => $row) - { - $cache_key = $row['id_product'].'_'.$row['id_product_attribute'].'_quantity'; + //Get quantity of each variations + foreach ($res as $key => $row) { + $cache_key = $row['id_product'].'_'.$row['id_product_attribute'].'_quantity'; - if (!Cache::isStored($cache_key)) - Cache::store( - $cache_key, - StockAvailable::getQuantityAvailableByProduct($row['id_product'], $row['id_product_attribute']) - ); + if (!Cache::isStored($cache_key)) { + Cache::store( + $cache_key, + StockAvailable::getQuantityAvailableByProduct($row['id_product'], $row['id_product_attribute']) + ); + } - $res[$key]['quantity'] = Cache::retrieve($cache_key); - } + $res[$key]['quantity'] = Cache::retrieve($cache_key); + } - return $res; - } + return $res; + } - /** - * Get product attribute combination by id_product_attribute - * - * @param int $id_product_attribute - * @param int $id_lang Language id - * @return array Product attribute combination by id_product_attribute - */ - public function getAttributeCombinationsById($id_product_attribute, $id_lang) - { - if (!Combination::isFeatureActive()) - return array(); - $sql = 'SELECT pa.*, product_attribute_shop.*, ag.`id_attribute_group`, ag.`is_color_group`, agl.`name` AS group_name, al.`name` AS attribute_name, + /** + * Get product attribute combination by id_product_attribute + * + * @param int $id_product_attribute + * @param int $id_lang Language id + * @return array Product attribute combination by id_product_attribute + */ + public function getAttributeCombinationsById($id_product_attribute, $id_lang) + { + if (!Combination::isFeatureActive()) { + return array(); + } + $sql = 'SELECT pa.*, product_attribute_shop.*, ag.`id_attribute_group`, ag.`is_color_group`, agl.`name` AS group_name, al.`name` AS attribute_name, a.`id_attribute` FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' @@ -2023,270 +2103,291 @@ class ProductCore extends ObjectModel GROUP BY pa.`id_product_attribute`, ag.`id_attribute_group` ORDER BY pa.`id_product_attribute`'; - $res = Db::getInstance()->executeS($sql); + $res = Db::getInstance()->executeS($sql); - //Get quantity of each variations - foreach ($res as $key => $row) - { - $cache_key = $row['id_product'].'_'.$row['id_product_attribute'].'_quantity'; + //Get quantity of each variations + foreach ($res as $key => $row) { + $cache_key = $row['id_product'].'_'.$row['id_product_attribute'].'_quantity'; - if (!Cache::isStored($cache_key)) - { - $result = StockAvailable::getQuantityAvailableByProduct($row['id_product'], $row['id_product_attribute']); - Cache::store( - $cache_key, - $result - ); - $res[$key]['quantity'] = $result; - } - else - $res[$key]['quantity'] = Cache::retrieve($cache_key); - } + if (!Cache::isStored($cache_key)) { + $result = StockAvailable::getQuantityAvailableByProduct($row['id_product'], $row['id_product_attribute']); + Cache::store( + $cache_key, + $result + ); + $res[$key]['quantity'] = $result; + } else { + $res[$key]['quantity'] = Cache::retrieve($cache_key); + } + } - return $res; - } + return $res; + } - public function getCombinationImages($id_lang) - { - if (!Combination::isFeatureActive()) - return false; + public function getCombinationImages($id_lang) + { + if (!Combination::isFeatureActive()) { + return false; + } - $product_attributes = Db::getInstance()->executeS( - 'SELECT `id_product_attribute` + $product_attributes = Db::getInstance()->executeS( + 'SELECT `id_product_attribute` FROM `'._DB_PREFIX_.'product_attribute` WHERE `id_product` = '.(int)$this->id - ); + ); - if (!$product_attributes) - return false; + if (!$product_attributes) { + return false; + } - $ids = array(); + $ids = array(); - foreach ($product_attributes as $product_attribute) - $ids[] = (int)$product_attribute['id_product_attribute']; + foreach ($product_attributes as $product_attribute) { + $ids[] = (int)$product_attribute['id_product_attribute']; + } - $result = Db::getInstance()->executeS(' + $result = Db::getInstance()->executeS(' SELECT pai.`id_image`, pai.`id_product_attribute`, il.`legend` FROM `'._DB_PREFIX_.'product_attribute_image` pai LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (il.`id_image` = pai.`id_image`) LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_image` = pai.`id_image`) WHERE pai.`id_product_attribute` IN ('.implode(', ', $ids).') AND il.`id_lang` = '.(int)$id_lang.' ORDER by i.`position`' - ); + ); - if (!$result) - return false; + if (!$result) { + return false; + } - $images = array(); + $images = array(); - foreach ($result as $row) - $images[$row['id_product_attribute']][] = $row; + foreach ($result as $row) { + $images[$row['id_product_attribute']][] = $row; + } - return $images; - } + return $images; + } - public static function getCombinationImageById($id_product_attribute, $id_lang) - { - if (!Combination::isFeatureActive() || !$id_product_attribute) - return false; + public static function getCombinationImageById($id_product_attribute, $id_lang) + { + if (!Combination::isFeatureActive() || !$id_product_attribute) { + return false; + } - $result = Db::getInstance()->executeS(' + $result = Db::getInstance()->executeS(' SELECT pai.`id_image`, pai.`id_product_attribute`, il.`legend` FROM `'._DB_PREFIX_.'product_attribute_image` pai LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (il.`id_image` = pai.`id_image`) LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_image` = pai.`id_image`) WHERE pai.`id_product_attribute` = '.(int)$id_product_attribute.' AND il.`id_lang` = '.(int)$id_lang.' ORDER by i.`position` LIMIT 1' - ); + ); - if (!$result) - return false; + if (!$result) { + return false; + } - return $result[0]; - } + return $result[0]; + } - /** - * Check if product has attributes combinations - * - * @return int Attributes combinations number - */ - public function hasAttributes() - { - if (!Combination::isFeatureActive()) - return 0; - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Check if product has attributes combinations + * + * @return int Attributes combinations number + */ + public function hasAttributes() + { + if (!Combination::isFeatureActive()) { + return 0; + } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE pa.`id_product` = '.(int)$this->id - ); - } + ); + } - /** - * Get new products - * - * @param int $id_lang Language id - * @param int $pageNumber Start from (optional) - * @param int $nbProducts Number of products to return (optional) - * @return array New products - */ - public static function getNewProducts($id_lang, $page_number = 0, $nb_products = 10, $count = false, $order_by = null, $order_way = null, Context $context = null) - { - if (!$context) - $context = Context::getContext(); + /** + * Get new products + * + * @param int $id_lang Language id + * @param int $pageNumber Start from (optional) + * @param int $nbProducts Number of products to return (optional) + * @return array New products + */ + public static function getNewProducts($id_lang, $page_number = 0, $nb_products = 10, $count = false, $order_by = null, $order_way = null, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } - $front = true; - if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) - $front = false; + $front = true; + if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) { + $front = false; + } - if ($page_number < 0) $page_number = 0; - if ($nb_products < 1) $nb_products = 10; - if (empty($order_by) || $order_by == 'position') $order_by = 'date_add'; - if (empty($order_way)) $order_way = 'DESC'; - if ($order_by == 'id_product' || $order_by == 'price' || $order_by == 'date_add' || $order_by == 'date_upd') - $order_by_prefix = 'p'; - elseif ($order_by == 'name') - $order_by_prefix = 'pl'; - if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) - die(Tools::displayError()); + if ($page_number < 0) { + $page_number = 0; + } + if ($nb_products < 1) { + $nb_products = 10; + } + if (empty($order_by) || $order_by == 'position') { + $order_by = 'date_add'; + } + if (empty($order_way)) { + $order_way = 'DESC'; + } + if ($order_by == 'id_product' || $order_by == 'price' || $order_by == 'date_add' || $order_by == 'date_upd') { + $order_by_prefix = 'p'; + } elseif ($order_by == 'name') { + $order_by_prefix = 'pl'; + } + if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) { + die(Tools::displayError()); + } - $sql_groups = ''; - if (Group::isFeatureActive()) - { - $groups = FrontController::getCurrentCustomerGroups(); - $sql_groups = ' AND EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp + $sql_groups = ''; + if (Group::isFeatureActive()) { + $groups = FrontController::getCurrentCustomerGroups(); + $sql_groups = ' AND EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.id_category = cg.id_category AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1').') WHERE cp.`id_product` = p.`id_product`)'; - } + } - if (strpos($order_by, '.') > 0) - { - $order_by = explode('.', $order_by); - $order_by_prefix = $order_by[0]; - $order_by = $order_by[1]; - } + if (strpos($order_by, '.') > 0) { + $order_by = explode('.', $order_by); + $order_by_prefix = $order_by[0]; + $order_by = $order_by[1]; + } - if ($count) - { - $sql = 'SELECT COUNT(p.`id_product`) AS nb + if ($count) { + $sql = 'SELECT COUNT(p.`id_product`) AS nb FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' WHERE product_shop.`active` = 1 AND product_shop.`date_add` > "'.date('Y-m-d', strtotime('-'.(Configuration::get('PS_NB_DAYS_NEW_PRODUCT') ? (int)Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY')).'" '.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').' '.$sql_groups; - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); - } + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); + } - $sql = new DbQuery(); - $sql->select( - 'p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, + $sql = new DbQuery(); + $sql->select( + 'p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, pl.`available_now`, pl.`available_later`, image_shop.`id_image` id_image, il.`legend`, m.`name` AS manufacturer_name, product_shop.`date_add` > "'.date('Y-m-d', strtotime('-'.(Configuration::get('PS_NB_DAYS_NEW_PRODUCT') ? (int)Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY')).'" as new' - ); + ); - $sql->from('product', 'p'); - $sql->join(Shop::addSqlAssociation('product', 'p')); - $sql->leftJoin('product_lang', 'pl', ' + $sql->from('product', 'p'); + $sql->join(Shop::addSqlAssociation('product', 'p')); + $sql->leftJoin('product_lang', 'pl', ' p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl') - ); - $sql->leftJoin('image_shop', 'image_shop', 'image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop='.(int)$context->shop->id); - $sql->leftJoin('image_lang', 'il', 'image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang); - $sql->leftJoin('manufacturer', 'm', 'm.`id_manufacturer` = p.`id_manufacturer`'); + ); + $sql->leftJoin('image_shop', 'image_shop', 'image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop='.(int)$context->shop->id); + $sql->leftJoin('image_lang', 'il', 'image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang); + $sql->leftJoin('manufacturer', 'm', 'm.`id_manufacturer` = p.`id_manufacturer`'); - $sql->where('product_shop.`active` = 1'); - if ($front) - $sql->where('product_shop.`visibility` IN ("both", "catalog")'); - $sql->where('product_shop.`date_add` > "'.date('Y-m-d', strtotime('-'.(Configuration::get('PS_NB_DAYS_NEW_PRODUCT') ? (int)Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY')).'"'); - if (Group::isFeatureActive()) - { - $sql->join('JOIN '._DB_PREFIX_.'category_product cp ON (cp.id_product = p.id_product)'); - $sql->join('JOIN '._DB_PREFIX_.'category_group cg ON (cg.id_category = cp.id_category)'); - $sql->where('cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1')); - } - $sql->groupBy('product_shop.id_product'); + $sql->where('product_shop.`active` = 1'); + if ($front) { + $sql->where('product_shop.`visibility` IN ("both", "catalog")'); + } + $sql->where('product_shop.`date_add` > "'.date('Y-m-d', strtotime('-'.(Configuration::get('PS_NB_DAYS_NEW_PRODUCT') ? (int)Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY')).'"'); + if (Group::isFeatureActive()) { + $sql->join('JOIN '._DB_PREFIX_.'category_product cp ON (cp.id_product = p.id_product)'); + $sql->join('JOIN '._DB_PREFIX_.'category_group cg ON (cg.id_category = cp.id_category)'); + $sql->where('cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1')); + } + $sql->groupBy('product_shop.id_product'); - $sql->orderBy((isset($order_by_prefix) ? pSQL($order_by_prefix).'.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way)); - $sql->limit($nb_products, $page_number * $nb_products); + $sql->orderBy((isset($order_by_prefix) ? pSQL($order_by_prefix).'.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way)); + $sql->limit($nb_products, $page_number * $nb_products); - if (Combination::isFeatureActive()) - { - $sql->select('product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, IFNULL(product_attribute_shop.id_product_attribute,0) id_product_attribute'); - $sql->leftJoin('product_attribute_shop', 'product_attribute_shop', 'p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='.(int)$context->shop->id); - } - $sql->join(Product::sqlStock('p', 0)); + if (Combination::isFeatureActive()) { + $sql->select('product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, IFNULL(product_attribute_shop.id_product_attribute,0) id_product_attribute'); + $sql->leftJoin('product_attribute_shop', 'product_attribute_shop', 'p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='.(int)$context->shop->id); + } + $sql->join(Product::sqlStock('p', 0)); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - if ($order_by == 'price') - Tools::orderbyPrice($result, $order_way); - if (!$result) - return false; + if ($order_by == 'price') { + Tools::orderbyPrice($result, $order_way); + } + if (!$result) { + return false; + } - $products_ids = array(); - foreach ($result as $row) - $products_ids[] = $row['id_product']; - // Thus you can avoid one query per product, because there will be only one query for all the products of the cart - Product::cacheFrontFeatures($products_ids, $id_lang); - return Product::getProductsProperties((int)$id_lang, $result); - } + $products_ids = array(); + foreach ($result as $row) { + $products_ids[] = $row['id_product']; + } + // Thus you can avoid one query per product, because there will be only one query for all the products of the cart + Product::cacheFrontFeatures($products_ids, $id_lang); + return Product::getProductsProperties((int)$id_lang, $result); + } - protected static function _getProductIdByDate($beginning, $ending, Context $context = null, $with_combination = false) - { - if (!$context) - $context = Context::getContext(); + protected static function _getProductIdByDate($beginning, $ending, Context $context = null, $with_combination = false) + { + if (!$context) { + $context = Context::getContext(); + } - $id_address = $context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; - $ids = Address::getCountryAndState($id_address); - $id_country = $ids['id_country'] ? (int)$ids['id_country'] : (int)Configuration::get('PS_COUNTRY_DEFAULT'); + $id_address = $context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; + $ids = Address::getCountryAndState($id_address); + $id_country = $ids['id_country'] ? (int)$ids['id_country'] : (int)Configuration::get('PS_COUNTRY_DEFAULT'); - return SpecificPrice::getProductIdByDate( - $context->shop->id, - $context->currency->id, - $id_country, - $context->customer->id_default_group, - $beginning, - $ending, - 0, - $with_combination - ); - } + return SpecificPrice::getProductIdByDate( + $context->shop->id, + $context->currency->id, + $id_country, + $context->customer->id_default_group, + $beginning, + $ending, + 0, + $with_combination + ); + } - /** - * Get a random special - * - * @param int $id_lang Language id - * @return array Special - */ - public static function getRandomSpecial($id_lang, $beginning = false, $ending = false, Context $context = null) - { - if (!$context) - $context = Context::getContext(); + /** + * Get a random special + * + * @param int $id_lang Language id + * @return array Special + */ + public static function getRandomSpecial($id_lang, $beginning = false, $ending = false, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } - $front = true; - if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) - $front = false; + $front = true; + if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) { + $front = false; + } - $current_date = date('Y-m-d H:i:s'); - $product_reductions = Product::_getProductIdByDate((!$beginning ? $current_date : $beginning), (!$ending ? $current_date : $ending), $context, true); + $current_date = date('Y-m-d H:i:s'); + $product_reductions = Product::_getProductIdByDate((!$beginning ? $current_date : $beginning), (!$ending ? $current_date : $ending), $context, true); - if ($product_reductions) - { - $ids_products = ''; - foreach ($product_reductions as $product_reduction) - $ids_products .= '('.(int)$product_reduction['id_product'].','.($product_reduction['id_product_attribute'] ? (int)$product_reduction['id_product_attribute'] :'0').'),'; + if ($product_reductions) { + $ids_products = ''; + foreach ($product_reductions as $product_reduction) { + $ids_products .= '('.(int)$product_reduction['id_product'].','.($product_reduction['id_product_attribute'] ? (int)$product_reduction['id_product_attribute'] :'0').'),'; + } - $ids_products = rtrim($ids_products, ','); - Db::getInstance(_PS_USE_SQL_SLAVE_)->execute('CREATE TEMPORARY TABLE `'._DB_PREFIX_.'product_reductions` (id_product INT UNSIGNED NOT NULL DEFAULT 0, id_product_attribute INT UNSIGNED NOT NULL DEFAULT 0) ENGINE=MEMORY', false); - if ($ids_products) - Db::getInstance(_PS_USE_SQL_SLAVE_)->execute('INSERT INTO `'._DB_PREFIX_.'product_reductions` VALUES '.$ids_products, false); + $ids_products = rtrim($ids_products, ','); + Db::getInstance()->execute('CREATE TEMPORARY TABLE `'._DB_PREFIX_.'product_reductions` (id_product INT UNSIGNED NOT NULL DEFAULT 0, id_product_attribute INT UNSIGNED NOT NULL DEFAULT 0) ENGINE=MEMORY', false); + if ($ids_products) { + Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'product_reductions` VALUES '.$ids_products, false); + } - $groups = FrontController::getCurrentCustomerGroups(); - $sql_groups = ' AND EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp + $groups = FrontController::getCurrentCustomerGroups(); + $sql_groups = ' AND EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.id_category = cg.id_category AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1').') WHERE cp.`id_product` = p.`id_product`)'; - // Please keep 2 distinct queries because RAND() is an awful way to achieve this result - $sql = 'SELECT product_shop.id_product, IFNULL(product_attribute_shop.id_product_attribute,0) id_product_attribute + // Please keep 2 distinct queries because RAND() is an awful way to achieve this result + $sql = 'SELECT product_shop.id_product, IFNULL(product_attribute_shop.id_product_attribute,0) id_product_attribute FROM `'._DB_PREFIX_.'product_reductions` pr, `'._DB_PREFIX_.'product` p @@ -2298,13 +2399,14 @@ class ProductCore extends ObjectModel '.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').' ORDER BY RAND()'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + $result = Db::getInstance()->getRow($sql); - if (!$id_product = $result['id_product']) - return false; + if (!$id_product = $result['id_product']) { + return false; + } - // no group by needed : there's only one attribute with cover=1 for a given id_product + shop - $sql = 'SELECT p.*, product_shop.*, stock.`out_of_stock` out_of_stock, pl.`description`, pl.`description_short`, + // no group by needed : there's only one attribute with cover=1 for a given id_product + shop + $sql = 'SELECT p.*, product_shop.*, stock.`out_of_stock` out_of_stock, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, pl.`available_now`, pl.`available_later`, p.`ean13`, p.`upc`, image_shop.`id_image` id_image, il.`legend`, DATEDIFF(product_shop.`date_add`, DATE_SUB("'.date('Y-m-d').' 00:00:00", @@ -2322,69 +2424,84 @@ class ProductCore extends ObjectModel '.Product::sqlStock('p', 0).' WHERE p.id_product = '.(int)$id_product; - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); - if (!$row) - return false; + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + if (!$row) { + return false; + } - $row['id_product_attribute'] = (int)$result['id_product_attribute']; - return Product::getProductProperties($id_lang, $row); - } - else - return false; - } + $row['id_product_attribute'] = (int)$result['id_product_attribute']; + return Product::getProductProperties($id_lang, $row); + } else { + return false; + } + } - /** - * Get prices drop - * - * @param int $id_lang Language id - * @param int $pageNumber Start from (optional) - * @param int $nbProducts Number of products to return (optional) - * @param bool $count Only in order to get total number (optional) - * @return array Prices drop - */ - public static function getPricesDrop($id_lang, $page_number = 0, $nb_products = 10, $count = false, - $order_by = null, $order_way = null, $beginning = false, $ending = false, Context $context = null) - { - if (!Validate::isBool($count)) - die(Tools::displayError()); + /** + * Get prices drop + * + * @param int $id_lang Language id + * @param int $pageNumber Start from (optional) + * @param int $nbProducts Number of products to return (optional) + * @param bool $count Only in order to get total number (optional) + * @return array Prices drop + */ + public static function getPricesDrop($id_lang, $page_number = 0, $nb_products = 10, $count = false, + $order_by = null, $order_way = null, $beginning = false, $ending = false, Context $context = null) + { + if (!Validate::isBool($count)) { + die(Tools::displayError()); + } - if (!$context) $context = Context::getContext(); - if ($page_number < 0) $page_number = 0; - if ($nb_products < 1) $nb_products = 10; - if (empty($order_by) || $order_by == 'position') $order_by = 'price'; - if (empty($order_way)) $order_way = 'DESC'; - if ($order_by == 'id_product' || $order_by == 'price' || $order_by == 'date_add' || $order_by == 'date_upd') - $order_by_prefix = 'p'; - elseif ($order_by == 'name') - $order_by_prefix = 'pl'; - if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) - die (Tools::displayError()); - $current_date = date('Y-m-d H:i:s'); - $ids_product = Product::_getProductIdByDate((!$beginning ? $current_date : $beginning), (!$ending ? $current_date : $ending), $context); + if (!$context) { + $context = Context::getContext(); + } + if ($page_number < 0) { + $page_number = 0; + } + if ($nb_products < 1) { + $nb_products = 10; + } + if (empty($order_by) || $order_by == 'position') { + $order_by = 'price'; + } + if (empty($order_way)) { + $order_way = 'DESC'; + } + if ($order_by == 'id_product' || $order_by == 'price' || $order_by == 'date_add' || $order_by == 'date_upd') { + $order_by_prefix = 'p'; + } elseif ($order_by == 'name') { + $order_by_prefix = 'pl'; + } + if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) { + die(Tools::displayError()); + } + $current_date = date('Y-m-d H:i:s'); + $ids_product = Product::_getProductIdByDate((!$beginning ? $current_date : $beginning), (!$ending ? $current_date : $ending), $context); - $tab_id_product = array(); - foreach ($ids_product as $product) - if (is_array($product)) - $tab_id_product[] = (int)$product['id_product']; - else - $tab_id_product[] = (int)$product; + $tab_id_product = array(); + foreach ($ids_product as $product) { + if (is_array($product)) { + $tab_id_product[] = (int)$product['id_product']; + } else { + $tab_id_product[] = (int)$product; + } + } - $front = true; - if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) - $front = false; + $front = true; + if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) { + $front = false; + } - $sql_groups = ''; - if (Group::isFeatureActive()) - { - $groups = FrontController::getCurrentCustomerGroups(); - $sql_groups = ' AND EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp + $sql_groups = ''; + if (Group::isFeatureActive()) { + $groups = FrontController::getCurrentCustomerGroups(); + $sql_groups = ' AND EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.id_category = cg.id_category AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1').') WHERE cp.`id_product` = p.`id_product`)'; - } + } - if ($count) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + if ($count) { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(DISTINCT p.`id_product`) FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' @@ -2393,17 +2510,16 @@ class ProductCore extends ObjectModel '.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').' '.((!$beginning && !$ending) ? 'AND p.`id_product` IN('.((is_array($tab_id_product) && count($tab_id_product)) ? implode(', ', $tab_id_product) : 0).')' : '').' '.$sql_groups); - } + } - if (strpos($order_by, '.') > 0) - { - $order_by = explode('.', $order_by); - $order_by = pSQL($order_by[0]).'.`'.pSQL($order_by[1]).'`'; - } + if (strpos($order_by, '.') > 0) { + $order_by = explode('.', $order_by); + $order_by = pSQL($order_by[0]).'.`'.pSQL($order_by[1]).'`'; + } - $sql = ' + $sql = ' SELECT - p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description`, pl.`description_short`, + p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description`, pl.`description_short`, pl.`available_now`, pl.`available_later`, IFNULL(product_attribute_shop.id_product_attribute, 0) id_product_attribute, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, image_shop.`id_image` id_image, il.`legend`, m.`name` AS manufacturer_name, @@ -2436,834 +2552,873 @@ class ProductCore extends ObjectModel ORDER BY '.(isset($order_by_prefix) ? pSQL($order_by_prefix).'.' : '').pSQL($order_by).' '.pSQL($order_way).' LIMIT '.(int)($page_number * $nb_products).', '.(int)$nb_products; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - if (!$result) - return false; + if (!$result) { + return false; + } - if ($order_by == 'price') - Tools::orderbyPrice($result, $order_way); + if ($order_by == 'price') { + Tools::orderbyPrice($result, $order_way); + } - return Product::getProductsProperties($id_lang, $result); - } + return Product::getProductsProperties($id_lang, $result); + } - /** - * getProductCategories return an array of categories which this product belongs to - * - * @return array of categories - */ - public static function getProductCategories($id_product = '') - { - $cache_id = 'Product::getProductCategories_'.(int)$id_product; - if (!Cache::isStored($cache_id)) - { - $ret = array(); + /** + * getProductCategories return an array of categories which this product belongs to + * + * @return array of categories + */ + public static function getProductCategories($id_product = '') + { + $cache_id = 'Product::getProductCategories_'.(int)$id_product; + if (!Cache::isStored($cache_id)) { + $ret = array(); - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT `id_category` FROM `'._DB_PREFIX_.'category_product` WHERE `id_product` = '.(int)$id_product - ); + ); - if ($row) - foreach ($row as $val) - $ret[] = $val['id_category']; - Cache::store($cache_id, $ret); - return $ret; - } - return Cache::retrieve($cache_id); - } + if ($row) { + foreach ($row as $val) { + $ret[] = $val['id_category']; + } + } + Cache::store($cache_id, $ret); + return $ret; + } + return Cache::retrieve($cache_id); + } - public static function getProductCategoriesFull($id_product = '', $id_lang = null) - { - if (!$id_lang) - $id_lang = Context::getContext()->language->id; + public static function getProductCategoriesFull($id_product = '', $id_lang = null) + { + if (!$id_lang) { + $id_lang = Context::getContext()->language->id; + } - $ret = array(); - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $ret = array(); + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT cp.`id_category`, cl.`name`, cl.`link_rewrite` FROM `'._DB_PREFIX_.'category_product` cp LEFT JOIN `'._DB_PREFIX_.'category` c ON (c.id_category = cp.id_category) LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (cp.`id_category` = cl.`id_category`'.Shop::addSqlRestrictionOnLang('cl').') '.Shop::addSqlAssociation('category', 'c').' WHERE cp.`id_product` = '.(int)$id_product.' AND cl.`id_lang` = '.(int)$id_lang - ); + ); - foreach ($row as $val) - $ret[$val['id_category']] = $val; + foreach ($row as $val) { + $ret[$val['id_category']] = $val; + } - return $ret; - } + return $ret; + } - /** - * getCategories return an array of categories which this product belongs to - * - * @return array of categories - */ - public function getCategories() - { - return Product::getProductCategories($this->id); - } + /** + * getCategories return an array of categories which this product belongs to + * + * @return array of categories + */ + public function getCategories() + { + return Product::getProductCategories($this->id); + } - /** - * Gets carriers assigned to the product - */ - public function getCarriers() - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * Gets carriers assigned to the product + */ + public function getCarriers() + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT c.* FROM `'._DB_PREFIX_.'product_carrier` pc INNER JOIN `'._DB_PREFIX_.'carrier` c ON (c.`id_reference` = pc.`id_carrier_reference` AND c.`deleted` = 0) WHERE pc.`id_product` = '.(int)$this->id.' AND pc.`id_shop` = '.(int)$this->id_shop); - } + } - /** - * Sets carriers assigned to the product - */ - public function setCarriers($carrier_list) - { - $data = array(); + /** + * Sets carriers assigned to the product + */ + public function setCarriers($carrier_list) + { + $data = array(); - foreach ($carrier_list as $carrier) - { - $data[] = array( - 'id_product' => (int)$this->id, - 'id_carrier_reference' => (int)$carrier, - 'id_shop' => (int)$this->id_shop - ); - } - Db::getInstance()->execute( - 'DELETE FROM `'._DB_PREFIX_.'product_carrier` + foreach ($carrier_list as $carrier) { + $data[] = array( + 'id_product' => (int)$this->id, + 'id_carrier_reference' => (int)$carrier, + 'id_shop' => (int)$this->id_shop + ); + } + Db::getInstance()->execute( + 'DELETE FROM `'._DB_PREFIX_.'product_carrier` WHERE id_product = '.(int)$this->id.' AND id_shop = '.(int)$this->id_shop - ); + ); - $unique_array = array(); - foreach ($data as $sub_array) - if (!in_array($sub_array, $unique_array)) - $unique_array[] = $sub_array; + $unique_array = array(); + foreach ($data as $sub_array) { + if (!in_array($sub_array, $unique_array)) { + $unique_array[] = $sub_array; + } + } - if (count($unique_array)) - Db::getInstance()->insert('product_carrier', $unique_array, false, true, Db::INSERT_IGNORE); - } + if (count($unique_array)) { + Db::getInstance()->insert('product_carrier', $unique_array, false, true, Db::INSERT_IGNORE); + } + } - /** - * Get product images and legends - * - * @param int $id_lang Language id for multilingual legends - * @return array Product images and legends - */ - public function getImages($id_lang, Context $context = null) - { - return Db::getInstance()->executeS(' + /** + * Get product images and legends + * + * @param int $id_lang Language id for multilingual legends + * @return array Product images and legends + */ + public function getImages($id_lang, Context $context = null) + { + return Db::getInstance()->executeS(' SELECT image_shop.`cover`, i.`id_image`, il.`legend`, i.`position` FROM `'._DB_PREFIX_.'image` i '.Shop::addSqlAssociation('image', 'i').' LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.') WHERE i.`id_product` = '.(int)$this->id.' ORDER BY `position`' - ); - } + ); + } - /** - * Get product cover image - * - * @return array Product cover image - */ - public static function getCover($id_product, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - $cache_id = 'Product::getCover_'.(int)$id_product.'-'.(int)$context->shop->id; - if (!Cache::isStored($cache_id)) - { - $sql = 'SELECT image_shop.`id_image` + /** + * Get product cover image + * + * @return array Product cover image + */ + public static function getCover($id_product, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + $cache_id = 'Product::getCover_'.(int)$id_product.'-'.(int)$context->shop->id; + if (!Cache::isStored($cache_id)) { + $sql = 'SELECT image_shop.`id_image` FROM `'._DB_PREFIX_.'image` i '.Shop::addSqlAssociation('image', 'i').' WHERE i.`id_product` = '.(int)$id_product.' AND image_shop.`cover` = 1'; - $result = Db::getInstance()->getRow($sql); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + $result = Db::getInstance()->getRow($sql); + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Returns product price - * - * @param int $id_product Product id - * @param bool $usetax With taxes or not (optional) - * @param int|null $id_product_attribute Product attribute id (optional). - * If set to false, do not apply the combination price impact. - * NULL does apply the default combination price impact. - * @param int $decimals Number of decimals (optional) - * @param int|null $divisor Useful when paying many time without fees (optional) - * @param bool $only_reduc Returns only the reduction amount - * @param bool $usereduc Set if the returned amount will include reduction - * @param int $quantity Required for quantity discount application (default value: 1) - * @param bool $force_associated_tax DEPRECATED - NOT USED Force to apply the associated tax. - * Only works when the parameter $usetax is true - * @param int|null $id_customer Customer ID (for customer group reduction) - * @param int|null $id_cart Cart ID. Required when the cookie is not accessible - * (e.g., inside a payment module, a cron task...) - * @param int|null $id_address Customer address ID. Required for price (tax included) - * calculation regarding the guest localization - * @param null $specific_price_output If a specific price applies regarding the previous parameters, - * this variable is filled with the corresponding SpecificPrice object - * @param bool $with_ecotax Insert ecotax in price output. - * @param bool $use_group_reduction - * @param Context $context - * @param bool $use_customer_price - * @return float Product price - */ - public static function getPriceStatic($id_product, $usetax = true, $id_product_attribute = null, $decimals = 6, $divisor = null, - $only_reduc = false, $usereduc = true, $quantity = 1, $force_associated_tax = false, $id_customer = null, $id_cart = null, - $id_address = null, &$specific_price_output = null, $with_ecotax = true, $use_group_reduction = true, Context $context = null, - $use_customer_price = true) - { - if (!$context) - $context = Context::getContext(); + /** + * Returns product price + * + * @param int $id_product Product id + * @param bool $usetax With taxes or not (optional) + * @param int|null $id_product_attribute Product attribute id (optional). + * If set to false, do not apply the combination price impact. + * NULL does apply the default combination price impact. + * @param int $decimals Number of decimals (optional) + * @param int|null $divisor Useful when paying many time without fees (optional) + * @param bool $only_reduc Returns only the reduction amount + * @param bool $usereduc Set if the returned amount will include reduction + * @param int $quantity Required for quantity discount application (default value: 1) + * @param bool $force_associated_tax DEPRECATED - NOT USED Force to apply the associated tax. + * Only works when the parameter $usetax is true + * @param int|null $id_customer Customer ID (for customer group reduction) + * @param int|null $id_cart Cart ID. Required when the cookie is not accessible + * (e.g., inside a payment module, a cron task...) + * @param int|null $id_address Customer address ID. Required for price (tax included) + * calculation regarding the guest localization + * @param null $specific_price_output If a specific price applies regarding the previous parameters, + * this variable is filled with the corresponding SpecificPrice object + * @param bool $with_ecotax Insert ecotax in price output. + * @param bool $use_group_reduction + * @param Context $context + * @param bool $use_customer_price + * @return float Product price + */ + public static function getPriceStatic($id_product, $usetax = true, $id_product_attribute = null, $decimals = 6, $divisor = null, + $only_reduc = false, $usereduc = true, $quantity = 1, $force_associated_tax = false, $id_customer = null, $id_cart = null, + $id_address = null, &$specific_price_output = null, $with_ecotax = true, $use_group_reduction = true, Context $context = null, + $use_customer_price = true) + { + if (!$context) { + $context = Context::getContext(); + } - $cur_cart = $context->cart; + $cur_cart = $context->cart; - if ($divisor !== null) - Tools::displayParameterAsDeprecated('divisor'); + if ($divisor !== null) { + Tools::displayParameterAsDeprecated('divisor'); + } - if (!Validate::isBool($usetax) || !Validate::isUnsignedId($id_product)) - die(Tools::displayError()); + if (!Validate::isBool($usetax) || !Validate::isUnsignedId($id_product)) { + die(Tools::displayError()); + } - // Initializations - $id_group = null; - if ($id_customer) - $id_group = Customer::getDefaultGroupId((int)$id_customer); - if (!$id_group) - $id_group = (int)Group::getCurrent()->id; + // Initializations + $id_group = null; + if ($id_customer) { + $id_group = Customer::getDefaultGroupId((int)$id_customer); + } + if (!$id_group) { + $id_group = (int)Group::getCurrent()->id; + } - // If there is cart in context or if the specified id_cart is different from the context cart id - if (!is_object($cur_cart) || (Validate::isUnsignedInt($id_cart) && $id_cart && $cur_cart->id != $id_cart)) - { - /* - * When a user (e.g., guest, customer, Google...) is on PrestaShop, he has already its cart as the global (see /init.php) - * When a non-user calls directly this method (e.g., payment module...) is on PrestaShop, he does not have already it BUT knows the cart ID - * When called from the back office, cart ID can be inexistant - */ - if (!$id_cart && !isset($context->employee)) - die(Tools::displayError()); - $cur_cart = new Cart($id_cart); - // Store cart in context to avoid multiple instantiations in BO - if (!Validate::isLoadedObject($context->cart)) - $context->cart = $cur_cart; - } + // If there is cart in context or if the specified id_cart is different from the context cart id + if (!is_object($cur_cart) || (Validate::isUnsignedInt($id_cart) && $id_cart && $cur_cart->id != $id_cart)) { + /* + * When a user (e.g., guest, customer, Google...) is on PrestaShop, he has already its cart as the global (see /init.php) + * When a non-user calls directly this method (e.g., payment module...) is on PrestaShop, he does not have already it BUT knows the cart ID + * When called from the back office, cart ID can be inexistant + */ + if (!$id_cart && !isset($context->employee)) { + die(Tools::displayError()); + } + $cur_cart = new Cart($id_cart); + // Store cart in context to avoid multiple instantiations in BO + if (!Validate::isLoadedObject($context->cart)) { + $context->cart = $cur_cart; + } + } - $cart_quantity = 0; - if ((int)$id_cart) - { - $cache_id = 'Product::getPriceStatic_'.(int)$id_product.'-'.(int)$id_cart; - if (!Cache::isStored($cache_id) || ($cart_quantity = Cache::retrieve($cache_id) != (int)$quantity)) - { - $sql = 'SELECT SUM(`quantity`) + $cart_quantity = 0; + if ((int)$id_cart) { + $cache_id = 'Product::getPriceStatic_'.(int)$id_product.'-'.(int)$id_cart; + if (!Cache::isStored($cache_id) || ($cart_quantity = Cache::retrieve($cache_id) != (int)$quantity)) { + $sql = 'SELECT SUM(`quantity`) FROM `'._DB_PREFIX_.'cart_product` WHERE `id_product` = '.(int)$id_product.' AND `id_cart` = '.(int)$id_cart; - $cart_quantity = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); - Cache::store($cache_id, $cart_quantity); - } - else - $cart_quantity = Cache::retrieve($cache_id); - } + $cart_quantity = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); + Cache::store($cache_id, $cart_quantity); + } else { + $cart_quantity = Cache::retrieve($cache_id); + } + } - $id_currency = Validate::isLoadedObject($context->currency) ? (int)$context->currency->id : (int)Configuration::get('PS_CURRENCY_DEFAULT'); + $id_currency = Validate::isLoadedObject($context->currency) ? (int)$context->currency->id : (int)Configuration::get('PS_CURRENCY_DEFAULT'); - // retrieve address informations - $id_country = (int)$context->country->id; - $id_state = 0; - $zipcode = 0; + // retrieve address informations + $id_country = (int)$context->country->id; + $id_state = 0; + $zipcode = 0; - if (!$id_address && Validate::isLoadedObject($cur_cart)) - $id_address = $cur_cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; + if (!$id_address && Validate::isLoadedObject($cur_cart)) { + $id_address = $cur_cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; + } - if ($id_address) - { - $address_infos = Address::getCountryAndState($id_address); - if ($address_infos['id_country']) - { - $id_country = (int)$address_infos['id_country']; - $id_state = (int)$address_infos['id_state']; - $zipcode = $address_infos['postcode']; - } - } - elseif (isset($context->customer->geoloc_id_country)) - { - $id_country = (int)$context->customer->geoloc_id_country; - $id_state = (int)$context->customer->id_state; - $zipcode = $context->customer->postcode; - } + if ($id_address) { + $address_infos = Address::getCountryAndState($id_address); + if ($address_infos['id_country']) { + $id_country = (int)$address_infos['id_country']; + $id_state = (int)$address_infos['id_state']; + $zipcode = $address_infos['postcode']; + } + } elseif (isset($context->customer->geoloc_id_country)) { + $id_country = (int)$context->customer->geoloc_id_country; + $id_state = (int)$context->customer->id_state; + $zipcode = $context->customer->postcode; + } - if (Tax::excludeTaxeOption()) - $usetax = false; + if (Tax::excludeTaxeOption()) { + $usetax = false; + } - if ($usetax != false - && !empty($address_infos['vat_number']) - && $address_infos['id_country'] != Configuration::get('VATNUMBER_COUNTRY') - && Configuration::get('VATNUMBER_MANAGEMENT')) - $usetax = false; + if ($usetax != false + && !empty($address_infos['vat_number']) + && $address_infos['id_country'] != Configuration::get('VATNUMBER_COUNTRY') + && Configuration::get('VATNUMBER_MANAGEMENT')) { + $usetax = false; + } - if (is_null($id_customer) && Validate::isLoadedObject($context->customer)) - $id_customer = $context->customer->id; + if (is_null($id_customer) && Validate::isLoadedObject($context->customer)) { + $id_customer = $context->customer->id; + } - $return = Product::priceCalculation( - $context->shop->id, - $id_product, - $id_product_attribute, - $id_country, - $id_state, - $zipcode, - $id_currency, - $id_group, - $quantity, - $usetax, - $decimals, - $only_reduc, - $usereduc, - $with_ecotax, - $specific_price_output, - $use_group_reduction, - $id_customer, - $use_customer_price, - $id_cart, - $cart_quantity - ); + $return = Product::priceCalculation( + $context->shop->id, + $id_product, + $id_product_attribute, + $id_country, + $id_state, + $zipcode, + $id_currency, + $id_group, + $quantity, + $usetax, + $decimals, + $only_reduc, + $usereduc, + $with_ecotax, + $specific_price_output, + $use_group_reduction, + $id_customer, + $use_customer_price, + $id_cart, + $cart_quantity + ); - return $return; - } + return $return; + } - /** - * Price calculation / Get product price - * - * @param int $id_shop Shop id - * @param int $id_product Product id - * @param int $id_product_attribute Product attribute id - * @param int $id_country Country id - * @param int $id_state State id - * @param string $zipcode - * @param int $id_currency Currency id - * @param int $id_group Group id - * @param int $quantity Quantity Required for Specific prices : quantity discount application - * @param bool $use_tax with (1) or without (0) tax - * @param int $decimals Number of decimals returned - * @param bool $only_reduc Returns only the reduction amount - * @param bool $use_reduc Set if the returned amount will include reduction - * @param bool $with_ecotax insert ecotax in price output. - * @param null $specific_price If a specific price applies regarding the previous parameters, - * this variable is filled with the corresponding SpecificPrice object - * @param bool $use_group_reduction - * @param int $id_customer - * @param bool $use_customer_price - * @param int $id_cart - * @param int $real_quantity - * @return float Product price - **/ - public static function priceCalculation($id_shop, $id_product, $id_product_attribute, $id_country, $id_state, $zipcode, $id_currency, - $id_group, $quantity, $use_tax, $decimals, $only_reduc, $use_reduc, $with_ecotax, &$specific_price, $use_group_reduction, - $id_customer = 0, $use_customer_price = true, $id_cart = 0, $real_quantity = 0) - { - static $address = null; - static $context = null; + /** + * Price calculation / Get product price + * + * @param int $id_shop Shop id + * @param int $id_product Product id + * @param int $id_product_attribute Product attribute id + * @param int $id_country Country id + * @param int $id_state State id + * @param string $zipcode + * @param int $id_currency Currency id + * @param int $id_group Group id + * @param int $quantity Quantity Required for Specific prices : quantity discount application + * @param bool $use_tax with (1) or without (0) tax + * @param int $decimals Number of decimals returned + * @param bool $only_reduc Returns only the reduction amount + * @param bool $use_reduc Set if the returned amount will include reduction + * @param bool $with_ecotax insert ecotax in price output. + * @param null $specific_price If a specific price applies regarding the previous parameters, + * this variable is filled with the corresponding SpecificPrice object + * @param bool $use_group_reduction + * @param int $id_customer + * @param bool $use_customer_price + * @param int $id_cart + * @param int $real_quantity + * @return float Product price + **/ + public static function priceCalculation($id_shop, $id_product, $id_product_attribute, $id_country, $id_state, $zipcode, $id_currency, + $id_group, $quantity, $use_tax, $decimals, $only_reduc, $use_reduc, $with_ecotax, &$specific_price, $use_group_reduction, + $id_customer = 0, $use_customer_price = true, $id_cart = 0, $real_quantity = 0) + { + static $address = null; + static $context = null; - if ($address === null) - $address = new Address(); + if ($address === null) { + $address = new Address(); + } - if ($context == null) - $context = Context::getContext()->cloneContext(); + if ($context == null) { + $context = Context::getContext()->cloneContext(); + } - if ($id_shop !== null && $context->shop->id != (int)$id_shop) - $context->shop = new Shop((int)$id_shop); + if ($id_shop !== null && $context->shop->id != (int)$id_shop) { + $context->shop = new Shop((int)$id_shop); + } - if (!$use_customer_price) - $id_customer = 0; + if (!$use_customer_price) { + $id_customer = 0; + } - if ($id_product_attribute === null) - $id_product_attribute = Product::getDefaultAttribute($id_product); + if ($id_product_attribute === null) { + $id_product_attribute = Product::getDefaultAttribute($id_product); + } - $cache_id = (int)$id_product.'-'.(int)$id_shop.'-'.(int)$id_currency.'-'.(int)$id_country.'-'.$id_state.'-'.$zipcode.'-'.(int)$id_group. - '-'.(int)$quantity.'-'.(int)$id_product_attribute. - '-'.(int)$with_ecotax.'-'.(int)$id_customer.'-'.(int)$use_group_reduction.'-'.(int)$id_cart.'-'.(int)$real_quantity. - '-'.($only_reduc?'1':'0').'-'.($use_reduc?'1':'0').'-'.($use_tax?'1':'0').'-'.(int)$decimals; + $cache_id = (int)$id_product.'-'.(int)$id_shop.'-'.(int)$id_currency.'-'.(int)$id_country.'-'.$id_state.'-'.$zipcode.'-'.(int)$id_group. + '-'.(int)$quantity.'-'.(int)$id_product_attribute. + '-'.(int)$with_ecotax.'-'.(int)$id_customer.'-'.(int)$use_group_reduction.'-'.(int)$id_cart.'-'.(int)$real_quantity. + '-'.($only_reduc?'1':'0').'-'.($use_reduc?'1':'0').'-'.($use_tax?'1':'0').'-'.(int)$decimals; - // reference parameter is filled before any returns - $specific_price = SpecificPrice::getSpecificPrice( - (int)$id_product, - $id_shop, - $id_currency, - $id_country, - $id_group, - $quantity, - $id_product_attribute, - $id_customer, - $id_cart, - $real_quantity - ); + // reference parameter is filled before any returns + $specific_price = SpecificPrice::getSpecificPrice( + (int)$id_product, + $id_shop, + $id_currency, + $id_country, + $id_group, + $quantity, + $id_product_attribute, + $id_customer, + $id_cart, + $real_quantity + ); - if (isset(self::$_prices[$cache_id])) - return self::$_prices[$cache_id]; + if (isset(self::$_prices[$cache_id])) { + return self::$_prices[$cache_id]; + } - // fetch price & attribute price - $cache_id_2 = $id_product.'-'.$id_shop; - if (!isset(self::$_pricesLevel2[$cache_id_2])) - { - $sql = new DbQuery(); - $sql->select('product_shop.`price`, product_shop.`ecotax`'); - $sql->from('product', 'p'); - $sql->innerJoin('product_shop', 'product_shop', '(product_shop.id_product=p.id_product AND product_shop.id_shop = '.(int)$id_shop.')'); - $sql->where('p.`id_product` = '.(int)$id_product); - if (Combination::isFeatureActive()) - { - $sql->select('IFNULL(product_attribute_shop.id_product_attribute,0) id_product_attribute, product_attribute_shop.`price` AS attribute_price, product_attribute_shop.default_on'); - $sql->leftJoin('product_attribute_shop', 'product_attribute_shop', '(product_attribute_shop.id_product = p.id_product AND product_attribute_shop.id_shop = '.(int)$id_shop.')'); - } - else - $sql->select('0 as id_product_attribute'); + // fetch price & attribute price + $cache_id_2 = $id_product.'-'.$id_shop; + if (!isset(self::$_pricesLevel2[$cache_id_2])) { + $sql = new DbQuery(); + $sql->select('product_shop.`price`, product_shop.`ecotax`'); + $sql->from('product', 'p'); + $sql->innerJoin('product_shop', 'product_shop', '(product_shop.id_product=p.id_product AND product_shop.id_shop = '.(int)$id_shop.')'); + $sql->where('p.`id_product` = '.(int)$id_product); + if (Combination::isFeatureActive()) { + $sql->select('IFNULL(product_attribute_shop.id_product_attribute,0) id_product_attribute, product_attribute_shop.`price` AS attribute_price, product_attribute_shop.default_on'); + $sql->leftJoin('product_attribute_shop', 'product_attribute_shop', '(product_attribute_shop.id_product = p.id_product AND product_attribute_shop.id_shop = '.(int)$id_shop.')'); + } else { + $sql->select('0 as id_product_attribute'); + } - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - if (is_array($res) && count($res)) - foreach ($res as $row) - { - $array_tmp = array( - 'price' => $row['price'], - 'ecotax' => $row['ecotax'], - 'attribute_price' => (isset($row['attribute_price']) ? $row['attribute_price'] : null) - ); - self::$_pricesLevel2[$cache_id_2][(int)$row['id_product_attribute']] = $array_tmp; + if (is_array($res) && count($res)) { + foreach ($res as $row) { + $array_tmp = array( + 'price' => $row['price'], + 'ecotax' => $row['ecotax'], + 'attribute_price' => (isset($row['attribute_price']) ? $row['attribute_price'] : null) + ); + self::$_pricesLevel2[$cache_id_2][(int)$row['id_product_attribute']] = $array_tmp; - if (isset($row['default_on']) && $row['default_on'] == 1) - self::$_pricesLevel2[$cache_id_2][0] = $array_tmp; - } - } + if (isset($row['default_on']) && $row['default_on'] == 1) { + self::$_pricesLevel2[$cache_id_2][0] = $array_tmp; + } + } + } + } - if (!isset(self::$_pricesLevel2[$cache_id_2][(int)$id_product_attribute])) - return; + if (!isset(self::$_pricesLevel2[$cache_id_2][(int)$id_product_attribute])) { + return; + } - $result = self::$_pricesLevel2[$cache_id_2][(int)$id_product_attribute]; + $result = self::$_pricesLevel2[$cache_id_2][(int)$id_product_attribute]; - if (!$specific_price || $specific_price['price'] < 0) - $price = (float)$result['price']; - else - $price = (float)$specific_price['price']; - // convert only if the specific price is in the default currency (id_currency = 0) - if (!$specific_price || !($specific_price['price'] >= 0 && $specific_price['id_currency'])) - $price = Tools::convertPrice($price, $id_currency); + if (!$specific_price || $specific_price['price'] < 0) { + $price = (float)$result['price']; + } else { + $price = (float)$specific_price['price']; + } + // convert only if the specific price is in the default currency (id_currency = 0) + if (!$specific_price || !($specific_price['price'] >= 0 && $specific_price['id_currency'])) { + $price = Tools::convertPrice($price, $id_currency); + } - // Attribute price - if (is_array($result) && (!$specific_price || !$specific_price['id_product_attribute'] || $specific_price['price'] < 0)) - { - $attribute_price = Tools::convertPrice($result['attribute_price'] !== null ? (float)$result['attribute_price'] : 0, $id_currency); - // If you want the default combination, please use NULL value instead - if ($id_product_attribute !== false) - $price += $attribute_price; - } + // Attribute price + if (is_array($result) && (!$specific_price || !$specific_price['id_product_attribute'] || $specific_price['price'] < 0)) { + $attribute_price = Tools::convertPrice($result['attribute_price'] !== null ? (float)$result['attribute_price'] : 0, $id_currency); + // If you want the default combination, please use NULL value instead + if ($id_product_attribute !== false) { + $price += $attribute_price; + } + } - // Tax - $address->id_country = $id_country; - $address->id_state = $id_state; - $address->postcode = $zipcode; + // Tax + $address->id_country = $id_country; + $address->id_state = $id_state; + $address->postcode = $zipcode; - $tax_manager = TaxManagerFactory::getManager($address, Product::getIdTaxRulesGroupByIdProduct((int)$id_product, $context)); - $product_tax_calculator = $tax_manager->getTaxCalculator(); + $tax_manager = TaxManagerFactory::getManager($address, Product::getIdTaxRulesGroupByIdProduct((int)$id_product, $context)); + $product_tax_calculator = $tax_manager->getTaxCalculator(); - // Add Tax - if ($use_tax) - $price = $product_tax_calculator->addTaxes($price); + // Add Tax + if ($use_tax) { + $price = $product_tax_calculator->addTaxes($price); + } - // Eco Tax - if (($result['ecotax'] || isset($result['attribute_ecotax'])) && $with_ecotax) - { - $ecotax = $result['ecotax']; - if (isset($result['attribute_ecotax']) && $result['attribute_ecotax'] > 0) - $ecotax = $result['attribute_ecotax']; + // Eco Tax + if (($result['ecotax'] || isset($result['attribute_ecotax'])) && $with_ecotax) { + $ecotax = $result['ecotax']; + if (isset($result['attribute_ecotax']) && $result['attribute_ecotax'] > 0) { + $ecotax = $result['attribute_ecotax']; + } - if ($id_currency) - $ecotax = Tools::convertPrice($ecotax, $id_currency); - if ($use_tax) - { - // reinit the tax manager for ecotax handling - $tax_manager = TaxManagerFactory::getManager( - $address, - (int)Configuration::get('PS_ECOTAX_TAX_RULES_GROUP_ID') - ); - $ecotax_tax_calculator = $tax_manager->getTaxCalculator(); - $price += $ecotax_tax_calculator->addTaxes($ecotax); - } - else - $price += $ecotax; - } + if ($id_currency) { + $ecotax = Tools::convertPrice($ecotax, $id_currency); + } + if ($use_tax) { + // reinit the tax manager for ecotax handling + $tax_manager = TaxManagerFactory::getManager( + $address, + (int)Configuration::get('PS_ECOTAX_TAX_RULES_GROUP_ID') + ); + $ecotax_tax_calculator = $tax_manager->getTaxCalculator(); + $price += $ecotax_tax_calculator->addTaxes($ecotax); + } else { + $price += $ecotax; + } + } - // Reduction - $specific_price_reduction = 0; - if (($only_reduc || $use_reduc) && $specific_price) - { - if ($specific_price['reduction_type'] == 'amount') - { - $reduction_amount = $specific_price['reduction']; + // Reduction + $specific_price_reduction = 0; + if (($only_reduc || $use_reduc) && $specific_price) { + if ($specific_price['reduction_type'] == 'amount') { + $reduction_amount = $specific_price['reduction']; - if (!$specific_price['id_currency']) - $reduction_amount = Tools::convertPrice($reduction_amount, $id_currency); + if (!$specific_price['id_currency']) { + $reduction_amount = Tools::convertPrice($reduction_amount, $id_currency); + } - $specific_price_reduction = $reduction_amount; + $specific_price_reduction = $reduction_amount; - // Adjust taxes if required + // Adjust taxes if required - if (!$use_tax && $specific_price['reduction_tax']) - $specific_price_reduction = $product_tax_calculator->removeTaxes($specific_price_reduction); - if ($use_tax && !$specific_price['reduction_tax']) - $specific_price_reduction = $product_tax_calculator->addTaxes($specific_price_reduction); - } - else - $specific_price_reduction = $price * $specific_price['reduction']; - } + if (!$use_tax && $specific_price['reduction_tax']) { + $specific_price_reduction = $product_tax_calculator->removeTaxes($specific_price_reduction); + } + if ($use_tax && !$specific_price['reduction_tax']) { + $specific_price_reduction = $product_tax_calculator->addTaxes($specific_price_reduction); + } + } else { + $specific_price_reduction = $price * $specific_price['reduction']; + } + } - if ($use_reduc) - $price -= $specific_price_reduction; + if ($use_reduc) { + $price -= $specific_price_reduction; + } - // Group reduction - if ($use_group_reduction) - { - $reduction_from_category = GroupReduction::getValueForProduct($id_product, $id_group); - if ($reduction_from_category !== false) - $group_reduction = $price * (float)$reduction_from_category; - else // apply group reduction if there is no group reduction for this category - $group_reduction = (($reduc = Group::getReductionByIdGroup($id_group)) != 0) ? ($price * $reduc / 100) : 0; + // Group reduction + if ($use_group_reduction) { + $reduction_from_category = GroupReduction::getValueForProduct($id_product, $id_group); + if ($reduction_from_category !== false) { + $group_reduction = $price * (float)$reduction_from_category; + } else { // apply group reduction if there is no group reduction for this category + $group_reduction = (($reduc = Group::getReductionByIdGroup($id_group)) != 0) ? ($price * $reduc / 100) : 0; + } - $price -= $group_reduction; - } + $price -= $group_reduction; + } - if ($only_reduc) - return Tools::ps_round($specific_price_reduction, $decimals); + if ($only_reduc) { + return Tools::ps_round($specific_price_reduction, $decimals); + } - $price = Tools::ps_round($price, $decimals); + $price = Tools::ps_round($price, $decimals); - if ($price < 0) - $price = 0; + if ($price < 0) { + $price = 0; + } - self::$_prices[$cache_id] = $price; - return self::$_prices[$cache_id]; - } + self::$_prices[$cache_id] = $price; + return self::$_prices[$cache_id]; + } - public static function convertAndFormatPrice($price, $currency = false, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - if (!$currency) - $currency = $context->currency; - return Tools::displayPrice(Tools::convertPrice($price, $currency), $currency); - } + public static function convertAndFormatPrice($price, $currency = false, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + if (!$currency) { + $currency = $context->currency; + } + return Tools::displayPrice(Tools::convertPrice($price, $currency), $currency); + } - public static function isDiscounted($id_product, $quantity = 1, Context $context = null) - { - if (!$context) - $context = Context::getContext(); + public static function isDiscounted($id_product, $quantity = 1, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } - $id_group = $context->customer->id_default_group; - $cart_quantity = !$context->cart ? 0 : Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + $id_group = $context->customer->id_default_group; + $cart_quantity = !$context->cart ? 0 : Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT SUM(`quantity`) FROM `'._DB_PREFIX_.'cart_product` WHERE `id_product` = '.(int)$id_product.' AND `id_cart` = '.(int)$context->cart->id - ); - $quantity = $cart_quantity ? $cart_quantity : $quantity; + ); + $quantity = $cart_quantity ? $cart_quantity : $quantity; - $id_currency = (int)$context->currency->id; - $ids = Address::getCountryAndState((int)$context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); - $id_country = $ids['id_country'] ? (int)$ids['id_country'] : (int)Configuration::get('PS_COUNTRY_DEFAULT'); - return (bool)SpecificPrice::getSpecificPrice((int)$id_product, $context->shop->id, $id_currency, $id_country, $id_group, $quantity, null, 0, 0, $quantity); - } + $id_currency = (int)$context->currency->id; + $ids = Address::getCountryAndState((int)$context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); + $id_country = $ids['id_country'] ? (int)$ids['id_country'] : (int)Configuration::get('PS_COUNTRY_DEFAULT'); + return (bool)SpecificPrice::getSpecificPrice((int)$id_product, $context->shop->id, $id_currency, $id_country, $id_group, $quantity, null, 0, 0, $quantity); + } - /** - * Get product price - * Same as static function getPriceStatic, no need to specify product id - * - * @param bool $tax With taxes or not (optional) - * @param int $id_product_attribute Product attribute id (optional) - * @param int $decimals Number of decimals (optional) - * @param int $divisor Util when paying many time without fees (optional) - * @return float Product price in euros - */ - public function getPrice($tax = true, $id_product_attribute = null, $decimals = 6, - $divisor = null, $only_reduc = false, $usereduc = true, $quantity = 1) - { - return Product::getPriceStatic((int)$this->id, $tax, $id_product_attribute, $decimals, $divisor, $only_reduc, $usereduc, $quantity); - } + /** + * Get product price + * Same as static function getPriceStatic, no need to specify product id + * + * @param bool $tax With taxes or not (optional) + * @param int $id_product_attribute Product attribute id (optional) + * @param int $decimals Number of decimals (optional) + * @param int $divisor Util when paying many time without fees (optional) + * @return float Product price in euros + */ + public function getPrice($tax = true, $id_product_attribute = null, $decimals = 6, + $divisor = null, $only_reduc = false, $usereduc = true, $quantity = 1) + { + return Product::getPriceStatic((int)$this->id, $tax, $id_product_attribute, $decimals, $divisor, $only_reduc, $usereduc, $quantity); + } - public function getPublicPrice($tax = true, $id_product_attribute = null, $decimals = 6, - $divisor = null, $only_reduc = false, $usereduc = true, $quantity = 1) - { - $specific_price_output = null; - return Product::getPriceStatic((int)$this->id, $tax, $id_product_attribute, $decimals, $divisor, $only_reduc, $usereduc, $quantity, - false, null, null, null, $specific_price_output, true, true, null, false); - } + public function getPublicPrice($tax = true, $id_product_attribute = null, $decimals = 6, + $divisor = null, $only_reduc = false, $usereduc = true, $quantity = 1) + { + $specific_price_output = null; + return Product::getPriceStatic((int)$this->id, $tax, $id_product_attribute, $decimals, $divisor, $only_reduc, $usereduc, $quantity, + false, null, null, null, $specific_price_output, true, true, null, false); + } - public function getIdProductAttributeMostExpensive() - { - if (!Combination::isFeatureActive()) - return 0; + public function getIdProductAttributeMostExpensive() + { + if (!Combination::isFeatureActive()) { + return 0; + } - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT pa.`id_product_attribute` FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE pa.`id_product` = '.(int)$this->id.' ORDER BY product_attribute_shop.`price` DESC'); - return (isset($row['id_product_attribute']) && $row['id_product_attribute']) ? (int)$row['id_product_attribute'] : 0; - } + return (isset($row['id_product_attribute']) && $row['id_product_attribute']) ? (int)$row['id_product_attribute'] : 0; + } - public function getDefaultIdProductAttribute() - { - if (!Combination::isFeatureActive()) - return 0; + public function getDefaultIdProductAttribute() + { + if (!Combination::isFeatureActive()) { + return 0; + } - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT pa.`id_product_attribute` FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE pa.`id_product` = '.(int)$this->id.' AND product_attribute_shop.default_on = 1' - ); + ); - return (isset($row['id_product_attribute']) && $row['id_product_attribute']) ? (int)$row['id_product_attribute'] : 0; - } + return (isset($row['id_product_attribute']) && $row['id_product_attribute']) ? (int)$row['id_product_attribute'] : 0; + } - public function getPriceWithoutReduct($notax = false, $id_product_attribute = false, $decimals = 6) - { - return Product::getPriceStatic((int)$this->id, !$notax, $id_product_attribute, $decimals, null, false, false); - } + public function getPriceWithoutReduct($notax = false, $id_product_attribute = false, $decimals = 6) + { + return Product::getPriceStatic((int)$this->id, !$notax, $id_product_attribute, $decimals, null, false, false); + } - /** - * Display price with right format and currency - * - * @param array $params Params - * @param $smarty Smarty object - * @return string Price with right format and currency - */ - public static function convertPrice($params, &$smarty) - { - return Tools::displayPrice($params['price'], Context::getContext()->currency); - } + /** + * Display price with right format and currency + * + * @param array $params Params + * @param $smarty Smarty object + * @return string Price with right format and currency + */ + public static function convertPrice($params, &$smarty) + { + return Tools::displayPrice($params['price'], Context::getContext()->currency); + } - /** - * Convert price with currency - * - * @param array $params - * @param object $smarty DEPRECATED - * @return string Ambigous <string, mixed, Ambigous <number, string>> - */ - public static function convertPriceWithCurrency($params, &$smarty) - { - return Tools::displayPrice($params['price'], $params['currency'], false); - } + /** + * Convert price with currency + * + * @param array $params + * @param object $smarty DEPRECATED + * @return string Ambigous <string, mixed, Ambigous <number, string>> + */ + public static function convertPriceWithCurrency($params, &$smarty) + { + return Tools::displayPrice($params['price'], $params['currency'], false); + } - public static function displayWtPrice($params, &$smarty) - { - return Tools::displayPrice($params['p'], Context::getContext()->currency); - } + public static function displayWtPrice($params, &$smarty) + { + return Tools::displayPrice($params['p'], Context::getContext()->currency); + } - /** - * Display WT price with currency - * - * @param array $params - * @param Smarty $smarty DEPRECATED - * @return string Ambigous <string, mixed, Ambigous <number, string>> - */ - public static function displayWtPriceWithCurrency($params, &$smarty) - { - return Tools::displayPrice($params['price'], $params['currency'], false); - } + /** + * Display WT price with currency + * + * @param array $params + * @param Smarty $smarty DEPRECATED + * @return string Ambigous <string, mixed, Ambigous <number, string>> + */ + public static function displayWtPriceWithCurrency($params, &$smarty) + { + return Tools::displayPrice($params['price'], $params['currency'], false); + } - /** - * Get available product quantities - * - * @param int $id_product Product id - * @param int $id_product_attribute Product attribute id (optional) - * @return int Available quantities - */ - public static function getQuantity($id_product, $id_product_attribute = null, $cache_is_pack = null) - { - if ((int)$cache_is_pack || ($cache_is_pack === null && Pack::isPack((int)$id_product))) - { - if (!Pack::isInStock((int)$id_product)) - return 0; - } + /** + * Get available product quantities + * + * @param int $id_product Product id + * @param int $id_product_attribute Product attribute id (optional) + * @return int Available quantities + */ + public static function getQuantity($id_product, $id_product_attribute = null, $cache_is_pack = null) + { + if ((int)$cache_is_pack || ($cache_is_pack === null && Pack::isPack((int)$id_product))) { + if (!Pack::isInStock((int)$id_product)) { + return 0; + } + } - // @since 1.5.0 - return (StockAvailable::getQuantityAvailableByProduct($id_product, $id_product_attribute)); - } + // @since 1.5.0 + return (StockAvailable::getQuantityAvailableByProduct($id_product, $id_product_attribute)); + } - /** - * Create JOIN query with 'stock_available' table - * - * @param string $productAlias Alias of product table - * @param string|int $productAttribute If string : alias of PA table ; if int : value of PA ; if null : nothing about PA - * @param bool $innerJoin LEFT JOIN or INNER JOIN - * @param Shop $shop - * @return string - */ - public static function sqlStock($product_alias, $product_attribute = null, $inner_join = false, Shop $shop = null) - { - $id_shop = ($shop !== null ? (int)$shop->id : null); - $sql = (($inner_join) ? ' INNER ' : ' LEFT ') - .'JOIN '._DB_PREFIX_.'stock_available stock + /** + * Create JOIN query with 'stock_available' table + * + * @param string $productAlias Alias of product table + * @param string|int $productAttribute If string : alias of PA table ; if int : value of PA ; if null : nothing about PA + * @param bool $innerJoin LEFT JOIN or INNER JOIN + * @param Shop $shop + * @return string + */ + public static function sqlStock($product_alias, $product_attribute = null, $inner_join = false, Shop $shop = null) + { + $id_shop = ($shop !== null ? (int)$shop->id : null); + $sql = (($inner_join) ? ' INNER ' : ' LEFT ') + .'JOIN '._DB_PREFIX_.'stock_available stock ON (stock.id_product = '.pSQL($product_alias).'.id_product'; - if (!is_null($product_attribute)) - { - if (!Combination::isFeatureActive()) - $sql .= ' AND stock.id_product_attribute = 0'; - elseif (is_numeric($product_attribute)) - $sql .= ' AND stock.id_product_attribute = '.$product_attribute; - elseif (is_string($product_attribute)) - $sql .= ' AND stock.id_product_attribute = IFNULL(`'.bqSQL($product_attribute).'`.id_product_attribute, 0)'; - } + if (!is_null($product_attribute)) { + if (!Combination::isFeatureActive()) { + $sql .= ' AND stock.id_product_attribute = 0'; + } elseif (is_numeric($product_attribute)) { + $sql .= ' AND stock.id_product_attribute = '.$product_attribute; + } elseif (is_string($product_attribute)) { + $sql .= ' AND stock.id_product_attribute = IFNULL(`'.bqSQL($product_attribute).'`.id_product_attribute, 0)'; + } + } - $sql .= StockAvailable::addSqlShopRestriction(null, $id_shop, 'stock').' )'; + $sql .= StockAvailable::addSqlShopRestriction(null, $id_shop, 'stock').' )'; - return $sql; - } + return $sql; + } - /** - * @deprecated since 1.5.0 - * - * It's not possible to use this method with new stockManager and stockAvailable features - * Now this method do nothing - * - * @see StockManager if you want to manage real stock - * @see StockAvailable if you want to manage available quantities for sale on your shop(s) - * - * @deprecated 1.5.3.0 - * @return false - */ - public static function updateQuantity() - { - Tools::displayAsDeprecated(); + /** + * @deprecated since 1.5.0 + * + * It's not possible to use this method with new stockManager and stockAvailable features + * Now this method do nothing + * + * @see StockManager if you want to manage real stock + * @see StockAvailable if you want to manage available quantities for sale on your shop(s) + * + * @deprecated 1.5.3.0 + * @return false + */ + public static function updateQuantity() + { + Tools::displayAsDeprecated(); - return false; - } + return false; + } - /** - * @deprecated since 1.5.0 - * - * It's not possible to use this method with new stockManager and stockAvailable features - * Now this method do nothing - * - * @deprecated 1.5.3.0 - * @see StockManager if you want to manage real stock - * @see StockAvailable if you want to manage available quantities for sale on your shop(s) - * @return false - */ - public static function reinjectQuantities() - { - Tools::displayAsDeprecated(); + /** + * @deprecated since 1.5.0 + * + * It's not possible to use this method with new stockManager and stockAvailable features + * Now this method do nothing + * + * @deprecated 1.5.3.0 + * @see StockManager if you want to manage real stock + * @see StockAvailable if you want to manage available quantities for sale on your shop(s) + * @return false + */ + public static function reinjectQuantities() + { + Tools::displayAsDeprecated(); - return false; - } + return false; + } - public static function isAvailableWhenOutOfStock($out_of_stock) - { - // @TODO 1.5.0 Update of STOCK_MANAGEMENT & ORDER_OUT_OF_STOCK - static $ps_stock_management = null; - if ($ps_stock_management === null) - $ps_stock_management = Configuration::get('PS_STOCK_MANAGEMENT'); + public static function isAvailableWhenOutOfStock($out_of_stock) + { + // @TODO 1.5.0 Update of STOCK_MANAGEMENT & ORDER_OUT_OF_STOCK + static $ps_stock_management = null; + if ($ps_stock_management === null) { + $ps_stock_management = Configuration::get('PS_STOCK_MANAGEMENT'); + } - if (!$ps_stock_management) - return true; - else - { - static $ps_order_out_of_stock = null; - if ($ps_order_out_of_stock === null) - $ps_order_out_of_stock = Configuration::get('PS_ORDER_OUT_OF_STOCK'); + if (!$ps_stock_management) { + return true; + } else { + static $ps_order_out_of_stock = null; + if ($ps_order_out_of_stock === null) { + $ps_order_out_of_stock = Configuration::get('PS_ORDER_OUT_OF_STOCK'); + } - return (int)$out_of_stock == 2 ? (int)$ps_order_out_of_stock : (int)$out_of_stock; - } - } + return (int)$out_of_stock == 2 ? (int)$ps_order_out_of_stock : (int)$out_of_stock; + } + } - /** - * Check product availability - * - * @param int $qty Quantity desired - * @return bool True if product is available with this quantity - */ - public function checkQty($qty) - { - if (Pack::isPack((int)$this->id) && !Pack::isInStock((int)$this->id)) - return false; + /** + * Check product availability + * + * @param int $qty Quantity desired + * @return bool True if product is available with this quantity + */ + public function checkQty($qty) + { + if (Pack::isPack((int)$this->id) && !Pack::isInStock((int)$this->id)) { + return false; + } - if ($this->isAvailableWhenOutOfStock(StockAvailable::outOfStock($this->id))) - return true; + if ($this->isAvailableWhenOutOfStock(StockAvailable::outOfStock($this->id))) { + return true; + } - if (isset($this->id_product_attribute)) - $id_product_attribute = $this->id_product_attribute; - else - $id_product_attribute = 0; + if (isset($this->id_product_attribute)) { + $id_product_attribute = $this->id_product_attribute; + } else { + $id_product_attribute = 0; + } - return ($qty <= StockAvailable::getQuantityAvailableByProduct($this->id, $id_product_attribute)); - } + return ($qty <= StockAvailable::getQuantityAvailableByProduct($this->id, $id_product_attribute)); + } - /** - * Check if there is no default attribute and create it if not - */ - public function checkDefaultAttributes() - { - if (!$this->id) - return false; + /** + * Check if there is no default attribute and create it if not + */ + public function checkDefaultAttributes() + { + if (!$this->id) { + return false; + } - if (Db::getInstance()->getValue('SELECT COUNT(*) + if (Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE product_attribute_shop.`default_on` = 1 - AND pa.`id_product` = '.(int)$this->id) > Shop::getTotalShops(true)) - Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'product_attribute_shop product_attribute_shop, '._DB_PREFIX_.'product_attribute pa + AND pa.`id_product` = '.(int)$this->id) > Shop::getTotalShops(true)) { + Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'product_attribute_shop product_attribute_shop, '._DB_PREFIX_.'product_attribute pa SET product_attribute_shop.default_on=NULL, pa.default_on = NULL WHERE product_attribute_shop.id_product_attribute=pa.id_product_attribute AND pa.id_product='.(int)$this->id - .Shop::addSqlRestriction(false, 'product_attribute_shop')); + .Shop::addSqlRestriction(false, 'product_attribute_shop')); + } - $row = Db::getInstance()->getRow(' + $row = Db::getInstance()->getRow(' SELECT pa.id_product FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE product_attribute_shop.`default_on` = 1 AND pa.`id_product` = '.(int)$this->id - ); - if ($row) - return true; + ); + if ($row) { + return true; + } - $mini = Db::getInstance()->getRow(' + $mini = Db::getInstance()->getRow(' SELECT MIN(pa.id_product_attribute) as `id_attr` FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE pa.`id_product` = '.(int)$this->id - ); - if (!$mini) - return false; + ); + if (!$mini) { + return false; + } - if (!ObjectModel::updateMultishopTable('Combination', array('default_on' => 1), 'a.id_product_attribute = '.(int)$mini['id_attr'])) - return false; - return true; - } + if (!ObjectModel::updateMultishopTable('Combination', array('default_on' => 1), 'a.id_product_attribute = '.(int)$mini['id_attr'])) { + return false; + } + return true; + } - public static function getAttributesColorList(Array $products, $have_stock = true) - { - if (!count($products)) - return array(); + public static function getAttributesColorList(Array $products, $have_stock = true) + { + if (!count($products)) { + return array(); + } - $id_lang = Context::getContext()->language->id; + $id_lang = Context::getContext()->language->id; - $check_stock = !Configuration::get('PS_DISP_UNAVAILABLE_ATTR'); - if (!$res = Db::getInstance()->executeS(' + $check_stock = !Configuration::get('PS_DISP_UNAVAILABLE_ATTR'); + if (!$res = Db::getInstance()->executeS(' SELECT pa.`id_product`, a.`color`, pac.`id_product_attribute`, '.($check_stock ? 'SUM(IF(stock.`quantity` > 0, 1, 0))' : '0').' qty, a.`id_attribute`, al.`name`, IF(color = "", a.id_attribute, color) group_by FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa'). - ($check_stock ? Product::sqlStock('pa', 'pa') : '').' + ($check_stock ? Product::sqlStock('pa', 'pa') : '').' JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON (pac.`id_product_attribute` = product_attribute_shop.`id_product_attribute`) JOIN `'._DB_PREFIX_.'attribute` a ON (a.`id_attribute` = pac.`id_attribute`) JOIN `'._DB_PREFIX_.'attribute_lang` al ON (a.`id_attribute` = al.`id_attribute` AND al.`id_lang` = '.(int)$id_lang.') @@ -3272,33 +3427,35 @@ class ProductCore extends ObjectModel GROUP BY pa.`id_product`, a.`id_attribute`, `group_by` '.($check_stock ? 'HAVING qty > 0' : '').' ORDER BY a.`position` ASC;' - ) - ) - return false; + ) + ) { + return false; + } - $colors = array(); - foreach ($res as $row) - { - if (Tools::isEmpty($row['color']) && !@filemtime(_PS_COL_IMG_DIR_.$row['id_attribute'].'.jpg')) - continue; + $colors = array(); + foreach ($res as $row) { + if (Tools::isEmpty($row['color']) && !@filemtime(_PS_COL_IMG_DIR_.$row['id_attribute'].'.jpg')) { + continue; + } - $colors[(int)$row['id_product']][] = array('id_product_attribute' => (int)$row['id_product_attribute'], 'color' => $row['color'], 'id_product' => $row['id_product'], 'name' => $row['name'], 'id_attribute' => $row['id_attribute']); - } + $colors[(int)$row['id_product']][] = array('id_product_attribute' => (int)$row['id_product_attribute'], 'color' => $row['color'], 'id_product' => $row['id_product'], 'name' => $row['name'], 'id_attribute' => $row['id_attribute']); + } - return $colors; - } + return $colors; + } - /** - * Get all available attribute groups - * - * @param int $id_lang Language id - * @return array Attribute groups - */ - public function getAttributesGroups($id_lang) - { - if (!Combination::isFeatureActive()) - return array(); - $sql = 'SELECT ag.`id_attribute_group`, ag.`is_color_group`, agl.`name` AS group_name, agl.`public_name` AS public_group_name, + /** + * Get all available attribute groups + * + * @param int $id_lang Language id + * @return array Attribute groups + */ + public function getAttributesGroups($id_lang) + { + if (!Combination::isFeatureActive()) { + return array(); + } + $sql = 'SELECT ag.`id_attribute_group`, ag.`is_color_group`, agl.`name` AS group_name, agl.`public_name` AS public_group_name, a.`id_attribute`, al.`name` AS attribute_name, a.`color` AS attribute_color, product_attribute_shop.`id_product_attribute`, IFNULL(stock.quantity, 0) as quantity, product_attribute_shop.`price`, product_attribute_shop.`ecotax`, product_attribute_shop.`weight`, product_attribute_shop.`default_on`, pa.`reference`, product_attribute_shop.`unit_price_impact`, @@ -3317,39 +3474,39 @@ class ProductCore extends ObjectModel AND agl.`id_lang` = '.(int)$id_lang.' GROUP BY id_attribute_group, id_product_attribute ORDER BY ag.`position` ASC, a.`position` ASC, agl.`name` ASC'; - return Db::getInstance()->executeS($sql); - } + return Db::getInstance()->executeS($sql); + } - /** - * Delete product accessories - * - * @return mixed Deletion result - */ - public function deleteAccessories() - { - return Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'accessory` WHERE `id_product_1` = '.(int)$this->id); - } + /** + * Delete product accessories + * + * @return mixed Deletion result + */ + public function deleteAccessories() + { + return Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'accessory` WHERE `id_product_1` = '.(int)$this->id); + } - /** - * Delete product from other products accessories - * - * @return mixed Deletion result - */ - public function deleteFromAccessories() - { - return Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'accessory` WHERE `id_product_2` = '.(int)$this->id); - } + /** + * Delete product from other products accessories + * + * @return mixed Deletion result + */ + public function deleteFromAccessories() + { + return Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'accessory` WHERE `id_product_2` = '.(int)$this->id); + } - /** - * Get product accessories (only names) - * - * @param int $id_lang Language id - * @param int $id_product Product id - * @return array Product accessories - */ - public static function getAccessoriesLight($id_lang, $id_product) - { - return Db::getInstance()->executeS(' + /** + * Get product accessories (only names) + * + * @param int $id_lang Language id + * @param int $id_product Product id + * @return array Product accessories + */ + public static function getAccessoriesLight($id_lang, $id_product) + { + return Db::getInstance()->executeS(' SELECT p.`id_product`, p.`reference`, pl.`name` FROM `'._DB_PREFIX_.'accessory` LEFT JOIN `'._DB_PREFIX_.'product` p ON (p.`id_product`= `id_product_2`) @@ -3359,18 +3516,18 @@ class ProductCore extends ObjectModel AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').' ) WHERE `id_product_1` = '.(int)$id_product - ); - } + ); + } - /** - * Get product accessories - * - * @param int $id_lang Language id - * @return array Product accessories - */ - public function getAccessories($id_lang, $active = true) - { - $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description`, pl.`description_short`, pl.`link_rewrite`, + /** + * Get product accessories + * + * @param int $id_lang Language id + * @return array Product accessories + */ + public function getAccessories($id_lang, $active = true) + { + $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, pl.`available_now`, pl.`available_later`, image_shop.`id_image` id_image, il.`legend`, m.`name` as manufacturer_name, cl.`name` AS category_default, IFNULL(product_attribute_shop.id_product_attribute, 0) id_product_attribute, DATEDIFF( @@ -3399,131 +3556,144 @@ class ProductCore extends ObjectModel LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (p.`id_manufacturer`= m.`id_manufacturer`) '.Product::sqlStock('p', 0).' WHERE `id_product_1` = '.(int)$this->id. - ($active ? ' AND product_shop.`active` = 1 AND product_shop.`visibility` != \'none\'' : '').' + ($active ? ' AND product_shop.`active` = 1 AND product_shop.`visibility` != \'none\'' : '').' GROUP BY product_shop.id_product'; - if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql)) - return false; + if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql)) { + return false; + } - foreach ($result as &$row) - $row['id_product_attribute'] = Product::getDefaultAttribute((int)$row['id_product']); + foreach ($result as &$row) { + $row['id_product_attribute'] = Product::getDefaultAttribute((int)$row['id_product']); + } - return $this->getProductsProperties($id_lang, $result); - } + return $this->getProductsProperties($id_lang, $result); + } - public static function getAccessoryById($accessory_id) - { - return Db::getInstance()->getRow('SELECT `id_product`, `name` FROM `'._DB_PREFIX_.'product_lang` WHERE `id_product` = '.(int)$accessory_id); - } + public static function getAccessoryById($accessory_id) + { + return Db::getInstance()->getRow('SELECT `id_product`, `name` FROM `'._DB_PREFIX_.'product_lang` WHERE `id_product` = '.(int)$accessory_id); + } - /** - * Link accessories with product - * - * @param array $accessories_id Accessories ids - */ - public function changeAccessories($accessories_id) - { - foreach ($accessories_id as $id_product_2) - Db::getInstance()->insert('accessory', array( - 'id_product_1' => (int)$this->id, - 'id_product_2' => (int)$id_product_2 - )); - } + /** + * Link accessories with product + * + * @param array $accessories_id Accessories ids + */ + public function changeAccessories($accessories_id) + { + foreach ($accessories_id as $id_product_2) { + Db::getInstance()->insert('accessory', array( + 'id_product_1' => (int)$this->id, + 'id_product_2' => (int)$id_product_2 + )); + } + } - /** - * Add new feature to product - */ - public function addFeaturesCustomToDB($id_value, $lang, $cust) - { - $row = array('id_feature_value' => (int)$id_value, 'id_lang' => (int)$lang, 'value' => pSQL($cust)); - return Db::getInstance()->insert('feature_value_lang', $row); - } + /** + * Add new feature to product + */ + public function addFeaturesCustomToDB($id_value, $lang, $cust) + { + $row = array('id_feature_value' => (int)$id_value, 'id_lang' => (int)$lang, 'value' => pSQL($cust)); + return Db::getInstance()->insert('feature_value_lang', $row); + } - public function addFeaturesToDB($id_feature, $id_value, $cust = 0) - { - if ($cust) - { - $row = array('id_feature' => (int)$id_feature, 'custom' => 1); - Db::getInstance()->insert('feature_value', $row); - $id_value = Db::getInstance()->Insert_ID(); - } - $row = array('id_feature' => (int)$id_feature, 'id_product' => (int)$this->id, 'id_feature_value' => (int)$id_value); - Db::getInstance()->insert('feature_product', $row); - SpecificPriceRule::applyAllRules(array((int)$this->id)); - if ($id_value) - return ($id_value); - } + public function addFeaturesToDB($id_feature, $id_value, $cust = 0) + { + if ($cust) { + $row = array('id_feature' => (int)$id_feature, 'custom' => 1); + Db::getInstance()->insert('feature_value', $row); + $id_value = Db::getInstance()->Insert_ID(); + } + $row = array('id_feature' => (int)$id_feature, 'id_product' => (int)$this->id, 'id_feature_value' => (int)$id_value); + Db::getInstance()->insert('feature_product', $row); + SpecificPriceRule::applyAllRules(array((int)$this->id)); + if ($id_value) { + return ($id_value); + } + } - public static function addFeatureProductImport($id_product, $id_feature, $id_feature_value) - { - return Db::getInstance()->execute(' + public static function addFeatureProductImport($id_product, $id_feature, $id_feature_value) + { + return Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'feature_product` (`id_feature`, `id_product`, `id_feature_value`) VALUES ('.(int)$id_feature.', '.(int)$id_product.', '.(int)$id_feature_value.') ON DUPLICATE KEY UPDATE `id_feature_value` = '.(int)$id_feature_value - ); - } + ); + } - /** - * Select all features for the object - * - * @return array Array with feature product's data - */ - public function getFeatures() - { - return Product::getFeaturesStatic((int)$this->id); - } + /** + * Select all features for the object + * + * @return array Array with feature product's data + */ + public function getFeatures() + { + return Product::getFeaturesStatic((int)$this->id); + } - public static function getFeaturesStatic($id_product) - { - if (!Feature::isFeatureActive()) - return array(); - if (!array_key_exists($id_product, self::$_cacheFeatures)) - self::$_cacheFeatures[$id_product] = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getFeaturesStatic($id_product) + { + if (!Feature::isFeatureActive()) { + return array(); + } + if (!array_key_exists($id_product, self::$_cacheFeatures)) { + self::$_cacheFeatures[$id_product] = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT fp.id_feature, fp.id_product, fp.id_feature_value, custom FROM `'._DB_PREFIX_.'feature_product` fp LEFT JOIN `'._DB_PREFIX_.'feature_value` fv ON (fp.id_feature_value = fv.id_feature_value) WHERE `id_product` = '.(int)$id_product - ); - return self::$_cacheFeatures[$id_product]; - } + ); + } + return self::$_cacheFeatures[$id_product]; + } - public static function cacheProductsFeatures($product_ids) - { - if (!Feature::isFeatureActive()) - return; + public static function cacheProductsFeatures($product_ids) + { + if (!Feature::isFeatureActive()) { + return; + } - $product_implode = array(); - foreach ($product_ids as $id_product) - if ((int)$id_product && !array_key_exists($id_product, self::$_cacheFeatures)) - $product_implode[] = (int)$id_product; - if (!count($product_implode)) - return; + $product_implode = array(); + foreach ($product_ids as $id_product) { + if ((int)$id_product && !array_key_exists($id_product, self::$_cacheFeatures)) { + $product_implode[] = (int)$id_product; + } + } + if (!count($product_implode)) { + return; + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT id_feature, id_product, id_feature_value FROM `'._DB_PREFIX_.'feature_product` WHERE `id_product` IN ('.implode($product_implode, ',').')'); - foreach ($result as $row) - { - if (!array_key_exists($row['id_product'], self::$_cacheFeatures)) - self::$_cacheFeatures[$row['id_product']] = array(); - self::$_cacheFeatures[$row['id_product']][] = $row; - } - } + foreach ($result as $row) { + if (!array_key_exists($row['id_product'], self::$_cacheFeatures)) { + self::$_cacheFeatures[$row['id_product']] = array(); + } + self::$_cacheFeatures[$row['id_product']][] = $row; + } + } - public static function cacheFrontFeatures($product_ids, $id_lang) - { - if (!Feature::isFeatureActive()) - return; + public static function cacheFrontFeatures($product_ids, $id_lang) + { + if (!Feature::isFeatureActive()) { + return; + } - $product_implode = array(); - foreach ($product_ids as $id_product) - if ((int)$id_product && !array_key_exists($id_product.'-'.$id_lang, self::$_cacheFeatures)) - $product_implode[] = (int)$id_product; - if (!count($product_implode)) - return; + $product_implode = array(); + foreach ($product_ids as $id_product) { + if ((int)$id_product && !array_key_exists($id_product.'-'.$id_lang, self::$_cacheFeatures)) { + $product_implode[] = (int)$id_product; + } + } + if (!count($product_implode)) { + return; + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT id_product, name, value, pf.id_feature FROM '._DB_PREFIX_.'feature_product pf LEFT JOIN '._DB_PREFIX_.'feature_lang fl ON (fl.id_feature = pf.id_feature AND fl.id_lang = '.(int)$id_lang.') @@ -3533,688 +3703,709 @@ class ProductCore extends ObjectModel WHERE `id_product` IN ('.implode($product_implode, ',').') ORDER BY f.position ASC'); - foreach ($result as $row) - { - if (!array_key_exists($row['id_product'].'-'.$id_lang, self::$_frontFeaturesCache)) - self::$_frontFeaturesCache[$row['id_product'].'-'.$id_lang] = array(); - if (!isset(self::$_frontFeaturesCache[$row['id_product'].'-'.$id_lang][$row['id_feature']])) - self::$_frontFeaturesCache[$row['id_product'].'-'.$id_lang][$row['id_feature']] = $row; - } - } + foreach ($result as $row) { + if (!array_key_exists($row['id_product'].'-'.$id_lang, self::$_frontFeaturesCache)) { + self::$_frontFeaturesCache[$row['id_product'].'-'.$id_lang] = array(); + } + if (!isset(self::$_frontFeaturesCache[$row['id_product'].'-'.$id_lang][$row['id_feature']])) { + self::$_frontFeaturesCache[$row['id_product'].'-'.$id_lang][$row['id_feature']] = $row; + } + } + } - /** - * Admin panel product search - * - * @param int $id_lang Language id - * @param string $query Search query - * @return array Matching products - */ - public static function searchByName($id_lang, $query, Context $context = null) - { - if (!$context) - $context = Context::getContext(); + /** + * Admin panel product search + * + * @param int $id_lang Language id + * @param string $query Search query + * @return array Matching products + */ + public static function searchByName($id_lang, $query, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } - $sql = new DbQuery(); - $sql->select('p.`id_product`, pl.`name`, p.`ean13`, p.`upc`, p.`active`, p.`reference`, m.`name` AS manufacturer_name, stock.`quantity`, product_shop.advanced_stock_management, p.`customizable`'); - $sql->from('product', 'p'); - $sql->join(Shop::addSqlAssociation('product', 'p')); - $sql->leftJoin('product_lang', 'pl', ' + $sql = new DbQuery(); + $sql->select('p.`id_product`, pl.`name`, p.`ean13`, p.`upc`, p.`active`, p.`reference`, m.`name` AS manufacturer_name, stock.`quantity`, product_shop.advanced_stock_management, p.`customizable`'); + $sql->from('product', 'p'); + $sql->join(Shop::addSqlAssociation('product', 'p')); + $sql->leftJoin('product_lang', 'pl', ' p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl') - ); - $sql->leftJoin('manufacturer', 'm', 'm.`id_manufacturer` = p.`id_manufacturer`'); + ); + $sql->leftJoin('manufacturer', 'm', 'm.`id_manufacturer` = p.`id_manufacturer`'); - $where = 'pl.`name` LIKE \'%'.pSQL($query).'%\' + $where = 'pl.`name` LIKE \'%'.pSQL($query).'%\' OR p.`ean13` LIKE \'%'.pSQL($query).'%\' OR p.`upc` LIKE \'%'.pSQL($query).'%\' OR p.`reference` LIKE \'%'.pSQL($query).'%\' OR p.`supplier_reference` LIKE \'%'.pSQL($query).'%\' OR EXISTS(SELECT * FROM `'._DB_PREFIX_.'product_supplier` sp WHERE sp.`id_product` = p.`id_product` AND `product_supplier_reference` LIKE \'%'.pSQL($query).'%\')'; - $sql->orderBy('pl.`name` ASC'); + $sql->orderBy('pl.`name` ASC'); - if (Combination::isFeatureActive()) - { - $where .= ' OR EXISTS(SELECT * FROM `'._DB_PREFIX_.'product_attribute` `pa` WHERE pa.`id_product` = p.`id_product` AND (pa.`reference` LIKE \'%'.pSQL($query).'%\' + if (Combination::isFeatureActive()) { + $where .= ' OR EXISTS(SELECT * FROM `'._DB_PREFIX_.'product_attribute` `pa` WHERE pa.`id_product` = p.`id_product` AND (pa.`reference` LIKE \'%'.pSQL($query).'%\' OR pa.`supplier_reference` LIKE \'%'.pSQL($query).'%\' OR pa.`ean13` LIKE \'%'.pSQL($query).'%\' OR pa.`upc` LIKE \'%'.pSQL($query).'%\'))'; - } - $sql->where($where); - $sql->join(Product::sqlStock('p', 0)); + } + $sql->where($where); + $sql->join(Product::sqlStock('p', 0)); - $result = Db::getInstance()->executeS($sql); + $result = Db::getInstance()->executeS($sql); - if (!$result) - return false; + if (!$result) { + return false; + } - $results_array = array(); - foreach ($result as $row) - { - $row['price_tax_incl'] = Product::getPriceStatic($row['id_product'], true, null, 2); - $row['price_tax_excl'] = Product::getPriceStatic($row['id_product'], false, null, 2); - $results_array[] = $row; - } - return $results_array; - } + $results_array = array(); + foreach ($result as $row) { + $row['price_tax_incl'] = Product::getPriceStatic($row['id_product'], true, null, 2); + $row['price_tax_excl'] = Product::getPriceStatic($row['id_product'], false, null, 2); + $results_array[] = $row; + } + return $results_array; + } - /** - * Duplicate attributes when duplicating a product - * - * @param int $id_product_old Old product id - * @param int $id_product_new New product id - */ - public static function duplicateAttributes($id_product_old, $id_product_new) - { - $return = true; - $combination_images = array(); + /** + * Duplicate attributes when duplicating a product + * + * @param int $id_product_old Old product id + * @param int $id_product_new New product id + */ + public static function duplicateAttributes($id_product_old, $id_product_new) + { + $return = true; + $combination_images = array(); - $result = Db::getInstance()->executeS(' + $result = Db::getInstance()->executeS(' SELECT pa.*, product_attribute_shop.* FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE pa.`id_product` = '.(int)$id_product_old - ); - $combinations = array(); + ); + $combinations = array(); - foreach ($result as $row) - { - $id_product_attribute_old = (int)$row['id_product_attribute']; - if (!isset($combinations[$id_product_attribute_old])) - { - $id_combination = null; - $id_shop = null; - $result2 = Db::getInstance()->executeS(' + foreach ($result as $row) { + $id_product_attribute_old = (int)$row['id_product_attribute']; + if (!isset($combinations[$id_product_attribute_old])) { + $id_combination = null; + $id_shop = null; + $result2 = Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'product_attribute_combination` WHERE `id_product_attribute` = '.$id_product_attribute_old - ); - } - else - { - $id_combination = (int)$combinations[$id_product_attribute_old]; - $id_shop = (int)$row['id_shop']; - $context_old = Shop::getContext(); - $context_shop_id_old = Shop::getContextShopID(); - Shop::setContext(Shop::CONTEXT_SHOP, $id_shop); + ); + } else { + $id_combination = (int)$combinations[$id_product_attribute_old]; + $id_shop = (int)$row['id_shop']; + $context_old = Shop::getContext(); + $context_shop_id_old = Shop::getContextShopID(); + Shop::setContext(Shop::CONTEXT_SHOP, $id_shop); + } - } + $row['id_product'] = $id_product_new; + unset($row['id_product_attribute']); - $row['id_product'] = $id_product_new; - unset($row['id_product_attribute']); + $combination = new Combination($id_combination, null, $id_shop); + foreach ($row as $k => $v) { + $combination->$k = $v; + } + $return &= $combination->save(); - $combination = new Combination($id_combination, null, $id_shop); - foreach ($row as $k => $v) - $combination->$k = $v; - $return &= $combination->save(); + $id_product_attribute_new = (int)$combination->id; - $id_product_attribute_new = (int)$combination->id; + if ($result_images = Product::_getAttributeImageAssociations($id_product_attribute_old)) { + $combination_images['old'][$id_product_attribute_old] = $result_images; + $combination_images['new'][$id_product_attribute_new] = $result_images; + } - if ($result_images = Product::_getAttributeImageAssociations($id_product_attribute_old)) - { - $combination_images['old'][$id_product_attribute_old] = $result_images; - $combination_images['new'][$id_product_attribute_new] = $result_images; - } + if (!isset($combinations[$id_product_attribute_old])) { + $combinations[$id_product_attribute_old] = (int)$id_product_attribute_new; + foreach ($result2 as $row2) { + $row2['id_product_attribute'] = $id_product_attribute_new; + $return &= Db::getInstance()->insert('product_attribute_combination', $row2); + } + } else { + Shop::setContext($context_old, $context_shop_id_old); + } - if (!isset($combinations[$id_product_attribute_old])) - { - $combinations[$id_product_attribute_old] = (int)$id_product_attribute_new; - foreach ($result2 as $row2) - { - $row2['id_product_attribute'] = $id_product_attribute_new; - $return &= Db::getInstance()->insert('product_attribute_combination', $row2); - } - } - else - Shop::setContext($context_old, $context_shop_id_old); - - //Copy suppliers - $result3 = Db::getInstance()->executeS(' + //Copy suppliers + $result3 = Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'product_supplier` WHERE `id_product_attribute` = '.(int)$id_product_attribute_old.' AND `id_product` = '.(int)$id_product_old); - foreach ($result3 as $row3) - { - unset($row3['id_product_supplier']); - $row3['id_product'] = $id_product_new; - $row3['id_product_attribute'] = $id_product_attribute_new; - $return &= Db::getInstance()->insert('product_supplier', $row3); - } - } + foreach ($result3 as $row3) { + unset($row3['id_product_supplier']); + $row3['id_product'] = $id_product_new; + $row3['id_product_attribute'] = $id_product_attribute_new; + $return &= Db::getInstance()->insert('product_supplier', $row3); + } + } - $impacts = self::getAttributesImpacts($id_product_old); + $impacts = self::getAttributesImpacts($id_product_old); - if (is_array($impacts) && count($impacts)) - { - $impact_sql = 'INSERT INTO `'._DB_PREFIX_.'attribute_impact` (`id_product`, `id_attribute`, `weight`, `price`) VALUES '; + if (is_array($impacts) && count($impacts)) { + $impact_sql = 'INSERT INTO `'._DB_PREFIX_.'attribute_impact` (`id_product`, `id_attribute`, `weight`, `price`) VALUES '; - foreach ($impacts as $id_attribute => $impact) - $impact_sql .= '('.(int)$id_product_new.', '.(int)$id_attribute.', '.(float)$impacts[$id_attribute]['weight'].', ' - .(float)$impacts[$id_attribute]['price'].'),'; + foreach ($impacts as $id_attribute => $impact) { + $impact_sql .= '('.(int)$id_product_new.', '.(int)$id_attribute.', '.(float)$impacts[$id_attribute]['weight'].', ' + .(float)$impacts[$id_attribute]['price'].'),'; + } - $impact_sql = substr_replace($impact_sql, '', -1); - $impact_sql .= ' ON DUPLICATE KEY UPDATE `price` = VALUES(price), `weight` = VALUES(weight)'; + $impact_sql = substr_replace($impact_sql, '', -1); + $impact_sql .= ' ON DUPLICATE KEY UPDATE `price` = VALUES(price), `weight` = VALUES(weight)'; - Db::getInstance()->execute($impact_sql); - } + Db::getInstance()->execute($impact_sql); + } - return !$return ? false : $combination_images; - } + return !$return ? false : $combination_images; + } - public static function getAttributesImpacts($id_product) - { - $return = array(); - $result = Db::getInstance()->executeS( - 'SELECT ai.`id_attribute`, ai.`price`, ai.`weight` + public static function getAttributesImpacts($id_product) + { + $return = array(); + $result = Db::getInstance()->executeS( + 'SELECT ai.`id_attribute`, ai.`price`, ai.`weight` FROM `'._DB_PREFIX_.'attribute_impact` ai WHERE ai.`id_product` = '.(int)$id_product); - if (!$result) - return array(); - foreach ($result as $impact) - { - $return[$impact['id_attribute']]['price'] = (float)$impact['price']; - $return[$impact['id_attribute']]['weight'] = (float)$impact['weight']; - } - return $return; - } + if (!$result) { + return array(); + } + foreach ($result as $impact) { + $return[$impact['id_attribute']]['price'] = (float)$impact['price']; + $return[$impact['id_attribute']]['weight'] = (float)$impact['weight']; + } + return $return; + } - /** - * Get product attribute image associations - * @param int $id_product_attribute - * @return array - */ - public static function _getAttributeImageAssociations($id_product_attribute) - { - $combination_images = array(); - $data = Db::getInstance()->executeS(' + /** + * Get product attribute image associations + * @param int $id_product_attribute + * @return array + */ + public static function _getAttributeImageAssociations($id_product_attribute) + { + $combination_images = array(); + $data = Db::getInstance()->executeS(' SELECT `id_image` FROM `'._DB_PREFIX_.'product_attribute_image` WHERE `id_product_attribute` = '.(int)$id_product_attribute); - foreach ($data as $row) - $combination_images[] = (int)$row['id_image']; - return $combination_images; - } + foreach ($data as $row) { + $combination_images[] = (int)$row['id_image']; + } + return $combination_images; + } - public static function duplicateAccessories($id_product_old, $id_product_new) - { - $return = true; + public static function duplicateAccessories($id_product_old, $id_product_new) + { + $return = true; - $result = Db::getInstance()->executeS(' + $result = Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'accessory` WHERE `id_product_1` = '.(int)$id_product_old); - foreach ($result as $row) - { - $data = array( - 'id_product_1' => (int)$id_product_new, - 'id_product_2' => (int)$row['id_product_2']); - $return &= Db::getInstance()->insert('accessory', $data); - } - return $return; - } + foreach ($result as $row) { + $data = array( + 'id_product_1' => (int)$id_product_new, + 'id_product_2' => (int)$row['id_product_2']); + $return &= Db::getInstance()->insert('accessory', $data); + } + return $return; + } - public static function duplicateTags($id_product_old, $id_product_new) - { - $tags = Db::getInstance()->executeS('SELECT `id_tag`, `id_lang` FROM `'._DB_PREFIX_.'product_tag` WHERE `id_product` = '.(int)$id_product_old); - if (!Db::getInstance()->NumRows()) - return true; + public static function duplicateTags($id_product_old, $id_product_new) + { + $tags = Db::getInstance()->executeS('SELECT `id_tag`, `id_lang` FROM `'._DB_PREFIX_.'product_tag` WHERE `id_product` = '.(int)$id_product_old); + if (!Db::getInstance()->NumRows()) { + return true; + } - $data = array(); - foreach ($tags as $tag) - $data[] = array( - 'id_product' => (int)$id_product_new, - 'id_tag' => (int)$tag['id_tag'], - 'id_lang' => (int)$tag['id_lang'], - ); + $data = array(); + foreach ($tags as $tag) { + $data[] = array( + 'id_product' => (int)$id_product_new, + 'id_tag' => (int)$tag['id_tag'], + 'id_lang' => (int)$tag['id_lang'], + ); + } - return Db::getInstance()->insert('product_tag', $data); - } + return Db::getInstance()->insert('product_tag', $data); + } - public static function duplicateDownload($id_product_old, $id_product_new) - { - $sql = 'SELECT `display_filename`, `filename`, `date_add`, `date_expiration`, `nb_days_accessible`, `nb_downloadable`, `active`, `is_shareable` + public static function duplicateDownload($id_product_old, $id_product_new) + { + $sql = 'SELECT `display_filename`, `filename`, `date_add`, `date_expiration`, `nb_days_accessible`, `nb_downloadable`, `active`, `is_shareable` FROM `'._DB_PREFIX_.'product_download` WHERE `id_product` = '.(int)$id_product_old; - $results = Db::getInstance()->executeS($sql); - if (!$results) - return true; + $results = Db::getInstance()->executeS($sql); + if (!$results) { + return true; + } - $data = array(); - foreach ($results as $row) - { - $new_filename = ProductDownload::getNewFilename(); - copy(_PS_DOWNLOAD_DIR_.$row['filename'], _PS_DOWNLOAD_DIR_.$new_filename); + $data = array(); + foreach ($results as $row) { + $new_filename = ProductDownload::getNewFilename(); + copy(_PS_DOWNLOAD_DIR_.$row['filename'], _PS_DOWNLOAD_DIR_.$new_filename); - $data[] = array( - 'id_product' => (int)$id_product_new, - 'display_filename' => pSQL($row['display_filename']), - 'filename' => pSQL($new_filename), - 'date_expiration' => pSQL($row['date_expiration']), - 'nb_days_accessible' => (int)$row['nb_days_accessible'], - 'nb_downloadable' => (int)$row['nb_downloadable'], - 'active' => (int)$row['active'], - 'is_shareable' => (int)$row['is_shareable'], - 'date_add' => date('Y-m-d H:i:s') - ); - } - return Db::getInstance()->insert('product_download', $data); - } + $data[] = array( + 'id_product' => (int)$id_product_new, + 'display_filename' => pSQL($row['display_filename']), + 'filename' => pSQL($new_filename), + 'date_expiration' => pSQL($row['date_expiration']), + 'nb_days_accessible' => (int)$row['nb_days_accessible'], + 'nb_downloadable' => (int)$row['nb_downloadable'], + 'active' => (int)$row['active'], + 'is_shareable' => (int)$row['is_shareable'], + 'date_add' => date('Y-m-d H:i:s') + ); + } + return Db::getInstance()->insert('product_download', $data); + } - public static function duplicateAttachments($id_product_old, $id_product_new) - { - // Get all ids attachments of the old product - $sql = 'SELECT `id_attachment` FROM `'._DB_PREFIX_.'product_attachment` WHERE `id_product` = '.(int)$id_product_old; - $results = Db::getInstance()->executeS($sql); + public static function duplicateAttachments($id_product_old, $id_product_new) + { + // Get all ids attachments of the old product + $sql = 'SELECT `id_attachment` FROM `'._DB_PREFIX_.'product_attachment` WHERE `id_product` = '.(int)$id_product_old; + $results = Db::getInstance()->executeS($sql); - if (!$results) - return true; + if (!$results) { + return true; + } - $data = array(); + $data = array(); - // Prepare data of table product_attachment - foreach ($results as $row) - $data[] = array( - 'id_product' => (int)$id_product_new, - 'id_attachment' => (int)$row['id_attachment'] - ); + // Prepare data of table product_attachment + foreach ($results as $row) { + $data[] = array( + 'id_product' => (int)$id_product_new, + 'id_attachment' => (int)$row['id_attachment'] + ); + } - // Duplicate product attachement - $res = Db::getInstance()->insert('product_attachment', $data); - Product::updateCacheAttachment((int)$id_product_new); - return $res; - } + // Duplicate product attachement + $res = Db::getInstance()->insert('product_attachment', $data); + Product::updateCacheAttachment((int)$id_product_new); + return $res; + } - /** - * Duplicate features when duplicating a product - * - * @param int $id_product_old Old product id - * @param int $id_product_old New product id - */ - public static function duplicateFeatures($id_product_old, $id_product_new) - { - $return = true; + /** + * Duplicate features when duplicating a product + * + * @param int $id_product_old Old product id + * @param int $id_product_old New product id + */ + public static function duplicateFeatures($id_product_old, $id_product_new) + { + $return = true; - $result = Db::getInstance()->executeS(' + $result = Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'feature_product` WHERE `id_product` = '.(int)$id_product_old); - foreach ($result as $row) - { - $result2 = Db::getInstance()->getRow(' + foreach ($result as $row) { + $result2 = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.'feature_value` WHERE `id_feature_value` = '.(int)$row['id_feature_value']); - // Custom feature value, need to duplicate it - if ($result2['custom']) - { - $old_id_feature_value = $result2['id_feature_value']; - unset($result2['id_feature_value']); - $return &= Db::getInstance()->insert('feature_value', $result2); - $max_fv = Db::getInstance()->getRow(' + // Custom feature value, need to duplicate it + if ($result2['custom']) { + $old_id_feature_value = $result2['id_feature_value']; + unset($result2['id_feature_value']); + $return &= Db::getInstance()->insert('feature_value', $result2); + $max_fv = Db::getInstance()->getRow(' SELECT MAX(`id_feature_value`) AS nb FROM `'._DB_PREFIX_.'feature_value`'); - $new_id_feature_value = $max_fv['nb']; + $new_id_feature_value = $max_fv['nb']; - foreach (Language::getIDs(false) as $id_lang) - { - $result3 = Db::getInstance()->getRow(' + foreach (Language::getIDs(false) as $id_lang) { + $result3 = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.'feature_value_lang` WHERE `id_feature_value` = '.(int)$old_id_feature_value.' AND `id_lang` = '.(int)$id_lang); - if ($result3) - { - $result3['id_feature_value'] = (int)$new_id_feature_value; - $result3['value'] = pSQL($result3['value']); - $return &= Db::getInstance()->insert('feature_value_lang', $result3); - } - } - $row['id_feature_value'] = $new_id_feature_value; - } + if ($result3) { + $result3['id_feature_value'] = (int)$new_id_feature_value; + $result3['value'] = pSQL($result3['value']); + $return &= Db::getInstance()->insert('feature_value_lang', $result3); + } + } + $row['id_feature_value'] = $new_id_feature_value; + } - $row['id_product'] = (int)$id_product_new; - $return &= Db::getInstance()->insert('feature_product', $row); - } - return $return; - } + $row['id_product'] = (int)$id_product_new; + $return &= Db::getInstance()->insert('feature_product', $row); + } + return $return; + } - protected static function _getCustomizationFieldsNLabels($product_id, $id_shop = null) - { - if (!Customization::isFeatureActive()) - return false; + protected static function _getCustomizationFieldsNLabels($product_id, $id_shop = null) + { + if (!Customization::isFeatureActive()) { + return false; + } - if (Shop::isFeatureActive() && !$id_shop) - $id_shop = (int)Context::getContext()->shop->id; + if (Shop::isFeatureActive() && !$id_shop) { + $id_shop = (int)Context::getContext()->shop->id; + } - $customizations = array(); - if (($customizations['fields'] = Db::getInstance()->executeS(' + $customizations = array(); + if (($customizations['fields'] = Db::getInstance()->executeS(' SELECT `id_customization_field`, `type`, `required` FROM `'._DB_PREFIX_.'customization_field` WHERE `id_product` = '.(int)$product_id.' - ORDER BY `id_customization_field`')) === false) - return false; + ORDER BY `id_customization_field`')) === false) { + return false; + } - if (empty($customizations['fields'])) - return array(); + if (empty($customizations['fields'])) { + return array(); + } - $customization_field_ids = array(); - foreach ($customizations['fields'] as $customization_field) - $customization_field_ids[] = (int)$customization_field['id_customization_field']; + $customization_field_ids = array(); + foreach ($customizations['fields'] as $customization_field) { + $customization_field_ids[] = (int)$customization_field['id_customization_field']; + } - if (($customization_labels = Db::getInstance()->executeS(' + if (($customization_labels = Db::getInstance()->executeS(' SELECT `id_customization_field`, `id_lang`, `name` FROM `'._DB_PREFIX_.'customization_field_lang` WHERE `id_customization_field` IN ('.implode(', ', $customization_field_ids).')'.($id_shop ? ' AND cfl.`id_shop` = '.$id_shop : '').' - ORDER BY `id_customization_field`')) === false) - return false; + ORDER BY `id_customization_field`')) === false) { + return false; + } - foreach ($customization_labels as $customization_label) - $customizations['labels'][$customization_label['id_customization_field']][] = $customization_label; + foreach ($customization_labels as $customization_label) { + $customizations['labels'][$customization_label['id_customization_field']][] = $customization_label; + } - return $customizations; - } + return $customizations; + } - public static function duplicateSpecificPrices($old_product_id, $product_id) - { - foreach (SpecificPrice::getIdsByProductId((int)$old_product_id) as $data) - { - $specific_price = new SpecificPrice((int)$data['id_specific_price']); - if (!$specific_price->duplicate((int)$product_id)) - return false; - } - return true; - } + public static function duplicateSpecificPrices($old_product_id, $product_id) + { + foreach (SpecificPrice::getIdsByProductId((int)$old_product_id) as $data) { + $specific_price = new SpecificPrice((int)$data['id_specific_price']); + if (!$specific_price->duplicate((int)$product_id)) { + return false; + } + } + return true; + } - public static function duplicateCustomizationFields($old_product_id, $product_id) - { - // If customization is not activated, return success - if (!Customization::isFeatureActive()) - return true; - if (($customizations = Product::_getCustomizationFieldsNLabels($old_product_id)) === false) - return false; - if (empty($customizations)) - return true; - foreach ($customizations['fields'] as $customization_field) - { - /* The new datas concern the new product */ - $customization_field['id_product'] = (int)$product_id; - $old_customization_field_id = (int)$customization_field['id_customization_field']; + public static function duplicateCustomizationFields($old_product_id, $product_id) + { + // If customization is not activated, return success + if (!Customization::isFeatureActive()) { + return true; + } + if (($customizations = Product::_getCustomizationFieldsNLabels($old_product_id)) === false) { + return false; + } + if (empty($customizations)) { + return true; + } + foreach ($customizations['fields'] as $customization_field) { + /* The new datas concern the new product */ + $customization_field['id_product'] = (int)$product_id; + $old_customization_field_id = (int)$customization_field['id_customization_field']; - unset($customization_field['id_customization_field']); + unset($customization_field['id_customization_field']); - if (!Db::getInstance()->insert('customization_field', $customization_field) - || !$customization_field_id = Db::getInstance()->Insert_ID()) - return false; + if (!Db::getInstance()->insert('customization_field', $customization_field) + || !$customization_field_id = Db::getInstance()->Insert_ID()) { + return false; + } - if (isset($customizations['labels'])) - { - foreach ($customizations['labels'][$old_customization_field_id] as $customization_label) - { - $data = array( - 'id_customization_field' => (int)$customization_field_id, - 'id_lang' => (int)$customization_label['id_lang'], - 'name' => pSQL($customization_label['name']), - ); + if (isset($customizations['labels'])) { + foreach ($customizations['labels'][$old_customization_field_id] as $customization_label) { + $data = array( + 'id_customization_field' => (int)$customization_field_id, + 'id_lang' => (int)$customization_label['id_lang'], + 'name' => pSQL($customization_label['name']), + ); - if (!Db::getInstance()->insert('customization_field_lang', $data)) - return false; - } - } - } - return true; - } + if (!Db::getInstance()->insert('customization_field_lang', $data)) { + return false; + } + } + } + } + return true; + } - /** - * Adds suppliers from old product onto a newly duplicated product - * - * @param int $id_product_old - * @param int $id_product_new - */ - public static function duplicateSuppliers($id_product_old, $id_product_new) - { - $result = Db::getInstance()->executeS(' + /** + * Adds suppliers from old product onto a newly duplicated product + * + * @param int $id_product_old + * @param int $id_product_new + */ + public static function duplicateSuppliers($id_product_old, $id_product_new) + { + $result = Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'product_supplier` WHERE `id_product` = '.(int)$id_product_old.' AND `id_product_attribute` = 0'); - foreach ($result as $row) - { - unset($row['id_product_supplier']); - $row['id_product'] = $id_product_new; - if (!Db::getInstance()->insert('product_supplier', $row)) - return false; - } + foreach ($result as $row) { + unset($row['id_product_supplier']); + $row['id_product'] = $id_product_new; + if (!Db::getInstance()->insert('product_supplier', $row)) { + return false; + } + } - return true; - } + return true; + } - /** - * Get the link of the product page of this product - */ - public function getLink(Context $context = null) - { - if (!$context) - $context = Context::getContext(); - return $context->link->getProductLink($this); - } + /** + * Get the link of the product page of this product + */ + public function getLink(Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + return $context->link->getProductLink($this); + } - public function getTags($id_lang) - { - if (!$this->isFullyLoaded && is_null($this->tags)) - $this->tags = Tag::getProductTags($this->id); + public function getTags($id_lang) + { + if (!$this->isFullyLoaded && is_null($this->tags)) { + $this->tags = Tag::getProductTags($this->id); + } - if (!($this->tags && array_key_exists($id_lang, $this->tags))) - return ''; + if (!($this->tags && array_key_exists($id_lang, $this->tags))) { + return ''; + } - $result = ''; - foreach ($this->tags[$id_lang] as $tag_name) - $result .= $tag_name.', '; + $result = ''; + foreach ($this->tags[$id_lang] as $tag_name) { + $result .= $tag_name.', '; + } - return rtrim($result, ', '); - } + return rtrim($result, ', '); + } - public static function defineProductImage($row, $id_lang) - { - if (isset($row['id_image']) && $row['id_image']) - return $row['id_product'].'-'.$row['id_image']; + public static function defineProductImage($row, $id_lang) + { + if (isset($row['id_image']) && $row['id_image']) { + return $row['id_product'].'-'.$row['id_image']; + } - return Language::getIsoById((int)$id_lang).'-default'; - } + return Language::getIsoById((int)$id_lang).'-default'; + } - public static function getProductProperties($id_lang, $row, Context $context = null) - { - if (!$row['id_product']) - return false; + public static function getProductProperties($id_lang, $row, Context $context = null) + { + if (!$row['id_product']) { + return false; + } - if ($context == null) - $context = Context::getContext(); + if ($context == null) { + $context = Context::getContext(); + } - $id_product_attribute = $row['id_product_attribute'] = (!empty($row['id_product_attribute']) ? (int)$row['id_product_attribute'] : null); + $id_product_attribute = $row['id_product_attribute'] = (!empty($row['id_product_attribute']) ? (int)$row['id_product_attribute'] : null); - // Product::getDefaultAttribute is only called if id_product_attribute is missing from the SQL query at the origin of it: - // consider adding it in order to avoid unnecessary queries - $row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']); - if (Combination::isFeatureActive() && $id_product_attribute === null - && ((isset($row['cache_default_attribute']) && ($ipa_default = $row['cache_default_attribute']) !== null) - || ($ipa_default = Product::getDefaultAttribute($row['id_product'], !$row['allow_oosp'])))) - $id_product_attribute = $row['id_product_attribute'] = $ipa_default; - if (!Combination::isFeatureActive() || !isset($row['id_product_attribute'])) - $id_product_attribute = $row['id_product_attribute'] = 0; + // Product::getDefaultAttribute is only called if id_product_attribute is missing from the SQL query at the origin of it: + // consider adding it in order to avoid unnecessary queries + $row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']); + if (Combination::isFeatureActive() && $id_product_attribute === null + && ((isset($row['cache_default_attribute']) && ($ipa_default = $row['cache_default_attribute']) !== null) + || ($ipa_default = Product::getDefaultAttribute($row['id_product'], !$row['allow_oosp'])))) { + $id_product_attribute = $row['id_product_attribute'] = $ipa_default; + } + if (!Combination::isFeatureActive() || !isset($row['id_product_attribute'])) { + $id_product_attribute = $row['id_product_attribute'] = 0; + } - // Tax - $usetax = Tax::excludeTaxeOption(); + // Tax + $usetax = Tax::excludeTaxeOption(); - $cache_key = $row['id_product'].'-'.$id_product_attribute.'-'.$id_lang.'-'.(int)$usetax; - if (isset($row['id_product_pack'])) - $cache_key .= '-pack'.$row['id_product_pack']; + $cache_key = $row['id_product'].'-'.$id_product_attribute.'-'.$id_lang.'-'.(int)$usetax; + if (isset($row['id_product_pack'])) { + $cache_key .= '-pack'.$row['id_product_pack']; + } - if (isset(self::$producPropertiesCache[$cache_key])) - return array_merge($row, self::$producPropertiesCache[$cache_key]); + if (isset(self::$producPropertiesCache[$cache_key])) { + return array_merge($row, self::$producPropertiesCache[$cache_key]); + } - // Datas - $row['category'] = Category::getLinkRewrite((int)$row['id_category_default'], (int)$id_lang); - $row['link'] = $context->link->getProductLink((int)$row['id_product'], $row['link_rewrite'], $row['category'], $row['ean13']); + // Datas + $row['category'] = Category::getLinkRewrite((int)$row['id_category_default'], (int)$id_lang); + $row['link'] = $context->link->getProductLink((int)$row['id_product'], $row['link_rewrite'], $row['category'], $row['ean13']); - $row['attribute_price'] = 0; - if ($id_product_attribute) - $row['attribute_price'] = (float)Product::getProductAttributePrice($id_product_attribute); + $row['attribute_price'] = 0; + if ($id_product_attribute) { + $row['attribute_price'] = (float)Product::getProductAttributePrice($id_product_attribute); + } - $row['price_tax_exc'] = Product::getPriceStatic( - (int)$row['id_product'], - false, - $id_product_attribute, - (self::$_taxCalculationMethod == PS_TAX_EXC ? 2 : 6) - ); + $row['price_tax_exc'] = Product::getPriceStatic( + (int)$row['id_product'], + false, + $id_product_attribute, + (self::$_taxCalculationMethod == PS_TAX_EXC ? 2 : 6) + ); - if (self::$_taxCalculationMethod == PS_TAX_EXC) - { - $row['price_tax_exc'] = Tools::ps_round($row['price_tax_exc'], 2); - $row['price'] = Product::getPriceStatic( - (int)$row['id_product'], - true, - $id_product_attribute, - 6 - ); - $row['price_without_reduction'] = Product::getPriceStatic( - (int)$row['id_product'], - false, - $id_product_attribute, - 2, - null, - false, - false - ); - } - else - { - $row['price'] = Tools::ps_round( - Product::getPriceStatic( - (int)$row['id_product'], - true, - $id_product_attribute, - 6 - ), - (int)Configuration::get('PS_PRICE_DISPLAY_PRECISION') - ); - $row['price_without_reduction'] = Product::getPriceStatic( - (int)$row['id_product'], - true, - $id_product_attribute, - 6, - null, - false, - false - ); - } + if (self::$_taxCalculationMethod == PS_TAX_EXC) { + $row['price_tax_exc'] = Tools::ps_round($row['price_tax_exc'], 2); + $row['price'] = Product::getPriceStatic( + (int)$row['id_product'], + true, + $id_product_attribute, + 6 + ); + $row['price_without_reduction'] = Product::getPriceStatic( + (int)$row['id_product'], + false, + $id_product_attribute, + 2, + null, + false, + false + ); + } else { + $row['price'] = Tools::ps_round( + Product::getPriceStatic( + (int)$row['id_product'], + true, + $id_product_attribute, + 6 + ), + (int)Configuration::get('PS_PRICE_DISPLAY_PRECISION') + ); + $row['price_without_reduction'] = Product::getPriceStatic( + (int)$row['id_product'], + true, + $id_product_attribute, + 6, + null, + false, + false + ); + } - $row['reduction'] = Product::getPriceStatic( - (int)$row['id_product'], - (bool)$usetax, - $id_product_attribute, - 6, - null, - true, - true, - 1, - true, - null, - null, - null, - $specific_prices - ); + $row['reduction'] = Product::getPriceStatic( + (int)$row['id_product'], + (bool)$usetax, + $id_product_attribute, + 6, + null, + true, + true, + 1, + true, + null, + null, + null, + $specific_prices + ); - $row['specific_prices'] = $specific_prices; + $row['specific_prices'] = $specific_prices; - $row['quantity'] = Product::getQuantity( - (int)$row['id_product'], - 0, - isset($row['cache_is_pack']) ? $row['cache_is_pack'] : null - ); + $row['quantity'] = Product::getQuantity( + (int)$row['id_product'], + 0, + isset($row['cache_is_pack']) ? $row['cache_is_pack'] : null + ); - $row['quantity_all_versions'] = $row['quantity']; + $row['quantity_all_versions'] = $row['quantity']; - if ($row['id_product_attribute']) - $row['quantity'] = Product::getQuantity( - (int)$row['id_product'], - $id_product_attribute, - isset($row['cache_is_pack']) ? $row['cache_is_pack'] : null - ); + if ($row['id_product_attribute']) { + $row['quantity'] = Product::getQuantity( + (int)$row['id_product'], + $id_product_attribute, + isset($row['cache_is_pack']) ? $row['cache_is_pack'] : null + ); + } - $row['id_image'] = Product::defineProductImage($row, $id_lang); - $row['features'] = Product::getFrontFeaturesStatic((int)$id_lang, $row['id_product']); + $row['id_image'] = Product::defineProductImage($row, $id_lang); + $row['features'] = Product::getFrontFeaturesStatic((int)$id_lang, $row['id_product']); - $row['attachments'] = array(); - if (!isset($row['cache_has_attachments']) || $row['cache_has_attachments']) - $row['attachments'] = Product::getAttachmentsStatic((int)$id_lang, $row['id_product']); + $row['attachments'] = array(); + if (!isset($row['cache_has_attachments']) || $row['cache_has_attachments']) { + $row['attachments'] = Product::getAttachmentsStatic((int)$id_lang, $row['id_product']); + } - $row['virtual'] = ((!isset($row['is_virtual']) || $row['is_virtual']) ? 1 : 0); + $row['virtual'] = ((!isset($row['is_virtual']) || $row['is_virtual']) ? 1 : 0); - // Pack management - $row['pack'] = (!isset($row['cache_is_pack']) ? Pack::isPack($row['id_product']) : (int)$row['cache_is_pack']); - $row['packItems'] = $row['pack'] ? Pack::getItemTable($row['id_product'], $id_lang) : array(); - $row['nopackprice'] = $row['pack'] ? Pack::noPackPrice($row['id_product']) : 0; - if ($row['pack'] && !Pack::isInStock($row['id_product'])) - $row['quantity'] = 0; + // Pack management + $row['pack'] = (!isset($row['cache_is_pack']) ? Pack::isPack($row['id_product']) : (int)$row['cache_is_pack']); + $row['packItems'] = $row['pack'] ? Pack::getItemTable($row['id_product'], $id_lang) : array(); + $row['nopackprice'] = $row['pack'] ? Pack::noPackPrice($row['id_product']) : 0; + if ($row['pack'] && !Pack::isInStock($row['id_product'])) { + $row['quantity'] = 0; + } - $row['customization_required'] = false; - if (isset($row['customizable']) && $row['customizable'] && Customization::isFeatureActive()) - if (count(Product::getRequiredCustomizableFieldsStatic((int)$row['id_product']))) - $row['customization_required'] = true; + $row['customization_required'] = false; + if (isset($row['customizable']) && $row['customizable'] && Customization::isFeatureActive()) { + if (count(Product::getRequiredCustomizableFieldsStatic((int)$row['id_product']))) { + $row['customization_required'] = true; + } + } - $row = Product::getTaxesInformations($row, $context); - self::$producPropertiesCache[$cache_key] = $row; - return self::$producPropertiesCache[$cache_key]; - } + $row = Product::getTaxesInformations($row, $context); + self::$producPropertiesCache[$cache_key] = $row; + return self::$producPropertiesCache[$cache_key]; + } - public static function getTaxesInformations($row, Context $context = null) - { - static $address = null; + public static function getTaxesInformations($row, Context $context = null) + { + static $address = null; - if ($context === null) - $context = Context::getContext(); - if ($address === null) - $address = new Address(); + if ($context === null) { + $context = Context::getContext(); + } + if ($address === null) { + $address = new Address(); + } - $address->id_country = (int)$context->country->id; - $address->id_state = 0; - $address->postcode = 0; + $address->id_country = (int)$context->country->id; + $address->id_state = 0; + $address->postcode = 0; - $tax_manager = TaxManagerFactory::getManager($address, Product::getIdTaxRulesGroupByIdProduct((int)$row['id_product'], $context)); - $row['rate'] = $tax_manager->getTaxCalculator()->getTotalRate(); - $row['tax_name'] = $tax_manager->getTaxCalculator()->getTaxesName(); + $tax_manager = TaxManagerFactory::getManager($address, Product::getIdTaxRulesGroupByIdProduct((int)$row['id_product'], $context)); + $row['rate'] = $tax_manager->getTaxCalculator()->getTotalRate(); + $row['tax_name'] = $tax_manager->getTaxCalculator()->getTaxesName(); - return $row; - } + return $row; + } - public static function getProductsProperties($id_lang, $query_result) - { - $results_array = array(); + public static function getProductsProperties($id_lang, $query_result) + { + $results_array = array(); - if (is_array($query_result)) - foreach ($query_result as $row) - if ($row2 = Product::getProductProperties($id_lang, $row)) - $results_array[] = $row2; + if (is_array($query_result)) { + foreach ($query_result as $row) { + if ($row2 = Product::getProductProperties($id_lang, $row)) { + $results_array[] = $row2; + } + } + } - return $results_array; - } + return $results_array; + } - /* - * Select all features for a given language - * - * @param $id_lang Language id - * @return array Array with feature's data - */ - public static function getFrontFeaturesStatic($id_lang, $id_product) - { - if (!Feature::isFeatureActive()) - return array(); - if (!array_key_exists($id_product.'-'.$id_lang, self::$_frontFeaturesCache)) - { - self::$_frontFeaturesCache[$id_product.'-'.$id_lang] = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /* + * Select all features for a given language + * + * @param $id_lang Language id + * @return array Array with feature's data + */ + public static function getFrontFeaturesStatic($id_lang, $id_product) + { + if (!Feature::isFeatureActive()) { + return array(); + } + if (!array_key_exists($id_product.'-'.$id_lang, self::$_frontFeaturesCache)) { + self::$_frontFeaturesCache[$id_product.'-'.$id_lang] = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT name, value, pf.id_feature FROM '._DB_PREFIX_.'feature_product pf LEFT JOIN '._DB_PREFIX_.'feature_lang fl ON (fl.id_feature = pf.id_feature AND fl.id_lang = '.(int)$id_lang.') @@ -4223,485 +4414,530 @@ class ProductCore extends ObjectModel '.Shop::addSqlAssociation('feature', 'f').' WHERE pf.id_product = '.(int)$id_product.' ORDER BY f.position ASC' - ); - } - return self::$_frontFeaturesCache[$id_product.'-'.$id_lang]; - } + ); + } + return self::$_frontFeaturesCache[$id_product.'-'.$id_lang]; + } - public function getFrontFeatures($id_lang) - { - return Product::getFrontFeaturesStatic($id_lang, $this->id); - } + public function getFrontFeatures($id_lang) + { + return Product::getFrontFeaturesStatic($id_lang, $this->id); + } - public static function getAttachmentsStatic($id_lang, $id_product) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getAttachmentsStatic($id_lang, $id_product) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM '._DB_PREFIX_.'product_attachment pa LEFT JOIN '._DB_PREFIX_.'attachment a ON a.id_attachment = pa.id_attachment LEFT JOIN '._DB_PREFIX_.'attachment_lang al ON (a.id_attachment = al.id_attachment AND al.id_lang = '.(int)$id_lang.') WHERE pa.id_product = '.(int)$id_product); - } + } - public function getAttachments($id_lang) - { - return Product::getAttachmentsStatic($id_lang, $this->id); - } + public function getAttachments($id_lang) + { + return Product::getAttachmentsStatic($id_lang, $this->id); + } - /* - ** Customization management - */ + /* + ** Customization management + */ - public static function getAllCustomizedDatas($id_cart, $id_lang = null, $only_in_cart = true, $id_shop = null) - { - if (!Customization::isFeatureActive()) - return false; + public static function getAllCustomizedDatas($id_cart, $id_lang = null, $only_in_cart = true, $id_shop = null) + { + if (!Customization::isFeatureActive()) { + return false; + } - // No need to query if there isn't any real cart! - if (!$id_cart) - return false; - if (!$id_lang) - $id_lang = Context::getContext()->language->id; - if (Shop::isFeatureActive() && !$id_shop) - $id_shop = (int)Context::getContext()->shop->id; + // No need to query if there isn't any real cart! + if (!$id_cart) { + return false; + } + if (!$id_lang) { + $id_lang = Context::getContext()->language->id; + } + if (Shop::isFeatureActive() && !$id_shop) { + $id_shop = (int)Context::getContext()->shop->id; + } - if (!$result = Db::getInstance()->executeS(' + if (!$result = Db::getInstance()->executeS(' SELECT cd.`id_customization`, c.`id_address_delivery`, c.`id_product`, cfl.`id_customization_field`, c.`id_product_attribute`, cd.`type`, cd.`index`, cd.`value`, cfl.`name` FROM `'._DB_PREFIX_.'customized_data` cd NATURAL JOIN `'._DB_PREFIX_.'customization` c LEFT JOIN `'._DB_PREFIX_.'customization_field_lang` cfl ON (cfl.id_customization_field = cd.`index` AND id_lang = '.(int)$id_lang. - ($id_shop ? ' AND cfl.`id_shop` = '.$id_shop : '').') + ($id_shop ? ' AND cfl.`id_shop` = '.$id_shop : '').') WHERE c.`id_cart` = '.(int)$id_cart. - ($only_in_cart ? ' AND c.`in_cart` = 1' : '').' - ORDER BY `id_product`, `id_product_attribute`, `type`, `index`')) - return false; + ($only_in_cart ? ' AND c.`in_cart` = 1' : '').' + ORDER BY `id_product`, `id_product_attribute`, `type`, `index`')) { + return false; + } - $customized_datas = array(); + $customized_datas = array(); - foreach ($result as $row) - $customized_datas[(int)$row['id_product']][(int)$row['id_product_attribute']][(int)$row['id_address_delivery']][(int)$row['id_customization']]['datas'][(int)$row['type']][] = $row; + foreach ($result as $row) { + $customized_datas[(int)$row['id_product']][(int)$row['id_product_attribute']][(int)$row['id_address_delivery']][(int)$row['id_customization']]['datas'][(int)$row['type']][] = $row; + } - if (!$result = Db::getInstance()->executeS( - 'SELECT `id_product`, `id_product_attribute`, `id_customization`, `id_address_delivery`, `quantity`, `quantity_refunded`, `quantity_returned` + if (!$result = Db::getInstance()->executeS( + 'SELECT `id_product`, `id_product_attribute`, `id_customization`, `id_address_delivery`, `quantity`, `quantity_refunded`, `quantity_returned` FROM `'._DB_PREFIX_.'customization` WHERE `id_cart` = '.(int)$id_cart.($only_in_cart ? ' - AND `in_cart` = 1' : ''))) - return false; + AND `in_cart` = 1' : ''))) { + return false; + } - foreach ($result as $row) - { - $customized_datas[(int)$row['id_product']][(int)$row['id_product_attribute']][(int)$row['id_address_delivery']][(int)$row['id_customization']]['quantity'] = (int)$row['quantity']; - $customized_datas[(int)$row['id_product']][(int)$row['id_product_attribute']][(int)$row['id_address_delivery']][(int)$row['id_customization']]['quantity_refunded'] = (int)$row['quantity_refunded']; - $customized_datas[(int)$row['id_product']][(int)$row['id_product_attribute']][(int)$row['id_address_delivery']][(int)$row['id_customization']]['quantity_returned'] = (int)$row['quantity_returned']; - } + foreach ($result as $row) { + $customized_datas[(int)$row['id_product']][(int)$row['id_product_attribute']][(int)$row['id_address_delivery']][(int)$row['id_customization']]['quantity'] = (int)$row['quantity']; + $customized_datas[(int)$row['id_product']][(int)$row['id_product_attribute']][(int)$row['id_address_delivery']][(int)$row['id_customization']]['quantity_refunded'] = (int)$row['quantity_refunded']; + $customized_datas[(int)$row['id_product']][(int)$row['id_product_attribute']][(int)$row['id_address_delivery']][(int)$row['id_customization']]['quantity_returned'] = (int)$row['quantity_returned']; + } - return $customized_datas; - } + return $customized_datas; + } - public static function addCustomizationPrice(&$products, &$customized_datas) - { - if (!$customized_datas) - return; + public static function addCustomizationPrice(&$products, &$customized_datas) + { + if (!$customized_datas) { + return; + } - foreach ($products as &$product_update) - { - if (!Customization::isFeatureActive()) - { - $product_update['customizationQuantityTotal'] = 0; - $product_update['customizationQuantityRefunded'] = 0; - $product_update['customizationQuantityReturned'] = 0; - } - else - { - $customization_quantity = 0; - $customization_quantity_refunded = 0; - $customization_quantity_returned = 0; + foreach ($products as &$product_update) { + if (!Customization::isFeatureActive()) { + $product_update['customizationQuantityTotal'] = 0; + $product_update['customizationQuantityRefunded'] = 0; + $product_update['customizationQuantityReturned'] = 0; + } else { + $customization_quantity = 0; + $customization_quantity_refunded = 0; + $customization_quantity_returned = 0; - /* Compatibility */ - $product_id = isset($product_update['id_product']) ? (int)$product_update['id_product'] : (int)$product_update['product_id']; - $product_attribute_id = isset($product_update['id_product_attribute']) ? (int)$product_update['id_product_attribute'] : (int)$product_update['product_attribute_id']; - $id_address_delivery = (int)$product_update['id_address_delivery']; - $product_quantity = isset($product_update['cart_quantity']) ? (int)$product_update['cart_quantity'] : (int)$product_update['product_quantity']; - $price = isset($product_update['price']) ? $product_update['price'] : $product_update['product_price']; - if (isset($product_update['price_wt']) && $product_update['price_wt']) - $price_wt = $product_update['price_wt']; - else - $price_wt = $price * (1 + ((isset($product_update['tax_rate']) ? $product_update['tax_rate'] : $product_update['rate']) * 0.01)); + /* Compatibility */ + $product_id = isset($product_update['id_product']) ? (int)$product_update['id_product'] : (int)$product_update['product_id']; + $product_attribute_id = isset($product_update['id_product_attribute']) ? (int)$product_update['id_product_attribute'] : (int)$product_update['product_attribute_id']; + $id_address_delivery = (int)$product_update['id_address_delivery']; + $product_quantity = isset($product_update['cart_quantity']) ? (int)$product_update['cart_quantity'] : (int)$product_update['product_quantity']; + $price = isset($product_update['price']) ? $product_update['price'] : $product_update['product_price']; + if (isset($product_update['price_wt']) && $product_update['price_wt']) { + $price_wt = $product_update['price_wt']; + } else { + $price_wt = $price * (1 + ((isset($product_update['tax_rate']) ? $product_update['tax_rate'] : $product_update['rate']) * 0.01)); + } - if (!isset($customized_datas[$product_id][$product_attribute_id][$id_address_delivery])) - $id_address_delivery = 0; - if (isset($customized_datas[$product_id][$product_attribute_id][$id_address_delivery])) - { - foreach ($customized_datas[$product_id][$product_attribute_id][$id_address_delivery] as $customization) - { - $customization_quantity += (int)$customization['quantity']; - $customization_quantity_refunded += (int)$customization['quantity_refunded']; - $customization_quantity_returned += (int)$customization['quantity_returned']; - } - } + if (!isset($customized_datas[$product_id][$product_attribute_id][$id_address_delivery])) { + $id_address_delivery = 0; + } + if (isset($customized_datas[$product_id][$product_attribute_id][$id_address_delivery])) { + foreach ($customized_datas[$product_id][$product_attribute_id][$id_address_delivery] as $customization) { + $customization_quantity += (int)$customization['quantity']; + $customization_quantity_refunded += (int)$customization['quantity_refunded']; + $customization_quantity_returned += (int)$customization['quantity_returned']; + } + } - $product_update['customizationQuantityTotal'] = $customization_quantity; - $product_update['customizationQuantityRefunded'] = $customization_quantity_refunded; - $product_update['customizationQuantityReturned'] = $customization_quantity_returned; + $product_update['customizationQuantityTotal'] = $customization_quantity; + $product_update['customizationQuantityRefunded'] = $customization_quantity_refunded; + $product_update['customizationQuantityReturned'] = $customization_quantity_returned; - if ($customization_quantity) - { - $product_update['total_wt'] = $price_wt * ($product_quantity - $customization_quantity); - $product_update['total_customization_wt'] = $price_wt * $customization_quantity; - $product_update['total'] = $price * ($product_quantity - $customization_quantity); - $product_update['total_customization'] = $price * $customization_quantity; - } - } - } - } + if ($customization_quantity) { + $product_update['total_wt'] = $price_wt * ($product_quantity - $customization_quantity); + $product_update['total_customization_wt'] = $price_wt * $customization_quantity; + $product_update['total'] = $price * ($product_quantity - $customization_quantity); + $product_update['total_customization'] = $price * $customization_quantity; + } + } + } + } - /* - ** Customization fields' label management - */ + /* + ** Customization fields' label management + */ - protected function _checkLabelField($field, $value) - { - if (!Validate::isLabel($value)) - return false; - $tmp = explode('_', $field); - if (count($tmp) < 4) - return false; - return $tmp; - } + protected function _checkLabelField($field, $value) + { + if (!Validate::isLabel($value)) { + return false; + } + $tmp = explode('_', $field); + if (count($tmp) < 4) { + return false; + } + return $tmp; + } - protected function _deleteOldLabels() - { - $max = array( - Product::CUSTOMIZE_FILE => (int)$this->uploadable_files, - Product::CUSTOMIZE_TEXTFIELD => (int)$this->text_fields - ); + protected function _deleteOldLabels() + { + $max = array( + Product::CUSTOMIZE_FILE => (int)$this->uploadable_files, + Product::CUSTOMIZE_TEXTFIELD => (int)$this->text_fields + ); - /* Get customization field ids */ - if (($result = Db::getInstance()->executeS( - 'SELECT `id_customization_field`, `type` + /* Get customization field ids */ + if (($result = Db::getInstance()->executeS( + 'SELECT `id_customization_field`, `type` FROM `'._DB_PREFIX_.'customization_field` WHERE `id_product` = '.(int)$this->id.' ORDER BY `id_customization_field`') - ) === false) - return false; + ) === false) { + return false; + } - if (empty($result)) - return true; + if (empty($result)) { + return true; + } - $customization_fields = array( - Product::CUSTOMIZE_FILE => array(), - Product::CUSTOMIZE_TEXTFIELD => array() - ); + $customization_fields = array( + Product::CUSTOMIZE_FILE => array(), + Product::CUSTOMIZE_TEXTFIELD => array() + ); - foreach ($result as $row) - $customization_fields[(int)$row['type']][] = (int)$row['id_customization_field']; + foreach ($result as $row) { + $customization_fields[(int)$row['type']][] = (int)$row['id_customization_field']; + } - $extra_file = count($customization_fields[Product::CUSTOMIZE_FILE]) - $max[Product::CUSTOMIZE_FILE]; - $extra_text = count($customization_fields[Product::CUSTOMIZE_TEXTFIELD]) - $max[Product::CUSTOMIZE_TEXTFIELD]; + $extra_file = count($customization_fields[Product::CUSTOMIZE_FILE]) - $max[Product::CUSTOMIZE_FILE]; + $extra_text = count($customization_fields[Product::CUSTOMIZE_TEXTFIELD]) - $max[Product::CUSTOMIZE_TEXTFIELD]; - /* If too much inside the database, deletion */ - if ($extra_file > 0 && count($customization_fields[Product::CUSTOMIZE_FILE]) - $extra_file >= 0 && - (!Db::getInstance()->execute( - 'DELETE `'._DB_PREFIX_.'customization_field`,`'._DB_PREFIX_.'customization_field_lang` + /* If too much inside the database, deletion */ + if ($extra_file > 0 && count($customization_fields[Product::CUSTOMIZE_FILE]) - $extra_file >= 0 && + (!Db::getInstance()->execute( + 'DELETE `'._DB_PREFIX_.'customization_field`,`'._DB_PREFIX_.'customization_field_lang` FROM `'._DB_PREFIX_.'customization_field` JOIN `'._DB_PREFIX_.'customization_field_lang` WHERE `'._DB_PREFIX_.'customization_field`.`id_product` = '.(int)$this->id.' AND `'._DB_PREFIX_.'customization_field`.`type` = '.Product::CUSTOMIZE_FILE.' AND `'._DB_PREFIX_.'customization_field_lang`.`id_customization_field` = `'._DB_PREFIX_.'customization_field`.`id_customization_field` AND `'._DB_PREFIX_.'customization_field`.`id_customization_field` >= '.(int)$customization_fields[Product::CUSTOMIZE_FILE][count($customization_fields[Product::CUSTOMIZE_FILE]) - $extra_file] - ))) - return false; + ))) { + return false; + } - if ($extra_text > 0 && count($customization_fields[Product::CUSTOMIZE_TEXTFIELD]) - $extra_text >= 0 && - (!Db::getInstance()->execute( - 'DELETE `'._DB_PREFIX_.'customization_field`,`'._DB_PREFIX_.'customization_field_lang` + if ($extra_text > 0 && count($customization_fields[Product::CUSTOMIZE_TEXTFIELD]) - $extra_text >= 0 && + (!Db::getInstance()->execute( + 'DELETE `'._DB_PREFIX_.'customization_field`,`'._DB_PREFIX_.'customization_field_lang` FROM `'._DB_PREFIX_.'customization_field` JOIN `'._DB_PREFIX_.'customization_field_lang` WHERE `'._DB_PREFIX_.'customization_field`.`id_product` = '.(int)$this->id.' AND `'._DB_PREFIX_.'customization_field`.`type` = '.Product::CUSTOMIZE_TEXTFIELD.' AND `'._DB_PREFIX_.'customization_field_lang`.`id_customization_field` = `'._DB_PREFIX_.'customization_field`.`id_customization_field` AND `'._DB_PREFIX_.'customization_field`.`id_customization_field` >= '.(int)$customization_fields[Product::CUSTOMIZE_TEXTFIELD][count($customization_fields[Product::CUSTOMIZE_TEXTFIELD]) - $extra_text] - ))) - return false; + ))) { + return false; + } - // Refresh cache of feature detachable - Configuration::updateGlobalValue('PS_CUSTOMIZATION_FEATURE_ACTIVE', Customization::isCurrentlyUsed()); + // Refresh cache of feature detachable + Configuration::updateGlobalValue('PS_CUSTOMIZATION_FEATURE_ACTIVE', Customization::isCurrentlyUsed()); - return true; - } + return true; + } - protected function _createLabel($languages, $type) - { - // Label insertion - if (!Db::getInstance()->execute(' + protected function _createLabel($languages, $type) + { + // Label insertion + if (!Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'customization_field` (`id_product`, `type`, `required`) VALUES ('.(int)$this->id.', '.(int)$type.', 0)') || - !$id_customization_field = (int)Db::getInstance()->Insert_ID()) - return false; + !$id_customization_field = (int)Db::getInstance()->Insert_ID()) { + return false; + } - // Multilingual label name creation - $values = ''; + // Multilingual label name creation + $values = ''; - foreach ($languages as $language) - foreach (Shop::getContextListShopID() as $id_shop) - $values .= '('.(int)$id_customization_field.', '.(int)$language['id_lang'].', '.$id_shop .',\'\'), '; + foreach ($languages as $language) { + foreach (Shop::getContextListShopID() as $id_shop) { + $values .= '('.(int)$id_customization_field.', '.(int)$language['id_lang'].', '.$id_shop .',\'\'), '; + } + } - $values = rtrim($values, ', '); - if (!Db::getInstance()->execute(' + $values = rtrim($values, ', '); + if (!Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'customization_field_lang` (`id_customization_field`, `id_lang`, `id_shop`, `name`) - VALUES '.$values)) - return false; + VALUES '.$values)) { + return false; + } - // Set cache of feature detachable to true - Configuration::updateGlobalValue('PS_CUSTOMIZATION_FEATURE_ACTIVE', '1'); + // Set cache of feature detachable to true + Configuration::updateGlobalValue('PS_CUSTOMIZATION_FEATURE_ACTIVE', '1'); - return true; - } + return true; + } - public function createLabels($uploadable_files, $text_fields) - { - $languages = Language::getLanguages(); - if ((int)$uploadable_files > 0) - for ($i = 0; $i < (int)$uploadable_files; $i++) - if (!$this->_createLabel($languages, Product::CUSTOMIZE_FILE)) - return false; + public function createLabels($uploadable_files, $text_fields) + { + $languages = Language::getLanguages(); + if ((int)$uploadable_files > 0) { + for ($i = 0; $i < (int)$uploadable_files; $i++) { + if (!$this->_createLabel($languages, Product::CUSTOMIZE_FILE)) { + return false; + } + } + } - if ((int)$text_fields > 0) - for ($i = 0; $i < (int)$text_fields; $i++) - if (!$this->_createLabel($languages, Product::CUSTOMIZE_TEXTFIELD)) - return false; + if ((int)$text_fields > 0) { + for ($i = 0; $i < (int)$text_fields; $i++) { + if (!$this->_createLabel($languages, Product::CUSTOMIZE_TEXTFIELD)) { + return false; + } + } + } - return true; - } + return true; + } - public function updateLabels() - { - $has_required_fields = 0; - foreach ($_POST as $field => $value) - /* Label update */ - if (strncmp($field, 'label_', 6) == 0) - { - if (!$tmp = $this->_checkLabelField($field, $value)) - return false; - /* Multilingual label name update */ - if (Shop::isFeatureActive()) - { - foreach (Shop::getContextListShopID() as $id_shop) - if (!Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'customization_field_lang` + public function updateLabels() + { + $has_required_fields = 0; + foreach ($_POST as $field => $value) { + /* Label update */ + if (strncmp($field, 'label_', 6) == 0) { + if (!$tmp = $this->_checkLabelField($field, $value)) { + return false; + } + /* Multilingual label name update */ + if (Shop::isFeatureActive()) { + foreach (Shop::getContextListShopID() as $id_shop) { + if (!Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'customization_field_lang` (`id_customization_field`, `id_lang`, `id_shop`, `name`) VALUES ('.(int)$tmp[2].', '.(int)$tmp[3].', '.$id_shop.', \''.pSQL($value).'\') - ON DUPLICATE KEY UPDATE `name` = \''.pSQL($value).'\'')) - return false; - } - elseif (!Db::getInstance()->execute(' + ON DUPLICATE KEY UPDATE `name` = \''.pSQL($value).'\'')) { + return false; + } + } + } elseif (!Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'customization_field_lang` (`id_customization_field`, `id_lang`, `name`) VALUES ('.(int)$tmp[2].', '.(int)$tmp[3].', \''.pSQL($value).'\') - ON DUPLICATE KEY UPDATE `name` = \''.pSQL($value).'\'')) - return false; + ON DUPLICATE KEY UPDATE `name` = \''.pSQL($value).'\'')) { + return false; + } - $is_required = isset($_POST['require_'.(int)$tmp[1].'_'.(int)$tmp[2]]) ? 1 : 0; - $has_required_fields |= $is_required; - /* Require option update */ - if (!Db::getInstance()->execute( - 'UPDATE `'._DB_PREFIX_.'customization_field` + $is_required = isset($_POST['require_'.(int)$tmp[1].'_'.(int)$tmp[2]]) ? 1 : 0; + $has_required_fields |= $is_required; + /* Require option update */ + if (!Db::getInstance()->execute( + 'UPDATE `'._DB_PREFIX_.'customization_field` SET `required` = '.(int)$is_required.' - WHERE `id_customization_field` = '.(int)$tmp[2])) - return false; - } + WHERE `id_customization_field` = '.(int)$tmp[2])) { + return false; + } + } + } - if ($has_required_fields && !ObjectModel::updateMultishopTable('product', array('customizable' => 2), 'a.id_product = '.(int)$this->id)) - return false; + if ($has_required_fields && !ObjectModel::updateMultishopTable('product', array('customizable' => 2), 'a.id_product = '.(int)$this->id)) { + return false; + } - if (!$this->_deleteOldLabels()) - return false; + if (!$this->_deleteOldLabels()) { + return false; + } - return true; - } + return true; + } - public function getCustomizationFields($id_lang = false, $id_shop = null) - { - if (!Customization::isFeatureActive()) - return false; + public function getCustomizationFields($id_lang = false, $id_shop = null) + { + if (!Customization::isFeatureActive()) { + return false; + } - if (Shop::isFeatureActive() && !$id_shop) - $id_shop = (int)Context::getContext()->shop->id; + if (Shop::isFeatureActive() && !$id_shop) { + $id_shop = (int)Context::getContext()->shop->id; + } - if (!$result = Db::getInstance()->executeS(' + if (!$result = Db::getInstance()->executeS(' SELECT cf.`id_customization_field`, cf.`type`, cf.`required`, cfl.`name`, cfl.`id_lang` FROM `'._DB_PREFIX_.'customization_field` cf NATURAL JOIN `'._DB_PREFIX_.'customization_field_lang` cfl WHERE cf.`id_product` = '.(int)$this->id.($id_lang ? ' AND cfl.`id_lang` = '.(int)$id_lang : ''). - ($id_shop ? ' AND cfl.`id_shop` = '.$id_shop : '').' - ORDER BY cf.`id_customization_field`')) - return false; + ($id_shop ? ' AND cfl.`id_shop` = '.$id_shop : '').' + ORDER BY cf.`id_customization_field`')) { + return false; + } - if ($id_lang) - return $result; + if ($id_lang) { + return $result; + } - $customization_fields = array(); - foreach ($result as $row) - $customization_fields[(int)$row['type']][(int)$row['id_customization_field']][(int)$row['id_lang']] = $row; + $customization_fields = array(); + foreach ($result as $row) { + $customization_fields[(int)$row['type']][(int)$row['id_customization_field']][(int)$row['id_lang']] = $row; + } - return $customization_fields; - } + return $customization_fields; + } - public function getCustomizationFieldIds() - { - if (!Customization::isFeatureActive()) - return array(); - return Db::getInstance()->executeS(' + public function getCustomizationFieldIds() + { + if (!Customization::isFeatureActive()) { + return array(); + } + return Db::getInstance()->executeS(' SELECT `id_customization_field`, `type`, `required` FROM `'._DB_PREFIX_.'customization_field` WHERE `id_product` = '.(int)$this->id); - } + } - public function getRequiredCustomizableFields() - { - if (!Customization::isFeatureActive()) - return array(); - return Product::getRequiredCustomizableFieldsStatic($this->id); - } + public function getRequiredCustomizableFields() + { + if (!Customization::isFeatureActive()) { + return array(); + } + return Product::getRequiredCustomizableFieldsStatic($this->id); + } - public static function getRequiredCustomizableFieldsStatic($id) - { - if (!$id || !Customization::isFeatureActive()) - return array(); - return Db::getInstance()->executeS(' + public static function getRequiredCustomizableFieldsStatic($id) + { + if (!$id || !Customization::isFeatureActive()) { + return array(); + } + return Db::getInstance()->executeS(' SELECT `id_customization_field`, `type` FROM `'._DB_PREFIX_.'customization_field` WHERE `id_product` = '.(int)$id.' AND `required` = 1' - ); - } + ); + } - public function hasAllRequiredCustomizableFields(Context $context = null) - { - if (!Customization::isFeatureActive()) - return true; - if (!$context) - $context = Context::getContext(); + public function hasAllRequiredCustomizableFields(Context $context = null) + { + if (!Customization::isFeatureActive()) { + return true; + } + if (!$context) { + $context = Context::getContext(); + } - $fields = $context->cart->getProductCustomization($this->id, null, true); - if (($required_fields = $this->getRequiredCustomizableFields()) === false) - return false; + $fields = $context->cart->getProductCustomization($this->id, null, true); + if (($required_fields = $this->getRequiredCustomizableFields()) === false) { + return false; + } - $fields_present = array(); - foreach ($fields as $field) - $fields_present[] = array('id_customization_field' => $field['index'], 'type' => $field['type']); + $fields_present = array(); + foreach ($fields as $field) { + $fields_present[] = array('id_customization_field' => $field['index'], 'type' => $field['type']); + } - if (is_array($required_fields) && count($required_fields)) - foreach ($required_fields as $required_field) - if (!in_array($required_field, $fields_present)) - return false; - return true; - } + if (is_array($required_fields) && count($required_fields)) { + foreach ($required_fields as $required_field) { + if (!in_array($required_field, $fields_present)) { + return false; + } + } + } + return true; + } - /** - * Checks if the product is in at least one of the submited categories - * - * @param int $id_product - * @param array $categories array of category arrays - * @return bool is the product in at least one category - */ - public static function idIsOnCategoryId($id_product, $categories) - { - if (!((int)$id_product > 0) || !is_array($categories) || empty($categories)) - return false; - $sql = 'SELECT id_product FROM `'._DB_PREFIX_.'category_product` WHERE `id_product` = '.(int)$id_product.' AND `id_category` IN ('; - foreach ($categories as $category) - $sql .= (int)$category['id_category'].','; - $sql = rtrim($sql, ',').')'; + /** + * Checks if the product is in at least one of the submited categories + * + * @param int $id_product + * @param array $categories array of category arrays + * @return bool is the product in at least one category + */ + public static function idIsOnCategoryId($id_product, $categories) + { + if (!((int)$id_product > 0) || !is_array($categories) || empty($categories)) { + return false; + } + $sql = 'SELECT id_product FROM `'._DB_PREFIX_.'category_product` WHERE `id_product` = '.(int)$id_product.' AND `id_category` IN ('; + foreach ($categories as $category) { + $sql .= (int)$category['id_category'].','; + } + $sql = rtrim($sql, ',').')'; - $hash = md5($sql); - if (!isset(self::$_incat[$hash])) - { - if (!Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql)) - return false; - self::$_incat[$hash] = (Db::getInstance(_PS_USE_SQL_SLAVE_)->NumRows() > 0 ? true : false); - } - return self::$_incat[$hash]; - } + $hash = md5($sql); + if (!isset(self::$_incat[$hash])) { + if (!Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql)) { + return false; + } + self::$_incat[$hash] = (Db::getInstance(_PS_USE_SQL_SLAVE_)->NumRows() > 0 ? true : false); + } + return self::$_incat[$hash]; + } - public function getNoPackPrice() - { - return Pack::noPackPrice((int)$this->id); - } + public function getNoPackPrice() + { + return Pack::noPackPrice((int)$this->id); + } - public function checkAccess($id_customer) - { - return Product::checkAccessStatic((int)$this->id, (int)$id_customer); - } + public function checkAccess($id_customer) + { + return Product::checkAccessStatic((int)$this->id, (int)$id_customer); + } - public static function checkAccessStatic($id_product, $id_customer) - { - if (!Group::isFeatureActive()) - return true; + public static function checkAccessStatic($id_product, $id_customer) + { + if (!Group::isFeatureActive()) { + return true; + } - $cache_id = 'Product::checkAccess_'.(int)$id_product.'-'.(int)$id_customer.(!$id_customer ? '-'.(int)Group::getCurrent()->id : ''); - if (!Cache::isStored($cache_id)) - { - if (!$id_customer) - $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + $cache_id = 'Product::checkAccess_'.(int)$id_product.'-'.(int)$id_customer.(!$id_customer ? '-'.(int)Group::getCurrent()->id : ''); + if (!Cache::isStored($cache_id)) { + if (!$id_customer) { + $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT ctg.`id_group` FROM `'._DB_PREFIX_.'category_product` cp INNER JOIN `'._DB_PREFIX_.'category_group` ctg ON (ctg.`id_category` = cp.`id_category`) WHERE cp.`id_product` = '.(int)$id_product.' AND ctg.`id_group` = '.(int)Group::getCurrent()->id); - else - $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + } else { + $result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT cg.`id_group` FROM `'._DB_PREFIX_.'category_product` cp INNER JOIN `'._DB_PREFIX_.'category_group` ctg ON (ctg.`id_category` = cp.`id_category`) INNER JOIN `'._DB_PREFIX_.'customer_group` cg ON (cg.`id_group` = ctg.`id_group`) WHERE cp.`id_product` = '.(int)$id_product.' AND cg.`id_customer` = '.(int)$id_customer); + } - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Add a stock movement for current product - * - * Since 1.5, this method only permit to add/remove available quantities of the current product in the current shop - * - * @see StockManager if you want to manage real stock - * @see StockAvailable if you want to manage available quantities for sale on your shop(s) - * - * @deprecated since 1.5.0 - * - * @param int $quantity - * @param int $id_reason - useless - * @param int $id_product_attribute - * @param int $id_order - DEPRECATED - * @param int $id_employee - DEPRECATED - * @return bool - */ - public function addStockMvt($quantity, $id_reason, $id_product_attribute = null, $id_order = null, $id_employee = null) - { - if (!$this->id || !$id_reason) - return false; + /** + * Add a stock movement for current product + * + * Since 1.5, this method only permit to add/remove available quantities of the current product in the current shop + * + * @see StockManager if you want to manage real stock + * @see StockAvailable if you want to manage available quantities for sale on your shop(s) + * + * @deprecated since 1.5.0 + * + * @param int $quantity + * @param int $id_reason - useless + * @param int $id_product_attribute + * @param int $id_order - DEPRECATED + * @param int $id_employee - DEPRECATED + * @return bool + */ + public function addStockMvt($quantity, $id_reason, $id_product_attribute = null, $id_order = null, $id_employee = null) + { + if (!$this->id || !$id_reason) { + return false; + } - if ($id_product_attribute == null) - $id_product_attribute = 0; + if ($id_product_attribute == null) { + $id_product_attribute = 0; + } - $reason = new StockMvtReason((int)$id_reason); - if (!Validate::isLoadedObject($reason)) - return false; + $reason = new StockMvtReason((int)$id_reason); + if (!Validate::isLoadedObject($reason)) { + return false; + } - $quantity = abs((int)$quantity) * $reason->sign; + $quantity = abs((int)$quantity) * $reason->sign; - return StockAvailable::updateQuantity($this->id, $id_product_attribute, $quantity); - } + return StockAvailable::updateQuantity($this->id, $id_product_attribute, $quantity); + } - /** - * @deprecated since 1.5.0 - */ - public function getStockMvts($id_lang) - { - Tools::displayAsDeprecated(); + /** + * @deprecated since 1.5.0 + */ + public function getStockMvts($id_lang) + { + Tools::displayAsDeprecated(); - return Db::getInstance()->executeS(' + return Db::getInstance()->executeS(' SELECT sm.id_stock_mvt, sm.date_add, sm.quantity, sm.id_order, CONCAT(pl.name, \' \', GROUP_CONCAT(IFNULL(al.name, \'\'), \'\')) product_name, CONCAT(e.lastname, \' \', e.firstname) employee, mrl.name reason FROM `'._DB_PREFIX_.'stock_mvt` sm @@ -4726,11 +4962,11 @@ class ProductCore extends ObjectModel WHERE sm.id_product='.(int)$this->id.' GROUP BY sm.id_stock_mvt '); - } + } - public static function getUrlRewriteInformations($id_product) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getUrlRewriteInformations($id_product) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT pl.`id_lang`, pl.`link_rewrite`, p.`ean13`, cl.`link_rewrite` AS category_rewrite FROM `'._DB_PREFIX_.'product` p LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product`'.Shop::addSqlRestrictionOnLang('pl').') @@ -4740,503 +4976,511 @@ class ProductCore extends ObjectModel WHERE p.`id_product` = '.(int)$id_product.' AND l.`active` = 1 '); - } + } - public function getIdTaxRulesGroup() - { - return $this->id_tax_rules_group; - } + public function getIdTaxRulesGroup() + { + return $this->id_tax_rules_group; + } - public static function getIdTaxRulesGroupByIdProduct($id_product, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - $key = 'product_id_tax_rules_group_'.(int)$id_product.'_'.(int)$context->shop->id; - if (!Cache::isStored($key)) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getIdTaxRulesGroupByIdProduct($id_product, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + $key = 'product_id_tax_rules_group_'.(int)$id_product.'_'.(int)$context->shop->id; + if (!Cache::isStored($key)) { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_tax_rules_group` FROM `'._DB_PREFIX_.'product_shop` WHERE `id_product` = '.(int)$id_product.' AND id_shop='.(int)$context->shop->id); - Cache::store($key, (int)$result); - return (int)$result; - } - return Cache::retrieve($key); - } + Cache::store($key, (int)$result); + return (int)$result; + } + return Cache::retrieve($key); + } - /** - * Returns tax rate. - * - * @param Address|null $address - * @return float The total taxes rate applied to the product - */ - public function getTaxesRate(Address $address = null) - { - if (!$address || !$address->id_country) - $address = Address::initialize(); + /** + * Returns tax rate. + * + * @param Address|null $address + * @return float The total taxes rate applied to the product + */ + public function getTaxesRate(Address $address = null) + { + if (!$address || !$address->id_country) { + $address = Address::initialize(); + } - $tax_manager = TaxManagerFactory::getManager($address, $this->id_tax_rules_group); - $tax_calculator = $tax_manager->getTaxCalculator(); + $tax_manager = TaxManagerFactory::getManager($address, $this->id_tax_rules_group); + $tax_calculator = $tax_manager->getTaxCalculator(); - return $tax_calculator->getTotalRate(); - } + return $tax_calculator->getTotalRate(); + } - /** - * Webservice getter : get product features association - * - * @return array - */ - public function getWsProductFeatures() - { - $rows = $this->getFeatures(); - foreach ($rows as $keyrow => $row) - { - foreach ($row as $keyfeature => $feature) - { - if ($keyfeature == 'id_feature') - { - $rows[$keyrow]['id'] = $feature; - unset($rows[$keyrow]['id_feature']); - } - unset($rows[$keyrow]['id_product']); - unset($rows[$keyrow]['custom']); - } - asort($rows[$keyrow]); - } - return $rows; - } + /** + * Webservice getter : get product features association + * + * @return array + */ + public function getWsProductFeatures() + { + $rows = $this->getFeatures(); + foreach ($rows as $keyrow => $row) { + foreach ($row as $keyfeature => $feature) { + if ($keyfeature == 'id_feature') { + $rows[$keyrow]['id'] = $feature; + unset($rows[$keyrow]['id_feature']); + } + unset($rows[$keyrow]['id_product']); + unset($rows[$keyrow]['custom']); + } + asort($rows[$keyrow]); + } + return $rows; + } - /** - * Webservice setter : set product features association - * - * @param $product_features Product Feature ids - * @return bool - */ - public function setWsProductFeatures($product_features) - { - Db::getInstance()->execute(' + /** + * Webservice setter : set product features association + * + * @param $product_features Product Feature ids + * @return bool + */ + public function setWsProductFeatures($product_features) + { + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'feature_product` WHERE `id_product` = '.(int)$this->id - ); - foreach ($product_features as $product_feature) - $this->addFeaturesToDB($product_feature['id'], $product_feature['id_feature_value']); - return true; - } + ); + foreach ($product_features as $product_feature) { + $this->addFeaturesToDB($product_feature['id'], $product_feature['id_feature_value']); + } + return true; + } - /** - * Webservice getter : get virtual field default combination - * - * @return int - */ - public function getWsDefaultCombination() - { - return Product::getDefaultAttribute($this->id); - } + /** + * Webservice getter : get virtual field default combination + * + * @return int + */ + public function getWsDefaultCombination() + { + return Product::getDefaultAttribute($this->id); + } - /** - * Webservice setter : set virtual field default combination - * - * @param int $id_combination id default combination - * @return bool - */ - public function setWsDefaultCombination($id_combination) - { - $this->deleteDefaultAttributes(); - return $this->setDefaultAttribute((int)$id_combination); - } + /** + * Webservice setter : set virtual field default combination + * + * @param int $id_combination id default combination + * @return bool + */ + public function setWsDefaultCombination($id_combination) + { + $this->deleteDefaultAttributes(); + return $this->setDefaultAttribute((int)$id_combination); + } - /** - * Webservice getter : get category ids of current product for association - * - * @return array - */ - public function getWsCategories() - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS( - 'SELECT cp.`id_category` AS id + /** + * Webservice getter : get category ids of current product for association + * + * @return array + */ + public function getWsCategories() + { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS( + 'SELECT cp.`id_category` AS id FROM `'._DB_PREFIX_.'category_product` cp LEFT JOIN `'._DB_PREFIX_.'category` c ON (c.id_category = cp.id_category) '.Shop::addSqlAssociation('category', 'c').' WHERE cp.`id_product` = '.(int)$this->id - ); - return $result; - } + ); + return $result; + } - /** - * Webservice setter : set category ids of current product for association - * - * @param array $category_ids category ids - * @return bool - */ - public function setWsCategories($category_ids) - { - $ids = array(); - foreach ($category_ids as $value) - $ids[] = $value['id']; - if ($this->deleteCategories()) - { - if ($ids) - { - $sql_values = ''; - $ids = array_map('intval', $ids); - foreach ($ids as $position => $id) - $sql_values[] = '('.(int)$id.', '.(int)$this->id.', '.(int)$position.')'; - $result = Db::getInstance()->execute(' + /** + * Webservice setter : set category ids of current product for association + * + * @param array $category_ids category ids + * @return bool + */ + public function setWsCategories($category_ids) + { + $ids = array(); + foreach ($category_ids as $value) { + $ids[] = $value['id']; + } + if ($this->deleteCategories()) { + if ($ids) { + $sql_values = ''; + $ids = array_map('intval', $ids); + foreach ($ids as $position => $id) { + $sql_values[] = '('.(int)$id.', '.(int)$this->id.', '.(int)$position.')'; + } + $result = Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'category_product` (`id_category`, `id_product`, `position`) VALUES '.implode(',', $sql_values) - ); - Hook::exec('updateProduct', array('id_product' => (int)$this->id)); - return $result; - } - } - Hook::exec('updateProduct', array('id_product' => (int)$this->id)); - return true; - } + ); + Hook::exec('updateProduct', array('id_product' => (int)$this->id)); + return $result; + } + } + Hook::exec('updateProduct', array('id_product' => (int)$this->id)); + return true; + } - /** - * Webservice getter : get product accessories ids of current product for association - * - * @return array - */ - public function getWsAccessories() - { - $result = Db::getInstance()->executeS( - 'SELECT p.`id_product` AS id + /** + * Webservice getter : get product accessories ids of current product for association + * + * @return array + */ + public function getWsAccessories() + { + $result = Db::getInstance()->executeS( + 'SELECT p.`id_product` AS id FROM `'._DB_PREFIX_.'accessory` a LEFT JOIN `'._DB_PREFIX_.'product` p ON (p.id_product = a.id_product_2) '.Shop::addSqlAssociation('product', 'p').' WHERE a.`id_product_1` = '.(int)$this->id - ); + ); - return $result; - } + return $result; + } - /** - * Webservice setter : set product accessories ids of current product for association - * - * @param $accessories product ids - */ - public function setWsAccessories($accessories) - { - $this->deleteAccessories(); - foreach ($accessories as $accessory) - Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'accessory` (`id_product_1`, `id_product_2`) VALUES ('.(int)$this->id.', '.(int)$accessory['id'].')'); + /** + * Webservice setter : set product accessories ids of current product for association + * + * @param $accessories product ids + */ + public function setWsAccessories($accessories) + { + $this->deleteAccessories(); + foreach ($accessories as $accessory) { + Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'accessory` (`id_product_1`, `id_product_2`) VALUES ('.(int)$this->id.', '.(int)$accessory['id'].')'); + } - return true; - } + return true; + } - /** - * Webservice getter : get combination ids of current product for association - * - * @return array - */ - public function getWsCombinations() - { - $result = Db::getInstance()->executeS( - 'SELECT pa.`id_product_attribute` as id + /** + * Webservice getter : get combination ids of current product for association + * + * @return array + */ + public function getWsCombinations() + { + $result = Db::getInstance()->executeS( + 'SELECT pa.`id_product_attribute` as id FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE pa.`id_product` = '.(int)$this->id - ); + ); - return $result; - } + return $result; + } - /** - * Webservice setter : set combination ids of current product for association - * - * @param $combinations combination ids - */ - public function setWsCombinations($combinations) - { - // No hook exec - $ids_new = array(); - foreach ($combinations as $combination) - $ids_new[] = (int)$combination['id']; + /** + * Webservice setter : set combination ids of current product for association + * + * @param $combinations combination ids + */ + public function setWsCombinations($combinations) + { + // No hook exec + $ids_new = array(); + foreach ($combinations as $combination) { + $ids_new[] = (int)$combination['id']; + } - $ids_orig = array(); - $original = Db::getInstance()->executeS( - 'SELECT pa.`id_product_attribute` as id + $ids_orig = array(); + $original = Db::getInstance()->executeS( + 'SELECT pa.`id_product_attribute` as id FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE pa.`id_product` = '.(int)$this->id - ); + ); - if (is_array($original)) - foreach ($original as $id) - $ids_orig[] = $id['id']; + if (is_array($original)) { + foreach ($original as $id) { + $ids_orig[] = $id['id']; + } + } - $all_ids = array(); - $all = Db::getInstance()->executeS('SELECT pa.`id_product_attribute` as id FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa')); - if (is_array($all)) - foreach ($all as $id) - $all_ids[] = $id['id']; + $all_ids = array(); + $all = Db::getInstance()->executeS('SELECT pa.`id_product_attribute` as id FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa')); + if (is_array($all)) { + foreach ($all as $id) { + $all_ids[] = $id['id']; + } + } - $to_add = array(); - foreach ($ids_new as $id) - if (!in_array($id, $ids_orig)) - $to_add[] = $id; + $to_add = array(); + foreach ($ids_new as $id) { + if (!in_array($id, $ids_orig)) { + $to_add[] = $id; + } + } - $to_delete = array(); - foreach ($ids_orig as $id) - if (!in_array($id, $ids_new)) - $to_delete[] = $id; + $to_delete = array(); + foreach ($ids_orig as $id) { + if (!in_array($id, $ids_new)) { + $to_delete[] = $id; + } + } - // Delete rows - if (count($to_delete) > 0) - foreach ($to_delete as $id) - { - $combination = new Combination($id); - $combination->delete(); - } + // Delete rows + if (count($to_delete) > 0) { + foreach ($to_delete as $id) { + $combination = new Combination($id); + $combination->delete(); + } + } - foreach ($to_add as $id) - { - // Update id_product if exists else create - if (in_array($id, $all_ids)) - Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'product_attribute` SET id_product = '.(int)$this->id.' WHERE id_product_attribute='.$id); - else - Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'product_attribute` (`id_product`) VALUES ('.$this->id.')'); - } - return true; - } + foreach ($to_add as $id) { + // Update id_product if exists else create + if (in_array($id, $all_ids)) { + Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'product_attribute` SET id_product = '.(int)$this->id.' WHERE id_product_attribute='.$id); + } else { + Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'product_attribute` (`id_product`) VALUES ('.$this->id.')'); + } + } + return true; + } - /** - * Webservice getter : get product option ids of current product for association - * - * @return array - */ - public function getWsProductOptionValues() - { - $result = Db::getInstance()->executeS('SELECT DISTINCT pac.id_attribute as id + /** + * Webservice getter : get product option ids of current product for association + * + * @return array + */ + public function getWsProductOptionValues() + { + $result = Db::getInstance()->executeS('SELECT DISTINCT pac.id_attribute as id FROM `'._DB_PREFIX_.'product_attribute` pa '.Shop::addSqlAssociation('product_attribute', 'pa').' LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON (pac.id_product_attribute = pa.id_product_attribute) WHERE pa.id_product = '.(int)$this->id); - return $result; - } + return $result; + } - /** - * Webservice getter : get virtual field position in category - * - * @return int - */ - public function getWsPositionInCategory() - { - $result = Db::getInstance()->executeS('SELECT position + /** + * Webservice getter : get virtual field position in category + * + * @return int + */ + public function getWsPositionInCategory() + { + $result = Db::getInstance()->executeS('SELECT position FROM `'._DB_PREFIX_.'category_product` WHERE id_category = '.(int)$this->id_category_default.' AND id_product = '.(int)$this->id); - if (count($result) > 0) - return $result[0]['position']; - return ''; - } + if (count($result) > 0) { + return $result[0]['position']; + } + return ''; + } - /** - * Webservice setter : set virtual field position in category - * - * @return bool - */ - public function setWsPositionInCategory($position) - { - if ($position < 0) - WebserviceRequest::getInstance()->setError(500, Tools::displayError('You cannot set a negative position, the minimum for a position is 0.'), 134); - $result = Db::getInstance()->executeS(' + /** + * Webservice setter : set virtual field position in category + * + * @return bool + */ + public function setWsPositionInCategory($position) + { + if ($position < 0) { + WebserviceRequest::getInstance()->setError(500, Tools::displayError('You cannot set a negative position, the minimum for a position is 0.'), 134); + } + $result = Db::getInstance()->executeS(' SELECT `id_product` FROM `'._DB_PREFIX_.'category_product` WHERE `id_category` = '.(int)$this->id_category_default.' ORDER BY `position` '); - if (($position > 0) && ($position + 1 > count($result))) - WebserviceRequest::getInstance()->setError(500, Tools::displayError('You cannot set a position greater than the total number of products in the category, minus 1 (position numbering starts at 0).'), 135); + if (($position > 0) && ($position + 1 > count($result))) { + WebserviceRequest::getInstance()->setError(500, Tools::displayError('You cannot set a position greater than the total number of products in the category, minus 1 (position numbering starts at 0).'), 135); + } - foreach ($result as &$value) - $value = $value['id_product']; - $current_position = $this->getWsPositionInCategory(); + foreach ($result as &$value) { + $value = $value['id_product']; + } + $current_position = $this->getWsPositionInCategory(); - if ($current_position && isset($result[$current_position])) - { - $save = $result[$current_position]; - unset($result[$current_position]); - array_splice($result, (int)$position, 0, $save); - } + if ($current_position && isset($result[$current_position])) { + $save = $result[$current_position]; + unset($result[$current_position]); + array_splice($result, (int)$position, 0, $save); + } - foreach ($result as $position => $id_product) - { - Db::getInstance()->update('category_product', array( - 'position' => $position, - ), '`id_category` = '.(int)$this->id_category_default.' AND `id_product` = '.(int)$id_product); - } - return true; - } + foreach ($result as $position => $id_product) { + Db::getInstance()->update('category_product', array( + 'position' => $position, + ), '`id_category` = '.(int)$this->id_category_default.' AND `id_product` = '.(int)$id_product); + } + return true; + } - /** - * Webservice getter : get virtual field id_default_image in category - * - * @return int - */ - public function getCoverWs() - { - $result = $this->getCover($this->id); - return $result['id_image']; - } + /** + * Webservice getter : get virtual field id_default_image in category + * + * @return int + */ + public function getCoverWs() + { + $result = $this->getCover($this->id); + return $result['id_image']; + } - /** - * Webservice setter : set virtual field id_default_image in category - * - * @return bool - */ - public function setCoverWs($id_image) - { - Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'image_shop` image_shop, `'._DB_PREFIX_.'image` i + /** + * Webservice setter : set virtual field id_default_image in category + * + * @return bool + */ + public function setCoverWs($id_image) + { + Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'image_shop` image_shop, `'._DB_PREFIX_.'image` i SET image_shop.`cover` = 0 WHERE i.`id_product` = '.(int)$this->id.' AND i.id_image = image_shop.id_image AND image_shop.id_shop='.(int)Context::getContext()->shop->id); - Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'image_shop` + Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'image_shop` SET `cover` = 1 WHERE `id_image` = '.(int)$id_image); - return true; - } + return true; + } - /** - * Webservice getter : get image ids of current product for association - * - * @return array - */ - public function getWsImages() - { - return Db::getInstance()->executeS(' + /** + * Webservice getter : get image ids of current product for association + * + * @return array + */ + public function getWsImages() + { + return Db::getInstance()->executeS(' SELECT i.`id_image` as id FROM `'._DB_PREFIX_.'image` i '.Shop::addSqlAssociation('image', 'i').' WHERE i.`id_product` = '.(int)$this->id.' ORDER BY i.`position`'); - } + } - public function getWsStockAvailables() - { - return Db::getInstance()->executeS('SELECT `id_stock_available` id, `id_product_attribute` + public function getWsStockAvailables() + { + return Db::getInstance()->executeS('SELECT `id_stock_available` id, `id_product_attribute` FROM `'._DB_PREFIX_.'stock_available` WHERE `id_product`='.($this->id).StockAvailable::addSqlShopRestriction()); - } + } - public function getWsTags() - { - return Db::getInstance()->executeS(' + public function getWsTags() + { + return Db::getInstance()->executeS(' SELECT `id_tag` as id FROM `'._DB_PREFIX_.'product_tag` WHERE `id_product` = '.(int)$this->id); - } + } - /** - * Webservice setter : set tag ids of current product for association - * - * @param $tag_ids tag ids - */ - public function setWsTags($tag_ids) - { - $ids = array(); - foreach ($tag_ids as $value) - $ids[] = $value['id']; - if ($this->deleteWsTags()) - { - if ($ids) - { - $sql_values = ''; - $ids = array_map('intval', $ids); - foreach ($ids as $position => $id) - { - $id_lang = Db::getInstance()->getValue('SELECT `id_lang` FROM `'._DB_PREFIX_.'tag` WHERE `id_tag`='.(int)$id); - $sql_values[] = '('.(int)$this->id.', '.(int)$id.', '.(int)$id_lang.')'; - } - $result = Db::getInstance()->execute(' + /** + * Webservice setter : set tag ids of current product for association + * + * @param $tag_ids tag ids + */ + public function setWsTags($tag_ids) + { + $ids = array(); + foreach ($tag_ids as $value) { + $ids[] = $value['id']; + } + if ($this->deleteWsTags()) { + if ($ids) { + $sql_values = ''; + $ids = array_map('intval', $ids); + foreach ($ids as $position => $id) { + $id_lang = Db::getInstance()->getValue('SELECT `id_lang` FROM `'._DB_PREFIX_.'tag` WHERE `id_tag`='.(int)$id); + $sql_values[] = '('.(int)$this->id.', '.(int)$id.', '.(int)$id_lang.')'; + } + $result = Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'product_tag` (`id_product`, `id_tag`, `id_lang`) VALUES '.implode(',', $sql_values) - ); - return $result; - } - } - return true; - } + ); + return $result; + } + } + return true; + } - /** - * Delete products tags entries without delete tags for webservice usage - * - * @return array Deletion result - */ - public function deleteWsTags() - { - return Db::getInstance()->delete('product_tag', 'id_product = '.(int)$this->id); - } + /** + * Delete products tags entries without delete tags for webservice usage + * + * @return array Deletion result + */ + public function deleteWsTags() + { + return Db::getInstance()->delete('product_tag', 'id_product = '.(int)$this->id); + } - public function getWsManufacturerName() - { - return Manufacturer::getNameById((int)$this->id_manufacturer); - } + public function getWsManufacturerName() + { + return Manufacturer::getNameById((int)$this->id_manufacturer); + } - public static function resetEcoTax() - { - return ObjectModel::updateMultishopTable('product', array( - 'ecotax' => 0, - )); - } + public static function resetEcoTax() + { + return ObjectModel::updateMultishopTable('product', array( + 'ecotax' => 0, + )); + } - /** - * Set Group reduction if needed - */ - public function setGroupReduction() - { - return GroupReduction::setProductReduction($this->id); - } + /** + * Set Group reduction if needed + */ + public function setGroupReduction() + { + return GroupReduction::setProductReduction($this->id); + } - /** - * Checks if reference exists - * @return bool - */ - public function existsRefInDatabase($reference) - { - $row = Db::getInstance()->getRow(' + /** + * Checks if reference exists + * @return bool + */ + public function existsRefInDatabase($reference) + { + $row = Db::getInstance()->getRow(' SELECT `reference` FROM `'._DB_PREFIX_.'product` p WHERE p.reference = "'.pSQL($reference).'"'); - return isset($row['reference']); - } + return isset($row['reference']); + } - /** - * Get all product attributes ids - * - * @since 1.5.0 - * @param int $id_product the id of the product - * @return array product attribute id list - */ - public static function getProductAttributesIds($id_product, $shop_only = false) - { - return Db::getInstance()->executeS(' + /** + * Get all product attributes ids + * + * @since 1.5.0 + * @param int $id_product the id of the product + * @return array product attribute id list + */ + public static function getProductAttributesIds($id_product, $shop_only = false) + { + return Db::getInstance()->executeS(' SELECT pa.id_product_attribute FROM `'._DB_PREFIX_.'product_attribute` pa'. - ($shop_only ? Shop::addSqlAssociation('product_attribute', 'pa') : '').' + ($shop_only ? Shop::addSqlAssociation('product_attribute', 'pa') : '').' WHERE pa.`id_product` = '.(int)$id_product); - } + } - /** - * Get label by lang and value by lang too - * @todo Remove existing module condition - * @param int $id_product - * @param int $product_attribute_id - * @return array - */ - public static function getAttributesParams($id_product, $id_product_attribute) - { - $id_lang = (int)Context::getContext()->language->id; - $id_shop = (int)Context::getContext()->shop->id; - $cache_id = 'Product::getAttributesParams_'.(int)$id_product.'-'.(int)$id_product_attribute.'-'.(int)$id_lang.'-'.(int)$id_shop; + /** + * Get label by lang and value by lang too + * @todo Remove existing module condition + * @param int $id_product + * @param int $product_attribute_id + * @return array + */ + public static function getAttributesParams($id_product, $id_product_attribute) + { + $id_lang = (int)Context::getContext()->language->id; + $id_shop = (int)Context::getContext()->shop->id; + $cache_id = 'Product::getAttributesParams_'.(int)$id_product.'-'.(int)$id_product_attribute.'-'.(int)$id_lang.'-'.(int)$id_shop; - // if blocklayered module is installed we check if user has set custom attribute name - if (Module::isInstalled('blocklayered') && Module::isEnabled('blocklayered')) - { - $nb_custom_values = Db::getInstance()->executeS(' + // if blocklayered module is installed we check if user has set custom attribute name + if (Module::isInstalled('blocklayered') && Module::isEnabled('blocklayered')) { + $nb_custom_values = Db::getInstance()->executeS(' SELECT DISTINCT la.`id_attribute`, la.`url_name` as `name` FROM `'._DB_PREFIX_.'attribute` a LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac @@ -5250,14 +5494,12 @@ class ProductCore extends ObjectModel AND pa.`id_product` = '.(int)$id_product.' AND pac.`id_product_attribute` = '.(int)$id_product_attribute); - if (!empty($nb_custom_values)) - { - $tab_id_attribute = array(); - foreach ($nb_custom_values as $attribute) - { - $tab_id_attribute[] = $attribute['id_attribute']; + if (!empty($nb_custom_values)) { + $tab_id_attribute = array(); + foreach ($nb_custom_values as $attribute) { + $tab_id_attribute[] = $attribute['id_attribute']; - $group = Db::getInstance()->executeS(' + $group = Db::getInstance()->executeS(' SELECT a.`id_attribute`, g.`id_attribute_group`, g.`url_name` as `group` FROM `'._DB_PREFIX_.'layered_indexable_attribute_group_lang_value` g LEFT JOIN `'._DB_PREFIX_.'attribute` a @@ -5265,9 +5507,8 @@ class ProductCore extends ObjectModel WHERE a.`id_attribute` = '.(int)$attribute['id_attribute'].' AND g.`id_lang` = '.(int)$id_lang.' AND g.`url_name` IS NOT NULL AND g.`url_name` != \'\''); - if (empty($group)) - { - $group = Db::getInstance()->executeS(' + if (empty($group)) { + $group = Db::getInstance()->executeS(' SELECT g.`id_attribute_group`, g.`name` as `group` FROM `'._DB_PREFIX_.'attribute_group_lang` g LEFT JOIN `'._DB_PREFIX_.'attribute` a @@ -5275,10 +5516,10 @@ class ProductCore extends ObjectModel WHERE a.`id_attribute` = '.(int)$attribute['id_attribute'].' AND g.`id_lang` = '.(int)$id_lang.' AND g.`name` IS NOT NULL'); - } - $result[] = array_merge($attribute, $group[0]); - } - $values_not_custom = Db::getInstance()->executeS(' + } + $result[] = array_merge($attribute, $group[0]); + } + $values_not_custom = Db::getInstance()->executeS(' SELECT DISTINCT a.`id_attribute`, a.`id_attribute_group`, al.`name`, agl.`name` as `group` FROM `'._DB_PREFIX_.'attribute` a LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al @@ -5293,13 +5534,12 @@ class ProductCore extends ObjectModel WHERE pa.`id_product` = '.(int)$id_product.' AND pac.id_product_attribute = '.(int)$id_product_attribute.' AND a.`id_attribute` NOT IN('.implode(', ', $tab_id_attribute).')'); - return array_merge($values_not_custom, $result); - } - } + return array_merge($values_not_custom, $result); + } + } - if (!Cache::isStored($cache_id)) - { - $result = Db::getInstance()->executeS(' + if (!Cache::isStored($cache_id)) { + $result = Db::getInstance()->executeS(' SELECT a.`id_attribute`, a.`id_attribute_group`, al.`name`, agl.`name` as `group` FROM `'._DB_PREFIX_.'attribute` a LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al @@ -5314,23 +5554,22 @@ class ProductCore extends ObjectModel WHERE pa.`id_product` = '.(int)$id_product.' AND pac.`id_product_attribute` = '.(int)$id_product_attribute.' AND agl.`id_lang` = '.(int)$id_lang); - Cache::store($cache_id, $result); - } - else - $result = Cache::retrieve($cache_id); - return $result; - } + Cache::store($cache_id, $result); + } else { + $result = Cache::retrieve($cache_id); + } + return $result; + } - /** - * @todo Remove existing module condition - * @param int $id_product - */ - public static function getAttributesInformationsByProduct($id_product) - { - // if blocklayered module is installed we check if user has set custom attribute name - if (Module::isInstalled('blocklayered') && Module::isEnabled('blocklayered')) - { - $nb_custom_values = Db::getInstance()->executeS(' + /** + * @todo Remove existing module condition + * @param int $id_product + */ + public static function getAttributesInformationsByProduct($id_product) + { + // if blocklayered module is installed we check if user has set custom attribute name + if (Module::isInstalled('blocklayered') && Module::isEnabled('blocklayered')) { + $nb_custom_values = Db::getInstance()->executeS(' SELECT DISTINCT la.`id_attribute`, la.`url_name` as `attribute` FROM `'._DB_PREFIX_.'attribute` a LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac @@ -5343,14 +5582,12 @@ class ProductCore extends ObjectModel WHERE la.`url_name` IS NOT NULL AND la.`url_name` != \'\' AND pa.`id_product` = '.(int)$id_product); - if (!empty($nb_custom_values)) - { - $tab_id_attribute = array(); - foreach ($nb_custom_values as $attribute) - { - $tab_id_attribute[] = $attribute['id_attribute']; + if (!empty($nb_custom_values)) { + $tab_id_attribute = array(); + foreach ($nb_custom_values as $attribute) { + $tab_id_attribute[] = $attribute['id_attribute']; - $group = Db::getInstance()->executeS(' + $group = Db::getInstance()->executeS(' SELECT g.`id_attribute_group`, g.`url_name` as `group` FROM `'._DB_PREFIX_.'layered_indexable_attribute_group_lang_value` g LEFT JOIN `'._DB_PREFIX_.'attribute` a @@ -5358,9 +5595,8 @@ class ProductCore extends ObjectModel WHERE a.`id_attribute` = '.(int)$attribute['id_attribute'].' AND g.`id_lang` = '.(int)Context::getContext()->language->id.' AND g.`url_name` IS NOT NULL AND g.`url_name` != \'\''); - if (empty($group)) - { - $group = Db::getInstance()->executeS(' + if (empty($group)) { + $group = Db::getInstance()->executeS(' SELECT g.`id_attribute_group`, g.`name` as `group` FROM `'._DB_PREFIX_.'attribute_group_lang` g LEFT JOIN `'._DB_PREFIX_.'attribute` a @@ -5368,10 +5604,10 @@ class ProductCore extends ObjectModel WHERE a.`id_attribute` = '.(int)$attribute['id_attribute'].' AND g.`id_lang` = '.(int)Context::getContext()->language->id.' AND g.`name` IS NOT NULL'); - } - $result[] = array_merge($attribute, $group[0]); - } - $values_not_custom = Db::getInstance()->executeS(' + } + $result[] = array_merge($attribute, $group[0]); + } + $values_not_custom = Db::getInstance()->executeS(' SELECT DISTINCT a.`id_attribute`, a.`id_attribute_group`, al.`name` as `attribute`, agl.`name` as `group` FROM `'._DB_PREFIX_.'attribute` a LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al @@ -5386,11 +5622,9 @@ class ProductCore extends ObjectModel '.Shop::addSqlAssociation('attribute', 'pac').' WHERE pa.`id_product` = '.(int)$id_product.' AND a.`id_attribute` NOT IN('.implode(', ', $tab_id_attribute).')'); - $result = array_merge($values_not_custom, $result); - } - else - { - $result = Db::getInstance()->executeS(' + $result = array_merge($values_not_custom, $result); + } else { + $result = Db::getInstance()->executeS(' SELECT DISTINCT a.`id_attribute`, a.`id_attribute_group`, al.`name` as `attribute`, agl.`name` as `group` FROM `'._DB_PREFIX_.'attribute` a LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al @@ -5404,11 +5638,9 @@ class ProductCore extends ObjectModel '.Shop::addSqlAssociation('product_attribute', 'pa').' '.Shop::addSqlAssociation('attribute', 'pac').' WHERE pa.`id_product` = '.(int)$id_product); - } - } - else - { - $result = Db::getInstance()->executeS(' + } + } else { + $result = Db::getInstance()->executeS(' SELECT DISTINCT a.`id_attribute`, a.`id_attribute_group`, al.`name` as `attribute`, agl.`name` as `group` FROM `'._DB_PREFIX_.'attribute` a LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al @@ -5422,306 +5654,313 @@ class ProductCore extends ObjectModel '.Shop::addSqlAssociation('product_attribute', 'pa').' '.Shop::addSqlAssociation('attribute', 'pac').' WHERE pa.`id_product` = '.(int)$id_product); - } - return $result; - } + } + return $result; + } - /** - * Get the combination url anchor of the product - * - * @param int $id_product_attribute - * @return string - */ - public function getAnchor($id_product_attribute, $with_id = false) - { - $attributes = Product::getAttributesParams($this->id, $id_product_attribute); - $anchor = '#'; - $sep = Configuration::get('PS_ATTRIBUTE_ANCHOR_SEPARATOR'); - foreach ($attributes as &$a) - { - foreach ($a as &$b) - $b = str_replace($sep, '_', Tools::link_rewrite($b)); - $anchor .= '/'.($with_id && isset($a['id_attribute']) && $a['id_attribute']? (int)$a['id_attribute'].$sep : '').$a['group'].$sep.$a['name']; - } - return $anchor; - } + /** + * Get the combination url anchor of the product + * + * @param int $id_product_attribute + * @return string + */ + public function getAnchor($id_product_attribute, $with_id = false) + { + $attributes = Product::getAttributesParams($this->id, $id_product_attribute); + $anchor = '#'; + $sep = Configuration::get('PS_ATTRIBUTE_ANCHOR_SEPARATOR'); + foreach ($attributes as &$a) { + foreach ($a as &$b) { + $b = str_replace($sep, '_', Tools::link_rewrite($b)); + } + $anchor .= '/'.($with_id && isset($a['id_attribute']) && $a['id_attribute']? (int)$a['id_attribute'].$sep : '').$a['group'].$sep.$a['name']; + } + return $anchor; + } - /** - * Gets the name of a given product, in the given lang - * - * @since 1.5.0 - * @param int $id_product - * @param int $id_product_attribute Optional - * @param int $id_lang Optional - * @return string - */ - public static function getProductName($id_product, $id_product_attribute = null, $id_lang = null) - { - // use the lang in the context if $id_lang is not defined - if (!$id_lang) - $id_lang = (int)Context::getContext()->language->id; + /** + * Gets the name of a given product, in the given lang + * + * @since 1.5.0 + * @param int $id_product + * @param int $id_product_attribute Optional + * @param int $id_lang Optional + * @return string + */ + public static function getProductName($id_product, $id_product_attribute = null, $id_lang = null) + { + // use the lang in the context if $id_lang is not defined + if (!$id_lang) { + $id_lang = (int)Context::getContext()->language->id; + } - // creates the query object - $query = new DbQuery(); + // creates the query object + $query = new DbQuery(); - // selects different names, if it is a combination - if ($id_product_attribute) - $query->select('IFNULL(CONCAT(pl.name, \' : \', GROUP_CONCAT(DISTINCT agl.`name`, \' - \', al.name SEPARATOR \', \')),pl.name) as name'); - else - $query->select('DISTINCT pl.name as name'); + // selects different names, if it is a combination + if ($id_product_attribute) { + $query->select('IFNULL(CONCAT(pl.name, \' : \', GROUP_CONCAT(DISTINCT agl.`name`, \' - \', al.name SEPARATOR \', \')),pl.name) as name'); + } else { + $query->select('DISTINCT pl.name as name'); + } - // adds joins & where clauses for combinations - if ($id_product_attribute) - { - $query->from('product_attribute', 'pa'); - $query->join(Shop::addSqlAssociation('product_attribute', 'pa')); - $query->innerJoin('product_lang', 'pl', 'pl.id_product = pa.id_product AND pl.id_lang = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl')); - $query->leftJoin('product_attribute_combination', 'pac', 'pac.id_product_attribute = pa.id_product_attribute'); - $query->leftJoin('attribute', 'atr', 'atr.id_attribute = pac.id_attribute'); - $query->leftJoin('attribute_lang', 'al', 'al.id_attribute = atr.id_attribute AND al.id_lang = '.(int)$id_lang); - $query->leftJoin('attribute_group_lang', 'agl', 'agl.id_attribute_group = atr.id_attribute_group AND agl.id_lang = '.(int)$id_lang); - $query->where('pa.id_product = '.(int)$id_product.' AND pa.id_product_attribute = '.(int)$id_product_attribute); - } - else // or just adds a 'where' clause for a simple product - { - $query->from('product_lang', 'pl'); - $query->where('pl.id_product = '.(int)$id_product); - $query->where('pl.id_lang = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl')); - } + // adds joins & where clauses for combinations + if ($id_product_attribute) { + $query->from('product_attribute', 'pa'); + $query->join(Shop::addSqlAssociation('product_attribute', 'pa')); + $query->innerJoin('product_lang', 'pl', 'pl.id_product = pa.id_product AND pl.id_lang = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl')); + $query->leftJoin('product_attribute_combination', 'pac', 'pac.id_product_attribute = pa.id_product_attribute'); + $query->leftJoin('attribute', 'atr', 'atr.id_attribute = pac.id_attribute'); + $query->leftJoin('attribute_lang', 'al', 'al.id_attribute = atr.id_attribute AND al.id_lang = '.(int)$id_lang); + $query->leftJoin('attribute_group_lang', 'agl', 'agl.id_attribute_group = atr.id_attribute_group AND agl.id_lang = '.(int)$id_lang); + $query->where('pa.id_product = '.(int)$id_product.' AND pa.id_product_attribute = '.(int)$id_product_attribute); + } else { + // or just adds a 'where' clause for a simple product - return Db::getInstance()->getValue($query); - } + $query->from('product_lang', 'pl'); + $query->where('pl.id_product = '.(int)$id_product); + $query->where('pl.id_lang = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl')); + } - public function addWs($autodate = true, $null_values = false) - { - $success = $this->add($autodate, $null_values); - if ($success && Configuration::get('PS_SEARCH_INDEXATION')) - Search::indexation(false, $this->id); - return $success; - } + return Db::getInstance()->getValue($query); + } - public function updateWs($null_values = false) - { - $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; - } + public function addWs($autodate = true, $null_values = false) + { + $success = $this->add($autodate, $null_values); + if ($success && Configuration::get('PS_SEARCH_INDEXATION')) { + Search::indexation(false, $this->id); + } + return $success; + } - /** - * For a given product, returns its real quantity - * - * @since 1.5.0 - * @param int $id_product - * @param int $id_product_attribute - * @param int $id_warehouse - * @param int $id_shop - * @return int real_quantity - */ - public static function getRealQuantity($id_product, $id_product_attribute = 0, $id_warehouse = 0, $id_shop = null) - { - static $manager = null; + public function updateWs($null_values = false) + { + $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; + } - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && is_null($manager)) - $manager = StockManagerFactory::getManager(); + /** + * For a given product, returns its real quantity + * + * @since 1.5.0 + * @param int $id_product + * @param int $id_product_attribute + * @param int $id_warehouse + * @param int $id_shop + * @return int real_quantity + */ + public static function getRealQuantity($id_product, $id_product_attribute = 0, $id_warehouse = 0, $id_shop = null) + { + static $manager = null; - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && Product::usesAdvancedStockManagement($id_product) && - StockAvailable::dependsOnStock($id_product, $id_shop)) - return $manager->getProductRealQuantities($id_product, $id_product_attribute, $id_warehouse, true); - else - return StockAvailable::getQuantityAvailableByProduct($id_product, $id_product_attribute, $id_shop); - } + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && is_null($manager)) { + $manager = StockManagerFactory::getManager(); + } - /** - * For a given product, tells if it uses the advanced stock management - * - * @since 1.5.0 - * @param int $id_product - * @return bool - */ - public static function usesAdvancedStockManagement($id_product) - { - $query = new DbQuery; - $query->select('product_shop.advanced_stock_management'); - $query->from('product', 'p'); - $query->join(Shop::addSqlAssociation('product', 'p')); - $query->where('p.id_product = '.(int)$id_product); + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && Product::usesAdvancedStockManagement($id_product) && + StockAvailable::dependsOnStock($id_product, $id_shop)) { + return $manager->getProductRealQuantities($id_product, $id_product_attribute, $id_warehouse, true); + } else { + return StockAvailable::getQuantityAvailableByProduct($id_product, $id_product_attribute, $id_shop); + } + } - return (bool)Db::getInstance()->getValue($query); - } + /** + * For a given product, tells if it uses the advanced stock management + * + * @since 1.5.0 + * @param int $id_product + * @return bool + */ + public static function usesAdvancedStockManagement($id_product) + { + $query = new DbQuery; + $query->select('product_shop.advanced_stock_management'); + $query->from('product', 'p'); + $query->join(Shop::addSqlAssociation('product', 'p')); + $query->where('p.id_product = '.(int)$id_product); - /** - * This method allows to flush price cache - * - * @since 1.5.0 - */ - public static function flushPriceCache() - { - self::$_prices = array(); - self::$_pricesLevel2 = array(); - } + return (bool)Db::getInstance()->getValue($query); + } - /** - * Get list of parent categories - * - * @since 1.5.0 - * @param int $id_lang - * @return array - */ - public function getParentCategories($id_lang = null) - { - if (!$id_lang) - $id_lang = Context::getContext()->language->id; + /** + * This method allows to flush price cache + * + * @since 1.5.0 + */ + public static function flushPriceCache() + { + self::$_prices = array(); + self::$_pricesLevel2 = array(); + } - $interval = Category::getInterval($this->id_category_default); - $sql = new DbQuery(); - $sql->from('category', 'c'); - $sql->leftJoin('category_lang', 'cl', 'c.id_category = cl.id_category AND id_lang = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('cl')); - $sql->where('c.nleft <= '.(int)$interval['nleft'].' AND c.nright >= '.(int)$interval['nright']); - $sql->orderBy('c.nleft'); + /** + * Get list of parent categories + * + * @since 1.5.0 + * @param int $id_lang + * @return array + */ + public function getParentCategories($id_lang = null) + { + if (!$id_lang) { + $id_lang = Context::getContext()->language->id; + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - } + $interval = Category::getInterval($this->id_category_default); + $sql = new DbQuery(); + $sql->from('category', 'c'); + $sql->leftJoin('category_lang', 'cl', 'c.id_category = cl.id_category AND id_lang = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('cl')); + $sql->where('c.nleft <= '.(int)$interval['nleft'].' AND c.nright >= '.(int)$interval['nright']); + $sql->orderBy('c.nleft'); - /** - * Fill the variables used for stock management - */ - public function loadStockData() - { - if (Validate::isLoadedObject($this)) - { - // By default, the product quantity correspond to the available quantity to sell in the current shop - $this->quantity = StockAvailable::getQuantityAvailableByProduct($this->id, 0); - $this->out_of_stock = StockAvailable::outOfStock($this->id); - $this->depends_on_stock = StockAvailable::dependsOnStock($this->id); - if (Context::getContext()->shop->getContext() == Shop::CONTEXT_GROUP && Context::getContext()->shop->getContextShopGroup()->share_stock == 1) - $this->advanced_stock_management = $this->useAdvancedStockManagement(); - } - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + } - public function useAdvancedStockManagement() - { - return Db::getInstance()->getValue(' + /** + * Fill the variables used for stock management + */ + public function loadStockData() + { + if (Validate::isLoadedObject($this)) { + // By default, the product quantity correspond to the available quantity to sell in the current shop + $this->quantity = StockAvailable::getQuantityAvailableByProduct($this->id, 0); + $this->out_of_stock = StockAvailable::outOfStock($this->id); + $this->depends_on_stock = StockAvailable::dependsOnStock($this->id); + if (Context::getContext()->shop->getContext() == Shop::CONTEXT_GROUP && Context::getContext()->shop->getContextShopGroup()->share_stock == 1) { + $this->advanced_stock_management = $this->useAdvancedStockManagement(); + } + } + } + + public function useAdvancedStockManagement() + { + return Db::getInstance()->getValue(' SELECT `advanced_stock_management` FROM '._DB_PREFIX_.'product_shop WHERE id_product='.(int)$this->id.Shop::addSqlRestriction() - ); - } + ); + } - public function setAdvancedStockManagement($value) - { - $this->advanced_stock_management = (int)$value; - if (Context::getContext()->shop->getContext() == Shop::CONTEXT_GROUP && Context::getContext()->shop->getContextShopGroup()->share_stock == 1) - Db::getInstance()->execute(' + public function setAdvancedStockManagement($value) + { + $this->advanced_stock_management = (int)$value; + if (Context::getContext()->shop->getContext() == Shop::CONTEXT_GROUP && Context::getContext()->shop->getContextShopGroup()->share_stock == 1) { + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'product_shop` SET `advanced_stock_management`='.(int)$value.' WHERE id_product='.(int)$this->id.Shop::addSqlRestriction() - ); - else - { - $this->setFieldsToUpdate(array('advanced_stock_management' => true)); - $this->save(); - } - } + ); + } else { + $this->setFieldsToUpdate(array('advanced_stock_management' => true)); + $this->save(); + } + } - /** - * get the default category according to the shop - */ - public function getDefaultCategory() - { - $default_category = Db::getInstance()->getValue(' + /** + * get the default category according to the shop + */ + public function getDefaultCategory() + { + $default_category = Db::getInstance()->getValue(' SELECT product_shop.`id_category_default` FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' WHERE p.`id_product` = '.(int)$this->id); - if (!$default_category) - return array('id_category_default' => Context::getContext()->shop->id_category); - else - return $default_category; + if (!$default_category) { + return array('id_category_default' => Context::getContext()->shop->id_category); + } else { + return $default_category; + } + } - } - - public static function getShopsByProduct($id_product) - { - return Db::getInstance()->executeS(' + public static function getShopsByProduct($id_product) + { + return Db::getInstance()->executeS(' SELECT `id_shop` FROM `'._DB_PREFIX_.'product_shop` WHERE `id_product` = '.(int)$id_product); - } + } - /** - * Remove all downloadable files for product and its attributes - * - * @return bool - */ - public function deleteDownload() - { - $result = true; - $collection_download = new PrestaShopCollection('ProductDownload'); - $collection_download->where('id_product', '=', $this->id); - foreach ($collection_download as $product_download) - { - /** @var ProductDownload $product_download */ - $result &= $product_download->delete($product_download->checkFile()); - } - return $result; - } + /** + * Remove all downloadable files for product and its attributes + * + * @return bool + */ + public function deleteDownload() + { + $result = true; + $collection_download = new PrestaShopCollection('ProductDownload'); + $collection_download->where('id_product', '=', $this->id); + foreach ($collection_download as $product_download) { + /** @var ProductDownload $product_download */ + $result &= $product_download->delete($product_download->checkFile()); + } + return $result; + } - /** - * @deprecated 1.5.0.10 - * @see Product::getAttributeCombinations() - * @param int $id_lang - */ - public function getAttributeCombinaisons($id_lang) - { - Tools::displayAsDeprecated('Use Product::getAttributeCombinations($id_lang)'); - return $this->getAttributeCombinations($id_lang); - } + /** + * @deprecated 1.5.0.10 + * @see Product::getAttributeCombinations() + * @param int $id_lang + */ + public function getAttributeCombinaisons($id_lang) + { + Tools::displayAsDeprecated('Use Product::getAttributeCombinations($id_lang)'); + return $this->getAttributeCombinations($id_lang); + } - /** - * @deprecated 1.5.0.10 - * @see Product::deleteAttributeCombination() - * @param int $id_product_attribute - */ - public function deleteAttributeCombinaison($id_product_attribute) - { - Tools::displayAsDeprecated('Use Product::deleteAttributeCombination($id_product_attribute)'); - return $this->deleteAttributeCombination($id_product_attribute); - } + /** + * @deprecated 1.5.0.10 + * @see Product::deleteAttributeCombination() + * @param int $id_product_attribute + */ + public function deleteAttributeCombinaison($id_product_attribute) + { + Tools::displayAsDeprecated('Use Product::deleteAttributeCombination($id_product_attribute)'); + return $this->deleteAttributeCombination($id_product_attribute); + } - /** - * Get the product type (simple, virtual, pack) - * @since in 1.5.0 - * - * @return int - */ - public function getType() - { - if (!$this->id) - return Product::PTYPE_SIMPLE; - if (Pack::isPack($this->id)) - return Product::PTYPE_PACK; - if ($this->is_virtual) - return Product::PTYPE_VIRTUAL; + /** + * Get the product type (simple, virtual, pack) + * @since in 1.5.0 + * + * @return int + */ + public function getType() + { + if (!$this->id) { + return Product::PTYPE_SIMPLE; + } + if (Pack::isPack($this->id)) { + return Product::PTYPE_PACK; + } + if ($this->is_virtual) { + return Product::PTYPE_VIRTUAL; + } - return Product::PTYPE_SIMPLE; - } + return Product::PTYPE_SIMPLE; + } - public function hasAttributesInOtherShops() - { - return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public function hasAttributesInOtherShops() + { + return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT pa.id_product_attribute FROM `'._DB_PREFIX_.'product_attribute` pa LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` pas ON (pa.`id_product_attribute` = pas.`id_product_attribute`) WHERE pa.`id_product` = '.(int)$this->id - ); - } + ); + } - public static function getIdTaxRulesGroupMostUsed() - { - return Db::getInstance()->getValue(' + public static function getIdTaxRulesGroupMostUsed() + { + return Db::getInstance()->getValue(' SELECT id_tax_rules_group FROM ( SELECT COUNT(*) n, product_shop.id_tax_rules_group @@ -5733,100 +5972,107 @@ class ProductCore extends ObjectModel ORDER BY n DESC LIMIT 1 ) most_used' - ); - } + ); + } - /** - * For a given ean13 reference, returns the corresponding id - * - * @param string $ean13 - * @return int id - */ - public static function getIdByEan13($ean13) - { - if (empty($ean13)) - return 0; + /** + * For a given ean13 reference, returns the corresponding id + * + * @param string $ean13 + * @return int id + */ + public static function getIdByEan13($ean13) + { + if (empty($ean13)) { + return 0; + } - if (!Validate::isEan13($ean13)) - return 0; + if (!Validate::isEan13($ean13)) { + return 0; + } - $query = new DbQuery(); - $query->select('p.id_product'); - $query->from('product', 'p'); - $query->where('p.ean13 = \''.pSQL($ean13).'\''); + $query = new DbQuery(); + $query->select('p.id_product'); + $query->from('product', 'p'); + $query->where('p.ean13 = \''.pSQL($ean13).'\''); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } - public function getWsType() - { - $type_information = array( - Product::PTYPE_SIMPLE => 'simple', - Product::PTYPE_PACK => 'pack', - Product::PTYPE_VIRTUAL => 'virtual', - ); - return $type_information[$this->getType()]; - } + public function getWsType() + { + $type_information = array( + Product::PTYPE_SIMPLE => 'simple', + Product::PTYPE_PACK => 'pack', + Product::PTYPE_VIRTUAL => 'virtual', + ); + return $type_information[$this->getType()]; + } - /* - Create the link rewrite if not exists or invalid on product creation - */ - public function modifierWsLinkRewrite() - { - foreach ($this->name as $id_lang => $name) - { - if (empty($this->link_rewrite[$id_lang])) - $this->link_rewrite[$id_lang] = Tools::link_rewrite($name); - elseif (!Validate::isLinkRewrite($this->link_rewrite[$id_lang])) - $this->link_rewrite[$id_lang] = Tools::link_rewrite($this->link_rewrite[$id_lang]); - } + /* + Create the link rewrite if not exists or invalid on product creation + */ + public function modifierWsLinkRewrite() + { + foreach ($this->name as $id_lang => $name) { + if (empty($this->link_rewrite[$id_lang])) { + $this->link_rewrite[$id_lang] = Tools::link_rewrite($name); + } elseif (!Validate::isLinkRewrite($this->link_rewrite[$id_lang])) { + $this->link_rewrite[$id_lang] = Tools::link_rewrite($this->link_rewrite[$id_lang]); + } + } - return true; - } + return true; + } - public function getWsProductBundle() - { - return Db::getInstance()->executeS('SELECT id_product_item as id, quantity FROM '._DB_PREFIX_.'pack WHERE id_product_pack = '.(int)$this->id); - } + public function getWsProductBundle() + { + return Db::getInstance()->executeS('SELECT id_product_item as id, quantity FROM '._DB_PREFIX_.'pack WHERE id_product_pack = '.(int)$this->id); + } - public function setWsType($type_str) - { - $reverse_type_information = array( - 'simple' => Product::PTYPE_SIMPLE, - 'pack' => Product::PTYPE_PACK, - 'virtual' => Product::PTYPE_VIRTUAL, - ); + public function setWsType($type_str) + { + $reverse_type_information = array( + 'simple' => Product::PTYPE_SIMPLE, + 'pack' => Product::PTYPE_PACK, + 'virtual' => Product::PTYPE_VIRTUAL, + ); - if (!isset($reverse_type_information[$type_str])) - return false; + if (!isset($reverse_type_information[$type_str])) { + return false; + } - $type = $reverse_type_information[$type_str]; + $type = $reverse_type_information[$type_str]; - if (Pack::isPack((int)$this->id) && $type != Product::PTYPE_PACK) - Pack::deleteItems($this->id); + if (Pack::isPack((int)$this->id) && $type != Product::PTYPE_PACK) { + Pack::deleteItems($this->id); + } - $this->cache_is_pack = ($type == Product::PTYPE_PACK); - $this->is_virtual = ($type == Product::PTYPE_VIRTUAL); + $this->cache_is_pack = ($type == Product::PTYPE_PACK); + $this->is_virtual = ($type == Product::PTYPE_VIRTUAL); - return true; - } + return true; + } - public function setWsProductBundle($items) - { - if ($this->is_virtual) - return false; + public function setWsProductBundle($items) + { + if ($this->is_virtual) { + return false; + } - Pack::deleteItems($this->id); + Pack::deleteItems($this->id); - foreach ($items as $item) - if ((int)$item['id'] > 0) - Pack::addItem($this->id, (int)$item['id'], (int)$item['quantity']); - return true; - } + foreach ($items as $item) { + if ((int)$item['id'] > 0) { + Pack::addItem($this->id, (int)$item['id'], (int)$item['quantity']); + } + } + return true; + } - public function isColorUnavailable($id_attribute, $id_shop) - { - return Db::getInstance()->getValue(' + public function isColorUnavailable($id_attribute, $id_shop) + { + return Db::getInstance()->getValue(' SELECT sa.id_product_attribute FROM '._DB_PREFIX_.'stock_available sa WHERE id_product='.(int)$this->id.' AND quantity <= 0 @@ -5840,17 +6086,17 @@ class ProductCore extends ObjectModel ON (pac.id_product_attribute AND product_attribute_shop.id_product_attribute) WHERE sa.id_product_attribute = pa.id_product_attribute AND pa.id_product='.(int)$this->id.' AND pac.id_attribute='.(int)$id_attribute.' )' - ); - } + ); + } - public static function getColorsListCacheId($id_product) - { - return 'productlist_colors|'.(int)$id_product.'|'.(int)Context::getContext()->shop->id.'|'.(int)Context::getContext()->cookie->id_lang; - } + public static function getColorsListCacheId($id_product) + { + return 'productlist_colors|'.(int)$id_product.'|'.(int)Context::getContext()->shop->id.'|'.(int)Context::getContext()->cookie->id_lang; + } - public static function setPackStockType($id_product, $pack_stock_type) - { - return Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'product p + public static function setPackStockType($id_product, $pack_stock_type) + { + return Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'product p '.Shop::addSqlAssociation('product', 'p').' SET product_shop.pack_stock_type = '.(int)$pack_stock_type.' WHERE p.`id_product` = '.(int)$id_product); - } + } } diff --git a/classes/ProductDownload.php b/classes/ProductDownload.php index 8f897a39..a86a7ed8 100644 --- a/classes/ProductDownload.php +++ b/classes/ProductDownload.php @@ -26,285 +26,293 @@ class ProductDownloadCore extends ObjectModel { - /** @var int Product id which download belongs */ - public $id_product; + /** @var int Product id which download belongs */ + public $id_product; - /** @var string DisplayFilename the name which appear */ - public $display_filename; + /** @var string DisplayFilename the name which appear */ + public $display_filename; - /** @var string PhysicallyFilename the name of the file on hard disk */ - public $filename; + /** @var string PhysicallyFilename the name of the file on hard disk */ + public $filename; - /** @var string DateDeposit when the file is upload */ - public $date_add; + /** @var string DateDeposit when the file is upload */ + public $date_add; - /** @var string DateExpiration deadline of the file */ - public $date_expiration; + /** @var string DateExpiration deadline of the file */ + public $date_expiration; - /** @var string NbDaysAccessible how many days the customer can access to file */ - public $nb_days_accessible; + /** @var string NbDaysAccessible how many days the customer can access to file */ + public $nb_days_accessible; - /** @var string NbDownloadable how many time the customer can download the file */ - public $nb_downloadable; + /** @var string NbDownloadable how many time the customer can download the file */ + public $nb_downloadable; - /** @var bool Active if file is accessible or not */ - public $active = 1; + /** @var bool Active if file is accessible or not */ + public $active = 1; - /** @var bool is_shareable indicates whether the product can be shared */ - public $is_shareable = 0; + /** @var bool is_shareable indicates whether the product can be shared */ + public $is_shareable = 0; - protected static $_productIds = array(); + protected static $_productIds = array(); - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'product_download', - 'primary' => 'id_product_download', - 'fields' => array( - 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'display_filename' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 255), - 'filename' => array('type' => self::TYPE_STRING, 'validate' => 'isSha1', 'size' => 255), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_expiration' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'nb_days_accessible' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'size' => 10), - 'nb_downloadable' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'size' => 10), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'is_shareable' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'product_download', + 'primary' => 'id_product_download', + 'fields' => array( + 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'display_filename' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 255), + 'filename' => array('type' => self::TYPE_STRING, 'validate' => 'isSha1', 'size' => 255), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_expiration' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'nb_days_accessible' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'size' => 10), + 'nb_downloadable' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'size' => 10), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'is_shareable' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + ), + ); - /** - * Build a virtual product - * - * @param int $id_product_download Existing productDownload id in order to load object (optional) - */ - public function __construct($id_product_download = null) - { - parent::__construct($id_product_download); - // @TODO check if the file is present on hard drive - } + /** + * Build a virtual product + * + * @param int $id_product_download Existing productDownload id in order to load object (optional) + */ + public function __construct($id_product_download = null) + { + parent::__construct($id_product_download); + // @TODO check if the file is present on hard drive + } - /** - * @see ObjectModel::getFields() - * @return array - */ - public function getFields() - { - $fields = parent::getFields(); - if (!$fields['date_expiration']) - $fields['date_expiration'] = '0000-00-00 00:00:00'; + /** + * @see ObjectModel::getFields() + * @return array + */ + public function getFields() + { + $fields = parent::getFields(); + if (!$fields['date_expiration']) { + $fields['date_expiration'] = '0000-00-00 00:00:00'; + } - return $fields; - } + return $fields; + } - public function add($autodate = true, $null_values = false) - { - return (bool)parent::add($autodate, $null_values); - } + public function add($autodate = true, $null_values = false) + { + return (bool)parent::add($autodate, $null_values); + } - public function update($null_values = false) - { - if (parent::update($null_values)) - { - // Refresh cache of feature detachable because the row can be deactive - Configuration::updateGlobalValue('PS_VIRTUAL_PROD_FEATURE_ACTIVE', ProductDownload::isCurrentlyUsed($this->def['table'], true)); - return true; - } - return false; - } + public function update($null_values = false) + { + if (parent::update($null_values)) { + // Refresh cache of feature detachable because the row can be deactive + Configuration::updateGlobalValue('PS_VIRTUAL_PROD_FEATURE_ACTIVE', ProductDownload::isCurrentlyUsed($this->def['table'], true)); + return true; + } + return false; + } - public function delete($delete_file = false) - { - $result = parent::delete(); - if ($result && $delete_file) - return $this->deleteFile(); - return $result; - } + public function delete($delete_file = false) + { + $result = parent::delete(); + if ($result && $delete_file) { + return $this->deleteFile(); + } + return $result; + } - /** - * Delete the file - * @param int $id_product_download : if we need to delete a specific product attribute file - * - * @return bool - */ - public function deleteFile($id_product_download = null) - { - if (!$this->checkFile()) - return false; + /** + * Delete the file + * @param int $id_product_download : if we need to delete a specific product attribute file + * + * @return bool + */ + public function deleteFile($id_product_download = null) + { + if (!$this->checkFile()) { + return false; + } - return unlink(_PS_DOWNLOAD_DIR_.$this->filename) - && Db::getInstance()->delete('product_download', 'id_product_download = '.(int)$id_product_download); - } + return unlink(_PS_DOWNLOAD_DIR_.$this->filename) + && Db::getInstance()->delete('product_download', 'id_product_download = '.(int)$id_product_download); + } - /** - * Check if file exists - * - * @return bool - */ - public function checkFile() - { - if (!$this->filename) return false; - return file_exists(_PS_DOWNLOAD_DIR_.$this->filename); - } + /** + * Check if file exists + * + * @return bool + */ + public function checkFile() + { + if (!$this->filename) { + return false; + } + return file_exists(_PS_DOWNLOAD_DIR_.$this->filename); + } - /** - * Check if download repository is writable - * - * @return bool - */ - public static function checkWritableDir() - { - return is_writable(_PS_DOWNLOAD_DIR_); - } + /** + * Check if download repository is writable + * + * @return bool + */ + public static function checkWritableDir() + { + return is_writable(_PS_DOWNLOAD_DIR_); + } - /** - * Return the id_product_download from an id_product - * - * @param int $id_product Product the id - * @return int Product the id for this virtual product - */ - public static function getIdFromIdProduct($id_product) - { - if (!ProductDownload::isFeatureActive()) - return false; - if (array_key_exists((int)$id_product, self::$_productIds)) - return self::$_productIds[$id_product]; - self::$_productIds[$id_product] = (int)Db::getInstance()->getValue(' + /** + * Return the id_product_download from an id_product + * + * @param int $id_product Product the id + * @return int Product the id for this virtual product + */ + public static function getIdFromIdProduct($id_product) + { + if (!ProductDownload::isFeatureActive()) { + return false; + } + if (array_key_exists((int)$id_product, self::$_productIds)) { + return self::$_productIds[$id_product]; + } + self::$_productIds[$id_product] = (int)Db::getInstance()->getValue(' SELECT `id_product_download` FROM `'._DB_PREFIX_.'product_download` WHERE `id_product` = '.(int)$id_product.' AND `active` = 1 ORDER BY `id_product_download` DESC'); - return self::$_productIds[$id_product]; - } + return self::$_productIds[$id_product]; + } - /** - * Return the display filename from a physical filename - * - * @since 1.5.0.1 - * - * @param string $filename Filename physically - * @return int Product the id for this virtual product - * - */ - public static function getIdFromFilename($filename) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Return the display filename from a physical filename + * + * @since 1.5.0.1 + * + * @param string $filename Filename physically + * @return int Product the id for this virtual product + * + */ + public static function getIdFromFilename($filename) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_product_download` FROM `'._DB_PREFIX_.'product_download` WHERE `filename` = \''.pSQL($filename).'\''); - } + } - /** - * Return the filename from an id_product - * - * @param int $id_product Product the id - * @return string Filename the filename for this virtual product - */ - public static function getFilenameFromIdProduct($id_product) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Return the filename from an id_product + * + * @param int $id_product Product the id + * @return string Filename the filename for this virtual product + */ + public static function getFilenameFromIdProduct($id_product) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `filename` FROM `'._DB_PREFIX_.'product_download` WHERE `id_product` = '.(int)$id_product.' AND `active` = 1 '); - } + } - /** - * Return the display filename from a physical filename - * - * @param string $filename Filename physically - * @return string Filename the display filename for this virtual product - */ - public static function getFilenameFromFilename($filename) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Return the display filename from a physical filename + * + * @param string $filename Filename physically + * @return string Filename the display filename for this virtual product + */ + public static function getFilenameFromFilename($filename) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `display_filename` FROM `'._DB_PREFIX_.'product_download` WHERE `filename` = \''.pSQL($filename).'\''); - } + } - /** - * Return html link - * - * @param string $class CSS selector (optionnal) - * @param bool $admin specific to backend (optionnal) - * @param string $hash hash code in table order detail (optionnal) - * @return string Html all the code for print a link to the file - */ - public function getTextLink($admin = true, $hash = false) - { - $key = $this->filename.'-'.($hash ? $hash : 'orderdetail'); - $link = ($admin) ? 'get-file-admin.php?' : _PS_BASE_URL_.__PS_BASE_URI__.'index.php?controller=get-file&'; - $link .= ($admin) ? 'file='.$this->filename : 'key='.$key; - return $link; - } + /** + * Return html link + * + * @param string $class CSS selector (optionnal) + * @param bool $admin specific to backend (optionnal) + * @param string $hash hash code in table order detail (optionnal) + * @return string Html all the code for print a link to the file + */ + public function getTextLink($admin = true, $hash = false) + { + $key = $this->filename.'-'.($hash ? $hash : 'orderdetail'); + $link = ($admin) ? 'get-file-admin.php?' : _PS_BASE_URL_.__PS_BASE_URI__.'index.php?controller=get-file&'; + $link .= ($admin) ? 'file='.$this->filename : 'key='.$key; + return $link; + } - /** - * Return html link - * - * @param string $class CSS selector - * @param bool $admin specific to backend - * @param bool $hash hash code in table order detail - * @return string Html all the code for print a link to the file - */ - public function getHtmlLink($class = false, $admin = true, $hash = false) - { - $link = $this->getTextLink($admin, $hash); - $html = '<a href="'.$link.'" title=""'; - if ($class) - $html .= ' class="'.$class.'"'; - $html .= '>'.$this->display_filename.'</a>'; - return $html; - } + /** + * Return html link + * + * @param string $class CSS selector + * @param bool $admin specific to backend + * @param bool $hash hash code in table order detail + * @return string Html all the code for print a link to the file + */ + public function getHtmlLink($class = false, $admin = true, $hash = false) + { + $link = $this->getTextLink($admin, $hash); + $html = '<a href="'.$link.'" title=""'; + if ($class) { + $html .= ' class="'.$class.'"'; + } + $html .= '>'.$this->display_filename.'</a>'; + return $html; + } - /** - * Return a deadline - * - * @return string Datetime in SQL format - */ - public function getDeadline() - { - if (!(int)$this->nb_days_accessible) - return '0000-00-00 00:00:00'; - $timestamp = strtotime('+'.(int)$this->nb_days_accessible.' day'); - return date('Y-m-d H:i:s', $timestamp); - } + /** + * Return a deadline + * + * @return string Datetime in SQL format + */ + public function getDeadline() + { + if (!(int)$this->nb_days_accessible) { + return '0000-00-00 00:00:00'; + } + $timestamp = strtotime('+'.(int)$this->nb_days_accessible.' day'); + return date('Y-m-d H:i:s', $timestamp); + } - /** - * Return a hash for control download access - * - * @return string Hash ready to insert in database - */ - public function getHash() - { - // TODO check if this hash not already in database - return sha1(microtime().$this->id); - } + /** + * Return a hash for control download access + * + * @return string Hash ready to insert in database + */ + public function getHash() + { + // TODO check if this hash not already in database + return sha1(microtime().$this->id); + } - /** - * Return a sha1 filename - * - * @return string Sha1 unique filename - */ - public static function getNewFilename() - { - do - $filename = sha1(microtime()); - while (file_exists(_PS_DOWNLOAD_DIR_.$filename)); - return $filename; - } + /** + * Return a sha1 filename + * + * @return string Sha1 unique filename + */ + public static function getNewFilename() + { + do { + $filename = sha1(microtime()); + } while (file_exists(_PS_DOWNLOAD_DIR_.$filename)); + return $filename; + } - /** - * This method is allow to know if a feature is used or active - * @since 1.5.0.1 - * @return bool - */ - public static function isFeatureActive() - { - return Configuration::get('PS_VIRTUAL_PROD_FEATURE_ACTIVE'); - } + /** + * This method is allow to know if a feature is used or active + * @since 1.5.0.1 + * @return bool + */ + public static function isFeatureActive() + { + return Configuration::get('PS_VIRTUAL_PROD_FEATURE_ACTIVE'); + } } diff --git a/classes/ProductSale.php b/classes/ProductSale.php index a570ecc3..9c44a9a4 100644 --- a/classes/ProductSale.php +++ b/classes/ProductSale.php @@ -26,65 +26,71 @@ class ProductSaleCore { - /* - ** Fill the `product_sale` SQL table with data from `order_detail` - ** @return bool True on success - */ - public static function fillProductSales() - { - $sql = 'REPLACE INTO '._DB_PREFIX_.'product_sale + /* + ** Fill the `product_sale` SQL table with data from `order_detail` + ** @return bool True on success + */ + public static function fillProductSales() + { + $sql = 'REPLACE INTO '._DB_PREFIX_.'product_sale (`id_product`, `quantity`, `sale_nbr`, `date_upd`) SELECT od.product_id, SUM(od.product_quantity), COUNT(od.product_id), NOW() FROM '._DB_PREFIX_.'order_detail od GROUP BY od.product_id'; - return Db::getInstance()->execute($sql); - } + return Db::getInstance()->execute($sql); + } - /* - ** Get number of actives products sold - ** @return int number of actives products listed in product_sales - */ - public static function getNbSales() - { - $sql = 'SELECT COUNT(ps.`id_product`) AS nb + /* + ** Get number of actives products sold + ** @return int number of actives products listed in product_sales + */ + public static function getNbSales() + { + $sql = 'SELECT COUNT(ps.`id_product`) AS nb FROM `'._DB_PREFIX_.'product_sale` ps LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = ps.`id_product` '.Shop::addSqlAssociation('product', 'p', false).' WHERE product_shop.`active` = 1'; - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); - } + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); + } - /* - ** Get required informations on best sales products - ** - ** @param int $id_lang Language id - ** @param int $page_number Start from (optional) - ** @param int $nb_products Number of products to return (optional) - ** @return array from Product::getProductProperties - */ - public static function getBestSales($id_lang, $page_number = 0, $nb_products = 10, $order_by = null, $order_way = null) - { - $context = Context::getContext(); - if ($page_number < 0) $page_number = 0; - if ($nb_products < 1) $nb_products = 10; - $final_order_by = $order_by; - $order_table = ''; + /* + ** Get required informations on best sales products + ** + ** @param int $id_lang Language id + ** @param int $page_number Start from (optional) + ** @param int $nb_products Number of products to return (optional) + ** @return array from Product::getProductProperties + */ + public static function getBestSales($id_lang, $page_number = 0, $nb_products = 10, $order_by = null, $order_way = null) + { + $context = Context::getContext(); + if ($page_number < 0) { + $page_number = 0; + } + if ($nb_products < 1) { + $nb_products = 10; + } + $final_order_by = $order_by; + $order_table = ''; - if (is_null($order_by)) - { - $order_by = 'quantity'; - $order_table = 'ps'; - } + if (is_null($order_by)) { + $order_by = 'quantity'; + $order_table = 'ps'; + } - if ($order_by == 'date_add' || $order_by == 'date_upd') - $order_table = 'product_shop'; + if ($order_by == 'date_add' || $order_by == 'date_upd') { + $order_table = 'product_shop'; + } - if (is_null($order_way) || $order_by == 'sales') $order_way = 'DESC'; + if (is_null($order_way) || $order_by == 'sales') { + $order_way = 'DESC'; + } - $interval = Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20; + $interval = Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20; - // no group by needed : there's only one attribute with default_on=1 for a given id_product + shop - // same for image with cover=1 - $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, + // no group by needed : there's only one attribute with default_on=1 for a given id_product + shop + // same for image with cover=1 + $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, '.(Combination::isFeatureActive()?'product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity,IFNULL(product_attribute_shop.id_product_attribute,0) id_product_attribute,':'').' pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, pl.`available_now`, pl.`available_later`, @@ -93,14 +99,15 @@ class ProductSaleCore ps.`quantity` AS sales, t.`rate`, pl.`meta_keywords`, pl.`meta_title`, pl.`meta_description`, DATEDIFF(p.`date_add`, DATE_SUB("'.date('Y-m-d').' 00:00:00", INTERVAL '.(int)$interval.' DAY)) > 0 AS new' - .' FROM `'._DB_PREFIX_.'product_sale` ps + .' FROM `'._DB_PREFIX_.'product_sale` ps LEFT JOIN `'._DB_PREFIX_.'product` p ON ps.`id_product` = p.`id_product` '.Shop::addSqlAssociation('product', 'p', false); - if (Combination::isFeatureActive()) - $sql .= ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop + if (Combination::isFeatureActive()) { + $sql .= ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop ON (p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='.(int)$context->shop->id.')'; + } - $sql .= ' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl + $sql .= ' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').' LEFT JOIN `'._DB_PREFIX_.'image_shop` image_shop @@ -113,50 +120,57 @@ class ProductSaleCore LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`) '.Product::sqlStock('p', 0); - $sql .= ' + $sql .= ' WHERE product_shop.`active` = 1 AND p.`visibility` != \'none\''; - if (Group::isFeatureActive()) - { - $groups = FrontController::getCurrentCustomerGroups(); - $sql .= ' AND EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp + if (Group::isFeatureActive()) { + $groups = FrontController::getCurrentCustomerGroups(); + $sql .= ' AND EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.id_category = cg.id_category AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1').') WHERE cp.`id_product` = p.`id_product`)'; - } + } - if ($final_order_by != 'price') - $sql .= ' + if ($final_order_by != 'price') { + $sql .= ' ORDER BY '.(!empty($order_table) ? '`'.pSQL($order_table).'`.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way).' LIMIT '.(int)($page_number * $nb_products).', '.(int)$nb_products; + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - if ($final_order_by == 'price') - Tools::orderbyPrice($result, $order_way); - if (!$result) - return false; - return Product::getProductsProperties($id_lang, $result); - } + if ($final_order_by == 'price') { + Tools::orderbyPrice($result, $order_way); + } + if (!$result) { + return false; + } + return Product::getProductsProperties($id_lang, $result); + } - /* - ** Get required informations on best sales products - ** - ** @param int $id_lang Language id - ** @param int $page_number Start from (optional) - ** @param int $nb_products Number of products to return (optional) - ** @return array keys : id_product, link_rewrite, name, id_image, legend, sales, ean13, upc, link - */ - public static function getBestSalesLight($id_lang, $page_number = 0, $nb_products = 10, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - if ($page_number < 0) $page_number = 0; - if ($nb_products < 1) $nb_products = 10; + /* + ** Get required informations on best sales products + ** + ** @param int $id_lang Language id + ** @param int $page_number Start from (optional) + ** @param int $nb_products Number of products to return (optional) + ** @return array keys : id_product, link_rewrite, name, id_image, legend, sales, ean13, upc, link + */ + public static function getBestSalesLight($id_lang, $page_number = 0, $nb_products = 10, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + if ($page_number < 0) { + $page_number = 0; + } + if ($nb_products < 1) { + $nb_products = 10; + } - // no group by needed : there's only one attribute with default_on=1 for a given id_product + shop - // same for image with cover=1 - $sql = ' + // no group by needed : there's only one attribute with default_on=1 for a given id_product + shop + // same for image with cover=1 + $sql = ' SELECT p.id_product, IFNULL(product_attribute_shop.id_product_attribute,0) id_product_attribute, pl.`link_rewrite`, pl.`name`, pl.`description_short`, product_shop.`id_category_default`, image_shop.`id_image` id_image, il.`legend`, @@ -180,56 +194,58 @@ class ProductSaleCore ON cl.`id_category` = product_shop.`id_category_default` AND cl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('cl').Product::sqlStock('p', 0); - $sql .= ' + $sql .= ' WHERE product_shop.`active` = 1 AND p.`visibility` != \'none\''; - if (Group::isFeatureActive()) - { - $groups = FrontController::getCurrentCustomerGroups(); - $sql .= ' AND EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp + if (Group::isFeatureActive()) { + $groups = FrontController::getCurrentCustomerGroups(); + $sql .= ' AND EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.id_category = cg.id_category AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1').') WHERE cp.`id_product` = p.`id_product`)'; - } + } - $sql .= ' + $sql .= ' ORDER BY ps.quantity DESC LIMIT '.(int)($page_number * $nb_products).', '.(int)$nb_products; - if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql)) - return false; + if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql)) { + return false; + } - return Product::getProductsProperties($id_lang, $result); - } + return Product::getProductsProperties($id_lang, $result); + } - public static function addProductSale($product_id, $qty = 1) - { - return Db::getInstance()->execute(' + public static function addProductSale($product_id, $qty = 1) + { + return Db::getInstance()->execute(' INSERT INTO '._DB_PREFIX_.'product_sale (`id_product`, `quantity`, `sale_nbr`, `date_upd`) VALUES ('.(int)$product_id.', '.(int)$qty.', 1, NOW()) ON DUPLICATE KEY UPDATE `quantity` = `quantity` + '.(int)$qty.', `sale_nbr` = `sale_nbr` + 1, `date_upd` = NOW()'); - } + } - public static function getNbrSales($id_product) - { - $result = Db::getInstance()->getRow('SELECT `sale_nbr` FROM '._DB_PREFIX_.'product_sale WHERE `id_product` = '.(int)$id_product); - if (!$result || empty($result) || !array_key_exists('sale_nbr', $result)) - return -1; - return (int)$result['sale_nbr']; - } + public static function getNbrSales($id_product) + { + $result = Db::getInstance()->getRow('SELECT `sale_nbr` FROM '._DB_PREFIX_.'product_sale WHERE `id_product` = '.(int)$id_product); + if (!$result || empty($result) || !array_key_exists('sale_nbr', $result)) { + return -1; + } + return (int)$result['sale_nbr']; + } - public static function removeProductSale($id_product, $qty = 1) - { - $total_sales = ProductSale::getNbrSales($id_product); - if ($total_sales > 1) - return Db::getInstance()->execute(' + public static function removeProductSale($id_product, $qty = 1) + { + $total_sales = ProductSale::getNbrSales($id_product); + if ($total_sales > 1) { + return Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'product_sale SET `quantity` = CAST(`quantity` AS SIGNED) - '.(int)$qty.', `sale_nbr` = CAST(`sale_nbr` AS SIGNED) - 1, `date_upd` = NOW() WHERE `id_product` = '.(int)$id_product - ); - elseif ($total_sales == 1) - return Db::getInstance()->delete('product_sale', 'id_product = '.(int)$id_product); - return true; - } + ); + } elseif ($total_sales == 1) { + return Db::getInstance()->delete('product_sale', 'id_product = '.(int)$id_product); + } + return true; + } } diff --git a/classes/ProductSupplier.php b/classes/ProductSupplier.php index cc6f2840..346126fe 100644 --- a/classes/ProductSupplier.php +++ b/classes/ProductSupplier.php @@ -29,204 +29,209 @@ */ class ProductSupplierCore extends ObjectModel { - /** - * @var int product ID - * */ - public $id_product; + /** + * @var int product ID + * */ + public $id_product; - /** - * @var int product attribute ID - * */ - public $id_product_attribute; + /** + * @var int product attribute ID + * */ + public $id_product_attribute; - /** - * @var int the supplier ID - * */ - public $id_supplier; + /** + * @var int the supplier ID + * */ + public $id_supplier; - /** - * @var string The supplier reference of the product - * */ - public $product_supplier_reference; + /** + * @var string The supplier reference of the product + * */ + public $product_supplier_reference; - /** - * @var int the currency ID for unit price tax excluded - * */ - public $id_currency; + /** + * @var int the currency ID for unit price tax excluded + * */ + public $id_currency; - /** - * @var string The unit price tax excluded of the product - * */ - public $product_supplier_price_te; + /** + * @var string The unit price tax excluded of the product + * */ + public $product_supplier_price_te; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'product_supplier', - 'primary' => 'id_product_supplier', - 'fields' => array( - 'product_supplier_reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference', 'size' => 32), - 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_supplier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'product_supplier_price_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'product_supplier', + 'primary' => 'id_product_supplier', + 'fields' => array( + 'product_supplier_reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference', 'size' => 32), + 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_supplier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'product_supplier_price_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + ), + ); - /** - * @see ObjectModel::$webserviceParameters - */ - protected $webserviceParameters = array( - 'objectsNodeName' => 'product_suppliers', - 'objectNodeName' => 'product_supplier', - 'fields' => array( - 'id_product' => array('xlink_resource' => 'products'), - 'id_product_attribute' => array('xlink_resource' => 'combinations'), - 'id_supplier' => array('xlink_resource' => 'suppliers'), - 'id_currency' => array('xlink_resource' => 'currencies'), - ), - ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'objectsNodeName' => 'product_suppliers', + 'objectNodeName' => 'product_supplier', + 'fields' => array( + 'id_product' => array('xlink_resource' => 'products'), + 'id_product_attribute' => array('xlink_resource' => 'combinations'), + 'id_supplier' => array('xlink_resource' => 'suppliers'), + 'id_currency' => array('xlink_resource' => 'currencies'), + ), + ); - /** - * @see ObjectModel::delete() - */ - public function delete() - { - $res = parent::delete(); + /** + * @see ObjectModel::delete() + */ + public function delete() + { + $res = parent::delete(); - if ($res && $this->id_product_attribute == 0) - { - $items = ProductSupplier::getSupplierCollection($this->id_product, false); - foreach ($items as $item) - { - /** @var ProductSupplier $item */ - if ($item->id_product_attribute > 0) - $item->delete(); - } - } + if ($res && $this->id_product_attribute == 0) { + $items = ProductSupplier::getSupplierCollection($this->id_product, false); + foreach ($items as $item) { + /** @var ProductSupplier $item */ + if ($item->id_product_attribute > 0) { + $item->delete(); + } + } + } - return $res; - } + return $res; + } - /** - * For a given product and supplier, gets the product supplier reference - * - * @param int $id_product - * @param int $id_product_attribute - * @param int $id_supplier - * @return string - */ - public static function getProductSupplierReference($id_product, $id_product_attribute, $id_supplier) - { - // build query - $query = new DbQuery(); - $query->select('ps.product_supplier_reference'); - $query->from('product_supplier', 'ps'); - $query->where('ps.id_product = '.(int)$id_product.' + /** + * For a given product and supplier, gets the product supplier reference + * + * @param int $id_product + * @param int $id_product_attribute + * @param int $id_supplier + * @return string + */ + public static function getProductSupplierReference($id_product, $id_product_attribute, $id_supplier) + { + // build query + $query = new DbQuery(); + $query->select('ps.product_supplier_reference'); + $query->from('product_supplier', 'ps'); + $query->where('ps.id_product = '.(int)$id_product.' AND ps.id_product_attribute = '.(int)$id_product_attribute.' AND ps.id_supplier = '.(int)$id_supplier - ); + ); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } - /** - * For a given product and supplier, gets the product supplier unit price - * - * @param int $id_product - * @param int $id_product_attribute - * @param int $id_supplier - * @param bool $with_currency Optional - * @return array - */ - public static function getProductSupplierPrice($id_product, $id_product_attribute, $id_supplier, $with_currency = false) - { - // build query - $query = new DbQuery(); - $query->select('ps.product_supplier_price_te'); - if ($with_currency) - $query->select('ps.id_currency'); - $query->from('product_supplier', 'ps'); - $query->where('ps.id_product = '.(int)$id_product.' + /** + * For a given product and supplier, gets the product supplier unit price + * + * @param int $id_product + * @param int $id_product_attribute + * @param int $id_supplier + * @param bool $with_currency Optional + * @return array + */ + public static function getProductSupplierPrice($id_product, $id_product_attribute, $id_supplier, $with_currency = false) + { + // build query + $query = new DbQuery(); + $query->select('ps.product_supplier_price_te'); + if ($with_currency) { + $query->select('ps.id_currency'); + } + $query->from('product_supplier', 'ps'); + $query->where('ps.id_product = '.(int)$id_product.' AND ps.id_product_attribute = '.(int)$id_product_attribute.' AND ps.id_supplier = '.(int)$id_supplier - ); + ); - if (!$with_currency) - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + if (!$with_currency) { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - if (isset($res[0])) - return $res[0]; + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + if (isset($res[0])) { + return $res[0]; + } - return $res; - } + return $res; + } - /** - * For a given product and supplier, gets corresponding ProductSupplier ID - * - * @param int $id_product - * @param int $id_product_attribute - * @param int $id_supplier - * @return array - */ - public static function getIdByProductAndSupplier($id_product, $id_product_attribute, $id_supplier) - { - // build query - $query = new DbQuery(); - $query->select('ps.id_product_supplier'); - $query->from('product_supplier', 'ps'); - $query->where('ps.id_product = '.(int)$id_product.' + /** + * For a given product and supplier, gets corresponding ProductSupplier ID + * + * @param int $id_product + * @param int $id_product_attribute + * @param int $id_supplier + * @return array + */ + public static function getIdByProductAndSupplier($id_product, $id_product_attribute, $id_supplier) + { + // build query + $query = new DbQuery(); + $query->select('ps.id_product_supplier'); + $query->from('product_supplier', 'ps'); + $query->where('ps.id_product = '.(int)$id_product.' AND ps.id_product_attribute = '.(int)$id_product_attribute.' AND ps.id_supplier = '.(int)$id_supplier - ); + ); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } - /** - * For a given product, retrieves its suppliers - * - * @param int $id_product - * @param int $group_by_supplier - * @return PrestaShopCollection Collection of ProductSupplier - */ - public static function getSupplierCollection($id_product, $group_by_supplier = true) - { - $suppliers = new PrestaShopCollection('ProductSupplier'); - $suppliers->where('id_product', '=', (int)$id_product); + /** + * For a given product, retrieves its suppliers + * + * @param int $id_product + * @param int $group_by_supplier + * @return PrestaShopCollection Collection of ProductSupplier + */ + public static function getSupplierCollection($id_product, $group_by_supplier = true) + { + $suppliers = new PrestaShopCollection('ProductSupplier'); + $suppliers->where('id_product', '=', (int)$id_product); - if ($group_by_supplier) - $suppliers->groupBy('id_supplier'); + if ($group_by_supplier) { + $suppliers->groupBy('id_supplier'); + } - return $suppliers; - } + return $suppliers; + } - /** - * For a given Supplier, Product, returns the purchased price - * - * @param int $id_product - * @param int $id_product_attribute Optional - * @param bool $converted_price Optional - * @return Array keys: price_te, id_currency - */ - public static function getProductPrice($id_supplier, $id_product, $id_product_attribute = 0, $converted_price = false) - { - if (is_null($id_supplier) || is_null($id_product)) - return; + /** + * For a given Supplier, Product, returns the purchased price + * + * @param int $id_product + * @param int $id_product_attribute Optional + * @param bool $converted_price Optional + * @return Array keys: price_te, id_currency + */ + public static function getProductPrice($id_supplier, $id_product, $id_product_attribute = 0, $converted_price = false) + { + if (is_null($id_supplier) || is_null($id_product)) { + return; + } - $query = new DbQuery(); - $query->select('product_supplier_price_te as price_te, id_currency'); - $query->from('product_supplier'); - $query->where('id_product = '.(int)$id_product.' AND id_product_attribute = '.(int)$id_product_attribute); - $query->where('id_supplier = '.(int)$id_supplier); + $query = new DbQuery(); + $query->select('product_supplier_price_te as price_te, id_currency'); + $query->from('product_supplier'); + $query->where('id_product = '.(int)$id_product.' AND id_product_attribute = '.(int)$id_product_attribute); + $query->where('id_supplier = '.(int)$id_supplier); - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query); - if ($converted_price) - return Tools::convertPrice($row['price_te'], $row['id_currency']); + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query); + if ($converted_price) { + return Tools::convertPrice($row['price_te'], $row['id_currency']); + } - return $row['price_te']; - } -} \ No newline at end of file + return $row['price_te']; + } +} diff --git a/classes/Profile.php b/classes/Profile.php index dd46a2b0..838f12fb 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -26,127 +26,128 @@ class ProfileCore extends ObjectModel { - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'profile', - 'primary' => 'id_profile', - 'multilang' => true, - 'fields' => array( - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'profile', + 'primary' => 'id_profile', + 'multilang' => true, + 'fields' => array( + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), + ), + ); - protected static $_cache_accesses = array(); + protected static $_cache_accesses = array(); - /** - * Get all available profiles - * - * @return array Profiles - */ - public static function getProfiles($id_lang) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * Get all available profiles + * + * @return array Profiles + */ + public static function getProfiles($id_lang) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT p.`id_profile`, `name` FROM `'._DB_PREFIX_.'profile` p LEFT JOIN `'._DB_PREFIX_.'profile_lang` pl ON (p.`id_profile` = pl.`id_profile` AND `id_lang` = '.(int)$id_lang.') ORDER BY `id_profile` ASC'); - } + } - /** - * Get the current profile name - * - * @return string Profile - */ - public static function getProfile($id_profile, $id_lang = null) - { - if (!$id_lang) - $id_lang = Configuration::get('PS_LANG_DEFAULT'); + /** + * Get the current profile name + * + * @return string Profile + */ + public static function getProfile($id_profile, $id_lang = null) + { + if (!$id_lang) { + $id_lang = Configuration::get('PS_LANG_DEFAULT'); + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT `name` FROM `'._DB_PREFIX_.'profile` p LEFT JOIN `'._DB_PREFIX_.'profile_lang` pl ON (p.`id_profile` = pl.`id_profile`) WHERE p.`id_profile` = '.(int)$id_profile.' AND pl.`id_lang` = '.(int)$id_lang - ); - } + ); + } - public function add($autodate = true, $null_values = false) - { - if (parent::add($autodate, true)) - { - $result = Db::getInstance()->execute('INSERT INTO '._DB_PREFIX_.'access (SELECT '.(int)$this->id.', id_tab, 0, 0, 0, 0 FROM '._DB_PREFIX_.'tab)'); - $result &= Db::getInstance()->execute(' + public function add($autodate = true, $null_values = false) + { + if (parent::add($autodate, true)) { + $result = Db::getInstance()->execute('INSERT INTO '._DB_PREFIX_.'access (SELECT '.(int)$this->id.', id_tab, 0, 0, 0, 0 FROM '._DB_PREFIX_.'tab)'); + $result &= Db::getInstance()->execute(' INSERT INTO '._DB_PREFIX_.'module_access (`id_profile`, `id_module`, `configure`, `view`, `uninstall`) (SELECT '.(int)$this->id.', id_module, 0, 1, 0 FROM '._DB_PREFIX_.'module) '); - return $result; - } - return false; - } + return $result; + } + return false; + } - public function delete() - { - if (parent::delete()) - return ( - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'access` WHERE `id_profile` = '.(int)$this->id) - && Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module_access` WHERE `id_profile` = '.(int)$this->id) - ); - return false; - } + public function delete() + { + if (parent::delete()) { + return ( + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'access` WHERE `id_profile` = '.(int)$this->id) + && Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module_access` WHERE `id_profile` = '.(int)$this->id) + ); + } + return false; + } - public static function getProfileAccess($id_profile, $id_tab) - { - // getProfileAccesses is cached so there is no performance leak - $accesses = Profile::getProfileAccesses($id_profile); - return (isset($accesses[$id_tab]) ? $accesses[$id_tab] : false); - } + public static function getProfileAccess($id_profile, $id_tab) + { + // getProfileAccesses is cached so there is no performance leak + $accesses = Profile::getProfileAccesses($id_profile); + return (isset($accesses[$id_tab]) ? $accesses[$id_tab] : false); + } - public static function getProfileAccesses($id_profile, $type = 'id_tab') - { - if (!in_array($type, array('id_tab', 'class_name'))) - return false; + public static function getProfileAccesses($id_profile, $type = 'id_tab') + { + if (!in_array($type, array('id_tab', 'class_name'))) { + return false; + } - if (!isset(self::$_cache_accesses[$id_profile])) - self::$_cache_accesses[$id_profile] = array(); + if (!isset(self::$_cache_accesses[$id_profile])) { + self::$_cache_accesses[$id_profile] = array(); + } - if (!isset(self::$_cache_accesses[$id_profile][$type])) - { - self::$_cache_accesses[$id_profile][$type] = array(); - // Super admin profile has full auth - if ($id_profile == _PS_ADMIN_PROFILE_) - { - foreach (Tab::getTabs(Context::getContext()->language->id) as $tab) - self::$_cache_accesses[$id_profile][$type][$tab[$type]] = array( - 'id_profile' => _PS_ADMIN_PROFILE_, - 'id_tab' => $tab['id_tab'], - 'class_name' => $tab['class_name'], - 'view' => '1', - 'add' => '1', - 'edit' => '1', - 'delete' => '1', - ); - } - else - { - $result = Db::getInstance()->executeS(' + if (!isset(self::$_cache_accesses[$id_profile][$type])) { + self::$_cache_accesses[$id_profile][$type] = array(); + // Super admin profile has full auth + if ($id_profile == _PS_ADMIN_PROFILE_) { + foreach (Tab::getTabs(Context::getContext()->language->id) as $tab) { + self::$_cache_accesses[$id_profile][$type][$tab[$type]] = array( + 'id_profile' => _PS_ADMIN_PROFILE_, + 'id_tab' => $tab['id_tab'], + 'class_name' => $tab['class_name'], + 'view' => '1', + 'add' => '1', + 'edit' => '1', + 'delete' => '1', + ); + } + } else { + $result = Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'access` a LEFT JOIN `'._DB_PREFIX_.'tab` t ON t.id_tab = a.id_tab WHERE `id_profile` = '.(int)$id_profile); - foreach ($result as $row) - self::$_cache_accesses[$id_profile][$type][$row[$type]] = $row; - } - } + foreach ($result as $row) { + self::$_cache_accesses[$id_profile][$type][$row[$type]] = $row; + } + } + } - return self::$_cache_accesses[$id_profile][$type]; - } -} \ No newline at end of file + return self::$_cache_accesses[$id_profile][$type]; + } +} diff --git a/classes/QuickAccess.php b/classes/QuickAccess.php index 703f97bb..aa75c8f2 100644 --- a/classes/QuickAccess.php +++ b/classes/QuickAccess.php @@ -26,54 +26,55 @@ class QuickAccessCore extends ObjectModel { - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var string Link */ - public $link; + /** @var string Link */ + public $link; - /** @var bool New windows or not */ - public $new_window; + /** @var bool New windows or not */ + public $new_window; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'quick_access', - 'primary' => 'id_quick_access', - 'multilang' => true, - 'fields' => array( - 'link' => array('type' => self::TYPE_STRING, 'validate' => 'isUrl', 'required' => true, 'size' => 255), - 'new_window' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'quick_access', + 'primary' => 'id_quick_access', + 'multilang' => true, + 'fields' => array( + 'link' => array('type' => self::TYPE_STRING, 'validate' => 'isUrl', 'required' => true, 'size' => 255), + 'new_window' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCleanHtml', 'required' => true, 'size' => 32), - ), - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCleanHtml', 'required' => true, 'size' => 32), + ), + ); - /** - * Get all available quick_accesses - * - * @return array QuickAccesses - */ - public static function getQuickAccesses($id_lang) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * Get all available quick_accesses + * + * @return array QuickAccesses + */ + public static function getQuickAccesses($id_lang) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'quick_access` qa LEFT JOIN `'._DB_PREFIX_.'quick_access_lang` qal ON (qa.`id_quick_access` = qal.`id_quick_access` AND qal.`id_lang` = '.(int)$id_lang.') ORDER BY `name` ASC'); - } + } - public function toggleNewWindow() - { - if (!array_key_exists('new_window', $this)) - throw new PrestaShopException('property "new_window" is missing in object '.get_class($this)); + public function toggleNewWindow() + { + if (!array_key_exists('new_window', $this)) { + throw new PrestaShopException('property "new_window" is missing in object '.get_class($this)); + } - $this->setFieldsToUpdate(array('new_window' => true)); + $this->setFieldsToUpdate(array('new_window' => true)); - $this->new_window = !(int)$this->new_window; + $this->new_window = !(int)$this->new_window; - return $this->update(false); - } -} \ No newline at end of file + return $this->update(false); + } +} diff --git a/classes/Referrer.php b/classes/Referrer.php index 8b8b8c7a..0f30a31d 100644 --- a/classes/Referrer.php +++ b/classes/Referrer.php @@ -26,50 +26,50 @@ class ReferrerCore extends ObjectModel { - public $id_shop; - public $name; - public $passwd; + public $id_shop; + public $name; + public $passwd; - public $http_referer_regexp; - public $http_referer_like; - public $request_uri_regexp; - public $request_uri_like; - public $http_referer_regexp_not; - public $http_referer_like_not; - public $request_uri_regexp_not; - public $request_uri_like_not; + public $http_referer_regexp; + public $http_referer_like; + public $request_uri_regexp; + public $request_uri_like; + public $http_referer_regexp_not; + public $http_referer_like_not; + public $request_uri_regexp_not; + public $request_uri_like_not; - public $base_fee; - public $percent_fee; - public $click_fee; + public $base_fee; + public $percent_fee; + public $click_fee; - public $date_add; + public $date_add; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'referrer', - 'primary' => 'id_referrer', - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), - 'passwd' => array('type' => self::TYPE_STRING, 'validate' => 'isPasswd', 'size' => 32), - 'http_referer_regexp' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 64), - 'request_uri_regexp' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 64), - 'http_referer_like' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 64), - 'request_uri_like' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 64), - 'http_referer_regexp_not' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml'), - 'request_uri_regexp_not' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml'), - 'http_referer_like_not' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml'), - 'request_uri_like_not' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml'), - 'base_fee' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'percent_fee' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPercentage'), - 'click_fee' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'referrer', + 'primary' => 'id_referrer', + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), + 'passwd' => array('type' => self::TYPE_STRING, 'validate' => 'isPasswd', 'size' => 32), + 'http_referer_regexp' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 64), + 'request_uri_regexp' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 64), + 'http_referer_like' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 64), + 'request_uri_like' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 64), + 'http_referer_regexp_not' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml'), + 'request_uri_regexp_not' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml'), + 'http_referer_like_not' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml'), + 'request_uri_like_not' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml'), + 'base_fee' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'percent_fee' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPercentage'), + 'click_fee' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - protected static $_join = '(r.http_referer_like IS NULL OR r.http_referer_like = \'\' OR cs.http_referer LIKE r.http_referer_like) + protected static $_join = '(r.http_referer_like IS NULL OR r.http_referer_like = \'\' OR cs.http_referer LIKE r.http_referer_like) AND (r.request_uri_like IS NULL OR r.request_uri_like = \'\' OR cs.request_uri LIKE r.request_uri_like) AND (r.http_referer_like_not IS NULL OR r.http_referer_like_not = \'\' OR cs.http_referer NOT LIKE r.http_referer_like_not) AND (r.request_uri_like_not IS NULL OR r.request_uri_like_not = \'\' OR cs.request_uri NOT LIKE r.request_uri_like_not) @@ -78,37 +78,39 @@ class ReferrerCore extends ObjectModel AND (r.http_referer_regexp_not IS NULL OR r.http_referer_regexp_not = \'\' OR cs.http_referer NOT REGEXP r.http_referer_regexp_not) AND (r.request_uri_regexp_not IS NULL OR r.request_uri_regexp_not = \'\' OR cs.request_uri NOT REGEXP r.request_uri_regexp_not)'; - public function add($autodate = true, $null_values = false) - { - if (!($result = parent::add($autodate, $null_values))) - return false; - Referrer::refreshCache(array(array('id_referrer' => $this->id))); - Referrer::refreshIndex(array(array('id_referrer' => $this->id))); - return $result; - } + public function add($autodate = true, $null_values = false) + { + if (!($result = parent::add($autodate, $null_values))) { + return false; + } + Referrer::refreshCache(array(array('id_referrer' => $this->id))); + Referrer::refreshIndex(array(array('id_referrer' => $this->id))); + return $result; + } - public static function cacheNewSource($id_connections_source) - { - if (!$id_connections_source) - return; + public static function cacheNewSource($id_connections_source) + { + if (!$id_connections_source) { + return; + } - $sql = 'INSERT INTO '._DB_PREFIX_.'referrer_cache (id_referrer, id_connections_source) ( + $sql = 'INSERT INTO '._DB_PREFIX_.'referrer_cache (id_referrer, id_connections_source) ( SELECT id_referrer, id_connections_source FROM '._DB_PREFIX_.'referrer r LEFT JOIN '._DB_PREFIX_.'connections_source cs ON ('.self::$_join.') WHERE id_connections_source = '.(int)$id_connections_source.' )'; - Db::getInstance()->execute($sql); - } + Db::getInstance()->execute($sql); + } - /** - * Get list of referrers connections of a customer - * - * @param int $id_customer - */ - public static function getReferrers($id_customer) - { - $sql = 'SELECT DISTINCT c.date_add, r.name, s.name AS shop_name + /** + * Get list of referrers connections of a customer + * + * @param int $id_customer + */ + public static function getReferrers($id_customer) + { + $sql = 'SELECT DISTINCT c.date_add, r.name, s.name AS shop_name FROM '._DB_PREFIX_.'guest g LEFT JOIN '._DB_PREFIX_.'connections c ON c.id_guest = g.id_guest LEFT JOIN '._DB_PREFIX_.'connections_source cs ON c.id_connections = cs.id_connections @@ -117,28 +119,26 @@ class ReferrerCore extends ObjectModel WHERE g.id_customer = '.(int)$id_customer.' AND r.name IS NOT NULL ORDER BY c.date_add DESC'; - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + } - /** - * Get some statistics on visitors connection for current referrer - * - * @param int $id_product - * @param int $employee - * @param Context $context - */ - public function getStatsVisits($id_product, $employee) - { - $join = $where = ''; - if ($id_product) - { - $join = 'LEFT JOIN `'._DB_PREFIX_.'page` p ON cp.`id_page` = p.`id_page` + /** + * Get some statistics on visitors connection for current referrer + * + * @param int $id_product + * @param int $employee + */ + public function getStatsVisits($id_product, $employee) + { + $join = $where = ''; + if ($id_product) { + $join = 'LEFT JOIN `'._DB_PREFIX_.'page` p ON cp.`id_page` = p.`id_page` LEFT JOIN `'._DB_PREFIX_.'page_type` pt ON pt.`id_page_type` = p.`id_page_type`'; - $where = ' AND pt.`name` = \'product\' + $where = ' AND pt.`name` = \'product\' AND p.`id_object` = '.(int)$id_product; - } + } - $sql = 'SELECT COUNT(DISTINCT cs.id_connections_source) AS visits, + $sql = 'SELECT COUNT(DISTINCT cs.id_connections_source) AS visits, COUNT(DISTINCT cs.id_connections) as visitors, COUNT(DISTINCT c.id_guest) as uniqs, COUNT(DISTINCT cp.time_start) as pages @@ -150,34 +150,32 @@ class ReferrerCore extends ObjectModel LEFT JOIN '._DB_PREFIX_.'connections_page cp ON cp.id_connections = c.id_connections '.$join.' WHERE 1'. - ((isset($employee->stats_date_from) && isset($employee->stats_date_from))? ' AND cs.date_add BETWEEN \''.pSQL($employee->stats_date_from).' 00:00:00\' AND \''.pSQL($employee->stats_date_to).' 23:59:59\'' : ''). - Shop::addSqlRestriction(false, 'rs'). - Shop::addSqlRestriction(false, 'c'). - ' AND rc.id_referrer = '.(int)$this->id. - $where; - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); - } + ((isset($employee->stats_date_from) && isset($employee->stats_date_to))? ' AND cs.date_add BETWEEN \''.pSQL($employee->stats_date_from).' 00:00:00\' AND \''.pSQL($employee->stats_date_to).' 23:59:59\'' : ''). + Shop::addSqlRestriction(false, 'rs'). + Shop::addSqlRestriction(false, 'c'). + ' AND rc.id_referrer = '.(int)$this->id. + $where; + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + } - /** - * Get some statistics on customers registrations for current referrer - * - * @param int $id_product - * @param int $employee - * @param Context $context - */ - public function getRegistrations($id_product, $employee) - { - $join = $where = ''; - if ($id_product) - { - $join = 'LEFT JOIN '._DB_PREFIX_.'connections_page cp ON cp.id_connections = c.id_connections + /** + * Get some statistics on customers registrations for current referrer + * + * @param int $id_product + * @param int $employee + */ + public function getRegistrations($id_product, $employee) + { + $join = $where = ''; + if ($id_product) { + $join = 'LEFT JOIN '._DB_PREFIX_.'connections_page cp ON cp.id_connections = c.id_connections LEFT JOIN `'._DB_PREFIX_.'page` p ON cp.`id_page` = p.`id_page` LEFT JOIN `'._DB_PREFIX_.'page_type` pt ON pt.`id_page_type` = p.`id_page_type`'; - $where = ' AND pt.`name` = \'product\' + $where = ' AND pt.`name` = \'product\' AND p.`id_object` = '.(int)$id_product; - } + } - $sql = 'SELECT COUNT(DISTINCT cu.id_customer) AS registrations + $sql = 'SELECT COUNT(DISTINCT cu.id_customer) AS registrations FROM '._DB_PREFIX_.'referrer_cache rc LEFT JOIN '._DB_PREFIX_.'referrer_shop rs ON rc.id_referrer = rs.id_referrer LEFT JOIN '._DB_PREFIX_.'connections_source cs ON rc.id_connections_source = cs.id_connections_source @@ -191,27 +189,26 @@ class ReferrerCore extends ObjectModel '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER, 'cu').' AND cu.date_add > cs.date_add AND rc.id_referrer = '.(int)$this->id - .$where; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); - return (int)$result['registrations']; - } + .$where; + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + return (int)$result['registrations']; + } - /** - * Get some statistics on orders for current referrer - * - * @param int $id_product - * @param int $employee - */ - public function getStatsSales($id_product, $employee) - { - $join = $where = ''; - if ($id_product) - { - $join = 'LEFT JOIN '._DB_PREFIX_.'order_detail od ON oo.id_order = od.id_order'; - $where = ' AND od.product_id = '.(int)$id_product; - } + /** + * Get some statistics on orders for current referrer + * + * @param int $id_product + * @param int $employee + */ + public function getStatsSales($id_product, $employee) + { + $join = $where = ''; + if ($id_product) { + $join = 'LEFT JOIN '._DB_PREFIX_.'order_detail od ON oo.id_order = od.id_order'; + $where = ' AND od.product_id = '.(int)$id_product; + } - $sql = 'SELECT oo.id_order + $sql = 'SELECT oo.id_order FROM '._DB_PREFIX_.'referrer_cache rc LEFT JOIN '._DB_PREFIX_.'referrer_shop rs ON rc.id_referrer = rs.id_referrer INNER JOIN '._DB_PREFIX_.'connections_source cs ON rc.id_connections_source = cs.id_connections_source @@ -226,90 +223,88 @@ class ReferrerCore extends ObjectModel AND oo.date_add > cs.date_add AND rc.id_referrer = '.(int)$this->id.' AND oo.valid = 1' - .$where; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + .$where; + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - $implode = array(); - foreach ($result as $row) - if ((int)$row['id_order']) - $implode[] = (int)$row['id_order']; + $implode = array(); + foreach ($result as $row) { + if ((int)$row['id_order']) { + $implode[] = (int)$row['id_order']; + } + } - if ($implode) - { - $sql = 'SELECT COUNT(id_order) AS orders, SUM(total_paid_real / conversion_rate) AS sales + if ($implode) { + $sql = 'SELECT COUNT(id_order) AS orders, SUM(total_paid_real / conversion_rate) AS sales FROM '._DB_PREFIX_.'orders WHERE id_order IN ('.implode($implode, ',').') '.Shop::addSqlRestriction(Shop::SHARE_ORDER).' AND valid = 1'; - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); - } - else - return array('orders' => 0, 'sales' => 0); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + } else { + return array('orders' => 0, 'sales' => 0); + } + } - /** - * Refresh cache data of referrer statistics in referrer_shop table - * - * @param array $referrers - * @param int $employee - * @return true - */ - public static function refreshCache($referrers = null, $employee = null) - { - if (!$referrers || !is_array($referrers)) - $referrers = Db::getInstance()->executeS('SELECT id_referrer FROM '._DB_PREFIX_.'referrer'); - foreach ($referrers as $row) - { - $referrer = new Referrer($row['id_referrer']); - foreach (Shop::getShops(true, null, true) as $shop_id) - { - if (!$referrer->isAssociatedToShop($shop_id)) - continue; + /** + * Refresh cache data of referrer statistics in referrer_shop table + * + * @param array $referrers + * @param int $employee + * @return true + */ + public static function refreshCache($referrers = null, $employee = null) + { + if (!$referrers || !is_array($referrers)) { + $referrers = Db::getInstance()->executeS('SELECT id_referrer FROM '._DB_PREFIX_.'referrer'); + } + foreach ($referrers as $row) { + $referrer = new Referrer($row['id_referrer']); + foreach (Shop::getShops(true, null, true) as $shop_id) { + if (!$referrer->isAssociatedToShop($shop_id)) { + continue; + } - $stats_visits = $referrer->getStatsVisits(null, $employee); - $registrations = $referrer->getRegistrations(null, $employee); - $stats_sales = $referrer->getStatsSales(null, $employee); + $stats_visits = $referrer->getStatsVisits(null, $employee); + $registrations = $referrer->getRegistrations(null, $employee); + $stats_sales = $referrer->getStatsSales(null, $employee); - Db::getInstance()->update('referrer_shop', array( - 'cache_visitors' => (int)$stats_visits['uniqs'], - 'cache_visits' => (int)$stats_visits['visits'], - 'cache_pages' => (int)$stats_visits['pages'], - 'cache_registrations' => (int)$registrations, - 'cache_orders' => (int)$stats_sales['orders'], - 'cache_sales' => number_format($stats_sales['sales'], 2, '.', ''), - 'cache_reg_rate' => $stats_visits['uniqs'] ? $registrations / $stats_visits['uniqs'] : 0, - 'cache_order_rate' => $stats_visits['uniqs'] ? $stats_sales['orders'] / $stats_visits['uniqs'] : 0, - ), 'id_referrer = '.(int)$referrer->id.' AND id_shop = '.(int)$shop_id); - } - } + Db::getInstance()->update('referrer_shop', array( + 'cache_visitors' => (int)$stats_visits['uniqs'], + 'cache_visits' => (int)$stats_visits['visits'], + 'cache_pages' => (int)$stats_visits['pages'], + 'cache_registrations' => (int)$registrations, + 'cache_orders' => (int)$stats_sales['orders'], + 'cache_sales' => number_format($stats_sales['sales'], 2, '.', ''), + 'cache_reg_rate' => $stats_visits['uniqs'] ? $registrations / $stats_visits['uniqs'] : 0, + 'cache_order_rate' => $stats_visits['uniqs'] ? $stats_sales['orders'] / $stats_visits['uniqs'] : 0, + ), 'id_referrer = '.(int)$referrer->id.' AND id_shop = '.(int)$shop_id); + } + } - Configuration::updateValue('PS_REFERRERS_CACHE_LIKE', ModuleGraph::getDateBetween($employee)); - Configuration::updateValue('PS_REFERRERS_CACHE_DATE', date('Y-m-d H:i:s')); - return true; - } + Configuration::updateValue('PS_REFERRERS_CACHE_LIKE', ModuleGraph::getDateBetween($employee)); + Configuration::updateValue('PS_REFERRERS_CACHE_DATE', date('Y-m-d H:i:s')); + return true; + } - /** - * Cache liaison between connections_source data and referrers data - * - * @param array $referrers - */ - public static function refreshIndex($referrers = null) - { - if (!$referrers || !is_array($referrers)) - { - Db::getInstance()->execute('TRUNCATE '._DB_PREFIX_.'referrer_cache'); - Db::getInstance()->execute(' + /** + * Cache liaison between connections_source data and referrers data + * + * @param array $referrers + */ + public static function refreshIndex($referrers = null) + { + if (!$referrers || !is_array($referrers)) { + Db::getInstance()->execute('TRUNCATE '._DB_PREFIX_.'referrer_cache'); + Db::getInstance()->execute(' INSERT INTO '._DB_PREFIX_.'referrer_cache (id_referrer, id_connections_source) ( SELECT id_referrer, id_connections_source FROM '._DB_PREFIX_.'referrer r LEFT JOIN '._DB_PREFIX_.'connections_source cs ON ('.self::$_join.') )'); - } - else - foreach ($referrers as $row) - { - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'referrer_cache WHERE id_referrer = '.(int)$row['id_referrer']); - Db::getInstance()->execute(' + } else { + foreach ($referrers as $row) { + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'referrer_cache WHERE id_referrer = '.(int)$row['id_referrer']); + Db::getInstance()->execute(' INSERT INTO '._DB_PREFIX_.'referrer_cache (id_referrer, id_connections_source) ( SELECT id_referrer, id_connections_source FROM '._DB_PREFIX_.'referrer r @@ -317,41 +312,43 @@ class ReferrerCore extends ObjectModel WHERE id_referrer = '.(int)$row['id_referrer'].' AND id_connections_source IS NOT NULL )'); - } - } + } + } + } - public static function getAjaxProduct($id_referrer, $id_product, $employee = null) - { - $context = Context::getContext(); - $product = new Product($id_product, false, Configuration::get('PS_LANG_DEFAULT')); - $currency = Currency::getCurrencyInstance(Configuration::get('PS_CURRENCY_DEFAULT')); - $referrer = new Referrer($id_referrer); - $stats_visits = $referrer->getStatsVisits($id_product, $employee); - $registrations = $referrer->getRegistrations($id_product, $employee); - $stats_sales = $referrer->getStatsSales($id_product, $employee); + public static function getAjaxProduct($id_referrer, $id_product, $employee = null) + { + $context = Context::getContext(); + $product = new Product($id_product, false, Configuration::get('PS_LANG_DEFAULT')); + $currency = Currency::getCurrencyInstance(Configuration::get('PS_CURRENCY_DEFAULT')); + $referrer = new Referrer($id_referrer); + $stats_visits = $referrer->getStatsVisits($id_product, $employee); + $registrations = $referrer->getRegistrations($id_product, $employee); + $stats_sales = $referrer->getStatsSales($id_product, $employee); - // If it's a product and it has no visits nor orders - if ((int)$id_product && !$stats_visits['visits'] && !$stats_sales['orders']) - exit; + // If it's a product and it has no visits nor orders + if ((int)$id_product && !$stats_visits['visits'] && !$stats_sales['orders']) { + exit; + } - $json_array = array( - 'id_product' => (int)$product->id, - 'product_name' => htmlspecialchars($product->name), - 'uniqs' => (int)$stats_visits['uniqs'], - 'visitors' => (int)$stats_visits['visitors'], - 'visits' => (int)$stats_visits['visits'], - 'pages' => (int)$stats_visits['pages'], - 'registrations' => (int)$registrations, - 'orders' => (int)$stats_sales['orders'], - 'sales' => Tools::displayPrice($stats_sales['sales'], $currency), - 'cart' => Tools::displayPrice(((int)$stats_sales['orders'] ? $stats_sales['sales'] / (int)$stats_sales['orders'] : 0), $currency), - 'reg_rate' => number_format((int)$stats_visits['uniqs'] ? (int)$registrations / (int)$stats_visits['uniqs'] : 0, 4, '.', ''), - 'order_rate' => number_format((int)$stats_visits['uniqs'] ? (int)$stats_sales['orders'] / (int)$stats_visits['uniqs'] : 0, 4, '.', ''), - 'click_fee' => Tools::displayPrice((int)$stats_visits['visits'] * $referrer->click_fee, $currency), - 'base_fee' => Tools::displayPrice($stats_sales['orders'] * $referrer->base_fee, $currency), - 'percent_fee' => Tools::displayPrice($stats_sales['sales'] * $referrer->percent_fee / 100, $currency), - ); + $json_array = array( + 'id_product' => (int)$product->id, + 'product_name' => htmlspecialchars($product->name), + 'uniqs' => (int)$stats_visits['uniqs'], + 'visitors' => (int)$stats_visits['visitors'], + 'visits' => (int)$stats_visits['visits'], + 'pages' => (int)$stats_visits['pages'], + 'registrations' => (int)$registrations, + 'orders' => (int)$stats_sales['orders'], + 'sales' => Tools::displayPrice($stats_sales['sales'], $currency), + 'cart' => Tools::displayPrice(((int)$stats_sales['orders'] ? $stats_sales['sales'] / (int)$stats_sales['orders'] : 0), $currency), + 'reg_rate' => number_format((int)$stats_visits['uniqs'] ? (int)$registrations / (int)$stats_visits['uniqs'] : 0, 4, '.', ''), + 'order_rate' => number_format((int)$stats_visits['uniqs'] ? (int)$stats_sales['orders'] / (int)$stats_visits['uniqs'] : 0, 4, '.', ''), + 'click_fee' => Tools::displayPrice((int)$stats_visits['visits'] * $referrer->click_fee, $currency), + 'base_fee' => Tools::displayPrice($stats_sales['orders'] * $referrer->base_fee, $currency), + 'percent_fee' => Tools::displayPrice($stats_sales['sales'] * $referrer->percent_fee / 100, $currency), + ); - die ('['.Tools::jsonEncode($json_array).']'); - } + die('['.Tools::jsonEncode($json_array).']'); + } } diff --git a/classes/RequestSql.php b/classes/RequestSql.php index a4f274e8..1f50dbde 100644 --- a/classes/RequestSql.php +++ b/classes/RequestSql.php @@ -26,633 +26,571 @@ class RequestSqlCore extends ObjectModel { - public $name; - public $sql; + public $name; + public $sql; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'request_sql', - 'primary' => 'id_request_sql', - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true, 'size' => 200), - 'sql' => array('type' => self::TYPE_SQL, 'validate' => 'isString', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'request_sql', + 'primary' => 'id_request_sql', + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true, 'size' => 200), + 'sql' => array('type' => self::TYPE_SQL, 'validate' => 'isString', 'required' => true), + ), + ); - /** @var array : List of params to tested */ - public $tested = array( - 'required' => array('SELECT', 'FROM'), - 'option' => array('WHERE', 'ORDER', 'LIMIT', 'HAVING', 'GROUP', 'UNION'), - 'operator' => array( - 'AND', '&&', 'BETWEEN', 'AND', 'BINARY', '&', '~', '|', '^', 'CASE', 'WHEN', 'END', 'DIV', '/', '<=>', '=', '>=', - '>', 'IS', 'NOT', 'NULL', '<<', '<=', '<', 'LIKE', '-', '%', '!=', '<>', 'REGEXP', '!', '||', 'OR', '+', '>>', 'RLIKE', 'SOUNDS', '*', - '-', 'XOR', 'IN' - ), - 'function' => array( - 'AVG', 'SUM', 'COUNT', 'MIN', 'MAX', 'STDDEV', 'STDDEV_SAMP', 'STDDEV_POP', 'VARIANCE', 'VAR_SAMP', 'VAR_POP', - 'GROUP_CONCAT', 'BIT_AND', 'BIT_OR', 'BIT_XOR' - ), - 'unauthorized' => array( - 'DELETE', 'ALTER', 'INSERT', 'REPLACE', 'CREATE', 'TRUNCATE', 'OPTIMIZE', 'GRANT', 'REVOKE', 'SHOW', 'HANDLER', - 'LOAD', 'ROLLBACK', 'SAVEPOINT', 'UNLOCK', 'INSTALL', 'UNINSTALL', 'ANALZYE', 'BACKUP', 'CHECK', 'CHECKSUM', 'REPAIR', 'RESTORE', 'CACHE', - 'DESCRIBE', 'EXPLAIN', 'USE', 'HELP', 'SET', 'DUPLICATE', 'VALUES', 'INTO', 'RENAME', 'CALL', 'PROCEDURE', 'FUNCTION', 'DATABASE', 'SERVER', - 'LOGFILE', 'DEFINER', 'RETURNS', 'EVENT', 'TABLESPACE', 'VIEW', 'TRIGGER', 'DATA', 'DO', 'PASSWORD', 'USER', 'PLUGIN', 'FLUSH', 'KILL', - 'RESET', 'START', 'STOP', 'PURGE', 'EXECUTE', 'PREPARE', 'DEALLOCATE', 'LOCK', 'USING', 'DROP', 'FOR', 'UPDATE', 'BEGIN', 'BY', 'ALL', 'SHARE', - 'MODE', 'TO','KEY', 'DISTINCTROW', 'DISTINCT', 'HIGH_PRIORITY', 'LOW_PRIORITY', 'DELAYED', 'IGNORE', 'FORCE', 'STRAIGHT_JOIN', - 'SQL_SMALL_RESULT', 'SQL_BIG_RESULT', 'QUICK', 'SQL_BUFFER_RESULT', 'SQL_CACHE', 'SQL_NO_CACHE', 'SQL_CALC_FOUND_ROWS', 'WITH' - ) - ); + /** @var array : List of params to tested */ + public $tested = array( + 'required' => array('SELECT', 'FROM'), + 'option' => array('WHERE', 'ORDER', 'LIMIT', 'HAVING', 'GROUP', 'UNION'), + 'operator' => array( + 'AND', '&&', 'BETWEEN', 'AND', 'BINARY', '&', '~', '|', '^', 'CASE', 'WHEN', 'END', 'DIV', '/', '<=>', '=', '>=', + '>', 'IS', 'NOT', 'NULL', '<<', '<=', '<', 'LIKE', '-', '%', '!=', '<>', 'REGEXP', '!', '||', 'OR', '+', '>>', 'RLIKE', 'SOUNDS', '*', + '-', 'XOR', 'IN' + ), + 'function' => array( + 'AVG', 'SUM', 'COUNT', 'MIN', 'MAX', 'STDDEV', 'STDDEV_SAMP', 'STDDEV_POP', 'VARIANCE', 'VAR_SAMP', 'VAR_POP', + 'GROUP_CONCAT', 'BIT_AND', 'BIT_OR', 'BIT_XOR' + ), + 'unauthorized' => array( + 'DELETE', 'ALTER', 'INSERT', 'REPLACE', 'CREATE', 'TRUNCATE', 'OPTIMIZE', 'GRANT', 'REVOKE', 'SHOW', 'HANDLER', + 'LOAD', 'ROLLBACK', 'SAVEPOINT', 'UNLOCK', 'INSTALL', 'UNINSTALL', 'ANALZYE', 'BACKUP', 'CHECK', 'CHECKSUM', 'REPAIR', 'RESTORE', 'CACHE', + 'DESCRIBE', 'EXPLAIN', 'USE', 'HELP', 'SET', 'DUPLICATE', 'VALUES', 'INTO', 'RENAME', 'CALL', 'PROCEDURE', 'FUNCTION', 'DATABASE', 'SERVER', + 'LOGFILE', 'DEFINER', 'RETURNS', 'EVENT', 'TABLESPACE', 'VIEW', 'TRIGGER', 'DATA', 'DO', 'PASSWORD', 'USER', 'PLUGIN', 'FLUSH', 'KILL', + 'RESET', 'START', 'STOP', 'PURGE', 'EXECUTE', 'PREPARE', 'DEALLOCATE', 'LOCK', 'USING', 'DROP', 'FOR', 'UPDATE', 'BEGIN', 'BY', 'ALL', 'SHARE', + 'MODE', 'TO','KEY', 'DISTINCTROW', 'DISTINCT', 'HIGH_PRIORITY', 'LOW_PRIORITY', 'DELAYED', 'IGNORE', 'FORCE', 'STRAIGHT_JOIN', + 'SQL_SMALL_RESULT', 'SQL_BIG_RESULT', 'QUICK', 'SQL_BUFFER_RESULT', 'SQL_CACHE', 'SQL_NO_CACHE', 'SQL_CALC_FOUND_ROWS', 'WITH' + ) + ); - public $attributes = array( - 'passwd' => '*******************', - 'secure_key' => '*******************' - ); + public $attributes = array( + 'passwd' => '*******************', + 'secure_key' => '*******************' + ); - /** @var array : list of errors */ - public $error_sql = array(); + /** @var array : list of errors */ + public $error_sql = array(); - /** - * Get list of request SQL - * - * @return array|bool - */ - public static function getRequestSql() - { - if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT * FROM `'._DB_PREFIX_.'request_sql` ORDER BY `id_request_sql`')) - return false; + /** + * Get list of request SQL + * + * @return array|bool + */ + public static function getRequestSql() + { + if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT * FROM `'._DB_PREFIX_.'request_sql` ORDER BY `id_request_sql`')) { + return false; + } - $request_sql = array(); - foreach ($result as $row) - $request_sql[] = $row['sql']; + $request_sql = array(); + foreach ($result as $row) { + $request_sql[] = $row['sql']; + } - return $request_sql; - } + return $request_sql; + } - /** - * Get list of request SQL by id request - * - * @param $id - * @return array - */ - public static function getRequestSqlById($id) - { - return Db::getInstance()->executeS('SELECT `sql` FROM `'._DB_PREFIX_.'request_sql` WHERE `id_request_sql` = '.(int)$id); - } + /** + * Get list of request SQL by id request + * + * @param $id + * @return array + */ + public static function getRequestSqlById($id) + { + return Db::getInstance()->executeS('SELECT `sql` FROM `'._DB_PREFIX_.'request_sql` WHERE `id_request_sql` = '.(int)$id); + } - /** - * Call the parserSQL() method in Tools class - * Cut the request in table for check it - * - * @param $sql - * @return bool - */ - public function parsingSql($sql) - { - return Tools::parserSQL($sql); - } + /** + * Call the parserSQL() method in Tools class + * Cut the request in table for check it + * + * @param $sql + * @return bool + */ + public function parsingSql($sql) + { + return Tools::parserSQL($sql); + } - /** - * Check if the parsing of the SQL request is good or not - * - * @param $tab - * @param bool $in - * @param $sql - * @return bool - */ - public function validateParser($tab, $in = false, $sql) - { - if (!$tab) - return false; - elseif (isset($tab['UNION'])) - { - $union = $tab['UNION']; - foreach ($union as $tab) - if (!$this->validateSql($tab, $in, $sql)) - return false; - return true; - } - else - return $this->validateSql($tab, $in, $sql); - } + /** + * Check if the parsing of the SQL request is good or not + * + * @param $tab + * @param bool $in + * @param $sql + * @return bool + */ + public function validateParser($tab, $in = false, $sql) + { + if (!$tab) { + return false; + } elseif (isset($tab['UNION'])) { + $union = $tab['UNION']; + foreach ($union as $tab) { + if (!$this->validateSql($tab, $in, $sql)) { + return false; + } + } + return true; + } else { + return $this->validateSql($tab, $in, $sql); + } + } - /** - * Cut the request for check each cutting - * - * @param $tab - * @param $in - * @param $sql - * @return bool - */ - public function validateSql($tab, $in, $sql) - { - if (!$this->testedRequired($tab)) - return false; - elseif (!$this->testedUnauthorized($tab)) - return false; - elseif (!$this->checkedFrom($tab['FROM'])) - return false; - elseif (!$this->checkedSelect($tab['SELECT'], $tab['FROM'], $in)) - return false; - elseif (isset($tab['WHERE'])) - { - if (!$this->checkedWhere($tab['WHERE'], $tab['FROM'], $sql)) - return false; - } - elseif (isset($tab['HAVING'])) - { - if (!$this->checkedHaving($tab['HAVING'], $tab['FROM'])) - return false; - } - elseif (isset($tab['ORDER'])) - { - if (!$this->checkedOrder($tab['ORDER'], $tab['FROM'])) - return false; - } - elseif (isset($tab['GROUP'])) - { - if (!$this->checkedGroupBy($tab['GROUP'], $tab['FROM'])) - return false; - } - elseif (isset($tab['LIMIT'])) - { - if (!$this->checkedLimit($tab['LIMIT'])) - return false; - } + /** + * Cut the request for check each cutting + * + * @param $tab + * @param $in + * @param $sql + * @return bool + */ + public function validateSql($tab, $in, $sql) + { + if (!$this->testedRequired($tab)) { + return false; + } elseif (!$this->testedUnauthorized($tab)) { + return false; + } elseif (!$this->checkedFrom($tab['FROM'])) { + return false; + } elseif (!$this->checkedSelect($tab['SELECT'], $tab['FROM'], $in)) { + return false; + } elseif (isset($tab['WHERE'])) { + if (!$this->checkedWhere($tab['WHERE'], $tab['FROM'], $sql)) { + return false; + } + } elseif (isset($tab['HAVING'])) { + if (!$this->checkedHaving($tab['HAVING'], $tab['FROM'])) { + return false; + } + } elseif (isset($tab['ORDER'])) { + if (!$this->checkedOrder($tab['ORDER'], $tab['FROM'])) { + return false; + } + } elseif (isset($tab['GROUP'])) { + if (!$this->checkedGroupBy($tab['GROUP'], $tab['FROM'])) { + return false; + } + } elseif (isset($tab['LIMIT'])) { + if (!$this->checkedLimit($tab['LIMIT'])) { + return false; + } + } - if (empty($this->_errors) && !Db::getInstance()->executeS($sql)) - return false; - return true; - } + if (empty($this->_errors) && !Db::getInstance()->executeS($sql)) { + return false; + } + return true; + } - /** - * Get list of all tables - * - * @return array - */ - public function getTables() - { - $results = Db::getInstance()->executeS('SHOW TABLES'); - foreach ($results as $result) - { - $key = array_keys($result); - $tables[] = $result[$key[0]]; - } - return $tables; - } + /** + * Get list of all tables + * + * @return array + */ + public function getTables() + { + $results = Db::getInstance()->executeS('SHOW TABLES'); + foreach ($results as $result) { + $key = array_keys($result); + $tables[] = $result[$key[0]]; + } + return $tables; + } - /** - * Get list of all attributes by an table - * - * @param $table - * @return array - */ - public function getAttributesByTable($table) - { - return Db::getInstance()->executeS('DESCRIBE '.pSQL($table)); - } + /** + * Get list of all attributes by an table + * + * @param $table + * @return array + */ + public function getAttributesByTable($table) + { + return Db::getInstance()->executeS('DESCRIBE '.pSQL($table)); + } - /** - * Cut an join sentence - * - * @param $attrs - * @param $from - * @return array|bool - */ - public function cutJoin($attrs, $from) - { - $tab = array(); + /** + * Cut an join sentence + * + * @param $attrs + * @param $from + * @return array|bool + */ + public function cutJoin($attrs, $from) + { + $tab = array(); - foreach ($attrs as $attr) - { - if (in_array($attr['expr_type'], array('operator', 'const'))) - continue; - if ($attribut = $this->cutAttribute($attr['base_expr'], $from)) - $tab[] = $attribut; - } + foreach ($attrs as $attr) { + if (in_array($attr['expr_type'], array('operator', 'const'))) { + continue; + } + if ($attribut = $this->cutAttribute($attr['base_expr'], $from)) { + $tab[] = $attribut; + } + } - return $tab; - } + return $tab; + } - /** - * Cut an attribute with or without the alias - * - * @param $attr - * @param $from - * @return array|bool - */ - public function cutAttribute($attr, $from) - { - $matches = array(); - if (preg_match('/((`(\()?([a-z0-9_])+`(\))?)|((\()?([a-z0-9_])+(\))?))\.((`(\()?([a-z0-9_])+`(\))?)|((\()?([a-z0-9_])+(\))?))$/i', $attr, $matches, PREG_OFFSET_CAPTURE)) - { - $tab = explode('.', str_replace(array('`', '(', ')'), '', $matches[0][0])); - if ($table = $this->returnNameTable($tab[0], $from)) - return array( - 'table' => $table, - 'alias' => $tab[0], - 'attribut' => $tab[1], - 'string' => $attr - ); - } - elseif (preg_match('/((`(\()?([a-z0-9_])+`(\))?)|((\()?([a-z0-9_])+(\))?))$/i', $attr, $matches, PREG_OFFSET_CAPTURE)) - { - $attribut = str_replace(array('`', '(', ')'), '', $matches[0][0]); - if ($table = $this->returnNameTable(false, $from, $attr)) - return array( - 'table' => $table, - 'attribut' => $attribut, - 'string' => $attr - ); - } - return false; - } + /** + * Cut an attribute with or without the alias + * + * @param $attr + * @param $from + * @return array|bool + */ + public function cutAttribute($attr, $from) + { + $matches = array(); + if (preg_match('/((`(\()?([a-z0-9_])+`(\))?)|((\()?([a-z0-9_])+(\))?))\.((`(\()?([a-z0-9_])+`(\))?)|((\()?([a-z0-9_])+(\))?))$/i', $attr, $matches, PREG_OFFSET_CAPTURE)) { + $tab = explode('.', str_replace(array('`', '(', ')'), '', $matches[0][0])); + if ($table = $this->returnNameTable($tab[0], $from)) { + return array( + 'table' => $table, + 'alias' => $tab[0], + 'attribut' => $tab[1], + 'string' => $attr + ); + } + } elseif (preg_match('/((`(\()?([a-z0-9_])+`(\))?)|((\()?([a-z0-9_])+(\))?))$/i', $attr, $matches, PREG_OFFSET_CAPTURE)) { + $attribut = str_replace(array('`', '(', ')'), '', $matches[0][0]); + if ($table = $this->returnNameTable(false, $from, $attr)) { + return array( + 'table' => $table, + 'attribut' => $attribut, + 'string' => $attr + ); + } + } + return false; + } - /** - * Get name of table by alias - * - * @param bool $alias - * @param $tables - * @return array|bool - */ - public function returnNameTable($alias = false, $tables, $attr = null) - { - if ($alias) - { - foreach ($tables as $table) - if (isset($table['alias']) && isset($table['table']) && $table['alias']['no_quotes'] == $alias) - return array($table['table']); - } - elseif (count($tables) > 1) - { - if ($attr !== null) - { - $tab = array(); - foreach ($tables as $table) - if ($this->attributExistInTable($attr, $table['table'])) - $tab = $table['table']; - if (count($tab) == 1) - return $tab; - } + /** + * Get name of table by alias + * + * @param bool $alias + * @param $tables + * @return array|bool + */ + public function returnNameTable($alias = false, $tables, $attr = null) + { + if ($alias) { + foreach ($tables as $table) { + if (isset($table['alias']) && isset($table['table']) && $table['alias']['no_quotes'] == $alias) { + return array($table['table']); + } + } + } elseif (count($tables) > 1) { + if ($attr !== null) { + $tab = array(); + foreach ($tables as $table) { + if ($this->attributExistInTable($attr, $table['table'])) { + $tab = $table['table']; + } + } + if (count($tab) == 1) { + return $tab; + } + } - $this->error_sql['returnNameTable'] = false; - return false; - } - else - { - $tab = array(); - foreach ($tables as $table) - $tab[] = $table['table']; - return $tab; - } - } + $this->error_sql['returnNameTable'] = false; + return false; + } else { + $tab = array(); + foreach ($tables as $table) { + $tab[] = $table['table']; + } + return $tab; + } + } - /** - * Check if an attributes existe in an table - * - * @param $attr - * @param $table - * @return bool - */ - public function attributExistInTable($attr, $table) - { - if (!$attr) - return true; - if (is_array($table) && (count($table) == 1)) - $table = $table[0]; - $attributs = $this->getAttributesByTable($table); - foreach ($attributs as $attribut) - if ($attribut['Field'] == trim($attr, ' `')) - return true; - return false; - } + /** + * Check if an attributes existe in an table + * + * @param $attr + * @param $table + * @return bool + */ + public function attributExistInTable($attr, $table) + { + if (!$attr) { + return true; + } + if (is_array($table) && (count($table) == 1)) { + $table = $table[0]; + } + $attributs = $this->getAttributesByTable($table); + foreach ($attributs as $attribut) { + if ($attribut['Field'] == trim($attr, ' `')) { + return true; + } + } + return false; + } - /** - * Check if all required sentence existing - * - * @param $tab - * @return bool - */ - public function testedRequired($tab) - { - foreach ($this->tested['required'] as $key) - if (!array_key_exists($key, $tab)) - { - $this->error_sql['testedRequired'] = $key; - return false; - } - return true; - } + /** + * Check if all required sentence existing + * + * @param $tab + * @return bool + */ + public function testedRequired($tab) + { + foreach ($this->tested['required'] as $key) { + if (!array_key_exists($key, $tab)) { + $this->error_sql['testedRequired'] = $key; + return false; + } + } + return true; + } - /** - * Check if an unauthorized existing in an array - * - * @param $tab - * @return bool - */ - public function testedUnauthorized($tab) - { - foreach ($this->tested['unauthorized'] as $key) - if (array_key_exists($key, $tab)) - { - $this->error_sql['testedUnauthorized'] = $key; - return false; - } - return true; - } + /** + * Check if an unauthorized existing in an array + * + * @param $tab + * @return bool + */ + public function testedUnauthorized($tab) + { + foreach ($this->tested['unauthorized'] as $key) { + if (array_key_exists($key, $tab)) { + $this->error_sql['testedUnauthorized'] = $key; + return false; + } + } + return true; + } - /** - * Check a "FROM" sentence - * - * @param $from - * @return bool - */ - public function checkedFrom($from) - { - $nb = count($from); - for ($i = 0; $i < $nb; $i++) - { - $table = $from[$i]; + /** + * Check a "FROM" sentence + * + * @param $from + * @return bool + */ + public function checkedFrom($from) + { + $nb = count($from); + for ($i = 0; $i < $nb; $i++) { + $table = $from[$i]; - if (isset($table['table']) && !in_array(str_replace('`', '', $table['table']), $this->getTables())) - { - $this->error_sql['checkedFrom']['table'] = $table['table']; - return false; - } - if ($table['ref_type'] == 'ON' && (trim($table['join_type']) == 'LEFT' || trim($table['join_type']) == 'JOIN')) - { - if ($attrs = $this->cutJoin($table['ref_clause'], $from)) - { - foreach ($attrs as $attr) - { - if (!$this->attributExistInTable($attr['attribut'], $attr['table'])) - { - $this->error_sql['checkedFrom']['attribut'] = array($attr['attribut'], implode(', ', $attr['table'])); - return false; - } - } - } - else - { - if (isset($this->error_sql['returnNameTable'])) - { - $this->error_sql['checkedFrom'] = $this->error_sql['returnNameTable']; - return false; - } - else - { - $this->error_sql['checkedFrom'] = false; - return false; - } - } - } - } - return true; - } + if (isset($table['table']) && !in_array(str_replace('`', '', $table['table']), $this->getTables())) { + $this->error_sql['checkedFrom']['table'] = $table['table']; + return false; + } + if ($table['ref_type'] == 'ON' && (trim($table['join_type']) == 'LEFT' || trim($table['join_type']) == 'JOIN')) { + if ($attrs = $this->cutJoin($table['ref_clause'], $from)) { + foreach ($attrs as $attr) { + if (!$this->attributExistInTable($attr['attribut'], $attr['table'])) { + $this->error_sql['checkedFrom']['attribut'] = array($attr['attribut'], implode(', ', $attr['table'])); + return false; + } + } + } else { + if (isset($this->error_sql['returnNameTable'])) { + $this->error_sql['checkedFrom'] = $this->error_sql['returnNameTable']; + return false; + } else { + $this->error_sql['checkedFrom'] = false; + return false; + } + } + } + } + return true; + } - /** - * Check a "SELECT" sentence - * - * @param $select - * @param $from - * @param bool $in - * @return bool - */ - public function checkedSelect($select, $from, $in = false) - { - $nb = count($select); - for ($i = 0; $i < $nb; $i++) - { - $attribut = $select[$i]; - if ($attribut['base_expr'] != '*' && !preg_match('/\.*$/', $attribut['base_expr'])) - { - if ($attribut['expr_type'] == 'colref') - { - if ($attr = $this->cutAttribute(trim($attribut['base_expr']), $from)) - { - if (!$this->attributExistInTable($attr['attribut'], $attr['table'])) - { - $this->error_sql['checkedSelect']['attribut'] = array($attr['attribut'], implode(', ', $attr['table'])); - return false; - } - } - else - { - if (isset($this->error_sql['returnNameTable'])) - { - $this->error_sql['checkedSelect'] = $this->error_sql['returnNameTable']; - return false; - } - else - { - $this->error_sql['checkedSelect'] = false; - return false; - } - } - } - } - elseif ($in) - { - $this->error_sql['checkedSelect']['*'] = false; - return false; - } - } - return true; - } + /** + * Check a "SELECT" sentence + * + * @param $select + * @param $from + * @param bool $in + * @return bool + */ + public function checkedSelect($select, $from, $in = false) + { + $nb = count($select); + for ($i = 0; $i < $nb; $i++) { + $attribut = $select[$i]; + if ($attribut['base_expr'] != '*' && !preg_match('/\.*$/', $attribut['base_expr'])) { + if ($attribut['expr_type'] == 'colref') { + if ($attr = $this->cutAttribute(trim($attribut['base_expr']), $from)) { + if (!$this->attributExistInTable($attr['attribut'], $attr['table'])) { + $this->error_sql['checkedSelect']['attribut'] = array($attr['attribut'], implode(', ', $attr['table'])); + return false; + } + } else { + if (isset($this->error_sql['returnNameTable'])) { + $this->error_sql['checkedSelect'] = $this->error_sql['returnNameTable']; + return false; + } else { + $this->error_sql['checkedSelect'] = false; + return false; + } + } + } + } elseif ($in) { + $this->error_sql['checkedSelect']['*'] = false; + return false; + } + } + return true; + } - /** - * Check a "WHERE" sentence - * - * @param $where - * @param $from - * @param $sql - * @return bool - */ - public function checkedWhere($where, $from, $sql) - { - $nb = count($where); - for ($i = 0; $i < $nb; $i++) - { - $attribut = $where[$i]; - if ($attribut['expr_type'] == 'colref' || $attribut['expr_type'] == 'reserved') - { - if ($attr = $this->cutAttribute(trim($attribut['base_expr']), $from)) - { - if (!$this->attributExistInTable($attr['attribut'], $attr['table'])) - { - $this->error_sql['checkedWhere']['attribut'] = array($attr['attribut'], implode(', ', $attr['table'])); - return false; - } - } - else - { - if (isset($this->error_sql['returnNameTable'])) - { - $this->error_sql['checkedWhere'] = $this->error_sql['returnNameTable']; - return false; - } - else - { - $this->error_sql['checkedWhere'] = false; - return false; - } - } - } - elseif ($attribut['expr_type'] == 'operator') - { - if (!in_array(strtoupper($attribut['base_expr']), $this->tested['operator'])) - { - $this->error_sql['checkedWhere']['operator'] = array($attribut['base_expr']); - return false; - } - } - elseif ($attribut['expr_type'] == 'subquery') - { - $tab = $attribut['sub_tree']; - return $this->validateParser($tab, true, $sql); - } - } - return true; - } + /** + * Check a "WHERE" sentence + * + * @param $where + * @param $from + * @param $sql + * @return bool + */ + public function checkedWhere($where, $from, $sql) + { + $nb = count($where); + for ($i = 0; $i < $nb; $i++) { + $attribut = $where[$i]; + if ($attribut['expr_type'] == 'colref' || $attribut['expr_type'] == 'reserved') { + if ($attr = $this->cutAttribute(trim($attribut['base_expr']), $from)) { + if (!$this->attributExistInTable($attr['attribut'], $attr['table'])) { + $this->error_sql['checkedWhere']['attribut'] = array($attr['attribut'], implode(', ', $attr['table'])); + return false; + } + } else { + if (isset($this->error_sql['returnNameTable'])) { + $this->error_sql['checkedWhere'] = $this->error_sql['returnNameTable']; + return false; + } else { + $this->error_sql['checkedWhere'] = false; + return false; + } + } + } elseif ($attribut['expr_type'] == 'operator') { + if (!in_array(strtoupper($attribut['base_expr']), $this->tested['operator'])) { + $this->error_sql['checkedWhere']['operator'] = array($attribut['base_expr']); + return false; + } + } elseif ($attribut['expr_type'] == 'subquery') { + $tab = $attribut['sub_tree']; + return $this->validateParser($tab, true, $sql); + } + } + return true; + } - /** - * Check a "HAVING" sentence - * - * @param $having - * @param $from - * @return bool - */ - public function checkedHaving($having, $from) - { - $nb = count($having); - for ($i = 0; $i < $nb; $i++) - { - $attribut = $having[$i]; - if ($attribut['expr_type'] == 'colref') - { - if ($attr = $this->cutAttribute(trim($attribut['base_expr']), $from)) - { - if (!$this->attributExistInTable($attr['attribut'], $attr['table'])) - { - $this->error_sql['checkedHaving']['attribut'] = array($attr['attribut'], implode(', ', $attr['table'])); - return false; - } - } - else - { - if (isset($this->error_sql['returnNameTable'])) - { - $this->error_sql['checkedHaving'] = $this->error_sql['returnNameTable']; - return false; - } - else - { - $this->error_sql['checkedHaving'] = false; - return false; - } - } - } + /** + * Check a "HAVING" sentence + * + * @param $having + * @param $from + * @return bool + */ + public function checkedHaving($having, $from) + { + $nb = count($having); + for ($i = 0; $i < $nb; $i++) { + $attribut = $having[$i]; + if ($attribut['expr_type'] == 'colref') { + if ($attr = $this->cutAttribute(trim($attribut['base_expr']), $from)) { + if (!$this->attributExistInTable($attr['attribut'], $attr['table'])) { + $this->error_sql['checkedHaving']['attribut'] = array($attr['attribut'], implode(', ', $attr['table'])); + return false; + } + } else { + if (isset($this->error_sql['returnNameTable'])) { + $this->error_sql['checkedHaving'] = $this->error_sql['returnNameTable']; + return false; + } else { + $this->error_sql['checkedHaving'] = false; + return false; + } + } + } - if ($attribut['expr_type'] == 'operator') - { - if (!in_array(strtoupper($attribut['base_expr']), $this->tested['operator'])) - { - $this->error_sql['checkedHaving']['operator'] = array($attribut['base_expr']); - return false; - } - } - } - return true; - } + if ($attribut['expr_type'] == 'operator') { + if (!in_array(strtoupper($attribut['base_expr']), $this->tested['operator'])) { + $this->error_sql['checkedHaving']['operator'] = array($attribut['base_expr']); + return false; + } + } + } + return true; + } - /** - * Check a "ORDER" sentence - * - * @param $order - * @param $from - * @return bool - */ - public function checkedOrder($order, $from) - { - $order = $order[0]; - if ($order['type'] == 'expression') - { - if ($attr = $this->cutAttribute(trim($order['base_expr']), $from)) - { - if (!$this->attributExistInTable($attr['attribut'], $attr['table'])) - { - $this->error_sql['checkedOrder']['attribut'] = array($attr['attribut'], implode(', ', $attr['table'])); - return false; - } - } - else - { - if (isset($this->error_sql['returnNameTable'])) - { - $this->error_sql['checkedOrder'] = $this->error_sql['returnNameTable']; - return false; - } - else - { - $this->error_sql['checkedOrder'] = false; - return false; - } - } - } - return true; - } + /** + * Check a "ORDER" sentence + * + * @param $order + * @param $from + * @return bool + */ + public function checkedOrder($order, $from) + { + $order = $order[0]; + if ($order['type'] == 'expression') { + if ($attr = $this->cutAttribute(trim($order['base_expr']), $from)) { + if (!$this->attributExistInTable($attr['attribut'], $attr['table'])) { + $this->error_sql['checkedOrder']['attribut'] = array($attr['attribut'], implode(', ', $attr['table'])); + return false; + } + } else { + if (isset($this->error_sql['returnNameTable'])) { + $this->error_sql['checkedOrder'] = $this->error_sql['returnNameTable']; + return false; + } else { + $this->error_sql['checkedOrder'] = false; + return false; + } + } + } + return true; + } - /** - * Check a "GROUP BY" sentence - * - * @param $group - * @param $from - * @return bool - */ - public function checkedGroupBy($group, $from) - { - $group = $group[0]; - if ($group['type'] == 'expression') - { - if ($attr = $this->cutAttribute(trim($group['base_expr']), $from)) - { - if (!$this->attributExistInTable($attr['attribut'], $attr['table'])) - { - $this->error_sql['checkedGroupBy']['attribut'] = array($attr['attribut'], implode(', ', $attr['table'])); - return false; - } - } - else - { - if (isset($this->error_sql['returnNameTable'])) - { - $this->error_sql['checkedGroupBy'] = $this->error_sql['returnNameTable']; - return false; - } - else - { - $this->error_sql['checkedGroupBy'] = false; - return false; - } - } - } - return true; - } + /** + * Check a "GROUP BY" sentence + * + * @param $group + * @param $from + * @return bool + */ + public function checkedGroupBy($group, $from) + { + $group = $group[0]; + if ($group['type'] == 'expression') { + if ($attr = $this->cutAttribute(trim($group['base_expr']), $from)) { + if (!$this->attributExistInTable($attr['attribut'], $attr['table'])) { + $this->error_sql['checkedGroupBy']['attribut'] = array($attr['attribut'], implode(', ', $attr['table'])); + return false; + } + } else { + if (isset($this->error_sql['returnNameTable'])) { + $this->error_sql['checkedGroupBy'] = $this->error_sql['returnNameTable']; + return false; + } else { + $this->error_sql['checkedGroupBy'] = false; + return false; + } + } + } + return true; + } - /** - * Check a "LIMIT" sentence - * - * @param $limit - * @return bool - */ - public function checkedLimit($limit) - { - if (!preg_match('#^[0-9]+$#', trim($limit['start'])) || !preg_match('#^[0-9]+$#', trim($limit['end']))) - { - $this->error_sql['checkedLimit'] = false; - return false; - } - return true; - } + /** + * Check a "LIMIT" sentence + * + * @param $limit + * @return bool + */ + public function checkedLimit($limit) + { + if (!preg_match('#^[0-9]+$#', trim($limit['start'])) || !preg_match('#^[0-9]+$#', trim($limit['end']))) { + $this->error_sql['checkedLimit'] = false; + return false; + } + return true; + } } diff --git a/classes/Rijndael.php b/classes/Rijndael.php index 6ae99c64..8c855186 100644 --- a/classes/Rijndael.php +++ b/classes/Rijndael.php @@ -26,48 +26,46 @@ class RijndaelCore { - protected $_key; - protected $_iv; + protected $_key; + protected $_iv; - public function __construct($key, $iv) - { - $this->_key = $key; - $this->_iv = base64_decode($iv); - } + public function __construct($key, $iv) + { + $this->_key = $key; + $this->_iv = base64_decode($iv); + } - /** - * Base64 is not required, but it is be more compact than urlencode - * - * @param string $plaintext - * @return bool|string - */ - public function encrypt($plaintext) - { - $length = (ini_get('mbstring.func_overload') & 2) ? mb_strlen($plaintext, ini_get('default_charset')) : strlen($plaintext); + /** + * Base64 is not required, but it is be more compact than urlencode + * + * @param string $plaintext + * @return bool|string + */ + public function encrypt($plaintext) + { + $length = (ini_get('mbstring.func_overload') & 2) ? mb_strlen($plaintext, ini_get('default_charset')) : strlen($plaintext); - if ($length >= 1048576) - return false; - return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->_key, $plaintext, MCRYPT_MODE_ECB, $this->_iv)).sprintf('%06d', $length); - } + if ($length >= 1048576) { + return false; + } + return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->_key, $plaintext, MCRYPT_MODE_ECB, $this->_iv)).sprintf('%06d', $length); + } - public function decrypt($ciphertext) - { - if (ini_get('mbstring.func_overload') & 2) - { - $length = intval(mb_substr($ciphertext, -6, 6, ini_get('default_charset'))); - $ciphertext = mb_substr($ciphertext, 0, -6, ini_get('default_charset')); - return mb_substr( - mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->_key, base64_decode($ciphertext), MCRYPT_MODE_ECB, $this->_iv), - 0, - $length, - ini_get('default_charset') - ); - } - else - { - $length = intval(substr($ciphertext, -6)); - $ciphertext = substr($ciphertext, 0, -6); - return substr(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->_key, base64_decode($ciphertext), MCRYPT_MODE_ECB, $this->_iv), 0, $length); - } - } -} \ No newline at end of file + public function decrypt($ciphertext) + { + if (ini_get('mbstring.func_overload') & 2) { + $length = intval(mb_substr($ciphertext, -6, 6, ini_get('default_charset'))); + $ciphertext = mb_substr($ciphertext, 0, -6, ini_get('default_charset')); + return mb_substr( + mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->_key, base64_decode($ciphertext), MCRYPT_MODE_ECB, $this->_iv), + 0, + $length, + ini_get('default_charset') + ); + } else { + $length = intval(substr($ciphertext, -6)); + $ciphertext = substr($ciphertext, 0, -6); + return substr(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->_key, base64_decode($ciphertext), MCRYPT_MODE_ECB, $this->_iv), 0, $length); + } + } +} diff --git a/classes/Risk.php b/classes/Risk.php index 4f641fdc..cca4d794 100644 --- a/classes/Risk.php +++ b/classes/Risk.php @@ -29,48 +29,49 @@ */ class RiskCore extends ObjectModel { - public $id_risk; - public $name; - public $color; - public $percent; + public $id_risk; + public $name; + public $color; + public $percent; - public static $definition = array( - 'table' => 'risk', - 'primary' => 'id_risk', - 'multilang' => true, - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isString', 'required' => true, 'size' => 20), - 'color' => array('type' => self::TYPE_STRING, 'validate' => 'isColor', 'size' => 32), - 'percent' => array('type' => self::TYPE_INT, 'validate' => 'isPercentage') - ), - ); + public static $definition = array( + 'table' => 'risk', + 'primary' => 'id_risk', + 'multilang' => true, + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isString', 'required' => true, 'size' => 20), + 'color' => array('type' => self::TYPE_STRING, 'validate' => 'isColor', 'size' => 32), + 'percent' => array('type' => self::TYPE_INT, 'validate' => 'isPercentage') + ), + ); - public function getFields() - { - $this->validateFields(); - $fields['id_risk'] = (int)$this->id_risk; - $fields['color'] = pSQL($this->color); - $fields['percent'] = (int)$this->percent; - return $fields; - } + public function getFields() + { + $this->validateFields(); + $fields['id_risk'] = (int)$this->id_risk; + $fields['color'] = pSQL($this->color); + $fields['percent'] = (int)$this->percent; + return $fields; + } - /** - * Check then return multilingual fields for database interaction - * - * @return array Multilingual fields - */ - public function getTranslationsFieldsChild() - { - $this->validateFieldsLang(); - return $this->getTranslationsFields(array('name')); - } + /** + * Check then return multilingual fields for database interaction + * + * @return array Multilingual fields + */ + public function getTranslationsFieldsChild() + { + $this->validateFieldsLang(); + return $this->getTranslationsFields(array('name')); + } - public static function getRisks($id_lang = null) - { - if (is_null($id_lang)) - $id_lang = Context::getContext()->language->id; + public static function getRisks($id_lang = null) + { + if (is_null($id_lang)) { + $id_lang = Context::getContext()->language->id; + } - $risks = new PrestaShopCollection('Risk', $id_lang); - return $risks; - } -} \ No newline at end of file + $risks = new PrestaShopCollection('Risk', $id_lang); + return $risks; + } +} diff --git a/classes/Scene.php b/classes/Scene.php index c026e754..6f536f49 100644 --- a/classes/Scene.php +++ b/classes/Scene.php @@ -26,280 +26,292 @@ class SceneCore extends ObjectModel { - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var bool Active Scene */ - public $active = true; + /** @var bool Active Scene */ + public $active = true; - /** @var array Zone for image map */ - public $zones = array(); + /** @var array Zone for image map */ + public $zones = array(); - /** @var array list of category where this scene is available */ - public $categories = array(); + /** @var array list of category where this scene is available */ + public $categories = array(); - /** @var array Products */ - public $products; + /** @var array Products */ + public $products; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'scene', - 'primary' => 'id_scene', - 'multilang' => true, - 'fields' => array( - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'scene', + 'primary' => 'id_scene', + 'multilang' => true, + 'fields' => array( + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 100), - ), - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 100), + ), + ); - protected static $feature_active = null; + protected static $feature_active = null; - public function __construct($id = null, $id_lang = null, $lite_result = true, $hide_scene_position = false) - { - parent::__construct($id, $id_lang); + public function __construct($id = null, $id_lang = null, $lite_result = true, $hide_scene_position = false) + { + parent::__construct($id, $id_lang); - if (!$lite_result) - $this->products = $this->getProducts(true, (int)$id_lang, false); - if ($hide_scene_position) - $this->name = Scene::hideScenePosition($this->name); - $this->image_dir = _PS_SCENE_IMG_DIR_; - } + if (!$lite_result) { + $this->products = $this->getProducts(true, (int)$id_lang, false); + } + if ($hide_scene_position) { + $this->name = Scene::hideScenePosition($this->name); + } + $this->image_dir = _PS_SCENE_IMG_DIR_; + } - public function update($null_values = false) - { - if (!$this->updateZoneProducts()) - return false; - if (!$this->updateCategories()) - return false; + public function update($null_values = false) + { + if (!$this->updateZoneProducts()) { + return false; + } + if (!$this->updateCategories()) { + return false; + } - if (parent::update($null_values)) - { - // Refresh cache of feature detachable - Configuration::updateGlobalValue('PS_SCENE_FEATURE_ACTIVE', Scene::isCurrentlyUsed($this->def['table'], true)); - return true; - } - return false; + if (parent::update($null_values)) { + // Refresh cache of feature detachable + Configuration::updateGlobalValue('PS_SCENE_FEATURE_ACTIVE', Scene::isCurrentlyUsed($this->def['table'], true)); + return true; + } + return false; + } - } + public function add($autodate = true, $null_values = false) + { + if (!empty($this->zones)) { + $this->addZoneProducts($this->zones); + } + if (!empty($this->categories)) { + $this->addCategories($this->categories); + } - public function add($autodate = true, $null_values = false) - { - if (!empty($this->zones)) - $this->addZoneProducts($this->zones); - if (!empty($this->categories)) - $this->addCategories($this->categories); + if (parent::add($autodate, $null_values)) { + // Put cache of feature detachable only if this new scene is active else we keep the old value + if ($this->active) { + Configuration::updateGlobalValue('PS_SCENE_FEATURE_ACTIVE', '1'); + } + return true; + } + return false; + } - if (parent::add($autodate, $null_values)) - { - // Put cache of feature detachable only if this new scene is active else we keep the old value - if ($this->active) - Configuration::updateGlobalValue('PS_SCENE_FEATURE_ACTIVE', '1'); - return true; - } - return false; - } + public function delete() + { + $this->deleteZoneProducts(); + $this->deleteCategories(); + if (parent::delete()) { + return $this->deleteImage() && + Configuration::updateGlobalValue('PS_SCENE_FEATURE_ACTIVE', Scene::isCurrentlyUsed($this->def['table'], true)); + } + return false; + } - public function delete() - { - $this->deleteZoneProducts(); - $this->deleteCategories(); - if (parent::delete()) - { - return $this->deleteImage() && - Configuration::updateGlobalValue('PS_SCENE_FEATURE_ACTIVE', Scene::isCurrentlyUsed($this->def['table'], true)); - } - return false; - } + public function deleteImage($force_delete = false) + { + if (file_exists($this->image_dir.'thumbs/'.$this->id.'-m_scene_default.'.$this->image_format) + && !unlink($this->image_dir.'thumbs/'.$this->id.'-m_scene_default.'.$this->image_format)) { + return false; + } + if (!(isset($_FILES) && count($_FILES))) { + return parent::deleteImage(); + } + return true; + } - public function deleteImage($force_delete = false) - { - if (file_exists($this->image_dir.'thumbs/'.$this->id.'-m_scene_default.'.$this->image_format) - && !unlink($this->image_dir.'thumbs/'.$this->id.'-m_scene_default.'.$this->image_format)) - return false; - if (!(isset($_FILES) && count($_FILES))) - return parent::deleteImage(); - return true; - } + public function addCategories($categories) + { + $data = array(); + foreach ($categories as $category) { + $data[] = array( + 'id_scene' => (int)$this->id, + 'id_category' => (int)$category, + ); + } + return Db::getInstance()->insert('scene_category', $data); + } - public function addCategories($categories) - { - $data = array(); - foreach ($categories as $category) - { - $data[] = array( - 'id_scene' => (int)$this->id, - 'id_category' => (int)$category, - ); - } - return Db::getInstance()->insert('scene_category', $data); - } - - public function deleteCategories() - { - return Db::getInstance()->execute(' + public function deleteCategories() + { + return Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'scene_category` WHERE `id_scene` = '.(int)$this->id); - } + } - public function updateCategories() - { - if (!$this->deleteCategories()) - return false; - if (!empty($this->categories) && !$this->addCategories($this->categories)) - return false; - return true; - } + public function updateCategories() + { + if (!$this->deleteCategories()) { + return false; + } + if (!empty($this->categories) && !$this->addCategories($this->categories)) { + return false; + } + return true; + } - public function addZoneProducts($zones) - { - $data = array(); - foreach ($zones as $zone) - { - $data[] = array( - 'id_scene' => (int)$this->id, - 'id_product' => (int)$zone['id_product'], - 'x_axis' => (int)$zone['x1'], - 'y_axis' => (int)$zone['y1'], - 'zone_width' => (int)$zone['width'], - 'zone_height' => (int)$zone['height'], - ); - } + public function addZoneProducts($zones) + { + $data = array(); + foreach ($zones as $zone) { + $data[] = array( + 'id_scene' => (int)$this->id, + 'id_product' => (int)$zone['id_product'], + 'x_axis' => (int)$zone['x1'], + 'y_axis' => (int)$zone['y1'], + 'zone_width' => (int)$zone['width'], + 'zone_height' => (int)$zone['height'], + ); + } - return Db::getInstance()->insert('scene_products', $data); - } + return Db::getInstance()->insert('scene_products', $data); + } - public function deleteZoneProducts() - { - return Db::getInstance()->execute(' + public function deleteZoneProducts() + { + return Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'scene_products` WHERE `id_scene` = '.(int)$this->id); - } + } - public function updateZoneProducts() - { - if (!$this->deleteZoneProducts()) - return false; - if ($this->zones && !$this->addZoneProducts($this->zones)) - return false; - return true; - } + public function updateZoneProducts() + { + if (!$this->deleteZoneProducts()) { + return false; + } + if ($this->zones && !$this->addZoneProducts($this->zones)) { + return false; + } + return true; + } - /** - * Get all scenes of a category - * - * @return array Products - */ - public static function getScenes($id_category, $id_lang = null, $only_active = true, $lite_result = true, $hide_scene_position = true, - Context $context = null) - { - if (!Scene::isFeatureActive()) - return array(); + /** + * Get all scenes of a category + * + * @return array Products + */ + public static function getScenes($id_category, $id_lang = null, $only_active = true, $lite_result = true, $hide_scene_position = true, + Context $context = null) + { + if (!Scene::isFeatureActive()) { + return array(); + } - $cache_key = 'Scene::getScenes'.$id_category.(int)$lite_result; - if (!Cache::isStored($cache_key)) - { - if (!$context) - $context = Context::getContext(); - $id_lang = is_null($id_lang) ? $context->language->id : $id_lang; + $cache_key = 'Scene::getScenes'.$id_category.(int)$lite_result; + if (!Cache::isStored($cache_key)) { + if (!$context) { + $context = Context::getContext(); + } + $id_lang = is_null($id_lang) ? $context->language->id : $id_lang; - $sql = 'SELECT s.* + $sql = 'SELECT s.* FROM `'._DB_PREFIX_.'scene_category` sc LEFT JOIN `'._DB_PREFIX_.'scene` s ON (sc.id_scene = s.id_scene) '.Shop::addSqlAssociation('scene', 's').' LEFT JOIN `'._DB_PREFIX_.'scene_lang` sl ON (sl.id_scene = s.id_scene) WHERE sc.id_category = '.(int)$id_category.' AND sl.id_lang = '.(int)$id_lang - .($only_active ? ' AND s.active = 1' : '').' + .($only_active ? ' AND s.active = 1' : '').' ORDER BY sl.name ASC'; - $scenes = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + $scenes = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - if (!$lite_result && $scenes) - foreach ($scenes as &$scene) - $scene = new Scene($scene['id_scene'], $id_lang, false, $hide_scene_position); - Cache::store($cache_key, $scenes); - } - else - $scenes = Cache::retrieve($cache_key); - return $scenes; - } + if (!$lite_result && $scenes) { + foreach ($scenes as &$scene) { + $scene = new Scene($scene['id_scene'], $id_lang, false, $hide_scene_position); + } + } + Cache::store($cache_key, $scenes); + } else { + $scenes = Cache::retrieve($cache_key); + } + return $scenes; + } - /** - * Get all products of this scene - * - * @return array Products - */ - public function getProducts($only_active = true, $id_lang = null, $lite_result = true, Context $context = null) - { - if (!Scene::isFeatureActive()) - return array(); + /** + * Get all products of this scene + * + * @return array Products + */ + public function getProducts($only_active = true, $id_lang = null, $lite_result = true, Context $context = null) + { + if (!Scene::isFeatureActive()) { + return array(); + } - if (!$context) - $context = Context::getContext(); - $id_lang = is_null($id_lang) ? $context->language->id : $id_lang; + if (!$context) { + $context = Context::getContext(); + } + $id_lang = is_null($id_lang) ? $context->language->id : $id_lang; - $products = Db::getInstance()->executeS(' + $products = Db::getInstance()->executeS(' SELECT s.* FROM `'._DB_PREFIX_.'scene_products` s LEFT JOIN `'._DB_PREFIX_.'product` p ON (p.id_product = s.id_product) '.Shop::addSqlAssociation('product', 'p').' WHERE s.id_scene = '.(int)$this->id.($only_active ? ' AND product_shop.active = 1' : '')); - if (!$lite_result && $products) - foreach ($products as &$product) - { - $product['details'] = new Product($product['id_product'], !$lite_result, $id_lang); - if (Validate::isLoadedObject($product['details'])) - { - $product['link'] = $context->link->getProductLink( - $product['details']->id, - $product['details']->link_rewrite, - $product['details']->category, - $product['details']->ean13 - ); - $cover = Product::getCover($product['details']->id); - if (is_array($cover)) - $product = array_merge($cover, $product); - } - } - return $products; - } + if (!$lite_result && $products) { + foreach ($products as &$product) { + $product['details'] = new Product($product['id_product'], !$lite_result, $id_lang); + if (Validate::isLoadedObject($product['details'])) { + $product['link'] = $context->link->getProductLink( + $product['details']->id, + $product['details']->link_rewrite, + $product['details']->category, + $product['details']->ean13 + ); + $cover = Product::getCover($product['details']->id); + if (is_array($cover)) { + $product = array_merge($cover, $product); + } + } + } + } + return $products; + } - /** - * Get categories where scene is indexed - * - * @param int $id_scene Scene id - * @return array Categories where scene is indexed - */ - public static function getIndexedCategories($id_scene) - { - return Db::getInstance()->executeS(' + /** + * Get categories where scene is indexed + * + * @param int $id_scene Scene id + * @return array Categories where scene is indexed + */ + public static function getIndexedCategories($id_scene) + { + return Db::getInstance()->executeS(' SELECT `id_category` FROM `'._DB_PREFIX_.'scene_category` WHERE `id_scene` = '.(int)$id_scene); - } + } - /** - * Hide scene prefix used for position - * - * @param string $name Scene name - * @return string Name without position - */ - public static function hideScenePosition($name) - { - return preg_replace('/^[0-9]+\./', '', $name); - } + /** + * Hide scene prefix used for position + * + * @param string $name Scene name + * @return string Name without position + */ + public static function hideScenePosition($name) + { + return preg_replace('/^[0-9]+\./', '', $name); + } - /** - * This method is allow to know if a feature is used or active - * @since 1.5.0.1 - * @return bool - */ - public static function isFeatureActive() - { - return Configuration::get('PS_SCENE_FEATURE_ACTIVE'); - } -} \ No newline at end of file + /** + * This method is allow to know if a feature is used or active + * @since 1.5.0.1 + * @return bool + */ + public static function isFeatureActive() + { + return Configuration::get('PS_SCENE_FEATURE_ACTIVE'); + } +} diff --git a/classes/Search.php b/classes/Search.php index 7dae32b8..e902495a 100644 --- a/classes/Search.php +++ b/classes/Search.php @@ -93,136 +93,141 @@ define('PREG_CLASS_CJK', '\x{3041}-\x{30ff}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{ class SearchCore { - public static function sanitize($string, $id_lang, $indexation = false, $iso_code = false) - { - $string = trim($string); - if (empty($string)) - return ''; + public static function sanitize($string, $id_lang, $indexation = false, $iso_code = false) + { + $string = trim($string); + if (empty($string)) { + return ''; + } - $string = Tools::strtolower(strip_tags($string)); - $string = html_entity_decode($string, ENT_NOQUOTES, 'utf-8'); + $string = Tools::strtolower(strip_tags($string)); + $string = html_entity_decode($string, ENT_NOQUOTES, 'utf-8'); - $string = preg_replace('/(['.PREG_CLASS_NUMBERS.']+)['.PREG_CLASS_PUNCTUATION.']+(?=['.PREG_CLASS_NUMBERS.'])/u', '\1', $string); - $string = preg_replace('/['.PREG_CLASS_SEARCH_EXCLUDE.']+/u', ' ', $string); + $string = preg_replace('/(['.PREG_CLASS_NUMBERS.']+)['.PREG_CLASS_PUNCTUATION.']+(?=['.PREG_CLASS_NUMBERS.'])/u', '\1', $string); + $string = preg_replace('/['.PREG_CLASS_SEARCH_EXCLUDE.']+/u', ' ', $string); - if ($indexation) - $string = preg_replace('/[._-]+/', ' ', $string); - else - { - $string = preg_replace('/[._]+/', '', $string); - $string = ltrim(preg_replace('/([^ ])-/', '$1 ', ' '.$string)); - $string = preg_replace('/[._]+/', '', $string); - $string = preg_replace('/[^\s]-+/', '', $string); - } + if ($indexation) { + $string = preg_replace('/[._-]+/', ' ', $string); + } else { + $string = preg_replace('/[._]+/', '', $string); + $string = ltrim(preg_replace('/([^ ])-/', '$1 ', ' '.$string)); + $string = preg_replace('/[._]+/', '', $string); + $string = preg_replace('/[^\s]-+/', '', $string); + } - $blacklist = Tools::strtolower(Configuration::get('PS_SEARCH_BLACKLIST', $id_lang)); - if (!empty($blacklist)) - { - $string = preg_replace('/(?<=\s)('.$blacklist.')(?=\s)/Su', '', $string); - $string = preg_replace('/^('.$blacklist.')(?=\s)/Su', '', $string); - $string = preg_replace('/(?<=\s)('.$blacklist.')$/Su', '', $string); - $string = preg_replace('/^('.$blacklist.')$/Su', '', $string); - } + $blacklist = Tools::strtolower(Configuration::get('PS_SEARCH_BLACKLIST', $id_lang)); + if (!empty($blacklist)) { + $string = preg_replace('/(?<=\s)('.$blacklist.')(?=\s)/Su', '', $string); + $string = preg_replace('/^('.$blacklist.')(?=\s)/Su', '', $string); + $string = preg_replace('/(?<=\s)('.$blacklist.')$/Su', '', $string); + $string = preg_replace('/^('.$blacklist.')$/Su', '', $string); + } - if (!$indexation) - { - $words = explode(' ', $string); - $processed_words = array(); - // search for aliases for each word of the query - foreach ($words as $word) - { - $alias = new Alias(null, $word); - if (Validate::isLoadedObject($alias)) - $processed_words[] = $alias->search; - else - $processed_words[] = $word; - } - $string = implode(' ', $processed_words); - } + if (!$indexation) { + $words = explode(' ', $string); + $processed_words = array(); + // search for aliases for each word of the query + foreach ($words as $word) { + $alias = new Alias(null, $word); + if (Validate::isLoadedObject($alias)) { + $processed_words[] = $alias->search; + } else { + $processed_words[] = $word; + } + } + $string = implode(' ', $processed_words); + } - // If the language is constituted with symbol and there is no "words", then split every chars - if (in_array($iso_code, array('zh', 'tw', 'ja')) && function_exists('mb_strlen')) - { - // Cut symbols from letters - $symbols = ''; - $letters = ''; - foreach (explode(' ', $string) as $mb_word) - if (strlen(Tools::replaceAccentedChars($mb_word)) == mb_strlen(Tools::replaceAccentedChars($mb_word))) - $letters .= $mb_word.' '; - else - $symbols .= $mb_word.' '; + // If the language is constituted with symbol and there is no "words", then split every chars + if (in_array($iso_code, array('zh', 'tw', 'ja')) && function_exists('mb_strlen')) { + // Cut symbols from letters + $symbols = ''; + $letters = ''; + foreach (explode(' ', $string) as $mb_word) { + if (strlen(Tools::replaceAccentedChars($mb_word)) == mb_strlen(Tools::replaceAccentedChars($mb_word))) { + $letters .= $mb_word.' '; + } else { + $symbols .= $mb_word.' '; + } + } - if (preg_match_all('/./u', $symbols, $matches)) - $symbols = implode(' ', $matches[0]); + if (preg_match_all('/./u', $symbols, $matches)) { + $symbols = implode(' ', $matches[0]); + } - $string = $letters.$symbols; - } - elseif ($indexation) - { - $minWordLen = (int)Configuration::get('PS_SEARCH_MINWORDLEN'); - if ($minWordLen > 1) - { - $minWordLen -= 1; - $string = preg_replace('/(?<=\s)[^\s]{1,'.$minWordLen.'}(?=\s)/Su', ' ', $string); - $string = preg_replace('/^[^\s]{1,'.$minWordLen.'}(?=\s)/Su', '', $string); - $string = preg_replace('/(?<=\s)[^\s]{1,'.$minWordLen.'}$/Su', '', $string); - $string = preg_replace('/^[^\s]{1,'.$minWordLen.'}$/Su', '', $string); - } - } + $string = $letters.$symbols; + } elseif ($indexation) { + $minWordLen = (int)Configuration::get('PS_SEARCH_MINWORDLEN'); + if ($minWordLen > 1) { + $minWordLen -= 1; + $string = preg_replace('/(?<=\s)[^\s]{1,'.$minWordLen.'}(?=\s)/Su', ' ', $string); + $string = preg_replace('/^[^\s]{1,'.$minWordLen.'}(?=\s)/Su', '', $string); + $string = preg_replace('/(?<=\s)[^\s]{1,'.$minWordLen.'}$/Su', '', $string); + $string = preg_replace('/^[^\s]{1,'.$minWordLen.'}$/Su', '', $string); + } + } - $string = trim(preg_replace('/\s+/', ' ', $string)); - return $string; - } + $string = Tools::replaceAccentedChars(trim(preg_replace('/\s+/', ' ', $string))); - public static function find($id_lang, $expr, $page_number = 1, $page_size = 1, $order_by = 'position', - $order_way = 'desc', $ajax = false, $use_cookie = true, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - $db = Db::getInstance(_PS_USE_SQL_SLAVE_); + return $string; + } - // TODO : smart page management - if ($page_number < 1) $page_number = 1; - if ($page_size < 1) $page_size = 1; + public static function find($id_lang, $expr, $page_number = 1, $page_size = 1, $order_by = 'position', + $order_way = 'desc', $ajax = false, $use_cookie = true, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + $db = Db::getInstance(_PS_USE_SQL_SLAVE_); - if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) - return false; + // TODO : smart page management + if ($page_number < 1) { + $page_number = 1; + } + if ($page_size < 1) { + $page_size = 1; + } - $intersect_array = array(); - $score_array = array(); - $words = explode(' ', Search::sanitize($expr, $id_lang, false, $context->language->iso_code)); + if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) { + return false; + } - foreach ($words as $key => $word) - if (!empty($word) && strlen($word) >= (int)Configuration::get('PS_SEARCH_MINWORDLEN')) - { - $word = str_replace('%', '\\%', $word); - $word = str_replace('_', '\\_', $word); - $start_search = Configuration::get('PS_SEARCH_START') ? '%': ''; - $end_search = Configuration::get('PS_SEARCH_END') ? '': '%'; + $intersect_array = array(); + $score_array = array(); + $words = explode(' ', Search::sanitize($expr, $id_lang, false, $context->language->iso_code)); - $intersect_array[] = 'SELECT si.id_product + foreach ($words as $key => $word) { + if (!empty($word) && strlen($word) >= (int)Configuration::get('PS_SEARCH_MINWORDLEN')) { + $word = str_replace(array('%', '_'), array('\\%', '\\_'), $word); + $start_search = Configuration::get('PS_SEARCH_START') ? '%': ''; + $end_search = Configuration::get('PS_SEARCH_END') ? '': '%'; + + $intersect_array[] = 'SELECT si.id_product FROM '._DB_PREFIX_.'search_word sw LEFT JOIN '._DB_PREFIX_.'search_index si ON sw.id_word = si.id_word WHERE sw.id_lang = '.(int)$id_lang.' AND sw.id_shop = '.$context->shop->id.' AND sw.word LIKE '.($word[0] == '-' - ? ' \''.$start_search.pSQL(Tools::substr($word, 1, PS_SEARCH_MAX_WORD_LENGTH)).$end_search.'\'' - : ' \''.$start_search.pSQL(Tools::substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH)).$end_search.'\'' - ); + ? ' \''.$start_search.pSQL(Tools::substr($word, 1, PS_SEARCH_MAX_WORD_LENGTH)).$end_search.'\'' + : ' \''.$start_search.pSQL(Tools::substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH)).$end_search.'\'' + ); - if ($word[0] != '-') - $score_array[] = 'sw.word LIKE \''.$start_search.pSQL(Tools::substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH)).$end_search.'\''; - } - else - unset($words[$key]); + if ($word[0] != '-') { + $score_array[] = 'sw.word LIKE \''.$start_search.pSQL(Tools::substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH)).$end_search.'\''; + } + } else { + unset($words[$key]); + } + } - if (!count($words)) - return ($ajax ? array() : array('total' => 0, 'result' => array())); + if (!count($words)) { + return ($ajax ? array() : array('total' => 0, 'result' => array())); + } - $score = ''; - if (is_array($score_array) && !empty($score_array)) - $score = ',( + $score = ''; + if (is_array($score_array) && !empty($score_array)) { + $score = ',( SELECT SUM(weight) FROM '._DB_PREFIX_.'search_word sw LEFT JOIN '._DB_PREFIX_.'search_index si ON sw.id_word = si.id_word @@ -231,15 +236,15 @@ class SearchCore AND si.id_product = p.id_product AND ('.implode(' OR ', $score_array).') ) position'; + } - $sql_groups = ''; - if (Group::isFeatureActive()) - { - $groups = FrontController::getCurrentCustomerGroups(); - $sql_groups = 'AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); - } + $sql_groups = ''; + if (Group::isFeatureActive()) { + $groups = FrontController::getCurrentCustomerGroups(); + $sql_groups = 'AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); + } - $results = $db->executeS(' + $results = $db->executeS(' SELECT cp.`id_product` FROM `'._DB_PREFIX_.'category_product` cp '.(Group::isFeatureActive() ? 'INNER JOIN `'._DB_PREFIX_.'category_group` cg ON cp.`id_category` = cg.`id_category`' : '').' @@ -252,33 +257,37 @@ class SearchCore AND product_shop.indexed = 1 '.$sql_groups, true, false); - $eligible_products = array(); - foreach ($results as $row) - $eligible_products[] = $row['id_product']; - foreach ($intersect_array as $query) - { - $eligible_products2 = array(); - foreach ($db->executeS($query, true, false) as $row) - $eligible_products2[] = $row['id_product']; + $eligible_products = array(); + foreach ($results as $row) { + $eligible_products[] = $row['id_product']; + } + foreach ($intersect_array as $query) { + $eligible_products2 = array(); + foreach ($db->executeS($query, true, false) as $row) { + $eligible_products2[] = $row['id_product']; + } - $eligible_products = array_intersect($eligible_products, $eligible_products2); - if (!count($eligible_products)) - return ($ajax ? array() : array('total' => 0, 'result' => array())); - } + $eligible_products = array_intersect($eligible_products, $eligible_products2); + if (!count($eligible_products)) { + return ($ajax ? array() : array('total' => 0, 'result' => array())); + } + } - $eligible_products = array_unique($eligible_products); + $eligible_products = array_unique($eligible_products); - $product_pool = ''; - foreach ($eligible_products as $id_product) - if ($id_product) - $product_pool .= (int)$id_product.','; - if (empty($product_pool)) - return ($ajax ? array() : array('total' => 0, 'result' => array())); - $product_pool = ((strpos($product_pool, ',') === false) ? (' = '.(int)$product_pool.' ') : (' IN ('.rtrim($product_pool, ',').') ')); + $product_pool = ''; + foreach ($eligible_products as $id_product) { + if ($id_product) { + $product_pool .= (int)$id_product.','; + } + } + if (empty($product_pool)) { + return ($ajax ? array() : array('total' => 0, 'result' => array())); + } + $product_pool = ((strpos($product_pool, ',') === false) ? (' = '.(int)$product_pool.' ') : (' IN ('.rtrim($product_pool, ',').') ')); - if ($ajax) - { - $sql = 'SELECT DISTINCT p.id_product, pl.name pname, cl.name cname, + if ($ajax) { + $sql = 'SELECT DISTINCT p.id_product, pl.name pname, cl.name cname, cl.link_rewrite crewrite, pl.link_rewrite prewrite '.$score.' FROM '._DB_PREFIX_.'product p INNER JOIN `'._DB_PREFIX_.'product_lang` pl ON ( @@ -292,20 +301,20 @@ class SearchCore ) WHERE p.`id_product` '.$product_pool.' ORDER BY position DESC LIMIT 10'; - return $db->executeS($sql, true, false); - } + return $db->executeS($sql, true, false); + } - if (strpos($order_by, '.') > 0) - { - $order_by = explode('.', $order_by); - $order_by = pSQL($order_by[0]).'.`'.pSQL($order_by[1]).'`'; - } - $alias = ''; - if ($order_by == 'price') - $alias = 'product_shop.'; - elseif (in_array($order_by, array('date_upd', 'date_add'))) - $alias = 'p.'; - $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, + if (strpos($order_by, '.') > 0) { + $order_by = explode('.', $order_by); + $order_by = pSQL($order_by[0]).'.`'.pSQL($order_by[1]).'`'; + } + $alias = ''; + if ($order_by == 'price') { + $alias = 'product_shop.'; + } elseif (in_array($order_by, array('date_upd', 'date_add'))) { + $alias = 'p.'; + } + $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`name`, image_shop.`id_image` id_image, il.`legend`, m.`name` manufacturer_name '.$score.', DATEDIFF( @@ -332,9 +341,9 @@ class SearchCore GROUP BY product_shop.id_product '.($order_by ? 'ORDER BY '.$alias.$order_by : '').($order_way ? ' '.$order_way : '').' LIMIT '.(int)(($page_number - 1) * $page_size).','.(int)$page_size; - $result = $db->executeS($sql, true, false); + $result = $db->executeS($sql, true, false); - $sql = 'SELECT COUNT(*) + $sql = 'SELECT COUNT(*) FROM '._DB_PREFIX_.'product p '.Shop::addSqlAssociation('product', 'p').' INNER JOIN `'._DB_PREFIX_.'product_lang` pl ON ( @@ -343,113 +352,120 @@ class SearchCore ) LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer` WHERE p.`id_product` '.$product_pool; - $total = $db->getValue($sql, false); + $total = $db->getValue($sql, false); - if (!$result) - $result_properties = false; - else - $result_properties = Product::getProductsProperties((int)$id_lang, $result); + if (!$result) { + $result_properties = false; + } else { + $result_properties = Product::getProductsProperties((int)$id_lang, $result); + } - return array('total' => $total,'result' => $result_properties); - } + return array('total' => $total,'result' => $result_properties); + } - /** - * @param Db $db - * @param int $id_product - * @param int $id_lang - * @return string - */ - public static function getTags($db, $id_product, $id_lang) - { - $tags = ''; - $tagsArray = $db->executeS(' + /** + * @param Db $db + * @param int $id_product + * @param int $id_lang + * @return string + */ + public static function getTags($db, $id_product, $id_lang) + { + $tags = ''; + $tagsArray = $db->executeS(' SELECT t.name FROM '._DB_PREFIX_.'product_tag pt LEFT JOIN '._DB_PREFIX_.'tag t ON (pt.id_tag = t.id_tag AND t.id_lang = '.(int)$id_lang.') WHERE pt.id_product = '.(int)$id_product, true, false); - foreach ($tagsArray as $tag) - $tags .= $tag['name'].' '; - return $tags; - } + foreach ($tagsArray as $tag) { + $tags .= $tag['name'].' '; + } + return $tags; + } - /** - * @param Db $db - * @param int $id_product - * @param int $id_lang - * @return string - */ - public static function getAttributes($db, $id_product, $id_lang) - { - if (!Combination::isFeatureActive()) - return ''; + /** + * @param Db $db + * @param int $id_product + * @param int $id_lang + * @return string + */ + public static function getAttributes($db, $id_product, $id_lang) + { + if (!Combination::isFeatureActive()) { + return ''; + } - $attributes = ''; - $attributesArray = $db->executeS(' + $attributes = ''; + $attributesArray = $db->executeS(' SELECT al.name FROM '._DB_PREFIX_.'product_attribute pa INNER JOIN '._DB_PREFIX_.'product_attribute_combination pac ON pa.id_product_attribute = pac.id_product_attribute INNER JOIN '._DB_PREFIX_.'attribute_lang al ON (pac.id_attribute = al.id_attribute AND al.id_lang = '.(int)$id_lang.') '.Shop::addSqlAssociation('product_attribute', 'pa').' WHERE pa.id_product = '.(int)$id_product, true, false); - foreach ($attributesArray as $attribute) - $attributes .= $attribute['name'].' '; - return $attributes; - } + foreach ($attributesArray as $attribute) { + $attributes .= $attribute['name'].' '; + } + return $attributes; + } - /** - * @param Db $db - * @param int $id_product - * @param int $id_lang - * @return string - */ - public static function getFeatures($db, $id_product, $id_lang) - { - if (!Feature::isFeatureActive()) - return ''; + /** + * @param Db $db + * @param int $id_product + * @param int $id_lang + * @return string + */ + public static function getFeatures($db, $id_product, $id_lang) + { + if (!Feature::isFeatureActive()) { + return ''; + } - $features = ''; - $featuresArray = $db->executeS(' + $features = ''; + $featuresArray = $db->executeS(' SELECT fvl.value FROM '._DB_PREFIX_.'feature_product fp LEFT JOIN '._DB_PREFIX_.'feature_value_lang fvl ON (fp.id_feature_value = fvl.id_feature_value AND fvl.id_lang = '.(int)$id_lang.') WHERE fp.id_product = '.(int)$id_product, true, false); - foreach ($featuresArray as $feature) - $features .= $feature['value'].' '; - return $features; - } + foreach ($featuresArray as $feature) { + $features .= $feature['value'].' '; + } + return $features; + } - /** - * @param $weight_array - * @return string - */ - protected static function getSQLProductAttributeFields(&$weight_array) - { - $sql = ''; - if (is_array($weight_array)) - foreach ($weight_array as $key => $weight) - if ((int)$weight) - switch ($key) - { - case 'pa_reference': - $sql .= ', pa.reference AS pa_reference'; - break; - case 'pa_supplier_reference': - $sql .= ', pa.supplier_reference AS pa_supplier_reference'; - break; - case 'pa_ean13': - $sql .= ', pa.ean13 AS pa_ean13'; - break; - case 'pa_upc': - $sql .= ', pa.upc AS pa_upc'; - break; - } - return $sql; - } + /** + * @param $weight_array + * @return string + */ + protected static function getSQLProductAttributeFields(&$weight_array) + { + $sql = ''; + if (is_array($weight_array)) { + foreach ($weight_array as $key => $weight) { + if ((int)$weight) { + switch ($key) { + case 'pa_reference': + $sql .= ', pa.reference AS pa_reference'; + break; + case 'pa_supplier_reference': + $sql .= ', pa.supplier_reference AS pa_supplier_reference'; + break; + case 'pa_ean13': + $sql .= ', pa.ean13 AS pa_ean13'; + break; + case 'pa_upc': + $sql .= ', pa.upc AS pa_upc'; + break; + } + } + } + } + return $sql; + } - protected static function getProductsToIndex($total_languages, $id_product = false, $limit = 50, $weight_array = array()) - { - $ids = null; - if (!$id_product) - { - // Limit products for each step but be sure that each attribute is taken into account - $sql = 'SELECT p.id_product FROM '._DB_PREFIX_.'product p + protected static function getProductsToIndex($total_languages, $id_product = false, $limit = 50, $weight_array = array()) + { + $ids = null; + if (!$id_product) { + // Limit products for each step but be sure that each attribute is taken into account + $sql = 'SELECT p.id_product FROM '._DB_PREFIX_.'product p '.Shop::addSqlAssociation('product', 'p', true, null, true).' WHERE product_shop.`indexed` = 0 AND product_shop.`visibility` IN ("both", "search") @@ -458,49 +474,52 @@ class SearchCore LIMIT '.(int)$limit; - $res = Db::getInstance()->executeS($sql, false); - while ($row = Db::getInstance()->nextRow($res)) - $ids[] = $row['id_product']; - } + $res = Db::getInstance()->executeS($sql, false); + while ($row = Db::getInstance()->nextRow($res)) { + $ids[] = $row['id_product']; + } + } - // Now get every attribute in every language - $sql = 'SELECT p.id_product, pl.id_lang, pl.id_shop, l.iso_code'; + // Now get every attribute in every language + $sql = 'SELECT p.id_product, pl.id_lang, pl.id_shop, l.iso_code'; - if (is_array($weight_array)) - foreach ($weight_array as $key => $weight) - if ((int)$weight) - switch ($key) - { - case 'pname': - $sql .= ', pl.name pname'; - break; - case 'reference': - $sql .= ', p.reference'; - break; - case 'supplier_reference': - $sql .= ', p.supplier_reference'; - break; - case 'ean13': - $sql .= ', p.ean13'; - break; - case 'upc': - $sql .= ', p.upc'; - break; - case 'description_short': - $sql .= ', pl.description_short'; - break; - case 'description': - $sql .= ', pl.description'; - break; - case 'cname': - $sql .= ', cl.name cname'; - break; - case 'mname': - $sql .= ', m.name mname'; - break; - } + if (is_array($weight_array)) { + foreach ($weight_array as $key => $weight) { + if ((int)$weight) { + switch ($key) { + case 'pname': + $sql .= ', pl.name pname'; + break; + case 'reference': + $sql .= ', p.reference'; + break; + case 'supplier_reference': + $sql .= ', p.supplier_reference'; + break; + case 'ean13': + $sql .= ', p.ean13'; + break; + case 'upc': + $sql .= ', p.upc'; + break; + case 'description_short': + $sql .= ', pl.description_short'; + break; + case 'description': + $sql .= ', pl.description'; + break; + case 'cname': + $sql .= ', cl.name cname'; + break; + case 'mname': + $sql .= ', m.name mname'; + break; + } + } + } + } - $sql .= ' FROM '._DB_PREFIX_.'product p + $sql .= ' FROM '._DB_PREFIX_.'product p LEFT JOIN '._DB_PREFIX_.'product_lang pl ON p.id_product = pl.id_product '.Shop::addSqlAssociation('product', 'p', true, null, true).' @@ -517,276 +536,278 @@ class SearchCore AND product_shop.`active` = 1 AND pl.`id_shop` = product_shop.`id_shop`'; - return Db::getInstance()->executeS($sql, true, false); - } + return Db::getInstance()->executeS($sql, true, false); + } - /** - * @param Db $db - * @param int $id_product - * @param string $sql_attribute - * - * @return array|null - */ - protected static function getAttributesFields($db, $id_product, $sql_attribute) - { - return $db->executeS('SELECT id_product '.$sql_attribute.' FROM '. - _DB_PREFIX_.'product_attribute pa WHERE pa.id_product = '.(int)$id_product, true, false); - } + /** + * @param Db $db + * @param int $id_product + * @param string $sql_attribute + * + * @return array|null + */ + protected static function getAttributesFields($db, $id_product, $sql_attribute) + { + return $db->executeS('SELECT id_product '.$sql_attribute.' FROM '. + _DB_PREFIX_.'product_attribute pa WHERE pa.id_product = '.(int)$id_product, true, false); + } - /** - * @param $product_array - * @param $weight_array - * @param $key - * @param $value - * @param $id_lang - * @param $iso_code - */ - protected static function fillProductArray(&$product_array, $weight_array, $key, $value, $id_lang, $iso_code) - { - if (strncmp($key, 'id_', 3) && isset($weight_array[$key])) - { - $words = explode(' ', Search::sanitize($value, (int)$id_lang, true, $iso_code)); - foreach ($words as $word) - if (!empty($word)) - { - $word = Tools::substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH); - // Remove accents - $word = Tools::replaceAccentedChars($word); + /** + * @param $product_array + * @param $weight_array + * @param $key + * @param $value + * @param $id_lang + * @param $iso_code + */ + protected static function fillProductArray(&$product_array, $weight_array, $key, $value, $id_lang, $iso_code) + { + if (strncmp($key, 'id_', 3) && isset($weight_array[$key])) { + $words = explode(' ', Search::sanitize($value, (int)$id_lang, true, $iso_code)); + foreach ($words as $word) { + if (!empty($word)) { + $word = Tools::substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH); - if (!isset($product_array[$word])) - $product_array[$word] = 0; - $product_array[$word] += $weight_array[$key]; - } - } - } + if (!isset($product_array[$word])) { + $product_array[$word] = 0; + } + $product_array[$word] += $weight_array[$key]; + } + } + } + } - public static function indexation($full = false, $id_product = false) - { - $db = Db::getInstance(); + public static function indexation($full = false, $id_product = false) + { + $db = Db::getInstance(); - if ($id_product) - $full = false; + if ($id_product) { + $full = false; + } - if ($full && Context::getContext()->shop->getContext() == Shop::CONTEXT_SHOP) - { - $db->execute('DELETE si, sw FROM `'._DB_PREFIX_.'search_index` si + if ($full && Context::getContext()->shop->getContext() == Shop::CONTEXT_SHOP) { + $db->execute('DELETE si, sw FROM `'._DB_PREFIX_.'search_index` si INNER JOIN `'._DB_PREFIX_.'product` p ON (p.id_product = si.id_product) '.Shop::addSqlAssociation('product', 'p').' INNER JOIN `'._DB_PREFIX_.'search_word` sw ON (sw.id_word = si.id_word AND product_shop.id_shop = sw.id_shop) WHERE product_shop.`visibility` IN ("both", "search") AND product_shop.`active` = 1'); - $db->execute('UPDATE `'._DB_PREFIX_.'product` p + $db->execute('UPDATE `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' SET p.`indexed` = 0, product_shop.`indexed` = 0 WHERE product_shop.`visibility` IN ("both", "search") AND product_shop.`active` = 1 '); - } - elseif ($full) - { - $db->execute('TRUNCATE '._DB_PREFIX_.'search_index'); - $db->execute('TRUNCATE '._DB_PREFIX_.'search_word'); - ObjectModel::updateMultishopTable('Product', array('indexed' => 0)); - } - else - { - $db->execute('DELETE si FROM `'._DB_PREFIX_.'search_index` si + } elseif ($full) { + $db->execute('TRUNCATE '._DB_PREFIX_.'search_index'); + $db->execute('TRUNCATE '._DB_PREFIX_.'search_word'); + ObjectModel::updateMultishopTable('Product', array('indexed' => 0)); + } else { + $db->execute('DELETE si FROM `'._DB_PREFIX_.'search_index` si INNER JOIN `'._DB_PREFIX_.'product` p ON (p.id_product = si.id_product) '.Shop::addSqlAssociation('product', 'p').' WHERE product_shop.`visibility` IN ("both", "search") AND product_shop.`active` = 1 AND '.($id_product ? 'p.`id_product` = '.(int)$id_product : 'product_shop.`indexed` = 0')); - $db->execute('UPDATE `'._DB_PREFIX_.'product` p + $db->execute('UPDATE `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' SET p.`indexed` = 0, product_shop.`indexed` = 0 WHERE product_shop.`visibility` IN ("both", "search") AND product_shop.`active` = 1 AND '.($id_product ? 'p.`id_product` = '.(int)$id_product : 'product_shop.`indexed` = 0')); - } + } - // Every fields are weighted according to the configuration in the backend - $weight_array = array( - 'pname' => Configuration::get('PS_SEARCH_WEIGHT_PNAME'), - 'reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), - 'pa_reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), - 'supplier_reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), - 'pa_supplier_reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), - 'ean13' => Configuration::get('PS_SEARCH_WEIGHT_REF'), - 'pa_ean13' => Configuration::get('PS_SEARCH_WEIGHT_REF'), - 'upc' => Configuration::get('PS_SEARCH_WEIGHT_REF'), - 'pa_upc' => Configuration::get('PS_SEARCH_WEIGHT_REF'), - 'description_short' => Configuration::get('PS_SEARCH_WEIGHT_SHORTDESC'), - 'description' => Configuration::get('PS_SEARCH_WEIGHT_DESC'), - 'cname' => Configuration::get('PS_SEARCH_WEIGHT_CNAME'), - 'mname' => Configuration::get('PS_SEARCH_WEIGHT_MNAME'), - 'tags' => Configuration::get('PS_SEARCH_WEIGHT_TAG'), - 'attributes' => Configuration::get('PS_SEARCH_WEIGHT_ATTRIBUTE'), - 'features' => Configuration::get('PS_SEARCH_WEIGHT_FEATURE') - ); + // Every fields are weighted according to the configuration in the backend + $weight_array = array( + 'pname' => Configuration::get('PS_SEARCH_WEIGHT_PNAME'), + 'reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), + 'pa_reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), + 'supplier_reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), + 'pa_supplier_reference' => Configuration::get('PS_SEARCH_WEIGHT_REF'), + 'ean13' => Configuration::get('PS_SEARCH_WEIGHT_REF'), + 'pa_ean13' => Configuration::get('PS_SEARCH_WEIGHT_REF'), + 'upc' => Configuration::get('PS_SEARCH_WEIGHT_REF'), + 'pa_upc' => Configuration::get('PS_SEARCH_WEIGHT_REF'), + 'description_short' => Configuration::get('PS_SEARCH_WEIGHT_SHORTDESC'), + 'description' => Configuration::get('PS_SEARCH_WEIGHT_DESC'), + 'cname' => Configuration::get('PS_SEARCH_WEIGHT_CNAME'), + 'mname' => Configuration::get('PS_SEARCH_WEIGHT_MNAME'), + 'tags' => Configuration::get('PS_SEARCH_WEIGHT_TAG'), + 'attributes' => Configuration::get('PS_SEARCH_WEIGHT_ATTRIBUTE'), + 'features' => Configuration::get('PS_SEARCH_WEIGHT_FEATURE') + ); - // Those are kind of global variables required to save the processed data in the database every X occurrences, in order to avoid overloading MySQL - $count_words = 0; - $query_array3 = array(); + // Those are kind of global variables required to save the processed data in the database every X occurrences, in order to avoid overloading MySQL + $count_words = 0; + $query_array3 = array(); - // Retrieve the number of languages - $total_languages = count(Language::getIDs(false)); + // Retrieve the number of languages + $total_languages = count(Language::getIDs(false)); - $sql_attribute = Search::getSQLProductAttributeFields($weight_array); - // Products are processed 50 by 50 in order to avoid overloading MySQL - while (($products = Search::getProductsToIndex($total_languages, $id_product, 50, $weight_array)) && (count($products) > 0)) - { - $products_array = array(); - // Now each non-indexed product is processed one by one, langage by langage - foreach ($products as $product) - { - if ((int)$weight_array['tags']) - $product['tags'] = Search::getTags($db, (int)$product['id_product'], (int)$product['id_lang']); - if ((int)$weight_array['attributes']) - $product['attributes'] = Search::getAttributes($db, (int)$product['id_product'], (int)$product['id_lang']); - if ((int)$weight_array['features']) - $product['features'] = Search::getFeatures($db, (int)$product['id_product'], (int)$product['id_lang']); - if ($sql_attribute) - { - $attribute_fields = Search::getAttributesFields($db, (int)$product['id_product'], $sql_attribute); - if ($attribute_fields) - $product['attributes_fields'] = $attribute_fields; - } + $sql_attribute = Search::getSQLProductAttributeFields($weight_array); + // Products are processed 50 by 50 in order to avoid overloading MySQL + while (($products = Search::getProductsToIndex($total_languages, $id_product, 50, $weight_array)) && (count($products) > 0)) { + $products_array = array(); + // Now each non-indexed product is processed one by one, langage by langage + foreach ($products as $product) { + if ((int)$weight_array['tags']) { + $product['tags'] = Search::getTags($db, (int)$product['id_product'], (int)$product['id_lang']); + } + if ((int)$weight_array['attributes']) { + $product['attributes'] = Search::getAttributes($db, (int)$product['id_product'], (int)$product['id_lang']); + } + if ((int)$weight_array['features']) { + $product['features'] = Search::getFeatures($db, (int)$product['id_product'], (int)$product['id_lang']); + } + if ($sql_attribute) { + $attribute_fields = Search::getAttributesFields($db, (int)$product['id_product'], $sql_attribute); + if ($attribute_fields) { + $product['attributes_fields'] = $attribute_fields; + } + } - // Data must be cleaned of html, bad characters, spaces and anything, then if the resulting words are long enough, they're added to the array - $product_array = array(); - foreach ($product as $key => $value) - { - if ($key == 'attributes_fields') - { - foreach($value as $pa_array) - foreach($pa_array as $pa_key => $pa_value) - Search::fillProductArray($product_array, $weight_array, $pa_key, $pa_value, $product['id_lang'], $product['iso_code']); - } - else - Search::fillProductArray($product_array, $weight_array, $key, $value, $product['id_lang'], $product['iso_code']); - } + // Data must be cleaned of html, bad characters, spaces and anything, then if the resulting words are long enough, they're added to the array + $product_array = array(); + foreach ($product as $key => $value) { + if ($key == 'attributes_fields') { + foreach ($value as $pa_array) { + foreach ($pa_array as $pa_key => $pa_value) { + Search::fillProductArray($product_array, $weight_array, $pa_key, $pa_value, $product['id_lang'], $product['iso_code']); + } + } + } else { + Search::fillProductArray($product_array, $weight_array, $key, $value, $product['id_lang'], $product['iso_code']); + } + } - // If we find words that need to be indexed, they're added to the word table in the database - if (is_array($product_array) && !empty($product_array)) - { - $query_array = $query_array2 = array(); - foreach ($product_array as $word => $weight) - if ($weight) - { - $query_array[$word] = '('.(int)$product['id_lang'].', '.(int)$product['id_shop'].', \''.pSQL($word).'\')'; - $query_array2[] = '\''.pSQL($word).'\''; - } + // If we find words that need to be indexed, they're added to the word table in the database + if (is_array($product_array) && !empty($product_array)) { + $query_array = $query_array2 = array(); + foreach ($product_array as $word => $weight) { + if ($weight) { + $query_array[$word] = '('.(int)$product['id_lang'].', '.(int)$product['id_shop'].', \''.pSQL($word).'\')'; + $query_array2[] = '\''.pSQL($word).'\''; + } + } - if (is_array($query_array) && !empty($query_array)) - { - // The words are inserted... - $db->execute(' + if (is_array($query_array) && !empty($query_array)) { + // The words are inserted... + $db->execute(' INSERT IGNORE INTO '._DB_PREFIX_.'search_word (id_lang, id_shop, word) VALUES '.implode(',', $query_array), false); - } - $word_ids_by_word = array(); - if (is_array($query_array2) && !empty($query_array2)) - { - // ...then their IDs are retrieved - $added_words = $db->executeS(' + } + $word_ids_by_word = array(); + if (is_array($query_array2) && !empty($query_array2)) { + // ...then their IDs are retrieved + $added_words = $db->executeS(' SELECT sw.id_word, sw.word FROM '._DB_PREFIX_.'search_word sw WHERE sw.word IN ('.implode(',', $query_array2).') AND sw.id_lang = '.(int)$product['id_lang'].' AND sw.id_shop = '.(int)$product['id_shop'], true, false); - foreach ($added_words as $word_id) - $word_ids_by_word['_'.$word_id['word']] = (int)$word_id['id_word']; - } - } + foreach ($added_words as $word_id) { + $word_ids_by_word['_'.$word_id['word']] = (int)$word_id['id_word']; + } + } + } - foreach ($product_array as $word => $weight) - { - if (!$weight) - continue; - if (!isset($word_ids_by_word['_'.$word])) - continue; - $id_word = $word_ids_by_word['_'.$word]; - if (!$id_word) - continue; - $query_array3[] = '('.(int)$product['id_product'].','. - (int)$id_word.','.(int)$weight.')'; - // Force save every 200 words in order to avoid overloading MySQL - if (++$count_words % 200 == 0) - Search::saveIndex($query_array3); - } + foreach ($product_array as $word => $weight) { + if (!$weight) { + continue; + } + if (!isset($word_ids_by_word['_'.$word])) { + continue; + } + $id_word = $word_ids_by_word['_'.$word]; + if (!$id_word) { + continue; + } + $query_array3[] = '('.(int)$product['id_product'].','. + (int)$id_word.','.(int)$weight.')'; + // Force save every 200 words in order to avoid overloading MySQL + if (++$count_words % 200 == 0) { + Search::saveIndex($query_array3); + } + } - $products_array[] = (int)$product['id_product']; - } - $products_array = array_unique($products_array); - Search::setProductsAsIndexed($products_array); + $products_array[] = (int)$product['id_product']; + } + $products_array = array_unique($products_array); + Search::setProductsAsIndexed($products_array); - // One last save is done at the end in order to save what's left - Search::saveIndex($query_array3); - } - return true; - } + // One last save is done at the end in order to save what's left + Search::saveIndex($query_array3); + } + return true; + } - public static function removeProductsSearchIndex($products) - { - if (is_array($products) && !empty($products)) - { - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'search_index WHERE id_product IN ('.implode(',', array_map('intval', $products)).')'); - ObjectModel::updateMultishopTable('Product', array('indexed' => 0), 'a.id_product IN ('.implode(',', array_map('intval', $products)).')'); - } - } + public static function removeProductsSearchIndex($products) + { + if (is_array($products) && !empty($products)) { + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'search_index WHERE id_product IN ('.implode(',', array_map('intval', $products)).')'); + ObjectModel::updateMultishopTable('Product', array('indexed' => 0), 'a.id_product IN ('.implode(',', array_map('intval', $products)).')'); + } + } - protected static function setProductsAsIndexed(&$products) - { - if (is_array($products) && !empty($products)) - ObjectModel::updateMultishopTable('Product', array('indexed' => 1), 'a.id_product IN ('.implode(',', $products).')'); - } + protected static function setProductsAsIndexed(&$products) + { + if (is_array($products) && !empty($products)) { + ObjectModel::updateMultishopTable('Product', array('indexed' => 1), 'a.id_product IN ('.implode(',', $products).')'); + } + } - /** $queryArray3 is automatically emptied in order to be reused immediatly */ - protected static function saveIndex(&$queryArray3) - { - if (is_array($queryArray3) && !empty($queryArray3)) - Db::getInstance()->execute( - 'INSERT INTO '._DB_PREFIX_.'search_index (id_product, id_word, weight) + /** $queryArray3 is automatically emptied in order to be reused immediatly */ + protected static function saveIndex(&$queryArray3) + { + if (is_array($queryArray3) && !empty($queryArray3)) { + Db::getInstance()->execute( + 'INSERT INTO '._DB_PREFIX_.'search_index (id_product, id_word, weight) VALUES '.implode(',', $queryArray3).' ON DUPLICATE KEY UPDATE weight = weight + VALUES(weight)', false - ); - $queryArray3 = array(); - } + ); + } + $queryArray3 = array(); + } - public static function searchTag($id_lang, $tag, $count = false, $pageNumber = 0, $pageSize = 10, $orderBy = false, $orderWay = false, - $useCookie = true, Context $context = null) - { - if (!$context) - $context = Context::getContext(); + public static function searchTag($id_lang, $tag, $count = false, $pageNumber = 0, $pageSize = 10, $orderBy = false, $orderWay = false, + $useCookie = true, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } - // Only use cookie if id_customer is not present - if ($useCookie) - $id_customer = (int)$context->customer->id; - else - $id_customer = 0; + // Only use cookie if id_customer is not present + if ($useCookie) { + $id_customer = (int)$context->customer->id; + } else { + $id_customer = 0; + } - if (!is_numeric($pageNumber) || !is_numeric($pageSize) || !Validate::isBool($count) || !Validate::isValidSearch($tag) - || $orderBy && !$orderWay || ($orderBy && !Validate::isOrderBy($orderBy)) || ($orderWay && !Validate::isOrderBy($orderWay))) - return false; + if (!is_numeric($pageNumber) || !is_numeric($pageSize) || !Validate::isBool($count) || !Validate::isValidSearch($tag) + || $orderBy && !$orderWay || ($orderBy && !Validate::isOrderBy($orderBy)) || ($orderWay && !Validate::isOrderBy($orderWay))) { + return false; + } - if ($pageNumber < 1) $pageNumber = 1; - if ($pageSize < 1) $pageSize = 10; + if ($pageNumber < 1) { + $pageNumber = 1; + } + if ($pageSize < 1) { + $pageSize = 10; + } - $id = Context::getContext()->shop->id; - $id_shop = $id ? $id : Configuration::get('PS_SHOP_DEFAULT'); + $id = Context::getContext()->shop->id; + $id_shop = $id ? $id : Configuration::get('PS_SHOP_DEFAULT'); - $sql_groups = ''; - if (Group::isFeatureActive()) - { - $groups = FrontController::getCurrentCustomerGroups(); - $sql_groups = 'AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); - } + $sql_groups = ''; + if (Group::isFeatureActive()) { + $groups = FrontController::getCurrentCustomerGroups(); + $sql_groups = 'AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); + } - if ($count) - { - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue( - 'SELECT COUNT(DISTINCT pt.`id_product`) nb + if ($count) { + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue( + 'SELECT COUNT(DISTINCT pt.`id_product`) nb FROM `'._DB_PREFIX_.'tag` t STRAIGHT_JOIN `'._DB_PREFIX_.'product_tag` pt ON (pt.`id_tag` = t.`id_tag` AND t.`id_lang` = '.(int)$id_lang.') @@ -800,9 +821,9 @@ class SearchCore AND cs.`id_shop` = '.(int)Context::getContext()->shop->id.' '.$sql_groups.' AND t.`name` LIKE \'%'.pSQL($tag).'%\''); - } + } - $sql = 'SELECT DISTINCT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description_short`, pl.`link_rewrite`, pl.`name`, pl.`available_now`, pl.`available_later`, + $sql = 'SELECT DISTINCT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description_short`, pl.`link_rewrite`, pl.`name`, pl.`available_now`, pl.`available_later`, MAX(image_shop.`id_image`) id_image, il.`legend`, m.`name` manufacturer_name, 1 position, DATEDIFF( p.`date_add`, @@ -837,9 +858,10 @@ class SearchCore GROUP BY product_shop.id_product ORDER BY position DESC'.($orderBy ? ', '.$orderBy : '').($orderWay ? ' '.$orderWay : '').' LIMIT '.(int)(($pageNumber - 1) * $pageSize).','.(int)$pageSize; - if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false)) - return false; + if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false)) { + return false; + } - return Product::getProductsProperties((int)$id_lang, $result); - } + return Product::getProductsProperties((int)$id_lang, $result); + } } diff --git a/classes/SearchEngine.php b/classes/SearchEngine.php index ca5fd694..acb6a04c 100644 --- a/classes/SearchEngine.php +++ b/classes/SearchEngine.php @@ -26,44 +26,46 @@ class SearchEngineCore extends ObjectModel { - public $server; - public $getvar; + public $server; + public $getvar; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'search_engine', - 'primary' => 'id_search_engine', - 'fields' => array( - 'server' => array('type' => self::TYPE_STRING, 'validate' => 'isUrl', 'required' => true), - 'getvar' => array('type' => self::TYPE_STRING, 'validate' => 'isModuleName', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'search_engine', + 'primary' => 'id_search_engine', + 'fields' => array( + 'server' => array('type' => self::TYPE_STRING, 'validate' => 'isUrl', 'required' => true), + 'getvar' => array('type' => self::TYPE_STRING, 'validate' => 'isModuleName', 'required' => true), + ), + ); - public static function getKeywords($url) - { - $parsed_url = @parse_url($url); - if (!isset($parsed_url['host']) || !isset($parsed_url['query'])) - return false; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT `server`, `getvar` FROM `'._DB_PREFIX_.'search_engine`'); - foreach ($result as $row) - { - $host =& $row['server']; - $varname =& $row['getvar']; - if (strstr($parsed_url['host'], $host)) - { - $array = array(); - preg_match('/[^a-z]'.$varname.'=.+\&/U', $parsed_url['query'], $array); - if (empty($array[0])) - preg_match('/[^a-z]'.$varname.'=.+$/', $parsed_url['query'], $array); - if (empty($array[0])) - return false; - $str = urldecode(str_replace('+', ' ', ltrim(substr(rtrim($array[0], '&'), strlen($varname) + 1), '='))); - if (!Validate::isMessage($str)) - return false; - return $str; - } - } - } -} \ No newline at end of file + public static function getKeywords($url) + { + $parsed_url = @parse_url($url); + if (!isset($parsed_url['host']) || !isset($parsed_url['query'])) { + return false; + } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT `server`, `getvar` FROM `'._DB_PREFIX_.'search_engine`'); + foreach ($result as $row) { + $host =& $row['server']; + $varname =& $row['getvar']; + if (strstr($parsed_url['host'], $host)) { + $array = array(); + preg_match('/[^a-z]'.$varname.'=.+\&/U', $parsed_url['query'], $array); + if (empty($array[0])) { + preg_match('/[^a-z]'.$varname.'=.+$/', $parsed_url['query'], $array); + } + if (empty($array[0])) { + return false; + } + $str = urldecode(str_replace('+', ' ', ltrim(substr(rtrim($array[0], '&'), strlen($varname) + 1), '='))); + if (!Validate::isMessage($str)) { + return false; + } + return $str; + } + } + } +} diff --git a/classes/SmartyCacheResourceMysql.php b/classes/SmartyCacheResourceMysql.php index e98d495d..71cd12a9 100644 --- a/classes/SmartyCacheResourceMysql.php +++ b/classes/SmartyCacheResourceMysql.php @@ -28,63 +28,60 @@ require_once(_PS_TOOL_DIR_.'smarty/Smarty.class.php'); class Smarty_CacheResource_Mysql extends Smarty_CacheResource_Custom { - /** - * fetch cached content and its modification time from data source - * - * @param string $id unique cache content identifier - * @param string $name template name - * @param string $cache_id cache id - * @param string $compile_id compile id - * @param string $content cached content - * @param int $mtime cache modification timestamp (epoch) - * @return void - */ - protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime) - { - $row = Db::getInstance()->getRow('SELECT modified, content FROM '._DB_PREFIX_.'smarty_cache WHERE id_smarty_cache = "'.pSQL($id, true).'"'); - if ($row) - { - $content = $row['content']; - $mtime = strtotime($row['modified']); - } - else - { - $content = null; - $mtime = null; - } - } + /** + * fetch cached content and its modification time from data source + * + * @param string $id unique cache content identifier + * @param string $name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @param string $content cached content + * @param int $mtime cache modification timestamp (epoch) + * @return void + */ + protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime) + { + $row = Db::getInstance()->getRow('SELECT modified, content FROM '._DB_PREFIX_.'smarty_cache WHERE id_smarty_cache = "'.pSQL($id, true).'"'); + if ($row) { + $content = $row['content']; + $mtime = strtotime($row['modified']); + } else { + $content = null; + $mtime = null; + } + } - /** - * Fetch cached content's modification timestamp from data source - * - * @note implementing this method is optional. Only implement it if modification times can be accessed faster than loading the complete cached content. - * @param string $id unique cache content identifier - * @param string $name template name - * @param string $cache_id cache id - * @param string $compile_id compile id - * @return int|boolean timestamp (epoch) the template was modified, or false if not found - */ - protected function fetchTimestamp($id, $name, $cache_id, $compile_id) - { - $value = Db::getInstance()->getValue('SELECT modified FROM '._DB_PREFIX_.'smarty_cache WHERE id_smarty_cache = "'.pSQL($id, true).'"'); - $mtime = strtotime($value); - return $mtime; - } + /** + * Fetch cached content's modification timestamp from data source + * + * @note implementing this method is optional. Only implement it if modification times can be accessed faster than loading the complete cached content. + * @param string $id unique cache content identifier + * @param string $name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @return int|boolean timestamp (epoch) the template was modified, or false if not found + */ + protected function fetchTimestamp($id, $name, $cache_id, $compile_id) + { + $value = Db::getInstance()->getValue('SELECT modified FROM '._DB_PREFIX_.'smarty_cache WHERE id_smarty_cache = "'.pSQL($id, true).'"'); + $mtime = strtotime($value); + return $mtime; + } - /** - * Save content to cache - * - * @param string $id unique cache content identifier - * @param string $name template name - * @param string $cache_id cache id - * @param string $compile_id compile id - * @param int|null $exp_time seconds till expiration time in seconds or null - * @param string $content content to cache - * @return bool success - */ - protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content) - { - Db::getInstance()->execute(' + /** + * Save content to cache + * + * @param string $id unique cache content identifier + * @param string $name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @param int|null $exp_time seconds till expiration time in seconds or null + * @param string $content content to cache + * @return bool success + */ + protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content) + { + Db::getInstance()->execute(' REPLACE INTO '._DB_PREFIX_.'smarty_cache (id_smarty_cache, name, cache_id, content) VALUES ( "'.pSQL($id, true).'", @@ -93,37 +90,39 @@ class Smarty_CacheResource_Mysql extends Smarty_CacheResource_Custom "'.pSQL($content, true).'" )'); - return (bool)Db::getInstance()->Affected_Rows(); - } + return (bool)Db::getInstance()->Affected_Rows(); + } - /** - * Delete content from cache - * - * @param string $name template name - * @param string $cache_id cache id - * @param string $compile_id compile id - * @param int|null $exp_time seconds till expiration or null - * @return int number of deleted caches - */ - protected function delete($name, $cache_id, $compile_id, $exp_time) - { - // delete the whole cache - if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) - { - // returning the number of deleted caches would require a second query to count them - Db::getInstance()->execute('TRUNCATE TABLE '._DB_PREFIX_.'smarty_cache'); - return -1; - } + /** + * Delete content from cache + * + * @param string $name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @param int|null $exp_time seconds till expiration or null + * @return int number of deleted caches + */ + protected function delete($name, $cache_id, $compile_id, $exp_time) + { + // delete the whole cache + if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) { + // returning the number of deleted caches would require a second query to count them + Db::getInstance()->execute('TRUNCATE TABLE '._DB_PREFIX_.'smarty_cache'); + return -1; + } - $where = array(); - if ($name !== null) - $where[] = 'name = "'.pSQL(sha1($name)).'"'; - if ($exp_time !== null) - $where[] = 'modified < DATE_SUB(NOW(), INTERVAL '.(int)$exp_time.' SECOND)'; - if ($cache_id !== null) - $where[] = '(cache_id = "'.pSQL($cache_id, true).'" OR cache_id LIKE "'.pSQL($cache_id .'|%', true).'")'; + $where = array(); + if ($name !== null) { + $where[] = 'name = "'.pSQL(sha1($name)).'"'; + } + if ($exp_time !== null) { + $where[] = 'modified < DATE_SUB(NOW(), INTERVAL '.(int)$exp_time.' SECOND)'; + } + if ($cache_id !== null) { + $where[] = '(cache_id = "'.pSQL($cache_id, true).'" OR cache_id LIKE "'.pSQL($cache_id .'|%', true).'")'; + } - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'smarty_cache WHERE '.implode(' AND ', $where)); - return Db::getInstance()->Affected_Rows(); - } -} \ No newline at end of file + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'smarty_cache WHERE '.implode(' AND ', $where)); + return Db::getInstance()->Affected_Rows(); + } +} diff --git a/classes/SmartyCustom.php b/classes/SmartyCustom.php index 78aa4e5d..727fa9f0 100644 --- a/classes/SmartyCustom.php +++ b/classes/SmartyCustom.php @@ -26,306 +26,295 @@ class SmartyCustomCore extends Smarty { + public function __construct() + { + parent::__construct(); + $this->template_class = 'Smarty_Custom_Template'; + } - public function __construct() - { - parent::__construct(); - $this->template_class = 'Smarty_Custom_Template'; - } + /** + * Delete compiled template file (lazy delete if resource_name is not specified) + * + * @param string $resource_name template name + * @param string $compile_id compile id + * @param int $exp_time expiration time + * + * @return int number of template files deleted + */ + public function clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null) + { + if ($resource_name == null) { + Db::getInstance()->execute('REPLACE INTO `'._DB_PREFIX_.'smarty_last_flush` (`type`, `last_flush`) VALUES (\'compile\', \''.date('Y-m-d H:i:s').'\')'); + return 0; + } else { + return parent::clearCompiledTemplate($resource_name, $compile_id, $exp_time); + } + } - /** - * Delete compiled template file (lazy delete if resource_name is not specified) - * - * @param string $resource_name template name - * @param string $compile_id compile id - * @param int $exp_time expiration time - * - * @return int number of template files deleted - */ - public function clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null) - { - if ($resource_name == null) - { - Db::getInstance()->execute('REPLACE INTO `'._DB_PREFIX_.'smarty_last_flush` (`type`, `last_flush`) VALUES (\'compile\', \''.date('Y-m-d H:i:s').'\')'); - return 0; - } - else - return parent::clearCompiledTemplate($resource_name, $compile_id, $exp_time); - } + /** + * Mark all template files to be regenerated + * + * @param int $exp_time expiration time + * @param string $type resource type + * + * @return int number of cache files which needs to be updated + */ + public function clearAllCache($exp_time = null, $type = null) + { + Db::getInstance()->execute('REPLACE INTO `'._DB_PREFIX_.'smarty_last_flush` (`type`, `last_flush`) VALUES (\'template\', \''.date('Y-m-d H:i:s').'\')'); + return $this->delete_from_lazy_cache(null, null, null); + } - /** - * Mark all template files to be regenerated - * - * @param int $exp_time expiration time - * @param string $type resource type - * - * @return int number of cache files which needs to be updated - */ - public function clearAllCache($exp_time = null, $type = null) - { - Db::getInstance()->execute('REPLACE INTO `'._DB_PREFIX_.'smarty_last_flush` (`type`, `last_flush`) VALUES (\'template\', \''.date('Y-m-d H:i:s').'\')'); - return $this->delete_from_lazy_cache(null, null, null); - } + /** + * Mark file to be regenerated for a specific template + * + * @param string $template_name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @param int $exp_time expiration time + * @param string $type resource type + * + * @return int number of cache files which needs to be updated + */ + public function clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null) + { + return $this->delete_from_lazy_cache($template_name, $cache_id, $compile_id); + } - /** - * Mark file to be regenerated for a specific template - * - * @param string $template_name template name - * @param string $cache_id cache id - * @param string $compile_id compile id - * @param int $exp_time expiration time - * @param string $type resource type - * - * @return int number of cache files which needs to be updated - */ - public function clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null) - { - return $this->delete_from_lazy_cache($template_name, $cache_id, $compile_id); - } + /** + * Check the compile cache needs to be invalidated (multi front + local cache compatible) + */ + public function check_compile_cache_invalidation() + { + static $last_flush = null; + if (!file_exists($this->getCompileDir().'last_flush')) { + @touch($this->getCompileDir().'last_flush'); + } elseif (defined('_DB_PREFIX_')) { + if ($last_flush === null) { + $sql = 'SELECT UNIX_TIMESTAMP(last_flush) as last_flush FROM `'._DB_PREFIX_.'smarty_last_flush` WHERE type=\'compile\''; + $last_flush = Db::getInstance()->getValue($sql, false); + } + if ((int)$last_flush && @filemtime($this->getCompileDir().'last_flush') < $last_flush) { + @touch($this->getCompileDir().'last_flush'); + parent::clearCompiledTemplate(); + } + } + } - /** - * Check the compile cache needs to be invalidated (multi front + local cache compatible) - */ - public function check_compile_cache_invalidation() - { - static $last_flush = null; - if (!file_exists($this->getCompileDir().'last_flush')) - @touch($this->getCompileDir().'last_flush'); - elseif (defined('_DB_PREFIX_')) - { - if ($last_flush === null) - { - $sql = 'SELECT UNIX_TIMESTAMP(last_flush) as last_flush FROM `'._DB_PREFIX_.'smarty_last_flush` WHERE type=\'compile\''; - $last_flush = Db::getInstance()->getValue($sql, false); - } - if ((int)$last_flush && @filemtime($this->getCompileDir().'last_flush') < $last_flush) - { - @touch($this->getCompileDir().'last_flush'); - parent::clearCompiledTemplate(); - } - } - } + /** + * {@inheritDoc} + */ + public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false) + { + $this->check_compile_cache_invalidation(); + return parent::fetch($template, $cache_id, $compile_id, $parent, $display, $merge_tpl_vars, $no_output_filter); + } - /** - * {@inheritDoc} - */ - public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false) - { - $this->check_compile_cache_invalidation(); - return parent::fetch($template, $cache_id, $compile_id, $parent, $display, $merge_tpl_vars, $no_output_filter); - } + /** + * {@inheritDoc} + */ + public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true) + { + $this->check_compile_cache_invalidation(); + if ($this->caching) { + $this->check_template_invalidation($template, $cache_id, $compile_id); + return parent::createTemplate($template, $cache_id, $compile_id, $parent, $do_clone); + } else { + return parent::createTemplate($template, $cache_id, $compile_id, $parent, $do_clone); + } + } - /** - * {@inheritDoc} - */ - public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true) - { - $this->check_compile_cache_invalidation(); - if ($this->caching) - { - $this->check_template_invalidation($template, $cache_id, $compile_id); - return parent::createTemplate($template, $cache_id, $compile_id, $parent, $do_clone); - } - else - return parent::createTemplate($template, $cache_id, $compile_id, $parent, $do_clone); - } + /** + * Handle the lazy template cache invalidation + * + * @param string $template template name + * @param string $cache_id cache id + * @param string $compile_id compile id + */ + public function check_template_invalidation($template, $cache_id, $compile_id) + { + static $last_flush = null; + if (!file_exists($this->getCacheDir().'last_template_flush')) { + @touch($this->getCacheDir().'last_template_flush'); + } elseif (defined('_DB_PREFIX_')) { + if ($last_flush === null) { + $sql = 'SELECT UNIX_TIMESTAMP(last_flush) as last_flush FROM `'._DB_PREFIX_.'smarty_last_flush` WHERE type=\'template\''; + $last_flush = Db::getInstance()->getValue($sql, false); + } - /** - * Handle the lazy template cache invalidation - * - * @param string $template template name - * @param string $cache_id cache id - * @param string $compile_id compile id - */ - public function check_template_invalidation($template, $cache_id, $compile_id) - { - static $last_flush = null; - if (!file_exists($this->getCacheDir().'last_template_flush')) - @touch($this->getCacheDir().'last_template_flush'); - elseif (defined('_DB_PREFIX_')) - { - if ($last_flush === null) - { - $sql = 'SELECT UNIX_TIMESTAMP(last_flush) as last_flush FROM `'._DB_PREFIX_.'smarty_last_flush` WHERE type=\'template\''; - $last_flush = Db::getInstance()->getValue($sql, false); - } + if ((int)$last_flush && @filemtime($this->getCacheDir().'last_template_flush') < $last_flush) { + @touch($this->getCacheDir().'last_template_flush'); + parent::clearAllCache(); + } else { + if ($cache_id !== null && (is_object($cache_id) || is_array($cache_id))) { + $cache_id = null; + } - if ((int)$last_flush && @filemtime($this->getCacheDir().'last_template_flush') < $last_flush) - { - @touch($this->getCacheDir().'last_template_flush'); - parent::clearAllCache(); - } - else - { - if ($cache_id !== null && (is_object($cache_id) || is_array($cache_id))) - $cache_id = null; + if ($this->is_in_lazy_cache($template, $cache_id, $compile_id) === false) { + // insert in cache before the effective cache creation to avoid nasty race condition + $this->insert_in_lazy_cache($template, $cache_id, $compile_id); + parent::clearCache($template, $cache_id, $compile_id); + } + } + } + } - if ($this->is_in_lazy_cache($template, $cache_id, $compile_id) === false) - { - // insert in cache before the effective cache creation to avoid nasty race condition - $this->insert_in_lazy_cache($template, $cache_id, $compile_id); - parent::clearCache($template, $cache_id, $compile_id); - } - } - } - } - - /** - * Store the cache file path - * - * @param string $filepath cache file path - * @param string $template template name - * @param string $cache_id cache id - * @param string $compile_id compile id - */ - public function update_filepath($filepath, $template, $cache_id, $compile_id) - { - $template_md5 = md5($template); - $sql = 'UPDATE `'._DB_PREFIX_.'smarty_lazy_cache` + /** + * Store the cache file path + * + * @param string $filepath cache file path + * @param string $template template name + * @param string $cache_id cache id + * @param string $compile_id compile id + */ + public function update_filepath($filepath, $template, $cache_id, $compile_id) + { + $template_md5 = md5($template); + $sql = 'UPDATE `'._DB_PREFIX_.'smarty_lazy_cache` SET filepath=\''.pSQL($filepath).'\' WHERE `template_hash`=\''.pSQL($template_md5).'\''; - $sql .= ' AND cache_id="'.pSQL((string)$cache_id).'"'; + $sql .= ' AND cache_id="'.pSQL((string)$cache_id).'"'; - if (strlen($compile_id) > 32) - $compile_id = md5($compile_id); - $sql .= ' AND compile_id="'.pSQL((string)$compile_id).'"'; - Db::getInstance()->execute($sql, false); - } + if (strlen($compile_id) > 32) { + $compile_id = md5($compile_id); + } + $sql .= ' AND compile_id="'.pSQL((string)$compile_id).'"'; + Db::getInstance()->execute($sql, false); + } - /** - * Check if the current template is stored in the lazy cache - * Entry in the lazy cache = no need to regenerate the template - * - * @param string $template template name - * @param string $cache_id cache id - * @param string $compile_id compile id - * - * @return bool - */ - public function is_in_lazy_cache($template, $cache_id, $compile_id) - { - static $is_in_lazy_cache = array(); - $template_md5 = md5($template); + /** + * Check if the current template is stored in the lazy cache + * Entry in the lazy cache = no need to regenerate the template + * + * @param string $template template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * + * @return bool + */ + public function is_in_lazy_cache($template, $cache_id, $compile_id) + { + static $is_in_lazy_cache = array(); + $template_md5 = md5($template); - if (strlen($compile_id) > 32) - $compile_id = md5($compile_id); + if (strlen($compile_id) > 32) { + $compile_id = md5($compile_id); + } - $key = md5($template_md5.'-'.$cache_id.'-'.$compile_id); + $key = md5($template_md5.'-'.$cache_id.'-'.$compile_id); - if (isset($is_in_lazy_cache[$key])) - return $is_in_lazy_cache[$key]; - else - { - $sql = 'SELECT UNIX_TIMESTAMP(last_update) as last_update, filepath FROM `'._DB_PREFIX_.'smarty_lazy_cache` + if (isset($is_in_lazy_cache[$key])) { + return $is_in_lazy_cache[$key]; + } else { + $sql = 'SELECT UNIX_TIMESTAMP(last_update) as last_update, filepath FROM `'._DB_PREFIX_.'smarty_lazy_cache` WHERE `template_hash`=\''.pSQL($template_md5).'\''; - $sql .= ' AND cache_id="'.pSQL((string)$cache_id).'"'; - $sql .= ' AND compile_id="'.pSQL((string)$compile_id).'"'; + $sql .= ' AND cache_id="'.pSQL((string)$cache_id).'"'; + $sql .= ' AND compile_id="'.pSQL((string)$compile_id).'"'; - $result = Db::getInstance()->getRow($sql, false); - // If the filepath is not yet set, it means the cache update is in progress in another process. - // In this case do not try to clear the cache again and tell to use the existing cache, if any - if ($result !== false && $result['filepath'] == '') - { - // If the cache update is stalled for more than 1min, something should be wrong, - // remove the entry from the lazy cache - if ($result['last_update'] < time() - 60) - $this->delete_from_lazy_cache($template, $cache_id, $compile_id); + $result = Db::getInstance()->getRow($sql, false); + // If the filepath is not yet set, it means the cache update is in progress in another process. + // In this case do not try to clear the cache again and tell to use the existing cache, if any + if ($result !== false && $result['filepath'] == '') { + // If the cache update is stalled for more than 1min, something should be wrong, + // remove the entry from the lazy cache + if ($result['last_update'] < time() - 60) { + $this->delete_from_lazy_cache($template, $cache_id, $compile_id); + } - $return = true; - } - else - { - if ($result === false - || @filemtime($this->getCacheDir().$result['filepath']) < $result['last_update']) - $return = false; - else - $return = $result['filepath']; - } - $is_in_lazy_cache[$key] = $return; - } - return $return; - } + $return = true; + } else { + if ($result === false + || @filemtime($this->getCacheDir().$result['filepath']) < $result['last_update']) { + $return = false; + } else { + $return = $result['filepath']; + } + } + $is_in_lazy_cache[$key] = $return; + } + return $return; + } - /** - * Insert the current template in the lazy cache - * - * @param string $template template name - * @param string $cache_id cache id - * @param string $compile_id compile id - * - * @return bool - */ - public function insert_in_lazy_cache($template, $cache_id, $compile_id) - { - $template_md5 = md5($template); - $sql = 'INSERT IGNORE INTO `'._DB_PREFIX_.'smarty_lazy_cache` + /** + * Insert the current template in the lazy cache + * + * @param string $template template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * + * @return bool + */ + public function insert_in_lazy_cache($template, $cache_id, $compile_id) + { + $template_md5 = md5($template); + $sql = 'INSERT IGNORE INTO `'._DB_PREFIX_.'smarty_lazy_cache` (`template_hash`, `cache_id`, `compile_id`, `last_update`) VALUES (\''.pSQL($template_md5).'\''; - $sql .= ',"'.pSQL((string)$cache_id).'"'; + $sql .= ',"'.pSQL((string)$cache_id).'"'; - if (strlen($compile_id) > 32) - $compile_id = md5($compile_id); - $sql .= ',"'.pSQL((string)$compile_id).'"'; - $sql .= ',"'.date('Y-m-d H:i:s').'")'; + if (strlen($compile_id) > 32) { + $compile_id = md5($compile_id); + } + $sql .= ',"'.pSQL((string)$compile_id).'"'; + $sql .= ',"'.date('Y-m-d H:i:s').'")'; - return Db::getInstance()->execute($sql, false); - } + return Db::getInstance()->execute($sql, false); + } - /** - * Delete the current template from the lazy cache or the whole cache if no template name is given - * - * @param string $template template name - * @param string $cache_id cache id - * @param string $compile_id compile id - * - * @return bool - */ - public function delete_from_lazy_cache($template, $cache_id, $compile_id) - { - if (!$template) - return Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'smarty_lazy_cache`', false); + /** + * Delete the current template from the lazy cache or the whole cache if no template name is given + * + * @param string $template template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * + * @return bool + */ + public function delete_from_lazy_cache($template, $cache_id, $compile_id) + { + if (!$template) { + return Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'smarty_lazy_cache`', false); + } - $template_md5 = md5($template); - $sql = 'DELETE FROM `'._DB_PREFIX_.'smarty_lazy_cache` + $template_md5 = md5($template); + $sql = 'DELETE FROM `'._DB_PREFIX_.'smarty_lazy_cache` WHERE template_hash=\''.pSQL($template_md5).'\''; - if ($cache_id != null) - { - $sql .= ' AND cache_id LIKE "'.pSQL((string)$cache_id).'%"'; - } + if ($cache_id != null) { + $sql .= ' AND cache_id LIKE "'.pSQL((string)$cache_id).'%"'; + } - if ($compile_id != null) - { - if (strlen($compile_id) > 32) - $compile_id = md5($compile_id); - $sql .= ' AND compile_id="'.pSQL((string)$compile_id).'"'; - } - Db::getInstance()->execute($sql, false); - return Db::getInstance()->Affected_Rows(); - } + if ($compile_id != null) { + if (strlen($compile_id) > 32) { + $compile_id = md5($compile_id); + } + $sql .= ' AND compile_id="'.pSQL((string)$compile_id).'"'; + } + Db::getInstance()->execute($sql, false); + return Db::getInstance()->Affected_Rows(); + } } -class Smarty_Custom_Template extends Smarty_Internal_Template { +class Smarty_Custom_Template extends Smarty_Internal_Template +{ + /** @var SmartyCustom|null */ + public $smarty = null; - /** @var SmartyCustom|null */ - public $smarty = null; - - public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false) - { - if ($this->smarty->caching) - { - $tpl = parent::fetch($template, $cache_id, $compile_id, $parent, $display, $merge_tpl_vars, $no_output_filter); - if (property_exists($this, 'cached')) - { - $filepath = str_replace($this->smarty->getCacheDir(), '', $this->cached->filepath); - if ($this->smarty->is_in_lazy_cache($this->template_resource, $this->cache_id, $this->compile_id) != $filepath) - $this->smarty->update_filepath($filepath, $this->template_resource, $this->cache_id, $this->compile_id); - } - return $tpl; - } - else - return parent::fetch($template, $cache_id, $compile_id, $parent, $display, $merge_tpl_vars, $no_output_filter); - } + public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false) + { + if ($this->smarty->caching) { + $tpl = parent::fetch($template, $cache_id, $compile_id, $parent, $display, $merge_tpl_vars, $no_output_filter); + if (property_exists($this, 'cached')) { + $filepath = str_replace($this->smarty->getCacheDir(), '', $this->cached->filepath); + if ($this->smarty->is_in_lazy_cache($this->template_resource, $this->cache_id, $this->compile_id) != $filepath) { + $this->smarty->update_filepath($filepath, $this->template_resource, $this->cache_id, $this->compile_id); + } + } + return $tpl; + } else { + return parent::fetch($template, $cache_id, $compile_id, $parent, $display, $merge_tpl_vars, $no_output_filter); + } + } } diff --git a/classes/SpecificPrice.php b/classes/SpecificPrice.php index 79b07af6..91e42331 100644 --- a/classes/SpecificPrice.php +++ b/classes/SpecificPrice.php @@ -26,192 +26,192 @@ class SpecificPriceCore extends ObjectModel { - public $id_product; - public $id_specific_price_rule = 0; - public $id_cart = 0; - public $id_product_attribute; - public $id_shop; - public $id_shop_group; - public $id_currency; - public $id_country; - public $id_group; - public $id_customer; - public $price; - public $from_quantity; - public $reduction; - public $reduction_tax = 1; - public $reduction_type; - public $from; - public $to; + public $id_product; + public $id_specific_price_rule = 0; + public $id_cart = 0; + public $id_product_attribute; + public $id_shop; + public $id_shop_group; + public $id_currency; + public $id_country; + public $id_group; + public $id_customer; + public $price; + public $from_quantity; + public $reduction; + public $reduction_tax = 1; + public $reduction_type; + public $from; + public $to; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'specific_price', - 'primary' => 'id_specific_price', - 'fields' => array( - 'id_shop_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_cart' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_specific_price_rule' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_country' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isNegativePrice', 'required' => true), - 'from_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), - 'reduction' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'reduction_tax' => array('type' => self::TYPE_INT, 'validate' => 'isBool', 'required' => true), - 'reduction_type' => array('type' => self::TYPE_STRING, 'validate' => 'isReductionType', 'required' => true), - 'from' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => true), - 'to' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'specific_price', + 'primary' => 'id_specific_price', + 'fields' => array( + 'id_shop_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_cart' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_specific_price_rule' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_country' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isNegativePrice', 'required' => true), + 'from_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), + 'reduction' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'reduction_tax' => array('type' => self::TYPE_INT, 'validate' => 'isBool', 'required' => true), + 'reduction_type' => array('type' => self::TYPE_STRING, 'validate' => 'isReductionType', 'required' => true), + 'from' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => true), + 'to' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => true), + ), + ); - protected $webserviceParameters = array( - 'objectsNodeName' => 'specific_prices', - 'objectNodeName' => 'specific_price', - 'fields' => array( - 'id_shop_group' => array('xlink_resource' => 'shop_groups'), - 'id_shop' => array('xlink_resource' => 'shops', 'required' => true), - 'id_cart' => array('xlink_resource' => 'carts', 'required' => true), - 'id_product' => array('xlink_resource' => 'products', 'required' => true), - 'id_product_attribute' => array('xlink_resource' => 'product_attributes'), - 'id_currency' => array('xlink_resource' => 'currencies', 'required' => true), - 'id_country' => array('xlink_resource' => 'countries', 'required' => true), - 'id_group' => array('xlink_resource' => 'groups', 'required' => true), - 'id_customer' => array('xlink_resource' => 'customers', 'required' => true), - ), - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'specific_prices', + 'objectNodeName' => 'specific_price', + 'fields' => array( + 'id_shop_group' => array('xlink_resource' => 'shop_groups'), + 'id_shop' => array('xlink_resource' => 'shops', 'required' => true), + 'id_cart' => array('xlink_resource' => 'carts', 'required' => true), + 'id_product' => array('xlink_resource' => 'products', 'required' => true), + 'id_product_attribute' => array('xlink_resource' => 'product_attributes'), + 'id_currency' => array('xlink_resource' => 'currencies', 'required' => true), + 'id_country' => array('xlink_resource' => 'countries', 'required' => true), + 'id_group' => array('xlink_resource' => 'groups', 'required' => true), + 'id_customer' => array('xlink_resource' => 'customers', 'required' => true), + ), + ); - protected static $_specificPriceCache = array(); - protected static $_cache_priorities = array(); + protected static $_specificPriceCache = array(); + protected static $_cache_priorities = array(); - public function add($autodate = true, $nullValues = false) - { - if (parent::add($autodate, $nullValues)) - { - // Flush cache when we adding a new specific price - SpecificPrice::$_specificPriceCache = array(); - Product::flushPriceCache(); - // Set cache of feature detachable to true - Configuration::updateGlobalValue('PS_SPECIFIC_PRICE_FEATURE_ACTIVE', '1'); - return true; - } - return false; - } + public function add($autodate = true, $nullValues = false) + { + if (parent::add($autodate, $nullValues)) { + // Flush cache when we adding a new specific price + SpecificPrice::$_specificPriceCache = array(); + Product::flushPriceCache(); + // Set cache of feature detachable to true + Configuration::updateGlobalValue('PS_SPECIFIC_PRICE_FEATURE_ACTIVE', '1'); + return true; + } + return false; + } - public function update($null_values = false) - { - if (parent::update($null_values)) - { - // Flush cache when we updating a new specific price - SpecificPrice::$_specificPriceCache = array(); - Product::flushPriceCache(); - return true; - } - return false; - } + public function update($null_values = false) + { + if (parent::update($null_values)) { + // Flush cache when we updating a new specific price + SpecificPrice::$_specificPriceCache = array(); + Product::flushPriceCache(); + return true; + } + return false; + } - public function delete() - { - if (parent::delete()) - { - // Flush cache when we deletind a new specific price - SpecificPrice::$_specificPriceCache = array(); - Product::flushPriceCache(); - // Refresh cache of feature detachable - Configuration::updateGlobalValue('PS_SPECIFIC_PRICE_FEATURE_ACTIVE', SpecificPrice::isCurrentlyUsed($this->def['table'])); - return true; - } - return false; - } + public function delete() + { + if (parent::delete()) { + // Flush cache when we deletind a new specific price + SpecificPrice::$_specificPriceCache = array(); + Product::flushPriceCache(); + // Refresh cache of feature detachable + Configuration::updateGlobalValue('PS_SPECIFIC_PRICE_FEATURE_ACTIVE', SpecificPrice::isCurrentlyUsed($this->def['table'])); + return true; + } + return false; + } - public static function getByProductId($id_product, $id_product_attribute = false, $id_cart = false) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getByProductId($id_product, $id_product_attribute = false, $id_cart = false) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'specific_price` WHERE `id_product` = '.(int)$id_product. - ($id_product_attribute ? ' AND id_product_attribute = '.(int)$id_product_attribute : '').' + ($id_product_attribute ? ' AND id_product_attribute = '.(int)$id_product_attribute : '').' AND id_cart = '.(int)$id_cart); - } + } - public static function deleteByIdCart($id_cart, $id_product = false, $id_product_attribute = false) - { - return Db::getInstance()->execute(' + public static function deleteByIdCart($id_cart, $id_product = false, $id_product_attribute = false) + { + return Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'specific_price` WHERE id_cart='.(int)$id_cart. - ($id_product ? ' AND id_product='.(int)$id_product.' AND id_product_attribute='.(int)$id_product_attribute : '')); - } + ($id_product ? ' AND id_product='.(int)$id_product.' AND id_product_attribute='.(int)$id_product_attribute : '')); + } - public static function getIdsByProductId($id_product, $id_product_attribute = false, $id_cart = 0) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getIdsByProductId($id_product, $id_product_attribute = false, $id_cart = 0) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT `id_specific_price` FROM `'._DB_PREFIX_.'specific_price` WHERE `id_product` = '.(int)$id_product.' AND id_product_attribute='.(int)$id_product_attribute.' AND id_cart='.(int)$id_cart); - } + } - /** - * score generation for quantity discount - */ - protected static function _getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_customer) - { - $select = '('; + /** + * score generation for quantity discount + */ + protected static function _getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_customer) + { + $select = '('; - $priority = SpecificPrice::getPriority($id_product); - foreach (array_reverse($priority) as $k => $field) - if (!empty($field)) - $select .= ' IF (`'.bqSQL($field).'` = '.(int)$$field.', '.pow(2, $k + 1).', 0) + '; + $priority = SpecificPrice::getPriority($id_product); + foreach (array_reverse($priority) as $k => $field) { + if (!empty($field)) { + $select .= ' IF (`'.bqSQL($field).'` = '.(int)$$field.', '.pow(2, $k + 1).', 0) + '; + } + } - return rtrim($select, ' +').') AS `score`'; - } + return rtrim($select, ' +').') AS `score`'; + } - public static function getPriority($id_product) - { - if (!SpecificPrice::isFeatureActive()) - return explode(';', Configuration::get('PS_SPECIFIC_PRICE_PRIORITIES')); + public static function getPriority($id_product) + { + if (!SpecificPrice::isFeatureActive()) { + return explode(';', Configuration::get('PS_SPECIFIC_PRICE_PRIORITIES')); + } - if (!isset(SpecificPrice::$_cache_priorities[(int)$id_product])) - { - SpecificPrice::$_cache_priorities[(int)$id_product] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + if (!isset(SpecificPrice::$_cache_priorities[(int)$id_product])) { + SpecificPrice::$_cache_priorities[(int)$id_product] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `priority`, `id_specific_price_priority` FROM `'._DB_PREFIX_.'specific_price_priority` WHERE `id_product` = '.(int)$id_product.' ORDER BY `id_specific_price_priority` DESC '); - } + } - $priority = SpecificPrice::$_cache_priorities[(int)$id_product]; + $priority = SpecificPrice::$_cache_priorities[(int)$id_product]; - if (!$priority) - $priority = Configuration::get('PS_SPECIFIC_PRICE_PRIORITIES'); - $priority = 'id_customer;'.$priority; + if (!$priority) { + $priority = Configuration::get('PS_SPECIFIC_PRICE_PRIORITIES'); + } + $priority = 'id_customer;'.$priority; - return preg_split('/;/', $priority); - } + return preg_split('/;/', $priority); + } - public static function getSpecificPrice($id_product, $id_shop, $id_currency, $id_country, $id_group, $quantity, $id_product_attribute = null, $id_customer = 0, $id_cart = 0, $real_quantity = 0) - { - if (!SpecificPrice::isFeatureActive()) - return array(); - /* - ** The date is not taken into account for the cache, but this is for the better because it keeps the consistency for the whole script. - ** The price must not change between the top and the bottom of the page - */ + public static function getSpecificPrice($id_product, $id_shop, $id_currency, $id_country, $id_group, $quantity, $id_product_attribute = null, $id_customer = 0, $id_cart = 0, $real_quantity = 0) + { + if (!SpecificPrice::isFeatureActive()) { + return array(); + } + /* + ** The date is not taken into account for the cache, but this is for the better because it keeps the consistency for the whole script. + ** The price must not change between the top and the bottom of the page + */ - $key = ((int)$id_product.'-'.(int)$id_shop.'-'.(int)$id_currency.'-'.(int)$id_country.'-'.(int)$id_group.'-'.(int)$quantity.'-'.(int)$id_product_attribute.'-'.(int)$id_cart.'-'.(int)$id_customer.'-'.(int)$real_quantity); - if (!array_key_exists($key, SpecificPrice::$_specificPriceCache)) - { - $now = date('Y-m-d H:i:00'); - $query = ' + $key = ((int)$id_product.'-'.(int)$id_shop.'-'.(int)$id_currency.'-'.(int)$id_country.'-'.(int)$id_group.'-'.(int)$quantity.'-'.(int)$id_product_attribute.'-'.(int)$id_cart.'-'.(int)$id_customer.'-'.(int)$real_quantity); + if (!array_key_exists($key, SpecificPrice::$_specificPriceCache)) { + $now = date('Y-m-d H:i:00'); + $query = ' SELECT *, '.SpecificPrice::_getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_customer).' FROM `'._DB_PREFIX_.'specific_price` USE INDEX (id_product_2) WHERE `id_product` IN (0, '.(int)$id_product.') @@ -230,54 +230,57 @@ class SpecificPriceCore extends ObjectModel AND id_cart IN (0, '.(int)$id_cart.') AND IF(`from_quantity` > 1, `from_quantity`, 0) <= '; - $query .= (Configuration::get('PS_QTY_DISCOUNT_ON_COMBINATION') || !$id_cart || !$real_quantity) ? (int)$quantity : max(1, (int)$real_quantity); - $query .= ' ORDER BY `id_product_attribute` DESC, `from_quantity` DESC, `id_specific_price_rule` ASC, `score` DESC, `to` DESC, `from` DESC'; + $query .= (Configuration::get('PS_QTY_DISCOUNT_ON_COMBINATION') || !$id_cart || !$real_quantity) ? (int)$quantity : max(1, (int)$real_quantity); + $query .= ' ORDER BY `id_product_attribute` DESC, `from_quantity` DESC, `id_specific_price_rule` ASC, `score` DESC, `to` DESC, `from` DESC'; - SpecificPrice::$_specificPriceCache[$key] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query); + SpecificPrice::$_specificPriceCache[$key] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query); + } + return SpecificPrice::$_specificPriceCache[$key]; + } - } - return SpecificPrice::$_specificPriceCache[$key]; - } + public static function setPriorities($priorities) + { + $value = ''; + if (is_array($priorities)) { + foreach ($priorities as $priority) { + $value .= pSQL($priority).';'; + } + } - public static function setPriorities($priorities) - { - $value = ''; - if (is_array($priorities)) - foreach ($priorities as $priority) - $value .= pSQL($priority).';'; + SpecificPrice::deletePriorities(); - SpecificPrice::deletePriorities(); + return Configuration::updateValue('PS_SPECIFIC_PRICE_PRIORITIES', rtrim($value, ';')); + } - return Configuration::updateValue('PS_SPECIFIC_PRICE_PRIORITIES', rtrim($value, ';')); - } - - public static function deletePriorities() - { - return Db::getInstance()->execute(' + public static function deletePriorities() + { + return Db::getInstance()->execute(' TRUNCATE `'._DB_PREFIX_.'specific_price_priority` '); - } + } - public static function setSpecificPriority($id_product, $priorities) - { - $value = ''; - foreach ($priorities as $priority) - $value .= pSQL($priority).';'; + public static function setSpecificPriority($id_product, $priorities) + { + $value = ''; + foreach ($priorities as $priority) { + $value .= pSQL($priority).';'; + } - return Db::getInstance()->execute(' + return Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'specific_price_priority` (`id_product`, `priority`) VALUES ('.(int)$id_product.',\''.pSQL(rtrim($value, ';')).'\') ON DUPLICATE KEY UPDATE `priority` = \''.pSQL(rtrim($value, ';')).'\' '); - } + } - public static function getQuantityDiscounts($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_product_attribute = null, $all_combinations = false, $id_customer = 0) - { - if (!SpecificPrice::isFeatureActive()) - return array(); + public static function getQuantityDiscounts($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_product_attribute = null, $all_combinations = false, $id_customer = 0) + { + if (!SpecificPrice::isFeatureActive()) { + return array(); + } - $now = date('Y-m-d H:i:00'); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $now = date('Y-m-d H:i:00'); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT *, '.SpecificPrice::_getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_customer).' FROM `'._DB_PREFIX_.'specific_price` USE INDEX (id_product_2) @@ -298,31 +301,33 @@ class SpecificPriceCore extends ObjectModel ORDER BY `from_quantity` ASC, `id_specific_price_rule` ASC, `score` DESC, `to` DESC, `from` DESC ', false, false); - $targeted_prices = array(); - $last_quantity = array(); + $targeted_prices = array(); + $last_quantity = array(); - while ($specific_price = Db::getInstance()->nextRow($result)) - { - if (!isset($last_quantity[(int)$specific_price['id_product_attribute']])) - $last_quantity[(int)$specific_price['id_product_attribute']] = $specific_price['from_quantity']; - elseif ($last_quantity[(int)$specific_price['id_product_attribute']] == $specific_price['from_quantity']) - continue; + while ($specific_price = Db::getInstance()->nextRow($result)) { + if (!isset($last_quantity[(int)$specific_price['id_product_attribute']])) { + $last_quantity[(int)$specific_price['id_product_attribute']] = $specific_price['from_quantity']; + } elseif ($last_quantity[(int)$specific_price['id_product_attribute']] == $specific_price['from_quantity']) { + continue; + } - $last_quantity[(int)$specific_price['id_product_attribute']] = $specific_price['from_quantity']; - if ($specific_price['from_quantity'] > 1) - $targeted_prices[] = $specific_price; - } + $last_quantity[(int)$specific_price['id_product_attribute']] = $specific_price['from_quantity']; + if ($specific_price['from_quantity'] > 1) { + $targeted_prices[] = $specific_price; + } + } - return $targeted_prices; - } + return $targeted_prices; + } - public static function getQuantityDiscount($id_product, $id_shop, $id_currency, $id_country, $id_group, $quantity, $id_product_attribute = null, $id_customer = 0) - { - if (!SpecificPrice::isFeatureActive()) - return array(); + public static function getQuantityDiscount($id_product, $id_shop, $id_currency, $id_country, $id_group, $quantity, $id_product_attribute = null, $id_customer = 0) + { + if (!SpecificPrice::isFeatureActive()) { + return array(); + } - $now = date('Y-m-d H:i:00'); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + $now = date('Y-m-d H:i:00'); + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT *, '.SpecificPrice::_getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_customer).' FROM `'._DB_PREFIX_.'specific_price` USE INDEX (id_product_2) @@ -343,14 +348,15 @@ class SpecificPriceCore extends ObjectModel ) ORDER BY `from_quantity` DESC, `score` DESC, `to` DESC, `from` DESC '); - } + } - public static function getProductIdByDate($id_shop, $id_currency, $id_country, $id_group, $beginning, $ending, $id_customer = 0, $with_combination_id = false) - { - if (!SpecificPrice::isFeatureActive()) - return array(); + public static function getProductIdByDate($id_shop, $id_currency, $id_country, $id_group, $beginning, $ending, $id_customer = 0, $with_combination_id = false) + { + if (!SpecificPrice::isFeatureActive()) { + return array(); + } - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT SQL_NO_CACHE `id_product`, `id_product_attribute` FROM `'._DB_PREFIX_.'specific_price` WHERE `id_shop` IN(0, '.(int)$id_shop.') AND @@ -367,50 +373,52 @@ class SpecificPriceCore extends ObjectModel AND `reduction` > 0 ', false, false); - $ids_product = array(); - while ($row = Db::getInstance()->nextRow($result)) - $ids_product[] = $with_combination_id ? array('id_product' => (int)$row['id_product'], 'id_product_attribute' => (int)$row['id_product_attribute']) : (int)$row['id_product']; + $ids_product = array(); + while ($row = Db::getInstance()->nextRow($result)) { + $ids_product[] = $with_combination_id ? array('id_product' => (int)$row['id_product'], 'id_product_attribute' => (int)$row['id_product_attribute']) : (int)$row['id_product']; + } - return $ids_product; - } + return $ids_product; + } - public static function deleteByProductId($id_product) - { - if (Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'specific_price` WHERE `id_product` = '.(int)$id_product)) - { - // Refresh cache of feature detachable - Configuration::updateGlobalValue('PS_SPECIFIC_PRICE_FEATURE_ACTIVE', SpecificPrice::isCurrentlyUsed('specific_price')); - return true; - } - return false; - } + public static function deleteByProductId($id_product) + { + if (Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'specific_price` WHERE `id_product` = '.(int)$id_product)) { + // Refresh cache of feature detachable + Configuration::updateGlobalValue('PS_SPECIFIC_PRICE_FEATURE_ACTIVE', SpecificPrice::isCurrentlyUsed('specific_price')); + return true; + } + return false; + } - public function duplicate($id_product = false) - { - if ($id_product) - $this->id_product = (int)$id_product; - unset($this->id); - return $this->add(); - } + public function duplicate($id_product = false) + { + if ($id_product) { + $this->id_product = (int)$id_product; + } + unset($this->id); + return $this->add(); + } - /** - * This method is allow to know if a feature is used or active - * @since 1.5.0.1 - * @return bool - */ - public static function isFeatureActive() - { - static $feature_active = null; + /** + * This method is allow to know if a feature is used or active + * @since 1.5.0.1 + * @return bool + */ + public static function isFeatureActive() + { + static $feature_active = null; - if ($feature_active === null) - $feature_active = Configuration::get('PS_SPECIFIC_PRICE_FEATURE_ACTIVE'); - return $feature_active; - } + if ($feature_active === null) { + $feature_active = Configuration::get('PS_SPECIFIC_PRICE_FEATURE_ACTIVE'); + } + return $feature_active; + } - public static function exists($id_product, $id_product_attribute, $id_shop, $id_group, $id_country, $id_currency, $id_customer, $from_quantity, $from, $to, $rule = false) - { - $rule = ' AND `id_specific_price_rule`'.(!$rule ? '=0' : '!=0'); - return (int)Db::getInstance()->getValue('SELECT `id_specific_price` + public static function exists($id_product, $id_product_attribute, $id_shop, $id_group, $id_country, $id_currency, $id_customer, $from_quantity, $from, $to, $rule = false) + { + $rule = ' AND `id_specific_price_rule`'.(!$rule ? '=0' : '!=0'); + return (int)Db::getInstance()->getValue('SELECT `id_specific_price` FROM '._DB_PREFIX_.'specific_price WHERE `id_product`='.(int)$id_product.' AND `id_product_attribute`='.(int)$id_product_attribute.' AND @@ -422,5 +430,5 @@ class SpecificPriceCore extends ObjectModel `from_quantity`='.(int)$from_quantity.' AND `from` >= \''.pSQL($from).'\' AND `to` <= \''.pSQL($to).'\''.$rule); - } -} \ No newline at end of file + } +} diff --git a/classes/SpecificPriceRule.php b/classes/SpecificPriceRule.php index ea98ad6f..5a3affb3 100644 --- a/classes/SpecificPriceRule.php +++ b/classes/SpecificPriceRule.php @@ -26,222 +26,220 @@ class SpecificPriceRuleCore extends ObjectModel { - public $name; - public $id_shop; - public $id_currency; - public $id_country; - public $id_group; - public $from_quantity; - public $price; - public $reduction; - public $reduction_tax; - public $reduction_type; - public $from; - public $to; + public $name; + public $id_shop; + public $id_currency; + public $id_country; + public $id_group; + public $from_quantity; + public $price; + public $reduction; + public $reduction_tax; + public $reduction_type; + public $from; + public $to; - protected static $rules_application_enable = true; + protected static $rules_application_enable = true; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'specific_price_rule', - 'primary' => 'id_specific_price_rule', - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true), - 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_country' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'from_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), - 'price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isNegativePrice', 'required' => true), - 'reduction' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'reduction_tax' => array('type' => self::TYPE_INT, 'validate' => 'isBool', 'required' => true), - 'reduction_type' => array('type' => self::TYPE_STRING, 'validate' => 'isReductionType', 'required' => true), - 'from' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => false), - 'to' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => false), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'specific_price_rule', + 'primary' => 'id_specific_price_rule', + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true), + 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_country' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'from_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), + 'price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isNegativePrice', 'required' => true), + 'reduction' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'reduction_tax' => array('type' => self::TYPE_INT, 'validate' => 'isBool', 'required' => true), + 'reduction_type' => array('type' => self::TYPE_STRING, 'validate' => 'isReductionType', 'required' => true), + 'from' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => false), + 'to' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => false), + ), + ); - protected $webserviceParameters = array( - 'objectsNodeName' => 'specific_price_rules', - 'objectNodeName' => 'specific_price_rule', - 'fields' => array( - 'id_shop' => array('xlink_resource' => 'shops', 'required' => true), - 'id_country' => array('xlink_resource' => 'countries', 'required' => true), - 'id_currency' => array('xlink_resource' => 'currencies', 'required' => true), - 'id_group' => array('xlink_resource' => 'groups', 'required' => true), - ), - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'specific_price_rules', + 'objectNodeName' => 'specific_price_rule', + 'fields' => array( + 'id_shop' => array('xlink_resource' => 'shops', 'required' => true), + 'id_country' => array('xlink_resource' => 'countries', 'required' => true), + 'id_currency' => array('xlink_resource' => 'currencies', 'required' => true), + 'id_group' => array('xlink_resource' => 'groups', 'required' => true), + ), + ); - public function delete() - { - $this->deleteConditions(); - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'specific_price WHERE id_specific_price_rule='.(int)$this->id); - return parent::delete(); - } + public function delete() + { + $this->deleteConditions(); + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'specific_price WHERE id_specific_price_rule='.(int)$this->id); + return parent::delete(); + } - public function deleteConditions() - { - $ids_condition_group = Db::getInstance()->executeS('SELECT id_specific_price_rule_condition_group + public function deleteConditions() + { + $ids_condition_group = Db::getInstance()->executeS('SELECT id_specific_price_rule_condition_group FROM '._DB_PREFIX_.'specific_price_rule_condition_group WHERE id_specific_price_rule='.(int)$this->id); - if ($ids_condition_group) - foreach ($ids_condition_group as $row) - { - Db::getInstance()->delete('specific_price_rule_condition_group', 'id_specific_price_rule_condition_group='.(int)$row['id_specific_price_rule_condition_group']); - Db::getInstance()->delete('specific_price_rule_condition', 'id_specific_price_rule_condition_group='.(int)$row['id_specific_price_rule_condition_group']); - } - } + if ($ids_condition_group) { + foreach ($ids_condition_group as $row) { + Db::getInstance()->delete('specific_price_rule_condition_group', 'id_specific_price_rule_condition_group='.(int)$row['id_specific_price_rule_condition_group']); + Db::getInstance()->delete('specific_price_rule_condition', 'id_specific_price_rule_condition_group='.(int)$row['id_specific_price_rule_condition_group']); + } + } + } - public static function disableAnyApplication() - { - SpecificPriceRule::$rules_application_enable = false; - } + public static function disableAnyApplication() + { + SpecificPriceRule::$rules_application_enable = false; + } - public static function enableAnyApplication() - { - SpecificPriceRule::$rules_application_enable = true; - } + public static function enableAnyApplication() + { + SpecificPriceRule::$rules_application_enable = true; + } - public function addConditions($conditions) - { - if (!is_array($conditions)) - return; + public function addConditions($conditions) + { + if (!is_array($conditions)) { + return; + } - $result = Db::getInstance()->insert('specific_price_rule_condition_group', array( - 'id_specific_price_rule' => (int)$this->id - )); - if (!$result) - return false; - $id_specific_price_rule_condition_group = (int)Db::getInstance()->Insert_ID(); - foreach ($conditions as $condition) - { - $result = Db::getInstance()->insert('specific_price_rule_condition', array( - 'id_specific_price_rule_condition_group' => (int)$id_specific_price_rule_condition_group, - 'type' => pSQL($condition['type']), - 'value' => (float)$condition['value'], - )); - if (!$result) - return false; - } - return true; - } + $result = Db::getInstance()->insert('specific_price_rule_condition_group', array( + 'id_specific_price_rule' => (int)$this->id + )); + if (!$result) { + return false; + } + $id_specific_price_rule_condition_group = (int)Db::getInstance()->Insert_ID(); + foreach ($conditions as $condition) { + $result = Db::getInstance()->insert('specific_price_rule_condition', array( + 'id_specific_price_rule_condition_group' => (int)$id_specific_price_rule_condition_group, + 'type' => pSQL($condition['type']), + 'value' => (float)$condition['value'], + )); + if (!$result) { + return false; + } + } + return true; + } - public function apply($products = false) - { - if (!SpecificPriceRule::$rules_application_enable) - return; + public function apply($products = false) + { + if (!SpecificPriceRule::$rules_application_enable) { + return; + } - $this->resetApplication($products); - $products = $this->getAffectedProducts($products); - foreach ($products as $product) - SpecificPriceRule::applyRuleToProduct((int)$this->id, (int)$product['id_product'], (int)$product['id_product_attribute']); - } + $this->resetApplication($products); + $products = $this->getAffectedProducts($products); + foreach ($products as $product) { + SpecificPriceRule::applyRuleToProduct((int)$this->id, (int)$product['id_product'], (int)$product['id_product_attribute']); + } + } - public function resetApplication($products = false) - { - $where = ''; - if ($products && count($products)) - $where .= ' AND id_product IN ('.implode(', ', array_map('intval', $products)).')'; - return Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'specific_price WHERE id_specific_price_rule='.(int)$this->id.$where); - } + public function resetApplication($products = false) + { + $where = ''; + if ($products && count($products)) { + $where .= ' AND id_product IN ('.implode(', ', array_map('intval', $products)).')'; + } + return Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'specific_price WHERE id_specific_price_rule='.(int)$this->id.$where); + } - /** - * @param array|bool $products - */ - public static function applyAllRules($products = false) - { - if (!SpecificPriceRule::$rules_application_enable) - return; + /** + * @param array|bool $products + */ + public static function applyAllRules($products = false) + { + if (!SpecificPriceRule::$rules_application_enable) { + return; + } - $rules = new PrestaShopCollection('SpecificPriceRule'); - foreach ($rules as $rule) - { - /** @var SpecificPriceRule $rule */ - $rule->apply($products); - } - } + $rules = new PrestaShopCollection('SpecificPriceRule'); + foreach ($rules as $rule) { + /** @var SpecificPriceRule $rule */ + $rule->apply($products); + } + } - public function getConditions() - { - $conditions = Db::getInstance()->executeS(' + public function getConditions() + { + $conditions = Db::getInstance()->executeS(' SELECT g.*, c.* FROM '._DB_PREFIX_.'specific_price_rule_condition_group g LEFT JOIN '._DB_PREFIX_.'specific_price_rule_condition c ON (c.id_specific_price_rule_condition_group = g.id_specific_price_rule_condition_group) WHERE g.id_specific_price_rule='.(int)$this->id - ); - $conditions_group = array(); - if ($conditions) - { - foreach ($conditions as &$condition) - { - if ($condition['type'] == 'attribute') - $condition['id_attribute_group'] = Db::getInstance()->getValue('SELECT id_attribute_group + ); + $conditions_group = array(); + if ($conditions) { + foreach ($conditions as &$condition) { + if ($condition['type'] == 'attribute') { + $condition['id_attribute_group'] = Db::getInstance()->getValue('SELECT id_attribute_group FROM '._DB_PREFIX_.'attribute WHERE id_attribute='.(int)$condition['value']); - elseif ($condition['type'] == 'feature') - $condition['id_feature'] = Db::getInstance()->getValue('SELECT id_feature + } elseif ($condition['type'] == 'feature') { + $condition['id_feature'] = Db::getInstance()->getValue('SELECT id_feature FROM '._DB_PREFIX_.'feature_value WHERE id_feature_value='.(int)$condition['value']); - $conditions_group[(int)$condition['id_specific_price_rule_condition_group']][] = $condition; - } - } - return $conditions_group; - } + } + $conditions_group[(int)$condition['id_specific_price_rule_condition_group']][] = $condition; + } + } + return $conditions_group; + } - /** - * Return the product list affected by this specific rule. - * - * @param bool|array $products Products list limitation. - * @return array Affected products list IDs. - * @throws PrestaShopDatabaseException - */ - public function getAffectedProducts($products = false) - { - $conditions_group = $this->getConditions(); - $current_shop_id = Context::getContext()->shop->id; + /** + * Return the product list affected by this specific rule. + * + * @param bool|array $products Products list limitation. + * @return array Affected products list IDs. + * @throws PrestaShopDatabaseException + */ + public function getAffectedProducts($products = false) + { + $conditions_group = $this->getConditions(); + $current_shop_id = Context::getContext()->shop->id; - $result = array(); + $result = array(); - if ($conditions_group) - { - foreach ($conditions_group as $id_condition_group => $condition_group) - { - // Base request - $query = new DbQuery(); - $query->select('p.`id_product`') - ->from('product', 'p') - ->leftJoin('product_shop', 'ps', 'p.`id_product` = ps.`id_product`') - ->where('ps.id_shop = '.(int)$current_shop_id); + if ($conditions_group) { + foreach ($conditions_group as $id_condition_group => $condition_group) { + // Base request + $query = new DbQuery(); + $query->select('p.`id_product`') + ->from('product', 'p') + ->leftJoin('product_shop', 'ps', 'p.`id_product` = ps.`id_product`') + ->where('ps.id_shop = '.(int)$current_shop_id); - $attributes_join_added = false; + $attributes_join_added = false; - // Add the conditions - foreach ($condition_group as $id_condition => $condition) - { - if ($condition['type'] == 'attribute') - { - if (!$attributes_join_added) - { - $query->select('pa.`id_product_attribute`') - ->leftJoin('product_attribute', 'pa', 'p.`id_product` = pa.`id_product`') - ->join(Shop::addSqlAssociation('product_attribute', 'pa', false)); + // Add the conditions + foreach ($condition_group as $id_condition => $condition) { + if ($condition['type'] == 'attribute') { + if (!$attributes_join_added) { + $query->select('pa.`id_product_attribute`') + ->leftJoin('product_attribute', 'pa', 'p.`id_product` = pa.`id_product`') + ->join(Shop::addSqlAssociation('product_attribute', 'pa', false)); - $attributes_join_added = true; - } + $attributes_join_added = true; + } - $query->leftJoin('product_attribute_combination', 'pac'.(int)$id_condition, 'pa.`id_product_attribute` = pac'.(int)$id_condition.'.`id_product_attribute`') - ->where('pac'.(int)$id_condition.'.`id_attribute` = '.(int)$condition['value']); - } - elseif ($condition['type'] == 'manufacturer') - $query->where('p.id_manufacturer = '.(int)$condition['value']); - elseif ($condition['type'] == 'category') - $query->leftJoin('category_product', 'cp'.(int)$id_condition, 'p.`id_product` = cp'.(int)$id_condition.'.`id_product`') - ->where('cp'.(int)$id_condition.'.id_category = '.(int)$condition['value']); - elseif ($condition['type'] == 'supplier') - $query->where('EXISTS( + $query->leftJoin('product_attribute_combination', 'pac'.(int)$id_condition, 'pa.`id_product_attribute` = pac'.(int)$id_condition.'.`id_product_attribute`') + ->where('pac'.(int)$id_condition.'.`id_attribute` = '.(int)$condition['value']); + } elseif ($condition['type'] == 'manufacturer') { + $query->where('p.id_manufacturer = '.(int)$condition['value']); + } elseif ($condition['type'] == 'category') { + $query->leftJoin('category_product', 'cp'.(int)$id_condition, 'p.`id_product` = cp'.(int)$id_condition.'.`id_product`') + ->where('cp'.(int)$id_condition.'.id_category = '.(int)$condition['value']); + } elseif ($condition['type'] == 'supplier') { + $query->where('EXISTS( SELECT `ps'.(int)$id_condition.'`.`id_product` FROM @@ -250,64 +248,67 @@ class SpecificPriceRuleCore extends ObjectModel `p`.`id_product` = `ps'.(int)$id_condition.'`.`id_product` AND `ps'.(int)$id_condition.'`.`id_supplier` = '.(int)$condition['value'].' )'); - elseif ($condition['type'] == 'feature') - $query->leftJoin('feature_product', 'fp'.(int)$id_condition, 'p.`id_product` = fp'.(int)$id_condition.'.`id_product`') - ->where('fp'.(int)$id_condition.'.`id_feature_value` = '.(int)$condition['value']); - } + } elseif ($condition['type'] == 'feature') { + $query->leftJoin('feature_product', 'fp'.(int)$id_condition, 'p.`id_product` = fp'.(int)$id_condition.'.`id_product`') + ->where('fp'.(int)$id_condition.'.`id_feature_value` = '.(int)$condition['value']); + } + } - // Products limitation - if ($products && count($products)) - $query->where('p.`id_product` IN ('.implode(', ', array_map('intval', $products)).')'); + // Products limitation + if ($products && count($products)) { + $query->where('p.`id_product` IN ('.implode(', ', array_map('intval', $products)).')'); + } - // Force the column id_product_attribute if not requested - if (!$attributes_join_added) - $query->select('NULL as `id_product_attribute`'); + // Force the column id_product_attribute if not requested + if (!$attributes_join_added) { + $query->select('NULL as `id_product_attribute`'); + } - $result = array_merge($result, Db::getInstance()->executeS($query)); - } - } - else - { - // All products without conditions - $query = new DbQuery(); - $query->select('p.`id_product`') - ->select('NULL as `id_product_attribute`') - ->from('product', 'p') - ->leftJoin('product_shop', 'ps', 'p.`id_product` = ps.`id_product`') - ->where('ps.id_shop = '.(int)$current_shop_id); + $result = array_merge($result, Db::getInstance()->executeS($query)); + } + } else { + // All products without conditions + $query = new DbQuery(); + $query->select('p.`id_product`') + ->select('NULL as `id_product_attribute`') + ->from('product', 'p') + ->leftJoin('product_shop', 'ps', 'p.`id_product` = ps.`id_product`') + ->where('ps.id_shop = '.(int)$current_shop_id); - if ($products && count($products)) - $query->where('p.`id_product` IN ('.implode(', ', array_map('intval', $products)).')'); + if ($products && count($products)) { + $query->where('p.`id_product` IN ('.implode(', ', array_map('intval', $products)).')'); + } - $result = Db::getInstance()->executeS($query); - } + $result = Db::getInstance()->executeS($query); + } - return $result; - } + return $result; + } - public static function applyRuleToProduct($id_rule, $id_product, $id_product_attribute = null) - { - $rule = new SpecificPriceRule((int)$id_rule); - if (!Validate::isLoadedObject($rule) || !$id_product) - return false; + public static function applyRuleToProduct($id_rule, $id_product, $id_product_attribute = null) + { + $rule = new SpecificPriceRule((int)$id_rule); + if (!Validate::isLoadedObject($rule) || !$id_product) { + return false; + } - $specific_price = new SpecificPrice(); - $specific_price->id_specific_price_rule = (int)$rule->id; - $specific_price->id_product = (int)$id_product; - $specific_price->id_product_attribute = (int)$id_product_attribute; - $specific_price->id_customer = 0; - $specific_price->id_shop = (int)$rule->id_shop; - $specific_price->id_country = (int)$rule->id_country; - $specific_price->id_currency = (int)$rule->id_currency; - $specific_price->id_group = (int)$rule->id_group; - $specific_price->from_quantity = (int)$rule->from_quantity; - $specific_price->price = (float)$rule->price; - $specific_price->reduction_type = $rule->reduction_type; - $specific_price->reduction_tax = $rule->reduction_tax; - $specific_price->reduction = ($rule->reduction_type == 'percentage' ? $rule->reduction / 100 : (float)$rule->reduction); - $specific_price->from = $rule->from; - $specific_price->to = $rule->to; + $specific_price = new SpecificPrice(); + $specific_price->id_specific_price_rule = (int)$rule->id; + $specific_price->id_product = (int)$id_product; + $specific_price->id_product_attribute = (int)$id_product_attribute; + $specific_price->id_customer = 0; + $specific_price->id_shop = (int)$rule->id_shop; + $specific_price->id_country = (int)$rule->id_country; + $specific_price->id_currency = (int)$rule->id_currency; + $specific_price->id_group = (int)$rule->id_group; + $specific_price->from_quantity = (int)$rule->from_quantity; + $specific_price->price = (float)$rule->price; + $specific_price->reduction_type = $rule->reduction_type; + $specific_price->reduction_tax = $rule->reduction_tax; + $specific_price->reduction = ($rule->reduction_type == 'percentage' ? $rule->reduction / 100 : (float)$rule->reduction); + $specific_price->from = $rule->from; + $specific_price->to = $rule->to; - return $specific_price->add(); - } + return $specific_price->add(); + } } diff --git a/classes/State.php b/classes/State.php index 6b5e43f7..2bfdb44d 100644 --- a/classes/State.php +++ b/classes/State.php @@ -26,203 +26,206 @@ class StateCore extends ObjectModel { - /** @var int Country id which state belongs */ - public $id_country; + /** @var int Country id which state belongs */ + public $id_country; - /** @var int Zone id which state belongs */ - public $id_zone; + /** @var int Zone id which state belongs */ + public $id_zone; - /** @var string 2 letters iso code */ - public $iso_code; + /** @var string 2 letters iso code */ + public $iso_code; - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var bool Status for delivery */ - public $active = true; + /** @var bool Status for delivery */ + public $active = true; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'state', - 'primary' => 'id_state', - 'fields' => array( - 'id_country' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_zone' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'iso_code' => array('type' => self::TYPE_STRING, 'validate' => 'isStateIsoCode', 'required' => true, 'size' => 7), - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'state', + 'primary' => 'id_state', + 'fields' => array( + 'id_country' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_zone' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'iso_code' => array('type' => self::TYPE_STRING, 'validate' => 'isStateIsoCode', 'required' => true, 'size' => 7), + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_zone' => array('xlink_resource'=> 'zones'), - 'id_country' => array('xlink_resource'=> 'countries') - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_zone' => array('xlink_resource'=> 'zones'), + 'id_country' => array('xlink_resource'=> 'countries') + ), + ); - public static function getStates($id_lang = false, $active = false) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getStates($id_lang = false, $active = false) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT `id_state`, `id_country`, `id_zone`, `iso_code`, `name`, `active` FROM `'._DB_PREFIX_.'state` '.($active ? 'WHERE active = 1' : '').' ORDER BY `name` ASC'); - } + } - /** - * Get a state name with its ID - * - * @param int $id_state Country ID - * @return string State name - */ - public static function getNameById($id_state) - { - if (!$id_state) - return false; - $cache_id = 'State::getNameById_'.(int)$id_state; - if (!Cache::isStored($cache_id)) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Get a state name with its ID + * + * @param int $id_state Country ID + * @return string State name + */ + public static function getNameById($id_state) + { + if (!$id_state) { + return false; + } + $cache_id = 'State::getNameById_'.(int)$id_state; + if (!Cache::isStored($cache_id)) { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `name` FROM `'._DB_PREFIX_.'state` WHERE `id_state` = '.(int)$id_state - ); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + ); + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Get a state id with its name - * - * @param string $id_state Country ID - * @return int state id - */ - public static function getIdByName($state) - { - if (empty($state)) - return false; - $cache_id = 'State::getIdByName_'.pSQL($state); - if (!Cache::isStored($cache_id)) - { - $result = (int)Db::getInstance()->getValue(' + /** + * Get a state id with its name + * + * @param string $id_state Country ID + * @return int state id + */ + public static function getIdByName($state) + { + if (empty($state)) { + return false; + } + $cache_id = 'State::getIdByName_'.pSQL($state); + if (!Cache::isStored($cache_id)) { + $result = (int)Db::getInstance()->getValue(' SELECT `id_state` FROM `'._DB_PREFIX_.'state` WHERE `name` = \''.pSQL($state).'\' '); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Get a state id with its iso code - * - * @param string $iso_code Iso code - * @return int state id - */ - public static function getIdByIso($iso_code, $id_country = null) - { - return Db::getInstance()->getValue(' + /** + * Get a state id with its iso code + * + * @param string $iso_code Iso code + * @return int state id + */ + public static function getIdByIso($iso_code, $id_country = null) + { + return Db::getInstance()->getValue(' SELECT `id_state` FROM `'._DB_PREFIX_.'state` WHERE `iso_code` = \''.pSQL($iso_code).'\' '.($id_country ? 'AND `id_country` = '.(int)$id_country : '')); - } + } - /** - * Delete a state only if is not in use - * - * @return bool - */ - public function delete() - { - if (!$this->isUsed()) - { - // Database deletion - $result = Db::getInstance()->delete($this->def['table'], '`'.$this->def['primary'].'` = '.(int)$this->id); - if (!$result) - return false; + /** + * Delete a state only if is not in use + * + * @return bool + */ + public function delete() + { + if (!$this->isUsed()) { + // Database deletion + $result = Db::getInstance()->delete($this->def['table'], '`'.$this->def['primary'].'` = '.(int)$this->id); + if (!$result) { + return false; + } - // Database deletion for multilingual fields related to the object - if (!empty($this->def['multilang'])) - Db::getInstance()->delete(bqSQL($this->def['table']).'_lang', '`'.$this->def['primary'].'` = '.(int)$this->id); - return $result; - } - else - return false; - } + // Database deletion for multilingual fields related to the object + if (!empty($this->def['multilang'])) { + Db::getInstance()->delete(bqSQL($this->def['table']).'_lang', '`'.$this->def['primary'].'` = '.(int)$this->id); + } + return $result; + } else { + return false; + } + } - /** - * Check if a state is used - * - * @return bool - */ - public function isUsed() - { - return ($this->countUsed() > 0); - } + /** + * Check if a state is used + * + * @return bool + */ + public function isUsed() + { + return ($this->countUsed() > 0); + } - /** - * Returns the number of utilisation of a state - * - * @return int count for this state - */ - public function countUsed() - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Returns the number of utilisation of a state + * + * @return int count for this state + */ + public function countUsed() + { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'address` WHERE `'.$this->def['primary'].'` = '.(int)$this->id - ); - return $result; - } + ); + return $result; + } - public static function getStatesByIdCountry($id_country) - { - if (empty($id_country)) - die(Tools::displayError()); + public static function getStatesByIdCountry($id_country) + { + if (empty($id_country)) { + die(Tools::displayError()); + } - return Db::getInstance()->executeS(' + return Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'state` s WHERE s.`id_country` = '.(int)$id_country - ); - } + ); + } - public static function hasCounties($id_state) - { - return count(County::getCounties((int)$id_state)); - } + public static function hasCounties($id_state) + { + return count(County::getCounties((int)$id_state)); + } - public static function getIdZone($id_state) - { - if (!Validate::isUnsignedId($id_state)) - die(Tools::displayError()); + public static function getIdZone($id_state) + { + if (!Validate::isUnsignedId($id_state)) { + die(Tools::displayError()); + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_zone` FROM `'._DB_PREFIX_.'state` WHERE `id_state` = '.(int)$id_state - ); - } + ); + } - /** - * @param $ids_states - * @param $id_zone - * @return bool - */ - public function affectZoneToSelection($ids_states, $id_zone) - { - // cast every array values to int (security) - $ids_states = array_map('intval', $ids_states); - return Db::getInstance()->execute(' + /** + * @param $ids_states + * @param $id_zone + * @return bool + */ + public function affectZoneToSelection($ids_states, $id_zone) + { + // cast every array values to int (security) + $ids_states = array_map('intval', $ids_states); + return Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'state` SET `id_zone` = '.(int)$id_zone.' WHERE `id_state` IN ('.implode(',', $ids_states).') '); - } -} \ No newline at end of file + } +} diff --git a/classes/Store.php b/classes/Store.php index f0f396ab..3d69878e 100644 --- a/classes/Store.php +++ b/classes/Store.php @@ -26,107 +26,107 @@ class StoreCore extends ObjectModel { - /** @var int Country id */ - public $id_country; + /** @var int Country id */ + public $id_country; - /** @var int State id */ - public $id_state; + /** @var int State id */ + public $id_state; - /** @var string Store name */ - public $name; + /** @var string Store name */ + public $name; - /** @var string Address first line */ - public $address1; + /** @var string Address first line */ + public $address1; - /** @var string Address second line (optional) */ - public $address2; + /** @var string Address second line (optional) */ + public $address2; - /** @var string Postal code */ - public $postcode; + /** @var string Postal code */ + public $postcode; - /** @var string City */ - public $city; + /** @var string City */ + public $city; - /** @var float Latitude */ - public $latitude; + /** @var float Latitude */ + public $latitude; - /** @var float Longitude */ - public $longitude; + /** @var float Longitude */ + public $longitude; - /** @var string Store hours (PHP serialized) */ - public $hours; + /** @var string Store hours (PHP serialized) */ + public $hours; - /** @var string Phone number */ - public $phone; + /** @var string Phone number */ + public $phone; - /** @var string Fax number */ - public $fax; + /** @var string Fax number */ + public $fax; - /** @var string Note */ - public $note; + /** @var string Note */ + public $note; - /** @var string e-mail */ - public $email; + /** @var string e-mail */ + public $email; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** @var string Object last modification date */ - public $date_upd; + /** @var string Object last modification date */ + public $date_upd; - /** @var bool Store status */ - public $active = true; + /** @var bool Store status */ + public $active = true; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'store', - 'primary' => 'id_store', - 'fields' => array( - 'id_country' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_state' => array('type' => self::TYPE_INT, 'validate' => 'isNullOrUnsignedId'), - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), - 'address1' => array('type' => self::TYPE_STRING, 'validate' => 'isAddress', 'required' => true, 'size' => 128), - 'address2' => array('type' => self::TYPE_STRING, 'validate' => 'isAddress', 'size' => 128), - 'postcode' => array('type' => self::TYPE_STRING, 'size' => 12), - 'city' => array('type' => self::TYPE_STRING, 'validate' => 'isCityName', 'required' => true, 'size' => 64), - 'latitude' => array('type' => self::TYPE_FLOAT, 'validate' => 'isCoordinate', 'size' => 13), - 'longitude' => array('type' => self::TYPE_FLOAT, 'validate' => 'isCoordinate', 'size' => 13), - 'hours' => array('type' => self::TYPE_STRING, 'validate' => 'isSerializedArray', 'size' => 65000), - 'phone' => array('type' => self::TYPE_STRING, 'validate' => 'isPhoneNumber', 'size' => 16), - 'fax' => array('type' => self::TYPE_STRING, 'validate' => 'isPhoneNumber', 'size' => 16), - 'note' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 65000), - 'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'size' => 128), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'store', + 'primary' => 'id_store', + 'fields' => array( + 'id_country' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_state' => array('type' => self::TYPE_INT, 'validate' => 'isNullOrUnsignedId'), + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), + 'address1' => array('type' => self::TYPE_STRING, 'validate' => 'isAddress', 'required' => true, 'size' => 128), + 'address2' => array('type' => self::TYPE_STRING, 'validate' => 'isAddress', 'size' => 128), + 'postcode' => array('type' => self::TYPE_STRING, 'size' => 12), + 'city' => array('type' => self::TYPE_STRING, 'validate' => 'isCityName', 'required' => true, 'size' => 64), + 'latitude' => array('type' => self::TYPE_FLOAT, 'validate' => 'isCoordinate', 'size' => 13), + 'longitude' => array('type' => self::TYPE_FLOAT, 'validate' => 'isCoordinate', 'size' => 13), + 'hours' => array('type' => self::TYPE_STRING, 'validate' => 'isSerializedArray', 'size' => 65000), + 'phone' => array('type' => self::TYPE_STRING, 'validate' => 'isPhoneNumber', 'size' => 16), + 'fax' => array('type' => self::TYPE_STRING, 'validate' => 'isPhoneNumber', 'size' => 16), + 'note' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 65000), + 'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'size' => 128), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_country' => array('xlink_resource'=> 'countries'), - 'id_state' => array('xlink_resource'=> 'states'), - 'hours' => array('getter' => 'getWsHours', 'setter' => 'setWsHours'), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_country' => array('xlink_resource'=> 'countries'), + 'id_state' => array('xlink_resource'=> 'states'), + 'hours' => array('getter' => 'getWsHours', 'setter' => 'setWsHours'), + ), + ); - public function __construct($id_store = null, $id_lang = null) - { - parent::__construct($id_store); - $this->id_image = ($this->id && file_exists(_PS_STORE_IMG_DIR_.(int)$this->id.'.jpg')) ? (int)$this->id : false; - $this->image_dir = _PS_STORE_IMG_DIR_; - } + public function __construct($id_store = null, $id_lang = null) + { + parent::__construct($id_store); + $this->id_image = ($this->id && file_exists(_PS_STORE_IMG_DIR_.(int)$this->id.'.jpg')) ? (int)$this->id : false; + $this->image_dir = _PS_STORE_IMG_DIR_; + } - public function getWsHours() - { - return implode(';', Tools::unSerialize($this->hours)); - } + public function getWsHours() + { + return implode(';', Tools::unSerialize($this->hours)); + } - public function setWsHours($hours) - { - $this->hours = serialize(explode(';', $hours)); - return true; - } + public function setWsHours($hours) + { + $this->hours = serialize(explode(';', $hours)); + return true; + } } diff --git a/classes/Supplier.php b/classes/Supplier.php index 75d54924..a3254894 100644 --- a/classes/Supplier.php +++ b/classes/Supplier.php @@ -26,123 +26,125 @@ class SupplierCore extends ObjectModel { - public $id; + public $id; - /** @var int supplier ID */ - public $id_supplier; + /** @var int supplier ID */ + public $id_supplier; - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var string A short description for the discount */ - public $description; + /** @var string A short description for the discount */ + public $description; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** @var string Object last modification date */ - public $date_upd; + /** @var string Object last modification date */ + public $date_upd; - /** @var string Friendly URL */ - public $link_rewrite; + /** @var string Friendly URL */ + public $link_rewrite; - /** @var string Meta title */ - public $meta_title; + /** @var string Meta title */ + public $meta_title; - /** @var string Meta keywords */ - public $meta_keywords; + /** @var string Meta keywords */ + public $meta_keywords; - /** @var string Meta description */ - public $meta_description; + /** @var string Meta description */ + public $meta_description; - /** @var bool active */ - public $active; + /** @var bool active */ + public $active; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'supplier', - 'primary' => 'id_supplier', - 'multilang' => true, - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isCatalogName', 'required' => true, 'size' => 64), - 'active' => array('type' => self::TYPE_BOOL), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'supplier', + 'primary' => 'id_supplier', + 'multilang' => true, + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isCatalogName', 'required' => true, 'size' => 64), + 'active' => array('type' => self::TYPE_BOOL), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - /* Lang fields */ - 'description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), - 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), - 'meta_description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - 'meta_keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), - ), - ); + /* Lang fields */ + 'description' => array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'), + 'meta_title' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128), + 'meta_description' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + 'meta_keywords' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'link_rewrite' => array('sqlId' => 'link_rewrite'), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'link_rewrite' => array('sqlId' => 'link_rewrite'), + ), + ); - public function __construct($id = null, $id_lang = null) - { - parent::__construct($id, $id_lang); + public function __construct($id = null, $id_lang = null) + { + parent::__construct($id, $id_lang); - $this->link_rewrite = $this->getLink(); - $this->image_dir = _PS_SUPP_IMG_DIR_; - } + $this->link_rewrite = $this->getLink(); + $this->image_dir = _PS_SUPP_IMG_DIR_; + } - public function getLink() - { - return Tools::link_rewrite($this->name); - } + public function getLink() + { + return Tools::link_rewrite($this->name); + } - /** - * Return suppliers - * - * @return array Suppliers - */ - public static function getSuppliers($get_nb_products = false, $id_lang = 0, $active = true, $p = false, $n = false, $all_groups = false) - { - if (!$id_lang) - $id_lang = Configuration::get('PS_LANG_DEFAULT'); - if (!Group::isFeatureActive()) - $all_groups = true; + /** + * Return suppliers + * + * @return array Suppliers + */ + public static function getSuppliers($get_nb_products = false, $id_lang = 0, $active = true, $p = false, $n = false, $all_groups = false) + { + if (!$id_lang) { + $id_lang = Configuration::get('PS_LANG_DEFAULT'); + } + if (!Group::isFeatureActive()) { + $all_groups = true; + } - $query = new DbQuery(); - $query->select('s.*, sl.`description`'); - $query->from('supplier', 's'); - $query->leftJoin('supplier_lang', 'sl', 's.`id_supplier` = sl.`id_supplier` AND sl.`id_lang` = '.(int)$id_lang); - $query->join(Shop::addSqlAssociation('supplier', 's')); - if ($active) - $query->where('s.`active` = 1'); - $query->orderBy(' s.`name` ASC'); - $query->limit($n, ($p - 1) * $n); - $query->groupBy('s.id_supplier'); + $query = new DbQuery(); + $query->select('s.*, sl.`description`'); + $query->from('supplier', 's'); + $query->leftJoin('supplier_lang', 'sl', 's.`id_supplier` = sl.`id_supplier` AND sl.`id_lang` = '.(int)$id_lang); + $query->join(Shop::addSqlAssociation('supplier', 's')); + if ($active) { + $query->where('s.`active` = 1'); + } + $query->orderBy(' s.`name` ASC'); + $query->limit($n, ($p - 1) * $n); + $query->groupBy('s.id_supplier'); - $suppliers = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - if ($suppliers === false) - return false; - if ($get_nb_products) - { - $sql_groups = ''; - if (!$all_groups) - { - $groups = FrontController::getCurrentCustomerGroups(); - $sql_groups = (count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); - } + $suppliers = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + if ($suppliers === false) { + return false; + } + if ($get_nb_products) { + $sql_groups = ''; + if (!$all_groups) { + $groups = FrontController::getCurrentCustomerGroups(); + $sql_groups = (count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); + } - $results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT ps.`id_supplier`, COUNT(DISTINCT ps.`id_product`) as nb_products FROM `'._DB_PREFIX_.'product_supplier` ps JOIN `'._DB_PREFIX_.'product` p ON (ps.`id_product`= p.`id_product`) '.Shop::addSqlAssociation('product', 'p').' LEFT JOIN `'._DB_PREFIX_.'supplier` as m ON (m.`id_supplier`= p.`id_supplier`) WHERE ps.id_product_attribute = 0'. - ($active ? ' AND product_shop.`active` = 1' : ''). - ' AND product_shop.`visibility` NOT IN ("none")'. - ($all_groups ? '' :' + ($active ? ' AND product_shop.`active` = 1' : ''). + ' AND product_shop.`visibility` NOT IN ("none")'. + ($all_groups ? '' :' AND ps.`id_product` IN ( SELECT cp.`id_product` FROM `'._DB_PREFIX_.'category_group` cg @@ -150,80 +152,94 @@ class SupplierCore extends ObjectModel WHERE cg.`id_group` '.$sql_groups.' )').' GROUP BY ps.`id_supplier`' - ); + ); - $counts = array(); - foreach ($results as $result) - $counts[(int)$result['id_supplier']] = (int)$result['nb_products']; + $counts = array(); + foreach ($results as $result) { + $counts[(int)$result['id_supplier']] = (int)$result['nb_products']; + } - if (count($counts) && is_array($suppliers)) - foreach ($suppliers as $key => $supplier) - if (isset($counts[(int)$supplier['id_supplier']])) - $suppliers[$key]['nb_products'] = $counts[(int)$supplier['id_supplier']]; - else - $suppliers[$key]['nb_products'] = 0; - } + if (count($counts) && is_array($suppliers)) { + foreach ($suppliers as $key => $supplier) { + if (isset($counts[(int)$supplier['id_supplier']])) { + $suppliers[$key]['nb_products'] = $counts[(int)$supplier['id_supplier']]; + } else { + $suppliers[$key]['nb_products'] = 0; + } + } + } + } - $nb_suppliers = count($suppliers); - $rewrite_settings = (int)Configuration::get('PS_REWRITING_SETTINGS'); - for ($i = 0; $i < $nb_suppliers; $i++) - $suppliers[$i]['link_rewrite'] = ($rewrite_settings ? Tools::link_rewrite($suppliers[$i]['name']) : 0); - return $suppliers; - } + $nb_suppliers = count($suppliers); + $rewrite_settings = (int)Configuration::get('PS_REWRITING_SETTINGS'); + for ($i = 0; $i < $nb_suppliers; $i++) { + $suppliers[$i]['link_rewrite'] = ($rewrite_settings ? Tools::link_rewrite($suppliers[$i]['name']) : 0); + } + return $suppliers; + } - /** - * Return name from id - * - * @param int $id_supplier Supplier ID - * @return string name - */ - static protected $cache_name = array(); - public static function getNameById($id_supplier) - { - if (!isset(self::$cache_name[$id_supplier])) - self::$cache_name[$id_supplier] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Return name from id + * + * @param int $id_supplier Supplier ID + * @return string name + */ + protected static $cache_name = array(); + public static function getNameById($id_supplier) + { + if (!isset(self::$cache_name[$id_supplier])) { + self::$cache_name[$id_supplier] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `name` FROM `'._DB_PREFIX_.'supplier` WHERE `id_supplier` = '.(int)$id_supplier); - return self::$cache_name[$id_supplier]; - } + } + return self::$cache_name[$id_supplier]; + } - public static function getIdByName($name) - { - $result = Db::getInstance()->getRow(' + public static function getIdByName($name) + { + $result = Db::getInstance()->getRow(' SELECT `id_supplier` FROM `'._DB_PREFIX_.'supplier` WHERE `name` = \''.pSQL($name).'\''); - if (isset($result['id_supplier'])) - return (int)$result['id_supplier']; + if (isset($result['id_supplier'])) { + return (int)$result['id_supplier']; + } - return false; - } + return false; + } - public static function getProducts($id_supplier, $id_lang, $p, $n, - $order_by = null, $order_way = null, $get_total = false, $active = true, $active_category = true) - { - $context = Context::getContext(); - $front = true; - if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) - $front = false; + public static function getProducts($id_supplier, $id_lang, $p, $n, + $order_by = null, $order_way = null, $get_total = false, $active = true, $active_category = true) + { + $context = Context::getContext(); + $front = true; + if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) { + $front = false; + } - if ($p < 1) $p = 1; - if (empty($order_by) || $order_by == 'position') $order_by = 'name'; - if (empty($order_way)) $order_way = 'ASC'; + if ($p < 1) { + $p = 1; + } + if (empty($order_by) || $order_by == 'position') { + $order_by = 'name'; + } + if (empty($order_way)) { + $order_way = 'ASC'; + } - if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) - die (Tools::displayError()); + if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) { + die(Tools::displayError()); + } - $sql_groups = ''; - if (Group::isFeatureActive()) - { - $groups = FrontController::getCurrentCustomerGroups(); - $sql_groups = 'WHERE cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); - } + $sql_groups = ''; + if (Group::isFeatureActive()) { + $groups = FrontController::getCurrentCustomerGroups(); + $sql_groups = 'WHERE cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); + } - /* Return only the number of products */ - if ($get_total) - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /* Return only the number of products */ + if ($get_total) { + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(DISTINCT ps.`id_product`) FROM `'._DB_PREFIX_.'product_supplier` ps JOIN `'._DB_PREFIX_.'product` p ON (ps.`id_product`= p.`id_product`) @@ -239,26 +255,25 @@ class SupplierCore extends ObjectModel '.($active_category ? ' INNER JOIN `'._DB_PREFIX_.'category` ca ON cp.`id_category` = ca.`id_category` AND ca.`active` = 1' : '').' '.$sql_groups.' )'); + } - $nb_days_new_product = Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20; + $nb_days_new_product = Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20; - if (strpos('.', $order_by) > 0) - { - $order_by = explode('.', $order_by); - $order_by = pSQL($order_by[0]).'.`'.pSQL($order_by[1]).'`'; - } - $alias = ''; - if (in_array($order_by, array('price', 'date_add', 'date_upd'))) - $alias = 'product_shop.'; - elseif ($order_by == 'id_product') - $alias = 'p.'; - elseif ($order_by == 'manufacturer_name') - { - $order_by = 'name'; - $alias = 'm.'; - } + if (strpos('.', $order_by) > 0) { + $order_by = explode('.', $order_by); + $order_by = pSQL($order_by[0]).'.`'.pSQL($order_by[1]).'`'; + } + $alias = ''; + if (in_array($order_by, array('price', 'date_add', 'date_upd'))) { + $alias = 'product_shop.'; + } elseif ($order_by == 'id_product') { + $alias = 'p.'; + } elseif ($order_by == 'manufacturer_name') { + $order_by = 'name'; + $alias = 'm.'; + } - $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, + $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description`, pl.`description_short`, @@ -276,7 +291,7 @@ class SupplierCore extends ObjectModel '.Shop::addSqlAssociation('product', 'p').' JOIN `'._DB_PREFIX_.'product_supplier` ps ON (ps.id_product = p.id_product AND ps.id_product_attribute = 0) '. - (Combination::isFeatureActive() ? 'LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop + (Combination::isFeatureActive() ? 'LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop ON (p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='.(int)$context->shop->id.')':'').' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').') @@ -288,16 +303,17 @@ class SupplierCore extends ObjectModel LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer` '.Product::sqlStock('p', 0); - if (Group::isFeatureActive() || $active_category) - { - $sql .= 'JOIN `'._DB_PREFIX_.'category_product` cp ON (p.id_product = cp.id_product)'; - if (Group::isFeatureActive()) - $sql .= 'JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.`id_category` = cg.`id_category` AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1').')'; - if ($active_category) - $sql .= 'JOIN `'._DB_PREFIX_.'category` ca ON cp.`id_category` = ca.`id_category` AND ca.`active` = 1'; - } + if (Group::isFeatureActive() || $active_category) { + $sql .= 'JOIN `'._DB_PREFIX_.'category_product` cp ON (p.id_product = cp.id_product)'; + if (Group::isFeatureActive()) { + $sql .= 'JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.`id_category` = cg.`id_category` AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1').')'; + } + if ($active_category) { + $sql .= 'JOIN `'._DB_PREFIX_.'category` ca ON cp.`id_category` = ca.`id_category` AND ca.`active` = 1'; + } + } - $sql .= ' + $sql .= ' WHERE ps.`id_supplier` = '.(int)$id_supplier.' '.($active ? ' AND product_shop.`active` = 1' : '').' '.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').' @@ -305,25 +321,28 @@ class SupplierCore extends ObjectModel ORDER BY '.$alias.pSQL($order_by).' '.pSQL($order_way).' LIMIT '.(((int)$p - 1) * (int)$n).','.(int)$n; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false); - if (!$result) - return false; + if (!$result) { + return false; + } - if ($order_by == 'price') - Tools::orderbyPrice($result, $order_way); + if ($order_by == 'price') { + Tools::orderbyPrice($result, $order_way); + } - return Product::getProductsProperties($id_lang, $result); - } + return Product::getProductsProperties($id_lang, $result); + } - public function getProductsLite($id_lang) - { - $context = Context::getContext(); - $front = true; - if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) - $front = false; + public function getProductsLite($id_lang) + { + $context = Context::getContext(); + $front = true; + if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) { + $front = false; + } - $sql = ' + $sql = ' SELECT p.`id_product`, pl.`name` FROM `'._DB_PREFIX_.'product` p @@ -339,59 +358,59 @@ class SupplierCore extends ObjectModel '.($front ? ' WHERE product_shop.`visibility` IN ("both", "catalog")' : '').' GROUP BY p.`id_product`'; - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - return $res; - } + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + return $res; + } - /* - * Tells if a supplier exists - * - * @param $id_supplier Supplier id - * @return bool - */ - public static function supplierExists($id_supplier) - { - $query = new DbQuery(); - $query->select('id_supplier'); - $query->from('supplier'); - $query->where('id_supplier = '.(int)$id_supplier); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + /* + * Tells if a supplier exists + * + * @param $id_supplier Supplier id + * @return bool + */ + public static function supplierExists($id_supplier) + { + $query = new DbQuery(); + $query->select('id_supplier'); + $query->from('supplier'); + $query->where('id_supplier = '.(int)$id_supplier); + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - return ($res > 0); - } + return ($res > 0); + } - /** - * @see ObjectModel::delete() - */ - public function delete() - { - if (parent::delete()) - { - CartRule::cleanProductRuleIntegrity('suppliers', $this->id); - return $this->deleteImage(); - } - } + /** + * @see ObjectModel::delete() + */ + public function delete() + { + if (parent::delete()) { + CartRule::cleanProductRuleIntegrity('suppliers', $this->id); + return $this->deleteImage(); + } + } - /** - * Gets product informations - * - * @since 1.5.0 - * @param int $id_supplier - * @param int $id_product - * @param int $id_product_attribute - * @return array - */ - public static function getProductInformationsBySupplier($id_supplier, $id_product, $id_product_attribute = 0) - { - $query = new DbQuery(); - $query->select('product_supplier_reference, product_supplier_price_te, id_currency'); - $query->from('product_supplier'); - $query->where('id_supplier = '.(int)$id_supplier); - $query->where('id_product = '.(int)$id_product); - $query->where('id_product_attribute = '.(int)$id_product_attribute); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + /** + * Gets product informations + * + * @since 1.5.0 + * @param int $id_supplier + * @param int $id_product + * @param int $id_product_attribute + * @return array + */ + public static function getProductInformationsBySupplier($id_supplier, $id_product, $id_product_attribute = 0) + { + $query = new DbQuery(); + $query->select('product_supplier_reference, product_supplier_price_te, id_currency'); + $query->from('product_supplier'); + $query->where('id_supplier = '.(int)$id_supplier); + $query->where('id_product = '.(int)$id_product); + $query->where('id_product_attribute = '.(int)$id_product_attribute); + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - if (count($res)) - return $res[0]; - } + if (count($res)) { + return $res[0]; + } + } } diff --git a/classes/Tab.php b/classes/Tab.php index a2951622..47aa3e47 100644 --- a/classes/Tab.php +++ b/classes/Tab.php @@ -26,497 +26,514 @@ class TabCore extends ObjectModel { - /** @var string Displayed name*/ - public $name; + /** @var string Displayed name*/ + public $name; - /** @var string Class and file name*/ - public $class_name; + /** @var string Class and file name*/ + public $class_name; - public $module; + public $module; - /** @var int parent ID */ - public $id_parent; + /** @var int parent ID */ + public $id_parent; - /** @var int position */ - public $position; + /** @var int position */ + public $position; - /** @var bool active */ - public $active = true; + /** @var bool active */ + public $active = true; - /** @var int hide_host_mode */ - public $hide_host_mode = false; + /** @var int hide_host_mode */ + public $hide_host_mode = false; - const TAB_MODULE_LIST_URL = _PS_TAB_MODULE_LIST_URL_; + const TAB_MODULE_LIST_URL = _PS_TAB_MODULE_LIST_URL_; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'tab', - 'primary' => 'id_tab', - 'multilang' => true, - 'fields' => array( - 'id_parent' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'position' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'module' => array('type' => self::TYPE_STRING, 'validate' => 'isTabName', 'size' => 64), - 'class_name' => array('type' => self::TYPE_STRING, 'required' => true, 'size' => 64), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'hide_host_mode' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'required' => true, 'validate' => 'isTabName', 'size' => 64), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'tab', + 'primary' => 'id_tab', + 'multilang' => true, + 'fields' => array( + 'id_parent' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'position' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'module' => array('type' => self::TYPE_STRING, 'validate' => 'isTabName', 'size' => 64), + 'class_name' => array('type' => self::TYPE_STRING, 'required' => true, 'size' => 64), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'hide_host_mode' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'required' => true, 'validate' => 'isTabName', 'size' => 64), + ), + ); - protected static $_getIdFromClassName = null; + protected static $_getIdFromClassName = null; - /** - * additionnal treatments for Tab when creating new one : - * - generate a new position - * - add access for admin profile - * - * @param bool $autodate - * @param bool $null_values - * @return int id_tab - */ - public function add($autodate = true, $null_values = false) - { - // @retrocompatibility with old menu (before 1.5.0.9) - $retro = array( - 'AdminPayment' => 'AdminParentModules', - 'AdminOrders' => 'AdminParentOrders', - 'AdminCustomers' => 'AdminParentCustomer', - 'AdminShipping' => 'AdminParentShipping', - 'AdminPreferences' => 'AdminParentPreferences', - 'AdminStats' => 'AdminParentStats', - 'AdminEmployees' => 'AdminAdmin', - ); + /** + * additionnal treatments for Tab when creating new one : + * - generate a new position + * - add access for admin profile + * + * @param bool $autodate + * @param bool $null_values + * @return int id_tab + */ + public function add($autodate = true, $null_values = false) + { + // @retrocompatibility with old menu (before 1.5.0.9) + $retro = array( + 'AdminPayment' => 'AdminParentModules', + 'AdminOrders' => 'AdminParentOrders', + 'AdminCustomers' => 'AdminParentCustomer', + 'AdminShipping' => 'AdminParentShipping', + 'AdminPreferences' => 'AdminParentPreferences', + 'AdminStats' => 'AdminParentStats', + 'AdminEmployees' => 'AdminAdmin', + ); - $class_name = Tab::getClassNameById($this->id_parent); - if (isset($retro[$class_name])) - $this->id_parent = Tab::getIdFromClassName($retro[$class_name]); - self::$_cache_tabs = array(); + $class_name = Tab::getClassNameById($this->id_parent); + if (isset($retro[$class_name])) { + $this->id_parent = Tab::getIdFromClassName($retro[$class_name]); + } + self::$_cache_tabs = array(); - // Set good position for new tab - $this->position = Tab::getNewLastPosition($this->id_parent); - $this->module = Tools::strtolower($this->module); + // Set good position for new tab + $this->position = Tab::getNewLastPosition($this->id_parent); + $this->module = Tools::strtolower($this->module); - // Add tab - if (parent::add($autodate, $null_values)) - { - //forces cache to be reloaded - self::$_getIdFromClassName = null; - return Tab::initAccess($this->id); - } - return false; - } + // Add tab + if (parent::add($autodate, $null_values)) { + //forces cache to be reloaded + self::$_getIdFromClassName = null; + return Tab::initAccess($this->id); + } + return false; + } - public function save($null_values = false, $autodate = true) - { - self::$_getIdFromClassName = null; - return parent::save(); - } + public function save($null_values = false, $autodate = true) + { + self::$_getIdFromClassName = null; + return parent::save(); + } - /** When creating a new tab $id_tab, this add default rights to the table access - * - * @todo this should not be public static but protected - * @param int $id_tab - * @param Context $context - * @return bool true if succeed - */ - public static function initAccess($id_tab, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - if (!$context->employee || !$context->employee->id_profile) - return false; + /** When creating a new tab $id_tab, this add default rights to the table access + * + * @todo this should not be public static but protected + * @param int $id_tab + * @param Context $context + * @return bool true if succeed + */ + public static function initAccess($id_tab, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + if (!$context->employee || !$context->employee->id_profile) { + return false; + } - /* Profile selection */ - $profiles = Db::getInstance()->executeS('SELECT `id_profile` FROM '._DB_PREFIX_.'profile WHERE `id_profile` != 1'); - if (!$profiles || empty($profiles)) - return true; + /* Profile selection */ + $profiles = Db::getInstance()->executeS('SELECT `id_profile` FROM '._DB_PREFIX_.'profile WHERE `id_profile` != 1'); + if (!$profiles || empty($profiles)) { + return true; + } - /* Query definition */ - $query = 'REPLACE INTO `'._DB_PREFIX_.'access` (`id_profile`, `id_tab`, `view`, `add`, `edit`, `delete`) VALUES '; - $query .= '(1, '.(int)$id_tab.', 1, 1, 1, 1),'; + /* Query definition */ + $query = 'REPLACE INTO `'._DB_PREFIX_.'access` (`id_profile`, `id_tab`, `view`, `add`, `edit`, `delete`) VALUES '; + $query .= '(1, '.(int)$id_tab.', 1, 1, 1, 1),'; - foreach ($profiles as $profile) - { - $rights = $profile['id_profile'] == $context->employee->id_profile ? 1 : 0; - $query .= '('.(int)$profile['id_profile'].', '.(int)$id_tab.', '.(int)$rights.', '.(int)$rights.', '.(int)$rights.', '.(int)$rights.'),'; - } - $query = trim($query, ', '); - return Db::getInstance()->execute($query); - } + foreach ($profiles as $profile) { + $rights = $profile['id_profile'] == $context->employee->id_profile ? 1 : 0; + $query .= '('.(int)$profile['id_profile'].', '.(int)$id_tab.', '.(int)$rights.', '.(int)$rights.', '.(int)$rights.', '.(int)$rights.'),'; + } + $query = trim($query, ', '); + return Db::getInstance()->execute($query); + } - public function delete() - { - if (Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'access WHERE `id_tab` = '.(int)$this->id) && parent::delete()) - { - if (is_array(self::$_getIdFromClassName) && isset(self::$_getIdFromClassName[strtolower($this->class_name)])) - self::$_getIdFromClassName = null; - return $this->cleanPositions($this->id_parent); - } - return false; - } + public function delete() + { + if (Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'access WHERE `id_tab` = '.(int)$this->id) && parent::delete()) { + if (is_array(self::$_getIdFromClassName) && isset(self::$_getIdFromClassName[strtolower($this->class_name)])) { + self::$_getIdFromClassName = null; + } + return $this->cleanPositions($this->id_parent); + } + return false; + } - /** - * Get tab id - * - * @return int tab id - */ - public static function getCurrentTabId() - { - $id_tab = Tab::getIdFromClassName(Tools::getValue('controller')); - // retro-compatibility 1.4/1.5 - if (empty ($id_tab)) - $id_tab = Tab::getIdFromClassName(Tools::getValue('tab')); - return $id_tab; - } + /** + * Get tab id + * + * @return int tab id + */ + public static function getCurrentTabId() + { + $id_tab = Tab::getIdFromClassName(Tools::getValue('controller')); + // retro-compatibility 1.4/1.5 + if (empty($id_tab)) { + $id_tab = Tab::getIdFromClassName(Tools::getValue('tab')); + } + return $id_tab; + } - /** - * Get tab parent id - * - * @return int tab parent id - */ - public static function getCurrentParentId() - { - $cache_id = 'getCurrentParentId_'.Tools::strtolower(Tools::getValue('controller')); - if (!Cache::isStored($cache_id)) - { - $value = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Get tab parent id + * + * @return int tab parent id + */ + public static function getCurrentParentId() + { + $cache_id = 'getCurrentParentId_'.Tools::strtolower(Tools::getValue('controller')); + if (!Cache::isStored($cache_id)) { + $value = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_parent` FROM `'._DB_PREFIX_.'tab` WHERE LOWER(class_name) = \''.pSQL(Tools::strtolower(Tools::getValue('controller'))).'\''); - if (!$value) - $value = -1; - Cache::store($cache_id, $value); - return $value; - } - return Cache::retrieve($cache_id); - } + if (!$value) { + $value = -1; + } + Cache::store($cache_id, $value); + return $value; + } + return Cache::retrieve($cache_id); + } - /** - * Get tab - * - * @return array tab - */ - public static function getTab($id_lang, $id_tab) - { - $cache_id = 'Tab::getTab_'.(int)$id_lang.'-'.(int)$id_tab; - if (!Cache::isStored($cache_id)) - { - /* Tabs selection */ - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + /** + * Get tab + * + * @return array tab + */ + public static function getTab($id_lang, $id_tab) + { + $cache_id = 'Tab::getTab_'.(int)$id_lang.'-'.(int)$id_tab; + if (!Cache::isStored($cache_id)) { + /* Tabs selection */ + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT * FROM `'._DB_PREFIX_.'tab` t LEFT JOIN `'._DB_PREFIX_.'tab_lang` tl ON (t.`id_tab` = tl.`id_tab` AND tl.`id_lang` = '.(int)$id_lang.') WHERE t.`id_tab` = '.(int)$id_tab.(defined('_PS_HOST_MODE_') ? ' AND `hide_host_mode` = 0' : '') - ); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + ); + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Return the list of tab used by a module - * - * @return array - */ - public static function getModuleTabList() - { - $list = array(); + /** + * Return the list of tab used by a module + * + * @return array + */ + public static function getModuleTabList() + { + $list = array(); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT t.`class_name`, t.`module` FROM `'._DB_PREFIX_.'tab` t WHERE t.`module` IS NOT NULL AND t.`module` != ""'); - if (is_array($result)) - foreach ($result as $detail) - $list[strtolower($detail['class_name'])] = $detail; - return $list; - } + if (is_array($result)) { + foreach ($result as $detail) { + $list[strtolower($detail['class_name'])] = $detail; + } + } + return $list; + } - /** - * Get tabs - * - * @return array tabs - */ - protected static $_cache_tabs = array(); - public static function getTabs($id_lang, $id_parent = null) - { - if (!isset(self::$_cache_tabs[$id_lang])) - { - self::$_cache_tabs[$id_lang] = array(); - // Keep t.*, tl.name instead of only * because if translations are missing, the join on tab_lang will overwrite the id_tab in the results - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * Get tabs + * + * @return array tabs + */ + protected static $_cache_tabs = array(); + public static function getTabs($id_lang, $id_parent = null) + { + if (!isset(self::$_cache_tabs[$id_lang])) { + self::$_cache_tabs[$id_lang] = array(); + // Keep t.*, tl.name instead of only * because if translations are missing, the join on tab_lang will overwrite the id_tab in the results + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT t.*, tl.name FROM `'._DB_PREFIX_.'tab` t LEFT JOIN `'._DB_PREFIX_.'tab_lang` tl ON (t.`id_tab` = tl.`id_tab` AND tl.`id_lang` = '.(int)$id_lang.') WHERE 1 '.(defined('_PS_HOST_MODE_') ? ' AND `hide_host_mode` = 0' : '').' ORDER BY t.`position` ASC' - ); + ); - if (is_array($result)) - foreach ($result as $row) - { - if (!isset(self::$_cache_tabs[$id_lang][$row['id_parent']])) - self::$_cache_tabs[$id_lang][$row['id_parent']] = array(); - self::$_cache_tabs[$id_lang][$row['id_parent']][] = $row; - } - } - if ($id_parent === null) - { - $array_all = array(); - foreach (self::$_cache_tabs[$id_lang] as $array_parent) - $array_all = array_merge($array_all, $array_parent); - return $array_all; - } + if (is_array($result)) { + foreach ($result as $row) { + if (!isset(self::$_cache_tabs[$id_lang][$row['id_parent']])) { + self::$_cache_tabs[$id_lang][$row['id_parent']] = array(); + } + self::$_cache_tabs[$id_lang][$row['id_parent']][] = $row; + } + } + } + if ($id_parent === null) { + $array_all = array(); + foreach (self::$_cache_tabs[$id_lang] as $array_parent) { + $array_all = array_merge($array_all, $array_parent); + } + return $array_all; + } - return (isset(self::$_cache_tabs[$id_lang][$id_parent]) ? self::$_cache_tabs[$id_lang][$id_parent] : array()); - } + return (isset(self::$_cache_tabs[$id_lang][$id_parent]) ? self::$_cache_tabs[$id_lang][$id_parent] : array()); + } - /** - * Get tab id from name - * - * @param string $class_name - * @return int id_tab - */ - public static function getIdFromClassName($class_name) - { - $class_name = strtolower($class_name); - if (self::$_getIdFromClassName === null) - { - self::$_getIdFromClassName = array(); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT id_tab, class_name FROM `'._DB_PREFIX_.'tab`', true, false); + /** + * Get tab id from name + * + * @param string $class_name + * @return int id_tab + */ + public static function getIdFromClassName($class_name) + { + $class_name = strtolower($class_name); + if (self::$_getIdFromClassName === null) { + self::$_getIdFromClassName = array(); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT id_tab, class_name FROM `'._DB_PREFIX_.'tab`', true, false); - if (is_array($result)) - foreach ($result as $row) - self::$_getIdFromClassName[strtolower($row['class_name'])] = $row['id_tab']; - } - return (isset(self::$_getIdFromClassName[$class_name]) ? (int)self::$_getIdFromClassName[$class_name] : false); - } + if (is_array($result)) { + foreach ($result as $row) { + self::$_getIdFromClassName[strtolower($row['class_name'])] = $row['id_tab']; + } + } + } + return (isset(self::$_getIdFromClassName[$class_name]) ? (int)self::$_getIdFromClassName[$class_name] : false); + } - /** - * Get collection from module name - * - * @param $module string Module name - * @param null $id_lang integer Language ID - * @return array|PrestaShopCollection Collection of tabs (or empty array) - */ - public static function getCollectionFromModule($module, $id_lang = null) - { - if (is_null($id_lang)) - $id_lang = Context::getContext()->language->id; + /** + * Get collection from module name + * + * @param $module string Module name + * @param null $id_lang integer Language ID + * @return array|PrestaShopCollection Collection of tabs (or empty array) + */ + public static function getCollectionFromModule($module, $id_lang = null) + { + if (is_null($id_lang)) { + $id_lang = Context::getContext()->language->id; + } - if (!Validate::isModuleName($module)) - return array(); + if (!Validate::isModuleName($module)) { + return array(); + } - $tabs = new PrestaShopCollection('Tab', (int)$id_lang); - $tabs->where('module', '=', $module); - return $tabs; - } + $tabs = new PrestaShopCollection('Tab', (int)$id_lang); + $tabs->where('module', '=', $module); + return $tabs; + } - /** - * Enabling tabs for module - * - * @param $module string Module Name - * @return bool Status - */ - public static function enablingForModule($module) - { - $tabs = Tab::getCollectionFromModule($module); - if (!empty($tabs)) - { - foreach ($tabs as $tab) - { - $tab->active = 1; - $tab->save(); - } - return true; - } - return false; - } + /** + * Enabling tabs for module + * + * @param $module string Module Name + * @return bool Status + */ + public static function enablingForModule($module) + { + $tabs = Tab::getCollectionFromModule($module); + if (!empty($tabs)) { + foreach ($tabs as $tab) { + $tab->active = 1; + $tab->save(); + } + return true; + } + return false; + } - /** - * Disabling tabs for module - * - * @param $module string Module name - * @return bool Status - */ - public static function disablingForModule($module) - { - $tabs = Tab::getCollectionFromModule($module); - if (!empty($tabs)) - { - foreach ($tabs as $tab) - { - $tab->active = 0; - $tab->save(); - } - return true; - } - return false; - } + /** + * Disabling tabs for module + * + * @param $module string Module name + * @return bool Status + */ + public static function disablingForModule($module) + { + $tabs = Tab::getCollectionFromModule($module); + if (!empty($tabs)) { + foreach ($tabs as $tab) { + $tab->active = 0; + $tab->save(); + } + return true; + } + return false; + } - /** - * Get Instance from tab class name - * - * @param $class_name string Name of tab class - * @param $id_lang integer id_lang - * @return Tab Tab object (empty if bad id or class name) - */ - public static function getInstanceFromClassName($class_name, $id_lang = null) - { - $id_tab = (int)Tab::getIdFromClassName($class_name); - return new Tab($id_tab, $id_lang); - } + /** + * Get Instance from tab class name + * + * @param $class_name string Name of tab class + * @param $id_lang integer id_lang + * @return Tab Tab object (empty if bad id or class name) + */ + public static function getInstanceFromClassName($class_name, $id_lang = null) + { + $id_tab = (int)Tab::getIdFromClassName($class_name); + return new Tab($id_tab, $id_lang); + } - public static function getNbTabs($id_parent = null) - { - return (int)Db::getInstance()->getValue(' + public static function getNbTabs($id_parent = null) + { + return (int)Db::getInstance()->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'tab` t '.(!is_null($id_parent) ? 'WHERE t.`id_parent` = '.(int)$id_parent : '') - ); - } + ); + } - /** - * return an available position in subtab for parent $id_parent - * - * @param mixed $id_parent - * @return int - */ - public static function getNewLastPosition($id_parent) - { - return (Db::getInstance()->getValue(' + /** + * return an available position in subtab for parent $id_parent + * + * @param mixed $id_parent + * @return int + */ + public static function getNewLastPosition($id_parent) + { + return (Db::getInstance()->getValue(' SELECT IFNULL(MAX(position),0)+1 FROM `'._DB_PREFIX_.'tab` WHERE `id_parent` = '.(int)$id_parent - )); - } + )); + } - public function move($direction) - { - $nb_tabs = Tab::getNbTabs($this->id_parent); - if ($direction != 'l' && $direction != 'r') - return false; - if ($nb_tabs <= 1) - return false; - if ($direction == 'l' && $this->position <= 1) - return false; - if ($direction == 'r' && $this->position >= $nb_tabs) - return false; + public function move($direction) + { + $nb_tabs = Tab::getNbTabs($this->id_parent); + if ($direction != 'l' && $direction != 'r') { + return false; + } + if ($nb_tabs <= 1) { + return false; + } + if ($direction == 'l' && $this->position <= 1) { + return false; + } + if ($direction == 'r' && $this->position >= $nb_tabs) { + return false; + } - $new_position = ($direction == 'l') ? $this->position - 1 : $this->position + 1; - Db::getInstance()->execute(' + $new_position = ($direction == 'l') ? $this->position - 1 : $this->position + 1; + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'tab` t SET position = '.(int)$this->position.' WHERE id_parent = '.(int)$this->id_parent.' AND position = '.(int)$new_position - ); - $this->position = $new_position; - return $this->update(); - } + ); + $this->position = $new_position; + return $this->update(); + } - public function cleanPositions($id_parent) - { - $result = Db::getInstance()->executeS(' + public function cleanPositions($id_parent) + { + $result = Db::getInstance()->executeS(' SELECT `id_tab` FROM `'._DB_PREFIX_.'tab` WHERE `id_parent` = '.(int)$id_parent.' ORDER BY `position` '); - $sizeof = count($result); - for ($i = 0; $i < $sizeof; ++$i) - Db::getInstance()->execute(' + $sizeof = count($result); + for ($i = 0; $i < $sizeof; ++$i) { + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'tab` SET `position` = '.($i + 1).' WHERE `id_tab` = '.(int)$result[$i]['id_tab'] - ); - return true; - } + ); + } + return true; + } - public function updatePosition($way, $position) - { - if (!$res = Db::getInstance()->executeS(' + public function updatePosition($way, $position) + { + if (!$res = Db::getInstance()->executeS(' SELECT t.`id_tab`, t.`position`, t.`id_parent` FROM `'._DB_PREFIX_.'tab` t WHERE t.`id_parent` = '.(int)$this->id_parent.' ORDER BY t.`position` ASC' - )) - return false; + )) { + return false; + } - foreach ($res as $tab) - if ((int)$tab['id_tab'] == (int)$this->id) - $moved_tab = $tab; + foreach ($res as $tab) { + if ((int)$tab['id_tab'] == (int)$this->id) { + $moved_tab = $tab; + } + } - if (!isset($moved_tab) || !isset($position)) - return false; - // < and > statements rather than BETWEEN operator - // since BETWEEN is treated differently according to databases - $result = (Db::getInstance()->execute(' + if (!isset($moved_tab) || !isset($position)) { + return false; + } + // < and > statements rather than BETWEEN operator + // since BETWEEN is treated differently according to databases + $result = (Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'tab` SET `position`= `position` '.($way ? '- 1' : '+ 1').' WHERE `position` '.($way - ? '> '.(int)$moved_tab['position'].' AND `position` <= '.(int)$position - : '< '.(int)$moved_tab['position'].' AND `position` >= '.(int)$position).' + ? '> '.(int)$moved_tab['position'].' AND `position` <= '.(int)$position + : '< '.(int)$moved_tab['position'].' AND `position` >= '.(int)$position).' AND `id_parent`='.(int)$moved_tab['id_parent']) - && Db::getInstance()->execute(' + && Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'tab` SET `position` = '.(int)$position.' WHERE `id_parent` = '.(int)$moved_tab['id_parent'].' AND `id_tab`='.(int)$moved_tab['id_tab'])); - return $result; - } + return $result; + } - public static function checkTabRights($id_tab) - { - static $tabAccesses = null; + public static function checkTabRights($id_tab) + { + static $tabAccesses = null; - if (Context::getContext()->employee->id_profile == _PS_ADMIN_PROFILE_) - return true; + if (Context::getContext()->employee->id_profile == _PS_ADMIN_PROFILE_) { + return true; + } - if ($tabAccesses === null) - $tabAccesses = Profile::getProfileAccesses(Context::getContext()->employee->id_profile); + if ($tabAccesses === null) { + $tabAccesses = Profile::getProfileAccesses(Context::getContext()->employee->id_profile); + } - if (isset($tabAccesses[(int)$id_tab]['view'])) - return ($tabAccesses[(int)$id_tab]['view'] === '1'); - return false; - } + if (isset($tabAccesses[(int)$id_tab]['view'])) { + return ($tabAccesses[(int)$id_tab]['view'] === '1'); + } + return false; + } - public static function recursiveTab($id_tab, $tabs) - { - $admin_tab = Tab::getTab((int)Context::getContext()->language->id, $id_tab); - $tabs[] = $admin_tab; - if ($admin_tab['id_parent'] > 0) - $tabs = Tab::recursiveTab($admin_tab['id_parent'], $tabs); - return $tabs; - } + public static function recursiveTab($id_tab, $tabs) + { + $admin_tab = Tab::getTab((int)Context::getContext()->language->id, $id_tab); + $tabs[] = $admin_tab; + if ($admin_tab['id_parent'] > 0) { + $tabs = Tab::recursiveTab($admin_tab['id_parent'], $tabs); + } + return $tabs; + } - /** - * Overrides update to set position to last when changing parent tab - * - * @see ObjectModel::update - * @param bool $null_values - * @return bool - */ - public function update($null_values = false) - { - $current_tab = new Tab($this->id); - if ($current_tab->id_parent != $this->id_parent) - $this->position = Tab::getNewLastPosition($this->id_parent); + /** + * Overrides update to set position to last when changing parent tab + * + * @see ObjectModel::update + * @param bool $null_values + * @return bool + */ + public function update($null_values = false) + { + $current_tab = new Tab($this->id); + if ($current_tab->id_parent != $this->id_parent) { + $this->position = Tab::getNewLastPosition($this->id_parent); + } - self::$_cache_tabs = array(); - return parent::update($null_values); - } + self::$_cache_tabs = array(); + return parent::update($null_values); + } - public static function getTabByIdProfile($id_parent, $id_profile) - { - return Db::getInstance()->executeS(' + public static function getTabByIdProfile($id_parent, $id_profile) + { + return Db::getInstance()->executeS(' SELECT t.`id_tab`, t.`id_parent`, tl.`name`, a.`id_profile` FROM `'._DB_PREFIX_.'tab` t LEFT JOIN `'._DB_PREFIX_.'access` a @@ -533,45 +550,50 @@ class TabCore extends ObjectModel '.(defined('_PS_HOST_MODE_') ? ' AND `hide_host_mode` = 0' : '').' ORDER BY t.`id_parent` ASC '); - } + } - /** - * @since 1.5.0 - */ - public static function getClassNameById($id_tab) - { - return Db::getInstance()->getValue('SELECT class_name FROM '._DB_PREFIX_.'tab WHERE id_tab = '.(int)$id_tab); - } + /** + * @since 1.5.0 + */ + public static function getClassNameById($id_tab) + { + return Db::getInstance()->getValue('SELECT class_name FROM '._DB_PREFIX_.'tab WHERE id_tab = '.(int)$id_tab); + } - public static function getTabModulesList($id_tab) - { - $modules_list = array('default_list' => array(), 'slider_list' => array()); - $xml_tab_modules_list = false; + public static function getTabModulesList($id_tab) + { + $modules_list = array('default_list' => array(), 'slider_list' => array()); + $xml_tab_modules_list = false; - if (file_exists(_PS_ROOT_DIR_.Module::CACHE_FILE_TAB_MODULES_LIST)) - $xml_tab_modules_list = @simplexml_load_file(_PS_ROOT_DIR_.Module::CACHE_FILE_TAB_MODULES_LIST); + if (file_exists(_PS_ROOT_DIR_.Module::CACHE_FILE_TAB_MODULES_LIST)) { + $xml_tab_modules_list = @simplexml_load_file(_PS_ROOT_DIR_.Module::CACHE_FILE_TAB_MODULES_LIST); + } - $class_name = null; - $display_type = 'default_list'; - if ($xml_tab_modules_list) - foreach ($xml_tab_modules_list->tab as $tab) - { - foreach ($tab->attributes() as $key => $value) - if ($key == 'class_name') - $class_name = (string)$value; + $class_name = null; + $display_type = 'default_list'; + if ($xml_tab_modules_list) { + foreach ($xml_tab_modules_list->tab as $tab) { + foreach ($tab->attributes() as $key => $value) { + if ($key == 'class_name') { + $class_name = (string)$value; + } + } - if (Tab::getIdFromClassName((string)$class_name) == $id_tab) - { - foreach ($tab->attributes() as $key => $value) - if ($key == 'display_type') - $display_type = (string)$value; + if (Tab::getIdFromClassName((string)$class_name) == $id_tab) { + foreach ($tab->attributes() as $key => $value) { + if ($key == 'display_type') { + $display_type = (string)$value; + } + } - foreach ($tab->children() as $module) - $modules_list[$display_type][(int)$module['position']] = (string)$module['name']; - ksort($modules_list[$display_type]); - } - } + foreach ($tab->children() as $module) { + $modules_list[$display_type][(int)$module['position']] = (string)$module['name']; + } + ksort($modules_list[$display_type]); + } + } + } - return $modules_list; - } + return $modules_list; + } } diff --git a/classes/Tag.php b/classes/Tag.php index cd970aae..f5eb41c8 100644 --- a/classes/Tag.php +++ b/classes/Tag.php @@ -26,117 +26,119 @@ class TagCore extends ObjectModel { - /** @var int Language id */ - public $id_lang; + /** @var int Language id */ + public $id_lang; - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'tag', - 'primary' => 'id_tag', - 'fields' => array( - 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'tag', + 'primary' => 'id_tag', + 'fields' => array( + 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_lang' => array('xlink_resource' => 'languages'), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_lang' => array('xlink_resource' => 'languages'), + ), + ); - public function __construct($id = null, $name = null, $id_lang = null) - { - $this->def = Tag::getDefinition($this); - $this->setDefinitionRetrocompatibility(); + public function __construct($id = null, $name = null, $id_lang = null) + { + $this->def = Tag::getDefinition($this); + $this->setDefinitionRetrocompatibility(); - if ($id) - parent::__construct($id); - elseif ($name && Validate::isGenericName($name) && $id_lang && Validate::isUnsignedId($id_lang)) - { - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + if ($id) { + parent::__construct($id); + } elseif ($name && Validate::isGenericName($name) && $id_lang && Validate::isUnsignedId($id_lang)) { + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT * FROM `'._DB_PREFIX_.'tag` t WHERE `name` = \''.pSQL($name).'\' AND `id_lang` = '.(int)$id_lang); - if ($row) - { - $this->id = (int)$row['id_tag']; - $this->id_lang = (int)$row['id_lang']; - $this->name = $row['name']; - } - } - } + if ($row) { + $this->id = (int)$row['id_tag']; + $this->id_lang = (int)$row['id_lang']; + $this->name = $row['name']; + } + } + } - public function add($autodate = true, $null_values = false) - { - if (!parent::add($autodate, $null_values)) - return false; - elseif (isset($_POST['products'])) - return $this->setProducts(Tools::getValue('products')); - return true; - } + public function add($autodate = true, $null_values = false) + { + if (!parent::add($autodate, $null_values)) { + return false; + } elseif (isset($_POST['products'])) { + return $this->setProducts(Tools::getValue('products')); + } + return true; + } - /** - * Add several tags in database and link it to a product - * - * @param int $id_lang Language id - * @param int $id_product Product id to link tags with - * @param string|array $tag_list List of tags, as array or as a string with comas - * @return bool Operation success - */ - public static function addTags($id_lang, $id_product, $tag_list, $separator = ',') - { - if (!Validate::isUnsignedId($id_lang)) - return false; + /** + * Add several tags in database and link it to a product + * + * @param int $id_lang Language id + * @param int $id_product Product id to link tags with + * @param string|array $tag_list List of tags, as array or as a string with comas + * @return bool Operation success + */ + public static function addTags($id_lang, $id_product, $tag_list, $separator = ',') + { + if (!Validate::isUnsignedId($id_lang)) { + return false; + } - if (!is_array($tag_list)) - $tag_list = array_filter(array_unique(array_map('trim', preg_split('#\\'.$separator.'#', $tag_list, null, PREG_SPLIT_NO_EMPTY)))); + if (!is_array($tag_list)) { + $tag_list = array_filter(array_unique(array_map('trim', preg_split('#\\'.$separator.'#', $tag_list, null, PREG_SPLIT_NO_EMPTY)))); + } - $list = array(); - if (is_array($tag_list)) - foreach ($tag_list as $tag) - { - if (!Validate::isGenericName($tag)) - return false; - $tag = trim(Tools::substr($tag, 0, self::$definition['fields']['name']['size'])); - $tag_obj = new Tag(null, $tag, (int)$id_lang); + $list = array(); + if (is_array($tag_list)) { + foreach ($tag_list as $tag) { + if (!Validate::isGenericName($tag)) { + return false; + } + $tag = trim(Tools::substr($tag, 0, self::$definition['fields']['name']['size'])); + $tag_obj = new Tag(null, $tag, (int)$id_lang); - /* Tag does not exist in database */ - if (!Validate::isLoadedObject($tag_obj)) - { - $tag_obj->name = $tag; - $tag_obj->id_lang = (int)$id_lang; - $tag_obj->add(); - } - if (!in_array($tag_obj->id, $list)) - $list[] = $tag_obj->id; - } - $data = ''; - foreach ($list as $tag) - $data .= '('.(int)$tag.','.(int)$id_product.','.(int)$id_lang.'),'; - $data = rtrim($data, ','); + /* Tag does not exist in database */ + if (!Validate::isLoadedObject($tag_obj)) { + $tag_obj->name = $tag; + $tag_obj->id_lang = (int)$id_lang; + $tag_obj->add(); + } + if (!in_array($tag_obj->id, $list)) { + $list[] = $tag_obj->id; + } + } + } + $data = ''; + foreach ($list as $tag) { + $data .= '('.(int)$tag.','.(int)$id_product.','.(int)$id_lang.'),'; + } + $data = rtrim($data, ','); - $result = Db::getInstance()->execute(' + $result = Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'product_tag` (`id_tag`, `id_product`, `id_lang`) VALUES '.$data); - self::updateTagCount(); + self::updateTagCount(); - return $result; - } + return $result; + } - public static function updateTagCount() - { - if (!Module::getBatchMode()) - { - Db::getInstance()->execute('REPLACE INTO `'._DB_PREFIX_.'tag_count` (id_group, id_tag, id_lang, id_shop, counter) + public static function updateTagCount() + { + if (!Module::getBatchMode()) { + Db::getInstance()->execute('REPLACE INTO `'._DB_PREFIX_.'tag_count` (id_group, id_tag, id_lang, id_shop, counter) SELECT cg.id_group, t.id_tag, t.id_lang, ps.id_shop, COUNT(pt.id_tag) AS times FROM `'._DB_PREFIX_.'product_tag` pt LEFT JOIN `'._DB_PREFIX_.'tag` t ON (t.id_tag = pt.id_tag) @@ -151,7 +153,7 @@ class TagCore extends ObjectModel WHERE cgo.`id_group` = cg.id_group AND p.`id_product` = cp.`id_product`) AND product_shop.id_shop = ps.id_shop GROUP BY pt.id_tag, cg.id_group'); - Db::getInstance()->execute('REPLACE INTO `'._DB_PREFIX_.'tag_count` (id_group, id_tag, id_lang, id_shop, counter) + Db::getInstance()->execute('REPLACE INTO `'._DB_PREFIX_.'tag_count` (id_group, id_tag, id_lang, id_shop, counter) SELECT 0, t.id_tag, t.id_lang, ps.id_shop, COUNT(pt.id_tag) AS times FROM `'._DB_PREFIX_.'product_tag` pt LEFT JOIN `'._DB_PREFIX_.'tag` t ON (t.id_tag = pt.id_tag) @@ -162,16 +164,15 @@ class TagCore extends ObjectModel WHERE pt.`id_lang` = 1 AND product_shop.`active` = 1 AND product_shop.id_shop = ps.id_shop GROUP BY pt.id_tag'); - } - } + } + } - public static function getMainTags($id_lang, $nb = 10) - { - $context = Context::getContext(); - if (Group::isFeatureActive()) - { - $groups = FrontController::getCurrentCustomerGroups(); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getMainTags($id_lang, $nb = 10) + { + $context = Context::getContext(); + if (Group::isFeatureActive()) { + $groups = FrontController::getCurrentCustomerGroups(); + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT t.name, counter AS times FROM `'._DB_PREFIX_.'tag_count` pt LEFT JOIN `'._DB_PREFIX_.'tag` t ON (t.id_tag = pt.id_tag) @@ -179,44 +180,46 @@ class TagCore extends ObjectModel AND pt.`id_lang` = '.(int)$id_lang.' AND pt.`id_shop` = '.(int)$context->shop->id.' ORDER BY times DESC LIMIT '.(int)$nb); - } - else - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + } else { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT t.name, counter AS times FROM `'._DB_PREFIX_.'tag_count` pt LEFT JOIN `'._DB_PREFIX_.'tag` t ON (t.id_tag = pt.id_tag) WHERE pt.id_group = 0 AND pt.`id_lang` = '.(int)$id_lang.' AND pt.`id_shop` = '.(int)$context->shop->id.' ORDER BY times DESC LIMIT '.(int)$nb); - } - } + } + } - public static function getProductTags($id_product) - { - if (!$tmp = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getProductTags($id_product) + { + if (!$tmp = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT t.`id_lang`, t.`name` FROM '._DB_PREFIX_.'tag t LEFT JOIN '._DB_PREFIX_.'product_tag pt ON (pt.id_tag = t.id_tag) - WHERE pt.`id_product`='.(int)$id_product)) - return false; - $result = array(); - foreach ($tmp as $tag) - $result[$tag['id_lang']][] = $tag['name']; - return $result; - } + WHERE pt.`id_product`='.(int)$id_product)) { + return false; + } + $result = array(); + foreach ($tmp as $tag) { + $result[$tag['id_lang']][] = $tag['name']; + } + return $result; + } - public function getProducts($associated = true, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - $id_lang = $this->id_lang ? $this->id_lang : $context->language->id; + public function getProducts($associated = true, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + $id_lang = $this->id_lang ? $this->id_lang : $context->language->id; - if (!$this->id && $associated) - return array(); + if (!$this->id && $associated) { + return array(); + } - $in = $associated ? 'IN' : 'NOT IN'; - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $in = $associated ? 'IN' : 'NOT IN'; + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT pl.name, pl.id_product FROM `'._DB_PREFIX_.'product` p LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON p.id_product = pl.id_product'.Shop::addSqlRestrictionOnLang('pl').' @@ -225,34 +228,34 @@ class TagCore extends ObjectModel AND product_shop.active = 1 '.($this->id ? ('AND p.id_product '.$in.' (SELECT pt.id_product FROM `'._DB_PREFIX_.'product_tag` pt WHERE pt.id_tag = '.(int)$this->id.')') : '').' ORDER BY pl.name'); - } + } - public function setProducts($array) - { - $result = Db::getInstance()->delete('product_tag', 'id_tag = '.(int)$this->id); - if (is_array($array)) - { - $array = array_map('intval', $array); - $result &= ObjectModel::updateMultishopTable('Product', array('indexed' => 0), 'a.id_product IN ('.implode(',', $array).')'); - $ids = array(); - foreach ($array as $id_product) - $ids[] = '('.(int)$id_product.','.(int)$this->id.','.(int)$this->id_lang.')'; + public function setProducts($array) + { + $result = Db::getInstance()->delete('product_tag', 'id_tag = '.(int)$this->id); + if (is_array($array)) { + $array = array_map('intval', $array); + $result &= ObjectModel::updateMultishopTable('Product', array('indexed' => 0), 'a.id_product IN ('.implode(',', $array).')'); + $ids = array(); + foreach ($array as $id_product) { + $ids[] = '('.(int)$id_product.','.(int)$this->id.','.(int)$this->id_lang.')'; + } - if ($result) - { - $result &= Db::getInstance()->execute('INSERT INTO '._DB_PREFIX_.'product_tag (id_product, id_tag, id_lang) VALUES '.implode(',', $ids)); - if (Configuration::get('PS_SEARCH_INDEXATION')) - $result &= Search::indexation(false); - } - } - self::updateTagCount(); - return $result; - } + if ($result) { + $result &= Db::getInstance()->execute('INSERT INTO '._DB_PREFIX_.'product_tag (id_product, id_tag, id_lang) VALUES '.implode(',', $ids)); + if (Configuration::get('PS_SEARCH_INDEXATION')) { + $result &= Search::indexation(false); + } + } + } + self::updateTagCount(); + return $result; + } - public static function deleteTagsForProduct($id_product) - { - $result = Db::getInstance()->delete('product_tag', 'id_product = '.(int)$id_product); - self::updateTagCount(); - return $result; - } + public static function deleteTagsForProduct($id_product) + { + $result = Db::getInstance()->delete('product_tag', 'id_product = '.(int)$id_product); + self::updateTagCount(); + return $result; + } } diff --git a/classes/Theme.php b/classes/Theme.php index f77d4bfc..e4a8e1e3 100644 --- a/classes/Theme.php +++ b/classes/Theme.php @@ -26,268 +26,269 @@ class ThemeCore extends ObjectModel { - public $name; - public $directory; - public $responsive; - public $default_left_column; - public $default_right_column; - public $product_per_page; + public $name; + public $directory; + public $responsive; + public $default_left_column; + public $default_right_column; + public $product_per_page; - const CACHE_FILE_CUSTOMER_THEMES_LIST = '/config/xml/customer_themes_list.xml'; + const CACHE_FILE_CUSTOMER_THEMES_LIST = '/config/xml/customer_themes_list.xml'; - const CACHE_FILE_MUST_HAVE_THEMES_LIST = '/config/xml/must_have_themes_list.xml'; + const CACHE_FILE_MUST_HAVE_THEMES_LIST = '/config/xml/must_have_themes_list.xml'; - const UPLOADED_THEME_DIR_NAME = 'uploaded'; + const UPLOADED_THEME_DIR_NAME = 'uploaded'; - /** @var int access rights of created folders (octal) */ - public static $access_rights = 0775; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'theme', - 'primary' => 'id_theme', - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 64, 'required' => true), - 'directory' => array('type' => self::TYPE_STRING, 'validate' => 'isDirName', 'size' => 64, 'required' => true), - 'responsive' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'default_left_column' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'default_right_column' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'product_per_page' => array('type' => self::TYPE_INT, 'validate' => 'isInt') - ), - ); + /** @var int access rights of created folders (octal) */ + public static $access_rights = 0775; + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'theme', + 'primary' => 'id_theme', + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 64, 'required' => true), + 'directory' => array('type' => self::TYPE_STRING, 'validate' => 'isDirName', 'size' => 64, 'required' => true), + 'responsive' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'default_left_column' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'default_right_column' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'product_per_page' => array('type' => self::TYPE_INT, 'validate' => 'isInt') + ), + ); - public static function getThemes() - { - $themes = new PrestaShopCollection('Theme'); - $themes->orderBy('name'); - return $themes; - } + public static function getThemes() + { + $themes = new PrestaShopCollection('Theme'); + $themes->orderBy('name'); + return $themes; + } - public static function getAllThemes($excluded_ids = false) - { - $themes = new PrestaShopCollection('Theme'); + public static function getAllThemes($excluded_ids = false) + { + $themes = new PrestaShopCollection('Theme'); - if (is_array($excluded_ids) && !empty($excluded_ids)) - $themes->where('id_theme', 'notin', $excluded_ids); + if (is_array($excluded_ids) && !empty($excluded_ids)) { + $themes->where('id_theme', 'notin', $excluded_ids); + } - $themes->orderBy('name'); - return $themes; - } + $themes->orderBy('name'); + return $themes; + } - /** - * return an array of all available theme (installed or not) - * - * @param bool $installed_only - * @return array string (directory) - */ - public static function getAvailable($installed_only = true) - { - static $dirlist = array(); - $available_theme = array(); + /** + * return an array of all available theme (installed or not) + * + * @param bool $installed_only + * @return array string (directory) + */ + public static function getAvailable($installed_only = true) + { + static $dirlist = array(); + $available_theme = array(); - if (empty($dirlist)) - { - $themes = scandir(_PS_ALL_THEMES_DIR_); - foreach ($themes as $theme) - if (is_dir(_PS_ALL_THEMES_DIR_.DIRECTORY_SEPARATOR.$theme) && $theme[0] != '.') - $dirlist[] = $theme; - } + if (empty($dirlist)) { + $themes = scandir(_PS_ALL_THEMES_DIR_); + foreach ($themes as $theme) { + if (is_dir(_PS_ALL_THEMES_DIR_.DIRECTORY_SEPARATOR.$theme) && $theme[0] != '.') { + $dirlist[] = $theme; + } + } + } - if ($installed_only) - { - $themes = Theme::getThemes(); - foreach ($themes as $theme_obj) - { - /** @var Theme $theme_obj */ - $themes_dir[] = $theme_obj->directory; - } + if ($installed_only) { + $themes = Theme::getThemes(); + foreach ($themes as $theme_obj) { + /** @var Theme $theme_obj */ + $themes_dir[] = $theme_obj->directory; + } - foreach ($dirlist as $theme) - if (false !== array_search($theme, $themes_dir)) - $available_theme[] = $theme; - } - else - $available_theme = $dirlist; + foreach ($dirlist as $theme) { + if (false !== array_search($theme, $themes_dir)) { + $available_theme[] = $theme; + } + } + } else { + $available_theme = $dirlist; + } - return $available_theme; + return $available_theme; + } - } - - /** - * check if a theme is used by a shop - * - * @return bool - */ - public function isUsed() - { - return Db::getInstance()->getValue('SELECT count(*) + /** + * check if a theme is used by a shop + * + * @return bool + */ + public function isUsed() + { + return Db::getInstance()->getValue('SELECT count(*) FROM '._DB_PREFIX_.'shop WHERE id_theme = '.(int)$this->id); - } + } - /** - * add only theme if the directory exists - * - * @param bool $null_values - * @param bool $autodate - * @return bool Insertion result - */ - public function add($autodate = true, $null_values = false) - { - if (!is_dir(_PS_ALL_THEMES_DIR_.$this->directory)) - return false; + /** + * add only theme if the directory exists + * + * @param bool $null_values + * @param bool $autodate + * @return bool Insertion result + */ + public function add($autodate = true, $null_values = false) + { + if (!is_dir(_PS_ALL_THEMES_DIR_.$this->directory)) { + return false; + } - return parent::add($autodate, $null_values); - } + return parent::add($autodate, $null_values); + } - /** - * Checks if theme exists (by folder) and returns Theme object. - * - * @param string $directory - * - * @return bool|Theme - */ - public static function getByDirectory($directory) - { - if (is_string($directory) && strlen($directory) > 0 && file_exists(_PS_ALL_THEMES_DIR_.$directory) && is_dir(_PS_ALL_THEMES_DIR_.$directory)) - { - $id_theme = (int)Db::getInstance()->getValue('SELECT id_theme FROM '._DB_PREFIX_.'theme WHERE directory="'.pSQL($directory).'"'); + /** + * Checks if theme exists (by folder) and returns Theme object. + * + * @param string $directory + * + * @return bool|Theme + */ + public static function getByDirectory($directory) + { + if (is_string($directory) && strlen($directory) > 0 && file_exists(_PS_ALL_THEMES_DIR_.$directory) && is_dir(_PS_ALL_THEMES_DIR_.$directory)) { + $id_theme = (int)Db::getInstance()->getValue('SELECT id_theme FROM '._DB_PREFIX_.'theme WHERE directory="'.pSQL($directory).'"'); - return $id_theme ? new Theme($id_theme) : false; - } + return $id_theme ? new Theme($id_theme) : false; + } - return false; - } + return false; + } - public static function getInstalledThemeDirectories() - { - $list = array(); - $tmp = Db::getInstance()->executeS('SELECT `directory` FROM '._DB_PREFIX_.'theme'); - foreach ($tmp as $t) - $list[] = $t['directory']; + public static function getInstalledThemeDirectories() + { + $list = array(); + $tmp = Db::getInstance()->executeS('SELECT `directory` FROM '._DB_PREFIX_.'theme'); + foreach ($tmp as $t) { + $list[] = $t['directory']; + } - return $list; - } + return $list; + } - public static function getThemeInfo($id_theme) - { - $theme = new Theme((int)$id_theme); - $theme_arr = array(); + public static function getThemeInfo($id_theme) + { + $theme = new Theme((int)$id_theme); + $theme_arr = array(); - if (file_exists(_PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml')) - $config_file = _PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml'; - elseif ($theme->name == 'default-bootstrap') - $config_file = _PS_ROOT_DIR_.'/config/xml/themes/default.xml'; - else - $config_file = false; + if (file_exists(_PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml')) { + $config_file = _PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml'; + } elseif ($theme->name == 'default-bootstrap') { + $config_file = _PS_ROOT_DIR_.'/config/xml/themes/default.xml'; + } else { + $config_file = false; + } - if ($config_file) - { - $theme_arr['theme_id'] = (int)$theme->id; - $xml_theme = @simplexml_load_file($config_file); + if ($config_file) { + $theme_arr['theme_id'] = (int)$theme->id; + $xml_theme = @simplexml_load_file($config_file); - if ($xml_theme !== false) - { - foreach ($xml_theme->attributes() as $key => $value) - $theme_arr['theme_'.$key] = (string)$value; + if ($xml_theme !== false) { + foreach ($xml_theme->attributes() as $key => $value) { + $theme_arr['theme_'.$key] = (string)$value; + } - foreach ($xml_theme->author->attributes() as $key => $value) - $theme_arr['author_'.$key] = (string)$value; + foreach ($xml_theme->author->attributes() as $key => $value) { + $theme_arr['author_'.$key] = (string)$value; + } - if ($theme_arr['theme_name'] == 'default-bootstrap') - $theme_arr['tc'] = Module::isEnabled('themeconfigurator'); - } - } - else - { - // If no xml we use data from database - $theme_arr['theme_id'] = (int)$theme->id; - $theme_arr['theme_name'] = $theme->name; - $theme_arr['theme_directory'] = $theme->directory; - } + if ($theme_arr['theme_name'] == 'default-bootstrap') { + $theme_arr['tc'] = Module::isEnabled('themeconfigurator'); + } + } + } else { + // If no xml we use data from database + $theme_arr['theme_id'] = (int)$theme->id; + $theme_arr['theme_name'] = $theme->name; + $theme_arr['theme_directory'] = $theme->directory; + } - return $theme_arr; - } + return $theme_arr; + } - public static function getNonInstalledTheme() - { - $installed_theme_directories = Theme::getInstalledThemeDirectories(); - $not_installed_theme = array(); - foreach (glob(_PS_ALL_THEMES_DIR_.'*', GLOB_ONLYDIR) as $theme_dir) - { - $dir = basename($theme_dir); - $config_file = _PS_ALL_THEMES_DIR_.$dir.'/config.xml'; - if (!in_array($dir, $installed_theme_directories) && @filemtime($config_file)) - { - if ($xml_theme = @simplexml_load_file($config_file)) - { - $theme = array(); - foreach ($xml_theme->attributes() as $key => $value) - $theme[$key] = (string)$value; + public static function getNonInstalledTheme() + { + $installed_theme_directories = Theme::getInstalledThemeDirectories(); + $not_installed_theme = array(); + foreach (glob(_PS_ALL_THEMES_DIR_.'*', GLOB_ONLYDIR) as $theme_dir) { + $dir = basename($theme_dir); + $config_file = _PS_ALL_THEMES_DIR_.$dir.'/config.xml'; + if (!in_array($dir, $installed_theme_directories) && @filemtime($config_file)) { + if ($xml_theme = @simplexml_load_file($config_file)) { + $theme = array(); + foreach ($xml_theme->attributes() as $key => $value) { + $theme[$key] = (string)$value; + } - if (!empty($theme)) - $not_installed_theme[] = $theme; - } - } - } + if (!empty($theme)) { + $not_installed_theme[] = $theme; + } + } + } + } - return $not_installed_theme; - } + return $not_installed_theme; + } - /** - * update the table PREFIX_theme_meta for the current theme - * @param array $metas - * @param bool $full_update If true, all the meta of the theme will be deleted prior the insert, otherwise only the current $metas will be deleted - * - */ - public function updateMetas($metas, $full_update = false) - { - if ($full_update) - Db::getInstance()->delete('theme_meta', 'id_theme='.(int)$this->id); + /** + * update the table PREFIX_theme_meta for the current theme + * @param array $metas + * @param bool $full_update If true, all the meta of the theme will be deleted prior the insert, otherwise only the current $metas will be deleted + * + */ + public function updateMetas($metas, $full_update = false) + { + if ($full_update) { + Db::getInstance()->delete('theme_meta', 'id_theme='.(int)$this->id); + } - $values = array(); - if ($this->id > 0) - { - foreach ($metas as $meta) - { - if (!$full_update) - Db::getInstance()->delete('theme_meta', 'id_theme='.(int)$this->id.' AND id_meta='.(int)$meta['id_meta']); + $values = array(); + if ($this->id > 0) { + foreach ($metas as $meta) { + if (!$full_update) { + Db::getInstance()->delete('theme_meta', 'id_theme='.(int)$this->id.' AND id_meta='.(int)$meta['id_meta']); + } - $values[] = array( - 'id_theme' => (int)$this->id, - 'id_meta' => (int)$meta['id_meta'], - 'left_column' => (int)$meta['left'], - 'right_column' => (int)$meta['right'] - ); - } - Db::getInstance()->insert('theme_meta', $values); - } - } + $values[] = array( + 'id_theme' => (int)$this->id, + 'id_meta' => (int)$meta['id_meta'], + 'left_column' => (int)$meta['left'], + 'right_column' => (int)$meta['right'] + ); + } + Db::getInstance()->insert('theme_meta', $values); + } + } - public function hasColumns($page) - { - return Db::getInstance()->getRow(' + public function hasColumns($page) + { + return Db::getInstance()->getRow(' SELECT IFNULL(left_column, default_left_column) as left_column, IFNULL(right_column, default_right_column) as right_column FROM '._DB_PREFIX_.'theme t LEFT JOIN '._DB_PREFIX_.'theme_meta tm ON (t.id_theme = tm.id_theme) LEFT JOIN '._DB_PREFIX_.'meta m ON (m.id_meta = tm.id_meta) WHERE t.id_theme ='.(int)$this->id.' AND m.page = "'.pSQL($page).'"'); - } + } - public function hasColumnsSettings($page) - { - return (bool)Db::getInstance()->getValue(' + public function hasColumnsSettings($page) + { + return (bool)Db::getInstance()->getValue(' SELECT m.`id_meta` FROM '._DB_PREFIX_.'theme t LEFT JOIN '._DB_PREFIX_.'theme_meta tm ON (t.id_theme = tm.id_theme) LEFT JOIN '._DB_PREFIX_.'meta m ON (m.id_meta = tm.id_meta) WHERE t.id_theme ='.(int)$this->id.' AND m.page = "'.pSQL($page).'"'); - } + } - public function hasLeftColumn($page = null) - { - return (bool)Db::getInstance()->getValue( - 'SELECT IFNULL( + public function hasLeftColumn($page = null) + { + return (bool)Db::getInstance()->getValue( + 'SELECT IFNULL( ( SELECT left_column FROM '._DB_PREFIX_.'theme t @@ -298,13 +299,13 @@ class ThemeCore extends ObjectModel ) FROM '._DB_PREFIX_.'theme WHERE id_theme ='.(int)$this->id - ); - } + ); + } - public function hasRightColumn($page = null) - { - return (bool)Db::getInstance()->getValue( - 'SELECT IFNULL( + public function hasRightColumn($page = null) + { + return (bool)Db::getInstance()->getValue( + 'SELECT IFNULL( ( SELECT right_column FROM '._DB_PREFIX_.'theme t @@ -315,67 +316,72 @@ class ThemeCore extends ObjectModel ) FROM '._DB_PREFIX_.'theme WHERE id_theme ='.(int)$this->id); - } + } - /** - * @return array|bool - */ - public function getMetas() - { - if (!Validate::isUnsignedId($this->id) || $this->id == 0) - return false; + /** + * @return array|bool + */ + public function getMetas() + { + if (!Validate::isUnsignedId($this->id) || $this->id == 0) { + return false; + } - return Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'theme_meta WHERE id_theme = '.(int)$this->id); - } + return Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'theme_meta WHERE id_theme = '.(int)$this->id); + } - /** - * @return bool - */ - public function removeMetas() - { - if (!Validate::isUnsignedId($this->id) || $this->id == 0) - return false; + /** + * @return bool + */ + public function removeMetas() + { + if (!Validate::isUnsignedId($this->id) || $this->id == 0) { + return false; + } - return Db::getInstance()->delete('theme_meta', 'id_theme = '.(int)$this->id); - } + return Db::getInstance()->delete('theme_meta', 'id_theme = '.(int)$this->id); + } - public function toggleResponsive() - { - // Object must have a variable called 'responsive' - if (!array_key_exists('responsive', $this)) - throw new PrestaShopException('property "responsive" is missing in object '.get_class($this)); + public function toggleResponsive() + { + // Object must have a variable called 'responsive' + if (!array_key_exists('responsive', $this)) { + throw new PrestaShopException('property "responsive" is missing in object '.get_class($this)); + } - // Update only responsive field - $this->setFieldsToUpdate(array('responsive' => true)); + // Update only responsive field + $this->setFieldsToUpdate(array('responsive' => true)); - // Update active responsive on object - $this->responsive = !(int)$this->responsive; + // Update active responsive on object + $this->responsive = !(int)$this->responsive; - // Change responsive to active/inactive - return $this->update(false); - } + // Change responsive to active/inactive + return $this->update(false); + } - public function toggleDefaultLeftColumn() - { - if (!array_key_exists('default_left_column', $this)) - throw new PrestaShopException('property "default_left_column" is missing in object '.get_class($this)); + public function toggleDefaultLeftColumn() + { + if (!array_key_exists('default_left_column', $this)) { + throw new PrestaShopException('property "default_left_column" is missing in object '.get_class($this)); + } - $this->setFieldsToUpdate(array('default_left_column' => true)); + $this->setFieldsToUpdate(array('default_left_column' => true)); - $this->default_left_column = !(int)$this->default_left_column; + $this->default_left_column = !(int)$this->default_left_column; - return $this->update(false); - } + return $this->update(false); + } - public function toggleDefaultRightColumn() - { - if (!array_key_exists('default_right_column', $this)) - throw new PrestaShopException('property "default_right_column" is missing in object '.get_class($this)); + public function toggleDefaultRightColumn() + { + if (!array_key_exists('default_right_column', $this)) { + throw new PrestaShopException('property "default_right_column" is missing in object '.get_class($this)); + } - $this->setFieldsToUpdate(array('default_right_column' => true)); + $this->setFieldsToUpdate(array('default_right_column' => true)); - $this->default_right_column = !(int)$this->default_right_column; + $this->default_right_column = !(int)$this->default_right_column; - return $this->update(false); - } + return $this->update(false); + } } diff --git a/classes/Tools.php b/classes/Tools.php index f2123a56..27f0f1fb 100644 --- a/classes/Tools.php +++ b/classes/Tools.php @@ -26,1217 +26,1267 @@ class ToolsCore { - protected static $file_exists_cache = array(); - protected static $_forceCompile; - protected static $_caching; - protected static $_user_plateform; - protected static $_user_browser; - - public static $round_mode = null; - - /** - * Random password generator - * - * @param int $length Desired length (optional) - * @param string $flag Output type (NUMERIC, ALPHANUMERIC, NO_NUMERIC, RANDOM) - * @return bool|string Password - */ - public static function passwdGen($length = 8, $flag = 'ALPHANUMERIC') - { - $length = (int)$length; - - if ($length <= 0) - return false; - - switch ($flag) - { - case 'NUMERIC': - $str = '0123456789'; - break; - case 'NO_NUMERIC': - $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - break; - case 'RANDOM': - $num_bytes = ceil($length * 0.75); - $bytes = self::getBytes($num_bytes); - return substr(rtrim(base64_encode($bytes), '='), 0, $length); - case 'ALPHANUMERIC': - default: - $str = 'abcdefghijkmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - break; - } - - $bytes = Tools::getBytes($length); - $position = 0; - $result = ''; - - for ($i = 0; $i < $length; $i++) - { - $position = ($position + ord($bytes[$i])) % strlen($str); - $result .= $str[$position]; - } - - return $result; - } - - /** - * Random bytes generator - * - * Thanks to Zend for entropy - * - * @param $length Desired length of random bytes - * @return bool|string Random bytes - */ - public static function getBytes($length) - { - $length = (int)$length; - - if ($length <= 0) - return false; - - if (function_exists('openssl_random_pseudo_bytes')) - { - $bytes = openssl_random_pseudo_bytes($length, $crypto_strong); - - if ($crypto_strong === true) - return $bytes; - } - - if (function_exists('mcrypt_create_iv')) - { - $bytes = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); - - if ($bytes !== false && strlen($bytes) === $length) - return $bytes; - } - - // Else try to get $length bytes of entropy. - // Thanks to Zend - - $result = ''; - $entropy = ''; - $msec_per_round = 400; - $bits_per_round = 2; - $total = $length; - $hash_length = 20; - - while (strlen($result) < $length) - { - $bytes = ($total > $hash_length) ? $hash_length : $total; - $total -= $bytes; - - for ($i=1; $i < 3; $i++) - { - $t1 = microtime(true); - $seed = mt_rand(); - - for ($j=1; $j < 50; $j++) - $seed = sha1($seed); - - $t2 = microtime(true); - $entropy .= $t1 . $t2; - } - - $div = (int) (($t2 - $t1) * 1000000); - - if ($div <= 0) - $div = 400; - - $rounds = (int) ($msec_per_round * 50 / $div); - $iter = $bytes * (int) (ceil(8 / $bits_per_round)); - - for ($i = 0; $i < $iter; $i ++) - { - $t1 = microtime(); - $seed = sha1(mt_rand()); - - for ($j = 0; $j < $rounds; $j++) - $seed = sha1($seed); - - $t2 = microtime(); - $entropy .= $t1 . $t2; - } - - $result .= sha1($entropy, true); - } - - return substr($result, 0, $length); - } - - public static function strReplaceFirst($search, $replace, $subject, $cur = 0) - { - return (strpos($subject, $search, $cur))?substr_replace($subject, $replace, (int)strpos($subject, $search, $cur), strlen($search)):$subject; - } - - /** - * Redirect user to another page - * - * @param string $url Desired URL - * @param string $base_uri Base URI (optional) - * @param Link $link - * @param string|array $headers A list of headers to send before redirection - */ - public static function redirect($url, $base_uri = __PS_BASE_URI__, Link $link = null, $headers = null) - { - if (!$link) - $link = Context::getContext()->link; - - if (strpos($url, 'http://') === false && strpos($url, 'https://') === false && $link) - { - if (strpos($url, $base_uri) === 0) - $url = substr($url, strlen($base_uri)); - if (strpos($url, 'index.php?controller=') !== false && strpos($url, 'index.php/') == 0) - { - $url = substr($url, strlen('index.php?controller=')); - if (Configuration::get('PS_REWRITING_SETTINGS')) - $url = Tools::strReplaceFirst('&', '?', $url); - } - - $explode = explode('?', $url); - // don't use ssl if url is home page - // used when logout for example - $use_ssl = !empty($url); - $url = $link->getPageLink($explode[0], $use_ssl); - if (isset($explode[1])) - $url .= '?'.$explode[1]; - } - - // Send additional headers - if ($headers) - { - if (!is_array($headers)) - $headers = array($headers); - - foreach ($headers as $header) - header($header); - } - - header('Location: '.$url); - exit; - } - - /** - * Redirect URLs already containing PS_BASE_URI - * - * @param string $url Desired URL - */ - public static function redirectLink($url) - { - if (!preg_match('@^https?://@i', $url)) - { - if (strpos($url, __PS_BASE_URI__) !== false && strpos($url, __PS_BASE_URI__) == 0) - $url = substr($url, strlen(__PS_BASE_URI__)); - if (strpos($url, 'index.php?controller=') !== false && strpos($url, 'index.php/') == 0) - $url = substr($url, strlen('index.php?controller=')); - $explode = explode('?', $url); - $url = Context::getContext()->link->getPageLink($explode[0]); - if (isset($explode[1])) - $url .= '?'.$explode[1]; - } - header('Location: '.$url); - exit; - } - - /** - * Redirect user to another admin page - * - * @param string $url Desired URL - */ - public static function redirectAdmin($url) - { - header('Location: '.$url); - exit; - } - - /** - * getShopProtocol return the available protocol for the current shop in use - * SSL if Configuration is set on and available for the server - * - * @return String - */ - public static function getShopProtocol() - { - $protocol = (Configuration::get('PS_SSL_ENABLED') || (!empty($_SERVER['HTTPS']) - && Tools::strtolower($_SERVER['HTTPS']) != 'off')) ? 'https://' : 'http://'; - return $protocol; - } - - /** - * getProtocol return the set protocol according to configuration (http[s]) - * @param bool $use_ssl true if require ssl - * @return String (http|https) - */ - public static function getProtocol($use_ssl = null) - { - return (!is_null($use_ssl) && $use_ssl ? 'https://' : 'http://'); - } - - /** - * getHttpHost return the <b>current</b> host used, with the protocol (http or https) if $http is true - * This function should not be used to choose http or https domain name. - * Use Tools::getShopDomain() or Tools::getShopDomainSsl instead - * - * @param bool $http - * @param bool $entities - * @return string host - */ - public static function getHttpHost($http = false, $entities = false, $ignore_port = false) - { - $host = (isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : $_SERVER['HTTP_HOST']); - if ($ignore_port && $pos = strpos($host, ':')) - $host = substr($host, 0, $pos); - if ($entities) - $host = htmlspecialchars($host, ENT_COMPAT, 'UTF-8'); - if ($http) - $host = (Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://').$host; - return $host; - } - - /** - * getShopDomain returns domain name according to configuration and ignoring ssl - * - * @param bool $http if true, return domain name with protocol - * @param bool $entities if true, convert special chars to HTML entities - * @return string domain - */ - public static function getShopDomain($http = false, $entities = false) - { - if (!$domain = ShopUrl::getMainShopDomain()) - $domain = Tools::getHttpHost(); - if ($entities) - $domain = htmlspecialchars($domain, ENT_COMPAT, 'UTF-8'); - if ($http) - $domain = 'http://'.$domain; - return $domain; - } - - /** - * getShopDomainSsl returns domain name according to configuration and depending on ssl activation - * - * @param bool $http if true, return domain name with protocol - * @param bool $entities if true, convert special chars to HTML entities - * @return string domain - */ - public static function getShopDomainSsl($http = false, $entities = false) - { - if (!$domain = ShopUrl::getMainShopDomainSSL()) - $domain = Tools::getHttpHost(); - if ($entities) - $domain = htmlspecialchars($domain, ENT_COMPAT, 'UTF-8'); - if ($http) - $domain = (Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://').$domain; - return $domain; - } - - /** - * Get the server variable SERVER_NAME - * - * @return string server name - */ - public static function getServerName() - { - if (isset($_SERVER['HTTP_X_FORWARDED_SERVER']) && $_SERVER['HTTP_X_FORWARDED_SERVER']) - return $_SERVER['HTTP_X_FORWARDED_SERVER']; - return $_SERVER['SERVER_NAME']; - } - - /** - * Get the server variable REMOTE_ADDR, or the first ip of HTTP_X_FORWARDED_FOR (when using proxy) - * - * @return string $remote_addr ip of client - */ - public static function getRemoteAddr() - { - if (function_exists('apache_request_headers')) - $headers = apache_request_headers(); - else - $headers = $_SERVER; - - if (array_key_exists('X-Forwarded-For', $headers)) - $_SERVER['HTTP_X_FORWARDED_FOR'] = $headers['X-Forwarded-For']; - - if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] && (!isset($_SERVER['REMOTE_ADDR']) - || preg_match('/^127\..*/i', trim($_SERVER['REMOTE_ADDR'])) || preg_match('/^172\.16.*/i', trim($_SERVER['REMOTE_ADDR'])) - || preg_match('/^192\.168\.*/i', trim($_SERVER['REMOTE_ADDR'])) || preg_match('/^10\..*/i', trim($_SERVER['REMOTE_ADDR'])))) - { - if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',')) - { - $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); - return $ips[0]; - } - else - return $_SERVER['HTTP_X_FORWARDED_FOR']; - } - else - return $_SERVER['REMOTE_ADDR']; - } - - /** - * Check if the current page use SSL connection on not - * - * @return bool uses SSL - */ - public static function usingSecureMode() - { - if (isset($_SERVER['HTTPS'])) - return in_array(Tools::strtolower($_SERVER['HTTPS']), array(1, 'on')); - // $_SERVER['SSL'] exists only in some specific configuration - if (isset($_SERVER['SSL'])) - return in_array(Tools::strtolower($_SERVER['SSL']), array(1, 'on')); - // $_SERVER['REDIRECT_HTTPS'] exists only in some specific configuration - if (isset($_SERVER['REDIRECT_HTTPS'])) - return in_array(Tools::strtolower($_SERVER['REDIRECT_HTTPS']), array(1, 'on')); - if (isset($_SERVER['HTTP_SSL'])) - return in_array(Tools::strtolower($_SERVER['HTTP_SSL']), array(1, 'on')); - if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) - return Tools::strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https'; - - return false; - } - - /** - * Get the current url prefix protocol (https/http) - * - * @return string protocol - */ - public static function getCurrentUrlProtocolPrefix() - { - if (Tools::usingSecureMode()) - return 'https://'; - else - return 'http://'; - } - - /** - * Secure an URL referrer - * - * @param string $referrer URL referrer - * @return string secured referrer - */ - public static function secureReferrer($referrer) - { - if (preg_match('/^http[s]?:\/\/'.Tools::getServerName().'(:'._PS_SSL_PORT_.')?\/.*$/Ui', $referrer)) - return $referrer; - return __PS_BASE_URI__; - } - - /** - * Get a value from $_POST / $_GET - * if unavailable, take a default value - * - * @param string $key Value key - * @param mixed $default_value (optional) - * @return mixed Value - */ - public static function getValue($key, $default_value = false) - { - if (!isset($key) || empty($key) || !is_string($key)) - return false; - - $ret = (isset($_POST[$key]) ? $_POST[$key] : (isset($_GET[$key]) ? $_GET[$key] : $default_value)); - - if (is_string($ret)) - return stripslashes(urldecode(preg_replace('/((\%5C0+)|(\%00+))/i', '', urlencode($ret)))); - - return $ret; - } - - - /** - * Get all values from $_POST/$_GET - * @return mixed - */ - public static function getAllValues() - { - return $_POST + $_GET; - } - - public static function getIsset($key) - { - if (!isset($key) || empty($key) || !is_string($key)) - return false; - return isset($_POST[$key]) ? true : (isset($_GET[$key]) ? true : false); - } - - /** - * Change language in cookie while clicking on a flag - * - * @return string iso code - */ - public static function setCookieLanguage($cookie = null) - { - if (!$cookie) - $cookie = Context::getContext()->cookie; - /* If language does not exist or is disabled, erase it */ - if ($cookie->id_lang) - { - $lang = new Language((int)$cookie->id_lang); - if (!Validate::isLoadedObject($lang) || !$lang->active || !$lang->isAssociatedToShop()) - $cookie->id_lang = null; - } - - if (!Configuration::get('PS_DETECT_LANG')) - unset($cookie->detect_language); - - /* Automatically detect language if not already defined, detect_language is set in Cookie::update */ - if (!Tools::getValue('isolang') && !Tools::getValue('id_lang') && (!$cookie->id_lang || isset($cookie->detect_language)) - && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) - { - $array = explode(',', Tools::strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE'])); - $string = $array[0]; - - if (Validate::isLanguageCode($string)) - { - $lang = Language::getLanguageByIETFCode($string); - if (Validate::isLoadedObject($lang) && $lang->active && $lang->isAssociatedToShop()) - { - Context::getContext()->language = $lang; - $cookie->id_lang = (int)$lang->id; - } - } - } - - if (isset($cookie->detect_language)) - unset($cookie->detect_language); - - /* If language file not present, you must use default language file */ - if (!$cookie->id_lang || !Validate::isUnsignedId($cookie->id_lang)) - $cookie->id_lang = (int)Configuration::get('PS_LANG_DEFAULT'); - - $iso = Language::getIsoById((int)$cookie->id_lang); - @include_once(_PS_THEME_DIR_.'lang/'.$iso.'.php'); - - return $iso; - } - - /** - * Set cookie id_lang - */ - public static function switchLanguage(Context $context = null) - { - if (!$context) - $context = Context::getContext(); - - // Install call the dispatcher and so the switchLanguage - // Stop this method by checking the cookie - if (!isset($context->cookie)) - return; - - if (($iso = Tools::getValue('isolang')) && Validate::isLanguageIsoCode($iso) && ($id_lang = (int)Language::getIdByIso($iso))) - $_GET['id_lang'] = $id_lang; - - // update language only if new id is different from old id - // or if default language changed - $cookie_id_lang = $context->cookie->id_lang; - $configuration_id_lang = Configuration::get('PS_LANG_DEFAULT'); - if ((($id_lang = (int)Tools::getValue('id_lang')) && Validate::isUnsignedId($id_lang) && $cookie_id_lang != (int)$id_lang) - || (($id_lang == $configuration_id_lang) && Validate::isUnsignedId($id_lang) && $id_lang != $cookie_id_lang)) - { - $context->cookie->id_lang = $id_lang; - $language = new Language($id_lang); - if (Validate::isLoadedObject($language) && $language->active) - $context->language = $language; - - $params = $_GET; - if (Configuration::get('PS_REWRITING_SETTINGS') || !Language::isMultiLanguageActivated()) - unset($params['id_lang']); - } - } - - public static function getCountry($address = null) - { - if ($id_country = Tools::getValue('id_country')); - elseif (isset($address) && isset($address->id_country) && $address->id_country) - $id_country = $address->id_country; - elseif (Configuration::get('PS_DETECT_COUNTRY') && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) - { - preg_match('#(?<=-)\w\w|\w\w(?!-)#', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $array); - if (is_array($array) && isset($array[0]) && Validate::isLanguageIsoCode($array[0])) - $id_country = Country::getByIso($array[0], true); - } - if (!isset($id_country) || !$id_country) - $id_country = Configuration::get('PS_COUNTRY_DEFAULT'); - return (int)$id_country; - } - - /** - * Set cookie currency from POST or default currency - * - * @return Currency object - */ - public static function setCurrency($cookie) - { - if (Tools::isSubmit('SubmitCurrency') && ($id_currency = Tools::getValue('id_currency'))) - { - /** @var Currency $currency */ - $currency = Currency::getCurrencyInstance((int)$id_currency); - if (is_object($currency) && $currency->id && !$currency->deleted && $currency->isAssociatedToShop()) - $cookie->id_currency = (int)$currency->id; - } - - $currency = null; - if ((int)$cookie->id_currency) - $currency = Currency::getCurrencyInstance((int)$cookie->id_currency); - if (!Validate::isLoadedObject($currency) || (bool)$currency->deleted || !(bool)$currency->active) - $currency = Currency::getCurrencyInstance(Configuration::get('PS_CURRENCY_DEFAULT')); - - $cookie->id_currency = (int)$currency->id; - if ($currency->isAssociatedToShop()) - return $currency; - else - { - // get currency from context - $currency = Shop::getEntityIds('currency', Context::getContext()->shop->id, true, true); - if (isset($currency[0]) && $currency[0]['id_currency']) - { - $cookie->id_currency = $currency[0]['id_currency']; - return Currency::getCurrencyInstance((int)$cookie->id_currency); - } - } - - return $currency; - } - - /** - * Return price with currency sign for a given product - * - * @param float $price Product price - * @param object|array $currency Current currency (object, id_currency, NULL => context currency) - * @return string Price correctly formated (sign, decimal separator...) - */ - public static function displayPrice($price, $currency = null, $no_utf8 = false, Context $context = null) - { - if (!is_numeric($price)) - return $price; - if (!$context) - $context = Context::getContext(); - if ($currency === null) - $currency = $context->currency; - // if you modified this function, don't forget to modify the Javascript function formatCurrency (in tools.js) - elseif (is_int($currency)) - $currency = Currency::getCurrencyInstance((int)$currency); - - if (is_array($currency)) - { - $c_char = $currency['sign']; - $c_format = $currency['format']; - $c_decimals = (int)$currency['decimals'] * _PS_PRICE_DISPLAY_PRECISION_; - $c_blank = $currency['blank']; - } - elseif (is_object($currency)) - { - $c_char = $currency->sign; - $c_format = $currency->format; - $c_decimals = (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_; - $c_blank = $currency->blank; - } - else - return false; - - $blank = ($c_blank ? ' ' : ''); - $ret = 0; - if (($is_negative = ($price < 0))) - $price *= -1; - $price = Tools::ps_round($price, $c_decimals); - - /* - * If the language is RTL and the selected currency format contains spaces as thousands separator - * then the number will be printed in reverse since the space is interpreted as separating words. - * To avoid this we replace the currency format containing a space with the one containing a comma (,) as thousand - * separator when the language is RTL. - * - * TODO: This is not ideal, a currency format should probably be tied to a language, not to a currency. - */ - if (($c_format == 2) && ($context->language->is_rtl == 1)) - $c_format = 4; - - switch ($c_format) - { - /* X 0,000.00 */ - case 1: - $ret = $c_char.$blank.number_format($price, $c_decimals, '.', ','); - break; - /* 0 000,00 X*/ - case 2: - $ret = number_format($price, $c_decimals, ',', ' ').$blank.$c_char; - break; - /* X 0.000,00 */ - case 3: - $ret = $c_char.$blank.number_format($price, $c_decimals, ',', '.'); - break; - /* 0,000.00 X */ - case 4: - $ret = number_format($price, $c_decimals, '.', ',').$blank.$c_char; - break; - /* X 0'000.00 Added for the switzerland currency */ - case 5: - $ret = number_format($price, $c_decimals, '.', "'").$blank.$c_char; - break; - } - if ($is_negative) - $ret = '-'.$ret; - if ($no_utf8) - return str_replace('€', chr(128), $ret); - return $ret; - } - - /* Just to fix a bug - * Need real CLDR functions - */ - public static function displayNumber($number, $currency) - { - if (is_array($currency)) - $format = $currency['format']; - elseif (is_object($currency)) - $format = $currency->format; - - return number_format($number, 0, '.', in_array($format, array(1, 4)) ? ',': ' '); - } - - public static function displayPriceSmarty($params, &$smarty) - { - if (array_key_exists('currency', $params)) - { - $currency = Currency::getCurrencyInstance((int)$params['currency']); - if (Validate::isLoadedObject($currency)) - return Tools::displayPrice($params['price'], $currency, false); - } - return Tools::displayPrice($params['price']); - } - - /** - * Return price converted - * - * @param float $price Product price - * @param object|array $currency Current currency object - * @param bool $to_currency convert to currency or from currency to default currency - * @param Context $context - * @return float Price - */ - public static function convertPrice($price, $currency = null, $to_currency = true, Context $context = null) - { - static $default_currency = null; - - if ($default_currency === null) - $default_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT'); - - if (!$context) - $context = Context::getContext(); - if ($currency === null) - $currency = $context->currency; - elseif (is_numeric($currency)) - $currency = Currency::getCurrencyInstance($currency); - - $c_id = (is_array($currency) ? $currency['id_currency'] : $currency->id); - $c_rate = (is_array($currency) ? $currency['conversion_rate'] : $currency->conversion_rate); - - if ($c_id != $default_currency) - { - if ($to_currency) - $price *= $c_rate; - else - $price /= $c_rate; - } - - return $price; - } - - /** - * Implement array_replace for PHP <= 5.2 - * - * @return array|mixed|null - */ - public static function array_replace() - { - if (!function_exists('array_replace')) - { - $args = func_get_args(); - $num_args = func_num_args(); - $res = array(); - for ($i = 0; $i < $num_args; $i++) - { - if (is_array($args[$i])) - { - foreach ($args[$i] as $key => $val) - $res[$key] = $val; - } - else - { - trigger_error(__FUNCTION__.'(): Argument #'.($i + 1).' is not an array', E_USER_WARNING); - return null; - } - } - return $res; - } - else - { - return call_user_func_array('array_replace', func_get_args()); - } - } - - /** - * - * Convert amount from a currency to an other currency automatically - * @param float $amount - * @param Currency $currency_from if null we used the default currency - * @param Currency $currency_to if null we used the default currency - */ - public static function convertPriceFull($amount, Currency $currency_from = null, Currency $currency_to = null) - { - if ($currency_from === $currency_to) - return $amount; - - if ($currency_from === null) - $currency_from = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); - - if ($currency_to === null) - $currency_to = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); - - if ($currency_from->id == Configuration::get('PS_CURRENCY_DEFAULT')) - $amount *= $currency_to->conversion_rate; - else - { - $conversion_rate = ($currency_from->conversion_rate == 0 ? 1 : $currency_from->conversion_rate); - // Convert amount to default currency (using the old currency rate) - $amount = $amount / $conversion_rate; - // Convert to new currency - $amount *= $currency_to->conversion_rate; - } - return Tools::ps_round($amount, _PS_PRICE_COMPUTE_PRECISION_); - } - - /** - * Display date regarding to language preferences - * - * @param array $params Date, format... - * @param object $smarty Smarty object for language preferences - * @return string Date - */ - public static function dateFormat($params, &$smarty) - { - return Tools::displayDate($params['date'], null, (isset($params['full']) ? $params['full'] : false)); - } - - /** - * Display date regarding to language preferences - * - * @param string $date Date to display format UNIX - * @param int $id_lang Language id DEPRECATED - * @param bool $full With time or not (optional) - * @param string $separator DEPRECATED - * @return string Date - */ - public static function displayDate($date, $id_lang = null, $full = false, $separator = null) - { - if ($id_lang !== null) - Tools::displayParameterAsDeprecated('id_lang'); - if ($separator !== null) - Tools::displayParameterAsDeprecated('separator'); - - if (!$date || !($time = strtotime($date))) - return $date; - - if ($date == '0000-00-00 00:00:00' || $date == '0000-00-00') - return ''; - - if (!Validate::isDate($date) || !Validate::isBool($full)) - throw new PrestaShopException('Invalid date'); - - $context = Context::getContext(); - $date_format = ($full ? $context->language->date_format_full : $context->language->date_format_lite); - return date($date_format, $time); - } - - /** - * Sanitize a string - * - * @param string $string String to sanitize - * @param bool $full String contains HTML or not (optional) - * @return string Sanitized string - */ - public static function safeOutput($string, $html = false) - { - if (!$html) - $string = strip_tags($string); - return @Tools::htmlentitiesUTF8($string, ENT_QUOTES); - } - - public static function htmlentitiesUTF8($string, $type = ENT_QUOTES) - { - if (is_array($string)) - return array_map(array('Tools', 'htmlentitiesUTF8'), $string); - - return htmlentities((string)$string, $type, 'utf-8'); - } - - public static function htmlentitiesDecodeUTF8($string) - { - if (is_array($string)) - { - $string = array_map(array('Tools', 'htmlentitiesDecodeUTF8'), $string); - return (string)array_shift($string); - } - return html_entity_decode((string)$string, ENT_QUOTES, 'utf-8'); - } - - public static function safePostVars() - { - if (!isset($_POST) || !is_array($_POST)) - $_POST = array(); - else - $_POST = array_map(array('Tools', 'htmlentitiesUTF8'), $_POST); - } - - /** - * Delete directory and subdirectories - * - * @param string $dirname Directory name - */ - public static function deleteDirectory($dirname, $delete_self = true) - { - $dirname = rtrim($dirname, '/').'/'; - if (file_exists($dirname)) - if ($files = scandir($dirname)) - { - foreach ($files as $file) - if ($file != '.' && $file != '..' && $file != '.svn') - { - if (is_dir($dirname.$file)) - Tools::deleteDirectory($dirname.$file, true); - elseif (file_exists($dirname.$file)) - { - @chmod($dirname.$file, 0777); // NT ? - unlink($dirname.$file); - } - } - if ($delete_self && file_exists($dirname)) - if (!rmdir($dirname)) - { - @chmod($dirname, 0777); // NT ? - return false; - } - return true; - } - return false; - } - - /** - * Delete file - * - * @param string $file File path - * @param array $exclude_files Excluded files - */ - public static function deleteFile($file, $exclude_files = array()) - { - if (isset($exclude_files) && !is_array($exclude_files)) - $exclude_files = array($exclude_files); - - if (file_exists($file) && is_file($file) && array_search(basename($file), $exclude_files) === false) - { - @chmod($file, 0777); // NT ? - unlink($file); - } - } - - /** - * Clear XML cache folder - */ - public static function clearXMLCache() - { - $themes = array(); - foreach (Theme::getThemes() as $theme) - { - /** @var Theme $theme */ - $themes[] = $theme->directory; - } - - foreach (scandir(_PS_ROOT_DIR_.'/config/xml') as $file) - { - $path_info = pathinfo($file, PATHINFO_EXTENSION); - if (($path_info == 'xml') && ($file != 'default.xml') && !in_array(basename($file, '.'.$path_info), $themes)) - self::deleteFile(_PS_ROOT_DIR_.'/config/xml/'.$file); - } - } - - /** - * Display an error according to an error code - * - * @param string $string Error message - * @param bool $htmlentities By default at true for parsing error message with htmlentities - */ - public static function displayError($string = 'Fatal error', $htmlentities = true, Context $context = null) - { - global $_ERRORS; - - if (is_null($context)) - $context = Context::getContext(); - - @include_once(_PS_TRANSLATIONS_DIR_.$context->language->iso_code.'/errors.php'); - - if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_ && $string == 'Fatal error') - return ('<pre>'.print_r(debug_backtrace(), true).'</pre>'); - if (!is_array($_ERRORS)) - return $htmlentities ? Tools::htmlentitiesUTF8($string) : $string; - $key = md5(str_replace('\'', '\\\'', $string)); - $str = (isset($_ERRORS) && is_array($_ERRORS) && array_key_exists($key, $_ERRORS)) ? $_ERRORS[$key] : $string; - return $htmlentities ? Tools::htmlentitiesUTF8(stripslashes($str)) : $str; - } - - /** - * Display an error with detailed object - * - * @param mixed $object - * @param bool $kill - * @return $object if $kill = false; - */ - public static function dieObject($object, $kill = true) - { - echo '<xmp style="text-align: left;">'; - print_r($object); - echo '</xmp><br />'; - - if ($kill) - die('END'); - - return $object; - } - - /** - * Display a var dump in firebug console - * - * @param object $object Object to display - */ - public static function fd($object, $type = 'log') - { - $types = array('log', 'debug', 'info', 'warn', 'error', 'assert'); - - if (!in_array($type, $types)) - $type = 'log'; - - echo ' + protected static $file_exists_cache = array(); + protected static $_forceCompile; + protected static $_caching; + protected static $_user_plateform; + protected static $_user_browser; + + public static $round_mode = null; + + /** + * Random password generator + * + * @param int $length Desired length (optional) + * @param string $flag Output type (NUMERIC, ALPHANUMERIC, NO_NUMERIC, RANDOM) + * @return bool|string Password + */ + public static function passwdGen($length = 8, $flag = 'ALPHANUMERIC') + { + $length = (int)$length; + + if ($length <= 0) { + return false; + } + + switch ($flag) { + case 'NUMERIC': + $str = '0123456789'; + break; + case 'NO_NUMERIC': + $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + break; + case 'RANDOM': + $num_bytes = ceil($length * 0.75); + $bytes = self::getBytes($num_bytes); + return substr(rtrim(base64_encode($bytes), '='), 0, $length); + case 'ALPHANUMERIC': + default: + $str = 'abcdefghijkmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + break; + } + + $bytes = Tools::getBytes($length); + $position = 0; + $result = ''; + + for ($i = 0; $i < $length; $i++) { + $position = ($position + ord($bytes[$i])) % strlen($str); + $result .= $str[$position]; + } + + return $result; + } + + /** + * Random bytes generator + * + * Thanks to Zend for entropy + * + * @param $length Desired length of random bytes + * @return bool|string Random bytes + */ + public static function getBytes($length) + { + $length = (int)$length; + + if ($length <= 0) { + return false; + } + + if (function_exists('openssl_random_pseudo_bytes')) { + $bytes = openssl_random_pseudo_bytes($length, $crypto_strong); + + if ($crypto_strong === true) { + return $bytes; + } + } + + if (function_exists('mcrypt_create_iv')) { + $bytes = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); + + if ($bytes !== false && strlen($bytes) === $length) { + return $bytes; + } + } + + // Else try to get $length bytes of entropy. + // Thanks to Zend + + $result = ''; + $entropy = ''; + $msec_per_round = 400; + $bits_per_round = 2; + $total = $length; + $hash_length = 20; + + while (strlen($result) < $length) { + $bytes = ($total > $hash_length) ? $hash_length : $total; + $total -= $bytes; + + for ($i=1; $i < 3; $i++) { + $t1 = microtime(true); + $seed = mt_rand(); + + for ($j=1; $j < 50; $j++) { + $seed = sha1($seed); + } + + $t2 = microtime(true); + $entropy .= $t1 . $t2; + } + + $div = (int) (($t2 - $t1) * 1000000); + + if ($div <= 0) { + $div = 400; + } + + $rounds = (int) ($msec_per_round * 50 / $div); + $iter = $bytes * (int) (ceil(8 / $bits_per_round)); + + for ($i = 0; $i < $iter; $i ++) { + $t1 = microtime(); + $seed = sha1(mt_rand()); + + for ($j = 0; $j < $rounds; $j++) { + $seed = sha1($seed); + } + + $t2 = microtime(); + $entropy .= $t1 . $t2; + } + + $result .= sha1($entropy, true); + } + + return substr($result, 0, $length); + } + + public static function strReplaceFirst($search, $replace, $subject, $cur = 0) + { + return (strpos($subject, $search, $cur))?substr_replace($subject, $replace, (int)strpos($subject, $search, $cur), strlen($search)):$subject; + } + + /** + * Redirect user to another page + * + * @param string $url Desired URL + * @param string $base_uri Base URI (optional) + * @param Link $link + * @param string|array $headers A list of headers to send before redirection + */ + public static function redirect($url, $base_uri = __PS_BASE_URI__, Link $link = null, $headers = null) + { + if (!$link) { + $link = Context::getContext()->link; + } + + if (strpos($url, 'http://') === false && strpos($url, 'https://') === false && $link) { + if (strpos($url, $base_uri) === 0) { + $url = substr($url, strlen($base_uri)); + } + if (strpos($url, 'index.php?controller=') !== false && strpos($url, 'index.php/') == 0) { + $url = substr($url, strlen('index.php?controller=')); + if (Configuration::get('PS_REWRITING_SETTINGS')) { + $url = Tools::strReplaceFirst('&', '?', $url); + } + } + + $explode = explode('?', $url); + // don't use ssl if url is home page + // used when logout for example + $use_ssl = !empty($url); + $url = $link->getPageLink($explode[0], $use_ssl); + if (isset($explode[1])) { + $url .= '?'.$explode[1]; + } + } + + // Send additional headers + if ($headers) { + if (!is_array($headers)) { + $headers = array($headers); + } + + foreach ($headers as $header) { + header($header); + } + } + + header('Location: '.$url); + exit; + } + + /** + * Redirect URLs already containing PS_BASE_URI + * + * @param string $url Desired URL + */ + public static function redirectLink($url) + { + if (!preg_match('@^https?://@i', $url)) { + if (strpos($url, __PS_BASE_URI__) !== false && strpos($url, __PS_BASE_URI__) == 0) { + $url = substr($url, strlen(__PS_BASE_URI__)); + } + if (strpos($url, 'index.php?controller=') !== false && strpos($url, 'index.php/') == 0) { + $url = substr($url, strlen('index.php?controller=')); + } + $explode = explode('?', $url); + $url = Context::getContext()->link->getPageLink($explode[0]); + if (isset($explode[1])) { + $url .= '?'.$explode[1]; + } + } + header('Location: '.$url); + exit; + } + + /** + * Redirect user to another admin page + * + * @param string $url Desired URL + */ + public static function redirectAdmin($url) + { + header('Location: '.$url); + exit; + } + + /** + * getShopProtocol return the available protocol for the current shop in use + * SSL if Configuration is set on and available for the server + * + * @return String + */ + public static function getShopProtocol() + { + $protocol = (Configuration::get('PS_SSL_ENABLED') || (!empty($_SERVER['HTTPS']) + && Tools::strtolower($_SERVER['HTTPS']) != 'off')) ? 'https://' : 'http://'; + return $protocol; + } + + /** + * getProtocol return the set protocol according to configuration (http[s]) + * @param bool $use_ssl true if require ssl + * @return String (http|https) + */ + public static function getProtocol($use_ssl = null) + { + return (!is_null($use_ssl) && $use_ssl ? 'https://' : 'http://'); + } + + /** + * getHttpHost return the <b>current</b> host used, with the protocol (http or https) if $http is true + * This function should not be used to choose http or https domain name. + * Use Tools::getShopDomain() or Tools::getShopDomainSsl instead + * + * @param bool $http + * @param bool $entities + * @return string host + */ + public static function getHttpHost($http = false, $entities = false, $ignore_port = false) + { + $host = (isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : $_SERVER['HTTP_HOST']); + if ($ignore_port && $pos = strpos($host, ':')) { + $host = substr($host, 0, $pos); + } + if ($entities) { + $host = htmlspecialchars($host, ENT_COMPAT, 'UTF-8'); + } + if ($http) { + $host = (Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://').$host; + } + return $host; + } + + /** + * getShopDomain returns domain name according to configuration and ignoring ssl + * + * @param bool $http if true, return domain name with protocol + * @param bool $entities if true, convert special chars to HTML entities + * @return string domain + */ + public static function getShopDomain($http = false, $entities = false) + { + if (!$domain = ShopUrl::getMainShopDomain()) { + $domain = Tools::getHttpHost(); + } + if ($entities) { + $domain = htmlspecialchars($domain, ENT_COMPAT, 'UTF-8'); + } + if ($http) { + $domain = 'http://'.$domain; + } + return $domain; + } + + /** + * getShopDomainSsl returns domain name according to configuration and depending on ssl activation + * + * @param bool $http if true, return domain name with protocol + * @param bool $entities if true, convert special chars to HTML entities + * @return string domain + */ + public static function getShopDomainSsl($http = false, $entities = false) + { + if (!$domain = ShopUrl::getMainShopDomainSSL()) { + $domain = Tools::getHttpHost(); + } + if ($entities) { + $domain = htmlspecialchars($domain, ENT_COMPAT, 'UTF-8'); + } + if ($http) { + $domain = (Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://').$domain; + } + return $domain; + } + + /** + * Get the server variable SERVER_NAME + * + * @return string server name + */ + public static function getServerName() + { + if (isset($_SERVER['HTTP_X_FORWARDED_SERVER']) && $_SERVER['HTTP_X_FORWARDED_SERVER']) { + return $_SERVER['HTTP_X_FORWARDED_SERVER']; + } + return $_SERVER['SERVER_NAME']; + } + + /** + * Get the server variable REMOTE_ADDR, or the first ip of HTTP_X_FORWARDED_FOR (when using proxy) + * + * @return string $remote_addr ip of client + */ + public static function getRemoteAddr() + { + if (function_exists('apache_request_headers')) { + $headers = apache_request_headers(); + } else { + $headers = $_SERVER; + } + + if (array_key_exists('X-Forwarded-For', $headers)) { + $_SERVER['HTTP_X_FORWARDED_FOR'] = $headers['X-Forwarded-For']; + } + + if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] && (!isset($_SERVER['REMOTE_ADDR']) + || preg_match('/^127\..*/i', trim($_SERVER['REMOTE_ADDR'])) || preg_match('/^172\.16.*/i', trim($_SERVER['REMOTE_ADDR'])) + || preg_match('/^192\.168\.*/i', trim($_SERVER['REMOTE_ADDR'])) || preg_match('/^10\..*/i', trim($_SERVER['REMOTE_ADDR'])))) { + if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',')) { + $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); + return $ips[0]; + } else { + return $_SERVER['HTTP_X_FORWARDED_FOR']; + } + } else { + return $_SERVER['REMOTE_ADDR']; + } + } + + /** + * Check if the current page use SSL connection on not + * + * @return bool uses SSL + */ + public static function usingSecureMode() + { + if (isset($_SERVER['HTTPS'])) { + return in_array(Tools::strtolower($_SERVER['HTTPS']), array(1, 'on')); + } + // $_SERVER['SSL'] exists only in some specific configuration + if (isset($_SERVER['SSL'])) { + return in_array(Tools::strtolower($_SERVER['SSL']), array(1, 'on')); + } + // $_SERVER['REDIRECT_HTTPS'] exists only in some specific configuration + if (isset($_SERVER['REDIRECT_HTTPS'])) { + return in_array(Tools::strtolower($_SERVER['REDIRECT_HTTPS']), array(1, 'on')); + } + if (isset($_SERVER['HTTP_SSL'])) { + return in_array(Tools::strtolower($_SERVER['HTTP_SSL']), array(1, 'on')); + } + if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { + return Tools::strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https'; + } + + return false; + } + + /** + * Get the current url prefix protocol (https/http) + * + * @return string protocol + */ + public static function getCurrentUrlProtocolPrefix() + { + if (Tools::usingSecureMode()) { + return 'https://'; + } else { + return 'http://'; + } + } + + /** + * Secure an URL referrer + * + * @param string $referrer URL referrer + * @return string secured referrer + */ + public static function secureReferrer($referrer) + { + if (preg_match('/^http[s]?:\/\/'.Tools::getServerName().'(:'._PS_SSL_PORT_.')?\/.*$/Ui', $referrer)) { + return $referrer; + } + return __PS_BASE_URI__; + } + + /** + * Get a value from $_POST / $_GET + * if unavailable, take a default value + * + * @param string $key Value key + * @param mixed $default_value (optional) + * @return mixed Value + */ + public static function getValue($key, $default_value = false) + { + if (!isset($key) || empty($key) || !is_string($key)) { + return false; + } + + $ret = (isset($_POST[$key]) ? $_POST[$key] : (isset($_GET[$key]) ? $_GET[$key] : $default_value)); + + if (is_string($ret)) { + return stripslashes(urldecode(preg_replace('/((\%5C0+)|(\%00+))/i', '', urlencode($ret)))); + } + + return $ret; + } + + + /** + * Get all values from $_POST/$_GET + * @return mixed + */ + public static function getAllValues() + { + return $_POST + $_GET; + } + + public static function getIsset($key) + { + if (!isset($key) || empty($key) || !is_string($key)) { + return false; + } + return isset($_POST[$key]) ? true : (isset($_GET[$key]) ? true : false); + } + + /** + * Change language in cookie while clicking on a flag + * + * @return string iso code + */ + public static function setCookieLanguage($cookie = null) + { + if (!$cookie) { + $cookie = Context::getContext()->cookie; + } + /* If language does not exist or is disabled, erase it */ + if ($cookie->id_lang) { + $lang = new Language((int)$cookie->id_lang); + if (!Validate::isLoadedObject($lang) || !$lang->active || !$lang->isAssociatedToShop()) { + $cookie->id_lang = null; + } + } + + if (!Configuration::get('PS_DETECT_LANG')) { + unset($cookie->detect_language); + } + + /* Automatically detect language if not already defined, detect_language is set in Cookie::update */ + if (!Tools::getValue('isolang') && !Tools::getValue('id_lang') && (!$cookie->id_lang || isset($cookie->detect_language)) + && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { + $array = explode(',', Tools::strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE'])); + $string = $array[0]; + + if (Validate::isLanguageCode($string)) { + $lang = Language::getLanguageByIETFCode($string); + if (Validate::isLoadedObject($lang) && $lang->active && $lang->isAssociatedToShop()) { + Context::getContext()->language = $lang; + $cookie->id_lang = (int)$lang->id; + } + } + } + + if (isset($cookie->detect_language)) { + unset($cookie->detect_language); + } + + /* If language file not present, you must use default language file */ + if (!$cookie->id_lang || !Validate::isUnsignedId($cookie->id_lang)) { + $cookie->id_lang = (int)Configuration::get('PS_LANG_DEFAULT'); + } + + $iso = Language::getIsoById((int)$cookie->id_lang); + @include_once(_PS_THEME_DIR_.'lang/'.$iso.'.php'); + + return $iso; + } + + /** + * Set cookie id_lang + */ + public static function switchLanguage(Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + + // Install call the dispatcher and so the switchLanguage + // Stop this method by checking the cookie + if (!isset($context->cookie)) { + return; + } + + if (($iso = Tools::getValue('isolang')) && Validate::isLanguageIsoCode($iso) && ($id_lang = (int)Language::getIdByIso($iso))) { + $_GET['id_lang'] = $id_lang; + } + + // update language only if new id is different from old id + // or if default language changed + $cookie_id_lang = $context->cookie->id_lang; + $configuration_id_lang = Configuration::get('PS_LANG_DEFAULT'); + if ((($id_lang = (int)Tools::getValue('id_lang')) && Validate::isUnsignedId($id_lang) && $cookie_id_lang != (int)$id_lang) + || (($id_lang == $configuration_id_lang) && Validate::isUnsignedId($id_lang) && $id_lang != $cookie_id_lang)) { + $context->cookie->id_lang = $id_lang; + $language = new Language($id_lang); + if (Validate::isLoadedObject($language) && $language->active) { + $context->language = $language; + } + + $params = $_GET; + if (Configuration::get('PS_REWRITING_SETTINGS') || !Language::isMultiLanguageActivated()) { + unset($params['id_lang']); + } + } + } + + public static function getCountry($address = null) + { + if ($id_country = Tools::getValue('id_country')); elseif (isset($address) && isset($address->id_country) && $address->id_country) { + $id_country = $address->id_country; + } elseif (Configuration::get('PS_DETECT_COUNTRY') && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { + preg_match('#(?<=-)\w\w|\w\w(?!-)#', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $array); + if (is_array($array) && isset($array[0]) && Validate::isLanguageIsoCode($array[0])) { + $id_country = (int)Country::getByIso($array[0], true); + } + } + if (!isset($id_country) || !$id_country) { + $id_country = Configuration::get('PS_COUNTRY_DEFAULT'); + } + return (int)$id_country; + } + + /** + * Set cookie currency from POST or default currency + * + * @return Currency object + */ + public static function setCurrency($cookie) + { + if (Tools::isSubmit('SubmitCurrency') && ($id_currency = Tools::getValue('id_currency'))) { + /** @var Currency $currency */ + $currency = Currency::getCurrencyInstance((int)$id_currency); + if (is_object($currency) && $currency->id && !$currency->deleted && $currency->isAssociatedToShop()) { + $cookie->id_currency = (int)$currency->id; + } + } + + $currency = null; + if ((int)$cookie->id_currency) { + $currency = Currency::getCurrencyInstance((int)$cookie->id_currency); + } + if (!Validate::isLoadedObject($currency) || (bool)$currency->deleted || !(bool)$currency->active) { + $currency = Currency::getCurrencyInstance(Configuration::get('PS_CURRENCY_DEFAULT')); + } + + $cookie->id_currency = (int)$currency->id; + if ($currency->isAssociatedToShop()) { + return $currency; + } else { + // get currency from context + $currency = Shop::getEntityIds('currency', Context::getContext()->shop->id, true, true); + if (isset($currency[0]) && $currency[0]['id_currency']) { + $cookie->id_currency = $currency[0]['id_currency']; + return Currency::getCurrencyInstance((int)$cookie->id_currency); + } + } + + return $currency; + } + + /** + * Return price with currency sign for a given product + * + * @param float $price Product price + * @param object|array $currency Current currency (object, id_currency, NULL => context currency) + * @return string Price correctly formated (sign, decimal separator...) + */ + public static function displayPrice($price, $currency = null, $no_utf8 = false, Context $context = null) + { + if (!is_numeric($price)) { + return $price; + } + if (!$context) { + $context = Context::getContext(); + } + if ($currency === null) { + $currency = $context->currency; + } + // if you modified this function, don't forget to modify the Javascript function formatCurrency (in tools.js) + elseif (is_int($currency)) { + $currency = Currency::getCurrencyInstance((int)$currency); + } + + if (is_array($currency)) { + $c_char = $currency['sign']; + $c_format = $currency['format']; + $c_decimals = (int)$currency['decimals'] * _PS_PRICE_DISPLAY_PRECISION_; + $c_blank = $currency['blank']; + } elseif (is_object($currency)) { + $c_char = $currency->sign; + $c_format = $currency->format; + $c_decimals = (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_; + $c_blank = $currency->blank; + } else { + return false; + } + + $blank = ($c_blank ? ' ' : ''); + $ret = 0; + if (($is_negative = ($price < 0))) { + $price *= -1; + } + $price = Tools::ps_round($price, $c_decimals); + + /* + * If the language is RTL and the selected currency format contains spaces as thousands separator + * then the number will be printed in reverse since the space is interpreted as separating words. + * To avoid this we replace the currency format containing a space with the one containing a comma (,) as thousand + * separator when the language is RTL. + * + * TODO: This is not ideal, a currency format should probably be tied to a language, not to a currency. + */ + if (($c_format == 2) && ($context->language->is_rtl == 1)) { + $c_format = 4; + } + + switch ($c_format) { + /* X 0,000.00 */ + case 1: + $ret = $c_char.$blank.number_format($price, $c_decimals, '.', ','); + break; + /* 0 000,00 X*/ + case 2: + $ret = number_format($price, $c_decimals, ',', ' ').$blank.$c_char; + break; + /* X 0.000,00 */ + case 3: + $ret = $c_char.$blank.number_format($price, $c_decimals, ',', '.'); + break; + /* 0,000.00 X */ + case 4: + $ret = number_format($price, $c_decimals, '.', ',').$blank.$c_char; + break; + /* X 0'000.00 Added for the switzerland currency */ + case 5: + $ret = number_format($price, $c_decimals, '.', "'").$blank.$c_char; + break; + } + if ($is_negative) { + $ret = '-'.$ret; + } + if ($no_utf8) { + return str_replace('€', chr(128), $ret); + } + return $ret; + } + + /* Just to fix a bug + * Need real CLDR functions + */ + public static function displayNumber($number, $currency) + { + if (is_array($currency)) { + $format = $currency['format']; + } elseif (is_object($currency)) { + $format = $currency->format; + } + + return number_format($number, 0, '.', in_array($format, array(1, 4)) ? ',': ' '); + } + + public static function displayPriceSmarty($params, &$smarty) + { + if (array_key_exists('currency', $params)) { + $currency = Currency::getCurrencyInstance((int)$params['currency']); + if (Validate::isLoadedObject($currency)) { + return Tools::displayPrice($params['price'], $currency, false); + } + } + return Tools::displayPrice($params['price']); + } + + /** + * Return price converted + * + * @param float $price Product price + * @param object|array $currency Current currency object + * @param bool $to_currency convert to currency or from currency to default currency + * @param Context $context + * @return float Price + */ + public static function convertPrice($price, $currency = null, $to_currency = true, Context $context = null) + { + static $default_currency = null; + + if ($default_currency === null) { + $default_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT'); + } + + if (!$context) { + $context = Context::getContext(); + } + if ($currency === null) { + $currency = $context->currency; + } elseif (is_numeric($currency)) { + $currency = Currency::getCurrencyInstance($currency); + } + + $c_id = (is_array($currency) ? $currency['id_currency'] : $currency->id); + $c_rate = (is_array($currency) ? $currency['conversion_rate'] : $currency->conversion_rate); + + if ($c_id != $default_currency) { + if ($to_currency) { + $price *= $c_rate; + } else { + $price /= $c_rate; + } + } + + return $price; + } + + /** + * Implement array_replace for PHP <= 5.2 + * + * @return array|mixed|null + */ + public static function array_replace() + { + if (!function_exists('array_replace')) { + $args = func_get_args(); + $num_args = func_num_args(); + $res = array(); + for ($i = 0; $i < $num_args; $i++) { + if (is_array($args[$i])) { + foreach ($args[$i] as $key => $val) { + $res[$key] = $val; + } + } else { + trigger_error(__FUNCTION__.'(): Argument #'.($i + 1).' is not an array', E_USER_WARNING); + return null; + } + } + return $res; + } else { + return call_user_func_array('array_replace', func_get_args()); + } + } + + /** + * + * Convert amount from a currency to an other currency automatically + * @param float $amount + * @param Currency $currency_from if null we used the default currency + * @param Currency $currency_to if null we used the default currency + */ + public static function convertPriceFull($amount, Currency $currency_from = null, Currency $currency_to = null) + { + if ($currency_from === $currency_to) { + return $amount; + } + + if ($currency_from === null) { + $currency_from = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); + } + + if ($currency_to === null) { + $currency_to = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); + } + + if ($currency_from->id == Configuration::get('PS_CURRENCY_DEFAULT')) { + $amount *= $currency_to->conversion_rate; + } else { + $conversion_rate = ($currency_from->conversion_rate == 0 ? 1 : $currency_from->conversion_rate); + // Convert amount to default currency (using the old currency rate) + $amount = $amount / $conversion_rate; + // Convert to new currency + $amount *= $currency_to->conversion_rate; + } + return Tools::ps_round($amount, _PS_PRICE_COMPUTE_PRECISION_); + } + + /** + * Display date regarding to language preferences + * + * @param array $params Date, format... + * @param object $smarty Smarty object for language preferences + * @return string Date + */ + public static function dateFormat($params, &$smarty) + { + return Tools::displayDate($params['date'], null, (isset($params['full']) ? $params['full'] : false)); + } + + /** + * Display date regarding to language preferences + * + * @param string $date Date to display format UNIX + * @param int $id_lang Language id DEPRECATED + * @param bool $full With time or not (optional) + * @param string $separator DEPRECATED + * @return string Date + */ + public static function displayDate($date, $id_lang = null, $full = false, $separator = null) + { + if ($id_lang !== null) { + Tools::displayParameterAsDeprecated('id_lang'); + } + if ($separator !== null) { + Tools::displayParameterAsDeprecated('separator'); + } + + if (!$date || !($time = strtotime($date))) { + return $date; + } + + if ($date == '0000-00-00 00:00:00' || $date == '0000-00-00') { + return ''; + } + + if (!Validate::isDate($date) || !Validate::isBool($full)) { + throw new PrestaShopException('Invalid date'); + } + + $context = Context::getContext(); + $date_format = ($full ? $context->language->date_format_full : $context->language->date_format_lite); + return date($date_format, $time); + } + + /** + * Sanitize a string + * + * @param string $string String to sanitize + * @param bool $full String contains HTML or not (optional) + * @return string Sanitized string + */ + public static function safeOutput($string, $html = false) + { + if (!$html) { + $string = strip_tags($string); + } + return @Tools::htmlentitiesUTF8($string, ENT_QUOTES); + } + + public static function htmlentitiesUTF8($string, $type = ENT_QUOTES) + { + if (is_array($string)) { + return array_map(array('Tools', 'htmlentitiesUTF8'), $string); + } + + return htmlentities((string)$string, $type, 'utf-8'); + } + + public static function htmlentitiesDecodeUTF8($string) + { + if (is_array($string)) { + $string = array_map(array('Tools', 'htmlentitiesDecodeUTF8'), $string); + return (string)array_shift($string); + } + return html_entity_decode((string)$string, ENT_QUOTES, 'utf-8'); + } + + public static function safePostVars() + { + if (!isset($_POST) || !is_array($_POST)) { + $_POST = array(); + } else { + $_POST = array_map(array('Tools', 'htmlentitiesUTF8'), $_POST); + } + } + + /** + * Delete directory and subdirectories + * + * @param string $dirname Directory name + */ + public static function deleteDirectory($dirname, $delete_self = true) + { + $dirname = rtrim($dirname, '/').'/'; + if (file_exists($dirname)) { + if ($files = scandir($dirname)) { + foreach ($files as $file) { + if ($file != '.' && $file != '..' && $file != '.svn') { + if (is_dir($dirname.$file)) { + Tools::deleteDirectory($dirname.$file, true); + } elseif (file_exists($dirname.$file)) { + @chmod($dirname.$file, 0777); // NT ? + unlink($dirname.$file); + } + } + } + if ($delete_self && file_exists($dirname)) { + if (!rmdir($dirname)) { + @chmod($dirname, 0777); // NT ? + return false; + } + } + return true; + } + } + return false; + } + + /** + * Delete file + * + * @param string $file File path + * @param array $exclude_files Excluded files + */ + public static function deleteFile($file, $exclude_files = array()) + { + if (isset($exclude_files) && !is_array($exclude_files)) { + $exclude_files = array($exclude_files); + } + + if (file_exists($file) && is_file($file) && array_search(basename($file), $exclude_files) === false) { + @chmod($file, 0777); // NT ? + unlink($file); + } + } + + /** + * Clear XML cache folder + */ + public static function clearXMLCache() + { + $themes = array(); + foreach (Theme::getThemes() as $theme) { + /** @var Theme $theme */ + $themes[] = $theme->directory; + } + + foreach (scandir(_PS_ROOT_DIR_.'/config/xml') as $file) { + $path_info = pathinfo($file, PATHINFO_EXTENSION); + if (($path_info == 'xml') && ($file != 'default.xml') && !in_array(basename($file, '.'.$path_info), $themes)) { + self::deleteFile(_PS_ROOT_DIR_.'/config/xml/'.$file); + } + } + } + + /** + * Display an error according to an error code + * + * @param string $string Error message + * @param bool $htmlentities By default at true for parsing error message with htmlentities + */ + public static function displayError($string = 'Fatal error', $htmlentities = true, Context $context = null) + { + global $_ERRORS; + + if (is_null($context)) { + $context = Context::getContext(); + } + + @include_once(_PS_TRANSLATIONS_DIR_.$context->language->iso_code.'/errors.php'); + + if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_ && $string == 'Fatal error') { + return ('<pre>'.print_r(debug_backtrace(), true).'</pre>'); + } + if (!is_array($_ERRORS)) { + return $htmlentities ? Tools::htmlentitiesUTF8($string) : $string; + } + $key = md5(str_replace('\'', '\\\'', $string)); + $str = (isset($_ERRORS) && is_array($_ERRORS) && array_key_exists($key, $_ERRORS)) ? $_ERRORS[$key] : $string; + return $htmlentities ? Tools::htmlentitiesUTF8(stripslashes($str)) : $str; + } + + /** + * Display an error with detailed object + * + * @param mixed $object + * @param bool $kill + * @return $object if $kill = false; + */ + public static function dieObject($object, $kill = true) + { + echo '<xmp style="text-align: left;">'; + print_r($object); + echo '</xmp><br />'; + + if ($kill) { + die('END'); + } + + return $object; + } + + /** + * Display a var dump in firebug console + * + * @param object $object Object to display + */ + public static function fd($object, $type = 'log') + { + $types = array('log', 'debug', 'info', 'warn', 'error', 'assert'); + + if (!in_array($type, $types)) { + $type = 'log'; + } + + echo ' <script type="text/javascript"> console.'.$type.'('.Tools::jsonEncode($object).'); </script> '; - } + } - /** - * ALIAS OF dieObject() - Display an error with detailed object - * - * @param object $object Object to display - */ - public static function d($object, $kill = true) - { - return (Tools::dieObject($object, $kill)); - } + /** + * ALIAS OF dieObject() - Display an error with detailed object + * + * @param object $object Object to display + */ + public static function d($object, $kill = true) + { + return (Tools::dieObject($object, $kill)); + } - public static function debug_backtrace($start = 0, $limit = null) - { - $backtrace = debug_backtrace(); - array_shift($backtrace); - for ($i = 0; $i < $start; ++$i) - array_shift($backtrace); + public static function debug_backtrace($start = 0, $limit = null) + { + $backtrace = debug_backtrace(); + array_shift($backtrace); + for ($i = 0; $i < $start; ++$i) { + array_shift($backtrace); + } - echo ' + echo ' <div style="margin:10px;padding:10px;border:1px solid #666666"> <ul>'; - $i = 0; - foreach ($backtrace as $id => $trace) - { - if ((int)$limit && (++$i > $limit )) - break; - $relative_file = (isset($trace['file'])) ? 'in /'.ltrim(str_replace(array(_PS_ROOT_DIR_, '\\'), array('', '/'), $trace['file']), '/') : ''; - $current_line = (isset($trace['line'])) ? ':'.$trace['line'] : ''; + $i = 0; + foreach ($backtrace as $id => $trace) { + if ((int)$limit && (++$i > $limit)) { + break; + } + $relative_file = (isset($trace['file'])) ? 'in /'.ltrim(str_replace(array(_PS_ROOT_DIR_, '\\'), array('', '/'), $trace['file']), '/') : ''; + $current_line = (isset($trace['line'])) ? ':'.$trace['line'] : ''; - echo '<li> + echo '<li> <b>'.((isset($trace['class'])) ? $trace['class'] : '').((isset($trace['type'])) ? $trace['type'] : '').$trace['function'].'</b> '.$relative_file.$current_line.' </li>'; - } - echo '</ul> + } + echo '</ul> </div>'; - } + } - /** - * ALIAS OF dieObject() - Display an error with detailed object but don't stop the execution - * - * @param object $object Object to display - */ - public static function p($object) - { - return (Tools::dieObject($object, false)); - } + /** + * ALIAS OF dieObject() - Display an error with detailed object but don't stop the execution + * + * @param object $object Object to display + */ + public static function p($object) + { + return (Tools::dieObject($object, false)); + } - /** - * Prints object information into error log - * - * @see error_log() - * @param mixed $object - * @param int|null $message_type - * @param string|null $destination - * @param string|null $extra_headers - * @return bool - */ - public static function error_log($object, $message_type = null, $destination = null, $extra_headers = null) - { - return error_log(print_r($object, true), $message_type, $destination, $extra_headers); - } + /** + * Prints object information into error log + * + * @see error_log() + * @param mixed $object + * @param int|null $message_type + * @param string|null $destination + * @param string|null $extra_headers + * @return bool + */ + public static function error_log($object, $message_type = null, $destination = null, $extra_headers = null) + { + return error_log(print_r($object, true), $message_type, $destination, $extra_headers); + } - /** - * Check if submit has been posted - * - * @param string $submit submit name - */ - public static function isSubmit($submit) - { - return ( - isset($_POST[$submit]) || isset($_POST[$submit.'_x']) || isset($_POST[$submit.'_y']) - || isset($_GET[$submit]) || isset($_GET[$submit.'_x']) || isset($_GET[$submit.'_y']) - ); - } + /** + * Check if submit has been posted + * + * @param string $submit submit name + */ + public static function isSubmit($submit) + { + return ( + isset($_POST[$submit]) || isset($_POST[$submit.'_x']) || isset($_POST[$submit.'_y']) + || isset($_GET[$submit]) || isset($_GET[$submit.'_x']) || isset($_GET[$submit.'_y']) + ); + } - /** - * @deprecated 1.5.0 - */ - public static function getMetaTags($id_lang, $page_name, $title = '') - { - Tools::displayAsDeprecated(); - return Meta::getMetaTags($id_lang, $page_name, $title); - } + /** + * @deprecated 1.5.0 + */ + public static function getMetaTags($id_lang, $page_name, $title = '') + { + Tools::displayAsDeprecated(); + return Meta::getMetaTags($id_lang, $page_name, $title); + } - /** - * @deprecated 1.5.0 - */ - public static function getHomeMetaTags($id_lang, $page_name) - { - Tools::displayAsDeprecated(); - return Meta::getHomeMetas($id_lang, $page_name); - } + /** + * @deprecated 1.5.0 + */ + public static function getHomeMetaTags($id_lang, $page_name) + { + Tools::displayAsDeprecated(); + return Meta::getHomeMetas($id_lang, $page_name); + } - /** - * @deprecated 1.5.0 - */ - public static function completeMetaTags($meta_tags, $default_value, Context $context = null) - { - Tools::displayAsDeprecated(); - return Meta::completeMetaTags($meta_tags, $default_value, $context); - } + /** + * @deprecated 1.5.0 + */ + public static function completeMetaTags($meta_tags, $default_value, Context $context = null) + { + Tools::displayAsDeprecated(); + return Meta::completeMetaTags($meta_tags, $default_value, $context); + } - /** - * Encrypt password - * - * @param string $passwd String to encrypt - */ - public static function encrypt($passwd) - { - return md5(_COOKIE_KEY_.$passwd); - } + /** + * Encrypt password + * + * @param string $passwd String to encrypt + */ + public static function encrypt($passwd) + { + return md5(_COOKIE_KEY_.$passwd); + } - /** - * Encrypt data string - * - * @param string $data String to encrypt - */ - public static function encryptIV($data) - { - return md5(_COOKIE_IV_.$data); - } + /** + * Encrypt data string + * + * @param string $data String to encrypt + */ + public static function encryptIV($data) + { + return md5(_COOKIE_IV_.$data); + } - /** - * Get token to prevent CSRF - * - * @param string $token token to encrypt - */ - public static function getToken($page = true, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - if ($page === true) - return (Tools::encrypt($context->customer->id.$context->customer->passwd.$_SERVER['SCRIPT_NAME'])); - else - return (Tools::encrypt($context->customer->id.$context->customer->passwd.$page)); - } + /** + * Get token to prevent CSRF + * + * @param string $token token to encrypt + */ + public static function getToken($page = true, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + if ($page === true) { + return (Tools::encrypt($context->customer->id.$context->customer->passwd.$_SERVER['SCRIPT_NAME'])); + } else { + return (Tools::encrypt($context->customer->id.$context->customer->passwd.$page)); + } + } - /** - * Tokenize a string - * - * @param string $string string to encript - */ - public static function getAdminToken($string) - { - return !empty($string) ? Tools::encrypt($string) : false; - } + /** + * Tokenize a string + * + * @param string $string string to encript + */ + public static function getAdminToken($string) + { + return !empty($string) ? Tools::encrypt($string) : false; + } - public static function getAdminTokenLite($tab, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - return Tools::getAdminToken($tab.(int)Tab::getIdFromClassName($tab).(int)$context->employee->id); - } + public static function getAdminTokenLite($tab, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + return Tools::getAdminToken($tab.(int)Tab::getIdFromClassName($tab).(int)$context->employee->id); + } - public static function getAdminTokenLiteSmarty($params, &$smarty) - { - $context = Context::getContext(); - return Tools::getAdminToken($params['tab'].(int)Tab::getIdFromClassName($params['tab']).(int)$context->employee->id); - } + public static function getAdminTokenLiteSmarty($params, &$smarty) + { + $context = Context::getContext(); + return Tools::getAdminToken($params['tab'].(int)Tab::getIdFromClassName($params['tab']).(int)$context->employee->id); + } - /** - * Get a valid URL to use from BackOffice - * - * @param string $url An URL to use in BackOffice - * @param bool $entites Set to true to use htmlentities function on URL param - */ - public static function getAdminUrl($url = null, $entities = false) - { - $link = Tools::getHttpHost(true).__PS_BASE_URI__; + /** + * Get a valid URL to use from BackOffice + * + * @param string $url An URL to use in BackOffice + * @param bool $entites Set to true to use htmlentities function on URL param + */ + public static function getAdminUrl($url = null, $entities = false) + { + $link = Tools::getHttpHost(true).__PS_BASE_URI__; - if (isset($url)) - $link .= ($entities ? Tools::htmlentitiesUTF8($url) : $url); + if (isset($url)) { + $link .= ($entities ? Tools::htmlentitiesUTF8($url) : $url); + } - return $link; - } + return $link; + } - /** - * Get a valid image URL to use from BackOffice - * - * @param string $image Image name - * @param bool $entites Set to true to use htmlentities function on image param - */ - public static function getAdminImageUrl($image = null, $entities = false) - { - return Tools::getAdminUrl(basename(_PS_IMG_DIR_).'/'.$image, $entities); - } + /** + * Get a valid image URL to use from BackOffice + * + * @param string $image Image name + * @param bool $entites Set to true to use htmlentities function on image param + */ + public static function getAdminImageUrl($image = null, $entities = false) + { + return Tools::getAdminUrl(basename(_PS_IMG_DIR_).'/'.$image, $entities); + } - /** - * Get the user's journey - * - * @param int $id_category Category ID - * @param string $path Path end - * @param bool $linkOntheLastItem Put or not a link on the current category - * @param string [optionnal] $categoryType defined what type of categories is used (products or cms) - */ - public static function getPath($id_category, $path = '', $link_on_the_item = false, $category_type = 'products', Context $context = null) - { - if (!$context) - $context = Context::getContext(); + /** + * Get the user's journey + * + * @param int $id_category Category ID + * @param string $path Path end + * @param bool $linkOntheLastItem Put or not a link on the current category + * @param string [optionnal] $categoryType defined what type of categories is used (products or cms) + */ + public static function getPath($id_category, $path = '', $link_on_the_item = false, $category_type = 'products', Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } - $id_category = (int)$id_category; - if ($id_category == 1) - return '<span class="navigation_end">'.$path.'</span>'; + $id_category = (int)$id_category; + if ($id_category == 1) { + return '<span class="navigation_end">'.$path.'</span>'; + } - $pipe = Configuration::get('PS_NAVIGATION_PIPE'); - if (empty($pipe)) - $pipe = '>'; + $pipe = Configuration::get('PS_NAVIGATION_PIPE'); + if (empty($pipe)) { + $pipe = '>'; + } - $full_path = ''; - if ($category_type === 'products') - { - $interval = Category::getInterval($id_category); - $id_root_category = $context->shop->getCategory(); - $interval_root = Category::getInterval($id_root_category); - if ($interval) - { - $sql = 'SELECT c.id_category, cl.name, cl.link_rewrite + $full_path = ''; + if ($category_type === 'products') { + $interval = Category::getInterval($id_category); + $id_root_category = $context->shop->getCategory(); + $interval_root = Category::getInterval($id_root_category); + if ($interval) { + $sql = 'SELECT c.id_category, cl.name, cl.link_rewrite FROM '._DB_PREFIX_.'category c LEFT JOIN '._DB_PREFIX_.'category_lang cl ON (cl.id_category = c.id_category'.Shop::addSqlRestrictionOnLang('cl').') '.Shop::addSqlAssociation('category', 'c').' @@ -1248,1186 +1298,1223 @@ class ToolsCore AND c.active = 1 AND c.level_depth > '.(int)$interval_root['level_depth'].' ORDER BY c.level_depth ASC'; - $categories = Db::getInstance()->executeS($sql); - - $n = 1; - $n_categories = count($categories); - foreach ($categories as $category) - { - $full_path .= - (($n < $n_categories || $link_on_the_item) ? '<a href="'.Tools::safeOutput($context->link->getCategoryLink((int)$category['id_category'], $category['link_rewrite'])).'" title="'.htmlentities($category['name'], ENT_NOQUOTES, 'UTF-8').'" data-gg="">' : ''). - htmlentities($category['name'], ENT_NOQUOTES, 'UTF-8'). - (($n < $n_categories || $link_on_the_item) ? '</a>' : ''). - (($n++ != $n_categories || !empty($path)) ? '<span class="navigation-pipe">'.$pipe.'</span>' : ''); - } - - return $full_path.$path; - } - } - elseif ($category_type === 'CMS') - { - $category = new CMSCategory($id_category, $context->language->id); - if (!Validate::isLoadedObject($category)) - die(Tools::displayError()); - $category_link = $context->link->getCMSCategoryLink($category); - - if ($path != $category->name) - $full_path .= '<a href="'.Tools::safeOutput($category_link).'" data-gg="">'.htmlentities($category->name, ENT_NOQUOTES, 'UTF-8').'</a><span class="navigation-pipe">'.$pipe.'</span>'.$path; - else - $full_path = ($link_on_the_item ? '<a href="'.Tools::safeOutput($category_link).'" data-gg="">' : '').htmlentities($path, ENT_NOQUOTES, 'UTF-8').($link_on_the_item ? '</a>' : ''); - - return Tools::getPath($category->id_parent, $full_path, $link_on_the_item, $category_type); - } - } - - /** - * @param string [optionnal] $type_cat defined what type of categories is used (products or cms) - */ - public static function getFullPath($id_category, $end, $type_cat = 'products', Context $context = null) - { - if (!$context) - $context = Context::getContext(); - - $id_category = (int)$id_category; - $pipe = (Configuration::get('PS_NAVIGATION_PIPE') ? Configuration::get('PS_NAVIGATION_PIPE') : '>'); - - $default_category = 1; - if ($type_cat === 'products') - { - $default_category = $context->shop->getCategory(); - $category = new Category($id_category, $context->language->id); - } - elseif ($type_cat === 'CMS') - $category = new CMSCategory($id_category, $context->language->id); - - if (!Validate::isLoadedObject($category)) - $id_category = $default_category; - if ($id_category == $default_category) - return htmlentities($end, ENT_NOQUOTES, 'UTF-8'); - - return Tools::getPath($id_category, $category->name, true, $type_cat).'<span class="navigation-pipe">'.$pipe.'</span> <span class="navigation_product">'.htmlentities($end, ENT_NOQUOTES, 'UTF-8').'</span>'; - } - - /** - * Return the friendly url from the provided string - * - * @param string $str - * @param bool $utf8_decode (deprecated) - * @return string - */ - public static function link_rewrite($str, $utf8_decode = null) - { - if ($utf8_decode !== null) - Tools::displayParameterAsDeprecated('utf8_decode'); - return Tools::str2url($str); - } - - /** - * Return a friendly url made from the provided string - * If the mbstring library is available, the output is the same as the js function of the same name - * - * @param string $str - * @return string - */ - public static function str2url($str) - { - static $array_str = array(); - static $allow_accented_chars = null; - static $has_mb_strtolower = null; - - if ($has_mb_strtolower === null) - $has_mb_strtolower = function_exists('mb_strtolower'); - - if (isset($array_str[$str])) - return $array_str[$str]; - - if (!is_string($str)) - return false; - - if ($str == '') - return ''; - - if ($allow_accented_chars === null) - $allow_accented_chars = Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL'); - - $return_str = trim($str); - - if ($has_mb_strtolower) - $return_str = mb_strtolower($return_str, 'utf-8'); - if (!$allow_accented_chars) - $return_str = Tools::replaceAccentedChars($return_str); - - // Remove all non-whitelist chars. - if ($allow_accented_chars) - $return_str = preg_replace('/[^a-zA-Z0-9\s\'\:\/\[\]\-\p{L}]/u', '', $return_str); - else - $return_str = preg_replace('/[^a-zA-Z0-9\s\'\:\/\[\]\-]/','', $return_str); - - $return_str = preg_replace('/[\s\'\:\/\[\]\-]+/', ' ', $return_str); - $return_str = str_replace(array(' ', '/'), '-', $return_str); - - // If it was not possible to lowercase the string with mb_strtolower, we do it after the transformations. - // This way we lose fewer special chars. - if (!$has_mb_strtolower) - $return_str = Tools::strtolower($return_str); - - $array_str[$str] = $return_str; - return $return_str; - } - - /** - * Replace all accented chars by their equivalent non accented chars. - * - * @param string $str - * @return string - */ - public static function replaceAccentedChars($str) - { - /* One source among others: - http://www.tachyonsoft.com/uc0000.htm - http://www.tachyonsoft.com/uc0001.htm - http://www.tachyonsoft.com/uc0004.htm - */ - $patterns = array( - - /* Lowercase */ - /* a */ '/[\x{00E0}\x{00E1}\x{00E2}\x{00E3}\x{00E4}\x{00E5}\x{0101}\x{0103}\x{0105}\x{0430}\x{00C0}-\x{00C3}\x{1EA0}-\x{1EB7}]/u', - /* b */ '/[\x{0431}]/u', - /* c */ '/[\x{00E7}\x{0107}\x{0109}\x{010D}\x{0446}]/u', - /* d */ '/[\x{010F}\x{0111}\x{0434}\x{0110}]/u', - /* e */ '/[\x{00E8}\x{00E9}\x{00EA}\x{00EB}\x{0113}\x{0115}\x{0117}\x{0119}\x{011B}\x{0435}\x{044D}\x{00C8}-\x{00CA}\x{1EB8}-\x{1EC7}]/u', - /* f */ '/[\x{0444}]/u', - /* g */ '/[\x{011F}\x{0121}\x{0123}\x{0433}\x{0491}]/u', - /* h */ '/[\x{0125}\x{0127}]/u', - /* i */ '/[\x{00EC}\x{00ED}\x{00EE}\x{00EF}\x{0129}\x{012B}\x{012D}\x{012F}\x{0131}\x{0438}\x{0456}\x{00CC}\x{00CD}\x{1EC8}-\x{1ECB}\x{0128}]/u', - /* j */ '/[\x{0135}\x{0439}]/u', - /* k */ '/[\x{0137}\x{0138}\x{043A}]/u', - /* l */ '/[\x{013A}\x{013C}\x{013E}\x{0140}\x{0142}\x{043B}]/u', - /* m */ '/[\x{043C}]/u', - /* n */ '/[\x{00F1}\x{0144}\x{0146}\x{0148}\x{0149}\x{014B}\x{043D}]/u', - /* o */ '/[\x{00F2}\x{00F3}\x{00F4}\x{00F5}\x{00F6}\x{00F8}\x{014D}\x{014F}\x{0151}\x{043E}\x{00D2}-\x{00D5}\x{01A0}\x{01A1}\x{1ECC}-\x{1EE3}]/u', - /* p */ '/[\x{043F}]/u', - /* r */ '/[\x{0155}\x{0157}\x{0159}\x{0440}]/u', - /* s */ '/[\x{015B}\x{015D}\x{015F}\x{0161}\x{0441}]/u', - /* ss */ '/[\x{00DF}]/u', - /* t */ '/[\x{0163}\x{0165}\x{0167}\x{0442}]/u', - /* u */ '/[\x{00F9}\x{00FA}\x{00FB}\x{00FC}\x{0169}\x{016B}\x{016D}\x{016F}\x{0171}\x{0173}\x{0443}\x{00D9}-\x{00DA}\x{0168}\x{01AF}\x{01B0}\x{1EE4}-\x{1EF1}]/u', - /* v */ '/[\x{0432}]/u', - /* w */ '/[\x{0175}]/u', - /* y */ '/[\x{00FF}\x{0177}\x{00FD}\x{044B}\x{1EF2}-\x{1EF9}\x{00DD}]/u', - /* z */ '/[\x{017A}\x{017C}\x{017E}\x{0437}]/u', - /* ae */ '/[\x{00E6}]/u', - /* ch */ '/[\x{0447}]/u', - /* kh */ '/[\x{0445}]/u', - /* oe */ '/[\x{0153}]/u', - /* sh */ '/[\x{0448}]/u', - /* shh*/ '/[\x{0449}]/u', - /* ya */ '/[\x{044F}]/u', - /* ye */ '/[\x{0454}]/u', - /* yi */ '/[\x{0457}]/u', - /* yo */ '/[\x{0451}]/u', - /* yu */ '/[\x{044E}]/u', - /* zh */ '/[\x{0436}]/u', - - /* Uppercase */ - /* A */ '/[\x{0100}\x{0102}\x{0104}\x{00C0}\x{00C1}\x{00C2}\x{00C3}\x{00C4}\x{00C5}\x{0410}]/u', - /* B */ '/[\x{0411}]]/u', - /* C */ '/[\x{00C7}\x{0106}\x{0108}\x{010A}\x{010C}\x{0426}]/u', - /* D */ '/[\x{010E}\x{0110}\x{0414}]/u', - /* E */ '/[\x{00C8}\x{00C9}\x{00CA}\x{00CB}\x{0112}\x{0114}\x{0116}\x{0118}\x{011A}\x{0415}\x{042D}]/u', - /* F */ '/[\x{0424}]/u', - /* G */ '/[\x{011C}\x{011E}\x{0120}\x{0122}\x{0413}\x{0490}]/u', - /* H */ '/[\x{0124}\x{0126}]/u', - /* I */ '/[\x{0128}\x{012A}\x{012C}\x{012E}\x{0130}\x{0418}\x{0406}]/u', - /* J */ '/[\x{0134}\x{0419}]/u', - /* K */ '/[\x{0136}\x{041A}]/u', - /* L */ '/[\x{0139}\x{013B}\x{013D}\x{0139}\x{0141}\x{041B}]/u', - /* M */ '/[\x{041C}]/u', - /* N */ '/[\x{00D1}\x{0143}\x{0145}\x{0147}\x{014A}\x{041D}]/u', - /* O */ '/[\x{00D3}\x{014C}\x{014E}\x{0150}\x{041E}]/u', - /* P */ '/[\x{041F}]/u', - /* R */ '/[\x{0154}\x{0156}\x{0158}\x{0420}]/u', - /* S */ '/[\x{015A}\x{015C}\x{015E}\x{0160}\x{0421}]/u', - /* T */ '/[\x{0162}\x{0164}\x{0166}\x{0422}]/u', - /* U */ '/[\x{00D9}\x{00DA}\x{00DB}\x{00DC}\x{0168}\x{016A}\x{016C}\x{016E}\x{0170}\x{0172}\x{0423}]/u', - /* V */ '/[\x{0412}]/u', - /* W */ '/[\x{0174}]/u', - /* Y */ '/[\x{0176}\x{042B}]/u', - /* Z */ '/[\x{0179}\x{017B}\x{017D}\x{0417}]/u', - /* AE */ '/[\x{00C6}]/u', - /* CH */ '/[\x{0427}]/u', - /* KH */ '/[\x{0425}]/u', - /* OE */ '/[\x{0152}]/u', - /* SH */ '/[\x{0428}]/u', - /* SHH*/ '/[\x{0429}]/u', - /* YA */ '/[\x{042F}]/u', - /* YE */ '/[\x{0404}]/u', - /* YI */ '/[\x{0407}]/u', - /* YO */ '/[\x{0401}]/u', - /* YU */ '/[\x{042E}]/u', - /* ZH */ '/[\x{0416}]/u'); - - // ö to oe - // å to aa - // ä to ae - - $replacements = array( - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 'ss', 't', 'u', 'v', 'w', 'y', 'z', 'ae', 'ch', 'kh', 'oe', 'sh', 'shh', 'ya', 'ye', 'yi', 'yo', 'yu', 'zh', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'V', 'W', 'Y', 'Z', 'AE', 'CH', 'KH', 'OE', 'SH', 'SHH', 'YA', 'YE', 'YI', 'YO', 'YU', 'ZH' - ); - - return preg_replace($patterns, $replacements, $str); - } - - /** - * Truncate strings - * - * @param string $str - * @param int $max_length Max length - * @param string $suffix Suffix optional - * @return string $str truncated - */ - /* CAUTION : Use it only on module hookEvents. - ** For other purposes use the smarty function instead */ - public static function truncate($str, $max_length, $suffix = '...') - { - if (Tools::strlen($str) <= $max_length) - return $str; - $str = utf8_decode($str); - return (utf8_encode(substr($str, 0, $max_length - Tools::strlen($suffix)).$suffix)); - } - - /*Copied from CakePHP String utility file*/ - public static function truncateString($text, $length = 120, $options = array()) - { - $default = array( - 'ellipsis' => '...', 'exact' => true, 'html' => true - ); - - $options = array_merge($default, $options); - extract($options); - /** - * @var string $ellipsis - * @var bool $exact - * @var bool $html - */ - - if ($html) - { - if (Tools::strlen(preg_replace('/<.*?>/', '', $text)) <= $length) - return $text; - - $total_length = Tools::strlen(strip_tags($ellipsis)); - $open_tags = array(); - $truncate = ''; - preg_match_all('/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER); - - foreach ($tags as $tag) - { - if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2])) - { - if (preg_match('/<[\w]+[^>]*>/s', $tag[0])) - array_unshift($open_tags, $tag[2]); - elseif (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $close_tag)) - { - $pos = array_search($close_tag[1], $open_tags); - if ($pos !== false) - array_splice($open_tags, $pos, 1); - } - } - $truncate .= $tag[1]; - $content_length = Tools::strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $tag[3])); - - if ($content_length + $total_length > $length) - { - $left = $length - $total_length; - $entities_length = 0; - - if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $tag[3], $entities, PREG_OFFSET_CAPTURE)) - { - foreach ($entities[0] as $entity) - { - if ($entity[1] + 1 - $entities_length <= $left) - { - $left--; - $entities_length += Tools::strlen($entity[0]); - } - else - break; - } - } - - $truncate .= Tools::substr($tag[3], 0, $left + $entities_length); - break; - } - else - { - $truncate .= $tag[3]; - $total_length += $content_length; - } - - if ($total_length >= $length) - break; - } - } - else - { - if (Tools::strlen($text) <= $length) - return $text; - - $truncate = Tools::substr($text, 0, $length - Tools::strlen($ellipsis)); - } - - if (!$exact) - { - $spacepos = Tools::strrpos($truncate, ' '); - if ($html) - { - $truncate_check = Tools::substr($truncate, 0, $spacepos); - $last_open_tag = Tools::strrpos($truncate_check, '<'); - $last_close_tag = Tools::strrpos($truncate_check, '>'); - - if ($last_open_tag > $last_close_tag) - { - preg_match_all('/<[\w]+[^>]*>/s', $truncate, $last_tag_matches); - $last_tag = array_pop($last_tag_matches[0]); - $spacepos = Tools::strrpos($truncate, $last_tag) + Tools::strlen($last_tag); - } - - $bits = Tools::substr($truncate, $spacepos); - preg_match_all('/<\/([a-z]+)>/', $bits, $dropped_tags, PREG_SET_ORDER); - - if (!empty($dropped_tags)) - { - if (!empty($open_tags)) - { - foreach ($dropped_tags as $closing_tag) - if (!in_array($closing_tag[1], $open_tags)) - array_unshift($open_tags, $closing_tag[1]); - } - else - { - foreach ($dropped_tags as $closing_tag) - $open_tags[] = $closing_tag[1]; - } - } - } - - $truncate = Tools::substr($truncate, 0, $spacepos); - } - - $truncate .= $ellipsis; - - if ($html) - foreach ($open_tags as $tag) - $truncate .= '</'.$tag.'>'; - - return $truncate; - } - - public static function normalizeDirectory($directory) - { - return rtrim($directory, '/\\').DIRECTORY_SEPARATOR; - } - - /** - * Generate date form - * - * @param int $year Year to select - * @param int $month Month to select - * @param int $day Day to select - * @return array $tab html data with 3 cells :['days'], ['months'], ['years'] - * - */ - public static function dateYears() - { - $tab = array(); - for ($i = date('Y'); $i >= 1900; $i--) - $tab[] = $i; - return $tab; - } - - public static function dateDays() - { - $tab = array(); - for ($i = 1; $i != 32; $i++) - $tab[] = $i; - return $tab; - } - - public static function dateMonths() - { - $tab = array(); - for ($i = 1; $i != 13; $i++) - $tab[$i] = date('F', mktime(0, 0, 0, $i, date('m'), date('Y'))); - return $tab; - } - - public static function hourGenerate($hours, $minutes, $seconds) - { - return implode(':', array($hours, $minutes, $seconds)); - } - - public static function dateFrom($date) - { - $tab = explode(' ', $date); - if (!isset($tab[1])) - $date .= ' '.Tools::hourGenerate(0, 0, 0); - return $date; - } - - public static function dateTo($date) - { - $tab = explode(' ', $date); - if (!isset($tab[1])) - $date .= ' '.Tools::hourGenerate(23, 59, 59); - return $date; - } - - public static function strtolower($str) - { - if (is_array($str)) - return false; - if (function_exists('mb_strtolower')) - return mb_strtolower($str, 'utf-8'); - return strtolower($str); - } - - public static function strlen($str, $encoding = 'UTF-8') - { - if (is_array($str)) - return false; - $str = html_entity_decode($str, ENT_COMPAT, 'UTF-8'); - if (function_exists('mb_strlen')) - return mb_strlen($str, $encoding); - return strlen($str); - } - - public static function stripslashes($string) - { - if (_PS_MAGIC_QUOTES_GPC_) - $string = stripslashes($string); - return $string; - } - - public static function strtoupper($str) - { - if (is_array($str)) - return false; - if (function_exists('mb_strtoupper')) - return mb_strtoupper($str, 'utf-8'); - return strtoupper($str); - } - - public static function substr($str, $start, $length = false, $encoding = 'utf-8') - { - if (is_array($str)) - return false; - if (function_exists('mb_substr')) - return mb_substr($str, (int)$start, ($length === false ? Tools::strlen($str) : (int)$length), $encoding); - return substr($str, $start, ($length === false ? Tools::strlen($str) : (int)$length)); - } - - public static function strpos($str, $find, $offset = 0, $encoding = 'UTF-8') - { - if (function_exists('mb_strpos')) - return mb_strpos($str, $find, $offset, $encoding); - return strpos($str, $find, $offset); - } - - public static function strrpos($str, $find, $offset = 0, $encoding = 'utf-8') - { - if (function_exists('mb_strrpos')) - return mb_strrpos($str, $find, $offset, $encoding); - return strrpos($str, $find, $offset); - } - - public static function ucfirst($str) - { - return Tools::strtoupper(Tools::substr($str, 0, 1)).Tools::substr($str, 1); - } - - public static function ucwords($str) - { - if (function_exists('mb_convert_case')) - return mb_convert_case($str, MB_CASE_TITLE); - return ucwords(Tools::strtolower($str)); - } - - public static function orderbyPrice(&$array, $order_way) - { - foreach ($array as &$row) - $row['price_tmp'] = Product::getPriceStatic($row['id_product'], true, ((isset($row['id_product_attribute']) && !empty($row['id_product_attribute'])) ? (int)$row['id_product_attribute'] : null), 2); - - unset($row); - - if (Tools::strtolower($order_way) == 'desc') - uasort($array, 'cmpPriceDesc'); - else - uasort($array, 'cmpPriceAsc'); - foreach ($array as &$row) - unset($row['price_tmp']); - } - - public static function iconv($from, $to, $string) - { - if (function_exists('iconv')) - return iconv($from, $to.'//TRANSLIT', str_replace('¥', '¥', str_replace('£', '£', str_replace('€', '€', $string)))); - return html_entity_decode(htmlentities($string, ENT_NOQUOTES, $from), ENT_NOQUOTES, $to); - } - - public static function isEmpty($field) - { - return ($field === '' || $field === null); - } - - /** - * returns the rounded value of $value to specified precision, according to your configuration; - * - * @note : PHP 5.3.0 introduce a 3rd parameter mode in round function - * - * @param float $value - * @param int $precision - * @return float - */ - public static function ps_round($value, $precision = 0, $round_mode = null) - { - if ($round_mode === null) - { - if (Tools::$round_mode == null) - Tools::$round_mode = (int)Configuration::get('PS_PRICE_ROUND_MODE'); - - $round_mode = Tools::$round_mode; - } - - switch ($round_mode) - { - case PS_ROUND_UP: - return Tools::ceilf($value, $precision); - case PS_ROUND_DOWN: - return Tools::floorf($value, $precision); - case PS_ROUND_HALF_DOWN: - case PS_ROUND_HALF_EVEN: - case PS_ROUND_HALF_ODD: - return Tools::math_round($value, $precision, $round_mode); - case PS_ROUND_HALF_UP: - default: - return Tools::math_round($value, $precision, PS_ROUND_HALF_UP); - } - } - - public static function math_round($value, $places, $mode = PS_ROUND_HALF_UP) - { - //If PHP_ROUND_HALF_UP exist (PHP 5.3) use it and pass correct mode value (PrestaShop define - 1) - if (defined('PHP_ROUND_HALF_UP')) - return round($value, $places, $mode - 1); - - $precision_places = 14 - floor(log10(abs($value))); - $f1 = pow(10.0, (double)abs($places)); - - /* If the decimal precision guaranteed by FP arithmetic is higher than - * the requested places BUT is small enough to make sure a non-zero value - * is returned, pre-round the result to the precision */ - if ($precision_places > $places && $precision_places - $places < 15) - { - $f2 = pow(10.0, (double)abs($precision_places)); - - if ($precision_places >= 0) - $tmp_value = $value * $f2; - else - $tmp_value = $value / $f2; - - /* preround the result (tmp_value will always be something * 1e14, - * thus never larger than 1e15 here) */ - $tmp_value = Tools::round_helper($tmp_value, $mode); - /* now correctly move the decimal point */ - $f2 = pow(10.0, (double)abs($places - $precision_places)); - /* because places < precision_places */ - $tmp_value = $tmp_value / $f2; - } - else - { - /* adjust the value */ - if ($places >= 0) - $tmp_value = $value * $f1; - else - $tmp_value = $value / $f1; - - /* This value is beyond our precision, so rounding it is pointless */ - if (abs($tmp_value) >= 1e15) - return $value; - } - - /* round the temp value */ - $tmp_value = Tools::round_helper($tmp_value, $mode); - - /* see if it makes sense to use simple division to round the value */ - if (abs($places) < 23) - { - if ($places > 0) - $tmp_value /= $f1; - else - $tmp_value *= $f1; - } - - return $tmp_value; - } - - public static function round_helper($value, $mode) - { - if ($value >= 0.0) - { - $tmp_value = floor($value + 0.5); - - if (($mode == PS_ROUND_HALF_DOWN && $value == (-0.5 + $tmp_value )) || - ($mode == PS_ROUND_HALF_EVEN && $value == (0.5 + 2 * floor($tmp_value / 2.0))) || - ($mode == PS_ROUND_HALF_ODD && $value == (0.5 + 2 * floor($tmp_value / 2.0) - 1.0))) - $tmp_value = $tmp_value - 1.0; - } - else - { - $tmp_value = ceil($value - 0.5); - - if (($mode == PS_ROUND_HALF_DOWN && $value == (0.5 + $tmp_value )) || - ($mode == PS_ROUND_HALF_EVEN && $value == (-0.5 + 2 * ceil($tmp_value / 2.0))) || - ($mode == PS_ROUND_HALF_ODD && $value == (-0.5 + 2 * ceil($tmp_value / 2.0) + 1.0))) - $tmp_value = $tmp_value + 1.0; - } - - return $tmp_value; - } - - /** - * returns the rounded value down of $value to specified precision - * - * @param float $value - * @param int $precision - * @return float - */ - public static function ceilf($value, $precision = 0) - { - $precision_factor = $precision == 0 ? 1 : pow(10, $precision); - $tmp = $value * $precision_factor; - $tmp2 = (string)$tmp; - // If the current value has already the desired precision - if (strpos($tmp2, '.') === false) - return ($value); - if ($tmp2[strlen($tmp2) - 1] == 0) - return $value; - return ceil($tmp) / $precision_factor; - } - - /** - * returns the rounded value up of $value to specified precision - * - * @param float $value - * @param int $precision - * @return float - */ - public static function floorf($value, $precision = 0) - { - $precision_factor = $precision == 0 ? 1 : pow(10, $precision); - $tmp = $value * $precision_factor; - $tmp2 = (string)$tmp; - // If the current value has already the desired precision - if (strpos($tmp2, '.') === false) - return ($value); - if ($tmp2[strlen($tmp2) - 1] == 0) - return $value; - return floor($tmp) / $precision_factor; - } - - /** - * file_exists() wrapper with cache to speedup performance - * - * @param string $filename File name - * @return bool Cached result of file_exists($filename) - */ - public static function file_exists_cache($filename) - { - if (!isset(self::$file_exists_cache[$filename])) - self::$file_exists_cache[$filename] = file_exists($filename); - return self::$file_exists_cache[$filename]; - } - - /** - * file_exists() wrapper with a call to clearstatcache prior - * - * @param string $filename File name - * @return bool Cached result of file_exists($filename) - */ - public static function file_exists_no_cache($filename) - { - clearstatcache(); - return file_exists($filename); - } - - public static function file_get_contents($url, $use_include_path = false, $stream_context = null, $curl_timeout = 5) - { - if ($stream_context == null && preg_match('/^https?:\/\//', $url)) - $stream_context = @stream_context_create(array('http' => array('timeout' => $curl_timeout))); - if (in_array(ini_get('allow_url_fopen'), array('On', 'on', '1')) || !preg_match('/^https?:\/\//', $url)) - return @file_get_contents($url, $use_include_path, $stream_context); - elseif (function_exists('curl_init')) - { - $curl = curl_init(); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($curl, CURLOPT_URL, $url); - curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5); - curl_setopt($curl, CURLOPT_TIMEOUT, $curl_timeout); - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); - if ($stream_context != null) - { - $opts = stream_context_get_options($stream_context); - if (isset($opts['http']['method']) && Tools::strtolower($opts['http']['method']) == 'post') - { - curl_setopt($curl, CURLOPT_POST, true); - if (isset($opts['http']['content'])) - { - parse_str($opts['http']['content'], $post_data); - curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data); - } - } - } - $content = curl_exec($curl); - curl_close($curl); - return $content; - } - else - return false; - } - - public static function simplexml_load_file($url, $class_name = null) - { - $cache_id = 'Tools::simplexml_load_file'.$url; - if (!Cache::isStored($cache_id)) - { - $result = @simplexml_load_string(Tools::file_get_contents($url), $class_name); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } - - public static function copy($source, $destination, $stream_context = null) - { - if (is_null($stream_context) && !preg_match('/^https?:\/\//', $source)) - return @copy($source, $destination); - return @file_put_contents($destination, Tools::file_get_contents($source, false, $stream_context)); - } - - /** - * @deprecated as of 1.5 use Media::minifyHTML() - */ - public static function minifyHTML($html_content) - { - Tools::displayAsDeprecated(); - return Media::minifyHTML($html_content); - } - - /** - * Translates a string with underscores into camel case (e.g. first_name -> firstName) - * @prototype string public static function toCamelCase(string $str[, bool $capitalise_first_char = false]) - */ - public static function toCamelCase($str, $catapitalise_first_char = false) - { - $str = Tools::strtolower($str); - if ($catapitalise_first_char) - $str = Tools::ucfirst($str); - return preg_replace_callback('/_+([a-z])/', create_function('$c', 'return strtoupper($c[1]);'), $str); - } - - /** - * Transform a CamelCase string to underscore_case string - * - * @param string $string - * @return string - */ - public static function toUnderscoreCase($string) - { - // 'CMSCategories' => 'cms_categories' - // 'RangePrice' => 'range_price' - return Tools::strtolower(trim(preg_replace('/([A-Z][a-z])/', '_$1', $string), '_')); - } - - public static function getBrightness($hex) - { - if (Tools::strtolower($hex) == 'transparent') - return '129'; - - $hex = str_replace('#', '', $hex); - $r = hexdec(substr($hex, 0, 2)); - $g = hexdec(substr($hex, 2, 2)); - $b = hexdec(substr($hex, 4, 2)); - return (($r * 299) + ($g * 587) + ($b * 114)) / 1000; - } - - /** - * @deprecated as of 1.5 use Media::minifyHTMLpregCallback() - */ - public static function minifyHTMLpregCallback($preg_matches) - { - Tools::displayAsDeprecated(); - return Media::minifyHTMLpregCallback($preg_matches); - } - - /** - * @deprecated as of 1.5 use Media::packJSinHTML() - */ - public static function packJSinHTML($html_content) - { - Tools::displayAsDeprecated(); - return Media::packJSinHTML($html_content); - } - - /** - * @deprecated as of 1.5 use Media::packJSinHTMLpregCallback() - */ - public static function packJSinHTMLpregCallback($preg_matches) - { - Tools::displayAsDeprecated(); - return Media::packJSinHTMLpregCallback($preg_matches); - } - - /** - * @deprecated as of 1.5 use Media::packJS() - */ - public static function packJS($js_content) - { - Tools::displayAsDeprecated(); - return Media::packJS($js_content); - } - - - public static function parserSQL($sql) - { - if (strlen($sql) > 0) - { - require_once(_PS_TOOL_DIR_.'parser_sql/PHPSQLParser.php'); - $parser = new PHPSQLParser($sql); - return $parser->parsed; - } - return false; - } - - /** - * @deprecated as of 1.5 use Media::minifyCSS() - */ - public static function minifyCSS($css_content, $fileuri = false) - { - Tools::displayAsDeprecated(); - return Media::minifyCSS($css_content, $fileuri); - } - - public static function replaceByAbsoluteURL($matches) - { - global $current_css_file; - $protocol_link = Tools::getCurrentUrlProtocolPrefix(); - - if (array_key_exists(1, $matches) && array_key_exists(2, $matches)) - { - if (!preg_match('/^(?:https?:)?\/\//iUs', $matches[2])) - { - $sep = '/'; - $tmp = substr($matches[2], 0, 1) == $sep ? $matches[2] : dirname($current_css_file).$sep.ltrim($matches[2], $sep); - $server = Tools::getMediaServer($tmp); - return $matches[1].$protocol_link.$server.$tmp; - } - else - return $matches[0]; - } - return false; - } - - /** - * addJS load a javascript file in the header - * - * @deprecated as of 1.5 use FrontController->addJS() - * @param mixed $js_uri - * @return void - */ - public static function addJS($js_uri) - { - Tools::displayAsDeprecated(); - $context = Context::getContext(); - $context->controller->addJs($js_uri); - } - - /** - * @deprecated as of 1.5 use FrontController->addCSS() - */ - public static function addCSS($css_uri, $css_media_type = 'all') - { - Tools::displayAsDeprecated(); - $context = Context::getContext(); - $context->controller->addCSS($css_uri, $css_media_type); - } - - /** - * @deprecated as of 1.5 use Media::cccCss() - */ - public static function cccCss($css_files) - { - Tools::displayAsDeprecated(); - return Media::cccCss($css_files); - } - - - /** - * @deprecated as of 1.5 use Media::cccJS() - */ - public static function cccJS($js_files) - { - Tools::displayAsDeprecated(); - return Media::cccJS($js_files); - } - - protected static $_cache_nb_media_servers = null; - - public static function getMediaServer($filename) - { - if (self::$_cache_nb_media_servers === null && defined('_MEDIA_SERVER_1_') && defined('_MEDIA_SERVER_2_') && defined('_MEDIA_SERVER_3_')) - { - if (_MEDIA_SERVER_1_ == '') - self::$_cache_nb_media_servers = 0; - elseif (_MEDIA_SERVER_2_ == '') - self::$_cache_nb_media_servers = 1; - elseif (_MEDIA_SERVER_3_ == '') - self::$_cache_nb_media_servers = 2; - else - self::$_cache_nb_media_servers = 3; - } - - if ($filename && self::$_cache_nb_media_servers && ($id_media_server = (abs(crc32($filename)) % self::$_cache_nb_media_servers + 1))) - return constant('_MEDIA_SERVER_'.$id_media_server.'_'); - - return Tools::usingSecureMode() ? Tools::getShopDomainSSL() : Tools::getShopDomain(); - } - - public static function generateHtaccess($path = null, $rewrite_settings = null, $cache_control = null, $specific = '', $disable_multiviews = null, $medias = false, $disable_modsec = null) - { - if (defined('PS_INSTALLATION_IN_PROGRESS') && $rewrite_settings === null) - return true; - - // Default values for parameters - if (is_null($path)) - $path = _PS_ROOT_DIR_.'/.htaccess'; - - if (is_null($cache_control)) - $cache_control = (int)Configuration::get('PS_HTACCESS_CACHE_CONTROL'); - if (is_null($disable_multiviews)) - $disable_multiviews = (int)Configuration::get('PS_HTACCESS_DISABLE_MULTIVIEWS'); - - if ($disable_modsec === null) - $disable_modsec = (int)Configuration::get('PS_HTACCESS_DISABLE_MODSEC'); - - // Check current content of .htaccess and save all code outside of prestashop comments - $specific_before = $specific_after = ''; - if (file_exists($path)) - { - $content = file_get_contents($path); - if (preg_match('#^(.*)\# ~~start~~.*\# ~~end~~[^\n]*(.*)$#s', $content, $m)) - { - $specific_before = $m[1]; - $specific_after = $m[2]; - } - else - { - // For retrocompatibility - if (preg_match('#\# http://www\.prestashop\.com - http://www\.prestashop\.com/forums\s*(.*)<IfModule mod_rewrite\.c>#si', $content, $m)) - $specific_before = $m[1]; - else - $specific_before = $content; - } - } - - // Write .htaccess data - if (!$write_fd = @fopen($path, 'w')) - return false; - if ($specific_before) - fwrite($write_fd, trim($specific_before)."\n\n"); - - $domains = array(); - foreach (ShopUrl::getShopUrls() as $shop_url) - { - /** @var ShopUrl $shop_url */ - if (!isset($domains[$shop_url->domain])) - $domains[$shop_url->domain] = array(); - - $domains[$shop_url->domain][] = array( - 'physical' => $shop_url->physical_uri, - 'virtual' => $shop_url->virtual_uri, - 'id_shop' => $shop_url->id_shop - ); - - if ($shop_url->domain == $shop_url->domain_ssl) - continue; - - if (!isset($domains[$shop_url->domain_ssl])) - $domains[$shop_url->domain_ssl] = array(); - - $domains[$shop_url->domain_ssl][] = array( - 'physical' => $shop_url->physical_uri, - 'virtual' => $shop_url->virtual_uri, - 'id_shop' => $shop_url->id_shop - ); - } - - // Write data in .htaccess file - fwrite($write_fd, "# ~~start~~ Do not remove this comment, Prestashop will keep automatically the code outside this comment when .htaccess will be generated again\n"); - fwrite($write_fd, "# .htaccess automaticaly generated by PrestaShop e-commerce open-source solution\n"); - fwrite($write_fd, "# http://www.prestashop.com - http://www.prestashop.com/forums\n\n"); - - if ($disable_modsec) - fwrite($write_fd, "<IfModule mod_security.c>\nSecFilterEngine Off\nSecFilterScanPOST Off\n</IfModule>\n\n"); - - // RewriteEngine - fwrite($write_fd, "<IfModule mod_rewrite.c>\n"); - - // Ensure HTTP_MOD_REWRITE variable is set in environment - fwrite($write_fd, "<IfModule mod_env.c>\n"); - fwrite($write_fd, "SetEnv HTTP_MOD_REWRITE On\n"); - fwrite($write_fd, "</IfModule>\n\n"); - - // Disable multiviews ? - if ($disable_multiviews) - fwrite($write_fd, "\n# Disable Multiviews\nOptions -Multiviews\n\n"); - - fwrite($write_fd, "RewriteEngine on\n"); - - if (!$medias && defined('_MEDIA_SERVER_1_') && defined('_MEDIA_SERVER_2_') && defined('_MEDIA_SERVER_3_')) - $medias = array(_MEDIA_SERVER_1_, _MEDIA_SERVER_2_, _MEDIA_SERVER_3_); - - $media_domains = ''; - if ($medias[0] != '') - $media_domains = 'RewriteCond %{HTTP_HOST} ^'.$medias[0].'$ [OR]'."\n"; - if ($medias[1] != '') - $media_domains .= 'RewriteCond %{HTTP_HOST} ^'.$medias[1].'$ [OR]'."\n"; - if ($medias[2] != '') - $media_domains .= 'RewriteCond %{HTTP_HOST} ^'.$medias[2].'$ [OR]'."\n"; - - if (Configuration::get('PS_WEBSERVICE_CGI_HOST')) - fwrite($write_fd, "RewriteCond %{HTTP:Authorization} ^(.*)\nRewriteRule . - [E=HTTP_AUTHORIZATION:%1]\n\n"); - - foreach ($domains as $domain => $list_uri) - { - $physicals = array(); - foreach ($list_uri as $uri) - { - fwrite($write_fd, PHP_EOL.PHP_EOL.'#Domain: '.$domain.PHP_EOL); - if (Shop::isFeatureActive()) - fwrite($write_fd, 'RewriteCond %{HTTP_HOST} ^'.$domain.'$'."\n"); - fwrite($write_fd, 'RewriteRule . - [E=REWRITEBASE:'.$uri['physical'].']'."\n"); - - // Webservice - fwrite($write_fd, 'RewriteRule ^api$ api/ [L]'."\n\n"); - fwrite($write_fd, 'RewriteRule ^api/(.*)$ %{ENV:REWRITEBASE}webservice/dispatcher.php?url=$1 [QSA,L]'."\n\n"); - - if (!$rewrite_settings) - $rewrite_settings = (int)Configuration::get('PS_REWRITING_SETTINGS', null, null, (int)$uri['id_shop']); - - $domain_rewrite_cond = 'RewriteCond %{HTTP_HOST} ^'.$domain.'$'."\n"; - // Rewrite virtual multishop uri - if ($uri['virtual']) - { - if (!$rewrite_settings) - { - fwrite($write_fd, $media_domains); - if (Shop::isFeatureActive()) - fwrite($write_fd, $domain_rewrite_cond); - fwrite($write_fd, 'RewriteRule ^'.trim($uri['virtual'], '/').'/?$ '.$uri['physical'].$uri['virtual']."index.php [L,R]\n"); - } - else - { - fwrite($write_fd, $media_domains); - if (Shop::isFeatureActive()) - fwrite($write_fd, $domain_rewrite_cond); - fwrite($write_fd, 'RewriteRule ^'.trim($uri['virtual'], '/').'$ '.$uri['physical'].$uri['virtual']." [L,R]\n"); - } - fwrite($write_fd, $media_domains); - if (Shop::isFeatureActive()) - fwrite($write_fd, $domain_rewrite_cond); - fwrite($write_fd, 'RewriteRule ^'.ltrim($uri['virtual'], '/').'(.*) '.$uri['physical']."$1 [L]\n\n"); - } - - if ($rewrite_settings) - { - // Compatibility with the old image filesystem - fwrite($write_fd, "# Images\n"); - if (Configuration::get('PS_LEGACY_IMAGES')) - { - fwrite($write_fd, $media_domains); - if (Shop::isFeatureActive()) - fwrite($write_fd, $domain_rewrite_cond); - fwrite($write_fd, 'RewriteRule ^([a-z0-9]+)\-([a-z0-9]+)(\-[_a-zA-Z0-9-]*)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1-$2$3$4.jpg [L]'."\n"); - fwrite($write_fd, $media_domains); - if (Shop::isFeatureActive()) - fwrite($write_fd, $domain_rewrite_cond); - fwrite($write_fd, 'RewriteRule ^([0-9]+)\-([0-9]+)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1-$2$3.jpg [L]'."\n"); - } - - // Rewrite product images < 100 millions - for ($i = 1; $i <= 8; $i++) - { - $img_path = $img_name = ''; - for ($j = 1; $j <= $i; $j++) - { - $img_path .= '$'.$j.'/'; - $img_name .= '$'.$j; - } - $img_name .= '$'.$j; - fwrite($write_fd, $media_domains); - if (Shop::isFeatureActive()) - fwrite($write_fd, $domain_rewrite_cond); - fwrite($write_fd, 'RewriteRule ^'.str_repeat('([0-9])', $i).'(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/'.$img_path.$img_name.'$'.($j + 1).".jpg [L]\n"); - } - fwrite($write_fd, $media_domains); - if (Shop::isFeatureActive()) - fwrite($write_fd, $domain_rewrite_cond); - fwrite($write_fd, 'RewriteRule ^c/([0-9]+)(\-[\.*_a-zA-Z0-9-]*)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/c/$1$2$3.jpg [L]'."\n"); - fwrite($write_fd, $media_domains); - if (Shop::isFeatureActive()) - fwrite($write_fd, $domain_rewrite_cond); - fwrite($write_fd, 'RewriteRule ^c/([a-zA-Z_-]+)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/c/$1$2.jpg [L]'."\n"); - } - - fwrite($write_fd, "# AlphaImageLoader for IE and fancybox\n"); - if (Shop::isFeatureActive()) - fwrite($write_fd, $domain_rewrite_cond); - fwrite($write_fd, 'RewriteRule ^images_ie/?([^/]+)\.(jpe?g|png|gif)$ js/jquery/plugins/fancybox/images/$1.$2 [L]'."\n"); - } - // Redirections to dispatcher - if ($rewrite_settings) - { - fwrite($write_fd, "\n# Dispatcher\n"); - fwrite($write_fd, "RewriteCond %{REQUEST_FILENAME} -s [OR]\n"); - fwrite($write_fd, "RewriteCond %{REQUEST_FILENAME} -l [OR]\n"); - fwrite($write_fd, "RewriteCond %{REQUEST_FILENAME} -d\n"); - if (Shop::isFeatureActive()) - fwrite($write_fd, $domain_rewrite_cond); - fwrite($write_fd, "RewriteRule ^.*$ - [NC,L]\n"); - if (Shop::isFeatureActive()) - fwrite($write_fd, $domain_rewrite_cond); - fwrite($write_fd, "RewriteRule ^.*\$ %{ENV:REWRITEBASE}index.php [NC,L]\n"); - } - } - - fwrite($write_fd, "</IfModule>\n\n"); - - fwrite($write_fd, "AddType application/vnd.ms-fontobject .eot\n"); - fwrite($write_fd, "AddType font/ttf .ttf\n"); - fwrite($write_fd, "AddType font/otf .otf\n"); - fwrite($write_fd, "AddType application/x-font-woff .woff\n"); - fwrite($write_fd, "<IfModule mod_headers.c> + $categories = Db::getInstance()->executeS($sql); + + $n = 1; + $n_categories = count($categories); + foreach ($categories as $category) { + $full_path .= + (($n < $n_categories || $link_on_the_item) ? '<a href="'.Tools::safeOutput($context->link->getCategoryLink((int)$category['id_category'], $category['link_rewrite'])).'" title="'.htmlentities($category['name'], ENT_NOQUOTES, 'UTF-8').'" data-gg="">' : ''). + htmlentities($category['name'], ENT_NOQUOTES, 'UTF-8'). + (($n < $n_categories || $link_on_the_item) ? '</a>' : ''). + (($n++ != $n_categories || !empty($path)) ? '<span class="navigation-pipe">'.$pipe.'</span>' : ''); + } + + return $full_path.$path; + } + } elseif ($category_type === 'CMS') { + $category = new CMSCategory($id_category, $context->language->id); + if (!Validate::isLoadedObject($category)) { + die(Tools::displayError()); + } + $category_link = $context->link->getCMSCategoryLink($category); + + if ($path != $category->name) { + $full_path .= '<a href="'.Tools::safeOutput($category_link).'" data-gg="">'.htmlentities($category->name, ENT_NOQUOTES, 'UTF-8').'</a><span class="navigation-pipe">'.$pipe.'</span>'.$path; + } else { + $full_path = ($link_on_the_item ? '<a href="'.Tools::safeOutput($category_link).'" data-gg="">' : '').htmlentities($path, ENT_NOQUOTES, 'UTF-8').($link_on_the_item ? '</a>' : ''); + } + + return Tools::getPath($category->id_parent, $full_path, $link_on_the_item, $category_type); + } + } + + /** + * @param string [optionnal] $type_cat defined what type of categories is used (products or cms) + */ + public static function getFullPath($id_category, $end, $type_cat = 'products', Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + + $id_category = (int)$id_category; + $pipe = (Configuration::get('PS_NAVIGATION_PIPE') ? Configuration::get('PS_NAVIGATION_PIPE') : '>'); + + $default_category = 1; + if ($type_cat === 'products') { + $default_category = $context->shop->getCategory(); + $category = new Category($id_category, $context->language->id); + } elseif ($type_cat === 'CMS') { + $category = new CMSCategory($id_category, $context->language->id); + } + + if (!Validate::isLoadedObject($category)) { + $id_category = $default_category; + } + if ($id_category == $default_category) { + return htmlentities($end, ENT_NOQUOTES, 'UTF-8'); + } + + return Tools::getPath($id_category, $category->name, true, $type_cat).'<span class="navigation-pipe">'.$pipe.'</span> <span class="navigation_product">'.htmlentities($end, ENT_NOQUOTES, 'UTF-8').'</span>'; + } + + /** + * Return the friendly url from the provided string + * + * @param string $str + * @param bool $utf8_decode (deprecated) + * @return string + */ + public static function link_rewrite($str, $utf8_decode = null) + { + if ($utf8_decode !== null) { + Tools::displayParameterAsDeprecated('utf8_decode'); + } + return Tools::str2url($str); + } + + /** + * Return a friendly url made from the provided string + * If the mbstring library is available, the output is the same as the js function of the same name + * + * @param string $str + * @return string + */ + public static function str2url($str) + { + static $array_str = array(); + static $allow_accented_chars = null; + static $has_mb_strtolower = null; + + if ($has_mb_strtolower === null) { + $has_mb_strtolower = function_exists('mb_strtolower'); + } + + if (isset($array_str[$str])) { + return $array_str[$str]; + } + + if (!is_string($str)) { + return false; + } + + if ($str == '') { + return ''; + } + + if ($allow_accented_chars === null) { + $allow_accented_chars = Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL'); + } + + $return_str = trim($str); + + if ($has_mb_strtolower) { + $return_str = mb_strtolower($return_str, 'utf-8'); + } + if (!$allow_accented_chars) { + $return_str = Tools::replaceAccentedChars($return_str); + } + + // Remove all non-whitelist chars. + if ($allow_accented_chars) { + $return_str = preg_replace('/[^a-zA-Z0-9\s\'\:\/\[\]\-\p{L}]/u', '', $return_str); + } else { + $return_str = preg_replace('/[^a-zA-Z0-9\s\'\:\/\[\]\-]/', '', $return_str); + } + + $return_str = preg_replace('/[\s\'\:\/\[\]\-]+/', ' ', $return_str); + $return_str = str_replace(array(' ', '/'), '-', $return_str); + + // If it was not possible to lowercase the string with mb_strtolower, we do it after the transformations. + // This way we lose fewer special chars. + if (!$has_mb_strtolower) { + $return_str = Tools::strtolower($return_str); + } + + $array_str[$str] = $return_str; + return $return_str; + } + + /** + * Replace all accented chars by their equivalent non accented chars. + * + * @param string $str + * @return string + */ + public static function replaceAccentedChars($str) + { + /* One source among others: + http://www.tachyonsoft.com/uc0000.htm + http://www.tachyonsoft.com/uc0001.htm + http://www.tachyonsoft.com/uc0004.htm + */ + $patterns = array( + + /* Lowercase */ + /* a */ '/[\x{00E0}\x{00E1}\x{00E2}\x{00E3}\x{00E4}\x{00E5}\x{0101}\x{0103}\x{0105}\x{0430}\x{00C0}-\x{00C3}\x{1EA0}-\x{1EB7}]/u', + /* b */ '/[\x{0431}]/u', + /* c */ '/[\x{00E7}\x{0107}\x{0109}\x{010D}\x{0446}]/u', + /* d */ '/[\x{010F}\x{0111}\x{0434}\x{0110}]/u', + /* e */ '/[\x{00E8}\x{00E9}\x{00EA}\x{00EB}\x{0113}\x{0115}\x{0117}\x{0119}\x{011B}\x{0435}\x{044D}\x{00C8}-\x{00CA}\x{1EB8}-\x{1EC7}]/u', + /* f */ '/[\x{0444}]/u', + /* g */ '/[\x{011F}\x{0121}\x{0123}\x{0433}\x{0491}]/u', + /* h */ '/[\x{0125}\x{0127}]/u', + /* i */ '/[\x{00EC}\x{00ED}\x{00EE}\x{00EF}\x{0129}\x{012B}\x{012D}\x{012F}\x{0131}\x{0438}\x{0456}\x{00CC}\x{00CD}\x{1EC8}-\x{1ECB}\x{0128}]/u', + /* j */ '/[\x{0135}\x{0439}]/u', + /* k */ '/[\x{0137}\x{0138}\x{043A}]/u', + /* l */ '/[\x{013A}\x{013C}\x{013E}\x{0140}\x{0142}\x{043B}]/u', + /* m */ '/[\x{043C}]/u', + /* n */ '/[\x{00F1}\x{0144}\x{0146}\x{0148}\x{0149}\x{014B}\x{043D}]/u', + /* o */ '/[\x{00F2}\x{00F3}\x{00F4}\x{00F5}\x{00F6}\x{00F8}\x{014D}\x{014F}\x{0151}\x{043E}\x{00D2}-\x{00D5}\x{01A0}\x{01A1}\x{1ECC}-\x{1EE3}]/u', + /* p */ '/[\x{043F}]/u', + /* r */ '/[\x{0155}\x{0157}\x{0159}\x{0440}]/u', + /* s */ '/[\x{015B}\x{015D}\x{015F}\x{0161}\x{0441}]/u', + /* ss */ '/[\x{00DF}]/u', + /* t */ '/[\x{0163}\x{0165}\x{0167}\x{0442}]/u', + /* u */ '/[\x{00F9}\x{00FA}\x{00FB}\x{00FC}\x{0169}\x{016B}\x{016D}\x{016F}\x{0171}\x{0173}\x{0443}\x{00D9}-\x{00DA}\x{0168}\x{01AF}\x{01B0}\x{1EE4}-\x{1EF1}]/u', + /* v */ '/[\x{0432}]/u', + /* w */ '/[\x{0175}]/u', + /* y */ '/[\x{00FF}\x{0177}\x{00FD}\x{044B}\x{1EF2}-\x{1EF9}\x{00DD}]/u', + /* z */ '/[\x{017A}\x{017C}\x{017E}\x{0437}]/u', + /* ae */ '/[\x{00E6}]/u', + /* ch */ '/[\x{0447}]/u', + /* kh */ '/[\x{0445}]/u', + /* oe */ '/[\x{0153}]/u', + /* sh */ '/[\x{0448}]/u', + /* shh*/ '/[\x{0449}]/u', + /* ya */ '/[\x{044F}]/u', + /* ye */ '/[\x{0454}]/u', + /* yi */ '/[\x{0457}]/u', + /* yo */ '/[\x{0451}]/u', + /* yu */ '/[\x{044E}]/u', + /* zh */ '/[\x{0436}]/u', + + /* Uppercase */ + /* A */ '/[\x{0100}\x{0102}\x{0104}\x{00C0}\x{00C1}\x{00C2}\x{00C3}\x{00C4}\x{00C5}\x{0410}]/u', + /* B */ '/[\x{0411}]/u', + /* C */ '/[\x{00C7}\x{0106}\x{0108}\x{010A}\x{010C}\x{0426}]/u', + /* D */ '/[\x{010E}\x{0110}\x{0414}]/u', + /* E */ '/[\x{00C8}\x{00C9}\x{00CA}\x{00CB}\x{0112}\x{0114}\x{0116}\x{0118}\x{011A}\x{0415}\x{042D}]/u', + /* F */ '/[\x{0424}]/u', + /* G */ '/[\x{011C}\x{011E}\x{0120}\x{0122}\x{0413}\x{0490}]/u', + /* H */ '/[\x{0124}\x{0126}]/u', + /* I */ '/[\x{0128}\x{012A}\x{012C}\x{012E}\x{0130}\x{0418}\x{0406}]/u', + /* J */ '/[\x{0134}\x{0419}]/u', + /* K */ '/[\x{0136}\x{041A}]/u', + /* L */ '/[\x{0139}\x{013B}\x{013D}\x{0139}\x{0141}\x{041B}]/u', + /* M */ '/[\x{041C}]/u', + /* N */ '/[\x{00D1}\x{0143}\x{0145}\x{0147}\x{014A}\x{041D}]/u', + /* O */ '/[\x{00D3}\x{014C}\x{014E}\x{0150}\x{041E}]/u', + /* P */ '/[\x{041F}]/u', + /* R */ '/[\x{0154}\x{0156}\x{0158}\x{0420}]/u', + /* S */ '/[\x{015A}\x{015C}\x{015E}\x{0160}\x{0421}]/u', + /* T */ '/[\x{0162}\x{0164}\x{0166}\x{0422}]/u', + /* U */ '/[\x{00D9}\x{00DA}\x{00DB}\x{00DC}\x{0168}\x{016A}\x{016C}\x{016E}\x{0170}\x{0172}\x{0423}]/u', + /* V */ '/[\x{0412}]/u', + /* W */ '/[\x{0174}]/u', + /* Y */ '/[\x{0176}\x{042B}]/u', + /* Z */ '/[\x{0179}\x{017B}\x{017D}\x{0417}]/u', + /* AE */ '/[\x{00C6}]/u', + /* CH */ '/[\x{0427}]/u', + /* KH */ '/[\x{0425}]/u', + /* OE */ '/[\x{0152}]/u', + /* SH */ '/[\x{0428}]/u', + /* SHH*/ '/[\x{0429}]/u', + /* YA */ '/[\x{042F}]/u', + /* YE */ '/[\x{0404}]/u', + /* YI */ '/[\x{0407}]/u', + /* YO */ '/[\x{0401}]/u', + /* YU */ '/[\x{042E}]/u', + /* ZH */ '/[\x{0416}]/u'); + + // ö to oe + // å to aa + // ä to ae + + $replacements = array( + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 'ss', 't', 'u', 'v', 'w', 'y', 'z', 'ae', 'ch', 'kh', 'oe', 'sh', 'shh', 'ya', 'ye', 'yi', 'yo', 'yu', 'zh', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'V', 'W', 'Y', 'Z', 'AE', 'CH', 'KH', 'OE', 'SH', 'SHH', 'YA', 'YE', 'YI', 'YO', 'YU', 'ZH' + ); + + return preg_replace($patterns, $replacements, $str); + } + + /** + * Truncate strings + * + * @param string $str + * @param int $max_length Max length + * @param string $suffix Suffix optional + * @return string $str truncated + */ + /* CAUTION : Use it only on module hookEvents. + ** For other purposes use the smarty function instead */ + public static function truncate($str, $max_length, $suffix = '...') + { + if (Tools::strlen($str) <= $max_length) { + return $str; + } + $str = utf8_decode($str); + return (utf8_encode(substr($str, 0, $max_length - Tools::strlen($suffix)).$suffix)); + } + + /*Copied from CakePHP String utility file*/ + public static function truncateString($text, $length = 120, $options = array()) + { + $default = array( + 'ellipsis' => '...', 'exact' => true, 'html' => true + ); + + $options = array_merge($default, $options); + extract($options); + /** + * @var string $ellipsis + * @var bool $exact + * @var bool $html + */ + + if ($html) { + if (Tools::strlen(preg_replace('/<.*?>/', '', $text)) <= $length) { + return $text; + } + + $total_length = Tools::strlen(strip_tags($ellipsis)); + $open_tags = array(); + $truncate = ''; + preg_match_all('/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER); + + foreach ($tags as $tag) { + if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2])) { + if (preg_match('/<[\w]+[^>]*>/s', $tag[0])) { + array_unshift($open_tags, $tag[2]); + } elseif (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $close_tag)) { + $pos = array_search($close_tag[1], $open_tags); + if ($pos !== false) { + array_splice($open_tags, $pos, 1); + } + } + } + $truncate .= $tag[1]; + $content_length = Tools::strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $tag[3])); + + if ($content_length + $total_length > $length) { + $left = $length - $total_length; + $entities_length = 0; + + if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $tag[3], $entities, PREG_OFFSET_CAPTURE)) { + foreach ($entities[0] as $entity) { + if ($entity[1] + 1 - $entities_length <= $left) { + $left--; + $entities_length += Tools::strlen($entity[0]); + } else { + break; + } + } + } + + $truncate .= Tools::substr($tag[3], 0, $left + $entities_length); + break; + } else { + $truncate .= $tag[3]; + $total_length += $content_length; + } + + if ($total_length >= $length) { + break; + } + } + } else { + if (Tools::strlen($text) <= $length) { + return $text; + } + + $truncate = Tools::substr($text, 0, $length - Tools::strlen($ellipsis)); + } + + if (!$exact) { + $spacepos = Tools::strrpos($truncate, ' '); + if ($html) { + $truncate_check = Tools::substr($truncate, 0, $spacepos); + $last_open_tag = Tools::strrpos($truncate_check, '<'); + $last_close_tag = Tools::strrpos($truncate_check, '>'); + + if ($last_open_tag > $last_close_tag) { + preg_match_all('/<[\w]+[^>]*>/s', $truncate, $last_tag_matches); + $last_tag = array_pop($last_tag_matches[0]); + $spacepos = Tools::strrpos($truncate, $last_tag) + Tools::strlen($last_tag); + } + + $bits = Tools::substr($truncate, $spacepos); + preg_match_all('/<\/([a-z]+)>/', $bits, $dropped_tags, PREG_SET_ORDER); + + if (!empty($dropped_tags)) { + if (!empty($open_tags)) { + foreach ($dropped_tags as $closing_tag) { + if (!in_array($closing_tag[1], $open_tags)) { + array_unshift($open_tags, $closing_tag[1]); + } + } + } else { + foreach ($dropped_tags as $closing_tag) { + $open_tags[] = $closing_tag[1]; + } + } + } + } + + $truncate = Tools::substr($truncate, 0, $spacepos); + } + + $truncate .= $ellipsis; + + if ($html) { + foreach ($open_tags as $tag) { + $truncate .= '</'.$tag.'>'; + } + } + + return $truncate; + } + + public static function normalizeDirectory($directory) + { + return rtrim($directory, '/\\').DIRECTORY_SEPARATOR; + } + + /** + * Generate date form + * + * @param int $year Year to select + * @param int $month Month to select + * @param int $day Day to select + * @return array $tab html data with 3 cells :['days'], ['months'], ['years'] + * + */ + public static function dateYears() + { + $tab = array(); + for ($i = date('Y'); $i >= 1900; $i--) { + $tab[] = $i; + } + return $tab; + } + + public static function dateDays() + { + $tab = array(); + for ($i = 1; $i != 32; $i++) { + $tab[] = $i; + } + return $tab; + } + + public static function dateMonths() + { + $tab = array(); + for ($i = 1; $i != 13; $i++) { + $tab[$i] = date('F', mktime(0, 0, 0, $i, date('m'), date('Y'))); + } + return $tab; + } + + public static function hourGenerate($hours, $minutes, $seconds) + { + return implode(':', array($hours, $minutes, $seconds)); + } + + public static function dateFrom($date) + { + $tab = explode(' ', $date); + if (!isset($tab[1])) { + $date .= ' '.Tools::hourGenerate(0, 0, 0); + } + return $date; + } + + public static function dateTo($date) + { + $tab = explode(' ', $date); + if (!isset($tab[1])) { + $date .= ' '.Tools::hourGenerate(23, 59, 59); + } + return $date; + } + + public static function strtolower($str) + { + if (is_array($str)) { + return false; + } + if (function_exists('mb_strtolower')) { + return mb_strtolower($str, 'utf-8'); + } + return strtolower($str); + } + + public static function strlen($str, $encoding = 'UTF-8') + { + if (is_array($str)) { + return false; + } + $str = html_entity_decode($str, ENT_COMPAT, 'UTF-8'); + if (function_exists('mb_strlen')) { + return mb_strlen($str, $encoding); + } + return strlen($str); + } + + public static function stripslashes($string) + { + if (_PS_MAGIC_QUOTES_GPC_) { + $string = stripslashes($string); + } + return $string; + } + + public static function strtoupper($str) + { + if (is_array($str)) { + return false; + } + if (function_exists('mb_strtoupper')) { + return mb_strtoupper($str, 'utf-8'); + } + return strtoupper($str); + } + + public static function substr($str, $start, $length = false, $encoding = 'utf-8') + { + if (is_array($str)) { + return false; + } + if (function_exists('mb_substr')) { + return mb_substr($str, (int)$start, ($length === false ? Tools::strlen($str) : (int)$length), $encoding); + } + return substr($str, $start, ($length === false ? Tools::strlen($str) : (int)$length)); + } + + public static function strpos($str, $find, $offset = 0, $encoding = 'UTF-8') + { + if (function_exists('mb_strpos')) { + return mb_strpos($str, $find, $offset, $encoding); + } + return strpos($str, $find, $offset); + } + + public static function strrpos($str, $find, $offset = 0, $encoding = 'utf-8') + { + if (function_exists('mb_strrpos')) { + return mb_strrpos($str, $find, $offset, $encoding); + } + return strrpos($str, $find, $offset); + } + + public static function ucfirst($str) + { + return Tools::strtoupper(Tools::substr($str, 0, 1)).Tools::substr($str, 1); + } + + public static function ucwords($str) + { + if (function_exists('mb_convert_case')) { + return mb_convert_case($str, MB_CASE_TITLE); + } + return ucwords(Tools::strtolower($str)); + } + + public static function orderbyPrice(&$array, $order_way) + { + foreach ($array as &$row) { + $row['price_tmp'] = Product::getPriceStatic($row['id_product'], true, ((isset($row['id_product_attribute']) && !empty($row['id_product_attribute'])) ? (int)$row['id_product_attribute'] : null), 2); + } + + unset($row); + + if (Tools::strtolower($order_way) == 'desc') { + uasort($array, 'cmpPriceDesc'); + } else { + uasort($array, 'cmpPriceAsc'); + } + foreach ($array as &$row) { + unset($row['price_tmp']); + } + } + + public static function iconv($from, $to, $string) + { + if (function_exists('iconv')) { + return iconv($from, $to.'//TRANSLIT', str_replace('¥', '¥', str_replace('£', '£', str_replace('€', '€', $string)))); + } + return html_entity_decode(htmlentities($string, ENT_NOQUOTES, $from), ENT_NOQUOTES, $to); + } + + public static function isEmpty($field) + { + return ($field === '' || $field === null); + } + + /** + * returns the rounded value of $value to specified precision, according to your configuration; + * + * @note : PHP 5.3.0 introduce a 3rd parameter mode in round function + * + * @param float $value + * @param int $precision + * @return float + */ + public static function ps_round($value, $precision = 0, $round_mode = null) + { + if ($round_mode === null) { + if (Tools::$round_mode == null) { + Tools::$round_mode = (int)Configuration::get('PS_PRICE_ROUND_MODE'); + } + + $round_mode = Tools::$round_mode; + } + + switch ($round_mode) { + case PS_ROUND_UP: + return Tools::ceilf($value, $precision); + case PS_ROUND_DOWN: + return Tools::floorf($value, $precision); + case PS_ROUND_HALF_DOWN: + case PS_ROUND_HALF_EVEN: + case PS_ROUND_HALF_ODD: + return Tools::math_round($value, $precision, $round_mode); + case PS_ROUND_HALF_UP: + default: + return Tools::math_round($value, $precision, PS_ROUND_HALF_UP); + } + } + + public static function math_round($value, $places, $mode = PS_ROUND_HALF_UP) + { + //If PHP_ROUND_HALF_UP exist (PHP 5.3) use it and pass correct mode value (PrestaShop define - 1) + if (defined('PHP_ROUND_HALF_UP')) { + return round($value, $places, $mode - 1); + } + + $precision_places = 14 - floor(log10(abs($value))); + $f1 = pow(10.0, (double)abs($places)); + + /* If the decimal precision guaranteed by FP arithmetic is higher than + * the requested places BUT is small enough to make sure a non-zero value + * is returned, pre-round the result to the precision */ + if ($precision_places > $places && $precision_places - $places < 15) { + $f2 = pow(10.0, (double)abs($precision_places)); + + if ($precision_places >= 0) { + $tmp_value = $value * $f2; + } else { + $tmp_value = $value / $f2; + } + + /* preround the result (tmp_value will always be something * 1e14, + * thus never larger than 1e15 here) */ + $tmp_value = Tools::round_helper($tmp_value, $mode); + /* now correctly move the decimal point */ + $f2 = pow(10.0, (double)abs($places - $precision_places)); + /* because places < precision_places */ + $tmp_value = $tmp_value / $f2; + } else { + /* adjust the value */ + if ($places >= 0) { + $tmp_value = $value * $f1; + } else { + $tmp_value = $value / $f1; + } + + /* This value is beyond our precision, so rounding it is pointless */ + if (abs($tmp_value) >= 1e15) { + return $value; + } + } + + /* round the temp value */ + $tmp_value = Tools::round_helper($tmp_value, $mode); + + /* see if it makes sense to use simple division to round the value */ + if (abs($places) < 23) { + if ($places > 0) { + $tmp_value /= $f1; + } else { + $tmp_value *= $f1; + } + } + + return $tmp_value; + } + + public static function round_helper($value, $mode) + { + if ($value >= 0.0) { + $tmp_value = floor($value + 0.5); + + if (($mode == PS_ROUND_HALF_DOWN && $value == (-0.5 + $tmp_value)) || + ($mode == PS_ROUND_HALF_EVEN && $value == (0.5 + 2 * floor($tmp_value / 2.0))) || + ($mode == PS_ROUND_HALF_ODD && $value == (0.5 + 2 * floor($tmp_value / 2.0) - 1.0))) { + $tmp_value = $tmp_value - 1.0; + } + } else { + $tmp_value = ceil($value - 0.5); + + if (($mode == PS_ROUND_HALF_DOWN && $value == (0.5 + $tmp_value)) || + ($mode == PS_ROUND_HALF_EVEN && $value == (-0.5 + 2 * ceil($tmp_value / 2.0))) || + ($mode == PS_ROUND_HALF_ODD && $value == (-0.5 + 2 * ceil($tmp_value / 2.0) + 1.0))) { + $tmp_value = $tmp_value + 1.0; + } + } + + return $tmp_value; + } + + /** + * returns the rounded value up of $value to specified precision + * + * @param float $value + * @param int $precision + * @return float + */ + public static function ceilf($value, $precision = 0) + { + $precision_factor = $precision == 0 ? 1 : pow(10, $precision); + $tmp = $value * $precision_factor; + $tmp2 = (string)$tmp; + // If the current value has already the desired precision + if (strpos($tmp2, '.') === false) { + return ($value); + } + if ($tmp2[strlen($tmp2) - 1] == 0) { + return $value; + } + return ceil($tmp) / $precision_factor; + } + + /** + * returns the rounded value down of $value to specified precision + * + * @param float $value + * @param int $precision + * @return float + */ + public static function floorf($value, $precision = 0) + { + $precision_factor = $precision == 0 ? 1 : pow(10, $precision); + $tmp = $value * $precision_factor; + $tmp2 = (string)$tmp; + // If the current value has already the desired precision + if (strpos($tmp2, '.') === false) { + return ($value); + } + if ($tmp2[strlen($tmp2) - 1] == 0) { + return $value; + } + return floor($tmp) / $precision_factor; + } + + /** + * file_exists() wrapper with cache to speedup performance + * + * @param string $filename File name + * @return bool Cached result of file_exists($filename) + */ + public static function file_exists_cache($filename) + { + if (!isset(self::$file_exists_cache[$filename])) { + self::$file_exists_cache[$filename] = file_exists($filename); + } + return self::$file_exists_cache[$filename]; + } + + /** + * file_exists() wrapper with a call to clearstatcache prior + * + * @param string $filename File name + * @return bool Cached result of file_exists($filename) + */ + public static function file_exists_no_cache($filename) + { + clearstatcache(); + return file_exists($filename); + } + + public static function file_get_contents($url, $use_include_path = false, $stream_context = null, $curl_timeout = 5) + { + if ($stream_context == null && preg_match('/^https?:\/\//', $url)) { + $stream_context = @stream_context_create(array('http' => array('timeout' => $curl_timeout))); + } + if (in_array(ini_get('allow_url_fopen'), array('On', 'on', '1')) || !preg_match('/^https?:\/\//', $url)) { + return @file_get_contents($url, $use_include_path, $stream_context); + } elseif (function_exists('curl_init')) { + $curl = curl_init(); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5); + curl_setopt($curl, CURLOPT_TIMEOUT, $curl_timeout); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); + if ($stream_context != null) { + $opts = stream_context_get_options($stream_context); + if (isset($opts['http']['method']) && Tools::strtolower($opts['http']['method']) == 'post') { + curl_setopt($curl, CURLOPT_POST, true); + if (isset($opts['http']['content'])) { + parse_str($opts['http']['content'], $post_data); + curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data); + } + } + } + $content = curl_exec($curl); + curl_close($curl); + return $content; + } else { + return false; + } + } + + public static function simplexml_load_file($url, $class_name = null) + { + $cache_id = 'Tools::simplexml_load_file'.$url; + if (!Cache::isStored($cache_id)) { + $result = @simplexml_load_string(Tools::file_get_contents($url), $class_name); + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } + + public static function copy($source, $destination, $stream_context = null) + { + if (is_null($stream_context) && !preg_match('/^https?:\/\//', $source)) { + return @copy($source, $destination); + } + return @file_put_contents($destination, Tools::file_get_contents($source, false, $stream_context)); + } + + /** + * @deprecated as of 1.5 use Media::minifyHTML() + */ + public static function minifyHTML($html_content) + { + Tools::displayAsDeprecated(); + return Media::minifyHTML($html_content); + } + + /** + * Translates a string with underscores into camel case (e.g. first_name -> firstName) + * @prototype string public static function toCamelCase(string $str[, bool $capitalise_first_char = false]) + */ + public static function toCamelCase($str, $catapitalise_first_char = false) + { + $str = Tools::strtolower($str); + if ($catapitalise_first_char) { + $str = Tools::ucfirst($str); + } + return preg_replace_callback('/_+([a-z])/', create_function('$c', 'return strtoupper($c[1]);'), $str); + } + + /** + * Transform a CamelCase string to underscore_case string + * + * @param string $string + * @return string + */ + public static function toUnderscoreCase($string) + { + // 'CMSCategories' => 'cms_categories' + // 'RangePrice' => 'range_price' + return Tools::strtolower(trim(preg_replace('/([A-Z][a-z])/', '_$1', $string), '_')); + } + + public static function getBrightness($hex) + { + if (Tools::strtolower($hex) == 'transparent') { + return '129'; + } + + $hex = str_replace('#', '', $hex); + + if (Tools::strlen($hex) == 3) { + $hex .= $hex; + } + + $r = hexdec(substr($hex, 0, 2)); + $g = hexdec(substr($hex, 2, 2)); + $b = hexdec(substr($hex, 4, 2)); + return (($r * 299) + ($g * 587) + ($b * 114)) / 1000; + } + + /** + * @deprecated as of 1.5 use Media::minifyHTMLpregCallback() + */ + public static function minifyHTMLpregCallback($preg_matches) + { + Tools::displayAsDeprecated(); + return Media::minifyHTMLpregCallback($preg_matches); + } + + /** + * @deprecated as of 1.5 use Media::packJSinHTML() + */ + public static function packJSinHTML($html_content) + { + Tools::displayAsDeprecated(); + return Media::packJSinHTML($html_content); + } + + /** + * @deprecated as of 1.5 use Media::packJSinHTMLpregCallback() + */ + public static function packJSinHTMLpregCallback($preg_matches) + { + Tools::displayAsDeprecated(); + return Media::packJSinHTMLpregCallback($preg_matches); + } + + /** + * @deprecated as of 1.5 use Media::packJS() + */ + public static function packJS($js_content) + { + Tools::displayAsDeprecated(); + return Media::packJS($js_content); + } + + + public static function parserSQL($sql) + { + if (strlen($sql) > 0) { + require_once(_PS_TOOL_DIR_.'parser_sql/PHPSQLParser.php'); + $parser = new PHPSQLParser($sql); + return $parser->parsed; + } + return false; + } + + /** + * @deprecated as of 1.5 use Media::minifyCSS() + */ + public static function minifyCSS($css_content, $fileuri = false) + { + Tools::displayAsDeprecated(); + return Media::minifyCSS($css_content, $fileuri); + } + + public static function replaceByAbsoluteURL($matches) + { + Tools::displayAsDeprecated(); + return Media::replaceByAbsoluteURL($matches); + } + + /** + * addJS load a javascript file in the header + * + * @deprecated as of 1.5 use FrontController->addJS() + * @param mixed $js_uri + * @return void + */ + public static function addJS($js_uri) + { + Tools::displayAsDeprecated(); + $context = Context::getContext(); + $context->controller->addJs($js_uri); + } + + /** + * @deprecated as of 1.5 use FrontController->addCSS() + */ + public static function addCSS($css_uri, $css_media_type = 'all') + { + Tools::displayAsDeprecated(); + $context = Context::getContext(); + $context->controller->addCSS($css_uri, $css_media_type); + } + + /** + * @deprecated as of 1.5 use Media::cccCss() + */ + public static function cccCss($css_files) + { + Tools::displayAsDeprecated(); + return Media::cccCss($css_files); + } + + + /** + * @deprecated as of 1.5 use Media::cccJS() + */ + public static function cccJS($js_files) + { + Tools::displayAsDeprecated(); + return Media::cccJS($js_files); + } + + protected static $_cache_nb_media_servers = null; + + public static function getMediaServer($filename) + { + if (self::$_cache_nb_media_servers === null && defined('_MEDIA_SERVER_1_') && defined('_MEDIA_SERVER_2_') && defined('_MEDIA_SERVER_3_')) { + if (_MEDIA_SERVER_1_ == '') { + self::$_cache_nb_media_servers = 0; + } elseif (_MEDIA_SERVER_2_ == '') { + self::$_cache_nb_media_servers = 1; + } elseif (_MEDIA_SERVER_3_ == '') { + self::$_cache_nb_media_servers = 2; + } else { + self::$_cache_nb_media_servers = 3; + } + } + + if ($filename && self::$_cache_nb_media_servers && ($id_media_server = (abs(crc32($filename)) % self::$_cache_nb_media_servers + 1))) { + return constant('_MEDIA_SERVER_'.$id_media_server.'_'); + } + + return Tools::usingSecureMode() ? Tools::getShopDomainSSL() : Tools::getShopDomain(); + } + + public static function generateHtaccess($path = null, $rewrite_settings = null, $cache_control = null, $specific = '', $disable_multiviews = null, $medias = false, $disable_modsec = null) + { + if (defined('PS_INSTALLATION_IN_PROGRESS') && $rewrite_settings === null) { + return true; + } + + // Default values for parameters + if (is_null($path)) { + $path = _PS_ROOT_DIR_.'/.htaccess'; + } + + if (is_null($cache_control)) { + $cache_control = (int)Configuration::get('PS_HTACCESS_CACHE_CONTROL'); + } + if (is_null($disable_multiviews)) { + $disable_multiviews = (int)Configuration::get('PS_HTACCESS_DISABLE_MULTIVIEWS'); + } + + if ($disable_modsec === null) { + $disable_modsec = (int)Configuration::get('PS_HTACCESS_DISABLE_MODSEC'); + } + + // Check current content of .htaccess and save all code outside of prestashop comments + $specific_before = $specific_after = ''; + if (file_exists($path)) { + $content = file_get_contents($path); + if (preg_match('#^(.*)\# ~~start~~.*\# ~~end~~[^\n]*(.*)$#s', $content, $m)) { + $specific_before = $m[1]; + $specific_after = $m[2]; + } else { + // For retrocompatibility + if (preg_match('#\# http://www\.prestashop\.com - http://www\.prestashop\.com/forums\s*(.*)<IfModule mod_rewrite\.c>#si', $content, $m)) { + $specific_before = $m[1]; + } else { + $specific_before = $content; + } + } + } + + // Write .htaccess data + if (!$write_fd = @fopen($path, 'w')) { + return false; + } + if ($specific_before) { + fwrite($write_fd, trim($specific_before)."\n\n"); + } + + $domains = array(); + foreach (ShopUrl::getShopUrls() as $shop_url) { + /** @var ShopUrl $shop_url */ + if (!isset($domains[$shop_url->domain])) { + $domains[$shop_url->domain] = array(); + } + + $domains[$shop_url->domain][] = array( + 'physical' => $shop_url->physical_uri, + 'virtual' => $shop_url->virtual_uri, + 'id_shop' => $shop_url->id_shop + ); + + if ($shop_url->domain == $shop_url->domain_ssl) { + continue; + } + + if (!isset($domains[$shop_url->domain_ssl])) { + $domains[$shop_url->domain_ssl] = array(); + } + + $domains[$shop_url->domain_ssl][] = array( + 'physical' => $shop_url->physical_uri, + 'virtual' => $shop_url->virtual_uri, + 'id_shop' => $shop_url->id_shop + ); + } + + // Write data in .htaccess file + fwrite($write_fd, "# ~~start~~ Do not remove this comment, Prestashop will keep automatically the code outside this comment when .htaccess will be generated again\n"); + fwrite($write_fd, "# .htaccess automaticaly generated by PrestaShop e-commerce open-source solution\n"); + fwrite($write_fd, "# http://www.prestashop.com - http://www.prestashop.com/forums\n\n"); + + if ($disable_modsec) { + fwrite($write_fd, "<IfModule mod_security.c>\nSecFilterEngine Off\nSecFilterScanPOST Off\n</IfModule>\n\n"); + } + + // RewriteEngine + fwrite($write_fd, "<IfModule mod_rewrite.c>\n"); + + // Ensure HTTP_MOD_REWRITE variable is set in environment + fwrite($write_fd, "<IfModule mod_env.c>\n"); + fwrite($write_fd, "SetEnv HTTP_MOD_REWRITE On\n"); + fwrite($write_fd, "</IfModule>\n\n"); + + // Disable multiviews ? + if ($disable_multiviews) { + fwrite($write_fd, "\n# Disable Multiviews\nOptions -Multiviews\n\n"); + } + + fwrite($write_fd, "RewriteEngine on\n"); + + if ( + !$medias && Configuration::getMultiShopValues('PS_MEDIA_SERVER_1') + && Configuration::getMultiShopValues('PS_MEDIA_SERVER_2') + && Configuration::getMultiShopValues('PS_MEDIA_SERVER_3') + ) { + $medias = array( + Configuration::getMultiShopValues('PS_MEDIA_SERVER_1'), + Configuration::getMultiShopValues('PS_MEDIA_SERVER_2'), + Configuration::getMultiShopValues('PS_MEDIA_SERVER_3') + ); + } + + $media_domains = ''; + foreach ($medias as $media) { + foreach ($media as $media_url) { + if ($media_url) { + $media_domains .= 'RewriteCond %{HTTP_HOST} ^'.$media_url.'$ [OR]'."\n"; + } + } + } + + if (Configuration::get('PS_WEBSERVICE_CGI_HOST')) { + fwrite($write_fd, "RewriteCond %{HTTP:Authorization} ^(.*)\nRewriteRule . - [E=HTTP_AUTHORIZATION:%1]\n\n"); + } + + foreach ($domains as $domain => $list_uri) { + $physicals = array(); + foreach ($list_uri as $uri) { + fwrite($write_fd, PHP_EOL.PHP_EOL.'#Domain: '.$domain.PHP_EOL); + if (Shop::isFeatureActive()) { + fwrite($write_fd, 'RewriteCond %{HTTP_HOST} ^'.$domain.'$'."\n"); + } + fwrite($write_fd, 'RewriteRule . - [E=REWRITEBASE:'.$uri['physical'].']'."\n"); + + // Webservice + fwrite($write_fd, 'RewriteRule ^api$ api/ [L]'."\n\n"); + fwrite($write_fd, 'RewriteRule ^api/(.*)$ %{ENV:REWRITEBASE}webservice/dispatcher.php?url=$1 [QSA,L]'."\n\n"); + + if (!$rewrite_settings) { + $rewrite_settings = (int)Configuration::get('PS_REWRITING_SETTINGS', null, null, (int)$uri['id_shop']); + } + + $domain_rewrite_cond = 'RewriteCond %{HTTP_HOST} ^'.$domain.'$'."\n"; + // Rewrite virtual multishop uri + if ($uri['virtual']) { + if (!$rewrite_settings) { + fwrite($write_fd, $media_domains); + if (Shop::isFeatureActive()) { + fwrite($write_fd, $domain_rewrite_cond); + } + fwrite($write_fd, 'RewriteRule ^'.trim($uri['virtual'], '/').'/?$ '.$uri['physical'].$uri['virtual']."index.php [L,R]\n"); + } else { + fwrite($write_fd, $media_domains); + if (Shop::isFeatureActive()) { + fwrite($write_fd, $domain_rewrite_cond); + } + fwrite($write_fd, 'RewriteRule ^'.trim($uri['virtual'], '/').'$ '.$uri['physical'].$uri['virtual']." [L,R]\n"); + } + fwrite($write_fd, $media_domains); + if (Shop::isFeatureActive()) { + fwrite($write_fd, $domain_rewrite_cond); + } + fwrite($write_fd, 'RewriteRule ^'.ltrim($uri['virtual'], '/').'(.*) '.$uri['physical']."$1 [L]\n\n"); + } + + if ($rewrite_settings) { + // Compatibility with the old image filesystem + fwrite($write_fd, "# Images\n"); + if (Configuration::get('PS_LEGACY_IMAGES')) { + fwrite($write_fd, $media_domains); + if (Shop::isFeatureActive()) { + fwrite($write_fd, $domain_rewrite_cond); + } + fwrite($write_fd, 'RewriteRule ^([a-z0-9]+)\-([a-z0-9]+)(\-[_a-zA-Z0-9-]*)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1-$2$3$4.jpg [L]'."\n"); + fwrite($write_fd, $media_domains); + if (Shop::isFeatureActive()) { + fwrite($write_fd, $domain_rewrite_cond); + } + fwrite($write_fd, 'RewriteRule ^([0-9]+)\-([0-9]+)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1-$2$3.jpg [L]'."\n"); + } + + // Rewrite product images < 100 millions + for ($i = 1; $i <= 8; $i++) { + $img_path = $img_name = ''; + for ($j = 1; $j <= $i; $j++) { + $img_path .= '$'.$j.'/'; + $img_name .= '$'.$j; + } + $img_name .= '$'.$j; + fwrite($write_fd, $media_domains); + if (Shop::isFeatureActive()) { + fwrite($write_fd, $domain_rewrite_cond); + } + fwrite($write_fd, 'RewriteRule ^'.str_repeat('([0-9])', $i).'(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/'.$img_path.$img_name.'$'.($j + 1).".jpg [L]\n"); + } + fwrite($write_fd, $media_domains); + if (Shop::isFeatureActive()) { + fwrite($write_fd, $domain_rewrite_cond); + } + fwrite($write_fd, 'RewriteRule ^c/([0-9]+)(\-[\.*_a-zA-Z0-9-]*)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/c/$1$2$3.jpg [L]'."\n"); + fwrite($write_fd, $media_domains); + if (Shop::isFeatureActive()) { + fwrite($write_fd, $domain_rewrite_cond); + } + fwrite($write_fd, 'RewriteRule ^c/([a-zA-Z_-]+)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/c/$1$2.jpg [L]'."\n"); + } + + fwrite($write_fd, "# AlphaImageLoader for IE and fancybox\n"); + if (Shop::isFeatureActive()) { + fwrite($write_fd, $domain_rewrite_cond); + } + fwrite($write_fd, 'RewriteRule ^images_ie/?([^/]+)\.(jpe?g|png|gif)$ js/jquery/plugins/fancybox/images/$1.$2 [L]'."\n"); + } + // Redirections to dispatcher + if ($rewrite_settings) { + fwrite($write_fd, "\n# Dispatcher\n"); + fwrite($write_fd, "RewriteCond %{REQUEST_FILENAME} -s [OR]\n"); + fwrite($write_fd, "RewriteCond %{REQUEST_FILENAME} -l [OR]\n"); + fwrite($write_fd, "RewriteCond %{REQUEST_FILENAME} -d\n"); + if (Shop::isFeatureActive()) { + fwrite($write_fd, $domain_rewrite_cond); + } + fwrite($write_fd, "RewriteRule ^.*$ - [NC,L]\n"); + if (Shop::isFeatureActive()) { + fwrite($write_fd, $domain_rewrite_cond); + } + fwrite($write_fd, "RewriteRule ^.*\$ %{ENV:REWRITEBASE}index.php [NC,L]\n"); + } + } + + fwrite($write_fd, "</IfModule>\n\n"); + + fwrite($write_fd, "AddType application/vnd.ms-fontobject .eot\n"); + fwrite($write_fd, "AddType font/ttf .ttf\n"); + fwrite($write_fd, "AddType font/otf .otf\n"); + fwrite($write_fd, "AddType application/x-font-woff .woff\n"); + fwrite($write_fd, "<IfModule mod_headers.c> <FilesMatch \"\.(ttf|ttc|otf|eot|woff|svg)$\"> Header add Access-Control-Allow-Origin \"*\" </FilesMatch> </IfModule>\n\n"); - // Cache control - if ($cache_control) - { - $cache_control = "<IfModule mod_expires.c> + // Cache control + if ($cache_control) { + $cache_control = "<IfModule mod_expires.c> ExpiresActive On ExpiresByType image/gif \"access plus 1 month\" ExpiresByType image/jpeg \"access plus 1 month\" @@ -2458,38 +2545,41 @@ FileETag none AddOutputFilterByType DEFLATE text/html text/css text/javascript application/javascript application/x-javascript font/ttf application/x-font-ttf font/otf application/x-font-otf font/opentype </IfModule> </IfModule>\n\n"; - fwrite($write_fd, $cache_control); - } + fwrite($write_fd, $cache_control); + } - // In case the user hasn't rewrite mod enabled - fwrite($write_fd, "#If rewrite mod isn't enabled\n"); + // In case the user hasn't rewrite mod enabled + fwrite($write_fd, "#If rewrite mod isn't enabled\n"); - // Do not remove ($domains is already iterated upper) - reset($domains); - $domain = current($domains); - fwrite($write_fd, 'ErrorDocument 404 '.$domain[0]['physical']."index.php?controller=404\n\n"); + // Do not remove ($domains is already iterated upper) + reset($domains); + $domain = current($domains); + fwrite($write_fd, 'ErrorDocument 404 '.$domain[0]['physical']."index.php?controller=404\n\n"); - fwrite($write_fd, "# ~~end~~ Do not remove this comment, Prestashop will keep automatically the code outside this comment when .htaccess will be generated again"); - if ($specific_after) - fwrite($write_fd, "\n\n".trim($specific_after)); - fclose($write_fd); + fwrite($write_fd, "# ~~end~~ Do not remove this comment, Prestashop will keep automatically the code outside this comment when .htaccess will be generated again"); + if ($specific_after) { + fwrite($write_fd, "\n\n".trim($specific_after)); + } + fclose($write_fd); - if (!defined('PS_INSTALLATION_IN_PROGRESS')) - Hook::exec('actionHtaccessCreate'); + if (!defined('PS_INSTALLATION_IN_PROGRESS')) { + Hook::exec('actionHtaccessCreate'); + } - return true; - } + return true; + } - public static function generateIndex() - { - if (defined('_DB_PREFIX_') && Configuration::get('PS_DISABLE_OVERRIDES')) - PrestaShopAutoload::getInstance()->_include_override_path = false; - PrestaShopAutoload::getInstance()->generateIndex(); - } + public static function generateIndex() + { + if (defined('_DB_PREFIX_') && Configuration::get('PS_DISABLE_OVERRIDES')) { + PrestaShopAutoload::getInstance()->_include_override_path = false; + } + PrestaShopAutoload::getInstance()->generateIndex(); + } - public static function getDefaultIndexContent() - { - return '<?php + public static function getDefaultIndexContent() + { + return '<?php /** * 2007-'.date('Y').' PrestaShop * @@ -2525,1111 +2615,1147 @@ header("Pragma: no-cache"); header("Location: ../"); exit; '; - } - - /** - * jsonDecode convert json string to php array / object - * - * @param string $json - * @param bool $assoc (since 1.4.2.4) if true, convert to associativ array - * @return array - */ - public static function jsonDecode($json, $assoc = false) - { - if (function_exists('json_decode')) - return json_decode($json, $assoc); - else - { - include_once(_PS_TOOL_DIR_.'json/json.php'); - $pear_json = new Services_JSON(($assoc) ? SERVICES_JSON_LOOSE_TYPE : 0); - return $pear_json->decode($json); - } - } - - /** - * Convert an array to json string - * - * @param array $data - * @return string json - */ - public static function jsonEncode($data) - { - if (function_exists('json_encode')) - return json_encode($data); - else - { - include_once(_PS_TOOL_DIR_.'json/json.php'); - $pear_json = new Services_JSON(); - return $pear_json->encode($data); - } - } - - /** - * Display a warning message indicating that the method is deprecated - */ - public static function displayAsDeprecated($message = null) - { - $backtrace = debug_backtrace(); - $callee = next($backtrace); - $class = isset($callee['class']) ? $callee['class'] : null; - if ($message === null) - $message = 'The function '.$callee['function'].' (Line '.$callee['line'].') is deprecated and will be removed in the next major version.'; - $error = 'Function <b>'.$callee['function'].'()</b> is deprecated in <b>'.$callee['file'].'</b> on line <b>'.$callee['line'].'</b><br />'; - - Tools::throwDeprecated($error, $message, $class); - } - - /** - * Display a warning message indicating that the parameter is deprecated - */ - public static function displayParameterAsDeprecated($parameter) - { - $backtrace = debug_backtrace(); - $callee = next($backtrace); - $error = 'Parameter <b>'.$parameter.'</b> in function <b>'.(isset($callee['function']) ? $callee['function'] : '').'()</b> is deprecated in <b>'.$callee['file'].'</b> on line <b>'.(isset($callee['line']) ? $callee['line'] : '(undefined)').'</b><br />'; - $message = 'The parameter '.$parameter.' in function '.$callee['function'].' (Line '.(isset($callee['line']) ? $callee['line'] : 'undefined').') is deprecated and will be removed in the next major version.'; - $class = isset($callee['class']) ? $callee['class'] : null; - - Tools::throwDeprecated($error, $message, $class); - } - - public static function displayFileAsDeprecated() - { - $backtrace = debug_backtrace(); - $callee = current($backtrace); - $error = 'File <b>'.$callee['file'].'</b> is deprecated<br />'; - $message = 'The file '.$callee['file'].' is deprecated and will be removed in the next major version.'; - $class = isset($callee['class']) ? $callee['class'] : null; - - Tools::throwDeprecated($error, $message, $class); - } - - protected static function throwDeprecated($error, $message, $class) - { - if (_PS_DISPLAY_COMPATIBILITY_WARNING_) - { - trigger_error($error, E_USER_WARNING); - PrestaShopLogger::addLog($message, 3, $class); - } - } - - public static function enableCache($level = 1, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - $smarty = $context->smarty; - if (!Configuration::get('PS_SMARTY_CACHE')) - return; - if ($smarty->force_compile == 0 && $smarty->caching == $level) - return; - self::$_forceCompile = (int)$smarty->force_compile; - self::$_caching = (int)$smarty->caching; - $smarty->force_compile = 0; - $smarty->caching = (int)$level; - $smarty->cache_lifetime = 31536000; // 1 Year - } - - public static function restoreCacheSettings(Context $context = null) - { - if (!$context) - $context = Context::getContext(); - - if (isset(self::$_forceCompile)) - $context->smarty->force_compile = (int)self::$_forceCompile; - if (isset(self::$_caching)) - $context->smarty->caching = (int)self::$_caching; - } - - public static function isCallable($function) - { - $disabled = explode(',', ini_get('disable_functions')); - return (!in_array($function, $disabled) && is_callable($function)); - } - - public static function pRegexp($s, $delim) - { - $s = str_replace($delim, '\\'.$delim, $s); - foreach (array('?', '[', ']', '(', ')', '{', '}', '-', '.', '+', '*', '^', '$', '`', '"', '%') as $char) - $s = str_replace($char, '\\'.$char, $s); - return $s; - } - - public static function str_replace_once($needle, $replace, $haystack) - { - $pos = false; - if ($needle) - $pos = strpos($haystack, $needle); - if ($pos === false) - return $haystack; - return substr_replace($haystack, $replace, $pos, strlen($needle)); - } - - /** - * Function property_exists does not exist in PHP < 5.1 - * - * @deprecated since 1.5.0 (PHP 5.1 required, so property_exists() is now natively supported) - * @param object $class - * @param string $property - * @return bool - */ - public static function property_exists($class, $property) - { - Tools::displayAsDeprecated(); - - if (function_exists('property_exists')) - return property_exists($class, $property); - - if (is_object($class)) - $vars = get_object_vars($class); - else - $vars = get_class_vars($class); - - return array_key_exists($property, $vars); - } - - /** - * @desc identify the version of php - * @return string - */ - public static function checkPhpVersion() - { - $version = null; - - if (defined('PHP_VERSION')) - $version = PHP_VERSION; - else - $version = phpversion(''); - - //Case management system of ubuntu, php version return 5.2.4-2ubuntu5.2 - if (strpos($version, '-') !== false) - $version = substr($version, 0, strpos($version, '-')); - - return $version; - } - - /** - * @desc try to open a zip file in order to check if it's valid - * @return bool success - */ - public static function ZipTest($from_file) - { - if (class_exists('ZipArchive', false)) - { - $zip = new ZipArchive(); - return ($zip->open($from_file, ZIPARCHIVE::CHECKCONS) === true); - } - else - { - require_once(_PS_ROOT_DIR_.'/tools/pclzip/pclzip.lib.php'); - $zip = new PclZip($from_file); - return ($zip->privCheckFormat() === true); - } - } - - public static function getSafeModeStatus() - { - if (!$safe_mode = @ini_get('safe_mode')) - $safe_mode = ''; - return in_array(Tools::strtolower($safe_mode), array(1, 'on')); - } - - /** - * @desc extract a zip file to the given directory - * @return bool success - */ - public static function ZipExtract($from_file, $to_dir) - { - if (!file_exists($to_dir)) - mkdir($to_dir, 0777); - if (class_exists('ZipArchive', false)) - { - $zip = new ZipArchive(); - if ($zip->open($from_file) === true && $zip->extractTo($to_dir) && $zip->close()) - return true; - return false; - } - else - { - require_once(_PS_ROOT_DIR_.'/tools/pclzip/pclzip.lib.php'); - $zip = new PclZip($from_file); - $list = $zip->extract(PCLZIP_OPT_PATH, $to_dir, PCLZIP_OPT_REPLACE_NEWER); - foreach ($list as $file) - if ($file['status'] != 'ok' && $file['status'] != 'already_a_directory') - return false; - return true; - } - } - - public static function chmodr($path, $filemode) - { - if (!is_dir($path)) - return @chmod($path, $filemode); - $dh = opendir($path); - while (($file = readdir($dh)) !== false) - { - if ($file != '.' && $file != '..') - { - $fullpath = $path.'/'.$file; - if (is_link($fullpath)) - return false; - elseif (!is_dir($fullpath) && !@chmod($fullpath, $filemode)) - return false; - elseif (!Tools::chmodr($fullpath, $filemode)) - return false; - } - } - closedir($dh); - if (@chmod($path, $filemode)) - return true; - else - return false; - } - - /** - * Get products order field name for queries. - * - * @param string $type by|way - * @param string $value If no index given, use default order from admin -> pref -> products - * @param bool|\bool(false)|string $prefix - * - * @return string Order by sql clause - */ - public static function getProductsOrder($type, $value = null, $prefix = false) - { - switch ($type) - { - case 'by' : - $list = array(0 => 'name', 1 => 'price', 2 => 'date_add', 3 => 'date_upd', 4 => 'position', 5 => 'manufacturer_name', 6 => 'quantity', 7 => 'reference'); - $value = (is_null($value) || $value === false || $value === '') ? (int)Configuration::get('PS_PRODUCTS_ORDER_BY') : $value; - $value = (isset($list[$value])) ? $list[$value] : ((in_array($value, $list)) ? $value : 'position'); - $order_by_prefix = ''; - if ($prefix) - { - if ($value == 'id_product' || $value == 'date_add' || $value == 'date_upd' || $value == 'price') - $order_by_prefix = 'p.'; - elseif ($value == 'name') - $order_by_prefix = 'pl.'; - elseif ($value == 'manufacturer_name' && $prefix) - { - $order_by_prefix = 'm.'; - $value = 'name'; - } - elseif ($value == 'position' || empty($value)) - $order_by_prefix = 'cp.'; - } - - return $order_by_prefix.$value; - break; - - case 'way' : - $value = (is_null($value) || $value === false || $value === '') ? (int)Configuration::get('PS_PRODUCTS_ORDER_WAY') : $value; - $list = array(0 => 'asc', 1 => 'desc'); - return ((isset($list[$value])) ? $list[$value] : ((in_array($value, $list)) ? $value : 'asc')); - break; - } - } - - /** - * Convert a shorthand byte value from a PHP configuration directive to an integer value - * @param string $value value to convert - * @return int - */ - public static function convertBytes($value) - { - if (is_numeric($value)) - return $value; - else - { - $value_length = strlen($value); - $qty = (int)substr($value, 0, $value_length - 1 ); - $unit = Tools::strtolower(substr($value, $value_length - 1)); - switch ($unit) - { - case 'k': - $qty *= 1024; - break; - case 'm': - $qty *= 1048576; - break; - case 'g': - $qty *= 1073741824; - break; - } - return $qty; - } - } - - /** - * @deprecated as of 1.5 use Controller::getController('PageNotFoundController')->run(); - */ - public static function display404Error() - { - header('HTTP/1.1 404 Not Found'); - header('Status: 404 Not Found'); - include(dirname(__FILE__).'/../404.php'); - die; - } - - /** - * Concat $begin and $end, add ? or & between strings - * - * @since 1.5.0 - * @param string $begin - * @param string $end - * @return string - */ - public static function url($begin, $end) - { - return $begin.((strpos($begin, '?') !== false) ? '&' : '?').$end; - } - - /** - * Display error and dies or silently log the error. - * - * @param string $msg - * @param bool $die - * @return bool success of logging - */ - public static function dieOrLog($msg, $die = true) - { - if ($die || (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_)) - die($msg); - return PrestaShopLogger::addLog($msg); - } - - /** - * Convert \n and \r\n and \r to <br /> - * - * @param string $string String to transform - * @return string New string - */ - public static function nl2br($str) - { - return str_replace(array("\r\n", "\r", "\n"), '<br />', $str); - } - - /** - * Clear cache for Smarty - * - * @param Smarty $smarty - */ - public static function clearCache($smarty = null, $tpl = false, $cache_id = null, $compile_id = null) - { - if ($smarty === null) - $smarty = Context::getContext()->smarty; - - if ($smarty === null) - return; - - if (!$tpl && $cache_id === null && $compile_id === null) - return $smarty->clearAllCache(); - - return $smarty->clearCache($tpl, $cache_id, $compile_id); - } - - /** - * Clear compile for Smarty - */ - public static function clearCompile($smarty = null) - { - if ($smarty === null) - $smarty = Context::getContext()->smarty; - - if ($smarty === null) - return; - - return $smarty->clearCompiledTemplate(); - } - - /** - * Clear Smarty cache and compile folders - */ - public static function clearSmartyCache() - { - $smarty = Context::getContext()->smarty; - Tools::clearCache($smarty); - Tools::clearCompile($smarty); - } - - public static function clearColorListCache($id_product = false) - { - // Change template dir if called from the BackOffice - $current_template_dir = Context::getContext()->smarty->getTemplateDir(); - Context::getContext()->smarty->setTemplateDir(_PS_THEME_DIR_); - Tools::clearCache(null, 'product-list-colors.tpl', - ($id_product ? 'productlist_colors|'.(int)$id_product.'|'.(int)Context::getContext()->shop->id : 'productlist_colors')); - Context::getContext()->smarty->setTemplateDir($current_template_dir); - } - - /** - * getMemoryLimit allow to get the memory limit in octet - * - * @since 1.4.5.0 - * @return int the memory limit value in octet - */ - public static function getMemoryLimit() - { - $memory_limit = @ini_get('memory_limit'); - - return Tools::getOctets($memory_limit); - } - - /** - * getOctet allow to gets the value of a configuration option in octet - * - * @since 1.5.0 - * @return int the value of a configuration option in octet - */ - public static function getOctets($option) - { - if (preg_match('/[0-9]+k/i', $option)) - return 1024 * (int)$option; - - if (preg_match('/[0-9]+m/i', $option)) - return 1024 * 1024 * (int)$option; - - if (preg_match('/[0-9]+g/i', $option)) - return 1024 * 1024 * 1024 * (int)$option; - - return $option; - } - - /** - * - * @return bool true if the server use 64bit arch - */ - public static function isX86_64arch() - { - return (PHP_INT_MAX == '9223372036854775807'); - } - - /** - * - * @return bool true if php-cli is used - */ - public static function isPHPCLI() - { - return (defined('STDIN') || (Tools::strtolower(php_sapi_name()) == 'cli' && (!isset($_SERVER['REMOTE_ADDR']) || empty($_SERVER['REMOTE_ADDR'])))); - } - - public static function argvToGET($argc, $argv) - { - if ($argc <= 1) - return; - - // get the first argument and parse it like a query string - parse_str($argv[1], $args); - if (!is_array($args) || !count($args)) - return; - $_GET = array_merge($args, $_GET); - $_SERVER['QUERY_STRING'] = $argv[1]; - } - - /** - * Get max file upload size considering server settings and optional max value - * - * @param int $max_size optional max file size - * @return int max file size in bytes - */ - public static function getMaxUploadSize($max_size = 0) - { - $post_max_size = Tools::convertBytes(ini_get('post_max_size')); - $upload_max_filesize = Tools::convertBytes(ini_get('upload_max_filesize')); - if ($max_size > 0) - $result = min($post_max_size, $upload_max_filesize, $max_size); - else - $result = min($post_max_size, $upload_max_filesize); - return $result; - } - - /** - * apacheModExists return true if the apache module $name is loaded - * @TODO move this method in class Information (when it will exist) - * - * Notes: This method requires either apache_get_modules or phpinfo() - * to be available. With CGI mod, we cannot get php modules - * - * @param string $name module name - * @return bool true if exists - * @since 1.4.5.0 - */ - public static function apacheModExists($name) - { - if (function_exists('apache_get_modules')) - { - static $apache_module_list = null; - - if (!is_array($apache_module_list)) - $apache_module_list = apache_get_modules(); - - // we need strpos (example, evasive can be evasive20) - foreach ($apache_module_list as $module) - { - if (strpos($module, $name) !== false) - return true; - } - } - return false; - } - - /** - * Copy the folder $src into $dst, $dst is created if it do not exist - * @param $src - * @param $dst - * @param bool $del if true, delete the file after copy - */ - public static function recurseCopy($src, $dst, $del = false) - { - if (!Tools::file_exists_cache($src)) - return false; - $dir = opendir($src); - - if (!Tools::file_exists_cache($dst)) - mkdir($dst); - while (false !== ($file = readdir($dir))) - { - if (($file != '.') && ($file != '..')) - { - if (is_dir($src.DIRECTORY_SEPARATOR.$file)) - self::recurseCopy($src.DIRECTORY_SEPARATOR.$file, $dst.DIRECTORY_SEPARATOR.$file, $del); - else - { - copy($src.DIRECTORY_SEPARATOR.$file, $dst.DIRECTORY_SEPARATOR.$file); - if ($del && is_writable($src.DIRECTORY_SEPARATOR.$file)) - unlink($src.DIRECTORY_SEPARATOR.$file); - } - } - } - closedir($dir); - if ($del && is_writable($src)) - rmdir($src); - } - - /** - * @params string $path Path to scan - * @params string $ext Extention to filter files - * @params string $dir Add this to prefix output for example /path/dir/* - * - * @return array List of file found - * @since 1.5.0 - */ - public static function scandir($path, $ext = 'php', $dir = '', $recursive = false) - { - $path = rtrim(rtrim($path, '\\'), '/').'/'; - $real_path = rtrim(rtrim($path.$dir, '\\'), '/').'/'; - $files = scandir($real_path); - if (!$files) - return array(); - - $filtered_files = array(); - - $real_ext = false; - if (!empty($ext)) - $real_ext = '.'.$ext; - $real_ext_length = strlen($real_ext); - - $subdir = ($dir) ? $dir.'/' : ''; - foreach ($files as $file) - { - if (!$real_ext || (strpos($file, $real_ext) && strpos($file, $real_ext) == (strlen($file) - $real_ext_length))) - $filtered_files[] = $subdir.$file; - - if ($recursive && $file[0] != '.' && is_dir($real_path.$file)) - foreach (Tools::scandir($path, $ext, $subdir.$file, $recursive) as $subfile) - $filtered_files[] = $subfile; - } - return $filtered_files; - } - - - /** - * Align version sent and use internal function - * - * @param $v1 - * @param $v2 - * @param string $operator - * @return mixed - */ - public static function version_compare($v1, $v2, $operator = '<') - { - Tools::alignVersionNumber($v1, $v2); - return version_compare($v1, $v2, $operator); - } - - /** - * Align 2 version with the same number of sub version - * version_compare will work better for its comparison :) - * (Means: '1.8' to '1.9.3' will change '1.8' to '1.8.0') - * - * @param $v1 - * @param $v2 - */ - public static function alignVersionNumber(&$v1, &$v2) - { - $len1 = count(explode('.', trim($v1, '.'))); - $len2 = count(explode('.', trim($v2, '.'))); - $len = 0; - $str = ''; - - if ($len1 > $len2) - { - $len = $len1 - $len2; - $str = &$v2; - } - elseif ($len2 > $len1) - { - $len = $len2 - $len1; - $str = &$v1; - } - - for ($len; $len > 0; $len--) - $str .= '.0'; - } - - public static function modRewriteActive() - { - if (Tools::apacheModExists('mod_rewrite')) - return true; - if ((isset($_SERVER['HTTP_MOD_REWRITE']) && Tools::strtolower($_SERVER['HTTP_MOD_REWRITE']) == 'on') || Tools::strtolower(getenv('HTTP_MOD_REWRITE')) == 'on') - return true; - return false; - } - - public static function unSerialize($serialized, $object = false) - { - if (is_string($serialized) && (strpos($serialized, 'O:') === false || !preg_match('/(^|;|{|})O:[0-9]+:"/', $serialized)) && !$object || $object) - return @unserialize($serialized); - - return false; - } - - /** - * Reproduce array_unique working before php version 5.2.9 - * @param array $array - * @return array - */ - public static function arrayUnique($array) - { - if (version_compare(phpversion(), '5.2.9', '<')) - return array_unique($array); - else - return array_unique($array, SORT_REGULAR); - } - - /** - * Delete unicode class from regular expression patterns - * @param string $pattern - * @return string pattern - */ - public static function cleanNonUnicodeSupport($pattern) - { - if (!defined('PREG_BAD_UTF8_OFFSET')) - return $pattern; - return preg_replace('/\\\[px]\{[a-z]{1,2}\}|(\/[a-z]*)u([a-z]*)$/i', '$1$2', $pattern); - } - - protected static $is_addons_up = true; - public static function addonsRequest - ($request, $params = array()) - { - if (!self::$is_addons_up) - return false; - - $post_data = http_build_query(array( - 'version' => isset($params['version']) ? $params['version'] : _PS_VERSION_, - 'iso_lang' => Tools::strtolower(isset($params['iso_lang']) ? $params['iso_lang'] : Context::getContext()->language->iso_code), - 'iso_code' => Tools::strtolower(isset($params['iso_country']) ? $params['iso_country'] : Country::getIsoById(Configuration::get('PS_COUNTRY_DEFAULT'))), - 'shop_url' => isset($params['shop_url']) ? $params['shop_url'] : Tools::getShopDomain(), - 'mail' => isset($params['email']) ? $params['email'] : Configuration::get('PS_SHOP_EMAIL') - )); - - $protocols = array('https'); - $end_point = 'api.addons.prestashop.com'; - - switch ($request) - { - case 'native': - $protocols[] = 'http'; - $post_data .= '&method=listing&action=native'; - break; - case 'native_all': - $protocols[] = 'http'; - $post_data .= '&method=listing&action=native&iso_code=all'; - break; - case 'must-have': - $protocols[] = 'http'; - $post_data .= '&method=listing&action=must-have'; - break; - case 'must-have-themes': - $protocols[] = 'http'; - $post_data .= '&method=listing&action=must-have-themes'; - break; - case 'customer': - $post_data .= '&method=listing&action=customer&username='.urlencode(trim(Context::getContext()->cookie->username_addons)) - .'&password='.urlencode(trim(Context::getContext()->cookie->password_addons)); - break; - case 'customer_themes': - $post_data .= '&method=listing&action=customer-themes&username='.urlencode(trim(Context::getContext()->cookie->username_addons)) - .'&password='.urlencode(trim(Context::getContext()->cookie->password_addons)); - break; - case 'check_customer': - $post_data .= '&method=check_customer&username='.urlencode($params['username_addons']).'&password='.urlencode($params['password_addons']); - break; - case 'check_module': - $post_data .= '&method=check&module_name='.urlencode($params['module_name']).'&module_key='.urlencode($params['module_key']); - break; - case 'module': - $post_data .= '&method=module&id_module='.urlencode($params['id_module']); - if (isset($params['username_addons']) && isset($params['password_addons'])) - $post_data .= '&username='.urlencode($params['username_addons']).'&password='.urlencode($params['password_addons']); - else - $protocols[] = 'http'; - break; - case 'hosted_module': - $post_data .= '&method=module&id_module='.urlencode((int)$params['id_module']).'&username='.urlencode($params['hosted_email']) - .'&password='.urlencode($params['password_addons']) - .'&shop_url='.urlencode(isset($params['shop_url']) ? $params['shop_url'] : Tools::getShopDomain()) - .'&mail='.urlencode(isset($params['email']) ? $params['email'] : Configuration::get('PS_SHOP_EMAIL')); - $protocols[] = 'https'; - break; - case 'install-modules': - $protocols[] = 'http'; - $post_data .= '&method=listing&action=install-modules'; - $post_data .= defined('_PS_HOST_MODE_') ? '-od' : ''; - break; - default: - return false; - } - d( $post_data ); - - $context = stream_context_create(array( - 'http' => array( - 'method' => 'POST', - 'content' => $post_data, - 'header' => 'Content-type: application/x-www-form-urlencoded', - 'timeout' => 5, - ) - )); - - foreach ($protocols as $protocol) - if ($content = Tools::file_get_contents($protocol.'://'.$end_point, false, $context)) - return $content; - - self::$is_addons_up = false; - return false; - } - - /** - * Returns an array containing information about - * HTTP file upload variable ($_FILES) - * - * @param string $input File upload field name - * @param bool $return_content If true, returns uploaded file contents - * - * @return array|null - */ - public static function fileAttachment($input = 'fileUpload', $return_content = true) - { - $file_attachment = null; - if (isset($_FILES[$input]['name']) && !empty($_FILES[$input]['name']) && !empty($_FILES[$input]['tmp_name'])) - { - $file_attachment['rename'] = uniqid().Tools::strtolower(substr($_FILES[$input]['name'], -5)); - if ($return_content) - $file_attachment['content'] = file_get_contents($_FILES[$input]['tmp_name']); - $file_attachment['tmp_name'] = $_FILES[$input]['tmp_name']; - $file_attachment['name'] = $_FILES[$input]['name']; - $file_attachment['mime'] = $_FILES[$input]['type']; - $file_attachment['error'] = $_FILES[$input]['error']; - $file_attachment['size'] = $_FILES[$input]['size']; - } - - return $file_attachment; - } - - public static function changeFileMTime($file_name) - { - @touch($file_name); - } - - public static function waitUntilFileIsModified($file_name, $timeout = 180) - { - @ini_set('max_execution_time', $timeout); - if (($time_limit = ini_get('max_execution_time')) === null) - $time_limit = 30; - - $time_limit -= 5; - $start_time = microtime(true); - $last_modified = @filemtime($file_name); - - while (true) - { - if (((microtime(true) - $start_time) > $time_limit) || @filemtime($file_name) > $last_modified) - break; - clearstatcache(); - usleep(300); - } - } - - /** - * Delete a substring from another one starting from the right - * @param string $str - * @param string $str_search - * @return string - */ - public static function rtrimString($str, $str_search) - { - $length_str = strlen($str_search); - if (strlen($str) >= $length_str && substr($str, -$length_str) == $str_search) - $str = substr($str, 0, -$length_str); - return $str; - } - - /** - * Format a number into a human readable format - * e.g. 24962496 => 23.81M - * @param $size - * @param int $precision - * - * @return string - */ - public static function formatBytes($size, $precision = 2) - { - if (!$size) - return '0'; - $base = log($size) / log(1024); - $suffixes = array('', 'k', 'M', 'G', 'T'); - - return round(pow(1024, $base - floor($base)), $precision).$suffixes[floor($base)]; - } - - public static function boolVal($value) - { - if (empty($value)) - $value = false; - return (bool)$value; - } - - public static function getUserPlatform() - { - if (isset(self::$_user_plateform)) - return self::$_user_plateform; - - $user_agent = $_SERVER['HTTP_USER_AGENT']; - self::$_user_plateform = 'unknown'; - - if (preg_match('/linux/i', $user_agent)) - self::$_user_plateform = 'Linux'; - elseif (preg_match('/macintosh|mac os x/i', $user_agent)) - self::$_user_plateform = 'Mac'; - elseif (preg_match('/windows|win32/i', $user_agent)) - self::$_user_plateform = 'Windows'; - - return self::$_user_plateform; - } - - public static function getUserBrowser() - { - if (isset(self::$_user_browser)) - return self::$_user_browser; - - $user_agent = $_SERVER['HTTP_USER_AGENT']; - self::$_user_browser = 'unknown'; - - if (preg_match('/MSIE/i', $user_agent) && !preg_match('/Opera/i', $user_agent)) - self::$_user_browser = 'Internet Explorer'; - elseif (preg_match('/Firefox/i', $user_agent)) - self::$_user_browser = 'Mozilla Firefox'; - elseif (preg_match('/Chrome/i', $user_agent)) - self::$_user_browser = 'Google Chrome'; - elseif (preg_match('/Safari/i', $user_agent)) - self::$_user_browser = 'Apple Safari'; - elseif (preg_match('/Opera/i', $user_agent)) - self::$_user_browser = 'Opera'; - elseif (preg_match('/Netscape/i', $user_agent)) - self::$_user_browser = 'Netscape'; - - return self::$_user_browser; - } - - /** - * Allows to display the category description without HTML tags and slashes - * @return string - */ - public static function getDescriptionClean($description) - { - return strip_tags(stripslashes($description)); - } - - public static function purifyHTML($html, $uri_unescape = null, $allow_style = false) - { - require_once (_PS_TOOL_DIR_.'htmlpurifier/HTMLPurifier.standalone.php'); - - static $use_html_purifier = null; - static $purifier = null; - - if (defined('PS_INSTALLATION_IN_PROGRESS') || !Configuration::configurationIsLoaded()) - return $html; - - if ($use_html_purifier === null) - $use_html_purifier = (bool)Configuration::get('PS_USE_HTMLPURIFIER'); - - if ($use_html_purifier) - { - if ($purifier === null) - { - $config = HTMLPurifier_Config::createDefault(); - - $config->set('Attr.EnableID', true); - $config->set('HTML.Trusted', true); - $config->set('Cache.SerializerPath', _PS_CACHE_DIR_.'purifier'); - $config->set('Attr.AllowedFrameTargets', array('_blank', '_self', '_parent', '_top')); - if (is_array($uri_unescape)) - $config->set('URI.UnescapeCharacters', implode('', $uri_unescape)); - - if (Configuration::get('PS_ALLOW_HTML_IFRAME')) - { - $config->set('HTML.SafeIframe', true); - $config->set('HTML.SafeObject', true); - $config->set('URI.SafeIframeRegexp', '/.*/'); - } - - /** @var HTMLPurifier_HTMLDefinition|HTMLPurifier_HTMLModule $def */ - // http://developers.whatwg.org/the-video-element.html#the-video-element - if ($def = $config->getHTMLDefinition(true)) - { - $def->addElement('video', 'Block', 'Optional: (source, Flow) | (Flow, source) | Flow', 'Common', array( - 'src' => 'URI', - 'type' => 'Text', - 'width' => 'Length', - 'height' => 'Length', - 'poster' => 'URI', - 'preload' => 'Enum#auto,metadata,none', - 'controls' => 'Bool', - )); - $def->addElement('source', 'Block', 'Flow', 'Common', array( - 'src' => 'URI', - 'type' => 'Text', - )); - if ($allow_style) - $def->addElement('style', 'Block', 'Flow', 'Common', array( - 'type' => 'Text', - )); - } - - $purifier = new HTMLPurifier($config); - - } - if (_PS_MAGIC_QUOTES_GPC_) - $html = stripslashes($html); - - $html = $purifier->purify($html); - - if (_PS_MAGIC_QUOTES_GPC_) - $html = addslashes($html); - } - - return $html; - } - - /** - * Check if a constant was already defined - * @param string $constant Constant name - * @param mixed $value Default value to set if not defined - */ - public static function safeDefine($constant, $value) - { - if (!defined($constant)) - define($constant, $value); - } - - /** - * Spread an amount on lines, adjusting the $column field, - * with the biggest adjustments going to the rows having the - * highest $sort_column. - * - * E.g.: - * - * $rows = [['a' => 5.1], ['a' => 8.2]]; - * - * spreadAmount(0.3, 1, $rows, 'a'); - * - * => $rows is [['a' => 8.4], ['a' => 5.2]] - * - * @param $amount float The amount to spread across the rows - * @param $precision int Rounding precision - * e.g. if $amount is 1, $precision is 0 and $rows = [['a' => 2], ['a' => 1]] - * then the resulting $rows will be [['a' => 3], ['a' => 1]] - * But if $precision were 1, then the resulting $rows would be [['a' => 2.5], ['a' => 1.5]] - * @param &$rows array An array, associative or not, containing arrays that have at least $column and $sort_column fields - * @param $column string The column on which to perform adjustments - */ - public static function spreadAmount($amount, $precision, &$rows, $column) - { - if (!is_array($rows) || empty($rows)) - return; - - $sort_function = create_function('$a, $b', "return \$b['$column'] > \$a['$column'] ? 1 : -1;"); - - uasort($rows, $sort_function); - - $unit = pow(10, $precision); - - $int_amount = (int)round($unit * $amount); - - $remainder = $int_amount % count($rows); - $amount_to_spread = ($int_amount - $remainder) / count($rows) / $unit; - - $sign = ($amount >= 0 ? 1 : -1); - $position = 0; - foreach ($rows as &$row) - { - $adjustment_factor = $amount_to_spread; - - if ($position < abs($remainder)) - $adjustment_factor += $sign * 1 / $unit; - - $row[$column] += $adjustment_factor; - - ++$position; - } - unset($row); - } - - /** - * Replaces elements from passed arrays into the first array recursively - * @param array $base The array in which elements are replaced. - * @param array $replacements The array from which elements will be extracted. - */ - public static function arrayReplaceRecursive($base, $replacements) - { - if (function_exists('array_replace_recursive')) - return array_replace_recursive($base, $replacements); - - foreach (array_slice(func_get_args(), 1) as $replacements) - { - $bref_stack = array(&$base); - $head_stack = array($replacements); - - do - { - end($bref_stack); - - $bref = &$bref_stack[key($bref_stack)]; - $head = array_pop($head_stack); - unset($bref_stack[key($bref_stack)]); - foreach (array_keys($head) as $key) - if (isset($key, $bref) && is_array($bref[$key]) && is_array($head[$key])) - { - $bref_stack[] = &$bref[$key]; - $head_stack[] = $head[$key]; - } - else - $bref[$key] = $head[$key]; - } - while (count($head_stack)); - } - return $base; - } + } + + /** + * jsonDecode convert json string to php array / object + * + * @param string $json + * @param bool $assoc (since 1.4.2.4) if true, convert to associativ array + * @return array + */ + public static function jsonDecode($json, $assoc = false) + { + if (function_exists('json_decode')) { + return json_decode($json, $assoc); + } else { + include_once(_PS_TOOL_DIR_.'json/json.php'); + $pear_json = new Services_JSON(($assoc) ? SERVICES_JSON_LOOSE_TYPE : 0); + return $pear_json->decode($json); + } + } + + /** + * Convert an array to json string + * + * @param array $data + * @return string json + */ + public static function jsonEncode($data) + { + if (function_exists('json_encode')) { + return json_encode($data); + } else { + include_once(_PS_TOOL_DIR_.'json/json.php'); + $pear_json = new Services_JSON(); + return $pear_json->encode($data); + } + } + + /** + * Display a warning message indicating that the method is deprecated + */ + public static function displayAsDeprecated($message = null) + { + $backtrace = debug_backtrace(); + $callee = next($backtrace); + $class = isset($callee['class']) ? $callee['class'] : null; + if ($message === null) { + $message = 'The function '.$callee['function'].' (Line '.$callee['line'].') is deprecated and will be removed in the next major version.'; + } + $error = 'Function <b>'.$callee['function'].'()</b> is deprecated in <b>'.$callee['file'].'</b> on line <b>'.$callee['line'].'</b><br />'; + + Tools::throwDeprecated($error, $message, $class); + } + + /** + * Display a warning message indicating that the parameter is deprecated + */ + public static function displayParameterAsDeprecated($parameter) + { + $backtrace = debug_backtrace(); + $callee = next($backtrace); + $error = 'Parameter <b>'.$parameter.'</b> in function <b>'.(isset($callee['function']) ? $callee['function'] : '').'()</b> is deprecated in <b>'.$callee['file'].'</b> on line <b>'.(isset($callee['line']) ? $callee['line'] : '(undefined)').'</b><br />'; + $message = 'The parameter '.$parameter.' in function '.$callee['function'].' (Line '.(isset($callee['line']) ? $callee['line'] : 'undefined').') is deprecated and will be removed in the next major version.'; + $class = isset($callee['class']) ? $callee['class'] : null; + + Tools::throwDeprecated($error, $message, $class); + } + + public static function displayFileAsDeprecated() + { + $backtrace = debug_backtrace(); + $callee = current($backtrace); + $error = 'File <b>'.$callee['file'].'</b> is deprecated<br />'; + $message = 'The file '.$callee['file'].' is deprecated and will be removed in the next major version.'; + $class = isset($callee['class']) ? $callee['class'] : null; + + Tools::throwDeprecated($error, $message, $class); + } + + protected static function throwDeprecated($error, $message, $class) + { + if (_PS_DISPLAY_COMPATIBILITY_WARNING_) { + trigger_error($error, E_USER_WARNING); + PrestaShopLogger::addLog($message, 3, $class); + } + } + + public static function enableCache($level = 1, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + $smarty = $context->smarty; + if (!Configuration::get('PS_SMARTY_CACHE')) { + return; + } + if ($smarty->force_compile == 0 && $smarty->caching == $level) { + return; + } + self::$_forceCompile = (int)$smarty->force_compile; + self::$_caching = (int)$smarty->caching; + $smarty->force_compile = 0; + $smarty->caching = (int)$level; + $smarty->cache_lifetime = 31536000; // 1 Year + } + + public static function restoreCacheSettings(Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + + if (isset(self::$_forceCompile)) { + $context->smarty->force_compile = (int)self::$_forceCompile; + } + if (isset(self::$_caching)) { + $context->smarty->caching = (int)self::$_caching; + } + } + + public static function isCallable($function) + { + $disabled = explode(',', ini_get('disable_functions')); + return (!in_array($function, $disabled) && is_callable($function)); + } + + public static function pRegexp($s, $delim) + { + $s = str_replace($delim, '\\'.$delim, $s); + foreach (array('?', '[', ']', '(', ')', '{', '}', '-', '.', '+', '*', '^', '$', '`', '"', '%') as $char) { + $s = str_replace($char, '\\'.$char, $s); + } + return $s; + } + + public static function str_replace_once($needle, $replace, $haystack) + { + $pos = false; + if ($needle) { + $pos = strpos($haystack, $needle); + } + if ($pos === false) { + return $haystack; + } + return substr_replace($haystack, $replace, $pos, strlen($needle)); + } + + /** + * Function property_exists does not exist in PHP < 5.1 + * + * @deprecated since 1.5.0 (PHP 5.1 required, so property_exists() is now natively supported) + * @param object $class + * @param string $property + * @return bool + */ + public static function property_exists($class, $property) + { + Tools::displayAsDeprecated(); + + if (function_exists('property_exists')) { + return property_exists($class, $property); + } + + if (is_object($class)) { + $vars = get_object_vars($class); + } else { + $vars = get_class_vars($class); + } + + return array_key_exists($property, $vars); + } + + /** + * @desc identify the version of php + * @return string + */ + public static function checkPhpVersion() + { + $version = null; + + if (defined('PHP_VERSION')) { + $version = PHP_VERSION; + } else { + $version = phpversion(''); + } + + //Case management system of ubuntu, php version return 5.2.4-2ubuntu5.2 + if (strpos($version, '-') !== false) { + $version = substr($version, 0, strpos($version, '-')); + } + + return $version; + } + + /** + * @desc try to open a zip file in order to check if it's valid + * @return bool success + */ + public static function ZipTest($from_file) + { + if (class_exists('ZipArchive', false)) { + $zip = new ZipArchive(); + return ($zip->open($from_file, ZIPARCHIVE::CHECKCONS) === true); + } else { + require_once(_PS_ROOT_DIR_.'/tools/pclzip/pclzip.lib.php'); + $zip = new PclZip($from_file); + return ($zip->privCheckFormat() === true); + } + } + + public static function getSafeModeStatus() + { + if (!$safe_mode = @ini_get('safe_mode')) { + $safe_mode = ''; + } + return in_array(Tools::strtolower($safe_mode), array(1, 'on')); + } + + /** + * @desc extract a zip file to the given directory + * @return bool success + */ + public static function ZipExtract($from_file, $to_dir) + { + if (!file_exists($to_dir)) { + mkdir($to_dir, 0777); + } + if (class_exists('ZipArchive', false)) { + $zip = new ZipArchive(); + if ($zip->open($from_file) === true && $zip->extractTo($to_dir) && $zip->close()) { + return true; + } + return false; + } else { + require_once(_PS_ROOT_DIR_.'/tools/pclzip/pclzip.lib.php'); + $zip = new PclZip($from_file); + $list = $zip->extract(PCLZIP_OPT_PATH, $to_dir, PCLZIP_OPT_REPLACE_NEWER); + foreach ($list as $file) { + if ($file['status'] != 'ok' && $file['status'] != 'already_a_directory') { + return false; + } + } + return true; + } + } + + public static function chmodr($path, $filemode) + { + if (!is_dir($path)) { + return @chmod($path, $filemode); + } + $dh = opendir($path); + while (($file = readdir($dh)) !== false) { + if ($file != '.' && $file != '..') { + $fullpath = $path.'/'.$file; + if (is_link($fullpath)) { + return false; + } elseif (!is_dir($fullpath) && !@chmod($fullpath, $filemode)) { + return false; + } elseif (!Tools::chmodr($fullpath, $filemode)) { + return false; + } + } + } + closedir($dh); + if (@chmod($path, $filemode)) { + return true; + } else { + return false; + } + } + + /** + * Get products order field name for queries. + * + * @param string $type by|way + * @param string $value If no index given, use default order from admin -> pref -> products + * @param bool|\bool(false)|string $prefix + * + * @return string Order by sql clause + */ + public static function getProductsOrder($type, $value = null, $prefix = false) + { + switch ($type) { + case 'by' : + $list = array(0 => 'name', 1 => 'price', 2 => 'date_add', 3 => 'date_upd', 4 => 'position', 5 => 'manufacturer_name', 6 => 'quantity', 7 => 'reference'); + $value = (is_null($value) || $value === false || $value === '') ? (int)Configuration::get('PS_PRODUCTS_ORDER_BY') : $value; + $value = (isset($list[$value])) ? $list[$value] : ((in_array($value, $list)) ? $value : 'position'); + $order_by_prefix = ''; + if ($prefix) { + if ($value == 'id_product' || $value == 'date_add' || $value == 'date_upd' || $value == 'price') { + $order_by_prefix = 'p.'; + } elseif ($value == 'name') { + $order_by_prefix = 'pl.'; + } elseif ($value == 'manufacturer_name' && $prefix) { + $order_by_prefix = 'm.'; + $value = 'name'; + } elseif ($value == 'position' || empty($value)) { + $order_by_prefix = 'cp.'; + } + } + + return $order_by_prefix.$value; + break; + + case 'way' : + $value = (is_null($value) || $value === false || $value === '') ? (int)Configuration::get('PS_PRODUCTS_ORDER_WAY') : $value; + $list = array(0 => 'asc', 1 => 'desc'); + return ((isset($list[$value])) ? $list[$value] : ((in_array($value, $list)) ? $value : 'asc')); + break; + } + } + + /** + * Convert a shorthand byte value from a PHP configuration directive to an integer value + * @param string $value value to convert + * @return int + */ + public static function convertBytes($value) + { + if (is_numeric($value)) { + return $value; + } else { + $value_length = strlen($value); + $qty = (int)substr($value, 0, $value_length - 1); + $unit = Tools::strtolower(substr($value, $value_length - 1)); + switch ($unit) { + case 'k': + $qty *= 1024; + break; + case 'm': + $qty *= 1048576; + break; + case 'g': + $qty *= 1073741824; + break; + } + return $qty; + } + } + + /** + * @deprecated as of 1.5 use Controller::getController('PageNotFoundController')->run(); + */ + public static function display404Error() + { + header('HTTP/1.1 404 Not Found'); + header('Status: 404 Not Found'); + include(dirname(__FILE__).'/../404.php'); + die; + } + + /** + * Concat $begin and $end, add ? or & between strings + * + * @since 1.5.0 + * @param string $begin + * @param string $end + * @return string + */ + public static function url($begin, $end) + { + return $begin.((strpos($begin, '?') !== false) ? '&' : '?').$end; + } + + /** + * Display error and dies or silently log the error. + * + * @param string $msg + * @param bool $die + * @return bool success of logging + */ + public static function dieOrLog($msg, $die = true) + { + if ($die || (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_)) { + die($msg); + } + return PrestaShopLogger::addLog($msg); + } + + /** + * Convert \n and \r\n and \r to <br /> + * + * @param string $string String to transform + * @return string New string + */ + public static function nl2br($str) + { + return str_replace(array("\r\n", "\r", "\n"), '<br />', $str); + } + + /** + * Clear cache for Smarty + * + * @param Smarty $smarty + */ + public static function clearCache($smarty = null, $tpl = false, $cache_id = null, $compile_id = null) + { + if ($smarty === null) { + $smarty = Context::getContext()->smarty; + } + + if ($smarty === null) { + return; + } + + if (!$tpl && $cache_id === null && $compile_id === null) { + return $smarty->clearAllCache(); + } + + return $smarty->clearCache($tpl, $cache_id, $compile_id); + } + + /** + * Clear compile for Smarty + */ + public static function clearCompile($smarty = null) + { + if ($smarty === null) { + $smarty = Context::getContext()->smarty; + } + + if ($smarty === null) { + return; + } + + return $smarty->clearCompiledTemplate(); + } + + /** + * Clear Smarty cache and compile folders + */ + public static function clearSmartyCache() + { + $smarty = Context::getContext()->smarty; + Tools::clearCache($smarty); + Tools::clearCompile($smarty); + } + + public static function clearColorListCache($id_product = false) + { + // Change template dir if called from the BackOffice + $current_template_dir = Context::getContext()->smarty->getTemplateDir(); + Context::getContext()->smarty->setTemplateDir(_PS_THEME_DIR_); + Tools::clearCache(null, 'product-list-colors.tpl', + ($id_product ? 'productlist_colors|'.(int)$id_product.'|'.(int)Context::getContext()->shop->id : 'productlist_colors')); + Context::getContext()->smarty->setTemplateDir($current_template_dir); + } + + /** + * getMemoryLimit allow to get the memory limit in octet + * + * @since 1.4.5.0 + * @return int the memory limit value in octet + */ + public static function getMemoryLimit() + { + $memory_limit = @ini_get('memory_limit'); + + return Tools::getOctets($memory_limit); + } + + /** + * getOctet allow to gets the value of a configuration option in octet + * + * @since 1.5.0 + * @return int the value of a configuration option in octet + */ + public static function getOctets($option) + { + if (preg_match('/[0-9]+k/i', $option)) { + return 1024 * (int)$option; + } + + if (preg_match('/[0-9]+m/i', $option)) { + return 1024 * 1024 * (int)$option; + } + + if (preg_match('/[0-9]+g/i', $option)) { + return 1024 * 1024 * 1024 * (int)$option; + } + + return $option; + } + + /** + * + * @return bool true if the server use 64bit arch + */ + public static function isX86_64arch() + { + return (PHP_INT_MAX == '9223372036854775807'); + } + + /** + * + * @return bool true if php-cli is used + */ + public static function isPHPCLI() + { + return (defined('STDIN') || (Tools::strtolower(php_sapi_name()) == 'cli' && (!isset($_SERVER['REMOTE_ADDR']) || empty($_SERVER['REMOTE_ADDR'])))); + } + + public static function argvToGET($argc, $argv) + { + if ($argc <= 1) { + return; + } + + // get the first argument and parse it like a query string + parse_str($argv[1], $args); + if (!is_array($args) || !count($args)) { + return; + } + $_GET = array_merge($args, $_GET); + $_SERVER['QUERY_STRING'] = $argv[1]; + } + + /** + * Get max file upload size considering server settings and optional max value + * + * @param int $max_size optional max file size + * @return int max file size in bytes + */ + public static function getMaxUploadSize($max_size = 0) + { + $post_max_size = Tools::convertBytes(ini_get('post_max_size')); + $upload_max_filesize = Tools::convertBytes(ini_get('upload_max_filesize')); + if ($max_size > 0) { + $result = min($post_max_size, $upload_max_filesize, $max_size); + } else { + $result = min($post_max_size, $upload_max_filesize); + } + return $result; + } + + /** + * apacheModExists return true if the apache module $name is loaded + * @TODO move this method in class Information (when it will exist) + * + * Notes: This method requires either apache_get_modules or phpinfo() + * to be available. With CGI mod, we cannot get php modules + * + * @param string $name module name + * @return bool true if exists + * @since 1.4.5.0 + */ + public static function apacheModExists($name) + { + if (function_exists('apache_get_modules')) { + static $apache_module_list = null; + + if (!is_array($apache_module_list)) { + $apache_module_list = apache_get_modules(); + } + + // we need strpos (example, evasive can be evasive20) + foreach ($apache_module_list as $module) { + if (strpos($module, $name) !== false) { + return true; + } + } + } + return false; + } + + /** + * Copy the folder $src into $dst, $dst is created if it do not exist + * @param $src + * @param $dst + * @param bool $del if true, delete the file after copy + */ + public static function recurseCopy($src, $dst, $del = false) + { + if (!Tools::file_exists_cache($src)) { + return false; + } + $dir = opendir($src); + + if (!Tools::file_exists_cache($dst)) { + mkdir($dst); + } + while (false !== ($file = readdir($dir))) { + if (($file != '.') && ($file != '..')) { + if (is_dir($src.DIRECTORY_SEPARATOR.$file)) { + self::recurseCopy($src.DIRECTORY_SEPARATOR.$file, $dst.DIRECTORY_SEPARATOR.$file, $del); + } else { + copy($src.DIRECTORY_SEPARATOR.$file, $dst.DIRECTORY_SEPARATOR.$file); + if ($del && is_writable($src.DIRECTORY_SEPARATOR.$file)) { + unlink($src.DIRECTORY_SEPARATOR.$file); + } + } + } + } + closedir($dir); + if ($del && is_writable($src)) { + rmdir($src); + } + } + + /** + * @params string $path Path to scan + * @params string $ext Extention to filter files + * @params string $dir Add this to prefix output for example /path/dir/* + * + * @return array List of file found + * @since 1.5.0 + */ + public static function scandir($path, $ext = 'php', $dir = '', $recursive = false) + { + $path = rtrim(rtrim($path, '\\'), '/').'/'; + $real_path = rtrim(rtrim($path.$dir, '\\'), '/').'/'; + $files = scandir($real_path); + if (!$files) { + return array(); + } + + $filtered_files = array(); + + $real_ext = false; + if (!empty($ext)) { + $real_ext = '.'.$ext; + } + $real_ext_length = strlen($real_ext); + + $subdir = ($dir) ? $dir.'/' : ''; + foreach ($files as $file) { + if (!$real_ext || (strpos($file, $real_ext) && strpos($file, $real_ext) == (strlen($file) - $real_ext_length))) { + $filtered_files[] = $subdir.$file; + } + + if ($recursive && $file[0] != '.' && is_dir($real_path.$file)) { + foreach (Tools::scandir($path, $ext, $subdir.$file, $recursive) as $subfile) { + $filtered_files[] = $subfile; + } + } + } + return $filtered_files; + } + + + /** + * Align version sent and use internal function + * + * @param $v1 + * @param $v2 + * @param string $operator + * @return mixed + */ + public static function version_compare($v1, $v2, $operator = '<') + { + Tools::alignVersionNumber($v1, $v2); + return version_compare($v1, $v2, $operator); + } + + /** + * Align 2 version with the same number of sub version + * version_compare will work better for its comparison :) + * (Means: '1.8' to '1.9.3' will change '1.8' to '1.8.0') + * + * @param $v1 + * @param $v2 + */ + public static function alignVersionNumber(&$v1, &$v2) + { + $len1 = count(explode('.', trim($v1, '.'))); + $len2 = count(explode('.', trim($v2, '.'))); + $len = 0; + $str = ''; + + if ($len1 > $len2) { + $len = $len1 - $len2; + $str = &$v2; + } elseif ($len2 > $len1) { + $len = $len2 - $len1; + $str = &$v1; + } + + for ($len; $len > 0; $len--) { + $str .= '.0'; + } + } + + public static function modRewriteActive() + { + if (Tools::apacheModExists('mod_rewrite')) { + return true; + } + if ((isset($_SERVER['HTTP_MOD_REWRITE']) && Tools::strtolower($_SERVER['HTTP_MOD_REWRITE']) == 'on') || Tools::strtolower(getenv('HTTP_MOD_REWRITE')) == 'on') { + return true; + } + return false; + } + + public static function unSerialize($serialized, $object = false) + { + if (is_string($serialized) && (strpos($serialized, 'O:') === false || !preg_match('/(^|;|{|})O:[0-9]+:"/', $serialized)) && !$object || $object) { + return @unserialize($serialized); + } + + return false; + } + + /** + * Reproduce array_unique working before php version 5.2.9 + * @param array $array + * @return array + */ + public static function arrayUnique($array) + { + if (version_compare(phpversion(), '5.2.9', '<')) { + return array_unique($array); + } else { + return array_unique($array, SORT_REGULAR); + } + } + + /** + * Delete unicode class from regular expression patterns + * @param string $pattern + * @return string pattern + */ + public static function cleanNonUnicodeSupport($pattern) + { + if (!defined('PREG_BAD_UTF8_OFFSET')) { + return $pattern; + } + return preg_replace('/\\\[px]\{[a-z]{1,2}\}|(\/[a-z]*)u([a-z]*)$/i', '$1$2', $pattern); + } + + protected static $is_addons_up = true; + public static function addonsRequest($request, $params = array()) + { + if (!self::$is_addons_up) { + return false; + } + + $post_data = http_build_query(array( + 'version' => isset($params['version']) ? $params['version'] : _PS_VERSION_, + 'iso_lang' => Tools::strtolower(isset($params['iso_lang']) ? $params['iso_lang'] : Context::getContext()->language->iso_code), + 'iso_code' => Tools::strtolower(isset($params['iso_country']) ? $params['iso_country'] : Country::getIsoById(Configuration::get('PS_COUNTRY_DEFAULT'))), + 'shop_url' => isset($params['shop_url']) ? $params['shop_url'] : Tools::getShopDomain(), + 'mail' => isset($params['email']) ? $params['email'] : Configuration::get('PS_SHOP_EMAIL') + )); + + $protocols = array('https'); + $end_point = 'api.addons.prestashop.com'; + + switch ($request) { + case 'native': + $protocols[] = 'http'; + $post_data .= '&method=listing&action=native'; + break; + case 'native_all': + $protocols[] = 'http'; + $post_data .= '&method=listing&action=native&iso_code=all'; + break; + case 'must-have': + $protocols[] = 'http'; + $post_data .= '&method=listing&action=must-have'; + break; + case 'must-have-themes': + $protocols[] = 'http'; + $post_data .= '&method=listing&action=must-have-themes'; + break; + case 'customer': + $post_data .= '&method=listing&action=customer&username='.urlencode(trim(Context::getContext()->cookie->username_addons)) + .'&password='.urlencode(trim(Context::getContext()->cookie->password_addons)); + break; + case 'customer_themes': + $post_data .= '&method=listing&action=customer-themes&username='.urlencode(trim(Context::getContext()->cookie->username_addons)) + .'&password='.urlencode(trim(Context::getContext()->cookie->password_addons)); + break; + case 'check_customer': + $post_data .= '&method=check_customer&username='.urlencode($params['username_addons']).'&password='.urlencode($params['password_addons']); + break; + case 'check_module': + $post_data .= '&method=check&module_name='.urlencode($params['module_name']).'&module_key='.urlencode($params['module_key']); + break; + case 'module': + $post_data .= '&method=module&id_module='.urlencode($params['id_module']); + if (isset($params['username_addons']) && isset($params['password_addons'])) { + $post_data .= '&username='.urlencode($params['username_addons']).'&password='.urlencode($params['password_addons']); + } else { + $protocols[] = 'http'; + } + break; + case 'hosted_module': + $post_data .= '&method=module&id_module='.urlencode((int)$params['id_module']).'&username='.urlencode($params['hosted_email']) + .'&password='.urlencode($params['password_addons']) + .'&shop_url='.urlencode(isset($params['shop_url']) ? $params['shop_url'] : Tools::getShopDomain()) + .'&mail='.urlencode(isset($params['email']) ? $params['email'] : Configuration::get('PS_SHOP_EMAIL')); + $protocols[] = 'https'; + break; + case 'install-modules': + $protocols[] = 'http'; + $post_data .= '&method=listing&action=install-modules'; + $post_data .= defined('_PS_HOST_MODE_') ? '-od' : ''; + break; + default: + return false; + } + + $context = stream_context_create(array( + 'http' => array( + 'method' => 'POST', + 'content' => $post_data, + 'header' => 'Content-type: application/x-www-form-urlencoded', + 'timeout' => 5, + ) + )); + + foreach ($protocols as $protocol) { + if ($content = Tools::file_get_contents($protocol.'://'.$end_point, false, $context)) { + return $content; + } + } + + self::$is_addons_up = false; + return false; + } + + /** + * Returns an array containing information about + * HTTP file upload variable ($_FILES) + * + * @param string $input File upload field name + * @param bool $return_content If true, returns uploaded file contents + * + * @return array|null + */ + public static function fileAttachment($input = 'fileUpload', $return_content = true) + { + $file_attachment = null; + if (isset($_FILES[$input]['name']) && !empty($_FILES[$input]['name']) && !empty($_FILES[$input]['tmp_name'])) { + $file_attachment['rename'] = uniqid().Tools::strtolower(substr($_FILES[$input]['name'], -5)); + if ($return_content) { + $file_attachment['content'] = file_get_contents($_FILES[$input]['tmp_name']); + } + $file_attachment['tmp_name'] = $_FILES[$input]['tmp_name']; + $file_attachment['name'] = $_FILES[$input]['name']; + $file_attachment['mime'] = $_FILES[$input]['type']; + $file_attachment['error'] = $_FILES[$input]['error']; + $file_attachment['size'] = $_FILES[$input]['size']; + } + + return $file_attachment; + } + + public static function changeFileMTime($file_name) + { + @touch($file_name); + } + + public static function waitUntilFileIsModified($file_name, $timeout = 180) + { + @ini_set('max_execution_time', $timeout); + if (($time_limit = ini_get('max_execution_time')) === null) { + $time_limit = 30; + } + + $time_limit -= 5; + $start_time = microtime(true); + $last_modified = @filemtime($file_name); + + while (true) { + if (((microtime(true) - $start_time) > $time_limit) || @filemtime($file_name) > $last_modified) { + break; + } + clearstatcache(); + usleep(300); + } + } + + /** + * Delete a substring from another one starting from the right + * @param string $str + * @param string $str_search + * @return string + */ + public static function rtrimString($str, $str_search) + { + $length_str = strlen($str_search); + if (strlen($str) >= $length_str && substr($str, -$length_str) == $str_search) { + $str = substr($str, 0, -$length_str); + } + return $str; + } + + /** + * Format a number into a human readable format + * e.g. 24962496 => 23.81M + * @param $size + * @param int $precision + * + * @return string + */ + public static function formatBytes($size, $precision = 2) + { + if (!$size) { + return '0'; + } + $base = log($size) / log(1024); + $suffixes = array('', 'k', 'M', 'G', 'T'); + + return round(pow(1024, $base - floor($base)), $precision).$suffixes[floor($base)]; + } + + public static function boolVal($value) + { + if (empty($value)) { + $value = false; + } + return (bool)$value; + } + + public static function getUserPlatform() + { + if (isset(self::$_user_plateform)) { + return self::$_user_plateform; + } + + $user_agent = $_SERVER['HTTP_USER_AGENT']; + self::$_user_plateform = 'unknown'; + + if (preg_match('/linux/i', $user_agent)) { + self::$_user_plateform = 'Linux'; + } elseif (preg_match('/macintosh|mac os x/i', $user_agent)) { + self::$_user_plateform = 'Mac'; + } elseif (preg_match('/windows|win32/i', $user_agent)) { + self::$_user_plateform = 'Windows'; + } + + return self::$_user_plateform; + } + + public static function getUserBrowser() + { + if (isset(self::$_user_browser)) { + return self::$_user_browser; + } + + $user_agent = $_SERVER['HTTP_USER_AGENT']; + self::$_user_browser = 'unknown'; + + if (preg_match('/MSIE/i', $user_agent) && !preg_match('/Opera/i', $user_agent)) { + self::$_user_browser = 'Internet Explorer'; + } elseif (preg_match('/Firefox/i', $user_agent)) { + self::$_user_browser = 'Mozilla Firefox'; + } elseif (preg_match('/Chrome/i', $user_agent)) { + self::$_user_browser = 'Google Chrome'; + } elseif (preg_match('/Safari/i', $user_agent)) { + self::$_user_browser = 'Apple Safari'; + } elseif (preg_match('/Opera/i', $user_agent)) { + self::$_user_browser = 'Opera'; + } elseif (preg_match('/Netscape/i', $user_agent)) { + self::$_user_browser = 'Netscape'; + } + + return self::$_user_browser; + } + + /** + * Allows to display the category description without HTML tags and slashes + * @return string + */ + public static function getDescriptionClean($description) + { + return strip_tags(stripslashes($description)); + } + + public static function purifyHTML($html, $uri_unescape = null, $allow_style = false) + { + require_once(_PS_TOOL_DIR_.'htmlpurifier/HTMLPurifier.standalone.php'); + + static $use_html_purifier = null; + static $purifier = null; + + if (defined('PS_INSTALLATION_IN_PROGRESS') || !Configuration::configurationIsLoaded()) { + return $html; + } + + if ($use_html_purifier === null) { + $use_html_purifier = (bool)Configuration::get('PS_USE_HTMLPURIFIER'); + } + + if ($use_html_purifier) { + if ($purifier === null) { + $config = HTMLPurifier_Config::createDefault(); + + $config->set('Attr.EnableID', true); + $config->set('HTML.Trusted', true); + $config->set('Cache.SerializerPath', _PS_CACHE_DIR_.'purifier'); + $config->set('Attr.AllowedFrameTargets', array('_blank', '_self', '_parent', '_top')); + if (is_array($uri_unescape)) { + $config->set('URI.UnescapeCharacters', implode('', $uri_unescape)); + } + + if (Configuration::get('PS_ALLOW_HTML_IFRAME')) { + $config->set('HTML.SafeIframe', true); + $config->set('HTML.SafeObject', true); + $config->set('URI.SafeIframeRegexp', '/.*/'); + } + + /** @var HTMLPurifier_HTMLDefinition|HTMLPurifier_HTMLModule $def */ + // http://developers.whatwg.org/the-video-element.html#the-video-element + if ($def = $config->getHTMLDefinition(true)) { + $def->addElement('video', 'Block', 'Optional: (source, Flow) | (Flow, source) | Flow', 'Common', array( + 'src' => 'URI', + 'type' => 'Text', + 'width' => 'Length', + 'height' => 'Length', + 'poster' => 'URI', + 'preload' => 'Enum#auto,metadata,none', + 'controls' => 'Bool', + )); + $def->addElement('source', 'Block', 'Flow', 'Common', array( + 'src' => 'URI', + 'type' => 'Text', + )); + if ($allow_style) { + $def->addElement('style', 'Block', 'Flow', 'Common', array( + 'type' => 'Text', + )); + } + } + + $purifier = new HTMLPurifier($config); + } + if (_PS_MAGIC_QUOTES_GPC_) { + $html = stripslashes($html); + } + + $html = $purifier->purify($html); + + if (_PS_MAGIC_QUOTES_GPC_) { + $html = addslashes($html); + } + } + + return $html; + } + + /** + * Check if a constant was already defined + * @param string $constant Constant name + * @param mixed $value Default value to set if not defined + */ + public static function safeDefine($constant, $value) + { + if (!defined($constant)) { + define($constant, $value); + } + } + + /** + * Spread an amount on lines, adjusting the $column field, + * with the biggest adjustments going to the rows having the + * highest $sort_column. + * + * E.g.: + * + * $rows = [['a' => 5.1], ['a' => 8.2]]; + * + * spreadAmount(0.3, 1, $rows, 'a'); + * + * => $rows is [['a' => 8.4], ['a' => 5.2]] + * + * @param $amount float The amount to spread across the rows + * @param $precision int Rounding precision + * e.g. if $amount is 1, $precision is 0 and $rows = [['a' => 2], ['a' => 1]] + * then the resulting $rows will be [['a' => 3], ['a' => 1]] + * But if $precision were 1, then the resulting $rows would be [['a' => 2.5], ['a' => 1.5]] + * @param &$rows array An array, associative or not, containing arrays that have at least $column and $sort_column fields + * @param $column string The column on which to perform adjustments + */ + public static function spreadAmount($amount, $precision, &$rows, $column) + { + if (!is_array($rows) || empty($rows)) { + return; + } + + $sort_function = create_function('$a, $b', "return \$b['$column'] > \$a['$column'] ? 1 : -1;"); + + uasort($rows, $sort_function); + + $unit = pow(10, $precision); + + $int_amount = (int)round($unit * $amount); + + $remainder = $int_amount % count($rows); + $amount_to_spread = ($int_amount - $remainder) / count($rows) / $unit; + + $sign = ($amount >= 0 ? 1 : -1); + $position = 0; + foreach ($rows as &$row) { + $adjustment_factor = $amount_to_spread; + + if ($position < abs($remainder)) { + $adjustment_factor += $sign * 1 / $unit; + } + + $row[$column] += $adjustment_factor; + + ++$position; + } + unset($row); + } + + /** + * Replaces elements from passed arrays into the first array recursively + * @param array $base The array in which elements are replaced. + * @param array $replacements The array from which elements will be extracted. + */ + public static function arrayReplaceRecursive($base, $replacements) + { + if (function_exists('array_replace_recursive')) { + return array_replace_recursive($base, $replacements); + } + + foreach (array_slice(func_get_args(), 1) as $replacements) { + $bref_stack = array(&$base); + $head_stack = array($replacements); + + do { + end($bref_stack); + + $bref = &$bref_stack[key($bref_stack)]; + $head = array_pop($head_stack); + unset($bref_stack[key($bref_stack)]); + foreach (array_keys($head) as $key) { + if (isset($key, $bref) && is_array($bref[$key]) && is_array($head[$key])) { + $bref_stack[] = &$bref[$key]; + $head_stack[] = $head[$key]; + } else { + $bref[$key] = $head[$key]; + } + } + } while (count($head_stack)); + } + return $base; + } } /** @@ -3642,18 +3768,20 @@ exit; /* Externalized because of a bug in PHP 5.1.6 when inside an object */ function cmpPriceAsc($a, $b) { - if ((float)$a['price_tmp'] < (float)$b['price_tmp']) - return (-1); - elseif ((float)$a['price_tmp'] > (float)$b['price_tmp']) - return (1); - return 0; + if ((float)$a['price_tmp'] < (float)$b['price_tmp']) { + return (-1); + } elseif ((float)$a['price_tmp'] > (float)$b['price_tmp']) { + return (1); + } + return 0; } function cmpPriceDesc($a, $b) { - if ((float)$a['price_tmp'] < (float)$b['price_tmp']) - return 1; - elseif ((float)$a['price_tmp'] > (float)$b['price_tmp']) - return -1; - return 0; + if ((float)$a['price_tmp'] < (float)$b['price_tmp']) { + return 1; + } elseif ((float)$a['price_tmp'] > (float)$b['price_tmp']) { + return -1; + } + return 0; } diff --git a/classes/Translate.php b/classes/Translate.php index be726127..487fe470 100644 --- a/classes/Translate.php +++ b/classes/Translate.php @@ -29,279 +29,290 @@ */ class TranslateCore { - /** - * Get a translation for an admin controller - * - * @param $string - * @param string $class - * @param bool $addslashes - * @param bool $htmlentities - * @return string - */ - public static function getAdminTranslation($string, $class = 'AdminTab', $addslashes = false, $htmlentities = true, $sprintf = null) - { - static $modules_tabs = null; + /** + * Get a translation for an admin controller + * + * @param $string + * @param string $class + * @param bool $addslashes + * @param bool $htmlentities + * @return string + */ + public static function getAdminTranslation($string, $class = 'AdminTab', $addslashes = false, $htmlentities = true, $sprintf = null) + { + static $modules_tabs = null; - // @todo remove global keyword in translations files and use static - global $_LANGADM; + // @todo remove global keyword in translations files and use static + global $_LANGADM; - if ($modules_tabs === null) - $modules_tabs = Tab::getModuleTabList(); + if ($modules_tabs === null) { + $modules_tabs = Tab::getModuleTabList(); + } - if ($_LANGADM == null) - { - $iso = Context::getContext()->language->iso_code; - if (empty($iso)) - $iso = Language::getIsoById((int)Configuration::get('PS_LANG_DEFAULT')); - if (file_exists(_PS_TRANSLATIONS_DIR_.$iso.'/admin.php')) - include_once(_PS_TRANSLATIONS_DIR_.$iso.'/admin.php'); - } + if ($_LANGADM == null) { + $iso = Context::getContext()->language->iso_code; + if (empty($iso)) { + $iso = Language::getIsoById((int)Configuration::get('PS_LANG_DEFAULT')); + } + if (file_exists(_PS_TRANSLATIONS_DIR_.$iso.'/admin.php')) { + include_once(_PS_TRANSLATIONS_DIR_.$iso.'/admin.php'); + } + } - if (isset($modules_tabs[strtolower($class)])) - { - $class_name_controller = $class.'controller'; - // if the class is extended by a module, use modules/[module_name]/xx.php lang file - if (class_exists($class_name_controller) && Module::getModuleNameFromClass($class_name_controller)) - return Translate::getModuleTranslation(Module::$classInModule[$class_name_controller], $string, $class_name_controller, $sprintf, $addslashes); - } + if (isset($modules_tabs[strtolower($class)])) { + $class_name_controller = $class.'controller'; + // if the class is extended by a module, use modules/[module_name]/xx.php lang file + if (class_exists($class_name_controller) && Module::getModuleNameFromClass($class_name_controller)) { + return Translate::getModuleTranslation(Module::$classInModule[$class_name_controller], $string, $class_name_controller, $sprintf, $addslashes); + } + } - $string = preg_replace("/\\\*'/", "\'", $string); - $key = md5($string); - if (isset($_LANGADM[$class.$key])) - $str = $_LANGADM[$class.$key]; - else - $str = Translate::getGenericAdminTranslation($string, $key, $_LANGADM); + $string = preg_replace("/\\\*'/", "\'", $string); + $key = md5($string); + if (isset($_LANGADM[$class.$key])) { + $str = $_LANGADM[$class.$key]; + } else { + $str = Translate::getGenericAdminTranslation($string, $key, $_LANGADM); + } - if ($htmlentities) - $str = htmlspecialchars($str, ENT_QUOTES, 'utf-8'); - $str = str_replace('"', '"', $str); + if ($htmlentities) { + $str = htmlspecialchars($str, ENT_QUOTES, 'utf-8'); + } + $str = str_replace('"', '"', $str); - if ($sprintf !== null) - $str = Translate::checkAndReplaceArgs($str, $sprintf); + if ($sprintf !== null) { + $str = Translate::checkAndReplaceArgs($str, $sprintf); + } - return ($addslashes ? addslashes($str) : stripslashes($str)); - } + return ($addslashes ? addslashes($str) : stripslashes($str)); + } - /** - * Return the translation for a string if it exists for the base AdminController or for helpers - * - * @param $string string to translate - * @param null $key md5 key if already calculated (optional) - * @param array $lang_array Global array of admin translations - * @return string translation - */ - public static function getGenericAdminTranslation($string, $key = null, &$lang_array) - { - $string = preg_replace("/\\\*'/", "\'", $string); - if (is_null($key)) - $key = md5($string); + /** + * Return the translation for a string if it exists for the base AdminController or for helpers + * + * @param $string string to translate + * @param null $key md5 key if already calculated (optional) + * @param array $lang_array Global array of admin translations + * @return string translation + */ + public static function getGenericAdminTranslation($string, $key = null, &$lang_array) + { + $string = preg_replace("/\\\*'/", "\'", $string); + if (is_null($key)) { + $key = md5($string); + } - if (isset($lang_array['AdminController'.$key])) - $str = $lang_array['AdminController'.$key]; - elseif (isset($lang_array['Helper'.$key])) - $str = $lang_array['Helper'.$key]; - elseif (isset($lang_array['AdminTab'.$key])) - $str = $lang_array['AdminTab'.$key]; - else - // note in 1.5, some translations has moved from AdminXX to helper/*.tpl - $str = $string; + if (isset($lang_array['AdminController'.$key])) { + $str = $lang_array['AdminController'.$key]; + } elseif (isset($lang_array['Helper'.$key])) { + $str = $lang_array['Helper'.$key]; + } elseif (isset($lang_array['AdminTab'.$key])) { + $str = $lang_array['AdminTab'.$key]; + } else { + // note in 1.5, some translations has moved from AdminXX to helper/*.tpl + $str = $string; + } - return $str; - } + return $str; + } - /** - * Get a translation for a module - * - * @param string|Module $module - * @param string $string - * @param string $source - * @return string - */ - public static function getModuleTranslation($module, $string, $source, $sprintf = null, $js = false) - { - global $_MODULES, $_MODULE, $_LANGADM; + /** + * Get a translation for a module + * + * @param string|Module $module + * @param string $string + * @param string $source + * @return string + */ + public static function getModuleTranslation($module, $string, $source, $sprintf = null, $js = false) + { + global $_MODULES, $_MODULE, $_LANGADM; - static $lang_cache = array(); - // $_MODULES is a cache of translations for all module. - // $translations_merged is a cache of wether a specific module's translations have already been added to $_MODULES - static $translations_merged = array(); + static $lang_cache = array(); + // $_MODULES is a cache of translations for all module. + // $translations_merged is a cache of wether a specific module's translations have already been added to $_MODULES + static $translations_merged = array(); - $name = $module instanceof Module ? $module->name : $module; + $name = $module instanceof Module ? $module->name : $module; - $language = Context::getContext()->language; + $language = Context::getContext()->language; - if (!isset($translations_merged[$name]) && isset(Context::getContext()->language)) - { - $files_by_priority = array( - // Translations in theme - _PS_THEME_DIR_.'modules/'.$name.'/translations/'.$language->iso_code.'.php', - _PS_THEME_DIR_.'modules/'.$name.'/'.$language->iso_code.'.php', - // PrestaShop 1.5 translations - _PS_MODULE_DIR_.$name.'/translations/'.$language->iso_code.'.php', - // PrestaShop 1.4 translations - _PS_MODULE_DIR_.$name.'/'.$language->iso_code.'.php' - ); - foreach ($files_by_priority as $file) - if (file_exists($file)) - { - include_once($file); - $_MODULES = !empty($_MODULES) ? $_MODULES + $_MODULE : $_MODULE; //we use "+" instead of array_merge() because array merge erase existing values. - $translations_merged[$name] = true; - } - } - $string = preg_replace("/\\\*'/", "\'", $string); - $key = md5($string); + if (!isset($translations_merged[$name]) && isset(Context::getContext()->language)) { + $files_by_priority = array( + // Translations in theme + _PS_THEME_DIR_.'modules/'.$name.'/translations/'.$language->iso_code.'.php', + _PS_THEME_DIR_.'modules/'.$name.'/'.$language->iso_code.'.php', + // PrestaShop 1.5 translations + _PS_MODULE_DIR_.$name.'/translations/'.$language->iso_code.'.php', + // PrestaShop 1.4 translations + _PS_MODULE_DIR_.$name.'/'.$language->iso_code.'.php' + ); + foreach ($files_by_priority as $file) { + if (file_exists($file)) { + include_once($file); + $_MODULES = !empty($_MODULES) ? $_MODULES + $_MODULE : $_MODULE; //we use "+" instead of array_merge() because array merge erase existing values. + $translations_merged[$name] = true; + } + } + } + $string = preg_replace("/\\\*'/", "\'", $string); + $key = md5($string); - $cache_key = $name.'|'.$string.'|'.$source.'|'.(int)$js; + $cache_key = $name.'|'.$string.'|'.$source.'|'.(int)$js; - if (!isset($lang_cache[$cache_key])) - { - if ($_MODULES == null) - { - if ($sprintf !== null) - $string = Translate::checkAndReplaceArgs($string, $sprintf); - return str_replace('"', '"', $string); - } + if (!isset($lang_cache[$cache_key])) { + if ($_MODULES == null) { + if ($sprintf !== null) { + $string = Translate::checkAndReplaceArgs($string, $sprintf); + } + return str_replace('"', '"', $string); + } - $current_key = strtolower('<{'.$name.'}'._THEME_NAME_.'>'.$source).'_'.$key; - $default_key = strtolower('<{'.$name.'}prestashop>'.$source).'_'.$key; + $current_key = strtolower('<{'.$name.'}'._THEME_NAME_.'>'.$source).'_'.$key; + $default_key = strtolower('<{'.$name.'}prestashop>'.$source).'_'.$key; - if ('controller' == ($file = substr($source, 0, - 10))) - { - $current_key_file = strtolower('<{'.$name.'}'._THEME_NAME_.'>'.$file).'_'.$key; - $default_key_file = strtolower('<{'.$name.'}prestashop>'.$file).'_'.$key; - } + if ('controller' == substr($source, -10, 10)) { ++ $file = substr($source, 0, -10); + $current_key_file = strtolower('<{'.$name.'}'._THEME_NAME_.'>'.$file).'_'.$key; + $default_key_file = strtolower('<{'.$name.'}prestashop>'.$file).'_'.$key; + } - if (isset($current_key_file) && !empty($_MODULES[$current_key_file])) - $ret = stripslashes($_MODULES[$current_key_file]); - elseif (isset($default_key_file) && !empty($_MODULES[$default_key_file])) - $ret = stripslashes($_MODULES[$default_key_file]); - elseif (!empty($_MODULES[$current_key])) - $ret = stripslashes($_MODULES[$current_key]); - elseif (!empty($_MODULES[$default_key])) - $ret = stripslashes($_MODULES[$default_key]); - // if translation was not found in module, look for it in AdminController or Helpers - elseif (!empty($_LANGADM)) - $ret = stripslashes(Translate::getGenericAdminTranslation($string, $key, $_LANGADM)); - else - $ret = stripslashes($string); + if (isset($current_key_file) && !empty($_MODULES[$current_key_file])) { + $ret = stripslashes($_MODULES[$current_key_file]); + } elseif (isset($default_key_file) && !empty($_MODULES[$default_key_file])) { + $ret = stripslashes($_MODULES[$default_key_file]); + } elseif (!empty($_MODULES[$current_key])) { + $ret = stripslashes($_MODULES[$current_key]); + } elseif (!empty($_MODULES[$default_key])) { + $ret = stripslashes($_MODULES[$default_key]); + } + // if translation was not found in module, look for it in AdminController or Helpers + elseif (!empty($_LANGADM)) { + $ret = stripslashes(Translate::getGenericAdminTranslation($string, $key, $_LANGADM)); + } else { + $ret = stripslashes($string); + } - if ($sprintf !== null) - $ret = Translate::checkAndReplaceArgs($ret, $sprintf); + if ($sprintf !== null) { + $ret = Translate::checkAndReplaceArgs($ret, $sprintf); + } - if ($js) - $ret = addslashes($ret); - else - $ret = htmlspecialchars($ret, ENT_COMPAT, 'UTF-8'); + if ($js) { + $ret = addslashes($ret); + } else { + $ret = htmlspecialchars($ret, ENT_COMPAT, 'UTF-8'); + } - if ($sprintf === null) - $lang_cache[$cache_key] = $ret; - else - return $ret; + if ($sprintf === null) { + $lang_cache[$cache_key] = $ret; + } else { + return $ret; + } + } + return $lang_cache[$cache_key]; + } - } - return $lang_cache[$cache_key]; - } + /** + * Get a translation for a PDF + * + * @param string $string + * @return string + */ + public static function getPdfTranslation($string, $sprintf = null) + { + global $_LANGPDF; - /** - * Get a translation for a PDF - * - * @param string $string - * @return string - */ - public static function getPdfTranslation($string, $sprintf = null) - { - global $_LANGPDF; + $iso = Context::getContext()->language->iso_code; - $iso = Context::getContext()->language->iso_code; + if (!Validate::isLangIsoCode($iso)) { + Tools::displayError(sprintf('Invalid iso lang (%s)', Tools::safeOutput($iso))); + } - if (!Validate::isLangIsoCode($iso)) - Tools::displayError(sprintf('Invalid iso lang (%s)', Tools::safeOutput($iso))); + $override_i18n_file = _PS_THEME_DIR_.'pdf/lang/'.$iso.'.php'; + $i18n_file = _PS_TRANSLATIONS_DIR_.$iso.'/pdf.php'; + if (file_exists($override_i18n_file)) { + $i18n_file = $override_i18n_file; + } - $override_i18n_file = _PS_THEME_DIR_.'pdf/lang/'.$iso.'.php'; - $i18n_file = _PS_TRANSLATIONS_DIR_.$iso.'/pdf.php'; - if (file_exists($override_i18n_file)) - $i18n_file = $override_i18n_file; + if (!include($i18n_file)) { + Tools::displayError(sprintf('Cannot include PDF translation language file : %s', $i18n_file)); + } - if (!include($i18n_file)) - Tools::displayError(sprintf('Cannot include PDF translation language file : %s', $i18n_file)); + if (!isset($_LANGPDF) || !is_array($_LANGPDF)) { + return str_replace('"', '"', $string); + } - if (!isset($_LANGPDF) || !is_array($_LANGPDF)) - return str_replace('"', '"', $string); + $string = preg_replace("/\\\*'/", "\'", $string); + $key = md5($string); - $string = preg_replace("/\\\*'/", "\'", $string); - $key = md5($string); + $str = (array_key_exists('PDF'.$key, $_LANGPDF) ? $_LANGPDF['PDF'.$key] : $string); - $str = (array_key_exists('PDF'.$key, $_LANGPDF) ? $_LANGPDF['PDF'.$key] : $string); + if ($sprintf !== null) { + $str = Translate::checkAndReplaceArgs($str, $sprintf); + } - if ($sprintf !== null) - $str = Translate::checkAndReplaceArgs($str, $sprintf); + return $str; + } - return $str; - } + /** + * Check if string use a specif syntax for sprintf and replace arguments if use it + * + * @param $string + * @param $args + * @return string + */ + public static function checkAndReplaceArgs($string, $args) + { + if (preg_match_all('#(?:%%|%(?:[0-9]+\$)?[+-]?(?:[ 0]|\'.)?-?[0-9]*(?:\.[0-9]+)?[bcdeufFosxX])#', $string, $matches) && !is_null($args)) { + if (!is_array($args)) { + $args = array($args); + } - /** - * Check if string use a specif syntax for sprintf and replace arguments if use it - * - * @param $string - * @param $args - * @return string - */ - public static function checkAndReplaceArgs($string, $args) - { - if (preg_match_all('#(?:%%|%(?:[0-9]+\$)?[+-]?(?:[ 0]|\'.)?-?[0-9]*(?:\.[0-9]+)?[bcdeufFosxX])#', $string, $matches) && !is_null($args)) - { - if (!is_array($args)) - $args = array($args); + return vsprintf($string, $args); + } + return $string; + } - return vsprintf($string, $args); - } - return $string; - } + /** + * Perform operations on translations after everything is escaped and before displaying it + */ + public static function postProcessTranslation($string, $params) + { + // If tags were explicitely provided, we want to use them *after* the translation string is escaped. + if (!empty($params['tags'])) { + foreach ($params['tags'] as $index => $tag) { + // Make positions start at 1 so that it behaves similar to the %1$d etc. sprintf positional params + $position = $index + 1; + // extract tag name + $match = array(); + if (preg_match('/^\s*<\s*(\w+)/', $tag, $match)) { + $opener = $tag; + $closer = '</'.$match[1].'>'; - /** - * Perform operations on translations after everything is escaped and before displaying it - */ - public static function postProcessTranslation($string, $params) - { - // If tags were explicitely provided, we want to use them *after* the translation string is escaped. - if (!empty($params['tags'])) - { - foreach ($params['tags'] as $index => $tag) - { - // Make positions start at 1 so that it behaves similar to the %1$d etc. sprintf positional params - $position = $index + 1; - // extract tag name - $match = array(); - if (preg_match('/^\s*<\s*(\w+)/', $tag, $match)) - { - $opener = $tag; - $closer = '</'.$match[1].'>'; + $string = str_replace('['.$position.']', $opener, $string); + $string = str_replace('[/'.$position.']', $closer, $string); + $string = str_replace('['.$position.'/]', $opener.$closer, $string); + } + } + } - $string = str_replace('['.$position.']', $opener, $string); - $string = str_replace('[/'.$position.']', $closer, $string); - $string = str_replace('['.$position.'/]', $opener.$closer, $string); - } - } - } + return $string; + } - return $string; - } + /** + * Compatibility method that just calls postProcessTranslation. + * @deprecated renamed this to postProcessTranslation, since it is not only used in relation to smarty. + */ + public static function smartyPostProcessTranslation($string, $params) + { + return Translate::postProcessTranslation($string, $params); + } - /** - * Compatibility method that just calls postProcessTranslation. - * @deprecated renamed this to postProcessTranslation, since it is not only used in relation to smarty. - */ - public static function smartyPostProcessTranslation($string, $params) - { - return Translate::postProcessTranslation($string, $params); - } - - /** - * Helper function to make calls to postProcessTranslation more readable. - */ - public static function ppTags($string, $tags) - { - return Translate::postProcessTranslation($string, array('tags' => $tags)); - } + /** + * Helper function to make calls to postProcessTranslation more readable. + */ + public static function ppTags($string, $tags) + { + return Translate::postProcessTranslation($string, array('tags' => $tags)); + } } diff --git a/classes/TranslatedConfiguration.php b/classes/TranslatedConfiguration.php index 074e21cd..f949af10 100644 --- a/classes/TranslatedConfiguration.php +++ b/classes/TranslatedConfiguration.php @@ -26,79 +26,78 @@ class TranslatedConfigurationCore extends Configuration { - protected $webserviceParameters = array( - 'objectNodeName' => 'translated_configuration', - 'objectsNodeName' => 'translated_configurations', - 'fields' => array( - 'value' => array(), - 'date_add' => array(), - 'date_upd' => array(), - ), - ); + protected $webserviceParameters = array( + 'objectNodeName' => 'translated_configuration', + 'objectsNodeName' => 'translated_configurations', + 'fields' => array( + 'value' => array(), + 'date_add' => array(), + 'date_upd' => array(), + ), + ); - public static $definition = array( - 'table' => 'configuration', - 'primary' => 'id_configuration', - 'multilang' => true, - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isConfigName', 'required' => true, 'size' => 32), - 'id_shop_group' => array('type' => self::TYPE_NOTHING, 'validate' => 'isUnsignedId'), - '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'), - ), - ); + public static $definition = array( + 'table' => 'configuration', + 'primary' => 'id_configuration', + 'multilang' => true, + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isConfigName', 'required' => true, 'size' => 32), + 'id_shop_group' => array('type' => self::TYPE_NOTHING, 'validate' => 'isUnsignedId'), + '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'), + ), + ); - public function __construct($id = null, $id_lang = null) - { - $this->def = ObjectModel::getDefinition($this); - // Check if the id configuration is set in the configuration_lang table. - // Otherwise configuration is not set as translated configuration. - if ($id !== null) - { - $id_translated = Db::getInstance()->executeS(' SELECT `'.bqSQL($this->def['primary']).'` + public function __construct($id = null, $id_lang = null) + { + $this->def = ObjectModel::getDefinition($this); + // Check if the id configuration is set in the configuration_lang table. + // Otherwise configuration is not set as translated configuration. + if ($id !== null) { + $id_translated = Db::getInstance()->executeS(' SELECT `'.bqSQL($this->def['primary']).'` FROM `'.bqSQL(_DB_PREFIX_.$this->def['table']).'_lang` WHERE `'.bqSQL($this->def['primary']).'`='.(int)$id.' LIMIT 0,1 '); - if (empty($id_translated)) - $id = null; - } - parent::__construct($id, $id_lang); - } + if (empty($id_translated)) { + $id = null; + } + } + parent::__construct($id, $id_lang); + } - public function add($autodate = true, $nullValues = false) - { - return $this->update($nullValues); - } + public function add($autodate = true, $nullValues = false) + { + return $this->update($nullValues); + } - public function update($nullValues = false) - { - $ishtml = false; - foreach ($this->value as $i18n_value) - { - if (Validate::isCleanHtml($i18n_value)) - { - $ishtml = true; - break; - } - } - Configuration::updateValue($this->name, $this->value, $ishtml); + public function update($nullValues = false) + { + $ishtml = false; + foreach ($this->value as $i18n_value) { + if (Validate::isCleanHtml($i18n_value)) { + $ishtml = true; + break; + } + } + Configuration::updateValue($this->name, $this->value, $ishtml); - $last_insert = Db::getInstance()->getRow(' + $last_insert = Db::getInstance()->getRow(' SELECT `id_configuration` AS id FROM `'._DB_PREFIX_.'configuration` WHERE `name` = \''.pSQL($this->name).'\''); - if ($last_insert) - $this->id = $last_insert['id']; + if ($last_insert) { + $this->id = $last_insert['id']; + } - return true; - } + return true; + } - public function getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit) - { - $query = ' + public function getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit) + { + $query = ' SELECT DISTINCT main.`'.$this->def['primary'].'` FROM `'._DB_PREFIX_.$this->def['table'].'` main '.$sql_join.' WHERE id_configuration IN @@ -108,6 +107,6 @@ class TranslatedConfigurationCore extends Configuration '.($sql_sort != '' ? $sql_sort : '').' '.($sql_limit != '' ? $sql_limit : '').' '; - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } } diff --git a/classes/Upgrader.php b/classes/Upgrader.php index 2e7f0417..1c3c8cf2 100644 --- a/classes/Upgrader.php +++ b/classes/Upgrader.php @@ -26,267 +26,274 @@ class UpgraderCore { - const DEFAULT_CHECK_VERSION_DELAY_HOURS = 24; - public $rss_version_link; - public $rss_md5file_link_dir; - /** - * @var bool contains true if last version is not installed - */ - protected $need_upgrade = false; - protected $changed_files = array(); - protected $missing_files = array(); + const DEFAULT_CHECK_VERSION_DELAY_HOURS = 24; + public $rss_version_link; + public $rss_md5file_link_dir; + /** + * @var bool contains true if last version is not installed + */ + protected $need_upgrade = false; + protected $changed_files = array(); + protected $missing_files = array(); - public $version_name; - public $version_num; - public $version_is_modified = null; - /** - * @var string contains hte url where to download the file - */ - public $link; - public $autoupgrade; - public $autoupgrade_module; - public $autoupgrade_last_version; - public $autoupgrade_module_link; - public $changelog; - public $md5; + public $version_name; + public $version_num; + public $version_is_modified = null; + /** + * @var string contains hte url where to download the file + */ + public $link; + public $autoupgrade; + public $autoupgrade_module; + public $autoupgrade_last_version; + public $autoupgrade_module_link; + public $changelog; + public $md5; - public function __construct($autoload = false) - { - $this->rss_version_link = _PS_API_URL_.'/xml/upgrader.xml'; - $this->rss_md5file_link_dir = _PS_API_URL_.'/xml/md5/'; + public function __construct($autoload = false) + { + $this->rss_version_link = _PS_API_URL_.'/xml/upgrader.xml'; + $this->rss_md5file_link_dir = _PS_API_URL_.'/xml/md5/'; - if ($autoload) - { - $this->loadFromConfig(); - // checkPSVersion to get need_upgrade - $this->checkPSVersion(); - } - } - public function __get($var) - { - if ($var == 'need_upgrade') - return $this->isLastVersion(); - } + if ($autoload) { + $this->loadFromConfig(); + // checkPSVersion to get need_upgrade + $this->checkPSVersion(); + } + } + public function __get($var) + { + if ($var == 'need_upgrade') { + return $this->isLastVersion(); + } + } - /** - * downloadLast download the last version of PrestaShop and save it in $dest/$filename - * - * @param string $dest directory where to save the file - * @param string $filename new filename - * @return bool - * - * @TODO ftp if copy is not possible (safe_mode for example) - */ - public function downloadLast($dest, $filename = 'prestashop.zip') - { - if (empty($this->link)) - $this->checkPSVersion(); + /** + * downloadLast download the last version of PrestaShop and save it in $dest/$filename + * + * @param string $dest directory where to save the file + * @param string $filename new filename + * @return bool + * + * @TODO ftp if copy is not possible (safe_mode for example) + */ + public function downloadLast($dest, $filename = 'prestashop.zip') + { + if (empty($this->link)) { + $this->checkPSVersion(); + } - $destPath = realpath($dest).DIRECTORY_SEPARATOR.$filename; - if (@copy($this->link, $destPath)) - return true; - else - return false; - } - public function isLastVersion() - { - if (empty($this->link)) - $this->checkPSVersion(); + $destPath = realpath($dest).DIRECTORY_SEPARATOR.$filename; + if (@copy($this->link, $destPath)) { + return true; + } else { + return false; + } + } + public function isLastVersion() + { + if (empty($this->link)) { + $this->checkPSVersion(); + } - return $this->need_upgrade; + return $this->need_upgrade; + } - } + /** + * checkPSVersion ask to prestashop.com if there is a new version. return an array if yes, false otherwise + * + * @return mixed + */ + public function checkPSVersion($force = false) + { + if (class_exists('Configuration')) { + $last_check = Configuration::get('PS_LAST_VERSION_CHECK'); + } else { + $last_check = 0; + } + // if we use the autoupgrade process, we will never refresh it + // except if no check has been done before + if ($force || ($last_check < time() - (3600 * Upgrader::DEFAULT_CHECK_VERSION_DELAY_HOURS))) { + libxml_set_streams_context(@stream_context_create(array('http' => array('timeout' => 3)))); + if ($feed = @simplexml_load_file($this->rss_version_link)) { + $this->version_name = (string)$feed->version->name; + $this->version_num = (string)$feed->version->num; + $this->link = (string)$feed->download->link; + $this->md5 = (string)$feed->download->md5; + $this->changelog = (string)$feed->download->changelog; + $this->autoupgrade = (int)$feed->autoupgrade; + $this->autoupgrade_module = (int)$feed->autoupgrade_module; + $this->autoupgrade_last_version = (string)$feed->autoupgrade_last_version; + $this->autoupgrade_module_link = (string)$feed->autoupgrade_module_link; + $this->desc = (string)$feed->desc; + $config_last_version = array( + 'name' => $this->version_name, + 'num' => $this->version_num, + 'link' => $this->link, + 'md5' => $this->md5, + 'autoupgrade' => $this->autoupgrade, + 'autoupgrade_module' => $this->autoupgrade_module, + 'autoupgrade_last_version' => $this->autoupgrade_last_version, + 'autoupgrade_module_link' => $this->autoupgrade_module_link, + 'changelog' => $this->changelog, + 'desc' => $this->desc + ); + if (class_exists('Configuration')) { + Configuration::updateValue('PS_LAST_VERSION', serialize($config_last_version)); + Configuration::updateValue('PS_LAST_VERSION_CHECK', time()); + } + } + } else { + $this->loadFromConfig(); + } + // retro-compatibility : + // return array(name,link) if you don't use the last version + // false otherwise + if (version_compare(_PS_VERSION_, $this->version_num, '<')) { + $this->need_upgrade = true; + return array('name' => $this->version_name, 'link' => $this->link); + } else { + return false; + } + } - /** - * checkPSVersion ask to prestashop.com if there is a new version. return an array if yes, false otherwise - * - * @return mixed - */ - public function checkPSVersion($force = false) - { - if (class_exists('Configuration')) - $last_check = Configuration::get('PS_LAST_VERSION_CHECK'); - else - $last_check = 0; - // if we use the autoupgrade process, we will never refresh it - // except if no check has been done before - if ($force || ($last_check < time() - (3600 * Upgrader::DEFAULT_CHECK_VERSION_DELAY_HOURS))) - { - libxml_set_streams_context(@stream_context_create(array('http' => array('timeout' => 3)))); - if ($feed = @simplexml_load_file($this->rss_version_link)) - { - $this->version_name = (string)$feed->version->name; - $this->version_num = (string)$feed->version->num; - $this->link = (string)$feed->download->link; - $this->md5 = (string)$feed->download->md5; - $this->changelog = (string)$feed->download->changelog; - $this->autoupgrade = (int)$feed->autoupgrade; - $this->autoupgrade_module = (int)$feed->autoupgrade_module; - $this->autoupgrade_last_version = (string)$feed->autoupgrade_last_version; - $this->autoupgrade_module_link = (string)$feed->autoupgrade_module_link; - $this->desc = (string)$feed->desc; - $config_last_version = array( - 'name' => $this->version_name, - 'num' => $this->version_num, - 'link' => $this->link, - 'md5' => $this->md5, - 'autoupgrade' => $this->autoupgrade, - 'autoupgrade_module' => $this->autoupgrade_module, - 'autoupgrade_last_version' => $this->autoupgrade_last_version, - 'autoupgrade_module_link' => $this->autoupgrade_module_link, - 'changelog' => $this->changelog, - 'desc' => $this->desc - ); - if (class_exists('Configuration')) - { - Configuration::updateValue('PS_LAST_VERSION', serialize($config_last_version)); - Configuration::updateValue('PS_LAST_VERSION_CHECK', time()); - } - } - } - else - $this->loadFromConfig(); - // retro-compatibility : - // return array(name,link) if you don't use the last version - // false otherwise - if (version_compare(_PS_VERSION_, $this->version_num, '<')) - { - $this->need_upgrade = true; - return array('name' => $this->version_name, 'link' => $this->link); - } - else - return false; - } + /** + * load the last version informations stocked in base + * + * @return Upgrader + */ + public function loadFromConfig() + { + $last_version_check = Tools::unSerialize(Configuration::get('PS_LAST_VERSION')); + if ($last_version_check) { + if (isset($last_version_check['name'])) { + $this->version_name = $last_version_check['name']; + } + if (isset($last_version_check['num'])) { + $this->version_num = $last_version_check['num']; + } + if (isset($last_version_check['link'])) { + $this->link = $last_version_check['link']; + } + if (isset($last_version_check['autoupgrade'])) { + $this->autoupgrade = $last_version_check['autoupgrade']; + } + if (isset($last_version_check['autoupgrade_module'])) { + $this->autoupgrade_module = $last_version_check['autoupgrade_module']; + } + if (isset($last_version_check['autoupgrade_last_version'])) { + $this->autoupgrade_last_version = $last_version_check['autoupgrade_last_version']; + } + if (isset($last_version_check['autoupgrade_module_link'])) { + $this->autoupgrade_module_link = $last_version_check['autoupgrade_module_link']; + } + if (isset($last_version_check['md5'])) { + $this->md5 = $last_version_check['md5']; + } + if (isset($last_version_check['desc'])) { + $this->desc = $last_version_check['desc']; + } + if (isset($last_version_check['changelog'])) { + $this->changelog = $last_version_check['changelog']; + } + } + return $this; + } - /** - * load the last version informations stocked in base - * - * @return Upgrader - */ - public function loadFromConfig() - { - $last_version_check = Tools::unSerialize(Configuration::get('PS_LAST_VERSION')); - if ($last_version_check) - { - if (isset($last_version_check['name'])) - $this->version_name = $last_version_check['name']; - if (isset($last_version_check['num'])) - $this->version_num = $last_version_check['num']; - if (isset($last_version_check['link'])) - $this->link = $last_version_check['link']; - if (isset($last_version_check['autoupgrade'])) - $this->autoupgrade = $last_version_check['autoupgrade']; - if (isset($last_version_check['autoupgrade_module'])) - $this->autoupgrade_module = $last_version_check['autoupgrade_module']; - if (isset($last_version_check['autoupgrade_last_version'])) - $this->autoupgrade_last_version = $last_version_check['autoupgrade_last_version']; - if (isset($last_version_check['autoupgrade_module_link'])) - $this->autoupgrade_module_link = $last_version_check['autoupgrade_module_link']; - if (isset($last_version_check['md5'])) - $this->md5 = $last_version_check['md5']; - if (isset($last_version_check['desc'])) - $this->desc = $last_version_check['desc']; - if (isset($last_version_check['changelog'])) - $this->changelog = $last_version_check['changelog']; - } - return $this; - } + /** + * return an array of files + * that the md5file does not match to the original md5file (provided by $rss_md5file_link_dir ) + * @return array + */ + public function getChangedFilesList() + { + if (is_array($this->changed_files) && count($this->changed_files) == 0) { + libxml_set_streams_context(@stream_context_create(array('http' => array('timeout' => 3)))); + $checksum = @simplexml_load_file($this->rss_md5file_link_dir._PS_VERSION_.'.xml'); + if ($checksum == false) { + $this->changed_files = false; + } else { + $this->browseXmlAndCompare($checksum->ps_root_dir[0]); + } + } + return $this->changed_files; + } - /** - * return an array of files - * that the md5file does not match to the original md5file (provided by $rss_md5file_link_dir ) - * @return array - */ - public function getChangedFilesList() - { - if (is_array($this->changed_files) && count($this->changed_files) == 0) - { - libxml_set_streams_context(@stream_context_create(array('http' => array('timeout' => 3)))); - $checksum = @simplexml_load_file($this->rss_md5file_link_dir._PS_VERSION_.'.xml'); - if ($checksum == false) - $this->changed_files = false; - else - $this->browseXmlAndCompare($checksum->ps_root_dir[0]); - } - return $this->changed_files; - } + /** populate $this->changed_files with $path + * in sub arrays mail, translation and core items + * @param string $path filepath to add, relative to _PS_ROOT_DIR_ + */ + protected function addChangedFile($path) + { + $this->version_is_modified = true; - /** populate $this->changed_files with $path - * in sub arrays mail, translation and core items - * @param string $path filepath to add, relative to _PS_ROOT_DIR_ - */ - protected function addChangedFile($path) - { - $this->version_is_modified = true; + if (strpos($path, 'mails/') !== false) { + $this->changed_files['mail'][] = $path; + } elseif ( + strpos($path, '/en.php') !== false + || strpos($path, '/fr.php') !== false + || strpos($path, '/es.php') !== false + || strpos($path, '/it.php') !== false + || strpos($path, '/de.php') !== false + || strpos($path, 'translations/') !== false + ) { + $this->changed_files['translation'][] = $path; + } else { + $this->changed_files['core'][] = $path; + } + } - if (strpos($path, 'mails/') !== false) - $this->changed_files['mail'][] = $path; - elseif ( - strpos($path, '/en.php') !== false - || strpos($path, '/fr.php') !== false - || strpos($path, '/es.php') !== false - || strpos($path, '/it.php') !== false - || strpos($path, '/de.php') !== false - || strpos($path, 'translations/') !== false - ) - $this->changed_files['translation'][] = $path; - else - $this->changed_files['core'][] = $path; - } + /** populate $this->missing_files with $path + * @param string $path filepath to add, relative to _PS_ROOT_DIR_ + */ + protected function addMissingFile($path) + { + $this->version_is_modified = true; + $this->missing_files[] = $path; + } - /** populate $this->missing_files with $path - * @param string $path filepath to add, relative to _PS_ROOT_DIR_ - */ - protected function addMissingFile($path) - { - $this->version_is_modified = true; - $this->missing_files[] = $path; - } + protected function browseXmlAndCompare($node, &$current_path = array(), $level = 1) + { + foreach ($node as $key => $child) { + /** @var SimpleXMLElement $child */ + if (is_object($child) && $child->getName() == 'dir') { + $current_path[$level] = (string)$child['name']; + $this->browseXmlAndCompare($child, $current_path, $level + 1); + } elseif (is_object($child) && $child->getName() == 'md5file') { + // We will store only relative path. + // absolute path is only used for file_exists and compare + $relative_path = ''; + for ($i = 1; $i < $level; $i++) { + $relative_path .= $current_path[$i].'/'; + } + $relative_path .= (string)$child['name']; + $fullpath = _PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$relative_path; - protected function browseXmlAndCompare($node, &$current_path = array(), $level = 1) - { - foreach ($node as $key => $child) - { - /** @var SimpleXMLElement $child */ - if (is_object($child) && $child->getName() == 'dir') - { - $current_path[$level] = (string)$child['name']; - $this->browseXmlAndCompare($child, $current_path, $level + 1); - } - elseif (is_object($child) && $child->getName() == 'md5file') - { - // We will store only relative path. - // absolute path is only used for file_exists and compare - $relative_path = ''; - for ($i = 1; $i < $level; $i++) - $relative_path .= $current_path[$i].'/'; - $relative_path .= (string)$child['name']; - $fullpath = _PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$relative_path; + $fullpath = str_replace('ps_root_dir', _PS_ROOT_DIR_, $fullpath); - $fullpath = str_replace('ps_root_dir', _PS_ROOT_DIR_, $fullpath); + // replace default admin dir by current one + $fullpath = str_replace(_PS_ROOT_DIR_.'/admin', _PS_ADMIN_DIR_, $fullpath); + if (!file_exists($fullpath)) { + $this->addMissingFile($relative_path); + } elseif (!$this->compareChecksum($fullpath, (string)$child)) { + $this->addChangedFile($relative_path); + } + // else, file is original (and ok) + } + } + } - // replace default admin dir by current one - $fullpath = str_replace(_PS_ROOT_DIR_.'/admin', _PS_ADMIN_DIR_, $fullpath); - if (!file_exists($fullpath)) - $this->addMissingFile($relative_path); - elseif (!$this->compareChecksum($fullpath, (string)$child)) - $this->addChangedFile($relative_path); - // else, file is original (and ok) - } - } - } - - protected function compareChecksum($path, $original_sum) - { - if (md5_file($path) == $original_sum) - return true; - return false; - } - - public function isAuthenticPrestashopVersion() - { - $this->getChangedFilesList(); - return !$this->version_is_modified; - } + protected function compareChecksum($path, $original_sum) + { + if (md5_file($path) == $original_sum) { + return true; + } + return false; + } + public function isAuthenticPrestashopVersion() + { + $this->getChangedFilesList(); + return !$this->version_is_modified; + } } diff --git a/classes/Uploader.php b/classes/Uploader.php index 145b9ace..9f389da2 100644 --- a/classes/Uploader.php +++ b/classes/Uploader.php @@ -26,269 +26,267 @@ class UploaderCore { - const DEFAULT_MAX_SIZE = 10485760; + const DEFAULT_MAX_SIZE = 10485760; - private $_check_file_size; - private $_accept_types; - private $_files; - private $_max_size; - private $_name; - private $_save_path; + private $_check_file_size; + private $_accept_types; + private $_files; + private $_max_size; + private $_name; + private $_save_path; - public function __construct($name = null) - { - $this->setName($name); - $this->setCheckFileSize(true); - $this->files = array(); - } + public function __construct($name = null) + { + $this->setName($name); + $this->setCheckFileSize(true); + $this->files = array(); + } - public function setAcceptTypes($value) - { - $this->_accept_types = $value; - return $this; - } + public function setAcceptTypes($value) + { + $this->_accept_types = $value; + return $this; + } - public function getAcceptTypes() - { - return $this->_accept_types; - } + public function getAcceptTypes() + { + return $this->_accept_types; + } - public function setCheckFileSize($value) - { - $this->_check_file_size = $value; - return $this; - } + public function setCheckFileSize($value) + { + $this->_check_file_size = $value; + return $this; + } - public function getFilePath($file_name = null) - { - if (!isset($file_name)) - return tempnam($this->getSavePath(), $this->getUniqueFileName()); + public function getFilePath($file_name = null) + { + if (!isset($file_name)) { + return tempnam($this->getSavePath(), $this->getUniqueFileName()); + } - return $this->getSavePath().$file_name; - } + return $this->getSavePath().$file_name; + } - public function getFiles() - { - if (!isset($this->_files)) - $this->_files = array(); + public function getFiles() + { + if (!isset($this->_files)) { + $this->_files = array(); + } - return $this->_files; - } + return $this->_files; + } - public function setMaxSize($value) - { - $this->_max_size = intval($value); - return $this; - } + public function setMaxSize($value) + { + $this->_max_size = intval($value); + return $this; + } - public function getMaxSize() - { - if (!isset($this->_max_size) || empty($this->_max_size)) - $this->setMaxSize(self::DEFAULT_MAX_SIZE); + public function getMaxSize() + { + if (!isset($this->_max_size) || empty($this->_max_size)) { + $this->setMaxSize(self::DEFAULT_MAX_SIZE); + } - return $this->_max_size; - } + return $this->_max_size; + } - public function setName($value) - { - $this->_name = $value; - return $this; - } + public function setName($value) + { + $this->_name = $value; + return $this; + } - public function getName() - { - return $this->_name; - } + public function getName() + { + return $this->_name; + } - public function setSavePath($value) - { - $this->_save_path = $value; - return $this; - } + public function setSavePath($value) + { + $this->_save_path = $value; + return $this; + } - public function getPostMaxSizeBytes() - { - $post_max_size = ini_get('post_max_size'); - $bytes = trim($post_max_size); - $last = strtolower($post_max_size[strlen($post_max_size) - 1]); + public function getPostMaxSizeBytes() + { + $post_max_size = ini_get('post_max_size'); + $bytes = trim($post_max_size); + $last = strtolower($post_max_size[strlen($post_max_size) - 1]); - switch ($last) - { - case 'g': $bytes *= 1024; - case 'm': $bytes *= 1024; - case 'k': $bytes *= 1024; - } + switch ($last) { + case 'g': $bytes *= 1024; + case 'm': $bytes *= 1024; + case 'k': $bytes *= 1024; + } - if ($bytes == '') - $bytes = null; - return $bytes; - } + if ($bytes == '') { + $bytes = null; + } + return $bytes; + } - public function getSavePath() - { - if (!isset($this->_save_path)) - $this->setSavePath(_PS_UPLOAD_DIR_); + public function getSavePath() + { + if (!isset($this->_save_path)) { + $this->setSavePath(_PS_UPLOAD_DIR_); + } - return $this->_normalizeDirectory($this->_save_path); - } + return $this->_normalizeDirectory($this->_save_path); + } - public function getUniqueFileName($prefix = 'PS') - { - return uniqid($prefix, true); - } + public function getUniqueFileName($prefix = 'PS') + { + return uniqid($prefix, true); + } - public function checkFileSize() - { - return (isset($this->_check_file_size) && $this->_check_file_size); - } + public function checkFileSize() + { + return (isset($this->_check_file_size) && $this->_check_file_size); + } - public function process($dest = null) - { - $upload = isset($_FILES[$this->getName()]) ? $_FILES[$this->getName()] : null; + public function process($dest = null) + { + $upload = isset($_FILES[$this->getName()]) ? $_FILES[$this->getName()] : null; - if ($upload && is_array($upload['tmp_name'])) - { - $tmp = array(); - foreach ($upload['tmp_name'] as $index => $value) - { $tmp[$index] = array( - 'tmp_name' => $upload['tmp_name'][$index], - 'name' => $upload['name'][$index], - 'size' => $upload['size'][$index], - 'type' => $upload['type'][$index], - 'error' => $upload['error'][$index] - ); + if ($upload && is_array($upload['tmp_name'])) { + $tmp = array(); + foreach ($upload['tmp_name'] as $index => $value) { + $tmp[$index] = array( + 'tmp_name' => $upload['tmp_name'][$index], + 'name' => $upload['name'][$index], + 'size' => $upload['size'][$index], + 'type' => $upload['type'][$index], + 'error' => $upload['error'][$index] + ); - $this->files[] = $this->upload($tmp[$index], $dest); - } - } - elseif ($upload) - $this->files[] = $this->upload($upload, $dest); + $this->files[] = $this->upload($tmp[$index], $dest); + } + } elseif ($upload) { + $this->files[] = $this->upload($upload, $dest); + } - return $this->files; - } + return $this->files; + } - public function upload($file, $dest = null) - { - if ($this->validate($file)) - { - if (isset($dest) && is_dir($dest)) - $file_path = $dest; - else - $file_path = $this->getFilePath(isset($dest) ? $dest : $file['name']); + public function upload($file, $dest = null) + { + if ($this->validate($file)) { + if (isset($dest) && is_dir($dest)) { + $file_path = $dest; + } else { + $file_path = $this->getFilePath(isset($dest) ? $dest : $file['name']); + } - if ($file['tmp_name'] && is_uploaded_file($file['tmp_name'] )) - move_uploaded_file($file['tmp_name'], $file_path); - else - // Non-multipart uploads (PUT method support) - file_put_contents($file_path, fopen('php://input', 'r')); + if ($file['tmp_name'] && is_uploaded_file($file['tmp_name'])) { + move_uploaded_file($file['tmp_name'], $file_path); + } else { + // Non-multipart uploads (PUT method support) + file_put_contents($file_path, fopen('php://input', 'r')); + } - $file_size = $this->_getFileSize($file_path, true); + $file_size = $this->_getFileSize($file_path, true); - if ($file_size === $file['size']) - $file['save_path'] = $file_path; - else - { - $file['size'] = $file_size; - unlink($file_path); - $file['error'] = Tools::displayError('Server file size is different from local file size'); - } - } + if ($file_size === $file['size']) { + $file['save_path'] = $file_path; + } else { + $file['size'] = $file_size; + unlink($file_path); + $file['error'] = Tools::displayError('Server file size is different from local file size'); + } + } - return $file; - } + return $file; + } - protected function checkUploadError($error_code) - { - $error = 0; - switch ($error_code) - { - case 1: - $error = sprintf(Tools::displayError('The uploaded file exceeds %s'), ini_get('upload_max_filesize')); - break; - case 2: - $error = sprintf(Tools::displayError('The uploaded file exceeds %s'), ini_get('post_max_size')); - break; - case 3: - $error = Tools::displayError('The uploaded file was only partially uploaded'); - break; - case 4: - $error = Tools::displayError('No file was uploaded'); - break; - case 6: - $error = Tools::displayError('Missing temporary folder'); - break; - case 7: - $error = Tools::displayError('Failed to write file to disk'); - break; - case 8: - $error = Tools::displayError('A PHP extension stopped the file upload'); - break; - default; - break; - } - return $error; - } + protected function checkUploadError($error_code) + { + $error = 0; + switch ($error_code) { + case 1: + $error = sprintf(Tools::displayError('The uploaded file exceeds %s'), ini_get('upload_max_filesize')); + break; + case 2: + $error = sprintf(Tools::displayError('The uploaded file exceeds %s'), ini_get('post_max_size')); + break; + case 3: + $error = Tools::displayError('The uploaded file was only partially uploaded'); + break; + case 4: + $error = Tools::displayError('No file was uploaded'); + break; + case 6: + $error = Tools::displayError('Missing temporary folder'); + break; + case 7: + $error = Tools::displayError('Failed to write file to disk'); + break; + case 8: + $error = Tools::displayError('A PHP extension stopped the file upload'); + break; + default; + break; + } + return $error; + } - protected function validate(&$file) - { - $file['error'] = $this->checkUploadError($file['error']); + protected function validate(&$file) + { + $file['error'] = $this->checkUploadError($file['error']); - $post_max_size = $this->getPostMaxSizeBytes(); + $post_max_size = $this->getPostMaxSizeBytes(); - if ($post_max_size && ($this->_getServerVars('CONTENT_LENGTH') > $post_max_size)) - { - $file['error'] = Tools::displayError('The uploaded file exceeds the post_max_size directive in php.ini'); - return false; - } + if ($post_max_size && ($this->_getServerVars('CONTENT_LENGTH') > $post_max_size)) { + $file['error'] = Tools::displayError('The uploaded file exceeds the post_max_size directive in php.ini'); + return false; + } - if (preg_match('/\%00/', $file['name'])) - { - $file['error'] = Tools::displayError('Invalid file name'); - return false; - } + if (preg_match('/\%00/', $file['name'])) { + $file['error'] = Tools::displayError('Invalid file name'); + return false; + } - $types = $this->getAcceptTypes(); + $types = $this->getAcceptTypes(); - //TODO check mime type. - if (isset($types) && !in_array(pathinfo($file['name'], PATHINFO_EXTENSION), $types)) - { - $file['error'] = Tools::displayError('Filetype not allowed'); - return false; - } + //TODO check mime type. + if (isset($types) && !in_array(pathinfo($file['name'], PATHINFO_EXTENSION), $types)) { + $file['error'] = Tools::displayError('Filetype not allowed'); + return false; + } - if ($this->checkFileSize() && $file['size'] > $this->getMaxSize()) - { - $file['error'] = sprintf(Tools::displayError('File (size : %1s) is too big (max : %2s)'), $file['size'], $this->getMaxSize()); - return false; - } + if ($this->checkFileSize() && $file['size'] > $this->getMaxSize()) { + $file['error'] = sprintf(Tools::displayError('File (size : %1s) is too big (max : %2s)'), $file['size'], $this->getMaxSize()); + return false; + } - return true; - } + return true; + } - protected function _getFileSize($file_path, $clear_stat_cache = false) - { - if ($clear_stat_cache) - clearstatcache(true, $file_path); + protected function _getFileSize($file_path, $clear_stat_cache = false) + { + if ($clear_stat_cache) { + clearstatcache(true, $file_path); + } - return filesize($file_path); - } + return filesize($file_path); + } - protected function _getServerVars($var) - { - return (isset($_SERVER[$var]) ? $_SERVER[$var] : ''); - } + protected function _getServerVars($var) + { + return (isset($_SERVER[$var]) ? $_SERVER[$var] : ''); + } - protected function _normalizeDirectory($directory) - { - $last = $directory[strlen($directory) - 1]; + protected function _normalizeDirectory($directory) + { + $last = $directory[strlen($directory) - 1]; - if (in_array($last, array('/', '\\'))) - { - $directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR; - return $directory; - } + if (in_array($last, array('/', '\\'))) { + $directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR; + return $directory; + } - $directory .= DIRECTORY_SEPARATOR; - return $directory; - } + $directory .= DIRECTORY_SEPARATOR; + return $directory; + } } diff --git a/classes/Validate.php b/classes/Validate.php index ecc44d25..2d7c4793 100644 --- a/classes/Validate.php +++ b/classes/Validate.php @@ -26,1055 +26,1073 @@ class ValidateCore { - const ADMIN_PASSWORD_LENGTH = 8; - const PASSWORD_LENGTH = 5; - - public static function isIp2Long($ip) - { - return preg_match('#^-?[0-9]+$#', (string)$ip); - } - - public static function isAnything() - { - return true; - } - - /** - * Check for e-mail validity - * - * @param string $email e-mail address to validate - * @return bool Validity is ok or not - */ - public static function isEmail($email) - { - return !empty($email) && preg_match(Tools::cleanNonUnicodeSupport('/^[a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]+[.a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]*@[a-z\p{L}0-9]+(?:[.]?[_a-z\p{L}0-9-])*\.[a-z\p{L}0-9]+$/ui'), $email); - } - - /** - * Check for module URL validity - * - * @param string $url module URL to validate - * @param array $errors Reference array for catching errors - * @return bool Validity is ok or not - */ - public static function isModuleUrl($url, &$errors) - { - if (!$url || $url == 'http://') - $errors[] = Tools::displayError('Please specify module URL'); - elseif (substr($url, -4) != '.tar' && substr($url, -4) != '.zip' && substr($url, -4) != '.tgz' && substr($url, -7) != '.tar.gz') - $errors[] = Tools::displayError('Unknown archive type'); - else - { - if ((strpos($url, 'http')) === false) - $url = 'http://'.$url; - if (!is_array(@get_headers($url))) - $errors[] = Tools::displayError('Invalid URL'); - } - if (!count($errors)) - return true; - return false; - - } - - /** - * Check for MD5 string validity - * - * @param string $md5 MD5 string to validate - * @return bool Validity is ok or not - */ - public static function isMd5($md5) - { - return preg_match('/^[a-f0-9A-F]{32}$/', $md5); - } - - /** - * Check for SHA1 string validity - * - * @param string $sha1 SHA1 string to validate - * @return bool Validity is ok or not - */ - public static function isSha1($sha1) - { - return preg_match('/^[a-fA-F0-9]{40}$/', $sha1); - } - - /** - * Check for a float number validity - * - * @param float $float Float number to validate - * @return bool Validity is ok or not - */ - public static function isFloat($float) - { - return strval((float)$float) == strval($float); - } - - public static function isUnsignedFloat($float) - { - return strval((float)$float) == strval($float) && $float >= 0; - } - - /** - * Check for a float number validity - * - * @param float $float Float number to validate - * @return bool Validity is ok or not - */ - public static function isOptFloat($float) - { - return empty($float) || Validate::isFloat($float); - } - - /** - * Check for a carrier name validity - * - * @param string $name Carrier name to validate - * @return bool Validity is ok or not - */ - public static function isCarrierName($name) - { - return empty($name) || preg_match(Tools::cleanNonUnicodeSupport('/^[^<>;=#{}]*$/u'), $name); - } - - /** - * Check for an image size validity - * - * @param string $size Image size to validate - * @return bool Validity is ok or not - */ - public static function isImageSize($size) - { - return preg_match('/^[0-9]{1,4}$/', $size); - } - - /** - * Check for name validity - * - * @param string $name Name to validate - * @return bool Validity is ok or not - */ - public static function isName($name) - { - return preg_match(Tools::cleanNonUnicodeSupport('/^[^0-9!<>,;?=+()@#"°{}_$%:]*$/u'), stripslashes($name)); - } - - /** - * Check for hook name validity - * - * @param string $hook Hook name to validate - * @return bool Validity is ok or not - */ - public static function isHookName($hook) - { - return preg_match('/^[a-zA-Z0-9_-]+$/', $hook); - } - - /** - * Check for sender name validity - * - * @param string $mail_name Sender name to validate - * @return bool Validity is ok or not - */ - public static function isMailName($mail_name) - { - return (is_string($mail_name) && preg_match(Tools::cleanNonUnicodeSupport('/^[^<>;=#{}]*$/u'), $mail_name)); - } - - /** - * Check for e-mail subject validity - * - * @param string $mail_subject e-mail subject to validate - * @return bool Validity is ok or not - */ - public static function isMailSubject($mail_subject) - { - return preg_match(Tools::cleanNonUnicodeSupport('/^[^<>]*$/u'), $mail_subject); - } - - /** - * Check for module name validity - * - * @param string $module_name Module name to validate - * @return bool Validity is ok or not - */ - public static function isModuleName($module_name) - { - return (is_string($module_name) && preg_match('/^[a-zA-Z0-9_-]+$/', $module_name)); - } - - /** - * Check for template name validity - * - * @param string $tpl_name Template name to validate - * @return bool Validity is ok or not - */ - public static function isTplName($tpl_name) - { - return preg_match('/^[a-zA-Z0-9_-]+$/', $tpl_name); - } - - /** - * Check for image type name validity - * - * @param string $type Image type name to validate - * @return bool Validity is ok or not - */ - public static function isImageTypeName($type) - { - return preg_match('/^[a-zA-Z0-9_ -]+$/', $type); - } - - /** - * Check for price validity - * - * @param string $price Price to validate - * @return bool Validity is ok or not - */ - public static function isPrice($price) - { - return preg_match('/^[0-9]{1,10}(\.[0-9]{1,9})?$/', $price); - } - - /** - * Check for price validity (including negative price) - * - * @param string $price Price to validate - * @return bool Validity is ok or not - */ - public static function isNegativePrice($price) - { - return preg_match('/^[-]?[0-9]{1,10}(\.[0-9]{1,9})?$/', $price); - } - - /** - * Check for language code (ISO) validity - * - * @param string $iso_code Language code (ISO) to validate - * @return bool Validity is ok or not - */ - public static function isLanguageIsoCode($iso_code) - { - return preg_match('/^[a-zA-Z]{2,3}$/', $iso_code); - } - - public static function isLanguageCode($s) - { - return preg_match('/^[a-zA-Z]{2}(-[a-zA-Z]{2})?$/', $s); - } - - public static function isStateIsoCode($iso_code) - { - return preg_match('/^[a-zA-Z0-9]{1,4}((-)[a-zA-Z0-9]{1,4})?$/', $iso_code); - } - - public static function isNumericIsoCode($iso_code) - { - return preg_match('/^[0-9]{2,3}$/', $iso_code); - } - - /** - * Check for voucher name validity - * - * @param string $voucher voucher to validate - * @return bool Validity is ok or not - */ - public static function isDiscountName($voucher) - { - return preg_match(Tools::cleanNonUnicodeSupport('/^[^!<>,;?=+()@"°{}_$%:]{3,32}$/u'), $voucher); - } - - /** - * Check for product or category name validity - * - * @param string $name Product or category name to validate - * @return bool Validity is ok or not - */ - public static function isCatalogName($name) - { - return preg_match(Tools::cleanNonUnicodeSupport('/^[^<>;=#{}]*$/u'), $name); - } - - /** - * Check for a message validity - * - * @param string $message Message to validate - * @return bool Validity is ok or not - */ - public static function isMessage($message) - { - return !preg_match('/[<>{}]/i', $message); - } - - /** - * Check for a country name validity - * - * @param string $name Country name to validate - * @return bool Validity is ok or not - */ - public static function isCountryName($name) - { - return preg_match('/^[a-zA-Z -]+$/', $name); - } - - /** - * Check for a link (url-rewriting only) validity - * - * @param string $link Link to validate - * @return bool Validity is ok or not - */ - public static function isLinkRewrite($link) - { - if (Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL')) - return preg_match(Tools::cleanNonUnicodeSupport('/^[_a-zA-Z0-9\pL\pS-]+$/u'), $link); - return preg_match('/^[_a-zA-Z0-9\-]+$/', $link); - } - - /** - * Check for a route pattern validity - * - * @param string $pattern to validate - * @return bool Validity is ok or not - */ - public static function isRoutePattern($pattern) - { - if (Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL')) - return preg_match(Tools::cleanNonUnicodeSupport('/^[_a-zA-Z0-9\(\)\.{}:\/\pL\pS-]+$/u'), $pattern); - return preg_match('/^[_a-zA-Z0-9\(\)\.{}:\/\-]+$/', $pattern); - } - - /** - * Check for a postal address validity - * - * @param string $address Address to validate - * @return bool Validity is ok or not - */ - public static function isAddress($address) - { - return empty($address) || preg_match(Tools::cleanNonUnicodeSupport('/^[^!<>?=+@{}_$%]*$/u'), $address); - } - - /** - * Check for city name validity - * - * @param string $city City name to validate - * @return bool Validity is ok or not - */ - public static function isCityName($city) - { - return preg_match(Tools::cleanNonUnicodeSupport('/^[^!<>;?=+@#"°{}_$%]*$/u'), $city); - } - - /** - * Check for search query validity - * - * @param string $search Query to validate - * @return bool Validity is ok or not - */ - public static function isValidSearch($search) - { - return preg_match(Tools::cleanNonUnicodeSupport('/^[^<>;=#{}]{0,64}$/u'), $search); - } - - /** - * Check for standard name validity - * - * @param string $name Name to validate - * @return bool Validity is ok or not - */ - public static function isGenericName($name) - { - return empty($name) || preg_match(Tools::cleanNonUnicodeSupport('/^[^<>={}]*$/u'), $name); - } - - /** - * Check for HTML field validity (no XSS please !) - * - * @param string $html HTML field to validate - * @return bool Validity is ok or not - */ - public static function isCleanHtml($html, $allow_iframe = false) - { - $events = 'onmousedown|onmousemove|onmmouseup|onmouseover|onmouseout|onload|onunload|onfocus|onblur|onchange'; - $events .= '|onsubmit|ondblclick|onclick|onkeydown|onkeyup|onkeypress|onmouseenter|onmouseleave|onerror|onselect|onreset|onabort|ondragdrop|onresize|onactivate|onafterprint|onmoveend'; - $events .= '|onafterupdate|onbeforeactivate|onbeforecopy|onbeforecut|onbeforedeactivate|onbeforeeditfocus|onbeforepaste|onbeforeprint|onbeforeunload|onbeforeupdate|onmove'; - $events .= '|onbounce|oncellchange|oncontextmenu|oncontrolselect|oncopy|oncut|ondataavailable|ondatasetchanged|ondatasetcomplete|ondeactivate|ondrag|ondragend|ondragenter|onmousewheel'; - $events .= '|ondragleave|ondragover|ondragstart|ondrop|onerrorupdate|onfilterchange|onfinish|onfocusin|onfocusout|onhashchange|onhelp|oninput|onlosecapture|onmessage|onmouseup|onmovestart'; - $events .= '|onoffline|ononline|onpaste|onpropertychange|onreadystatechange|onresizeend|onresizestart|onrowenter|onrowexit|onrowsdelete|onrowsinserted|onscroll|onsearch|onselectionchange'; - $events .= '|onselectstart|onstart|onstop'; - - if (preg_match('/<[\s]*script/ims', $html) || preg_match('/('.$events.')[\s]*=/ims', $html) || preg_match('/.*script\:/ims', $html)) - return false; - - if (!$allow_iframe && preg_match('/<[\s]*(i?frame|form|input|embed|object)/ims', $html)) - return false; - - return true; - } - - /** - * Check for product reference validity - * - * @param string $reference Product reference to validate - * @return bool Validity is ok or not - */ - public static function isReference($reference) - { - return preg_match(Tools::cleanNonUnicodeSupport('/^[^<>;={}]*$/u'), $reference); - } - - /** - * Check for password validity - * - * @param string $passwd Password to validate - * @param int $size - * @return bool Validity is ok or not - */ - public static function isPasswd($passwd, $size = Validate::PASSWORD_LENGTH) - { - return (Tools::strlen($passwd) >= $size && Tools::strlen($passwd) < 255); - } - - public static function isPasswdAdmin($passwd) - { - return Validate::isPasswd($passwd, Validate::ADMIN_PASSWORD_LENGTH); - } - - /** - * Check for configuration key validity - * - * @param string $config_name Configuration key to validate - * @return bool Validity is ok or not - */ - public static function isConfigName($config_name) - { - return preg_match('/^[a-zA-Z_0-9-]+$/', $config_name); - } - - /** - * Check date formats like http://php.net/manual/en/function.date.php - * - * @param string $date_format date format to check - * @return bool Validity is ok or not - */ - public static function isPhpDateFormat($date_format) - { - // We can't really check if this is valid or not, because this is a string and you can write whatever you want in it. - // That's why only < et > are forbidden (HTML) - return preg_match('/^[^<>]+$/', $date_format); - } - - /** - * Check for date format - * - * @param string $date Date to validate - * @return bool Validity is ok or not - */ - public static function isDateFormat($date) - { - return (bool)preg_match('/^([0-9]{4})-((0?[0-9])|(1[0-2]))-((0?[0-9])|([1-2][0-9])|(3[01]))( [0-9]{2}:[0-9]{2}:[0-9]{2})?$/', $date); - } - - /** - * Check for date validity - * - * @param string $date Date to validate - * @return bool Validity is ok or not - */ - public static function isDate($date) - { - if (!preg_match('/^([0-9]{4})-((?:0?[0-9])|(?:1[0-2]))-((?:0?[0-9])|(?:[1-2][0-9])|(?:3[01]))( [0-9]{2}:[0-9]{2}:[0-9]{2})?$/', $date, $matches)) - return false; - return checkdate((int)$matches[2], (int)$matches[3], (int)$matches[1]); - } - - /** - * Check for birthDate validity - * - * @param string $date birthdate to validate - * @return bool Validity is ok or not - */ - public static function isBirthDate($date) - { - if (empty($date) || $date == '0000-00-00') - return true; - if (preg_match('/^([0-9]{4})-((?:0?[1-9])|(?:1[0-2]))-((?:0?[1-9])|(?:[1-2][0-9])|(?:3[01]))([0-9]{2}:[0-9]{2}:[0-9]{2})?$/', $date, $birth_date)) - { - if ($birth_date[1] > date('Y') && $birth_date[2] > date('m') && $birth_date[3] > date('d') - || $birth_date[1] == date('Y') && $birth_date[2] == date('m') && $birth_date[3] > date('d') - || $birth_date[1] == date('Y') && $birth_date[2] > date('m')) - return false; - return true; - } - return false; - } - - /** - * Check for boolean validity - * - * @param bool $bool Boolean to validate - * @return bool Validity is ok or not - */ - public static function isBool($bool) - { - return $bool === null || is_bool($bool) || preg_match('/^(0|1)$/', $bool); - } - - /** - * Check for phone number validity - * - * @param string $number Phone number to validate - * @return bool Validity is ok or not - */ - public static function isPhoneNumber($number) - { - return preg_match('/^[+0-9. ()-]*$/', $number); - } - - /** - * Check for barcode validity (EAN-13) - * - * @param string $ean13 Barcode to validate - * @return bool Validity is ok or not - */ - public static function isEan13($ean13) - { - return !$ean13 || preg_match('/^[0-9]{0,13}$/', $ean13); - } - - /** - * Check for barcode validity (UPC) - * - * @param string $upc Barcode to validate - * @return bool Validity is ok or not - */ - public static function isUpc($upc) - { - return !$upc || preg_match('/^[0-9]{0,12}$/', $upc); - } - - /** - * Check for postal code validity - * - * @param string $postcode Postal code to validate - * @return bool Validity is ok or not - */ - public static function isPostCode($postcode) - { - return empty($postcode) || preg_match('/^[a-zA-Z 0-9-]+$/', $postcode); - } - - /** - * Check for zip code format validity - * - * @param string $zip_code zip code format to validate - * @return bool Validity is ok or not - */ - public static function isZipCodeFormat($zip_code) - { - if (!empty($zip_code)) - return preg_match('/^[NLCnlc 0-9-]+$/', $zip_code); - return true; - } - - /** - * Check for table or identifier validity - * Mostly used in database for ordering : ASC / DESC - * - * @param string $way Keyword to validate - * @return bool Validity is ok or not - */ - public static function isOrderWay($way) - { - return ($way === 'ASC' | $way === 'DESC' | $way === 'asc' | $way === 'desc'); - } - - /** - * Check for table or identifier validity - * Mostly used in database for ordering : ORDER BY field - * - * @param string $order Field to validate - * @return bool Validity is ok or not - */ - public static function isOrderBy($order) - { - return preg_match('/^[a-zA-Z0-9.!_-]+$/', $order); - } - - /** - * Check for table or identifier validity - * Mostly used in database for table names and id_table - * - * @param string $table Table/identifier to validate - * @return bool Validity is ok or not - */ - public static function isTableOrIdentifier($table) - { - return preg_match('/^[a-zA-Z0-9_-]+$/', $table); - } - - /** - * @deprecated 1.5.0 You should not use list like this, please use an array when you build a SQL query - */ - public static function isValuesList() - { - Tools::displayAsDeprecated(); - return true; - /* For history reason, we keep this line */ - // return preg_match('/^[0-9,\'(). NULL]+$/', $list); - } - - /** - * Check for tags list validity - * - * @param string $list List to validate - * @return bool Validity is ok or not - */ - public static function isTagsList($list) - { - return preg_match(Tools::cleanNonUnicodeSupport('/^[^!<>;?=+#"°{}_$%]*$/u'), $list); - } - - /** - * Check for product visibility - * - * @param string $s visibility to check - * @return bool Validity is ok or not - */ - public static function isProductVisibility($s) - { - return preg_match('/^both|catalog|search|none$/i', $s); - } - - /** - * Check for an integer validity - * - * @param int $value Integer to validate - * @return bool Validity is ok or not - */ - public static function isInt($value) - { - return ((string)(int)$value === (string)$value || $value === false); - } - - /** - * Check for an integer validity (unsigned) - * - * @param int $value Integer to validate - * @return bool Validity is ok or not - */ - public static function isUnsignedInt($value) - { - return ((string)(int)$value === (string)$value && $value < 4294967296 && $value >= 0); - } - - /** - * Check for an percentage validity (between 0 and 100) - * - * @param float $value Float to validate - * @return bool Validity is ok or not - */ - public static function isPercentage($value) - { - return (Validate::isFloat($value) && $value >= 0 && $value <= 100); - } - - /** - * Check for an integer validity (unsigned) - * Mostly used in database for auto-increment - * - * @param int $id Integer to validate - * @return bool Validity is ok or not - */ - public static function isUnsignedId($id) - { - return Validate::isUnsignedInt($id); /* Because an id could be equal to zero when there is no association */ - } - - public static function isNullOrUnsignedId($id) - { - return $id === null || Validate::isUnsignedId($id); - } - - /** - * Check object validity - * - * @param object $object Object to validate - * @return bool Validity is ok or not - */ - public static function isLoadedObject($object) - { - return is_object($object) && $object->id; - } - - /** - * Check object validity - * - * @param int $object Object to validate - * @return bool Validity is ok or not - */ - public static function isColor($color) - { - return preg_match('/^(#[0-9a-fA-F]{6}|[a-zA-Z0-9-]*)$/', $color); - } - - /** - * Check url validity (disallowed empty string) - * - * @param string $url Url to validate - * @return bool Validity is ok or not - */ - public static function isUrl($url) - { - return preg_match(Tools::cleanNonUnicodeSupport('/^[~:#,$%&_=\(\)\.\? \+\-@\/a-zA-Z0-9\pL\pS-]+$/u'), $url); - } - - /** - * Check tracking number validity (disallowed empty string) - * - * @param string $tracking_number Tracking number to validate - * @return bool Validity is ok or not - */ - public static function isTrackingNumber($tracking_number) - { - return preg_match('/^[~:#,%&_=\(\)\[\]\.\? \+\-@\/a-zA-Z0-9]+$/', $tracking_number); - } - - /** - * Check url validity (allowed empty string) - * - * @param string $url Url to validate - * @return bool Validity is ok or not - */ - public static function isUrlOrEmpty($url) - { - return empty($url) || Validate::isUrl($url); - } - - /** - * Check if URL is absolute - * - * @param string $url URL to validate - * @return bool Validity is ok or not - */ - public static function isAbsoluteUrl($url) - { - if (!empty($url)) - return preg_match('/^(https?:)?\/\/[$~:;#,%&_=\(\)\[\]\.\? \+\-@\/a-zA-Z0-9]+$/', $url); - return true; - } - - public static function isMySQLEngine($engine) - { - return (in_array($engine, array('InnoDB', 'MyISAM'))); - } - - public static function isUnixName($data) - { - return preg_match(Tools::cleanNonUnicodeSupport('/^[a-z0-9\._-]+$/ui'), $data); - } - - public static function isTablePrefix($data) - { - // Even if "-" is theorically allowed, it will be considered a syntax error if you do not add backquotes (`) around the table name - return preg_match(Tools::cleanNonUnicodeSupport('/^[a-z0-9_]+$/ui'), $data); - } - - /** - * Check for standard name file validity - * - * @param string $name Name to validate - * @return bool Validity is ok or not - */ - public static function isFileName($name) - { - return preg_match('/^[a-zA-Z0-9_.-]+$/', $name); - } - - /** - * Check for standard name directory validity - * - * @param string $dir Directory to validate - * @return bool Validity is ok or not - */ - public static function isDirName($dir) - { - return (bool)preg_match('/^[a-zA-Z0-9_.-]*$/', $dir); - } - - /** - * Check for admin panel tab name validity - * - * @param string $name Name to validate - * @return bool Validity is ok or not - */ - public static function isTabName($name) - { - return preg_match(Tools::cleanNonUnicodeSupport('/^[^<>]+$/u'), $name); - } - - public static function isWeightUnit($unit) - { - return (Validate::isGenericName($unit) & (Tools::strlen($unit) < 5)); - } - - public static function isDistanceUnit($unit) - { - return (Validate::isGenericName($unit) & (Tools::strlen($unit) < 5)); - } - - public static function isSubDomainName($domain) - { - return preg_match('/^[a-zA-Z0-9-_]*$/', $domain); - } - - public static function isVoucherDescription($text) - { - return preg_match('/^([^<>{}]|<br \/>)*$/i', $text); - } - - /** - * Check if the value is a sort direction value (DESC/ASC) - * - * @param string $value - * @return bool Validity is ok or not - */ - public static function isSortDirection($value) - { - return ($value !== null && ($value === 'ASC' || $value === 'DESC')); - } - - /** - * Customization fields' label validity - * - * @param string $label - * @return bool Validity is ok or not - */ - public static function isLabel($label) - { - return (preg_match(Tools::cleanNonUnicodeSupport('/^[^{}<>]*$/u'), $label)); - } - - /** - * Price display method validity - * - * @param int $data Data to validate - * @return bool Validity is ok or not - */ - public static function isPriceDisplayMethod($data) - { - return ($data == PS_TAX_EXC || $data == PS_TAX_INC); - } - - /** - * @param string $dni to validate - * @return bool - */ - public static function isDniLite($dni) - { - return empty($dni) || (bool)preg_match('/^[0-9A-Za-z-.]{1,16}$/U', $dni); - } - - /** - * Check if $data is a PrestaShop cookie object - * - * @param mixed $data to validate - * @return bool - */ - public static function isCookie($data) - { - return (is_object($data) && get_class($data) == 'Cookie'); - } - - /** - * Price display method validity - * - * @param string $data Data to validate - * @return bool Validity is ok or not - */ - public static function isString($data) - { - return is_string($data); - } - - /** - * Check if the data is a reduction type (amout or percentage) - * - * @param string $data Data to validate - * @return bool Validity is ok or not - */ - public static function isReductionType($data) - { - return ($data === 'amount' || $data === 'percentage'); - } - - /** - * Check for bool_id - * - * @param string $ids - * @return bool Validity is ok or not - */ - public static function isBoolId($ids) - { - return (bool)preg_match('#^[01]_[0-9]+$#', $ids); - } - - /** - * @deprecated 1.5.0 Use Validate::isBoolId() - */ - public static function isBool_Id($ids) - { - Tools::displayAsDeprecated(); - return Validate::isBoolId($ids); - } - - /** - * Check the localization pack part selected - * - * @param string $data Localization pack to check - * @return bool Validity is ok or not - */ - public static function isLocalizationPackSelection($data) - { - return in_array((string)$data, array('states', 'taxes', 'currencies', 'languages', 'units', 'groups')); - } - - /** - * Check for PHP serialized data - * - * @param string $data Serialized data to validate - * @return bool Validity is ok or not - */ - public static function isSerializedArray($data) - { - return $data === null || (is_string($data) && preg_match('/^a:[0-9]+:{.*;}$/s', $data)); - } - - /** - * Check for Latitude/Longitude - * - * @param string $data Coordinate to validate - * @return bool Validity is ok or not - */ - public static function isCoordinate($data) - { - return $data === null || preg_match('/^\-?[0-9]{1,8}\.[0-9]{1,8}$/s', $data); - } - - /** - * Check for Language Iso Code - * - * @param string $iso_code - * @return bool Validity is ok or not - */ - public static function isLangIsoCode($iso_code) - { - return (bool)preg_match('/^[a-zA-Z]{2,3}$/s', $iso_code); - } - - /** - * Check for Language File Name - * - * @param string $file_name - * @return bool Validity is ok or not - */ - public static function isLanguageFileName($file_name) - { - return (bool)preg_match('/^[a-zA-Z]{2,3}\.(?:gzip|tar\.gz)$/s', $file_name); - } - - /** - * - * @param array $ids - * @return bool return true if the array contain only unsigned int value - */ - public static function isArrayWithIds($ids) - { - if (count($ids)) - foreach ($ids as $id) - if ($id == 0 || !Validate::isUnsignedInt($id)) - return false; - return true; - } - - /** - * - * @param array $zones - * @return bool return true if array contain all value required for an image map zone - */ - public static function isSceneZones($zones) - { - foreach ($zones as $zone) - { - if (!isset($zone['x1']) || !Validate::isUnsignedInt($zone['x1'])) - return false; - if (!isset($zone['y1']) || !Validate::isUnsignedInt($zone['y1'])) - return false; - if (!isset($zone['width']) || !Validate::isUnsignedInt($zone['width'])) - return false; - if (!isset($zone['height']) || !Validate::isUnsignedInt($zone['height'])) - return false; - if (!isset($zone['id_product']) || !Validate::isUnsignedInt($zone['id_product'])) - return false; - } - return true; - } - - /** - * - * @param array $stock_management - * @return bool return true if is a valide stock management - */ - public static function isStockManagement($stock_management) - { - if (!in_array($stock_management, array('WA', 'FIFO', 'LIFO'))) - return false; - return true; - } - - /** - * Validate SIRET Code - * - * @param string $siret SIRET Code - * @return bool Return true if is valid - */ - public static function isSiret($siret) - { - if (Tools::strlen($siret) != 14) - return false; - $sum = 0; - for ($i = 0; $i != 14; $i++) - { - $tmp = ((($i + 1) % 2) + 1) * intval($siret[$i]); - if ($tmp >= 10) - $tmp -= 9; - $sum += $tmp; - } - return ($sum % 10 === 0); - } - - /** - * Validate APE Code - * - * @param string $ape APE Code - * @return bool Return true if is valid - */ - public static function isApe($ape) - { - return (bool)preg_match('/^[0-9]{3,4}[a-zA-Z]{1}$/s', $ape); - } - - public static function isControllerName($name) - { - return (bool)(is_string($name) && preg_match(Tools::cleanNonUnicodeSupport('/^[0-9a-zA-Z-_]*$/u'), $name)); - } - - public static function isPrestaShopVersion($version) - { - return (preg_match('/^[0-1]\.[0-9]{1,2}(\.[0-9]{1,2}){0,2}$/', $version) && ip2long($version)); - } - - public static function isOrderInvoiceNumber($id) - { - return (preg_match('/^(?:'.Configuration::get('PS_INVOICE_PREFIX', Context::getContext()->language->id).')\s*([0-9]+)$/i', $id)); - } + const ADMIN_PASSWORD_LENGTH = 8; + const PASSWORD_LENGTH = 5; + + public static function isIp2Long($ip) + { + return preg_match('#^-?[0-9]+$#', (string)$ip); + } + + public static function isAnything() + { + return true; + } + + /** + * Check for e-mail validity + * + * @param string $email e-mail address to validate + * @return bool Validity is ok or not + */ + public static function isEmail($email) + { + return !empty($email) && preg_match(Tools::cleanNonUnicodeSupport('/^[a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]+[.a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]*@[a-z\p{L}0-9]+(?:[.]?[_a-z\p{L}0-9-])*\.[a-z\p{L}0-9]+$/ui'), $email); + } + + /** + * Check for module URL validity + * + * @param string $url module URL to validate + * @param array $errors Reference array for catching errors + * @return bool Validity is ok or not + */ + public static function isModuleUrl($url, &$errors) + { + if (!$url || $url == 'http://') { + $errors[] = Tools::displayError('Please specify module URL'); + } elseif (substr($url, -4) != '.tar' && substr($url, -4) != '.zip' && substr($url, -4) != '.tgz' && substr($url, -7) != '.tar.gz') { + $errors[] = Tools::displayError('Unknown archive type'); + } else { + if ((strpos($url, 'http')) === false) { + $url = 'http://'.$url; + } + if (!is_array(@get_headers($url))) { + $errors[] = Tools::displayError('Invalid URL'); + } + } + if (!count($errors)) { + return true; + } + return false; + } + + /** + * Check for MD5 string validity + * + * @param string $md5 MD5 string to validate + * @return bool Validity is ok or not + */ + public static function isMd5($md5) + { + return preg_match('/^[a-f0-9A-F]{32}$/', $md5); + } + + /** + * Check for SHA1 string validity + * + * @param string $sha1 SHA1 string to validate + * @return bool Validity is ok or not + */ + public static function isSha1($sha1) + { + return preg_match('/^[a-fA-F0-9]{40}$/', $sha1); + } + + /** + * Check for a float number validity + * + * @param float $float Float number to validate + * @return bool Validity is ok or not + */ + public static function isFloat($float) + { + return strval((float)$float) == strval($float); + } + + public static function isUnsignedFloat($float) + { + return strval((float)$float) == strval($float) && $float >= 0; + } + + /** + * Check for a float number validity + * + * @param float $float Float number to validate + * @return bool Validity is ok or not + */ + public static function isOptFloat($float) + { + return empty($float) || Validate::isFloat($float); + } + + /** + * Check for a carrier name validity + * + * @param string $name Carrier name to validate + * @return bool Validity is ok or not + */ + public static function isCarrierName($name) + { + return empty($name) || preg_match(Tools::cleanNonUnicodeSupport('/^[^<>;=#{}]*$/u'), $name); + } + + /** + * Check for an image size validity + * + * @param string $size Image size to validate + * @return bool Validity is ok or not + */ + public static function isImageSize($size) + { + return preg_match('/^[0-9]{1,4}$/', $size); + } + + /** + * Check for name validity + * + * @param string $name Name to validate + * @return bool Validity is ok or not + */ + public static function isName($name) + { + return preg_match(Tools::cleanNonUnicodeSupport('/^[^0-9!<>,;?=+()@#"°{}_$%:]*$/u'), stripslashes($name)); + } + + /** + * Check for hook name validity + * + * @param string $hook Hook name to validate + * @return bool Validity is ok or not + */ + public static function isHookName($hook) + { + return preg_match('/^[a-zA-Z0-9_-]+$/', $hook); + } + + /** + * Check for sender name validity + * + * @param string $mail_name Sender name to validate + * @return bool Validity is ok or not + */ + public static function isMailName($mail_name) + { + return (is_string($mail_name) && preg_match(Tools::cleanNonUnicodeSupport('/^[^<>;=#{}]*$/u'), $mail_name)); + } + + /** + * Check for e-mail subject validity + * + * @param string $mail_subject e-mail subject to validate + * @return bool Validity is ok or not + */ + public static function isMailSubject($mail_subject) + { + return preg_match(Tools::cleanNonUnicodeSupport('/^[^<>]*$/u'), $mail_subject); + } + + /** + * Check for module name validity + * + * @param string $module_name Module name to validate + * @return bool Validity is ok or not + */ + public static function isModuleName($module_name) + { + return (is_string($module_name) && preg_match('/^[a-zA-Z0-9_-]+$/', $module_name)); + } + + /** + * Check for template name validity + * + * @param string $tpl_name Template name to validate + * @return bool Validity is ok or not + */ + public static function isTplName($tpl_name) + { + return preg_match('/^[a-zA-Z0-9_-]+$/', $tpl_name); + } + + /** + * Check for image type name validity + * + * @param string $type Image type name to validate + * @return bool Validity is ok or not + */ + public static function isImageTypeName($type) + { + return preg_match('/^[a-zA-Z0-9_ -]+$/', $type); + } + + /** + * Check for price validity + * + * @param string $price Price to validate + * @return bool Validity is ok or not + */ + public static function isPrice($price) + { + return preg_match('/^[0-9]{1,10}(\.[0-9]{1,9})?$/', $price); + } + + /** + * Check for price validity (including negative price) + * + * @param string $price Price to validate + * @return bool Validity is ok or not + */ + public static function isNegativePrice($price) + { + return preg_match('/^[-]?[0-9]{1,10}(\.[0-9]{1,9})?$/', $price); + } + + /** + * Check for language code (ISO) validity + * + * @param string $iso_code Language code (ISO) to validate + * @return bool Validity is ok or not + */ + public static function isLanguageIsoCode($iso_code) + { + return preg_match('/^[a-zA-Z]{2,3}$/', $iso_code); + } + + public static function isLanguageCode($s) + { + return preg_match('/^[a-zA-Z]{2}(-[a-zA-Z]{2})?$/', $s); + } + + public static function isStateIsoCode($iso_code) + { + return preg_match('/^[a-zA-Z0-9]{1,4}((-)[a-zA-Z0-9]{1,4})?$/', $iso_code); + } + + public static function isNumericIsoCode($iso_code) + { + return preg_match('/^[0-9]{2,3}$/', $iso_code); + } + + /** + * Check for voucher name validity + * + * @param string $voucher voucher to validate + * @return bool Validity is ok or not + */ + public static function isDiscountName($voucher) + { + return preg_match(Tools::cleanNonUnicodeSupport('/^[^!<>,;?=+()@"°{}_$%:]{3,32}$/u'), $voucher); + } + + /** + * Check for product or category name validity + * + * @param string $name Product or category name to validate + * @return bool Validity is ok or not + */ + public static function isCatalogName($name) + { + return preg_match(Tools::cleanNonUnicodeSupport('/^[^<>;=#{}]*$/u'), $name); + } + + /** + * Check for a message validity + * + * @param string $message Message to validate + * @return bool Validity is ok or not + */ + public static function isMessage($message) + { + return !preg_match('/[<>{}]/i', $message); + } + + /** + * Check for a country name validity + * + * @param string $name Country name to validate + * @return bool Validity is ok or not + */ + public static function isCountryName($name) + { + return preg_match('/^[a-zA-Z -]+$/', $name); + } + + /** + * Check for a link (url-rewriting only) validity + * + * @param string $link Link to validate + * @return bool Validity is ok or not + */ + public static function isLinkRewrite($link) + { + if (Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL')) { + return preg_match(Tools::cleanNonUnicodeSupport('/^[_a-zA-Z0-9\pL\pS-]+$/u'), $link); + } + return preg_match('/^[_a-zA-Z0-9\-]+$/', $link); + } + + /** + * Check for a route pattern validity + * + * @param string $pattern to validate + * @return bool Validity is ok or not + */ + public static function isRoutePattern($pattern) + { + if (Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL')) { + return preg_match(Tools::cleanNonUnicodeSupport('/^[_a-zA-Z0-9\(\)\.{}:\/\pL\pS-]+$/u'), $pattern); + } + return preg_match('/^[_a-zA-Z0-9\(\)\.{}:\/\-]+$/', $pattern); + } + + /** + * Check for a postal address validity + * + * @param string $address Address to validate + * @return bool Validity is ok or not + */ + public static function isAddress($address) + { + return empty($address) || preg_match(Tools::cleanNonUnicodeSupport('/^[^!<>?=+@{}_$%]*$/u'), $address); + } + + /** + * Check for city name validity + * + * @param string $city City name to validate + * @return bool Validity is ok or not + */ + public static function isCityName($city) + { + return preg_match(Tools::cleanNonUnicodeSupport('/^[^!<>;?=+@#"°{}_$%]*$/u'), $city); + } + + /** + * Check for search query validity + * + * @param string $search Query to validate + * @return bool Validity is ok or not + */ + public static function isValidSearch($search) + { + return preg_match(Tools::cleanNonUnicodeSupport('/^[^<>;=#{}]{0,64}$/u'), $search); + } + + /** + * Check for standard name validity + * + * @param string $name Name to validate + * @return bool Validity is ok or not + */ + public static function isGenericName($name) + { + return empty($name) || preg_match(Tools::cleanNonUnicodeSupport('/^[^<>={}]*$/u'), $name); + } + + /** + * Check for HTML field validity (no XSS please !) + * + * @param string $html HTML field to validate + * @return bool Validity is ok or not + */ + public static function isCleanHtml($html, $allow_iframe = false) + { + $events = 'onmousedown|onmousemove|onmmouseup|onmouseover|onmouseout|onload|onunload|onfocus|onblur|onchange'; + $events .= '|onsubmit|ondblclick|onclick|onkeydown|onkeyup|onkeypress|onmouseenter|onmouseleave|onerror|onselect|onreset|onabort|ondragdrop|onresize|onactivate|onafterprint|onmoveend'; + $events .= '|onafterupdate|onbeforeactivate|onbeforecopy|onbeforecut|onbeforedeactivate|onbeforeeditfocus|onbeforepaste|onbeforeprint|onbeforeunload|onbeforeupdate|onmove'; + $events .= '|onbounce|oncellchange|oncontextmenu|oncontrolselect|oncopy|oncut|ondataavailable|ondatasetchanged|ondatasetcomplete|ondeactivate|ondrag|ondragend|ondragenter|onmousewheel'; + $events .= '|ondragleave|ondragover|ondragstart|ondrop|onerrorupdate|onfilterchange|onfinish|onfocusin|onfocusout|onhashchange|onhelp|oninput|onlosecapture|onmessage|onmouseup|onmovestart'; + $events .= '|onoffline|ononline|onpaste|onpropertychange|onreadystatechange|onresizeend|onresizestart|onrowenter|onrowexit|onrowsdelete|onrowsinserted|onscroll|onsearch|onselectionchange'; + $events .= '|onselectstart|onstart|onstop'; + + if (preg_match('/<[\s]*script/ims', $html) || preg_match('/('.$events.')[\s]*=/ims', $html) || preg_match('/.*script\:/ims', $html)) { + return false; + } + + if (!$allow_iframe && preg_match('/<[\s]*(i?frame|form|input|embed|object)/ims', $html)) { + return false; + } + + return true; + } + + /** + * Check for product reference validity + * + * @param string $reference Product reference to validate + * @return bool Validity is ok or not + */ + public static function isReference($reference) + { + return preg_match(Tools::cleanNonUnicodeSupport('/^[^<>;={}]*$/u'), $reference); + } + + /** + * Check for password validity + * + * @param string $passwd Password to validate + * @param int $size + * @return bool Validity is ok or not + */ + public static function isPasswd($passwd, $size = Validate::PASSWORD_LENGTH) + { + return (Tools::strlen($passwd) >= $size && Tools::strlen($passwd) < 255); + } + + public static function isPasswdAdmin($passwd) + { + return Validate::isPasswd($passwd, Validate::ADMIN_PASSWORD_LENGTH); + } + + /** + * Check for configuration key validity + * + * @param string $config_name Configuration key to validate + * @return bool Validity is ok or not + */ + public static function isConfigName($config_name) + { + return preg_match('/^[a-zA-Z_0-9-]+$/', $config_name); + } + + /** + * Check date formats like http://php.net/manual/en/function.date.php + * + * @param string $date_format date format to check + * @return bool Validity is ok or not + */ + public static function isPhpDateFormat($date_format) + { + // We can't really check if this is valid or not, because this is a string and you can write whatever you want in it. + // That's why only < et > are forbidden (HTML) + return preg_match('/^[^<>]+$/', $date_format); + } + + /** + * Check for date format + * + * @param string $date Date to validate + * @return bool Validity is ok or not + */ + public static function isDateFormat($date) + { + return (bool)preg_match('/^([0-9]{4})-((0?[0-9])|(1[0-2]))-((0?[0-9])|([1-2][0-9])|(3[01]))( [0-9]{2}:[0-9]{2}:[0-9]{2})?$/', $date); + } + + /** + * Check for date validity + * + * @param string $date Date to validate + * @return bool Validity is ok or not + */ + public static function isDate($date) + { + if (!preg_match('/^([0-9]{4})-((?:0?[0-9])|(?:1[0-2]))-((?:0?[0-9])|(?:[1-2][0-9])|(?:3[01]))( [0-9]{2}:[0-9]{2}:[0-9]{2})?$/', $date, $matches)) { + return false; + } + return checkdate((int)$matches[2], (int)$matches[3], (int)$matches[1]); + } + + /** + * Check for birthDate validity + * + * @param string $date birthdate to validate + * @return bool Validity is ok or not + */ + public static function isBirthDate($date) + { + if (empty($date) || $date == '0000-00-00') { + return true; + } + if (preg_match('/^([0-9]{4})-((?:0?[1-9])|(?:1[0-2]))-((?:0?[1-9])|(?:[1-2][0-9])|(?:3[01]))([0-9]{2}:[0-9]{2}:[0-9]{2})?$/', $date, $birth_date)) { + if ($birth_date[1] > date('Y') && $birth_date[2] > date('m') && $birth_date[3] > date('d') + || $birth_date[1] == date('Y') && $birth_date[2] == date('m') && $birth_date[3] > date('d') + || $birth_date[1] == date('Y') && $birth_date[2] > date('m')) { + return false; + } + return true; + } + return false; + } + + /** + * Check for boolean validity + * + * @param bool $bool Boolean to validate + * @return bool Validity is ok or not + */ + public static function isBool($bool) + { + return $bool === null || is_bool($bool) || preg_match('/^(0|1)$/', $bool); + } + + /** + * Check for phone number validity + * + * @param string $number Phone number to validate + * @return bool Validity is ok or not + */ + public static function isPhoneNumber($number) + { + return preg_match('/^[+0-9. ()-]*$/', $number); + } + + /** + * Check for barcode validity (EAN-13) + * + * @param string $ean13 Barcode to validate + * @return bool Validity is ok or not + */ + public static function isEan13($ean13) + { + return !$ean13 || preg_match('/^[0-9]{0,13}$/', $ean13); + } + + /** + * Check for barcode validity (UPC) + * + * @param string $upc Barcode to validate + * @return bool Validity is ok or not + */ + public static function isUpc($upc) + { + return !$upc || preg_match('/^[0-9]{0,12}$/', $upc); + } + + /** + * Check for postal code validity + * + * @param string $postcode Postal code to validate + * @return bool Validity is ok or not + */ + public static function isPostCode($postcode) + { + return empty($postcode) || preg_match('/^[a-zA-Z 0-9-]+$/', $postcode); + } + + /** + * Check for zip code format validity + * + * @param string $zip_code zip code format to validate + * @return bool Validity is ok or not + */ + public static function isZipCodeFormat($zip_code) + { + if (!empty($zip_code)) { + return preg_match('/^[NLCnlc 0-9-]+$/', $zip_code); + } + return true; + } + + /** + * Check for table or identifier validity + * Mostly used in database for ordering : ASC / DESC + * + * @param string $way Keyword to validate + * @return bool Validity is ok or not + */ + public static function isOrderWay($way) + { + return ($way === 'ASC' | $way === 'DESC' | $way === 'asc' | $way === 'desc'); + } + + /** + * Check for table or identifier validity + * Mostly used in database for ordering : ORDER BY field + * + * @param string $order Field to validate + * @return bool Validity is ok or not + */ + public static function isOrderBy($order) + { + return preg_match('/^[a-zA-Z0-9.!_-]+$/', $order); + } + + /** + * Check for table or identifier validity + * Mostly used in database for table names and id_table + * + * @param string $table Table/identifier to validate + * @return bool Validity is ok or not + */ + public static function isTableOrIdentifier($table) + { + return preg_match('/^[a-zA-Z0-9_-]+$/', $table); + } + + /** + * @deprecated 1.5.0 You should not use list like this, please use an array when you build a SQL query + */ + public static function isValuesList() + { + Tools::displayAsDeprecated(); + return true; + /* For history reason, we keep this line */ + // return preg_match('/^[0-9,\'(). NULL]+$/', $list); + } + + /** + * Check for tags list validity + * + * @param string $list List to validate + * @return bool Validity is ok or not + */ + public static function isTagsList($list) + { + return preg_match(Tools::cleanNonUnicodeSupport('/^[^!<>;?=+#"°{}_$%]*$/u'), $list); + } + + /** + * Check for product visibility + * + * @param string $s visibility to check + * @return bool Validity is ok or not + */ + public static function isProductVisibility($s) + { + return preg_match('/^both|catalog|search|none$/i', $s); + } + + /** + * Check for an integer validity + * + * @param int $value Integer to validate + * @return bool Validity is ok or not + */ + public static function isInt($value) + { + return ((string)(int)$value === (string)$value || $value === false); + } + + /** + * Check for an integer validity (unsigned) + * + * @param int $value Integer to validate + * @return bool Validity is ok or not + */ + public static function isUnsignedInt($value) + { + return ((string)(int)$value === (string)$value && $value < 4294967296 && $value >= 0); + } + + /** + * Check for an percentage validity (between 0 and 100) + * + * @param float $value Float to validate + * @return bool Validity is ok or not + */ + public static function isPercentage($value) + { + return (Validate::isFloat($value) && $value >= 0 && $value <= 100); + } + + /** + * Check for an integer validity (unsigned) + * Mostly used in database for auto-increment + * + * @param int $id Integer to validate + * @return bool Validity is ok or not + */ + public static function isUnsignedId($id) + { + return Validate::isUnsignedInt($id); /* Because an id could be equal to zero when there is no association */ + } + + public static function isNullOrUnsignedId($id) + { + return $id === null || Validate::isUnsignedId($id); + } + + /** + * Check object validity + * + * @param object $object Object to validate + * @return bool Validity is ok or not + */ + public static function isLoadedObject($object) + { + return is_object($object) && $object->id; + } + + /** + * Check object validity + * + * @param int $object Object to validate + * @return bool Validity is ok or not + */ + public static function isColor($color) + { + return preg_match('/^(#[0-9a-fA-F]{6}|[a-zA-Z0-9-]*)$/', $color); + } + + /** + * Check url validity (disallowed empty string) + * + * @param string $url Url to validate + * @return bool Validity is ok or not + */ + public static function isUrl($url) + { + return preg_match(Tools::cleanNonUnicodeSupport('/^[~:#,$%&_=\(\)\.\? \+\-@\/a-zA-Z0-9\pL\pS-]+$/u'), $url); + } + + /** + * Check tracking number validity (disallowed empty string) + * + * @param string $tracking_number Tracking number to validate + * @return bool Validity is ok or not + */ + public static function isTrackingNumber($tracking_number) + { + return preg_match('/^[~:#,%&_=\(\)\[\]\.\? \+\-@\/a-zA-Z0-9]+$/', $tracking_number); + } + + /** + * Check url validity (allowed empty string) + * + * @param string $url Url to validate + * @return bool Validity is ok or not + */ + public static function isUrlOrEmpty($url) + { + return empty($url) || Validate::isUrl($url); + } + + /** + * Check if URL is absolute + * + * @param string $url URL to validate + * @return bool Validity is ok or not + */ + public static function isAbsoluteUrl($url) + { + if (!empty($url)) { + return preg_match('/^(https?:)?\/\/[$~:;#,%&_=\(\)\[\]\.\? \+\-@\/a-zA-Z0-9]+$/', $url); + } + return true; + } + + public static function isMySQLEngine($engine) + { + return (in_array($engine, array('InnoDB', 'MyISAM'))); + } + + public static function isUnixName($data) + { + return preg_match(Tools::cleanNonUnicodeSupport('/^[a-z0-9\._-]+$/ui'), $data); + } + + public static function isTablePrefix($data) + { + // Even if "-" is theorically allowed, it will be considered a syntax error if you do not add backquotes (`) around the table name + return preg_match(Tools::cleanNonUnicodeSupport('/^[a-z0-9_]+$/ui'), $data); + } + + /** + * Check for standard name file validity + * + * @param string $name Name to validate + * @return bool Validity is ok or not + */ + public static function isFileName($name) + { + return preg_match('/^[a-zA-Z0-9_.-]+$/', $name); + } + + /** + * Check for standard name directory validity + * + * @param string $dir Directory to validate + * @return bool Validity is ok or not + */ + public static function isDirName($dir) + { + return (bool)preg_match('/^[a-zA-Z0-9_.-]*$/', $dir); + } + + /** + * Check for admin panel tab name validity + * + * @param string $name Name to validate + * @return bool Validity is ok or not + */ + public static function isTabName($name) + { + return preg_match(Tools::cleanNonUnicodeSupport('/^[^<>]+$/u'), $name); + } + + public static function isWeightUnit($unit) + { + return (Validate::isGenericName($unit) & (Tools::strlen($unit) < 5)); + } + + public static function isDistanceUnit($unit) + { + return (Validate::isGenericName($unit) & (Tools::strlen($unit) < 5)); + } + + public static function isSubDomainName($domain) + { + return preg_match('/^[a-zA-Z0-9-_]*$/', $domain); + } + + public static function isVoucherDescription($text) + { + return preg_match('/^([^<>{}]|<br \/>)*$/i', $text); + } + + /** + * Check if the value is a sort direction value (DESC/ASC) + * + * @param string $value + * @return bool Validity is ok or not + */ + public static function isSortDirection($value) + { + return ($value !== null && ($value === 'ASC' || $value === 'DESC')); + } + + /** + * Customization fields' label validity + * + * @param string $label + * @return bool Validity is ok or not + */ + public static function isLabel($label) + { + return (preg_match(Tools::cleanNonUnicodeSupport('/^[^{}<>]*$/u'), $label)); + } + + /** + * Price display method validity + * + * @param int $data Data to validate + * @return bool Validity is ok or not + */ + public static function isPriceDisplayMethod($data) + { + return ($data == PS_TAX_EXC || $data == PS_TAX_INC); + } + + /** + * @param string $dni to validate + * @return bool + */ + public static function isDniLite($dni) + { + return empty($dni) || (bool)preg_match('/^[0-9A-Za-z-.]{1,16}$/U', $dni); + } + + /** + * Check if $data is a PrestaShop cookie object + * + * @param mixed $data to validate + * @return bool + */ + public static function isCookie($data) + { + return (is_object($data) && get_class($data) == 'Cookie'); + } + + /** + * Price display method validity + * + * @param string $data Data to validate + * @return bool Validity is ok or not + */ + public static function isString($data) + { + return is_string($data); + } + + /** + * Check if the data is a reduction type (amout or percentage) + * + * @param string $data Data to validate + * @return bool Validity is ok or not + */ + public static function isReductionType($data) + { + return ($data === 'amount' || $data === 'percentage'); + } + + /** + * Check for bool_id + * + * @param string $ids + * @return bool Validity is ok or not + */ + public static function isBoolId($ids) + { + return (bool)preg_match('#^[01]_[0-9]+$#', $ids); + } + + /** + * @deprecated 1.5.0 Use Validate::isBoolId() + */ + public static function isBool_Id($ids) + { + Tools::displayAsDeprecated(); + return Validate::isBoolId($ids); + } + + /** + * Check the localization pack part selected + * + * @param string $data Localization pack to check + * @return bool Validity is ok or not + */ + public static function isLocalizationPackSelection($data) + { + return in_array((string)$data, array('states', 'taxes', 'currencies', 'languages', 'units', 'groups')); + } + + /** + * Check for PHP serialized data + * + * @param string $data Serialized data to validate + * @return bool Validity is ok or not + */ + public static function isSerializedArray($data) + { + return $data === null || (is_string($data) && preg_match('/^a:[0-9]+:{.*;}$/s', $data)); + } + + /** + * Check for Latitude/Longitude + * + * @param string $data Coordinate to validate + * @return bool Validity is ok or not + */ + public static function isCoordinate($data) + { + return $data === null || preg_match('/^\-?[0-9]{1,8}\.[0-9]{1,8}$/s', $data); + } + + /** + * Check for Language Iso Code + * + * @param string $iso_code + * @return bool Validity is ok or not + */ + public static function isLangIsoCode($iso_code) + { + return (bool)preg_match('/^[a-zA-Z]{2,3}$/s', $iso_code); + } + + /** + * Check for Language File Name + * + * @param string $file_name + * @return bool Validity is ok or not + */ + public static function isLanguageFileName($file_name) + { + return (bool)preg_match('/^[a-zA-Z]{2,3}\.(?:gzip|tar\.gz)$/s', $file_name); + } + + /** + * + * @param array $ids + * @return bool return true if the array contain only unsigned int value + */ + public static function isArrayWithIds($ids) + { + if (count($ids)) { + foreach ($ids as $id) { + if ($id == 0 || !Validate::isUnsignedInt($id)) { + return false; + } + } + } + return true; + } + + /** + * + * @param array $zones + * @return bool return true if array contain all value required for an image map zone + */ + public static function isSceneZones($zones) + { + foreach ($zones as $zone) { + if (!isset($zone['x1']) || !Validate::isUnsignedInt($zone['x1'])) { + return false; + } + if (!isset($zone['y1']) || !Validate::isUnsignedInt($zone['y1'])) { + return false; + } + if (!isset($zone['width']) || !Validate::isUnsignedInt($zone['width'])) { + return false; + } + if (!isset($zone['height']) || !Validate::isUnsignedInt($zone['height'])) { + return false; + } + if (!isset($zone['id_product']) || !Validate::isUnsignedInt($zone['id_product'])) { + return false; + } + } + return true; + } + + /** + * + * @param array $stock_management + * @return bool return true if is a valide stock management + */ + public static function isStockManagement($stock_management) + { + if (!in_array($stock_management, array('WA', 'FIFO', 'LIFO'))) { + return false; + } + return true; + } + + /** + * Validate SIRET Code + * + * @param string $siret SIRET Code + * @return bool Return true if is valid + */ + public static function isSiret($siret) + { + if (Tools::strlen($siret) != 14) { + return false; + } + $sum = 0; + for ($i = 0; $i != 14; $i++) { + $tmp = ((($i + 1) % 2) + 1) * intval($siret[$i]); + if ($tmp >= 10) { + $tmp -= 9; + } + $sum += $tmp; + } + return ($sum % 10 === 0); + } + + /** + * Validate APE Code + * + * @param string $ape APE Code + * @return bool Return true if is valid + */ + public static function isApe($ape) + { + return (bool)preg_match('/^[0-9]{3,4}[a-zA-Z]{1}$/s', $ape); + } + + public static function isControllerName($name) + { + return (bool)(is_string($name) && preg_match(Tools::cleanNonUnicodeSupport('/^[0-9a-zA-Z-_]*$/u'), $name)); + } + + public static function isPrestaShopVersion($version) + { + return (preg_match('/^[0-1]\.[0-9]{1,2}(\.[0-9]{1,2}){0,2}$/', $version) && ip2long($version)); + } + + public static function isOrderInvoiceNumber($id) + { + return (preg_match('/^(?:'.Configuration::get('PS_INVOICE_PREFIX', Context::getContext()->language->id).')\s*([0-9]+)$/i', $id)); + } } diff --git a/classes/Zone.php b/classes/Zone.php index 444da46d..f2538e90 100644 --- a/classes/Zone.php +++ b/classes/Zone.php @@ -26,84 +26,82 @@ class ZoneCore extends ObjectModel { - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var bool Zone status */ - public $active = true; + /** @var bool Zone status */ + public $active = true; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'zone', - 'primary' => 'id_zone', - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'zone', + 'primary' => 'id_zone', + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + ), + ); - protected $webserviceParameters = array(); + protected $webserviceParameters = array(); - /** - * Get all available geographical zones - * - * @param bool $active - * @return array Zones - */ - public static function getZones($active = false) - { - $cache_id = 'Zone::getZones_'.(bool)$active; - if (!Cache::isStored($cache_id)) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * Get all available geographical zones + * + * @param bool $active + * @return array Zones + */ + public static function getZones($active = false) + { + $cache_id = 'Zone::getZones_'.(bool)$active; + if (!Cache::isStored($cache_id)) { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'zone` '.($active ? 'WHERE active = 1' : '').' ORDER BY `name` ASC '); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Get a zone ID from its default language name - * - * @param string $name - * @return int id_zone - */ - public static function getIdByName($name) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Get a zone ID from its default language name + * + * @param string $name + * @return int id_zone + */ + public static function getIdByName($name) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_zone` FROM `'._DB_PREFIX_.'zone` WHERE `name` = \''.pSQL($name).'\' '); - } + } - /** - * Delete a zone - * - * @return bool Deletion result - */ - public function delete() - { - if (parent::delete()) - { - // Delete regarding delivery preferences - $result = Db::getInstance()->delete('carrier_zone', 'id_zone = '.(int)$this->id); - $result &= Db::getInstance()->delete('delivery', 'id_zone = '.(int)$this->id); + /** + * Delete a zone + * + * @return bool Deletion result + */ + public function delete() + { + if (parent::delete()) { + // Delete regarding delivery preferences + $result = Db::getInstance()->delete('carrier_zone', 'id_zone = '.(int)$this->id); + $result &= Db::getInstance()->delete('delivery', 'id_zone = '.(int)$this->id); - // Update Country & state zone with 0 - $result &= Db::getInstance()->update('country', array('id_zone' => 0), 'id_zone = '.(int)$this->id); - $result &= Db::getInstance()->update('state', array('id_zone' => 0), 'id_zone = '.(int)$this->id); + // Update Country & state zone with 0 + $result &= Db::getInstance()->update('country', array('id_zone' => 0), 'id_zone = '.(int)$this->id); + $result &= Db::getInstance()->update('state', array('id_zone' => 0), 'id_zone = '.(int)$this->id); - return $result; - } + return $result; + } - return false; - } + return false; + } } diff --git a/classes/cache/CacheMemcache.php b/classes/cache/CacheMemcache.php index 2f8c95be..086ad7c8 100644 --- a/classes/cache/CacheMemcache.php +++ b/classes/cache/CacheMemcache.php @@ -96,7 +96,7 @@ class CacheMemcacheCore extends Cache { if (!$this->is_connected) return false; - return ($this->memcache->get($key) !== FALSE); + return ($this->memcache->get($key) !== false); } /** diff --git a/classes/cache/CacheMemcached.php b/classes/cache/CacheMemcached.php index 014de246..3b87d5e6 100644 --- a/classes/cache/CacheMemcached.php +++ b/classes/cache/CacheMemcached.php @@ -71,7 +71,7 @@ class CacheMemcachedCore extends Cache foreach ($servers as $server) $this->memcached->addServer($server['ip'], $server['port'], (int) $server['weight']); - $this->is_connected = in_array('255.255.255', $this->memcached->getVersion(), TRUE) === FALSE; + $this->is_connected = in_array('255.255.255', $this->memcached->getVersion(), true) === false; } /** @@ -102,7 +102,7 @@ class CacheMemcachedCore extends Cache { if (!$this->is_connected) return false; - return ($this->memcached->get($key) !== FALSE); + return ($this->memcached->get($key) !== false); } /** @@ -239,4 +239,4 @@ class CacheMemcachedCore extends Cache { return Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'memcached_servers WHERE id_memcached_server='.(int)$id_server); } -} \ No newline at end of file +} diff --git a/classes/cache/index.php b/classes/cache/index.php index c642967a..91fa49fb 100644 --- a/classes/cache/index.php +++ b/classes/cache/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/classes/controller/AdminController.php b/classes/controller/AdminController.php index 112ec507..996734b1 100644 --- a/classes/controller/AdminController.php +++ b/classes/controller/AdminController.php @@ -26,3725 +26,3772 @@ class AdminControllerCore extends Controller { - /** @var string */ - public $path; + /** @var string */ + public $path; - /** @var string */ - public static $currentIndex; + /** @var string */ + public static $currentIndex; - /** @var string */ - public $content; + /** @var string */ + public $content; - /** @var array */ - public $warnings = array(); + /** @var array */ + public $warnings = array(); - /** @var array */ - public $informations = array(); + /** @var array */ + public $informations = array(); - /** @var array */ - public $confirmations = array(); + /** @var array */ + public $confirmations = array(); - /** @var string|false */ - public $shopShareDatas = false; + /** @var string|false */ + public $shopShareDatas = false; - /** @var array */ - public $_languages = array(); + /** @var array */ + public $_languages = array(); - /** @var int */ - public $default_form_language; + /** @var int */ + public $default_form_language; - /** @var bool */ - public $allow_employee_form_lang; + /** @var bool */ + public $allow_employee_form_lang; - /** @var string */ - public $layout = 'layout.tpl'; + /** @var string */ + public $layout = 'layout.tpl'; - /** @var bool */ - public $bootstrap = false; + /** @var bool */ + public $bootstrap = false; - /** @var string|array */ - protected $meta_title = array(); + /** @var string|array */ + protected $meta_title = array(); - /** @var string */ - public $template = 'content.tpl'; + /** @var string */ + public $template = 'content.tpl'; - /** @var string Associated table name */ - public $table = 'configuration'; + /** @var string Associated table name */ + public $table = 'configuration'; - /** @var string */ - public $list_id; + /** @var string */ + public $list_id; - /** @var string|false Object identifier inside the associated table */ - protected $identifier = false; + /** @var string|false Object identifier inside the associated table */ + protected $identifier = false; - /** @var string */ - protected $identifier_name = 'name'; + /** @var string */ + protected $identifier_name = 'name'; - /** @var string Associated object class name */ - public $className; + /** @var string Associated object class name */ + public $className; - /** @var array */ - public $tabAccess; + /** @var array */ + public $tabAccess; - /** @var int Tab id */ - public $id = -1; + /** @var int Tab id */ + public $id = -1; - /** @var bool */ - public $required_database = false; + /** @var bool */ + public $required_database = false; - /** @var string Security token */ - public $token; + /** @var string Security token */ + public $token; - /** @var string "shop" or "group_shop" */ - public $shopLinkType; + /** @var string "shop" or "group_shop" */ + public $shopLinkType; - /** @var string Default ORDER BY clause when $_orderBy is not defined */ - protected $_defaultOrderBy = false; + /** @var string Default ORDER BY clause when $_orderBy is not defined */ + protected $_defaultOrderBy = false; - /** @var string */ - protected $_defaultOrderWay = 'ASC'; + /** @var string */ + protected $_defaultOrderWay = 'ASC'; - /** @var array */ - public $tpl_form_vars = array(); + /** @var array */ + public $tpl_form_vars = array(); - /** @var array */ - public $tpl_list_vars = array(); + /** @var array */ + public $tpl_list_vars = array(); - /** @var array */ - public $tpl_delete_link_vars = array(); + /** @var array */ + public $tpl_delete_link_vars = array(); - /** @var array */ - public $tpl_option_vars = array(); + /** @var array */ + public $tpl_option_vars = array(); - /** @var array */ - public $tpl_view_vars = array(); + /** @var array */ + public $tpl_view_vars = array(); - /** @var array */ - public $tpl_required_fields_vars = array(); + /** @var array */ + public $tpl_required_fields_vars = array(); - /** @var string|null */ - public $base_tpl_view = null; + /** @var string|null */ + public $base_tpl_view = null; - /** @var string|null */ - public $base_tpl_form = null; + /** @var string|null */ + public $base_tpl_form = null; - /** @var bool If you want more fieldsets in the form */ - public $multiple_fieldsets = false; + /** @var bool If you want more fieldsets in the form */ + public $multiple_fieldsets = false; - /** @var array|false */ - public $fields_value = false; + /** @var array|false */ + public $fields_value = false; - /** @var array Errors displayed after post processing */ - public $errors = array(); + /** @var array Errors displayed after post processing */ + public $errors = array(); - /** @var bool Define if the header of the list contains filter and sorting links or not */ - protected $list_simple_header; + /** @var bool Define if the header of the list contains filter and sorting links or not */ + protected $list_simple_header; - /** @var array List to be generated */ - protected $fields_list; + /** @var array List to be generated */ + protected $fields_list; - /** @var array Modules list filters */ - protected $filter_modules_list = null; + /** @var array Modules list filters */ + protected $filter_modules_list = null; - /** @var array Modules list filters */ - protected $modules_list = array(); + /** @var array Modules list filters */ + protected $modules_list = array(); - /** @var array Edit form to be generated */ - protected $fields_form; + /** @var array Edit form to be generated */ + protected $fields_form; - /** @var array Override of $fields_form */ - protected $fields_form_override; + /** @var array Override of $fields_form */ + protected $fields_form_override; - /** @var string Override form action */ - protected $submit_action; + /** @var string Override form action */ + protected $submit_action; - /** @var array List of option forms to be generated */ - protected $fields_options = array(); + /** @var array List of option forms to be generated */ + protected $fields_options = array(); - /** @var string */ - protected $shopLink; + /** @var string */ + protected $shopLink; - /** @var string SQL query */ - protected $_listsql = ''; + /** @var string SQL query */ + protected $_listsql = ''; - /** @var array Cache for query results */ - protected $_list = array(); + /** @var array Cache for query results */ + protected $_list = array(); - /** @var string|array Toolbar title */ - protected $toolbar_title; + /** @var string|array Toolbar title */ + protected $toolbar_title; - /** @var array List of toolbar buttons */ - protected $toolbar_btn = null; + /** @var array List of toolbar buttons */ + protected $toolbar_btn = null; - /** @var bool Scrolling toolbar */ - protected $toolbar_scroll = true; + /** @var bool Scrolling toolbar */ + protected $toolbar_scroll = true; - /** @var bool Set to false to hide toolbar and page title */ - protected $show_toolbar = true; + /** @var bool Set to false to hide toolbar and page title */ + protected $show_toolbar = true; - /** @var bool Set to true to show toolbar and page title for options */ - protected $show_toolbar_options = false; + /** @var bool Set to true to show toolbar and page title for options */ + protected $show_toolbar_options = false; - /** @var int Number of results in list */ - protected $_listTotal = 0; + /** @var int Number of results in list */ + protected $_listTotal = 0; - /** @var bool Automatically join language table if true */ - public $lang = false; + /** @var bool Automatically join language table if true */ + public $lang = false; - /** @var array WHERE clause determined by filter fields */ - protected $_filter; + /** @var array WHERE clause determined by filter fields */ + protected $_filter; - /** @var string */ - protected $_filterHaving; + /** @var string */ + protected $_filterHaving; - /** @var array Temporary SQL table WHERE clause determined by filter fields */ - protected $_tmpTableFilter = ''; + /** @var array Temporary SQL table WHERE clause determined by filter fields */ + protected $_tmpTableFilter = ''; - /** @var array Number of results in list per page (used in select field) */ - protected $_pagination = array(20, 50, 100, 300, 1000); + /** @var array Number of results in list per page (used in select field) */ + protected $_pagination = array(20, 50, 100, 300, 1000); - /** @var int Default number of results in list per page */ - protected $_default_pagination = 50; + /** @var int Default number of results in list per page */ + protected $_default_pagination = 50; - /** @var string ORDER BY clause determined by field/arrows in list header */ - protected $_orderBy; + /** @var string ORDER BY clause determined by field/arrows in list header */ + protected $_orderBy; - /** @var string Order way (ASC, DESC) determined by arrows in list header */ - protected $_orderWay; + /** @var string Order way (ASC, DESC) determined by arrows in list header */ + protected $_orderWay; - /** @var array List of available actions for each list row - default actions are view, edit, delete, duplicate */ - protected $actions_available = array('view', 'edit', 'duplicate', 'delete'); + /** @var array List of available actions for each list row - default actions are view, edit, delete, duplicate */ + protected $actions_available = array('view', 'edit', 'duplicate', 'delete'); - /** @var array List of required actions for each list row */ - protected $actions = array(); + /** @var array List of required actions for each list row */ + protected $actions = array(); - /** @var array List of row ids associated with a given action for witch this action have to not be available */ - protected $list_skip_actions = array(); + /** @var array List of row ids associated with a given action for witch this action have to not be available */ + protected $list_skip_actions = array(); - /* @var bool Don't show header & footer */ - protected $lite_display = false; + /* @var bool Don't show header & footer */ + protected $lite_display = false; - /** @var bool List content lines are clickable if true */ - protected $list_no_link = false; + /** @var bool List content lines are clickable if true */ + protected $list_no_link = false; - /** @var bool */ - protected $allow_export = false; + /** @var bool */ + protected $allow_export = false; - /** @var array Cache for translations */ - public static $cache_lang = array(); + /** @var array Cache for translations */ + public static $cache_lang = array(); - /** @var array Required_fields to display in the Required Fields form */ - public $required_fields = array(); + /** @var array Required_fields to display in the Required Fields form */ + public $required_fields = array(); - /** @var HelperList */ - protected $helper; + /** @var HelperList */ + protected $helper; - /** - * Actions to execute on multiple selections. - * - * Usage: - * - * array( - * 'actionName' => array( - * 'text' => $this->l('Message displayed on the submit button (mandatory)'), - * 'confirm' => $this->l('If set, this confirmation message will pop-up (optional)')), - * 'anotherAction' => array(...) - * ); - * - * If your action is named 'actionName', you need to have a method named bulkactionName() that will be executed when the button is clicked. - * - * @var array - */ - protected $bulk_actions; + /** + * Actions to execute on multiple selections. + * + * Usage: + * + * array( + * 'actionName' => array( + * 'text' => $this->l('Message displayed on the submit button (mandatory)'), + * 'confirm' => $this->l('If set, this confirmation message will pop-up (optional)')), + * 'anotherAction' => array(...) + * ); + * + * If your action is named 'actionName', you need to have a method named bulkactionName() that will be executed when the button is clicked. + * + * @var array + */ + protected $bulk_actions; - /* @var array Ids of the rows selected */ - protected $boxes; + /* @var array Ids of the rows selected */ + protected $boxes; - /** @var string Do not automatically select * anymore but select only what is necessary */ - protected $explicitSelect = false; + /** @var string Do not automatically select * anymore but select only what is necessary */ + protected $explicitSelect = false; - /** @var string Add fields into data query to display list */ - protected $_select; + /** @var string Add fields into data query to display list */ + protected $_select; - /** @var string Join tables into data query to display list */ - protected $_join; + /** @var string Join tables into data query to display list */ + protected $_join; - /** @var string Add conditions into data query to display list */ - protected $_where; + /** @var string Add conditions into data query to display list */ + protected $_where; - /** @var string Group rows into data query to display list */ - protected $_group; + /** @var string Group rows into data query to display list */ + protected $_group; - /** @var string Having rows into data query to display list */ - protected $_having; + /** @var string Having rows into data query to display list */ + protected $_having; - /** @var string Use SQL_CALC_FOUND_ROWS / FOUND_ROWS to count the number of records */ - protected $_use_found_rows = true; + /** @var string Use SQL_CALC_FOUND_ROWS / FOUND_ROWS to count the number of records */ + protected $_use_found_rows = true; - /** @var bool */ - protected $is_cms = false; + /** @var bool */ + protected $is_cms = false; - /** @var string Identifier to use for changing positions in lists (can be omitted if positions cannot be changed) */ - protected $position_identifier; + /** @var string Identifier to use for changing positions in lists (can be omitted if positions cannot be changed) */ + protected $position_identifier; - /** @var string|int */ - protected $position_group_identifier; + /** @var string|int */ + protected $position_group_identifier; - /** @var bool Table records are not deleted but marked as deleted if set to true */ - protected $deleted = false; + /** @var bool Table records are not deleted but marked as deleted if set to true */ + protected $deleted = false; - /** @var bool Is a list filter set */ - protected $filter; + /** @var bool Is a list filter set */ + protected $filter; - /** @var bool */ - protected $noLink; + /** @var bool */ + protected $noLink; - /** @var bool|null */ - protected $specificConfirmDelete = null; + /** @var bool|null */ + protected $specificConfirmDelete = null; - /** @var bool */ - protected $colorOnBackground; + /** @var bool */ + protected $colorOnBackground; - /** @var bool If true, activates color on hover */ - protected $row_hover = true; + /** @var bool If true, activates color on hover */ + protected $row_hover = true; - /** @var string Action to perform : 'edit', 'view', 'add', ... */ - protected $action; + /** @var string Action to perform : 'edit', 'view', 'add', ... */ + protected $action; - /** @var string */ - protected $display; + /** @var string */ + protected $display; - /** @var bool */ - protected $_includeContainer = true; + /** @var bool */ + protected $_includeContainer = true; - /** @var array */ - protected $tab_modules_list = array('default_list' => array(), 'slider_list' => array()); + /** @var array */ + protected $tab_modules_list = array('default_list' => array(), 'slider_list' => array()); - /** @var string */ - public $tpl_folder; + /** @var string */ + public $tpl_folder; - /** @var string */ - protected $bo_theme; + /** @var string */ + protected $bo_theme; - /** @var bool Redirect or not after a creation */ - protected $_redirect = true; + /** @var bool Redirect or not after a creation */ + protected $_redirect = true; - /** @var array Name and directory where class image are located */ - public $fieldImageSettings = array(); + /** @var array Name and directory where class image are located */ + public $fieldImageSettings = array(); - /** @var string Image type */ - public $imageType = 'jpg'; + /** @var string Image type */ + public $imageType = 'jpg'; - /** @var ObjectModel Instantiation of the class associated with the AdminController */ - protected $object; + /** @var ObjectModel Instantiation of the class associated with the AdminController */ + protected $object; - /** @var int Current object ID */ - protected $id_object; + /** @var int Current object ID */ + protected $id_object; - /** @var string Current controller name without suffix */ - public $controller_name; + /** @var string Current controller name without suffix */ + public $controller_name; - /** @var int */ - public $multishop_context = -1; + /** @var int */ + public $multishop_context = -1; - /** @var false */ - public $multishop_context_group = true; + /** @var false */ + public $multishop_context_group = true; - /** @var array Current breadcrumb position as an array of tab names */ - protected $breadcrumbs; + /** @var array Current breadcrumb position as an array of tab names */ + protected $breadcrumbs; - /** @var bool Bootstrap variable */ - public $show_page_header_toolbar = false; + /** @var bool Bootstrap variable */ + public $show_page_header_toolbar = false; - /** @var string Bootstrap variable */ - public $page_header_toolbar_title; + /** @var string Bootstrap variable */ + public $page_header_toolbar_title; - /** @var array|Traversable Bootstrap variable */ - public $page_header_toolbar_btn = array(); + /** @var array|Traversable Bootstrap variable */ + public $page_header_toolbar_btn = array(); - /** @var bool Bootstrap variable */ - public $show_form_cancel_button; + /** @var bool Bootstrap variable */ + public $show_form_cancel_button; - /** @var string */ - public $admin_webpath; + /** @var string */ + public $admin_webpath; - /** @var array */ - protected $list_natives_modules = array(); + /** @var array */ + protected $list_natives_modules = array(); - /** @var array */ - protected $list_partners_modules = array(); + /** @var array */ + protected $list_partners_modules = array(); - /** @var array */ - public $modals = array(); + /** @var array */ + public $modals = array(); - /** @var bool */ - protected $logged_on_addons = false; + /** @var bool */ + protected $logged_on_addons = false; - /** @var bool if logged employee has access to AdminImport */ - protected $can_import = false; - - public function __construct() - { - global $timer_start; - $this->timer_start = $timer_start; - // Has to be remove for the next Prestashop version - global $token; - - $this->controller_type = 'admin'; - $this->controller_name = get_class($this); - if (strpos($this->controller_name, 'Controller')) - $this->controller_name = substr($this->controller_name, 0, -10); - parent::__construct(); - - if ($this->multishop_context == -1) - $this->multishop_context = Shop::CONTEXT_ALL | Shop::CONTEXT_GROUP | Shop::CONTEXT_SHOP; - - $default_theme_name = 'default'; - - if (defined('_PS_BO_DEFAULT_THEME_') && _PS_BO_DEFAULT_THEME_ - && @filemtime(_PS_BO_ALL_THEMES_DIR_._PS_BO_DEFAULT_THEME_.DIRECTORY_SEPARATOR.'template')) - $default_theme_name = _PS_BO_DEFAULT_THEME_; - - $this->bo_theme = ((Validate::isLoadedObject($this->context->employee) - && $this->context->employee->bo_theme) ? $this->context->employee->bo_theme : $default_theme_name); - - if (!@filemtime(_PS_BO_ALL_THEMES_DIR_.$this->bo_theme.DIRECTORY_SEPARATOR.'template')) - $this->bo_theme = $default_theme_name; - - $this->bo_css = ((Validate::isLoadedObject($this->context->employee) - && $this->context->employee->bo_css) ? $this->context->employee->bo_css : 'admin-theme.css'); - - if (!@filemtime(_PS_BO_ALL_THEMES_DIR_.$this->bo_theme.DIRECTORY_SEPARATOR.'css'.DIRECTORY_SEPARATOR.$this->bo_css)) - $this->bo_css = 'admin-theme.css'; - - $this->context->smarty->setTemplateDir(array( - _PS_BO_ALL_THEMES_DIR_.$this->bo_theme.DIRECTORY_SEPARATOR.'template', - _PS_OVERRIDE_DIR_.'controllers'.DIRECTORY_SEPARATOR.'admin'.DIRECTORY_SEPARATOR.'templates' - )); - - $this->id = Tab::getIdFromClassName($this->controller_name); - $this->token = Tools::getAdminToken($this->controller_name.(int)$this->id.(int)$this->context->employee->id); - - $token = $this->token; - - $this->_conf = array( - 1 => $this->l('Successful deletion'), - 2 => $this->l('The selection has been successfully deleted.'), - 3 => $this->l('Successful creation'), - 4 => $this->l('Successful update'), - 5 => $this->l('The status has been successfully updated.'), - 6 => $this->l('The settings have been successfully updated.'), - 7 => $this->l('The image was successfully deleted.'), - 8 => $this->l('The module was successfully downloaded.'), - 9 => $this->l('The thumbnails were successfully regenerated.'), - 10 => $this->l('The message was successfully sent to the customer.'), - 11 => $this->l('Comment successfully added'), - 12 => $this->l('Module(s) installed successfully.'), - 13 => $this->l('Module(s) uninstalled successfully.'), - 14 => $this->l('The translation was successfully copied.'), - 15 => $this->l('The translations have been successfully added.'), - 16 => $this->l('The module transplanted successfully to the hook.'), - 17 => $this->l('The module was successfully removed from the hook.'), - 18 => $this->l('Successful upload'), - 19 => $this->l('Duplication was completed successfully.'), - 20 => $this->l('The translation was added successfully, but the language has not been created.'), - 21 => $this->l('Module reset successfully.'), - 22 => $this->l('Module deleted successfully.'), - 23 => $this->l('Localization pack imported successfully.'), - 24 => $this->l('Localization pack imported successfully.'), - 25 => $this->l('The selected images have successfully been moved.'), - 26 => $this->l('Your cover image selection has been saved.'), - 27 => $this->l('The image\'s shop association has been modified.'), - 28 => $this->l('A zone has been assigned to the selection successfully.'), - 29 => $this->l('Successful upgrade'), - 30 => $this->l('A partial refund was successfully created.'), - 31 => $this->l('The discount was successfully generated.'), - 32 => $this->l('Successfully signed in to PrestaShop Addons') - ); - - if (!$this->identifier) $this->identifier = 'id_'.$this->table; - if (!$this->_defaultOrderBy) $this->_defaultOrderBy = $this->identifier; - $this->tabAccess = Profile::getProfileAccess($this->context->employee->id_profile, $this->id); - - // Fix for homepage - if ($this->controller_name == 'AdminDashboard') - $_POST['token'] = $this->token; - - if (!Shop::isFeatureActive()) - $this->shopLinkType = ''; - - //$this->base_template_folder = _PS_BO_ALL_THEMES_DIR_.$this->bo_theme.'/template'; - $this->override_folder = Tools::toUnderscoreCase(substr($this->controller_name, 5)).'/'; - // Get the name of the folder containing the custom tpl files - $this->tpl_folder = Tools::toUnderscoreCase(substr($this->controller_name, 5)).'/'; - - $this->initShopContext(); - - $this->context->currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); - - $this->admin_webpath = str_ireplace(_PS_CORE_DIR_, '', _PS_ADMIN_DIR_); - $this->admin_webpath = preg_replace('/^'.preg_quote(DIRECTORY_SEPARATOR, '/').'/', '', $this->admin_webpath); - - // Check if logged on Addons - $this->logged_on_addons = false; - if (isset($this->context->cookie->username_addons) && isset($this->context->cookie->password_addons) && !empty($this->context->cookie->username_addons) && !empty($this->context->cookie->password_addons)) - $this->logged_on_addons = true; - - // Set context mode - if (defined('_PS_HOST_MODE_') && _PS_HOST_MODE_) - { - if (isset($this->context->cookie->is_contributor) && (int)$this->context->cookie->is_contributor === 1) - $this->context->mode = Context::MODE_HOST_CONTRIB; - else - $this->context->mode = Context::MODE_HOST; - } - elseif (isset($this->context->cookie->is_contributor) && (int)$this->context->cookie->is_contributor === 1) - $this->context->mode = Context::MODE_STD_CONTRIB; - else - $this->context->mode = Context::MODE_STD; - - //* Check if logged employee has access to AdminImport controller */ - $import_access = Profile::getProfileAccess($this->context->employee->id_profile, Tab::getIdFromClassName('AdminImport')); - if (is_array($import_access) && isset($import_access['view']) && $import_access['view'] == 1) - $this->can_import = true; - - $this->context->smarty->assign(array( - 'context_mode' => $this->context->mode, - 'logged_on_addons' => $this->logged_on_addons, - 'can_import' => $this->can_import, - )); - } - - /** - * Set breadcrumbs array for the controller page - * - * @param int|null $tab_id - * @param array|null $tabs - */ - public function initBreadcrumbs($tab_id = null, $tabs = null) - { - if (is_array($tabs) || count($tabs)) - $tabs = array(); - - if (is_null($tab_id)) - $tab_id = $this->id; - - $tabs = Tab::recursiveTab($tab_id, $tabs); - - $dummy = array('name' => '', 'href' => '', 'icon' => ''); - $breadcrumbs2 = array( - 'container' => $dummy, - 'tab' => $dummy, - 'action' => $dummy - ); - if (isset($tabs[0])) - { - $this->addMetaTitle($tabs[0]['name']); - $breadcrumbs2['tab']['name'] = $tabs[0]['name']; - $breadcrumbs2['tab']['href'] = __PS_BASE_URI__.basename(_PS_ADMIN_DIR_ ).'/'.$this->context->link->getAdminLink($tabs[0]['class_name']); - if (!isset($tabs[1])) - $breadcrumbs2['tab']['icon'] = 'icon-'.$tabs[0]['class_name']; - } - if (isset($tabs[1])) - { - $breadcrumbs2['container']['name'] = $tabs[1]['name']; - $breadcrumbs2['container']['href'] = __PS_BASE_URI__.basename(_PS_ADMIN_DIR_ ).'/'.$this->context->link->getAdminLink($tabs[1]['class_name']); - $breadcrumbs2['container']['icon'] = 'icon-'.$tabs[1]['class_name']; - } - - /* content, edit, list, add, details, options, view */ - switch ($this->display) - { - case 'add': - $breadcrumbs2['action']['name'] = $this->l('Add', null, null, false); - $breadcrumbs2['action']['icon'] = 'icon-plus'; - break; - case 'edit': - $breadcrumbs2['action']['name'] = $this->l('Edit', null, null, false); - $breadcrumbs2['action']['icon'] = 'icon-pencil'; - break; - case '': - case 'list': - $breadcrumbs2['action']['name'] = $this->l('List', null, null, false); - $breadcrumbs2['action']['icon'] = 'icon-th-list'; - break; - case 'details': - case 'view': - $breadcrumbs2['action']['name'] = $this->l('View details', null, null, false); - $breadcrumbs2['action']['icon'] = 'icon-zoom-in'; - break; - case 'options': - $breadcrumbs2['action']['name'] = $this->l('Options', null, null, false); - $breadcrumbs2['action']['icon'] = 'icon-cogs'; - break; - case 'generator': - $breadcrumbs2['action']['name'] = $this->l('Generator', null, null, false); - $breadcrumbs2['action']['icon'] = 'icon-flask'; - break; - } - - $this->context->smarty->assign(array( - 'breadcrumbs2' => $breadcrumbs2, - 'quick_access_current_link_name' => $breadcrumbs2['tab']['name'].(isset($breadcrumbs2['action']) ? ' - '.$breadcrumbs2['action']['name'] : ''), - 'quick_access_current_link_icon' => $breadcrumbs2['container']['icon'] - )); - - /* BEGIN - Backward compatibility < 1.6.0.3 */ - $this->breadcrumbs[] = $tabs[0]['name']; - $navigation_pipe = (Configuration::get('PS_NAVIGATION_PIPE') ? Configuration::get('PS_NAVIGATION_PIPE') : '>'); - $this->context->smarty->assign('navigationPipe', $navigation_pipe); - /* END - Backward compatibility < 1.6.0.3 */ - } - - /** - * Set default toolbar_title to admin breadcrumb - * - * @return void - */ - public function initToolbarTitle() - { - $this->toolbar_title = is_array($this->breadcrumbs) ? array_unique($this->breadcrumbs) : array($this->breadcrumbs); - - switch ($this->display) - { - case 'edit': - $this->toolbar_title[] = $this->l('Edit', null, null, false); - $this->addMetaTitle($this->l('Edit', null, null, false)); - break; - - case 'add': - $this->toolbar_title[] = $this->l('Add new', null, null, false); - $this->addMetaTitle($this->l('Add new', null, null, false)); - break; - - case 'view': - $this->toolbar_title[] = $this->l('View', null, null, false); - $this->addMetaTitle($this->l('View', null, null, false)); - break; - } - - if ($filter = $this->addFiltersToBreadcrumbs()) - $this->toolbar_title[] = $filter; - } - - /** - * @return string|void - */ - public function addFiltersToBreadcrumbs() - { - if ($this->filter && is_array($this->fields_list)) - { - $filters = array(); - foreach ($this->fields_list as $field => $t) - { - if (isset($t['filter_key'])) - $field = $t['filter_key']; - if ($val = Tools::getValue($this->table.'Filter_'.$field)) - { - if (!is_array($val)) - { - $filter_value = ''; - if (isset($t['type']) && $t['type'] == 'bool') - $filter_value = ((bool)$val) ? $this->l('yes') : $this->l('no'); - elseif (is_string($val)) - $filter_value = htmlspecialchars($val, ENT_QUOTES, 'UTF-8'); - if (!empty($filter_value)) - $filters[] = sprintf($this->l('%s: %s'), $t['title'], $filter_value); - } - else - { - $filter_value = ''; - foreach ($val as $v) - if (is_string($v) && !empty($v)) - $filter_value .= ' - '.htmlspecialchars($v, ENT_QUOTES, 'UTF-8'); - $filter_value = ltrim($filter_value, ' -'); - if (!empty($filter_value)) - $filters[] = sprintf($this->l('%s: %s'), $t['title'], $filter_value); - } - } - } - - if (count($filters)) - return sprintf($this->l('filter by %s'), implode(', ', $filters)); - } - } - - /** - * Check rights to view the current tab - * - * @param bool $disable - * @return bool - */ - public function viewAccess($disable = false) - { - if ($disable) - return true; - - if ($this->tabAccess['view'] === '1') - return true; - return false; - } - - /** - * Check for security token - * - * @return bool - */ - public function checkToken() - { - $token = Tools::getValue('token'); - if (!empty($token) && $token === $this->token) - return true; - - if (count($_POST) || !isset($_GET['controller']) || !Validate::isControllerName($_GET['controller']) || $token) - return false; - - foreach ($_GET as $key => $value) - if (is_array($value) || !in_array($key, array('controller', 'controllerUri'))) - return false; - - $cookie = Context::getContext()->cookie; - $whitelist = array('date_add', 'id_lang', 'id_employee', 'email', 'profile', 'passwd', 'remote_addr', 'shopContext', 'collapse_menu', 'checksum'); - foreach ($cookie->getAll() as $key => $value) - if (!in_array($key, $whitelist)) - unset($cookie->$key); - - $cookie->write(); - - return true; - } - - /** - * Set the filters used for the list display - */ - public function processFilter() - { - Hook::exec('action'.$this->controller_name.'ListingFieldsModifier', array( - 'fields' => &$this->fields_list, - )); - - if (!isset($this->list_id)) - $this->list_id = $this->table; - - $prefix = str_replace(array('admin', 'controller'), '', Tools::strtolower(get_class($this))); - - if (isset($this->list_id)) - { - foreach ($_POST as $key => $value) - { - if ($value === '') - unset($this->context->cookie->{$prefix.$key}); - elseif (stripos($key, $this->list_id.'Filter_') === 0) - $this->context->cookie->{$prefix.$key} = !is_array($value) ? $value : serialize($value); - elseif (stripos($key, 'submitFilter') === 0) - $this->context->cookie->$key = !is_array($value) ? $value : serialize($value); - } - - foreach ($_GET as $key => $value) - { - if (stripos($key, $this->list_id.'Filter_') === 0) - $this->context->cookie->{$prefix.$key} = !is_array($value) ? $value : serialize($value); - elseif (stripos($key, 'submitFilter') === 0) - $this->context->cookie->$key = !is_array($value) ? $value : serialize($value); - if (stripos($key, $this->list_id.'Orderby') === 0 && Validate::isOrderBy($value)) - { - if ($value === '' || $value == $this->_defaultOrderBy) - unset($this->context->cookie->{$prefix.$key}); - else - $this->context->cookie->{$prefix.$key} = $value; - } - elseif (stripos($key, $this->list_id.'Orderway') === 0 && Validate::isOrderWay($value)) - { - if ($value === '' || $value == $this->_defaultOrderWay) - unset($this->context->cookie->{$prefix.$key}); - else - $this->context->cookie->{$prefix.$key} = $value; - } - } - } - - $filters = $this->context->cookie->getFamily($prefix.$this->list_id.'Filter_'); - $definition = ObjectModel::getDefinition($this->className); - - foreach ($filters as $key => $value) - { - /* Extracting filters from $_POST on key filter_ */ - if ($value != null && !strncmp($key, $prefix.$this->list_id.'Filter_', 7 + Tools::strlen($prefix.$this->list_id))) - { - $key = Tools::substr($key, 7 + Tools::strlen($prefix.$this->list_id)); - /* Table alias could be specified using a ! eg. alias!field */ - $tmp_tab = explode('!', $key); - $filter = count($tmp_tab) > 1 ? $tmp_tab[1] : $tmp_tab[0]; - - if ($field = $this->filterToField($key, $filter)) - { - $type = (array_key_exists('filter_type', $field) ? $field['filter_type'] : (array_key_exists('type', $field) ? $field['type'] : false)); - if (($type == 'date' || $type == 'datetime') && is_string($value)) - $value = Tools::unSerialize($value); - $key = isset($tmp_tab[1]) ? $tmp_tab[0].'.`'.$tmp_tab[1].'`' : '`'.$tmp_tab[0].'`'; - - // Assignment by reference - if (array_key_exists('tmpTableFilter', $field)) - $sql_filter = & $this->_tmpTableFilter; - elseif (array_key_exists('havingFilter', $field)) - $sql_filter = & $this->_filterHaving; - else - $sql_filter = & $this->_filter; - - /* Only for date filtering (from, to) */ - if (is_array($value)) - { - if (isset($value[0]) && !empty($value[0])) - { - if (!Validate::isDate($value[0])) - $this->errors[] = Tools::displayError('The \'From\' date format is invalid (YYYY-MM-DD)'); - else - $sql_filter .= ' AND '.pSQL($key).' >= \''.pSQL(Tools::dateFrom($value[0])).'\''; - } - - if (isset($value[1]) && !empty($value[1])) - { - if (!Validate::isDate($value[1])) - $this->errors[] = Tools::displayError('The \'To\' date format is invalid (YYYY-MM-DD)'); - else - $sql_filter .= ' AND '.pSQL($key).' <= \''.pSQL(Tools::dateTo($value[1])).'\''; - } - } - else - { - $sql_filter .= ' AND '; - $check_key = ($key == $this->identifier || $key == '`'.$this->identifier.'`'); - $alias = !empty($definition['fields'][$filter]['shop']) ? 'sa' : 'a'; - - if ($type == 'int' || $type == 'bool') - $sql_filter .= (($check_key || $key == '`active`') ? $alias.'.' : '').pSQL($key).' = '.(int)$value.' '; - elseif ($type == 'decimal') - $sql_filter .= ($check_key ? $alias.'.' : '').pSQL($key).' = '.(float)$value.' '; - elseif ($type == 'select') - $sql_filter .= ($check_key ? $alias.'.' : '').pSQL($key).' = \''.pSQL($value).'\' '; - else - { - if ($type == 'price') - $value = (float)str_replace(',', '.', $value); - $sql_filter .= ($check_key ? $alias.'.' : '').pSQL($key).' LIKE \'%'.pSQL(trim($value)).'%\' '; - } - } - } - } - } - } - - /** - * @TODO uses redirectAdmin only if !$this->ajax - * @return bool - */ - public function postProcess() - { - try { - if ($this->ajax) - { - // from ajax-tab.php - $action = Tools::getValue('action'); - // no need to use displayConf() here - if (!empty($action) && method_exists($this, 'ajaxProcess'.Tools::toCamelCase($action))) - { - Hook::exec('actionAdmin'.ucfirst($this->action).'Before', array('controller' => $this)); - Hook::exec('action'.get_class($this).ucfirst($this->action).'Before', array('controller' => $this)); - - $return = $this->{'ajaxProcess'.Tools::toCamelCase($action)}(); - - Hook::exec('actionAdmin'.ucfirst($this->action).'After', array('controller' => $this, 'return' => $return)); - Hook::exec('action'.get_class($this).ucfirst($this->action).'After', array('controller' => $this, 'return' => $return)); - - return $return; - } - elseif (!empty($action) && $this->controller_name == 'AdminModules' && Tools::getIsset('configure')) - { - $module_obj = Module::getInstanceByName(Tools::getValue('configure')); - if (Validate::isLoadedObject($module_obj) && method_exists($module_obj, 'ajaxProcess'.$action)) - return $module_obj->{'ajaxProcess'.$action}(); - } - elseif (method_exists($this, 'ajaxProcess')) - return $this->ajaxProcess(); - } - else - { - // Process list filtering - if ($this->filter && $this->action != 'reset_filters') - $this->processFilter(); - - // If the method named after the action exists, call "before" hooks, then call action method, then call "after" hooks - if (!empty($this->action) && method_exists($this, 'process'.ucfirst(Tools::toCamelCase($this->action)))) - { - // Hook before action - Hook::exec('actionAdmin'.ucfirst($this->action).'Before', array('controller' => $this)); - Hook::exec('action'.get_class($this).ucfirst($this->action).'Before', array('controller' => $this)); - // Call process - $return = $this->{'process'.Tools::toCamelCase($this->action)}(); - // Hook After Action - Hook::exec('actionAdmin'.ucfirst($this->action).'After', array('controller' => $this, 'return' => $return)); - Hook::exec('action'.get_class($this).ucfirst($this->action).'After', array('controller' => $this, 'return' => $return)); - return $return; - } - } - } catch (PrestaShopException $e) { - $this->errors[] = $e->getMessage(); - }; - return false; - } - - /** - * Object Delete images - * - * @return ObjectModel|false - */ - public function processDeleteImage() - { - if (Validate::isLoadedObject($object = $this->loadObject())) - { - if (($object->deleteImage())) - { - $redirect = self::$currentIndex.'&add'.$this->table.'&'.$this->identifier.'='.Tools::getValue($this->identifier).'&conf=7&token='.$this->token; - if (!$this->ajax) - $this->redirect_after = $redirect; - else - $this->content = 'ok'; - } - } - $this->errors[] = Tools::displayError('An error occurred while attempting to delete the image. (cannot load object).'); - return $object; - } - - /** - * @param string $text_delimiter - * @throws PrestaShopException - */ - public function processExport($text_delimiter = '"') - { - // clean buffer - if (ob_get_level() && ob_get_length() > 0) - ob_clean(); - $this->getList($this->context->language->id, null, null, 0, false); - if (!count($this->_list)) - return; - - header('Content-type: text/csv'); - header('Content-Type: application/force-download; charset=UTF-8'); - header('Cache-Control: no-store, no-cache'); - header('Content-disposition: attachment; filename="'.$this->table.'_'.date('Y-m-d_His').'.csv"'); - - $headers = array(); - foreach ($this->fields_list as $key => $datas) - { - if ($datas['title'] == 'PDF') - unset($this->fields_list[$key]); - else - $headers[] = Tools::htmlentitiesDecodeUTF8($datas['title']); - } - $content = array(); - foreach ($this->_list as $i => $row) - { - $content[$i] = array(); - $path_to_image = false; - foreach ($this->fields_list as $key => $params) - { - $field_value = isset($row[$key]) ? Tools::htmlentitiesDecodeUTF8( - Tools::nl2br($row[$key])) : ''; - if ($key == 'image') - { - if ($params['image'] != 'p' || Configuration::get('PS_LEGACY_IMAGES')) - $path_to_image = Tools::getShopDomain(true)._PS_IMG_.$params['image'].'/'.$row['id_'.$this->table].(isset($row['id_image']) ? '-'.(int)$row['id_image'] : '').'.'.$this->imageType; - else - $path_to_image = Tools::getShopDomain(true)._PS_IMG_.$params['image'].'/'.Image::getImgFolderStatic($row['id_image']).(int)$row['id_image'].'.'.$this->imageType; - if ($path_to_image) - $field_value = $path_to_image; - } - if (isset($params['callback'])) - { - $callback_obj = (isset($params['callback_object'])) ? $params['callback_object'] : $this->context->controller; - if (!preg_match('/<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)/ism', call_user_func_array(array($callback_obj, $params['callback']), array($field_value, $row)))) - $field_value = call_user_func_array(array($callback_obj, $params['callback']), array($field_value, $row)); - } - $content[$i][] = $field_value; - } - } - - $this->context->smarty->assign(array( - 'export_precontent' => "\xEF\xBB\xBF", - 'export_headers' => $headers, - 'export_content' => $content, - 'text_delimiter' => $text_delimiter - ) - ); - - $this->layout = 'layout-export.tpl'; - } - - /** - * Object Delete - * - * @return ObjectModel|false - * @throws PrestaShopException - */ - public function processDelete() - { - if (Validate::isLoadedObject($object = $this->loadObject())) - { - $res = true; - // check if request at least one object with noZeroObject - if (isset($object->noZeroObject) && count(call_user_func(array($this->className, $object->noZeroObject))) <= 1) - { - $this->errors[] = Tools::displayError('You need at least one object.'). - ' <b>'.$this->table.'</b><br />'. - Tools::displayError('You cannot delete all of the items.'); - } - elseif (array_key_exists('delete', $this->list_skip_actions) && in_array($object->id, $this->list_skip_actions['delete'])) //check if some ids are in list_skip_actions and forbid deletion - $this->errors[] = Tools::displayError('You cannot delete this item.'); - else - { - if ($this->deleted) - { - if (!empty($this->fieldImageSettings)) - $res = $object->deleteImage(); - - if (!$res) - $this->errors[] = Tools::displayError('Unable to delete associated images.'); - - $object->deleted = 1; - if ($res = $object->update()) - $this->redirect_after = self::$currentIndex.'&conf=1&token='.$this->token; - } - elseif ($res = $object->delete()) - $this->redirect_after = self::$currentIndex.'&conf=1&token='.$this->token; - $this->errors[] = Tools::displayError('An error occurred during deletion.'); - if ($res) - PrestaShopLogger::addLog(sprintf($this->l('%s deletion', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); - } - } - else - { - $this->errors[] = Tools::displayError('An error occurred while deleting the object.'). - ' <b>'.$this->table.'</b> '. - Tools::displayError('(cannot load object)'); - } - return $object; - } - - /** - * Call the right method for creating or updating object - * - * @return ObjectModel|false|void - */ - public function processSave() - { - if ($this->id_object) - { - $this->object = $this->loadObject(); - return $this->processUpdate(); - } - else - return $this->processAdd(); - } - - /** - * Object creation - * - * @return ObjectModel|false - * @throws PrestaShopException - */ - public function processAdd() - { - if (!isset($this->className) || empty($this->className)) - return false; - - $this->validateRules(); - if (count($this->errors) <= 0) - { - $this->object = new $this->className(); - - $this->copyFromPost($this->object, $this->table); - $this->beforeAdd($this->object); - if (method_exists($this->object, 'add') && !$this->object->add()) - { - $this->errors[] = Tools::displayError('An error occurred while creating an object.'). - ' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>'; - } - /* voluntary do affectation here */ - elseif (($_POST[$this->identifier] = $this->object->id) && $this->postImage($this->object->id) && !count($this->errors) && $this->_redirect) - { - PrestaShopLogger::addLog(sprintf($this->l('%s addition', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); - $parent_id = (int)Tools::getValue('id_parent', 1); - $this->afterAdd($this->object); - $this->updateAssoShop($this->object->id); - // Save and stay on same form - if (empty($this->redirect_after) && $this->redirect_after !== false && Tools::isSubmit('submitAdd'.$this->table.'AndStay')) - $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$this->object->id.'&conf=3&update'.$this->table.'&token='.$this->token; - // Save and back to parent - if (empty($this->redirect_after) && $this->redirect_after !== false && Tools::isSubmit('submitAdd'.$this->table.'AndBackToParent')) - $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$parent_id.'&conf=3&token='.$this->token; - // Default behavior (save and back) - if (empty($this->redirect_after) && $this->redirect_after !== false) - $this->redirect_after = self::$currentIndex.($parent_id ? '&'.$this->identifier.'='.$this->object->id : '').'&conf=3&token='.$this->token; - } - } - - $this->errors = array_unique($this->errors); - if (!empty($this->errors)) - { - // if we have errors, we stay on the form instead of going back to the list - $this->display = 'edit'; - return false; - } - - return $this->object; - } - - /** - * Object update - * - * @return ObjectModel|false|void - * @throws PrestaShopException - */ - public function processUpdate() - { - /* Checking fields validity */ - $this->validateRules(); - if (empty($this->errors)) - { - $id = (int)Tools::getValue($this->identifier); - - /* Object update */ - if (isset($id) && !empty($id)) - { - /** @var ObjectModel $object */ - $object = new $this->className($id); - if (Validate::isLoadedObject($object)) - { - /* Specific to objects which must not be deleted */ - if ($this->deleted && $this->beforeDelete($object)) - { - // Create new one with old objet values - /** @var ObjectModel $object_new */ - $object_new = $object->duplicateObject(); - if (Validate::isLoadedObject($object_new)) - { - // Update old object to deleted - $object->deleted = 1; - $object->update(); - - // Update new object with post values - $this->copyFromPost($object_new, $this->table); - $result = $object_new->update(); - if (Validate::isLoadedObject($object_new)) - $this->afterDelete($object_new, $object->id); - } - } - else - { - $this->copyFromPost($object, $this->table); - $result = $object->update(); - $this->afterUpdate($object); - } - - if ($object->id) - $this->updateAssoShop($object->id); - - if (!$result) - { - $this->errors[] = Tools::displayError('An error occurred while updating an object.'). - ' <b>'.$this->table.'</b> ('.Db::getInstance()->getMsgError().')'; - } - elseif ($this->postImage($object->id) && !count($this->errors) && $this->_redirect) - { - $parent_id = (int)Tools::getValue('id_parent', 1); - // Specific back redirect - if ($back = Tools::getValue('back')) - $this->redirect_after = urldecode($back).'&conf=4'; - // Specific scene feature - // @todo change stay_here submit name (not clear for redirect to scene ... ) - if (Tools::getValue('stay_here') == 'on' || Tools::getValue('stay_here') == 'true' || Tools::getValue('stay_here') == '1') - $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$object->id.'&conf=4&updatescene&token='.$this->token; - // Save and stay on same form - // @todo on the to following if, we may prefer to avoid override redirect_after previous value - if (Tools::isSubmit('submitAdd'.$this->table.'AndStay')) - $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$object->id.'&conf=4&update'.$this->table.'&token='.$this->token; - // Save and back to parent - if (Tools::isSubmit('submitAdd'.$this->table.'AndBackToParent')) - $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$parent_id.'&conf=4&token='.$this->token; - - // Default behavior (save and back) - if (empty($this->redirect_after) && $this->redirect_after !== false) - $this->redirect_after = self::$currentIndex.($parent_id ? '&'.$this->identifier.'='.$object->id : '').'&conf=4&token='.$this->token; - } - PrestaShopLogger::addLog(sprintf($this->l('%s modification', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$object->id, true, (int)$this->context->employee->id); - } - else - $this->errors[] = Tools::displayError('An error occurred while updating an object.'). - ' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - } - } - $this->errors = array_unique($this->errors); - if (!empty($this->errors)) - { - // if we have errors, we stay on the form instead of going back to the list - $this->display = 'edit'; - return false; - } - - if (isset($object)) - return $object; - return; - } - - /** - * Change object required fields - * - * @return ObjectModel - */ - public function processUpdateFields() - { - if (!is_array($fields = Tools::getValue('fieldsBox'))) - $fields = array(); - - /** @var $object ObjectModel */ - $object = new $this->className(); - - if (!$object->addFieldsRequiredDatabase($fields)) - $this->errors[] = Tools::displayError('An error occurred when attempting to update the required fields.'); - else - $this->redirect_after = self::$currentIndex.'&conf=4&token='.$this->token; - - return $object; - } - - /** - * Change object status (active, inactive) - * - * @return ObjectModel|false - * @throws PrestaShopException - */ - public function processStatus() - { - if (Validate::isLoadedObject($object = $this->loadObject())) - { - if ($object->toggleStatus()) - { - $matches = array(); - if (preg_match('/[\?|&]controller=([^&]*)/', (string)$_SERVER['HTTP_REFERER'], $matches) !== false - && strtolower($matches[1]) != strtolower(preg_replace('/controller/i', '', get_class($this)))) - $this->redirect_after = preg_replace('/[\?|&]conf=([^&]*)/i', '', (string)$_SERVER['HTTP_REFERER']); - else - $this->redirect_after = self::$currentIndex.'&token='.$this->token; - - $id_category = (($id_category = (int)Tools::getValue('id_category')) && Tools::getValue('id_product')) ? '&id_category='.$id_category : ''; - - $page = (int)Tools::getValue('page'); - $page = $page > 1 ? '&submitFilter'.$this->table.'='.(int)$page : ''; - $this->redirect_after .= '&conf=5'.$id_category.$page; - } - else - $this->errors[] = Tools::displayError('An error occurred while updating the status.'); - } - else - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.'). - ' <b>'.$this->table.'</b> '. - Tools::displayError('(cannot load object)'); - - return $object; - } - - /** - * Change object position - * - * @return ObjectModel|false - */ - public function processPosition() - { - if (!Validate::isLoadedObject($object = $this->loadObject())) - { - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.'). - ' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - } - elseif (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) - $this->errors[] = Tools::displayError('Failed to update the position.'); - else - { - $id_identifier_str = ($id_identifier = (int)Tools::getValue($this->identifier)) ? '&'.$this->identifier.'='.$id_identifier : ''; - $redirect = self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=5'.$id_identifier_str.'&token='.$this->token; - $this->redirect_after = $redirect; - } - return $object; - } - - /** - * Cancel all filters for this tab - * - * @param int|null $list_id - */ - public function processResetFilters($list_id = null) - { - if ($list_id === null) - $list_id = isset($this->list_id) ? $this->list_id : $this->table; - - $prefix = str_replace(array('admin', 'controller'), '', Tools::strtolower(get_class($this))); - $filters = $this->context->cookie->getFamily($prefix.$list_id.'Filter_'); - foreach ($filters as $cookie_key => $filter) - if (strncmp($cookie_key, $prefix.$list_id.'Filter_', 7 + Tools::strlen($prefix.$list_id)) == 0) - { - $key = substr($cookie_key, 7 + Tools::strlen($prefix.$list_id)); - if (is_array($this->fields_list) && array_key_exists($key, $this->fields_list)) - $this->context->cookie->$cookie_key = null; - unset($this->context->cookie->$cookie_key); - } - - if (isset($this->context->cookie->{'submitFilter'.$list_id})) - unset($this->context->cookie->{'submitFilter'.$list_id}); - if (isset($this->context->cookie->{$prefix.$list_id.'Orderby'})) - unset($this->context->cookie->{$prefix.$list_id.'Orderby'}); - if (isset($this->context->cookie->{$prefix.$list_id.'Orderway'})) - unset($this->context->cookie->{$prefix.$list_id.'Orderway'}); - - $_POST = array(); - $this->_filter = false; - unset($this->_filterHaving); - unset($this->_having); - } - - /** - * Update options and preferences - */ - protected function processUpdateOptions() - { - $this->beforeUpdateOptions(); - - $languages = Language::getLanguages(false); - - $hide_multishop_checkbox = (Shop::getTotalShops(false, null) < 2) ? true : false; - foreach ($this->fields_options as $category_data) - { - if (!isset($category_data['fields'])) - continue; - - $fields = $category_data['fields']; - - foreach ($fields as $field => $values) - { - if (isset($values['type']) && $values['type'] == 'selectLang') - { - foreach ($languages as $lang) - if (Tools::getValue($field.'_'.strtoupper($lang['iso_code']))) - $fields[$field.'_'.strtoupper($lang['iso_code'])] = array( - 'type' => 'select', - 'cast' => 'strval', - 'identifier' => 'mode', - 'list' => $values['list'] - ); - } - } - - // Validate fields - foreach ($fields as $field => $values) - { - // We don't validate fields with no visibility - if (!$hide_multishop_checkbox && Shop::isFeatureActive() && isset($values['visibility']) && $values['visibility'] > Shop::getContext()) - continue; - - // Check if field is required - if ((!Shop::isFeatureActive() && isset($values['required']) && $values['required']) - || (Shop::isFeatureActive() && isset($_POST['multishopOverrideOption'][$field]) && isset($values['required']) && $values['required'])) - if (isset($values['type']) && $values['type'] == 'textLang') - { - foreach ($languages as $language) - if (($value = Tools::getValue($field.'_'.$language['id_lang'])) == false && (string)$value != '0') - $this->errors[] = sprintf(Tools::displayError('field %s is required.'), $values['title']); - } - elseif (($value = Tools::getValue($field)) == false && (string)$value != '0') - $this->errors[] = sprintf(Tools::displayError('field %s is required.'), $values['title']); - - // Check field validator - if (isset($values['type']) && $values['type'] == 'textLang') - { - foreach ($languages as $language) - if (Tools::getValue($field.'_'.$language['id_lang']) && isset($values['validation'])) - if (!Validate::$values['validation'](Tools::getValue($field.'_'.$language['id_lang']))) - $this->errors[] = sprintf(Tools::displayError('field %s is invalid.'), $values['title']); - } - elseif (Tools::getValue($field) && isset($values['validation'])) - if (!Validate::$values['validation'](Tools::getValue($field))) - $this->errors[] = sprintf(Tools::displayError('field %s is invalid.'), $values['title']); - - // Set default value - if (Tools::getValue($field) === false && isset($values['default'])) - $_POST[$field] = $values['default']; - } - - if (!count($this->errors)) - { - foreach ($fields as $key => $options) - { - if (Shop::isFeatureActive() && isset($options['visibility']) && $options['visibility'] > Shop::getContext()) - continue; - - if (!$hide_multishop_checkbox && Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL && empty($options['no_multishop_checkbox']) && empty($_POST['multishopOverrideOption'][$key])) - { - Configuration::deleteFromContext($key); - continue; - } - - // check if a method updateOptionFieldName is available - $method_name = 'updateOption'.Tools::toCamelCase($key, true); - if (method_exists($this, $method_name)) - $this->$method_name(Tools::getValue($key)); - elseif (isset($options['type']) && in_array($options['type'], array('textLang', 'textareaLang'))) - { - $list = array(); - foreach ($languages as $language) - { - $key_lang = Tools::getValue($key.'_'.$language['id_lang']); - $val = (isset($options['cast']) ? $options['cast']($key_lang) : $key_lang); - if ($this->validateField($val, $options)) - { - if (Validate::isCleanHtml($val)) - $list[$language['id_lang']] = $val; - else - $this->errors[] = Tools::displayError('Can not add configuration '.$key.' for lang '.Language::getIsoById((int)$language['id_lang'])); - } - } - Configuration::updateValue($key, $list, isset($values['validation']) && isset($options['validation']) && $options['validation'] == 'isCleanHtml' ? true : false); - } - else - { - $val = (isset($options['cast']) ? $options['cast'](Tools::getValue($key)) : Tools::getValue($key)); - if ($this->validateField($val, $options)) - { - if (Validate::isCleanHtml($val)) - Configuration::updateValue($key, $val); - else - $this->errors[] = Tools::displayError('Can not add configuration '.$key); - } - } - } - } - } - - $this->display = 'list'; - if (empty($this->errors)) - $this->confirmations[] = $this->_conf[6]; - } - - public function initPageHeaderToolbar() - { - if (empty($this->toolbar_title)) - $this->initToolbarTitle(); - - if (!is_array($this->toolbar_title)) - $this->toolbar_title = array($this->toolbar_title); - - switch ($this->display) - { - case 'view': - // Default cancel button - like old back link - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; - if (!Validate::isCleanHtml($back)) - die(Tools::displayError()); - if (!$this->lite_display) - $this->page_header_toolbar_btn['back'] = array( - 'href' => $back, - 'desc' => $this->l('Back to list') - ); - $obj = $this->loadObject(true); - if (Validate::isLoadedObject($obj) && isset($obj->{$this->identifier_name}) && !empty($obj->{$this->identifier_name})) - { - array_pop($this->toolbar_title); - array_pop($this->meta_title); - $this->toolbar_title[] = is_array($obj->{$this->identifier_name}) ? $obj->{$this->identifier_name}[$this->context->employee->id_lang] : $obj->{$this->identifier_name}; - $this->addMetaTitle($this->toolbar_title[count($this->toolbar_title) - 1]); - } - break; - case 'edit': - $obj = $this->loadObject(true); - if (Validate::isLoadedObject($obj) && isset($obj->{$this->identifier_name}) && !empty($obj->{$this->identifier_name})) - { - array_pop($this->toolbar_title); - array_pop($this->meta_title); - $this->toolbar_title[] = sprintf($this->l('Edit: %s'), - (is_array($obj->{$this->identifier_name}) && isset($obj->{$this->identifier_name}[$this->context->employee->id_lang])) ? $obj->{$this->identifier_name}[$this->context->employee->id_lang] : $obj->{$this->identifier_name}); - $this->addMetaTitle($this->toolbar_title[count($this->toolbar_title) - 1]); - } - break; - } - - if (is_array($this->page_header_toolbar_btn) - && $this->page_header_toolbar_btn instanceof Traversable - || count($this->toolbar_title)) - $this->show_page_header_toolbar = true; - - if (empty($this->page_header_toolbar_title)) - $this->page_header_toolbar_title = $this->toolbar_title[count($this->toolbar_title) - 1]; - $this->addPageHeaderToolBarModulesListButton(); - - $this->context->smarty->assign('help_link', 'http://help.prestashop.com/'.Language::getIsoById($this->context->employee->id_lang).'/doc/' - .Tools::getValue('controller').'?version='._PS_VERSION_.'&country='.Language::getIsoById($this->context->employee->id_lang)); - } - - /** - * assign default action in toolbar_btn smarty var, if they are not set. - * uses override to specifically add, modify or remove items - * - */ - public function initToolbar() - { - switch ($this->display) - { - case 'add': - case 'edit': - // Default save button - action dynamically handled in javascript - $this->toolbar_btn['save'] = array( - 'href' => '#', - 'desc' => $this->l('Save') - ); - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; - if (!Validate::isCleanHtml($back)) - die(Tools::displayError()); - if (!$this->lite_display) - $this->toolbar_btn['cancel'] = array( - 'href' => $back, - 'desc' => $this->l('Cancel') - ); - break; - case 'view': - // Default cancel button - like old back link - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; - if (!Validate::isCleanHtml($back)) - die(Tools::displayError()); - if (!$this->lite_display) - $this->toolbar_btn['back'] = array( - 'href' => $back, - 'desc' => $this->l('Back to list') - ); - break; - case 'options': - $this->toolbar_btn['save'] = array( - 'href' => '#', - 'desc' => $this->l('Save') - ); - break; - default: // list - $this->toolbar_btn['new'] = array( - 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token, - 'desc' => $this->l('Add new') - ); - if ($this->allow_export) - $this->toolbar_btn['export'] = array( - 'href' => self::$currentIndex.'&export'.$this->table.'&token='.$this->token, - 'desc' => $this->l('Export') - ); - } - $this->addToolBarModulesListButton(); - } - - /** - * Load class object using identifier in $_GET (if possible) - * otherwise return an empty object, or die - * - * @param bool $opt Return an empty object if load fail - * @return ObjectModel|false - */ - protected function loadObject($opt = false) - { - if (!isset($this->className) || empty($this->className)) - return true; - - $id = (int)Tools::getValue($this->identifier); - if ($id && Validate::isUnsignedId($id)) - { - if (!$this->object) - $this->object = new $this->className($id); - if (Validate::isLoadedObject($this->object)) - return $this->object; - // throw exception - $this->errors[] = Tools::displayError('The object cannot be loaded (or found)'); - return false; - } - elseif ($opt) - { - if (!$this->object) - $this->object = new $this->className(); - return $this->object; - } - else - { - $this->errors[] = Tools::displayError('The object cannot be loaded (the identifier is missing or invalid)'); - return false; - } - } - - /** - * Check if the token is valid, else display a warning page - * - * @return bool - */ - public function checkAccess() - { - if (!$this->checkToken()) - { - // If this is an XSS attempt, then we should only display a simple, secure page - // ${1} in the replacement string of the regexp is required, - // because the token may begin with a number and mix up with it (e.g. $17) - $url = preg_replace('/([&?]token=)[^&]*(&.*)?$/', '${1}'.$this->token.'$2', $_SERVER['REQUEST_URI']); - if (false === strpos($url, '?token=') && false === strpos($url, '&token=')) - $url .= '&token='.$this->token; - if (strpos($url, '?') === false) - $url = str_replace('&token', '?controller=AdminDashboard&token', $url); - - $this->context->smarty->assign('url', htmlentities($url)); - return false; - } - return true; - } - - /** - * @param string $key - * @param string $filter - * @return array|false - */ - protected function filterToField($key, $filter) - { - if (!isset($this->fields_list)) - return false; - - foreach ($this->fields_list as $field) - if (array_key_exists('filter_key', $field) && $field['filter_key'] == $key) - return $field; - if (array_key_exists($filter, $this->fields_list)) - return $this->fields_list[$filter]; - return false; - } - - public function displayNoSmarty() - { - } - - /** - * @return void - */ - public function displayAjax() - { - if ($this->json) - { - $this->context->smarty->assign(array( - 'json' => true, - 'status' => $this->status, - )); - } - $this->layout = 'layout-ajax.tpl'; - $this->display_header = false; - $this->display_header_javascript = false; - $this->display_footer = false; - return $this->display(); - } - - protected function redirect() - { - Tools::redirectAdmin($this->redirect_after); - } - - /** - * @return void - * @throws Exception - * @throws SmartyException - */ - public function display() - { - $this->context->smarty->assign(array( - 'display_header' => $this->display_header, - 'display_header_javascript'=> $this->display_header_javascript, - 'display_footer' => $this->display_footer, - 'js_def' => Media::getJsDef(), - )); - - // Use page title from meta_title if it has been set else from the breadcrumbs array - if (!$this->meta_title) - $this->meta_title = $this->toolbar_title; - if (is_array($this->meta_title)) - $this->meta_title = strip_tags(implode(' '.Configuration::get('PS_NAVIGATION_PIPE').' ', $this->meta_title)); - $this->context->smarty->assign('meta_title', $this->meta_title); - - $template_dirs = $this->context->smarty->getTemplateDir(); - - // Check if header/footer have been overriden - $dir = $this->context->smarty->getTemplateDir(0).'controllers'.DIRECTORY_SEPARATOR.trim($this->override_folder, '\\/').DIRECTORY_SEPARATOR; - $module_list_dir = $this->context->smarty->getTemplateDir(0).'helpers'.DIRECTORY_SEPARATOR.'modules_list'.DIRECTORY_SEPARATOR; - - $header_tpl = file_exists($dir.'header.tpl') ? $dir.'header.tpl' : 'header.tpl'; - $page_header_toolbar = file_exists($dir.'page_header_toolbar.tpl') ? $dir.'page_header_toolbar.tpl' : 'page_header_toolbar.tpl'; - $footer_tpl = file_exists($dir.'footer.tpl') ? $dir.'footer.tpl' : 'footer.tpl'; - $modal_module_list = file_exists($module_list_dir.'modal.tpl') ? $module_list_dir.'modal.tpl' : 'modal.tpl'; - $tpl_action = $this->tpl_folder.$this->display.'.tpl'; - - // Check if action template has been overriden - foreach ($template_dirs as $template_dir) - if (file_exists($template_dir.DIRECTORY_SEPARATOR.$tpl_action) && $this->display != 'view' && $this->display != 'options') - { - if (method_exists($this, $this->display.Tools::toCamelCase($this->className))) - $this->{$this->display.Tools::toCamelCase($this->className)}(); - $this->context->smarty->assign('content', $this->context->smarty->fetch($tpl_action)); - break; - } - - if (!$this->ajax) - { - $template = $this->createTemplate($this->template); - $page = $template->fetch(); - } - else - $page = $this->content; - - if ($conf = Tools::getValue('conf')) - $this->context->smarty->assign('conf', $this->json ? Tools::jsonEncode($this->_conf[(int)$conf]) : $this->_conf[(int)$conf]); - - foreach (array('errors', 'warnings', 'informations', 'confirmations') as $type) - { - if (!is_array($this->$type)) - $this->$type = (array)$this->$type; - $this->context->smarty->assign($type, $this->json ? Tools::jsonEncode(array_unique($this->$type)) : array_unique($this->$type)); - } - - if ($this->show_page_header_toolbar && !$this->lite_display) - $this->context->smarty->assign(array( - 'page_header_toolbar' => $this->context->smarty->fetch($page_header_toolbar), - 'modal_module_list' => $this->context->smarty->fetch($modal_module_list), - ) - ); - - $this->context->smarty->assign(array( - 'page' => $this->json ? Tools::jsonEncode($page) : $page, - 'header' => $this->context->smarty->fetch($header_tpl), - 'footer' => $this->context->smarty->fetch($footer_tpl), - ) - ); - - $this->smartyOutputContent($this->layout); - } - - /** - * Add a warning message to display at the top of the page - * - * @param string $msg - */ - protected function displayWarning($msg) - { - $this->warnings[] = $msg; - } - - /** - * Add a info message to display at the top of the page - * - * @param string $msg - */ - protected function displayInformation($msg) - { - $this->informations[] = $msg; - } - - /** - * Assign smarty variables for the header - */ - public function initHeader() - { - header('Cache-Control: no-store, no-cache'); - - // Multishop - $is_multishop = Shop::isFeatureActive(); - - // Quick access - if ((int)$this->context->employee->id) - { - $quick_access = QuickAccess::getQuickAccesses($this->context->language->id); - foreach ($quick_access as $index => $quick) - { - if ($quick['link'] == '../' && Shop::getContext() == Shop::CONTEXT_SHOP) - { - $url = $this->context->shop->getBaseURL(); - if (!$url) - { - unset($quick_access[$index]); - continue; - } - $quick_access[$index]['link'] = $url; - } - else - { - preg_match('/controller=(.+)(&.+)?$/', $quick['link'], $admin_tab); - if (isset($admin_tab[1])) - { - if (strpos($admin_tab[1], '&')) - $admin_tab[1] = substr($admin_tab[1], 0, strpos($admin_tab[1], '&')); - - $token = Tools::getAdminToken($admin_tab[1].(int)Tab::getIdFromClassName($admin_tab[1]).(int)$this->context->employee->id); - $quick_access[$index]['target'] = $admin_tab[1]; - $quick_access[$index]['link'] .= '&token='.$token; - } - } - } - } - - // Tab list - $tabs = Tab::getTabs($this->context->language->id, 0); - $current_id = Tab::getCurrentParentId(); - foreach ($tabs as $index => $tab) - { - if (!Tab::checkTabRights($tab['id_tab']) - || ($tab['class_name'] == 'AdminStock' && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') == 0) - || $tab['class_name'] == 'AdminCarrierWizard') - { - unset($tabs[$index]); - continue; - } - - $img_cache_url = 'themes/'.$this->context->employee->bo_theme.'/img/t/'.$tab['class_name'].'.png'; - $img_exists_cache = Tools::file_exists_cache(_PS_ADMIN_DIR_.$img_cache_url); - // retrocompatibility : change png to gif if icon not exists - if (!$img_exists_cache) - $img_exists_cache = Tools::file_exists_cache(_PS_ADMIN_DIR_.str_replace('.png', '.gif', $img_cache_url)); - - if ($img_exists_cache) - $path_img = $img = $img_exists_cache; - else - { - $path_img = _PS_IMG_DIR_.'t/'.$tab['class_name'].'.png'; - // Relative link will always work, whatever the base uri set in the admin - $img = '../img/t/'.$tab['class_name'].'.png'; - } - - if (trim($tab['module']) != '') - { - $path_img = _PS_MODULE_DIR_.$tab['module'].'/'.$tab['class_name'].'.png'; - // Relative link will always work, whatever the base uri set in the admin - $img = '../modules/'.$tab['module'].'/'.$tab['class_name'].'.png'; - } - - // retrocompatibility - if (!file_exists($path_img)) - $img = str_replace('png', 'gif', $img); - // tab[class_name] does not contains the "Controller" suffix - $tabs[$index]['current'] = ($tab['class_name'].'Controller' == get_class($this)) || ($current_id == $tab['id_tab']); - $tabs[$index]['img'] = $img; - $tabs[$index]['href'] = $this->context->link->getAdminLink($tab['class_name']); - - $sub_tabs = Tab::getTabs($this->context->language->id, $tab['id_tab']); - foreach ($sub_tabs as $index2 => $sub_tab) - { - //check if module is enable and - if (isset($sub_tab['module']) && !empty($sub_tab['module'])) - { - $module = Module::getInstanceByName($sub_tab['module']); - if (is_object($module) && !$module->isEnabledForShopContext()) - { - unset($sub_tabs[$index2]); - continue; - } - } - - // class_name is the name of the class controller - if (Tab::checkTabRights($sub_tab['id_tab']) === true && (bool)$sub_tab['active'] && $sub_tab['class_name'] != 'AdminCarrierWizard') - { - $sub_tabs[$index2]['href'] = $this->context->link->getAdminLink($sub_tab['class_name']); - $sub_tabs[$index2]['current'] = ($sub_tab['class_name'].'Controller' == get_class($this) || $sub_tab['class_name'] == Tools::getValue('controller')); - } - elseif ($sub_tab['class_name'] == 'AdminCarrierWizard' && $sub_tab['class_name'].'Controller' == get_class($this)) - { - foreach ($sub_tabs as $i => $tab) - if ($tab['class_name'] == 'AdminCarriers') - break; - - $sub_tabs[$i]['current'] = true; - unset($sub_tabs[$index2]); - } - else - unset($sub_tabs[$index2]); - } - $tabs[$index]['sub_tabs'] = array_values($sub_tabs); - } - - if (Validate::isLoadedObject($this->context->employee)) - { - $accesses = Profile::getProfileAccesses($this->context->employee->id_profile, 'class_name'); - $helperShop = new HelperShop(); - /* Hooks are voluntary out the initialize array (need those variables already assigned) */ - $bo_color = empty($this->context->employee->bo_color) ? '#FFFFFF' : $this->context->employee->bo_color; - $this->context->smarty->assign(array( - 'autorefresh_notifications' => Configuration::get('PS_ADMINREFRESH_NOTIFICATION'), - 'help_box' => Configuration::get('PS_HELPBOX'), - 'round_mode' => Configuration::get('PS_PRICE_ROUND_MODE'), - 'brightness' => Tools::getBrightness($bo_color) < 128 ? 'white' : '#383838', - 'bo_width' => (int)$this->context->employee->bo_width, - 'bo_color' => isset($this->context->employee->bo_color) ? Tools::htmlentitiesUTF8($this->context->employee->bo_color) : null, - 'show_new_orders' => Configuration::get('PS_SHOW_NEW_ORDERS') && isset($accesses['AdminOrders']) && $accesses['AdminOrders']['view'], - 'show_new_customers' => Configuration::get('PS_SHOW_NEW_CUSTOMERS') && isset($accesses['AdminCustomers']) && $accesses['AdminCustomers']['view'], - 'show_new_messages' => Configuration::get('PS_SHOW_NEW_MESSAGES') && isset($accesses['AdminCustomerThreads']) && $accesses['AdminCustomerThreads']['view'], - 'employee' => $this->context->employee, - 'current_version' => (string)Configuration::get('PS_INSTALL_VERSION'), - 'search_type' => Tools::getValue('bo_search_type'), - 'bo_query' => Tools::safeOutput(Tools::stripslashes(Tools::getValue('bo_query'))), - 'quick_access' => $quick_access, - 'multi_shop' => Shop::isFeatureActive(), - 'shop_list' => $helperShop->getRenderedShopList(), - 'shop' => $this->context->shop, - 'shop_group' => new ShopGroup((int)Shop::getContextShopGroupID()), - 'is_multishop' => $is_multishop, - 'multishop_context' => $this->multishop_context, - 'default_tab_link' => $this->context->link->getAdminLink(Tab::getClassNameById((int)Context::getContext()->employee->default_tab)), - 'collapse_menu' => isset($this->context->cookie->collapse_menu) ? (int)$this->context->cookie->collapse_menu : 0, - )); - } - else - $this->context->smarty->assign('default_tab_link', $this->context->link->getAdminLink('AdminDashboard')); - - // Shop::initialize() in config.php may empty $this->context->shop->virtual_uri so using a new shop instance for getBaseUrl() - $this->context->shop = new Shop((int)$this->context->shop->id); - - $this->context->smarty->assign(array( - 'img_dir' => _PS_IMG_, - 'iso' => $this->context->language->iso_code, - 'class_name' => $this->className, - 'iso_user' => $this->context->language->iso_code, - 'country_iso_code' => $this->context->country->iso_code, - 'version' => _PS_VERSION_, - 'lang_iso' => $this->context->language->iso_code, - 'full_language_code' => $this->context->language->language_code, - 'link' => $this->context->link, - 'shop_name' => Configuration::get('PS_SHOP_NAME'), - 'base_url' => $this->context->shop->getBaseURL(), - 'tab' => isset($tab) ? $tab : null, // Deprecated, this tab is declared in the foreach, so it's the last tab in the foreach - 'current_parent_id' => (int)Tab::getCurrentParentId(), - 'tabs' => $tabs, - 'install_dir_exists' => file_exists(_PS_ADMIN_DIR_.'/../install'), - 'pic_dir' => _THEME_PROD_PIC_DIR_, - 'controller_name' => htmlentities(Tools::getValue('controller')), - 'currentIndex' => self::$currentIndex, - 'bootstrap' => $this->bootstrap, - 'default_language' => (int)Configuration::get('PS_LANG_DEFAULT'), - 'display_addons_connection' => Tab::checkTabRights(Tab::getIdFromClassName('AdminModulesController')) - )); - - $module = Module::getInstanceByName('themeconfigurator'); - if (is_object($module) && $module->active && (int)Configuration::get('PS_TC_ACTIVE') == 1 && $this->context->shop->getBaseURL()) - { - $request = - 'live_configurator_token='.$module->getLiveConfiguratorToken() - .'&id_employee='.(int)$this->context->employee->id - .'&id_shop='.(int)$this->context->shop->id - .(Configuration::get('PS_TC_THEME') != '' ? '&theme='.Configuration::get('PS_TC_THEME') : '') - .(Configuration::get('PS_TC_FONT') != '' ? '&theme_font='.Configuration::get('PS_TC_FONT') : ''); - $this->context->smarty->assign('base_url_tc', $this->context->link->getPageLink('index', null, $id_lang = null, $request)); - } - } - - /** - * Declare an action to use for each row in the list - * - * @param string $action - */ - public function addRowAction($action) - { - $action = strtolower($action); - $this->actions[] = $action; - } - - /** - * Add an action to use for each row in the list - * - * @param string $action - * @param array $list - */ - public function addRowActionSkipList($action, $list) - { - $action = strtolower($action); - $list = (array)$list; - - if (array_key_exists($action, $this->list_skip_actions)) - $this->list_skip_actions[$action] = array_merge($this->list_skip_actions[$action], $list); - else - $this->list_skip_actions[$action] = $list; - } - - /** - * Assign smarty variables for all default views, list and form, then call other init functions - */ - public function initContent() - { - if (!$this->viewAccess()) - { - $this->errors[] = Tools::displayError('You do not have permission to view this.'); - return; - } - - $this->getLanguages(); - $this->initToolbar(); - $this->initTabModuleList(); - $this->initPageHeaderToolbar(); - - if ($this->display == 'edit' || $this->display == 'add') - { - if (!$this->loadObject(true)) - return; - - $this->content .= $this->renderForm(); - } - elseif ($this->display == 'view') - { - // Some controllers use the view action without an object - if ($this->className) - $this->loadObject(true); - $this->content .= $this->renderView(); - } - elseif ($this->display == 'details') - $this->content .= $this->renderDetails(); - - elseif (!$this->ajax) - { - $this->content .= $this->renderModulesList(); - $this->content .= $this->renderKpis(); - $this->content .= $this->renderList(); - $this->content .= $this->renderOptions(); - - // if we have to display the required fields form - if ($this->required_database) - $this->content .= $this->displayRequiredFields(); - } - - $this->context->smarty->assign(array( - 'maintenance_mode' => !(bool)Configuration::get('PS_SHOP_ENABLE'), - 'content' => $this->content, - 'lite_display' => $this->lite_display, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'title' => $this->page_header_toolbar_title, - 'toolbar_btn' => $this->page_header_toolbar_btn, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } - - /** - * Init tab modules list and add button in toolbar - */ - protected function initTabModuleList() - { - if (!$this->isFresh(Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, 86400)) - @file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, Tools::addonsRequest('must-have')); - if (!$this->isFresh(Module::CACHE_FILE_TAB_MODULES_LIST, 604800)) - $this->refresh(Module::CACHE_FILE_TAB_MODULES_LIST, _PS_TAB_MODULE_LIST_URL_); - - $this->tab_modules_list = Tab::getTabModulesList($this->id); - - if (is_array($this->tab_modules_list['default_list']) && count($this->tab_modules_list['default_list'])) - $this->filter_modules_list = $this->tab_modules_list['default_list']; - elseif (is_array($this->tab_modules_list['slider_list']) && count($this->tab_modules_list['slider_list'])) - { - $this->addToolBarModulesListButton(); - $this->addPageHeaderToolBarModulesListButton(); - $this->context->smarty->assign(array( - 'tab_modules_list' => implode(',', $this->tab_modules_list['slider_list']), - 'admin_module_ajax_url' => $this->context->link->getAdminLink('AdminModules'), - 'back_tab_modules_list' => $this->context->link->getAdminLink(Tools::getValue('controller')), - 'tab_modules_open' => (int)Tools::getValue('tab_modules_open') - )); - } - - } - - protected function addPageHeaderToolBarModulesListButton() - { - $this->filterTabModuleList(); - - if (is_array($this->tab_modules_list['slider_list']) && count($this->tab_modules_list['slider_list'])) - $this->page_header_toolbar_btn['modules-list'] = array( - 'href' => '#', - 'desc' => $this->l('Recommended Modules and Services') - ); - } - - protected function addToolBarModulesListButton() - { - $this->filterTabModuleList(); - - if (is_array($this->tab_modules_list['slider_list']) && count($this->tab_modules_list['slider_list'])) - $this->toolbar_btn['modules-list'] = array( - 'href' => '#', - 'desc' => $this->l('Recommended Modules and Services') - ); - } - - protected function filterTabModuleList() - { - static $list_is_filtered = null; - - if ($list_is_filtered !== null) - return; - - if (!$this->isFresh(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 86400)) - file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, Tools::addonsRequest('native')); - - if (!$this->isFresh(Module::CACHE_FILE_ALL_COUNTRY_MODULES_LIST, 86400)) - file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_ALL_COUNTRY_MODULES_LIST, Tools::addonsRequest('native_all')); - - if (!$this->isFresh(Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, 86400)) - @file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, Tools::addonsRequest('must-have')); - - libxml_use_internal_errors(true); - - $country_module_list = file_get_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST); - $must_have_module_list = file_get_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST); - $all_module_list = array(); - - if (!empty($country_module_list) && $country_module_list_xml = simplexml_load_string($country_module_list)) - { - $country_module_list_array = array(); - if (is_object($country_module_list_xml->module)) - foreach ($country_module_list_xml->module as $k => $m) - $all_module_list[] = (string)$m->name; - } - - if (!empty($must_have_module_list) && $must_have_module_list_xml = simplexml_load_string($must_have_module_list)) - { - $must_have_module_list_array = array(); - if (is_object($country_module_list_xml->module)) - foreach ($must_have_module_list_xml->module as $l => $mo) - $all_module_list[] = (string)$mo->name; - } - - $this->tab_modules_list['slider_list'] = array_intersect($this->tab_modules_list['slider_list'], $all_module_list); - - $list_is_filtered = true; - } - - /** - * Initialize the invalid doom page of death - * - * @return void - */ - public function initCursedPage() - { - $this->layout = 'invalid_token.tpl'; - } - - /** - * Assign smarty variables for the footer - */ - public function initFooter() - { - //RTL Support - //rtl.js overrides inline styles - //iso_code.css overrides default fonts for every language (optional) - if ($this->context->language->is_rtl) - { - $this->addJS(_PS_JS_DIR_.'rtl.js'); - $this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/'.$this->context->language->iso_code.'.css', 'all', false); - } - - // We assign js and css files on the last step before display template, because controller can add many js and css files - $this->context->smarty->assign('css_files', $this->css_files); - $this->context->smarty->assign('js_files', array_unique($this->js_files)); - - $this->context->smarty->assign(array( - 'ps_version' => _PS_VERSION_, - 'timer_start' => $this->timer_start, - 'iso_is_fr' => strtoupper($this->context->language->iso_code) == 'FR', - 'modals' => $this->renderModal(), - )); - } - - /** - * @throws Exception - * @throws SmartyException - */ - public function initModal() - { - if ($this->logged_on_addons) - { - $this->context->smarty->assign(array( - 'logged_on_addons' => 1, - 'username_addons' => $this->context->cookie->username_addons - )); - } - - // Iso needed to generate Addons login - $iso_code_caps = strtoupper($this->context->language->iso_code); - - $this->context->smarty->assign(array( - 'check_url_fopen' => (ini_get('allow_url_fopen') ? 'ok' : 'ko'), - 'check_openssl' => (extension_loaded('openssl') ? 'ok' : 'ko'), - 'add_permission' => 1, - 'addons_register_link' => '//addons.prestashop.com/'.$this->context->language->iso_code.'/login?' - .'email='.urlencode($this->context->employee->email) - .'&firstname='.urlencode($this->context->employee->firstname) - .'&lastname='.urlencode($this->context->employee->lastname) - .'&website='.urlencode($this->context->shop->getBaseURL()) - .'&utm_source=back-office&utm_medium=connect-to-addons' - .'&utm_campaign=back-office-'.Tools::strtoupper($this->context->language->iso_code) - .'&utm_content='.(defined('_PS_HOST_MODE_') ? 'cloud' : 'download').'#createnow', - 'addons_forgot_password_link' => '//addons.prestashop.com/'.$this->context->language->iso_code.'/forgot-your-password' - )); - - $this->modals[] = array( - 'modal_id' => 'modal_addons_connect', - 'modal_class' => 'modal-md', - 'modal_title' => '<i class="icon-puzzle-piece"></i> <a target="_blank" href="http://addons.prestashop.com/' - .'?utm_source=back-office&utm_medium=modules' - .'&utm_campaign=back-office-'.Tools::strtoupper($this->context->language->iso_code) - .'&utm_content='.(defined('_PS_HOST_MODE_') ? 'cloud' : 'download').'">PrestaShop Addons</a>', - 'modal_content' => $this->context->smarty->fetch('controllers/modules/login_addons.tpl'), - ); - } - - /** - * @return string - * @throws Exception - * @throws SmartyException - */ - public function renderModal() - { - $modal_render = ''; - if (is_array($this->modals) && count($this->modals)) - { - foreach ($this->modals as $modal) - { - $this->context->smarty->assign($modal); - $modal_render .= $this->context->smarty->fetch('modal.tpl'); - } - } - return $modal_render; - } - - /** - * @return string - */ - public function renderModulesList() - { - // Load cache file modules list (natives and partners modules) - $xml_modules = false; - if (file_exists(_PS_ROOT_DIR_.Module::CACHE_FILE_MODULES_LIST)) - $xml_modules = @simplexml_load_file(_PS_ROOT_DIR_.Module::CACHE_FILE_MODULES_LIST); - if ($xml_modules) - foreach ($xml_modules->children() as $xml_module) - { - /** @var SimpleXMLElement $xml_module */ - foreach ($xml_module->children() as $module) - { - /** @var SimpleXMLElement $module */ - foreach ($module->attributes() as $key => $value) - { - if ($xml_module->attributes() == 'native' && $key == 'name') - $this->list_natives_modules[] = (string)$value; - if ($xml_module->attributes() == 'partner' && $key == 'name') - $this->list_partners_modules[] = (string)$value; - } - } - } - - if ($this->getModulesList($this->filter_modules_list)) - { - $tmp = array(); - foreach ($this->modules_list as $key => $module) - if ($module->active) - { - $tmp[] = $module; - unset($this->modules_list[$key]); - } - - $this->modules_list = array_merge($tmp, $this->modules_list); - - foreach ($this->modules_list as $key => $module) - { - if (in_array($module->name, $this->list_partners_modules)) - $this->modules_list[$key]->type = 'addonsPartner'; - if (isset($module->description_full) && trim($module->description_full) != '') - $module->show_quick_view = true; - } - $helper = new Helper(); - return $helper->renderModulesList($this->modules_list); - } - } - - /** - * Function used to render the list to display for this controller - * - * @return string|false - * @throws PrestaShopException - */ - public function renderList() - { - if (!($this->fields_list && is_array($this->fields_list))) - return false; - $this->getList($this->context->language->id); - - // If list has 'active' field, we automatically create bulk action - if (isset($this->fields_list) && is_array($this->fields_list) && array_key_exists('active', $this->fields_list) - && !empty($this->fields_list['active'])) - { - if (!is_array($this->bulk_actions)) - $this->bulk_actions = array(); - - $this->bulk_actions = array_merge(array( - 'enableSelection' => array( - 'text' => $this->l('Enable selection'), - 'icon' => 'icon-power-off text-success' - ), - 'disableSelection' => array( - 'text' => $this->l('Disable selection'), - 'icon' => 'icon-power-off text-danger' - ), - 'divider' => array( - 'text' => 'divider' - ) - ), $this->bulk_actions); - } - - $helper = new HelperList(); - - // Empty list is ok - if (!is_array($this->_list)) - { - $this->displayWarning($this->l('Bad SQL query', 'Helper').'<br />'.htmlspecialchars($this->_list_error)); - return false; - } - - $this->setHelperDisplay($helper); - $helper->_default_pagination = $this->_default_pagination; - $helper->_pagination = $this->_pagination; - $helper->tpl_vars = $this->getTemplateListVars(); - $helper->tpl_delete_link_vars = $this->tpl_delete_link_vars; - - // For compatibility reasons, we have to check standard actions in class attributes - foreach ($this->actions_available as $action) - if (!in_array($action, $this->actions) && isset($this->$action) && $this->$action) - $this->actions[] = $action; - - $helper->is_cms = $this->is_cms; - $helper->sql = $this->_listsql; - $list = $helper->generateList($this->_list, $this->fields_list); - - return $list; - } - - public function getTemplateListVars() - { - return $this->tpl_list_vars; - } - - /** - * Override to render the view page - * - * @return string - */ - public function renderView() - { - $helper = new HelperView($this); - $this->setHelperDisplay($helper); - $helper->tpl_vars = $this->getTemplateViewVars(); - if (!is_null($this->base_tpl_view)) - $helper->base_tpl = $this->base_tpl_view; - $view = $helper->generateView(); - - return $view; - } - - public function getTemplateViewVars() - { - return $this->tpl_view_vars; - } - - /** - * Override to render the view page - * - * @return string|false - */ - public function renderDetails() - { - return $this->renderList(); - } - - /** - * Function used to render the form for this controller - * - * @return string - * @throws Exception - * @throws SmartyException - */ - public function renderForm() - { - if (!$this->default_form_language) - $this->getLanguages(); - - if (Tools::getValue('submitFormAjax')) - $this->content .= $this->context->smarty->fetch('form_submit_ajax.tpl'); - - if ($this->fields_form && is_array($this->fields_form)) - { - if (!$this->multiple_fieldsets) - $this->fields_form = array(array('form' => $this->fields_form)); - - // For add a fields via an override of $fields_form, use $fields_form_override - if (is_array($this->fields_form_override) && !empty($this->fields_form_override)) - $this->fields_form[0]['form']['input'] = array_merge($this->fields_form[0]['form']['input'], $this->fields_form_override); - - $fields_value = $this->getFieldsValue($this->object); - - Hook::exec('action'.$this->controller_name.'FormModifier', array( - 'fields' => &$this->fields_form, - 'fields_value' => &$fields_value, - 'form_vars' => &$this->tpl_form_vars, - )); - - $helper = new HelperForm($this); - $this->setHelperDisplay($helper); - $helper->fields_value = $fields_value; - $helper->submit_action = $this->submit_action; - $helper->tpl_vars = $this->getTemplateFormVars(); - $helper->show_cancel_button = (isset($this->show_form_cancel_button)) ? $this->show_form_cancel_button : ($this->display == 'add' || $this->display == 'edit'); - - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; - if (!Validate::isCleanHtml($back)) - die(Tools::displayError()); - - $helper->back_url = $back; - !is_null($this->base_tpl_form) ? $helper->base_tpl = $this->base_tpl_form : ''; - if ($this->tabAccess['view']) - { - if (Tools::getValue('back')) - $helper->tpl_vars['back'] = Tools::safeOutput(Tools::getValue('back')); - else - $helper->tpl_vars['back'] = Tools::safeOutput(Tools::getValue(self::$currentIndex.'&token='.$this->token)); - } - $form = $helper->generateForm($this->fields_form); - - return $form; - } - } - - public function getTemplateFormVars() - { - return $this->tpl_form_vars; - } - - public function renderKpis() - { - } - - /** - * Function used to render the options for this controller - * - * @return string - */ - public function renderOptions() - { - Hook::exec('action'.$this->controller_name.'OptionsModifier', array( - 'options' => &$this->fields_options, - 'option_vars' => &$this->tpl_option_vars, - )); - - if ($this->fields_options && is_array($this->fields_options)) - { - if (isset($this->display) && $this->display != 'options' && $this->display != 'list') - $this->show_toolbar = false; - else - $this->display = 'options'; - - unset($this->toolbar_btn); - $this->initToolbar(); - $helper = new HelperOptions($this); - $this->setHelperDisplay($helper); - $helper->id = $this->id; - $helper->tpl_vars = $this->tpl_option_vars; - $options = $helper->generateOptions($this->fields_options); - - return $options; - } - } - - /** - * This function sets various display options for helper list - * - * @param Helper $helper - * @return void - */ - public function setHelperDisplay(Helper $helper) - { - if (empty($this->toolbar_title)) - $this->initToolbarTitle(); - // tocheck - if ($this->object && $this->object->id) - $helper->id = $this->object->id; - - // @todo : move that in Helper - $helper->title = is_array($this->toolbar_title) ? implode(' '.Configuration::get('PS_NAVIGATION_PIPE').' ', $this->toolbar_title) : $this->toolbar_title; - $helper->toolbar_btn = $this->toolbar_btn; - $helper->show_toolbar = $this->show_toolbar; - $helper->toolbar_scroll = $this->toolbar_scroll; - $helper->override_folder = $this->tpl_folder; - $helper->actions = $this->actions; - $helper->simple_header = $this->list_simple_header; - $helper->bulk_actions = $this->bulk_actions; - $helper->currentIndex = self::$currentIndex; - $helper->className = $this->className; - $helper->table = $this->table; - $helper->name_controller = Tools::getValue('controller'); - $helper->orderBy = $this->_orderBy; - $helper->orderWay = $this->_orderWay; - $helper->listTotal = $this->_listTotal; - $helper->shopLink = $this->shopLink; - $helper->shopLinkType = $this->shopLinkType; - $helper->identifier = $this->identifier; - $helper->token = $this->token; - $helper->languages = $this->_languages; - $helper->specificConfirmDelete = $this->specificConfirmDelete; - $helper->imageType = $this->imageType; - $helper->no_link = $this->list_no_link; - $helper->colorOnBackground = $this->colorOnBackground; - $helper->ajax_params = (isset($this->ajax_params) ? $this->ajax_params : null); - $helper->default_form_language = $this->default_form_language; - $helper->allow_employee_form_lang = $this->allow_employee_form_lang; - $helper->multiple_fieldsets = $this->multiple_fieldsets; - $helper->row_hover = $this->row_hover; - $helper->position_identifier = $this->position_identifier; - $helper->position_group_identifier = $this->position_group_identifier; - $helper->controller_name = $this->controller_name; - $helper->list_id = isset($this->list_id) ? $this->list_id : $this->table; - $helper->bootstrap = $this->bootstrap; - - // For each action, try to add the corresponding skip elements list - $helper->list_skip_actions = $this->list_skip_actions; - - $this->helper = $helper; - } - - /** - * @deprecated 1.6.0 - */ - public function setDeprecatedMedia() - { - - } - - public function setMedia() - { - //Bootstrap - $this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/'.$this->bo_css, 'all', 0); - - $this->addJquery(); - $this->addjQueryPlugin(array('scrollTo', 'alerts', 'chosen', 'autosize', 'fancybox' )); - $this->addjQueryPlugin('growl', null, false); - $this->addJqueryUI(array('ui.slider', 'ui.datepicker')); - - Media::addJsDef(array('host_mode' => (defined('_PS_HOST_MODE_') && _PS_HOST_MODE_))); - - $this->addJS(array( - _PS_JS_DIR_.'admin.js', - _PS_JS_DIR_.'tools.js', - _PS_JS_DIR_.'jquery/plugins/timepicker/jquery-ui-timepicker-addon.js' - )); - - //loads specific javascripts for the admin theme - $this->addJS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/vendor/bootstrap.min.js'); - $this->addJS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/vendor/modernizr.min.js'); - $this->addJS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/modernizr-loads.js'); - $this->addJS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/vendor/moment-with-langs.min.js'); - - if (!$this->lite_display) - $this->addJS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/help.js'); - - if (!Tools::getValue('submitFormAjax')) - $this->addJS(_PS_JS_DIR_.'admin/notifications.js'); - - if (defined('_PS_HOST_MODE_') && _PS_HOST_MODE_) - { - $this->addJS('https://cdn.statuspage.io/se-v2.js'); - - Media::addJsDefL('status_operational', $this->l('Operational')); - Media::addJsDefL('status_degraded_performance', $this->l('Degraded Performance')); - Media::addJsDefL('status_partial_outage', $this->l('Partial Outage')); - Media::addJsDefL('status_major_outage', $this->l('Major Outage')); - Media::addJsDef(array('host_cluster' => defined('_PS_HOST_CLUSTER_') ? _PS_HOST_CLUSTER_ : 'fr1')); - } - - // Execute Hook AdminController SetMedia - Hook::exec('actionAdminControllerSetMedia'); - - // Specific Admin Theme - $this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/overrides.css', 'all', PHP_INT_MAX); - } - - /** - * Non-static method which uses AdminController::translate() - * - * @param string $string Term or expression in english - * @param string|null $class Name of the class - * @param bool $addslashes If set to true, the return value will pass through addslashes(). Otherwise, stripslashes(). - * @param bool $htmlentities If set to true(default), the return value will pass through htmlentities($string, ENT_QUOTES, 'utf-8') - * @return string The translation if available, or the english default text. - */ - protected function l($string, $class = null, $addslashes = false, $htmlentities = true) - { - if ($class === null || $class == 'AdminTab') - $class = substr(get_class($this), 0, -10); - // classname has changed, from AdminXXX to AdminXXXController, so we remove 10 characters and we keep same keys - elseif (strtolower(substr($class, -10)) == 'controller') - $class = substr($class, 0, -10); - return Translate::getAdminTranslation($string, $class, $addslashes, $htmlentities); - } - - /** - * Init context and dependencies, handles POST and GET - */ - public function init() - { - // Has to be removed for the next Prestashop version - global $currentIndex; - - parent::init(); - - if (Tools::getValue('ajax')) - $this->ajax = '1'; - - /* Server Params */ - $protocol_link = (Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) ? 'https://' : 'http://'; - $protocol_content = (Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) ? 'https://' : 'http://'; - - $this->context->link = new Link($protocol_link, $protocol_content); - - if (isset($_GET['logout'])) - $this->context->employee->logout(); - - if (isset(Context::getContext()->cookie->last_activity)) - { - if ($this->context->cookie->last_activity + 900 < time()) - $this->context->employee->logout(); - else - $this->context->cookie->last_activity = time(); - } - - if ($this->controller_name != 'AdminLogin' && (!isset($this->context->employee) || !$this->context->employee->isLoggedBack())) - { - if (isset($this->context->employee)) - $this->context->employee->logout(); - - $email = false; - if (Tools::getValue('email') && Validate::isEmail(Tools::getValue('email'))) - $email = Tools::getValue('email'); - - Tools::redirectAdmin($this->context->link->getAdminLink('AdminLogin').((!isset($_GET['logout']) && $this->controller_name != 'AdminNotFound' && Tools::getValue('controller')) ? '&redirect='.$this->controller_name : '').($email ? '&email='.$email : '')); - } - - // Set current index - $current_index = 'index.php'.(($controller = Tools::getValue('controller')) ? '?controller='.$controller : ''); - if ($back = Tools::getValue('back')) - $current_index .= '&back='.urlencode($back); - self::$currentIndex = $current_index; - $currentIndex = $current_index; - - if ((int)Tools::getValue('liteDisplaying')) - { - $this->display_header = false; - $this->display_header_javascript = true; - $this->display_footer = false; - $this->content_only = false; - $this->lite_display = true; - } - - if ($this->ajax && method_exists($this, 'ajaxPreprocess')) - $this->ajaxPreProcess(); - - $this->context->smarty->assign(array( - 'table' => $this->table, - 'current' => self::$currentIndex, - 'token' => $this->token, - 'host_mode' => defined('_PS_HOST_MODE_') ? 1 : 0, - 'stock_management' => (int)Configuration::get('PS_STOCK_MANAGEMENT') - )); - - if ($this->display_header) - $this->context->smarty->assign('displayBackOfficeHeader', Hook::exec('displayBackOfficeHeader', array())); - - $this->context->smarty->assign(array( - 'displayBackOfficeTop' => Hook::exec('displayBackOfficeTop', array()), - 'submit_form_ajax' => (int)Tools::getValue('submitFormAjax') - )); - - Employee::setLastConnectionDate($this->context->employee->id); - - $this->initProcess(); - $this->initBreadcrumbs(); - $this->initModal(); - } - - /** - * @throws PrestaShopException - */ - public function initShopContext() - { - if (!$this->context->employee->isLoggedBack()) - return; - - // Change shop context ? - if (Shop::isFeatureActive() && Tools::getValue('setShopContext') !== false) - { - $this->context->cookie->shopContext = Tools::getValue('setShopContext'); - $url = parse_url($_SERVER['REQUEST_URI']); - $query = (isset($url['query'])) ? $url['query'] : ''; - parse_str($query, $parse_query); - unset($parse_query['setShopContext'], $parse_query['conf']); - $this->redirect_after = $url['path'].'?'.http_build_query($parse_query, '', '&'); - } - elseif (!Shop::isFeatureActive()) - $this->context->cookie->shopContext = 's-'.(int)Configuration::get('PS_SHOP_DEFAULT'); - elseif (Shop::getTotalShops(false, null) < 2) - $this->context->cookie->shopContext = 's-'.(int)$this->context->employee->getDefaultShopID(); - - $shop_id = ''; - Shop::setContext(Shop::CONTEXT_ALL); - if ($this->context->cookie->shopContext) - { - $split = explode('-', $this->context->cookie->shopContext); - if (count($split) == 2) - { - if ($split[0] == 'g') - { - if ($this->context->employee->hasAuthOnShopGroup((int)$split[1])) - Shop::setContext(Shop::CONTEXT_GROUP, (int)$split[1]); - else - { - $shop_id = (int)$this->context->employee->getDefaultShopID(); - Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); - } - } - elseif (Shop::getShop($split[1]) && $this->context->employee->hasAuthOnShop($split[1])) - { - $shop_id = (int)$split[1]; - Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); - } - else - { - $shop_id = (int)$this->context->employee->getDefaultShopID(); - Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); - } - } - } - - // Check multishop context and set right context if need - if (!($this->multishop_context & Shop::getContext())) - { - if (Shop::getContext() == Shop::CONTEXT_SHOP && !($this->multishop_context & Shop::CONTEXT_SHOP)) - Shop::setContext(Shop::CONTEXT_GROUP, Shop::getContextShopGroupID()); - if (Shop::getContext() == Shop::CONTEXT_GROUP && !($this->multishop_context & Shop::CONTEXT_GROUP)) - Shop::setContext(Shop::CONTEXT_ALL); - } - - // Replace existing shop if necessary - if (!$shop_id) - $this->context->shop = new Shop((int)Configuration::get('PS_SHOP_DEFAULT')); - elseif ($this->context->shop->id != $shop_id) - $this->context->shop = new Shop((int)$shop_id); - - if ($this->context->shop->id_theme != $this->context->theme->id) - $this->context->theme = new Theme((int)$this->context->shop->id_theme); - - // Replace current default country - $this->context->country = new Country((int)Configuration::get('PS_COUNTRY_DEFAULT')); - } - - /** - * Retrieve GET and POST value and translate them to actions - */ - public function initProcess() - { - if (!isset($this->list_id)) - $this->list_id = $this->table; - - // Manage list filtering - if (Tools::isSubmit('submitFilter'.$this->list_id) - || $this->context->cookie->{'submitFilter'.$this->list_id} !== false - || Tools::getValue($this->list_id.'Orderby') - || Tools::getValue($this->list_id.'Orderway')) - $this->filter = true; - - $this->id_object = (int)Tools::getValue($this->identifier); - - /* Delete object image */ - if (isset($_GET['deleteImage'])) - { - if ($this->tabAccess['delete'] === '1') - $this->action = 'delete_image'; - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - /* Delete object */ - elseif (isset($_GET['delete'.$this->table])) - { - if ($this->tabAccess['delete'] === '1') - $this->action = 'delete'; - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - /* Change object statuts (active, inactive) */ - elseif ((isset($_GET['status'.$this->table]) || isset($_GET['status'])) && Tools::getValue($this->identifier)) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'status'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - /* Move an object */ - elseif (isset($_GET['position'])) - { - if ($this->tabAccess['edit'] == '1') - $this->action = 'position'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('submitAdd'.$this->table) - || Tools::isSubmit('submitAdd'.$this->table.'AndStay') - || Tools::isSubmit('submitAdd'.$this->table.'AndPreview') - || Tools::isSubmit('submitAdd'.$this->table.'AndBackToParent')) - { - // case 1: updating existing entry - if ($this->id_object) - { - if ($this->tabAccess['edit'] === '1') - { - $this->action = 'save'; - if (Tools::isSubmit('submitAdd'.$this->table.'AndStay')) - $this->display = 'edit'; - else - $this->display = 'list'; - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - // case 2: creating new entry - else - { - if ($this->tabAccess['add'] === '1') - { - $this->action = 'save'; - if (Tools::isSubmit('submitAdd'.$this->table.'AndStay')) - $this->display = 'edit'; - else - $this->display = 'list'; - } - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - } - elseif (isset($_GET['add'.$this->table])) - { - if ($this->tabAccess['add'] === '1') - { - $this->action = 'new'; - $this->display = 'add'; - } - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - elseif (isset($_GET['update'.$this->table]) && isset($_GET[$this->identifier])) - { - $this->display = 'edit'; - if ($this->tabAccess['edit'] !== '1') - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (isset($_GET['view'.$this->table])) - { - if ($this->tabAccess['view'] === '1') - { - $this->display = 'view'; - $this->action = 'view'; - } - else - $this->errors[] = Tools::displayError('You do not have permission to view this.'); - } - elseif (isset($_GET['details'.$this->table])) - { - if ($this->tabAccess['view'] === '1') - { - $this->display = 'details'; - $this->action = 'details'; - } - else - $this->errors[] = Tools::displayError('You do not have permission to view this.'); - } - elseif (isset($_GET['export'.$this->table])) - { - if ($this->tabAccess['view'] === '1') - $this->action = 'export'; - } - /* Cancel all filters for this tab */ - elseif (isset($_POST['submitReset'.$this->list_id])) - $this->action = 'reset_filters'; - /* Submit options list */ - elseif (Tools::isSubmit('submitOptions'.$this->table) || Tools::isSubmit('submitOptions')) - { - $this->display = 'options'; - if ($this->tabAccess['edit'] === '1') - $this->action = 'update_options'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::getValue('action') && method_exists($this, 'process'.ucfirst(Tools::toCamelCase(Tools::getValue('action'))))) - $this->action = Tools::getValue('action'); - elseif (Tools::isSubmit('submitFields') && $this->required_database && $this->tabAccess['add'] === '1' && $this->tabAccess['delete'] === '1') - $this->action = 'update_fields'; - elseif (is_array($this->bulk_actions)) - { - $submit_bulk_actions = array_merge(array( - 'enableSelection' => array( - 'text' => $this->l('Enable selection'), - 'icon' => 'icon-power-off text-success' - ), - 'disableSelection' => array( - 'text' => $this->l('Disable selection'), - 'icon' => 'icon-power-off text-danger' - ) - ), $this->bulk_actions); - foreach ($submit_bulk_actions as $bulk_action => $params) - { - if (Tools::isSubmit('submitBulk'.$bulk_action.$this->table) || Tools::isSubmit('submitBulk'.$bulk_action)) - { - if ($bulk_action === 'delete') - { - if ($this->tabAccess['delete'] === '1') - { - $this->action = 'bulk'.$bulk_action; - $this->boxes = Tools::getValue($this->table.'Box'); - if (empty($this->boxes) && $this->table == 'attribute') - $this->boxes = Tools::getValue($this->table.'_valuesBox'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - break; - } - elseif ($this->tabAccess['edit'] === '1') - { - $this->action = 'bulk'.$bulk_action; - $this->boxes = Tools::getValue($this->table.'Box'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - break; - } - elseif (Tools::isSubmit('submitBulk')) - { - if ($bulk_action === 'delete') - { - if ($this->tabAccess['delete'] === '1') - { - $this->action = 'bulk'.$bulk_action; - $this->boxes = Tools::getValue($this->table.'Box'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - break; - } - elseif ($this->tabAccess['edit'] === '1') - { - $this->action = 'bulk'.Tools::getValue('select_submitBulk'); - $this->boxes = Tools::getValue($this->table.'Box'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - break; - } - } - } - elseif (!empty($this->fields_options) && empty($this->fields_list)) - $this->display = 'options'; - } - - /** - * Get the current objects' list form the database - * - * @param int $id_lang Language used for display - * @param string|null $order_by ORDER BY clause - * @param string|null $order_way Order way (ASC, DESC) - * @param int $start Offset in LIMIT clause - * @param int|null $limit Row count in LIMIT clause - * @param int|bool $id_lang_shop - * @throws PrestaShopDatabaseException - * @throws PrestaShopException - */ - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - Hook::exec('action'.$this->controller_name.'ListingFieldsModifier', array( - 'select' => &$this->_select, - 'join' => &$this->_join, - 'where' => &$this->_where, - 'group_by' => &$this->_group, - 'order_by' => &$this->_orderBy, - 'order_way' => &$this->_orderWay, - 'fields' => &$this->fields_list, - )); - - if (!isset($this->list_id)) - $this->list_id = $this->table; - - /* Manage default params values */ - $use_limit = true; - if ($limit === false) - $use_limit = false; - elseif (empty($limit)) - { - if (isset($this->context->cookie->{$this->list_id.'_pagination'}) && $this->context->cookie->{$this->list_id.'_pagination'}) - $limit = $this->context->cookie->{$this->list_id.'_pagination'}; - else - $limit = $this->_default_pagination; - } - - if (!Validate::isTableOrIdentifier($this->table)) - throw new PrestaShopException(sprintf('Table name %s is invalid:', $this->table)); - $prefix = str_replace(array('admin', 'controller'), '', Tools::strtolower(get_class($this))); - if (empty($order_by)) - { - if ($this->context->cookie->{$prefix.$this->list_id.'Orderby'}) - $order_by = $this->context->cookie->{$prefix.$this->list_id.'Orderby'}; - elseif ($this->_orderBy) - $order_by = $this->_orderBy; - else - $order_by = $this->_defaultOrderBy; - } - - if (empty($order_way)) - { - if ($this->context->cookie->{$prefix.$this->list_id.'Orderway'}) - $order_way = $this->context->cookie->{$prefix.$this->list_id.'Orderway'}; - elseif ($this->_orderWay) - $order_way = $this->_orderWay; - else - $order_way = $this->_defaultOrderWay; - } - - $limit = (int)Tools::getValue($this->list_id.'_pagination', $limit); - if (in_array($limit, $this->_pagination) && $limit != $this->_default_pagination) - $this->context->cookie->{$this->list_id.'_pagination'} = $limit; - else - unset($this->context->cookie->{$this->list_id.'_pagination'}); - - /* Check params validity */ - if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way) - || !is_numeric($start) || !is_numeric($limit) - || !Validate::isUnsignedId($id_lang)) - throw new PrestaShopException('get list params is not valid'); - - if (!isset($this->fields_list[$order_by]['order_key']) && isset($this->fields_list[$order_by]['filter_key'])) - $this->fields_list[$order_by]['order_key'] = $this->fields_list[$order_by]['filter_key']; - - if (isset($this->fields_list[$order_by]) && isset($this->fields_list[$order_by]['order_key'])) - $order_by = $this->fields_list[$order_by]['order_key']; - - /* Determine offset from current page */ - $start = 0; - if ((int)Tools::getValue('submitFilter'.$this->list_id)) - $start = ((int)Tools::getValue('submitFilter'.$this->list_id) - 1) * $limit; - elseif (empty($start) && isset($this->context->cookie->{$this->list_id.'_start'}) && Tools::isSubmit('export'.$this->table)) - $start = $this->context->cookie->{$this->list_id.'_start'}; - - // Either save or reset the offset in the cookie - if ($start) - $this->context->cookie->{$this->list_id.'_start'} = $start; - elseif (isset($this->context->cookie->{$this->list_id.'_start'})) - unset($this->context->cookie->{$this->list_id.'_start'}); - - /* Cache */ - $this->_lang = (int)$id_lang; - $this->_orderBy = $order_by; - - if (preg_match('/[.!]/', $order_by)) - { - $order_by_split = preg_split('/[.!]/', $order_by); - $order_by = bqSQL($order_by_split[0]).'.`'.bqSQL($order_by_split[1]).'`'; - } - elseif ($order_by) - $order_by = '`'.bqSQL($order_by).'`'; - - $this->_orderWay = Tools::strtoupper($order_way); - - /* SQL table : orders, but class name is Order */ - $sql_table = $this->table == 'order' ? 'orders' : $this->table; - - // Add SQL shop restriction - $select_shop = $join_shop = $where_shop = ''; - if ($this->shopLinkType) - { - $select_shop = ', shop.name as shop_name '; - $join_shop = ' LEFT JOIN '._DB_PREFIX_.$this->shopLinkType.' shop + /** @var bool if logged employee has access to AdminImport */ + protected $can_import = false; + + public function __construct() + { + global $timer_start; + $this->timer_start = $timer_start; + // Has to be remove for the next Prestashop version + global $token; + + $this->controller_type = 'admin'; + $this->controller_name = get_class($this); + if (strpos($this->controller_name, 'Controller')) { + $this->controller_name = substr($this->controller_name, 0, -10); + } + parent::__construct(); + + if ($this->multishop_context == -1) { + $this->multishop_context = Shop::CONTEXT_ALL | Shop::CONTEXT_GROUP | Shop::CONTEXT_SHOP; + } + + $default_theme_name = 'default'; + + if (defined('_PS_BO_DEFAULT_THEME_') && _PS_BO_DEFAULT_THEME_ + && @filemtime(_PS_BO_ALL_THEMES_DIR_._PS_BO_DEFAULT_THEME_.DIRECTORY_SEPARATOR.'template')) { + $default_theme_name = _PS_BO_DEFAULT_THEME_; + } + + $this->bo_theme = ((Validate::isLoadedObject($this->context->employee) + && $this->context->employee->bo_theme) ? $this->context->employee->bo_theme : $default_theme_name); + + if (!@filemtime(_PS_BO_ALL_THEMES_DIR_.$this->bo_theme.DIRECTORY_SEPARATOR.'template')) { + $this->bo_theme = $default_theme_name; + } + + $this->bo_css = ((Validate::isLoadedObject($this->context->employee) + && $this->context->employee->bo_css) ? $this->context->employee->bo_css : 'admin-theme.css'); + + if (!@filemtime(_PS_BO_ALL_THEMES_DIR_.$this->bo_theme.DIRECTORY_SEPARATOR.'css'.DIRECTORY_SEPARATOR.$this->bo_css)) { + $this->bo_css = 'admin-theme.css'; + } + + $this->context->smarty->setTemplateDir(array( + _PS_BO_ALL_THEMES_DIR_.$this->bo_theme.DIRECTORY_SEPARATOR.'template', + _PS_OVERRIDE_DIR_.'controllers'.DIRECTORY_SEPARATOR.'admin'.DIRECTORY_SEPARATOR.'templates' + )); + + $this->id = Tab::getIdFromClassName($this->controller_name); + $this->token = Tools::getAdminToken($this->controller_name.(int)$this->id.(int)$this->context->employee->id); + + $token = $this->token; + + $this->_conf = array( + 1 => $this->l('Successful deletion'), + 2 => $this->l('The selection has been successfully deleted.'), + 3 => $this->l('Successful creation'), + 4 => $this->l('Successful update'), + 5 => $this->l('The status has been successfully updated.'), + 6 => $this->l('The settings have been successfully updated.'), + 7 => $this->l('The image was successfully deleted.'), + 8 => $this->l('The module was successfully downloaded.'), + 9 => $this->l('The thumbnails were successfully regenerated.'), + 10 => $this->l('The message was successfully sent to the customer.'), + 11 => $this->l('Comment successfully added'), + 12 => $this->l('Module(s) installed successfully.'), + 13 => $this->l('Module(s) uninstalled successfully.'), + 14 => $this->l('The translation was successfully copied.'), + 15 => $this->l('The translations have been successfully added.'), + 16 => $this->l('The module transplanted successfully to the hook.'), + 17 => $this->l('The module was successfully removed from the hook.'), + 18 => $this->l('Successful upload'), + 19 => $this->l('Duplication was completed successfully.'), + 20 => $this->l('The translation was added successfully, but the language has not been created.'), + 21 => $this->l('Module reset successfully.'), + 22 => $this->l('Module deleted successfully.'), + 23 => $this->l('Localization pack imported successfully.'), + 24 => $this->l('Localization pack imported successfully.'), + 25 => $this->l('The selected images have successfully been moved.'), + 26 => $this->l('Your cover image selection has been saved.'), + 27 => $this->l('The image\'s shop association has been modified.'), + 28 => $this->l('A zone has been assigned to the selection successfully.'), + 29 => $this->l('Successful upgrade'), + 30 => $this->l('A partial refund was successfully created.'), + 31 => $this->l('The discount was successfully generated.'), + 32 => $this->l('Successfully signed in to PrestaShop Addons') + ); + + if (!$this->identifier) { + $this->identifier = 'id_'.$this->table; + } + if (!$this->_defaultOrderBy) { + $this->_defaultOrderBy = $this->identifier; + } + $this->tabAccess = Profile::getProfileAccess($this->context->employee->id_profile, $this->id); + + // Fix for homepage + if ($this->controller_name == 'AdminDashboard') { + $_POST['token'] = $this->token; + } + + if (!Shop::isFeatureActive()) { + $this->shopLinkType = ''; + } + + //$this->base_template_folder = _PS_BO_ALL_THEMES_DIR_.$this->bo_theme.'/template'; + $this->override_folder = Tools::toUnderscoreCase(substr($this->controller_name, 5)).'/'; + // Get the name of the folder containing the custom tpl files + $this->tpl_folder = Tools::toUnderscoreCase(substr($this->controller_name, 5)).'/'; + + $this->initShopContext(); + + $this->context->currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); + + $this->admin_webpath = str_ireplace(_PS_CORE_DIR_, '', _PS_ADMIN_DIR_); + $this->admin_webpath = preg_replace('/^'.preg_quote(DIRECTORY_SEPARATOR, '/').'/', '', $this->admin_webpath); + + // Check if logged on Addons + $this->logged_on_addons = false; + if (isset($this->context->cookie->username_addons) && isset($this->context->cookie->password_addons) && !empty($this->context->cookie->username_addons) && !empty($this->context->cookie->password_addons)) { + $this->logged_on_addons = true; + } + + // Set context mode + if (defined('_PS_HOST_MODE_') && _PS_HOST_MODE_) { + if (isset($this->context->cookie->is_contributor) && (int)$this->context->cookie->is_contributor === 1) { + $this->context->mode = Context::MODE_HOST_CONTRIB; + } else { + $this->context->mode = Context::MODE_HOST; + } + } elseif (isset($this->context->cookie->is_contributor) && (int)$this->context->cookie->is_contributor === 1) { + $this->context->mode = Context::MODE_STD_CONTRIB; + } else { + $this->context->mode = Context::MODE_STD; + } + + //* Check if logged employee has access to AdminImport controller */ + $import_access = Profile::getProfileAccess($this->context->employee->id_profile, Tab::getIdFromClassName('AdminImport')); + if (is_array($import_access) && isset($import_access['view']) && $import_access['view'] == 1) { + $this->can_import = true; + } + + $this->context->smarty->assign(array( + 'context_mode' => $this->context->mode, + 'logged_on_addons' => $this->logged_on_addons, + 'can_import' => $this->can_import, + )); + } + + /** + * Set breadcrumbs array for the controller page + * + * @param int|null $tab_id + * @param array|null $tabs + */ + public function initBreadcrumbs($tab_id = null, $tabs = null) + { + if (is_array($tabs) || count($tabs)) { + $tabs = array(); + } + + if (is_null($tab_id)) { + $tab_id = $this->id; + } + + $tabs = Tab::recursiveTab($tab_id, $tabs); + + $dummy = array('name' => '', 'href' => '', 'icon' => ''); + $breadcrumbs2 = array( + 'container' => $dummy, + 'tab' => $dummy, + 'action' => $dummy + ); + if (isset($tabs[0])) { + $this->addMetaTitle($tabs[0]['name']); + $breadcrumbs2['tab']['name'] = $tabs[0]['name']; + $breadcrumbs2['tab']['href'] = __PS_BASE_URI__.basename(_PS_ADMIN_DIR_).'/'.$this->context->link->getAdminLink($tabs[0]['class_name']); + if (!isset($tabs[1])) { + $breadcrumbs2['tab']['icon'] = 'icon-'.$tabs[0]['class_name']; + } + } + if (isset($tabs[1])) { + $breadcrumbs2['container']['name'] = $tabs[1]['name']; + $breadcrumbs2['container']['href'] = __PS_BASE_URI__.basename(_PS_ADMIN_DIR_).'/'.$this->context->link->getAdminLink($tabs[1]['class_name']); + $breadcrumbs2['container']['icon'] = 'icon-'.$tabs[1]['class_name']; + } + + /* content, edit, list, add, details, options, view */ + switch ($this->display) { + case 'add': + $breadcrumbs2['action']['name'] = $this->l('Add', null, null, false); + $breadcrumbs2['action']['icon'] = 'icon-plus'; + break; + case 'edit': + $breadcrumbs2['action']['name'] = $this->l('Edit', null, null, false); + $breadcrumbs2['action']['icon'] = 'icon-pencil'; + break; + case '': + case 'list': + $breadcrumbs2['action']['name'] = $this->l('List', null, null, false); + $breadcrumbs2['action']['icon'] = 'icon-th-list'; + break; + case 'details': + case 'view': + $breadcrumbs2['action']['name'] = $this->l('View details', null, null, false); + $breadcrumbs2['action']['icon'] = 'icon-zoom-in'; + break; + case 'options': + $breadcrumbs2['action']['name'] = $this->l('Options', null, null, false); + $breadcrumbs2['action']['icon'] = 'icon-cogs'; + break; + case 'generator': + $breadcrumbs2['action']['name'] = $this->l('Generator', null, null, false); + $breadcrumbs2['action']['icon'] = 'icon-flask'; + break; + } + + $this->context->smarty->assign(array( + 'breadcrumbs2' => $breadcrumbs2, + 'quick_access_current_link_name' => $breadcrumbs2['tab']['name'].(isset($breadcrumbs2['action']) ? ' - '.$breadcrumbs2['action']['name'] : ''), + 'quick_access_current_link_icon' => $breadcrumbs2['container']['icon'] + )); + + /* BEGIN - Backward compatibility < 1.6.0.3 */ + $this->breadcrumbs[] = $tabs[0]['name']; + $navigation_pipe = (Configuration::get('PS_NAVIGATION_PIPE') ? Configuration::get('PS_NAVIGATION_PIPE') : '>'); + $this->context->smarty->assign('navigationPipe', $navigation_pipe); + /* END - Backward compatibility < 1.6.0.3 */ + } + + /** + * Set default toolbar_title to admin breadcrumb + * + * @return void + */ + public function initToolbarTitle() + { + $this->toolbar_title = is_array($this->breadcrumbs) ? array_unique($this->breadcrumbs) : array($this->breadcrumbs); + + switch ($this->display) { + case 'edit': + $this->toolbar_title[] = $this->l('Edit', null, null, false); + $this->addMetaTitle($this->l('Edit', null, null, false)); + break; + + case 'add': + $this->toolbar_title[] = $this->l('Add new', null, null, false); + $this->addMetaTitle($this->l('Add new', null, null, false)); + break; + + case 'view': + $this->toolbar_title[] = $this->l('View', null, null, false); + $this->addMetaTitle($this->l('View', null, null, false)); + break; + } + + if ($filter = $this->addFiltersToBreadcrumbs()) { + $this->toolbar_title[] = Tools::htmlentitiesDecodeUTF8($filter); + } + } + + /** + * @return string|void + */ + public function addFiltersToBreadcrumbs() + { + if ($this->filter && is_array($this->fields_list)) { + $filters = array(); + + foreach ($this->fields_list as $field => $t) { + if (isset($t['filter_key'])) { + $field = $t['filter_key']; + } + if ($val = Tools::getValue($this->table.'Filter_'.$field)) { + if (!is_array($val)) { + $filter_value = ''; + if (isset($t['type']) && $t['type'] == 'bool') { + $filter_value = ((bool)$val) ? $this->l('yes') : $this->l('no'); + } elseif (is_string($val)) { + $filter_value = htmlspecialchars($val, ENT_QUOTES, 'UTF-8'); + } + if (!empty($filter_value)) { + $filters[] = sprintf($this->l('%s: %s'), $t['title'], $filter_value); + } + } else { + $filter_value = ''; + foreach ($val as $v) { + if (is_string($v) && !empty($v)) { + $filter_value .= ' - '.htmlspecialchars($v, ENT_QUOTES, 'UTF-8'); + } + } + $filter_value = ltrim($filter_value, ' -'); + if (!empty($filter_value)) { + $filters[] = sprintf($this->l('%s: %s'), $t['title'], $filter_value); + } + } + } + } + + if (count($filters)) { + return sprintf($this->l('filter by %s'), implode(', ', $filters)); + } + } + } + + /** + * Check rights to view the current tab + * + * @param bool $disable + * @return bool + */ + public function viewAccess($disable = false) + { + if ($disable) { + return true; + } + + if ($this->tabAccess['view'] === '1') { + return true; + } + return false; + } + + /** + * Check for security token + * + * @return bool + */ + public function checkToken() + { + $token = Tools::getValue('token'); + if (!empty($token) && $token === $this->token) { + return true; + } + + if (count($_POST) || !isset($_GET['controller']) || !Validate::isControllerName($_GET['controller']) || $token) { + return false; + } + + foreach ($_GET as $key => $value) { + if (is_array($value) || !in_array($key, array('controller', 'controllerUri'))) { + return false; + } + } + + $cookie = Context::getContext()->cookie; + $whitelist = array('date_add', 'id_lang', 'id_employee', 'email', 'profile', 'passwd', 'remote_addr', 'shopContext', 'collapse_menu', 'checksum'); + foreach ($cookie->getAll() as $key => $value) { + if (!in_array($key, $whitelist)) { + unset($cookie->$key); + } + } + + $cookie->write(); + + return true; + } + + /** + * Set the filters used for the list display + */ + public function processFilter() + { + Hook::exec('action'.$this->controller_name.'ListingFieldsModifier', array( + 'fields' => &$this->fields_list, + )); + + if (!isset($this->list_id)) { + $this->list_id = $this->table; + } + + $prefix = str_replace(array('admin', 'controller'), '', Tools::strtolower(get_class($this))); + + if (isset($this->list_id)) { + foreach ($_POST as $key => $value) { + if ($value === '') { + unset($this->context->cookie->{$prefix.$key}); + } elseif (stripos($key, $this->list_id.'Filter_') === 0) { + $this->context->cookie->{$prefix.$key} = !is_array($value) ? $value : serialize($value); + } elseif (stripos($key, 'submitFilter') === 0) { + $this->context->cookie->$key = !is_array($value) ? $value : serialize($value); + } + } + + foreach ($_GET as $key => $value) { + if (stripos($key, $this->list_id.'Filter_') === 0) { + $this->context->cookie->{$prefix.$key} = !is_array($value) ? $value : serialize($value); + } elseif (stripos($key, 'submitFilter') === 0) { + $this->context->cookie->$key = !is_array($value) ? $value : serialize($value); + } + if (stripos($key, $this->list_id.'Orderby') === 0 && Validate::isOrderBy($value)) { + if ($value === '' || $value == $this->_defaultOrderBy) { + unset($this->context->cookie->{$prefix.$key}); + } else { + $this->context->cookie->{$prefix.$key} = $value; + } + } elseif (stripos($key, $this->list_id.'Orderway') === 0 && Validate::isOrderWay($value)) { + if ($value === '' || $value == $this->_defaultOrderWay) { + unset($this->context->cookie->{$prefix.$key}); + } else { + $this->context->cookie->{$prefix.$key} = $value; + } + } + } + } + + $filters = $this->context->cookie->getFamily($prefix.$this->list_id.'Filter_'); + $definition = ObjectModel::getDefinition($this->className); + + foreach ($filters as $key => $value) { + /* Extracting filters from $_POST on key filter_ */ + if ($value != null && !strncmp($key, $prefix.$this->list_id.'Filter_', 7 + Tools::strlen($prefix.$this->list_id))) { + $key = Tools::substr($key, 7 + Tools::strlen($prefix.$this->list_id)); + /* Table alias could be specified using a ! eg. alias!field */ + $tmp_tab = explode('!', $key); + $filter = count($tmp_tab) > 1 ? $tmp_tab[1] : $tmp_tab[0]; + + if ($field = $this->filterToField($key, $filter)) { + $type = (array_key_exists('filter_type', $field) ? $field['filter_type'] : (array_key_exists('type', $field) ? $field['type'] : false)); + if (($type == 'date' || $type == 'datetime') && is_string($value)) { + $value = Tools::unSerialize($value); + } + $key = isset($tmp_tab[1]) ? $tmp_tab[0].'.`'.$tmp_tab[1].'`' : '`'.$tmp_tab[0].'`'; + + // Assignment by reference + if (array_key_exists('tmpTableFilter', $field)) { + $sql_filter = & $this->_tmpTableFilter; + } elseif (array_key_exists('havingFilter', $field)) { + $sql_filter = & $this->_filterHaving; + } else { + $sql_filter = & $this->_filter; + } + + /* Only for date filtering (from, to) */ + if (is_array($value)) { + if (isset($value[0]) && !empty($value[0])) { + if (!Validate::isDate($value[0])) { + $this->errors[] = Tools::displayError('The \'From\' date format is invalid (YYYY-MM-DD)'); + } else { + $sql_filter .= ' AND '.pSQL($key).' >= \''.pSQL(Tools::dateFrom($value[0])).'\''; + } + } + + if (isset($value[1]) && !empty($value[1])) { + if (!Validate::isDate($value[1])) { + $this->errors[] = Tools::displayError('The \'To\' date format is invalid (YYYY-MM-DD)'); + } else { + $sql_filter .= ' AND '.pSQL($key).' <= \''.pSQL(Tools::dateTo($value[1])).'\''; + } + } + } else { + $sql_filter .= ' AND '; + $check_key = ($key == $this->identifier || $key == '`'.$this->identifier.'`'); + $alias = ($definition && !empty($definition['fields'][$filter]['shop'])) ? 'sa' : 'a'; + + if ($type == 'int' || $type == 'bool') { + $sql_filter .= (($check_key || $key == '`active`') ? $alias.'.' : '').pSQL($key).' = '.(int)$value.' '; + } elseif ($type == 'decimal') { + $sql_filter .= ($check_key ? $alias.'.' : '').pSQL($key).' = '.(float)$value.' '; + } elseif ($type == 'select') { + $sql_filter .= ($check_key ? $alias.'.' : '').pSQL($key).' = \''.pSQL($value).'\' '; + } elseif ($type == 'price') { + $value = (float)str_replace(',', '.', $value); + $sql_filter .= ($check_key ? $alias.'.' : '').pSQL($key).' = '.pSQL(trim($value)).' '; + } else { + + $sql_filter .= ($check_key ? $alias.'.' : '').pSQL($key).' LIKE \'%'.pSQL(trim($value)).'%\' '; + } + } + } + } + } + } + + /** + * @TODO uses redirectAdmin only if !$this->ajax + * @return bool + */ + public function postProcess() + { + try { + if ($this->ajax) { + // from ajax-tab.php + $action = Tools::getValue('action'); + // no need to use displayConf() here + if (!empty($action) && method_exists($this, 'ajaxProcess'.Tools::toCamelCase($action))) { + Hook::exec('actionAdmin'.ucfirst($this->action).'Before', array('controller' => $this)); + Hook::exec('action'.get_class($this).ucfirst($this->action).'Before', array('controller' => $this)); + + $return = $this->{'ajaxProcess'.Tools::toCamelCase($action)}(); + + Hook::exec('actionAdmin'.ucfirst($this->action).'After', array('controller' => $this, 'return' => $return)); + Hook::exec('action'.get_class($this).ucfirst($this->action).'After', array('controller' => $this, 'return' => $return)); + + return $return; + } elseif (!empty($action) && $this->controller_name == 'AdminModules' && Tools::getIsset('configure')) { + $module_obj = Module::getInstanceByName(Tools::getValue('configure')); + if (Validate::isLoadedObject($module_obj) && method_exists($module_obj, 'ajaxProcess'.$action)) { + return $module_obj->{'ajaxProcess'.$action}(); + } + } elseif (method_exists($this, 'ajaxProcess')) { + return $this->ajaxProcess(); + } + } else { + // Process list filtering + if ($this->filter && $this->action != 'reset_filters') { + $this->processFilter(); + } + + // If the method named after the action exists, call "before" hooks, then call action method, then call "after" hooks + if (!empty($this->action) && method_exists($this, 'process'.ucfirst(Tools::toCamelCase($this->action)))) { + // Hook before action + Hook::exec('actionAdmin'.ucfirst($this->action).'Before', array('controller' => $this)); + Hook::exec('action'.get_class($this).ucfirst($this->action).'Before', array('controller' => $this)); + // Call process + $return = $this->{'process'.Tools::toCamelCase($this->action)}(); + // Hook After Action + Hook::exec('actionAdmin'.ucfirst($this->action).'After', array('controller' => $this, 'return' => $return)); + Hook::exec('action'.get_class($this).ucfirst($this->action).'After', array('controller' => $this, 'return' => $return)); + return $return; + } + } + } catch (PrestaShopException $e) { + $this->errors[] = $e->getMessage(); + }; + return false; + } + + /** + * Object Delete images + * + * @return ObjectModel|false + */ + public function processDeleteImage() + { + if (Validate::isLoadedObject($object = $this->loadObject())) { + if (($object->deleteImage())) { + $redirect = self::$currentIndex.'&add'.$this->table.'&'.$this->identifier.'='.Tools::getValue($this->identifier).'&conf=7&token='.$this->token; + if (!$this->ajax) { + $this->redirect_after = $redirect; + } else { + $this->content = 'ok'; + } + } + } + $this->errors[] = Tools::displayError('An error occurred while attempting to delete the image. (cannot load object).'); + return $object; + } + + /** + * @param string $text_delimiter + * @throws PrestaShopException + */ + public function processExport($text_delimiter = '"') + { + // clean buffer + if (ob_get_level() && ob_get_length() > 0) { + ob_clean(); + } + $this->getList($this->context->language->id, null, null, 0, false); + if (!count($this->_list)) { + return; + } + + header('Content-type: text/csv'); + header('Content-Type: application/force-download; charset=UTF-8'); + header('Cache-Control: no-store, no-cache'); + header('Content-disposition: attachment; filename="'.$this->table.'_'.date('Y-m-d_His').'.csv"'); + + $headers = array(); + foreach ($this->fields_list as $key => $datas) { + if ($datas['title'] == 'PDF') { + unset($this->fields_list[$key]); + } else { + $headers[] = Tools::htmlentitiesDecodeUTF8($datas['title']); + } + } + $content = array(); + foreach ($this->_list as $i => $row) { + $content[$i] = array(); + $path_to_image = false; + foreach ($this->fields_list as $key => $params) { + $field_value = isset($row[$key]) ? Tools::htmlentitiesDecodeUTF8(Tools::nl2br($row[$key])) : ''; + if ($key == 'image') { + if ($params['image'] != 'p' || Configuration::get('PS_LEGACY_IMAGES')) { + $path_to_image = Tools::getShopDomain(true)._PS_IMG_.$params['image'].'/'.$row['id_'.$this->table].(isset($row['id_image']) ? '-'.(int)$row['id_image'] : '').'.'.$this->imageType; + } else { + $path_to_image = Tools::getShopDomain(true)._PS_IMG_.$params['image'].'/'.Image::getImgFolderStatic($row['id_image']).(int)$row['id_image'].'.'.$this->imageType; + } + if ($path_to_image) { + $field_value = $path_to_image; + } + } + if (isset($params['callback'])) { + $callback_obj = (isset($params['callback_object'])) ? $params['callback_object'] : $this->context->controller; + if (!preg_match('/<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)/ism', call_user_func_array(array($callback_obj, $params['callback']), array($field_value, $row)))) { + $field_value = call_user_func_array(array($callback_obj, $params['callback']), array($field_value, $row)); + } + } + $content[$i][] = $field_value; + } + } + + $this->context->smarty->assign(array( + 'export_precontent' => "", + 'export_headers' => $headers, + 'export_content' => $content, + 'text_delimiter' => $text_delimiter + ) + ); + + $this->layout = 'layout-export.tpl'; + } + + /** + * Object Delete + * + * @return ObjectModel|false + * @throws PrestaShopException + */ + public function processDelete() + { + if (Validate::isLoadedObject($object = $this->loadObject())) { + $res = true; + // check if request at least one object with noZeroObject + if (isset($object->noZeroObject) && count(call_user_func(array($this->className, $object->noZeroObject))) <= 1) { + $this->errors[] = Tools::displayError('You need at least one object.'). + ' <b>'.$this->table.'</b><br />'. + Tools::displayError('You cannot delete all of the items.'); + } elseif (array_key_exists('delete', $this->list_skip_actions) && in_array($object->id, $this->list_skip_actions['delete'])) { //check if some ids are in list_skip_actions and forbid deletion + $this->errors[] = Tools::displayError('You cannot delete this item.'); + } else { + if ($this->deleted) { + if (!empty($this->fieldImageSettings)) { + $res = $object->deleteImage(); + } + + if (!$res) { + $this->errors[] = Tools::displayError('Unable to delete associated images.'); + } + + $object->deleted = 1; + if ($res = $object->update()) { + $this->redirect_after = self::$currentIndex.'&conf=1&token='.$this->token; + } + } elseif ($res = $object->delete()) { + $this->redirect_after = self::$currentIndex.'&conf=1&token='.$this->token; + } + $this->errors[] = Tools::displayError('An error occurred during deletion.'); + if ($res) { + PrestaShopLogger::addLog(sprintf($this->l('%s deletion', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); + } + } + } else { + $this->errors[] = Tools::displayError('An error occurred while deleting the object.'). + ' <b>'.$this->table.'</b> '. + Tools::displayError('(cannot load object)'); + } + return $object; + } + + /** + * Call the right method for creating or updating object + * + * @return ObjectModel|false|void + */ + public function processSave() + { + if ($this->id_object) { + $this->object = $this->loadObject(); + return $this->processUpdate(); + } else { + return $this->processAdd(); + } + } + + /** + * Object creation + * + * @return ObjectModel|false + * @throws PrestaShopException + */ + public function processAdd() + { + if (!isset($this->className) || empty($this->className)) { + return false; + } + + $this->validateRules(); + if (count($this->errors) <= 0) { + $this->object = new $this->className(); + + $this->copyFromPost($this->object, $this->table); + $this->beforeAdd($this->object); + if (method_exists($this->object, 'add') && !$this->object->add()) { + $this->errors[] = Tools::displayError('An error occurred while creating an object.'). + ' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>'; + } elseif (($_POST[$this->identifier] = $this->object->id /* voluntary do affectation here */) && $this->postImage($this->object->id) && !count($this->errors) && $this->_redirect) { + PrestaShopLogger::addLog(sprintf($this->l('%s addition', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); + $parent_id = (int)Tools::getValue('id_parent', 1); + $this->afterAdd($this->object); + $this->updateAssoShop($this->object->id); + // Save and stay on same form + if (empty($this->redirect_after) && $this->redirect_after !== false && Tools::isSubmit('submitAdd'.$this->table.'AndStay')) { + $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$this->object->id.'&conf=3&update'.$this->table.'&token='.$this->token; + } + // Save and back to parent + if (empty($this->redirect_after) && $this->redirect_after !== false && Tools::isSubmit('submitAdd'.$this->table.'AndBackToParent')) { + $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$parent_id.'&conf=3&token='.$this->token; + } + // Default behavior (save and back) + if (empty($this->redirect_after) && $this->redirect_after !== false) { + $this->redirect_after = self::$currentIndex.($parent_id ? '&'.$this->identifier.'='.$this->object->id : '').'&conf=3&token='.$this->token; + } + } + } + + $this->errors = array_unique($this->errors); + if (!empty($this->errors)) { + // if we have errors, we stay on the form instead of going back to the list + $this->display = 'edit'; + return false; + } + + return $this->object; + } + + /** + * Object update + * + * @return ObjectModel|false|void + * @throws PrestaShopException + */ + public function processUpdate() + { + /* Checking fields validity */ + $this->validateRules(); + if (empty($this->errors)) { + $id = (int)Tools::getValue($this->identifier); + + /* Object update */ + if (isset($id) && !empty($id)) { + /** @var ObjectModel $object */ + $object = new $this->className($id); + if (Validate::isLoadedObject($object)) { + /* Specific to objects which must not be deleted */ + if ($this->deleted && $this->beforeDelete($object)) { + // Create new one with old objet values + /** @var ObjectModel $object_new */ + $object_new = $object->duplicateObject(); + if (Validate::isLoadedObject($object_new)) { + // Update old object to deleted + $object->deleted = 1; + $object->update(); + + // Update new object with post values + $this->copyFromPost($object_new, $this->table); + $result = $object_new->update(); + if (Validate::isLoadedObject($object_new)) { + $this->afterDelete($object_new, $object->id); + } + } + } else { + $this->copyFromPost($object, $this->table); + $result = $object->update(); + $this->afterUpdate($object); + } + + if ($object->id) { + $this->updateAssoShop($object->id); + } + + if (!$result) { + $this->errors[] = Tools::displayError('An error occurred while updating an object.'). + ' <b>'.$this->table.'</b> ('.Db::getInstance()->getMsgError().')'; + } elseif ($this->postImage($object->id) && !count($this->errors) && $this->_redirect) { + $parent_id = (int)Tools::getValue('id_parent', 1); + // Specific back redirect + if ($back = Tools::getValue('back')) { + $this->redirect_after = urldecode($back).'&conf=4'; + } + // Specific scene feature + // @todo change stay_here submit name (not clear for redirect to scene ... ) + if (Tools::getValue('stay_here') == 'on' || Tools::getValue('stay_here') == 'true' || Tools::getValue('stay_here') == '1') { + $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$object->id.'&conf=4&updatescene&token='.$this->token; + } + // Save and stay on same form + // @todo on the to following if, we may prefer to avoid override redirect_after previous value + if (Tools::isSubmit('submitAdd'.$this->table.'AndStay')) { + $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$object->id.'&conf=4&update'.$this->table.'&token='.$this->token; + } + // Save and back to parent + if (Tools::isSubmit('submitAdd'.$this->table.'AndBackToParent')) { + $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$parent_id.'&conf=4&token='.$this->token; + } + + // Default behavior (save and back) + if (empty($this->redirect_after) && $this->redirect_after !== false) { + $this->redirect_after = self::$currentIndex.($parent_id ? '&'.$this->identifier.'='.$object->id : '').'&conf=4&token='.$this->token; + } + } + PrestaShopLogger::addLog(sprintf($this->l('%s modification', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$object->id, true, (int)$this->context->employee->id); + } else { + $this->errors[] = Tools::displayError('An error occurred while updating an object.'). + ' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } + } + } + $this->errors = array_unique($this->errors); + if (!empty($this->errors)) { + // if we have errors, we stay on the form instead of going back to the list + $this->display = 'edit'; + return false; + } + + if (isset($object)) { + return $object; + } + return; + } + + /** + * Change object required fields + * + * @return ObjectModel + */ + public function processUpdateFields() + { + if (!is_array($fields = Tools::getValue('fieldsBox'))) { + $fields = array(); + } + + /** @var $object ObjectModel */ + $object = new $this->className(); + + if (!$object->addFieldsRequiredDatabase($fields)) { + $this->errors[] = Tools::displayError('An error occurred when attempting to update the required fields.'); + } else { + $this->redirect_after = self::$currentIndex.'&conf=4&token='.$this->token; + } + + return $object; + } + + /** + * Change object status (active, inactive) + * + * @return ObjectModel|false + * @throws PrestaShopException + */ + public function processStatus() + { + if (Validate::isLoadedObject($object = $this->loadObject())) { + if ($object->toggleStatus()) { + $matches = array(); + if (preg_match('/[\?|&]controller=([^&]*)/', (string)$_SERVER['HTTP_REFERER'], $matches) !== false + && strtolower($matches[1]) != strtolower(preg_replace('/controller/i', '', get_class($this)))) { + $this->redirect_after = preg_replace('/[\?|&]conf=([^&]*)/i', '', (string)$_SERVER['HTTP_REFERER']); + } else { + $this->redirect_after = self::$currentIndex.'&token='.$this->token; + } + + $id_category = (($id_category = (int)Tools::getValue('id_category')) && Tools::getValue('id_product')) ? '&id_category='.$id_category : ''; + + $page = (int)Tools::getValue('page'); + $page = $page > 1 ? '&submitFilter'.$this->table.'='.(int)$page : ''; + $this->redirect_after .= '&conf=5'.$id_category.$page; + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the status.'); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.'). + ' <b>'.$this->table.'</b> '. + Tools::displayError('(cannot load object)'); + } + + return $object; + } + + /** + * Change object position + * + * @return ObjectModel|false + */ + public function processPosition() + { + if (!Validate::isLoadedObject($object = $this->loadObject())) { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.'). + ' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } elseif (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) { + $this->errors[] = Tools::displayError('Failed to update the position.'); + } else { + $id_identifier_str = ($id_identifier = (int)Tools::getValue($this->identifier)) ? '&'.$this->identifier.'='.$id_identifier : ''; + $redirect = self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=5'.$id_identifier_str.'&token='.$this->token; + $this->redirect_after = $redirect; + } + return $object; + } + + /** + * Cancel all filters for this tab + * + * @param int|null $list_id + */ + public function processResetFilters($list_id = null) + { + if ($list_id === null) { + $list_id = isset($this->list_id) ? $this->list_id : $this->table; + } + + $prefix = str_replace(array('admin', 'controller'), '', Tools::strtolower(get_class($this))); + $filters = $this->context->cookie->getFamily($prefix.$list_id.'Filter_'); + foreach ($filters as $cookie_key => $filter) { + if (strncmp($cookie_key, $prefix.$list_id.'Filter_', 7 + Tools::strlen($prefix.$list_id)) == 0) { + $key = substr($cookie_key, 7 + Tools::strlen($prefix.$list_id)); + if (is_array($this->fields_list) && array_key_exists($key, $this->fields_list)) { + $this->context->cookie->$cookie_key = null; + } + unset($this->context->cookie->$cookie_key); + } + } + + if (isset($this->context->cookie->{'submitFilter'.$list_id})) { + unset($this->context->cookie->{'submitFilter'.$list_id}); + } + if (isset($this->context->cookie->{$prefix.$list_id.'Orderby'})) { + unset($this->context->cookie->{$prefix.$list_id.'Orderby'}); + } + if (isset($this->context->cookie->{$prefix.$list_id.'Orderway'})) { + unset($this->context->cookie->{$prefix.$list_id.'Orderway'}); + } + + $_POST = array(); + $this->_filter = false; + unset($this->_filterHaving); + unset($this->_having); + } + + /** + * Update options and preferences + */ + protected function processUpdateOptions() + { + $this->beforeUpdateOptions(); + + $languages = Language::getLanguages(false); + + $hide_multishop_checkbox = (Shop::getTotalShops(false, null) < 2) ? true : false; + foreach ($this->fields_options as $category_data) { + if (!isset($category_data['fields'])) { + continue; + } + + $fields = $category_data['fields']; + + foreach ($fields as $field => $values) { + if (isset($values['type']) && $values['type'] == 'selectLang') { + foreach ($languages as $lang) { + if (Tools::getValue($field.'_'.strtoupper($lang['iso_code']))) { + $fields[$field.'_'.strtoupper($lang['iso_code'])] = array( + 'type' => 'select', + 'cast' => 'strval', + 'identifier' => 'mode', + 'list' => $values['list'] + ); + } + } + } + } + + // Validate fields + foreach ($fields as $field => $values) { + // We don't validate fields with no visibility + if (!$hide_multishop_checkbox && Shop::isFeatureActive() && isset($values['visibility']) && $values['visibility'] > Shop::getContext()) { + continue; + } + + // Check if field is required + if ((!Shop::isFeatureActive() && isset($values['required']) && $values['required']) + || (Shop::isFeatureActive() && isset($_POST['multishopOverrideOption'][$field]) && isset($values['required']) && $values['required'])) { + if (isset($values['type']) && $values['type'] == 'textLang') { + foreach ($languages as $language) { + if (($value = Tools::getValue($field.'_'.$language['id_lang'])) == false && (string)$value != '0') { + $this->errors[] = sprintf(Tools::displayError('field %s is required.'), $values['title']); + } + } + } elseif (($value = Tools::getValue($field)) == false && (string)$value != '0') { + $this->errors[] = sprintf(Tools::displayError('field %s is required.'), $values['title']); + } + } + + // Check field validator + if (isset($values['type']) && $values['type'] == 'textLang') { + foreach ($languages as $language) { + if (Tools::getValue($field.'_'.$language['id_lang']) && isset($values['validation'])) { + if (!Validate::$values['validation'](Tools::getValue($field.'_'.$language['id_lang']))) { + $this->errors[] = sprintf(Tools::displayError('field %s is invalid.'), $values['title']); + } + } + } + } elseif (Tools::getValue($field) && isset($values['validation'])) { + if (!Validate::$values['validation'](Tools::getValue($field))) { + $this->errors[] = sprintf(Tools::displayError('field %s is invalid.'), $values['title']); + } + } + + // Set default value + if (Tools::getValue($field) === false && isset($values['default'])) { + $_POST[$field] = $values['default']; + } + } + + if (!count($this->errors)) { + foreach ($fields as $key => $options) { + if (Shop::isFeatureActive() && isset($options['visibility']) && $options['visibility'] > Shop::getContext()) { + continue; + } + + if (!$hide_multishop_checkbox && Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL && empty($options['no_multishop_checkbox']) && empty($_POST['multishopOverrideOption'][$key])) { + Configuration::deleteFromContext($key); + continue; + } + + // check if a method updateOptionFieldName is available + $method_name = 'updateOption'.Tools::toCamelCase($key, true); + if (method_exists($this, $method_name)) { + $this->$method_name(Tools::getValue($key)); + } elseif (isset($options['type']) && in_array($options['type'], array('textLang', 'textareaLang'))) { + $list = array(); + foreach ($languages as $language) { + $key_lang = Tools::getValue($key.'_'.$language['id_lang']); + $val = (isset($options['cast']) ? $options['cast']($key_lang) : $key_lang); + if ($this->validateField($val, $options)) { + if (Validate::isCleanHtml($val)) { + $list[$language['id_lang']] = $val; + } else { + $this->errors[] = Tools::displayError('Can not add configuration '.$key.' for lang '.Language::getIsoById((int)$language['id_lang'])); + } + } + } + Configuration::updateValue($key, $list, isset($values['validation']) && isset($options['validation']) && $options['validation'] == 'isCleanHtml' ? true : false); + } else { + $val = (isset($options['cast']) ? $options['cast'](Tools::getValue($key)) : Tools::getValue($key)); + if ($this->validateField($val, $options)) { + if (Validate::isCleanHtml($val)) { + Configuration::updateValue($key, $val); + } else { + $this->errors[] = Tools::displayError('Can not add configuration '.$key); + } + } + } + } + } + } + + $this->display = 'list'; + if (empty($this->errors)) { + $this->confirmations[] = $this->_conf[6]; + } + } + + public function initPageHeaderToolbar() + { + if (empty($this->toolbar_title)) { + $this->initToolbarTitle(); + } + + if (!is_array($this->toolbar_title)) { + $this->toolbar_title = array($this->toolbar_title); + } + + switch ($this->display) { + case 'view': + // Default cancel button - like old back link + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } + if (!Validate::isCleanHtml($back)) { + die(Tools::displayError()); + } + if (!$this->lite_display) { + $this->page_header_toolbar_btn['back'] = array( + 'href' => $back, + 'desc' => $this->l('Back to list') + ); + } + $obj = $this->loadObject(true); + if (Validate::isLoadedObject($obj) && isset($obj->{$this->identifier_name}) && !empty($obj->{$this->identifier_name})) { + array_pop($this->toolbar_title); + array_pop($this->meta_title); + $this->toolbar_title[] = is_array($obj->{$this->identifier_name}) ? $obj->{$this->identifier_name}[$this->context->employee->id_lang] : $obj->{$this->identifier_name}; + $this->addMetaTitle($this->toolbar_title[count($this->toolbar_title) - 1]); + } + break; + case 'edit': + $obj = $this->loadObject(true); + if (Validate::isLoadedObject($obj) && isset($obj->{$this->identifier_name}) && !empty($obj->{$this->identifier_name})) { + array_pop($this->toolbar_title); + array_pop($this->meta_title); + $this->toolbar_title[] = sprintf($this->l('Edit: %s'), (is_array($obj->{$this->identifier_name}) && isset($obj->{$this->identifier_name}[$this->context->employee->id_lang])) ? $obj->{$this->identifier_name}[$this->context->employee->id_lang] : $obj->{$this->identifier_name}); + $this->addMetaTitle($this->toolbar_title[count($this->toolbar_title) - 1]); + } + break; + } + + if (is_array($this->page_header_toolbar_btn) + && $this->page_header_toolbar_btn instanceof Traversable + || count($this->toolbar_title)) { + $this->show_page_header_toolbar = true; + } + + if (empty($this->page_header_toolbar_title)) { + $this->page_header_toolbar_title = $this->toolbar_title[count($this->toolbar_title) - 1]; + } + $this->addPageHeaderToolBarModulesListButton(); + + $this->context->smarty->assign('help_link', 'http://help.prestashop.com/'.Language::getIsoById($this->context->employee->id_lang).'/doc/' + .Tools::getValue('controller').'?version='._PS_VERSION_.'&country='.Language::getIsoById($this->context->employee->id_lang)); + } + + /** + * assign default action in toolbar_btn smarty var, if they are not set. + * uses override to specifically add, modify or remove items + * + */ + public function initToolbar() + { + switch ($this->display) { + case 'add': + case 'edit': + // Default save button - action dynamically handled in javascript + $this->toolbar_btn['save'] = array( + 'href' => '#', + 'desc' => $this->l('Save') + ); + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } + if (!Validate::isCleanHtml($back)) { + die(Tools::displayError()); + } + if (!$this->lite_display) { + $this->toolbar_btn['cancel'] = array( + 'href' => $back, + 'desc' => $this->l('Cancel') + ); + } + break; + case 'view': + // Default cancel button - like old back link + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } + if (!Validate::isCleanHtml($back)) { + die(Tools::displayError()); + } + if (!$this->lite_display) { + $this->toolbar_btn['back'] = array( + 'href' => $back, + 'desc' => $this->l('Back to list') + ); + } + break; + case 'options': + $this->toolbar_btn['save'] = array( + 'href' => '#', + 'desc' => $this->l('Save') + ); + break; + default: // list + $this->toolbar_btn['new'] = array( + 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token, + 'desc' => $this->l('Add new') + ); + if ($this->allow_export) { + $this->toolbar_btn['export'] = array( + 'href' => self::$currentIndex.'&export'.$this->table.'&token='.$this->token, + 'desc' => $this->l('Export') + ); + } + } + $this->addToolBarModulesListButton(); + } + + /** + * Load class object using identifier in $_GET (if possible) + * otherwise return an empty object, or die + * + * @param bool $opt Return an empty object if load fail + * @return ObjectModel|false + */ + protected function loadObject($opt = false) + { + if (!isset($this->className) || empty($this->className)) { + return true; + } + + $id = (int)Tools::getValue($this->identifier); + if ($id && Validate::isUnsignedId($id)) { + if (!$this->object) { + $this->object = new $this->className($id); + } + if (Validate::isLoadedObject($this->object)) { + return $this->object; + } + // throw exception + $this->errors[] = Tools::displayError('The object cannot be loaded (or found)'); + return false; + } elseif ($opt) { + if (!$this->object) { + $this->object = new $this->className(); + } + return $this->object; + } else { + $this->errors[] = Tools::displayError('The object cannot be loaded (the identifier is missing or invalid)'); + return false; + } + } + + /** + * Check if the token is valid, else display a warning page + * + * @return bool + */ + public function checkAccess() + { + if (!$this->checkToken()) { + // If this is an XSS attempt, then we should only display a simple, secure page + // ${1} in the replacement string of the regexp is required, + // because the token may begin with a number and mix up with it (e.g. $17) + $url = preg_replace('/([&?]token=)[^&]*(&.*)?$/', '${1}'.$this->token.'$2', $_SERVER['REQUEST_URI']); + if (false === strpos($url, '?token=') && false === strpos($url, '&token=')) { + $url .= '&token='.$this->token; + } + if (strpos($url, '?') === false) { + $url = str_replace('&token', '?controller=AdminDashboard&token', $url); + } + + $this->context->smarty->assign('url', htmlentities($url)); + return false; + } + return true; + } + + /** + * @param string $key + * @param string $filter + * @return array|false + */ + protected function filterToField($key, $filter) + { + if (!isset($this->fields_list)) { + return false; + } + + foreach ($this->fields_list as $field) { + if (array_key_exists('filter_key', $field) && $field['filter_key'] == $key) { + return $field; + } + } + if (array_key_exists($filter, $this->fields_list)) { + return $this->fields_list[$filter]; + } + return false; + } + + public function displayNoSmarty() + { + } + + /** + * @return void + */ + public function displayAjax() + { + if ($this->json) { + $this->context->smarty->assign(array( + 'json' => true, + 'status' => $this->status, + )); + } + $this->layout = 'layout-ajax.tpl'; + $this->display_header = false; + $this->display_header_javascript = false; + $this->display_footer = false; + return $this->display(); + } + + protected function redirect() + { + Tools::redirectAdmin($this->redirect_after); + } + + /** + * @return void + * @throws Exception + * @throws SmartyException + */ + public function display() + { + $this->context->smarty->assign(array( + 'display_header' => $this->display_header, + 'display_header_javascript'=> $this->display_header_javascript, + 'display_footer' => $this->display_footer, + 'js_def' => Media::getJsDef(), + )); + + // Use page title from meta_title if it has been set else from the breadcrumbs array + if (!$this->meta_title) { + $this->meta_title = $this->toolbar_title; + } + if (is_array($this->meta_title)) { + $this->meta_title = strip_tags(implode(' '.Configuration::get('PS_NAVIGATION_PIPE').' ', $this->meta_title)); + } + $this->context->smarty->assign('meta_title', $this->meta_title); + + $template_dirs = $this->context->smarty->getTemplateDir(); + + // Check if header/footer have been overriden + $dir = $this->context->smarty->getTemplateDir(0).'controllers'.DIRECTORY_SEPARATOR.trim($this->override_folder, '\\/').DIRECTORY_SEPARATOR; + $module_list_dir = $this->context->smarty->getTemplateDir(0).'helpers'.DIRECTORY_SEPARATOR.'modules_list'.DIRECTORY_SEPARATOR; + + $header_tpl = file_exists($dir.'header.tpl') ? $dir.'header.tpl' : 'header.tpl'; + $page_header_toolbar = file_exists($dir.'page_header_toolbar.tpl') ? $dir.'page_header_toolbar.tpl' : 'page_header_toolbar.tpl'; + $footer_tpl = file_exists($dir.'footer.tpl') ? $dir.'footer.tpl' : 'footer.tpl'; + $modal_module_list = file_exists($module_list_dir.'modal.tpl') ? $module_list_dir.'modal.tpl' : 'modal.tpl'; + $tpl_action = $this->tpl_folder.$this->display.'.tpl'; + + // Check if action template has been overriden + foreach ($template_dirs as $template_dir) { + if (file_exists($template_dir.DIRECTORY_SEPARATOR.$tpl_action) && $this->display != 'view' && $this->display != 'options') { + if (method_exists($this, $this->display.Tools::toCamelCase($this->className))) { + $this->{$this->display.Tools::toCamelCase($this->className)}(); + } + $this->context->smarty->assign('content', $this->context->smarty->fetch($tpl_action)); + break; + } + } + + if (!$this->ajax) { + $template = $this->createTemplate($this->template); + $page = $template->fetch(); + } else { + $page = $this->content; + } + + if ($conf = Tools::getValue('conf')) { + $this->context->smarty->assign('conf', $this->json ? Tools::jsonEncode($this->_conf[(int)$conf]) : $this->_conf[(int)$conf]); + } + + foreach (array('errors', 'warnings', 'informations', 'confirmations') as $type) { + if (!is_array($this->$type)) { + $this->$type = (array)$this->$type; + } + $this->context->smarty->assign($type, $this->json ? Tools::jsonEncode(array_unique($this->$type)) : array_unique($this->$type)); + } + + if ($this->show_page_header_toolbar && !$this->lite_display) { + $this->context->smarty->assign( + array( + 'page_header_toolbar' => $this->context->smarty->fetch($page_header_toolbar), + 'modal_module_list' => $this->context->smarty->fetch($modal_module_list), + ) + ); + } + + $this->context->smarty->assign( + array( + 'page' => $this->json ? Tools::jsonEncode($page) : $page, + 'header' => $this->context->smarty->fetch($header_tpl), + 'footer' => $this->context->smarty->fetch($footer_tpl), + ) + ); + + $this->smartyOutputContent($this->layout); + } + + /** + * Add a warning message to display at the top of the page + * + * @param string $msg + */ + protected function displayWarning($msg) + { + $this->warnings[] = $msg; + } + + /** + * Add a info message to display at the top of the page + * + * @param string $msg + */ + protected function displayInformation($msg) + { + $this->informations[] = $msg; + } + + /** + * Assign smarty variables for the header + */ + public function initHeader() + { + header('Cache-Control: no-store, no-cache'); + + // Multishop + $is_multishop = Shop::isFeatureActive(); + + // Quick access + if ((int)$this->context->employee->id) { + $quick_access = QuickAccess::getQuickAccesses($this->context->language->id); + foreach ($quick_access as $index => $quick) { + if ($quick['link'] == '../' && Shop::getContext() == Shop::CONTEXT_SHOP) { + $url = $this->context->shop->getBaseURL(); + if (!$url) { + unset($quick_access[$index]); + continue; + } + $quick_access[$index]['link'] = $url; + } else { + preg_match('/controller=(.+)(&.+)?$/', $quick['link'], $admin_tab); + if (isset($admin_tab[1])) { + if (strpos($admin_tab[1], '&')) { + $admin_tab[1] = substr($admin_tab[1], 0, strpos($admin_tab[1], '&')); + } + + $token = Tools::getAdminToken($admin_tab[1].(int)Tab::getIdFromClassName($admin_tab[1]).(int)$this->context->employee->id); + $quick_access[$index]['target'] = $admin_tab[1]; + $quick_access[$index]['link'] .= '&token='.$token; + } + } + } + } + + // Tab list + $tabs = Tab::getTabs($this->context->language->id, 0); + $current_id = Tab::getCurrentParentId(); + foreach ($tabs as $index => $tab) { + if (!Tab::checkTabRights($tab['id_tab']) + || ($tab['class_name'] == 'AdminStock' && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') == 0) + || $tab['class_name'] == 'AdminCarrierWizard') { + unset($tabs[$index]); + continue; + } + + $img_cache_url = 'themes/'.$this->context->employee->bo_theme.'/img/t/'.$tab['class_name'].'.png'; + $img_exists_cache = Tools::file_exists_cache(_PS_ADMIN_DIR_.$img_cache_url); + // retrocompatibility : change png to gif if icon not exists + if (!$img_exists_cache) { + $img_exists_cache = Tools::file_exists_cache(_PS_ADMIN_DIR_.str_replace('.png', '.gif', $img_cache_url)); + } + + if ($img_exists_cache) { + $path_img = $img = $img_exists_cache; + } else { + $path_img = _PS_IMG_DIR_.'t/'.$tab['class_name'].'.png'; + // Relative link will always work, whatever the base uri set in the admin + $img = '../img/t/'.$tab['class_name'].'.png'; + } + + if (trim($tab['module']) != '') { + $path_img = _PS_MODULE_DIR_.$tab['module'].'/'.$tab['class_name'].'.png'; + // Relative link will always work, whatever the base uri set in the admin + $img = '../modules/'.$tab['module'].'/'.$tab['class_name'].'.png'; + } + + // retrocompatibility + if (!file_exists($path_img)) { + $img = str_replace('png', 'gif', $img); + } + // tab[class_name] does not contains the "Controller" suffix + $tabs[$index]['current'] = ($tab['class_name'].'Controller' == get_class($this)) || ($current_id == $tab['id_tab']); + $tabs[$index]['img'] = $img; + $tabs[$index]['href'] = $this->context->link->getAdminLink($tab['class_name']); + + $sub_tabs = Tab::getTabs($this->context->language->id, $tab['id_tab']); + foreach ($sub_tabs as $index2 => $sub_tab) { + //check if module is enable and + if (isset($sub_tab['module']) && !empty($sub_tab['module'])) { + $module = Module::getInstanceByName($sub_tab['module']); + if (is_object($module) && !$module->isEnabledForShopContext()) { + unset($sub_tabs[$index2]); + continue; + } + } + + // class_name is the name of the class controller + if (Tab::checkTabRights($sub_tab['id_tab']) === true && (bool)$sub_tab['active'] && $sub_tab['class_name'] != 'AdminCarrierWizard') { + $sub_tabs[$index2]['href'] = $this->context->link->getAdminLink($sub_tab['class_name']); + $sub_tabs[$index2]['current'] = ($sub_tab['class_name'].'Controller' == get_class($this) || $sub_tab['class_name'] == Tools::getValue('controller')); + } elseif ($sub_tab['class_name'] == 'AdminCarrierWizard' && $sub_tab['class_name'].'Controller' == get_class($this)) { + foreach ($sub_tabs as $i => $tab) { + if ($tab['class_name'] == 'AdminCarriers') { + break; + } + } + + $sub_tabs[$i]['current'] = true; + unset($sub_tabs[$index2]); + } else { + unset($sub_tabs[$index2]); + } + } + $tabs[$index]['sub_tabs'] = array_values($sub_tabs); + } + + if (Validate::isLoadedObject($this->context->employee)) { + $accesses = Profile::getProfileAccesses($this->context->employee->id_profile, 'class_name'); + $helperShop = new HelperShop(); + /* Hooks are voluntary out the initialize array (need those variables already assigned) */ + $bo_color = empty($this->context->employee->bo_color) ? '#FFFFFF' : $this->context->employee->bo_color; + $this->context->smarty->assign(array( + 'autorefresh_notifications' => Configuration::get('PS_ADMINREFRESH_NOTIFICATION'), + 'help_box' => Configuration::get('PS_HELPBOX'), + 'round_mode' => Configuration::get('PS_PRICE_ROUND_MODE'), + 'brightness' => Tools::getBrightness($bo_color) < 128 ? 'white' : '#383838', + 'bo_width' => (int)$this->context->employee->bo_width, + 'bo_color' => isset($this->context->employee->bo_color) ? Tools::htmlentitiesUTF8($this->context->employee->bo_color) : null, + 'show_new_orders' => Configuration::get('PS_SHOW_NEW_ORDERS') && isset($accesses['AdminOrders']) && $accesses['AdminOrders']['view'], + 'show_new_customers' => Configuration::get('PS_SHOW_NEW_CUSTOMERS') && isset($accesses['AdminCustomers']) && $accesses['AdminCustomers']['view'], + 'show_new_messages' => Configuration::get('PS_SHOW_NEW_MESSAGES') && isset($accesses['AdminCustomerThreads']) && $accesses['AdminCustomerThreads']['view'], + 'employee' => $this->context->employee, + 'search_type' => Tools::getValue('bo_search_type'), + 'bo_query' => Tools::safeOutput(Tools::stripslashes(Tools::getValue('bo_query'))), + 'quick_access' => $quick_access, + 'multi_shop' => Shop::isFeatureActive(), + 'shop_list' => $helperShop->getRenderedShopList(), + 'shop' => $this->context->shop, + 'shop_group' => new ShopGroup((int)Shop::getContextShopGroupID()), + 'is_multishop' => $is_multishop, + 'multishop_context' => $this->multishop_context, + 'default_tab_link' => $this->context->link->getAdminLink(Tab::getClassNameById((int)Context::getContext()->employee->default_tab)), + 'login_link' => $this->context->link->getAdminLink('AdminLogin'), + 'collapse_menu' => isset($this->context->cookie->collapse_menu) ? (int)$this->context->cookie->collapse_menu : 0, + )); + } else { + $this->context->smarty->assign('default_tab_link', $this->context->link->getAdminLink('AdminDashboard')); + } + + // Shop::initialize() in config.php may empty $this->context->shop->virtual_uri so using a new shop instance for getBaseUrl() + $this->context->shop = new Shop((int)$this->context->shop->id); + + $this->context->smarty->assign(array( + 'img_dir' => _PS_IMG_, + 'iso' => $this->context->language->iso_code, + 'class_name' => $this->className, + 'iso_user' => $this->context->language->iso_code, + 'country_iso_code' => $this->context->country->iso_code, + 'version' => _PS_VERSION_, + 'lang_iso' => $this->context->language->iso_code, + 'full_language_code' => $this->context->language->language_code, + 'link' => $this->context->link, + 'shop_name' => Configuration::get('PS_SHOP_NAME'), + 'base_url' => $this->context->shop->getBaseURL(), + 'tab' => isset($tab) ? $tab : null, // Deprecated, this tab is declared in the foreach, so it's the last tab in the foreach + 'current_parent_id' => (int)Tab::getCurrentParentId(), + 'tabs' => $tabs, + 'install_dir_exists' => file_exists(_PS_ADMIN_DIR_.'/../install'), + 'pic_dir' => _THEME_PROD_PIC_DIR_, + 'controller_name' => htmlentities(Tools::getValue('controller')), + 'currentIndex' => self::$currentIndex, + 'bootstrap' => $this->bootstrap, + 'default_language' => (int)Configuration::get('PS_LANG_DEFAULT'), + 'display_addons_connection' => Tab::checkTabRights(Tab::getIdFromClassName('AdminModulesController')) + )); + + $module = Module::getInstanceByName('themeconfigurator'); + if (is_object($module) && $module->active && (int)Configuration::get('PS_TC_ACTIVE') == 1 && $this->context->shop->getBaseURL()) { + $request = + 'live_configurator_token='.$module->getLiveConfiguratorToken() + .'&id_employee='.(int)$this->context->employee->id + .'&id_shop='.(int)$this->context->shop->id + .(Configuration::get('PS_TC_THEME') != '' ? '&theme='.Configuration::get('PS_TC_THEME') : '') + .(Configuration::get('PS_TC_FONT') != '' ? '&theme_font='.Configuration::get('PS_TC_FONT') : ''); + $this->context->smarty->assign('base_url_tc', $this->context->link->getPageLink('index', null, $id_lang = null, $request)); + } + } + + /** + * Declare an action to use for each row in the list + * + * @param string $action + */ + public function addRowAction($action) + { + $action = strtolower($action); + $this->actions[] = $action; + } + + /** + * Add an action to use for each row in the list + * + * @param string $action + * @param array $list + */ + public function addRowActionSkipList($action, $list) + { + $action = strtolower($action); + $list = (array)$list; + + if (array_key_exists($action, $this->list_skip_actions)) { + $this->list_skip_actions[$action] = array_merge($this->list_skip_actions[$action], $list); + } else { + $this->list_skip_actions[$action] = $list; + } + } + + /** + * Assign smarty variables for all default views, list and form, then call other init functions + */ + public function initContent() + { + if (!$this->viewAccess()) { + $this->errors[] = Tools::displayError('You do not have permission to view this.'); + return; + } + + $this->getLanguages(); + $this->initToolbar(); + $this->initTabModuleList(); + $this->initPageHeaderToolbar(); + + if ($this->display == 'edit' || $this->display == 'add') { + if (!$this->loadObject(true)) { + return; + } + + $this->content .= $this->renderForm(); + } elseif ($this->display == 'view') { + // Some controllers use the view action without an object + if ($this->className) { + $this->loadObject(true); + } + $this->content .= $this->renderView(); + } elseif ($this->display == 'details') { + $this->content .= $this->renderDetails(); + } elseif (!$this->ajax) { + $this->content .= $this->renderModulesList(); + $this->content .= $this->renderKpis(); + $this->content .= $this->renderList(); + $this->content .= $this->renderOptions(); + + // if we have to display the required fields form + if ($this->required_database) { + $this->content .= $this->displayRequiredFields(); + } + } + + $this->context->smarty->assign(array( + 'maintenance_mode' => !(bool)Configuration::get('PS_SHOP_ENABLE'), + 'content' => $this->content, + 'lite_display' => $this->lite_display, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'title' => $this->page_header_toolbar_title, + 'toolbar_btn' => $this->page_header_toolbar_btn, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } + + /** + * Init tab modules list and add button in toolbar + */ + protected function initTabModuleList() + { + if (!$this->isFresh(Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, 86400)) { + @file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, Tools::addonsRequest('must-have')); + } + if (!$this->isFresh(Module::CACHE_FILE_TAB_MODULES_LIST, 604800)) { + $this->refresh(Module::CACHE_FILE_TAB_MODULES_LIST, _PS_TAB_MODULE_LIST_URL_); + } + + $this->tab_modules_list = Tab::getTabModulesList($this->id); + + $modules = Module::getModulesOnDisk(); + + $tmp = array(); + foreach ($modules as $module) { + $tmp[] = $module->name; + } + + foreach ($this->tab_modules_list['slider_list'] as $key => $module) { + if (!in_array($module, $tmp)) { + unset($this->tab_modules_list['slider_list'][$key]); + } + } + + + if (is_array($this->tab_modules_list['default_list']) && count($this->tab_modules_list['default_list'])) { + $this->filter_modules_list = $this->tab_modules_list['default_list']; + } elseif (is_array($this->tab_modules_list['slider_list']) && count($this->tab_modules_list['slider_list'])) { + $this->addToolBarModulesListButton(); + $this->addPageHeaderToolBarModulesListButton(); + $this->context->smarty->assign(array( + 'tab_modules_list' => implode(',', $this->tab_modules_list['slider_list']), + 'admin_module_ajax_url' => $this->context->link->getAdminLink('AdminModules'), + 'back_tab_modules_list' => $this->context->link->getAdminLink(Tools::getValue('controller')), + 'tab_modules_open' => (int)Tools::getValue('tab_modules_open') + )); + } + } + + protected function addPageHeaderToolBarModulesListButton() + { + $this->filterTabModuleList(); + + if (is_array($this->tab_modules_list['slider_list']) && count($this->tab_modules_list['slider_list'])) { + $this->page_header_toolbar_btn['modules-list'] = array( + 'href' => '#', + 'desc' => $this->l('Recommended Modules and Services') + ); + } + } + + protected function addToolBarModulesListButton() + { + $this->filterTabModuleList(); + + if (is_array($this->tab_modules_list['slider_list']) && count($this->tab_modules_list['slider_list'])) { + $this->toolbar_btn['modules-list'] = array( + 'href' => '#', + 'desc' => $this->l('Recommended Modules and Services') + ); + } + } + + protected function filterTabModuleList() + { + static $list_is_filtered = null; + + if ($list_is_filtered !== null) { + return; + } + + if (!$this->isFresh(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 86400)) { + file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, Tools::addonsRequest('native')); + } + + if (!$this->isFresh(Module::CACHE_FILE_ALL_COUNTRY_MODULES_LIST, 86400)) { + file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_ALL_COUNTRY_MODULES_LIST, Tools::addonsRequest('native_all')); + } + + if (!$this->isFresh(Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, 86400)) { + @file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, Tools::addonsRequest('must-have')); + } + + libxml_use_internal_errors(true); + + $country_module_list = file_get_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST); + $must_have_module_list = file_get_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST); + $all_module_list = array(); + + if (!empty($country_module_list) && $country_module_list_xml = @simplexml_load_string($country_module_list)) { + $country_module_list_array = array(); + if (is_object($country_module_list_xml->module)) { + foreach ($country_module_list_xml->module as $k => $m) { + $all_module_list[] = (string)$m->name; + } + } + } else { + foreach (libxml_get_errors() as $error) { + $this->errors[] = Tools::displayError(sprintf('Error found : %1$s in country_module_list.xml file.', $error->message)); + } + } + + libxml_clear_errors(); + + + + if (!empty($must_have_module_list) && $must_have_module_list_xml = @simplexml_load_string($must_have_module_list)) { + $must_have_module_list_array = array(); + if (is_object($country_module_list_xml->module)) { + foreach ($must_have_module_list_xml->module as $l => $mo) { + $all_module_list[] = (string)$mo->name; + } + } + } else { + foreach (libxml_get_errors() as $error) { + $this->errors[] = Tools::displayError(sprintf('Error found : %1$s in must_have_module_list.xml file.', $error->message)); + } + } + + libxml_clear_errors(); + + $this->tab_modules_list['slider_list'] = array_intersect($this->tab_modules_list['slider_list'], $all_module_list); + + $list_is_filtered = true; + } + + /** + * Initialize the invalid doom page of death + * + * @return void + */ + public function initCursedPage() + { + $this->layout = 'invalid_token.tpl'; + } + + /** + * Assign smarty variables for the footer + */ + public function initFooter() + { + //RTL Support + //rtl.js overrides inline styles + //iso_code.css overrides default fonts for every language (optional) + if ($this->context->language->is_rtl) { + $this->addJS(_PS_JS_DIR_.'rtl.js'); + $this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/'.$this->context->language->iso_code.'.css', 'all', false); + } + + // We assign js and css files on the last step before display template, because controller can add many js and css files + $this->context->smarty->assign('css_files', $this->css_files); + $this->context->smarty->assign('js_files', array_unique($this->js_files)); + + $this->context->smarty->assign(array( + 'ps_version' => _PS_VERSION_, + 'timer_start' => $this->timer_start, + 'iso_is_fr' => strtoupper($this->context->language->iso_code) == 'FR', + 'modals' => $this->renderModal(), + )); + } + + /** + * @throws Exception + * @throws SmartyException + */ + public function initModal() + { + if ($this->logged_on_addons) { + $this->context->smarty->assign(array( + 'logged_on_addons' => 1, + 'username_addons' => $this->context->cookie->username_addons + )); + } + + // Iso needed to generate Addons login + $iso_code_caps = strtoupper($this->context->language->iso_code); + + $this->context->smarty->assign(array( + 'check_url_fopen' => (ini_get('allow_url_fopen') ? 'ok' : 'ko'), + 'check_openssl' => (extension_loaded('openssl') ? 'ok' : 'ko'), + 'add_permission' => 1, + 'addons_register_link' => 'https://addons.prestashop.com/'.$this->context->language->iso_code.'/login?' + .'email='.urlencode($this->context->employee->email) + .'&firstname='.urlencode($this->context->employee->firstname) + .'&lastname='.urlencode($this->context->employee->lastname) + .'&website='.urlencode($this->context->shop->getBaseURL()) + .'&utm_source=back-office&utm_medium=connect-to-addons' + .'&utm_campaign=back-office-'.Tools::strtoupper($this->context->language->iso_code) + .'&utm_content='.(defined('_PS_HOST_MODE_') ? 'cloud' : 'download').'#createnow', + 'addons_forgot_password_link' => '//addons.prestashop.com/'.$this->context->language->iso_code.'/forgot-your-password' + )); + + $this->modals[] = array( + 'modal_id' => 'modal_addons_connect', + 'modal_class' => 'modal-md', + 'modal_title' => '<i class="icon-puzzle-piece"></i> <a target="_blank" href="http://addons.prestashop.com/' + .'?utm_source=back-office&utm_medium=modules' + .'&utm_campaign=back-office-'.Tools::strtoupper($this->context->language->iso_code) + .'&utm_content='.(defined('_PS_HOST_MODE_') ? 'cloud' : 'download').'">PrestaShop Addons</a>', + 'modal_content' => $this->context->smarty->fetch('controllers/modules/login_addons.tpl'), + ); + } + + /** + * @return string + * @throws Exception + * @throws SmartyException + */ + public function renderModal() + { + $modal_render = ''; + if (is_array($this->modals) && count($this->modals)) { + foreach ($this->modals as $modal) { + $this->context->smarty->assign($modal); + $modal_render .= $this->context->smarty->fetch('modal.tpl'); + } + } + return $modal_render; + } + + /** + * @return string + */ + public function renderModulesList() + { + // Load cache file modules list (natives and partners modules) + $xml_modules = false; + if (file_exists(_PS_ROOT_DIR_.Module::CACHE_FILE_MODULES_LIST)) { + $xml_modules = @simplexml_load_file(_PS_ROOT_DIR_.Module::CACHE_FILE_MODULES_LIST); + } + if ($xml_modules) { + foreach ($xml_modules->children() as $xml_module) { + /** @var SimpleXMLElement $xml_module */ + foreach ($xml_module->children() as $module) { + /** @var SimpleXMLElement $module */ + foreach ($module->attributes() as $key => $value) { + if ($xml_module->attributes() == 'native' && $key == 'name') { + $this->list_natives_modules[] = (string)$value; + } + if ($xml_module->attributes() == 'partner' && $key == 'name') { + $this->list_partners_modules[] = (string)$value; + } + } + } + } + } + + if ($this->getModulesList($this->filter_modules_list)) { + $tmp = array(); + foreach ($this->modules_list as $key => $module) { + if ($module->active) { + $tmp[] = $module; + unset($this->modules_list[$key]); + } + } + + $this->modules_list = array_merge($tmp, $this->modules_list); + + foreach ($this->modules_list as $key => $module) { + if (in_array($module->name, $this->list_partners_modules)) { + $this->modules_list[$key]->type = 'addonsPartner'; + } + if (isset($module->description_full) && trim($module->description_full) != '') { + $module->show_quick_view = true; + } + } + $helper = new Helper(); + return $helper->renderModulesList($this->modules_list); + } + } + + /** + * Function used to render the list to display for this controller + * + * @return string|false + * @throws PrestaShopException + */ + public function renderList() + { + if (!($this->fields_list && is_array($this->fields_list))) { + return false; + } + $this->getList($this->context->language->id); + + // If list has 'active' field, we automatically create bulk action + if (isset($this->fields_list) && is_array($this->fields_list) && array_key_exists('active', $this->fields_list) + && !empty($this->fields_list['active'])) { + if (!is_array($this->bulk_actions)) { + $this->bulk_actions = array(); + } + + $this->bulk_actions = array_merge(array( + 'enableSelection' => array( + 'text' => $this->l('Enable selection'), + 'icon' => 'icon-power-off text-success' + ), + 'disableSelection' => array( + 'text' => $this->l('Disable selection'), + 'icon' => 'icon-power-off text-danger' + ), + 'divider' => array( + 'text' => 'divider' + ) + ), $this->bulk_actions); + } + + $helper = new HelperList(); + + // Empty list is ok + if (!is_array($this->_list)) { + $this->displayWarning($this->l('Bad SQL query', 'Helper').'<br />'.htmlspecialchars($this->_list_error)); + return false; + } + + $this->setHelperDisplay($helper); + $helper->_default_pagination = $this->_default_pagination; + $helper->_pagination = $this->_pagination; + $helper->tpl_vars = $this->getTemplateListVars(); + $helper->tpl_delete_link_vars = $this->tpl_delete_link_vars; + + // For compatibility reasons, we have to check standard actions in class attributes + foreach ($this->actions_available as $action) { + if (!in_array($action, $this->actions) && isset($this->$action) && $this->$action) { + $this->actions[] = $action; + } + } + + $helper->is_cms = $this->is_cms; + $helper->sql = $this->_listsql; + $list = $helper->generateList($this->_list, $this->fields_list); + + return $list; + } + + public function getTemplateListVars() + { + return $this->tpl_list_vars; + } + + /** + * Override to render the view page + * + * @return string + */ + public function renderView() + { + $helper = new HelperView($this); + $this->setHelperDisplay($helper); + $helper->tpl_vars = $this->getTemplateViewVars(); + if (!is_null($this->base_tpl_view)) { + $helper->base_tpl = $this->base_tpl_view; + } + $view = $helper->generateView(); + + return $view; + } + + public function getTemplateViewVars() + { + return $this->tpl_view_vars; + } + + /** + * Override to render the view page + * + * @return string|false + */ + public function renderDetails() + { + return $this->renderList(); + } + + /** + * Function used to render the form for this controller + * + * @return string + * @throws Exception + * @throws SmartyException + */ + public function renderForm() + { + if (!$this->default_form_language) { + $this->getLanguages(); + } + + if (Tools::getValue('submitFormAjax')) { + $this->content .= $this->context->smarty->fetch('form_submit_ajax.tpl'); + } + + if ($this->fields_form && is_array($this->fields_form)) { + if (!$this->multiple_fieldsets) { + $this->fields_form = array(array('form' => $this->fields_form)); + } + + // For add a fields via an override of $fields_form, use $fields_form_override + if (is_array($this->fields_form_override) && !empty($this->fields_form_override)) { + $this->fields_form[0]['form']['input'] = array_merge($this->fields_form[0]['form']['input'], $this->fields_form_override); + } + + $fields_value = $this->getFieldsValue($this->object); + + Hook::exec('action'.$this->controller_name.'FormModifier', array( + 'fields' => &$this->fields_form, + 'fields_value' => &$fields_value, + 'form_vars' => &$this->tpl_form_vars, + )); + + $helper = new HelperForm($this); + $this->setHelperDisplay($helper); + $helper->fields_value = $fields_value; + $helper->submit_action = $this->submit_action; + $helper->tpl_vars = $this->getTemplateFormVars(); + $helper->show_cancel_button = (isset($this->show_form_cancel_button)) ? $this->show_form_cancel_button : ($this->display == 'add' || $this->display == 'edit'); + + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } + if (!Validate::isCleanHtml($back)) { + die(Tools::displayError()); + } + + $helper->back_url = $back; + !is_null($this->base_tpl_form) ? $helper->base_tpl = $this->base_tpl_form : ''; + if ($this->tabAccess['view']) { + if (Tools::getValue('back')) { + $helper->tpl_vars['back'] = Tools::safeOutput(Tools::getValue('back')); + } else { + $helper->tpl_vars['back'] = Tools::safeOutput(Tools::getValue(self::$currentIndex.'&token='.$this->token)); + } + } + $form = $helper->generateForm($this->fields_form); + + return $form; + } + } + + public function getTemplateFormVars() + { + return $this->tpl_form_vars; + } + + public function renderKpis() + { + } + + /** + * Function used to render the options for this controller + * + * @return string + */ + public function renderOptions() + { + Hook::exec('action'.$this->controller_name.'OptionsModifier', array( + 'options' => &$this->fields_options, + 'option_vars' => &$this->tpl_option_vars, + )); + + if ($this->fields_options && is_array($this->fields_options)) { + if (isset($this->display) && $this->display != 'options' && $this->display != 'list') { + $this->show_toolbar = false; + } else { + $this->display = 'options'; + } + + unset($this->toolbar_btn); + $this->initToolbar(); + $helper = new HelperOptions($this); + $this->setHelperDisplay($helper); + $helper->id = $this->id; + $helper->tpl_vars = $this->tpl_option_vars; + $options = $helper->generateOptions($this->fields_options); + + return $options; + } + } + + /** + * This function sets various display options for helper list + * + * @param Helper $helper + * @return void + */ + public function setHelperDisplay(Helper $helper) + { + if (empty($this->toolbar_title)) { + $this->initToolbarTitle(); + } + // tocheck + if ($this->object && $this->object->id) { + $helper->id = $this->object->id; + } + + // @todo : move that in Helper + $helper->title = is_array($this->toolbar_title) ? implode(' '.Configuration::get('PS_NAVIGATION_PIPE').' ', $this->toolbar_title) : $this->toolbar_title; + $helper->toolbar_btn = $this->toolbar_btn; + $helper->show_toolbar = $this->show_toolbar; + $helper->toolbar_scroll = $this->toolbar_scroll; + $helper->override_folder = $this->tpl_folder; + $helper->actions = $this->actions; + $helper->simple_header = $this->list_simple_header; + $helper->bulk_actions = $this->bulk_actions; + $helper->currentIndex = self::$currentIndex; + $helper->className = $this->className; + $helper->table = $this->table; + $helper->name_controller = Tools::getValue('controller'); + $helper->orderBy = $this->_orderBy; + $helper->orderWay = $this->_orderWay; + $helper->listTotal = $this->_listTotal; + $helper->shopLink = $this->shopLink; + $helper->shopLinkType = $this->shopLinkType; + $helper->identifier = $this->identifier; + $helper->token = $this->token; + $helper->languages = $this->_languages; + $helper->specificConfirmDelete = $this->specificConfirmDelete; + $helper->imageType = $this->imageType; + $helper->no_link = $this->list_no_link; + $helper->colorOnBackground = $this->colorOnBackground; + $helper->ajax_params = (isset($this->ajax_params) ? $this->ajax_params : null); + $helper->default_form_language = $this->default_form_language; + $helper->allow_employee_form_lang = $this->allow_employee_form_lang; + $helper->multiple_fieldsets = $this->multiple_fieldsets; + $helper->row_hover = $this->row_hover; + $helper->position_identifier = $this->position_identifier; + $helper->position_group_identifier = $this->position_group_identifier; + $helper->controller_name = $this->controller_name; + $helper->list_id = isset($this->list_id) ? $this->list_id : $this->table; + $helper->bootstrap = $this->bootstrap; + + // For each action, try to add the corresponding skip elements list + $helper->list_skip_actions = $this->list_skip_actions; + + $this->helper = $helper; + } + + /** + * @deprecated 1.6.0 + */ + public function setDeprecatedMedia() + { + } + + public function setMedia() + { + //Bootstrap + $this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/'.$this->bo_css, 'all', 0); + + $this->addJquery(); + $this->addjQueryPlugin(array('scrollTo', 'alerts', 'chosen', 'autosize', 'fancybox' )); + $this->addjQueryPlugin('growl', null, false); + $this->addJqueryUI(array('ui.slider', 'ui.datepicker')); + + Media::addJsDef(array('host_mode' => (defined('_PS_HOST_MODE_') && _PS_HOST_MODE_))); + + $this->addJS(array( + _PS_JS_DIR_.'admin.js', + _PS_JS_DIR_.'tools.js', + _PS_JS_DIR_.'jquery/plugins/timepicker/jquery-ui-timepicker-addon.js' + )); + + //loads specific javascripts for the admin theme + $this->addJS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/vendor/bootstrap.min.js'); + $this->addJS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/vendor/modernizr.min.js'); + $this->addJS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/modernizr-loads.js'); + $this->addJS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/vendor/moment-with-langs.min.js'); + + if (!$this->lite_display) { + $this->addJS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/help.js'); + } + + if (!Tools::getValue('submitFormAjax')) { + $this->addJS(_PS_JS_DIR_.'admin/notifications.js'); + } + + if (defined('_PS_HOST_MODE_') && _PS_HOST_MODE_) { + $this->addJS('https://cdn.statuspage.io/se-v2.js'); + + Media::addJsDefL('status_operational', $this->l('Operational', null, true, false)); + Media::addJsDefL('status_degraded_performance', $this->l('Degraded Performance', null, true, false)); + Media::addJsDefL('status_partial_outage', $this->l('Partial Outage', null, true, false)); + Media::addJsDefL('status_major_outage', $this->l('Major Outage', null, true, false)); + Media::addJsDef(array('host_cluster' => defined('_PS_HOST_CLUSTER_') ? _PS_HOST_CLUSTER_ : 'fr1')); + } + + // Execute Hook AdminController SetMedia + Hook::exec('actionAdminControllerSetMedia'); + + // Specific Admin Theme + $this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/overrides.css', 'all', PHP_INT_MAX); + } + + /** + * Non-static method which uses AdminController::translate() + * + * @param string $string Term or expression in english + * @param string|null $class Name of the class + * @param bool $addslashes If set to true, the return value will pass through addslashes(). Otherwise, stripslashes(). + * @param bool $htmlentities If set to true(default), the return value will pass through htmlentities($string, ENT_QUOTES, 'utf-8') + * @return string The translation if available, or the english default text. + */ + protected function l($string, $class = null, $addslashes = false, $htmlentities = true) + { + if ($class === null || $class == 'AdminTab') { + $class = substr(get_class($this), 0, -10); + } elseif (strtolower(substr($class, -10)) == 'controller') { + /* classname has changed, from AdminXXX to AdminXXXController, so we remove 10 characters and we keep same keys */ + $class = substr($class, 0, -10); + } + return Translate::getAdminTranslation($string, $class, $addslashes, $htmlentities); + } + + /** + * Init context and dependencies, handles POST and GET + */ + public function init() + { + // Has to be removed for the next Prestashop version + global $currentIndex; + + parent::init(); + + if (Tools::getValue('ajax')) { + $this->ajax = '1'; + } + + /* Server Params */ + $protocol_link = (Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) ? 'https://' : 'http://'; + $protocol_content = (Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) ? 'https://' : 'http://'; + + $this->context->link = new Link($protocol_link, $protocol_content); + + if (isset($_GET['logout'])) { + $this->context->employee->logout(); + } + + if (isset(Context::getContext()->cookie->last_activity)) { + if ($this->context->cookie->last_activity + 900 < time()) { + $this->context->employee->logout(); + } else { + $this->context->cookie->last_activity = time(); + } + } + + if ($this->controller_name != 'AdminLogin' && (!isset($this->context->employee) || !$this->context->employee->isLoggedBack())) { + if (isset($this->context->employee)) { + $this->context->employee->logout(); + } + + $email = false; + if (Tools::getValue('email') && Validate::isEmail(Tools::getValue('email'))) { + $email = Tools::getValue('email'); + } + + Tools::redirectAdmin($this->context->link->getAdminLink('AdminLogin').((!isset($_GET['logout']) && $this->controller_name != 'AdminNotFound' && Tools::getValue('controller')) ? '&redirect='.$this->controller_name : '').($email ? '&email='.$email : '')); + } + + // Set current index + $current_index = 'index.php'.(($controller = Tools::getValue('controller')) ? '?controller='.$controller : ''); + if ($back = Tools::getValue('back')) { + $current_index .= '&back='.urlencode($back); + } + self::$currentIndex = $current_index; + $currentIndex = $current_index; + + if ((int)Tools::getValue('liteDisplaying')) { + $this->display_header = false; + $this->display_header_javascript = true; + $this->display_footer = false; + $this->content_only = false; + $this->lite_display = true; + } + + if ($this->ajax && method_exists($this, 'ajaxPreprocess')) { + $this->ajaxPreProcess(); + } + + $this->context->smarty->assign(array( + 'table' => $this->table, + 'current' => self::$currentIndex, + 'token' => $this->token, + 'host_mode' => defined('_PS_HOST_MODE_') ? 1 : 0, + 'stock_management' => (int)Configuration::get('PS_STOCK_MANAGEMENT') + )); + + if ($this->display_header) { + $this->context->smarty->assign('displayBackOfficeHeader', Hook::exec('displayBackOfficeHeader', array())); + } + + $this->context->smarty->assign(array( + 'displayBackOfficeTop' => Hook::exec('displayBackOfficeTop', array()), + 'submit_form_ajax' => (int)Tools::getValue('submitFormAjax') + )); + + Employee::setLastConnectionDate($this->context->employee->id); + + $this->initProcess(); + $this->initBreadcrumbs(); + $this->initModal(); + } + + /** + * @throws PrestaShopException + */ + public function initShopContext() + { + if (!$this->context->employee->isLoggedBack()) { + return; + } + + // Change shop context ? + if (Shop::isFeatureActive() && Tools::getValue('setShopContext') !== false) { + $this->context->cookie->shopContext = Tools::getValue('setShopContext'); + $url = parse_url($_SERVER['REQUEST_URI']); + $query = (isset($url['query'])) ? $url['query'] : ''; + parse_str($query, $parse_query); + unset($parse_query['setShopContext'], $parse_query['conf']); + $this->redirect_after = $url['path'].'?'.http_build_query($parse_query, '', '&'); + } elseif (!Shop::isFeatureActive()) { + $this->context->cookie->shopContext = 's-'.(int)Configuration::get('PS_SHOP_DEFAULT'); + } elseif (Shop::getTotalShops(false, null) < 2) { + $this->context->cookie->shopContext = 's-'.(int)$this->context->employee->getDefaultShopID(); + } + + $shop_id = ''; + Shop::setContext(Shop::CONTEXT_ALL); + if ($this->context->cookie->shopContext) { + $split = explode('-', $this->context->cookie->shopContext); + if (count($split) == 2) { + if ($split[0] == 'g') { + if ($this->context->employee->hasAuthOnShopGroup((int)$split[1])) { + Shop::setContext(Shop::CONTEXT_GROUP, (int)$split[1]); + } else { + $shop_id = (int)$this->context->employee->getDefaultShopID(); + Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); + } + } elseif (Shop::getShop($split[1]) && $this->context->employee->hasAuthOnShop($split[1])) { + $shop_id = (int)$split[1]; + Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); + } else { + $shop_id = (int)$this->context->employee->getDefaultShopID(); + Shop::setContext(Shop::CONTEXT_SHOP, $shop_id); + } + } + } + + // Check multishop context and set right context if need + if (!($this->multishop_context & Shop::getContext())) { + if (Shop::getContext() == Shop::CONTEXT_SHOP && !($this->multishop_context & Shop::CONTEXT_SHOP)) { + Shop::setContext(Shop::CONTEXT_GROUP, Shop::getContextShopGroupID()); + } + if (Shop::getContext() == Shop::CONTEXT_GROUP && !($this->multishop_context & Shop::CONTEXT_GROUP)) { + Shop::setContext(Shop::CONTEXT_ALL); + } + } + + // Replace existing shop if necessary + if (!$shop_id) { + $this->context->shop = new Shop((int)Configuration::get('PS_SHOP_DEFAULT')); + } elseif ($this->context->shop->id != $shop_id) { + $this->context->shop = new Shop((int)$shop_id); + } + + if ($this->context->shop->id_theme != $this->context->theme->id) { + $this->context->theme = new Theme((int)$this->context->shop->id_theme); + } + + // Replace current default country + $this->context->country = new Country((int)Configuration::get('PS_COUNTRY_DEFAULT')); + } + + /** + * Retrieve GET and POST value and translate them to actions + */ + public function initProcess() + { + if (!isset($this->list_id)) { + $this->list_id = $this->table; + } + + // Manage list filtering + if (Tools::isSubmit('submitFilter'.$this->list_id) + || $this->context->cookie->{'submitFilter'.$this->list_id} !== false + || Tools::getValue($this->list_id.'Orderby') + || Tools::getValue($this->list_id.'Orderway')) { + $this->filter = true; + } + + $this->id_object = (int)Tools::getValue($this->identifier); + + /* Delete object image */ + if (isset($_GET['deleteImage'])) { + if ($this->tabAccess['delete'] === '1') { + $this->action = 'delete_image'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } elseif (isset($_GET['delete'.$this->table])) { + /* Delete object */ + if ($this->tabAccess['delete'] === '1') { + $this->action = 'delete'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } elseif ((isset($_GET['status'.$this->table]) || isset($_GET['status'])) && Tools::getValue($this->identifier)) { + /* Change object statuts (active, inactive) */ + if ($this->tabAccess['edit'] === '1') { + $this->action = 'status'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (isset($_GET['position'])) { + /* Move an object */ + if ($this->tabAccess['edit'] == '1') { + $this->action = 'position'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('submitAdd'.$this->table) + || Tools::isSubmit('submitAdd'.$this->table.'AndStay') + || Tools::isSubmit('submitAdd'.$this->table.'AndPreview') + || Tools::isSubmit('submitAdd'.$this->table.'AndBackToParent')) { + // case 1: updating existing entry + if ($this->id_object) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'save'; + if (Tools::isSubmit('submitAdd'.$this->table.'AndStay')) { + $this->display = 'edit'; + } else { + $this->display = 'list'; + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } else { + // case 2: creating new entry + if ($this->tabAccess['add'] === '1') { + $this->action = 'save'; + if (Tools::isSubmit('submitAdd'.$this->table.'AndStay')) { + $this->display = 'edit'; + } else { + $this->display = 'list'; + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } + } elseif (isset($_GET['add'.$this->table])) { + if ($this->tabAccess['add'] === '1') { + $this->action = 'new'; + $this->display = 'add'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } elseif (isset($_GET['update'.$this->table]) && isset($_GET[$this->identifier])) { + $this->display = 'edit'; + if ($this->tabAccess['edit'] !== '1') { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (isset($_GET['view'.$this->table])) { + if ($this->tabAccess['view'] === '1') { + $this->display = 'view'; + $this->action = 'view'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to view this.'); + } + } elseif (isset($_GET['details'.$this->table])) { + if ($this->tabAccess['view'] === '1') { + $this->display = 'details'; + $this->action = 'details'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to view this.'); + } + } elseif (isset($_GET['export'.$this->table])) { + if ($this->tabAccess['view'] === '1') { + $this->action = 'export'; + } + } elseif (isset($_POST['submitReset'.$this->list_id])) { + /* Cancel all filters for this tab */ + $this->action = 'reset_filters'; + } elseif (Tools::isSubmit('submitOptions'.$this->table) || Tools::isSubmit('submitOptions')) { + /* Submit options list */ + $this->display = 'options'; + if ($this->tabAccess['edit'] === '1') { + $this->action = 'update_options'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::getValue('action') && method_exists($this, 'process'.ucfirst(Tools::toCamelCase(Tools::getValue('action'))))) { + $this->action = Tools::getValue('action'); + } elseif (Tools::isSubmit('submitFields') && $this->required_database && $this->tabAccess['add'] === '1' && $this->tabAccess['delete'] === '1') { + $this->action = 'update_fields'; + } elseif (is_array($this->bulk_actions)) { + $submit_bulk_actions = array_merge(array( + 'enableSelection' => array( + 'text' => $this->l('Enable selection'), + 'icon' => 'icon-power-off text-success' + ), + 'disableSelection' => array( + 'text' => $this->l('Disable selection'), + 'icon' => 'icon-power-off text-danger' + ) + ), $this->bulk_actions); + foreach ($submit_bulk_actions as $bulk_action => $params) { + if (Tools::isSubmit('submitBulk'.$bulk_action.$this->table) || Tools::isSubmit('submitBulk'.$bulk_action)) { + if ($bulk_action === 'delete') { + if ($this->tabAccess['delete'] === '1') { + $this->action = 'bulk'.$bulk_action; + $this->boxes = Tools::getValue($this->table.'Box'); + if (empty($this->boxes) && $this->table == 'attribute') { + $this->boxes = Tools::getValue($this->table.'_valuesBox'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + break; + } elseif ($this->tabAccess['edit'] === '1') { + $this->action = 'bulk'.$bulk_action; + $this->boxes = Tools::getValue($this->table.'Box'); + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + break; + } elseif (Tools::isSubmit('submitBulk')) { + if ($bulk_action === 'delete') { + if ($this->tabAccess['delete'] === '1') { + $this->action = 'bulk'.$bulk_action; + $this->boxes = Tools::getValue($this->table.'Box'); + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + break; + } elseif ($this->tabAccess['edit'] === '1') { + $this->action = 'bulk'.Tools::getValue('select_submitBulk'); + $this->boxes = Tools::getValue($this->table.'Box'); + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + break; + } + } + } elseif (!empty($this->fields_options) && empty($this->fields_list)) { + $this->display = 'options'; + } + } + + /** + * Get the current objects' list form the database + * + * @param int $id_lang Language used for display + * @param string|null $order_by ORDER BY clause + * @param string|null $order_way Order way (ASC, DESC) + * @param int $start Offset in LIMIT clause + * @param int|null $limit Row count in LIMIT clause + * @param int|bool $id_lang_shop + * @throws PrestaShopDatabaseException + * @throws PrestaShopException + */ + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + Hook::exec('action'.$this->controller_name.'ListingFieldsModifier', array( + 'select' => &$this->_select, + 'join' => &$this->_join, + 'where' => &$this->_where, + 'group_by' => &$this->_group, + 'order_by' => &$this->_orderBy, + 'order_way' => &$this->_orderWay, + 'fields' => &$this->fields_list, + )); + + if (!isset($this->list_id)) { + $this->list_id = $this->table; + } + + /* Manage default params values */ + $use_limit = true; + if ($limit === false) { + $use_limit = false; + } elseif (empty($limit)) { + if (isset($this->context->cookie->{$this->list_id.'_pagination'}) && $this->context->cookie->{$this->list_id.'_pagination'}) { + $limit = $this->context->cookie->{$this->list_id.'_pagination'}; + } else { + $limit = $this->_default_pagination; + } + } + + if (!Validate::isTableOrIdentifier($this->table)) { + throw new PrestaShopException(sprintf('Table name %s is invalid:', $this->table)); + } + $prefix = str_replace(array('admin', 'controller'), '', Tools::strtolower(get_class($this))); + if (empty($order_by)) { + if ($this->context->cookie->{$prefix.$this->list_id.'Orderby'}) { + $order_by = $this->context->cookie->{$prefix.$this->list_id.'Orderby'}; + } elseif ($this->_orderBy) { + $order_by = $this->_orderBy; + } else { + $order_by = $this->_defaultOrderBy; + } + } + + if (empty($order_way)) { + if ($this->context->cookie->{$prefix.$this->list_id.'Orderway'}) { + $order_way = $this->context->cookie->{$prefix.$this->list_id.'Orderway'}; + } elseif ($this->_orderWay) { + $order_way = $this->_orderWay; + } else { + $order_way = $this->_defaultOrderWay; + } + } + + $limit = (int)Tools::getValue($this->list_id.'_pagination', $limit); + if (in_array($limit, $this->_pagination) && $limit != $this->_default_pagination) { + $this->context->cookie->{$this->list_id.'_pagination'} = $limit; + } else { + unset($this->context->cookie->{$this->list_id.'_pagination'}); + } + + /* Check params validity */ + if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way) + || !is_numeric($start) || !is_numeric($limit) + || !Validate::isUnsignedId($id_lang)) { + throw new PrestaShopException('get list params is not valid'); + } + + if (!isset($this->fields_list[$order_by]['order_key']) && isset($this->fields_list[$order_by]['filter_key'])) { + $this->fields_list[$order_by]['order_key'] = $this->fields_list[$order_by]['filter_key']; + } + + if (isset($this->fields_list[$order_by]) && isset($this->fields_list[$order_by]['order_key'])) { + $order_by = $this->fields_list[$order_by]['order_key']; + } + + /* Determine offset from current page */ + $start = 0; + if ((int)Tools::getValue('submitFilter'.$this->list_id)) { + $start = ((int)Tools::getValue('submitFilter'.$this->list_id) - 1) * $limit; + } elseif (empty($start) && isset($this->context->cookie->{$this->list_id.'_start'}) && Tools::isSubmit('export'.$this->table)) { + $start = $this->context->cookie->{$this->list_id.'_start'}; + } + + // Either save or reset the offset in the cookie + if ($start) { + $this->context->cookie->{$this->list_id.'_start'} = $start; + } elseif (isset($this->context->cookie->{$this->list_id.'_start'})) { + unset($this->context->cookie->{$this->list_id.'_start'}); + } + + /* Cache */ + $this->_lang = (int)$id_lang; + $this->_orderBy = $order_by; + + if (preg_match('/[.!]/', $order_by)) { + $order_by_split = preg_split('/[.!]/', $order_by); + $order_by = bqSQL($order_by_split[0]).'.`'.bqSQL($order_by_split[1]).'`'; + } elseif ($order_by) { + $order_by = '`'.bqSQL($order_by).'`'; + } + + $this->_orderWay = Tools::strtoupper($order_way); + + /* SQL table : orders, but class name is Order */ + $sql_table = $this->table == 'order' ? 'orders' : $this->table; + + // Add SQL shop restriction + $select_shop = $join_shop = $where_shop = ''; + if ($this->shopLinkType) { + $select_shop = ', shop.name as shop_name '; + $join_shop = ' LEFT JOIN '._DB_PREFIX_.$this->shopLinkType.' shop ON a.id_'.$this->shopLinkType.' = shop.id_'.$this->shopLinkType; - $where_shop = Shop::addSqlRestriction($this->shopShareDatas, 'a', $this->shopLinkType); - } + $where_shop = Shop::addSqlRestriction($this->shopShareDatas, 'a', $this->shopLinkType); + } - if ($this->multishop_context && Shop::isTableAssociated($this->table) && !empty($this->className)) - { - if (Shop::getContext() != Shop::CONTEXT_ALL || !$this->context->employee->isSuperAdmin()) - { - $test_join = !preg_match('#`?'.preg_quote(_DB_PREFIX_.$this->table.'_shop').'`? *sa#', $this->_join); - if (Shop::isFeatureActive() && $test_join && Shop::isTableAssociated($this->table)) - { - $this->_where .= ' AND EXISTS ( + if ($this->multishop_context && Shop::isTableAssociated($this->table) && !empty($this->className)) { + if (Shop::getContext() != Shop::CONTEXT_ALL || !$this->context->employee->isSuperAdmin()) { + $test_join = !preg_match('#`?'.preg_quote(_DB_PREFIX_.$this->table.'_shop').'`? *sa#', $this->_join); + if (Shop::isFeatureActive() && $test_join && Shop::isTableAssociated($this->table)) { + $this->_where .= ' AND EXISTS ( SELECT 1 FROM `'._DB_PREFIX_.$this->table.'_shop` sa WHERE a.'.$this->identifier.' = sa.'.$this->identifier.' AND sa.id_shop IN ('.implode(', ', Shop::getContextListShopID()).') )'; - } - } - } + } + } + } - /* Query in order to get results with all fields */ - $lang_join = ''; - if ($this->lang) - { - $lang_join = 'LEFT JOIN `'._DB_PREFIX_.$this->table.'_lang` b ON (b.`'.$this->identifier.'` = a.`'.$this->identifier.'` AND b.`id_lang` = '.(int)$id_lang; - if ($id_lang_shop) - { - if (!Shop::isFeatureActive()) - $lang_join .= ' AND b.`id_shop` = '.(int)Configuration::get('PS_SHOP_DEFAULT'); - elseif (Shop::getContext() == Shop::CONTEXT_SHOP) - $lang_join .= ' AND b.`id_shop` = '.(int)$id_lang_shop; - else - $lang_join .= ' AND b.`id_shop` = a.id_shop_default'; - } - $lang_join .= ')'; - } + /* Query in order to get results with all fields */ + $lang_join = ''; + if ($this->lang) { + $lang_join = 'LEFT JOIN `'._DB_PREFIX_.$this->table.'_lang` b ON (b.`'.$this->identifier.'` = a.`'.$this->identifier.'` AND b.`id_lang` = '.(int)$id_lang; + if ($id_lang_shop) { + if (!Shop::isFeatureActive()) { + $lang_join .= ' AND b.`id_shop` = '.(int)Configuration::get('PS_SHOP_DEFAULT'); + } elseif (Shop::getContext() == Shop::CONTEXT_SHOP) { + $lang_join .= ' AND b.`id_shop` = '.(int)$id_lang_shop; + } else { + $lang_join .= ' AND b.`id_shop` = a.id_shop_default'; + } + } + $lang_join .= ')'; + } - $having_clause = ''; - if (isset($this->_filterHaving) || isset($this->_having)) - { - $having_clause = ' HAVING '; - if (isset($this->_filterHaving)) - $having_clause .= ltrim($this->_filterHaving, ' AND '); - if (isset($this->_having)) - $having_clause .= $this->_having.' '; - } + $having_clause = ''; + if (isset($this->_filterHaving) || isset($this->_having)) { + $having_clause = ' HAVING '; + if (isset($this->_filterHaving)) { + $having_clause .= ltrim($this->_filterHaving, ' AND '); + } + if (isset($this->_having)) { + $having_clause .= $this->_having.' '; + } + } - do - { - $this->_listsql = ''; + do { + $this->_listsql = ''; - if ($this->explicitSelect) - { - foreach ($this->fields_list as $key => $array_value) - { - // Add it only if it is not already in $this->_select - if (isset($this->_select) && preg_match('/[\s]`?'.preg_quote($key, '/').'`?\s*,/', $this->_select)) - continue; + if ($this->explicitSelect) { + foreach ($this->fields_list as $key => $array_value) { + // Add it only if it is not already in $this->_select + if (isset($this->_select) && preg_match('/[\s]`?'.preg_quote($key, '/').'`?\s*,/', $this->_select)) { + continue; + } - if (isset($array_value['filter_key'])) - $this->_listsql .= str_replace('!', '.`', $array_value['filter_key']).'` AS `'.$key.'`, '; - elseif ($key == 'id_'.$this->table) - $this->_listsql .= 'a.`'.bqSQL($key).'`, '; - elseif ($key != 'image' && !preg_match('/'.preg_quote($key, '/').'/i', $this->_select)) - $this->_listsql .= '`'.bqSQL($key).'`, '; - } - $this->_listsql = rtrim(trim($this->_listsql), ','); - } - else - $this->_listsql .= ($this->lang ? 'b.*,' : '').' a.*'; + if (isset($array_value['filter_key'])) { + $this->_listsql .= str_replace('!', '.`', $array_value['filter_key']).'` AS `'.$key.'`, '; + } elseif ($key == 'id_'.$this->table) { + $this->_listsql .= 'a.`'.bqSQL($key).'`, '; + } elseif ($key != 'image' && !preg_match('/'.preg_quote($key, '/').'/i', $this->_select)) { + $this->_listsql .= '`'.bqSQL($key).'`, '; + } + } + $this->_listsql = rtrim(trim($this->_listsql), ','); + } else { + $this->_listsql .= ($this->lang ? 'b.*,' : '').' a.*'; + } - $this->_listsql .= ' + $this->_listsql .= ' '.(isset($this->_select) ? ', '.rtrim($this->_select, ', ') : '').$select_shop; - $sql_from = ' + $sql_from = ' FROM `'._DB_PREFIX_.$sql_table.'` a '; - $sql_join = ' + $sql_join = ' '.$lang_join.' '.(isset($this->_join) ? $this->_join.' ' : '').' '.$join_shop; - $sql_where = ' '.(isset($this->_where) ? $this->_where.' ' : '').($this->deleted ? 'AND a.`deleted` = 0 ' : ''). - (isset($this->_filter) ? $this->_filter : '').$where_shop.' + $sql_where = ' '.(isset($this->_where) ? $this->_where.' ' : '').($this->deleted ? 'AND a.`deleted` = 0 ' : ''). + (isset($this->_filter) ? $this->_filter : '').$where_shop.' '.(isset($this->_group) ? $this->_group.' ' : '').' '.$having_clause; - $sql_order_by = ' ORDER BY '.((str_replace('`', '', $order_by) == $this->identifier) ? 'a.' : '').$order_by.' '.pSQL($order_way). - ($this->_tmpTableFilter ? ') tmpTable WHERE 1'.$this->_tmpTableFilter : ''); - $sql_limit = ' '.(($use_limit === true) ? ' LIMIT '.(int)$start.', '.(int)$limit : ''); + $sql_order_by = ' ORDER BY '.((str_replace('`', '', $order_by) == $this->identifier) ? 'a.' : '').$order_by.' '.pSQL($order_way). + ($this->_tmpTableFilter ? ') tmpTable WHERE 1'.$this->_tmpTableFilter : ''); + $sql_limit = ' '.(($use_limit === true) ? ' LIMIT '.(int)$start.', '.(int)$limit : ''); - if ($this->_use_found_rows) - { - $this->_listsql = 'SELECT SQL_CALC_FOUND_ROWS + if ($this->_use_found_rows || isset($this->_filterHaving) || isset($this->_having)) { + $this->_listsql = 'SELECT SQL_CALC_FOUND_ROWS '.($this->_tmpTableFilter ? ' * FROM (SELECT ' : '').$this->_listsql.$sql_from.$sql_join.' WHERE 1 '.$sql_where. - $sql_order_by.$sql_limit; - $list_count = 'SELECT FOUND_ROWS() AS `'._DB_PREFIX_.$this->table.'`'; - } - else - { - $this->_listsql = 'SELECT + $sql_order_by.$sql_limit; + $list_count = 'SELECT FOUND_ROWS() AS `'._DB_PREFIX_.$this->table.'`'; + } else { + $this->_listsql = 'SELECT '.($this->_tmpTableFilter ? ' * FROM (SELECT ' : '').$this->_listsql.$sql_from.$sql_join.' WHERE 1 '.$sql_where. - $sql_order_by.$sql_limit; - $list_count = 'SELECT COUNT(*) AS `'._DB_PREFIX_.$this->table.'` '.$sql_from.$sql_join.' WHERE 1 '.$sql_where; - } - - $this->_list = Db::getInstance()->executeS($this->_listsql, true, false); - - if ($this->_list === false) - { - $this->_list_error = Db::getInstance()->getMsgError(); - break; - } - - $this->_listTotal = Db::getInstance()->getValue($list_count, false); - - if ($use_limit === true) - { - $start = (int)$start - (int)$limit; - if ($start < 0) - break; - } - else - break; - - } while (empty($this->_list)); - - Hook::exec('action'.$this->controller_name.'ListingResultsModifier', array( - 'list' => &$this->_list, - 'list_total' => &$this->_listTotal, - )); - } - - /** - * @param array|string $filter_modules_list - * @return bool - * @throws PrestaShopException - */ - public function getModulesList($filter_modules_list) - { - if (!is_array($filter_modules_list) && !is_null($filter_modules_list)) - $filter_modules_list = array($filter_modules_list); - - if (!count($filter_modules_list)) - return false; //if there is no modules to display just return false; - - $all_modules = Module::getModulesOnDisk(true); - $this->modules_list = array(); - foreach ($all_modules as $module) - { - $perm = true; - if ($module->id) - $perm &= Module::getPermissionStatic($module->id, 'configure'); - else - { - $id_admin_module = Tab::getIdFromClassName('AdminModules'); - $access = Profile::getProfileAccess($this->context->employee->id_profile, $id_admin_module); - if (!$access['edit']) - $perm &= false; - } - - if (in_array($module->name, $filter_modules_list) && $perm) - { - $this->fillModuleData($module, 'array'); - $this->modules_list[array_search($module->name, $filter_modules_list)] = $module; - } - } - ksort($this->modules_list); - - if (count($this->modules_list)) - return true; - - return false; //no module found on disk just return false; - - } - - /** - * @return array - */ - public function getLanguages() - { - $cookie = $this->context->cookie; - $this->allow_employee_form_lang = (int)Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG'); - if ($this->allow_employee_form_lang && !$cookie->employee_form_lang) - $cookie->employee_form_lang = (int)Configuration::get('PS_LANG_DEFAULT'); - - $lang_exists = false; - $this->_languages = Language::getLanguages(false); - foreach ($this->_languages as $lang) - if (isset($cookie->employee_form_lang) && $cookie->employee_form_lang == $lang['id_lang']) - $lang_exists = true; - - $this->default_form_language = $lang_exists ? (int)$cookie->employee_form_lang : (int)Configuration::get('PS_LANG_DEFAULT'); - - foreach ($this->_languages as $k => $language) - $this->_languages[$k]['is_default'] = (int)($language['id_lang'] == $this->default_form_language); - - return $this->_languages; - } - - - /** - * Return the list of fields value - * - * @param ObjectModel $obj Object - * @return array - */ - public function getFieldsValue($obj) - { - foreach ($this->fields_form as $fieldset) - if (isset($fieldset['form']['input'])) - foreach ($fieldset['form']['input'] as $input) - if (!isset($this->fields_value[$input['name']])) - if (isset($input['type']) && $input['type'] == 'shop') - { - if ($obj->id) - { - $result = Shop::getShopById((int)$obj->id, $this->identifier, $this->table); - foreach ($result as $row) - $this->fields_value['shop'][$row['id_'.$input['type']]][] = $row['id_shop']; - } - } - elseif (isset($input['lang']) && $input['lang']) - foreach ($this->_languages as $language) - { - $field_value = $this->getFieldValue($obj, $input['name'], $language['id_lang']); - if (empty($field_value)) - { - if (isset($input['default_value']) && is_array($input['default_value']) && isset($input['default_value'][$language['id_lang']])) - $field_value = $input['default_value'][$language['id_lang']]; - elseif (isset($input['default_value'])) - $field_value = $input['default_value']; - } - $this->fields_value[$input['name']][$language['id_lang']] = $field_value; - } - else - { - $field_value = $this->getFieldValue($obj, $input['name']); - if ($field_value === false && isset($input['default_value'])) - $field_value = $input['default_value']; - $this->fields_value[$input['name']] = $field_value; - } - - return $this->fields_value; - } - - /** - * Return field value if possible (both classical and multilingual fields) - * - * Case 1 : Return value if present in $_POST / $_GET - * Case 2 : Return object value - * - * @param ObjectModel $obj Object - * @param string $key Field name - * @param int|null $id_lang Language id (optional) - * @return string - */ - public function getFieldValue($obj, $key, $id_lang = null) - { - if ($id_lang) - $default_value = (isset($obj->id) && $obj->id && isset($obj->{$key}[$id_lang])) ? $obj->{$key}[$id_lang] : false; - else - $default_value = isset($obj->{$key}) ? $obj->{$key} : false; - - return Tools::getValue($key.($id_lang ? '_'.$id_lang : ''), $default_value); - } - - /** - * Manage page display (form, list...) - * - * @param string|bool $class_name Allow to validate a different class than the current one - * @throws PrestaShopException - */ - public function validateRules($class_name = false) - { - if (!$class_name) - $class_name = $this->className; - - /** @var $object ObjectModel */ - $object = new $class_name(); - - if (method_exists($this, 'getValidationRules')) - $definition = $this->getValidationRules(); - else - $definition = ObjectModel::getDefinition($class_name); - - $default_language = new Language((int)Configuration::get('PS_LANG_DEFAULT')); - $languages = Language::getLanguages(false); - - foreach ($definition['fields'] as $field => $def) - { - $skip = array(); - if (in_array($field, array('passwd', 'no-picture'))) - $skip = array('required'); - - if (isset($def['lang']) && $def['lang']) - { - if (isset($def['required']) && $def['required']) - { - $value = Tools::getValue($field.'_'.$default_language->id); - if (empty($value)) - $this->errors[$field.'_'.$default_language->id] = sprintf( - Tools::displayError('The field %1$s is required at least in %2$s.'), - $object->displayFieldName($field, $class_name), - $default_language->name - ); - } - - foreach ($languages as $language) - { - $value = Tools::getValue($field.'_'.$language['id_lang']); - if (!empty($value)) - if (($error = $object->validateField($field, $value, $language['id_lang'], $skip, true)) !== true) - $this->errors[$field.'_'.$language['id_lang']] = $error; - } - } - elseif (($error = $object->validateField($field, Tools::getValue($field), null, $skip, true)) !== true) - $this->errors[$field] = $error; - } - - /* Overload this method for custom checking */ - $this->_childValidation(); - - /* Checking for multilingual fields validity */ - if (isset($rules['validateLang']) && is_array($rules['validateLang'])) - foreach ($rules['validateLang'] as $field_lang => $function) - foreach ($languages as $language) - if (($value = Tools::getValue($field_lang.'_'.$language['id_lang'])) !== false && !empty($value)) - { - if (Tools::strtolower($function) == 'iscleanhtml' && Configuration::get('PS_ALLOW_HTML_IFRAME')) - $res = Validate::$function($value, true); - else - $res = Validate::$function($value); - if (!$res) - $this->errors[$field_lang.'_'.$language['id_lang']] = sprintf( - Tools::displayError('The %1$s field (%2$s) is invalid.'), - call_user_func(array($class_name, 'displayFieldName'), $field_lang, $class_name), - $language['name'] - ); - } - } - - /** - * Overload this method for custom checking - */ - protected function _childValidation() - { - } - - /** - * Display object details - */ - public function viewDetails() - { - } - - /** - * Called before deletion - * - * @param ObjectModel $object Object - * @return bool - */ - protected function beforeDelete($object) - { - return false; - } - - /** - * Called before deletion - * - * @param ObjectModel $object Object - * @param int $old_id - * @return bool - */ - protected function afterDelete($object, $old_id) - { - return true; - } - - /** - * @param ObjectModel $object - * @return bool - */ - protected function afterAdd($object) - { - return true; - } - - /** - * @param ObjectModel $object - * @return bool - */ - protected function afterUpdate($object) - { - return true; - } - - /** - * Check rights to view the current tab - * - * @return bool - */ - protected function afterImageUpload() - { - return true; - } - - /** - * Copy data values from $_POST to object - * - * @param ObjectModel &$object Object - * @param string $table Object table - */ - protected function copyFromPost(&$object, $table) - { - /* Classical fields */ - foreach ($_POST as $key => $value) - if (array_key_exists($key, $object) && $key != 'id_'.$table) - { - /* Do not take care of password field if empty */ - if ($key == 'passwd' && Tools::getValue('id_'.$table) && empty($value)) - continue; - /* Automatically encrypt password in MD5 */ - if ($key == 'passwd' && !empty($value)) - $value = Tools::encrypt($value); - $object->{$key} = $value; - } - - /* Multilingual fields */ - $class_vars = get_class_vars(get_class($object)); - $fields = array(); - if (isset($class_vars['definition']['fields'])) - $fields = $class_vars['definition']['fields']; - - foreach ($fields as $field => $params) - if (array_key_exists('lang', $params) && $params['lang']) - foreach (Language::getIDs(false) as $id_lang) - if (Tools::isSubmit($field.'_'.(int)$id_lang)) - $object->{$field}[(int)$id_lang] = Tools::getValue($field.'_'.(int)$id_lang); - } - - /** - * Returns an array with selected shops and type (group or boutique shop) - * - * @param string $table - * @return array - */ - protected function getSelectedAssoShop($table) - { - if (!Shop::isFeatureActive() || !Shop::isTableAssociated($table)) - return array(); - - $shops = Shop::getShops(true, null, true); - if (count($shops) == 1 && isset($shops[0])) - return array($shops[0], 'shop'); - - $assos = array(); - if (Tools::isSubmit('checkBoxShopAsso_'.$table)) - foreach (Tools::getValue('checkBoxShopAsso_'.$table) as $id_shop => $value) - $assos[] = (int)$id_shop; - elseif (Shop::getTotalShops(false) == 1)// if we do not have the checkBox multishop, we can have an admin with only one shop and being in multishop - $assos[] = (int)Shop::getContextShopID(); - return $assos; - } - - /** - * Update the associations of shops - * - * @param int $id_object - * @return bool|void - * @throws PrestaShopDatabaseException - */ - protected function updateAssoShop($id_object) - { - if (!Shop::isFeatureActive()) - return; - - if (!Shop::isTableAssociated($this->table)) - return; - - $assos_data = $this->getSelectedAssoShop($this->table); - - // Get list of shop id we want to exclude from asso deletion - $exclude_ids = $assos_data; - foreach (Db::getInstance()->executeS('SELECT id_shop FROM '._DB_PREFIX_.'shop') as $row) - if (!$this->context->employee->hasAuthOnShop($row['id_shop'])) - $exclude_ids[] = $row['id_shop']; - Db::getInstance()->delete($this->table.'_shop', '`'.bqSQL($this->identifier).'` = '.(int)$id_object.($exclude_ids ? ' AND id_shop NOT IN ('.implode(', ', array_map('intval', $exclude_ids)).')' : '')); - - $insert = array(); - foreach ($assos_data as $id_shop) - $insert[] = array( - $this->identifier => (int)$id_object, - 'id_shop' => (int)$id_shop, - ); - return Db::getInstance()->insert($this->table.'_shop', $insert, false, true, Db::INSERT_IGNORE); - } - - /** - * @param mixed $value - * @param array $field - * @return bool - */ - protected function validateField($value, $field) - { - if (isset($field['validation'])) - { - $valid_method_exists = method_exists('Validate', $field['validation']); - if ((!isset($field['empty']) || !$field['empty'] || (isset($field['empty']) && $field['empty'] && $value)) && $valid_method_exists) - { - if (!Validate::$field['validation']($value)) - { - $this->errors[] = Tools::displayError($field['title'].' : Incorrect value'); - return false; - } - } - } - - return true; - } - - /** - * Can be overridden - */ - public function beforeUpdateOptions() - { - } - - /** - * Overload this method for custom checking - * - * @param int $id Object id used for deleting images - * @return bool - */ - protected function postImage($id) - { - if (isset($this->fieldImageSettings['name']) && isset($this->fieldImageSettings['dir'])) - return $this->uploadImage($id, $this->fieldImageSettings['name'], $this->fieldImageSettings['dir'].'/'); - elseif (!empty($this->fieldImageSettings)) - foreach ($this->fieldImageSettings as $image) - if (isset($image['name']) && isset($image['dir'])) - $this->uploadImage($id, $image['name'], $image['dir'].'/'); - return !count($this->errors) ? true : false; - } - - /** - * @param int $id - * @param string $name - * @param string $dir - * @param string|bool $ext - * @param int|null $width - * @param int|null $height - * @return bool - */ - protected function uploadImage($id, $name, $dir, $ext = false, $width = null, $height = null) - { - if (isset($_FILES[$name]['tmp_name']) && !empty($_FILES[$name]['tmp_name'])) - { - // Delete old image - if (Validate::isLoadedObject($object = $this->loadObject())) - $object->deleteImage(); - else - return false; - - // Check image validity - $max_size = isset($this->max_image_size) ? $this->max_image_size : 0; - if ($error = ImageManager::validateUpload($_FILES[$name], Tools::getMaxUploadSize($max_size))) - $this->errors[] = $error; - - $tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS'); - if (!$tmp_name) - return false; - - if (!move_uploaded_file($_FILES[$name]['tmp_name'], $tmp_name)) - return false; - - // Evaluate the memory required to resize the image: if it's too much, you can't resize it. - if (!ImageManager::checkImageMemoryLimit($tmp_name)) - $this->errors[] = Tools::displayError('Due to memory limit restrictions, this image cannot be loaded. Please increase your memory_limit value via your server\'s configuration settings. '); - - // Copy new image - if (empty($this->errors) && !ImageManager::resize($tmp_name, _PS_IMG_DIR_.$dir.$id.'.'.$this->imageType, (int)$width, (int)$height, ($ext ? $ext : $this->imageType))) - $this->errors[] = Tools::displayError('An error occurred while uploading the image.'); - - if (count($this->errors)) - return false; - if ($this->afterImageUpload()) - { - unlink($tmp_name); - return true; - } - return false; - } - return true; - } - - /** - * Delete multiple items - * - * @return bool true if success - */ - protected function processBulkDelete() - { - if (is_array($this->boxes) && !empty($this->boxes)) - { - $object = new $this->className(); - - if (isset($object->noZeroObject)) - { - $objects_count = count(call_user_func(array($this->className, $object->noZeroObject))); - - // Check if all object will be deleted - if ($objects_count <= 1 || count($this->boxes) == $objects_count) - $this->errors[] = Tools::displayError('You need at least one object.'). - ' <b>'.$this->table.'</b><br />'. - Tools::displayError('You cannot delete all of the items.'); - } - else - { - $result = true; - foreach ($this->boxes as $id) - { - /** @var $to_delete ObjectModel */ - $to_delete = new $this->className($id); - $delete_ok = true; - if ($this->deleted) - { - $to_delete->deleted = 1; - if (!$to_delete->update()) - { - $result = false; - $delete_ok = false; - } - } - else - if (!$to_delete->delete()) - { - $result = false; - $delete_ok = false; - } - - if ($delete_ok) - PrestaShopLogger::addLog(sprintf($this->l('%s deletion', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$to_delete->id, true, (int)$this->context->employee->id); - else - $this->errors[] = sprintf(Tools::displayError('Can\'t delete #%d'), $id); - } - if ($result) - $this->redirect_after = self::$currentIndex.'&conf=2&token='.$this->token; - $this->errors[] = Tools::displayError('An error occurred while deleting this selection.'); - } - } - else - $this->errors[] = Tools::displayError('You must select at least one element to delete.'); - - if (isset($result)) - return $result; - else - return false; - } - - protected function ajaxProcessOpenHelp() - { - $help_class_name = $_GET['controller']; - $popup_content = "<!doctype html> + $sql_order_by.$sql_limit; + $list_count = 'SELECT COUNT(*) AS `'._DB_PREFIX_.$this->table.'` '.$sql_from.$sql_join.' WHERE 1 '.$sql_where; + } + + $this->_list = Db::getInstance()->executeS($this->_listsql, true, false); + + if ($this->_list === false) { + $this->_list_error = Db::getInstance()->getMsgError(); + break; + } + + $this->_listTotal = Db::getInstance()->getValue($list_count, false); + + if ($use_limit === true) { + $start = (int)$start - (int)$limit; + if ($start < 0) { + break; + } + } else { + break; + } + } while (empty($this->_list)); + + Hook::exec('action'.$this->controller_name.'ListingResultsModifier', array( + 'list' => &$this->_list, + 'list_total' => &$this->_listTotal, + )); + } + + /** + * @param array|string $filter_modules_list + * @return bool + * @throws PrestaShopException + */ + public function getModulesList($filter_modules_list) + { + if (!is_array($filter_modules_list) && !is_null($filter_modules_list)) { + $filter_modules_list = array($filter_modules_list); + } + + if (!count($filter_modules_list)) { + return false; + } //if there is no modules to display just return false; + + $all_modules = Module::getModulesOnDisk(true); + $this->modules_list = array(); + foreach ($all_modules as $module) { + $perm = true; + if ($module->id) { + $perm &= Module::getPermissionStatic($module->id, 'configure'); + } else { + $id_admin_module = Tab::getIdFromClassName('AdminModules'); + $access = Profile::getProfileAccess($this->context->employee->id_profile, $id_admin_module); + if (!$access['edit']) { + $perm &= false; + } + } + + if (in_array($module->name, $filter_modules_list) && $perm) { + $this->fillModuleData($module, 'array'); + $this->modules_list[array_search($module->name, $filter_modules_list)] = $module; + } + } + ksort($this->modules_list); + + if (count($this->modules_list)) { + return true; + } + + return false; //no module found on disk just return false; + } + + /** + * @return array + */ + public function getLanguages() + { + $cookie = $this->context->cookie; + $this->allow_employee_form_lang = (int)Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG'); + if ($this->allow_employee_form_lang && !$cookie->employee_form_lang) { + $cookie->employee_form_lang = (int)Configuration::get('PS_LANG_DEFAULT'); + } + + $lang_exists = false; + $this->_languages = Language::getLanguages(false); + foreach ($this->_languages as $lang) { + if (isset($cookie->employee_form_lang) && $cookie->employee_form_lang == $lang['id_lang']) { + $lang_exists = true; + } + } + + $this->default_form_language = $lang_exists ? (int)$cookie->employee_form_lang : (int)Configuration::get('PS_LANG_DEFAULT'); + + foreach ($this->_languages as $k => $language) { + $this->_languages[$k]['is_default'] = (int)($language['id_lang'] == $this->default_form_language); + } + + return $this->_languages; + } + + + /** + * Return the list of fields value + * + * @param ObjectModel $obj Object + * @return array + */ + public function getFieldsValue($obj) + { + foreach ($this->fields_form as $fieldset) { + if (isset($fieldset['form']['input'])) { + foreach ($fieldset['form']['input'] as $input) { + if (!isset($this->fields_value[$input['name']])) { + if (isset($input['type']) && $input['type'] == 'shop') { + if ($obj->id) { + $result = Shop::getShopById((int)$obj->id, $this->identifier, $this->table); + foreach ($result as $row) { + $this->fields_value['shop'][$row['id_'.$input['type']]][] = $row['id_shop']; + } + } + } elseif (isset($input['lang']) && $input['lang']) { + foreach ($this->_languages as $language) { + $field_value = $this->getFieldValue($obj, $input['name'], $language['id_lang']); + if (empty($field_value)) { + if (isset($input['default_value']) && is_array($input['default_value']) && isset($input['default_value'][$language['id_lang']])) { + $field_value = $input['default_value'][$language['id_lang']]; + } elseif (isset($input['default_value'])) { + $field_value = $input['default_value']; + } + } + $this->fields_value[$input['name']][$language['id_lang']] = $field_value; + } + } else { + $field_value = $this->getFieldValue($obj, $input['name']); + if ($field_value === false && isset($input['default_value'])) { + $field_value = $input['default_value']; + } + $this->fields_value[$input['name']] = $field_value; + } + } + } + } + } + + return $this->fields_value; + } + + /** + * Return field value if possible (both classical and multilingual fields) + * + * Case 1 : Return value if present in $_POST / $_GET + * Case 2 : Return object value + * + * @param ObjectModel $obj Object + * @param string $key Field name + * @param int|null $id_lang Language id (optional) + * @return string + */ + public function getFieldValue($obj, $key, $id_lang = null) + { + if ($id_lang) { + $default_value = (isset($obj->id) && $obj->id && isset($obj->{$key}[$id_lang])) ? $obj->{$key}[$id_lang] : false; + } else { + $default_value = isset($obj->{$key}) ? $obj->{$key} : false; + } + + return Tools::getValue($key.($id_lang ? '_'.$id_lang : ''), $default_value); + } + + /** + * Manage page display (form, list...) + * + * @param string|bool $class_name Allow to validate a different class than the current one + * @throws PrestaShopException + */ + public function validateRules($class_name = false) + { + if (!$class_name) { + $class_name = $this->className; + } + + /** @var $object ObjectModel */ + $object = new $class_name(); + + if (method_exists($this, 'getValidationRules')) { + $definition = $this->getValidationRules(); + } else { + $definition = ObjectModel::getDefinition($class_name); + } + + $default_language = new Language((int)Configuration::get('PS_LANG_DEFAULT')); + $languages = Language::getLanguages(false); + + foreach ($definition['fields'] as $field => $def) { + $skip = array(); + if (in_array($field, array('passwd', 'no-picture'))) { + $skip = array('required'); + } + + if (isset($def['lang']) && $def['lang']) { + if (isset($def['required']) && $def['required']) { + $value = Tools::getValue($field.'_'.$default_language->id); + if (empty($value)) { + $this->errors[$field.'_'.$default_language->id] = sprintf( + Tools::displayError('The field %1$s is required at least in %2$s.'), + $object->displayFieldName($field, $class_name), + $default_language->name + ); + } + } + + foreach ($languages as $language) { + $value = Tools::getValue($field.'_'.$language['id_lang']); + if (!empty($value)) { + if (($error = $object->validateField($field, $value, $language['id_lang'], $skip, true)) !== true) { + $this->errors[$field.'_'.$language['id_lang']] = $error; + } + } + } + } elseif (($error = $object->validateField($field, Tools::getValue($field), null, $skip, true)) !== true) { + $this->errors[$field] = $error; + } + } + + /* Overload this method for custom checking */ + $this->_childValidation(); + + /* Checking for multilingual fields validity */ + if (isset($rules['validateLang']) && is_array($rules['validateLang'])) { + foreach ($rules['validateLang'] as $field_lang => $function) { + foreach ($languages as $language) { + if (($value = Tools::getValue($field_lang.'_'.$language['id_lang'])) !== false && !empty($value)) { + if (Tools::strtolower($function) == 'iscleanhtml' && Configuration::get('PS_ALLOW_HTML_IFRAME')) { + $res = Validate::$function($value, true); + } else { + $res = Validate::$function($value); + } + if (!$res) { + $this->errors[$field_lang.'_'.$language['id_lang']] = sprintf( + Tools::displayError('The %1$s field (%2$s) is invalid.'), + call_user_func(array($class_name, 'displayFieldName'), $field_lang, $class_name), + $language['name'] + ); + } + } + } + } + } + } + + /** + * Overload this method for custom checking + */ + protected function _childValidation() + { + } + + /** + * Display object details + */ + public function viewDetails() + { + } + + /** + * Called before deletion + * + * @param ObjectModel $object Object + * @return bool + */ + protected function beforeDelete($object) + { + return false; + } + + /** + * Called before deletion + * + * @param ObjectModel $object Object + * @param int $old_id + * @return bool + */ + protected function afterDelete($object, $old_id) + { + return true; + } + + /** + * @param ObjectModel $object + * @return bool + */ + protected function afterAdd($object) + { + return true; + } + + /** + * @param ObjectModel $object + * @return bool + */ + protected function afterUpdate($object) + { + return true; + } + + /** + * Check rights to view the current tab + * + * @return bool + */ + protected function afterImageUpload() + { + return true; + } + + /** + * Copy data values from $_POST to object + * + * @param ObjectModel &$object Object + * @param string $table Object table + */ + protected function copyFromPost(&$object, $table) + { + /* Classical fields */ + foreach ($_POST as $key => $value) { + if (array_key_exists($key, $object) && $key != 'id_'.$table) { + /* Do not take care of password field if empty */ + if ($key == 'passwd' && Tools::getValue('id_'.$table) && empty($value)) { + continue; + } + /* Automatically encrypt password in MD5 */ + if ($key == 'passwd' && !empty($value)) { + $value = Tools::encrypt($value); + } + $object->{$key} = $value; + } + } + + /* Multilingual fields */ + $class_vars = get_class_vars(get_class($object)); + $fields = array(); + if (isset($class_vars['definition']['fields'])) { + $fields = $class_vars['definition']['fields']; + } + + foreach ($fields as $field => $params) { + if (array_key_exists('lang', $params) && $params['lang']) { + foreach (Language::getIDs(false) as $id_lang) { + if (Tools::isSubmit($field.'_'.(int)$id_lang)) { + $object->{$field}[(int)$id_lang] = Tools::getValue($field.'_'.(int)$id_lang); + } + } + } + } + } + + /** + * Returns an array with selected shops and type (group or boutique shop) + * + * @param string $table + * @return array + */ + protected function getSelectedAssoShop($table) + { + if (!Shop::isFeatureActive() || !Shop::isTableAssociated($table)) { + return array(); + } + + $shops = Shop::getShops(true, null, true); + if (count($shops) == 1 && isset($shops[0])) { + return array($shops[0], 'shop'); + } + + $assos = array(); + if (Tools::isSubmit('checkBoxShopAsso_'.$table)) { + foreach (Tools::getValue('checkBoxShopAsso_'.$table) as $id_shop => $value) { + $assos[] = (int)$id_shop; + } + } elseif (Shop::getTotalShops(false) == 1) { + // if we do not have the checkBox multishop, we can have an admin with only one shop and being in multishop + $assos[] = (int)Shop::getContextShopID(); + } + return $assos; + } + + /** + * Update the associations of shops + * + * @param int $id_object + * @return bool|void + * @throws PrestaShopDatabaseException + */ + protected function updateAssoShop($id_object) + { + if (!Shop::isFeatureActive()) { + return; + } + + if (!Shop::isTableAssociated($this->table)) { + return; + } + + $assos_data = $this->getSelectedAssoShop($this->table); + + // Get list of shop id we want to exclude from asso deletion + $exclude_ids = $assos_data; + foreach (Db::getInstance()->executeS('SELECT id_shop FROM '._DB_PREFIX_.'shop') as $row) { + if (!$this->context->employee->hasAuthOnShop($row['id_shop'])) { + $exclude_ids[] = $row['id_shop']; + } + } + Db::getInstance()->delete($this->table.'_shop', '`'.bqSQL($this->identifier).'` = '.(int)$id_object.($exclude_ids ? ' AND id_shop NOT IN ('.implode(', ', array_map('intval', $exclude_ids)).')' : '')); + + $insert = array(); + foreach ($assos_data as $id_shop) { + $insert[] = array( + $this->identifier => (int)$id_object, + 'id_shop' => (int)$id_shop, + ); + } + return Db::getInstance()->insert($this->table.'_shop', $insert, false, true, Db::INSERT_IGNORE); + } + + /** + * @param mixed $value + * @param array $field + * @return bool + */ + protected function validateField($value, $field) + { + if (isset($field['validation'])) { + $valid_method_exists = method_exists('Validate', $field['validation']); + if ((!isset($field['empty']) || !$field['empty'] || (isset($field['empty']) && $field['empty'] && $value)) && $valid_method_exists) { + if (!Validate::$field['validation']($value)) { + $this->errors[] = Tools::displayError($field['title'].' : Incorrect value'); + return false; + } + } + } + + return true; + } + + /** + * Can be overridden + */ + public function beforeUpdateOptions() + { + } + + /** + * Overload this method for custom checking + * + * @param int $id Object id used for deleting images + * @return bool + */ + protected function postImage($id) + { + if (isset($this->fieldImageSettings['name']) && isset($this->fieldImageSettings['dir'])) { + return $this->uploadImage($id, $this->fieldImageSettings['name'], $this->fieldImageSettings['dir'].'/'); + } elseif (!empty($this->fieldImageSettings)) { + foreach ($this->fieldImageSettings as $image) { + if (isset($image['name']) && isset($image['dir'])) { + $this->uploadImage($id, $image['name'], $image['dir'].'/'); + } + } + } + return !count($this->errors) ? true : false; + } + + /** + * @param int $id + * @param string $name + * @param string $dir + * @param string|bool $ext + * @param int|null $width + * @param int|null $height + * @return bool + */ + protected function uploadImage($id, $name, $dir, $ext = false, $width = null, $height = null) + { + if (isset($_FILES[$name]['tmp_name']) && !empty($_FILES[$name]['tmp_name'])) { + // Delete old image + if (Validate::isLoadedObject($object = $this->loadObject())) { + $object->deleteImage(); + } else { + return false; + } + + // Check image validity + $max_size = isset($this->max_image_size) ? $this->max_image_size : 0; + if ($error = ImageManager::validateUpload($_FILES[$name], Tools::getMaxUploadSize($max_size))) { + $this->errors[] = $error; + } + + $tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS'); + if (!$tmp_name) { + return false; + } + + if (!move_uploaded_file($_FILES[$name]['tmp_name'], $tmp_name)) { + return false; + } + + // Evaluate the memory required to resize the image: if it's too much, you can't resize it. + if (!ImageManager::checkImageMemoryLimit($tmp_name)) { + $this->errors[] = Tools::displayError('Due to memory limit restrictions, this image cannot be loaded. Please increase your memory_limit value via your server\'s configuration settings. '); + } + + // Copy new image + if (empty($this->errors) && !ImageManager::resize($tmp_name, _PS_IMG_DIR_.$dir.$id.'.'.$this->imageType, (int)$width, (int)$height, ($ext ? $ext : $this->imageType))) { + $this->errors[] = Tools::displayError('An error occurred while uploading the image.'); + } + + if (count($this->errors)) { + return false; + } + if ($this->afterImageUpload()) { + unlink($tmp_name); + return true; + } + return false; + } + return true; + } + + /** + * Delete multiple items + * + * @return bool true if success + */ + protected function processBulkDelete() + { + if (is_array($this->boxes) && !empty($this->boxes)) { + $object = new $this->className(); + + if (isset($object->noZeroObject)) { + $objects_count = count(call_user_func(array($this->className, $object->noZeroObject))); + + // Check if all object will be deleted + if ($objects_count <= 1 || count($this->boxes) == $objects_count) { + $this->errors[] = Tools::displayError('You need at least one object.'). + ' <b>'.$this->table.'</b><br />'. + Tools::displayError('You cannot delete all of the items.'); + } + } else { + $result = true; + foreach ($this->boxes as $id) { + /** @var $to_delete ObjectModel */ + $to_delete = new $this->className($id); + $delete_ok = true; + if ($this->deleted) { + $to_delete->deleted = 1; + if (!$to_delete->update()) { + $result = false; + $delete_ok = false; + } + } elseif (!$to_delete->delete()) { + $result = false; + $delete_ok = false; + } + + if ($delete_ok) { + PrestaShopLogger::addLog(sprintf($this->l('%s deletion', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$to_delete->id, true, (int)$this->context->employee->id); + } else { + $this->errors[] = sprintf(Tools::displayError('Can\'t delete #%d'), $id); + } + } + if ($result) { + $this->redirect_after = self::$currentIndex.'&conf=2&token='.$this->token; + } + $this->errors[] = Tools::displayError('An error occurred while deleting this selection.'); + } + } else { + $this->errors[] = Tools::displayError('You must select at least one element to delete.'); + } + + if (isset($result)) { + return $result; + } else { + return false; + } + } + + protected function ajaxProcessOpenHelp() + { + $help_class_name = $_GET['controller']; + $popup_content = "<!doctype html> <html> <head> <meta charset='UTF-8'> @@ -3767,539 +3814,551 @@ class AdminControllerCore extends Controller </head> <body><div id='help-container' class='help-popup'></div></body> </html>"; - die($popup_content); - } - - /** - * Enable multiple items - * - * @return bool true if success - */ - protected function processBulkEnableSelection() - { - return $this->processBulkStatusSelection(1); - } - - /** - * Disable multiple items - * - * @return bool true if success - */ - protected function processBulkDisableSelection() - { - return $this->processBulkStatusSelection(0); - } - - /** - * Toggle status of multiple items - * - * @param bool $status - * @return bool true if success - * @throws PrestaShopException - */ - protected function processBulkStatusSelection($status) - { - $result = true; - if (is_array($this->boxes) && !empty($this->boxes)) - { - foreach ($this->boxes as $id) - { - /** @var ObjectModel $object */ - $object = new $this->className((int)$id); - $object->active = (int)$status; - $result &= $object->update(); - } - } - return $result; - } - - /** - * @return bool - */ - protected function processBulkAffectZone() - { - $result = false; - if (is_array($this->boxes) && !empty($this->boxes)) - { - /** @var Country|State $object */ - $object = new $this->className(); - $result = $object->affectZoneToSelection(Tools::getValue($this->table.'Box'), Tools::getValue('zone_to_affect')); - - if ($result) - $this->redirect_after = self::$currentIndex.'&conf=28&token='.$this->token; - $this->errors[] = Tools::displayError('An error occurred while affecting a zone to the selection.'); - } - else - $this->errors[] = Tools::displayError('You must select at least one element to affect a new zone.'); - - return $result; - } - - /** - * Called before Add - * - * @param ObjectModel $object Object - * @return bool - */ - protected function beforeAdd($object) - { - return true; - } - - /** - * Prepare the view to display the required fields form - * - * @return string|void - */ - public function displayRequiredFields() - { - if (!$this->tabAccess['add'] || !$this->tabAccess['delete'] === '1' || !$this->required_database) - return; - - $helper = new Helper(); - $helper->currentIndex = self::$currentIndex; - $helper->token = $this->token; - $helper->override_folder = $this->override_folder; - return $helper->renderRequiredFields($this->className, $this->identifier, $this->required_fields); - } - - /** - * Create a template from the override file, else from the base file. - * - * @param string $tpl_name filename - * @return Smarty_Internal_Template - */ - public function createTemplate($tpl_name) - { - // Use override tpl if it exists - // If view access is denied, we want to use the default template that will be used to display an error - if ($this->viewAccess() && $this->override_folder) - { - if (!Configuration::get('PS_DISABLE_OVERRIDES') && file_exists($this->context->smarty->getTemplateDir(1).DIRECTORY_SEPARATOR.$this->override_folder.$tpl_name)) - return $this->context->smarty->createTemplate($this->override_folder.$tpl_name, $this->context->smarty); - elseif (file_exists($this->context->smarty->getTemplateDir(0).'controllers'.DIRECTORY_SEPARATOR.$this->override_folder.$tpl_name)) - return $this->context->smarty->createTemplate('controllers'.DIRECTORY_SEPARATOR.$this->override_folder.$tpl_name, $this->context->smarty); - } - - return $this->context->smarty->createTemplate($this->context->smarty->getTemplateDir(0).$tpl_name, $this->context->smarty); - } - - /** - * Shortcut to set up a json success payload - * - * @param string $message Success message - */ - public function jsonConfirmation($message) - { - $this->json = true; - $this->confirmations[] = $message; - if ($this->status === '') - $this->status = 'ok'; - } - - /** - * Shortcut to set up a json error payload - * - * @param string $message Error message - */ - public function jsonError($message) - { - $this->json = true; - $this->errors[] = $message; - if ($this->status === '') - $this->status = 'error'; - } - - /** - * @param string $file - * @param int $timeout - * @return bool - */ - public function isFresh($file, $timeout = 604800) - { - if (($time = @filemtime(_PS_ROOT_DIR_.$file)) && filesize(_PS_ROOT_DIR_.$file) > 0) - return ((time() - $time) < $timeout); - - return false; - } - - /** @var bool */ - protected static $is_prestashop_up = true; - - /** - * @param string $file_to_refresh - * @param string $external_file - * @return bool - */ - public function refresh($file_to_refresh, $external_file) - { - if (self::$is_prestashop_up && $content = Tools::file_get_contents($external_file)) - return (bool)file_put_contents(_PS_ROOT_DIR_.$file_to_refresh, $content); - self::$is_prestashop_up = false; - return false; - } - - /** - * @param Module $module - * @param string $output_type - * @param string|null $back - */ - public function fillModuleData(&$module, $output_type = 'link', $back = null) - { - /** @var Module $obj */ - $obj = null; - if ($module->onclick_option) - $obj = new $module->name(); - // Fill module data - $module->logo = '../../img/questionmark.png'; - - if (@filemtime(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.basename(_PS_MODULE_DIR_).DIRECTORY_SEPARATOR.$module->name - .DIRECTORY_SEPARATOR.'logo.gif')) - $module->logo = 'logo.gif'; - if (@filemtime(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.basename(_PS_MODULE_DIR_).DIRECTORY_SEPARATOR.$module->name - .DIRECTORY_SEPARATOR.'logo.png')) - $module->logo = 'logo.png'; - - $link_admin_modules = $this->context->link->getAdminLink('AdminModules', true); - - $module->options['install_url'] = $link_admin_modules.'&install='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name); - $module->options['update_url'] = $link_admin_modules.'&update='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name); - $module->options['uninstall_url'] = $link_admin_modules.'&uninstall='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name); - - $module->optionsHtml = $this->displayModuleOptions($module, $output_type, $back); - - $module->options['uninstall_onclick'] = ((!$module->onclick_option) ? - ((empty($module->confirmUninstall)) ? 'return confirm(\''.$this->l('Do you really want to uninstall this module?').'\');' : 'return confirm(\''.addslashes($module->confirmUninstall).'\');') : - $obj->onclickOption('uninstall', $module->options['uninstall_url'])); - - if ((Tools::getValue('module_name') == $module->name || in_array($module->name, explode('|', Tools::getValue('modules_list')))) && (int)Tools::getValue('conf') > 0) - $module->message = $this->_conf[(int)Tools::getValue('conf')]; - - if ((Tools::getValue('module_name') == $module->name || in_array($module->name, explode('|', Tools::getValue('modules_list')))) && (int)Tools::getValue('conf') > 0) - unset($obj); - } - - /** @var array */ - protected $translationsTab = array(); - - /** - * Display modules list - * - * @param Module $module - * @param string $output_type (link or select) - * @param string|null $back - * @return string|array - */ - public function displayModuleOptions($module, $output_type = 'link', $back = null) - { - if (!isset($module->enable_device)) - $module->enable_device = Context::DEVICE_COMPUTER | Context::DEVICE_TABLET | Context::DEVICE_MOBILE; - - $this->translationsTab['confirm_uninstall_popup'] = (isset($module->confirmUninstall) ? $module->confirmUninstall : $this->l('Do you really want to uninstall this module?')); - if (!isset($this->translationsTab['Disable this module'])) - { - $this->translationsTab['Disable this module'] = $this->l('Disable this module'); - $this->translationsTab['Enable this module for all shops'] = $this->l('Enable this module for all shops'); - $this->translationsTab['Disable'] = $this->l('Disable'); - $this->translationsTab['Enable'] = $this->l('Enable'); - $this->translationsTab['Disable on mobiles'] = $this->l('Disable on mobiles'); - $this->translationsTab['Disable on tablets'] = $this->l('Disable on tablets'); - $this->translationsTab['Disable on computers'] = $this->l('Disable on computers'); - $this->translationsTab['Display on mobiles'] = $this->l('Display on mobiles'); - $this->translationsTab['Display on tablets'] = $this->l('Display on tablets'); - $this->translationsTab['Display on computers'] = $this->l('Display on computers'); - $this->translationsTab['Reset'] = $this->l('Reset'); - $this->translationsTab['Configure'] = $this->l('Configure'); - $this->translationsTab['Delete'] = $this->l('Delete'); - $this->translationsTab['Install'] = $this->l('Install'); - $this->translationsTab['Uninstall'] = $this->l('Uninstall'); - $this->translationsTab['Would you like to delete the content related to this module ?'] = $this->l('Would you like to delete the content related to this module ?'); - $this->translationsTab['This action will permanently remove the module from the server. Are you sure you want to do this?'] = $this->l('This action will permanently remove the module from the server. Are you sure you want to do this?'); - $this->translationsTab['Remove from Favorites'] = $this->l('Remove from Favorites'); - $this->translationsTab['Mark as Favorite'] = $this->l('Mark as Favorite'); - } - - $link_admin_modules = $this->context->link->getAdminLink('AdminModules', true); - $modules_options = array(); - - $configure_module = array( - 'href' => $link_admin_modules.'&configure='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.urlencode($module->name), - 'onclick' => $module->onclick_option && isset($module->onclick_option_content['configure']) ? $module->onclick_option_content['configure'] : '', - 'title' => '', - 'text' => $this->translationsTab['Configure'], - 'cond' => $module->id && isset($module->is_configurable) && $module->is_configurable, - 'icon' => 'wrench', - ); - - $desactive_module = array( - 'href' => $link_admin_modules.'&module_name='.urlencode($module->name).'&'.($module->active ? 'enable=0' : 'enable=1').'&tab_module='.$module->tab, - 'onclick' => $module->active && $module->onclick_option && isset($module->onclick_option_content['desactive']) ? $module->onclick_option_content['desactive'] : '' , - 'title' => Shop::isFeatureActive() ? htmlspecialchars($module->active ? $this->translationsTab['Disable this module'] : $this->translationsTab['Enable this module for all shops']) : '', - 'text' => $module->active ? $this->translationsTab['Disable'] : $this->translationsTab['Enable'], - 'cond' => $module->id, - 'icon' => 'off', - ); - $link_reset_module = $link_admin_modules.'&module_name='.urlencode($module->name).'&reset&tab_module='.$module->tab; - - $is_reset_ready = false; - if (Validate::isModuleName($module->name)) - if (method_exists(Module::getInstanceByName($module->name), 'reset')) - $is_reset_ready = true; - - $reset_module = array( - 'href' => $link_reset_module, - 'onclick' => $module->onclick_option && isset($module->onclick_option_content['reset']) ? $module->onclick_option_content['reset'] : '', - 'title' => '', - 'text' => $this->translationsTab['Reset'], - 'cond' => $module->id && $module->active, - 'icon' => 'undo', - 'class' => ($is_reset_ready ? 'reset_ready' : '') - ); - - $delete_module = array( - 'href' => $link_admin_modules.'&delete='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.urlencode($module->name), - 'onclick' => $module->onclick_option && isset($module->onclick_option_content['delete']) ? $module->onclick_option_content['delete'] : 'return confirm(\''.$this->translationsTab['This action will permanently remove the module from the server. Are you sure you want to do this?'].'\');', - 'title' => '', - 'text' => $this->translationsTab['Delete'], - 'cond' => true, - 'icon' => 'trash', - 'class' => 'text-danger' - ); - - $display_mobile = array( - 'href' => $link_admin_modules.'&module_name='.urlencode($module->name).'&'.($module->enable_device & Context::DEVICE_MOBILE ? 'disable_device' : 'enable_device').'='.Context::DEVICE_MOBILE.'&tab_module='.$module->tab, - 'onclick' => '', - 'title' => htmlspecialchars($module->enable_device & Context::DEVICE_MOBILE ? $this->translationsTab['Disable on mobiles'] : $this->translationsTab['Display on mobiles']), - 'text' => $module->enable_device & Context::DEVICE_MOBILE ? $this->translationsTab['Disable on mobiles'] : $this->translationsTab['Display on mobiles'], - 'cond' => $module->id, - 'icon' => 'mobile' - ); - - $display_tablet = array( - 'href' => $link_admin_modules.'&module_name='.urlencode($module->name).'&'.($module->enable_device & Context::DEVICE_TABLET ? 'disable_device' : 'enable_device').'='.Context::DEVICE_TABLET.'&tab_module='.$module->tab, - 'onclick' => '', - 'title' => htmlspecialchars($module->enable_device & Context::DEVICE_TABLET ? $this->translationsTab['Disable on tablets'] : $this->translationsTab['Display on tablets']), - 'text' => $module->enable_device & Context::DEVICE_TABLET ? $this->translationsTab['Disable on tablets'] : $this->translationsTab['Display on tablets'], - 'cond' => $module->id, - 'icon' => 'tablet' - ); - - $display_computer = array( - 'href' => $link_admin_modules.'&module_name='.urlencode($module->name).'&'.($module->enable_device & Context::DEVICE_COMPUTER ? 'disable_device' : 'enable_device').'='.Context::DEVICE_COMPUTER.'&tab_module='.$module->tab, - 'onclick' => '', - 'title' => htmlspecialchars($module->enable_device & Context::DEVICE_COMPUTER ? $this->translationsTab['Disable on computers'] : $this->translationsTab['Display on computers']), - 'text' => $module->enable_device & Context::DEVICE_COMPUTER ? $this->translationsTab['Disable on computers'] : $this->translationsTab['Display on computers'], - 'cond' => $module->id, - 'icon' => 'desktop' - ); - - $install = array( - 'href' => $link_admin_modules.'&install='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name).(!is_null($back) ? '&back='.urlencode($back) : ''), - 'onclick' => '', - 'title' => $this->translationsTab['Install'], - 'text' => $this->translationsTab['Install'], - 'cond' => $module->id, - 'icon' => 'plus-sign-alt' - ); - - $uninstall = array( - 'href' => $link_admin_modules.'&uninstall='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name).(!is_null($back) ? '&back='.urlencode($back) : ''), - 'onclick' => (isset($module->onclick_option_content['uninstall']) ? $module->onclick_option_content['uninstall'] : 'return confirm(\''.$this->translationsTab['confirm_uninstall_popup'].'\');'), - 'title' => $this->translationsTab['Uninstall'], - 'text' => $this->translationsTab['Uninstall'], - 'cond' => $module->id, - 'icon' => 'minus-sign-alt' - ); - - $remove_from_favorite = array( - 'href' => '#', - 'class' => 'action_unfavorite toggle_favorite', - 'onclick' =>'', - 'title' => $this->translationsTab['Remove from Favorites'], - 'text' => $this->translationsTab['Remove from Favorites'], - 'cond' => $module->id, - 'icon' => 'star', - 'data-value' => '0', - 'data-module' => $module->name - ); - - $mark_as_favorite = array( - 'href' => '#', - 'class' => 'action_favorite toggle_favorite', - 'onclick' => '', - 'title' => $this->translationsTab['Mark as Favorite'], - 'text' => $this->translationsTab['Mark as Favorite'], - 'cond' => $module->id, - 'icon' => 'star', - 'data-value' => '1', - 'data-module' => $module->name - ); - - $update = array( - 'href' => $module->options['update_url'], - 'onclick' => '', - 'title' => 'Update it!', - 'text' => 'Update it!', - 'icon' => 'refresh', - 'cond' => $module->id, - ); - - $divider = array( - 'href' => '#', - 'onclick' => '', - 'title' => 'divider', - 'text' => 'divider', - 'cond' => $module->id, - ); - - if (isset($module->version_addons) && $module->version_addons) - $modules_options[] = $update; - - if ($module->active) - { - $modules_options[] = $configure_module; - $modules_options[] = $desactive_module; - $modules_options[] = $display_mobile; - $modules_options[] = $display_tablet; - $modules_options[] = $display_computer; - } - else - { - $modules_options[] = $desactive_module; - $modules_options[] = $configure_module; - } - - $modules_options[] = $reset_module; - - if ($output_type == 'select') - { - if (!$module->id) - $modules_options[] = $install; - else - $modules_options[] = $uninstall; - } - elseif ($output_type == 'array') - if ($module->id) - $modules_options[] = $uninstall; - - if (isset($module->preferences) && isset($module->preferences['favorite']) && $module->preferences['favorite'] == 1) - { - $remove_from_favorite['style'] = ''; - $mark_as_favorite['style'] = 'display:none;'; - $modules_options[] = $remove_from_favorite; - $modules_options[] = $mark_as_favorite; - } - else - { - $mark_as_favorite['style'] = ''; - $remove_from_favorite['style'] = 'display:none;'; - $modules_options[] = $remove_from_favorite; - $modules_options[] = $mark_as_favorite; - } - - if ($module->id == 0) - { - $install['cond'] = 1; - $install['flag_install'] = 1; - $modules_options[] = $install; - } - $modules_options[] = $divider; - $modules_options[] = $delete_module; - - $return = ''; - foreach ($modules_options as $option_name => $option) - { - if ($option['cond']) - { - if ($output_type == 'link') - { - $return .= '<li><a class="'.$option_name.' action_module'; - $return .= '" href="'.$option['href'].(!is_null($back) ? '&back='.urlencode($back) : '').'"'; - $return .= ' onclick="'.$option['onclick'].'" title="'.$option['title'].'"><i class="icon-'.(isset($option['icon']) && $option['icon'] ? $option['icon']:'cog' ).'"></i> '.$option['text'].'</a></li>'; - } - elseif ($output_type == 'array') - { - if (!is_array($return)) - $return = array(); - - $html = '<a class="'; - - $is_install = isset($option['flag_install']) ? true : false; - - if (isset($option['class'])) - $html .= $option['class']; - if ($is_install) - $html .= ' btn btn-success'; - if (!$is_install && count($return) == 0) - $html .= ' btn btn-default'; - - $html .= '"'; - - if (isset($option['data-value'])) - $html .= ' data-value="'.$option['data-value'].'"'; - - if (isset($option['data-module'])) - $html .= ' data-module="'.$option['data-module'].'"'; - - if (isset($option['style'])) - $html .= ' style="'.$option['style'].'"'; - - $html .= ' href="'.htmlentities($option['href']).(!is_null($back) ? '&back='.urlencode($back) : '').'" onclick="'.$option['onclick'].'" title="'.$option['title'].'"><i class="icon-'.(isset($option['icon']) && $option['icon'] ? $option['icon']:'cog' ).'"></i> '.$option['text'].'</a>'; - $return[] = $html; - } - elseif ($output_type == 'select') - $return .= '<option id="'.$option_name.'" data-href="'.htmlentities($option['href']).(!is_null($back) ? '&back='.urlencode($back) : '').'" data-onclick="'.$option['onclick'].'">'.$option['text'].'</option>'; - } - } - - if ($output_type == 'select') - $return = '<select id="select_'.$module->name.'">'.$return.'</select>'; - - return $return; - } - - public function ajaxProcessGetModuleQuickView() - { - $modules = Module::getModulesOnDisk(); - - foreach ($modules as $module) - if ($module->name == Tools::getValue('module')) - break; - - $url = $module->url; - - if (isset($module->type) && ($module->type == 'addonsPartner' || $module->type == 'addonsNative')) - $url = $this->context->link->getAdminLink('AdminModules').'&install='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name); - - $this->context->smarty->assign(array( - 'displayName' => $module->displayName, - 'image' => $module->image, - 'nb_rates' => (int)$module->nb_rates[0], - 'avg_rate' => (int)$module->avg_rate[0], - 'badges' => $module->badges, - 'compatibility' => $module->compatibility, - 'description_full' => $module->description_full, - 'additional_description' => $module->additional_description, - 'is_addons_partner' => (isset($module->type) && ($module->type == 'addonsPartner' || $module->type == 'addonsNative')), - 'url' => $url, - 'price' => $module->price - - )); - // Fetch the translations in the right place - they are not defined by our current controller! - Context::getContext()->override_controller_name_for_translations = 'AdminModules'; - $this->smartyOutputContent('controllers/modules/quickview.tpl'); - die(1); - } - - /** - * Add an entry to the meta title. - * - * @param string $entry New entry. - */ - public function addMetaTitle($entry) - { - // Only add entry if the meta title was not forced. - if (is_array($this->meta_title)) - $this->meta_title[] = $entry; - } + die($popup_content); + } + + /** + * Enable multiple items + * + * @return bool true if success + */ + protected function processBulkEnableSelection() + { + return $this->processBulkStatusSelection(1); + } + + /** + * Disable multiple items + * + * @return bool true if success + */ + protected function processBulkDisableSelection() + { + return $this->processBulkStatusSelection(0); + } + + /** + * Toggle status of multiple items + * + * @param bool $status + * @return bool true if success + * @throws PrestaShopException + */ + protected function processBulkStatusSelection($status) + { + $result = true; + if (is_array($this->boxes) && !empty($this->boxes)) { + foreach ($this->boxes as $id) { + /** @var ObjectModel $object */ + $object = new $this->className((int)$id); + $object->active = (int)$status; + $result &= $object->update(); + } + } + return $result; + } + + /** + * @return bool + */ + protected function processBulkAffectZone() + { + $result = false; + if (is_array($this->boxes) && !empty($this->boxes)) { + /** @var Country|State $object */ + $object = new $this->className(); + $result = $object->affectZoneToSelection(Tools::getValue($this->table.'Box'), Tools::getValue('zone_to_affect')); + + if ($result) { + $this->redirect_after = self::$currentIndex.'&conf=28&token='.$this->token; + } + $this->errors[] = Tools::displayError('An error occurred while affecting a zone to the selection.'); + } else { + $this->errors[] = Tools::displayError('You must select at least one element to affect a new zone.'); + } + + return $result; + } + + /** + * Called before Add + * + * @param ObjectModel $object Object + * @return bool + */ + protected function beforeAdd($object) + { + return true; + } + + /** + * Prepare the view to display the required fields form + * + * @return string|void + */ + public function displayRequiredFields() + { + if (!$this->tabAccess['add'] || !$this->tabAccess['delete'] === '1' || !$this->required_database) { + return; + } + + $helper = new Helper(); + $helper->currentIndex = self::$currentIndex; + $helper->token = $this->token; + $helper->override_folder = $this->override_folder; + return $helper->renderRequiredFields($this->className, $this->identifier, $this->required_fields); + } + + /** + * Create a template from the override file, else from the base file. + * + * @param string $tpl_name filename + * @return Smarty_Internal_Template + */ + public function createTemplate($tpl_name) + { + // Use override tpl if it exists + // If view access is denied, we want to use the default template that will be used to display an error + if ($this->viewAccess() && $this->override_folder) { + if (!Configuration::get('PS_DISABLE_OVERRIDES') && file_exists($this->context->smarty->getTemplateDir(1).DIRECTORY_SEPARATOR.$this->override_folder.$tpl_name)) { + return $this->context->smarty->createTemplate($this->override_folder.$tpl_name, $this->context->smarty); + } elseif (file_exists($this->context->smarty->getTemplateDir(0).'controllers'.DIRECTORY_SEPARATOR.$this->override_folder.$tpl_name)) { + return $this->context->smarty->createTemplate('controllers'.DIRECTORY_SEPARATOR.$this->override_folder.$tpl_name, $this->context->smarty); + } + } + + return $this->context->smarty->createTemplate($this->context->smarty->getTemplateDir(0).$tpl_name, $this->context->smarty); + } + + /** + * Shortcut to set up a json success payload + * + * @param string $message Success message + */ + public function jsonConfirmation($message) + { + $this->json = true; + $this->confirmations[] = $message; + if ($this->status === '') { + $this->status = 'ok'; + } + } + + /** + * Shortcut to set up a json error payload + * + * @param string $message Error message + */ + public function jsonError($message) + { + $this->json = true; + $this->errors[] = $message; + if ($this->status === '') { + $this->status = 'error'; + } + } + + /** + * @param string $file + * @param int $timeout + * @return bool + */ + public function isFresh($file, $timeout = 604800) + { + if (($time = @filemtime(_PS_ROOT_DIR_.$file)) && filesize(_PS_ROOT_DIR_.$file) > 0) { + return ((time() - $time) < $timeout); + } + + return false; + } + + /** @var bool */ + protected static $is_prestashop_up = true; + + /** + * @param string $file_to_refresh + * @param string $external_file + * @return bool + */ + public function refresh($file_to_refresh, $external_file) + { + if (self::$is_prestashop_up && $content = Tools::file_get_contents($external_file)) { + return (bool)file_put_contents(_PS_ROOT_DIR_.$file_to_refresh, $content); + } + self::$is_prestashop_up = false; + return false; + } + + /** + * @param Module $module + * @param string $output_type + * @param string|null $back + */ + public function fillModuleData(&$module, $output_type = 'link', $back = null) + { + /** @var Module $obj */ + $obj = null; + if ($module->onclick_option) { + $obj = new $module->name(); + } + // Fill module data + $module->logo = '../../img/questionmark.png'; + + if (@filemtime(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.basename(_PS_MODULE_DIR_).DIRECTORY_SEPARATOR.$module->name + .DIRECTORY_SEPARATOR.'logo.gif')) { + $module->logo = 'logo.gif'; + } + if (@filemtime(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.basename(_PS_MODULE_DIR_).DIRECTORY_SEPARATOR.$module->name + .DIRECTORY_SEPARATOR.'logo.png')) { + $module->logo = 'logo.png'; + } + + $link_admin_modules = $this->context->link->getAdminLink('AdminModules', true); + + $module->options['install_url'] = $link_admin_modules.'&install='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name); + $module->options['update_url'] = $link_admin_modules.'&update='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name); + $module->options['uninstall_url'] = $link_admin_modules.'&uninstall='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name); + + $module->optionsHtml = $this->displayModuleOptions($module, $output_type, $back); + + $module->options['uninstall_onclick'] = ((!$module->onclick_option) ? + ((empty($module->confirmUninstall)) ? 'return confirm(\''.$this->l('Do you really want to uninstall this module?').'\');' : 'return confirm(\''.addslashes($module->confirmUninstall).'\');') : + $obj->onclickOption('uninstall', $module->options['uninstall_url'])); + + if ((Tools::getValue('module_name') == $module->name || in_array($module->name, explode('|', Tools::getValue('modules_list')))) && (int)Tools::getValue('conf') > 0) { + $module->message = $this->_conf[(int)Tools::getValue('conf')]; + } + + if ((Tools::getValue('module_name') == $module->name || in_array($module->name, explode('|', Tools::getValue('modules_list')))) && (int)Tools::getValue('conf') > 0) { + unset($obj); + } + } + + /** @var array */ + protected $translationsTab = array(); + + /** + * Display modules list + * + * @param Module $module + * @param string $output_type (link or select) + * @param string|null $back + * @return string|array + */ + public function displayModuleOptions($module, $output_type = 'link', $back = null) + { + if (!isset($module->enable_device)) { + $module->enable_device = Context::DEVICE_COMPUTER | Context::DEVICE_TABLET | Context::DEVICE_MOBILE; + } + + $this->translationsTab['confirm_uninstall_popup'] = (isset($module->confirmUninstall) ? $module->confirmUninstall : $this->l('Do you really want to uninstall this module?')); + if (!isset($this->translationsTab['Disable this module'])) { + $this->translationsTab['Disable this module'] = $this->l('Disable this module'); + $this->translationsTab['Enable this module for all shops'] = $this->l('Enable this module for all shops'); + $this->translationsTab['Disable'] = $this->l('Disable'); + $this->translationsTab['Enable'] = $this->l('Enable'); + $this->translationsTab['Disable on mobiles'] = $this->l('Disable on mobiles'); + $this->translationsTab['Disable on tablets'] = $this->l('Disable on tablets'); + $this->translationsTab['Disable on computers'] = $this->l('Disable on computers'); + $this->translationsTab['Display on mobiles'] = $this->l('Display on mobiles'); + $this->translationsTab['Display on tablets'] = $this->l('Display on tablets'); + $this->translationsTab['Display on computers'] = $this->l('Display on computers'); + $this->translationsTab['Reset'] = $this->l('Reset'); + $this->translationsTab['Configure'] = $this->l('Configure'); + $this->translationsTab['Delete'] = $this->l('Delete'); + $this->translationsTab['Install'] = $this->l('Install'); + $this->translationsTab['Uninstall'] = $this->l('Uninstall'); + $this->translationsTab['Would you like to delete the content related to this module ?'] = $this->l('Would you like to delete the content related to this module ?'); + $this->translationsTab['This action will permanently remove the module from the server. Are you sure you want to do this?'] = $this->l('This action will permanently remove the module from the server. Are you sure you want to do this?'); + $this->translationsTab['Remove from Favorites'] = $this->l('Remove from Favorites'); + $this->translationsTab['Mark as Favorite'] = $this->l('Mark as Favorite'); + } + + $link_admin_modules = $this->context->link->getAdminLink('AdminModules', true); + $modules_options = array(); + + $configure_module = array( + 'href' => $link_admin_modules.'&configure='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.urlencode($module->name), + 'onclick' => $module->onclick_option && isset($module->onclick_option_content['configure']) ? $module->onclick_option_content['configure'] : '', + 'title' => '', + 'text' => $this->translationsTab['Configure'], + 'cond' => $module->id && isset($module->is_configurable) && $module->is_configurable, + 'icon' => 'wrench', + ); + + $desactive_module = array( + 'href' => $link_admin_modules.'&module_name='.urlencode($module->name).'&'.($module->active ? 'enable=0' : 'enable=1').'&tab_module='.$module->tab, + 'onclick' => $module->active && $module->onclick_option && isset($module->onclick_option_content['desactive']) ? $module->onclick_option_content['desactive'] : '' , + 'title' => Shop::isFeatureActive() ? htmlspecialchars($module->active ? $this->translationsTab['Disable this module'] : $this->translationsTab['Enable this module for all shops']) : '', + 'text' => $module->active ? $this->translationsTab['Disable'] : $this->translationsTab['Enable'], + 'cond' => $module->id, + 'icon' => 'off', + ); + $link_reset_module = $link_admin_modules.'&module_name='.urlencode($module->name).'&reset&tab_module='.$module->tab; + + $is_reset_ready = false; + if (Validate::isModuleName($module->name)) { + if (method_exists(Module::getInstanceByName($module->name), 'reset')) { + $is_reset_ready = true; + } + } + + $reset_module = array( + 'href' => $link_reset_module, + 'onclick' => $module->onclick_option && isset($module->onclick_option_content['reset']) ? $module->onclick_option_content['reset'] : '', + 'title' => '', + 'text' => $this->translationsTab['Reset'], + 'cond' => $module->id && $module->active, + 'icon' => 'undo', + 'class' => ($is_reset_ready ? 'reset_ready' : '') + ); + + $delete_module = array( + 'href' => $link_admin_modules.'&delete='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.urlencode($module->name), + 'onclick' => $module->onclick_option && isset($module->onclick_option_content['delete']) ? $module->onclick_option_content['delete'] : 'return confirm(\''.$this->translationsTab['This action will permanently remove the module from the server. Are you sure you want to do this?'].'\');', + 'title' => '', + 'text' => $this->translationsTab['Delete'], + 'cond' => true, + 'icon' => 'trash', + 'class' => 'text-danger' + ); + + $display_mobile = array( + 'href' => $link_admin_modules.'&module_name='.urlencode($module->name).'&'.($module->enable_device & Context::DEVICE_MOBILE ? 'disable_device' : 'enable_device').'='.Context::DEVICE_MOBILE.'&tab_module='.$module->tab, + 'onclick' => '', + 'title' => htmlspecialchars($module->enable_device & Context::DEVICE_MOBILE ? $this->translationsTab['Disable on mobiles'] : $this->translationsTab['Display on mobiles']), + 'text' => $module->enable_device & Context::DEVICE_MOBILE ? $this->translationsTab['Disable on mobiles'] : $this->translationsTab['Display on mobiles'], + 'cond' => $module->id, + 'icon' => 'mobile' + ); + + $display_tablet = array( + 'href' => $link_admin_modules.'&module_name='.urlencode($module->name).'&'.($module->enable_device & Context::DEVICE_TABLET ? 'disable_device' : 'enable_device').'='.Context::DEVICE_TABLET.'&tab_module='.$module->tab, + 'onclick' => '', + 'title' => htmlspecialchars($module->enable_device & Context::DEVICE_TABLET ? $this->translationsTab['Disable on tablets'] : $this->translationsTab['Display on tablets']), + 'text' => $module->enable_device & Context::DEVICE_TABLET ? $this->translationsTab['Disable on tablets'] : $this->translationsTab['Display on tablets'], + 'cond' => $module->id, + 'icon' => 'tablet' + ); + + $display_computer = array( + 'href' => $link_admin_modules.'&module_name='.urlencode($module->name).'&'.($module->enable_device & Context::DEVICE_COMPUTER ? 'disable_device' : 'enable_device').'='.Context::DEVICE_COMPUTER.'&tab_module='.$module->tab, + 'onclick' => '', + 'title' => htmlspecialchars($module->enable_device & Context::DEVICE_COMPUTER ? $this->translationsTab['Disable on computers'] : $this->translationsTab['Display on computers']), + 'text' => $module->enable_device & Context::DEVICE_COMPUTER ? $this->translationsTab['Disable on computers'] : $this->translationsTab['Display on computers'], + 'cond' => $module->id, + 'icon' => 'desktop' + ); + + $install = array( + 'href' => $link_admin_modules.'&install='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name).(!is_null($back) ? '&back='.urlencode($back) : ''), + 'onclick' => '', + 'title' => $this->translationsTab['Install'], + 'text' => $this->translationsTab['Install'], + 'cond' => $module->id, + 'icon' => 'plus-sign-alt' + ); + + $uninstall = array( + 'href' => $link_admin_modules.'&uninstall='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name).(!is_null($back) ? '&back='.urlencode($back) : ''), + 'onclick' => (isset($module->onclick_option_content['uninstall']) ? $module->onclick_option_content['uninstall'] : 'return confirm(\''.$this->translationsTab['confirm_uninstall_popup'].'\');'), + 'title' => $this->translationsTab['Uninstall'], + 'text' => $this->translationsTab['Uninstall'], + 'cond' => $module->id, + 'icon' => 'minus-sign-alt' + ); + + $remove_from_favorite = array( + 'href' => '#', + 'class' => 'action_unfavorite toggle_favorite', + 'onclick' =>'', + 'title' => $this->translationsTab['Remove from Favorites'], + 'text' => $this->translationsTab['Remove from Favorites'], + 'cond' => $module->id, + 'icon' => 'star', + 'data-value' => '0', + 'data-module' => $module->name + ); + + $mark_as_favorite = array( + 'href' => '#', + 'class' => 'action_favorite toggle_favorite', + 'onclick' => '', + 'title' => $this->translationsTab['Mark as Favorite'], + 'text' => $this->translationsTab['Mark as Favorite'], + 'cond' => $module->id, + 'icon' => 'star', + 'data-value' => '1', + 'data-module' => $module->name + ); + + $update = array( + 'href' => $module->options['update_url'], + 'onclick' => '', + 'title' => 'Update it!', + 'text' => 'Update it!', + 'icon' => 'refresh', + 'cond' => $module->id, + ); + + $divider = array( + 'href' => '#', + 'onclick' => '', + 'title' => 'divider', + 'text' => 'divider', + 'cond' => $module->id, + ); + + if (isset($module->version_addons) && $module->version_addons) { + $modules_options[] = $update; + } + + if ($module->active) { + $modules_options[] = $configure_module; + $modules_options[] = $desactive_module; + $modules_options[] = $display_mobile; + $modules_options[] = $display_tablet; + $modules_options[] = $display_computer; + } else { + $modules_options[] = $desactive_module; + $modules_options[] = $configure_module; + } + + $modules_options[] = $reset_module; + + if ($output_type == 'select') { + if (!$module->id) { + $modules_options[] = $install; + } else { + $modules_options[] = $uninstall; + } + } elseif ($output_type == 'array') { + if ($module->id) { + $modules_options[] = $uninstall; + } + } + + if (isset($module->preferences) && isset($module->preferences['favorite']) && $module->preferences['favorite'] == 1) { + $remove_from_favorite['style'] = ''; + $mark_as_favorite['style'] = 'display:none;'; + $modules_options[] = $remove_from_favorite; + $modules_options[] = $mark_as_favorite; + } else { + $mark_as_favorite['style'] = ''; + $remove_from_favorite['style'] = 'display:none;'; + $modules_options[] = $remove_from_favorite; + $modules_options[] = $mark_as_favorite; + } + + if ($module->id == 0) { + $install['cond'] = 1; + $install['flag_install'] = 1; + $modules_options[] = $install; + } + $modules_options[] = $divider; + $modules_options[] = $delete_module; + + $return = ''; + foreach ($modules_options as $option_name => $option) { + if ($option['cond']) { + if ($output_type == 'link') { + $return .= '<li><a class="'.$option_name.' action_module'; + $return .= '" href="'.$option['href'].(!is_null($back) ? '&back='.urlencode($back) : '').'"'; + $return .= ' onclick="'.$option['onclick'].'" title="'.$option['title'].'"><i class="icon-'.(isset($option['icon']) && $option['icon'] ? $option['icon']:'cog').'"></i> '.$option['text'].'</a></li>'; + } elseif ($output_type == 'array') { + if (!is_array($return)) { + $return = array(); + } + + $html = '<a class="'; + + $is_install = isset($option['flag_install']) ? true : false; + + if (isset($option['class'])) { + $html .= $option['class']; + } + if ($is_install) { + $html .= ' btn btn-success'; + } + if (!$is_install && count($return) == 0) { + $html .= ' btn btn-default'; + } + + $html .= '"'; + + if (isset($option['data-value'])) { + $html .= ' data-value="'.$option['data-value'].'"'; + } + + if (isset($option['data-module'])) { + $html .= ' data-module="'.$option['data-module'].'"'; + } + + if (isset($option['style'])) { + $html .= ' style="'.$option['style'].'"'; + } + + $html .= ' href="'.htmlentities($option['href']).(!is_null($back) ? '&back='.urlencode($back) : '').'" onclick="'.$option['onclick'].'" title="'.$option['title'].'"><i class="icon-'.(isset($option['icon']) && $option['icon'] ? $option['icon']:'cog').'"></i> '.$option['text'].'</a>'; + $return[] = $html; + } elseif ($output_type == 'select') { + $return .= '<option id="'.$option_name.'" data-href="'.htmlentities($option['href']).(!is_null($back) ? '&back='.urlencode($back) : '').'" data-onclick="'.$option['onclick'].'">'.$option['text'].'</option>'; + } + } + } + + if ($output_type == 'select') { + $return = '<select id="select_'.$module->name.'">'.$return.'</select>'; + } + + return $return; + } + + public function ajaxProcessGetModuleQuickView() + { + $modules = Module::getModulesOnDisk(); + + foreach ($modules as $module) { + if ($module->name == Tools::getValue('module')) { + break; + } + } + + $url = $module->url; + + if (isset($module->type) && ($module->type == 'addonsPartner' || $module->type == 'addonsNative')) { + $url = $this->context->link->getAdminLink('AdminModules').'&install='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name); + } + + $this->context->smarty->assign(array( + 'displayName' => $module->displayName, + 'image' => $module->image, + 'nb_rates' => (int)$module->nb_rates[0], + 'avg_rate' => (int)$module->avg_rate[0], + 'badges' => $module->badges, + 'compatibility' => $module->compatibility, + 'description_full' => $module->description_full, + 'additional_description' => $module->additional_description, + 'is_addons_partner' => (isset($module->type) && ($module->type == 'addonsPartner' || $module->type == 'addonsNative')), + 'url' => $url, + 'price' => $module->price + + )); + // Fetch the translations in the right place - they are not defined by our current controller! + Context::getContext()->override_controller_name_for_translations = 'AdminModules'; + $this->smartyOutputContent('controllers/modules/quickview.tpl'); + die(1); + } + + /** + * Add an entry to the meta title. + * + * @param string $entry New entry. + */ + public function addMetaTitle($entry) + { + // Only add entry if the meta title was not forced. + if (is_array($this->meta_title)) { + $this->meta_title[] = $entry; + } + } } diff --git a/classes/controller/Controller.php b/classes/controller/Controller.php index e5d8b268..79b6f65e 100644 --- a/classes/controller/Controller.php +++ b/classes/controller/Controller.php @@ -30,595 +30,613 @@ */ abstract class ControllerCore { - /** @var Context */ - protected $context; - - /** @var array List of CSS files */ - public $css_files = array(); - - /** @var array List of JavaScript files */ - public $js_files = array(); - - /** @var array List of PHP errors */ - public static $php_errors = array(); - - /** @var bool Set to true to display page header */ - protected $display_header; - - /** @var bool Set to true to display page header javascript */ - protected $display_header_javascript; - - /** @var string Template filename for the page content */ - protected $template; - - /** @var string Set to true to display page footer */ - protected $display_footer; - - /** @var bool Set to true to only render page content (used to get iframe content) */ - protected $content_only = false; - - /** @var bool If AJAX parameter is detected in request, set this flag to true */ - public $ajax = false; - - /** @var bool If set to true, page content and messages will be encoded to JSON before responding to AJAX request */ - protected $json = false; - - /** @var string JSON response status string */ - protected $status = ''; - - /** - * @see Controller::run() - * @var string|null Redirect link. If not empty, the user will be redirected after initializing and processing input. - */ - protected $redirect_after = null; - - /** @var string Controller type. Possible values: 'front', 'modulefront', 'admin', 'moduleadmin' */ - public $controller_type; - - /** @var string Controller name */ - public $php_self; - - /** - * Check if the controller is available for the current user/visitor - */ - abstract public function checkAccess(); - - /** - * Check if the current user/visitor has valid view permissions - */ - abstract public function viewAccess(); - - /** - * Initialize the page - */ - public function init() - { - if (_PS_MODE_DEV_ && $this->controller_type == 'admin') - set_error_handler(array(__CLASS__, 'myErrorHandler')); - - if (!defined('_PS_BASE_URL_')) - define('_PS_BASE_URL_', Tools::getShopDomain(true)); - - if (!defined('_PS_BASE_URL_SSL_')) - define('_PS_BASE_URL_SSL_', Tools::getShopDomainSsl(true)); - } - - /** - * Do the page treatment: process input, process AJAX, etc. - */ - abstract public function postProcess(); - - /** - * Displays page view - */ - abstract public function display(); - - /** - * Sets default media list for this controller - */ - abstract public function setMedia(); - - /** - * returns a new instance of this controller - * - * @param string $class_name - * @param bool $auth - * @param bool $ssl - * @return Controller - */ - public static function getController($class_name, $auth = false, $ssl = false) - { - return new $class_name($auth, $ssl); - } - - public function __construct() - { - if (is_null($this->display_header)) - $this->display_header = true; - - if (is_null($this->display_header_javascript)) - $this->display_header_javascript = true; - - if (is_null($this->display_footer)) - $this->display_footer = true; - - $this->context = Context::getContext(); - $this->context->controller = $this; - - // Usage of ajax parameter is deprecated - $this->ajax = Tools::getValue('ajax') || Tools::isSubmit('ajax'); - - if (!headers_sent() - && isset($_SERVER['HTTP_USER_AGENT']) - && (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false - || strpos($_SERVER['HTTP_USER_AGENT'], 'Trident') !== false)) - header('X-UA-Compatible: IE=edge,chrome=1'); - } - - /** - * Starts the controller process (this method should not be overridden!) - */ - public function run() - { - $this->init(); - if ($this->checkAccess()) - { - // setMedia MUST be called before postProcess - if (!$this->content_only && ($this->display_header || (isset($this->className) && $this->className))) - $this->setMedia(); - - // postProcess handles ajaxProcess - $this->postProcess(); - - if (!empty($this->redirect_after)) - $this->redirect(); - - if (!$this->content_only && ($this->display_header || (isset($this->className) && $this->className))) - $this->initHeader(); - - if ($this->viewAccess()) - $this->initContent(); - else - $this->errors[] = Tools::displayError('Access denied.'); - - if (!$this->content_only && ($this->display_footer || (isset($this->className) && $this->className))) - $this->initFooter(); - - // Default behavior for ajax process is to use $_POST[action] or $_GET[action] - // then using displayAjax[action] - if ($this->ajax) - { - $action = Tools::toCamelCase(Tools::getValue('action'), true); - - if (!empty($action) && method_exists($this, 'displayAjax'.$action)) - $this->{'displayAjax'.$action}(); - elseif (method_exists($this, 'displayAjax')) - $this->displayAjax(); - } - else - $this->display(); - } - else - { - $this->initCursedPage(); - $this->smartyOutputContent($this->layout); - } - } - - /** - * Sets page header display - * - * @param bool $display - */ - public function displayHeader($display = true) - { - $this->display_header = $display; - } - - /** - * Sets page header javascript display - * - * @param bool $display - */ - public function displayHeaderJavaScript($display = true) - { - $this->display_header_javascript = $display; - } - - /** - * Sets page header display - * - * @param bool $display - */ - public function displayFooter($display = true) - { - $this->display_footer = $display; - } - - /** - * Sets template file for page content output - * - * @param string $template - */ - public function setTemplate($template) - { - $this->template = $template; - } - - /** - * Assigns Smarty variables for the page header - */ - abstract public function initHeader(); - - /** - * Assigns Smarty variables for the page main content - */ - abstract public function initContent(); - - /** - * Assigns Smarty variables when access is forbidden - */ - abstract public function initCursedPage(); - - /** - * Assigns Smarty variables for the page footer - */ - abstract public function initFooter(); - - /** - * Redirects to $this->redirect_after after the process if there is no error - */ - abstract protected function redirect(); - - /** - * Set $this->redirect_after that will be used by redirect() after the process - */ - public function setRedirectAfter($url) - { - $this->redirect_after = $url; - } - - /** - * Adds a new stylesheet(s) to the page header. - * - * @param string|array $css_uri Path to CSS file, or list of css files like this : array(array(uri => media_type), ...) - * @param string $css_media_type - * @param int|null $offset - * @param bool $check_path - * @return true - */ - public function addCSS($css_uri, $css_media_type = 'all', $offset = null, $check_path = true) - { - if (!is_array($css_uri)) - $css_uri = array($css_uri); - - foreach ($css_uri as $css_file => $media) - { - if (is_string($css_file) && strlen($css_file) > 1) - { - if ($check_path) - $css_path = Media::getCSSPath($css_file, $media); - else - $css_path = array($css_file => $media); - } - else - { - if ($check_path) - $css_path = Media::getCSSPath($media, $css_media_type); - else - $css_path = array($media => $css_media_type); - } - - $key = is_array($css_path) ? key($css_path) : $css_path; - if ($css_path && (!isset($this->css_files[$key]) || ($this->css_files[$key] != reset($css_path)))) - { - $size = count($this->css_files); - if ($offset === null || $offset > $size || $offset < 0 || !is_numeric($offset)) - $offset = $size; - - $this->css_files = array_merge(array_slice($this->css_files, 0, $offset), $css_path, array_slice($this->css_files, $offset)); - } - } - } - - /** - * Removes CSS stylesheet(s) from the queued stylesheet list - * - * @param string|array $css_uri Path to CSS file or an array like: array(array(uri => media_type), ...) - * @param string $css_media_type - * @param bool $check_path - */ - public function removeCSS($css_uri, $css_media_type = 'all', $check_path = true) - { - if (!is_array($css_uri)) - $css_uri = array($css_uri); - - foreach ($css_uri as $css_file => $media) - { - if (is_string($css_file) && strlen($css_file) > 1) - { - if ($check_path) - $css_path = Media::getCSSPath($css_file, $media); - else - $css_path = array($css_file => $media); - } - else - { - if ($check_path) - $css_path = Media::getCSSPath($media, $css_media_type); - else - $css_path = array($media => $css_media_type); - } - - if ($css_path && isset($this->css_files[key($css_path)]) && ($this->css_files[key($css_path)] == reset($css_path))) - unset($this->css_files[key($css_path)]); - } - } - - /** - * Adds a new JavaScript file(s) to the page header. - * - * @param string|array $js_uri Path to JS file or an array like: array(uri, ...) - * @param bool $check_path - * @return void - */ - public function addJS($js_uri, $check_path = true) - { - if (is_array($js_uri)) - foreach ($js_uri as $js_file) - { - $js_path = $js_file; - if ($check_path) - $js_path = Media::getJSPath($js_file); - - // $key = is_array($js_path) ? key($js_path) : $js_path; - if ($js_path && !in_array($js_path, $this->js_files)) - $this->js_files[] = $js_path; - } - else - { - $js_path = $js_uri; - if ($check_path) - $js_path = Media::getJSPath($js_uri); - - if ($js_path && !in_array($js_path, $this->js_files)) - $this->js_files[] = $js_path; - } - } - - /** - * Removes JS file(s) from the queued JS file list - * - * @param string|array $js_uri Path to JS file or an array like: array(uri, ...) - * @param bool $check_path - */ - public function removeJS($js_uri, $check_path = true) - { - if (is_array($js_uri)) - foreach ($js_uri as $js_file) - { - $js_path = $js_file; - if ($check_path) - $js_path = Media::getJSPath($js_file); - - if ($js_path && in_array($js_path, $this->js_files)) - unset($this->js_files[array_search($js_path, $this->js_files)]); - } - else - { - $js_path = $js_uri; - if ($check_path) - $js_path = Media::getJSPath($js_uri); - - if ($js_path) - unset($this->js_files[array_search($js_path, $this->js_files)]); - } - } - - /** - * Adds jQuery library file to queued JS file list - * - * @param string|null $version jQuery library version - * @param string|null $folder jQuery file folder - * @param bool $minifier If set tot true, a minified version will be included. - */ - public function addJquery($version = null, $folder = null, $minifier = true) - { - $this->addJS(Media::getJqueryPath($version, $folder, $minifier), false); - } - - /** - * Adds jQuery UI component(s) to queued JS file list - * - * @param string|array $component - * @param string $theme - * @param bool $check_dependencies - */ - public function addJqueryUI($component, $theme = 'base', $check_dependencies = true) - { - if (!is_array($component)) - $component = array($component); - - foreach ($component as $ui) - { - $ui_path = Media::getJqueryUIPath($ui, $theme, $check_dependencies); - $this->addCSS($ui_path['css'], 'all', false); - $this->addJS($ui_path['js'], false); - } - } - - /** - * Adds jQuery plugin(s) to queued JS file list - * - * @param string|array $name - * @param string null $folder - * @param bool $css - */ - public function addJqueryPlugin($name, $folder = null, $css = true) - { - if (!is_array($name)) - $name = array($name); - if (is_array($name)) - { - foreach ($name as $plugin) - { - $plugin_path = Media::getJqueryPluginPath($plugin, $folder); - - if (!empty($plugin_path['js'])) - $this->addJS($plugin_path['js'], false); - if ($css && !empty($plugin_path['css'])) - $this->addCSS(key($plugin_path['css']), 'all', null, false); - } - } - } - - /** - * Checks if the controller has been called from XmlHttpRequest (AJAX) - * - * @since 1.5 - * @return bool - */ - public function isXmlHttpRequest() - { - return (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'); - } - - /** - * Renders controller templates and generates page content - * - * @param array|string $content Template file(s) to be rendered - * @throws Exception - * @throws SmartyException - */ - protected function smartyOutputContent($content) - { - $this->context->cookie->write(); - - $html = ''; - $js_tag = 'js_def'; - $this->context->smarty->assign($js_tag, $js_tag); - - if (is_array($content)) - foreach ($content as $tpl) - $html .= $this->context->smarty->fetch($tpl); - else - $html = $this->context->smarty->fetch($content); - - $html = trim($html); - - if (in_array($this->controller_type, array('front', 'modulefront')) && !empty($html) && $this->getLayout()) - { - $live_edit_content = ''; - if (!$this->useMobileTheme() && $this->checkLiveEditAccess()) - $live_edit_content = $this->getLiveEditFooter(); - - $dom_available = extension_loaded('dom') ? true : false; - $defer = (bool)Configuration::get('PS_JS_DEFER'); - - if ($defer && $dom_available) - $html = Media::deferInlineScripts($html); - $html = trim(str_replace(array('</body>', '</html>'), '', $html))."\n"; - - $this->context->smarty->assign(array( - $js_tag => Media::getJsDef(), - 'js_files' => $defer ? array_unique($this->js_files) : array(), - 'js_inline' => ($defer && $dom_available) ? Media::getInlineScript() : array() - )); - - $javascript = $this->context->smarty->fetch(_PS_ALL_THEMES_DIR_.'javascript.tpl'); - - if ($defer) - echo $html.$javascript; - else - echo preg_replace('/(?<!\$)'.$js_tag.'/', $javascript, $html).$live_edit_content.((!isset($this->ajax) || ! $this->ajax) ? '</body></html>' : ''); - } - else - echo $html; - } - - /** - * Checks if a template is cached - * - * @param string $template - * @param string|null $cache_id Cache item ID - * @param string|null $compile_id - * @return bool - */ - protected function isCached($template, $cache_id = null, $compile_id = null) - { - Tools::enableCache(); - $res = $this->context->smarty->isCached($template, $cache_id, $compile_id); - Tools::restoreCacheSettings(); - - return $res; - } - - /** - * Custom error handler - * - * @param string $errno - * @param string $errstr - * @param string $errfile - * @param int $errline - * @return bool - */ - public static function myErrorHandler($errno, $errstr, $errfile, $errline) - { - if (error_reporting() === 0) - return false; - - switch ($errno) - { - case E_USER_ERROR: - case E_ERROR: - die('Fatal error: '.$errstr.' in '.$errfile.' on line '.$errline); - break; - case E_USER_WARNING: - case E_WARNING: - $type = 'Warning'; - break; - case E_USER_NOTICE: - case E_NOTICE: - $type = 'Notice'; - break; - default: - $type = 'Unknown error'; - break; - } - - Controller::$php_errors[] = array( - 'type' => $type, - 'errline' => (int)$errline, - 'errfile' => str_replace('\\', '\\\\', $errfile), // Hack for Windows paths - 'errno' => (int)$errno, - 'errstr' => $errstr - ); - Context::getContext()->smarty->assign('php_errors', Controller::$php_errors); - - return true; - } - - /** - * Dies and echoes output value - * - * @param string|null $value - * @param string|null $controller - * @param string|null $method - */ - protected function ajaxDie($value = null, $controller = null, $method = null) - { - if ($controller === null) - $controller = get_class($this); - - if ($method === null) - { - $bt = debug_backtrace(); - $method = $bt[1]['function']; - } - - Hook::exec('actionBeforeAjaxDie', array('controller' => $controller, 'method' => $method, 'value' => $value)); - Hook::exec('actionBeforeAjaxDie'.$controller.$method, array('value' => $value)); - - die($value); - } + /** @var Context */ + protected $context; + + /** @var array List of CSS files */ + public $css_files = array(); + + /** @var array List of JavaScript files */ + public $js_files = array(); + + /** @var array List of PHP errors */ + public static $php_errors = array(); + + /** @var bool Set to true to display page header */ + protected $display_header; + + /** @var bool Set to true to display page header javascript */ + protected $display_header_javascript; + + /** @var string Template filename for the page content */ + protected $template; + + /** @var string Set to true to display page footer */ + protected $display_footer; + + /** @var bool Set to true to only render page content (used to get iframe content) */ + protected $content_only = false; + + /** @var bool If AJAX parameter is detected in request, set this flag to true */ + public $ajax = false; + + /** @var bool If set to true, page content and messages will be encoded to JSON before responding to AJAX request */ + protected $json = false; + + /** @var string JSON response status string */ + protected $status = ''; + + /** + * @see Controller::run() + * @var string|null Redirect link. If not empty, the user will be redirected after initializing and processing input. + */ + protected $redirect_after = null; + + /** @var string Controller type. Possible values: 'front', 'modulefront', 'admin', 'moduleadmin' */ + public $controller_type; + + /** @var string Controller name */ + public $php_self; + + /** + * Check if the controller is available for the current user/visitor + */ + abstract public function checkAccess(); + + /** + * Check if the current user/visitor has valid view permissions + */ + abstract public function viewAccess(); + + /** + * Initialize the page + */ + public function init() + { + if (_PS_MODE_DEV_ && $this->controller_type == 'admin') { + set_error_handler(array(__CLASS__, 'myErrorHandler')); + } + + if (!defined('_PS_BASE_URL_')) { + define('_PS_BASE_URL_', Tools::getShopDomain(true)); + } + + if (!defined('_PS_BASE_URL_SSL_')) { + define('_PS_BASE_URL_SSL_', Tools::getShopDomainSsl(true)); + } + } + + /** + * Do the page treatment: process input, process AJAX, etc. + */ + abstract public function postProcess(); + + /** + * Displays page view + */ + abstract public function display(); + + /** + * Sets default media list for this controller + */ + abstract public function setMedia(); + + /** + * returns a new instance of this controller + * + * @param string $class_name + * @param bool $auth + * @param bool $ssl + * @return Controller + */ + public static function getController($class_name, $auth = false, $ssl = false) + { + return new $class_name($auth, $ssl); + } + + public function __construct() + { + if (is_null($this->display_header)) { + $this->display_header = true; + } + + if (is_null($this->display_header_javascript)) { + $this->display_header_javascript = true; + } + + if (is_null($this->display_footer)) { + $this->display_footer = true; + } + + $this->context = Context::getContext(); + $this->context->controller = $this; + + // Usage of ajax parameter is deprecated + $this->ajax = Tools::getValue('ajax') || Tools::isSubmit('ajax'); + + if (!headers_sent() + && isset($_SERVER['HTTP_USER_AGENT']) + && (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false + || strpos($_SERVER['HTTP_USER_AGENT'], 'Trident') !== false)) { + header('X-UA-Compatible: IE=edge,chrome=1'); + } + } + + /** + * Starts the controller process (this method should not be overridden!) + */ + public function run() + { + $this->init(); + if ($this->checkAccess()) { + // setMedia MUST be called before postProcess + if (!$this->content_only && ($this->display_header || (isset($this->className) && $this->className))) { + $this->setMedia(); + } + + // postProcess handles ajaxProcess + $this->postProcess(); + + if (!empty($this->redirect_after)) { + $this->redirect(); + } + + if (!$this->content_only && ($this->display_header || (isset($this->className) && $this->className))) { + $this->initHeader(); + } + + if ($this->viewAccess()) { + $this->initContent(); + } else { + $this->errors[] = Tools::displayError('Access denied.'); + } + + if (!$this->content_only && ($this->display_footer || (isset($this->className) && $this->className))) { + $this->initFooter(); + } + + // Default behavior for ajax process is to use $_POST[action] or $_GET[action] + // then using displayAjax[action] + if ($this->ajax) { + $action = Tools::toCamelCase(Tools::getValue('action'), true); + + if (!empty($action) && method_exists($this, 'displayAjax'.$action)) { + $this->{'displayAjax'.$action}(); + } elseif (method_exists($this, 'displayAjax')) { + $this->displayAjax(); + } + } else { + $this->display(); + } + } else { + $this->initCursedPage(); + $this->smartyOutputContent($this->layout); + } + } + + /** + * Sets page header display + * + * @param bool $display + */ + public function displayHeader($display = true) + { + $this->display_header = $display; + } + + /** + * Sets page header javascript display + * + * @param bool $display + */ + public function displayHeaderJavaScript($display = true) + { + $this->display_header_javascript = $display; + } + + /** + * Sets page header display + * + * @param bool $display + */ + public function displayFooter($display = true) + { + $this->display_footer = $display; + } + + /** + * Sets template file for page content output + * + * @param string $template + */ + public function setTemplate($template) + { + $this->template = $template; + } + + /** + * Assigns Smarty variables for the page header + */ + abstract public function initHeader(); + + /** + * Assigns Smarty variables for the page main content + */ + abstract public function initContent(); + + /** + * Assigns Smarty variables when access is forbidden + */ + abstract public function initCursedPage(); + + /** + * Assigns Smarty variables for the page footer + */ + abstract public function initFooter(); + + /** + * Redirects to $this->redirect_after after the process if there is no error + */ + abstract protected function redirect(); + + /** + * Set $this->redirect_after that will be used by redirect() after the process + */ + public function setRedirectAfter($url) + { + $this->redirect_after = $url; + } + + /** + * Adds a new stylesheet(s) to the page header. + * + * @param string|array $css_uri Path to CSS file, or list of css files like this : array(array(uri => media_type), ...) + * @param string $css_media_type + * @param int|null $offset + * @param bool $check_path + * @return true + */ + public function addCSS($css_uri, $css_media_type = 'all', $offset = null, $check_path = true) + { + if (!is_array($css_uri)) { + $css_uri = array($css_uri); + } + + foreach ($css_uri as $css_file => $media) { + if (is_string($css_file) && strlen($css_file) > 1) { + if ($check_path) { + $css_path = Media::getCSSPath($css_file, $media); + } else { + $css_path = array($css_file => $media); + } + } else { + if ($check_path) { + $css_path = Media::getCSSPath($media, $css_media_type); + } else { + $css_path = array($media => $css_media_type); + } + } + + $key = is_array($css_path) ? key($css_path) : $css_path; + if ($css_path && (!isset($this->css_files[$key]) || ($this->css_files[$key] != reset($css_path)))) { + $size = count($this->css_files); + if ($offset === null || $offset > $size || $offset < 0 || !is_numeric($offset)) { + $offset = $size; + } + + $this->css_files = array_merge(array_slice($this->css_files, 0, $offset), $css_path, array_slice($this->css_files, $offset)); + } + } + } + + /** + * Removes CSS stylesheet(s) from the queued stylesheet list + * + * @param string|array $css_uri Path to CSS file or an array like: array(array(uri => media_type), ...) + * @param string $css_media_type + * @param bool $check_path + */ + public function removeCSS($css_uri, $css_media_type = 'all', $check_path = true) + { + if (!is_array($css_uri)) { + $css_uri = array($css_uri); + } + + foreach ($css_uri as $css_file => $media) { + if (is_string($css_file) && strlen($css_file) > 1) { + if ($check_path) { + $css_path = Media::getCSSPath($css_file, $media); + } else { + $css_path = array($css_file => $media); + } + } else { + if ($check_path) { + $css_path = Media::getCSSPath($media, $css_media_type); + } else { + $css_path = array($media => $css_media_type); + } + } + + if ($css_path && isset($this->css_files[key($css_path)]) && ($this->css_files[key($css_path)] == reset($css_path))) { + unset($this->css_files[key($css_path)]); + } + } + } + + /** + * Adds a new JavaScript file(s) to the page header. + * + * @param string|array $js_uri Path to JS file or an array like: array(uri, ...) + * @param bool $check_path + * @return void + */ + public function addJS($js_uri, $check_path = true) + { + if (is_array($js_uri)) { + foreach ($js_uri as $js_file) { + $js_path = $js_file; + if ($check_path) { + $js_path = Media::getJSPath($js_file); + } + + // $key = is_array($js_path) ? key($js_path) : $js_path; + if ($js_path && !in_array($js_path, $this->js_files)) { + $this->js_files[] = $js_path; + } + } + } else { + $js_path = $js_uri; + if ($check_path) { + $js_path = Media::getJSPath($js_uri); + } + + if ($js_path && !in_array($js_path, $this->js_files)) { + $this->js_files[] = $js_path; + } + } + } + + /** + * Removes JS file(s) from the queued JS file list + * + * @param string|array $js_uri Path to JS file or an array like: array(uri, ...) + * @param bool $check_path + */ + public function removeJS($js_uri, $check_path = true) + { + if (is_array($js_uri)) { + foreach ($js_uri as $js_file) { + $js_path = $js_file; + if ($check_path) { + $js_path = Media::getJSPath($js_file); + } + + if ($js_path && in_array($js_path, $this->js_files)) { + unset($this->js_files[array_search($js_path, $this->js_files)]); + } + } + } else { + $js_path = $js_uri; + if ($check_path) { + $js_path = Media::getJSPath($js_uri); + } + + if ($js_path) { + unset($this->js_files[array_search($js_path, $this->js_files)]); + } + } + } + + /** + * Adds jQuery library file to queued JS file list + * + * @param string|null $version jQuery library version + * @param string|null $folder jQuery file folder + * @param bool $minifier If set tot true, a minified version will be included. + */ + public function addJquery($version = null, $folder = null, $minifier = true) + { + $this->addJS(Media::getJqueryPath($version, $folder, $minifier), false); + } + + /** + * Adds jQuery UI component(s) to queued JS file list + * + * @param string|array $component + * @param string $theme + * @param bool $check_dependencies + */ + public function addJqueryUI($component, $theme = 'base', $check_dependencies = true) + { + if (!is_array($component)) { + $component = array($component); + } + + foreach ($component as $ui) { + $ui_path = Media::getJqueryUIPath($ui, $theme, $check_dependencies); + $this->addCSS($ui_path['css'], 'all', false); + $this->addJS($ui_path['js'], false); + } + } + + /** + * Adds jQuery plugin(s) to queued JS file list + * + * @param string|array $name + * @param string null $folder + * @param bool $css + */ + public function addJqueryPlugin($name, $folder = null, $css = true) + { + if (!is_array($name)) { + $name = array($name); + } + if (is_array($name)) { + foreach ($name as $plugin) { + $plugin_path = Media::getJqueryPluginPath($plugin, $folder); + + if (!empty($plugin_path['js'])) { + $this->addJS($plugin_path['js'], false); + } + if ($css && !empty($plugin_path['css'])) { + $this->addCSS(key($plugin_path['css']), 'all', null, false); + } + } + } + } + + /** + * Checks if the controller has been called from XmlHttpRequest (AJAX) + * + * @since 1.5 + * @return bool + */ + public function isXmlHttpRequest() + { + return (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'); + } + + /** + * Renders controller templates and generates page content + * + * @param array|string $content Template file(s) to be rendered + * @throws Exception + * @throws SmartyException + */ + protected function smartyOutputContent($content) + { + $this->context->cookie->write(); + + $html = ''; + $js_tag = 'js_def'; + $this->context->smarty->assign($js_tag, $js_tag); + + if (is_array($content)) { + foreach ($content as $tpl) { + $html .= $this->context->smarty->fetch($tpl); + } + } else { + $html = $this->context->smarty->fetch($content); + } + + $html = trim($html); + + if (in_array($this->controller_type, array('front', 'modulefront')) && !empty($html) && $this->getLayout()) { + $live_edit_content = ''; + if (!$this->useMobileTheme() && $this->checkLiveEditAccess()) { + $live_edit_content = $this->getLiveEditFooter(); + } + + $dom_available = extension_loaded('dom') ? true : false; + $defer = (bool)Configuration::get('PS_JS_DEFER'); + + if ($defer && $dom_available) { + $html = Media::deferInlineScripts($html); + } + $html = trim(str_replace(array('</body>', '</html>'), '', $html))."\n"; + + $this->context->smarty->assign(array( + $js_tag => Media::getJsDef(), + 'js_files' => $defer ? array_unique($this->js_files) : array(), + 'js_inline' => ($defer && $dom_available) ? Media::getInlineScript() : array() + )); + + $javascript = $this->context->smarty->fetch(_PS_ALL_THEMES_DIR_.'javascript.tpl'); + + if ($defer && (!isset($this->ajax) || ! $this->ajax)) { + echo $html.$javascript; + } else { + echo preg_replace('/(?<!\$)'.$js_tag.'/', $javascript, $html); + } + echo $live_edit_content.((!isset($this->ajax) || ! $this->ajax) ? '</body></html>' : ''); + } else { + echo $html; + } + } + + /** + * Checks if a template is cached + * + * @param string $template + * @param string|null $cache_id Cache item ID + * @param string|null $compile_id + * @return bool + */ + protected function isCached($template, $cache_id = null, $compile_id = null) + { + Tools::enableCache(); + $res = $this->context->smarty->isCached($template, $cache_id, $compile_id); + Tools::restoreCacheSettings(); + + return $res; + } + + /** + * Custom error handler + * + * @param string $errno + * @param string $errstr + * @param string $errfile + * @param int $errline + * @return bool + */ + public static function myErrorHandler($errno, $errstr, $errfile, $errline) + { + if (error_reporting() === 0) { + return false; + } + + switch ($errno) { + case E_USER_ERROR: + case E_ERROR: + die('Fatal error: '.$errstr.' in '.$errfile.' on line '.$errline); + break; + case E_USER_WARNING: + case E_WARNING: + $type = 'Warning'; + break; + case E_USER_NOTICE: + case E_NOTICE: + $type = 'Notice'; + break; + default: + $type = 'Unknown error'; + break; + } + + Controller::$php_errors[] = array( + 'type' => $type, + 'errline' => (int)$errline, + 'errfile' => str_replace('\\', '\\\\', $errfile), // Hack for Windows paths + 'errno' => (int)$errno, + 'errstr' => $errstr + ); + Context::getContext()->smarty->assign('php_errors', Controller::$php_errors); + + return true; + } + + /** + * Dies and echoes output value + * + * @param string|null $value + * @param string|null $controller + * @param string|null $method + */ + protected function ajaxDie($value = null, $controller = null, $method = null) + { + if ($controller === null) { + $controller = get_class($this); + } + + if ($method === null) { + $bt = debug_backtrace(); + $method = $bt[1]['function']; + } + + Hook::exec('actionBeforeAjaxDie', array('controller' => $controller, 'method' => $method, 'value' => $value)); + Hook::exec('actionBeforeAjaxDie'.$controller.$method, array('value' => $value)); + + die($value); + } } diff --git a/classes/controller/FrontController.php b/classes/controller/FrontController.php index 7024f272..8efb8408 100644 --- a/classes/controller/FrontController.php +++ b/classes/controller/FrontController.php @@ -26,1633 +26,1662 @@ class FrontControllerCore extends Controller { - /** - * @deprecated Deprecated shortcuts as of 1.5.0.1 - Use $context->smarty instead - * @var $smarty Smarty - */ - protected static $smarty; - - /** - * @deprecated Deprecated shortcuts as of 1.5.0.1 - Use $context->cookie instead - * @var $cookie Cookie - */ - protected static $cookie; - - /** - * @deprecated Deprecated shortcuts as of 1.5.0.1 - Use $context->link instead - * @var $link Link - */ - protected static $link; - - /** - * @deprecated Deprecated shortcuts as of 1.5.0.1 - Use $context->cart instead - * @var $cart Cart - */ - protected static $cart; - - /** @var array Controller errors */ - public $errors = array(); - - /** @var string Language ISO code */ - public $iso; - - /** @var string ORDER BY field */ - public $orderBy; - - /** @var string Order way string ('ASC', 'DESC') */ - public $orderWay; - - /** @var int Current page number */ - public $p; - - /** @var int Items (products) per page */ - public $n; - - /** @var bool If set to true, will redirected user to login page during init function. */ - public $auth = false; - - /** - * If set to true, user can be logged in as guest when checking if logged in. - * - * @see $auth - * @var bool - */ - public $guestAllowed = false; - - /** - * Route of PrestaShop page to redirect to after forced login. - * - * @see $auth - * @var bool - */ - public $authRedirection = false; - - /** @var bool SSL connection flag */ - public $ssl = false; - - /** @var bool If true, switches display to restricted country page during init. */ - protected $restrictedCountry = false; - - /** @var bool If true, forces display to maintenance page. */ - protected $maintenance = false; - - /** @var bool If false, does not build left page column content and hides it. */ - public $display_column_left = true; - - /** @var bool If false, does not build right page column content and hides it. */ - public $display_column_right = true; - - /** - * True if controller has already been initialized. - * Prevents initializing controller more than once. - * - * @var bool - */ - public static $initialized = false; - - /** - * @var array Holds current customer's groups. - */ - protected static $currentCustomerGroups; - - /** - * @var int - */ - public $nb_items_per_page; - - /** - * Controller constructor - * - * @global bool $useSSL SSL connection flag - */ - public function __construct() - { - $this->controller_type = 'front'; - - global $useSSL; - - parent::__construct(); - - if (Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE')) - $this->ssl = true; - - if (isset($useSSL)) - $this->ssl = $useSSL; - else - $useSSL = $this->ssl; - - if (isset($this->php_self) && is_object(Context::getContext()->theme)) - { - $columns = Context::getContext()->theme->hasColumns($this->php_self); - - // Don't use theme tables if not configured in DB - if ($columns) - { - $this->display_column_left = $columns['left_column']; - $this->display_column_right = $columns['right_column']; - } - } - } - - /** - * Check if the controller is available for the current user/visitor - * - * @see Controller::checkAccess() - * @return bool - */ - public function checkAccess() - { - return true; - } - - /** - * Check if the current user/visitor has valid view permissions - * - * @see Controller::viewAccess - * @return bool - */ - public function viewAccess() - { - return true; - } - - /** - * Initializes front controller: sets smarty variables, - * class properties, redirects depending on context, etc. - * - * @global bool $useSSL SSL connection flag - * @global Cookie $cookie Visitor's cookie - * @global Smarty $smarty - * @global Cart $cart Visitor's cart - * @global string $iso Language ISO - * @global Country $defaultCountry Visitor's country object - * @global string $protocol_link - * @global string $protocol_content - * @global Link $link - * @global array $css_files - * @global array $js_files - * @global Currency $currency Visitor's selected currency - * - * @throws PrestaShopException - */ - public function init() - { - /** - * Globals are DEPRECATED as of version 1.5.0.1 - * Use the Context object to access objects instead. - * Example: $this->context->cart - */ - global $useSSL, $cookie, $smarty, $cart, $iso, $defaultCountry, $protocol_link, $protocol_content, $link, $css_files, $js_files, $currency; - - if (self::$initialized) - return; - - self::$initialized = true; - - parent::init(); - - // If current URL use SSL, set it true (used a lot for module redirect) - if (Tools::usingSecureMode()) - $useSSL = true; - - // For compatibility with globals, DEPRECATED as of version 1.5.0.1 - $css_files = $this->css_files; - $js_files = $this->js_files; - - $this->sslRedirection(); - - if ($this->ajax) - { - $this->display_header = false; - $this->display_footer = false; - } - - // If account created with the 2 steps register process, remove 'account_created' from cookie - if (isset($this->context->cookie->account_created)) - { - $this->context->smarty->assign('account_created', 1); - unset($this->context->cookie->account_created); - } - - ob_start(); - - // Init cookie language - // @TODO This method must be moved into switchLanguage - Tools::setCookieLanguage($this->context->cookie); - - $protocol_link = (Configuration::get('PS_SSL_ENABLED') || Tools::usingSecureMode()) ? 'https://' : 'http://'; - $useSSL = ((isset($this->ssl) && $this->ssl && Configuration::get('PS_SSL_ENABLED')) || Tools::usingSecureMode()) ? true : false; - $protocol_content = ($useSSL) ? 'https://' : 'http://'; - $link = new Link($protocol_link, $protocol_content); - $this->context->link = $link; - - if ($id_cart = (int)$this->recoverCart()) - $this->context->cookie->id_cart = (int)$id_cart; - - if ($this->auth && !$this->context->customer->isLogged($this->guestAllowed)) - Tools::redirect('index.php?controller=authentication'.($this->authRedirection ? '&back='.$this->authRedirection : '')); - - /* Theme is missing */ - if (!is_dir(_PS_THEME_DIR_)) - throw new PrestaShopException((sprintf(Tools::displayError('Current theme unavailable "%s". Please check your theme directory name and permissions.'), basename(rtrim(_PS_THEME_DIR_, '/\\'))))); - - if (Configuration::get('PS_GEOLOCATION_ENABLED')) - { - if (($new_default = $this->geolocationManagement($this->context->country)) && Validate::isLoadedObject($new_default)) - $this->context->country = $new_default; - } - elseif (Configuration::get('PS_DETECT_COUNTRY')) - { - $has_currency = isset($this->context->cookie->id_currency) && (int)$this->context->cookie->id_currency; - $has_country = isset($this->context->cookie->iso_code_country) && $this->context->cookie->iso_code_country; - $has_address_type = false; - - if ((int)$this->context->cookie->id_cart && ($cart = new Cart($this->context->cookie->id_cart)) && Validate::isLoadedObject($cart)) - $has_address_type = isset($cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) && $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; - - if ((!$has_currency || $has_country) && !$has_address_type) - { - $id_country = $has_country && !Validate::isLanguageIsoCode($this->context->cookie->iso_code_country) ? - (int)Country::getByIso(strtoupper($this->context->cookie->iso_code_country)) : (int)Tools::getCountry(); - - $country = new Country($id_country, (int)$this->context->cookie->id_lang); - - if (validate::isLoadedObject($country) && $this->context->country->id !== $country->id) - { - $this->context->country = $country; - $this->context->cookie->id_currency = (int)Currency::getCurrencyInstance($country->id_currency ? (int)$country->id_currency : (int)Configuration::get('PS_CURRENCY_DEFAULT'))->id; - $this->context->cookie->iso_code_country = strtoupper($country->iso_code); - } - } - } - - $currency = Tools::setCurrency($this->context->cookie); - - if (isset($_GET['logout']) || ($this->context->customer->logged && Customer::isBanned($this->context->customer->id))) - { - $this->context->customer->logout(); - - Tools::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null); - } - elseif (isset($_GET['mylogout'])) - { - $this->context->customer->mylogout(); - Tools::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null); - } - - /* Cart already exists */ - if ((int)$this->context->cookie->id_cart) - { - if (!isset($cart)) - $cart = new Cart($this->context->cookie->id_cart); - - if (Validate::isLoadedObject($cart) && $cart->OrderExists()) - { - PrestaShopLogger::addLog('Frontcontroller::init - Cart cannot be loaded or an order has already been placed using this cart', 1, null, 'Cart', (int)$this->context->cookie->id_cart, true); - unset($this->context->cookie->id_cart, $cart, $this->context->cookie->checkedTOS); - $this->context->cookie->check_cgv = false; - } - /* Delete product of cart, if user can't make an order from his country */ - elseif (intval(Configuration::get('PS_GEOLOCATION_ENABLED')) && - !in_array(strtoupper($this->context->cookie->iso_code_country), explode(';', Configuration::get('PS_ALLOWED_COUNTRIES'))) && - $cart->nbProducts() && intval(Configuration::get('PS_GEOLOCATION_NA_BEHAVIOR')) != -1 && - !FrontController::isInWhitelistForGeolocation() && - !in_array($_SERVER['SERVER_NAME'], array('localhost', '127.0.0.1'))) - { - PrestaShopLogger::addLog('Frontcontroller::init - GEOLOCATION is deleting a cart', 1, null, 'Cart', (int)$this->context->cookie->id_cart, true); - unset($this->context->cookie->id_cart, $cart); - } - // update cart values - elseif ($this->context->cookie->id_customer != $cart->id_customer || $this->context->cookie->id_lang != $cart->id_lang || $currency->id != $cart->id_currency) - { - if ($this->context->cookie->id_customer) - $cart->id_customer = (int)$this->context->cookie->id_customer; - $cart->id_lang = (int)$this->context->cookie->id_lang; - $cart->id_currency = (int)$currency->id; - $cart->update(); - } - /* Select an address if not set */ - if (isset($cart) && (!isset($cart->id_address_delivery) || $cart->id_address_delivery == 0 || - !isset($cart->id_address_invoice) || $cart->id_address_invoice == 0) && $this->context->cookie->id_customer) - { - $to_update = false; - if (!isset($cart->id_address_delivery) || $cart->id_address_delivery == 0) - { - $to_update = true; - $cart->id_address_delivery = (int)Address::getFirstCustomerAddressId($cart->id_customer); - } - if (!isset($cart->id_address_invoice) || $cart->id_address_invoice == 0) - { - $to_update = true; - $cart->id_address_invoice = (int)Address::getFirstCustomerAddressId($cart->id_customer); - } - if ($to_update) - $cart->update(); - } - } - - if (!isset($cart) || !$cart->id) - { - $cart = new Cart(); - $cart->id_lang = (int)$this->context->cookie->id_lang; - $cart->id_currency = (int)$this->context->cookie->id_currency; - $cart->id_guest = (int)$this->context->cookie->id_guest; - $cart->id_shop_group = (int)$this->context->shop->id_shop_group; - $cart->id_shop = $this->context->shop->id; - if ($this->context->cookie->id_customer) - { - $cart->id_customer = (int)$this->context->cookie->id_customer; - $cart->id_address_delivery = (int)Address::getFirstCustomerAddressId($cart->id_customer); - $cart->id_address_invoice = (int)$cart->id_address_delivery; - } - else - { - $cart->id_address_delivery = 0; - $cart->id_address_invoice = 0; - } - - // Needed if the merchant want to give a free product to every visitors - $this->context->cart = $cart; - CartRule::autoAddToCart($this->context); - } - else - $this->context->cart = $cart; - - /* get page name to display it in body id */ - - // Are we in a payment module - $module_name = ''; - if (Validate::isModuleName(Tools::getValue('module'))) - $module_name = Tools::getValue('module'); - - if (!empty($this->page_name)) - $page_name = $this->page_name; - elseif (!empty($this->php_self)) - $page_name = $this->php_self; - elseif (Tools::getValue('fc') == 'module' && $module_name != '' && (Module::getInstanceByName($module_name) instanceof PaymentModule)) - $page_name = 'module-payment-submit'; - // @retrocompatibility Are we in a module ? - elseif (preg_match('#^'.preg_quote($this->context->shop->physical_uri, '#').'modules/([a-zA-Z0-9_-]+?)/(.*)$#', $_SERVER['REQUEST_URI'], $m)) - $page_name = 'module-'.$m[1].'-'.str_replace(array('.php', '/'), array('', '-'), $m[2]); - else - { - $page_name = Dispatcher::getInstance()->getController(); - $page_name = (preg_match('/^[0-9]/', $page_name) ? 'page_'.$page_name : $page_name); - } - - $this->context->smarty->assign(Meta::getMetaTags($this->context->language->id, $page_name)); - $this->context->smarty->assign('request_uri', Tools::safeOutput(urldecode($_SERVER['REQUEST_URI']))); - - /* Breadcrumb */ - $navigation_pipe = (Configuration::get('PS_NAVIGATION_PIPE') ? Configuration::get('PS_NAVIGATION_PIPE') : '>'); - $this->context->smarty->assign('navigationPipe', $navigation_pipe); - - // Automatically redirect to the canonical URL if needed - if (!empty($this->php_self) && !Tools::getValue('ajax')) - $this->canonicalRedirection($this->context->link->getPageLink($this->php_self, $this->ssl, $this->context->language->id)); - - Product::initPricesComputation(); - - $display_tax_label = $this->context->country->display_tax_label; - if (isset($cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) && $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) - { - $infos = Address::getCountryAndState((int)$cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); - $country = new Country((int)$infos['id_country']); - $this->context->country = $country; - if (Validate::isLoadedObject($country)) - $display_tax_label = $country->display_tax_label; - } - - $languages = Language::getLanguages(true, $this->context->shop->id); - $meta_language = array(); - foreach ($languages as $lang) - $meta_language[] = $lang['iso_code']; - - $compared_products = array(); - if (Configuration::get('PS_COMPARATOR_MAX_ITEM') && isset($this->context->cookie->id_compare)) - $compared_products = CompareProduct::getCompareProducts($this->context->cookie->id_compare); - - $this->context->smarty->assign(array( - // Useful for layout.tpl - 'mobile_device' => $this->context->getMobileDevice(), - 'link' => $link, - 'cart' => $cart, - 'currency' => $currency, - 'currencyRate' => (float)$currency->getConversationRate(), - 'cookie' => $this->context->cookie, - 'page_name' => $page_name, - 'hide_left_column' => !$this->display_column_left, - 'hide_right_column' => !$this->display_column_right, - 'base_dir' => _PS_BASE_URL_.__PS_BASE_URI__, - 'base_dir_ssl' => $protocol_link.Tools::getShopDomainSsl().__PS_BASE_URI__, - 'force_ssl' => Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE'), - 'content_dir' => $protocol_content.Tools::getHttpHost().__PS_BASE_URI__, - 'base_uri' => $protocol_content.Tools::getHttpHost().__PS_BASE_URI__.(!Configuration::get('PS_REWRITING_SETTINGS') ? 'index.php' : ''), - 'tpl_dir' => _PS_THEME_DIR_, - 'tpl_uri' => _THEME_DIR_, - 'modules_dir' => _MODULE_DIR_, - 'mail_dir' => _MAIL_DIR_, - 'lang_iso' => $this->context->language->iso_code, - 'lang_id' => (int)$this->context->language->id, - 'language_code' => $this->context->language->language_code ? $this->context->language->language_code : $this->context->language->iso_code, - 'come_from' => Tools::getHttpHost(true, true).Tools::htmlentitiesUTF8(str_replace(array('\'', '\\'), '', urldecode($_SERVER['REQUEST_URI']))), - 'cart_qties' => (int)$cart->nbProducts(), - 'currencies' => Currency::getCurrencies(), - 'languages' => $languages, - 'meta_language' => implode(',', $meta_language), - 'priceDisplay' => Product::getTaxCalculationMethod((int)$this->context->cookie->id_customer), - 'is_logged' => (bool)$this->context->customer->isLogged(), - 'is_guest' => (bool)$this->context->customer->isGuest(), - 'add_prod_display' => (int)Configuration::get('PS_ATTRIBUTE_CATEGORY_DISPLAY'), - 'shop_name' => Configuration::get('PS_SHOP_NAME'), - 'roundMode' => (int)Configuration::get('PS_PRICE_ROUND_MODE'), - 'use_taxes' => (int)Configuration::get('PS_TAX'), - 'show_taxes' => (int)(Configuration::get('PS_TAX_DISPLAY') == 1 && (int)Configuration::get('PS_TAX')), - 'display_tax_label' => (bool)$display_tax_label, - 'vat_management' => (int)Configuration::get('VATNUMBER_MANAGEMENT'), - 'opc' => (bool)Configuration::get('PS_ORDER_PROCESS_TYPE'), - 'PS_CATALOG_MODE' => (bool)Configuration::get('PS_CATALOG_MODE') || (Group::isFeatureActive() && !(bool)Group::getCurrent()->show_prices), - 'b2b_enable' => (bool)Configuration::get('PS_B2B_ENABLE'), - 'request' => $link->getPaginationLink(false, false, false, true), - 'PS_STOCK_MANAGEMENT' => Configuration::get('PS_STOCK_MANAGEMENT'), - 'quick_view' => (bool)Configuration::get('PS_QUICK_VIEW'), - 'shop_phone' => Configuration::get('PS_SHOP_PHONE'), - 'compared_products' => is_array($compared_products) ? $compared_products : array(), - 'comparator_max_item' => (int)Configuration::get('PS_COMPARATOR_MAX_ITEM'), - 'currencySign' => $currency->sign, // backward compat, see global.tpl - 'currencyFormat' => $currency->format, // backward compat - 'currencyBlank' => $currency->blank, // backward compat - )); - - // Add the tpl files directory for mobile - if ($this->useMobileTheme()) - $this->context->smarty->assign(array( - 'tpl_mobile_uri' => _PS_THEME_MOBILE_DIR_, - )); - - // Deprecated - $this->context->smarty->assign(array( - 'id_currency_cookie' => (int)$currency->id, - 'logged' => $this->context->customer->isLogged(), - 'customerName' => ($this->context->customer->logged ? $this->context->cookie->customer_firstname.' '.$this->context->cookie->customer_lastname : false) - )); - - $assign_array = array( - 'img_ps_dir' => _PS_IMG_, - 'img_cat_dir' => _THEME_CAT_DIR_, - 'img_lang_dir' => _THEME_LANG_DIR_, - 'img_prod_dir' => _THEME_PROD_DIR_, - 'img_manu_dir' => _THEME_MANU_DIR_, - 'img_sup_dir' => _THEME_SUP_DIR_, - 'img_ship_dir' => _THEME_SHIP_DIR_, - 'img_store_dir' => _THEME_STORE_DIR_, - 'img_col_dir' => _THEME_COL_DIR_, - 'img_dir' => _THEME_IMG_DIR_, - 'css_dir' => _THEME_CSS_DIR_, - 'js_dir' => _THEME_JS_DIR_, - 'pic_dir' => _THEME_PROD_PIC_DIR_ - ); - - // Add the images directory for mobile - if ($this->useMobileTheme()) - $assign_array['img_mobile_dir'] = _THEME_MOBILE_IMG_DIR_; - - // Add the CSS directory for mobile - if ($this->useMobileTheme()) - $assign_array['css_mobile_dir'] = _THEME_MOBILE_CSS_DIR_; - - foreach ($assign_array as $assign_key => $assign_value) - if (substr($assign_value, 0, 1) == '/' || $protocol_content == 'https://') - $this->context->smarty->assign($assign_key, $protocol_content.Tools::getMediaServer($assign_value).$assign_value); - else - $this->context->smarty->assign($assign_key, $assign_value); - - /** - * These shortcuts are DEPRECATED as of version 1.5.0.1 - * Use the Context to access objects instead. - * Example: $this->context->cart - */ - self::$cookie = $this->context->cookie; - self::$cart = $cart; - self::$smarty = $this->context->smarty; - self::$link = $link; - $defaultCountry = $this->context->country; - - $this->displayMaintenancePage(); - - if ($this->restrictedCountry) - $this->displayRestrictedCountryPage(); - - if (Tools::isSubmit('live_edit') && !$this->checkLiveEditAccess()) - Tools::redirect('index.php?controller=404'); - - $this->iso = $iso; - $this->context->cart = $cart; - $this->context->currency = $currency; - } - - /** - * Method that is executed after init() and checkAccess(). - * Used to process user input. - * - * @see Controller::run() - */ - public function postProcess() - { - } - - /** - * Initializes common front page content: header, footer and side columns - */ - public function initContent() - { - $this->process(); - - if (!isset($this->context->cart)) - $this->context->cart = new Cart(); - - if (!$this->useMobileTheme()) - { - // These hooks aren't used for the mobile theme. - // Needed hooks are called in the tpl files. - $this->context->smarty->assign(array( - 'HOOK_HEADER' => Hook::exec('displayHeader'), - 'HOOK_TOP' => Hook::exec('displayTop'), - 'HOOK_LEFT_COLUMN' => ($this->display_column_left ? Hook::exec('displayLeftColumn') : ''), - 'HOOK_RIGHT_COLUMN' => ($this->display_column_right ? Hook::exec('displayRightColumn', array('cart' => $this->context->cart)) : ''), - )); - } - else - $this->context->smarty->assign('HOOK_MOBILE_HEADER', Hook::exec('displayMobileHeader')); - } - - /** - * Compiles and outputs page header section (including HTML <head>) - * - * @param bool $display If true, renders visual page header section - * @deprecated 1.5.0.1 - */ - public function displayHeader($display = true) - { - Tools::displayAsDeprecated(); - - $this->initHeader(); - $hook_header = Hook::exec('displayHeader'); - if ((Configuration::get('PS_CSS_THEME_CACHE') || Configuration::get('PS_JS_THEME_CACHE')) && is_writable(_PS_THEME_DIR_.'cache')) - { - // CSS compressor management - if (Configuration::get('PS_CSS_THEME_CACHE')) - $this->css_files = Media::cccCss($this->css_files); - - //JS compressor management - if (Configuration::get('PS_JS_THEME_CACHE')) - $this->js_files = Media::cccJs($this->js_files); - } - - // Call hook before assign of css_files and js_files in order to include correctly all css and javascript files - $this->context->smarty->assign(array( - 'HOOK_HEADER' => $hook_header, - 'HOOK_TOP' => Hook::exec('displayTop'), - 'HOOK_LEFT_COLUMN' => ($this->display_column_left ? Hook::exec('displayLeftColumn') : ''), - 'HOOK_RIGHT_COLUMN' => ($this->display_column_right ? Hook::exec('displayRightColumn', array('cart' => $this->context->cart)) : ''), - 'HOOK_FOOTER' => Hook::exec('displayFooter') - )); - - $this->context->smarty->assign(array( - 'css_files' => $this->css_files, - 'js_files' => ($this->getLayout() && (bool)Configuration::get('PS_JS_DEFER')) ? array() : $this->js_files - )); - - $this->display_header = $display; - $this->smartyOutputContent(_PS_THEME_DIR_.'header.tpl'); - } - - /** - * Compiles and outputs page footer section - * - * @deprecated 1.5.0.1 - */ - public function displayFooter($display = true) - { - Tools::displayAsDeprecated(); - $this->smartyOutputContent(_PS_THEME_DIR_.'footer.tpl'); - } - - /** - * Renders and outputs maintenance page and ends controller process. - */ - public function initCursedPage() - { - $this->displayMaintenancePage(); - } - - /** - * Called before compiling common page sections (header, footer, columns). - * Good place to modify smarty variables. - * - * @see FrontController::initContent() - */ - public function process() - { - } - - /** - * Redirects to redirect_after link - * - * @see $redirect_after - */ - protected function redirect() - { - Tools::redirectLink($this->redirect_after); - } - - /** - * Renders page content. - * Used for retrocompatibility with PS 1.4 - */ - public function displayContent() - { - } - - /** - * Compiles and outputs full page content - * - * @return bool - * @throws Exception - * @throws SmartyException - */ - public function display() - { - Tools::safePostVars(); - - // assign css_files and js_files at the very last time - if ((Configuration::get('PS_CSS_THEME_CACHE') || Configuration::get('PS_JS_THEME_CACHE')) && is_writable(_PS_THEME_DIR_.'cache')) - { - // CSS compressor management - if (Configuration::get('PS_CSS_THEME_CACHE')) - $this->css_files = Media::cccCss($this->css_files); - //JS compressor management - if (Configuration::get('PS_JS_THEME_CACHE') && !$this->useMobileTheme()) - $this->js_files = Media::cccJs($this->js_files); - } - - $this->context->smarty->assign(array( - 'css_files' => $this->css_files, - 'js_files' => ($this->getLayout() && (bool)Configuration::get('PS_JS_DEFER')) ? array() : $this->js_files, - 'js_defer' => (bool)Configuration::get('PS_JS_DEFER'), - 'errors' => $this->errors, - 'display_header' => $this->display_header, - 'display_footer' => $this->display_footer, - )); - - $layout = $this->getLayout(); - if ($layout) - { - if ($this->template) - $template = $this->context->smarty->fetch($this->template); - else // For retrocompatibility with 1.4 controller - { - ob_start(); - $this->displayContent(); - $template = ob_get_contents(); - ob_clean(); - - } - $this->context->smarty->assign('template', $template); - $this->smartyOutputContent($layout); - } - else - { - Tools::displayAsDeprecated('layout.tpl is missing in your theme directory'); - if ($this->display_header) - $this->smartyOutputContent(_PS_THEME_DIR_.'header.tpl'); - - if ($this->template) - $this->smartyOutputContent($this->template); - else // For retrocompatibility with 1.4 controller - $this->displayContent(); - - if ($this->display_footer) - $this->smartyOutputContent(_PS_THEME_DIR_.'footer.tpl'); - } - - return true; - } - - /** - * Displays maintenance page if shop is closed. - */ - protected function displayMaintenancePage() - { - if ($this->maintenance == true || !(int)Configuration::get('PS_SHOP_ENABLE')) - { - $this->maintenance = true; - if (!in_array(Tools::getRemoteAddr(), explode(',', Configuration::get('PS_MAINTENANCE_IP')))) - { - header('HTTP/1.1 503 temporarily overloaded'); - - $this->context->smarty->assign($this->initLogoAndFavicon()); - $this->context->smarty->assign(array( - 'HOOK_MAINTENANCE' => Hook::exec('displayMaintenance', array()), - )); - - // If the controller is a module, then getTemplatePath will try to find the template in the modules, so we need to instanciate a real frontcontroller - $front_controller = preg_match('/ModuleFrontController$/', get_class($this)) ? new FrontController() : $this; - $this->smartyOutputContent($front_controller->getTemplatePath($this->getThemeDir().'maintenance.tpl')); - exit; - } - } - } - - /** - * Displays 'country restricted' page if user's country is not allowed. - */ - protected function displayRestrictedCountryPage() - { - header('HTTP/1.1 503 temporarily overloaded'); - $this->context->smarty->assign(array( - 'shop_name' => $this->context->shop->name, - 'favicon_url' => _PS_IMG_.Configuration::get('PS_FAVICON'), - 'logo_url' => $this->context->link->getMediaLink(_PS_IMG_.Configuration::get('PS_LOGO')) - )); - $this->smartyOutputContent($this->getTemplatePath($this->getThemeDir().'restricted-country.tpl')); - exit; - } - - /** - * Redirects to correct protocol if settings and request methods don't match. - */ - protected function sslRedirection() - { - // If we call a SSL controller without SSL or a non SSL controller with SSL, we redirect with the right protocol - if (Configuration::get('PS_SSL_ENABLED') && $_SERVER['REQUEST_METHOD'] != 'POST' && $this->ssl != Tools::usingSecureMode()) - { - $this->context->cookie->disallowWriting(); - header('HTTP/1.1 301 Moved Permanently'); - header('Cache-Control: no-cache'); - if ($this->ssl) - header('Location: '.Tools::getShopDomainSsl(true).$_SERVER['REQUEST_URI']); - else - header('Location: '.Tools::getShopDomain(true).$_SERVER['REQUEST_URI']); - exit(); - } - } - - /** - * Redirects to canonical URL - * - * @param string $canonical_url - */ - protected function canonicalRedirection($canonical_url = '') - { - if (!$canonical_url || !Configuration::get('PS_CANONICAL_REDIRECT') || strtoupper($_SERVER['REQUEST_METHOD']) != 'GET' || Tools::getValue('live_edit')) - return; - - $match_url = rawurldecode(Tools::getCurrentUrlProtocolPrefix().$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); - if (!preg_match('/^'.Tools::pRegexp(rawurldecode($canonical_url), '/').'([&?].*)?$/', $match_url)) - { - $params = array(); - $url_details = parse_url($canonical_url); - - if (!empty($url_details['query'])) - { - parse_str($url_details['query'], $query); - foreach ($query as $key => $value) - $params[Tools::safeOutput($key)] = Tools::safeOutput($value); - } - $excluded_key = array('isolang', 'id_lang', 'controller', 'fc', 'id_product', 'id_category', 'id_manufacturer', 'id_supplier', 'id_cms'); - foreach ($_GET as $key => $value) - if (!in_array($key, $excluded_key) && Validate::isUrl($key) && Validate::isUrl($value)) - $params[Tools::safeOutput($key)] = Tools::safeOutput($value); - - $str_params = http_build_query($params, '', '&'); - if (!empty($str_params)) - $final_url = preg_replace('/^([^?]*)?.*$/', '$1', $canonical_url).'?'.$str_params; - else - $final_url = preg_replace('/^([^?]*)?.*$/', '$1', $canonical_url); - - // Don't send any cookie - Context::getContext()->cookie->disallowWriting(); - - if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_ && $_SERVER['REQUEST_URI'] != __PS_BASE_URI__) - die('[Debug] This page has moved<br />Please use the following URL instead: <a href="'.$final_url.'">'.$final_url.'</a>'); - - $redirect_type = Configuration::get('PS_CANONICAL_REDIRECT') == 2 ? '301' : '302'; - header('HTTP/1.0 '.$redirect_type.' Moved'); - header('Cache-Control: no-cache'); - Tools::redirectLink($final_url); - } - } - - /** - * Geolocation management - * - * @param Country $default_country - * @return Country|false - */ - protected function geolocationManagement($default_country) - { - if (!in_array($_SERVER['SERVER_NAME'], array('localhost', '127.0.0.1'))) - { - /* Check if Maxmind Database exists */ - if (@filemtime(_PS_GEOIP_DIR_._PS_GEOIP_CITY_FILE_)) - { - if (!isset($this->context->cookie->iso_code_country) || (isset($this->context->cookie->iso_code_country) && !in_array(strtoupper($this->context->cookie->iso_code_country), explode(';', Configuration::get('PS_ALLOWED_COUNTRIES'))))) - { - include_once(_PS_GEOIP_DIR_.'geoipcity.inc'); - - $gi = geoip_open(realpath(_PS_GEOIP_DIR_._PS_GEOIP_CITY_FILE_), GEOIP_STANDARD); - $record = geoip_record_by_addr($gi, Tools::getRemoteAddr()); - - if (is_object($record)) - { - if (!in_array(strtoupper($record->country_code), explode(';', Configuration::get('PS_ALLOWED_COUNTRIES'))) && !FrontController::isInWhitelistForGeolocation()) - { - if (Configuration::get('PS_GEOLOCATION_BEHAVIOR') == _PS_GEOLOCATION_NO_CATALOG_) - $this->restrictedCountry = true; - elseif (Configuration::get('PS_GEOLOCATION_BEHAVIOR') == _PS_GEOLOCATION_NO_ORDER_) - $this->context->smarty->assign(array( - 'restricted_country_mode' => true, - 'geolocation_country' => $record->country_name - )); - } - else - { - $has_been_set = !isset($this->context->cookie->iso_code_country); - $this->context->cookie->iso_code_country = strtoupper($record->country_code); - } - } - } - - if (isset($this->context->cookie->iso_code_country) && $this->context->cookie->iso_code_country && !Validate::isLanguageIsoCode($this->context->cookie->iso_code_country)) - $this->context->cookie->iso_code_country = Country::getIsoById(Configuration::get('PS_COUNTRY_DEFAULT')); - - if (isset($this->context->cookie->iso_code_country) && ($id_country = Country::getByIso(strtoupper($this->context->cookie->iso_code_country)))) - { - /* Update defaultCountry */ - if ($default_country->iso_code != $this->context->cookie->iso_code_country) - $default_country = new Country($id_country); - if (isset($has_been_set) && $has_been_set) - $this->context->cookie->id_currency = (int)($default_country->id_currency ? (int)$default_country->id_currency : (int)Configuration::get('PS_CURRENCY_DEFAULT')); - return $default_country; - } - elseif (Configuration::get('PS_GEOLOCATION_NA_BEHAVIOR') == _PS_GEOLOCATION_NO_CATALOG_ && !FrontController::isInWhitelistForGeolocation()) - $this->restrictedCountry = true; - elseif (Configuration::get('PS_GEOLOCATION_NA_BEHAVIOR') == _PS_GEOLOCATION_NO_ORDER_ && !FrontController::isInWhitelistForGeolocation()) - $this->context->smarty->assign(array( - 'restricted_country_mode' => true, - 'geolocation_country' => isset($record->country_name) && $record->country_name ? $record->country_name : 'Undefined' - )); - } - } - return false; - } - - /** - * Specific medias for mobile device. - * If autoload directory is present in the mobile theme, these files will not be loaded - */ - public function setMobileMedia() - { - $this->addJquery(); - - if (!file_exists($this->getThemeDir().'js/autoload/')) - { - $this->addJS(_THEME_MOBILE_JS_DIR_.'jquery.mobile-1.3.0.min.js'); - $this->addJS(_THEME_MOBILE_JS_DIR_.'jqm-docs.js'); - $this->addJS(_PS_JS_DIR_.'tools.js'); - $this->addJS(_THEME_MOBILE_JS_DIR_.'global.js'); - $this->addJqueryPlugin('fancybox'); - } - - if (!file_exists($this->getThemeDir().'css/autoload/')) - { - $this->addCSS(_THEME_MOBILE_CSS_DIR_.'jquery.mobile-1.3.0.min.css', 'all'); - $this->addCSS(_THEME_MOBILE_CSS_DIR_.'jqm-docs.css', 'all'); - $this->addCSS(_THEME_MOBILE_CSS_DIR_.'global.css', 'all'); - } - } - - /** - * Sets controller CSS and JS files. - * - * @return bool - */ - public function setMedia() - { - /** - * If website is accessed by mobile device - * @see FrontControllerCore::setMobileMedia() - */ - if ($this->useMobileTheme()) - { - $this->setMobileMedia(); - return true; - } - - $this->addCSS(_THEME_CSS_DIR_.'grid_prestashop.css', 'all'); // retro compat themes 1.5.0.1 - $this->addCSS(_THEME_CSS_DIR_.'global.css', 'all'); - $this->addJquery(); - $this->addJqueryPlugin('easing'); - $this->addJS(_PS_JS_DIR_.'tools.js'); - $this->addJS(_THEME_JS_DIR_.'global.js'); - - // Automatically add js files from js/autoload directory in the template - if (@filemtime($this->getThemeDir().'js/autoload/')) - foreach (scandir($this->getThemeDir().'js/autoload/', 0) as $file) - if (preg_match('/^[^.].*\.js$/', $file)) - $this->addJS($this->getThemeDir().'js/autoload/'.$file); - // Automatically add css files from css/autoload directory in the template - if (@filemtime($this->getThemeDir().'css/autoload/')) - foreach (scandir($this->getThemeDir().'css/autoload', 0) as $file) - if (preg_match('/^[^.].*\.css$/', $file)) - $this->addCSS($this->getThemeDir().'css/autoload/'.$file); - - if (Tools::isSubmit('live_edit') && Tools::getValue('ad') && Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee'))) - { - $this->addJqueryUI('ui.sortable'); - $this->addjqueryPlugin('fancybox'); - $this->addJS(_PS_JS_DIR_.'hookLiveEdit.js'); - } - - if (Configuration::get('PS_QUICK_VIEW')) - $this->addjqueryPlugin('fancybox'); - - if (Configuration::get('PS_COMPARATOR_MAX_ITEM') > 0) - $this->addJS(_THEME_JS_DIR_.'products-comparison.js'); - - // Execute Hook FrontController SetMedia - Hook::exec('actionFrontControllerSetMedia', array()); - - return true; - } - - /** - * Initializes page header variables - */ - public function initHeader() - { - /** @see P3P Policies (http://www.w3.org/TR/2002/REC-P3P-20020416/#compact_policies) */ - header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"'); - header('Powered-By: PrestaShop'); - - // Hooks are voluntary out the initialize array (need those variables already assigned) - $this->context->smarty->assign(array( - 'time' => time(), - 'img_update_time' => Configuration::get('PS_IMG_UPDATE_TIME'), - 'static_token' => Tools::getToken(false), - 'token' => Tools::getToken(), - 'priceDisplayPrecision' => _PS_PRICE_DISPLAY_PRECISION_, - 'content_only' => (int)Tools::getValue('content_only'), - )); - - $this->context->smarty->assign($this->initLogoAndFavicon()); - } - - /** - * Initializes page footer variables - */ - public function initFooter() - { - $this->context->smarty->assign(array( - 'HOOK_FOOTER' => Hook::exec('displayFooter'), - 'conditions' => Configuration::get('PS_CONDITIONS'), - 'id_cgv' => Configuration::get('PS_CONDITIONS_CMS_ID'), - 'PS_SHOP_NAME' => Configuration::get('PS_SHOP_NAME'), - 'PS_ALLOW_MOBILE_DEVICE' => isset($_SERVER['HTTP_USER_AGENT']) && (bool)Configuration::get('PS_ALLOW_MOBILE_DEVICE') && @filemtime(_PS_THEME_MOBILE_DIR_) - )); - - /** - * RTL support - * rtl.css overrides theme css files for RTL - * iso_code.css overrides default font for every language (optional) - */ - if ($this->context->language->is_rtl) - { - $this->addCSS(_THEME_CSS_DIR_.'rtl.css'); - $this->addCSS(_THEME_CSS_DIR_.$this->context->language->iso_code.'.css'); - } - - } - - /** - * Checks if the user can use Live Edit feature - * - * @return bool - */ - public function checkLiveEditAccess() - { - if (!Tools::isSubmit('live_edit') || !Tools::getValue('ad') || !Tools::getValue('liveToken')) - return false; - - if (Tools::getValue('liveToken') != Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee'))) - return false; - - return is_dir(_PS_CORE_DIR_.DIRECTORY_SEPARATOR.Tools::getValue('ad')); - } - - /** - * Renders Live Edit widget - * - * @return string HTML - */ - public function getLiveEditFooter() - { - if ($this->checkLiveEditAccess()) - { - $data = $this->context->smarty->createData(); - $data->assign(array( - 'ad' => Tools::getValue('ad'), - 'live_edit' => true, - 'hook_list' => Hook::$executed_hooks, - 'id_shop' => $this->context->shop->id - )); - return $this->context->smarty->createTemplate(_PS_ALL_THEMES_DIR_.'live_edit.tpl', $data)->fetch(); - } - else - return ''; - } - - /** - * Assigns product list page sorting variables - */ - public function productSort() - { - // $this->orderBy = Tools::getProductsOrder('by', Tools::getValue('orderby')); - // $this->orderWay = Tools::getProductsOrder('way', Tools::getValue('orderway')); - // 'orderbydefault' => Tools::getProductsOrder('by'), - // 'orderwayposition' => Tools::getProductsOrder('way'), // Deprecated: orderwayposition - // 'orderwaydefault' => Tools::getProductsOrder('way'), - - $stock_management = Configuration::get('PS_STOCK_MANAGEMENT') ? true : false; // no display quantity order if stock management disabled - $order_by_values = array(0 => 'name', 1 => 'price', 2 => 'date_add', 3 => 'date_upd', 4 => 'position', 5 => 'manufacturer_name', 6 => 'quantity', 7 => 'reference'); - $order_way_values = array(0 => 'asc', 1 => 'desc'); - - $this->orderBy = Tools::strtolower(Tools::getValue('orderby', $order_by_values[(int)Configuration::get('PS_PRODUCTS_ORDER_BY')])); - $this->orderWay = Tools::strtolower(Tools::getValue('orderway', $order_way_values[(int)Configuration::get('PS_PRODUCTS_ORDER_WAY')])); - - if (!in_array($this->orderBy, $order_by_values)) - $this->orderBy = $order_by_values[0]; - - if (!in_array($this->orderWay, $order_way_values)) - $this->orderWay = $order_way_values[0]; - - $this->context->smarty->assign(array( - 'orderby' => $this->orderBy, - 'orderway' => $this->orderWay, - 'orderbydefault' => $order_by_values[(int)Configuration::get('PS_PRODUCTS_ORDER_BY')], - 'orderwayposition' => $order_way_values[(int)Configuration::get('PS_PRODUCTS_ORDER_WAY')], // Deprecated: orderwayposition - 'orderwaydefault' => $order_way_values[(int)Configuration::get('PS_PRODUCTS_ORDER_WAY')], - 'stock_management' => (int)$stock_management - )); - } - - /** - * Assigns product list page pagination variables - * - * @param int|null $total_products - * @throws PrestaShopException - */ - public function pagination($total_products = null) - { - if (!self::$initialized) - $this->init(); - elseif (!$this->context) - $this->context = Context::getContext(); - - // Retrieve the default number of products per page and the other available selections - $default_products_per_page = max(1, (int)Configuration::get('PS_PRODUCTS_PER_PAGE')); - $n_array = array($default_products_per_page, $default_products_per_page * 2, $default_products_per_page * 5); - - if ((int)Tools::getValue('n') && (int)$total_products > 0) - $n_array[] = $total_products; - // Retrieve the current number of products per page (either the default, the GET parameter or the one in the cookie) - $this->n = $default_products_per_page; - if (isset($this->context->cookie->nb_item_per_page) && in_array($this->context->cookie->nb_item_per_page, $n_array)) - $this->n = (int)$this->context->cookie->nb_item_per_page; - - if ((int)Tools::getValue('n') && in_array((int)Tools::getValue('n'), $n_array)) - $this->n = (int)Tools::getValue('n'); - - // Retrieve the page number (either the GET parameter or the first page) - $this->p = (int)Tools::getValue('p', 1); - // If the parameter is not correct then redirect (do not merge with the previous line, the redirect is required in order to avoid duplicate content) - if (!is_numeric($this->p) || $this->p < 1) - Tools::redirect($this->context->link->getPaginationLink(false, false, $this->n, false, 1, false)); - - // Remove the page parameter in order to get a clean URL for the pagination template - $current_url = preg_replace('/(\?)?(&)?p=\d+/', '$1', Tools::htmlentitiesUTF8($_SERVER['REQUEST_URI'])); - - if ($this->n != $default_products_per_page || isset($this->context->cookie->nb_item_per_page)) - $this->context->cookie->nb_item_per_page = $this->n; - - $pages_nb = ceil($total_products / (int)$this->n); - if ($this->p > $pages_nb && $total_products != 0) - Tools::redirect($this->context->link->getPaginationLink(false, false, $this->n, false, $pages_nb, false)); - - $range = 2; /* how many pages around page selected */ - $start = (int)($this->p - $range); - if ($start < 1) - $start = 1; - - $stop = (int)($this->p + $range); - if ($stop > $pages_nb) - $stop = (int)$pages_nb; - - $this->context->smarty->assign(array( - 'nb_products' => $total_products, - 'products_per_page' => $this->n, - 'pages_nb' => $pages_nb, - 'p' => $this->p, - 'n' => $this->n, - 'nArray' => $n_array, - 'range' => $range, - 'start' => $start, - 'stop' => $stop, - 'current_url' => $current_url, - )); - } - - /** - * Sets and returns customer groups that the current customer(visitor) belongs to. - * - * @return array - * @throws PrestaShopDatabaseException - */ - public static function getCurrentCustomerGroups() - { - if (!Group::isFeatureActive()) - return array(); - - $context = Context::getContext(); - if (!isset($context->customer) || !$context->customer->id) - return array(); - - if (!is_array(self::$currentCustomerGroups)) - { - self::$currentCustomerGroups = array(); - $result = Db::getInstance()->executeS('SELECT id_group FROM '._DB_PREFIX_.'customer_group WHERE id_customer = '.(int)$context->customer->id); - foreach ($result as $row) - self::$currentCustomerGroups[] = $row['id_group']; - } - - return self::$currentCustomerGroups; - } - - /** - * Checks if user's location is whitelisted. - * - * @staticvar bool|null $allowed - * @return bool - */ - protected static function isInWhitelistForGeolocation() - { - static $allowed = null; - - if ($allowed !== null) - return $allowed; - - $allowed = false; - $user_ip = Tools::getRemoteAddr(); - $ips = array(); - - // retrocompatibility - $ips_old = explode(';', Configuration::get('PS_GEOLOCATION_WHITELIST')); - if (is_array($ips_old) && count($ips_old)) - foreach ($ips_old as $ip) - $ips = array_merge($ips, explode("\n", $ip)); - - $ips = array_map('trim', $ips); - if (is_array($ips) && count($ips)) - foreach ($ips as $ip) - if (!empty($ip) && preg_match('/^'.$ip.'.*/', $user_ip)) - $allowed = true; - - return $allowed; - } - - /** - * Checks if token is valid - * - * @since 1.5.0.1 - * @return bool - */ - public function isTokenValid() - { - if (!Configuration::get('PS_TOKEN_ENABLE')) - return true; - - return (strcasecmp(Tools::getToken(false), Tools::getValue('token')) == 0); - } - - /** - * Adds a media file(s) (CSS, JS) to page header - * - * @param string|array $media_uri Path to file, or an array of paths like: array(array(uri => media_type), ...) - * @param string|null $css_media_type CSS media type - * @param int|null $offset - * @param bool $remove If True, removes media files - * @param bool $check_path If true, checks if files exists - * @return true|void - */ - public function addMedia($media_uri, $css_media_type = null, $offset = null, $remove = false, $check_path = true) - { - if (!is_array($media_uri)) - { - if ($css_media_type) - $media_uri = array($media_uri => $css_media_type); - else - $media_uri = array($media_uri); - } - - $list_uri = array(); - foreach ($media_uri as $file => $media) - { - if (!Validate::isAbsoluteUrl($media)) - { - $different = 0; - $different_css = 0; - $type = 'css'; - if (!$css_media_type) - { - $type = 'js'; - $file = $media; - } - if (strpos($file, __PS_BASE_URI__.'modules/') === 0) - { - $override_path = str_replace(__PS_BASE_URI__.'modules/', _PS_ROOT_DIR_.'/themes/'._THEME_NAME_.'/'.$type.'/modules/', $file, $different); - if (strrpos($override_path, $type.'/'.basename($file)) !== false) - $override_path_css = str_replace($type.'/'.basename($file), basename($file), $override_path, $different_css); - - if ($different && @filemtime($override_path)) - $file = str_replace(__PS_BASE_URI__.'modules/', __PS_BASE_URI__.'themes/'._THEME_NAME_.'/'.$type.'/modules/', $file, $different); - elseif ($different_css && @filemtime($override_path_css)) - $file = $override_path_css; - if ($css_media_type) - $list_uri[$file] = $media; - else - $list_uri[] = $file; - } - else - $list_uri[$file] = $media; - } - else - $list_uri[$file] = $media; - } - - if ($remove) - { - if ($css_media_type) - return parent::removeCSS($list_uri, $css_media_type); - return parent::removeJS($list_uri); - } - - if ($css_media_type) - return parent::addCSS($list_uri, $css_media_type, $offset, $check_path); - - return parent::addJS($list_uri, $check_path); - } - - /** - * Removes media file(s) from page header - * - * @param string|array $media_uri Path to file, or an array paths of like: array(array(uri => media_type), ...) - * @param string|null $css_media_type CSS media type - * @param bool $check_path If true, checks if files exists - */ - public function removeMedia($media_uri, $css_media_type = null, $check_path = true) - { - FrontController::addMedia($media_uri, $css_media_type, null, true, $check_path); - } - - /** - * Add one or several CSS for front, checking if css files are overridden in theme/css/modules/ directory - * @see Controller::addCSS() - * - * @param array|string $css_uri $media_uri Path to file, or an array of paths like: array(array(uri => media_type), ...) - * @param string $css_media_type CSS media type - * @param int|null $offset - * @param bool $check_path If true, checks if files exists - * @return true|void - */ - public function addCSS($css_uri, $css_media_type = 'all', $offset = null, $check_path = true) - { - return FrontController::addMedia($css_uri, $css_media_type, $offset = null, false, $check_path); - } - - /** - * Removes CSS file(s) from page header - * - * @param array|string $css_uri $media_uri Path to file, or an array of paths like: array(array(uri => media_type), ...) - * @param string $css_media_type CSS media type - * @param bool $check_path If true, checks if files exists - */ - public function removeCSS($css_uri, $css_media_type = 'all', $check_path = true) - { - return FrontController::removeMedia($css_uri, $css_media_type, $check_path); - } - - /** - * Add one or several JS files for front, checking if js files are overridden in theme/js/modules/ directory - * @see Controller::addJS() - * - * @param array|string $js_uri Path to file, or an array of paths - * @param bool $check_path If true, checks if files exists - * @return true|void - */ - public function addJS($js_uri, $check_path = true) - { - return Frontcontroller::addMedia($js_uri, null, null, false, $check_path); - } - - /** - * Removes JS file(s) from page header - * - * @param array|string $js_uri Path to file, or an array of paths - * @param bool $check_path If true, checks if files exists - */ - public function removeJS($js_uri, $check_path = true) - { - return FrontController::removeMedia($js_uri, null, $check_path); - } - - /** - * Recovers cart information - * - * @return int|false - */ - protected function recoverCart() - { - if (($id_cart = (int)Tools::getValue('recover_cart')) && Tools::getValue('token_cart') == md5(_COOKIE_KEY_.'recover_cart_'.$id_cart)) - { - $cart = new Cart((int)$id_cart); - if (Validate::isLoadedObject($cart)) - { - $customer = new Customer((int)$cart->id_customer); - if (Validate::isLoadedObject($customer)) - { - $customer->logged = 1; - $this->context->customer = $customer; - $this->context->cookie->id_customer = (int)$customer->id; - $this->context->cookie->customer_lastname = $customer->lastname; - $this->context->cookie->customer_firstname = $customer->firstname; - $this->context->cookie->logged = 1; - $this->context->cookie->check_cgv = 1; - $this->context->cookie->is_guest = $customer->isGuest(); - $this->context->cookie->passwd = $customer->passwd; - $this->context->cookie->email = $customer->email; - return $id_cart; - } - } - } - else - return false; - } - - /** - * Sets template file for page content output - * - * @param string $default_template - */ - public function setTemplate($default_template) - { - if ($this->useMobileTheme()) - $this->setMobileTemplate($default_template); - else - { - $template = $this->getOverrideTemplate(); - if ($template) - parent::setTemplate($template); - else - parent::setTemplate($default_template); - } - } - - /** - * Returns an overridden template path (if any) for this controller. - * If not overridden, will return false. This method can be easily overriden in a - * specific controller. - * - * @since 1.5.0.13 - * @return string|bool - */ - public function getOverrideTemplate() - { - return Hook::exec('DisplayOverrideTemplate', array('controller' => $this)); - } - - /** - * Checks if mobile theme is active and in use. - * - * @staticvar bool|null $use_mobile_template - * @return bool - */ - protected function useMobileTheme() - { - static $use_mobile_template = null; - - // The mobile theme must have a layout to be used - if ($use_mobile_template === null) - $use_mobile_template = ($this->context->getMobileDevice() && file_exists(_PS_THEME_MOBILE_DIR_.'layout.tpl')); - - return $use_mobile_template; - } - - /** - * Returns theme directory (regular or mobile) - * - * @return string - */ - protected function getThemeDir() - { - return $this->useMobileTheme() ? _PS_THEME_MOBILE_DIR_ : _PS_THEME_DIR_; - } - - - /** - * Returns theme override directory (regular or mobile) - * - * @return string - */ - protected function getOverrideThemeDir() - { - return $this->useMobileTheme() ? _PS_THEME_MOBILE_OVERRIDE_DIR_ : _PS_THEME_OVERRIDE_DIR_; - } - - /** - * Returns the layout corresponding to the current page by using the override system - * Ex: - * On the url: http://localhost/index.php?id_product=1&controller=product, this method will - * check if the layout exists in the following files (in that order), and return the first found: - * - /themes/default/override/layout-product-1.tpl - * - /themes/default/override/layout-product.tpl - * - /themes/default/layout.tpl - * - * @since 1.5.0.13 - * @return bool|string - */ - public function getLayout() - { - $entity = $this->php_self; - $id_item = (int)Tools::getValue('id_'.$entity); - - $layout_dir = $this->getThemeDir(); - $layout_override_dir = $this->getOverrideThemeDir(); - - $layout = false; - if ($entity) - { - if ($id_item > 0 && file_exists($layout_override_dir.'layout-'.$entity.'-'.$id_item.'.tpl')) - $layout = $layout_override_dir.'layout-'.$entity.'-'.$id_item.'.tpl'; - elseif (file_exists($layout_override_dir.'layout-'.$entity.'.tpl')) - $layout = $layout_override_dir.'layout-'.$entity.'.tpl'; - } - - if (!$layout && file_exists($layout_dir.'layout.tpl')) - $layout = $layout_dir.'layout.tpl'; - - return $layout; - } - - /** - * Returns template path - * - * @param string $template - * @return string - */ - public function getTemplatePath($template) - { - if (!$this->useMobileTheme()) - return $template; - - $tpl_file = basename($template); - $dirname = dirname($template).(substr(dirname($template), -1, 1) == '/' ? '' : '/'); - - if ($dirname == _PS_THEME_DIR_) - { - if (file_exists(_PS_THEME_MOBILE_DIR_.$tpl_file)) - $template = _PS_THEME_MOBILE_DIR_.$tpl_file; - } - elseif ($dirname == _PS_THEME_MOBILE_DIR_) - { - if (!file_exists(_PS_THEME_MOBILE_DIR_.$tpl_file) && file_exists(_PS_THEME_DIR_.$tpl_file)) - $template = _PS_THEME_DIR_.$tpl_file; - } - - return $template; - } - - /** - * Checks if the template set is available for mobile themes, - * otherwise front template is chosen. - * - * @param string $template - */ - public function setMobileTemplate($template) - { - // Needed for site map - $blockmanufacturer = Module::getInstanceByName('blockmanufacturer'); - $blocksupplier = Module::getInstanceByName('blocksupplier'); - - $this->context->smarty->assign(array( - 'categoriesTree' => Category::getRootCategory()->recurseLiteCategTree(0), - 'categoriescmsTree' => CMSCategory::getRecurseCategory($this->context->language->id, 1, 1, 1), - 'voucherAllowed' => (int)CartRule::isFeatureActive(), - 'display_manufacturer_link' => (bool)$blockmanufacturer->active, - 'display_supplier_link' => (bool)$blocksupplier->active, - 'PS_DISPLAY_SUPPLIERS' => Configuration::get('PS_DISPLAY_SUPPLIERS'), - 'PS_DISPLAY_BEST_SELLERS' => Configuration::get('PS_DISPLAY_BEST_SELLERS'), - 'display_store' => Configuration::get('PS_STORES_DISPLAY_SITEMAP'), - 'conditions' => Configuration::get('PS_CONDITIONS'), - 'id_cgv' => Configuration::get('PS_CONDITIONS_CMS_ID'), - 'PS_SHOP_NAME' => Configuration::get('PS_SHOP_NAME'), - )); - - $template = $this->getTemplatePath($template); - - $assign = array(); - $assign['tpl_file'] = basename($template, '.tpl'); - if (isset($this->php_self)) - $assign['controller_name'] = $this->php_self; - - $this->context->smarty->assign($assign); - $this->template = $template; - } - - /** - * Returns logo and favicon variables, depending - * on active theme type (regular or mobile) - * - * @since 1.5.3.0 - * @return array - */ - public function initLogoAndFavicon() - { - $mobile_device = $this->context->getMobileDevice(); - - if ($mobile_device && Configuration::get('PS_LOGO_MOBILE')) - $logo = $this->context->link->getMediaLink(_PS_IMG_.Configuration::get('PS_LOGO_MOBILE').'?'.Configuration::get('PS_IMG_UPDATE_TIME')); - else - $logo = $this->context->link->getMediaLink(_PS_IMG_.Configuration::get('PS_LOGO')); - - return array( - 'favicon_url' => _PS_IMG_.Configuration::get('PS_FAVICON'), - 'logo_image_width' => ($mobile_device == false ? Configuration::get('SHOP_LOGO_WIDTH') : Configuration::get('SHOP_LOGO_MOBILE_WIDTH')), - 'logo_image_height' => ($mobile_device == false ? Configuration::get('SHOP_LOGO_HEIGHT') : Configuration::get('SHOP_LOGO_MOBILE_HEIGHT')), - 'logo_url' => $logo - ); - } - - /** - * Renders and adds color list HTML for each product in a list - * - * @param array $products - */ - public function addColorsToProductList(&$products) - { - if (!is_array($products) || !count($products) || !file_exists(_PS_THEME_DIR_.'product-list-colors.tpl')) - return; - - $products_need_cache = array(); - foreach ($products as &$product) - if (!$this->isCached(_PS_THEME_DIR_.'product-list-colors.tpl', $this->getColorsListCacheId($product['id_product']))) - $products_need_cache[] = (int)$product['id_product']; - - unset($product); - - $colors = false; - if (count($products_need_cache)) - $colors = Product::getAttributesColorList($products_need_cache); - - Tools::enableCache(); - foreach ($products as &$product) - { - $tpl = $this->context->smarty->createTemplate(_PS_THEME_DIR_.'product-list-colors.tpl', $this->getColorsListCacheId($product['id_product'])); - if (isset($colors[$product['id_product']])) - $tpl->assign(array( - 'id_product' => $product['id_product'], - 'colors_list' => $colors[$product['id_product']], - 'link' => Context::getContext()->link, - 'img_col_dir' => _THEME_COL_DIR_, - 'col_img_dir' => _PS_COL_IMG_DIR_ - )); - - if (!in_array($product['id_product'], $products_need_cache) || isset($colors[$product['id_product']])) - $product['color_list'] = $tpl->fetch(_PS_THEME_DIR_.'product-list-colors.tpl', $this->getColorsListCacheId($product['id_product'])); - else - $product['color_list'] = ''; - } - Tools::restoreCacheSettings(); - } - - /** - * Returns cache ID for product color list - * - * @param int $id_product - * @return string - */ - protected function getColorsListCacheId($id_product) - { - return Product::getColorsListCacheId($id_product); - } + /** + * @deprecated Deprecated shortcuts as of 1.5.0.1 - Use $context->smarty instead + * @var $smarty Smarty + */ + protected static $smarty; + + /** + * @deprecated Deprecated shortcuts as of 1.5.0.1 - Use $context->cookie instead + * @var $cookie Cookie + */ + protected static $cookie; + + /** + * @deprecated Deprecated shortcuts as of 1.5.0.1 - Use $context->link instead + * @var $link Link + */ + protected static $link; + + /** + * @deprecated Deprecated shortcuts as of 1.5.0.1 - Use $context->cart instead + * @var $cart Cart + */ + protected static $cart; + + /** @var array Controller errors */ + public $errors = array(); + + /** @var string Language ISO code */ + public $iso; + + /** @var string ORDER BY field */ + public $orderBy; + + /** @var string Order way string ('ASC', 'DESC') */ + public $orderWay; + + /** @var int Current page number */ + public $p; + + /** @var int Items (products) per page */ + public $n; + + /** @var bool If set to true, will redirected user to login page during init function. */ + public $auth = false; + + /** + * If set to true, user can be logged in as guest when checking if logged in. + * + * @see $auth + * @var bool + */ + public $guestAllowed = false; + + /** + * Route of PrestaShop page to redirect to after forced login. + * + * @see $auth + * @var bool + */ + public $authRedirection = false; + + /** @var bool SSL connection flag */ + public $ssl = false; + + /** @var bool If true, switches display to restricted country page during init. */ + protected $restrictedCountry = false; + + /** @var bool If true, forces display to maintenance page. */ + protected $maintenance = false; + + /** @var bool If false, does not build left page column content and hides it. */ + public $display_column_left = true; + + /** @var bool If false, does not build right page column content and hides it. */ + public $display_column_right = true; + + /** + * True if controller has already been initialized. + * Prevents initializing controller more than once. + * + * @var bool + */ + public static $initialized = false; + + /** + * @var array Holds current customer's groups. + */ + protected static $currentCustomerGroups; + + /** + * @var int + */ + public $nb_items_per_page; + + /** + * Controller constructor + * + * @global bool $useSSL SSL connection flag + */ + public function __construct() + { + $this->controller_type = 'front'; + + global $useSSL; + + parent::__construct(); + + if (Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE')) { + $this->ssl = true; + } + + if (isset($useSSL)) { + $this->ssl = $useSSL; + } else { + $useSSL = $this->ssl; + } + + if (isset($this->php_self) && is_object(Context::getContext()->theme)) { + $columns = Context::getContext()->theme->hasColumns($this->php_self); + + // Don't use theme tables if not configured in DB + if ($columns) { + $this->display_column_left = $columns['left_column']; + $this->display_column_right = $columns['right_column']; + } + } + } + + /** + * Check if the controller is available for the current user/visitor + * + * @see Controller::checkAccess() + * @return bool + */ + public function checkAccess() + { + return true; + } + + /** + * Check if the current user/visitor has valid view permissions + * + * @see Controller::viewAccess + * @return bool + */ + public function viewAccess() + { + return true; + } + + /** + * Initializes front controller: sets smarty variables, + * class properties, redirects depending on context, etc. + * + * @global bool $useSSL SSL connection flag + * @global Cookie $cookie Visitor's cookie + * @global Smarty $smarty + * @global Cart $cart Visitor's cart + * @global string $iso Language ISO + * @global Country $defaultCountry Visitor's country object + * @global string $protocol_link + * @global string $protocol_content + * @global Link $link + * @global array $css_files + * @global array $js_files + * @global Currency $currency Visitor's selected currency + * + * @throws PrestaShopException + */ + public function init() + { + /** + * Globals are DEPRECATED as of version 1.5.0.1 + * Use the Context object to access objects instead. + * Example: $this->context->cart + */ + global $useSSL, $cookie, $smarty, $cart, $iso, $defaultCountry, $protocol_link, $protocol_content, $link, $css_files, $js_files, $currency; + + if (self::$initialized) { + return; + } + + self::$initialized = true; + + parent::init(); + + // If current URL use SSL, set it true (used a lot for module redirect) + if (Tools::usingSecureMode()) { + $useSSL = true; + } + + // For compatibility with globals, DEPRECATED as of version 1.5.0.1 + $css_files = $this->css_files; + $js_files = $this->js_files; + + $this->sslRedirection(); + + if ($this->ajax) { + $this->display_header = false; + $this->display_footer = false; + } + + // If account created with the 2 steps register process, remove 'account_created' from cookie + if (isset($this->context->cookie->account_created)) { + $this->context->smarty->assign('account_created', 1); + unset($this->context->cookie->account_created); + } + + ob_start(); + + // Init cookie language + // @TODO This method must be moved into switchLanguage + Tools::setCookieLanguage($this->context->cookie); + + $protocol_link = (Configuration::get('PS_SSL_ENABLED') || Tools::usingSecureMode()) ? 'https://' : 'http://'; + $useSSL = ((isset($this->ssl) && $this->ssl && Configuration::get('PS_SSL_ENABLED')) || Tools::usingSecureMode()) ? true : false; + $protocol_content = ($useSSL) ? 'https://' : 'http://'; + $link = new Link($protocol_link, $protocol_content); + $this->context->link = $link; + + if ($id_cart = (int)$this->recoverCart()) { + $this->context->cookie->id_cart = (int)$id_cart; + } + + if ($this->auth && !$this->context->customer->isLogged($this->guestAllowed)) { + Tools::redirect('index.php?controller=authentication'.($this->authRedirection ? '&back='.$this->authRedirection : '')); + } + + /* Theme is missing */ + if (!is_dir(_PS_THEME_DIR_)) { + throw new PrestaShopException((sprintf(Tools::displayError('Current theme unavailable "%s". Please check your theme directory name and permissions.'), basename(rtrim(_PS_THEME_DIR_, '/\\'))))); + } + + if (Configuration::get('PS_GEOLOCATION_ENABLED')) { + if (($new_default = $this->geolocationManagement($this->context->country)) && Validate::isLoadedObject($new_default)) { + $this->context->country = $new_default; + } + } elseif (Configuration::get('PS_DETECT_COUNTRY')) { + $has_currency = isset($this->context->cookie->id_currency) && (int)$this->context->cookie->id_currency; + $has_country = isset($this->context->cookie->iso_code_country) && $this->context->cookie->iso_code_country; + $has_address_type = false; + + if ((int)$this->context->cookie->id_cart && ($cart = new Cart($this->context->cookie->id_cart)) && Validate::isLoadedObject($cart)) { + $has_address_type = isset($cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) && $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}; + } + + if ((!$has_currency || $has_country) && !$has_address_type) { + $id_country = $has_country && !Validate::isLanguageIsoCode($this->context->cookie->iso_code_country) ? + (int)Country::getByIso(strtoupper($this->context->cookie->iso_code_country)) : (int)Tools::getCountry(); + + $country = new Country($id_country, (int)$this->context->cookie->id_lang); + + if (validate::isLoadedObject($country) && $this->context->country->id !== $country->id) { + $this->context->country = $country; + $this->context->cookie->id_currency = (int)Currency::getCurrencyInstance($country->id_currency ? (int)$country->id_currency : (int)Configuration::get('PS_CURRENCY_DEFAULT'))->id; + $this->context->cookie->iso_code_country = strtoupper($country->iso_code); + } + } + } + + $currency = Tools::setCurrency($this->context->cookie); + + if (isset($_GET['logout']) || ($this->context->customer->logged && Customer::isBanned($this->context->customer->id))) { + $this->context->customer->logout(); + + Tools::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null); + } elseif (isset($_GET['mylogout'])) { + $this->context->customer->mylogout(); + Tools::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null); + } + + /* Cart already exists */ + if ((int)$this->context->cookie->id_cart) { + if (!isset($cart)) { + $cart = new Cart($this->context->cookie->id_cart); + } + + if (Validate::isLoadedObject($cart) && $cart->OrderExists()) { + PrestaShopLogger::addLog('Frontcontroller::init - Cart cannot be loaded or an order has already been placed using this cart', 1, null, 'Cart', (int)$this->context->cookie->id_cart, true); + unset($this->context->cookie->id_cart, $cart, $this->context->cookie->checkedTOS); + $this->context->cookie->check_cgv = false; + } + /* Delete product of cart, if user can't make an order from his country */ + elseif (intval(Configuration::get('PS_GEOLOCATION_ENABLED')) && + !in_array(strtoupper($this->context->cookie->iso_code_country), explode(';', Configuration::get('PS_ALLOWED_COUNTRIES'))) && + $cart->nbProducts() && intval(Configuration::get('PS_GEOLOCATION_NA_BEHAVIOR')) != -1 && + !FrontController::isInWhitelistForGeolocation() && + !in_array($_SERVER['SERVER_NAME'], array('localhost', '127.0.0.1'))) { + PrestaShopLogger::addLog('Frontcontroller::init - GEOLOCATION is deleting a cart', 1, null, 'Cart', (int)$this->context->cookie->id_cart, true); + unset($this->context->cookie->id_cart, $cart); + } + // update cart values + elseif ($this->context->cookie->id_customer != $cart->id_customer || $this->context->cookie->id_lang != $cart->id_lang || $currency->id != $cart->id_currency) { + if ($this->context->cookie->id_customer) { + $cart->id_customer = (int)$this->context->cookie->id_customer; + } + $cart->id_lang = (int)$this->context->cookie->id_lang; + $cart->id_currency = (int)$currency->id; + $cart->update(); + } + /* Select an address if not set */ + if (isset($cart) && (!isset($cart->id_address_delivery) || $cart->id_address_delivery == 0 || + !isset($cart->id_address_invoice) || $cart->id_address_invoice == 0) && $this->context->cookie->id_customer) { + $to_update = false; + if (!isset($cart->id_address_delivery) || $cart->id_address_delivery == 0) { + $to_update = true; + $cart->id_address_delivery = (int)Address::getFirstCustomerAddressId($cart->id_customer); + } + if (!isset($cart->id_address_invoice) || $cart->id_address_invoice == 0) { + $to_update = true; + $cart->id_address_invoice = (int)Address::getFirstCustomerAddressId($cart->id_customer); + } + if ($to_update) { + $cart->update(); + } + } + } + + if (!isset($cart) || !$cart->id) { + $cart = new Cart(); + $cart->id_lang = (int)$this->context->cookie->id_lang; + $cart->id_currency = (int)$this->context->cookie->id_currency; + $cart->id_guest = (int)$this->context->cookie->id_guest; + $cart->id_shop_group = (int)$this->context->shop->id_shop_group; + $cart->id_shop = $this->context->shop->id; + if ($this->context->cookie->id_customer) { + $cart->id_customer = (int)$this->context->cookie->id_customer; + $cart->id_address_delivery = (int)Address::getFirstCustomerAddressId($cart->id_customer); + $cart->id_address_invoice = (int)$cart->id_address_delivery; + } else { + $cart->id_address_delivery = 0; + $cart->id_address_invoice = 0; + } + + // Needed if the merchant want to give a free product to every visitors + $this->context->cart = $cart; + CartRule::autoAddToCart($this->context); + } else { + $this->context->cart = $cart; + } + + /* get page name to display it in body id */ + + // Are we in a payment module + $module_name = ''; + if (Validate::isModuleName(Tools::getValue('module'))) { + $module_name = Tools::getValue('module'); + } + + if (!empty($this->page_name)) { + $page_name = $this->page_name; + } elseif (!empty($this->php_self)) { + $page_name = $this->php_self; + } elseif (Tools::getValue('fc') == 'module' && $module_name != '' && (Module::getInstanceByName($module_name) instanceof PaymentModule)) { + $page_name = 'module-payment-submit'; + } + // @retrocompatibility Are we in a module ? + elseif (preg_match('#^'.preg_quote($this->context->shop->physical_uri, '#').'modules/([a-zA-Z0-9_-]+?)/(.*)$#', $_SERVER['REQUEST_URI'], $m)) { + $page_name = 'module-'.$m[1].'-'.str_replace(array('.php', '/'), array('', '-'), $m[2]); + } else { + $page_name = Dispatcher::getInstance()->getController(); + $page_name = (preg_match('/^[0-9]/', $page_name) ? 'page_'.$page_name : $page_name); + } + + $this->context->smarty->assign(Meta::getMetaTags($this->context->language->id, $page_name)); + $this->context->smarty->assign('request_uri', Tools::safeOutput(urldecode($_SERVER['REQUEST_URI']))); + + /* Breadcrumb */ + $navigation_pipe = (Configuration::get('PS_NAVIGATION_PIPE') ? Configuration::get('PS_NAVIGATION_PIPE') : '>'); + $this->context->smarty->assign('navigationPipe', $navigation_pipe); + + // Automatically redirect to the canonical URL if needed + if (!empty($this->php_self) && !Tools::getValue('ajax')) { + $this->canonicalRedirection($this->context->link->getPageLink($this->php_self, $this->ssl, $this->context->language->id)); + } + + Product::initPricesComputation(); + + $display_tax_label = $this->context->country->display_tax_label; + if (isset($cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) && $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) { + $infos = Address::getCountryAndState((int)$cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); + $country = new Country((int)$infos['id_country']); + $this->context->country = $country; + if (Validate::isLoadedObject($country)) { + $display_tax_label = $country->display_tax_label; + } + } + + $languages = Language::getLanguages(true, $this->context->shop->id); + $meta_language = array(); + foreach ($languages as $lang) { + $meta_language[] = $lang['iso_code']; + } + + $compared_products = array(); + if (Configuration::get('PS_COMPARATOR_MAX_ITEM') && isset($this->context->cookie->id_compare)) { + $compared_products = CompareProduct::getCompareProducts($this->context->cookie->id_compare); + } + + $this->context->smarty->assign(array( + // Useful for layout.tpl + 'mobile_device' => $this->context->getMobileDevice(), + 'link' => $link, + 'cart' => $cart, + 'currency' => $currency, + 'currencyRate' => (float)$currency->getConversationRate(), + 'cookie' => $this->context->cookie, + 'page_name' => $page_name, + 'hide_left_column' => !$this->display_column_left, + 'hide_right_column' => !$this->display_column_right, + 'base_dir' => _PS_BASE_URL_.__PS_BASE_URI__, + 'base_dir_ssl' => $protocol_link.Tools::getShopDomainSsl().__PS_BASE_URI__, + 'force_ssl' => Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE'), + 'content_dir' => $protocol_content.Tools::getHttpHost().__PS_BASE_URI__, + 'base_uri' => $protocol_content.Tools::getHttpHost().__PS_BASE_URI__.(!Configuration::get('PS_REWRITING_SETTINGS') ? 'index.php' : ''), + 'tpl_dir' => _PS_THEME_DIR_, + 'tpl_uri' => _THEME_DIR_, + 'modules_dir' => _MODULE_DIR_, + 'mail_dir' => _MAIL_DIR_, + 'lang_iso' => $this->context->language->iso_code, + 'lang_id' => (int)$this->context->language->id, + 'language_code' => $this->context->language->language_code ? $this->context->language->language_code : $this->context->language->iso_code, + 'come_from' => Tools::getHttpHost(true, true).Tools::htmlentitiesUTF8(str_replace(array('\'', '\\'), '', urldecode($_SERVER['REQUEST_URI']))), + 'cart_qties' => (int)$cart->nbProducts(), + 'currencies' => Currency::getCurrencies(), + 'languages' => $languages, + 'meta_language' => implode(',', $meta_language), + 'priceDisplay' => Product::getTaxCalculationMethod((int)$this->context->cookie->id_customer), + 'is_logged' => (bool)$this->context->customer->isLogged(), + 'is_guest' => (bool)$this->context->customer->isGuest(), + 'add_prod_display' => (int)Configuration::get('PS_ATTRIBUTE_CATEGORY_DISPLAY'), + 'shop_name' => Configuration::get('PS_SHOP_NAME'), + 'roundMode' => (int)Configuration::get('PS_PRICE_ROUND_MODE'), + 'use_taxes' => (int)Configuration::get('PS_TAX'), + 'show_taxes' => (int)(Configuration::get('PS_TAX_DISPLAY') == 1 && (int)Configuration::get('PS_TAX')), + 'display_tax_label' => (bool)$display_tax_label, + 'vat_management' => (int)Configuration::get('VATNUMBER_MANAGEMENT'), + 'opc' => (bool)Configuration::get('PS_ORDER_PROCESS_TYPE'), + 'PS_CATALOG_MODE' => (bool)Configuration::get('PS_CATALOG_MODE') || (Group::isFeatureActive() && !(bool)Group::getCurrent()->show_prices), + 'b2b_enable' => (bool)Configuration::get('PS_B2B_ENABLE'), + 'request' => $link->getPaginationLink(false, false, false, true), + 'PS_STOCK_MANAGEMENT' => Configuration::get('PS_STOCK_MANAGEMENT'), + 'quick_view' => (bool)Configuration::get('PS_QUICK_VIEW'), + 'shop_phone' => Configuration::get('PS_SHOP_PHONE'), + 'compared_products' => is_array($compared_products) ? $compared_products : array(), + 'comparator_max_item' => (int)Configuration::get('PS_COMPARATOR_MAX_ITEM'), + 'currencySign' => $currency->sign, // backward compat, see global.tpl + 'currencyFormat' => $currency->format, // backward compat + 'currencyBlank' => $currency->blank, // backward compat + )); + + // Add the tpl files directory for mobile + if ($this->useMobileTheme()) { + $this->context->smarty->assign(array( + 'tpl_mobile_uri' => _PS_THEME_MOBILE_DIR_, + )); + } + + // Deprecated + $this->context->smarty->assign(array( + 'id_currency_cookie' => (int)$currency->id, + 'logged' => $this->context->customer->isLogged(), + 'customerName' => ($this->context->customer->logged ? $this->context->cookie->customer_firstname.' '.$this->context->cookie->customer_lastname : false) + )); + + $assign_array = array( + 'img_ps_dir' => _PS_IMG_, + 'img_cat_dir' => _THEME_CAT_DIR_, + 'img_lang_dir' => _THEME_LANG_DIR_, + 'img_prod_dir' => _THEME_PROD_DIR_, + 'img_manu_dir' => _THEME_MANU_DIR_, + 'img_sup_dir' => _THEME_SUP_DIR_, + 'img_ship_dir' => _THEME_SHIP_DIR_, + 'img_store_dir' => _THEME_STORE_DIR_, + 'img_col_dir' => _THEME_COL_DIR_, + 'img_dir' => _THEME_IMG_DIR_, + 'css_dir' => _THEME_CSS_DIR_, + 'js_dir' => _THEME_JS_DIR_, + 'pic_dir' => _THEME_PROD_PIC_DIR_ + ); + + // Add the images directory for mobile + if ($this->useMobileTheme()) { + $assign_array['img_mobile_dir'] = _THEME_MOBILE_IMG_DIR_; + } + + // Add the CSS directory for mobile + if ($this->useMobileTheme()) { + $assign_array['css_mobile_dir'] = _THEME_MOBILE_CSS_DIR_; + } + + foreach ($assign_array as $assign_key => $assign_value) { + if (substr($assign_value, 0, 1) == '/' || $protocol_content == 'https://') { + $this->context->smarty->assign($assign_key, $protocol_content.Tools::getMediaServer($assign_value).$assign_value); + } else { + $this->context->smarty->assign($assign_key, $assign_value); + } + } + + /** + * These shortcuts are DEPRECATED as of version 1.5.0.1 + * Use the Context to access objects instead. + * Example: $this->context->cart + */ + self::$cookie = $this->context->cookie; + self::$cart = $cart; + self::$smarty = $this->context->smarty; + self::$link = $link; + $defaultCountry = $this->context->country; + + $this->displayMaintenancePage(); + + if ($this->restrictedCountry) { + $this->displayRestrictedCountryPage(); + } + + if (Tools::isSubmit('live_edit') && !$this->checkLiveEditAccess()) { + Tools::redirect('index.php?controller=404'); + } + + $this->iso = $iso; + $this->context->cart = $cart; + $this->context->currency = $currency; + } + + /** + * Method that is executed after init() and checkAccess(). + * Used to process user input. + * + * @see Controller::run() + */ + public function postProcess() + { + } + + /** + * Initializes common front page content: header, footer and side columns + */ + public function initContent() + { + $this->process(); + + if (!isset($this->context->cart)) { + $this->context->cart = new Cart(); + } + + if (!$this->useMobileTheme()) { + // These hooks aren't used for the mobile theme. + // Needed hooks are called in the tpl files. + $this->context->smarty->assign(array( + 'HOOK_HEADER' => Hook::exec('displayHeader'), + 'HOOK_TOP' => Hook::exec('displayTop'), + 'HOOK_LEFT_COLUMN' => ($this->display_column_left ? Hook::exec('displayLeftColumn') : ''), + 'HOOK_RIGHT_COLUMN' => ($this->display_column_right ? Hook::exec('displayRightColumn', array('cart' => $this->context->cart)) : ''), + )); + } else { + $this->context->smarty->assign('HOOK_MOBILE_HEADER', Hook::exec('displayMobileHeader')); + } + } + + /** + * Compiles and outputs page header section (including HTML <head>) + * + * @param bool $display If true, renders visual page header section + * @deprecated 1.5.0.1 + */ + public function displayHeader($display = true) + { + Tools::displayAsDeprecated(); + + $this->initHeader(); + $hook_header = Hook::exec('displayHeader'); + if ((Configuration::get('PS_CSS_THEME_CACHE') || Configuration::get('PS_JS_THEME_CACHE')) && is_writable(_PS_THEME_DIR_.'cache')) { + // CSS compressor management + if (Configuration::get('PS_CSS_THEME_CACHE')) { + $this->css_files = Media::cccCss($this->css_files); + } + + //JS compressor management + if (Configuration::get('PS_JS_THEME_CACHE')) { + $this->js_files = Media::cccJs($this->js_files); + } + } + + // Call hook before assign of css_files and js_files in order to include correctly all css and javascript files + $this->context->smarty->assign(array( + 'HOOK_HEADER' => $hook_header, + 'HOOK_TOP' => Hook::exec('displayTop'), + 'HOOK_LEFT_COLUMN' => ($this->display_column_left ? Hook::exec('displayLeftColumn') : ''), + 'HOOK_RIGHT_COLUMN' => ($this->display_column_right ? Hook::exec('displayRightColumn', array('cart' => $this->context->cart)) : ''), + 'HOOK_FOOTER' => Hook::exec('displayFooter') + )); + + $this->context->smarty->assign(array( + 'css_files' => $this->css_files, + 'js_files' => ($this->getLayout() && (bool)Configuration::get('PS_JS_DEFER')) ? array() : $this->js_files + )); + + $this->display_header = $display; + $this->smartyOutputContent(_PS_THEME_DIR_.'header.tpl'); + } + + /** + * Compiles and outputs page footer section + * + * @deprecated 1.5.0.1 + */ + public function displayFooter($display = true) + { + Tools::displayAsDeprecated(); + $this->smartyOutputContent(_PS_THEME_DIR_.'footer.tpl'); + } + + /** + * Renders and outputs maintenance page and ends controller process. + */ + public function initCursedPage() + { + $this->displayMaintenancePage(); + } + + /** + * Called before compiling common page sections (header, footer, columns). + * Good place to modify smarty variables. + * + * @see FrontController::initContent() + */ + public function process() + { + } + + /** + * Redirects to redirect_after link + * + * @see $redirect_after + */ + protected function redirect() + { + Tools::redirectLink($this->redirect_after); + } + + /** + * Renders page content. + * Used for retrocompatibility with PS 1.4 + */ + public function displayContent() + { + } + + /** + * Compiles and outputs full page content + * + * @return bool + * @throws Exception + * @throws SmartyException + */ + public function display() + { + Tools::safePostVars(); + + // assign css_files and js_files at the very last time + if ((Configuration::get('PS_CSS_THEME_CACHE') || Configuration::get('PS_JS_THEME_CACHE')) && is_writable(_PS_THEME_DIR_.'cache')) { + // CSS compressor management + if (Configuration::get('PS_CSS_THEME_CACHE')) { + $this->css_files = Media::cccCss($this->css_files); + } + //JS compressor management + if (Configuration::get('PS_JS_THEME_CACHE') && !$this->useMobileTheme()) { + $this->js_files = Media::cccJs($this->js_files); + } + } + + $this->context->smarty->assign(array( + 'css_files' => $this->css_files, + 'js_files' => ($this->getLayout() && (bool)Configuration::get('PS_JS_DEFER')) ? array() : $this->js_files, + 'js_defer' => (bool)Configuration::get('PS_JS_DEFER'), + 'errors' => $this->errors, + 'display_header' => $this->display_header, + 'display_footer' => $this->display_footer, + )); + + $layout = $this->getLayout(); + if ($layout) { + if ($this->template) { + $template = $this->context->smarty->fetch($this->template); + } else { + // For retrocompatibility with 1.4 controller + + ob_start(); + $this->displayContent(); + $template = ob_get_contents(); + ob_clean(); + } + $this->context->smarty->assign('template', $template); + $this->smartyOutputContent($layout); + } else { + Tools::displayAsDeprecated('layout.tpl is missing in your theme directory'); + if ($this->display_header) { + $this->smartyOutputContent(_PS_THEME_DIR_.'header.tpl'); + } + + if ($this->template) { + $this->smartyOutputContent($this->template); + } else { // For retrocompatibility with 1.4 controller + $this->displayContent(); + } + + if ($this->display_footer) { + $this->smartyOutputContent(_PS_THEME_DIR_.'footer.tpl'); + } + } + + return true; + } + + /** + * Displays maintenance page if shop is closed. + */ + protected function displayMaintenancePage() + { + if ($this->maintenance == true || !(int)Configuration::get('PS_SHOP_ENABLE')) { + $this->maintenance = true; + if (!in_array(Tools::getRemoteAddr(), explode(',', Configuration::get('PS_MAINTENANCE_IP')))) { + header('HTTP/1.1 503 temporarily overloaded'); + + $this->context->smarty->assign($this->initLogoAndFavicon()); + $this->context->smarty->assign(array( + 'HOOK_MAINTENANCE' => Hook::exec('displayMaintenance', array()), + )); + + // If the controller is a module, then getTemplatePath will try to find the template in the modules, so we need to instanciate a real frontcontroller + $front_controller = preg_match('/ModuleFrontController$/', get_class($this)) ? new FrontController() : $this; + $this->smartyOutputContent($front_controller->getTemplatePath($this->getThemeDir().'maintenance.tpl')); + exit; + } + } + } + + /** + * Displays 'country restricted' page if user's country is not allowed. + */ + protected function displayRestrictedCountryPage() + { + header('HTTP/1.1 503 temporarily overloaded'); + $this->context->smarty->assign(array( + 'shop_name' => $this->context->shop->name, + 'favicon_url' => _PS_IMG_.Configuration::get('PS_FAVICON'), + 'logo_url' => $this->context->link->getMediaLink(_PS_IMG_.Configuration::get('PS_LOGO')) + )); + $this->smartyOutputContent($this->getTemplatePath($this->getThemeDir().'restricted-country.tpl')); + exit; + } + + /** + * Redirects to correct protocol if settings and request methods don't match. + */ + protected function sslRedirection() + { + // If we call a SSL controller without SSL or a non SSL controller with SSL, we redirect with the right protocol + if (Configuration::get('PS_SSL_ENABLED') && $_SERVER['REQUEST_METHOD'] != 'POST' && $this->ssl != Tools::usingSecureMode()) { + $this->context->cookie->disallowWriting(); + header('HTTP/1.1 301 Moved Permanently'); + header('Cache-Control: no-cache'); + if ($this->ssl) { + header('Location: '.Tools::getShopDomainSsl(true).$_SERVER['REQUEST_URI']); + } else { + header('Location: '.Tools::getShopDomain(true).$_SERVER['REQUEST_URI']); + } + exit(); + } + } + + /** + * Redirects to canonical URL + * + * @param string $canonical_url + */ + protected function canonicalRedirection($canonical_url = '') + { + if (!$canonical_url || !Configuration::get('PS_CANONICAL_REDIRECT') || strtoupper($_SERVER['REQUEST_METHOD']) != 'GET' || Tools::getValue('live_edit')) { + return; + } + + $match_url = rawurldecode(Tools::getCurrentUrlProtocolPrefix().$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); + if (!preg_match('/^'.Tools::pRegexp(rawurldecode($canonical_url), '/').'([&?].*)?$/', $match_url)) { + $params = array(); + $url_details = parse_url($canonical_url); + + if (!empty($url_details['query'])) { + parse_str($url_details['query'], $query); + foreach ($query as $key => $value) { + $params[Tools::safeOutput($key)] = Tools::safeOutput($value); + } + } + $excluded_key = array('isolang', 'id_lang', 'controller', 'fc', 'id_product', 'id_category', 'id_manufacturer', 'id_supplier', 'id_cms'); + foreach ($_GET as $key => $value) { + if (!in_array($key, $excluded_key) && Validate::isUrl($key) && Validate::isUrl($value)) { + $params[Tools::safeOutput($key)] = Tools::safeOutput($value); + } + } + + $str_params = http_build_query($params, '', '&'); + if (!empty($str_params)) { + $final_url = preg_replace('/^([^?]*)?.*$/', '$1', $canonical_url).'?'.$str_params; + } else { + $final_url = preg_replace('/^([^?]*)?.*$/', '$1', $canonical_url); + } + + // Don't send any cookie + Context::getContext()->cookie->disallowWriting(); + + if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_ && $_SERVER['REQUEST_URI'] != __PS_BASE_URI__) { + die('[Debug] This page has moved<br />Please use the following URL instead: <a href="'.$final_url.'">'.$final_url.'</a>'); + } + + $redirect_type = Configuration::get('PS_CANONICAL_REDIRECT') == 2 ? '301' : '302'; + header('HTTP/1.0 '.$redirect_type.' Moved'); + header('Cache-Control: no-cache'); + Tools::redirectLink($final_url); + } + } + + /** + * Geolocation management + * + * @param Country $default_country + * @return Country|false + */ + protected function geolocationManagement($default_country) + { + if (!in_array($_SERVER['SERVER_NAME'], array('localhost', '127.0.0.1'))) { + /* Check if Maxmind Database exists */ + if (@filemtime(_PS_GEOIP_DIR_._PS_GEOIP_CITY_FILE_)) { + if (!isset($this->context->cookie->iso_code_country) || (isset($this->context->cookie->iso_code_country) && !in_array(strtoupper($this->context->cookie->iso_code_country), explode(';', Configuration::get('PS_ALLOWED_COUNTRIES'))))) { + include_once(_PS_GEOIP_DIR_.'geoipcity.inc'); + + $gi = geoip_open(realpath(_PS_GEOIP_DIR_._PS_GEOIP_CITY_FILE_), GEOIP_STANDARD); + $record = geoip_record_by_addr($gi, Tools::getRemoteAddr()); + + if (is_object($record)) { + if (!in_array(strtoupper($record->country_code), explode(';', Configuration::get('PS_ALLOWED_COUNTRIES'))) && !FrontController::isInWhitelistForGeolocation()) { + if (Configuration::get('PS_GEOLOCATION_BEHAVIOR') == _PS_GEOLOCATION_NO_CATALOG_) { + $this->restrictedCountry = true; + } elseif (Configuration::get('PS_GEOLOCATION_BEHAVIOR') == _PS_GEOLOCATION_NO_ORDER_) { + $this->context->smarty->assign(array( + 'restricted_country_mode' => true, + 'geolocation_country' => $record->country_name + )); + } + } else { + $has_been_set = !isset($this->context->cookie->iso_code_country); + $this->context->cookie->iso_code_country = strtoupper($record->country_code); + } + } + } + + if (isset($this->context->cookie->iso_code_country) && $this->context->cookie->iso_code_country && !Validate::isLanguageIsoCode($this->context->cookie->iso_code_country)) { + $this->context->cookie->iso_code_country = Country::getIsoById(Configuration::get('PS_COUNTRY_DEFAULT')); + } + + if (isset($this->context->cookie->iso_code_country) && ($id_country = (int)Country::getByIso(strtoupper($this->context->cookie->iso_code_country)))) { + /* Update defaultCountry */ + if ($default_country->iso_code != $this->context->cookie->iso_code_country) { + $default_country = new Country($id_country); + } + if (isset($has_been_set) && $has_been_set) { + $this->context->cookie->id_currency = (int)($default_country->id_currency ? (int)$default_country->id_currency : (int)Configuration::get('PS_CURRENCY_DEFAULT')); + } + return $default_country; + } elseif (Configuration::get('PS_GEOLOCATION_NA_BEHAVIOR') == _PS_GEOLOCATION_NO_CATALOG_ && !FrontController::isInWhitelistForGeolocation()) { + $this->restrictedCountry = true; + } elseif (Configuration::get('PS_GEOLOCATION_NA_BEHAVIOR') == _PS_GEOLOCATION_NO_ORDER_ && !FrontController::isInWhitelistForGeolocation()) { + $this->context->smarty->assign(array( + 'restricted_country_mode' => true, + 'geolocation_country' => isset($record->country_name) && $record->country_name ? $record->country_name : 'Undefined' + )); + } + } + } + return false; + } + + /** + * Specific medias for mobile device. + * If autoload directory is present in the mobile theme, these files will not be loaded + */ + public function setMobileMedia() + { + $this->addJquery(); + + if (!file_exists($this->getThemeDir().'js/autoload/')) { + $this->addJS(_THEME_MOBILE_JS_DIR_.'jquery.mobile-1.3.0.min.js'); + $this->addJS(_THEME_MOBILE_JS_DIR_.'jqm-docs.js'); + $this->addJS(_PS_JS_DIR_.'tools.js'); + $this->addJS(_THEME_MOBILE_JS_DIR_.'global.js'); + $this->addJqueryPlugin('fancybox'); + } + + if (!file_exists($this->getThemeDir().'css/autoload/')) { + $this->addCSS(_THEME_MOBILE_CSS_DIR_.'jquery.mobile-1.3.0.min.css', 'all'); + $this->addCSS(_THEME_MOBILE_CSS_DIR_.'jqm-docs.css', 'all'); + $this->addCSS(_THEME_MOBILE_CSS_DIR_.'global.css', 'all'); + } + } + + /** + * Sets controller CSS and JS files. + * + * @return bool + */ + public function setMedia() + { + /** + * If website is accessed by mobile device + * @see FrontControllerCore::setMobileMedia() + */ + if ($this->useMobileTheme()) { + $this->setMobileMedia(); + return true; + } + + $this->addCSS(_THEME_CSS_DIR_.'grid_prestashop.css', 'all'); // retro compat themes 1.5.0.1 + $this->addCSS(_THEME_CSS_DIR_.'global.css', 'all'); + $this->addJquery(); + $this->addJqueryPlugin('easing'); + $this->addJS(_PS_JS_DIR_.'tools.js'); + $this->addJS(_THEME_JS_DIR_.'global.js'); + + // Automatically add js files from js/autoload directory in the template + if (@filemtime($this->getThemeDir().'js/autoload/')) { + foreach (scandir($this->getThemeDir().'js/autoload/', 0) as $file) { + if (preg_match('/^[^.].*\.js$/', $file)) { + $this->addJS($this->getThemeDir().'js/autoload/'.$file); + } + } + } + // Automatically add css files from css/autoload directory in the template + if (@filemtime($this->getThemeDir().'css/autoload/')) { + foreach (scandir($this->getThemeDir().'css/autoload', 0) as $file) { + if (preg_match('/^[^.].*\.css$/', $file)) { + $this->addCSS($this->getThemeDir().'css/autoload/'.$file); + } + } + } + + if (Tools::isSubmit('live_edit') && Tools::getValue('ad') && Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee'))) { + $this->addJqueryUI('ui.sortable'); + $this->addjqueryPlugin('fancybox'); + $this->addJS(_PS_JS_DIR_.'hookLiveEdit.js'); + } + + if (Configuration::get('PS_QUICK_VIEW')) { + $this->addjqueryPlugin('fancybox'); + } + + if (Configuration::get('PS_COMPARATOR_MAX_ITEM') > 0) { + $this->addJS(_THEME_JS_DIR_.'products-comparison.js'); + } + + // Execute Hook FrontController SetMedia + Hook::exec('actionFrontControllerSetMedia', array()); + + return true; + } + + /** + * Initializes page header variables + */ + public function initHeader() + { + /** @see P3P Policies (http://www.w3.org/TR/2002/REC-P3P-20020416/#compact_policies) */ + header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"'); + header('Powered-By: PrestaShop'); + + // Hooks are voluntary out the initialize array (need those variables already assigned) + $this->context->smarty->assign(array( + 'time' => time(), + 'img_update_time' => Configuration::get('PS_IMG_UPDATE_TIME'), + 'static_token' => Tools::getToken(false), + 'token' => Tools::getToken(), + 'priceDisplayPrecision' => _PS_PRICE_DISPLAY_PRECISION_, + 'content_only' => (int)Tools::getValue('content_only'), + )); + + $this->context->smarty->assign($this->initLogoAndFavicon()); + } + + /** + * Initializes page footer variables + */ + public function initFooter() + { + $this->context->smarty->assign(array( + 'HOOK_FOOTER' => Hook::exec('displayFooter'), + 'conditions' => Configuration::get('PS_CONDITIONS'), + 'id_cgv' => Configuration::get('PS_CONDITIONS_CMS_ID'), + 'PS_SHOP_NAME' => Configuration::get('PS_SHOP_NAME'), + 'PS_ALLOW_MOBILE_DEVICE' => isset($_SERVER['HTTP_USER_AGENT']) && (bool)Configuration::get('PS_ALLOW_MOBILE_DEVICE') && @filemtime(_PS_THEME_MOBILE_DIR_) + )); + + /** + * RTL support + * rtl.css overrides theme css files for RTL + * iso_code.css overrides default font for every language (optional) + */ + if ($this->context->language->is_rtl) { + $this->addCSS(_THEME_CSS_DIR_.'rtl.css'); + $this->addCSS(_THEME_CSS_DIR_.$this->context->language->iso_code.'.css'); + } + } + + /** + * Checks if the user can use Live Edit feature + * + * @return bool + */ + public function checkLiveEditAccess() + { + if (!Tools::isSubmit('live_edit') || !Tools::getValue('ad') || !Tools::getValue('liveToken')) { + return false; + } + + if (Tools::getValue('liveToken') != Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee'))) { + return false; + } + + return is_dir(_PS_CORE_DIR_.DIRECTORY_SEPARATOR.Tools::getValue('ad')); + } + + /** + * Renders Live Edit widget + * + * @return string HTML + */ + public function getLiveEditFooter() + { + if ($this->checkLiveEditAccess()) { + $data = $this->context->smarty->createData(); + $data->assign(array( + 'ad' => Tools::getValue('ad'), + 'live_edit' => true, + 'hook_list' => Hook::$executed_hooks, + 'id_shop' => $this->context->shop->id + )); + return $this->context->smarty->createTemplate(_PS_ALL_THEMES_DIR_.'live_edit.tpl', $data)->fetch(); + } else { + return ''; + } + } + + /** + * Assigns product list page sorting variables + */ + public function productSort() + { + // $this->orderBy = Tools::getProductsOrder('by', Tools::getValue('orderby')); + // $this->orderWay = Tools::getProductsOrder('way', Tools::getValue('orderway')); + // 'orderbydefault' => Tools::getProductsOrder('by'), + // 'orderwayposition' => Tools::getProductsOrder('way'), // Deprecated: orderwayposition + // 'orderwaydefault' => Tools::getProductsOrder('way'), + + $stock_management = Configuration::get('PS_STOCK_MANAGEMENT') ? true : false; // no display quantity order if stock management disabled + $order_by_values = array(0 => 'name', 1 => 'price', 2 => 'date_add', 3 => 'date_upd', 4 => 'position', 5 => 'manufacturer_name', 6 => 'quantity', 7 => 'reference'); + $order_way_values = array(0 => 'asc', 1 => 'desc'); + + $this->orderBy = Tools::strtolower(Tools::getValue('orderby', $order_by_values[(int)Configuration::get('PS_PRODUCTS_ORDER_BY')])); + $this->orderWay = Tools::strtolower(Tools::getValue('orderway', $order_way_values[(int)Configuration::get('PS_PRODUCTS_ORDER_WAY')])); + + if (!in_array($this->orderBy, $order_by_values)) { + $this->orderBy = $order_by_values[0]; + } + + if (!in_array($this->orderWay, $order_way_values)) { + $this->orderWay = $order_way_values[0]; + } + + $this->context->smarty->assign(array( + 'orderby' => $this->orderBy, + 'orderway' => $this->orderWay, + 'orderbydefault' => $order_by_values[(int)Configuration::get('PS_PRODUCTS_ORDER_BY')], + 'orderwayposition' => $order_way_values[(int)Configuration::get('PS_PRODUCTS_ORDER_WAY')], // Deprecated: orderwayposition + 'orderwaydefault' => $order_way_values[(int)Configuration::get('PS_PRODUCTS_ORDER_WAY')], + 'stock_management' => (int)$stock_management + )); + } + + /** + * Assigns product list page pagination variables + * + * @param int|null $total_products + * @throws PrestaShopException + */ + public function pagination($total_products = null) + { + if (!self::$initialized) { + $this->init(); + } elseif (!$this->context) { + $this->context = Context::getContext(); + } + + // Retrieve the default number of products per page and the other available selections + $default_products_per_page = max(1, (int)Configuration::get('PS_PRODUCTS_PER_PAGE')); + $n_array = array($default_products_per_page, $default_products_per_page * 2, $default_products_per_page * 5); + + if ((int)Tools::getValue('n') && (int)$total_products > 0) { + $n_array[] = $total_products; + } + // Retrieve the current number of products per page (either the default, the GET parameter or the one in the cookie) + $this->n = $default_products_per_page; + if (isset($this->context->cookie->nb_item_per_page) && in_array($this->context->cookie->nb_item_per_page, $n_array)) { + $this->n = (int)$this->context->cookie->nb_item_per_page; + } + + if ((int)Tools::getValue('n') && in_array((int)Tools::getValue('n'), $n_array)) { + $this->n = (int)Tools::getValue('n'); + } + + // Retrieve the page number (either the GET parameter or the first page) + $this->p = (int)Tools::getValue('p', 1); + // If the parameter is not correct then redirect (do not merge with the previous line, the redirect is required in order to avoid duplicate content) + if (!is_numeric($this->p) || $this->p < 1) { + Tools::redirect($this->context->link->getPaginationLink(false, false, $this->n, false, 1, false)); + } + + // Remove the page parameter in order to get a clean URL for the pagination template + $current_url = preg_replace('/(\?)?(&)?p=\d+/', '$1', Tools::htmlentitiesUTF8($_SERVER['REQUEST_URI'])); + + if ($this->n != $default_products_per_page || isset($this->context->cookie->nb_item_per_page)) { + $this->context->cookie->nb_item_per_page = $this->n; + } + + $pages_nb = ceil($total_products / (int)$this->n); + if ($this->p > $pages_nb && $total_products != 0) { + Tools::redirect($this->context->link->getPaginationLink(false, false, $this->n, false, $pages_nb, false)); + } + + $range = 2; /* how many pages around page selected */ + $start = (int)($this->p - $range); + if ($start < 1) { + $start = 1; + } + + $stop = (int)($this->p + $range); + if ($stop > $pages_nb) { + $stop = (int)$pages_nb; + } + + $this->context->smarty->assign(array( + 'nb_products' => $total_products, + 'products_per_page' => $this->n, + 'pages_nb' => $pages_nb, + 'p' => $this->p, + 'n' => $this->n, + 'nArray' => $n_array, + 'range' => $range, + 'start' => $start, + 'stop' => $stop, + 'current_url' => $current_url, + )); + } + + /** + * Sets and returns customer groups that the current customer(visitor) belongs to. + * + * @return array + * @throws PrestaShopDatabaseException + */ + public static function getCurrentCustomerGroups() + { + if (!Group::isFeatureActive()) { + return array(); + } + + $context = Context::getContext(); + if (!isset($context->customer) || !$context->customer->id) { + return array(); + } + + if (!is_array(self::$currentCustomerGroups)) { + self::$currentCustomerGroups = array(); + $result = Db::getInstance()->executeS('SELECT id_group FROM '._DB_PREFIX_.'customer_group WHERE id_customer = '.(int)$context->customer->id); + foreach ($result as $row) { + self::$currentCustomerGroups[] = $row['id_group']; + } + } + + return self::$currentCustomerGroups; + } + + /** + * Checks if user's location is whitelisted. + * + * @staticvar bool|null $allowed + * @return bool + */ + protected static function isInWhitelistForGeolocation() + { + static $allowed = null; + + if ($allowed !== null) { + return $allowed; + } + + $allowed = false; + $user_ip = Tools::getRemoteAddr(); + $ips = array(); + + // retrocompatibility + $ips_old = explode(';', Configuration::get('PS_GEOLOCATION_WHITELIST')); + if (is_array($ips_old) && count($ips_old)) { + foreach ($ips_old as $ip) { + $ips = array_merge($ips, explode("\n", $ip)); + } + } + + $ips = array_map('trim', $ips); + if (is_array($ips) && count($ips)) { + foreach ($ips as $ip) { + if (!empty($ip) && preg_match('/^'.$ip.'.*/', $user_ip)) { + $allowed = true; + } + } + } + + return $allowed; + } + + /** + * Checks if token is valid + * + * @since 1.5.0.1 + * @return bool + */ + public function isTokenValid() + { + if (!Configuration::get('PS_TOKEN_ENABLE')) { + return true; + } + + return (strcasecmp(Tools::getToken(false), Tools::getValue('token')) == 0); + } + + /** + * Adds a media file(s) (CSS, JS) to page header + * + * @param string|array $media_uri Path to file, or an array of paths like: array(array(uri => media_type), ...) + * @param string|null $css_media_type CSS media type + * @param int|null $offset + * @param bool $remove If True, removes media files + * @param bool $check_path If true, checks if files exists + * @return true|void + */ + public function addMedia($media_uri, $css_media_type = null, $offset = null, $remove = false, $check_path = true) + { + if (!is_array($media_uri)) { + if ($css_media_type) { + $media_uri = array($media_uri => $css_media_type); + } else { + $media_uri = array($media_uri); + } + } + + $list_uri = array(); + foreach ($media_uri as $file => $media) { + if (!Validate::isAbsoluteUrl($media)) { + $different = 0; + $different_css = 0; + $type = 'css'; + if (!$css_media_type) { + $type = 'js'; + $file = $media; + } + if (strpos($file, __PS_BASE_URI__.'modules/') === 0) { + $override_path = str_replace(__PS_BASE_URI__.'modules/', _PS_ROOT_DIR_.'/themes/'._THEME_NAME_.'/'.$type.'/modules/', $file, $different); + if (strrpos($override_path, $type.'/'.basename($file)) !== false) { + $override_path_css = str_replace($type.'/'.basename($file), basename($file), $override_path, $different_css); + } + + if ($different && @filemtime($override_path)) { + $file = str_replace(__PS_BASE_URI__.'modules/', __PS_BASE_URI__.'themes/'._THEME_NAME_.'/'.$type.'/modules/', $file, $different); + } elseif ($different_css && @filemtime($override_path_css)) { + $file = $override_path_css; + } + if ($css_media_type) { + $list_uri[$file] = $media; + } else { + $list_uri[] = $file; + } + } else { + $list_uri[$file] = $media; + } + } else { + $list_uri[$file] = $media; + } + } + + if ($remove) { + if ($css_media_type) { + return parent::removeCSS($list_uri, $css_media_type); + } + return parent::removeJS($list_uri); + } + + if ($css_media_type) { + return parent::addCSS($list_uri, $css_media_type, $offset, $check_path); + } + + return parent::addJS($list_uri, $check_path); + } + + /** + * Removes media file(s) from page header + * + * @param string|array $media_uri Path to file, or an array paths of like: array(array(uri => media_type), ...) + * @param string|null $css_media_type CSS media type + * @param bool $check_path If true, checks if files exists + */ + public function removeMedia($media_uri, $css_media_type = null, $check_path = true) + { + FrontController::addMedia($media_uri, $css_media_type, null, true, $check_path); + } + + /** + * Add one or several CSS for front, checking if css files are overridden in theme/css/modules/ directory + * @see Controller::addCSS() + * + * @param array|string $css_uri $media_uri Path to file, or an array of paths like: array(array(uri => media_type), ...) + * @param string $css_media_type CSS media type + * @param int|null $offset + * @param bool $check_path If true, checks if files exists + * @return true|void + */ + public function addCSS($css_uri, $css_media_type = 'all', $offset = null, $check_path = true) + { + return FrontController::addMedia($css_uri, $css_media_type, $offset = null, false, $check_path); + } + + /** + * Removes CSS file(s) from page header + * + * @param array|string $css_uri $media_uri Path to file, or an array of paths like: array(array(uri => media_type), ...) + * @param string $css_media_type CSS media type + * @param bool $check_path If true, checks if files exists + */ + public function removeCSS($css_uri, $css_media_type = 'all', $check_path = true) + { + return FrontController::removeMedia($css_uri, $css_media_type, $check_path); + } + + /** + * Add one or several JS files for front, checking if js files are overridden in theme/js/modules/ directory + * @see Controller::addJS() + * + * @param array|string $js_uri Path to file, or an array of paths + * @param bool $check_path If true, checks if files exists + * @return true|void + */ + public function addJS($js_uri, $check_path = true) + { + return Frontcontroller::addMedia($js_uri, null, null, false, $check_path); + } + + /** + * Removes JS file(s) from page header + * + * @param array|string $js_uri Path to file, or an array of paths + * @param bool $check_path If true, checks if files exists + */ + public function removeJS($js_uri, $check_path = true) + { + return FrontController::removeMedia($js_uri, null, $check_path); + } + + /** + * Recovers cart information + * + * @return int|false + */ + protected function recoverCart() + { + if (($id_cart = (int)Tools::getValue('recover_cart')) && Tools::getValue('token_cart') == md5(_COOKIE_KEY_.'recover_cart_'.$id_cart)) { + $cart = new Cart((int)$id_cart); + if (Validate::isLoadedObject($cart)) { + $customer = new Customer((int)$cart->id_customer); + if (Validate::isLoadedObject($customer)) { + $customer->logged = 1; + $this->context->customer = $customer; + $this->context->cookie->id_customer = (int)$customer->id; + $this->context->cookie->customer_lastname = $customer->lastname; + $this->context->cookie->customer_firstname = $customer->firstname; + $this->context->cookie->logged = 1; + $this->context->cookie->check_cgv = 1; + $this->context->cookie->is_guest = $customer->isGuest(); + $this->context->cookie->passwd = $customer->passwd; + $this->context->cookie->email = $customer->email; + return $id_cart; + } + } + } else { + return false; + } + } + + /** + * Sets template file for page content output + * + * @param string $default_template + */ + public function setTemplate($default_template) + { + if ($this->useMobileTheme()) { + $this->setMobileTemplate($default_template); + } else { + $template = $this->getOverrideTemplate(); + if ($template) { + parent::setTemplate($template); + } else { + parent::setTemplate($default_template); + } + } + } + + /** + * Returns an overridden template path (if any) for this controller. + * If not overridden, will return false. This method can be easily overriden in a + * specific controller. + * + * @since 1.5.0.13 + * @return string|bool + */ + public function getOverrideTemplate() + { + return Hook::exec('DisplayOverrideTemplate', array('controller' => $this)); + } + + /** + * Checks if mobile theme is active and in use. + * + * @staticvar bool|null $use_mobile_template + * @return bool + */ + protected function useMobileTheme() + { + static $use_mobile_template = null; + + // The mobile theme must have a layout to be used + if ($use_mobile_template === null) { + $use_mobile_template = ($this->context->getMobileDevice() && file_exists(_PS_THEME_MOBILE_DIR_.'layout.tpl')); + } + + return $use_mobile_template; + } + + /** + * Returns theme directory (regular or mobile) + * + * @return string + */ + protected function getThemeDir() + { + return $this->useMobileTheme() ? _PS_THEME_MOBILE_DIR_ : _PS_THEME_DIR_; + } + + + /** + * Returns theme override directory (regular or mobile) + * + * @return string + */ + protected function getOverrideThemeDir() + { + return $this->useMobileTheme() ? _PS_THEME_MOBILE_OVERRIDE_DIR_ : _PS_THEME_OVERRIDE_DIR_; + } + + /** + * Returns the layout corresponding to the current page by using the override system + * Ex: + * On the url: http://localhost/index.php?id_product=1&controller=product, this method will + * check if the layout exists in the following files (in that order), and return the first found: + * - /themes/default/override/layout-product-1.tpl + * - /themes/default/override/layout-product.tpl + * - /themes/default/layout.tpl + * + * @since 1.5.0.13 + * @return bool|string + */ + public function getLayout() + { + $entity = $this->php_self; + $id_item = (int)Tools::getValue('id_'.$entity); + + $layout_dir = $this->getThemeDir(); + $layout_override_dir = $this->getOverrideThemeDir(); + + $layout = false; + if ($entity) { + if ($id_item > 0 && file_exists($layout_override_dir.'layout-'.$entity.'-'.$id_item.'.tpl')) { + $layout = $layout_override_dir.'layout-'.$entity.'-'.$id_item.'.tpl'; + } elseif (file_exists($layout_override_dir.'layout-'.$entity.'.tpl')) { + $layout = $layout_override_dir.'layout-'.$entity.'.tpl'; + } + } + + if (!$layout && file_exists($layout_dir.'layout.tpl')) { + $layout = $layout_dir.'layout.tpl'; + } + + return $layout; + } + + /** + * Returns template path + * + * @param string $template + * @return string + */ + public function getTemplatePath($template) + { + if (!$this->useMobileTheme()) { + return $template; + } + + $tpl_file = basename($template); + $dirname = dirname($template).(substr(dirname($template), -1, 1) == '/' ? '' : '/'); + + if ($dirname == _PS_THEME_DIR_) { + if (file_exists(_PS_THEME_MOBILE_DIR_.$tpl_file)) { + $template = _PS_THEME_MOBILE_DIR_.$tpl_file; + } + } elseif ($dirname == _PS_THEME_MOBILE_DIR_) { + if (!file_exists(_PS_THEME_MOBILE_DIR_.$tpl_file) && file_exists(_PS_THEME_DIR_.$tpl_file)) { + $template = _PS_THEME_DIR_.$tpl_file; + } + } + + return $template; + } + + /** + * Checks if the template set is available for mobile themes, + * otherwise front template is chosen. + * + * @param string $template + */ + public function setMobileTemplate($template) + { + // Needed for site map + $blockmanufacturer = Module::getInstanceByName('blockmanufacturer'); + $blocksupplier = Module::getInstanceByName('blocksupplier'); + + $this->context->smarty->assign(array( + 'categoriesTree' => Category::getRootCategory()->recurseLiteCategTree(0), + 'categoriescmsTree' => CMSCategory::getRecurseCategory($this->context->language->id, 1, 1, 1), + 'voucherAllowed' => (int)CartRule::isFeatureActive(), + 'display_manufacturer_link' => (bool)$blockmanufacturer->active, + 'display_supplier_link' => (bool)$blocksupplier->active, + 'PS_DISPLAY_SUPPLIERS' => Configuration::get('PS_DISPLAY_SUPPLIERS'), + 'PS_DISPLAY_BEST_SELLERS' => Configuration::get('PS_DISPLAY_BEST_SELLERS'), + 'display_store' => Configuration::get('PS_STORES_DISPLAY_SITEMAP'), + 'conditions' => Configuration::get('PS_CONDITIONS'), + 'id_cgv' => Configuration::get('PS_CONDITIONS_CMS_ID'), + 'PS_SHOP_NAME' => Configuration::get('PS_SHOP_NAME'), + )); + + $template = $this->getTemplatePath($template); + + $assign = array(); + $assign['tpl_file'] = basename($template, '.tpl'); + if (isset($this->php_self)) { + $assign['controller_name'] = $this->php_self; + } + + $this->context->smarty->assign($assign); + $this->template = $template; + } + + /** + * Returns logo and favicon variables, depending + * on active theme type (regular or mobile) + * + * @since 1.5.3.0 + * @return array + */ + public function initLogoAndFavicon() + { + $mobile_device = $this->context->getMobileDevice(); + + if ($mobile_device && Configuration::get('PS_LOGO_MOBILE')) { + $logo = $this->context->link->getMediaLink(_PS_IMG_.Configuration::get('PS_LOGO_MOBILE').'?'.Configuration::get('PS_IMG_UPDATE_TIME')); + } else { + $logo = $this->context->link->getMediaLink(_PS_IMG_.Configuration::get('PS_LOGO')); + } + + return array( + 'favicon_url' => _PS_IMG_.Configuration::get('PS_FAVICON'), + 'logo_image_width' => ($mobile_device == false ? Configuration::get('SHOP_LOGO_WIDTH') : Configuration::get('SHOP_LOGO_MOBILE_WIDTH')), + 'logo_image_height' => ($mobile_device == false ? Configuration::get('SHOP_LOGO_HEIGHT') : Configuration::get('SHOP_LOGO_MOBILE_HEIGHT')), + 'logo_url' => $logo + ); + } + + /** + * Renders and adds color list HTML for each product in a list + * + * @param array $products + */ + public function addColorsToProductList(&$products) + { + if (!is_array($products) || !count($products) || !file_exists(_PS_THEME_DIR_.'product-list-colors.tpl')) { + return; + } + + $products_need_cache = array(); + foreach ($products as &$product) { + if (!$this->isCached(_PS_THEME_DIR_.'product-list-colors.tpl', $this->getColorsListCacheId($product['id_product']))) { + $products_need_cache[] = (int)$product['id_product']; + } + } + + unset($product); + + $colors = false; + if (count($products_need_cache)) { + $colors = Product::getAttributesColorList($products_need_cache); + } + + Tools::enableCache(); + foreach ($products as &$product) { + $tpl = $this->context->smarty->createTemplate(_PS_THEME_DIR_.'product-list-colors.tpl', $this->getColorsListCacheId($product['id_product'])); + if (isset($colors[$product['id_product']])) { + $tpl->assign(array( + 'id_product' => $product['id_product'], + 'colors_list' => $colors[$product['id_product']], + 'link' => Context::getContext()->link, + 'img_col_dir' => _THEME_COL_DIR_, + 'col_img_dir' => _PS_COL_IMG_DIR_ + )); + } + + if (!in_array($product['id_product'], $products_need_cache) || isset($colors[$product['id_product']])) { + $product['color_list'] = $tpl->fetch(_PS_THEME_DIR_.'product-list-colors.tpl', $this->getColorsListCacheId($product['id_product'])); + } else { + $product['color_list'] = ''; + } + } + Tools::restoreCacheSettings(); + } + + /** + * Returns cache ID for product color list + * + * @param int $id_product + * @return string + */ + protected function getColorsListCacheId($id_product) + { + return Product::getColorsListCacheId($id_product); + } } diff --git a/classes/controller/ModuleAdminController.php b/classes/controller/ModuleAdminController.php index ee094c5f..c74fb93f 100644 --- a/classes/controller/ModuleAdminController.php +++ b/classes/controller/ModuleAdminController.php @@ -29,50 +29,53 @@ */ abstract class ModuleAdminControllerCore extends AdminController { - /** @var Module */ - public $module; + /** @var Module */ + public $module; - /** - * @throws PrestaShopException - */ - public function __construct() - { - parent::__construct(); + /** + * @throws PrestaShopException + */ + public function __construct() + { + parent::__construct(); - $this->controller_type = 'moduleadmin'; + $this->controller_type = 'moduleadmin'; - $tab = new Tab($this->id); - if (!$tab->module) - throw new PrestaShopException('Admin tab '.get_class($this).' is not a module tab'); + $tab = new Tab($this->id); + if (!$tab->module) { + throw new PrestaShopException('Admin tab '.get_class($this).' is not a module tab'); + } - $this->module = Module::getInstanceByName($tab->module); - if (!$this->module->id) - throw new PrestaShopException("Module {$tab->module} not found"); - } + $this->module = Module::getInstanceByName($tab->module); + if (!$this->module->id) { + throw new PrestaShopException("Module {$tab->module} not found"); + } + } - /** - * Creates a template object - * - * @param string $tpl_name Template filename - * @return Smarty_Internal_Template - */ - public function createTemplate($tpl_name) - { - if (file_exists(_PS_THEME_DIR_.'modules/'.$this->module->name.'/views/templates/admin/'.$tpl_name) && $this->viewAccess()) - return $this->context->smarty->createTemplate(_PS_THEME_DIR_.'modules/'.$this->module->name.'/views/templates/admin/'.$tpl_name, $this->context->smarty); - elseif (file_exists($this->getTemplatePath().$this->override_folder.$tpl_name) && $this->viewAccess()) - return $this->context->smarty->createTemplate($this->getTemplatePath().$this->override_folder.$tpl_name, $this->context->smarty); + /** + * Creates a template object + * + * @param string $tpl_name Template filename + * @return Smarty_Internal_Template + */ + public function createTemplate($tpl_name) + { + if (file_exists(_PS_THEME_DIR_.'modules/'.$this->module->name.'/views/templates/admin/'.$tpl_name) && $this->viewAccess()) { + return $this->context->smarty->createTemplate(_PS_THEME_DIR_.'modules/'.$this->module->name.'/views/templates/admin/'.$tpl_name, $this->context->smarty); + } elseif (file_exists($this->getTemplatePath().$this->override_folder.$tpl_name) && $this->viewAccess()) { + return $this->context->smarty->createTemplate($this->getTemplatePath().$this->override_folder.$tpl_name, $this->context->smarty); + } - return parent::createTemplate($tpl_name); - } + return parent::createTemplate($tpl_name); + } - /** - * Get path to back office templates for the module - * - * @return string - */ - public function getTemplatePath() - { - return _PS_MODULE_DIR_.$this->module->name.'/views/templates/admin/'; - } + /** + * Get path to back office templates for the module + * + * @return string + */ + public function getTemplatePath() + { + return _PS_MODULE_DIR_.$this->module->name.'/views/templates/admin/'; + } } diff --git a/classes/controller/ModuleFrontController.php b/classes/controller/ModuleFrontController.php index 11b8bd20..fecd23f6 100644 --- a/classes/controller/ModuleFrontController.php +++ b/classes/controller/ModuleFrontController.php @@ -29,60 +29,62 @@ */ class ModuleFrontControllerCore extends FrontController { - /** @var Module */ - public $module; + /** @var Module */ + public $module; - public function __construct() - { - $this->module = Module::getInstanceByName(Tools::getValue('module')); - if (!$this->module->active) - Tools::redirect('index'); + public function __construct() + { + $this->module = Module::getInstanceByName(Tools::getValue('module')); + if (!$this->module->active) { + Tools::redirect('index'); + } - $this->page_name = 'module-'.$this->module->name.'-'.Dispatcher::getInstance()->getController(); + $this->page_name = 'module-'.$this->module->name.'-'.Dispatcher::getInstance()->getController(); - parent::__construct(); + parent::__construct(); - $this->controller_type = 'modulefront'; + $this->controller_type = 'modulefront'; - $in_base = isset($this->page_name) && is_object(Context::getContext()->theme) && Context::getContext()->theme->hasColumnsSettings($this->page_name); + $in_base = isset($this->page_name) && is_object(Context::getContext()->theme) && Context::getContext()->theme->hasColumnsSettings($this->page_name); - $tmp = isset($this->display_column_left) ? (bool)$this->display_column_left : true; - $this->display_column_left = $in_base ? Context::getContext()->theme->hasLeftColumn($this->page_name) : $tmp; + $tmp = isset($this->display_column_left) ? (bool)$this->display_column_left : true; + $this->display_column_left = $in_base ? Context::getContext()->theme->hasLeftColumn($this->page_name) : $tmp; - $tmp = isset($this->display_column_right) ? (bool)$this->display_column_right : true; - $this->display_column_right = $in_base ? Context::getContext()->theme->hasRightColumn($this->page_name) : $tmp; + $tmp = isset($this->display_column_right) ? (bool)$this->display_column_right : true; + $this->display_column_right = $in_base ? Context::getContext()->theme->hasRightColumn($this->page_name) : $tmp; + } - } + /** + * Assigns module template for page content + * + * @param string $template Template filename + * @throws PrestaShopException + */ + public function setTemplate($template) + { + if (!$path = $this->getTemplatePath($template)) { + throw new PrestaShopException("Template '$template' not found"); + } - /** - * Assigns module template for page content - * - * @param string $template Template filename - * @throws PrestaShopException - */ - public function setTemplate($template) - { - if (!$path = $this->getTemplatePath($template)) - throw new PrestaShopException("Template '$template' not found"); + $this->template = $path; + } - $this->template = $path; - } + /** + * Finds and returns module front template that take the highest precedence + * + * @param string $template Template filename + * @return string|false + */ + public function getTemplatePath($template) + { + if (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$this->module->name.'/'.$template)) { + return _PS_THEME_DIR_.'modules/'.$this->module->name.'/'.$template; + } elseif (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$this->module->name.'/views/templates/front/'.$template)) { + return _PS_THEME_DIR_.'modules/'.$this->module->name.'/views/templates/front/'.$template; + } elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$this->module->name.'/views/templates/front/'.$template)) { + return _PS_MODULE_DIR_.$this->module->name.'/views/templates/front/'.$template; + } - /** - * Finds and returns module front template that take the highest precedence - * - * @param string $template Template filename - * @return string|false - */ - public function getTemplatePath($template) - { - if (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$this->module->name.'/'.$template)) - return _PS_THEME_DIR_.'modules/'.$this->module->name.'/'.$template; - elseif (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$this->module->name.'/views/templates/front/'.$template)) - return _PS_THEME_DIR_.'modules/'.$this->module->name.'/views/templates/front/'.$template; - elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$this->module->name.'/views/templates/front/'.$template)) - return _PS_MODULE_DIR_.$this->module->name.'/views/templates/front/'.$template; - - return false; - } + return false; + } } diff --git a/classes/controller/index.php b/classes/controller/index.php index c642967a..91fa49fb 100644 --- a/classes/controller/index.php +++ b/classes/controller/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/classes/db/Db.php b/classes/db/Db.php index 2affef7b..48e7066a 100644 --- a/classes/db/Db.php +++ b/classes/db/Db.php @@ -24,749 +24,776 @@ * International Registered Trademark & Property of PrestaShop SA */ -if (file_exists(_PS_ROOT_DIR_.'/config/settings.inc.php')) - include_once(_PS_ROOT_DIR_.'/config/settings.inc.php'); +if (file_exists(_PS_ROOT_DIR_.'/config/settings.inc.php')) { + include_once(_PS_ROOT_DIR_.'/config/settings.inc.php'); +} /** * Class DbCore */ abstract class DbCore { - /** @var int Constant used by insert() method */ - const INSERT = 1; - - /** @var int Constant used by insert() method */ - const INSERT_IGNORE = 2; - - /** @var int Constant used by insert() method */ - const REPLACE = 3; - - /** @var int Constant used by insert() method */ - const ON_DUPLICATE_KEY = 4; - - /** @var string Server (eg. localhost) */ - protected $server; - - /** @var string Database user (eg. root) */ - protected $user; - - /** @var string Database password (eg. can be empty !) */ - protected $password; - - /** @var string Database name */ - protected $database; - - /** @var bool */ - protected $is_cache_enabled; - - /** @var PDO|mysqli|resource Resource link */ - protected $link; - - /** @var PDOStatement|mysqli_result|resource|bool SQL cached result */ - protected $result; - - /** @var array List of DB instances */ - public static $instance = array(); - - /** @var array List of server settings */ - public static $_servers = array(); - - /** @var null Flag used to load slave servers only once. - * See loadSlaveServers() method. - */ - public static $_slave_servers_loaded = null; - - /** - * Store last executed query - * - * @var string - */ - protected $last_query; - - /** - * Store hash of the last executed query - * - * @var string - */ - protected $last_query_hash; - - /** - * Last cached query - * - * @var string - */ - protected $last_cached; - - /** - * Opens a database connection - * - * @return PDO|mysqli|resource - */ - abstract public function connect(); - - /** - * Closes database connection - */ - abstract public function disconnect(); - - /** - * Execute a query and get result resource - * - * @param string $sql - * @return PDOStatement|mysqli_result|resource|bool - */ - abstract protected function _query($sql); - - /** - * Get number of rows in a result - * - * @param mixed $result - * @return int - */ - abstract protected function _numRows($result); - - /** - * Get the ID generated from the previous INSERT operation - * - * @return int|string - */ - abstract public function Insert_ID(); - - /** - * Get number of affected rows in previous database operation - * - * @return int - */ - abstract public function Affected_Rows(); - - /** - * Get next row for a query which does not return an array - * - * @param PDOStatement|mysqli_result|resource|bool $result - * @return array|object|false|null - */ - abstract public function nextRow($result = false); - - /** - * Get all rows for a query which return an array - * - * @param PDOStatement|mysqli_result|resource|bool|null $result - * @return array - */ - abstract protected function getAll($result = false); - - /** - * Get database version - * - * @return string - */ - abstract public function getVersion(); - - /** - * Protect string against SQL injections - * - * @param string $str - * @return string - */ - abstract public function _escape($str); - - /** - * Returns the text of the error message from previous database operation - * - * @return string - */ - abstract public function getMsgError(); - - /** - * Returns the number of the error from previous database operation - * - * @return int - */ - abstract public function getNumberError(); - - /** - * Sets the current active database on the server that's associated with the specified link identifier. - * Do not remove, useful for some modules. - * - * @param string $db_name - * @return bool|int - */ - abstract public function set_db($db_name); - - /** - * Selects best table engine. - * - * @return string - */ - abstract public function getBestEngine(); - - /** - * Returns database object instance. - * - * @param bool $master Decides whether the connection to be returned by the master server or the slave server - * @return Db Singleton instance of Db object - */ - public static function getInstance($master = true) - { - static $id = 0; - - // This MUST not be declared with the class members because some defines (like _DB_SERVER_) may not exist yet (the constructor can be called directly with params) - if (!self::$_servers) - self::$_servers = array( - array('server' => _DB_SERVER_, 'user' => _DB_USER_, 'password' => _DB_PASSWD_, 'database' => _DB_NAME_), /* MySQL Master server */ - ); - - if (!$master) - Db::loadSlaveServers(); - - $total_servers = count(self::$_servers); - if ($master || $total_servers == 1) - $id_server = 0; - else - { - $id++; - $id_server = ($total_servers > 2 && ($id % $total_servers) != 0) ? $id % $total_servers : 1; - } - - if (!isset(self::$instance[$id_server])) - { - $class = Db::getClass(); - self::$instance[$id_server] = new $class( - self::$_servers[$id_server]['server'], - self::$_servers[$id_server]['user'], - self::$_servers[$id_server]['password'], - self::$_servers[$id_server]['database'] - ); - } - - return self::$instance[$id_server]; - } - - /** - * @param $test_db Db - * Unit testing purpose only - */ - public static function setInstanceForTesting($test_db) - { - self::$instance[0] = $test_db; - } - - /** - * Unit testing purpose only - */ - public static function deleteTestingInstance() - { - self::$instance = array(); - } - - /** - * Loads configuration settings for slave servers if needed. - */ - protected static function loadSlaveServers() - { - if (self::$_slave_servers_loaded !== null) - return; - - // Add here your slave(s) server(s) in this file - if (file_exists(_PS_ROOT_DIR_.'/config/db_slave_server.inc.php')) - self::$_servers = array_merge(self::$_servers, require(_PS_ROOT_DIR_.'/config/db_slave_server.inc.php')); - - self::$_slave_servers_loaded = true; - } - - /** - * Returns the best child layer database class. - * - * @return string - */ - public static function getClass() - { - $class = 'MySQL'; - if (PHP_VERSION_ID >= 50200 && extension_loaded('pdo_mysql')) - $class = 'DbPDO'; - elseif (extension_loaded('mysqli')) - $class = 'DbMySQLi'; - - return $class; - } - - /** - * Instantiates a database connection - * - * @param string $server Server address - * @param string $user User login - * @param string $password User password - * @param string $database Database name - * @param bool $connect If false, don't connect in constructor (since 1.5.0.1) - */ - public function __construct($server, $user, $password, $database, $connect = true) - { - $this->server = $server; - $this->user = $user; - $this->password = $password; - $this->database = $database; - $this->is_cache_enabled = (defined('_PS_CACHE_ENABLED_')) ? _PS_CACHE_ENABLED_ : false; - - if (!defined('_PS_DEBUG_SQL_')) - define('_PS_DEBUG_SQL_', false); - - if ($connect) - $this->connect(); - } - - /** - * Disable the use of the cache - * - */ - public function disableCache() - { - $this->is_cache_enabled = false; - } - - /** - * Enable & flush the cache - * - */ - public function enableCache() - { - $this->is_cache_enabled = true; - Cache::getInstance()->flush(); - } - - /** - * Closes connection to database - */ - public function __destruct() - { - if ($this->link) - $this->disconnect(); - } - - /** - * Executes SQL query based on selected type - * - * @deprecated 1.5.0.1 Use insert() or update() method instead. - * @param string $table - * @param array $data - * @param string $type (INSERT, INSERT IGNORE, REPLACE, UPDATE). - * @param string $where - * @param int $limit - * @param bool $use_cache - * @param bool $use_null - * @return bool - * @throws PrestaShopDatabaseException - */ - public function autoExecute($table, $data, $type, $where = '', $limit = 0, $use_cache = true, $use_null = false) - { - $type = strtoupper($type); - switch ($type) - { - case 'INSERT' : - return $this->insert($table, $data, $use_null, $use_cache, Db::INSERT, false); - - case 'INSERT IGNORE' : - return $this->insert($table, $data, $use_null, $use_cache, Db::INSERT_IGNORE, false); - - case 'REPLACE' : - return $this->insert($table, $data, $use_null, $use_cache, Db::REPLACE, false); - - case 'UPDATE' : - return $this->update($table, $data, $where, $limit, $use_null, $use_cache, false); - - default : - throw new PrestaShopDatabaseException('Wrong argument (miss type) in Db::autoExecute()'); - } - } - - /** - * Filter SQL query within a blacklist - * - * @param string $table Table where insert/update data - * @param array $values Data to insert/update - * @param string $type INSERT or UPDATE - * @param string $where WHERE clause, only for UPDATE (optional) - * @param int $limit LIMIT clause (optional) - * @return bool - * @throws PrestaShopDatabaseException - */ - public function autoExecuteWithNullValues($table, $values, $type, $where = '', $limit = 0) - { - return $this->autoExecute($table, $values, $type, $where, $limit, 0, true); - } - - /** - * Execute a query and get result resource - * - * @param string|DbQuery $sql - * @return bool|mysqli_result|PDOStatement|resource - * @throws PrestaShopDatabaseException - */ - public function query($sql) - { - if ($sql instanceof DbQuery) - $sql = $sql->build(); - - $this->result = $this->_query($sql); - - if (!$this->result && $this->getNumberError() == 2006) - { - if ($this->connect()) - $this->result = $this->_query($sql); - } - - if (_PS_DEBUG_SQL_) - $this->displayError($sql); - - return $this->result; - } - - /** - * Executes an INSERT query - * - * @param string $table Table name without prefix - * @param array $data Data to insert as associative array. If $data is a list of arrays, multiple insert will be done - * @param bool $null_values If we want to use NULL values instead of empty quotes - * @param bool $use_cache - * @param int $type Must be Db::INSERT or Db::INSERT_IGNORE or Db::REPLACE - * @param bool $add_prefix Add or not _DB_PREFIX_ before table name - * @return bool - * @throws PrestaShopDatabaseException - */ - public function insert($table, $data, $null_values = false, $use_cache = true, $type = Db::INSERT, $add_prefix = true) - { - if (!$data && !$null_values) - return true; - - if ($add_prefix) - $table = _DB_PREFIX_.$table; - - if ($type == Db::INSERT) - $insert_keyword = 'INSERT'; - elseif ($type == Db::INSERT_IGNORE) - $insert_keyword = 'INSERT IGNORE'; - elseif ($type == Db::REPLACE) - $insert_keyword = 'REPLACE'; - elseif ($type == Db::ON_DUPLICATE_KEY) - $insert_keyword = 'INSERT'; - else - throw new PrestaShopDatabaseException('Bad keyword, must be Db::INSERT or Db::INSERT_IGNORE or Db::REPLACE'); - - // Check if $data is a list of row - $current = current($data); - if (!is_array($current) || isset($current['type'])) - $data = array($data); - - $keys = array(); - $values_stringified = array(); - $first_loop = true; - $duplicate_key_stringified = ''; - foreach ($data as $row_data) - { - $values = array(); - foreach ($row_data as $key => $value) - { - if (!$first_loop) - { - // Check if row array mapping are the same - if (!in_array("`$key`", $keys)) - throw new PrestaShopDatabaseException('Keys form $data subarray don\'t match'); - - if ($duplicate_key_stringified != '') - throw new PrestaShopDatabaseException('On duplicate key cannot be used on insert with more than 1 VALUE group'); - } - else - $keys[] = '`'.bqSQL($key).'`'; - - if (!is_array($value)) - $value = array('type' => 'text', 'value' => $value); - if ($value['type'] == 'sql') - $values[] = $string_value = $value['value']; - else - $values[] = $string_value = $null_values && ($value['value'] === '' || is_null($value['value'])) ? 'NULL' : "'{$value['value']}'"; - - if ($type == Db::ON_DUPLICATE_KEY) - $duplicate_key_stringified .= '`'.bqSQL($key).'` = '.$string_value.','; - } - $first_loop = false; - $values_stringified[] = '('.implode(', ', $values).')'; - } - $keys_stringified = implode(', ', $keys); - - $sql = $insert_keyword.' INTO `'.$table.'` ('.$keys_stringified.') VALUES '.implode(', ', $values_stringified); - if ($type == Db::ON_DUPLICATE_KEY) - $sql .= ' ON DUPLICATE KEY UPDATE '.substr($duplicate_key_stringified, 0, -1); - - return (bool)$this->q($sql, $use_cache); - } - - /** - * Executes an UPDATE query - * - * @param string $table Table name without prefix - * @param array $data Data to insert as associative array. If $data is a list of arrays, multiple insert will be done - * @param string $where WHERE condition - * @param int $limit - * @param bool $null_values If we want to use NULL values instead of empty quotes - * @param bool $use_cache - * @param bool $add_prefix Add or not _DB_PREFIX_ before table name - * @return bool - */ - public function update($table, $data, $where = '', $limit = 0, $null_values = false, $use_cache = true, $add_prefix = true) - { - if (!$data) - return true; - - if ($add_prefix) - $table = _DB_PREFIX_.$table; - - $sql = 'UPDATE `'.bqSQL($table).'` SET '; - foreach ($data as $key => $value) - { - if (!is_array($value)) - $value = array('type' => 'text', 'value' => $value); - if ($value['type'] == 'sql') - $sql .= '`'.bqSQL($key)."` = {$value['value']},"; - else - $sql .= ($null_values && ($value['value'] === '' || is_null($value['value']))) ? '`'.bqSQL($key).'` = NULL,' : '`'.bqSQL($key)."` = '{$value['value']}',"; - } - - $sql = rtrim($sql, ','); - if ($where) - $sql .= ' WHERE '.$where; - if ($limit) - $sql .= ' LIMIT '.(int)$limit; - - return (bool)$this->q($sql, $use_cache); - } - - /** - * Executes a DELETE query - * - * @param string $table Name of the table to delete - * @param string $where WHERE clause on query - * @param int $limit Number max of rows to delete - * @param bool $use_cache Use cache or not - * @param bool $add_prefix Add or not _DB_PREFIX_ before table name - * @return bool - */ - public function delete($table, $where = '', $limit = 0, $use_cache = true, $add_prefix = true) - { - if (_DB_PREFIX_ && !preg_match('#^'._DB_PREFIX_.'#i', $table) && $add_prefix) - $table = _DB_PREFIX_.$table; - - $this->result = false; - $sql = 'DELETE FROM `'.bqSQL($table).'`'.($where ? ' WHERE '.$where : '').($limit ? ' LIMIT '.(int)$limit : ''); - $res = $this->query($sql); - if ($use_cache && $this->is_cache_enabled) - Cache::getInstance()->deleteQuery($sql); - - return (bool)$res; - } - - /** - * Executes a query - * - * @param string|DbQuery $sql - * @param bool $use_cache - * @return bool - */ - public function execute($sql, $use_cache = true) - { - if ($sql instanceof DbQuery) - $sql = $sql->build(); - - $this->result = $this->query($sql); - if ($use_cache && $this->is_cache_enabled) - Cache::getInstance()->deleteQuery($sql); - - return (bool)$this->result; - } - - /** - * Executes return the result of $sql as array - * - * @param string|DbQuery $sql Query to execute - * @param bool $array Return an array instead of a result object (deprecated since 1.5.0.1, use query method instead) - * @param bool $use_cache - * @return array|false|null|mysqli_result|PDOStatement|resource - * @throws PrestaShopDatabaseException - */ - public function executeS($sql, $array = true, $use_cache = true) - { - if ($sql instanceof DbQuery) - $sql = $sql->build(); - - $this->result = false; - $this->last_query = $sql; - - if ($use_cache && $this->is_cache_enabled && $array) - { - $this->last_query_hash = Tools::encryptIV($sql); - if (($result = Cache::getInstance()->get($this->last_query_hash)) !== false) - { - $this->last_cached = true; - return $result; - } - } - - // This method must be used only with queries which display results - if (!preg_match('#^\s*\(?\s*(select|show|explain|describe|desc)\s#i', $sql)) - { - if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_) - throw new PrestaShopDatabaseException('Db->executeS() must be used only with select, show, explain or describe queries'); - return $this->execute($sql, $use_cache); - } - - $this->result = $this->query($sql); - - if (!$this->result) - $result = false; - else - { - if (!$array) - { - $use_cache = false; - $result = $this->result; - } - else - $result = $this->getAll($this->result); - } - - $this->last_cached = false; - if ($use_cache && $this->is_cache_enabled && $array) - Cache::getInstance()->setQuery($sql, $result); - - return $result; - } - - /** - * Returns an associative array containing the first row of the query - * This function automatically adds "LIMIT 1" to the query - * - * @param string|DbQuery $sql the select query (without "LIMIT 1") - * @param bool $use_cache Find it in cache first - * @return array|bool|object|null - */ - public function getRow($sql, $use_cache = true) - { - if ($sql instanceof DbQuery) - $sql = $sql->build(); - - $sql = rtrim($sql, " \t\n\r\0\x0B;").' LIMIT 1'; - $this->result = false; - $this->last_query = $sql; - - if ($use_cache && $this->is_cache_enabled) - { - $this->last_query_hash = Tools::encryptIV($sql); - if (($result = Cache::getInstance()->get($this->last_query_hash)) !== false) - { - $this->last_cached = true; - return $result; - } - } - - $this->result = $this->query($sql); - if (!$this->result) - $result = false; - else - $result = $this->nextRow($this->result); - - $this->last_cached = false; - - if (is_null($result)) - $result = false; - - if ($use_cache && $this->is_cache_enabled) - Cache::getInstance()->setQuery($sql, $result); - - return $result; - } - - /** - * Returns a value from the first row, first column of a SELECT query - * - * @param string|DbQuery $sql - * @param bool $use_cache - * @return string|false|null - */ - public function getValue($sql, $use_cache = true) - { - if ($sql instanceof DbQuery) - $sql = $sql->build(); - - if (!$result = $this->getRow($sql, $use_cache)) - return false; - - return array_shift($result); - } - - /** - * Get number of rows for last result - * - * @return int - */ - public function numRows() - { - if (!$this->last_cached && $this->result) - { - $nrows = $this->_numRows($this->result); - if ($this->is_cache_enabled) - Cache::getInstance()->set($this->last_query_hash.'_nrows', $nrows); - return $nrows; - } - elseif ($this->is_cache_enabled && $this->last_cached) - return Cache::getInstance()->get($this->last_query_hash.'_nrows'); - } - - /** - * Executes a query - * - * @param string|DbQuery $sql - * @param bool $use_cache - * @return bool|mysqli_result|PDOStatement|resource - * @throws PrestaShopDatabaseException - */ - protected function q($sql, $use_cache = true) - { - if ($sql instanceof DbQuery) - $sql = $sql->build(); - - $this->result = false; - $result = $this->query($sql); - if ($use_cache && $this->is_cache_enabled) - Cache::getInstance()->deleteQuery($sql); - - if (_PS_DEBUG_SQL_) - $this->displayError($sql); - - return $result; - } - - /** - * Displays last SQL error - * - * @param string|bool $sql - * @throws PrestaShopDatabaseException - */ - public function displayError($sql = false) - { - global $webservice_call; - - $errno = $this->getNumberError(); - if ($webservice_call && $errno) - { - $dbg = debug_backtrace(); - WebserviceRequest::getInstance()->setError(500, '[SQL Error] '.$this->getMsgError().'. From '.(isset($dbg[3]['class']) ? $dbg[3]['class'] : '').'->'.$dbg[3]['function'].'() Query was : '.$sql, 97); - } - elseif (_PS_DEBUG_SQL_ && $errno && !defined('PS_INSTALLATION_IN_PROGRESS')) - { - if ($sql) - throw new PrestaShopDatabaseException($this->getMsgError().'<br /><br /><pre>'.$sql.'</pre>'); - - throw new PrestaShopDatabaseException($this->getMsgError()); - } - } + /** @var int Constant used by insert() method */ + const INSERT = 1; + + /** @var int Constant used by insert() method */ + const INSERT_IGNORE = 2; + + /** @var int Constant used by insert() method */ + const REPLACE = 3; + + /** @var int Constant used by insert() method */ + const ON_DUPLICATE_KEY = 4; + + /** @var string Server (eg. localhost) */ + protected $server; + + /** @var string Database user (eg. root) */ + protected $user; + + /** @var string Database password (eg. can be empty !) */ + protected $password; + + /** @var string Database name */ + protected $database; + + /** @var bool */ + protected $is_cache_enabled; + + /** @var PDO|mysqli|resource Resource link */ + protected $link; + + /** @var PDOStatement|mysqli_result|resource|bool SQL cached result */ + protected $result; + + /** @var array List of DB instances */ + public static $instance = array(); + + /** @var array List of server settings */ + public static $_servers = array(); + + /** @var null Flag used to load slave servers only once. + * See loadSlaveServers() method. + */ + public static $_slave_servers_loaded = null; + + /** + * Store last executed query + * + * @var string + */ + protected $last_query; + + /** + * Store hash of the last executed query + * + * @var string + */ + protected $last_query_hash; + + /** + * Last cached query + * + * @var string + */ + protected $last_cached; + + /** + * Opens a database connection + * + * @return PDO|mysqli|resource + */ + abstract public function connect(); + + /** + * Closes database connection + */ + abstract public function disconnect(); + + /** + * Execute a query and get result resource + * + * @param string $sql + * @return PDOStatement|mysqli_result|resource|bool + */ + abstract protected function _query($sql); + + /** + * Get number of rows in a result + * + * @param mixed $result + * @return int + */ + abstract protected function _numRows($result); + + /** + * Get the ID generated from the previous INSERT operation + * + * @return int|string + */ + abstract public function Insert_ID(); + + /** + * Get number of affected rows in previous database operation + * + * @return int + */ + abstract public function Affected_Rows(); + + /** + * Get next row for a query which does not return an array + * + * @param PDOStatement|mysqli_result|resource|bool $result + * @return array|object|false|null + */ + abstract public function nextRow($result = false); + + /** + * Get all rows for a query which return an array + * + * @param PDOStatement|mysqli_result|resource|bool|null $result + * @return array + */ + abstract protected function getAll($result = false); + + /** + * Get database version + * + * @return string + */ + abstract public function getVersion(); + + /** + * Protect string against SQL injections + * + * @param string $str + * @return string + */ + abstract public function _escape($str); + + /** + * Returns the text of the error message from previous database operation + * + * @return string + */ + abstract public function getMsgError(); + + /** + * Returns the number of the error from previous database operation + * + * @return int + */ + abstract public function getNumberError(); + + /** + * Sets the current active database on the server that's associated with the specified link identifier. + * Do not remove, useful for some modules. + * + * @param string $db_name + * @return bool|int + */ + abstract public function set_db($db_name); + + /** + * Selects best table engine. + * + * @return string + */ + abstract public function getBestEngine(); + + /** + * Returns database object instance. + * + * @param bool $master Decides whether the connection to be returned by the master server or the slave server + * @return Db Singleton instance of Db object + */ + public static function getInstance($master = true) + { + static $id = 0; + + // This MUST not be declared with the class members because some defines (like _DB_SERVER_) may not exist yet (the constructor can be called directly with params) + if (!self::$_servers) { + self::$_servers = array( + array('server' => _DB_SERVER_, 'user' => _DB_USER_, 'password' => _DB_PASSWD_, 'database' => _DB_NAME_), /* MySQL Master server */ + ); + } + + if (!$master) { + Db::loadSlaveServers(); + } + + $total_servers = count(self::$_servers); + if ($master || $total_servers == 1) { + $id_server = 0; + } else { + $id++; + $id_server = ($total_servers > 2 && ($id % $total_servers) != 0) ? $id % $total_servers : 1; + } + + if (!isset(self::$instance[$id_server])) { + $class = Db::getClass(); + self::$instance[$id_server] = new $class( + self::$_servers[$id_server]['server'], + self::$_servers[$id_server]['user'], + self::$_servers[$id_server]['password'], + self::$_servers[$id_server]['database'] + ); + } + + return self::$instance[$id_server]; + } + + /** + * @param $test_db Db + * Unit testing purpose only + */ + public static function setInstanceForTesting($test_db) + { + self::$instance[0] = $test_db; + } + + /** + * Unit testing purpose only + */ + public static function deleteTestingInstance() + { + self::$instance = array(); + } + + /** + * Loads configuration settings for slave servers if needed. + */ + protected static function loadSlaveServers() + { + if (self::$_slave_servers_loaded !== null) { + return; + } + + // Add here your slave(s) server(s) in this file + if (file_exists(_PS_ROOT_DIR_.'/config/db_slave_server.inc.php')) { + self::$_servers = array_merge(self::$_servers, require(_PS_ROOT_DIR_.'/config/db_slave_server.inc.php')); + } + + self::$_slave_servers_loaded = true; + } + + /** + * Returns the best child layer database class. + * + * @return string + */ + public static function getClass() + { + $class = 'MySQL'; + if (PHP_VERSION_ID >= 50200 && extension_loaded('pdo_mysql')) { + $class = 'DbPDO'; + } elseif (extension_loaded('mysqli')) { + $class = 'DbMySQLi'; + } + + return $class; + } + + /** + * Instantiates a database connection + * + * @param string $server Server address + * @param string $user User login + * @param string $password User password + * @param string $database Database name + * @param bool $connect If false, don't connect in constructor (since 1.5.0.1) + */ + public function __construct($server, $user, $password, $database, $connect = true) + { + $this->server = $server; + $this->user = $user; + $this->password = $password; + $this->database = $database; + $this->is_cache_enabled = (defined('_PS_CACHE_ENABLED_')) ? _PS_CACHE_ENABLED_ : false; + + if (!defined('_PS_DEBUG_SQL_')) { + define('_PS_DEBUG_SQL_', false); + } + + if ($connect) { + $this->connect(); + } + } + + /** + * Disable the use of the cache + * + */ + public function disableCache() + { + $this->is_cache_enabled = false; + } + + /** + * Enable & flush the cache + * + */ + public function enableCache() + { + $this->is_cache_enabled = true; + Cache::getInstance()->flush(); + } + + /** + * Closes connection to database + */ + public function __destruct() + { + if ($this->link) { + $this->disconnect(); + } + } + + /** + * Executes SQL query based on selected type + * + * @deprecated 1.5.0.1 Use insert() or update() method instead. + * @param string $table + * @param array $data + * @param string $type (INSERT, INSERT IGNORE, REPLACE, UPDATE). + * @param string $where + * @param int $limit + * @param bool $use_cache + * @param bool $use_null + * @return bool + * @throws PrestaShopDatabaseException + */ + public function autoExecute($table, $data, $type, $where = '', $limit = 0, $use_cache = true, $use_null = false) + { + $type = strtoupper($type); + switch ($type) { + case 'INSERT' : + return $this->insert($table, $data, $use_null, $use_cache, Db::INSERT, false); + + case 'INSERT IGNORE' : + return $this->insert($table, $data, $use_null, $use_cache, Db::INSERT_IGNORE, false); + + case 'REPLACE' : + return $this->insert($table, $data, $use_null, $use_cache, Db::REPLACE, false); + + case 'UPDATE' : + return $this->update($table, $data, $where, $limit, $use_null, $use_cache, false); + + default : + throw new PrestaShopDatabaseException('Wrong argument (miss type) in Db::autoExecute()'); + } + } + + /** + * Filter SQL query within a blacklist + * + * @param string $table Table where insert/update data + * @param array $values Data to insert/update + * @param string $type INSERT or UPDATE + * @param string $where WHERE clause, only for UPDATE (optional) + * @param int $limit LIMIT clause (optional) + * @return bool + * @throws PrestaShopDatabaseException + */ + public function autoExecuteWithNullValues($table, $values, $type, $where = '', $limit = 0) + { + return $this->autoExecute($table, $values, $type, $where, $limit, 0, true); + } + + /** + * Execute a query and get result resource + * + * @param string|DbQuery $sql + * @return bool|mysqli_result|PDOStatement|resource + * @throws PrestaShopDatabaseException + */ + public function query($sql) + { + if ($sql instanceof DbQuery) { + $sql = $sql->build(); + } + + $this->result = $this->_query($sql); + + if (!$this->result && $this->getNumberError() == 2006) { + if ($this->connect()) { + $this->result = $this->_query($sql); + } + } + + if (_PS_DEBUG_SQL_) { + $this->displayError($sql); + } + + return $this->result; + } + + /** + * Executes an INSERT query + * + * @param string $table Table name without prefix + * @param array $data Data to insert as associative array. If $data is a list of arrays, multiple insert will be done + * @param bool $null_values If we want to use NULL values instead of empty quotes + * @param bool $use_cache + * @param int $type Must be Db::INSERT or Db::INSERT_IGNORE or Db::REPLACE + * @param bool $add_prefix Add or not _DB_PREFIX_ before table name + * @return bool + * @throws PrestaShopDatabaseException + */ + public function insert($table, $data, $null_values = false, $use_cache = true, $type = Db::INSERT, $add_prefix = true) + { + if (!$data && !$null_values) { + return true; + } + + if ($add_prefix) { + $table = _DB_PREFIX_.$table; + } + + if ($type == Db::INSERT) { + $insert_keyword = 'INSERT'; + } elseif ($type == Db::INSERT_IGNORE) { + $insert_keyword = 'INSERT IGNORE'; + } elseif ($type == Db::REPLACE) { + $insert_keyword = 'REPLACE'; + } elseif ($type == Db::ON_DUPLICATE_KEY) { + $insert_keyword = 'INSERT'; + } else { + throw new PrestaShopDatabaseException('Bad keyword, must be Db::INSERT or Db::INSERT_IGNORE or Db::REPLACE'); + } + + // Check if $data is a list of row + $current = current($data); + if (!is_array($current) || isset($current['type'])) { + $data = array($data); + } + + $keys = array(); + $values_stringified = array(); + $first_loop = true; + $duplicate_key_stringified = ''; + foreach ($data as $row_data) { + $values = array(); + foreach ($row_data as $key => $value) { + if (!$first_loop) { + // Check if row array mapping are the same + if (!in_array("`$key`", $keys)) { + throw new PrestaShopDatabaseException('Keys form $data subarray don\'t match'); + } + + if ($duplicate_key_stringified != '') { + throw new PrestaShopDatabaseException('On duplicate key cannot be used on insert with more than 1 VALUE group'); + } + } else { + $keys[] = '`'.bqSQL($key).'`'; + } + + if (!is_array($value)) { + $value = array('type' => 'text', 'value' => $value); + } + if ($value['type'] == 'sql') { + $values[] = $string_value = $value['value']; + } else { + $values[] = $string_value = $null_values && ($value['value'] === '' || is_null($value['value'])) ? 'NULL' : "'{$value['value']}'"; + } + + if ($type == Db::ON_DUPLICATE_KEY) { + $duplicate_key_stringified .= '`'.bqSQL($key).'` = '.$string_value.','; + } + } + $first_loop = false; + $values_stringified[] = '('.implode(', ', $values).')'; + } + $keys_stringified = implode(', ', $keys); + + $sql = $insert_keyword.' INTO `'.$table.'` ('.$keys_stringified.') VALUES '.implode(', ', $values_stringified); + if ($type == Db::ON_DUPLICATE_KEY) { + $sql .= ' ON DUPLICATE KEY UPDATE '.substr($duplicate_key_stringified, 0, -1); + } + + return (bool)$this->q($sql, $use_cache); + } + + /** + * Executes an UPDATE query + * + * @param string $table Table name without prefix + * @param array $data Data to insert as associative array. If $data is a list of arrays, multiple insert will be done + * @param string $where WHERE condition + * @param int $limit + * @param bool $null_values If we want to use NULL values instead of empty quotes + * @param bool $use_cache + * @param bool $add_prefix Add or not _DB_PREFIX_ before table name + * @return bool + */ + public function update($table, $data, $where = '', $limit = 0, $null_values = false, $use_cache = true, $add_prefix = true) + { + if (!$data) { + return true; + } + + if ($add_prefix) { + $table = _DB_PREFIX_.$table; + } + + $sql = 'UPDATE `'.bqSQL($table).'` SET '; + foreach ($data as $key => $value) { + if (!is_array($value)) { + $value = array('type' => 'text', 'value' => $value); + } + if ($value['type'] == 'sql') { + $sql .= '`'.bqSQL($key)."` = {$value['value']},"; + } else { + $sql .= ($null_values && ($value['value'] === '' || is_null($value['value']))) ? '`'.bqSQL($key).'` = NULL,' : '`'.bqSQL($key)."` = '{$value['value']}',"; + } + } + + $sql = rtrim($sql, ','); + if ($where) { + $sql .= ' WHERE '.$where; + } + if ($limit) { + $sql .= ' LIMIT '.(int)$limit; + } + + return (bool)$this->q($sql, $use_cache); + } + + /** + * Executes a DELETE query + * + * @param string $table Name of the table to delete + * @param string $where WHERE clause on query + * @param int $limit Number max of rows to delete + * @param bool $use_cache Use cache or not + * @param bool $add_prefix Add or not _DB_PREFIX_ before table name + * @return bool + */ + public function delete($table, $where = '', $limit = 0, $use_cache = true, $add_prefix = true) + { + if (_DB_PREFIX_ && !preg_match('#^'._DB_PREFIX_.'#i', $table) && $add_prefix) { + $table = _DB_PREFIX_.$table; + } + + $this->result = false; + $sql = 'DELETE FROM `'.bqSQL($table).'`'.($where ? ' WHERE '.$where : '').($limit ? ' LIMIT '.(int)$limit : ''); + $res = $this->query($sql); + if ($use_cache && $this->is_cache_enabled) { + Cache::getInstance()->deleteQuery($sql); + } + + return (bool)$res; + } + + /** + * Executes a query + * + * @param string|DbQuery $sql + * @param bool $use_cache + * @return bool + */ + public function execute($sql, $use_cache = true) + { + if ($sql instanceof DbQuery) { + $sql = $sql->build(); + } + + $this->result = $this->query($sql); + if ($use_cache && $this->is_cache_enabled) { + Cache::getInstance()->deleteQuery($sql); + } + + return (bool)$this->result; + } + + /** + * Executes return the result of $sql as array + * + * @param string|DbQuery $sql Query to execute + * @param bool $array Return an array instead of a result object (deprecated since 1.5.0.1, use query method instead) + * @param bool $use_cache + * @return array|false|null|mysqli_result|PDOStatement|resource + * @throws PrestaShopDatabaseException + */ + public function executeS($sql, $array = true, $use_cache = true) + { + if ($sql instanceof DbQuery) { + $sql = $sql->build(); + } + + $this->result = false; + $this->last_query = $sql; + + if ($use_cache && $this->is_cache_enabled && $array) { + $this->last_query_hash = Tools::encryptIV($sql); + if (($result = Cache::getInstance()->get($this->last_query_hash)) !== false) { + $this->last_cached = true; + return $result; + } + } + + // This method must be used only with queries which display results + if (!preg_match('#^\s*\(?\s*(select|show|explain|describe|desc)\s#i', $sql)) { + if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_) { + throw new PrestaShopDatabaseException('Db->executeS() must be used only with select, show, explain or describe queries'); + } + return $this->execute($sql, $use_cache); + } + + $this->result = $this->query($sql); + + if (!$this->result) { + $result = false; + } else { + if (!$array) { + $use_cache = false; + $result = $this->result; + } else { + $result = $this->getAll($this->result); + } + } + + $this->last_cached = false; + if ($use_cache && $this->is_cache_enabled && $array) { + Cache::getInstance()->setQuery($sql, $result); + } + + return $result; + } + + /** + * Returns an associative array containing the first row of the query + * This function automatically adds "LIMIT 1" to the query + * + * @param string|DbQuery $sql the select query (without "LIMIT 1") + * @param bool $use_cache Find it in cache first + * @return array|bool|object|null + */ + public function getRow($sql, $use_cache = true) + { + if ($sql instanceof DbQuery) { + $sql = $sql->build(); + } + + $sql = rtrim($sql, " \t\n\r\0\x0B;").' LIMIT 1'; + $this->result = false; + $this->last_query = $sql; + + if ($use_cache && $this->is_cache_enabled) { + $this->last_query_hash = Tools::encryptIV($sql); + if (($result = Cache::getInstance()->get($this->last_query_hash)) !== false) { + $this->last_cached = true; + return $result; + } + } + + $this->result = $this->query($sql); + if (!$this->result) { + $result = false; + } else { + $result = $this->nextRow($this->result); + } + + $this->last_cached = false; + + if (is_null($result)) { + $result = false; + } + + if ($use_cache && $this->is_cache_enabled) { + Cache::getInstance()->setQuery($sql, $result); + } + + return $result; + } + + /** + * Returns a value from the first row, first column of a SELECT query + * + * @param string|DbQuery $sql + * @param bool $use_cache + * @return string|false|null + */ + public function getValue($sql, $use_cache = true) + { + if ($sql instanceof DbQuery) { + $sql = $sql->build(); + } + + if (!$result = $this->getRow($sql, $use_cache)) { + return false; + } + + return array_shift($result); + } + + /** + * Get number of rows for last result + * + * @return int + */ + public function numRows() + { + if (!$this->last_cached && $this->result) { + $nrows = $this->_numRows($this->result); + if ($this->is_cache_enabled) { + Cache::getInstance()->set($this->last_query_hash.'_nrows', $nrows); + } + return $nrows; + } elseif ($this->is_cache_enabled && $this->last_cached) { + return Cache::getInstance()->get($this->last_query_hash.'_nrows'); + } + } + + /** + * Executes a query + * + * @param string|DbQuery $sql + * @param bool $use_cache + * @return bool|mysqli_result|PDOStatement|resource + * @throws PrestaShopDatabaseException + */ + protected function q($sql, $use_cache = true) + { + if ($sql instanceof DbQuery) { + $sql = $sql->build(); + } + + $this->result = false; + $result = $this->query($sql); + if ($use_cache && $this->is_cache_enabled) { + Cache::getInstance()->deleteQuery($sql); + } + + if (_PS_DEBUG_SQL_) { + $this->displayError($sql); + } + + return $result; + } + + /** + * Displays last SQL error + * + * @param string|bool $sql + * @throws PrestaShopDatabaseException + */ + public function displayError($sql = false) + { + global $webservice_call; + + $errno = $this->getNumberError(); + if ($webservice_call && $errno) { + $dbg = debug_backtrace(); + WebserviceRequest::getInstance()->setError(500, '[SQL Error] '.$this->getMsgError().'. From '.(isset($dbg[3]['class']) ? $dbg[3]['class'] : '').'->'.$dbg[3]['function'].'() Query was : '.$sql, 97); + } elseif (_PS_DEBUG_SQL_ && $errno && !defined('PS_INSTALLATION_IN_PROGRESS')) { + if ($sql) { + throw new PrestaShopDatabaseException($this->getMsgError().'<br /><br /><pre>'.$sql.'</pre>'); + } + + throw new PrestaShopDatabaseException($this->getMsgError()); + } + } /** * Sanitize data which will be injected into SQL query @@ -775,150 +802,152 @@ abstract class DbCore * @param bool $html_ok Does data contain HTML code ? (optional) * @return string Sanitized data */ - public function escape($string, $html_ok = false, $bq_sql = false) - { - if (_PS_MAGIC_QUOTES_GPC_) - $string = stripslashes($string); + public function escape($string, $html_ok = false, $bq_sql = false) + { + if (_PS_MAGIC_QUOTES_GPC_) { + $string = stripslashes($string); + } - if (!is_numeric($string)) - { - $string = $this->_escape($string); + if (!is_numeric($string)) { + $string = $this->_escape($string); - if (!$html_ok) - $string = strip_tags(Tools::nl2br($string)); + if (!$html_ok) { + $string = strip_tags(Tools::nl2br($string)); + } - if ($bq_sql === true) - $string = str_replace('`', '\`', $string); - } + if ($bq_sql === true) { + $string = str_replace('`', '\`', $string); + } + } - return $string; - } + return $string; + } - /** - * Try a connection to the database - * - * @param string $server Server address - * @param string $user Login for database connection - * @param string $pwd Password for database connection - * @param string $db Database name - * @param bool $new_db_link - * @param string|bool $engine - * @param int $timeout - * @return int Error code or 0 if connection was successful - */ - public static function checkConnection($server, $user, $pwd, $db, $new_db_link = true, $engine = null, $timeout = 5) - { - return call_user_func_array(array(Db::getClass(), 'tryToConnect'), array($server, $user, $pwd, $db, $new_db_link, $engine, $timeout)); - } + /** + * Try a connection to the database + * + * @param string $server Server address + * @param string $user Login for database connection + * @param string $pwd Password for database connection + * @param string $db Database name + * @param bool $new_db_link + * @param string|bool $engine + * @param int $timeout + * @return int Error code or 0 if connection was successful + */ + public static function checkConnection($server, $user, $pwd, $db, $new_db_link = true, $engine = null, $timeout = 5) + { + return call_user_func_array(array(Db::getClass(), 'tryToConnect'), array($server, $user, $pwd, $db, $new_db_link, $engine, $timeout)); + } - /** - * Try a connection to the database and set names to UTF-8 - * - * @param string $server Server address - * @param string $user Login for database connection - * @param string $pwd Password for database connection - * @return bool - */ - public static function checkEncoding($server, $user, $pwd) - { - return call_user_func_array(array(Db::getClass(), 'tryUTF8'), array($server, $user, $pwd)); - } + /** + * Try a connection to the database and set names to UTF-8 + * + * @param string $server Server address + * @param string $user Login for database connection + * @param string $pwd Password for database connection + * @return bool + */ + public static function checkEncoding($server, $user, $pwd) + { + return call_user_func_array(array(Db::getClass(), 'tryUTF8'), array($server, $user, $pwd)); + } - /** - * Try a connection to the database and check if at least one table with same prefix exists - * - * @param string $server Server address - * @param string $user Login for database connection - * @param string $pwd Password for database connection - * @param string $db Database name - * @param string $prefix Tables prefix - * @return bool - */ - public static function hasTableWithSamePrefix($server, $user, $pwd, $db, $prefix) - { - return call_user_func_array(array(Db::getClass(), 'hasTableWithSamePrefix'), array($server, $user, $pwd, $db, $prefix)); - } + /** + * Try a connection to the database and check if at least one table with same prefix exists + * + * @param string $server Server address + * @param string $user Login for database connection + * @param string $pwd Password for database connection + * @param string $db Database name + * @param string $prefix Tables prefix + * @return bool + */ + public static function hasTableWithSamePrefix($server, $user, $pwd, $db, $prefix) + { + return call_user_func_array(array(Db::getClass(), 'hasTableWithSamePrefix'), array($server, $user, $pwd, $db, $prefix)); + } - /** - * Tries to connect to the database and create a table (checking creation privileges) - * - * @param string $server - * @param string $user - * @param string $pwd - * @param string $db - * @param string $prefix - * @param string|null $engine Table engine - * @return bool|string True, false or error - */ - public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine = null) - { - return call_user_func_array(array(Db::getClass(), 'checkCreatePrivilege'), array($server, $user, $pwd, $db, $prefix, $engine)); - } + /** + * Tries to connect to the database and create a table (checking creation privileges) + * + * @param string $server + * @param string $user + * @param string $pwd + * @param string $db + * @param string $prefix + * @param string|null $engine Table engine + * @return bool|string True, false or error + */ + public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine = null) + { + return call_user_func_array(array(Db::getClass(), 'checkCreatePrivilege'), array($server, $user, $pwd, $db, $prefix, $engine)); + } - /** - * Checks if auto increment value and offset is 1 - * - * @param string $server - * @param string $user - * @param string $pwd - * @return bool - */ - public static function checkAutoIncrement($server, $user, $pwd) - { - return call_user_func_array(array(Db::getClass(), 'checkAutoIncrement'), array($server, $user, $pwd)); - } + /** + * Checks if auto increment value and offset is 1 + * + * @param string $server + * @param string $user + * @param string $pwd + * @return bool + */ + public static function checkAutoIncrement($server, $user, $pwd) + { + return call_user_func_array(array(Db::getClass(), 'checkAutoIncrement'), array($server, $user, $pwd)); + } - /** - * Executes a query - * - * @deprecated 1.5.0.1 - * @param string|DbQuery $sql - * @param bool $use_cache - * @return array|bool|mysqli_result|PDOStatement|resource - * @throws PrestaShopDatabaseException - */ - public static function s($sql, $use_cache = true) - { - Tools::displayAsDeprecated(); - return Db::getInstance()->executeS($sql, true, $use_cache); - } + /** + * Executes a query + * + * @deprecated 1.5.0.1 + * @param string|DbQuery $sql + * @param bool $use_cache + * @return array|bool|mysqli_result|PDOStatement|resource + * @throws PrestaShopDatabaseException + */ + public static function s($sql, $use_cache = true) + { + Tools::displayAsDeprecated(); + return Db::getInstance()->executeS($sql, true, $use_cache); + } - /** - * Executes a query - * - * @deprecated 1.5.0.1 - * @param $sql - * @param int $use_cache - * @return array|bool|mysqli_result|PDOStatement|resource - */ - public static function ps($sql, $use_cache = 1) - { - Tools::displayAsDeprecated(); - $ret = Db::s($sql, $use_cache); - return $ret; - } + /** + * Executes a query + * + * @deprecated 1.5.0.1 + * @param $sql + * @param int $use_cache + * @return array|bool|mysqli_result|PDOStatement|resource + */ + public static function ps($sql, $use_cache = 1) + { + Tools::displayAsDeprecated(); + $ret = Db::s($sql, $use_cache); + return $ret; + } - /** - * Executes a query and kills process (dies) - * - * @deprecated 1.5.0.1 - * @param $sql - * @param int $use_cache - */ - public static function ds($sql, $use_cache = 1) - { - Tools::displayAsDeprecated(); - Db::s($sql, $use_cache); - die(); - } + /** + * Executes a query and kills process (dies) + * + * @deprecated 1.5.0.1 + * @param $sql + * @param int $use_cache + */ + public static function ds($sql, $use_cache = 1) + { + Tools::displayAsDeprecated(); + Db::s($sql, $use_cache); + die(); + } - /** - * Get used link instance - * - * @return PDO|mysqli|resource Resource - */ - public function getLink() - { - return $this->link; - } + /** + * Get used link instance + * + * @return PDO|mysqli|resource Resource + */ + public function getLink() + { + return $this->link; + } } diff --git a/classes/db/DbMySQLi.php b/classes/db/DbMySQLi.php index ead51dd2..5c35008f 100644 --- a/classes/db/DbMySQLi.php +++ b/classes/db/DbMySQLi.php @@ -31,371 +31,386 @@ */ class DbMySQLiCore extends Db { - /** @var mysqli */ - protected $link; + /** @var mysqli */ + protected $link; - /* @var mysqli_result */ - protected $result; + /* @var mysqli_result */ + protected $result; - /** - * Tries to connect to the database - * - * @see DbCore::connect() - * @return mysqli - * @throws PrestaShopDatabaseException - */ - public function connect() - { - if (strpos($this->server, ':') !== false) - { - list($server, $port) = explode(':', $this->server); - $this->link = @new mysqli($server, $this->user, $this->password, $this->database, $port); - } - else - $this->link = @new mysqli($this->server, $this->user, $this->password, $this->database); + /** + * Tries to connect to the database + * + * @see DbCore::connect() + * @return mysqli + * @throws PrestaShopDatabaseException + */ + public function connect() + { + if (strpos($this->server, ':') !== false) { + list($server, $port) = explode(':', $this->server); + $this->link = @new mysqli($server, $this->user, $this->password, $this->database, $port); + } else { + $this->link = @new mysqli($this->server, $this->user, $this->password, $this->database); + } - // Do not use object way for error because this work bad before PHP 5.2.9 - if (mysqli_connect_error()) - throw new PrestaShopDatabaseException(sprintf(Tools::displayError('Link to database cannot be established: %s'), mysqli_connect_error())); + // Do not use object way for error because this work bad before PHP 5.2.9 + if (mysqli_connect_error()) { + throw new PrestaShopDatabaseException(sprintf(Tools::displayError('Link to database cannot be established: %s'), mysqli_connect_error())); + } - // UTF-8 support - if (!$this->link->query('SET NAMES \'utf8\'')) - throw new PrestaShopDatabaseException(Tools::displayError('PrestaShop Fatal error: no utf-8 support. Please check your server configuration.')); + // UTF-8 support + if (!$this->link->query('SET NAMES \'utf8\'')) { + throw new PrestaShopDatabaseException(Tools::displayError('PrestaShop Fatal error: no utf-8 support. Please check your server configuration.')); + } - return $this->link; - } + return $this->link; + } - /** - * Tries to connect and create a new database - * - * @param string $host - * @param string|null $user - * @param string|null $password - * @param string|null $database - * @param bool $dropit If true, drops the created database. - * @return bool|mysqli_result - */ - public static function createDatabase($host, $user = null, $password = null, $database = null, $dropit = false) - { - if (strpos($host, ':') !== false) - { - list($host, $port) = explode(':', $host); - $link = @new mysqli($host, $user, $password, null, $port); - } - else - $link = @new mysqli($host, $user, $password); - $success = $link->query('CREATE DATABASE `'.str_replace('`', '\\`', $database).'`'); - if ($dropit && ($link->query('DROP DATABASE `'.str_replace('`', '\\`', $database).'`') !== false)) - return true; - return $success; - } + /** + * Tries to connect and create a new database + * + * @param string $host + * @param string|null $user + * @param string|null $password + * @param string|null $database + * @param bool $dropit If true, drops the created database. + * @return bool|mysqli_result + */ + public static function createDatabase($host, $user = null, $password = null, $database = null, $dropit = false) + { + if (strpos($host, ':') !== false) { + list($host, $port) = explode(':', $host); + $link = @new mysqli($host, $user, $password, null, $port); + } else { + $link = @new mysqli($host, $user, $password); + } + $success = $link->query('CREATE DATABASE `'.str_replace('`', '\\`', $database).'`'); + if ($dropit && ($link->query('DROP DATABASE `'.str_replace('`', '\\`', $database).'`') !== false)) { + return true; + } + return $success; + } - /** - * Destroys the database connection link - * - * @see DbCore::disconnect() - */ - public function disconnect() - { - @$this->link->close(); - } + /** + * Destroys the database connection link + * + * @see DbCore::disconnect() + */ + public function disconnect() + { + @$this->link->close(); + } - /** - * Executes an SQL statement, returning a result set as a mysqli_result object or true/false. - * - * @see DbCore::_query() - * @param string $sql - * @return bool|mysqli_result - */ - protected function _query($sql) - { - return $this->link->query($sql); - } + /** + * Executes an SQL statement, returning a result set as a mysqli_result object or true/false. + * + * @see DbCore::_query() + * @param string $sql + * @return bool|mysqli_result + */ + protected function _query($sql) + { + return $this->link->query($sql); + } - /** - * Returns the next row from the result set. - * - * @see DbCore::nextRow() - * @param bool|mysqli_result $result - * @return array|bool - */ - public function nextRow($result = false) - { - if (!$result) - $result = $this->result; + /** + * Returns the next row from the result set. + * + * @see DbCore::nextRow() + * @param bool|mysqli_result $result + * @return array|bool + */ + public function nextRow($result = false) + { + if (!$result) { + $result = $this->result; + } - if (!is_object($result)) - return false; + if (!is_object($result)) { + return false; + } - return $result->fetch_assoc(); - } + return $result->fetch_assoc(); + } - /** - * Returns all rows from the result set. - * - * @see DbCore::getAll() - * @param bool|mysqli_result $result - * @return array|false - */ - protected function getAll($result = false) - { - if (!$result) - $result = $this->result; + /** + * Returns all rows from the result set. + * + * @see DbCore::getAll() + * @param bool|mysqli_result $result + * @return array|false + */ + protected function getAll($result = false) + { + if (!$result) { + $result = $this->result; + } - if (!is_object($result)) - return false; + if (!is_object($result)) { + return false; + } - if (method_exists($result, 'fetch_all')) - return $result->fetch_all(MYSQLI_ASSOC); - else - { - $ret = array(); + if (method_exists($result, 'fetch_all')) { + return $result->fetch_all(MYSQLI_ASSOC); + } else { + $ret = array(); - while ($row = $this->nextRow($result)) - $ret[] = $row; + while ($row = $this->nextRow($result)) { + $ret[] = $row; + } - return $ret; - } - } + return $ret; + } + } - /** - * Returns row count from the result set. - * - * @see DbCore::_numRows() - * @param bool|mysqli_result $result - * @return int - */ - protected function _numRows($result) - { - return $result->num_rows; - } + /** + * Returns row count from the result set. + * + * @see DbCore::_numRows() + * @param bool|mysqli_result $result + * @return int + */ + protected function _numRows($result) + { + return $result->num_rows; + } - /** - * Returns ID of the last inserted row. - * - * @see DbCore::Insert_ID() - * @return string|int - */ - public function Insert_ID() - { - return $this->link->insert_id; - } + /** + * Returns ID of the last inserted row. + * + * @see DbCore::Insert_ID() + * @return string|int + */ + public function Insert_ID() + { + return $this->link->insert_id; + } - /** - * Return the number of rows affected by the last SQL query. - * - * @see DbCore::Affected_Rows() - * @return int - */ - public function Affected_Rows() - { - return $this->link->affected_rows; - } + /** + * Return the number of rows affected by the last SQL query. + * + * @see DbCore::Affected_Rows() + * @return int + */ + public function Affected_Rows() + { + return $this->link->affected_rows; + } - /** - * Returns error message. - * - * @see DbCore::getMsgError() - * @param bool $query - * @return string - */ - public function getMsgError($query = false) - { - return $this->link->error; - } + /** + * Returns error message. + * + * @see DbCore::getMsgError() + * @param bool $query + * @return string + */ + public function getMsgError($query = false) + { + return $this->link->error; + } - /** - * Returns error code. - * - * @see DbCore::getNumberError() - * @return int - */ - public function getNumberError() - { - return $this->link->errno; - } + /** + * Returns error code. + * + * @see DbCore::getNumberError() + * @return int + */ + public function getNumberError() + { + return $this->link->errno; + } - /** - * Returns database server version. - * - * @see DbCore::getVersion() - * @return string - */ - public function getVersion() - { - return $this->getValue('SELECT VERSION()'); - } + /** + * Returns database server version. + * + * @see DbCore::getVersion() + * @return string + */ + public function getVersion() + { + return $this->getValue('SELECT VERSION()'); + } - /** - * Escapes illegal characters in a string. - * - * @see DbCore::_escape() - * @param string $str - * @return string - */ - public function _escape($str) - { - return $this->link->real_escape_string($str); - } + /** + * Escapes illegal characters in a string. + * + * @see DbCore::_escape() + * @param string $str + * @return string + */ + public function _escape($str) + { + return $this->link->real_escape_string($str); + } - /** - * Switches to a different database. - * - * @see DbCore::set_db() - * @param string $db_name - * @return bool - */ - public function set_db($db_name) - { - return $this->link->query('USE `'.bqSQL($db_name).'`'); - } + /** + * Switches to a different database. + * + * @see DbCore::set_db() + * @param string $db_name + * @return bool + */ + public function set_db($db_name) + { + return $this->link->query('USE `'.bqSQL($db_name).'`'); + } - /** - * Try a connection to the database and check if at least one table with same prefix exists - * - * @see Db::hasTableWithSamePrefix() - * @param string $server Server address - * @param string $user Login for database connection - * @param string $pwd Password for database connection - * @param string $db Database name - * @param string $prefix Tables prefix - * @return bool - */ - public static function hasTableWithSamePrefix($server, $user, $pwd, $db, $prefix) - { - $link = @new mysqli($server, $user, $pwd, $db); - if (mysqli_connect_error()) - return false; + /** + * Try a connection to the database and check if at least one table with same prefix exists + * + * @see Db::hasTableWithSamePrefix() + * @param string $server Server address + * @param string $user Login for database connection + * @param string $pwd Password for database connection + * @param string $db Database name + * @param string $prefix Tables prefix + * @return bool + */ + public static function hasTableWithSamePrefix($server, $user, $pwd, $db, $prefix) + { + $link = @new mysqli($server, $user, $pwd, $db); + if (mysqli_connect_error()) { + return false; + } - $sql = 'SHOW TABLES LIKE \''.$prefix.'%\''; - $result = $link->query($sql); - return (bool)$result->fetch_assoc(); - } + $sql = 'SHOW TABLES LIKE \''.$prefix.'%\''; + $result = $link->query($sql); + return (bool)$result->fetch_assoc(); + } - /** - * Try a connection to the database - * - * @see Db::checkConnection() - * @param string $server Server address - * @param string $user Login for database connection - * @param string $pwd Password for database connection - * @param string $db Database name - * @param bool $newDbLink - * @param string|bool $engine - * @param int $timeout - * @return int Error code or 0 if connection was successful - */ - public static function tryToConnect($server, $user, $pwd, $db, $new_db_link = true, $engine = null, $timeout = 5) - { - $link = mysqli_init(); - if (!$link) - return -1; + /** + * Try a connection to the database + * + * @see Db::checkConnection() + * @param string $server Server address + * @param string $user Login for database connection + * @param string $pwd Password for database connection + * @param string $db Database name + * @param bool $newDbLink + * @param string|bool $engine + * @param int $timeout + * @return int Error code or 0 if connection was successful + */ + public static function tryToConnect($server, $user, $pwd, $db, $new_db_link = true, $engine = null, $timeout = 5) + { + $link = mysqli_init(); + if (!$link) { + return -1; + } - if (!$link->options(MYSQLI_OPT_CONNECT_TIMEOUT, $timeout)) - return 1; + if (!$link->options(MYSQLI_OPT_CONNECT_TIMEOUT, $timeout)) { + return 1; + } - // There is an @ because mysqli throw a warning when the database does not exists - if (!@$link->real_connect($server, $user, $pwd, $db)) - return (mysqli_connect_errno() == 1049) ? 2 : 1; + // There is an @ because mysqli throw a warning when the database does not exists + if (!@$link->real_connect($server, $user, $pwd, $db)) { + return (mysqli_connect_errno() == 1049) ? 2 : 1; + } - $link->close(); - return 0; - } + $link->close(); + return 0; + } - /** - * Selects best table engine. - * - * @return string - */ - public function getBestEngine() - { - $value = 'InnoDB'; + /** + * Selects best table engine. + * + * @return string + */ + public function getBestEngine() + { + $value = 'InnoDB'; - $sql = 'SHOW VARIABLES WHERE Variable_name = \'have_innodb\''; - $result = $this->link->query($sql); - if (!$result) - $value = 'MyISAM'; - $row = $result->fetch_assoc(); - if (!$row || strtolower($row['Value']) != 'yes') - $value = 'MyISAM'; + $sql = 'SHOW VARIABLES WHERE Variable_name = \'have_innodb\''; + $result = $this->link->query($sql); + if (!$result) { + $value = 'MyISAM'; + } + $row = $result->fetch_assoc(); + if (!$row || strtolower($row['Value']) != 'yes') { + $value = 'MyISAM'; + } - /* MySQL >= 5.6 */ - $sql = 'SHOW ENGINES'; - $result = $this->link->query($sql); - while ($row = $result->fetch_assoc()) - if ($row['Engine'] == 'InnoDB') - { - if (in_array($row['Support'], array('DEFAULT', 'YES'))) - $value = 'InnoDB'; - break; - } + /* MySQL >= 5.6 */ + $sql = 'SHOW ENGINES'; + $result = $this->link->query($sql); + while ($row = $result->fetch_assoc()) { + if ($row['Engine'] == 'InnoDB') { + if (in_array($row['Support'], array('DEFAULT', 'YES'))) { + $value = 'InnoDB'; + } + break; + } + } - return $value; - } + return $value; + } - /** - * Tries to connect to the database and create a table (checking creation privileges) - * - * @param string $server - * @param string $user - * @param string $pwd - * @param string $db - * @param string $prefix - * @param string|null $engine Table engine - * @return bool|string True, false or error - */ - public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine = null) - { - $link = @new mysqli($server, $user, $pwd, $db); - if (mysqli_connect_error()) - return false; + /** + * Tries to connect to the database and create a table (checking creation privileges) + * + * @param string $server + * @param string $user + * @param string $pwd + * @param string $db + * @param string $prefix + * @param string|null $engine Table engine + * @return bool|string True, false or error + */ + public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine = null) + { + $link = @new mysqli($server, $user, $pwd, $db); + if (mysqli_connect_error()) { + return false; + } - if ($engine === null) - $engine = 'MyISAM'; + if ($engine === null) { + $engine = 'MyISAM'; + } - $result = $link->query(' + $result = $link->query(' CREATE TABLE `'.$prefix.'test` ( `test` tinyint(1) unsigned NOT NULL ) ENGINE='.$engine); - if (!$result) - return $link->error; + if (!$result) { + return $link->error; + } - $link->query('DROP TABLE `'.$prefix.'test`'); - return true; - } + $link->query('DROP TABLE `'.$prefix.'test`'); + return true; + } - /** - * Try a connection to the database and set names to UTF-8 - * - * @see Db::checkEncoding() - * @param string $server Server address - * @param string $user Login for database connection - * @param string $pwd Password for database connection - * @return bool - */ - public static function tryUTF8($server, $user, $pwd) - { - $link = @new mysqli($server, $user, $pwd); - $ret = $link->query("SET NAMES 'UTF8'"); - $link->close(); - return $ret; - } + /** + * Try a connection to the database and set names to UTF-8 + * + * @see Db::checkEncoding() + * @param string $server Server address + * @param string $user Login for database connection + * @param string $pwd Password for database connection + * @return bool + */ + public static function tryUTF8($server, $user, $pwd) + { + $link = @new mysqli($server, $user, $pwd); + $ret = $link->query("SET NAMES 'UTF8'"); + $link->close(); + return $ret; + } - /** - * Checks if auto increment value and offset is 1 - * - * @param string $server - * @param string $user - * @param string $pwd - * @return bool - */ - public static function checkAutoIncrement($server, $user, $pwd) - { - $link = @new mysqli($server, $user, $pwd); - $ret = (bool)(($result = $link->query('SELECT @@auto_increment_increment as aii')) && ($row = $result->fetch_assoc()) && $row['aii'] == 1); - $ret &= (bool)(($result = $link->query('SELECT @@auto_increment_offset as aio')) && ($row = $result->fetch_assoc()) && $row['aio'] == 1); - $link->close(); - return $ret; - } + /** + * Checks if auto increment value and offset is 1 + * + * @param string $server + * @param string $user + * @param string $pwd + * @return bool + */ + public static function checkAutoIncrement($server, $user, $pwd) + { + $link = @new mysqli($server, $user, $pwd); + $ret = (bool)(($result = $link->query('SELECT @@auto_increment_increment as aii')) && ($row = $result->fetch_assoc()) && $row['aii'] == 1); + $ret &= (bool)(($result = $link->query('SELECT @@auto_increment_offset as aio')) && ($row = $result->fetch_assoc()) && $row['aio'] == 1); + $link->close(); + return $ret; + } } diff --git a/classes/db/DbPDO.php b/classes/db/DbPDO.php index 67016604..b9c0aa23 100644 --- a/classes/db/DbPDO.php +++ b/classes/db/DbPDO.php @@ -31,390 +31,401 @@ */ class DbPDOCore extends Db { - /** @var PDO */ - protected $link; + /** @var PDO */ + protected $link; - /* @var PDOStatement */ - protected $result; + /* @var PDOStatement */ + protected $result; - /** - * Returns a new PDO object (database link) - * - * @param string $host - * @param string $user - * @param string $password - * @param string $dbname - * @param int $timeout - * @return PDO - */ - protected static function _getPDO($host, $user, $password, $dbname, $timeout = 5) - { - $dsn = 'mysql:'; - if ($dbname) - $dsn .= 'dbname='.$dbname.';'; - if (preg_match('/^(.*):([0-9]+)$/', $host, $matches)) - $dsn .= 'host='.$matches[1].';port='.$matches[2]; - elseif (preg_match('#^.*:(/.*)$#', $host, $matches)) - $dsn .= 'unix_socket='.$matches[1]; - else - $dsn .= 'host='.$host; + /** + * Returns a new PDO object (database link) + * + * @param string $host + * @param string $user + * @param string $password + * @param string $dbname + * @param int $timeout + * @return PDO + */ + protected static function _getPDO($host, $user, $password, $dbname, $timeout = 5) + { + $dsn = 'mysql:'; + if ($dbname) { + $dsn .= 'dbname='.$dbname.';'; + } + if (preg_match('/^(.*):([0-9]+)$/', $host, $matches)) { + $dsn .= 'host='.$matches[1].';port='.$matches[2]; + } elseif (preg_match('#^.*:(/.*)$#', $host, $matches)) { + $dsn .= 'unix_socket='.$matches[1]; + } else { + $dsn .= 'host='.$host; + } - return new PDO($dsn, $user, $password, array(PDO::ATTR_TIMEOUT => $timeout, PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true)); - } + return new PDO($dsn, $user, $password, array(PDO::ATTR_TIMEOUT => $timeout, PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true)); + } - /** - * Tries to connect and create a new database - * - * @param string $host - * @param string $user - * @param string $password - * @param string $dbname - * @param bool $dropit If true, drops the created database. - * @return bool|int - */ - public static function createDatabase($host, $user, $password, $dbname, $dropit = false) - { - try { - $link = DbPDO::_getPDO($host, $user, $password, false); - $success = $link->exec('CREATE DATABASE `'.str_replace('`', '\\`', $dbname).'`'); - if ($dropit && ($link->exec('DROP DATABASE `'.str_replace('`', '\\`', $dbname).'`') !== false)) - return true; - } catch (PDOException $e) { - return false; - } - return $success; - } + /** + * Tries to connect and create a new database + * + * @param string $host + * @param string $user + * @param string $password + * @param string $dbname + * @param bool $dropit If true, drops the created database. + * @return bool|int + */ + public static function createDatabase($host, $user, $password, $dbname, $dropit = false) + { + try { + $link = DbPDO::_getPDO($host, $user, $password, false); + $success = $link->exec('CREATE DATABASE `'.str_replace('`', '\\`', $dbname).'`'); + if ($dropit && ($link->exec('DROP DATABASE `'.str_replace('`', '\\`', $dbname).'`') !== false)) { + return true; + } + } catch (PDOException $e) { + return false; + } + return $success; + } - /** - * Tries to connect to the database - * - * @see DbCore::connect() - * @return PDO - */ - public function connect() - { - try { - $this->link = $this->_getPDO($this->server, $this->user, $this->password, $this->database, 5); - } catch (PDOException $e) { - die(sprintf(Tools::displayError('Link to database cannot be established: %s'), utf8_encode($e->getMessage()))); - } + /** + * Tries to connect to the database + * + * @see DbCore::connect() + * @return PDO + */ + public function connect() + { + try { + $this->link = $this->_getPDO($this->server, $this->user, $this->password, $this->database, 5); + } catch (PDOException $e) { + die(sprintf(Tools::displayError('Link to database cannot be established: %s'), utf8_encode($e->getMessage()))); + } - // UTF-8 support - if ($this->link->exec('SET NAMES \'utf8\'') === false) - die(Tools::displayError('PrestaShop Fatal error: no utf-8 support. Please check your server configuration.')); + // UTF-8 support + if ($this->link->exec('SET NAMES \'utf8\'') === false) { + die(Tools::displayError('PrestaShop Fatal error: no utf-8 support. Please check your server configuration.')); + } - return $this->link; - } + return $this->link; + } - /** - * Destroys the database connection link - * - * @see DbCore::disconnect() - */ - public function disconnect() - { - unset($this->link); - } + /** + * Destroys the database connection link + * + * @see DbCore::disconnect() + */ + public function disconnect() + { + unset($this->link); + } - /** - * Executes an SQL statement, returning a result set as a PDOStatement object or true/false. - * - * @see DbCore::_query() - * @param string $sql - * @return PDOStatement - */ - protected function _query($sql) - { - return $this->link->query($sql); - } + /** + * Executes an SQL statement, returning a result set as a PDOStatement object or true/false. + * + * @see DbCore::_query() + * @param string $sql + * @return PDOStatement + */ + protected function _query($sql) + { + return $this->link->query($sql); + } - /** - * Returns the next row from the result set. - * - * @see DbCore::nextRow() - * @param bool $result - * @return array|false|null - */ - public function nextRow($result = false) - { - if (!$result) - $result = $this->result; + /** + * Returns the next row from the result set. + * + * @see DbCore::nextRow() + * @param bool $result + * @return array|false|null + */ + public function nextRow($result = false) + { + if (!$result) { + $result = $this->result; + } - if (!is_object($result)) - return false; + if (!is_object($result)) { + return false; + } - return $result->fetch(PDO::FETCH_ASSOC); - } + return $result->fetch(PDO::FETCH_ASSOC); + } - /** - * Returns all rows from the result set. - * - * @see DbCore::getAll() - * @param bool $result - * @return array|false|null - */ - protected function getAll($result = false) - { - if (!$result) - $result = $this->result; + /** + * Returns all rows from the result set. + * + * @see DbCore::getAll() + * @param bool $result + * @return array|false|null + */ + protected function getAll($result = false) + { + if (!$result) { + $result = $this->result; + } - if (!is_object($result)) - return false; + if (!is_object($result)) { + return false; + } - return $result->fetchAll(PDO::FETCH_ASSOC); - } + return $result->fetchAll(PDO::FETCH_ASSOC); + } - /** - * Returns row count from the result set. - * - * @see DbCore::_numRows() - * @param PDOStatement $result - * @return int - */ - protected function _numRows($result) - { - return $result->rowCount(); - } + /** + * Returns row count from the result set. + * + * @see DbCore::_numRows() + * @param PDOStatement $result + * @return int + */ + protected function _numRows($result) + { + return $result->rowCount(); + } - /** - * Returns ID of the last inserted row. - * - * @see DbCore::Insert_ID() - * @return string|int - */ - public function Insert_ID() - { - return $this->link->lastInsertId(); - } + /** + * Returns ID of the last inserted row. + * + * @see DbCore::Insert_ID() + * @return string|int + */ + public function Insert_ID() + { + return $this->link->lastInsertId(); + } - /** - * Return the number of rows affected by the last SQL query. - * - * @see DbCore::Affected_Rows() - * @return int - */ - public function Affected_Rows() - { - return $this->result->rowCount(); - } + /** + * Return the number of rows affected by the last SQL query. + * + * @see DbCore::Affected_Rows() + * @return int + */ + public function Affected_Rows() + { + return $this->result->rowCount(); + } - /** - * Returns error message. - * - * @see DbCore::getMsgError() - * @param bool $query - * @return string - */ - public function getMsgError($query = false) - { - $error = $this->link->errorInfo(); - return ($error[0] == '00000') ? '' : $error[2]; - } + /** + * Returns error message. + * + * @see DbCore::getMsgError() + * @param bool $query + * @return string + */ + public function getMsgError($query = false) + { + $error = $this->link->errorInfo(); + return ($error[0] == '00000') ? '' : $error[2]; + } - /** - * Returns error code. - * - * @see DbCore::getNumberError() - * @return int - */ - public function getNumberError() - { - $error = $this->link->errorInfo(); - return isset($error[1]) ? $error[1] : 0; - } + /** + * Returns error code. + * + * @see DbCore::getNumberError() + * @return int + */ + public function getNumberError() + { + $error = $this->link->errorInfo(); + return isset($error[1]) ? $error[1] : 0; + } - /** - * Returns database server version. - * - * @see DbCore::getVersion() - * @return string - */ - public function getVersion() - { - return $this->getValue('SELECT VERSION()'); - } + /** + * Returns database server version. + * + * @see DbCore::getVersion() + * @return string + */ + public function getVersion() + { + return $this->getValue('SELECT VERSION()'); + } - /** - * Escapes illegal characters in a string. - * - * @see DbCore::_escape() - * @param string $str - * @return string - */ - public function _escape($str) - { - $search = array("\\", "\0", "\n", "\r", "\x1a", "'", '"'); - $replace = array("\\\\", "\\0", "\\n", "\\r", "\Z", "\'", '\"'); - return str_replace($search, $replace, $str); - } + /** + * Escapes illegal characters in a string. + * + * @see DbCore::_escape() + * @param string $str + * @return string + */ + public function _escape($str) + { + $search = array("\\", "\0", "\n", "\r", "\x1a", "'", '"'); + $replace = array("\\\\", "\\0", "\\n", "\\r", "\Z", "\'", '\"'); + return str_replace($search, $replace, $str); + } - /** - * Switches to a different database. - * - * @see DbCore::set_db() - * @param string $db_name - * @return int - */ - public function set_db($db_name) - { - return $this->link->exec('USE '.pSQL($db_name)); - } + /** + * Switches to a different database. + * + * @see DbCore::set_db() + * @param string $db_name + * @return int + */ + public function set_db($db_name) + { + return $this->link->exec('USE '.pSQL($db_name)); + } - /** - * Try a connection to the database and check if at least one table with same prefix exists - * - * @see Db::hasTableWithSamePrefix() - * @param string $server Server address - * @param string $user Login for database connection - * @param string $pwd Password for database connection - * @param string $db Database name - * @param string $prefix Tables prefix - * @return bool - */ - public static function hasTableWithSamePrefix($server, $user, $pwd, $db, $prefix) - { - try { - $link = DbPDO::_getPDO($server, $user, $pwd, $db, 5); - } catch (PDOException $e) { - return false; - } + /** + * Try a connection to the database and check if at least one table with same prefix exists + * + * @see Db::hasTableWithSamePrefix() + * @param string $server Server address + * @param string $user Login for database connection + * @param string $pwd Password for database connection + * @param string $db Database name + * @param string $prefix Tables prefix + * @return bool + */ + public static function hasTableWithSamePrefix($server, $user, $pwd, $db, $prefix) + { + try { + $link = DbPDO::_getPDO($server, $user, $pwd, $db, 5); + } catch (PDOException $e) { + return false; + } - $sql = 'SHOW TABLES LIKE \''.$prefix.'%\''; - $result = $link->query($sql); - return (bool)$result->fetch(); - } + $sql = 'SHOW TABLES LIKE \''.$prefix.'%\''; + $result = $link->query($sql); + return (bool)$result->fetch(); + } - /** - * Tries to connect to the database and create a table (checking creation privileges) - * - * @param string $server - * @param string $user - * @param string $pwd - * @param string $db - * @param string $prefix - * @param string|null $engine Table engine - * @return bool|string True, false or error - */ - public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine = null) - { - try { - $link = DbPDO::_getPDO($server, $user, $pwd, $db, 5); - } catch (PDOException $e) { - return false; - } + /** + * Tries to connect to the database and create a table (checking creation privileges) + * + * @param string $server + * @param string $user + * @param string $pwd + * @param string $db + * @param string $prefix + * @param string|null $engine Table engine + * @return bool|string True, false or error + */ + public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine = null) + { + try { + $link = DbPDO::_getPDO($server, $user, $pwd, $db, 5); + } catch (PDOException $e) { + return false; + } - if ($engine === null) - $engine = 'MyISAM'; + if ($engine === null) { + $engine = 'MyISAM'; + } - $result = $link->query(' + $result = $link->query(' CREATE TABLE `'.$prefix.'test` ( `test` tinyint(1) unsigned NOT NULL ) ENGINE='.$engine); - if (!$result) - { - $error = $link->errorInfo(); - return $error[2]; - } - $link->query('DROP TABLE `'.$prefix.'test`'); - return true; - } + if (!$result) { + $error = $link->errorInfo(); + return $error[2]; + } + $link->query('DROP TABLE `'.$prefix.'test`'); + return true; + } - /** - * Try a connection to the database - * - * @see Db::checkConnection() - * @param string $server Server address - * @param string $user Login for database connection - * @param string $pwd Password for database connection - * @param string $db Database name - * @param bool $newDbLink - * @param string|bool $engine - * @param int $timeout - * @return int Error code or 0 if connection was successful - */ - public static function tryToConnect($server, $user, $pwd, $db, $new_db_link = true, $engine = null, $timeout = 5) - { - try { - $link = DbPDO::_getPDO($server, $user, $pwd, $db, $timeout); - } catch (PDOException $e) { - // hhvm wrongly reports error status 42000 when the database does not exist - might change in the future - return ($e->getCode() == 1049 || (defined('HHVM_VERSION') && $e->getCode() == 42000)) ? 2 : 1; - } - unset($link); - return 0; - } + /** + * Try a connection to the database + * + * @see Db::checkConnection() + * @param string $server Server address + * @param string $user Login for database connection + * @param string $pwd Password for database connection + * @param string $db Database name + * @param bool $newDbLink + * @param string|bool $engine + * @param int $timeout + * @return int Error code or 0 if connection was successful + */ + public static function tryToConnect($server, $user, $pwd, $db, $new_db_link = true, $engine = null, $timeout = 5) + { + try { + $link = DbPDO::_getPDO($server, $user, $pwd, $db, $timeout); + } catch (PDOException $e) { + // hhvm wrongly reports error status 42000 when the database does not exist - might change in the future + return ($e->getCode() == 1049 || (defined('HHVM_VERSION') && $e->getCode() == 42000)) ? 2 : 1; + } + unset($link); + return 0; + } - /** - * Selects best table engine. - * - * @return string - */ - public function getBestEngine() - { - $value = 'InnoDB'; + /** + * Selects best table engine. + * + * @return string + */ + public function getBestEngine() + { + $value = 'InnoDB'; - $sql = 'SHOW VARIABLES WHERE Variable_name = \'have_innodb\''; - $result = $this->link->query($sql); - if (!$result) - $value = 'MyISAM'; - $row = $result->fetch(); - if (!$row || strtolower($row['Value']) != 'yes') - $value = 'MyISAM'; + $sql = 'SHOW VARIABLES WHERE Variable_name = \'have_innodb\''; + $result = $this->link->query($sql); + if (!$result) { + $value = 'MyISAM'; + } + $row = $result->fetch(); + if (!$row || strtolower($row['Value']) != 'yes') { + $value = 'MyISAM'; + } - /* MySQL >= 5.6 */ - $sql = 'SHOW ENGINES'; - $result = $this->link->query($sql); - while ($row = $result->fetch()) - if ($row['Engine'] == 'InnoDB') - { - if (in_array($row['Support'], array('DEFAULT', 'YES'))) - $value = 'InnoDB'; - break; - } + /* MySQL >= 5.6 */ + $sql = 'SHOW ENGINES'; + $result = $this->link->query($sql); + while ($row = $result->fetch()) { + if ($row['Engine'] == 'InnoDB') { + if (in_array($row['Support'], array('DEFAULT', 'YES'))) { + $value = 'InnoDB'; + } + break; + } + } - return $value; - } + return $value; + } - /** - * Try a connection to the database and set names to UTF-8 - * - * @see Db::checkEncoding() - * @param string $server Server address - * @param string $user Login for database connection - * @param string $pwd Password for database connection - * @return bool - */ - public static function tryUTF8($server, $user, $pwd) - { - try { - $link = DbPDO::_getPDO($server, $user, $pwd, false, 5); - } catch (PDOException $e) { - return false; - } - $result = $link->exec('SET NAMES \'utf8\''); - unset($link); + /** + * Try a connection to the database and set names to UTF-8 + * + * @see Db::checkEncoding() + * @param string $server Server address + * @param string $user Login for database connection + * @param string $pwd Password for database connection + * @return bool + */ + public static function tryUTF8($server, $user, $pwd) + { + try { + $link = DbPDO::_getPDO($server, $user, $pwd, false, 5); + } catch (PDOException $e) { + return false; + } + $result = $link->exec('SET NAMES \'utf8\''); + unset($link); - return ($result === false) ? false : true; - } + return ($result === false) ? false : true; + } - /** - * Checks if auto increment value and offset is 1 - * - * @param string $server - * @param string $user - * @param string $pwd - * @return bool - */ - public static function checkAutoIncrement($server, $user, $pwd) - { - try { - $link = DbPDO::_getPDO($server, $user, $pwd, false, 5); - } catch (PDOException $e) { - return false; - } - $ret = (bool)(($result = $link->query('SELECT @@auto_increment_increment as aii')) && ($row = $result->fetch()) && $row['aii'] == 1); - $ret &= (bool)(($result = $link->query('SELECT @@auto_increment_offset as aio')) && ($row = $result->fetch()) && $row['aio'] == 1); - unset($link); - return $ret; - } + /** + * Checks if auto increment value and offset is 1 + * + * @param string $server + * @param string $user + * @param string $pwd + * @return bool + */ + public static function checkAutoIncrement($server, $user, $pwd) + { + try { + $link = DbPDO::_getPDO($server, $user, $pwd, false, 5); + } catch (PDOException $e) { + return false; + } + $ret = (bool)(($result = $link->query('SELECT @@auto_increment_increment as aii')) && ($row = $result->fetch()) && $row['aii'] == 1); + $ret &= (bool)(($result = $link->query('SELECT @@auto_increment_offset as aio')) && ($row = $result->fetch()) && $row['aio'] == 1); + unset($link); + return $ret; + } } diff --git a/classes/db/DbQuery.php b/classes/db/DbQuery.php index a30b143f..ac4ecfd6 100644 --- a/classes/db/DbQuery.php +++ b/classes/db/DbQuery.php @@ -31,274 +31,303 @@ */ class DbQueryCore { - /** - * List of data to build the query - * - * @var array - */ - protected $query = array( - 'type' => 'SELECT', - 'select' => array(), - 'from' => '', - 'join' => array(), - 'where' => array(), - 'group' => array(), - 'having' => array(), - 'order' => array(), - 'limit' => array('offset' => 0, 'limit' => 0), - ); + /** + * List of data to build the query + * + * @var array + */ + protected $query = array( + 'type' => 'SELECT', + 'select' => array(), + 'from' => '', + 'join' => array(), + 'where' => array(), + 'group' => array(), + 'having' => array(), + 'order' => array(), + 'limit' => array('offset' => 0, 'limit' => 0), + ); - /** - * Sets type of the query - * - * @param string $type SELECT|DELETE - * - * @return DbQuery - */ - public function type($type) - { - $types = array('SELECT', 'DELETE'); + /** + * Sets type of the query + * + * @param string $type SELECT|DELETE + * + * @return DbQuery + */ + public function type($type) + { + $types = array('SELECT', 'DELETE'); - if (!empty($type) && in_array($type, $types)) - $this->query['type'] = $type; + if (!empty($type) && in_array($type, $types)) { + $this->query['type'] = $type; + } - return $this; - } + return $this; + } - /** - * Adds fields to SELECT clause - * - * @param string $fields List of fields to concat to other fields - * - * @return DbQuery - */ - public function select($fields) - { - if (!empty($fields)) - $this->query['select'][] = $fields; + /** + * Adds fields to SELECT clause + * + * @param string $fields List of fields to concat to other fields + * + * @return DbQuery + */ + public function select($fields) + { + if (!empty($fields)) { + $this->query['select'][] = $fields; + } - return $this; - } + return $this; + } - /** - * Sets table for FROM clause - * - * @param string $table Table name - * @param string|null $alias Table alias - * - * @return DbQuery - */ - public function from($table, $alias = null) - { - if (!empty($table)) - $this->query['from'][] = '`'._DB_PREFIX_.$table.'`'.($alias ? ' '.$alias : ''); + /** + * Sets table for FROM clause + * + * @param string $table Table name + * @param string|null $alias Table alias + * + * @return DbQuery + */ + public function from($table, $alias = null) + { + if (!empty($table)) { + $this->query['from'][] = '`'._DB_PREFIX_.$table.'`'.($alias ? ' '.$alias : ''); + } - return $this; - } + return $this; + } - /** - * Adds JOIN clause - * E.g. $this->join('RIGHT JOIN '._DB_PREFIX_.'product p ON ...'); - * - * @param string $join Complete string - * - * @return DbQuery - */ - public function join($join) - { - if (!empty($join)) - $this->query['join'][] = $join; + /** + * Adds JOIN clause + * E.g. $this->join('RIGHT JOIN '._DB_PREFIX_.'product p ON ...'); + * + * @param string $join Complete string + * + * @return DbQuery + */ + public function join($join) + { + if (!empty($join)) { + $this->query['join'][] = $join; + } - return $this; - } + return $this; + } - /** - * Adds a LEFT JOIN clause - * - * @param string $table Table name (without prefix) - * @param string|null $alias Table alias - * @param string|null $on ON clause - * - * @return DbQuery - */ - public function leftJoin($table, $alias = null, $on = null) - { - return $this->join('LEFT JOIN `'._DB_PREFIX_.bqSQL($table).'`'.($alias ? ' `'.pSQL($alias).'`' : '').($on ? ' ON '.$on : '')); - } + /** + * Adds a LEFT JOIN clause + * + * @param string $table Table name (without prefix) + * @param string|null $alias Table alias + * @param string|null $on ON clause + * + * @return DbQuery + */ + public function leftJoin($table, $alias = null, $on = null) + { + return $this->join('LEFT JOIN `'._DB_PREFIX_.bqSQL($table).'`'.($alias ? ' `'.pSQL($alias).'`' : '').($on ? ' ON '.$on : '')); + } - /** - * Adds an INNER JOIN clause - * E.g. $this->innerJoin('product p ON ...') - * - * @param string $table Table name (without prefix) - * @param string|null $alias Table alias - * @param string|null $on ON clause - * - * @return DbQuery - */ - public function innerJoin($table, $alias = null, $on = null) - { - return $this->join('INNER JOIN `'._DB_PREFIX_.bqSQL($table).'`'.($alias ? ' '.pSQL($alias) : '').($on ? ' ON '.$on : '')); - } + /** + * Adds an INNER JOIN clause + * E.g. $this->innerJoin('product p ON ...') + * + * @param string $table Table name (without prefix) + * @param string|null $alias Table alias + * @param string|null $on ON clause + * + * @return DbQuery + */ + public function innerJoin($table, $alias = null, $on = null) + { + return $this->join('INNER JOIN `'._DB_PREFIX_.bqSQL($table).'`'.($alias ? ' '.pSQL($alias) : '').($on ? ' ON '.$on : '')); + } - /** - * Adds a LEFT OUTER JOIN clause - * - * @param string $table Table name (without prefix) - * @param string|null $alias Table alias - * @param string|null $on ON clause - * - * @return DbQuery - */ - public function leftOuterJoin($table, $alias = null, $on = null) - { - return $this->join('LEFT OUTER JOIN `'._DB_PREFIX_.bqSQL($table).'`'.($alias ? ' '.pSQL($alias) : '').($on ? ' ON '.$on : '')); - } + /** + * Adds a LEFT OUTER JOIN clause + * + * @param string $table Table name (without prefix) + * @param string|null $alias Table alias + * @param string|null $on ON clause + * + * @return DbQuery + */ + public function leftOuterJoin($table, $alias = null, $on = null) + { + return $this->join('LEFT OUTER JOIN `'._DB_PREFIX_.bqSQL($table).'`'.($alias ? ' '.pSQL($alias) : '').($on ? ' ON '.$on : '')); + } - /** - * Adds a NATURAL JOIN clause - * - * @param string $table Table name (without prefix) - * @param string|null $alias Table alias - * - * @return DbQuery - */ - public function naturalJoin($table, $alias = null) - { - return $this->join('NATURAL JOIN `'._DB_PREFIX_.bqSQL($table).'`'.($alias ? ' '.pSQL($alias) : '')); - } + /** + * Adds a NATURAL JOIN clause + * + * @param string $table Table name (without prefix) + * @param string|null $alias Table alias + * + * @return DbQuery + */ + public function naturalJoin($table, $alias = null) + { + return $this->join('NATURAL JOIN `'._DB_PREFIX_.bqSQL($table).'`'.($alias ? ' '.pSQL($alias) : '')); + } - /** - * Adds a restriction in WHERE clause (each restriction will be separated by AND statement) - * - * @param string $restriction - * - * @return DbQuery - */ - public function where($restriction) - { - if (!empty($restriction)) - $this->query['where'][] = $restriction; + /** + * Adds a RIGHT JOIN clause + * + * @param string $table Table name (without prefix) + * @param string|null $alias Table alias + * @param string|null $on ON clause + * + * @return DbQuery + */ + public function rightJoin($table, $alias = null, $on = null) + { + return $this->join('RIGHT JOIN `'._DB_PREFIX_.bqSQL($table).'`'.($alias ? ' `'.pSQL($alias).'`' : '').($on ? ' ON '.$on : '')); + } - return $this; - } + /** + * Adds a restriction in WHERE clause (each restriction will be separated by AND statement) + * + * @param string $restriction + * + * @return DbQuery + */ + public function where($restriction) + { + if (!empty($restriction)) { + $this->query['where'][] = $restriction; + } - /** - * Adds a restriction in HAVING clause (each restriction will be separated by AND statement) - * - * @param string $restriction - * - * @return DbQuery - */ - public function having($restriction) - { - if (!empty($restriction)) - $this->query['having'][] = $restriction; + return $this; + } - return $this; - } + /** + * Adds a restriction in HAVING clause (each restriction will be separated by AND statement) + * + * @param string $restriction + * + * @return DbQuery + */ + public function having($restriction) + { + if (!empty($restriction)) { + $this->query['having'][] = $restriction; + } - /** - * Adds an ORDER BY restriction - * - * @param string $fields List of fields to sort. E.g. $this->order('myField, b.mySecondField DESC') - * - * @return DbQuery - */ - public function orderBy($fields) - { - if (!empty($fields)) - $this->query['order'][] = $fields; + return $this; + } - return $this; - } + /** + * Adds an ORDER BY restriction + * + * @param string $fields List of fields to sort. E.g. $this->order('myField, b.mySecondField DESC') + * + * @return DbQuery + */ + public function orderBy($fields) + { + if (!empty($fields)) { + $this->query['order'][] = $fields; + } - /** - * Adds a GROUP BY restriction - * - * @param string $fields List of fields to group. E.g. $this->group('myField1, myField2') - * - * @return DbQuery - */ - public function groupBy($fields) - { - if (!empty($fields)) - $this->query['group'][] = $fields; + return $this; + } - return $this; - } + /** + * Adds a GROUP BY restriction + * + * @param string $fields List of fields to group. E.g. $this->group('myField1, myField2') + * + * @return DbQuery + */ + public function groupBy($fields) + { + if (!empty($fields)) { + $this->query['group'][] = $fields; + } - /** - * Sets query offset and limit - * - * @param int $limit - * @param int $offset - * - * @return DbQuery - */ - public function limit($limit, $offset = 0) - { - $offset = (int)$offset; - if ($offset < 0) - $offset = 0; + return $this; + } - $this->query['limit'] = array( - 'offset' => $offset, - 'limit' => (int)$limit, - ); + /** + * Sets query offset and limit + * + * @param int $limit + * @param int $offset + * + * @return DbQuery + */ + public function limit($limit, $offset = 0) + { + $offset = (int)$offset; + if ($offset < 0) { + $offset = 0; + } - return $this; - } + $this->query['limit'] = array( + 'offset' => $offset, + 'limit' => (int)$limit, + ); - /** - * Generates query and return SQL string - * - * @return string - * @throws PrestaShopException - */ - public function build() - { - if ($this->query['type'] == 'SELECT') - $sql = 'SELECT '.((($this->query['select'])) ? implode(",\n", $this->query['select']) : '*')."\n"; - else - $sql = $this->query['type'].' '; + return $this; + } - if (!$this->query['from']) - throw new PrestaShopException('Table name not set in DbQuery object. Cannot build a valid SQL query.'); + /** + * Generates query and return SQL string + * + * @return string + * @throws PrestaShopException + */ + public function build() + { + if ($this->query['type'] == 'SELECT') { + $sql = 'SELECT '.((($this->query['select'])) ? implode(",\n", $this->query['select']) : '*')."\n"; + } else { + $sql = $this->query['type'].' '; + } - $sql .= 'FROM '.implode(', ', $this->query['from'])."\n"; + if (!$this->query['from']) { + throw new PrestaShopException('Table name not set in DbQuery object. Cannot build a valid SQL query.'); + } - if ($this->query['join']) - $sql .= implode("\n", $this->query['join'])."\n"; + $sql .= 'FROM '.implode(', ', $this->query['from'])."\n"; - if ($this->query['where']) - $sql .= 'WHERE ('.implode(') AND (', $this->query['where']).")\n"; + if ($this->query['join']) { + $sql .= implode("\n", $this->query['join'])."\n"; + } - if ($this->query['group']) - $sql .= 'GROUP BY '.implode(', ', $this->query['group'])."\n"; + if ($this->query['where']) { + $sql .= 'WHERE ('.implode(') AND (', $this->query['where']).")\n"; + } - if ($this->query['having']) - $sql .= 'HAVING ('.implode(') AND (', $this->query['having']).")\n"; + if ($this->query['group']) { + $sql .= 'GROUP BY '.implode(', ', $this->query['group'])."\n"; + } - if ($this->query['order']) - $sql .= 'ORDER BY '.implode(', ', $this->query['order'])."\n"; + if ($this->query['having']) { + $sql .= 'HAVING ('.implode(') AND (', $this->query['having']).")\n"; + } - if ($this->query['limit']['limit']) - { - $limit = $this->query['limit']; - $sql .= 'LIMIT '.($limit['offset'] ? $limit['offset'].', ' : '').$limit['limit']; - } + if ($this->query['order']) { + $sql .= 'ORDER BY '.implode(', ', $this->query['order'])."\n"; + } - return $sql; - } + if ($this->query['limit']['limit']) { + $limit = $this->query['limit']; + $sql .= 'LIMIT '.($limit['offset'] ? $limit['offset'].', ' : '').$limit['limit']; + } - /** - * Converts object to string - * - * @return string - */ - public function __toString() - { - return $this->build(); - } -} \ No newline at end of file + return $sql; + } + + /** + * Converts object to string + * + * @return string + */ + public function __toString() + { + return $this->build(); + } +} diff --git a/classes/db/MySQL.php b/classes/db/MySQL.php index d065d72c..38984b41 100644 --- a/classes/db/MySQL.php +++ b/classes/db/MySQL.php @@ -29,352 +29,371 @@ */ class MySQLCore extends Db { - /** @var resource */ - protected $link; + /** @var resource */ + protected $link; - /* @var resource */ - protected $result; + /* @var resource */ + protected $result; - /** - * Tries to connect to the database - * - * @see DbCore::connect() - * @return resource - * @throws PrestaShopDatabaseException - */ - public function connect() - { - if (!defined('_PS_MYSQL_REAL_ESCAPE_STRING_')) - define('_PS_MYSQL_REAL_ESCAPE_STRING_', function_exists('mysql_real_escape_string')); + /** + * Tries to connect to the database + * + * @see DbCore::connect() + * @return resource + * @throws PrestaShopDatabaseException + */ + public function connect() + { + if (!defined('_PS_MYSQL_REAL_ESCAPE_STRING_')) { + define('_PS_MYSQL_REAL_ESCAPE_STRING_', function_exists('mysql_real_escape_string')); + } - if (!$this->link = mysql_connect($this->server, $this->user, $this->password)) - throw new PrestaShopDatabaseException(Tools::displayError('Link to database cannot be established.')); + if (!$this->link = mysql_connect($this->server, $this->user, $this->password)) { + throw new PrestaShopDatabaseException(Tools::displayError('Link to database cannot be established.')); + } - if (!$this->set_db($this->database)) - throw new PrestaShopDatabaseException(Tools::displayError('The database selection cannot be made.')); + if (!$this->set_db($this->database)) { + throw new PrestaShopDatabaseException(Tools::displayError('The database selection cannot be made.')); + } - // UTF-8 support - if (!mysql_query('SET NAMES \'utf8\'', $this->link)) - throw new PrestaShopDatabaseException(Tools::displayError('PrestaShop Fatal error: no utf-8 support. Please check your server configuration.')); + // UTF-8 support + if (!mysql_query('SET NAMES \'utf8\'', $this->link)) { + throw new PrestaShopDatabaseException(Tools::displayError('PrestaShop Fatal error: no utf-8 support. Please check your server configuration.')); + } - return $this->link; - } + return $this->link; + } - /** - * Tries to connect and create a new database - * - * @param string $host - * @param string $user - * @param string $password - * @param string $dbname - * @param bool $dropit If true, drops the created database. - * @return bool|resource - */ - public static function createDatabase($host, $user, $password, $dbname, $dropit = false) - { - $link = mysql_connect($host, $user, $password); - $success = mysql_query('CREATE DATABASE `'.str_replace('`', '\\`', $dbname).'`', $link); - if ($dropit && (mysql_query('DROP DATABASE `'.str_replace('`', '\\`', $dbname).'`', $link) !== false)) - return true; + /** + * Tries to connect and create a new database + * + * @param string $host + * @param string $user + * @param string $password + * @param string $dbname + * @param bool $dropit If true, drops the created database. + * @return bool|resource + */ + public static function createDatabase($host, $user, $password, $dbname, $dropit = false) + { + $link = mysql_connect($host, $user, $password); + $success = mysql_query('CREATE DATABASE `'.str_replace('`', '\\`', $dbname).'`', $link); + if ($dropit && (mysql_query('DROP DATABASE `'.str_replace('`', '\\`', $dbname).'`', $link) !== false)) { + return true; + } - return $success; - } + return $success; + } - /** - * Destroys the database connection link - * - * @see DbCore::disconnect() - */ - public function disconnect() - { - mysql_close($this->link); - } + /** + * Destroys the database connection link + * + * @see DbCore::disconnect() + */ + public function disconnect() + { + mysql_close($this->link); + } - /** - * Executes an SQL statement, returning a result set as a result resource object. - * - * @see DbCore::_query() - * @param string $sql - * @return resource - */ - protected function _query($sql) - { - return mysql_query($sql, $this->link); - } + /** + * Executes an SQL statement, returning a result set as a result resource object. + * + * @see DbCore::_query() + * @param string $sql + * @return resource + */ + protected function _query($sql) + { + return mysql_query($sql, $this->link); + } - /** - * Returns the next row from the result set. - * - * @see DbCore::nextRow() - * @param bool|resource $result - * @return array|bool - */ - public function nextRow($result = false) - { - $return = false; - if (is_resource($result) && $result) - $return = mysql_fetch_assoc($result); - elseif (is_resource($this->_result) && $this->_result) - $return = mysql_fetch_assoc($this->_result); + /** + * Returns the next row from the result set. + * + * @see DbCore::nextRow() + * @param bool|resource $result + * @return array|bool + */ + public function nextRow($result = false) + { + $return = false; + if (is_resource($result) && $result) { + $return = mysql_fetch_assoc($result); + } elseif (is_resource($this->_result) && $this->_result) { + $return = mysql_fetch_assoc($this->_result); + } - return $return; - } + return $return; + } - /** - * Returns the next row from the result set. - * - * @see DbCore::_numRows() - * @param resource $result - * @return int - */ - protected function _numRows($result) - { - return mysql_num_rows($result); - } + /** + * Returns the next row from the result set. + * + * @see DbCore::_numRows() + * @param resource $result + * @return int + */ + protected function _numRows($result) + { + return mysql_num_rows($result); + } - /** - * Returns ID of the last inserted row. - * - * @see DbCore::Insert_ID() - * @return int - */ - public function Insert_ID() - { - return mysql_insert_id($this->link); - } + /** + * Returns ID of the last inserted row. + * + * @see DbCore::Insert_ID() + * @return int + */ + public function Insert_ID() + { + return mysql_insert_id($this->link); + } - /** - * Return the number of rows affected by the last SQL query. - * - * @see DbCore::Affected_Rows() - * @return int - */ - public function Affected_Rows() - { - return mysql_affected_rows($this->link); - } + /** + * Return the number of rows affected by the last SQL query. + * + * @see DbCore::Affected_Rows() + * @return int + */ + public function Affected_Rows() + { + return mysql_affected_rows($this->link); + } - /** - * Returns error message. - * - * @see DbCore::getMsgError() - * @param bool $query - * @return string - */ - public function getMsgError($query = false) - { - return mysql_error($this->link); - } + /** + * Returns error message. + * + * @see DbCore::getMsgError() + * @param bool $query + * @return string + */ + public function getMsgError($query = false) + { + return mysql_error($this->link); + } - /** - * Returns error code. - * - * @see DbCore::getNumberError() - * @return int - */ - public function getNumberError() - { - return mysql_errno($this->link); - } + /** + * Returns error code. + * + * @see DbCore::getNumberError() + * @return int + */ + public function getNumberError() + { + return mysql_errno($this->link); + } - /** - * Returns database server version. - * - * @see DbCore::getVersion() - * @return string - */ - public function getVersion() - { - return mysql_get_server_info($this->link); - } + /** + * Returns database server version. + * + * @see DbCore::getVersion() + * @return string + */ + public function getVersion() + { + return mysql_get_server_info($this->link); + } - /** - * Escapes illegal characters in a string. - * - * @see DbCore::_escape() - * @param string $str - * @return string - */ - public function _escape($str) - { - return _PS_MYSQL_REAL_ESCAPE_STRING_ ? mysql_real_escape_string($str, $this->link) : addslashes($str); - } + /** + * Escapes illegal characters in a string. + * + * @see DbCore::_escape() + * @param string $str + * @return string + */ + public function _escape($str) + { + return _PS_MYSQL_REAL_ESCAPE_STRING_ ? mysql_real_escape_string($str, $this->link) : addslashes($str); + } - /** - * Switches to a different database. - * - * @see DbCore::set_db() - * @param string $db_name - * @return bool - */ - public function set_db($db_name) - { - return mysql_select_db($db_name, $this->link); - } + /** + * Switches to a different database. + * + * @see DbCore::set_db() + * @param string $db_name + * @return bool + */ + public function set_db($db_name) + { + return mysql_select_db($db_name, $this->link); + } - /** - * Returns all rows from the result set. - * - * @see DbCore::getAll() - * @param bool|resource $result - * @return array - */ - protected function getAll($result = false) - { - if (!$result) - $result = $this->result; + /** + * Returns all rows from the result set. + * + * @see DbCore::getAll() + * @param bool|resource $result + * @return array + */ + protected function getAll($result = false) + { + if (!$result) { + $result = $this->result; + } - $data = array(); - while ($row = $this->nextRow($result)) - $data[] = $row; + $data = array(); + while ($row = $this->nextRow($result)) { + $data[] = $row; + } - return $data; - } + return $data; + } - /** - * Try a connection to the database and check if at least one table with same prefix exists - * - * @see Db::hasTableWithSamePrefix() - * @param string $server Server address - * @param string $user Login for database connection - * @param string $pwd Password for database connection - * @param string $db Database name - * @param string $prefix Tables prefix - * @return bool - */ - public static function hasTableWithSamePrefix($server, $user, $pwd, $db, $prefix) - { - if (!$link = @mysql_connect($server, $user, $pwd, true)) - return false; - if (!@mysql_select_db($db, $link)) - return false; + /** + * Try a connection to the database and check if at least one table with same prefix exists + * + * @see Db::hasTableWithSamePrefix() + * @param string $server Server address + * @param string $user Login for database connection + * @param string $pwd Password for database connection + * @param string $db Database name + * @param string $prefix Tables prefix + * @return bool + */ + public static function hasTableWithSamePrefix($server, $user, $pwd, $db, $prefix) + { + if (!$link = @mysql_connect($server, $user, $pwd, true)) { + return false; + } + if (!@mysql_select_db($db, $link)) { + return false; + } - $sql = 'SHOW TABLES LIKE \''.$prefix.'%\''; - $result = mysql_query($sql); - return (bool)@mysql_fetch_assoc($result); - } + $sql = 'SHOW TABLES LIKE \''.$prefix.'%\''; + $result = mysql_query($sql); + return (bool)@mysql_fetch_assoc($result); + } - /** - * Try a connection to the database - * - * @see Db::checkConnection() - * @param string $server Server address - * @param string $user Login for database connection - * @param string $pwd Password for database connection - * @param string $db Database name - * @param bool $newDbLink - * @param string|null $engine - * @param int $timeout - * @return int Error code or 0 if connection was successful - */ - public static function tryToConnect($server, $user, $pwd, $db, $new_db_link = true, $engine = null, $timeout = 5) - { - ini_set('mysql.connect_timeout', $timeout); - if (!$link = @mysql_connect($server, $user, $pwd, $new_db_link)) - return 1; - if (!@mysql_select_db($db, $link)) - return 2; - @mysql_close($link); + /** + * Try a connection to the database + * + * @see Db::checkConnection() + * @param string $server Server address + * @param string $user Login for database connection + * @param string $pwd Password for database connection + * @param string $db Database name + * @param bool $newDbLink + * @param string|null $engine + * @param int $timeout + * @return int Error code or 0 if connection was successful + */ + public static function tryToConnect($server, $user, $pwd, $db, $new_db_link = true, $engine = null, $timeout = 5) + { + ini_set('mysql.connect_timeout', $timeout); + if (!$link = @mysql_connect($server, $user, $pwd, $new_db_link)) { + return 1; + } + if (!@mysql_select_db($db, $link)) { + return 2; + } + @mysql_close($link); - return 0; - } + return 0; + } - /** - * Selects best table engine. - * - * @return string - */ - public function getBestEngine() - { - $value = 'InnoDB'; + /** + * Selects best table engine. + * + * @return string + */ + public function getBestEngine() + { + $value = 'InnoDB'; - $sql = 'SHOW VARIABLES WHERE Variable_name = \'have_innodb\''; - $result = mysql_query($sql); - if (!$result) - $value = 'MyISAM'; - $row = mysql_fetch_assoc($result); - if (!$row || strtolower($row['Value']) != 'yes') - $value = 'MyISAM'; + $sql = 'SHOW VARIABLES WHERE Variable_name = \'have_innodb\''; + $result = mysql_query($sql); + if (!$result) { + $value = 'MyISAM'; + } + $row = mysql_fetch_assoc($result); + if (!$row || strtolower($row['Value']) != 'yes') { + $value = 'MyISAM'; + } - /* MySQL >= 5.6 */ - $sql = 'SHOW ENGINES'; - $result = mysql_query($sql); - while ($row = mysql_fetch_assoc($result)) - if ($row['Engine'] == 'InnoDB') - { - if (in_array($row['Support'], array('DEFAULT', 'YES'))) - $value = 'InnoDB'; - break; - } + /* MySQL >= 5.6 */ + $sql = 'SHOW ENGINES'; + $result = mysql_query($sql); + while ($row = mysql_fetch_assoc($result)) { + if ($row['Engine'] == 'InnoDB') { + if (in_array($row['Support'], array('DEFAULT', 'YES'))) { + $value = 'InnoDB'; + } + break; + } + } - return $value; - } + return $value; + } - /** - * Tries to connect to the database and create a table (checking creation privileges) - * - * @param string $server - * @param string $user - * @param string $pwd - * @param string $db - * @param string $prefix - * @param string|null $engine Table engine - * @return bool|string True, false or error - */ - public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine = null) - { - ini_set('mysql.connect_timeout', 5); - if (!$link = @mysql_connect($server, $user, $pwd, true)) - return false; - if (!@mysql_select_db($db, $link)) - return false; + /** + * Tries to connect to the database and create a table (checking creation privileges) + * + * @param string $server + * @param string $user + * @param string $pwd + * @param string $db + * @param string $prefix + * @param string|null $engine Table engine + * @return bool|string True, false or error + */ + public static function checkCreatePrivilege($server, $user, $pwd, $db, $prefix, $engine = null) + { + ini_set('mysql.connect_timeout', 5); + if (!$link = @mysql_connect($server, $user, $pwd, true)) { + return false; + } + if (!@mysql_select_db($db, $link)) { + return false; + } - if ($engine === null) - $engine = 'MyISAM'; + if ($engine === null) { + $engine = 'MyISAM'; + } - $result = mysql_query(' + $result = mysql_query(' CREATE TABLE `'.$prefix.'test` ( `test` tinyint(1) unsigned NOT NULL ) ENGINE='.$engine, $link); - if (!$result) - return mysql_error($link); + if (!$result) { + return mysql_error($link); + } - mysql_query('DROP TABLE `'.$prefix.'test`', $link); - return true; - } + mysql_query('DROP TABLE `'.$prefix.'test`', $link); + return true; + } - /** - * Try a connection to the database and set names to UTF-8 - * - * @see Db::checkEncoding() - * @param string $server Server address - * @param string $user Login for database connection - * @param string $pwd Password for database connection - * @return bool - */ - public static function tryUTF8($server, $user, $pwd) - { - $link = @mysql_connect($server, $user, $pwd); - $ret = mysql_query('SET NAMES \'utf8\'', $link); - @mysql_close($link); - return $ret; - } + /** + * Try a connection to the database and set names to UTF-8 + * + * @see Db::checkEncoding() + * @param string $server Server address + * @param string $user Login for database connection + * @param string $pwd Password for database connection + * @return bool + */ + public static function tryUTF8($server, $user, $pwd) + { + $link = @mysql_connect($server, $user, $pwd); + $ret = mysql_query('SET NAMES \'utf8\'', $link); + @mysql_close($link); + return $ret; + } - /** - * Checks if auto increment value and offset is 1 - * - * @param string $server - * @param string $user - * @param string $pwd - * @return bool - */ - public static function checkAutoIncrement($server, $user, $pwd) - { - $link = @mysql_connect($server, $user, $pwd); - $ret = (bool)(($result = mysql_query('SELECT @@auto_increment_increment as aii', $link)) && ($row = mysql_fetch_assoc($result)) && $row['aii'] == 1); - $ret &= (bool)(($result = mysql_query('SELECT @@auto_increment_offset as aio', $link)) && ($row = mysql_fetch_assoc($result)) && $row['aio'] == 1); - @mysql_close($link); - return $ret; - } + /** + * Checks if auto increment value and offset is 1 + * + * @param string $server + * @param string $user + * @param string $pwd + * @return bool + */ + public static function checkAutoIncrement($server, $user, $pwd) + { + $link = @mysql_connect($server, $user, $pwd); + $ret = (bool)(($result = mysql_query('SELECT @@auto_increment_increment as aii', $link)) && ($row = mysql_fetch_assoc($result)) && $row['aii'] == 1); + $ret &= (bool)(($result = mysql_query('SELECT @@auto_increment_offset as aio', $link)) && ($row = mysql_fetch_assoc($result)) && $row['aio'] == 1); + @mysql_close($link); + return $ret; + } } diff --git a/classes/db/index.php b/classes/db/index.php index c642967a..91fa49fb 100644 --- a/classes/db/index.php +++ b/classes/db/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/classes/exception/PrestaShopDatabaseException.php b/classes/exception/PrestaShopDatabaseException.php index c54a4bca..870a556b 100644 --- a/classes/exception/PrestaShopDatabaseException.php +++ b/classes/exception/PrestaShopDatabaseException.php @@ -29,8 +29,8 @@ */ class PrestaShopDatabaseExceptionCore extends PrestaShopException { - public function __toString() - { - return $this->message; - } -} \ No newline at end of file + public function __toString() + { + return $this->message; + } +} diff --git a/classes/exception/PrestaShopException.php b/classes/exception/PrestaShopException.php index 516dc4f8..a57a967c 100644 --- a/classes/exception/PrestaShopException.php +++ b/classes/exception/PrestaShopException.php @@ -29,16 +29,15 @@ */ class PrestaShopExceptionCore extends Exception { - /** - * This method acts like an error handler, if dev mode is on, display the error else use a better silent way - */ - public function displayMessage() - { - header('HTTP/1.1 500 Internal Server Error'); - if (_PS_MODE_DEV_ || defined('_PS_ADMIN_DIR_')) - { - // Display error message - echo '<style> + /** + * This method acts like an error handler, if dev mode is on, display the error else use a better silent way + */ + public function displayMessage() + { + header('HTTP/1.1 500 Internal Server Error'); + if (_PS_MODE_DEV_ || defined('_PS_ADMIN_DIR_')) { + // Display error message + echo '<style> #psException{font-family: Verdana; font-size: 14px} #psException h2{color: #F20000} #psException p{padding-left: 20px} @@ -49,131 +48,132 @@ class PrestaShopExceptionCore extends Exception #psException .psArgs pre{background-color: #F1FDFE;} #psException pre .selected{color: #F20000; font-weight: bold;} </style>'; - echo '<div id="psException">'; - echo '<h2>['.get_class($this).']</h2>'; - echo $this->getExtendedMessage(); + echo '<div id="psException">'; + echo '<h2>['.get_class($this).']</h2>'; + echo $this->getExtendedMessage(); - $this->displayFileDebug($this->getFile(), $this->getLine()); + $this->displayFileDebug($this->getFile(), $this->getLine()); - // Display debug backtrace - echo '<ul>'; - foreach ($this->getTrace() as $id => $trace) - { - $relative_file = (isset($trace['file'])) ? ltrim(str_replace(array(_PS_ROOT_DIR_, '\\'), array('', '/'), $trace['file']), '/') : ''; - $current_line = (isset($trace['line'])) ? $trace['line'] : ''; - if (defined('_PS_ADMIN_DIR_')) - $relative_file = str_replace(basename(_PS_ADMIN_DIR_).DIRECTORY_SEPARATOR, 'admin'.DIRECTORY_SEPARATOR, $relative_file); - echo '<li>'; - echo '<b>'.((isset($trace['class'])) ? $trace['class'] : '').((isset($trace['type'])) ? $trace['type'] : '').$trace['function'].'</b>'; - echo ' - <a style="font-size: 12px; color: #000000; cursor:pointer; color: blue;" onclick="document.getElementById(\'psTrace_'.$id.'\').style.display = (document.getElementById(\'psTrace_'.$id.'\').style.display != \'block\') ? \'block\' : \'none\'; return false">[line '.$current_line.' - '.$relative_file.']</a>'; + // Display debug backtrace + echo '<ul>'; + foreach ($this->getTrace() as $id => $trace) { + $relative_file = (isset($trace['file'])) ? ltrim(str_replace(array(_PS_ROOT_DIR_, '\\'), array('', '/'), $trace['file']), '/') : ''; + $current_line = (isset($trace['line'])) ? $trace['line'] : ''; + if (defined('_PS_ADMIN_DIR_')) { + $relative_file = str_replace(basename(_PS_ADMIN_DIR_).DIRECTORY_SEPARATOR, 'admin'.DIRECTORY_SEPARATOR, $relative_file); + } + echo '<li>'; + echo '<b>'.((isset($trace['class'])) ? $trace['class'] : '').((isset($trace['type'])) ? $trace['type'] : '').$trace['function'].'</b>'; + echo ' - <a style="font-size: 12px; color: #000000; cursor:pointer; color: blue;" onclick="document.getElementById(\'psTrace_'.$id.'\').style.display = (document.getElementById(\'psTrace_'.$id.'\').style.display != \'block\') ? \'block\' : \'none\'; return false">[line '.$current_line.' - '.$relative_file.']</a>'; - if (isset($trace['args']) && count($trace['args'])) - echo ' - <a style="font-size: 12px; color: #000000; cursor:pointer; color: blue;" onclick="document.getElementById(\'psArgs_'.$id.'\').style.display = (document.getElementById(\'psArgs_'.$id.'\').style.display != \'block\') ? \'block\' : \'none\'; return false">['.count($trace['args']).' Arguments]</a>'; + if (isset($trace['args']) && count($trace['args'])) { + echo ' - <a style="font-size: 12px; color: #000000; cursor:pointer; color: blue;" onclick="document.getElementById(\'psArgs_'.$id.'\').style.display = (document.getElementById(\'psArgs_'.$id.'\').style.display != \'block\') ? \'block\' : \'none\'; return false">['.count($trace['args']).' Arguments]</a>'; + } - if ($relative_file) - $this->displayFileDebug($trace['file'], $trace['line'], $id); - if (isset($trace['args']) && count($trace['args'])) - $this->displayArgsDebug($trace['args'], $id); - echo '</li>'; - } - echo '</ul>'; - echo '</div>'; - } - else - { - // If not in mode dev, display an error page - if (file_exists(_PS_ROOT_DIR_.'/error500.html')) - echo file_get_contents(_PS_ROOT_DIR_.'/error500.html'); - } - // Log the error in the disk - $this->logError(); - exit; - } + if ($relative_file) { + $this->displayFileDebug($trace['file'], $trace['line'], $id); + } + if (isset($trace['args']) && count($trace['args'])) { + $this->displayArgsDebug($trace['args'], $id); + } + echo '</li>'; + } + echo '</ul>'; + echo '</div>'; + } else { + // If not in mode dev, display an error page + if (file_exists(_PS_ROOT_DIR_.'/error500.html')) { + echo file_get_contents(_PS_ROOT_DIR_.'/error500.html'); + } + } + // Log the error in the disk + $this->logError(); + exit; + } - /** - * Display lines around current line - * - * @param string $file - * @param int $line - * @param string $id - */ - protected function displayFileDebug($file, $line, $id = null) - { - $lines = file($file); - $offset = $line - 6; - $total = 11; - if ($offset < 0) - { - $total += $offset; - $offset = 0; - } - $lines = array_slice($lines, $offset, $total); - ++$offset; + /** + * Display lines around current line + * + * @param string $file + * @param int $line + * @param string $id + */ + protected function displayFileDebug($file, $line, $id = null) + { + $lines = file($file); + $offset = $line - 6; + $total = 11; + if ($offset < 0) { + $total += $offset; + $offset = 0; + } + $lines = array_slice($lines, $offset, $total); + ++$offset; - echo '<div class="psTrace" id="psTrace_'.$id.'" '.((is_null($id) ? 'style="display: block"' : '')).'><pre>'; - foreach ($lines as $k => $l) - { - $string = ($offset + $k).'. '.htmlspecialchars($l); - if ($offset + $k == $line) - echo '<span class="selected">'.$string.'</span>'; - else - echo $string; - } - echo '</pre></div>'; - } + echo '<div class="psTrace" id="psTrace_'.$id.'" '.((is_null($id) ? 'style="display: block"' : '')).'><pre>'; + foreach ($lines as $k => $l) { + $string = ($offset + $k).'. '.htmlspecialchars($l); + if ($offset + $k == $line) { + echo '<span class="selected">'.$string.'</span>'; + } else { + echo $string; + } + } + echo '</pre></div>'; + } - /** - * Display arguments list of traced function - * - * @param array $args List of arguments - * @param string $id ID of argument - */ - protected function displayArgsDebug($args, $id) - { - echo '<div class="psArgs" id="psArgs_'.$id.'"><pre>'; - foreach ($args as $arg => $value) - { - echo '<b>Argument ['.Tools::safeOutput($arg)."]</b>\n"; - echo Tools::safeOutput(print_r($value, true)); - echo "\n"; - } - echo '</pre>'; - } + /** + * Display arguments list of traced function + * + * @param array $args List of arguments + * @param string $id ID of argument + */ + protected function displayArgsDebug($args, $id) + { + echo '<div class="psArgs" id="psArgs_'.$id.'"><pre>'; + foreach ($args as $arg => $value) { + echo '<b>Argument ['.Tools::safeOutput($arg)."]</b>\n"; + echo Tools::safeOutput(print_r($value, true)); + echo "\n"; + } + echo '</pre>'; + } - /** - * Log the error on the disk - */ - protected function logError() - { - $logger = new FileLogger(); - $logger->setFilename(_PS_ROOT_DIR_.'/log/'.date('Ymd').'_exception.log'); - $logger->logError($this->getExtendedMessage(false)); - } + /** + * Log the error on the disk + */ + protected function logError() + { + $logger = new FileLogger(); + $logger->setFilename(_PS_ROOT_DIR_.'/log/'.date('Ymd').'_exception.log'); + $logger->logError($this->getExtendedMessage(false)); + } - /** - * @deprecated 1.5.5 - */ - protected function getExentedMessage($html = true) - { - Tools::displayAsDeprecated(); - return $this->getExtendedMessage($html); - } + /** + * @deprecated 1.5.5 + */ + protected function getExentedMessage($html = true) + { + Tools::displayAsDeprecated(); + return $this->getExtendedMessage($html); + } - /** - * Return the content of the Exception - * @return string content of the exception - */ - protected function getExtendedMessage($html = true) - { - $format = '<p><b>%s</b><br /><i>at line </i><b>%d</b><i> in file </i><b>%s</b></p>'; - if (!$html) - $format = strip_tags(str_replace('<br />', ' ', $format)); + /** + * Return the content of the Exception + * @return string content of the exception + */ + protected function getExtendedMessage($html = true) + { + $format = '<p><b>%s</b><br /><i>at line </i><b>%d</b><i> in file </i><b>%s</b></p>'; + if (!$html) { + $format = strip_tags(str_replace('<br />', ' ', $format)); + } - return sprintf( - $format, - $this->getMessage(), - $this->getLine(), - ltrim(str_replace(array(_PS_ROOT_DIR_, '\\'), array('', '/'), $this->getFile()), '/') - ); - } -} \ No newline at end of file + return sprintf( + $format, + $this->getMessage(), + $this->getLine(), + ltrim(str_replace(array(_PS_ROOT_DIR_, '\\'), array('', '/'), $this->getFile()), '/') + ); + } +} diff --git a/classes/exception/PrestaShopModuleException.php b/classes/exception/PrestaShopModuleException.php index 81a1fecd..001d56df 100644 --- a/classes/exception/PrestaShopModuleException.php +++ b/classes/exception/PrestaShopModuleException.php @@ -29,5 +29,4 @@ */ class PrestaShopModuleExceptionCore extends PrestaShopException { - -} \ No newline at end of file +} diff --git a/classes/exception/PrestaShopPaymentException.php b/classes/exception/PrestaShopPaymentException.php index 81bbe436..2a6a0102 100644 --- a/classes/exception/PrestaShopPaymentException.php +++ b/classes/exception/PrestaShopPaymentException.php @@ -29,5 +29,4 @@ */ class PrestaShopPaymentExceptionCore extends PrestaShopException { - -} \ No newline at end of file +} diff --git a/classes/exception/index.php b/classes/exception/index.php index d78cacbb..bc9342b7 100644 --- a/classes/exception/index.php +++ b/classes/exception/index.php @@ -23,13 +23,13 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * International Registered Trademark & Property of PrestaShop SA */ - + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); - + header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); - + header("Location: ../"); -exit; \ No newline at end of file +exit; diff --git a/classes/helper/Helper.php b/classes/helper/Helper.php index e40de4ed..f9fcd431 100644 --- a/classes/helper/Helper.php +++ b/classes/helper/Helper.php @@ -26,246 +26,248 @@ class HelperCore { - public $currentIndex; - public $table = 'configuration'; - public $identifier; - public $token; - public $toolbar_btn; - public $ps_help_context; - public $title; - public $show_toolbar = true; - public $context; - public $toolbar_scroll = false; - public $bootstrap = false; + public $currentIndex; + public $table = 'configuration'; + public $identifier; + public $token; + public $toolbar_btn; + public $ps_help_context; + public $title; + public $show_toolbar = true; + public $context; + public $toolbar_scroll = false; + public $bootstrap = false; - /** - * @var Module - */ - public $module; + /** + * @var Module + */ + public $module; - /** @var string Helper tpl folder */ - public $base_folder; + /** @var string Helper tpl folder */ + public $base_folder; - /** @var string Controller tpl folder */ - public $override_folder; + /** @var string Controller tpl folder */ + public $override_folder; - /** - * @var Smarty_Internal_Template base template object - */ - protected $tpl; + /** + * @var Smarty_Internal_Template base template object + */ + protected $tpl; - /** - * @var string base template name - */ - public $base_tpl = 'content.tpl'; + /** + * @var string base template name + */ + public $base_tpl = 'content.tpl'; - public $tpl_vars = array(); + public $tpl_vars = array(); - public function __construct() - { - $this->context = Context::getContext(); - } + public function __construct() + { + $this->context = Context::getContext(); + } - public function setTpl($tpl) - { - $this->tpl = $this->createTemplate($tpl); - } + public function setTpl($tpl) + { + $this->tpl = $this->createTemplate($tpl); + } - /** - * Create a template from the override file, else from the base file. - * - * @param string $tpl_name filename - * @return Smarty_Internal_Template - */ - public function createTemplate($tpl_name) - { - if ($this->override_folder) - { - if ($this->context->controller instanceof ModuleAdminController) - $override_tpl_path = $this->context->controller->getTemplatePath().$this->override_folder.$this->base_folder.$tpl_name; - elseif ($this->module) - $override_tpl_path = _PS_MODULE_DIR_.$this->module->name.'/views/templates/admin/_configure/'.$this->override_folder.$this->base_folder.$tpl_name; - else - { - if (file_exists($this->context->smarty->getTemplateDir(1).$this->override_folder.$this->base_folder.$tpl_name)) - $override_tpl_path = $this->context->smarty->getTemplateDir(1).$this->override_folder.$this->base_folder.$tpl_name; - elseif (file_exists($this->context->smarty->getTemplateDir(0).'controllers'.DIRECTORY_SEPARATOR.$this->override_folder.$this->base_folder.$tpl_name)) - $override_tpl_path = $this->context->smarty->getTemplateDir(0).'controllers'.DIRECTORY_SEPARATOR.$this->override_folder.$this->base_folder.$tpl_name; + /** + * Create a template from the override file, else from the base file. + * + * @param string $tpl_name filename + * @return Smarty_Internal_Template + */ + public function createTemplate($tpl_name) + { + if ($this->override_folder) { + if ($this->context->controller instanceof ModuleAdminController) { + $override_tpl_path = $this->context->controller->getTemplatePath().$this->override_folder.$this->base_folder.$tpl_name; + } elseif ($this->module) { + $override_tpl_path = _PS_MODULE_DIR_.$this->module->name.'/views/templates/admin/_configure/'.$this->override_folder.$this->base_folder.$tpl_name; + } else { + if (file_exists($this->context->smarty->getTemplateDir(1).$this->override_folder.$this->base_folder.$tpl_name)) { + $override_tpl_path = $this->context->smarty->getTemplateDir(1).$this->override_folder.$this->base_folder.$tpl_name; + } elseif (file_exists($this->context->smarty->getTemplateDir(0).'controllers'.DIRECTORY_SEPARATOR.$this->override_folder.$this->base_folder.$tpl_name)) { + $override_tpl_path = $this->context->smarty->getTemplateDir(0).'controllers'.DIRECTORY_SEPARATOR.$this->override_folder.$this->base_folder.$tpl_name; + } + } + } elseif ($this->module) { + $override_tpl_path = _PS_MODULE_DIR_.$this->module->name.'/views/templates/admin/_configure/'.$this->base_folder.$tpl_name; + } - } - } - elseif ($this->module) - $override_tpl_path = _PS_MODULE_DIR_.$this->module->name.'/views/templates/admin/_configure/'.$this->base_folder.$tpl_name; + if (isset($override_tpl_path) && file_exists($override_tpl_path)) { + return $this->context->smarty->createTemplate($override_tpl_path, $this->context->smarty); + } else { + return $this->context->smarty->createTemplate($this->base_folder.$tpl_name, $this->context->smarty); + } + } - if (isset($override_tpl_path) && file_exists($override_tpl_path)) - return $this->context->smarty->createTemplate($override_tpl_path, $this->context->smarty); - else - return $this->context->smarty->createTemplate($this->base_folder.$tpl_name, $this->context->smarty); - } + /** + * default behaviour for helper is to return a tpl fetched + * + * @return string + */ + public function generate() + { + $this->tpl->assign($this->tpl_vars); + return $this->tpl->fetch(); + } - /** - * default behaviour for helper is to return a tpl fetched - * - * @return string - */ - public function generate() - { - $this->tpl->assign($this->tpl_vars); - return $this->tpl->fetch(); - } + /** + * @deprecated 1.5.0 + */ + public static function renderAdminCategorieTree($translations, + $selected_cat = array(), + $input_name = 'categoryBox', + $use_radio = false, + $use_search = false, + $disabled_categories = array(), + $use_in_popup = false) + { + Tools::displayAsDeprecated(); - /** - * @deprecated 1.5.0 - */ - public static function renderAdminCategorieTree($translations, - $selected_cat = array(), - $input_name = 'categoryBox', - $use_radio = false, - $use_search = false, - $disabled_categories = array(), - $use_in_popup = false) - { - Tools::displayAsDeprecated(); + $helper = new Helper(); + if (isset($translations['Root'])) { + $root = $translations['Root']; + } elseif (isset($translations['Home'])) { + $root = array('name' => $translations['Home'], 'id_category' => 1); + } else { + throw new PrestaShopException('Missing root category parameter.'); + } - $helper = new Helper(); - if (isset($translations['Root'])) - $root = $translations['Root']; - elseif (isset($translations['Home'])) - $root = array('name' => $translations['Home'], 'id_category' => 1); - else - throw new PrestaShopException('Missing root category parameter.'); + return $helper->renderCategoryTree($root, $selected_cat, $input_name, $use_radio, $use_search, $disabled_categories, $use_in_popup); + } - return $helper->renderCategoryTree($root, $selected_cat, $input_name, $use_radio, $use_search, $disabled_categories, $use_in_popup); - } + /** + * + * @param array $root array with the name and ID of the tree root category, if null the Shop's root category will be used + * @param array $selected_cat array of selected categories + * Format + * Array + * ( + * [0] => 1 + * [1] => 2 + * ) + * OR + * Array + * ( + * [1] => Array + * ( + * [id_category] => 1 + * [name] => Home page + * ) + * ) + * @param string $input_name name of input + * @param bool $use_radio use radio tree or checkbox tree + * @param bool $use_search display a find category search box + * @param array $disabled_categories + * @return string + */ + public function renderCategoryTree($root = null, + $selected_cat = array(), + $input_name = 'categoryBox', + $use_radio = false, + $use_search = false, + $disabled_categories = array()) + { + $translations = array( + 'selected' => $this->l('Selected'), + 'Collapse All' => $this->l('Collapse All'), + 'Expand All' => $this->l('Expand All'), + 'Check All' => $this->l('Check All'), + 'Uncheck All' => $this->l('Uncheck All'), + 'search' => $this->l('Find a category') + ); - /** - * - * @param array $root array with the name and ID of the tree root category, if null the Shop's root category will be used - * @param array $selected_cat array of selected categories - * Format - * Array - * ( - * [0] => 1 - * [1] => 2 - * ) - * OR - * Array - * ( - * [1] => Array - * ( - * [id_category] => 1 - * [name] => Home page - * ) - * ) - * @param string $input_name name of input - * @param bool $use_radio use radio tree or checkbox tree - * @param bool $use_search display a find category search box - * @param array $disabled_categories - * @return string - */ - public function renderCategoryTree($root = null, - $selected_cat = array(), - $input_name = 'categoryBox', - $use_radio = false, - $use_search = false, - $disabled_categories = array()) - { - $translations = array( - 'selected' => $this->l('Selected'), - 'Collapse All' => $this->l('Collapse All'), - 'Expand All' => $this->l('Expand All'), - 'Check All' => $this->l('Check All'), - 'Uncheck All' => $this->l('Uncheck All'), - 'search' => $this->l('Find a category') - ); + if (Tools::isSubmit('id_shop')) { + $id_shop = Tools::getValue('id_shop'); + } elseif (Context::getContext()->shop->id) { + $id_shop = Context::getContext()->shop->id; + } elseif (!Shop::isFeatureActive()) { + $id_shop = Configuration::get('PS_SHOP_DEFAULT'); + } else { + $id_shop = 0; + } + $shop = new Shop($id_shop); + $root_category = Category::getRootCategory(null, $shop); + $disabled_categories[] = (int)Configuration::get('PS_ROOT_CATEGORY'); + if (!$root) { + $root = array('name' => $root_category->name, 'id_category' => $root_category->id); + } - if (Tools::isSubmit('id_shop')) - $id_shop = Tools::getValue('id_shop'); - else - if (Context::getContext()->shop->id) - $id_shop = Context::getContext()->shop->id; - else - if (!Shop::isFeatureActive()) - $id_shop = Configuration::get('PS_SHOP_DEFAULT'); - else - $id_shop = 0; - $shop = new Shop($id_shop); - $root_category = Category::getRootCategory(null, $shop); - $disabled_categories[] = (int)Configuration::get('PS_ROOT_CATEGORY'); - if (!$root) - $root = array('name' => $root_category->name, 'id_category' => $root_category->id); + if (!$use_radio) { + $input_name = $input_name.'[]'; + } - if (!$use_radio) - $input_name = $input_name.'[]'; + if ($use_search) { + $this->context->controller->addJs(_PS_JS_DIR_.'jquery/plugins/autocomplete/jquery.autocomplete.js'); + } - if ($use_search) - $this->context->controller->addJs(_PS_JS_DIR_.'jquery/plugins/autocomplete/jquery.autocomplete.js'); - - $html = ' + $html = ' <script type="text/javascript"> var inputName = \''.addcslashes($input_name, '\'').'\';'."\n"; - if (count($selected_cat) > 0) - { - if (isset($selected_cat[0])) - $html .= ' var selectedCat = "'.implode(',', array_map('intval', $selected_cat)).'";'."\n"; - else - $html .= ' var selectedCat = "'.implode(',', array_map('intval', array_keys($selected_cat))).'";'."\n"; - } - else - $html .= ' var selectedCat = \'\';'."\n"; - $html .= ' var selectedLabel = \''.$translations['selected'].'\'; + if (count($selected_cat) > 0) { + if (isset($selected_cat[0])) { + $html .= ' var selectedCat = "'.implode(',', array_map('intval', $selected_cat)).'";'."\n"; + } else { + $html .= ' var selectedCat = "'.implode(',', array_map('intval', array_keys($selected_cat))).'";'."\n"; + } + } else { + $html .= ' var selectedCat = \'\';'."\n"; + } + $html .= ' var selectedLabel = \''.$translations['selected'].'\'; var home = \''.addcslashes($root['name'], '\'').'\'; var use_radio = '.(int)$use_radio.';'; - $html .= '</script>'; + $html .= '</script>'; - $html .= ' + $html .= ' <div class="category-filter"> <a class="btn btn-link" href="#" id="collapse_all"><i class="icon-collapse"></i> '.$translations['Collapse All'].'</a> <a class="btn btn-link" href="#" id="expand_all"><i class="icon-expand"></i> '.$translations['Expand All'].'</a> '.(!$use_radio ? ' <a class="btn btn-link" href="#" id="check_all"><i class="icon-check"></i> '.$translations['Check All'].'</a> <a class="btn btn-link" href="#" id="uncheck_all"><i class="icon-check-empty"></i> '.$translations['Uncheck All'].'</a>' : '') - .($use_search ? ' + .($use_search ? ' <div class="row"> <label class="control-label col-lg-6" for="search_cat">'.$translations['search'].' :</label> <div class="col-lg-6"> <input type="text" name="search_cat" id="search_cat"/> </div> </div>' : '') - .'</div>'; + .'</div>'; - $home_is_selected = false; - if (is_array($selected_cat)) - foreach ($selected_cat as $cat) - { - if (is_array($cat)) - { - $disabled = in_array($cat['id_category'], $disabled_categories); - if ($cat['id_category'] != $root['id_category']) - $html .= '<input '.($disabled?'disabled="disabled"':'').' type="hidden" name="'.$input_name.'" value="'.$cat['id_category'].'" >'; - else - $home_is_selected = true; - } - else - { - $disabled = in_array($cat, $disabled_categories); - if ($cat != $root['id_category']) - $html .= '<input '.($disabled?'disabled="disabled"':'').' type="hidden" name="'.$input_name.'" value="'.$cat.'" >'; - else - $home_is_selected = true; - } - } + $home_is_selected = false; + if (is_array($selected_cat)) { + foreach ($selected_cat as $cat) { + if (is_array($cat)) { + $disabled = in_array($cat['id_category'], $disabled_categories); + if ($cat['id_category'] != $root['id_category']) { + $html .= '<input '.($disabled?'disabled="disabled"':'').' type="hidden" name="'.$input_name.'" value="'.$cat['id_category'].'" >'; + } else { + $home_is_selected = true; + } + } else { + $disabled = in_array($cat, $disabled_categories); + if ($cat != $root['id_category']) { + $html .= '<input '.($disabled?'disabled="disabled"':'').' type="hidden" name="'.$input_name.'" value="'.$cat.'" >'; + } else { + $home_is_selected = true; + } + } + } + } - $root_input = ''; - if ($root['id_category'] != (int)Configuration::get('PS_ROOT_CATEGORY') || (Tools::isSubmit('ajax') && Tools::getValue('action') == 'getCategoriesFromRootCategory')) - $root_input = ' + $root_input = ''; + if ($root['id_category'] != (int)Configuration::get('PS_ROOT_CATEGORY') || (Tools::isSubmit('ajax') && Tools::getValue('action') == 'getCategoriesFromRootCategory')) { + $root_input = ' <p class="checkbox"><i class="icon-folder-open"></i><label> <input type="'.(!$use_radio ? 'checkbox' : 'radio').'" name="' - .$input_name.'" value="'.$root['id_category'].'" ' - .($home_is_selected ? 'checked' : '').' onclick="clickOnCategoryBox($(this));" />' - .$root['name']. - '</label></p>'; - $html .= ' + .$input_name.'" value="'.$root['id_category'].'" ' + .($home_is_selected ? 'checked' : '').' onclick="clickOnCategoryBox($(this));" />' + .$root['name']. + '</label></p>'; + } + $html .= ' <div class="container"> <div class="well"> <ul id="categories-treeview"> @@ -279,134 +281,144 @@ class HelperCore </div> </div>'; - if ($use_search) - $html .= '<script type="text/javascript">searchCategory();</script>'; - return $html; - } + if ($use_search) { + $html .= '<script type="text/javascript">searchCategory();</script>'; + } + return $html; + } - /** - * use translations files to replace english expression. - * - * @param mixed $string term or expression in english - * @param string $class - * @param bool $addslashes if set to true, the return value will pass through addslashes(). Otherwise, stripslashes(). - * @param bool $htmlentities if set to true(default), the return value will pass through htmlentities($string, ENT_QUOTES, 'utf-8') - * @return string the translation if available, or the english default text. - */ - protected function l($string, $class = 'AdminTab', $addslashes = false, $htmlentities = true) - { - // if the class is extended by a module, use modules/[module_name]/xx.php lang file - $current_class = get_class($this); - if (Module::getModuleNameFromClass($current_class)) - return Translate::getModuleTranslation(Module::$classInModule[$current_class], $string, $current_class); + /** + * use translations files to replace english expression. + * + * @param mixed $string term or expression in english + * @param string $class + * @param bool $addslashes if set to true, the return value will pass through addslashes(). Otherwise, stripslashes(). + * @param bool $htmlentities if set to true(default), the return value will pass through htmlentities($string, ENT_QUOTES, 'utf-8') + * @return string the translation if available, or the english default text. + */ + protected function l($string, $class = 'AdminTab', $addslashes = false, $htmlentities = true) + { + // if the class is extended by a module, use modules/[module_name]/xx.php lang file + $current_class = get_class($this); + if (Module::getModuleNameFromClass($current_class)) { + return Translate::getModuleTranslation(Module::$classInModule[$current_class], $string, $current_class); + } - return Translate::getAdminTranslation($string, get_class($this), $addslashes, $htmlentities); - } + return Translate::getAdminTranslation($string, get_class($this), $addslashes, $htmlentities); + } - /** - * Render a form with potentials required fields - * - * @param string $class_name - * @param string $identifier - * @param array $table_fields - * @return string - */ - public function renderRequiredFields($class_name, $identifier, $table_fields) - { - $rules = call_user_func_array(array($class_name, 'getValidationRules'), array($class_name)); - $required_class_fields = array($identifier); - foreach ($rules['required'] as $required) - $required_class_fields[] = $required; + /** + * Render a form with potentials required fields + * + * @param string $class_name + * @param string $identifier + * @param array $table_fields + * @return string + */ + public function renderRequiredFields($class_name, $identifier, $table_fields) + { + $rules = call_user_func_array(array($class_name, 'getValidationRules'), array($class_name)); + $required_class_fields = array($identifier); + foreach ($rules['required'] as $required) { + $required_class_fields[] = $required; + } - /** @var ObjectModel $object */ - $object = new $class_name(); - $res = $object->getFieldsRequiredDatabase(); + /** @var ObjectModel $object */ + $object = new $class_name(); + $res = $object->getFieldsRequiredDatabase(); - $required_fields = array(); - foreach ($res as $row) - $required_fields[(int)$row['id_required_field']] = $row['field_name']; + $required_fields = array(); + foreach ($res as $row) { + $required_fields[(int)$row['id_required_field']] = $row['field_name']; + } - $this->tpl_vars = array( - 'table_fields' => $table_fields, - 'irow' => 0, - 'required_class_fields' => $required_class_fields, - 'required_fields' => $required_fields, - 'current' => $this->currentIndex, - 'token' => $this->token - ); + $this->tpl_vars = array( + 'table_fields' => $table_fields, + 'irow' => 0, + 'required_class_fields' => $required_class_fields, + 'required_fields' => $required_fields, + 'current' => $this->currentIndex, + 'token' => $this->token + ); - $tpl = $this->createTemplate('helpers/required_fields.tpl'); - $tpl->assign($this->tpl_vars); + $tpl = $this->createTemplate('helpers/required_fields.tpl'); + $tpl->assign($this->tpl_vars); - return $tpl->fetch(); - } + return $tpl->fetch(); + } - public function renderModulesList($modules_list) - { - $this->tpl_vars = array( - 'modules_list' => $modules_list, - 'modules_uri' => __PS_BASE_URI__.basename(_PS_MODULE_DIR_) - ); - // The translations for this are defined by AdminModules, so override the context for the translations - $override_controller_name_for_translations = Context::getContext()->override_controller_name_for_translations; - Context::getContext()->override_controller_name_for_translations = 'AdminModules'; - $tpl = $this->createTemplate('helpers/modules_list/list.tpl'); - $tpl->assign($this->tpl_vars); - $html = $tpl->fetch(); - // Restore the previous context - Context::getContext()->override_controller_name_for_translations = $override_controller_name_for_translations; - return $html; - } + public function renderModulesList($modules_list) + { + $this->tpl_vars = array( + 'modules_list' => $modules_list, + 'modules_uri' => __PS_BASE_URI__.basename(_PS_MODULE_DIR_) + ); + // The translations for this are defined by AdminModules, so override the context for the translations + $override_controller_name_for_translations = Context::getContext()->override_controller_name_for_translations; + Context::getContext()->override_controller_name_for_translations = 'AdminModules'; + $tpl = $this->createTemplate('helpers/modules_list/list.tpl'); + $tpl->assign($this->tpl_vars); + $html = $tpl->fetch(); + // Restore the previous context + Context::getContext()->override_controller_name_for_translations = $override_controller_name_for_translations; + return $html; + } - /** - * Render shop list - * - * @deprecated deprecated since 1.6.1.0 use HelperShop->getRenderedShopList - * - * @return string - */ - public static function renderShopList() - { - Tools::displayAsDeprecated(); + /** + * Render shop list + * + * @deprecated deprecated since 1.6.1.0 use HelperShop->getRenderedShopList + * + * @return string + */ + public static function renderShopList() + { + Tools::displayAsDeprecated(); - if (!Shop::isFeatureActive() || Shop::getTotalShops(false, null) < 2) - return null; + if (!Shop::isFeatureActive() || Shop::getTotalShops(false, null) < 2) { + return null; + } - $tree = Shop::getTree(); - $context = Context::getContext(); + $tree = Shop::getTree(); + $context = Context::getContext(); - // Get default value - $shop_context = Shop::getContext(); - if ($shop_context == Shop::CONTEXT_ALL || ($context->controller->multishop_context_group == false && $shop_context == Shop::CONTEXT_GROUP)) - $value = ''; - elseif ($shop_context == Shop::CONTEXT_GROUP) - $value = 'g-'.Shop::getContextShopGroupID(); - else - $value = 's-'.Shop::getContextShopID(); + // Get default value + $shop_context = Shop::getContext(); + if ($shop_context == Shop::CONTEXT_ALL || ($context->controller->multishop_context_group == false && $shop_context == Shop::CONTEXT_GROUP)) { + $value = ''; + } elseif ($shop_context == Shop::CONTEXT_GROUP) { + $value = 'g-'.Shop::getContextShopGroupID(); + } else { + $value = 's-'.Shop::getContextShopID(); + } - // Generate HTML - $url = $_SERVER['REQUEST_URI'].(($_SERVER['QUERY_STRING']) ? '&' : '?').'setShopContext='; - $shop = new Shop(Shop::getContextShopID()); + // Generate HTML + $url = $_SERVER['REQUEST_URI'].(($_SERVER['QUERY_STRING']) ? '&' : '?').'setShopContext='; + $shop = new Shop(Shop::getContextShopID()); - // $html = '<a href="#"><i class="icon-home"></i> '.$shop->name.'</a>'; - $html = '<select class="shopList" onchange="location.href = \''.htmlspecialchars($url).'\'+$(this).val();">'; - $html .= '<option value="" class="first">'.Translate::getAdminTranslation('All shops').'</option>'; + // $html = '<a href="#"><i class="icon-home"></i> '.$shop->name.'</a>'; + $html = '<select class="shopList" onchange="location.href = \''.htmlspecialchars($url).'\'+$(this).val();">'; + $html .= '<option value="" class="first">'.Translate::getAdminTranslation('All shops').'</option>'; - foreach ($tree as $group_id => $group_data) - { - if ((!isset($context->controller->multishop_context) || $context->controller->multishop_context & Shop::CONTEXT_GROUP)) - $html .= '<option class="group" value="g-'.$group_id.'"'.(((empty($value) && $shop_context == Shop::CONTEXT_GROUP) || $value == 'g-'.$group_id) ? ' selected="selected"' : '').($context->controller->multishop_context_group == false ? ' disabled="disabled"' : '').'>'.Translate::getAdminTranslation('Group:').' '.htmlspecialchars($group_data['name']).'</option>'; - else - $html .= '<optgroup class="group" label="'.Translate::getAdminTranslation('Group:').' '.htmlspecialchars($group_data['name']).'"'.($context->controller->multishop_context_group == false ? ' disabled="disabled"' : '').'>'; - if (!isset($context->controller->multishop_context) || $context->controller->multishop_context & Shop::CONTEXT_SHOP) - foreach ($group_data['shops'] as $shop_id => $shop_data) - if ($shop_data['active']) - $html .= '<option value="s-'.$shop_id.'" class="shop"'.(($value == 's-'.$shop_id) ? ' selected="selected"' : '').'>'.($context->controller->multishop_context_group == false ? htmlspecialchars($group_data['name']).' - ' : '').$shop_data['name'].'</option>'; - if (!(!isset($context->controller->multishop_context) || $context->controller->multishop_context & Shop::CONTEXT_GROUP)) - $html .= '</optgroup>'; - } - $html .= '</select>'; + foreach ($tree as $group_id => $group_data) { + if ((!isset($context->controller->multishop_context) || $context->controller->multishop_context & Shop::CONTEXT_GROUP)) { + $html .= '<option class="group" value="g-'.$group_id.'"'.(((empty($value) && $shop_context == Shop::CONTEXT_GROUP) || $value == 'g-'.$group_id) ? ' selected="selected"' : '').($context->controller->multishop_context_group == false ? ' disabled="disabled"' : '').'>'.Translate::getAdminTranslation('Group:').' '.htmlspecialchars($group_data['name']).'</option>'; + } else { + $html .= '<optgroup class="group" label="'.Translate::getAdminTranslation('Group:').' '.htmlspecialchars($group_data['name']).'"'.($context->controller->multishop_context_group == false ? ' disabled="disabled"' : '').'>'; + } + if (!isset($context->controller->multishop_context) || $context->controller->multishop_context & Shop::CONTEXT_SHOP) { + foreach ($group_data['shops'] as $shop_id => $shop_data) { + if ($shop_data['active']) { + $html .= '<option value="s-'.$shop_id.'" class="shop"'.(($value == 's-'.$shop_id) ? ' selected="selected"' : '').'>'.($context->controller->multishop_context_group == false ? htmlspecialchars($group_data['name']).' - ' : '').$shop_data['name'].'</option>'; + } + } + } + if (!(!isset($context->controller->multishop_context) || $context->controller->multishop_context & Shop::CONTEXT_GROUP)) { + $html .= '</optgroup>'; + } + } + $html .= '</select>'; - return $html; - } + return $html; + } } diff --git a/classes/helper/HelperCalendar.php b/classes/helper/HelperCalendar.php index 3dde5c1c..fbe891df 100644 --- a/classes/helper/HelperCalendar.php +++ b/classes/helper/HelperCalendar.php @@ -26,229 +26,243 @@ class HelperCalendarCore extends Helper { - const DEFAULT_DATE_FORMAT = 'Y-mm-dd'; - const DEFAULT_COMPARE_OPTION = 1; + const DEFAULT_DATE_FORMAT = 'Y-mm-dd'; + const DEFAULT_COMPARE_OPTION = 1; - private $_actions; - private $_compare_actions; - private $_compare_date_from; - private $_compare_date_to; - private $_compare_date_option; - private $_date_format; - private $_date_from; - private $_date_to; - private $_rtl; + private $_actions; + private $_compare_actions; + private $_compare_date_from; + private $_compare_date_to; + private $_compare_date_option; + private $_date_format; + private $_date_from; + private $_date_to; + private $_rtl; - public function __construct() - { - $this->base_folder = 'helpers/calendar/'; - $this->base_tpl = 'calendar.tpl'; - parent::__construct(); - } + public function __construct() + { + $this->base_folder = 'helpers/calendar/'; + $this->base_tpl = 'calendar.tpl'; + parent::__construct(); + } - public function setActions($value) - { - if (!is_array($value) && !$value instanceof Traversable) - throw new PrestaShopException('Actions value must be an traversable array'); + public function setActions($value) + { + if (!is_array($value) && !$value instanceof Traversable) { + throw new PrestaShopException('Actions value must be an traversable array'); + } - $this->_actions = $value; - return $this; - } + $this->_actions = $value; + return $this; + } - public function getActions() - { - if (!isset($this->_actions)) - $this->_actions = array(); + public function getActions() + { + if (!isset($this->_actions)) { + $this->_actions = array(); + } - return $this->_actions; - } + return $this->_actions; + } - public function setCompareActions($value) - { - if (!is_array($value) && !$value instanceof Traversable) - throw new PrestaShopException('Actions value must be an traversable array'); + public function setCompareActions($value) + { + if (!is_array($value) && !$value instanceof Traversable) { + throw new PrestaShopException('Actions value must be an traversable array'); + } - $this->_compare_actions = $value; - return $this; - } + $this->_compare_actions = $value; + return $this; + } - public function getCompareActions() - { - if (!isset($this->_compare_actions)) - $this->_compare_actions = array(); + public function getCompareActions() + { + if (!isset($this->_compare_actions)) { + $this->_compare_actions = array(); + } - return $this->_compare_actions; - } + return $this->_compare_actions; + } - public function setCompareDateFrom($value) - { - $this->_compare_date_from = $value; - return $this; - } + public function setCompareDateFrom($value) + { + $this->_compare_date_from = $value; + return $this; + } - public function getCompareDateFrom() - { - return $this->_compare_date_from; - } + public function getCompareDateFrom() + { + return $this->_compare_date_from; + } - public function setCompareDateTo($value) - { - $this->_compare_date_to = $value; - return $this; - } + public function setCompareDateTo($value) + { + $this->_compare_date_to = $value; + return $this; + } - public function getCompareDateTo() - { - return $this->_compare_date_to; - } + public function getCompareDateTo() + { + return $this->_compare_date_to; + } - public function setCompareOption($value) - { - $this->_compare_date_option = (int)$value; - return $this; - } + public function setCompareOption($value) + { + $this->_compare_date_option = (int)$value; + return $this; + } - public function getCompareOption() - { - if (!isset($this->_compare_date_option)) - $this->_compare_date_option = self::DEFAULT_COMPARE_OPTION; + public function getCompareOption() + { + if (!isset($this->_compare_date_option)) { + $this->_compare_date_option = self::DEFAULT_COMPARE_OPTION; + } - return $this->_compare_date_option; - } + return $this->_compare_date_option; + } - public function setDateFormat($value) - { - if (!is_string($value)) - throw new PrestaShopException('Date format must be a string'); + public function setDateFormat($value) + { + if (!is_string($value)) { + throw new PrestaShopException('Date format must be a string'); + } - $this->_date_format = $value; - return $this; - } + $this->_date_format = $value; + return $this; + } - public function getDateFormat() - { - if (!isset($this->_date_format)) - $this->_date_format = self::DEFAULT_DATE_FORMAT; + public function getDateFormat() + { + if (!isset($this->_date_format)) { + $this->_date_format = self::DEFAULT_DATE_FORMAT; + } - return $this->_date_format; - } + return $this->_date_format; + } - public function setDateFrom($value) - { - if (!isset($value) || $value == '') - $value = date('Y-m-d', strtotime('-31 days')); + public function setDateFrom($value) + { + if (!isset($value) || $value == '') { + $value = date('Y-m-d', strtotime('-31 days')); + } - if (!is_string($value)) - throw new PrestaShopException('Date must be a string'); + if (!is_string($value)) { + throw new PrestaShopException('Date must be a string'); + } - $this->_date_from = $value; - return $this; - } + $this->_date_from = $value; + return $this; + } - public function getDateFrom() - { - if (!isset($this->_date_from)) - $this->_date_from = date('Y-m-d', strtotime('-31 days')); + public function getDateFrom() + { + if (!isset($this->_date_from)) { + $this->_date_from = date('Y-m-d', strtotime('-31 days')); + } - return $this->_date_from; - } + return $this->_date_from; + } - public function setDateTo($value) - { - if (!isset($value) || $value == '') - $value = date('Y-m-d'); + public function setDateTo($value) + { + if (!isset($value) || $value == '') { + $value = date('Y-m-d'); + } - if (!is_string($value)) - throw new PrestaShopException('Date must be a string'); + if (!is_string($value)) { + throw new PrestaShopException('Date must be a string'); + } - $this->_date_to = $value; - return $this; - } + $this->_date_to = $value; + return $this; + } - public function getDateTo() - { - if (!isset($this->_date_to)) - $this->_date_to = date('Y-m-d'); + public function getDateTo() + { + if (!isset($this->_date_to)) { + $this->_date_to = date('Y-m-d'); + } - return $this->_date_to; - } + return $this->_date_to; + } - public function setRTL($value) - { - $this->_rtl = (bool)$value; - return $this; - } + public function setRTL($value) + { + $this->_rtl = (bool)$value; + return $this; + } - public function addAction($action) - { - if (!isset($this->_actions)) - $this->_actions = array(); + public function addAction($action) + { + if (!isset($this->_actions)) { + $this->_actions = array(); + } - $this->_actions[] = $action; + $this->_actions[] = $action; - return $this; - } + return $this; + } - public function addCompareAction($action) - { - if (!isset($this->_compare_actions)) - $this->_compare_actions = array(); + public function addCompareAction($action) + { + if (!isset($this->_compare_actions)) { + $this->_compare_actions = array(); + } - $this->_compare_actions[] = $action; + $this->_compare_actions[] = $action; - return $this; - } + return $this; + } - public function generate() - { - $context = Context::getContext(); - $admin_webpath = str_ireplace(_PS_CORE_DIR_, '', _PS_ADMIN_DIR_); - $admin_webpath = preg_replace('/^'.preg_quote(DIRECTORY_SEPARATOR, '/').'/', '', $admin_webpath); - $bo_theme = ((Validate::isLoadedObject($context->employee) - && $context->employee->bo_theme) ? $context->employee->bo_theme : 'default'); + public function generate() + { + $context = Context::getContext(); + $admin_webpath = str_ireplace(_PS_CORE_DIR_, '', _PS_ADMIN_DIR_); + $admin_webpath = preg_replace('/^'.preg_quote(DIRECTORY_SEPARATOR, '/').'/', '', $admin_webpath); + $bo_theme = ((Validate::isLoadedObject($context->employee) + && $context->employee->bo_theme) ? $context->employee->bo_theme : 'default'); - if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR - .'template')) - $bo_theme = 'default'; + if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR + .'template')) { + $bo_theme = 'default'; + } - if ($context->controller->ajax) - { - $html = '<script type="text/javascript" src="'.__PS_BASE_URI__.$admin_webpath - .'/themes/'.$bo_theme.'/js/date-range-picker.js"></script>'; - $html .= '<script type="text/javascript" src="'.__PS_BASE_URI__.$admin_webpath - .'/themes/'.$bo_theme.'/js/calendar.js"></script>'; - } - else - { - $html = ''; - $context->controller->addJs(__PS_BASE_URI__.$admin_webpath - .'/themes/'.$bo_theme.'/js/date-range-picker.js'); - $context->controller->addJs(__PS_BASE_URI__.$admin_webpath - .'/themes/'.$bo_theme.'/js/calendar.js'); - } + if ($context->controller->ajax) { + $html = '<script type="text/javascript" src="'.__PS_BASE_URI__.$admin_webpath + .'/themes/'.$bo_theme.'/js/date-range-picker.js"></script>'; + $html .= '<script type="text/javascript" src="'.__PS_BASE_URI__.$admin_webpath + .'/themes/'.$bo_theme.'/js/calendar.js"></script>'; + } else { + $html = ''; + $context->controller->addJs(__PS_BASE_URI__.$admin_webpath + .'/themes/'.$bo_theme.'/js/date-range-picker.js'); + $context->controller->addJs(__PS_BASE_URI__.$admin_webpath + .'/themes/'.$bo_theme.'/js/calendar.js'); + } - $this->tpl = $this->createTemplate($this->base_tpl); - $this->tpl->assign(array( - 'date_format' => $this->getDateFormat(), - 'date_from' => $this->getDateFrom(), - 'date_to' => $this->getDateTo(), - 'compare_date_from' => $this->getCompareDateFrom(), - 'compare_date_to' => $this->getCompareDateTo(), - 'actions' => $this->getActions(), - 'compare_actions' => $this->getCompareActions(), - 'compare_option' => $this->getCompareOption(), - 'is_rtl' => $this->isRTL() - )); + $this->tpl = $this->createTemplate($this->base_tpl); + $this->tpl->assign(array( + 'date_format' => $this->getDateFormat(), + 'date_from' => $this->getDateFrom(), + 'date_to' => $this->getDateTo(), + 'compare_date_from' => $this->getCompareDateFrom(), + 'compare_date_to' => $this->getCompareDateTo(), + 'actions' => $this->getActions(), + 'compare_actions' => $this->getCompareActions(), + 'compare_option' => $this->getCompareOption(), + 'is_rtl' => $this->isRTL() + )); - $html .= parent::generate(); - return $html; - } + $html .= parent::generate(); + return $html; + } - public function isRTL() - { - if (!isset($this->_rtl)) - $this->_rtl = Context::getContext()->language->is_rtl; + public function isRTL() + { + if (!isset($this->_rtl)) { + $this->_rtl = Context::getContext()->language->is_rtl; + } - return $this->_rtl; - } + return $this->_rtl; + } } diff --git a/classes/helper/HelperForm.php b/classes/helper/HelperForm.php index fbe62f47..88243b86 100644 --- a/classes/helper/HelperForm.php +++ b/classes/helper/HelperForm.php @@ -29,287 +29,301 @@ */ class HelperFormCore extends Helper { - public $id; - public $first_call = true; + public $id; + public $first_call = true; - /** @var array of forms fields */ - protected $fields_form = array(); + /** @var array of forms fields */ + protected $fields_form = array(); - /** @var array values of form fields */ - public $fields_value = array(); - public $name_controller = ''; + /** @var array values of form fields */ + public $fields_value = array(); + public $name_controller = ''; - /** @var string if not null, a title will be added on that list */ - public $title = null; + /** @var string if not null, a title will be added on that list */ + public $title = null; - /** @var string Used to override default 'submitAdd' parameter in form action attribute */ - public $submit_action; + /** @var string Used to override default 'submitAdd' parameter in form action attribute */ + public $submit_action; - public $token; - public $languages = null; - public $default_form_language = null; - public $allow_employee_form_lang = null; - public $show_cancel_button = false; - public $back_url = '#'; + public $token; + public $languages = null; + public $default_form_language = null; + public $allow_employee_form_lang = null; + public $show_cancel_button = false; + public $back_url = '#'; - public function __construct() - { - $this->base_folder = 'helpers/form/'; - $this->base_tpl = 'form.tpl'; - parent::__construct(); - } + public function __construct() + { + $this->base_folder = 'helpers/form/'; + $this->base_tpl = 'form.tpl'; + parent::__construct(); + } - public function generateForm($fields_form) - { - $this->fields_form = $fields_form; - return $this->generate(); - } + public function generateForm($fields_form) + { + $this->fields_form = $fields_form; + return $this->generate(); + } - public function generate() - { - $this->tpl = $this->createTemplate($this->base_tpl); - if (is_null($this->submit_action)) - $this->submit_action = 'submitAdd'.$this->table; + public function generate() + { + $this->tpl = $this->createTemplate($this->base_tpl); + if (is_null($this->submit_action)) { + $this->submit_action = 'submitAdd'.$this->table; + } - $categories = true; - $color = true; - $date = true; - $tinymce = true; - $textarea_autosize = true; - $file = true; - foreach ($this->fields_form as $fieldset_key => &$fieldset) - { - if (isset($fieldset['form']['tabs'])) - $tabs[] = $fieldset['form']['tabs']; + $categories = true; + $color = true; + $date = true; + $tinymce = true; + $textarea_autosize = true; + $file = true; + foreach ($this->fields_form as $fieldset_key => &$fieldset) { + if (isset($fieldset['form']['tabs'])) { + $tabs[] = $fieldset['form']['tabs']; + } - if (isset($fieldset['form']['input'])) - foreach ($fieldset['form']['input'] as $key => &$params) - { - // If the condition is not met, the field will not be displayed - if (isset($params['condition']) && !$params['condition']) - unset($this->fields_form[$fieldset_key]['form']['input'][$key]); - switch ($params['type']) - { - case 'categories': - if ($categories) - { - if (!isset($params['tree']['id'])) - throw new PrestaShopException('Id must be filled for categories tree'); + if (isset($fieldset['form']['input'])) { + foreach ($fieldset['form']['input'] as $key => &$params) { + // If the condition is not met, the field will not be displayed + if (isset($params['condition']) && !$params['condition']) { + unset($this->fields_form[$fieldset_key]['form']['input'][$key]); + } + switch ($params['type']) { + case 'categories': + if ($categories) { + if (!isset($params['tree']['id'])) { + throw new PrestaShopException('Id must be filled for categories tree'); + } - $tree = new HelperTreeCategories($params['tree']['id'], isset($params['tree']['title']) ? $params['tree']['title'] : null); + $tree = new HelperTreeCategories($params['tree']['id'], isset($params['tree']['title']) ? $params['tree']['title'] : null); - if (isset($params['name'])) - $tree->setInputName($params['name']); + if (isset($params['name'])) { + $tree->setInputName($params['name']); + } - if (isset($params['tree']['selected_categories'])) - $tree->setSelectedCategories($params['tree']['selected_categories']); + if (isset($params['tree']['selected_categories'])) { + $tree->setSelectedCategories($params['tree']['selected_categories']); + } - if (isset($params['tree']['disabled_categories'])) - $tree->setDisabledCategories($params['tree']['disabled_categories']); + if (isset($params['tree']['disabled_categories'])) { + $tree->setDisabledCategories($params['tree']['disabled_categories']); + } - if (isset($params['tree']['root_category'])) - $tree->setRootCategory($params['tree']['root_category']); + if (isset($params['tree']['root_category'])) { + $tree->setRootCategory($params['tree']['root_category']); + } - if (isset($params['tree']['use_search'])) - $tree->setUseSearch($params['tree']['use_search']); + if (isset($params['tree']['use_search'])) { + $tree->setUseSearch($params['tree']['use_search']); + } - if (isset($params['tree']['use_checkbox'])) - $tree->setUseCheckBox($params['tree']['use_checkbox']); + if (isset($params['tree']['use_checkbox'])) { + $tree->setUseCheckBox($params['tree']['use_checkbox']); + } - if (isset($params['tree']['set_data'])) - $tree->setData($params['tree']['set_data']); + if (isset($params['tree']['set_data'])) { + $tree->setData($params['tree']['set_data']); + } - $this->context->smarty->assign('categories_tree', $tree->render()); - $categories = false; - } - break; + $this->context->smarty->assign('categories_tree', $tree->render()); + $categories = false; + } + break; - case 'file': - $uploader = new HelperUploader(); - $uploader->setId(isset($params['id'])?$params['id']:null); - $uploader->setName($params['name']); - $uploader->setUrl(isset($params['url'])?$params['url']:null); - $uploader->setMultiple(isset($params['multiple'])?$params['multiple']:false); - $uploader->setUseAjax(isset($params['ajax'])?$params['ajax']:false); - $uploader->setMaxFiles(isset($params['max_files'])?$params['max_files']:null); + case 'file': + $uploader = new HelperUploader(); + $uploader->setId(isset($params['id'])?$params['id']:null); + $uploader->setName($params['name']); + $uploader->setUrl(isset($params['url'])?$params['url']:null); + $uploader->setMultiple(isset($params['multiple'])?$params['multiple']:false); + $uploader->setUseAjax(isset($params['ajax'])?$params['ajax']:false); + $uploader->setMaxFiles(isset($params['max_files'])?$params['max_files']:null); - if (isset($params['files']) && $params['files']) - $uploader->setFiles($params['files']); - elseif (isset($params['image']) && $params['image']) // Use for retrocompatibility - $uploader->setFiles(array( - 0 => array( - 'type' => HelperUploader::TYPE_IMAGE, - 'image' => isset($params['image'])?$params['image']:null, - 'size' => isset($params['size'])?$params['size']:null, - 'delete_url' => isset($params['delete_url'])?$params['delete_url']:null - ))); + if (isset($params['files']) && $params['files']) { + $uploader->setFiles($params['files']); + } elseif (isset($params['image']) && $params['image']) { // Use for retrocompatibility + $uploader->setFiles(array( + 0 => array( + 'type' => HelperUploader::TYPE_IMAGE, + 'image' => isset($params['image'])?$params['image']:null, + 'size' => isset($params['size'])?$params['size']:null, + 'delete_url' => isset($params['delete_url'])?$params['delete_url']:null + ))); + } - if (isset($params['file']) && $params['file']) // Use for retrocompatibility - $uploader->setFiles(array( - 0 => array( - 'type' => HelperUploader::TYPE_FILE, - 'size' => isset($params['size'])?$params['size']:null, - 'delete_url' => isset($params['delete_url'])?$params['delete_url']:null, - 'download_url' => isset($params['file'])?$params['file']:null - ))); + if (isset($params['file']) && $params['file']) { // Use for retrocompatibility + $uploader->setFiles(array( + 0 => array( + 'type' => HelperUploader::TYPE_FILE, + 'size' => isset($params['size'])?$params['size']:null, + 'delete_url' => isset($params['delete_url'])?$params['delete_url']:null, + 'download_url' => isset($params['file'])?$params['file']:null + ))); + } - if (isset($params['thumb']) && $params['thumb']) // Use for retrocompatibility - $uploader->setFiles(array( - 0 => array( - 'type' => HelperUploader::TYPE_IMAGE, - 'image' => isset($params['thumb'])?'<img src="'.$params['thumb'].'" alt="'.(isset($params['title']) ? $params['title'] : '').'" title="'.(isset($params['title']) ? $params['title'] : '').'" />':null, - ))); + if (isset($params['thumb']) && $params['thumb']) { // Use for retrocompatibility + $uploader->setFiles(array( + 0 => array( + 'type' => HelperUploader::TYPE_IMAGE, + 'image' => isset($params['thumb'])?'<img src="'.$params['thumb'].'" alt="'.(isset($params['title']) ? $params['title'] : '').'" title="'.(isset($params['title']) ? $params['title'] : '').'" />':null, + ))); + } - $uploader->setTitle(isset($params['title'])?$params['title']:null); - $params['file'] = $uploader->render(); - break; + $uploader->setTitle(isset($params['title'])?$params['title']:null); + $params['file'] = $uploader->render(); + break; - case 'color': - if ($color) - { - // Added JS file - $this->context->controller->addJqueryPlugin('colorpicker'); - $color = false; - } - break; + case 'color': + if ($color) { + // Added JS file + $this->context->controller->addJqueryPlugin('colorpicker'); + $color = false; + } + break; - case 'date': - if ($date) - { - $this->context->controller->addJqueryUI('ui.datepicker'); - $date = false; - } - break; + case 'date': + if ($date) { + $this->context->controller->addJqueryUI('ui.datepicker'); + $date = false; + } + break; - case 'textarea': - if ($tinymce) - { - $iso = $this->context->language->iso_code; - $this->tpl_vars['iso'] = file_exists(_PS_CORE_DIR_.'/js/tiny_mce/langs/'.$iso.'.js') ? $iso : 'en'; - $this->tpl_vars['path_css'] = _THEME_CSS_DIR_; - $this->tpl_vars['ad'] = __PS_BASE_URI__.basename(_PS_ADMIN_DIR_); - $this->tpl_vars['tinymce'] = true; + case 'textarea': + if ($tinymce) { + $iso = $this->context->language->iso_code; + $this->tpl_vars['iso'] = file_exists(_PS_CORE_DIR_.'/js/tiny_mce/langs/'.$iso.'.js') ? $iso : 'en'; + $this->tpl_vars['path_css'] = _THEME_CSS_DIR_; + $this->tpl_vars['ad'] = __PS_BASE_URI__.basename(_PS_ADMIN_DIR_); + $this->tpl_vars['tinymce'] = true; - $this->context->controller->addJS(_PS_JS_DIR_.'tiny_mce/tiny_mce.js'); - $this->context->controller->addJS(_PS_JS_DIR_.'admin/tinymce.inc.js'); - $tinymce = false; - } + $this->context->controller->addJS(_PS_JS_DIR_.'tiny_mce/tiny_mce.js'); + $this->context->controller->addJS(_PS_JS_DIR_.'admin/tinymce.inc.js'); + $tinymce = false; + } - if ($textarea_autosize) - { - $this->context->controller->addJqueryPlugin('autosize'); - $textarea_autosize = false; - } - break; + if ($textarea_autosize) { + $this->context->controller->addJqueryPlugin('autosize'); + $textarea_autosize = false; + } + break; - case 'shop' : - $disable_shops = isset($params['disable_shared']) ? $params['disable_shared'] : false; - $params['html'] = $this->renderAssoShop($disable_shops); - if (Shop::getTotalShops(false) == 1) - if ((isset($this->fields_form[$fieldset_key]['form']['force']) && !$this->fields_form[$fieldset_key]['form']['force']) || !isset($this->fields_form[$fieldset_key]['form']['force'])) - unset($this->fields_form[$fieldset_key]['form']['input'][$key]); - break; - } - } - } + case 'shop' : + $disable_shops = isset($params['disable_shared']) ? $params['disable_shared'] : false; + $params['html'] = $this->renderAssoShop($disable_shops); + if (Shop::getTotalShops(false) == 1) { + if ((isset($this->fields_form[$fieldset_key]['form']['force']) && !$this->fields_form[$fieldset_key]['form']['force']) || !isset($this->fields_form[$fieldset_key]['form']['force'])) { + unset($this->fields_form[$fieldset_key]['form']['input'][$key]); + } + } + break; + } + } + } + } - $this->tpl->assign(array( - 'title' => $this->title, - 'toolbar_btn' => $this->toolbar_btn, - 'show_toolbar' => $this->show_toolbar, - 'toolbar_scroll' => $this->toolbar_scroll, - 'submit_action' => $this->submit_action, - 'firstCall' => $this->first_call, - 'current' => $this->currentIndex, - 'token' => $this->token, - 'table' => $this->table, - 'identifier' => $this->identifier, - 'name_controller' => $this->name_controller, - 'languages' => $this->languages, - 'current_id_lang' => $this->context->language->id, - 'defaultFormLanguage' => $this->default_form_language, - 'allowEmployeeFormLang' => $this->allow_employee_form_lang, - 'form_id' => $this->id, - 'tabs' => (isset($tabs)) ? $tabs : null, - 'fields' => $this->fields_form, - 'fields_value' => $this->fields_value, - 'required_fields' => $this->getFieldsRequired(), - 'vat_number' => Module::isInstalled('vatnumber') && file_exists(_PS_MODULE_DIR_.'vatnumber/ajax.php'), - 'module_dir' => _MODULE_DIR_, - 'base_url' => $this->context->shop->getBaseURL(), - 'contains_states' => (isset($this->fields_value['id_country']) && isset($this->fields_value['id_state'])) ? Country::containsStates($this->fields_value['id_country']) : null, - 'show_cancel_button' => $this->show_cancel_button, - 'back_url' => $this->back_url - )); + $this->tpl->assign(array( + 'title' => $this->title, + 'toolbar_btn' => $this->toolbar_btn, + 'show_toolbar' => $this->show_toolbar, + 'toolbar_scroll' => $this->toolbar_scroll, + 'submit_action' => $this->submit_action, + 'firstCall' => $this->first_call, + 'current' => $this->currentIndex, + 'token' => $this->token, + 'table' => $this->table, + 'identifier' => $this->identifier, + 'name_controller' => $this->name_controller, + 'languages' => $this->languages, + 'current_id_lang' => $this->context->language->id, + 'defaultFormLanguage' => $this->default_form_language, + 'allowEmployeeFormLang' => $this->allow_employee_form_lang, + 'form_id' => $this->id, + 'tabs' => (isset($tabs)) ? $tabs : null, + 'fields' => $this->fields_form, + 'fields_value' => $this->fields_value, + 'required_fields' => $this->getFieldsRequired(), + 'vat_number' => Module::isInstalled('vatnumber') && file_exists(_PS_MODULE_DIR_.'vatnumber/ajax.php'), + 'module_dir' => _MODULE_DIR_, + 'base_url' => $this->context->shop->getBaseURL(), + 'contains_states' => (isset($this->fields_value['id_country']) && isset($this->fields_value['id_state'])) ? Country::containsStates($this->fields_value['id_country']) : null, + 'show_cancel_button' => $this->show_cancel_button, + 'back_url' => $this->back_url + )); - return parent::generate(); - } + return parent::generate(); + } - /** - * Return true if there are required fields - */ - public function getFieldsRequired() - { - foreach ($this->fields_form as $fieldset) - if (isset($fieldset['form']['input'])) - foreach ($fieldset['form']['input'] as $input) - if (!empty($input['required']) && $input['type'] != 'radio') - return true; - return false; - } + /** + * Return true if there are required fields + */ + public function getFieldsRequired() + { + foreach ($this->fields_form as $fieldset) { + if (isset($fieldset['form']['input'])) { + foreach ($fieldset['form']['input'] as $input) { + if (!empty($input['required']) && $input['type'] != 'radio') { + return true; + } + } + } + } + return false; + } - /** - * Render an area to determinate shop association - * - * @return string - */ - public function renderAssoShop($disable_shared = false, $template_directory = null) - { - if (!Shop::isFeatureActive()) - return; + /** + * Render an area to determinate shop association + * + * @return string + */ + public function renderAssoShop($disable_shared = false, $template_directory = null) + { + if (!Shop::isFeatureActive()) { + return; + } - $assos = array(); - if ((int)$this->id) - { - $sql = 'SELECT `id_shop`, `'.bqSQL($this->identifier).'` + $assos = array(); + if ((int)$this->id) { + $sql = 'SELECT `id_shop`, `'.bqSQL($this->identifier).'` FROM `'._DB_PREFIX_.bqSQL($this->table).'_shop` WHERE `'.bqSQL($this->identifier).'` = '.(int)$this->id; - foreach (Db::getInstance()->executeS($sql) as $row) - $assos[$row['id_shop']] = $row['id_shop']; - } - else - { - switch (Shop::getContext()) - { - case Shop::CONTEXT_SHOP : - $assos[Shop::getContextShopID()] = Shop::getContextShopID(); - break; + foreach (Db::getInstance()->executeS($sql) as $row) { + $assos[$row['id_shop']] = $row['id_shop']; + } + } else { + switch (Shop::getContext()) { + case Shop::CONTEXT_SHOP : + $assos[Shop::getContextShopID()] = Shop::getContextShopID(); + break; - case Shop::CONTEXT_GROUP : - foreach (Shop::getShops(false, Shop::getContextShopGroupID(), true) as $id_shop) - $assos[$id_shop] = $id_shop; - break; + case Shop::CONTEXT_GROUP : + foreach (Shop::getShops(false, Shop::getContextShopGroupID(), true) as $id_shop) { + $assos[$id_shop] = $id_shop; + } + break; - default : - foreach (Shop::getShops(false, null, true) as $id_shop) - $assos[$id_shop] = $id_shop; - break; - } - } + default : + foreach (Shop::getShops(false, null, true) as $id_shop) { + $assos[$id_shop] = $id_shop; + } + break; + } + } - /*$nb_shop = 0; - foreach ($tree as &$value) - { - $value['disable_shops'] = (isset($value[$disable_shared]) && $value[$disable_shared]); - $nb_shop += count($value['shops']); - }*/ + /*$nb_shop = 0; + foreach ($tree as &$value) + { + $value['disable_shops'] = (isset($value[$disable_shared]) && $value[$disable_shared]); + $nb_shop += count($value['shops']); + }*/ - $tree = new HelperTreeShops('shop-tree', 'Shops'); - if (isset($template_directory)) - $tree->setTemplateDirectory($template_directory); - $tree->setSelectedShops($assos); - $tree->setAttribute('table', $this->table); - return $tree->render(); - } + $tree = new HelperTreeShops('shop-tree', 'Shops'); + if (isset($template_directory)) { + $tree->setTemplateDirectory($template_directory); + } + $tree->setSelectedShops($assos); + $tree->setAttribute('table', $this->table); + return $tree->render(); + } } diff --git a/classes/helper/HelperImageUploader.php b/classes/helper/HelperImageUploader.php index 0e226b3b..b864e2dd 100644 --- a/classes/helper/HelperImageUploader.php +++ b/classes/helper/HelperImageUploader.php @@ -26,54 +26,50 @@ class HelperImageUploaderCore extends HelperUploader { - public function getMaxSize() - { - return (int)Tools::getMaxUploadSize(); - } + public function getMaxSize() + { + return (int)Tools::getMaxUploadSize(); + } - public function getSavePath() - { - return $this->_normalizeDirectory(_PS_TMP_IMG_DIR_); - } + public function getSavePath() + { + return $this->_normalizeDirectory(_PS_TMP_IMG_DIR_); + } - public function getFilePath($file_name = null) - { - //Force file path - return tempnam($this->getSavePath(), $this->getUniqueFileName()); - } + public function getFilePath($file_name = null) + { + //Force file path + return tempnam($this->getSavePath(), $this->getUniqueFileName()); + } - protected function validate(&$file) - { - $file['error'] = $this->checkUploadError($file['error']); + protected function validate(&$file) + { + $file['error'] = $this->checkUploadError($file['error']); - $post_max_size = Tools::convertBytes(ini_get('post_max_size')); + $post_max_size = Tools::convertBytes(ini_get('post_max_size')); - $upload_max_filesize = Tools::convertBytes(ini_get('upload_max_filesize')); + $upload_max_filesize = Tools::convertBytes(ini_get('upload_max_filesize')); - if ($post_max_size && ($this->_getServerVars('CONTENT_LENGTH') > $post_max_size)) - { - $file['error'] = Tools::displayError('The uploaded file exceeds the post_max_size directive in php.ini'); - return false; - } + if ($post_max_size && ($this->_getServerVars('CONTENT_LENGTH') > $post_max_size)) { + $file['error'] = Tools::displayError('The uploaded file exceeds the post_max_size directive in php.ini'); + return false; + } - if ($upload_max_filesize && ($this->_getServerVars('CONTENT_LENGTH') > $upload_max_filesize)) - { - $file['error'] = Tools::displayError('The uploaded file exceeds the upload_max_filesize directive in php.ini'); - return false; - } + if ($upload_max_filesize && ($this->_getServerVars('CONTENT_LENGTH') > $upload_max_filesize)) { + $file['error'] = Tools::displayError('The uploaded file exceeds the upload_max_filesize directive in php.ini'); + return false; + } - if ($error = ImageManager::validateUpload($file, Tools::getMaxUploadSize($this->getMaxSize()), $this->getAcceptTypes())) - { - $file['error'] = $error; - return false; - } + if ($error = ImageManager::validateUpload($file, Tools::getMaxUploadSize($this->getMaxSize()), $this->getAcceptTypes())) { + $file['error'] = $error; + return false; + } - if ($file['size'] > $this->getMaxSize()) - { - $file['error'] = sprintf(Tools::displayError('File (size : %1s) is too big (max : %2s)'), $file['size'], $this->getMaxSize()); - return false; - } + if ($file['size'] > $this->getMaxSize()) { + $file['error'] = sprintf(Tools::displayError('File (size : %1s) is too big (max : %2s)'), $file['size'], $this->getMaxSize()); + return false; + } - return true; - } + return true; + } } diff --git a/classes/helper/HelperKpi.php b/classes/helper/HelperKpi.php index a54e5e3b..62f90f87 100644 --- a/classes/helper/HelperKpi.php +++ b/classes/helper/HelperKpi.php @@ -26,40 +26,40 @@ class HelperKpiCore extends Helper { - public $base_folder = 'helpers/kpi/'; - public $base_tpl = 'kpi.tpl'; + public $base_folder = 'helpers/kpi/'; + public $base_tpl = 'kpi.tpl'; - public $id; - public $icon; - public $chart; - public $color; - public $title; - public $subtitle; - public $value; - public $data; - public $source; - public $refresh = true; - public $href; - public $tooltip; + public $id; + public $icon; + public $chart; + public $color; + public $title; + public $subtitle; + public $value; + public $data; + public $source; + public $refresh = true; + public $href; + public $tooltip; - public function generate() - { - $this->tpl = $this->createTemplate($this->base_tpl); + public function generate() + { + $this->tpl = $this->createTemplate($this->base_tpl); - $this->tpl->assign(array( - 'id' => $this->id, - 'icon' => $this->icon, - 'chart' => (bool)$this->chart, - 'color' => $this->color, - 'title' => $this->title, - 'subtitle' => $this->subtitle, - 'value' => $this->value, - 'data' => $this->data, - 'source' => $this->source, - 'refresh' => $this->refresh, - 'href' => $this->href, - 'tooltip' => $this->tooltip - )); - return $this->tpl->fetch(); - } -} \ No newline at end of file + $this->tpl->assign(array( + 'id' => $this->id, + 'icon' => $this->icon, + 'chart' => (bool)$this->chart, + 'color' => $this->color, + 'title' => $this->title, + 'subtitle' => $this->subtitle, + 'value' => $this->value, + 'data' => $this->data, + 'source' => $this->source, + 'refresh' => $this->refresh, + 'href' => $this->href, + 'tooltip' => $this->tooltip + )); + return $this->tpl->fetch(); + } +} diff --git a/classes/helper/HelperKpiRow.php b/classes/helper/HelperKpiRow.php index 722fa4cc..8dc11d1f 100644 --- a/classes/helper/HelperKpiRow.php +++ b/classes/helper/HelperKpiRow.php @@ -26,16 +26,16 @@ class HelperKpiRowCore extends Helper { - public $base_folder = 'helpers/kpi/'; - public $base_tpl = 'row.tpl'; + public $base_folder = 'helpers/kpi/'; + public $base_tpl = 'row.tpl'; - public $kpis = array(); + public $kpis = array(); - public function generate() - { - $this->tpl = $this->createTemplate($this->base_tpl); + public function generate() + { + $this->tpl = $this->createTemplate($this->base_tpl); - $this->tpl->assign('kpis', $this->kpis); - return $this->tpl->fetch(); - } -} \ No newline at end of file + $this->tpl->assign('kpis', $this->kpis); + return $this->tpl->fetch(); + } +} diff --git a/classes/helper/HelperList.php b/classes/helper/HelperList.php index 051b3fbc..9e5b3ebb 100644 --- a/classes/helper/HelperList.php +++ b/classes/helper/HelperList.php @@ -29,702 +29,722 @@ */ class HelperListCore extends Helper { - /** @var array Cache for query results */ - protected $_list = array(); + /** @var array Cache for query results */ + protected $_list = array(); - /** @var int Number of results in list */ - public $listTotal = 0; + /** @var int Number of results in list */ + public $listTotal = 0; - /** @var array WHERE clause determined by filter fields */ - protected $_filter; + /** @var array WHERE clause determined by filter fields */ + protected $_filter; - /** @var array Number of results in list per page (used in select field) */ - public $_pagination = array(20, 50, 100, 300, 1000); + /** @var array Number of results in list per page (used in select field) */ + public $_pagination = array(20, 50, 100, 300, 1000); - /** @var int Default number of results in list per page */ - public $_default_pagination = 50; + /** @var int Default number of results in list per page */ + public $_default_pagination = 50; - /** @var string ORDER BY clause determined by field/arrows in list header */ - public $orderBy; + /** @var string ORDER BY clause determined by field/arrows in list header */ + public $orderBy; - /** @var string Default ORDER BY clause when $orderBy is not defined */ - public $_defaultOrderBy = false; + /** @var string Default ORDER BY clause when $orderBy is not defined */ + public $_defaultOrderBy = false; - /** @var array : list of vars for button delete*/ - public $tpl_delete_link_vars = array(); + /** @var array : list of vars for button delete*/ + public $tpl_delete_link_vars = array(); - /** @var string Order way (ASC, DESC) determined by arrows in list header */ - public $orderWay; + /** @var string Order way (ASC, DESC) determined by arrows in list header */ + public $orderWay; - public $identifier; + public $identifier; - protected $deleted = 0; + protected $deleted = 0; - /** @var array $cache_lang use to cache texts in current language */ - public static $cache_lang = array(); + /** @var array $cache_lang use to cache texts in current language */ + public static $cache_lang = array(); - public $is_cms = false; + public $is_cms = false; - public $position_identifier; + public $position_identifier; - public $table_id; + public $table_id; - /** - * @var array Customize list display - * - * align : determine value alignment - * prefix : displayed before value - * suffix : displayed after value - * image : object image - * icon : icon determined by values - * active : allow to toggle status - */ - protected $fields_list; - - /** @var bool Content line is clickable if true */ - public $no_link = false; - - /** @var Smarty_Internal_Template|string */ - protected $header_tpl = 'list_header.tpl'; - - /** @var Smarty_Internal_Template|string */ - protected $content_tpl = 'list_content.tpl'; - - /** @var Smarty_Internal_Template|string */ - protected $footer_tpl = 'list_footer.tpl'; - - /** @var array list of required actions for each list row */ - public $actions = array(); - - /** @var array list of row ids associated with a given action for witch this action have to not be available */ - public $list_skip_actions = array(); - - public $bulk_actions = false; - public $force_show_bulk_actions = false; - public $specificConfirmDelete = null; - public $colorOnBackground; - - /** @var bool If true, activates color on hover */ - public $row_hover = true; - - /** @var string|null If not null, a title will be added on that list */ - public $title = null; - - /** @var bool ask for simple header : no filters, no paginations and no sorting */ - public $simple_header = false; - - public $ajax_params = array(); - - public $page; - - public function __construct() - { - $this->base_folder = 'helpers/list/'; - $this->base_tpl = 'list.tpl'; - - parent::__construct(); - } - - /** - * Return an html list given the data to fill it up - * - * @param array $list entries to display (rows) - * @param array $fields_display fields (cols) - * @return string html - */ - public function generateList($list, $fields_display) - { - // Append when we get a syntax error in SQL query - if ($list === false) - { - $this->context->controller->warnings[] = $this->l('Bad SQL query', 'Helper'); - return false; - } - - $this->tpl = $this->createTemplate($this->base_tpl); - $this->header_tpl = $this->createTemplate($this->header_tpl); - $this->content_tpl = $this->createTemplate($this->content_tpl); - $this->footer_tpl = $this->createTemplate($this->footer_tpl); - - $this->_list = $list; - $this->fields_list = $fields_display; - - $this->orderBy = preg_replace('/^([a-z _]*!)/Ui', '', $this->orderBy); - $this->orderWay = preg_replace('/^([a-z _]*!)/Ui', '', $this->orderWay); - - $this->tpl->assign(array( - 'header' => $this->displayListHeader(), // Display list header (filtering, pagination and column names) - 'content' => $this->displayListContent(), // Show the content of the table - 'footer' => $this->displayListFooter() // Close list table and submit button - )); - return parent::generate(); - } - - /** - * Fetch the template for action enable - * - * @param string $token - * @param string $id - * @param int $value state enabled or not - * @param string $active status - * @param int $id_category - * @param int $id_product - * @return string - */ - public function displayEnableLink($token, $id, $value, $active, $id_category = null, $id_product = null, $ajax = false) - { - $tpl_enable = $this->createTemplate('list_action_enable.tpl'); - $tpl_enable->assign(array( - 'ajax' => $ajax, - 'enabled' => (bool)$value, - 'url_enable' => $this->currentIndex.'&'.$this->identifier.'='.$id.'&'.$active.$this->table.($ajax ? '&action='.$active.$this->table.'&ajax='.(int)$ajax : ''). - ((int)$id_category && (int)$id_product ? '&id_category='.(int)$id_category : '').($this->page && $this->page > 1 ? '&page='.(int)$this->page : '').'&token='.($token != null ? $token : $this->token) - )); - return $tpl_enable->fetch(); - } - - public function displayListContent() - { - if (isset($this->fields_list['position'])) - { - if ($this->position_identifier) - if (isset($this->position_group_identifier)) - $position_group_identifier = Tools::getIsset($this->position_group_identifier) ? Tools::getValue($this->position_group_identifier) : $this->position_group_identifier; - else - $position_group_identifier = (int)Tools::getValue('id_'.($this->is_cms ? 'cms_' : '').'category', ($this->is_cms ? '1' : Category::getRootCategory()->id )); - else - $position_group_identifier = Category::getRootCategory()->id; - - $positions = array_map(create_function('$elem', 'return (int)($elem[\'position\']);'), $this->_list); - sort($positions); - } - - // key_to_get is used to display the correct product category or cms category after a position change - $identifier = in_array($this->identifier, array('id_category', 'id_cms_category')) ? '_parent' : ''; - if ($identifier) - $key_to_get = 'id_'.($this->is_cms ? 'cms_' : '').'category'.$identifier; - - foreach ($this->_list as $index => $tr) - { - $id = null; - if (isset($tr[$this->identifier])) - $id = $tr[$this->identifier]; - $name = isset($tr['name']) ? $tr['name'] : null; - - if ($this->shopLinkType) - $this->_list[$index]['short_shop_name'] = Tools::strlen($tr['shop_name']) > 15 ? Tools::substr($tr['shop_name'], 0, 15).'...' : $tr['shop_name']; - - $is_first = true; - // Check all available actions to add to the current list row - foreach ($this->actions as $action) - { - //Check if the action is available for the current row - if (!array_key_exists($action, $this->list_skip_actions) || !in_array($id, $this->list_skip_actions[$action])) - { - $method_name = 'display'.ucfirst($action).'Link'; - - if (method_exists($this->context->controller, $method_name)) - $this->_list[$index][$action] = $this->context->controller->$method_name($this->token, $id, $name); - elseif ($this->module instanceof Module && method_exists($this->module, $method_name)) - $this->_list[$index][$action] = $this->module->$method_name($this->token, $id, $name); - elseif (method_exists($this, $method_name)) - $this->_list[$index][$action] = $this->$method_name($this->token, $id, $name); - } - - if ($is_first && isset($this->_list[$index][$action])) - { - $is_first = false; - - if (!preg_match('/a\s*.*class/', $this->_list[$index][$action])) - $this->_list[$index][$action] = preg_replace('/href\s*=\s*\"([^\"]*)\"/', - 'href="$1" class="btn btn-default"', $this->_list[$index][$action]); - elseif (!preg_match('/a\s*.*class\s*=\s*\".*btn.*\"/', $this->_list[$index][$action])) - $this->_list[$index][$action] = preg_replace('/a(\s*.*)class\s*=\s*\"(.*)\"/', - 'a $1 class="$2 btn btn-default"', $this->_list[$index][$action]); - } - } - - // @todo skip action for bulk actions - // $this->_list[$index]['has_bulk_actions'] = true; - foreach ($this->fields_list as $key => $params) - { - $tmp = explode('!', $key); - $key = isset($tmp[1]) ? $tmp[1] : $tmp[0]; - - if (isset($params['active'])) - { - // If method is defined in calling controller, use it instead of the Helper method - if (method_exists($this->context->controller, 'displayEnableLink')) - $calling_obj = $this->context->controller; - elseif (isset($this->module) && method_exists($this->module, 'displayEnableLink')) - $calling_obj = $this->module; - else - $calling_obj = $this; - - if (!isset($params['ajax'])) - $params['ajax'] = false; - $this->_list[$index][$key] = $calling_obj->displayEnableLink( - $this->token, - $id, - $tr[$key], - $params['active'], - Tools::getValue('id_category'), - Tools::getValue('id_product'), - $params['ajax'] - ); - } - elseif (isset($params['activeVisu'])) - $this->_list[$index][$key] = (bool)$tr[$key]; - elseif (isset($params['position'])) - { - $this->_list[$index][$key] = array( - 'position' => $tr[$key], - 'position_url_down' => $this->currentIndex. - (isset($key_to_get) ? '&'.$key_to_get.'='.(int)$position_group_identifier : ''). - '&'.$this->position_identifier.'='.$id. - '&way=1&position='.((int)$tr['position'] + 1).'&token='.$this->token, - 'position_url_up' => $this->currentIndex. - (isset($key_to_get) ? '&'.$key_to_get.'='.(int)$position_group_identifier : ''). - '&'.$this->position_identifier.'='.$id. - '&way=0&position='.((int)$tr['position'] - 1).'&token='.$this->token - ); - } - elseif (isset($params['image'])) - { - // item_id is the product id in a product image context, else it is the image id. - $item_id = isset($params['image_id']) ? $tr[$params['image_id']] : $id; - if ($params['image'] != 'p' || Configuration::get('PS_LEGACY_IMAGES')) - $path_to_image = _PS_IMG_DIR_.$params['image'].'/'.$item_id.(isset($tr['id_image']) ? '-'.(int)$tr['id_image'] : '').'.'.$this->imageType; - else - $path_to_image = _PS_IMG_DIR_.$params['image'].'/'.Image::getImgFolderStatic($tr['id_image']).(int)$tr['id_image'].'.'.$this->imageType; - $this->_list[$index][$key] = ImageManager::thumbnail($path_to_image, $this->table.'_mini_'.$item_id.'_'.$this->context->shop->id.'.'.$this->imageType, 45, $this->imageType); - } - elseif (isset($params['icon']) && isset($tr[$key]) && (isset($params['icon'][$tr[$key]]) || isset($params['icon']['default']))) - { - if (!$this->bootstrap) - { - if (isset($params['icon'][$tr[$key]]) && is_array($params['icon'][$tr[$key]])) - $this->_list[$index][$key] = array( - 'src' => $params['icon'][$tr[$key]]['src'], - 'alt' => $params['icon'][$tr[$key]]['alt'], - ); - else - $this->_list[$index][$key] = array( - 'src' => isset($params['icon'][$tr[$key]]) ? $params['icon'][$tr[$key]] : $params['icon']['default'], - 'alt' => isset($params['icon'][$tr[$key]]) ? $params['icon'][$tr[$key]] : $params['icon']['default'], - ); - } - else - if (isset($params['icon'][$tr[$key]])) - $this->_list[$index][$key] = $params['icon'][$tr[$key]]; - } - elseif (isset($params['type']) && $params['type'] == 'float') - $this->_list[$index][$key] = rtrim(rtrim($tr[$key], '0'), '.'); - elseif (isset($tr[$key])) - { - $echo = $tr[$key]; - if (isset($params['callback'])) - { - $callback_obj = (isset($params['callback_object'])) ? $params['callback_object'] : $this->context->controller; - $this->_list[$index][$key] = call_user_func_array(array($callback_obj, $params['callback']), array($echo, $tr)); - } - else - $this->_list[$index][$key] = $echo; - } - } - } - - $this->content_tpl->assign(array_merge($this->tpl_vars, array( - 'shop_link_type' => $this->shopLinkType, - 'name' => isset($name) ? $name : null, - 'position_identifier' => $this->position_identifier, - 'identifier' => $this->identifier, - 'table' => $this->table, - 'token' => $this->token, - 'color_on_bg' => $this->colorOnBackground, - 'position_group_identifier' => isset($position_group_identifier) ? $position_group_identifier : false, - 'bulk_actions' => $this->bulk_actions, - 'positions' => isset($positions) ? $positions : null, - 'order_by' => $this->orderBy, - 'order_way' => $this->orderWay, - 'is_cms' => $this->is_cms, - 'fields_display' => $this->fields_list, - 'list' => $this->_list, - 'actions' => $this->actions, - 'no_link' => $this->no_link, - 'current_index' => $this->currentIndex, - 'view' => in_array('view', $this->actions), - 'edit' => in_array('edit', $this->actions), - 'has_actions' => !empty($this->actions), - 'list_skip_actions' => $this->list_skip_actions, - 'row_hover' => $this->row_hover, - 'list_id' => isset($this->list_id) ? $this->list_id : $this->table, - 'checked_boxes' => Tools::getValue((isset($this->list_id) ? $this->list_id : $this->table).'Box') - ))); - return $this->content_tpl->fetch(); - } - - /** - * Display duplicate action link - */ - public function displayDuplicateLink($token = null, $id, $name = null) - { - $tpl = $this->createTemplate('list_action_duplicate.tpl'); - if (!array_key_exists('Bad SQL query', self::$cache_lang)) - self::$cache_lang['Duplicate'] = $this->l('Duplicate', 'Helper'); - - if (!array_key_exists('Copy images too?', self::$cache_lang)) - self::$cache_lang['Copy images too?'] = $this->l('This will copy the images too. If you wish to proceed, click "Yes". If not, click "No".', 'Helper'); - - $duplicate = $this->currentIndex.'&'.$this->identifier.'='.$id.'&duplicate'.$this->table; - - $confirm = self::$cache_lang['Copy images too?']; - - if (($this->table == 'product') && !Image::hasImages($this->context->language->id, (int)$id)) - $confirm = ''; - - $tpl->assign(array( - 'href' => $this->currentIndex.'&'.$this->identifier.'='.$id.'&view'.$this->table.'&token='.($token != null ? $token : $this->token), - 'action' => self::$cache_lang['Duplicate'], - 'confirm' => $confirm, - 'location_ok' => $duplicate.'&token='.($token != null ? $token : $this->token), - 'location_ko' => $duplicate.'&noimage=1&token='.($token ? $token : $this->token), - )); - - return $tpl->fetch(); - } - - - /** - * Display action show details of a table row - * This action need an ajax request with a return like this: - * { - * use_parent_structure: true // If false, data need to be an html - * data: - * [ - * {field_name: 'value'} - * ], - * fields_display: // attribute $fields_list of the admin controller - * } - * or somethins like this: - * { - * use_parent_structure: false // If false, data need to be an html - * data: - * '<p>My html content</p>', - * fields_display: // attribute $fields_list of the admin controller - * } - */ - public function displayDetailsLink($token = null, $id, $name = null) - { - $tpl = $this->createTemplate('list_action_details.tpl'); - if (!array_key_exists('Details', self::$cache_lang)) - self::$cache_lang['Details'] = $this->l('Details', 'Helper'); - - $ajax_params = $this->ajax_params; - if (!is_array($ajax_params) || !isset($ajax_params['action'])) - $ajax_params['action'] = 'details'; - - $tpl->assign(array( - 'id' => $id, - 'href' => $this->currentIndex.'&'.$this->identifier.'='.$id.'&details'.$this->table.'&token='.($token != null ? $token : $this->token), - 'controller' => str_replace('Controller', '', get_class($this->context->controller)), - 'token' => $token != null ? $token : $this->token, - 'action' => self::$cache_lang['Details'], - 'params' => $ajax_params, - 'json_params' => Tools::jsonEncode($ajax_params) - )); - return $tpl->fetch(); - } - - /** - * Display view action link - */ - public function displayViewLink($token = null, $id, $name = null) - { - $tpl = $this->createTemplate('list_action_view.tpl'); - if (!array_key_exists('View', self::$cache_lang)) - self::$cache_lang['View'] = $this->l('View', 'Helper'); - - $tpl->assign(array( - 'href' => $this->currentIndex.'&'.$this->identifier.'='.$id.'&view'.$this->table.'&token='.($token != null ? $token : $this->token), - 'action' => self::$cache_lang['View'], - )); - - return $tpl->fetch(); - - } - - /** - * Display edit action link - */ - public function displayEditLink($token = null, $id, $name = null) - { - $tpl = $this->createTemplate('list_action_edit.tpl'); - if (!array_key_exists('Edit', self::$cache_lang)) - self::$cache_lang['Edit'] = $this->l('Edit', 'Helper'); - - $tpl->assign(array( - 'href' => $this->currentIndex.'&'.$this->identifier.'='.$id.'&update'.$this->table.($this->page && $this->page > 1 ? '&page='.(int)$this->page : '').'&token='.($token != null ? $token : $this->token), - 'action' => self::$cache_lang['Edit'], - 'id' => $id - )); - - return $tpl->fetch(); - } - - /** - * Display delete action link - */ - public function displayDeleteLink($token = null, $id, $name = null) - { - $tpl = $this->createTemplate('list_action_delete.tpl'); - - if (!array_key_exists('Delete', self::$cache_lang)) - self::$cache_lang['Delete'] = $this->l('Delete', 'Helper'); - - if (!array_key_exists('DeleteItem', self::$cache_lang)) - self::$cache_lang['DeleteItem'] = $this->l('Delete selected item?', 'Helper', true, false); - - if (!array_key_exists('Name', self::$cache_lang)) - self::$cache_lang['Name'] = $this->l('Name:', 'Helper', true, false); - - if (!is_null($name)) - $name = addcslashes('\n\n'.self::$cache_lang['Name'].' '.$name, '\''); - - $data = array( - $this->identifier => $id, - 'href' => $this->currentIndex.'&'.$this->identifier.'='.$id.'&delete'.$this->table.'&token='.($token != null ? $token : $this->token), - 'action' => self::$cache_lang['Delete'], - ); - - if ($this->specificConfirmDelete !== false) - $data['confirm'] = !is_null($this->specificConfirmDelete) ? '\r'.$this->specificConfirmDelete : Tools::safeOutput(self::$cache_lang['DeleteItem'].$name); - - $tpl->assign(array_merge($this->tpl_delete_link_vars, $data)); - - return $tpl->fetch(); - } - - /** - * Display default action link - */ - public function displayDefaultLink($token = null, $id, $name = null) - { - $tpl = $this->createTemplate('list_action_default.tpl'); - if (!array_key_exists('Default', self::$cache_lang)) - self::$cache_lang['Default'] = $this->l('Default', 'Helper'); - - $tpl->assign(array( - 'href' => $this->currentIndex.'&'.$this->identifier.'='.(int)$id.'&default'.$this->table.'&token='.($token != null ? $token : $this->token), - 'action' => self::$cache_lang['Default'], - 'name' => $name, - )); - - return $tpl->fetch(); - } - - /** - * Display list header (filtering, pagination and column names) - */ - public function displayListHeader() - { - if (!isset($this->list_id)) - $this->list_id = $this->table; - - $id_cat = (int)Tools::getValue('id_'.($this->is_cms ? 'cms_' : '').'category'); - - if (!isset($token) || empty($token)) - $token = $this->token; - - /* Determine total page number */ - $pagination = $this->_default_pagination; - if (in_array((int)Tools::getValue($this->list_id.'_pagination'), $this->_pagination)) - $pagination = (int)Tools::getValue($this->list_id.'_pagination'); - elseif (isset($this->context->cookie->{$this->list_id.'_pagination'}) && $this->context->cookie->{$this->list_id.'_pagination'}) - $pagination = $this->context->cookie->{$this->list_id.'_pagination'}; - - $total_pages = max(1, ceil($this->listTotal / $pagination)); - - $identifier = Tools::getIsset($this->identifier) ? '&'.$this->identifier.'='.(int)Tools::getValue($this->identifier) : ''; - $order = ''; - if (Tools::getIsset($this->table.'Orderby')) - $order = '&'.$this->table.'Orderby='.urlencode($this->orderBy).'&'.$this->table.'Orderway='.urlencode(strtolower($this->orderWay)); - - $action = $this->currentIndex.$identifier.'&token='.$token.'#'.$this->list_id; - - /* Determine current page number */ - $page = (int)Tools::getValue('submitFilter'.$this->list_id); - - if (!$page) - $page = 1; - - if ($page > $total_pages) - $page = $total_pages; - - $this->page = (int)$page; - - /* Choose number of results per page */ - $selected_pagination = Tools::getValue($this->list_id.'_pagination', - isset($this->context->cookie->{$this->list_id.'_pagination'}) ? $this->context->cookie->{$this->list_id.'_pagination'} : $this->_default_pagination - ); - - if (!isset($this->table_id) && $this->position_identifier && (int)Tools::getValue($this->position_identifier, 1)) - $this->table_id = substr($this->identifier, 3, strlen($this->identifier)); - - if ($this->position_identifier && ($this->orderBy == 'position' && $this->orderWay != 'DESC')) - $table_dnd = true; - - $prefix = isset($this->controller_name) ? str_replace(array('admin', 'controller'), '', Tools::strtolower($this->controller_name)) : ''; - $ajax = false; - foreach ($this->fields_list as $key => $params) - { - if (!isset($params['type'])) - $params['type'] = 'text'; - - $value_key = $prefix.$this->list_id.'Filter_'.(array_key_exists('filter_key', $params) && $key != 'active' ? $params['filter_key'] : $key); - $value = Context::getContext()->cookie->{$value_key}; - if (!$value && Tools::getIsset($value_key)) - $value = Tools::getValue($value_key); - - switch ($params['type']) - { - case 'bool': - if (isset($params['ajax']) && $params['ajax']) - $ajax = true; - break; - - case 'date': - case 'datetime': - if (is_string($value)) - $value = Tools::unSerialize($value); - if (!Validate::isCleanHtml($value[0]) || !Validate::isCleanHtml($value[1])) - $value = ''; - $name = $this->list_id.'Filter_'.(isset($params['filter_key']) ? $params['filter_key'] : $key); - $name_id = str_replace('!', '__', $name); - - $params['id_date'] = $name_id; - $params['name_date'] = $name; - - $this->context->controller->addJqueryUI('ui.datepicker'); - break; - - case 'select': - foreach ($params['list'] as $option_value => $option_display) - { - if (isset(Context::getContext()->cookie->{$prefix.$this->list_id.'Filter_'.$params['filter_key']}) - && Context::getContext()->cookie->{$prefix.$this->list_id.'Filter_'.$params['filter_key']} == $option_value - && Context::getContext()->cookie->{$prefix.$this->list_id.'Filter_'.$params['filter_key']} != '') - $this->fields_list[$key]['select'][$option_value]['selected'] = 'selected'; - } - break; - - case 'text': - if (!Validate::isCleanHtml($value)) - $value = ''; - } - - $params['value'] = $value; - $this->fields_list[$key] = $params; - } - - $has_value = false; - $has_search_field = false; - - foreach ($this->fields_list as $key => $field) - { - if (isset($field['value']) && $field['value'] !== false && $field['value'] !== '') - { - if (is_array($field['value']) && trim(implode('', $field['value'])) == '') - continue; - - $has_value = true; - break; - } - if (!(isset($field['search']) && $field['search'] === false)) - $has_search_field = true; - } - - Context::getContext()->smarty->assign(array( - 'page' => $page, - 'simple_header' => $this->simple_header, - 'total_pages' => $total_pages, - 'selected_pagination' => $selected_pagination, - 'pagination' => $this->_pagination, - 'list_total' => $this->listTotal, - 'sql' => isset($this->sql) && $this->sql ? str_replace('\n', ' ', str_replace('\r', '', $this->sql)) : false, - 'token' => $this->token, - 'table' => $this->table, - 'bulk_actions' => $this->bulk_actions, - 'show_toolbar' => $this->show_toolbar, - 'toolbar_scroll' => $this->toolbar_scroll, - 'toolbar_btn' => $this->toolbar_btn, - 'has_bulk_actions' => $this->hasBulkActions($has_value), - )); - - $this->header_tpl->assign(array_merge(array( - 'ajax' => $ajax, - 'title' => array_key_exists('title', $this->tpl_vars) ? $this->tpl_vars['title'] : $this->title, - 'show_filters' => ((count($this->_list) > 1 && $has_search_field) || $has_value ), - 'filters_has_value' => $has_value, - 'currentIndex' => $this->currentIndex, - 'action' => $action, - 'is_order_position' => $this->position_identifier && $this->orderBy == 'position', - 'order_way' => $this->orderWay, - 'order_by' => $this->orderBy, - 'fields_display' => $this->fields_list, - 'delete' => in_array('delete', $this->actions), - 'identifier' => $this->identifier, - 'id_cat' => $id_cat, - 'shop_link_type' => $this->shopLinkType, - 'has_actions' => !empty($this->actions), - 'table_id' => isset($this->table_id) ? $this->table_id : null, - 'table_dnd' => isset($table_dnd) ? $table_dnd : null, - 'name' => isset($name) ? $name : null, - 'name_id' => isset($name_id) ? $name_id : null, - 'row_hover' => $this->row_hover, - 'list_id' => isset($this->list_id) ? $this->list_id : $this->table - ), $this->tpl_vars)); - - return $this->header_tpl->fetch(); - } - - public function hasBulkActions($has_value = false) - { - if ($this->force_show_bulk_actions) - return true; - - if (count($this->_list) <= 1 && !$has_value) - return false; - - if (isset($this->list_skip_actions) && count($this->list_skip_actions) - && isset($this->bulk_actions) && is_array($this->bulk_actions) && count($this->bulk_actions)) - { - foreach ($this->bulk_actions as $action => $data) - if (array_key_exists($action, $this->list_skip_actions)) - { - foreach ($this->_list as $key => $row) - if (!in_array($row[$this->identifier], $this->list_skip_actions[$action])) - return true; - - return false; - } - } - - return !empty($this->bulk_actions); - } - - /** - * Close list table and submit button - */ - public function displayListFooter() - { - if (!isset($this->list_id)) - $this->list_id = $this->table; - - $this->footer_tpl->assign(array_merge($this->tpl_vars, array( - 'current' => $this->currentIndex, - 'list_id' => $this->list_id - ))); - return $this->footer_tpl->fetch(); - } + /** + * @var array Customize list display + * + * align : determine value alignment + * prefix : displayed before value + * suffix : displayed after value + * image : object image + * icon : icon determined by values + * active : allow to toggle status + */ + protected $fields_list; + + /** @var bool Content line is clickable if true */ + public $no_link = false; + + /** @var Smarty_Internal_Template|string */ + protected $header_tpl = 'list_header.tpl'; + + /** @var Smarty_Internal_Template|string */ + protected $content_tpl = 'list_content.tpl'; + + /** @var Smarty_Internal_Template|string */ + protected $footer_tpl = 'list_footer.tpl'; + + /** @var array list of required actions for each list row */ + public $actions = array(); + + /** @var array list of row ids associated with a given action for witch this action have to not be available */ + public $list_skip_actions = array(); + + public $bulk_actions = false; + public $force_show_bulk_actions = false; + public $specificConfirmDelete = null; + public $colorOnBackground; + + /** @var bool If true, activates color on hover */ + public $row_hover = true; + + /** @var string|null If not null, a title will be added on that list */ + public $title = null; + + /** @var bool ask for simple header : no filters, no paginations and no sorting */ + public $simple_header = false; + + public $ajax_params = array(); + + public $page; + + public function __construct() + { + $this->base_folder = 'helpers/list/'; + $this->base_tpl = 'list.tpl'; + + parent::__construct(); + } + + /** + * Return an html list given the data to fill it up + * + * @param array $list entries to display (rows) + * @param array $fields_display fields (cols) + * @return string html + */ + public function generateList($list, $fields_display) + { + // Append when we get a syntax error in SQL query + if ($list === false) { + $this->context->controller->warnings[] = $this->l('Bad SQL query', 'Helper'); + return false; + } + + $this->tpl = $this->createTemplate($this->base_tpl); + $this->header_tpl = $this->createTemplate($this->header_tpl); + $this->content_tpl = $this->createTemplate($this->content_tpl); + $this->footer_tpl = $this->createTemplate($this->footer_tpl); + + $this->_list = $list; + $this->fields_list = $fields_display; + + $this->orderBy = preg_replace('/^([a-z _]*!)/Ui', '', $this->orderBy); + $this->orderWay = preg_replace('/^([a-z _]*!)/Ui', '', $this->orderWay); + + $this->tpl->assign(array( + 'header' => $this->displayListHeader(), // Display list header (filtering, pagination and column names) + 'content' => $this->displayListContent(), // Show the content of the table + 'footer' => $this->displayListFooter() // Close list table and submit button + )); + return parent::generate(); + } + + /** + * Fetch the template for action enable + * + * @param string $token + * @param string $id + * @param int $value state enabled or not + * @param string $active status + * @param int $id_category + * @param int $id_product + * @return string + */ + public function displayEnableLink($token, $id, $value, $active, $id_category = null, $id_product = null, $ajax = false) + { + $tpl_enable = $this->createTemplate('list_action_enable.tpl'); + $tpl_enable->assign(array( + 'ajax' => $ajax, + 'enabled' => (bool)$value, + 'url_enable' => $this->currentIndex.'&'.$this->identifier.'='.$id.'&'.$active.$this->table.($ajax ? '&action='.$active.$this->table.'&ajax='.(int)$ajax : ''). + ((int)$id_category && (int)$id_product ? '&id_category='.(int)$id_category : '').($this->page && $this->page > 1 ? '&page='.(int)$this->page : '').'&token='.($token != null ? $token : $this->token) + )); + return $tpl_enable->fetch(); + } + + public function displayListContent() + { + if (isset($this->fields_list['position'])) { + if ($this->position_identifier) { + if (isset($this->position_group_identifier)) { + $position_group_identifier = Tools::getIsset($this->position_group_identifier) ? Tools::getValue($this->position_group_identifier) : $this->position_group_identifier; + } else { + $position_group_identifier = (int)Tools::getValue('id_'.($this->is_cms ? 'cms_' : '').'category', ($this->is_cms ? '1' : Category::getRootCategory()->id)); + } + } else { + $position_group_identifier = Category::getRootCategory()->id; + } + + $positions = array_map(create_function('$elem', 'return (int)($elem[\'position\']);'), $this->_list); + sort($positions); + } + + // key_to_get is used to display the correct product category or cms category after a position change + $identifier = in_array($this->identifier, array('id_category', 'id_cms_category')) ? '_parent' : ''; + if ($identifier) { + $key_to_get = 'id_'.($this->is_cms ? 'cms_' : '').'category'.$identifier; + } + + foreach ($this->_list as $index => $tr) { + $id = null; + if (isset($tr[$this->identifier])) { + $id = $tr[$this->identifier]; + } + $name = isset($tr['name']) ? $tr['name'] : null; + + if ($this->shopLinkType) { + $this->_list[$index]['short_shop_name'] = Tools::strlen($tr['shop_name']) > 15 ? Tools::substr($tr['shop_name'], 0, 15).'...' : $tr['shop_name']; + } + + $is_first = true; + // Check all available actions to add to the current list row + foreach ($this->actions as $action) { + //Check if the action is available for the current row + if (!array_key_exists($action, $this->list_skip_actions) || !in_array($id, $this->list_skip_actions[$action])) { + $method_name = 'display'.ucfirst($action).'Link'; + + if (method_exists($this->context->controller, $method_name)) { + $this->_list[$index][$action] = $this->context->controller->$method_name($this->token, $id, $name); + } elseif ($this->module instanceof Module && method_exists($this->module, $method_name)) { + $this->_list[$index][$action] = $this->module->$method_name($this->token, $id, $name); + } elseif (method_exists($this, $method_name)) { + $this->_list[$index][$action] = $this->$method_name($this->token, $id, $name); + } + } + + if ($is_first && isset($this->_list[$index][$action])) { + $is_first = false; + + if (!preg_match('/a\s*.*class/', $this->_list[$index][$action])) { + $this->_list[$index][$action] = preg_replace('/href\s*=\s*\"([^\"]*)\"/', + 'href="$1" class="btn btn-default"', $this->_list[$index][$action]); + } elseif (!preg_match('/a\s*.*class\s*=\s*\".*btn.*\"/', $this->_list[$index][$action])) { + $this->_list[$index][$action] = preg_replace('/a(\s*.*)class\s*=\s*\"(.*)\"/', + 'a $1 class="$2 btn btn-default"', $this->_list[$index][$action]); + } + } + } + + // @todo skip action for bulk actions + // $this->_list[$index]['has_bulk_actions'] = true; + foreach ($this->fields_list as $key => $params) { + $tmp = explode('!', $key); + $key = isset($tmp[1]) ? $tmp[1] : $tmp[0]; + + if (isset($params['active'])) { + // If method is defined in calling controller, use it instead of the Helper method + if (method_exists($this->context->controller, 'displayEnableLink')) { + $calling_obj = $this->context->controller; + } elseif (isset($this->module) && method_exists($this->module, 'displayEnableLink')) { + $calling_obj = $this->module; + } else { + $calling_obj = $this; + } + + if (!isset($params['ajax'])) { + $params['ajax'] = false; + } + $this->_list[$index][$key] = $calling_obj->displayEnableLink( + $this->token, + $id, + $tr[$key], + $params['active'], + Tools::getValue('id_category'), + Tools::getValue('id_product'), + $params['ajax'] + ); + } elseif (isset($params['activeVisu'])) { + $this->_list[$index][$key] = (bool)$tr[$key]; + } elseif (isset($params['position'])) { + $this->_list[$index][$key] = array( + 'position' => $tr[$key], + 'position_url_down' => $this->currentIndex. + (isset($key_to_get) ? '&'.$key_to_get.'='.(int)$position_group_identifier : ''). + '&'.$this->position_identifier.'='.$id. + '&way=1&position='.((int)$tr['position'] + 1).'&token='.$this->token, + 'position_url_up' => $this->currentIndex. + (isset($key_to_get) ? '&'.$key_to_get.'='.(int)$position_group_identifier : ''). + '&'.$this->position_identifier.'='.$id. + '&way=0&position='.((int)$tr['position'] - 1).'&token='.$this->token + ); + } elseif (isset($params['image'])) { + // item_id is the product id in a product image context, else it is the image id. + $item_id = isset($params['image_id']) ? $tr[$params['image_id']] : $id; + if ($params['image'] != 'p' || Configuration::get('PS_LEGACY_IMAGES')) { + $path_to_image = _PS_IMG_DIR_.$params['image'].'/'.$item_id.(isset($tr['id_image']) ? '-'.(int)$tr['id_image'] : '').'.'.$this->imageType; + } else { + $path_to_image = _PS_IMG_DIR_.$params['image'].'/'.Image::getImgFolderStatic($tr['id_image']).(int)$tr['id_image'].'.'.$this->imageType; + } + $this->_list[$index][$key] = ImageManager::thumbnail($path_to_image, $this->table.'_mini_'.$item_id.'_'.$this->context->shop->id.'.'.$this->imageType, 45, $this->imageType); + } elseif (isset($params['icon']) && isset($tr[$key]) && (isset($params['icon'][$tr[$key]]) || isset($params['icon']['default']))) { + if (!$this->bootstrap) { + if (isset($params['icon'][$tr[$key]]) && is_array($params['icon'][$tr[$key]])) { + $this->_list[$index][$key] = array( + 'src' => $params['icon'][$tr[$key]]['src'], + 'alt' => $params['icon'][$tr[$key]]['alt'], + ); + } else { + $this->_list[$index][$key] = array( + 'src' => isset($params['icon'][$tr[$key]]) ? $params['icon'][$tr[$key]] : $params['icon']['default'], + 'alt' => isset($params['icon'][$tr[$key]]) ? $params['icon'][$tr[$key]] : $params['icon']['default'], + ); + } + } elseif (isset($params['icon'][$tr[$key]])) { + $this->_list[$index][$key] = $params['icon'][$tr[$key]]; + } + } elseif (isset($params['type']) && $params['type'] == 'float') { + $this->_list[$index][$key] = rtrim(rtrim($tr[$key], '0'), '.'); + } elseif (isset($tr[$key])) { + $echo = $tr[$key]; + if (isset($params['callback'])) { + $callback_obj = (isset($params['callback_object'])) ? $params['callback_object'] : $this->context->controller; + $this->_list[$index][$key] = call_user_func_array(array($callback_obj, $params['callback']), array($echo, $tr)); + } else { + $this->_list[$index][$key] = $echo; + } + } + } + } + + $this->content_tpl->assign(array_merge($this->tpl_vars, array( + 'shop_link_type' => $this->shopLinkType, + 'name' => isset($name) ? $name : null, + 'position_identifier' => $this->position_identifier, + 'identifier' => $this->identifier, + 'table' => $this->table, + 'token' => $this->token, + 'color_on_bg' => $this->colorOnBackground, + 'position_group_identifier' => isset($position_group_identifier) ? $position_group_identifier : false, + 'bulk_actions' => $this->bulk_actions, + 'positions' => isset($positions) ? $positions : null, + 'order_by' => $this->orderBy, + 'order_way' => $this->orderWay, + 'is_cms' => $this->is_cms, + 'fields_display' => $this->fields_list, + 'list' => $this->_list, + 'actions' => $this->actions, + 'no_link' => $this->no_link, + 'current_index' => $this->currentIndex, + 'view' => in_array('view', $this->actions), + 'edit' => in_array('edit', $this->actions), + 'has_actions' => !empty($this->actions), + 'list_skip_actions' => $this->list_skip_actions, + 'row_hover' => $this->row_hover, + 'list_id' => isset($this->list_id) ? $this->list_id : $this->table, + 'checked_boxes' => Tools::getValue((isset($this->list_id) ? $this->list_id : $this->table).'Box') + ))); + return $this->content_tpl->fetch(); + } + + /** + * Display duplicate action link + */ + public function displayDuplicateLink($token = null, $id, $name = null) + { + $tpl = $this->createTemplate('list_action_duplicate.tpl'); + if (!array_key_exists('Bad SQL query', self::$cache_lang)) { + self::$cache_lang['Duplicate'] = $this->l('Duplicate', 'Helper'); + } + + if (!array_key_exists('Copy images too?', self::$cache_lang)) { + self::$cache_lang['Copy images too?'] = $this->l('This will copy the images too. If you wish to proceed, click "Yes". If not, click "No".', 'Helper'); + } + + $duplicate = $this->currentIndex.'&'.$this->identifier.'='.$id.'&duplicate'.$this->table; + + $confirm = self::$cache_lang['Copy images too?']; + + if (($this->table == 'product') && !Image::hasImages($this->context->language->id, (int)$id)) { + $confirm = ''; + } + + $tpl->assign(array( + 'href' => $this->currentIndex.'&'.$this->identifier.'='.$id.'&view'.$this->table.'&token='.($token != null ? $token : $this->token), + 'action' => self::$cache_lang['Duplicate'], + 'confirm' => $confirm, + 'location_ok' => $duplicate.'&token='.($token != null ? $token : $this->token), + 'location_ko' => $duplicate.'&noimage=1&token='.($token ? $token : $this->token), + )); + + return $tpl->fetch(); + } + + + /** + * Display action show details of a table row + * This action need an ajax request with a return like this: + * { + * use_parent_structure: true // If false, data need to be an html + * data: + * [ + * {field_name: 'value'} + * ], + * fields_display: // attribute $fields_list of the admin controller + * } + * or somethins like this: + * { + * use_parent_structure: false // If false, data need to be an html + * data: + * '<p>My html content</p>', + * fields_display: // attribute $fields_list of the admin controller + * } + */ + public function displayDetailsLink($token = null, $id, $name = null) + { + $tpl = $this->createTemplate('list_action_details.tpl'); + if (!array_key_exists('Details', self::$cache_lang)) { + self::$cache_lang['Details'] = $this->l('Details', 'Helper'); + } + + $ajax_params = $this->ajax_params; + if (!is_array($ajax_params) || !isset($ajax_params['action'])) { + $ajax_params['action'] = 'details'; + } + + $tpl->assign(array( + 'id' => $id, + 'href' => $this->currentIndex.'&'.$this->identifier.'='.$id.'&details'.$this->table.'&token='.($token != null ? $token : $this->token), + 'controller' => str_replace('Controller', '', get_class($this->context->controller)), + 'token' => $token != null ? $token : $this->token, + 'action' => self::$cache_lang['Details'], + 'params' => $ajax_params, + 'json_params' => Tools::jsonEncode($ajax_params) + )); + return $tpl->fetch(); + } + + /** + * Display view action link + */ + public function displayViewLink($token = null, $id, $name = null) + { + $tpl = $this->createTemplate('list_action_view.tpl'); + if (!array_key_exists('View', self::$cache_lang)) { + self::$cache_lang['View'] = $this->l('View', 'Helper'); + } + + $tpl->assign(array( + 'href' => $this->currentIndex.'&'.$this->identifier.'='.$id.'&view'.$this->table.'&token='.($token != null ? $token : $this->token), + 'action' => self::$cache_lang['View'], + )); + + return $tpl->fetch(); + } + + /** + * Display edit action link + */ + public function displayEditLink($token = null, $id, $name = null) + { + $tpl = $this->createTemplate('list_action_edit.tpl'); + if (!array_key_exists('Edit', self::$cache_lang)) { + self::$cache_lang['Edit'] = $this->l('Edit', 'Helper'); + } + + $tpl->assign(array( + 'href' => $this->currentIndex.'&'.$this->identifier.'='.$id.'&update'.$this->table.($this->page && $this->page > 1 ? '&page='.(int)$this->page : '').'&token='.($token != null ? $token : $this->token), + 'action' => self::$cache_lang['Edit'], + 'id' => $id + )); + + return $tpl->fetch(); + } + + /** + * Display delete action link + */ + public function displayDeleteLink($token = null, $id, $name = null) + { + $tpl = $this->createTemplate('list_action_delete.tpl'); + + if (!array_key_exists('Delete', self::$cache_lang)) { + self::$cache_lang['Delete'] = $this->l('Delete', 'Helper'); + } + + if (!array_key_exists('DeleteItem', self::$cache_lang)) { + self::$cache_lang['DeleteItem'] = $this->l('Delete selected item?', 'Helper', true, false); + } + + if (!array_key_exists('Name', self::$cache_lang)) { + self::$cache_lang['Name'] = $this->l('Name:', 'Helper', true, false); + } + + if (!is_null($name)) { + $name = addcslashes('\n\n'.self::$cache_lang['Name'].' '.$name, '\''); + } + + $data = array( + $this->identifier => $id, + 'href' => $this->currentIndex.'&'.$this->identifier.'='.$id.'&delete'.$this->table.'&token='.($token != null ? $token : $this->token), + 'action' => self::$cache_lang['Delete'], + ); + + if ($this->specificConfirmDelete !== false) { + $data['confirm'] = !is_null($this->specificConfirmDelete) ? '\r'.$this->specificConfirmDelete : Tools::safeOutput(self::$cache_lang['DeleteItem'].$name); + } + + $tpl->assign(array_merge($this->tpl_delete_link_vars, $data)); + + return $tpl->fetch(); + } + + /** + * Display default action link + */ + public function displayDefaultLink($token = null, $id, $name = null) + { + $tpl = $this->createTemplate('list_action_default.tpl'); + if (!array_key_exists('Default', self::$cache_lang)) { + self::$cache_lang['Default'] = $this->l('Default', 'Helper'); + } + + $tpl->assign(array( + 'href' => $this->currentIndex.'&'.$this->identifier.'='.(int)$id.'&default'.$this->table.'&token='.($token != null ? $token : $this->token), + 'action' => self::$cache_lang['Default'], + 'name' => $name, + )); + + return $tpl->fetch(); + } + + /** + * Display list header (filtering, pagination and column names) + */ + public function displayListHeader() + { + if (!isset($this->list_id)) { + $this->list_id = $this->table; + } + + $id_cat = (int)Tools::getValue('id_'.($this->is_cms ? 'cms_' : '').'category'); + + if (!isset($token) || empty($token)) { + $token = $this->token; + } + + /* Determine total page number */ + $pagination = $this->_default_pagination; + if (in_array((int)Tools::getValue($this->list_id.'_pagination'), $this->_pagination)) { + $pagination = (int)Tools::getValue($this->list_id.'_pagination'); + } elseif (isset($this->context->cookie->{$this->list_id.'_pagination'}) && $this->context->cookie->{$this->list_id.'_pagination'}) { + $pagination = $this->context->cookie->{$this->list_id.'_pagination'}; + } + + $total_pages = max(1, ceil($this->listTotal / $pagination)); + + $identifier = Tools::getIsset($this->identifier) ? '&'.$this->identifier.'='.(int)Tools::getValue($this->identifier) : ''; + $order = ''; + if (Tools::getIsset($this->table.'Orderby')) { + $order = '&'.$this->table.'Orderby='.urlencode($this->orderBy).'&'.$this->table.'Orderway='.urlencode(strtolower($this->orderWay)); + } + + $action = $this->currentIndex.$identifier.'&token='.$token.'#'.$this->list_id; + + /* Determine current page number */ + $page = (int)Tools::getValue('submitFilter'.$this->list_id); + + if (!$page) { + $page = 1; + } + + if ($page > $total_pages) { + $page = $total_pages; + } + + $this->page = (int)$page; + + /* Choose number of results per page */ + $selected_pagination = Tools::getValue($this->list_id.'_pagination', + isset($this->context->cookie->{$this->list_id.'_pagination'}) ? $this->context->cookie->{$this->list_id.'_pagination'} : $this->_default_pagination + ); + + if (!isset($this->table_id) && $this->position_identifier && (int)Tools::getValue($this->position_identifier, 1)) { + $this->table_id = substr($this->identifier, 3, strlen($this->identifier)); + } + + if ($this->position_identifier && ($this->orderBy == 'position' && $this->orderWay != 'DESC')) { + $table_dnd = true; + } + + $prefix = isset($this->controller_name) ? str_replace(array('admin', 'controller'), '', Tools::strtolower($this->controller_name)) : ''; + $ajax = false; + foreach ($this->fields_list as $key => $params) { + if (!isset($params['type'])) { + $params['type'] = 'text'; + } + + $value_key = $prefix.$this->list_id.'Filter_'.(array_key_exists('filter_key', $params) && $key != 'active' ? $params['filter_key'] : $key); + $value = Context::getContext()->cookie->{$value_key}; + if (!$value && Tools::getIsset($value_key)) { + $value = Tools::getValue($value_key); + } + + switch ($params['type']) { + case 'bool': + if (isset($params['ajax']) && $params['ajax']) { + $ajax = true; + } + break; + + case 'date': + case 'datetime': + if (is_string($value)) { + $value = Tools::unSerialize($value); + } + if (!Validate::isCleanHtml($value[0]) || !Validate::isCleanHtml($value[1])) { + $value = ''; + } + $name = $this->list_id.'Filter_'.(isset($params['filter_key']) ? $params['filter_key'] : $key); + $name_id = str_replace('!', '__', $name); + + $params['id_date'] = $name_id; + $params['name_date'] = $name; + + $this->context->controller->addJqueryUI('ui.datepicker'); + break; + + case 'select': + foreach ($params['list'] as $option_value => $option_display) { + if (isset(Context::getContext()->cookie->{$prefix.$this->list_id.'Filter_'.$params['filter_key']}) + && Context::getContext()->cookie->{$prefix.$this->list_id.'Filter_'.$params['filter_key']} == $option_value + && Context::getContext()->cookie->{$prefix.$this->list_id.'Filter_'.$params['filter_key']} != '') { + $this->fields_list[$key]['select'][$option_value]['selected'] = 'selected'; + } + } + break; + + case 'text': + if (!Validate::isCleanHtml($value)) { + $value = ''; + } + } + + $params['value'] = $value; + $this->fields_list[$key] = $params; + } + + $has_value = false; + $has_search_field = false; + + foreach ($this->fields_list as $key => $field) { + if (isset($field['value']) && $field['value'] !== false && $field['value'] !== '') { + if (is_array($field['value']) && trim(implode('', $field['value'])) == '') { + continue; + } + + $has_value = true; + break; + } + if (!(isset($field['search']) && $field['search'] === false)) { + $has_search_field = true; + } + } + + Context::getContext()->smarty->assign(array( + 'page' => $page, + 'simple_header' => $this->simple_header, + 'total_pages' => $total_pages, + 'selected_pagination' => $selected_pagination, + 'pagination' => $this->_pagination, + 'list_total' => $this->listTotal, + 'sql' => isset($this->sql) && $this->sql ? str_replace('\n', ' ', str_replace('\r', '', $this->sql)) : false, + 'token' => $this->token, + 'table' => $this->table, + 'bulk_actions' => $this->bulk_actions, + 'show_toolbar' => $this->show_toolbar, + 'toolbar_scroll' => $this->toolbar_scroll, + 'toolbar_btn' => $this->toolbar_btn, + 'has_bulk_actions' => $this->hasBulkActions($has_value), + 'filters_has_value' => (bool)$has_value + )); + + $this->header_tpl->assign(array_merge(array( + 'ajax' => $ajax, + 'title' => array_key_exists('title', $this->tpl_vars) ? $this->tpl_vars['title'] : $this->title, + 'show_filters' => ((count($this->_list) > 1 && $has_search_field) || $has_value), + 'currentIndex' => $this->currentIndex, + 'action' => $action, + 'is_order_position' => $this->position_identifier && $this->orderBy == 'position', + 'order_way' => $this->orderWay, + 'order_by' => $this->orderBy, + 'fields_display' => $this->fields_list, + 'delete' => in_array('delete', $this->actions), + 'identifier' => $this->identifier, + 'id_cat' => $id_cat, + 'shop_link_type' => $this->shopLinkType, + 'has_actions' => !empty($this->actions), + 'table_id' => isset($this->table_id) ? $this->table_id : null, + 'table_dnd' => isset($table_dnd) ? $table_dnd : null, + 'name' => isset($name) ? $name : null, + 'name_id' => isset($name_id) ? $name_id : null, + 'row_hover' => $this->row_hover, + 'list_id' => isset($this->list_id) ? $this->list_id : $this->table + ), $this->tpl_vars)); + + return $this->header_tpl->fetch(); + } + + public function hasBulkActions($has_value = false) + { + if ($this->force_show_bulk_actions) { + return true; + } + + if (count($this->_list) <= 1 && !$has_value) { + return false; + } + + if (isset($this->list_skip_actions) && count($this->list_skip_actions) + && isset($this->bulk_actions) && is_array($this->bulk_actions) && count($this->bulk_actions)) { + foreach ($this->bulk_actions as $action => $data) { + if (array_key_exists($action, $this->list_skip_actions)) { + foreach ($this->_list as $key => $row) { + if (!in_array($row[$this->identifier], $this->list_skip_actions[$action])) { + return true; + } + } + + return false; + } + } + } + + return !empty($this->bulk_actions); + } + + /** + * Close list table and submit button + */ + public function displayListFooter() + { + if (!isset($this->list_id)) { + $this->list_id = $this->table; + } + + $this->footer_tpl->assign(array_merge($this->tpl_vars, array( + 'current' => $this->currentIndex, + 'list_id' => $this->list_id + ))); + return $this->footer_tpl->fetch(); + } } diff --git a/classes/helper/HelperOptions.php b/classes/helper/HelperOptions.php index 083a9184..f054a2e7 100644 --- a/classes/helper/HelperOptions.php +++ b/classes/helper/HelperOptions.php @@ -29,147 +29,152 @@ */ class HelperOptionsCore extends Helper { - public $required = false; + public $required = false; - public function __construct() - { - $this->base_folder = 'helpers/options/'; - $this->base_tpl = 'options.tpl'; - parent::__construct(); - } + public function __construct() + { + $this->base_folder = 'helpers/options/'; + $this->base_tpl = 'options.tpl'; + parent::__construct(); + } - /** - * Generate a form for options - * @param array $option_list - * @return string html - */ - public function generateOptions($option_list) - { - $this->tpl = $this->createTemplate($this->base_tpl); - $tab = Tab::getTab($this->context->language->id, $this->id); - if (!isset($languages)) - $languages = Language::getLanguages(false); + /** + * Generate a form for options + * @param array $option_list + * @return string html + */ + public function generateOptions($option_list) + { + $this->tpl = $this->createTemplate($this->base_tpl); + $tab = Tab::getTab($this->context->language->id, $this->id); + if (!isset($languages)) { + $languages = Language::getLanguages(false); + } - $use_multishop = false; - $hide_multishop_checkbox = (Shop::getTotalShops(false, null) < 2) ? true : false; - foreach ($option_list as $category => $category_data) - { - if (!is_array($category_data)) - continue; + $use_multishop = false; + $hide_multishop_checkbox = (Shop::getTotalShops(false, null) < 2) ? true : false; + foreach ($option_list as $category => $category_data) { + if (!is_array($category_data)) { + continue; + } - if (!isset($category_data['image'])) - $category_data['image'] = (!empty($tab['module']) && file_exists($_SERVER['DOCUMENT_ROOT']._MODULE_DIR_.$tab['module'].'/'.$tab['class_name'].'.gif') ? _MODULE_DIR_.$tab['module'].'/' : '../img/t/').$tab['class_name'].'.gif'; + if (!isset($category_data['image'])) { + $category_data['image'] = (!empty($tab['module']) && file_exists($_SERVER['DOCUMENT_ROOT']._MODULE_DIR_.$tab['module'].'/'.$tab['class_name'].'.gif') ? _MODULE_DIR_.$tab['module'].'/' : '../img/t/').$tab['class_name'].'.gif'; + } - if (!isset($category_data['fields'])) - $category_data['fields'] = array(); + if (!isset($category_data['fields'])) { + $category_data['fields'] = array(); + } - $category_data['hide_multishop_checkbox'] = true; + $category_data['hide_multishop_checkbox'] = true; - if (isset($category_data['tabs'])) - { - $tabs[$category] = $category_data['tabs']; - $tabs[$category]['misc'] = $this->l('Miscellaneous'); - } + if (isset($category_data['tabs'])) { + $tabs[$category] = $category_data['tabs']; + $tabs[$category]['misc'] = $this->l('Miscellaneous'); + } - foreach ($category_data['fields'] as $key => $field) - { - if (empty($field['no_multishop_checkbox']) && !$hide_multishop_checkbox) - $category_data['hide_multishop_checkbox'] = false; + foreach ($category_data['fields'] as $key => $field) { + if (empty($field['no_multishop_checkbox']) && !$hide_multishop_checkbox) { + $category_data['hide_multishop_checkbox'] = false; + } - // Set field value unless explicitly denied - if (!isset($field['auto_value']) || $field['auto_value']) - $field['value'] = $this->getOptionValue($key, $field); + // Set field value unless explicitly denied + if (!isset($field['auto_value']) || $field['auto_value']) { + $field['value'] = $this->getOptionValue($key, $field); + } - // Check if var is invisible (can't edit it in current shop context), or disable (use default value for multishop) - $is_disabled = $is_invisible = false; - if (Shop::isFeatureActive()) - { - if (isset($field['visibility']) && $field['visibility'] > Shop::getContext()) - { - $is_disabled = true; - $is_invisible = true; - } - elseif (Shop::getContext() != Shop::CONTEXT_ALL && !Configuration::isOverridenByCurrentContext($key)) - $is_disabled = true; - } - $field['is_disabled'] = $is_disabled; - $field['is_invisible'] = $is_invisible; + // Check if var is invisible (can't edit it in current shop context), or disable (use default value for multishop) + $is_disabled = $is_invisible = false; + if (Shop::isFeatureActive()) { + if (isset($field['visibility']) && $field['visibility'] > Shop::getContext()) { + $is_disabled = true; + $is_invisible = true; + } elseif (Shop::getContext() != Shop::CONTEXT_ALL && !Configuration::isOverridenByCurrentContext($key)) { + $is_disabled = true; + } + } + $field['is_disabled'] = $is_disabled; + $field['is_invisible'] = $is_invisible; - $field['required'] = isset($field['required']) ? $field['required'] : $this->required; + $field['required'] = isset($field['required']) ? $field['required'] : $this->required; - if ($field['type'] == 'color') - $this->context->controller->addJqueryPlugin('colorpicker'); + if ($field['type'] == 'color') { + $this->context->controller->addJqueryPlugin('colorpicker'); + } - if ($field['type'] == 'texarea' || $field['type'] == 'textareaLang') - $this->context->controller->addJqueryPlugin('autosize'); + if ($field['type'] == 'texarea' || $field['type'] == 'textareaLang') { + $this->context->controller->addJqueryPlugin('autosize'); + } - if ($field['type'] == 'file') - { - $uploader = new HelperUploader(); - $uploader->setId(isset($field['id'])?$field['id']:null); - $uploader->setName($field['name']); - $uploader->setUrl(isset($field['url'])?$field['url']:null); - $uploader->setMultiple(isset($field['multiple'])?$field['multiple']:false); - $uploader->setUseAjax(isset($field['ajax'])?$field['ajax']:false); - $uploader->setMaxFiles(isset($field['max_files'])?$field['max_files']:null); + if ($field['type'] == 'file') { + $uploader = new HelperUploader(); + $uploader->setId(isset($field['id'])?$field['id']:null); + $uploader->setName($field['name']); + $uploader->setUrl(isset($field['url'])?$field['url']:null); + $uploader->setMultiple(isset($field['multiple'])?$field['multiple']:false); + $uploader->setUseAjax(isset($field['ajax'])?$field['ajax']:false); + $uploader->setMaxFiles(isset($field['max_files'])?$field['max_files']:null); - if (isset($field['files']) && $field['files']) - $uploader->setFiles($field['files']); - elseif (isset($field['image']) && $field['image']) // Use for retrocompatibility - $uploader->setFiles(array( - 0 => array( - 'type' => HelperUploader::TYPE_IMAGE, - 'image' => isset($field['image'])?$field['image']:null, - 'size' => isset($field['size'])?$field['size']:null, - 'delete_url' => isset($field['delete_url'])?$field['delete_url']:null - ))); + if (isset($field['files']) && $field['files']) { + $uploader->setFiles($field['files']); + } elseif (isset($field['image']) && $field['image']) { // Use for retrocompatibility + $uploader->setFiles(array( + 0 => array( + 'type' => HelperUploader::TYPE_IMAGE, + 'image' => isset($field['image'])?$field['image']:null, + 'size' => isset($field['size'])?$field['size']:null, + 'delete_url' => isset($field['delete_url'])?$field['delete_url']:null + ))); + } - if (isset($field['file']) && $field['file']) // Use for retrocompatibility - $uploader->setFiles(array( - 0 => array( - 'type' => HelperUploader::TYPE_FILE, - 'size' => isset($field['size'])?$field['size']:null, - 'delete_url' => isset($field['delete_url'])?$field['delete_url']:null, - 'download_url' => isset($field['file'])?$field['file']:null - ))); + if (isset($field['file']) && $field['file']) { // Use for retrocompatibility + $uploader->setFiles(array( + 0 => array( + 'type' => HelperUploader::TYPE_FILE, + 'size' => isset($field['size'])?$field['size']:null, + 'delete_url' => isset($field['delete_url'])?$field['delete_url']:null, + 'download_url' => isset($field['file'])?$field['file']:null + ))); + } - if (isset($field['thumb']) && $field['thumb']) // Use for retrocompatibility - $uploader->setFiles(array( - 0 => array( - 'type' => HelperUploader::TYPE_IMAGE, - 'image' => isset($field['thumb'])?'<img src="'.$field['thumb'].'" alt="'.$field['title'].'" title="'.$field['title'].'" />':null, - ))); + if (isset($field['thumb']) && $field['thumb']) { // Use for retrocompatibility + $uploader->setFiles(array( + 0 => array( + 'type' => HelperUploader::TYPE_IMAGE, + 'image' => isset($field['thumb'])?'<img src="'.$field['thumb'].'" alt="'.$field['title'].'" title="'.$field['title'].'" />':null, + ))); + } - $uploader->setTitle(isset($field['title'])?$field['title']:null); - $field['file'] = $uploader->render(); - } + $uploader->setTitle(isset($field['title'])?$field['title']:null); + $field['file'] = $uploader->render(); + } - // Cast options values if specified - if ($field['type'] == 'select' && isset($field['cast'])) - foreach ($field['list'] as $option_key => $option) - $field['list'][$option_key][$field['identifier']] = $field['cast']($option[$field['identifier']]); + // Cast options values if specified + if ($field['type'] == 'select' && isset($field['cast'])) { + foreach ($field['list'] as $option_key => $option) { + $field['list'][$option_key][$field['identifier']] = $field['cast']($option[$field['identifier']]); + } + } - // Fill values for all languages for all lang fields - if (substr($field['type'], -4) == 'Lang') - { - foreach ($languages as $language) - { - if ($field['type'] == 'textLang') - $value = Tools::getValue($key.'_'.$language['id_lang'], Configuration::get($key, $language['id_lang'])); - elseif ($field['type'] == 'textareaLang') - $value = Configuration::get($key, $language['id_lang']); - elseif ($field['type'] == 'selectLang') - $value = Configuration::get($key, $language['id_lang']); - $field['languages'][$language['id_lang']] = $value; - $field['value'][$language['id_lang']] = $this->getOptionValue($key.'_'.strtoupper($language['iso_code']), $field); - } - } + // Fill values for all languages for all lang fields + if (substr($field['type'], -4) == 'Lang') { + foreach ($languages as $language) { + if ($field['type'] == 'textLang') { + $value = Tools::getValue($key.'_'.$language['id_lang'], Configuration::get($key, $language['id_lang'])); + } elseif ($field['type'] == 'textareaLang') { + $value = Configuration::get($key, $language['id_lang']); + } elseif ($field['type'] == 'selectLang') { + $value = Configuration::get($key, $language['id_lang']); + } + $field['languages'][$language['id_lang']] = $value; + $field['value'][$language['id_lang']] = $this->getOptionValue($key.'_'.strtoupper($language['iso_code']), $field); + } + } - // pre-assign vars to the tpl - // @todo move this - if ($field['type'] == 'maintenance_ip') - { - $field['script_ip'] = ' + // pre-assign vars to the tpl + // @todo move this + if ($field['type'] == 'maintenance_ip') { + $field['script_ip'] = ' <script type="text/javascript"> function addRemoteAddr() { @@ -180,101 +185,103 @@ class HelperOptionsCore extends Helper $(\'input[name=PS_MAINTENANCE_IP]\').attr(\'value\',\''.Tools::getRemoteAddr().'\'); } </script>'; - $field['link_remove_ip'] = '<button type="button" class="btn btn-default" onclick="addRemoteAddr();"><i class="icon-plus"></i> '.$this->l('Add my IP', 'Helper').'</button>'; - } + $field['link_remove_ip'] = '<button type="button" class="btn btn-default" onclick="addRemoteAddr();"><i class="icon-plus"></i> '.$this->l('Add my IP', 'Helper').'</button>'; + } - // Multishop default value - $field['multishop_default'] = false; - if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL && !$is_invisible) - { - $field['multishop_default'] = true; - $use_multishop = true; - } + // Multishop default value + $field['multishop_default'] = false; + if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL && !$is_invisible) { + $field['multishop_default'] = true; + $use_multishop = true; + } - // Assign the modifications back to parent array - $category_data['fields'][$key] = $field; + // Assign the modifications back to parent array + $category_data['fields'][$key] = $field; - // Is at least one required field present? - if (isset($field['required']) && $field['required']) - $category_data['required_fields'] = true; - } - // Assign the modifications back to parent array - $option_list[$category] = $category_data; - } + // Is at least one required field present? + if (isset($field['required']) && $field['required']) { + $category_data['required_fields'] = true; + } + } + // Assign the modifications back to parent array + $option_list[$category] = $category_data; + } - $this->tpl->assign(array( - 'title' => $this->title, - 'toolbar_btn' => $this->toolbar_btn, - 'show_toolbar' => $this->show_toolbar, - 'toolbar_scroll' => $this->toolbar_scroll, - 'current' => $this->currentIndex, - 'table' => $this->table, - 'token' => $this->token, - 'tabs' => (isset($tabs)) ? $tabs : null, - 'option_list' => $option_list, - 'current_id_lang' => $this->context->language->id, - 'languages' => isset($languages) ? $languages : null, - 'currency_left_sign' => $this->context->currency->getSign('left'), - 'currency_right_sign' => $this->context->currency->getSign('right'), - 'use_multishop' => $use_multishop, - )); + $this->tpl->assign(array( + 'title' => $this->title, + 'toolbar_btn' => $this->toolbar_btn, + 'show_toolbar' => $this->show_toolbar, + 'toolbar_scroll' => $this->toolbar_scroll, + 'current' => $this->currentIndex, + 'table' => $this->table, + 'token' => $this->token, + 'tabs' => (isset($tabs)) ? $tabs : null, + 'option_list' => $option_list, + 'current_id_lang' => $this->context->language->id, + 'languages' => isset($languages) ? $languages : null, + 'currency_left_sign' => $this->context->currency->getSign('left'), + 'currency_right_sign' => $this->context->currency->getSign('right'), + 'use_multishop' => $use_multishop, + )); - return parent::generate(); - } + return parent::generate(); + } - /** - * Type = image - */ - public function displayOptionTypeImage($key, $field, $value) - { - echo '<table cellspacing="0" cellpadding="0">'; - echo '<tr>'; + /** + * Type = image + */ + public function displayOptionTypeImage($key, $field, $value) + { + echo '<table cellspacing="0" cellpadding="0">'; + echo '<tr>'; - $i = 0; - foreach ($field['list'] as $theme) - { - echo '<td class="center" style="width: 180px; padding:0px 20px 20px 0px;">'; - echo '<input type="radio" name="'.$key.'" id="'.$key.'_'.$theme['name'].'_on" style="vertical-align: text-bottom;" value="'.$theme['name'].'"'.(_THEME_NAME_ == $theme['name'] ? 'checked="checked"' : '').' />'; - echo '<label class="t" for="'.$key.'_'.$theme['name'].'_on"> '.Tools::strtolower($theme['name']).'</label>'; - echo '<br />'; - echo '<label class="t" for="'.$key.'_'.$theme['name'].'_on">'; - echo '<img src="../themes/'.$theme['name'].'/preview.jpg" alt="'.Tools::strtolower($theme['name']).'">'; - echo '</label>'; - echo '</td>'; - if (isset($field['max']) && ($i + 1) % $field['max'] == 0) - echo '</tr><tr>'; - $i++; - } - echo '</tr>'; - echo '</table>'; - } + $i = 0; + foreach ($field['list'] as $theme) { + echo '<td class="center" style="width: 180px; padding:0px 20px 20px 0px;">'; + echo '<input type="radio" name="'.$key.'" id="'.$key.'_'.$theme['name'].'_on" style="vertical-align: text-bottom;" value="'.$theme['name'].'"'.(_THEME_NAME_ == $theme['name'] ? 'checked="checked"' : '').' />'; + echo '<label class="t" for="'.$key.'_'.$theme['name'].'_on"> '.Tools::strtolower($theme['name']).'</label>'; + echo '<br />'; + echo '<label class="t" for="'.$key.'_'.$theme['name'].'_on">'; + echo '<img src="../themes/'.$theme['name'].'/preview.jpg" alt="'.Tools::strtolower($theme['name']).'">'; + echo '</label>'; + echo '</td>'; + if (isset($field['max']) && ($i + 1) % $field['max'] == 0) { + echo '</tr><tr>'; + } + $i++; + } + echo '</tr>'; + echo '</table>'; + } - /** - * Type = price - */ - public function displayOptionTypePrice($key, $field, $value) - { - echo $this->context->currency->getSign('left'); - $this->displayOptionTypeText($key, $field, $value); - echo $this->context->currency->getSign('right').' '.$this->l('(tax excl.)', 'Helper'); - } + /** + * Type = price + */ + public function displayOptionTypePrice($key, $field, $value) + { + echo $this->context->currency->getSign('left'); + $this->displayOptionTypeText($key, $field, $value); + echo $this->context->currency->getSign('right').' '.$this->l('(tax excl.)', 'Helper'); + } - /** - * Type = disabled - */ - public function displayOptionTypeDisabled($key, $field, $value) - { - echo $field['disabled']; - } + /** + * Type = disabled + */ + public function displayOptionTypeDisabled($key, $field, $value) + { + echo $field['disabled']; + } - public function getOptionValue($key, $field) - { - $value = Tools::getValue($key, Configuration::get($key)); - if (!Validate::isCleanHtml($value)) - $value = Configuration::get($key); + public function getOptionValue($key, $field) + { + $value = Tools::getValue($key, Configuration::get($key)); + if (!Validate::isCleanHtml($value)) { + $value = Configuration::get($key); + } - if (isset($field['defaultValue']) && !$value) - $value = $field['defaultValue']; - return Tools::purifyHTML($value); - } + if (isset($field['defaultValue']) && !$value) { + $value = $field['defaultValue']; + } + return Tools::purifyHTML($value); + } } diff --git a/classes/helper/HelperShop.php b/classes/helper/HelperShop.php index 87ce6f09..8644815c 100644 --- a/classes/helper/HelperShop.php +++ b/classes/helper/HelperShop.php @@ -27,40 +27,37 @@ class HelperShopCore extends Helper { /** - * Render shop list + * Render shop list * - * @return string - */ + * @return string + */ public function getRenderedShopList() { - if (!Shop::isFeatureActive() || Shop::getTotalShops(false, null) < 2) - return ''; + if (!Shop::isFeatureActive() || Shop::getTotalShops(false, null) < 2) { + return ''; + } $shop_context = Shop::getContext(); $context = Context::getContext(); $tree = Shop::getTree(); - if ($shop_context == Shop::CONTEXT_ALL || ($context->controller->multishop_context_group == false && $shop_context == Shop::CONTEXT_GROUP)) - { + if ($shop_context == Shop::CONTEXT_ALL || ($context->controller->multishop_context_group == false && $shop_context == Shop::CONTEXT_GROUP)) { $current_shop_value = ''; $current_shop_name = Translate::getAdminTranslation('All shops'); - } - elseif ($shop_context == Shop::CONTEXT_GROUP) - { + } elseif ($shop_context == Shop::CONTEXT_GROUP) { $current_shop_value = 'g-'.Shop::getContextShopGroupID(); $current_shop_name = sprintf(Translate::getAdminTranslation('%s group'), $tree[Shop::getContextShopGroupID()]['name']); - } - else - { + } else { $current_shop_value = 's-'.Shop::getContextShopID(); - foreach ($tree as $group_id => $group_data) - foreach ($group_data['shops'] as $shop_id => $shop_data) - if ($shop_id == Shop::getContextShopID()) - { + foreach ($tree as $group_id => $group_data) { + foreach ($group_data['shops'] as $shop_id => $shop_data) { + if ($shop_id == Shop::getContextShopID()) { $current_shop_name = $shop_data['name']; break; } + } + } } $tpl = $this->createTemplate('helpers/shops_list/list.tpl'); diff --git a/classes/helper/HelperTreeCategories.php b/classes/helper/HelperTreeCategories.php index bbf18e28..b3d630ac 100644 --- a/classes/helper/HelperTreeCategories.php +++ b/classes/helper/HelperTreeCategories.php @@ -26,408 +26,421 @@ class HelperTreeCategoriesCore extends TreeCore { - const DEFAULT_TEMPLATE = 'tree_categories.tpl'; - const DEFAULT_NODE_FOLDER_TEMPLATE = 'tree_node_folder_radio.tpl'; - const DEFAULT_NODE_ITEM_TEMPLATE = 'tree_node_item_radio.tpl'; + const DEFAULT_TEMPLATE = 'tree_categories.tpl'; + const DEFAULT_NODE_FOLDER_TEMPLATE = 'tree_node_folder_radio.tpl'; + const DEFAULT_NODE_ITEM_TEMPLATE = 'tree_node_item_radio.tpl'; - private $_disabled_categories; - private $_input_name; - private $_lang; - private $_root_category; - private $_selected_categories; - private $_full_tree = false; - private $_shop; - private $_use_checkbox; - private $_use_search; - private $_use_shop_restriction; - private $_children_only = false; + private $_disabled_categories; + private $_input_name; + private $_lang; + private $_root_category; + private $_selected_categories; + private $_full_tree = false; + private $_shop; + private $_use_checkbox; + private $_use_search; + private $_use_shop_restriction; + private $_children_only = false; - public function __construct($id, $title = null, $root_category = null, - $lang = null, $use_shop_restriction = true) - { - parent::__construct($id); + public function __construct($id, $title = null, $root_category = null, + $lang = null, $use_shop_restriction = true) + { + parent::__construct($id); - if (isset($title)) - $this->setTitle($title); + if (isset($title)) { + $this->setTitle($title); + } - if (isset($root_category)) - $this->setRootCategory($root_category); + if (isset($root_category)) { + $this->setRootCategory($root_category); + } - $this->setLang($lang); - $this->setUseShopRestriction($use_shop_restriction); - } + $this->setLang($lang); + $this->setUseShopRestriction($use_shop_restriction); + } - private function fillTree(&$categories, $id_category) - { - $tree = array(); - foreach($categories[$id_category] as $category) - { - $tree[$category['id_category']] = $category; - if (!empty($categories[$category['id_category']])) - $tree[$category['id_category']]['children'] = $this->fillTree($categories, $category['id_category']); - else if ($result = Category::hasChildren($category['id_category'], $this->getLang(), false, $this->getShop()->id)) - $tree[$category['id_category']]['children'] = array($result[0]['id_category'] => $result[0]); - } - return $tree; - } + private function fillTree(&$categories, $id_category) + { + $tree = array(); + foreach ($categories[$id_category] as $category) { + $tree[$category['id_category']] = $category; + if (!empty($categories[$category['id_category']])) { + $tree[$category['id_category']]['children'] = $this->fillTree($categories, $category['id_category']); + } elseif ($result = Category::hasChildren($category['id_category'], $this->getLang(), false, $this->getShop()->id)) { + $tree[$category['id_category']]['children'] = array($result[0]['id_category'] => $result[0]); + } + } + return $tree; + } - public function getData() - { - if (!isset($this->_data)) - { + public function getData() + { + if (!isset($this->_data)) { $shop = $this->getShop(); $lang = $this->getLang(); $root_category = (int)$this->getRootCategory(); - if ($this->_full_tree) - { - $this->setData(Category::getNestedCategories( - $root_category, $lang, false, null, $this->useShopRestriction())); - $this->setDataSearch(Category::getAllCategoriesName($root_category, $lang, false, null, $this->useShopRestriction())); - } - else if ($this->_children_only) - { - $categories[$root_category] = Category::getChildren($root_category, $lang, false, $shop->id); - $children = $this->fillTree($categories, $root_category); - $this->setData($children); - } - else - { - $new_selected_categories = array(); - $selected_categories = $this->getSelectedCategories(); - $categories[$root_category] = Category::getChildren($root_category, $lang, false, $shop->id); - foreach($selected_categories as $selected_category) - { - $category = new Category($selected_category, $lang, $shop->id); - $new_selected_categories[] = $selected_category; - $parents = $category->getParentsCategories($lang); - foreach($parents as $value) - $new_selected_categories[] = $value['id_category']; - } - $new_selected_categories = array_unique($new_selected_categories); - foreach($new_selected_categories as $selected_category) - { - $current_category = Category::getChildren($selected_category, $lang, false, $shop->id); - if (!empty($current_category)) - $categories[$selected_category] = $current_category; - } + if ($this->_full_tree) { + $this->setData(Category::getNestedCategories( + $root_category, $lang, false, null, $this->useShopRestriction())); + $this->setDataSearch(Category::getAllCategoriesName($root_category, $lang, false, null, $this->useShopRestriction())); + } elseif ($this->_children_only) { + if (empty($root_category)) { + $root_category = Category::getRootCategory()->id; + } + $categories[$root_category] = Category::getChildren($root_category, $lang, false, $shop->id); + $children = $this->fillTree($categories, $root_category); + $this->setData($children); + } else { + if (empty($root_category)) { + $root_category = Category::getRootCategory()->id; + } + $new_selected_categories = array(); + $selected_categories = $this->getSelectedCategories(); + $categories[$root_category] = Category::getChildren($root_category, $lang, false, $shop->id); + foreach ($selected_categories as $selected_category) { + $category = new Category($selected_category, $lang, $shop->id); + $new_selected_categories[] = $selected_category; + $parents = $category->getParentsCategories($lang); + foreach ($parents as $value) { + $new_selected_categories[] = $value['id_category']; + } + } + $new_selected_categories = array_unique($new_selected_categories); + foreach ($new_selected_categories as $selected_category) { + $current_category = Category::getChildren($selected_category, $lang, false, $shop->id); + if (!empty($current_category)) { + $categories[$selected_category] = $current_category; + } + } - $tree = Category::getCategoryInformations(array($root_category), $lang); + $tree = Category::getCategoryInformations(array($root_category), $lang); - $children = $this->fillTree($categories, $root_category); + $children = $this->fillTree($categories, $root_category); - if (!empty($children)) - $tree[$root_category]['children'] = $children; + if (!empty($children)) { + $tree[$root_category]['children'] = $children; + } - $this->setData($tree); - $this->setDataSearch(Category::getAllCategoriesName($root_category, $lang, false, null, $this->useShopRestriction())); - } - } + $this->setData($tree); + $this->setDataSearch(Category::getAllCategoriesName($root_category, $lang, false, null, $this->useShopRestriction())); + } + } - return $this->_data; - } + return $this->_data; + } - public function setChildrenOnly($value) - { - $this->_children_only = $value; - return $this; - } + public function setChildrenOnly($value) + { + $this->_children_only = $value; + return $this; + } - public function setFullTree($value) - { - $this->_full_tree = $value; - return $this; - } + public function setFullTree($value) + { + $this->_full_tree = $value; + return $this; + } - public function getFullTree() - { - return $this->_full_tree; - } + public function getFullTree() + { + return $this->_full_tree; + } - public function setDisabledCategories($value) - { - $this->_disabled_categories = $value; - return $this; - } + public function setDisabledCategories($value) + { + $this->_disabled_categories = $value; + return $this; + } - public function getDisabledCategories() - { - return $this->_disabled_categories; - } + public function getDisabledCategories() + { + return $this->_disabled_categories; + } - public function setInputName($value) - { - $this->_input_name = $value; - return $this; - } + public function setInputName($value) + { + $this->_input_name = $value; + return $this; + } - public function getInputName() - { - if (!isset($this->_input_name)) - $this->setInputName('categoryBox'); + public function getInputName() + { + if (!isset($this->_input_name)) { + $this->setInputName('categoryBox'); + } - return $this->_input_name; - } + return $this->_input_name; + } - public function setLang($value) - { - $this->_lang = $value; - return $this; - } + public function setLang($value) + { + $this->_lang = $value; + return $this; + } - public function getLang() - { - if (!isset($this->_lang)) - $this->setLang($this->getContext()->employee->id_lang); + public function getLang() + { + if (!isset($this->_lang)) { + $this->setLang($this->getContext()->employee->id_lang); + } - return $this->_lang; - } + return $this->_lang; + } - public function getNodeFolderTemplate() - { - if (!isset($this->_node_folder_template)) - $this->setNodeFolderTemplate(self::DEFAULT_NODE_FOLDER_TEMPLATE); + public function getNodeFolderTemplate() + { + if (!isset($this->_node_folder_template)) { + $this->setNodeFolderTemplate(self::DEFAULT_NODE_FOLDER_TEMPLATE); + } - return $this->_node_folder_template; - } + return $this->_node_folder_template; + } - public function getNodeItemTemplate() - { - if (!isset($this->_node_item_template)) - $this->setNodeItemTemplate(self::DEFAULT_NODE_ITEM_TEMPLATE); + public function getNodeItemTemplate() + { + if (!isset($this->_node_item_template)) { + $this->setNodeItemTemplate(self::DEFAULT_NODE_ITEM_TEMPLATE); + } - return $this->_node_item_template; - } + return $this->_node_item_template; + } - public function setRootCategory($value) - { - if (!Validate::isInt($value)) - throw new PrestaShopException('Root category must be an integer value'); + public function setRootCategory($value) + { + if (!Validate::isInt($value)) { + throw new PrestaShopException('Root category must be an integer value'); + } - $this->_root_category = $value; - return $this; - } + $this->_root_category = $value; + return $this; + } - public function getRootCategory() - { - return $this->_root_category; - } + public function getRootCategory() + { + return $this->_root_category; + } - public function setSelectedCategories($value) - { - if (!is_array($value)) - throw new PrestaShopException('Selected categories value must be an array'); + public function setSelectedCategories($value) + { + if (!is_array($value)) { + throw new PrestaShopException('Selected categories value must be an array'); + } - $this->_selected_categories = $value; - return $this; - } + $this->_selected_categories = $value; + return $this; + } - public function getSelectedCategories() - { - if (!isset($this->_selected_categories)) - $this->_selected_categories = array(); + public function getSelectedCategories() + { + if (!isset($this->_selected_categories)) { + $this->_selected_categories = array(); + } - return $this->_selected_categories; - } + return $this->_selected_categories; + } - public function setShop($value) - { - $this->_shop = $value; - return $this; - } + public function setShop($value) + { + $this->_shop = $value; + return $this; + } - public function getShop() - { - if (!isset($this->_shop)) - { - if (Tools::isSubmit('id_shop')) - $this->setShop(new Shop(Tools::getValue('id_shop'))); - else - if ($this->getContext()->shop->id) - $this->setShop(new Shop($this->getContext()->shop->id)); - else - if (!Shop::isFeatureActive()) - $this->setShop(new Shop(Configuration::get('PS_SHOP_DEFAULT'))); - else - $this->setShop(new Shop(0)); - } + public function getShop() + { + if (!isset($this->_shop)) { + if (Tools::isSubmit('id_shop')) { + $this->setShop(new Shop(Tools::getValue('id_shop'))); + } elseif ($this->getContext()->shop->id) { + $this->setShop(new Shop($this->getContext()->shop->id)); + } elseif (!Shop::isFeatureActive()) { + $this->setShop(new Shop(Configuration::get('PS_SHOP_DEFAULT'))); + } else { + $this->setShop(new Shop(0)); + } + } - return $this->_shop; - } + return $this->_shop; + } - public function getTemplate() - { - if (!isset($this->_template)) - $this->setTemplate(self::DEFAULT_TEMPLATE); + public function getTemplate() + { + if (!isset($this->_template)) { + $this->setTemplate(self::DEFAULT_TEMPLATE); + } - return $this->_template; - } + return $this->_template; + } - public function setUseCheckBox($value) - { - $this->_use_checkbox = (bool)$value; - return $this; - } + public function setUseCheckBox($value) + { + $this->_use_checkbox = (bool)$value; + return $this; + } - public function setUseSearch($value) - { - $this->_use_search = (bool)$value; - return $this; - } + public function setUseSearch($value) + { + $this->_use_search = (bool)$value; + return $this; + } - public function setUseShopRestriction($value) - { - $this->_use_shop_restriction = (bool)$value; - return $this; - } + public function setUseShopRestriction($value) + { + $this->_use_shop_restriction = (bool)$value; + return $this; + } - public function useCheckBox() - { - return (isset($this->_use_checkbox) && $this->_use_checkbox); - } + public function useCheckBox() + { + return (isset($this->_use_checkbox) && $this->_use_checkbox); + } - public function useSearch() - { - return (isset($this->_use_search) && $this->_use_search); - } + public function useSearch() + { + return (isset($this->_use_search) && $this->_use_search); + } - public function useShopRestriction() - { - return (isset($this->_use_shop_restriction) && $this->_use_shop_restriction); - } + public function useShopRestriction() + { + return (isset($this->_use_shop_restriction) && $this->_use_shop_restriction); + } - public function render($data = null) - { - if (!isset($data)) - $data = $this->getData(); + public function render($data = null) + { + if (!isset($data)) { + $data = $this->getData(); + } - if (isset($this->_disabled_categories) - && !empty($this->_disabled_categories)) - $this->_disableCategories($data, $this->getDisabledCategories()); + if (isset($this->_disabled_categories) + && !empty($this->_disabled_categories)) { + $this->_disableCategories($data, $this->getDisabledCategories()); + } - if (isset($this->_selected_categories) - && !empty($this->_selected_categories)) - $this->_getSelectedChildNumbers($data, $this->getSelectedCategories()); + if (isset($this->_selected_categories) + && !empty($this->_selected_categories)) { + $this->_getSelectedChildNumbers($data, $this->getSelectedCategories()); + } - //Default bootstrap style of search is push-right, so we add this button first - if ($this->useSearch()) - { - $this->addAction(new TreeToolbarSearchCategories( - 'Find a category:', - $this->getId().'-categories-search') - ); - $this->setAttribute('use_search', $this->useSearch()); - } + //Default bootstrap style of search is push-right, so we add this button first + if ($this->useSearch()) { + $this->addAction(new TreeToolbarSearchCategories( + 'Find a category:', + $this->getId().'-categories-search') + ); + $this->setAttribute('use_search', $this->useSearch()); + } - $collapse_all = new TreeToolbarLink( - 'Collapse All', - '#', - '$(\'#'.$this->getId().'\').tree(\'collapseAll\');$(\'#collapse-all-'.$this->getId().'\').hide();$(\'#expand-all-'.$this->getId().'\').show(); return false;', - 'icon-collapse-alt'); - $collapse_all->setAttribute('id', 'collapse-all-'.$this->getId()); - $expand_all = new TreeToolbarLink( - 'Expand All', - '#', - '$(\'#'.$this->getId().'\').tree(\'expandAll\');$(\'#collapse-all-'.$this->getId().'\').show();$(\'#expand-all-'.$this->getId().'\').hide(); return false;', - 'icon-expand-alt'); - $expand_all->setAttribute('id', 'expand-all-'.$this->getId()); - $this->addAction($collapse_all); - $this->addAction($expand_all); + $collapse_all = new TreeToolbarLink( + 'Collapse All', + '#', + '$(\'#'.$this->getId().'\').tree(\'collapseAll\');$(\'#collapse-all-'.$this->getId().'\').hide();$(\'#expand-all-'.$this->getId().'\').show(); return false;', + 'icon-collapse-alt'); + $collapse_all->setAttribute('id', 'collapse-all-'.$this->getId()); + $expand_all = new TreeToolbarLink( + 'Expand All', + '#', + '$(\'#'.$this->getId().'\').tree(\'expandAll\');$(\'#collapse-all-'.$this->getId().'\').show();$(\'#expand-all-'.$this->getId().'\').hide(); return false;', + 'icon-expand-alt'); + $expand_all->setAttribute('id', 'expand-all-'.$this->getId()); + $this->addAction($collapse_all); + $this->addAction($expand_all); - if ($this->useCheckBox()) - { - $check_all = new TreeToolbarLink( - 'Check All', - '#', - 'checkAllAssociatedCategories($(\'#'.$this->getId().'\')); return false;', - 'icon-check-sign'); - $check_all->setAttribute('id', 'check-all-'.$this->getId()); - $uncheck_all = new TreeToolbarLink( - 'Uncheck All', - '#', - 'uncheckAllAssociatedCategories($(\'#'.$this->getId().'\')); return false;', - 'icon-check-empty'); - $uncheck_all->setAttribute('id', 'uncheck-all-'.$this->getId()); - $this->addAction($check_all); - $this->addAction($uncheck_all); - $this->setNodeFolderTemplate('tree_node_folder_checkbox.tpl'); - $this->setNodeItemTemplate('tree_node_item_checkbox.tpl'); - $this->setAttribute('use_checkbox', $this->useCheckBox()); - } + if ($this->useCheckBox()) { + $check_all = new TreeToolbarLink( + 'Check All', + '#', + 'checkAllAssociatedCategories($(\'#'.$this->getId().'\')); return false;', + 'icon-check-sign'); + $check_all->setAttribute('id', 'check-all-'.$this->getId()); + $uncheck_all = new TreeToolbarLink( + 'Uncheck All', + '#', + 'uncheckAllAssociatedCategories($(\'#'.$this->getId().'\')); return false;', + 'icon-check-empty'); + $uncheck_all->setAttribute('id', 'uncheck-all-'.$this->getId()); + $this->addAction($check_all); + $this->addAction($uncheck_all); + $this->setNodeFolderTemplate('tree_node_folder_checkbox.tpl'); + $this->setNodeItemTemplate('tree_node_item_checkbox.tpl'); + $this->setAttribute('use_checkbox', $this->useCheckBox()); + } - $this->setAttribute('selected_categories', $this->getSelectedCategories()); - $this->getContext()->smarty->assign('root_category', Configuration::get('PS_ROOT_CATEGORY')); - $this->getContext()->smarty->assign('token', Tools::getAdminTokenLite('AdminProducts')); - return parent::render($data); - } + $this->setAttribute('selected_categories', $this->getSelectedCategories()); + $this->getContext()->smarty->assign('root_category', Configuration::get('PS_ROOT_CATEGORY')); + $this->getContext()->smarty->assign('token', Tools::getAdminTokenLite('AdminProducts')); + return parent::render($data); + } - /* Override */ - public function renderNodes($data = null) - { - if (!isset($data)) - $data = $this->getData(); + /* Override */ + public function renderNodes($data = null) + { + if (!isset($data)) { + $data = $this->getData(); + } - if (!is_array($data) && !$data instanceof Traversable) - throw new PrestaShopException('Data value must be an traversable array'); + if (!is_array($data) && !$data instanceof Traversable) { + throw new PrestaShopException('Data value must be an traversable array'); + } - $html = ''; - foreach ($data as $item) - { - if (array_key_exists('children', $item) - && !empty($item['children'])) - $html .= $this->getContext()->smarty->createTemplate( - $this->getTemplateFile($this->getNodeFolderTemplate()), - $this->getContext()->smarty - )->assign(array( - 'input_name' => $this->getInputName(), - 'children' => $this->renderNodes($item['children']), - 'node' => $item - ))->fetch(); - else - $html .= $this->getContext()->smarty->createTemplate( - $this->getTemplateFile($this->getNodeItemTemplate()), - $this->getContext()->smarty - )->assign(array( - 'input_name' => $this->getInputName(), - 'node' => $item - ))->fetch(); - } + $html = ''; + foreach ($data as $item) { + if (array_key_exists('children', $item) + && !empty($item['children'])) { + $html .= $this->getContext()->smarty->createTemplate( + $this->getTemplateFile($this->getNodeFolderTemplate()), + $this->getContext()->smarty + )->assign(array( + 'input_name' => $this->getInputName(), + 'children' => $this->renderNodes($item['children']), + 'node' => $item + ))->fetch(); + } else { + $html .= $this->getContext()->smarty->createTemplate( + $this->getTemplateFile($this->getNodeItemTemplate()), + $this->getContext()->smarty + )->assign(array( + 'input_name' => $this->getInputName(), + 'node' => $item + ))->fetch(); + } + } - return $html; - } + return $html; + } - private function _disableCategories(&$categories, $disabled_categories = null) - { - foreach ($categories as &$category) - { - if (!isset($disabled_categories) || in_array($category['id_category'], $disabled_categories)) - { - $category['disabled'] = true; - if (array_key_exists('children', $category) && is_array($category['children'])) - self::_disableCategories($category['children']); - } - elseif (array_key_exists('children', $category) && is_array($category['children'])) - self::_disableCategories($category['children'], $disabled_categories); - } - } + private function _disableCategories(&$categories, $disabled_categories = null) + { + foreach ($categories as &$category) { + if (!isset($disabled_categories) || in_array($category['id_category'], $disabled_categories)) { + $category['disabled'] = true; + if (array_key_exists('children', $category) && is_array($category['children'])) { + self::_disableCategories($category['children']); + } + } elseif (array_key_exists('children', $category) && is_array($category['children'])) { + self::_disableCategories($category['children'], $disabled_categories); + } + } + } - private function _getSelectedChildNumbers(&$categories, $selected, &$parent = null) - { - $selected_childs = 0; + private function _getSelectedChildNumbers(&$categories, $selected, &$parent = null) + { + $selected_childs = 0; - foreach ($categories as $key => &$category) - { - if (isset($parent) && in_array($category['id_category'], $selected)) - $selected_childs++; + foreach ($categories as $key => &$category) { + if (isset($parent) && in_array($category['id_category'], $selected)) { + $selected_childs++; + } - if (isset($category['children']) && !empty($category['children'])) - $selected_childs += $this->_getSelectedChildNumbers($category['children'], $selected, $category); - } + if (isset($category['children']) && !empty($category['children'])) { + $selected_childs += $this->_getSelectedChildNumbers($category['children'], $selected, $category); + } + } - if (!isset($parent['selected_childs'])) - $parent['selected_childs'] = 0; + if (!isset($parent['selected_childs'])) { + $parent['selected_childs'] = 0; + } - $parent['selected_childs'] = $selected_childs; - return $selected_childs; - } -} \ No newline at end of file + $parent['selected_childs'] = $selected_childs; + return $selected_childs; + } +} diff --git a/classes/helper/HelperTreeShops.php b/classes/helper/HelperTreeShops.php index 03adf4a6..3ce30980 100644 --- a/classes/helper/HelperTreeShops.php +++ b/classes/helper/HelperTreeShops.php @@ -26,152 +26,165 @@ class HelperTreeShopsCore extends TreeCore { - const DEFAULT_TEMPLATE = 'tree_shops.tpl'; - const DEFAULT_NODE_FOLDER_TEMPLATE = 'tree_node_folder_checkbox_shops.tpl'; - const DEFAULT_NODE_ITEM_TEMPLATE = 'tree_node_item_checkbox_shops.tpl'; + const DEFAULT_TEMPLATE = 'tree_shops.tpl'; + const DEFAULT_NODE_FOLDER_TEMPLATE = 'tree_node_folder_checkbox_shops.tpl'; + const DEFAULT_NODE_ITEM_TEMPLATE = 'tree_node_item_checkbox_shops.tpl'; - private $_lang; - private $_selected_shops; + private $_lang; + private $_selected_shops; - public function __construct($id, $title = null, $lang = null) - { - parent::__construct($id); + public function __construct($id, $title = null, $lang = null) + { + parent::__construct($id); - if (isset($title)) - $this->setTitle($title); + if (isset($title)) { + $this->setTitle($title); + } - $this->setLang($lang); - } + $this->setLang($lang); + } - public function getData() - { - if (!isset($this->_data)) - $this->setData(Shop::getTree()); + public function getData() + { + if (!isset($this->_data)) { + $this->setData(Shop::getTree()); + } - return $this->_data; - } + return $this->_data; + } - public function setLang($value) - { - $this->_lang = $value; - return $this; - } + public function setLang($value) + { + $this->_lang = $value; + return $this; + } - public function getLang() - { - if (!isset($this->_lang)) - $this->setLang($this->getContext()->employee->id_lang); + public function getLang() + { + if (!isset($this->_lang)) { + $this->setLang($this->getContext()->employee->id_lang); + } - return $this->_lang; - } + return $this->_lang; + } - public function getNodeFolderTemplate() - { - if (!isset($this->_node_folder_template)) - $this->setNodeFolderTemplate(self::DEFAULT_NODE_FOLDER_TEMPLATE); + public function getNodeFolderTemplate() + { + if (!isset($this->_node_folder_template)) { + $this->setNodeFolderTemplate(self::DEFAULT_NODE_FOLDER_TEMPLATE); + } - return $this->_node_folder_template; - } + return $this->_node_folder_template; + } - public function getNodeItemTemplate() - { - if (!isset($this->_node_item_template)) - $this->setNodeItemTemplate(self::DEFAULT_NODE_ITEM_TEMPLATE); + public function getNodeItemTemplate() + { + if (!isset($this->_node_item_template)) { + $this->setNodeItemTemplate(self::DEFAULT_NODE_ITEM_TEMPLATE); + } - return $this->_node_item_template; - } + return $this->_node_item_template; + } - public function setSelectedShops($value) - { - if (!is_array($value)) - throw new PrestaShopException('Selected shops value must be an array'); + public function setSelectedShops($value) + { + if (!is_array($value)) { + throw new PrestaShopException('Selected shops value must be an array'); + } - $this->_selected_shops = $value; - return $this; - } + $this->_selected_shops = $value; + return $this; + } - public function getSelectedShops() - { - if (!isset($this->_selected_shops)) - $this->_selected_shops = array(); + public function getSelectedShops() + { + if (!isset($this->_selected_shops)) { + $this->_selected_shops = array(); + } - return $this->_selected_shops; - } + return $this->_selected_shops; + } - public function getTemplate() - { - if (!isset($this->_template)) - $this->setTemplate(self::DEFAULT_TEMPLATE); + public function getTemplate() + { + if (!isset($this->_template)) { + $this->setTemplate(self::DEFAULT_TEMPLATE); + } - return $this->_template; - } + return $this->_template; + } - public function render($data = null, $use_default_actions = true, $use_selected_shop = true) - { - if (!isset($data)) - $data = $this->getData(); + public function render($data = null, $use_default_actions = true, $use_selected_shop = true) + { + if (!isset($data)) { + $data = $this->getData(); + } - if ($use_default_actions) - $this->setActions(array( - new TreeToolbarLink( - 'Collapse All', - '#', - '$(\'#'.$this->getId().'\').tree(\'collapseAll\'); return false;', - 'icon-collapse-alt'), - new TreeToolbarLink( - 'Expand All', - '#', - '$(\'#'.$this->getId().'\').tree(\'expandAll\'); return false;', - 'icon-expand-alt'), - new TreeToolbarLink( - 'Check All', - '#', - 'checkAllAssociatedShops($(\'#'.$this->getId().'\')); return false;', - 'icon-check-sign'), - new TreeToolbarLink( - 'Uncheck All', - '#', - 'uncheckAllAssociatedShops($(\'#'.$this->getId().'\')); return false;', - 'icon-check-empty') - ) - ); + if ($use_default_actions) { + $this->setActions(array( + new TreeToolbarLink( + 'Collapse All', + '#', + '$(\'#'.$this->getId().'\').tree(\'collapseAll\'); return false;', + 'icon-collapse-alt'), + new TreeToolbarLink( + 'Expand All', + '#', + '$(\'#'.$this->getId().'\').tree(\'expandAll\'); return false;', + 'icon-expand-alt'), + new TreeToolbarLink( + 'Check All', + '#', + 'checkAllAssociatedShops($(\'#'.$this->getId().'\')); return false;', + 'icon-check-sign'), + new TreeToolbarLink( + 'Uncheck All', + '#', + 'uncheckAllAssociatedShops($(\'#'.$this->getId().'\')); return false;', + 'icon-check-empty') + ) + ); + } - if ($use_selected_shop) - $this->setAttribute('selected_shops', $this->getSelectedShops()); + if ($use_selected_shop) { + $this->setAttribute('selected_shops', $this->getSelectedShops()); + } - return parent::render($data); - } + return parent::render($data); + } - public function renderNodes($data = null) - { - if (!isset($data)) - $data = $this->getData(); + public function renderNodes($data = null) + { + if (!isset($data)) { + $data = $this->getData(); + } - if (!is_array($data) && !$data instanceof Traversable) - throw new PrestaShopException('Data value must be an traversable array'); + if (!is_array($data) && !$data instanceof Traversable) { + throw new PrestaShopException('Data value must be an traversable array'); + } - $html = ''; + $html = ''; - foreach ($data as $item) - { - if (array_key_exists('shops', $item) - && !empty($item['shops'])) - $html .= $this->getContext()->smarty->createTemplate( - $this->getTemplateFile($this->getNodeFolderTemplate()), - $this->getContext()->smarty - )->assign($this->getAttributes())->assign(array( - 'children' => $this->renderNodes($item['shops']), - 'node' => $item - ))->fetch(); - else - $html .= $this->getContext()->smarty->createTemplate( - $this->getTemplateFile($this->getNodeItemTemplate()), - $this->getContext()->smarty - )->assign($this->getAttributes())->assign(array( - 'node' => $item - ))->fetch(); - } + foreach ($data as $item) { + if (array_key_exists('shops', $item) + && !empty($item['shops'])) { + $html .= $this->getContext()->smarty->createTemplate( + $this->getTemplateFile($this->getNodeFolderTemplate()), + $this->getContext()->smarty + )->assign($this->getAttributes())->assign(array( + 'children' => $this->renderNodes($item['shops']), + 'node' => $item + ))->fetch(); + } else { + $html .= $this->getContext()->smarty->createTemplate( + $this->getTemplateFile($this->getNodeItemTemplate()), + $this->getContext()->smarty + )->assign($this->getAttributes())->assign(array( + 'node' => $item + ))->fetch(); + } + } - return $html; - } -} \ No newline at end of file + return $html; + } +} diff --git a/classes/helper/HelperUploader.php b/classes/helper/HelperUploader.php index 881109b0..d2bcd14f 100644 --- a/classes/helper/HelperUploader.php +++ b/classes/helper/HelperUploader.php @@ -26,259 +26,270 @@ class HelperUploaderCore extends Uploader { - const DEFAULT_TEMPLATE_DIRECTORY = 'helpers/uploader'; - const DEFAULT_TEMPLATE = 'simple.tpl'; - const DEFAULT_AJAX_TEMPLATE = 'ajax.tpl'; + const DEFAULT_TEMPLATE_DIRECTORY = 'helpers/uploader'; + const DEFAULT_TEMPLATE = 'simple.tpl'; + const DEFAULT_AJAX_TEMPLATE = 'ajax.tpl'; - const TYPE_IMAGE = 'image'; - const TYPE_FILE = 'file'; + const TYPE_IMAGE = 'image'; + const TYPE_FILE = 'file'; - private $_context; - private $_drop_zone; - private $_id; - private $_files; - private $_name; - private $_max_files; - private $_multiple; - private $_post_max_size; - protected $_template; - private $_template_directory; - private $_title; - private $_url; - private $_use_ajax; + private $_context; + private $_drop_zone; + private $_id; + private $_files; + private $_name; + private $_max_files; + private $_multiple; + private $_post_max_size; + protected $_template; + private $_template_directory; + private $_title; + private $_url; + private $_use_ajax; - public function setContext($value) - { - $this->_context = $value; - return $this; - } + public function setContext($value) + { + $this->_context = $value; + return $this; + } - public function getContext() - { - if (!isset($this->_context)) - $this->_context = Context::getContext(); + public function getContext() + { + if (!isset($this->_context)) { + $this->_context = Context::getContext(); + } - return $this->_context; - } + return $this->_context; + } - public function setDropZone($value) - { - $this->_drop_zone = $value; - return $this; - } + public function setDropZone($value) + { + $this->_drop_zone = $value; + return $this; + } - public function getDropZone() - { - if (!isset($this->_drop_zone)) - $this->setDropZone("$('#".$this->getId()."-add-button')"); + public function getDropZone() + { + if (!isset($this->_drop_zone)) { + $this->setDropZone("$('#".$this->getId()."-add-button')"); + } - return $this->_drop_zone; - } + return $this->_drop_zone; + } - public function setId($value) - { - $this->_id = (string)$value; - return $this; - } + public function setId($value) + { + $this->_id = (string)$value; + return $this; + } - public function getId() - { - if (!isset($this->_id) || trim($this->_id) === '') - $this->_id = $this->getName(); + public function getId() + { + if (!isset($this->_id) || trim($this->_id) === '') { + $this->_id = $this->getName(); + } - return $this->_id; - } + return $this->_id; + } - public function setFiles($value) - { - $this->_files = $value; - return $this; - } + public function setFiles($value) + { + $this->_files = $value; + return $this; + } - public function getFiles() - { - if (!isset($this->_files)) - $this->_files = array(); + public function getFiles() + { + if (!isset($this->_files)) { + $this->_files = array(); + } - return $this->_files; - } + return $this->_files; + } - public function setMaxFiles($value) - { - $this->_max_files = isset($value) ? intval($value) : $value; - return $this; - } + public function setMaxFiles($value) + { + $this->_max_files = isset($value) ? intval($value) : $value; + return $this; + } - public function getMaxFiles() - { - return $this->_max_files; - } + public function getMaxFiles() + { + return $this->_max_files; + } - public function setMultiple($value) - { - $this->_multiple = (bool)$value; - return $this; - } + public function setMultiple($value) + { + $this->_multiple = (bool)$value; + return $this; + } - public function setName($value) - { - $this->_name = (string)$value; - return $this; - } + public function setName($value) + { + $this->_name = (string)$value; + return $this; + } - public function getName() - { - return $this->_name; - } + public function getName() + { + return $this->_name; + } - public function setPostMaxSize($value) - { - $this->_post_max_size = $value; - $this->setMaxSize($value); - return $this; - } + public function setPostMaxSize($value) + { + $this->_post_max_size = $value; + $this->setMaxSize($value); + return $this; + } - public function getPostMaxSize() - { - if (!isset($this->_post_max_size)) - $this->_post_max_size = parent::getPostMaxSize(); + public function getPostMaxSize() + { + if (!isset($this->_post_max_size)) { + $this->_post_max_size = parent::getPostMaxSize(); + } - return $this->_post_max_size; - } + return $this->_post_max_size; + } - public function setTemplate($value) - { - $this->_template = $value; - return $this; - } + public function setTemplate($value) + { + $this->_template = $value; + return $this; + } - public function getTemplate() - { - if (!isset($this->_template)) - $this->setTemplate(self::DEFAULT_TEMPLATE); + public function getTemplate() + { + if (!isset($this->_template)) { + $this->setTemplate(self::DEFAULT_TEMPLATE); + } - return $this->_template; - } + return $this->_template; + } - public function setTemplateDirectory($value) - { - $this->_template_directory = $value; - return $this; - } + public function setTemplateDirectory($value) + { + $this->_template_directory = $value; + return $this; + } - public function getTemplateDirectory() - { - if (!isset($this->_template_directory)) - $this->_template_directory = self::DEFAULT_TEMPLATE_DIRECTORY; + public function getTemplateDirectory() + { + if (!isset($this->_template_directory)) { + $this->_template_directory = self::DEFAULT_TEMPLATE_DIRECTORY; + } - return $this->_normalizeDirectory($this->_template_directory); - } + return $this->_normalizeDirectory($this->_template_directory); + } - public function getTemplateFile($template) - { - if (preg_match_all('/((?:^|[A-Z])[a-z]+)/', get_class($this->getContext()->controller), $matches) !== false) - $controller_name = strtolower($matches[0][1]); + public function getTemplateFile($template) + { + if (preg_match_all('/((?:^|[A-Z])[a-z]+)/', get_class($this->getContext()->controller), $matches) !== false) { + $controller_name = strtolower($matches[0][1]); + } - if ($this->getContext()->controller instanceof ModuleAdminController && file_exists($this->_normalizeDirectory( - $this->getContext()->controller->getTemplatePath()).$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->controller->getTemplatePath()) - .$this->getTemplateDirectory().$template; - elseif ($this->getContext()->controller instanceof AdminController && isset($controller_name) - && file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' - .DIRECTORY_SEPARATOR.$controller_name.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' - .DIRECTORY_SEPARATOR.$controller_name.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template; - elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) - .$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) - .$this->getTemplateDirectory().$template; - elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) - .$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) - .$this->getTemplateDirectory().$template; - else - return $this->getTemplateDirectory().$template; - } + if ($this->getContext()->controller instanceof ModuleAdminController && file_exists($this->_normalizeDirectory( + $this->getContext()->controller->getTemplatePath()).$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->controller->getTemplatePath()) + .$this->getTemplateDirectory().$template; + } elseif ($this->getContext()->controller instanceof AdminController && isset($controller_name) + && file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' + .DIRECTORY_SEPARATOR.$controller_name.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' + .DIRECTORY_SEPARATOR.$controller_name.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template; + } elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) + .$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) + .$this->getTemplateDirectory().$template; + } elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) + .$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) + .$this->getTemplateDirectory().$template; + } else { + return $this->getTemplateDirectory().$template; + } + } - public function setTitle($value) - { - $this->_title = $value; - return $this; - } + public function setTitle($value) + { + $this->_title = $value; + return $this; + } - public function getTitle() - { - return $this->_title; - } + public function getTitle() + { + return $this->_title; + } - public function setUrl($value) - { - $this->_url = (string)$value; - return $this; - } + public function setUrl($value) + { + $this->_url = (string)$value; + return $this; + } - public function getUrl() - { - return $this->_url; - } + public function getUrl() + { + return $this->_url; + } - public function setUseAjax($value) - { - $this->_use_ajax = (bool)$value; - return $this; - } + public function setUseAjax($value) + { + $this->_use_ajax = (bool)$value; + return $this; + } - public function isMultiple() - { - return (isset($this->_multiple) && $this->_multiple); - } + public function isMultiple() + { + return (isset($this->_multiple) && $this->_multiple); + } - public function render() - { - $admin_webpath = str_ireplace(_PS_CORE_DIR_, '', _PS_ADMIN_DIR_); - $admin_webpath = preg_replace('/^'.preg_quote(DIRECTORY_SEPARATOR, '/').'/', '', $admin_webpath); - $bo_theme = ((Validate::isLoadedObject($this->getContext()->employee) - && $this->getContext()->employee->bo_theme) ? $this->getContext()->employee->bo_theme : 'default'); + public function render() + { + $admin_webpath = str_ireplace(_PS_CORE_DIR_, '', _PS_ADMIN_DIR_); + $admin_webpath = preg_replace('/^'.preg_quote(DIRECTORY_SEPARATOR, '/').'/', '', $admin_webpath); + $bo_theme = ((Validate::isLoadedObject($this->getContext()->employee) + && $this->getContext()->employee->bo_theme) ? $this->getContext()->employee->bo_theme : 'default'); - if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR - .'template')) - $bo_theme = 'default'; + if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR + .'template')) { + $bo_theme = 'default'; + } - $this->getContext()->controller->addJs(__PS_BASE_URI__.$admin_webpath - .'/themes/'.$bo_theme.'/js/jquery.iframe-transport.js'); - $this->getContext()->controller->addJs(__PS_BASE_URI__.$admin_webpath - .'/themes/'.$bo_theme.'/js/jquery.fileupload.js'); - $this->getContext()->controller->addJs(__PS_BASE_URI__.$admin_webpath - .'/themes/'.$bo_theme.'/js/jquery.fileupload-process.js'); - $this->getContext()->controller->addJs(__PS_BASE_URI__.$admin_webpath - .'/themes/'.$bo_theme.'/js/jquery.fileupload-validate.js'); - $this->getContext()->controller->addJs(__PS_BASE_URI__.'js/vendor/spin.js'); - $this->getContext()->controller->addJs(__PS_BASE_URI__.'js/vendor/ladda.js'); + $this->getContext()->controller->addJs(__PS_BASE_URI__.$admin_webpath + .'/themes/'.$bo_theme.'/js/jquery.iframe-transport.js'); + $this->getContext()->controller->addJs(__PS_BASE_URI__.$admin_webpath + .'/themes/'.$bo_theme.'/js/jquery.fileupload.js'); + $this->getContext()->controller->addJs(__PS_BASE_URI__.$admin_webpath + .'/themes/'.$bo_theme.'/js/jquery.fileupload-process.js'); + $this->getContext()->controller->addJs(__PS_BASE_URI__.$admin_webpath + .'/themes/'.$bo_theme.'/js/jquery.fileupload-validate.js'); + $this->getContext()->controller->addJs(__PS_BASE_URI__.'js/vendor/spin.js'); + $this->getContext()->controller->addJs(__PS_BASE_URI__.'js/vendor/ladda.js'); - if ($this->useAjax() && !isset($this->_template)) - $this->setTemplate(self::DEFAULT_AJAX_TEMPLATE); + if ($this->useAjax() && !isset($this->_template)) { + $this->setTemplate(self::DEFAULT_AJAX_TEMPLATE); + } - $template = $this->getContext()->smarty->createTemplate( - $this->getTemplateFile($this->getTemplate()), $this->getContext()->smarty - ); + $template = $this->getContext()->smarty->createTemplate( + $this->getTemplateFile($this->getTemplate()), $this->getContext()->smarty + ); - $template->assign(array( - 'id' => $this->getId(), - 'name' => $this->getName(), - 'url' => $this->getUrl(), - 'multiple' => $this->isMultiple(), - 'files' => $this->getFiles(), - 'title' => $this->getTitle(), - 'max_files' => $this->getMaxFiles(), - 'post_max_size' => $this->getPostMaxSizeBytes(), - 'drop_zone' => $this->getDropZone() - )); + $template->assign(array( + 'id' => $this->getId(), + 'name' => $this->getName(), + 'url' => $this->getUrl(), + 'multiple' => $this->isMultiple(), + 'files' => $this->getFiles(), + 'title' => $this->getTitle(), + 'max_files' => $this->getMaxFiles(), + 'post_max_size' => $this->getPostMaxSizeBytes(), + 'drop_zone' => $this->getDropZone() + )); - return $template->fetch(); - } + return $template->fetch(); + } - public function useAjax() - { - return (isset($this->_use_ajax) && $this->_use_ajax); - } + public function useAjax() + { + return (isset($this->_use_ajax) && $this->_use_ajax); + } } diff --git a/classes/helper/HelperView.php b/classes/helper/HelperView.php index 4e098e9a..3620e9b2 100644 --- a/classes/helper/HelperView.php +++ b/classes/helper/HelperView.php @@ -26,36 +26,36 @@ class HelperViewCore extends Helper { - public $id; - public $toolbar = true; - public $table; - public $token; + public $id; + public $toolbar = true; + public $table; + public $token; - /** @var string|null If not null, a title will be added on that list */ - public $title = null; + /** @var string|null If not null, a title will be added on that list */ + public $title = null; - public function __construct() - { - $this->base_folder = 'helpers/view/'; - $this->base_tpl = 'view.tpl'; - parent::__construct(); - } + public function __construct() + { + $this->base_folder = 'helpers/view/'; + $this->base_tpl = 'view.tpl'; + parent::__construct(); + } - public function generateView() - { - $this->tpl = $this->createTemplate($this->base_tpl); + public function generateView() + { + $this->tpl = $this->createTemplate($this->base_tpl); - $this->tpl->assign(array( - 'title' => $this->title, - 'current' => $this->currentIndex, - 'token' => $this->token, - 'table' => $this->table, - 'show_toolbar' => $this->show_toolbar, - 'toolbar_scroll' => $this->toolbar_scroll, - 'toolbar_btn' => $this->toolbar_btn, - 'link' => $this->context->link - )); + $this->tpl->assign(array( + 'title' => $this->title, + 'current' => $this->currentIndex, + 'token' => $this->token, + 'table' => $this->table, + 'show_toolbar' => $this->show_toolbar, + 'toolbar_scroll' => $this->toolbar_scroll, + 'toolbar_btn' => $this->toolbar_btn, + 'link' => $this->context->link + )); - return parent::generate(); - } + return parent::generate(); + } } diff --git a/classes/helper/index.php b/classes/helper/index.php index c642967a..91fa49fb 100644 --- a/classes/helper/index.php +++ b/classes/helper/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/classes/log/AbstractLogger.php b/classes/log/AbstractLogger.php index 36df80ac..80ddbe09 100644 --- a/classes/log/AbstractLogger.php +++ b/classes/log/AbstractLogger.php @@ -26,85 +26,86 @@ abstract class AbstractLoggerCore { - public $level; - protected $level_value = array( - 0 => 'DEBUG', - 1 => 'INFO', - 2 => 'WARNING', - 3 => 'ERROR', - ); + public $level; + protected $level_value = array( + 0 => 'DEBUG', + 1 => 'INFO', + 2 => 'WARNING', + 3 => 'ERROR', + ); - const DEBUG = 0; - const INFO = 1; - const WARNING = 2; - const ERROR = 3; + const DEBUG = 0; + const INFO = 1; + const WARNING = 2; + const ERROR = 3; - public function __construct($level = self::INFO) - { - if (array_key_exists((int)$level, $this->level_value)) - $this->level = $level; - else - $this->level = self::INFO; - } + public function __construct($level = self::INFO) + { + if (array_key_exists((int)$level, $this->level_value)) { + $this->level = $level; + } else { + $this->level = self::INFO; + } + } - /** - * Log the message - * - * @param string message - * @param level - */ - abstract protected function logMessage($message, $level); + /** + * Log the message + * + * @param string message + * @param level + */ + abstract protected function logMessage($message, $level); - /** - * Check the level and log the message if needed - * - * @param string message - * @param level - */ - public function log($message, $level = self::DEBUG) - { - if ($level >= $this->level) - $this->logMessage($message, $level); - } + /** + * Check the level and log the message if needed + * + * @param string message + * @param level + */ + public function log($message, $level = self::DEBUG) + { + if ($level >= $this->level) { + $this->logMessage($message, $level); + } + } - /** - * Log a debug message - * - * @param string message - */ - public function logDebug($message) - { - $this->log($message, self::DEBUG); - } + /** + * Log a debug message + * + * @param string message + */ + public function logDebug($message) + { + $this->log($message, self::DEBUG); + } - /** - * Log an info message - * - * @param string message - */ - public function logInfo($message) - { - $this->log($message, self::INFO); - } + /** + * Log an info message + * + * @param string message + */ + public function logInfo($message) + { + $this->log($message, self::INFO); + } - /** - * Log a warning message - * - * @param string message - */ - public function logWarning($message) - { - $this->log($message, self::WARNING); - } + /** + * Log a warning message + * + * @param string message + */ + public function logWarning($message) + { + $this->log($message, self::WARNING); + } - /** - * Log an error message - * - * @param string message - */ - public function logError($message) - { - $this->log($message, self::ERROR); - } + /** + * Log an error message + * + * @param string message + */ + public function logError($message) + { + $this->log($message, self::ERROR); + } } - diff --git a/classes/log/FileLogger.php b/classes/log/FileLogger.php index 99736467..29c2591a 100644 --- a/classes/log/FileLogger.php +++ b/classes/log/FileLogger.php @@ -26,47 +26,49 @@ class FileLoggerCore extends AbstractLogger { - protected $filename = ''; + protected $filename = ''; - /** - * Write the message in the log file - * - * @param string message - * @param level - */ - protected function logMessage($message, $level) - { - if (!is_string($message)) - $message = print_r($message, true); - $formatted_message = '*'.$this->level_value[$level].'* '."\t".date('Y/m/d - H:i:s').': '.$message."\r\n"; - return (bool)file_put_contents($this->getFilename(), $formatted_message, FILE_APPEND); - } + /** + * Write the message in the log file + * + * @param string message + * @param level + */ + protected function logMessage($message, $level) + { + if (!is_string($message)) { + $message = print_r($message, true); + } + $formatted_message = '*'.$this->level_value[$level].'* '."\t".date('Y/m/d - H:i:s').': '.$message."\r\n"; + return (bool)file_put_contents($this->getFilename(), $formatted_message, FILE_APPEND); + } - /** - * Check if the specified filename is writable and set the filename - * - * @param string $filename - */ - public function setFilename($filename) - { - if (is_writable(dirname($filename))) - $this->filename = $filename; - else - die('Directory '.dirname($filename).' is not writable'); - } + /** + * Check if the specified filename is writable and set the filename + * + * @param string $filename + */ + public function setFilename($filename) + { + if (is_writable(dirname($filename))) { + $this->filename = $filename; + } else { + die('Directory '.dirname($filename).' is not writable'); + } + } - /** - * Log the message - * - * @param string message - * @param level - */ - public function getFilename() - { - if (empty($this->filename)) - die('Filename is empty.'); + /** + * Log the message + * + * @param string message + * @param level + */ + public function getFilename() + { + if (empty($this->filename)) { + die('Filename is empty.'); + } - return $this->filename; - } + return $this->filename; + } } - diff --git a/classes/log/index.php b/classes/log/index.php index c642967a..91fa49fb 100644 --- a/classes/log/index.php +++ b/classes/log/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/classes/module/CarrierModule.php b/classes/module/CarrierModule.php index cb0f01fe..17a9ab28 100644 --- a/classes/module/CarrierModule.php +++ b/classes/module/CarrierModule.php @@ -26,6 +26,6 @@ abstract class CarrierModuleCore extends Module { - abstract public function getOrderShippingCost($params, $shipping_cost); - abstract public function getOrderShippingCostExternal($params); -} \ No newline at end of file + abstract public function getOrderShippingCost($params, $shipping_cost); + abstract public function getOrderShippingCostExternal($params); +} diff --git a/classes/module/ImportModule.php b/classes/module/ImportModule.php index eba7e9d1..464c2d5d 100644 --- a/classes/module/ImportModule.php +++ b/classes/module/ImportModule.php @@ -33,77 +33,85 @@ abstract class ImportModuleCore extends Module { - protected $_link = null; + protected $_link = null; - public $server; + public $server; - public $user; + public $user; - public $passwd; + public $passwd; - public $database; + public $database; - /** @var string Prefix database */ - public $prefix; + /** @var string Prefix database */ + public $prefix; - public function __destruct() - { - if ($this->_link) - @mysql_close($this->_link); - } + public function __destruct() + { + if ($this->_link) { + @mysql_close($this->_link); + } + } - protected function initDatabaseConnection() - { - if ($this->_link != null) - return $this->_link; - if ($this->_link = mysql_connect($this->server, $this->user, $this->passwd, true)) - { - if (!mysql_select_db($this->database, $this->_link)) - die(Tools::displayError('The database selection cannot be made.')); - if (!mysql_query('SET NAMES \'utf8\'', $this->_link)) - die(Tools::displayError('Fatal error: no UTF-8 support. Please check your server configuration.')); - } - else - die(Tools::displayError('Link to database cannot be established.')); - return $this->_link; - } + protected function initDatabaseConnection() + { + if ($this->_link != null) { + return $this->_link; + } + if ($this->_link = mysql_connect($this->server, $this->user, $this->passwd, true)) { + if (!mysql_select_db($this->database, $this->_link)) { + die(Tools::displayError('The database selection cannot be made.')); + } + if (!mysql_query('SET NAMES \'utf8\'', $this->_link)) { + die(Tools::displayError('Fatal error: no UTF-8 support. Please check your server configuration.')); + } + } else { + die(Tools::displayError('Link to database cannot be established.')); + } + return $this->_link; + } - public function ExecuteS($query) - { - $this->initDatabaseConnection(); - $result = mysql_query($query, $this->_link); - $result_array = array(); - if ($result !== true) - while ($row = mysql_fetch_assoc($result)) - $result_array[] = $row; - return $result_array; - } + public function ExecuteS($query) + { + $this->initDatabaseConnection(); + $result = mysql_query($query, $this->_link); + $result_array = array(); + if ($result !== true) { + while ($row = mysql_fetch_assoc($result)) { + $result_array[] = $row; + } + } + return $result_array; + } - public function Execute($query) - { - $this->initDatabaseConnection(); - return mysql_query($query, $this->_link); - } + public function Execute($query) + { + $this->initDatabaseConnection(); + return mysql_query($query, $this->_link); + } - public function getValue($query) - { - $this->initDatabaseConnection(); - $result = $this->executeS($query); - if (!count($result)) - return 0; - else - return array_shift($result[0]); - } + public function getValue($query) + { + $this->initDatabaseConnection(); + $result = $this->executeS($query); + if (!count($result)) { + return 0; + } else { + return array_shift($result[0]); + } + } - public static function getImportModulesOnDisk() - { - $modules = Module::getModulesOnDisk(true); - foreach ($modules as $key => $module) - if (!isset($module->parent_class) || $module->parent_class != 'ImportModule') - unset($modules[$key]); - return $modules; - } + public static function getImportModulesOnDisk() + { + $modules = Module::getModulesOnDisk(true); + foreach ($modules as $key => $module) { + if (!isset($module->parent_class) || $module->parent_class != 'ImportModule') { + unset($modules[$key]); + } + } + return $modules; + } - abstract public function getDefaultIdLang(); -} \ No newline at end of file + abstract public function getDefaultIdLang(); +} diff --git a/classes/module/Module.php b/classes/module/Module.php index 41a75d74..5f3b666d 100644 --- a/classes/module/Module.php +++ b/classes/module/Module.php @@ -26,240 +26,247 @@ abstract class ModuleCore { - /** @var int Module ID */ - public $id = null; + /** @var int Module ID */ + public $id = null; - /** @var float Version */ - public $version; - public $database_version; + /** @var float Version */ + public $version; + public $database_version; - /** - * @since 1.5.0.1 - * @var string Registered Version in database - */ - public $registered_version; + /** + * @since 1.5.0.1 + * @var string Registered Version in database + */ + public $registered_version; - /** @var array filled with known compliant PS versions */ - public $ps_versions_compliancy = array(); + /** @var array filled with known compliant PS versions */ + public $ps_versions_compliancy = array(); - /** @var array filled with modules needed for install */ - public $dependencies = array(); + /** @var array filled with modules needed for install */ + public $dependencies = array(); - /** @var string Unique name */ - public $name; + /** @var string Unique name */ + public $name; - /** @var string Human name */ - public $displayName; + /** @var string Human name */ + public $displayName; - /** @var string A little description of the module */ - public $description; + /** @var string A little description of the module */ + public $description; - /** @var string author of the module */ - public $author; + /** @var string author of the module */ + public $author; - /** @var string URI author of the module */ - public $author_uri = ''; + /** @var string URI author of the module */ + public $author_uri = ''; - /** @var string Module key provided by addons.prestashop.com */ - public $module_key = ''; + /** @var string Module key provided by addons.prestashop.com */ + public $module_key = ''; - public $description_full; + public $description_full; - public $additional_description; + public $additional_description; - public $compatibility; + public $compatibility; - public $nb_rates; + public $nb_rates; - public $avg_rate; + public $avg_rate; - public $badges; + public $badges; - /** @var int need_instance */ - public $need_instance = 1; + /** @var int need_instance */ + public $need_instance = 1; - /** @var string Admin tab corresponding to the module */ - public $tab = null; + /** @var string Admin tab corresponding to the module */ + public $tab = null; - /** @var bool Status */ - public $active = false; + /** @var bool Status */ + public $active = false; - /** @var bool Is the module certified by addons.prestashop.com */ - public $trusted = false; + /** @var bool Is the module certified by addons.prestashop.com */ + public $trusted = false; - /** @var string Fill it if the module is installed but not yet set up */ - public $warning; + /** @var string Fill it if the module is installed but not yet set up */ + public $warning; - public $enable_device = 7; + public $enable_device = 7; - /** @var array to store the limited country */ - public $limited_countries = array(); + /** @var array to store the limited country */ + public $limited_countries = array(); - /** @var array names of the controllers */ - public $controllers = array(); + /** @var array names of the controllers */ + public $controllers = array(); - /** @var array used by AdminTab to determine which lang file to use (admin.php or module lang file) */ - public static $classInModule = array(); + /** @var array used by AdminTab to determine which lang file to use (admin.php or module lang file) */ + public static $classInModule = array(); - /** @var array current language translations */ - protected $_lang = array(); + /** @var array current language translations */ + protected $_lang = array(); - /** @var string Module web path (eg. '/shop/modules/modulename/') */ - protected $_path = null; - /** - * @since 1.5.0.1 - * @var string Module local path (eg. '/home/prestashop/modules/modulename/') - */ - protected $local_path = null; + /** @var string Module web path (eg. '/shop/modules/modulename/') */ + protected $_path = null; + /** + * @since 1.5.0.1 + * @var string Module local path (eg. '/home/prestashop/modules/modulename/') + */ + protected $local_path = null; - /** @var array Array filled with module errors */ - protected $_errors = array(); + /** @var array Array filled with module errors */ + protected $_errors = array(); - /** @var array Array array filled with module success */ - protected $_confirmations = array(); + /** @var array Array array filled with module success */ + protected $_confirmations = array(); - /** @var string Main table used for modules installed */ - protected $table = 'module'; + /** @var string Main table used for modules installed */ + protected $table = 'module'; - /** @var string Identifier of the main table */ - protected $identifier = 'id_module'; + /** @var string Identifier of the main table */ + protected $identifier = 'id_module'; - /** @var array Array cache filled with modules informations */ - protected static $modules_cache; + /** @var array Array cache filled with modules informations */ + protected static $modules_cache; - /** @var array Array cache filled with modules instances */ - protected static $_INSTANCE = array(); + /** @var array Array cache filled with modules instances */ + protected static $_INSTANCE = array(); - /** @var bool Config xml generation mode */ - protected static $_generate_config_xml_mode = false; + /** @var bool Config xml generation mode */ + protected static $_generate_config_xml_mode = false; - /** @var array Array filled with cache translations */ - protected static $l_cache = array(); + /** @var array Array filled with cache translations */ + protected static $l_cache = array(); - /** @var array Array filled with cache permissions (modules / employee profiles) */ - protected static $cache_permissions = array(); + /** @var array Array filled with cache permissions (modules / employee profiles) */ + protected static $cache_permissions = array(); - /** @var Context */ - protected $context; + /** @var Context */ + protected $context; - /** @var Smarty_Data */ - protected $smarty; + /** @var Smarty_Data */ + protected $smarty; - /** @var Smarty_Internal_Template|null */ - protected $current_subtemplate = null; + /** @var Smarty_Internal_Template|null */ + protected $current_subtemplate = null; - protected static $update_translations_after_install = true; + protected static $update_translations_after_install = true; - protected static $_batch_mode = false; - protected static $_defered_clearCache = array(); - protected static $_defered_func_call = array(); + protected static $_batch_mode = false; + protected static $_defered_clearCache = array(); + protected static $_defered_func_call = array(); - /** @var bool If true, allow push */ - public $allow_push; + /** @var bool If true, allow push */ + public $allow_push; - public $push_time_limit = 180; + public $push_time_limit = 180; - /** @var bool Define if we will log modules performances for this session */ - public static $_log_modules_perfs = null; - /** @var bool Random session for modules perfs logs*/ - public static $_log_modules_perfs_session = null; + /** @var bool Define if we will log modules performances for this session */ + public static $_log_modules_perfs = null; + /** @var bool Random session for modules perfs logs*/ + public static $_log_modules_perfs_session = null; - const CACHE_FILE_MODULES_LIST = '/config/xml/modules_list.xml'; + const CACHE_FILE_MODULES_LIST = '/config/xml/modules_list.xml'; - const CACHE_FILE_TAB_MODULES_LIST = '/config/xml/tab_modules_list.xml'; + const CACHE_FILE_TAB_MODULES_LIST = '/config/xml/tab_modules_list.xml'; - const CACHE_FILE_ALL_COUNTRY_MODULES_LIST = '/config/xml/modules_native_addons.xml'; - const CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST = '/config/xml/default_country_modules_list.xml'; + const CACHE_FILE_ALL_COUNTRY_MODULES_LIST = '/config/xml/modules_native_addons.xml'; + const CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST = '/config/xml/default_country_modules_list.xml'; - const CACHE_FILE_CUSTOMER_MODULES_LIST = '/config/xml/customer_modules_list.xml'; + const CACHE_FILE_CUSTOMER_MODULES_LIST = '/config/xml/customer_modules_list.xml'; - const CACHE_FILE_MUST_HAVE_MODULES_LIST = '/config/xml/must_have_modules_list.xml'; + const CACHE_FILE_MUST_HAVE_MODULES_LIST = '/config/xml/must_have_modules_list.xml'; - const CACHE_FILE_TRUSTED_MODULES_LIST = '/config/xml/trusted_modules_list.xml'; - const CACHE_FILE_UNTRUSTED_MODULES_LIST = '/config/xml/untrusted_modules_list.xml'; + const CACHE_FILE_TRUSTED_MODULES_LIST = '/config/xml/trusted_modules_list.xml'; + const CACHE_FILE_UNTRUSTED_MODULES_LIST = '/config/xml/untrusted_modules_list.xml'; - public static $hosted_modules_blacklist = array('autoupgrade'); + public static $hosted_modules_blacklist = array('autoupgrade'); - /** - * Set the flag to indicate we are doing an import - * - * @param bool $value - */ - public static function setBatchMode($value) - { - self::$_batch_mode = (bool)$value; - } + /** + * Set the flag to indicate we are doing an import + * + * @param bool $value + */ + public static function setBatchMode($value) + { + self::$_batch_mode = (bool)$value; + } - /** - * @return bool - */ - public static function getBatchMode() - { - return self::$_batch_mode; - } + /** + * @return bool + */ + public static function getBatchMode() + { + return self::$_batch_mode; + } - public static function processDeferedFuncCall() - { - self::setBatchMode(false); - foreach(self::$_defered_func_call as $func_call) - call_user_func_array($func_call[0], $func_call[1]); - - self::$_defered_func_call = array(); - } - - /** - * Clear the caches stored in $_defered_clearCache - * - */ - public static function processDeferedClearCache() - { - self::setBatchMode(false); - - foreach(self::$_defered_clearCache as $clearCache_array) - self::_deferedClearCache($clearCache_array[0], $clearCache_array[1], $clearCache_array[2]); - - self::$_defered_clearCache = array(); - } - - /** - * Constructor - * - * @param string $name Module unique name - * @param Context $context - */ - public function __construct($name = null, Context $context = null) - { - if (isset($this->ps_versions_compliancy) && !isset($this->ps_versions_compliancy['min'])) - $this->ps_versions_compliancy['min'] = '1.4.0.0'; - - if (isset($this->ps_versions_compliancy) && !isset($this->ps_versions_compliancy['max'])) - $this->ps_versions_compliancy['max'] = _PS_VERSION_; - - if (strlen($this->ps_versions_compliancy['min']) == 3) - $this->ps_versions_compliancy['min'] .= '.0.0'; - - if (strlen($this->ps_versions_compliancy['max']) == 3) - $this->ps_versions_compliancy['max'] .= '.999.999'; - - // Load context and smarty - $this->context = $context ? $context : Context::getContext(); - if (is_object($this->context->smarty)) - $this->smarty = $this->context->smarty->createData($this->context->smarty); - - // If the module has no name we gave him its id as name - if ($this->name === null) - $this->name = $this->id; - - // If the module has the name we load the corresponding data from the cache - if ($this->name != null) - { - // If cache is not generated, we generate it - if (self::$modules_cache == null && !is_array(self::$modules_cache)) - { - $id_shop = (Validate::isLoadedObject($this->context->shop) ? $this->context->shop->id : 1); - self::$modules_cache = array(); - // Join clause is done to check if the module is activated in current shop context - $result = Db::getInstance()->executeS(' + public static function processDeferedFuncCall() + { + self::setBatchMode(false); + foreach (self::$_defered_func_call as $func_call) { + call_user_func_array($func_call[0], $func_call[1]); + } + + self::$_defered_func_call = array(); + } + + /** + * Clear the caches stored in $_defered_clearCache + * + */ + public static function processDeferedClearCache() + { + self::setBatchMode(false); + + foreach (self::$_defered_clearCache as $clearCache_array) { + self::_deferedClearCache($clearCache_array[0], $clearCache_array[1], $clearCache_array[2]); + } + + self::$_defered_clearCache = array(); + } + + /** + * Constructor + * + * @param string $name Module unique name + * @param Context $context + */ + public function __construct($name = null, Context $context = null) + { + if (isset($this->ps_versions_compliancy) && !isset($this->ps_versions_compliancy['min'])) { + $this->ps_versions_compliancy['min'] = '1.4.0.0'; + } + + if (isset($this->ps_versions_compliancy) && !isset($this->ps_versions_compliancy['max'])) { + $this->ps_versions_compliancy['max'] = _PS_VERSION_; + } + + if (strlen($this->ps_versions_compliancy['min']) == 3) { + $this->ps_versions_compliancy['min'] .= '.0.0'; + } + + if (strlen($this->ps_versions_compliancy['max']) == 3) { + $this->ps_versions_compliancy['max'] .= '.999.999'; + } + + // Load context and smarty + $this->context = $context ? $context : Context::getContext(); + if (is_object($this->context->smarty)) { + $this->smarty = $this->context->smarty->createData($this->context->smarty); + } + + // If the module has no name we gave him its id as name + if ($this->name === null) { + $this->name = $this->id; + } + + // If the module has the name we load the corresponding data from the cache + if ($this->name != null) { + // If cache is not generated, we generate it + if (self::$modules_cache == null && !is_array(self::$modules_cache)) { + $id_shop = (Validate::isLoadedObject($this->context->shop) ? $this->context->shop->id : Configuration::get('PS_SHOP_DEFAULT')); + + self::$modules_cache = array(); + // Join clause is done to check if the module is activated in current shop context + $result = Db::getInstance()->executeS(' SELECT m.`id_module`, m.`name`, ( SELECT id_module FROM `'._DB_PREFIX_.'module_shop` ms @@ -268,95 +275,98 @@ abstract class ModuleCore LIMIT 1 ) as mshop FROM `'._DB_PREFIX_.'module` m'); - foreach ($result as $row) - { - self::$modules_cache[$row['name']] = $row; - self::$modules_cache[$row['name']]['active'] = ($row['mshop'] > 0) ? 1 : 0; - } - } + foreach ($result as $row) { + self::$modules_cache[$row['name']] = $row; + self::$modules_cache[$row['name']]['active'] = ($row['mshop'] > 0) ? 1 : 0; + } + } - // We load configuration from the cache - if (isset(self::$modules_cache[$this->name])) - { - if (isset(self::$modules_cache[$this->name]['id_module'])) - $this->id = self::$modules_cache[$this->name]['id_module']; - foreach (self::$modules_cache[$this->name] as $key => $value) - if (array_key_exists($key, $this)) - $this->{$key} = $value; - $this->_path = __PS_BASE_URI__.'modules/'.$this->name.'/'; - } - $this->local_path = _PS_MODULE_DIR_.$this->name.'/'; - } - } + // We load configuration from the cache + if (isset(self::$modules_cache[$this->name])) { + if (isset(self::$modules_cache[$this->name]['id_module'])) { + $this->id = self::$modules_cache[$this->name]['id_module']; + } + foreach (self::$modules_cache[$this->name] as $key => $value) { + if (array_key_exists($key, $this)) { + $this->{$key} = $value; + } + } + $this->_path = __PS_BASE_URI__.'modules/'.$this->name.'/'; + } + if (!$this->context->controller instanceof Controller) { + self::$modules_cache = null; + } + $this->local_path = _PS_MODULE_DIR_.$this->name.'/'; + } + } - /** - * Insert module into datable - */ - public function install() - { - Hook::exec('actionModuleInstallBefore', array('object' => $this)); - // Check module name validation - if (!Validate::isModuleName($this->name)) - { - $this->_errors[] = Tools::displayError('Unable to install the module (Module name is not valid).'); - return false; - } + /** + * Insert module into datable + */ + public function install() + { + Hook::exec('actionModuleInstallBefore', array('object' => $this)); + // Check module name validation + if (!Validate::isModuleName($this->name)) { + $this->_errors[] = Tools::displayError('Unable to install the module (Module name is not valid).'); + return false; + } - // Check PS version compliancy - if (!$this->checkCompliancy()) - { - $this->_errors[] = Tools::displayError('The version of your module is not compliant with your PrestaShop version.'); - return false; - } + // Check PS version compliancy + if (!$this->checkCompliancy()) { + $this->_errors[] = Tools::displayError('The version of your module is not compliant with your PrestaShop version.'); + return false; + } - // Check module dependencies - if (count($this->dependencies) > 0) - foreach ($this->dependencies as $dependency) - if (!Db::getInstance()->getRow('SELECT `id_module` FROM `'._DB_PREFIX_.'module` WHERE LOWER(`name`) = \''.pSQL(Tools::strtolower($dependency)).'\'')) - { - $error = Tools::displayError('Before installing this module, you have to install this/these module(s) first:').'<br />'; - foreach ($this->dependencies as $d) - $error .= '- '.$d.'<br />'; - $this->_errors[] = $error; - return false; - } + // Check module dependencies + if (count($this->dependencies) > 0) { + foreach ($this->dependencies as $dependency) { + if (!Db::getInstance()->getRow('SELECT `id_module` FROM `'._DB_PREFIX_.'module` WHERE LOWER(`name`) = \''.pSQL(Tools::strtolower($dependency)).'\'')) { + $error = Tools::displayError('Before installing this module, you have to install this/these module(s) first:').'<br />'; + foreach ($this->dependencies as $d) { + $error .= '- '.$d.'<br />'; + } + $this->_errors[] = $error; + return false; + } + } + } - // Check if module is installed - $result = Module::isInstalled($this->name); - if ($result) - { - $this->_errors[] = Tools::displayError('This module has already been installed.'); - return false; - } + // Check if module is installed + $result = Module::isInstalled($this->name); + if ($result) { + $this->_errors[] = Tools::displayError('This module has already been installed.'); + return false; + } - // Install overrides - try { - $this->installOverrides(); - } catch (Exception $e) { - $this->_errors[] = sprintf(Tools::displayError('Unable to install override: %s'), $e->getMessage()); - $this->uninstallOverrides(); - return false; - } + // Install overrides + try { + $this->installOverrides(); + } catch (Exception $e) { + $this->_errors[] = sprintf(Tools::displayError('Unable to install override: %s'), $e->getMessage()); + $this->uninstallOverrides(); + return false; + } - if (!$this->installControllers()) - return false; + if (!$this->installControllers()) { + return false; + } - // Install module and retrieve the installation id - $result = Db::getInstance()->insert($this->table, array('name' => $this->name, 'active' => 1, 'version' => $this->version)); - if (!$result) - { - $this->_errors[] = Tools::displayError('Technical error: PrestaShop could not install this module.'); - return false; - } - $this->id = Db::getInstance()->Insert_ID(); + // Install module and retrieve the installation id + $result = Db::getInstance()->insert($this->table, array('name' => $this->name, 'active' => 1, 'version' => $this->version)); + if (!$result) { + $this->_errors[] = Tools::displayError('Technical error: PrestaShop could not install this module.'); + return false; + } + $this->id = Db::getInstance()->Insert_ID(); - Cache::clean('Module::isInstalled'.$this->name); + Cache::clean('Module::isInstalled'.$this->name); - // Enable the module for current shops in context - $this->enable(); + // Enable the module for current shops in context + $this->enable(); - // Permissions management - Db::getInstance()->execute(' + // Permissions management + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'module_access` (`id_profile`, `id_module`, `view`, `configure`, `uninstall`) ( SELECT id_profile, '.(int)$this->id.', 1, 1, 1 FROM '._DB_PREFIX_.'access a @@ -365,7 +375,7 @@ abstract class ModuleCore WHERE class_name = \'AdminModules\' LIMIT 1) AND a.`view` = 1)'); - Db::getInstance()->execute(' + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'module_access` (`id_profile`, `id_module`, `view`, `configure`, `uninstall`) ( SELECT id_profile, '.(int)$this->id.', 1, 0, 0 FROM '._DB_PREFIX_.'access a @@ -374,1506 +384,1549 @@ abstract class ModuleCore WHERE class_name = \'AdminModules\' LIMIT 1) AND a.`view` = 0)'); - // Adding Restrictions for client groups - Group::addRestrictionsForModule($this->id, Shop::getShops(true, null, true)); - Hook::exec('actionModuleInstallAfter', array('object' => $this)); + // Adding Restrictions for client groups + Group::addRestrictionsForModule($this->id, Shop::getShops(true, null, true)); + Hook::exec('actionModuleInstallAfter', array('object' => $this)); - if (Module::$update_translations_after_install) - $this->updateModuleTranslations(); + if (Module::$update_translations_after_install) { + $this->updateModuleTranslations(); + } - return true; - } + return true; + } - public function checkCompliancy() - { - if (version_compare(_PS_VERSION_, $this->ps_versions_compliancy['min'], '<') || version_compare(_PS_VERSION_, $this->ps_versions_compliancy['max'], '>')) - return false; - else - return true; - } + public function checkCompliancy() + { + if (version_compare(_PS_VERSION_, $this->ps_versions_compliancy['min'], '<') || version_compare(_PS_VERSION_, $this->ps_versions_compliancy['max'], '>')) { + return false; + } else { + return true; + } + } - public static function updateTranslationsAfterInstall($update = true) - { - Module::$update_translations_after_install = (bool)$update; - } + public static function updateTranslationsAfterInstall($update = true) + { + Module::$update_translations_after_install = (bool)$update; + } - public function updateModuleTranslations() - { - return Language::updateModulesTranslations(array($this->name)); - } + public function updateModuleTranslations() + { + return Language::updateModulesTranslations(array($this->name)); + } - /** - * Set errors, warning or success message of a module upgrade - * - * @param $upgrade_detail - */ - protected function setUpgradeMessage($upgrade_detail) - { - // Store information if a module has been upgraded (memory optimization) - if ($upgrade_detail['available_upgrade']) - { - if ($upgrade_detail['success']) - { - $this->_confirmations[] = sprintf(Tools::displayError('Current version: %s'), $this->version); - $this->_confirmations[] = sprintf(Tools::displayError('%d file upgrade applied'), $upgrade_detail['number_upgraded']); - } - else - { - if (!$upgrade_detail['number_upgraded']) - $this->_errors[] = Tools::displayError('No upgrade has been applied'); - else - { - $this->_errors[] = sprintf(Tools::displayError('Upgraded from: %s to %s'), $upgrade_detail['upgraded_from'], $upgrade_detail['upgraded_to']); - $this->_errors[] = sprintf(Tools::displayError('%d upgrade left'), $upgrade_detail['number_upgrade_left']); - } + /** + * Set errors, warning or success message of a module upgrade + * + * @param $upgrade_detail + */ + protected function setUpgradeMessage($upgrade_detail) + { + // Store information if a module has been upgraded (memory optimization) + if ($upgrade_detail['available_upgrade']) { + if ($upgrade_detail['success']) { + $this->_confirmations[] = sprintf(Tools::displayError('Current version: %s'), $this->version); + $this->_confirmations[] = sprintf(Tools::displayError('%d file upgrade applied'), $upgrade_detail['number_upgraded']); + } else { + if (!$upgrade_detail['number_upgraded']) { + $this->_errors[] = Tools::displayError('No upgrade has been applied'); + } else { + $this->_errors[] = sprintf(Tools::displayError('Upgraded from: %s to %s'), $upgrade_detail['upgraded_from'], $upgrade_detail['upgraded_to']); + $this->_errors[] = sprintf(Tools::displayError('%d upgrade left'), $upgrade_detail['number_upgrade_left']); + } - if (isset($upgrade_detail['duplicate']) && $upgrade_detail['duplicate']) - $this->_errors[] = sprintf(Tools::displayError('Module %s cannot be upgraded this time: please refresh this page to update it.'), $this->name); - else - $this->_errors[] = Tools::displayError('To prevent any problem, this module has been turned off'); - } - } - } + if (isset($upgrade_detail['duplicate']) && $upgrade_detail['duplicate']) { + $this->_errors[] = sprintf(Tools::displayError('Module %s cannot be upgraded this time: please refresh this page to update it.'), $this->name); + } else { + $this->_errors[] = Tools::displayError('To prevent any problem, this module has been turned off'); + } + } + } + } - /** - * Init the upgrade module - * - * @param $module - * @return bool - */ - public static function initUpgradeModule($module) - { - if (((int)$module->installed == 1) & (empty($module->database_version) === true)) - { - Module::upgradeModuleVersion($module->name, $module->version); - $module->database_version = $module->version; - } + /** + * Init the upgrade module + * + * @param $module + * @return bool + */ + public static function initUpgradeModule($module) + { + if (((int)$module->installed == 1) & (empty($module->database_version) === true)) { + Module::upgradeModuleVersion($module->name, $module->version); + $module->database_version = $module->version; + } - // Init cache upgrade details - self::$modules_cache[$module->name]['upgrade'] = array( - 'success' => false, // bool to know if upgrade succeed or not - 'available_upgrade' => 0, // Number of available module before any upgrade - 'number_upgraded' => 0, // Number of upgrade done - 'number_upgrade_left' => 0, - 'upgrade_file_left' => array(), // List of the upgrade file left - 'version_fail' => 0, // Version of the upgrade failure - 'upgraded_from' => 0, // Version number before upgrading anything - 'upgraded_to' => 0, // Last upgrade applied - ); + // Init cache upgrade details + self::$modules_cache[$module->name]['upgrade'] = array( + 'success' => false, // bool to know if upgrade succeed or not + 'available_upgrade' => 0, // Number of available module before any upgrade + 'number_upgraded' => 0, // Number of upgrade done + 'number_upgrade_left' => 0, + 'upgrade_file_left' => array(), // List of the upgrade file left + 'version_fail' => 0, // Version of the upgrade failure + 'upgraded_from' => 0, // Version number before upgrading anything + 'upgraded_to' => 0, // Last upgrade applied + ); - // Need Upgrade will check and load upgrade file to the moduleCache upgrade case detail - $ret = $module->installed && Module::needUpgrade($module); - return $ret; - } + // Need Upgrade will check and load upgrade file to the moduleCache upgrade case detail + $ret = $module->installed && Module::needUpgrade($module); + return $ret; + } - /** - * Run the upgrade for a given module name and version - * - * @return array - */ - public function runUpgradeModule() - { - $upgrade = &self::$modules_cache[$this->name]['upgrade']; - foreach ($upgrade['upgrade_file_left'] as $num => $file_detail) - { - foreach ($file_detail['upgrade_function'] as $item) - if (function_exists($item)) - { - $upgrade['success'] = false; - $upgrade['duplicate'] = true; - break 2; - } + /** + * Run the upgrade for a given module name and version + * + * @return array + */ + public function runUpgradeModule() + { + $upgrade = &self::$modules_cache[$this->name]['upgrade']; + foreach ($upgrade['upgrade_file_left'] as $num => $file_detail) { + foreach ($file_detail['upgrade_function'] as $item) { + if (function_exists($item)) { + $upgrade['success'] = false; + $upgrade['duplicate'] = true; + break 2; + } + } - include($file_detail['file']); + include($file_detail['file']); - // Call the upgrade function if defined - $upgrade['success'] = false; - foreach ($file_detail['upgrade_function'] as $item) - if (function_exists($item)) - $upgrade['success'] = $item($this); + // Call the upgrade function if defined + $upgrade['success'] = false; + foreach ($file_detail['upgrade_function'] as $item) { + if (function_exists($item)) { + $upgrade['success'] = $item($this); + } + } - // Set detail when an upgrade succeed or failed - if ($upgrade['success']) - { - $upgrade['number_upgraded'] += 1; - $upgrade['upgraded_to'] = $file_detail['version']; + // Set detail when an upgrade succeed or failed + if ($upgrade['success']) { + $upgrade['number_upgraded'] += 1; + $upgrade['upgraded_to'] = $file_detail['version']; - unset($upgrade['upgrade_file_left'][$num]); - } - else - { - $upgrade['version_fail'] = $file_detail['version']; + unset($upgrade['upgrade_file_left'][$num]); + } else { + $upgrade['version_fail'] = $file_detail['version']; - // If any errors, the module is disabled - $this->disable(); - break; - } - } + // If any errors, the module is disabled + $this->disable(); + break; + } + } - $upgrade['number_upgrade_left'] = count($upgrade['upgrade_file_left']); + $upgrade['number_upgrade_left'] = count($upgrade['upgrade_file_left']); - // Update module version in DB with the last succeed upgrade - if ($upgrade['upgraded_to']) - Module::upgradeModuleVersion($this->name, $upgrade['upgraded_to']); - $this->setUpgradeMessage($upgrade); - return $upgrade; - } + // Update module version in DB with the last succeed upgrade + if ($upgrade['upgraded_to']) { + Module::upgradeModuleVersion($this->name, $upgrade['upgraded_to']); + } + $this->setUpgradeMessage($upgrade); + return $upgrade; + } - /** - * Upgrade the registered version to a new one - * - * @param $name - * @param $version - * @return bool - */ - public static function upgradeModuleVersion($name, $version) - { - return Db::getInstance()->execute(' + /** + * Upgrade the registered version to a new one + * + * @param $name + * @param $version + * @return bool + */ + public static function upgradeModuleVersion($name, $version) + { + return Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'module` m SET m.version = \''.pSQL($version).'\' WHERE m.name = \''.pSQL($name).'\''); - } + } - /** - * Check if a module need to be upgraded. - * This method modify the module_cache adding an upgrade list file - * - * @param $module - * @return bool - */ - public static function needUpgrade($module) - { - self::$modules_cache[$module->name]['upgrade']['upgraded_from'] = $module->database_version; - // Check the version of the module with the registered one and look if any upgrade file exist - if (Tools::version_compare($module->version, $module->database_version, '>')) - { - $old_version = $module->database_version; - $module = Module::getInstanceByName($module->name); - if ($module instanceof Module) - return $module->loadUpgradeVersionList($module->name, $module->version, $old_version); - } - return null; - } + /** + * Check if a module need to be upgraded. + * This method modify the module_cache adding an upgrade list file + * + * @param $module + * @return bool + */ + public static function needUpgrade($module) + { + self::$modules_cache[$module->name]['upgrade']['upgraded_from'] = $module->database_version; + // Check the version of the module with the registered one and look if any upgrade file exist + if (Tools::version_compare($module->version, $module->database_version, '>')) { + $old_version = $module->database_version; + $module = Module::getInstanceByName($module->name); + if ($module instanceof Module) { + return $module->loadUpgradeVersionList($module->name, $module->version, $old_version); + } + } + return null; + } - /** - * Load the available list of upgrade of a specified module - * with an associated version - * - * @param $module_name - * @param $module_version - * @param $registered_version - * @return bool to know directly if any files have been found - */ - protected static function loadUpgradeVersionList($module_name, $module_version, $registered_version) - { - $list = array(); + /** + * Load the available list of upgrade of a specified module + * with an associated version + * + * @param $module_name + * @param $module_version + * @param $registered_version + * @return bool to know directly if any files have been found + */ + protected static function loadUpgradeVersionList($module_name, $module_version, $registered_version) + { + $list = array(); - $upgrade_path = _PS_MODULE_DIR_.$module_name.'/upgrade/'; + $upgrade_path = _PS_MODULE_DIR_.$module_name.'/upgrade/'; - // Check if folder exist and it could be read - if (file_exists($upgrade_path) && ($files = scandir($upgrade_path))) - { - // Read each file name - foreach ($files as $file) - if (!in_array($file, array('.', '..', '.svn', 'index.php')) && preg_match('/\.php$/', $file)) - { - $tab = explode('-', $file); + // Check if folder exist and it could be read + if (file_exists($upgrade_path) && ($files = scandir($upgrade_path))) { + // Read each file name + foreach ($files as $file) { + if (!in_array($file, array('.', '..', '.svn', 'index.php')) && preg_match('/\.php$/', $file)) { + $tab = explode('-', $file); - if (!isset($tab[1])) - continue; + if (!isset($tab[1])) { + continue; + } - $file_version = basename($tab[1], '.php'); - // Compare version, if minor than actual, we need to upgrade the module - if (count($tab) == 2 && - (Tools::version_compare($file_version, $module_version, '<=') && - Tools::version_compare($file_version, $registered_version, '>'))) - { - $list[] = array( - 'file' => $upgrade_path.$file, - 'version' => $file_version, - 'upgrade_function' => array( - 'upgrade_module_'.str_replace('.', '_', $file_version), - 'upgradeModule'.str_replace('.', '', $file_version)) - ); - } - } - } + $file_version = basename($tab[1], '.php'); + // Compare version, if minor than actual, we need to upgrade the module + if (count($tab) == 2 && + (Tools::version_compare($file_version, $module_version, '<=') && + Tools::version_compare($file_version, $registered_version, '>'))) { + $list[] = array( + 'file' => $upgrade_path.$file, + 'version' => $file_version, + 'upgrade_function' => array( + 'upgrade_module_'.str_replace('.', '_', $file_version), + 'upgradeModule'.str_replace('.', '', $file_version)) + ); + } + } + } + } - // No files upgrade, then upgrade succeed - if (count($list) == 0) - { - self::$modules_cache[$module_name]['upgrade']['success'] = true; - Module::upgradeModuleVersion($module_name, $module_version); - } + // No files upgrade, then upgrade succeed + if (count($list) == 0) { + self::$modules_cache[$module_name]['upgrade']['success'] = true; + Module::upgradeModuleVersion($module_name, $module_version); + } - usort($list, 'ps_module_version_sort'); + usort($list, 'ps_module_version_sort'); - // Set the list to module cache - self::$modules_cache[$module_name]['upgrade']['upgrade_file_left'] = $list; - self::$modules_cache[$module_name]['upgrade']['available_upgrade'] = count($list); - return (bool)count($list); - } + // Set the list to module cache + self::$modules_cache[$module_name]['upgrade']['upgrade_file_left'] = $list; + self::$modules_cache[$module_name]['upgrade']['available_upgrade'] = count($list); + return (bool)count($list); + } - /** - * Return the status of the upgraded module - * - * @param $module_name - * @return bool - */ - public static function getUpgradeStatus($module_name) - { - return (isset(self::$modules_cache[$module_name]) && - self::$modules_cache[$module_name]['upgrade']['success']); - } + /** + * Return the status of the upgraded module + * + * @param $module_name + * @return bool + */ + public static function getUpgradeStatus($module_name) + { + return (isset(self::$modules_cache[$module_name]) && + self::$modules_cache[$module_name]['upgrade']['success']); + } - /** - * Delete module from datable - * - * @return bool result - */ - public function uninstall() - { - // Check module installation id validation - if (!Validate::isUnsignedId($this->id)) - { - $this->_errors[] = Tools::displayError('The module is not installed.'); - return false; - } + /** + * Delete module from datable + * + * @return bool result + */ + public function uninstall() + { + // Check module installation id validation + if (!Validate::isUnsignedId($this->id)) { + $this->_errors[] = Tools::displayError('The module is not installed.'); + return false; + } - // Uninstall overrides - if (!$this->uninstallOverrides()) - return false; + // Uninstall overrides + if (!$this->uninstallOverrides()) { + return false; + } - // Retrieve hooks used by the module - $sql = 'SELECT `id_hook` FROM `'._DB_PREFIX_.'hook_module` WHERE `id_module` = '.(int)$this->id; - $result = Db::getInstance()->executeS($sql); - foreach ($result as $row) - { - $this->unregisterHook((int)$row['id_hook']); - $this->unregisterExceptions((int)$row['id_hook']); - } + // Retrieve hooks used by the module + $sql = 'SELECT `id_hook` FROM `'._DB_PREFIX_.'hook_module` WHERE `id_module` = '.(int)$this->id; + $result = Db::getInstance()->executeS($sql); + foreach ($result as $row) { + $this->unregisterHook((int)$row['id_hook']); + $this->unregisterExceptions((int)$row['id_hook']); + } - foreach ($this->controllers as $controller) - { - $page_name = 'module-'.$this->name.'-'.$controller; - $meta = Db::getInstance()->getValue('SELECT id_meta FROM `'._DB_PREFIX_.'meta` WHERE page="'.pSQL($page_name).'"'); - if ((int)$meta > 0) - { - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'theme_meta` WHERE id_meta='.(int)$meta); - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'meta_lang` WHERE id_meta='.(int)$meta); - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'meta` WHERE id_meta='.(int)$meta); - } - } + foreach ($this->controllers as $controller) { + $page_name = 'module-'.$this->name.'-'.$controller; + $meta = Db::getInstance()->getValue('SELECT id_meta FROM `'._DB_PREFIX_.'meta` WHERE page="'.pSQL($page_name).'"'); + if ((int)$meta > 0) { + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'theme_meta` WHERE id_meta='.(int)$meta); + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'meta_lang` WHERE id_meta='.(int)$meta); + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'meta` WHERE id_meta='.(int)$meta); + } + } - // Disable the module for all shops - $this->disable(true); + // Disable the module for all shops + $this->disable(true); - // Delete permissions module access - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module_access` WHERE `id_module` = '.(int)$this->id); + // Delete permissions module access + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module_access` WHERE `id_module` = '.(int)$this->id); - // Remove restrictions for client groups - Group::truncateRestrictionsByModule($this->id); + // Remove restrictions for client groups + Group::truncateRestrictionsByModule($this->id); - // Uninstall the module - if (Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module` WHERE `id_module` = '.(int)$this->id)) - { - Cache::clean('Module::isInstalled'.$this->name); - Cache::clean('Module::getModuleIdByName_'.pSQL($this->name)); - return true; - } + // Uninstall the module + if (Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'module` WHERE `id_module` = '.(int)$this->id)) { + Cache::clean('Module::isInstalled'.$this->name); + Cache::clean('Module::getModuleIdByName_'.pSQL($this->name)); + return true; + } - return false; - } + return false; + } - /** - * This function enable module $name. If an $name is an array, - * this will enable all of them - * - * @param array|string $name - * @return true if succeed - * @since 1.4.1 - */ - public static function enableByName($name) - { - // If $name is not an array, we set it as an array - if (!is_array($name)) - $name = array($name); - $res = true; - // Enable each module - foreach ($name as $n) - if (Validate::isModuleName($n)) - $res &= Module::getInstanceByName($n)->enable(); - return $res; - } + /** + * This function enable module $name. If an $name is an array, + * this will enable all of them + * + * @param array|string $name + * @return true if succeed + * @since 1.4.1 + */ + public static function enableByName($name) + { + // If $name is not an array, we set it as an array + if (!is_array($name)) { + $name = array($name); + } + $res = true; + // Enable each module + foreach ($name as $n) { + if (Validate::isModuleName($n)) { + $res &= Module::getInstanceByName($n)->enable(); + } + } + return $res; + } - /** - * Activate current module. - * - * @param bool $force_all If true, enable module for all shop - */ - public function enable($force_all = false) - { - // Retrieve all shops where the module is enabled - $list = Shop::getContextListShopID(); - if (!$this->id || !is_array($list)) - return false; - $sql = 'SELECT `id_shop` FROM `'._DB_PREFIX_.'module_shop` + /** + * Activate current module. + * + * @param bool $force_all If true, enable module for all shop + */ + public function enable($force_all = false) + { + // Retrieve all shops where the module is enabled + $list = Shop::getContextListShopID(); + if (!$this->id || !is_array($list)) { + return false; + } + $sql = 'SELECT `id_shop` FROM `'._DB_PREFIX_.'module_shop` WHERE `id_module` = '.(int)$this->id. - ((!$force_all) ? ' AND `id_shop` IN('.implode(', ', $list).')' : ''); + ((!$force_all) ? ' AND `id_shop` IN('.implode(', ', $list).')' : ''); - // Store the results in an array - $items = array(); - if ($results = Db::getInstance($sql)->executeS($sql)) - foreach ($results as $row) - $items[] = $row['id_shop']; + // Store the results in an array + $items = array(); + if ($results = Db::getInstance($sql)->executeS($sql)) { + foreach ($results as $row) { + $items[] = $row['id_shop']; + } + } - // Enable module in the shop where it is not enabled yet - foreach ($list as $id) - if (!in_array($id, $items)) - Db::getInstance()->insert('module_shop', array( - 'id_module' => $this->id, - 'id_shop' => $id, - )); + // Enable module in the shop where it is not enabled yet + foreach ($list as $id) { + if (!in_array($id, $items)) { + Db::getInstance()->insert('module_shop', array( + 'id_module' => $this->id, + 'id_shop' => $id, + )); + } + } - return true; - } + return true; + } - public function enableDevice($device) - { - Db::getInstance()->execute(' + public function enableDevice($device) + { + Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'module_shop SET enable_device = enable_device + '.(int)$device.' WHERE enable_device &~ '.(int)$device.' AND id_module='.(int)$this->id. - Shop::addSqlRestriction() - ); + Shop::addSqlRestriction() + ); - return true; - } + return true; + } - public function disableDevice($device) - { - Db::getInstance()->execute(' + public function disableDevice($device) + { + Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'module_shop SET enable_device = enable_device - '.(int)$device.' WHERE enable_device & '.(int)$device.' AND id_module='.(int)$this->id. - Shop::addSqlRestriction() - ); + Shop::addSqlRestriction() + ); - return true; - } + return true; + } - /** - * This function disable module $name. If an $name is an array, - * this will disable all of them - * - * @param array|string $name - * @return true if succeed - * @since 1.4.1 - */ - public static function disableByName($name) - { - // If $name is not an array, we set it as an array - if (!is_array($name)) - $name = array($name); - $res = true; - // Disable each module - foreach ($name as $n) - if (Validate::isModuleName($n)) - $res &= Module::getInstanceByName($n)->disable(); - return $res; - } + /** + * This function disable module $name. If an $name is an array, + * this will disable all of them + * + * @param array|string $name + * @return true if succeed + * @since 1.4.1 + */ + public static function disableByName($name) + { + // If $name is not an array, we set it as an array + if (!is_array($name)) { + $name = array($name); + } + $res = true; + // Disable each module + foreach ($name as $n) { + if (Validate::isModuleName($n)) { + $res &= Module::getInstanceByName($n)->disable(); + } + } + return $res; + } - /** - * Desactivate current module. - * - * @param bool $force_all If true, disable module for all shop - */ - public function disable($force_all = false) - { - // Disable module for all shops - $sql = 'DELETE FROM `'._DB_PREFIX_.'module_shop` WHERE `id_module` = '.(int)$this->id.' '.((!$force_all) ? ' AND `id_shop` IN('.implode(', ', Shop::getContextListShopID()).')' : ''); - Db::getInstance()->execute($sql); - } + /** + * Desactivate current module. + * + * @param bool $force_all If true, disable module for all shop + */ + public function disable($force_all = false) + { + // Disable module for all shops + $sql = 'DELETE FROM `'._DB_PREFIX_.'module_shop` WHERE `id_module` = '.(int)$this->id.' '.((!$force_all) ? ' AND `id_shop` IN('.implode(', ', Shop::getContextListShopID()).')' : ''); + Db::getInstance()->execute($sql); + } - /** - * Display flags in forms for translations - * @deprecated since 1.6.0.10 - * - * @param array $languages All languages available - * @param int $default_language Default language id - * @param string $ids Multilingual div ids in form - * @param string $id Current div id] - * @param bool $return define the return way : false for a display, true for a return - * @param bool $use_vars_instead_of_ids use an js vars instead of ids seperate by "¤" - */ - public function displayFlags($languages, $default_language, $ids, $id, $return = false, $use_vars_instead_of_ids = false) - { - if (count($languages) == 1) - return false; + /** + * Display flags in forms for translations + * @deprecated since 1.6.0.10 + * + * @param array $languages All languages available + * @param int $default_language Default language id + * @param string $ids Multilingual div ids in form + * @param string $id Current div id] + * @param bool $return define the return way : false for a display, true for a return + * @param bool $use_vars_instead_of_ids use an js vars instead of ids seperate by "¤" + */ + public function displayFlags($languages, $default_language, $ids, $id, $return = false, $use_vars_instead_of_ids = false) + { + if (count($languages) == 1) { + return false; + } - $output = ' + $output = ' <div class="displayed_flag"> <img src="../img/l/'.$default_language.'.jpg" class="pointer" id="language_current_'.$id.'" onclick="toggleLanguageFlags(this);" alt="" /> </div> <div id="languages_'.$id.'" class="language_flags"> '.$this->l('Choose language:').'<br /><br />'; - foreach ($languages as $language) - if ($use_vars_instead_of_ids) - $output .= '<img src="../img/l/'.(int)$language['id_lang'].'.jpg" class="pointer" alt="'.$language['name'].'" title="'.$language['name'].'" onclick="changeLanguage(\''.$id.'\', '.$ids.', '.$language['id_lang'].', \''.$language['iso_code'].'\');" /> '; - else - $output .= '<img src="../img/l/'.(int)$language['id_lang'].'.jpg" class="pointer" alt="'.$language['name'].'" title="'.$language['name'].'" onclick="changeLanguage(\''.$id.'\', \''.$ids.'\', '.$language['id_lang'].', \''.$language['iso_code'].'\');" /> '; - $output .= '</div>'; + foreach ($languages as $language) { + if ($use_vars_instead_of_ids) { + $output .= '<img src="../img/l/'.(int)$language['id_lang'].'.jpg" class="pointer" alt="'.$language['name'].'" title="'.$language['name'].'" onclick="changeLanguage(\''.$id.'\', '.$ids.', '.$language['id_lang'].', \''.$language['iso_code'].'\');" /> '; + } else { + $output .= '<img src="../img/l/'.(int)$language['id_lang'].'.jpg" class="pointer" alt="'.$language['name'].'" title="'.$language['name'].'" onclick="changeLanguage(\''.$id.'\', \''.$ids.'\', '.$language['id_lang'].', \''.$language['iso_code'].'\');" /> '; + } + } + $output .= '</div>'; - if ($return) - return $output; - echo $output; - } + if ($return) { + return $output; + } + echo $output; + } - /** - * Connect module to a hook - * - * @param string $hook_name Hook name - * @param array $shop_list List of shop linked to the hook (if null, link hook to all shops) - * @return bool result - */ - public function registerHook($hook_name, $shop_list = null) - { - $return = true; - if (is_array($hook_name)) - $hook_names = $hook_name; - else - $hook_names = array($hook_name); + /** + * Connect module to a hook + * + * @param string $hook_name Hook name + * @param array $shop_list List of shop linked to the hook (if null, link hook to all shops) + * @return bool result + */ + public function registerHook($hook_name, $shop_list = null) + { + $return = true; + if (is_array($hook_name)) { + $hook_names = $hook_name; + } else { + $hook_names = array($hook_name); + } - foreach ($hook_names as $hook_name) - { - // Check hook name validation and if module is installed - if (!Validate::isHookName($hook_name)) - throw new PrestaShopException('Invalid hook name'); - if (!isset($this->id) || !is_numeric($this->id)) - return false; + foreach ($hook_names as $hook_name) { + // Check hook name validation and if module is installed + if (!Validate::isHookName($hook_name)) { + throw new PrestaShopException('Invalid hook name'); + } + if (!isset($this->id) || !is_numeric($this->id)) { + return false; + } - // Retrocompatibility - $hook_name_bak = $hook_name; - if ($alias = Hook::getRetroHookName($hook_name)) - $hook_name = $alias; + // Retrocompatibility + $hook_name_bak = $hook_name; + if ($alias = Hook::getRetroHookName($hook_name)) { + $hook_name = $alias; + } - Hook::exec('actionModuleRegisterHookBefore', array('object' => $this, 'hook_name' => $hook_name)); - // Get hook id - $id_hook = Hook::getIdByName($hook_name); - $live_edit = Hook::getLiveEditById((int)Hook::getIdByName($hook_name_bak)); + Hook::exec('actionModuleRegisterHookBefore', array('object' => $this, 'hook_name' => $hook_name)); + // Get hook id + $id_hook = Hook::getIdByName($hook_name); + $live_edit = Hook::getLiveEditById((int)Hook::getIdByName($hook_name_bak)); - // If hook does not exist, we create it - if (!$id_hook) - { - $new_hook = new Hook(); - $new_hook->name = pSQL($hook_name); - $new_hook->title = pSQL($hook_name); - $new_hook->live_edit = (bool)preg_match('/^display/i', $new_hook->name); - $new_hook->position = (bool)$new_hook->live_edit; - $new_hook->add(); - $id_hook = $new_hook->id; - if (!$id_hook) - return false; - } + // If hook does not exist, we create it + if (!$id_hook) { + $new_hook = new Hook(); + $new_hook->name = pSQL($hook_name); + $new_hook->title = pSQL($hook_name); + $new_hook->live_edit = (bool)preg_match('/^display/i', $new_hook->name); + $new_hook->position = (bool)$new_hook->live_edit; + $new_hook->add(); + $id_hook = $new_hook->id; + if (!$id_hook) { + return false; + } + } - // If shop lists is null, we fill it with all shops - if (is_null($shop_list)) - $shop_list = Shop::getCompleteListOfShopsID(); + // If shop lists is null, we fill it with all shops + if (is_null($shop_list)) { + $shop_list = Shop::getCompleteListOfShopsID(); + } - $shop_list_employee = Shop::getShops(true, null, true); + $shop_list_employee = Shop::getShops(true, null, true); - foreach ($shop_list as $shop_id) - { - // Check if already register - $sql = 'SELECT hm.`id_module` + foreach ($shop_list as $shop_id) { + // Check if already register + $sql = 'SELECT hm.`id_module` FROM `'._DB_PREFIX_.'hook_module` hm, `'._DB_PREFIX_.'hook` h WHERE hm.`id_module` = '.(int)$this->id.' AND h.`id_hook` = '.$id_hook.' AND h.`id_hook` = hm.`id_hook` AND `id_shop` = '.(int)$shop_id; - if (Db::getInstance()->getRow($sql)) - continue; + if (Db::getInstance()->getRow($sql)) { + continue; + } - // Get module position in hook - $sql = 'SELECT MAX(`position`) AS position + // Get module position in hook + $sql = 'SELECT MAX(`position`) AS position FROM `'._DB_PREFIX_.'hook_module` WHERE `id_hook` = '.(int)$id_hook.' AND `id_shop` = '.(int)$shop_id; - if (!$position = Db::getInstance()->getValue($sql)) - $position = 0; + if (!$position = Db::getInstance()->getValue($sql)) { + $position = 0; + } - // Register module in hook - $return &= Db::getInstance()->insert('hook_module', array( - 'id_module' => (int)$this->id, - 'id_hook' => (int)$id_hook, - 'id_shop' => (int)$shop_id, - 'position' => (int)($position + 1), - )); + // Register module in hook + $return &= Db::getInstance()->insert('hook_module', array( + 'id_module' => (int)$this->id, + 'id_hook' => (int)$id_hook, + 'id_shop' => (int)$shop_id, + 'position' => (int)($position + 1), + )); - if (!in_array($shop_id, $shop_list_employee)) - { - $where = '`id_module` = '.(int)$this->id.' AND `id_shop` = '.(int)$shop_id; - $return &= Db::getInstance()->delete('module_shop', $where); - } - } + if (!in_array($shop_id, $shop_list_employee)) { + $where = '`id_module` = '.(int)$this->id.' AND `id_shop` = '.(int)$shop_id; + $return &= Db::getInstance()->delete('module_shop', $where); + } + } - Hook::exec('actionModuleRegisterHookAfter', array('object' => $this, 'hook_name' => $hook_name)); - } - return $return; - } + Hook::exec('actionModuleRegisterHookAfter', array('object' => $this, 'hook_name' => $hook_name)); + } + return $return; + } - /** - * Unregister module from hook - * - * @param mixed $id_hook Hook id (can be a hook name since 1.5.0) - * @param array $shop_list List of shop - * @return bool result - */ - public function unregisterHook($hook_id, $shop_list = null) - { - // Get hook id if a name is given as argument - if (!is_numeric($hook_id)) - { - $hook_name = (string)$hook_id; - // Retrocompatibility - $hook_id = Hook::getIdByName($hook_name); - if (!$hook_id) - return false; - } - else - $hook_name = Hook::getNameById((int)$hook_id); + /** + * Unregister module from hook + * + * @param mixed $id_hook Hook id (can be a hook name since 1.5.0) + * @param array $shop_list List of shop + * @return bool result + */ + public function unregisterHook($hook_id, $shop_list = null) + { + // Get hook id if a name is given as argument + if (!is_numeric($hook_id)) { + $hook_name = (string)$hook_id; + // Retrocompatibility + $hook_id = Hook::getIdByName($hook_name); + if (!$hook_id) { + return false; + } + } else { + $hook_name = Hook::getNameById((int)$hook_id); + } - Hook::exec('actionModuleUnRegisterHookBefore', array('object' => $this, 'hook_name' => $hook_name)); + Hook::exec('actionModuleUnRegisterHookBefore', array('object' => $this, 'hook_name' => $hook_name)); - // Unregister module on hook by id - $sql = 'DELETE FROM `'._DB_PREFIX_.'hook_module` + // Unregister module on hook by id + $sql = 'DELETE FROM `'._DB_PREFIX_.'hook_module` WHERE `id_module` = '.(int)$this->id.' AND `id_hook` = '.(int)$hook_id - .(($shop_list) ? ' AND `id_shop` IN('.implode(', ', array_map('intval', $shop_list)).')' : ''); - $result = Db::getInstance()->execute($sql); + .(($shop_list) ? ' AND `id_shop` IN('.implode(', ', array_map('intval', $shop_list)).')' : ''); + $result = Db::getInstance()->execute($sql); - // Clean modules position - $this->cleanPositions($hook_id, $shop_list); + // Clean modules position + $this->cleanPositions($hook_id, $shop_list); - Hook::exec('actionModuleUnRegisterHookAfter', array('object' => $this, 'hook_name' => $hook_name)); + Hook::exec('actionModuleUnRegisterHookAfter', array('object' => $this, 'hook_name' => $hook_name)); - return $result; - } + return $result; + } - /** - * Unregister exceptions linked to module - * - * @param int $id_hook Hook id - * @param array $shop_list List of shop - * @return bool result - */ - public function unregisterExceptions($hook_id, $shop_list = null) - { - $sql = 'DELETE FROM `'._DB_PREFIX_.'hook_module_exceptions` + /** + * Unregister exceptions linked to module + * + * @param int $id_hook Hook id + * @param array $shop_list List of shop + * @return bool result + */ + public function unregisterExceptions($hook_id, $shop_list = null) + { + $sql = 'DELETE FROM `'._DB_PREFIX_.'hook_module_exceptions` WHERE `id_module` = '.(int)$this->id.' AND `id_hook` = '.(int)$hook_id - .(($shop_list) ? ' AND `id_shop` IN('.implode(', ', array_map('intval', $shop_list)).')' : ''); - return Db::getInstance()->execute($sql); - } + .(($shop_list) ? ' AND `id_shop` IN('.implode(', ', array_map('intval', $shop_list)).')' : ''); + return Db::getInstance()->execute($sql); + } - /** - * Add exceptions for module->Hook - * - * @param int $id_hook Hook id - * @param array $excepts List of file name - * @param array $shop_list List of shop - * @return bool result - */ - public function registerExceptions($id_hook, $excepts, $shop_list = null) - { - // If shop lists is null, we fill it with all shops - if (is_null($shop_list)) - $shop_list = Shop::getContextListShopID(); + /** + * Add exceptions for module->Hook + * + * @param int $id_hook Hook id + * @param array $excepts List of file name + * @param array $shop_list List of shop + * @return bool result + */ + public function registerExceptions($id_hook, $excepts, $shop_list = null) + { + // If shop lists is null, we fill it with all shops + if (is_null($shop_list)) { + $shop_list = Shop::getContextListShopID(); + } - // Save modules exception for each shop - foreach ($shop_list as $shop_id) - { - foreach ($excepts as $except) - { - if (!$except) - continue; - $insert_exception = array( - 'id_module' => (int)$this->id, - 'id_hook' => (int)$id_hook, - 'id_shop' => (int)$shop_id, - 'file_name' => pSQL($except), - ); - $result = Db::getInstance()->insert('hook_module_exceptions', $insert_exception); - if (!$result) - return false; - } - } - return true; - } + // Save modules exception for each shop + foreach ($shop_list as $shop_id) { + foreach ($excepts as $except) { + if (!$except) { + continue; + } + $insert_exception = array( + 'id_module' => (int)$this->id, + 'id_hook' => (int)$id_hook, + 'id_shop' => (int)$shop_id, + 'file_name' => pSQL($except), + ); + $result = Db::getInstance()->insert('hook_module_exceptions', $insert_exception); + if (!$result) { + return false; + } + } + } + return true; + } - /** - * Edit exceptions for module->Hook - * - * @param int $hookID Hook id - * @param array $excepts List of shopID and file name - * @return bool result - */ - public function editExceptions($id_hook, $excepts) - { - $result = true; - foreach ($excepts as $shop_id => $except) - { - $shop_list = ($shop_id == 0) ? Shop::getContextListShopID() : array($shop_id); - $this->unregisterExceptions($id_hook, $shop_list); - $result &= $this->registerExceptions($id_hook, $except, $shop_list); - } + /** + * Edit exceptions for module->Hook + * + * @param int $hookID Hook id + * @param array $excepts List of shopID and file name + * @return bool result + */ + public function editExceptions($id_hook, $excepts) + { + $result = true; + foreach ($excepts as $shop_id => $except) { + $shop_list = ($shop_id == 0) ? Shop::getContextListShopID() : array($shop_id); + $this->unregisterExceptions($id_hook, $shop_list); + $result &= $this->registerExceptions($id_hook, $except, $shop_list); + } - return $result; - } + return $result; + } - /** - * This function is used to determine the module name - * of an AdminTab which belongs to a module, in order to keep translation - * related to a module in its directory (instead of $_LANGADM) - * - * @param mixed $current_class the - * @return bool|string if the class belongs to a module, will return the module name. Otherwise, return false. - */ - public static function getModuleNameFromClass($current_class) - { - // Module can now define AdminTab keeping the module translations method, - // i.e. in modules/[module name]/[iso_code].php - if (!isset(self::$classInModule[$current_class]) && class_exists($current_class)) - { - global $_MODULES; - $_MODULE = array(); - $reflection_class = new ReflectionClass($current_class); - $file_path = realpath($reflection_class->getFileName()); - $realpath_module_dir = realpath(_PS_MODULE_DIR_); - if (substr(realpath($file_path), 0, strlen($realpath_module_dir)) == $realpath_module_dir) - { - // For controllers in module/controllers path - if (basename(dirname(dirname($file_path))) == 'controllers') - self::$classInModule[$current_class] = basename(dirname(dirname(dirname($file_path)))); - // For old AdminTab controllers - else - self::$classInModule[$current_class] = substr(dirname($file_path), strlen($realpath_module_dir) + 1); + /** + * This function is used to determine the module name + * of an AdminTab which belongs to a module, in order to keep translation + * related to a module in its directory (instead of $_LANGADM) + * + * @param mixed $current_class the + * @return bool|string if the class belongs to a module, will return the module name. Otherwise, return false. + */ + public static function getModuleNameFromClass($current_class) + { + // Module can now define AdminTab keeping the module translations method, + // i.e. in modules/[module name]/[iso_code].php + if (!isset(self::$classInModule[$current_class]) && class_exists($current_class)) { + global $_MODULES; + $_MODULE = array(); + $reflection_class = new ReflectionClass($current_class); + $file_path = realpath($reflection_class->getFileName()); + $realpath_module_dir = realpath(_PS_MODULE_DIR_); + if (substr(realpath($file_path), 0, strlen($realpath_module_dir)) == $realpath_module_dir) { + // For controllers in module/controllers path + if (basename(dirname(dirname($file_path))) == 'controllers') { + self::$classInModule[$current_class] = basename(dirname(dirname(dirname($file_path)))); + } else { + // For old AdminTab controllers + self::$classInModule[$current_class] = substr(dirname($file_path), strlen($realpath_module_dir) + 1); + } - $file = _PS_MODULE_DIR_.self::$classInModule[$current_class].'/'.Context::getContext()->language->iso_code.'.php'; - if (Tools::file_exists_cache($file) && include_once($file)) - $_MODULES = !empty($_MODULES) ? array_merge($_MODULES, $_MODULE) : $_MODULE; - } - else - self::$classInModule[$current_class] = false; - } + $file = _PS_MODULE_DIR_.self::$classInModule[$current_class].'/'.Context::getContext()->language->iso_code.'.php'; + if (Tools::file_exists_cache($file) && include_once($file)) { + $_MODULES = !empty($_MODULES) ? array_merge($_MODULES, $_MODULE) : $_MODULE; + } + } else { + self::$classInModule[$current_class] = false; + } + } - // return name of the module, or false - return self::$classInModule[$current_class]; - } + // return name of the module, or false + return self::$classInModule[$current_class]; + } - /** - * Return an instance of the specified module - * - * @param string $module_name Module name - * @return Module - */ - public static function getInstanceByName($module_name) - { - if (!Validate::isModuleName($module_name)) - { - if (_PS_MODE_DEV_) - die(Tools::displayError(Tools::safeOutput($module_name).' is not a valid module name.')); - return false; - } + /** + * Return an instance of the specified module + * + * @param string $module_name Module name + * @return Module + */ + public static function getInstanceByName($module_name) + { + if (!Validate::isModuleName($module_name)) { + if (_PS_MODE_DEV_) { + die(Tools::displayError(Tools::safeOutput($module_name).' is not a valid module name.')); + } + return false; + } - if (!isset(self::$_INSTANCE[$module_name])) - { - if (!Tools::file_exists_no_cache(_PS_MODULE_DIR_.$module_name.'/'.$module_name.'.php')) - return false; - return Module::coreLoadModule($module_name); - } - return self::$_INSTANCE[$module_name]; - } + if (!isset(self::$_INSTANCE[$module_name])) { + if (!Tools::file_exists_no_cache(_PS_MODULE_DIR_.$module_name.'/'.$module_name.'.php')) { + return false; + } + return Module::coreLoadModule($module_name); + } + return self::$_INSTANCE[$module_name]; + } - protected static function coreLoadModule($module_name) - { - // Define if we will log modules performances for this session - if (Module::$_log_modules_perfs === null) - { - $modulo = _PS_DEBUG_PROFILING_ ? 1 : Configuration::get('PS_log_modules_perfs_MODULO'); - Module::$_log_modules_perfs = ($modulo && mt_rand(0, $modulo - 1) == 0); - if (Module::$_log_modules_perfs) - Module::$_log_modules_perfs_session = mt_rand(); - } + protected static function coreLoadModule($module_name) + { + // Define if we will log modules performances for this session + if (Module::$_log_modules_perfs === null) { + $modulo = _PS_DEBUG_PROFILING_ ? 1 : Configuration::get('PS_log_modules_perfs_MODULO'); + Module::$_log_modules_perfs = ($modulo && mt_rand(0, $modulo - 1) == 0); + if (Module::$_log_modules_perfs) { + Module::$_log_modules_perfs_session = mt_rand(); + } + } - // Store time and memory before and after hook call and save the result in the database - if (Module::$_log_modules_perfs) - { - $time_start = microtime(true); - $memory_start = memory_get_usage(true); - } + // Store time and memory before and after hook call and save the result in the database + if (Module::$_log_modules_perfs) { + $time_start = microtime(true); + $memory_start = memory_get_usage(true); + } - include_once(_PS_MODULE_DIR_.$module_name.'/'.$module_name.'.php'); + include_once(_PS_MODULE_DIR_.$module_name.'/'.$module_name.'.php'); - $r = false; - if (Tools::file_exists_no_cache(_PS_OVERRIDE_DIR_.'modules/'.$module_name.'/'.$module_name.'.php')) - { - include_once(_PS_OVERRIDE_DIR_.'modules/'.$module_name.'/'.$module_name.'.php'); - $override = $module_name.'Override'; + $r = false; + if (Tools::file_exists_no_cache(_PS_OVERRIDE_DIR_.'modules/'.$module_name.'/'.$module_name.'.php')) { + include_once(_PS_OVERRIDE_DIR_.'modules/'.$module_name.'/'.$module_name.'.php'); + $override = $module_name.'Override'; - if (class_exists($override, false)) - $r = self::$_INSTANCE[$module_name] = new $override; - } + if (class_exists($override, false)) { + $r = self::$_INSTANCE[$module_name] = Adapter_ServiceLocator::get($override); + } + } - if (!$r && class_exists($module_name, false)) - $r = self::$_INSTANCE[$module_name] = Adapter_ServiceLocator::get($module_name); + if (!$r && class_exists($module_name, false)) { + $r = self::$_INSTANCE[$module_name] = Adapter_ServiceLocator::get($module_name); + } - if (Module::$_log_modules_perfs) - { - $time_end = microtime(true); - $memory_end = memory_get_usage(true); + if (Module::$_log_modules_perfs) { + $time_end = microtime(true); + $memory_end = memory_get_usage(true); - Db::getInstance()->execute(' + Db::getInstance()->execute(' INSERT INTO '._DB_PREFIX_.'modules_perfs (session, module, method, time_start, time_end, memory_start, memory_end) VALUES ('.(int)Module::$_log_modules_perfs_session.', "'.pSQL($module_name).'", "__construct", "'.pSQL($time_start).'", "'.pSQL($time_end).'", '.(int)$memory_start.', '.(int)$memory_end.')'); - } + } - return $r; - } + return $r; + } - /** - * Return an instance of the specified module - * - * @param int $id_module Module ID - * @return Module instance - */ - public static function getInstanceById($id_module) - { - static $id2name = null; + /** + * Return an instance of the specified module + * + * @param int $id_module Module ID + * @return Module instance + */ + public static function getInstanceById($id_module) + { + static $id2name = null; - if (is_null($id2name)) - { - $id2name = array(); - $sql = 'SELECT `id_module`, `name` FROM `'._DB_PREFIX_.'module`'; - if ($results = Db::getInstance()->executeS($sql)) - foreach ($results as $row) - $id2name[$row['id_module']] = $row['name']; - } + if (is_null($id2name)) { + $id2name = array(); + $sql = 'SELECT `id_module`, `name` FROM `'._DB_PREFIX_.'module`'; + if ($results = Db::getInstance()->executeS($sql)) { + foreach ($results as $row) { + $id2name[$row['id_module']] = $row['name']; + } + } + } - if (isset($id2name[$id_module])) - return Module::getInstanceByName($id2name[$id_module]); + if (isset($id2name[$id_module])) { + return Module::getInstanceByName($id2name[$id_module]); + } - return false; - } + return false; + } - public static function configXmlStringFormat($string) - { - return Tools::htmlentitiesDecodeUTF8($string); - } + public static function configXmlStringFormat($string) + { + return Tools::htmlentitiesDecodeUTF8($string); + } - public static function getModuleName($module) - { - $iso = substr(Context::getContext()->language->iso_code, 0, 2); + public static function getModuleName($module) + { + $iso = substr(Context::getContext()->language->iso_code, 0, 2); - // Config file - $config_file = _PS_MODULE_DIR_.$module.'/config_'.$iso.'.xml'; - // For "en" iso code, we keep the default config.xml name - if ($iso == 'en' || !file_exists($config_file)) - { - $config_file = _PS_MODULE_DIR_.$module.'/config.xml'; - if (!file_exists($config_file)) - return 'Module '.ucfirst($module); - } + // Config file + $config_file = _PS_MODULE_DIR_.$module.'/config_'.$iso.'.xml'; + // For "en" iso code, we keep the default config.xml name + if ($iso == 'en' || !file_exists($config_file)) { + $config_file = _PS_MODULE_DIR_.$module.'/config.xml'; + if (!file_exists($config_file)) { + return 'Module '.ucfirst($module); + } + } - // Load config.xml - libxml_use_internal_errors(true); - $xml_module = simplexml_load_file($config_file); - foreach (libxml_get_errors() as $error) - { - libxml_clear_errors(); - return 'Module '.ucfirst($module); - } - libxml_clear_errors(); + // Load config.xml + libxml_use_internal_errors(true); + $xml_module = @simplexml_load_file($config_file); + if (!$xml_module) { + return 'Module '.ucfirst($module); + } + foreach (libxml_get_errors() as $error) { + libxml_clear_errors(); + return 'Module '.ucfirst($module); + } + libxml_clear_errors(); - // Find translations - global $_MODULES; - $file = _PS_MODULE_DIR_.$module.'/'.Context::getContext()->language->iso_code.'.php'; - if (Tools::file_exists_cache($file) && include_once($file)) - if (isset($_MODULE) && is_array($_MODULE)) - $_MODULES = !empty($_MODULES) ? array_merge($_MODULES, $_MODULE) : $_MODULE; + // Find translations + global $_MODULES; + $file = _PS_MODULE_DIR_.$module.'/'.Context::getContext()->language->iso_code.'.php'; + if (Tools::file_exists_cache($file) && include_once($file)) { + if (isset($_MODULE) && is_array($_MODULE)) { + $_MODULES = !empty($_MODULES) ? array_merge($_MODULES, $_MODULE) : $_MODULE; + } + } - // Return Name - return Translate::getModuleTranslation((string)$xml_module->name, Module::configXmlStringFormat($xml_module->displayName), (string)$xml_module->name); - } + // Return Name + return Translate::getModuleTranslation((string)$xml_module->name, Module::configXmlStringFormat($xml_module->displayName), (string)$xml_module->name); + } - protected static function useTooMuchMemory() - { - $memory_limit = Tools::getMemoryLimit(); - if (function_exists('memory_get_usage') && $memory_limit != '-1') - { - $current_memory = memory_get_usage(true); - $memory_threshold = (int)max($memory_limit * 0.15, Tools::isX86_64arch() ? 4194304 : 2097152); - $memory_left = $memory_limit - $current_memory; + protected static function useTooMuchMemory() + { + $memory_limit = Tools::getMemoryLimit(); + if (function_exists('memory_get_usage') && $memory_limit != '-1') { + $current_memory = memory_get_usage(true); + $memory_threshold = (int)max($memory_limit * 0.15, Tools::isX86_64arch() ? 4194304 : 2097152); + $memory_left = $memory_limit - $current_memory; - if ($memory_left <= $memory_threshold) - return true; - } - return false; - } + if ($memory_left <= $memory_threshold) { + return true; + } + } + return false; + } - /** - * Return available modules - * - * @param bool $use_config in order to use config.xml file in module dir - * @return array Modules - */ - public static function getModulesOnDisk($use_config = false, $logged_on_addons = false, $id_employee = false) - { - global $_MODULES; + /** + * Return available modules + * + * @param bool $use_config in order to use config.xml file in module dir + * @return array Modules + */ + public static function getModulesOnDisk($use_config = false, $logged_on_addons = false, $id_employee = false) + { + global $_MODULES; - // Init var - $module_list = array(); - $module_name_list = array(); - $modules_name_to_cursor = array(); - $errors = array(); + // Init var + $module_list = array(); + $module_name_list = array(); + $modules_name_to_cursor = array(); + $errors = array(); - // Get modules directory list and memory limit - $modules_dir = Module::getModulesDirOnDisk(); + // Get modules directory list and memory limit + $modules_dir = Module::getModulesDirOnDisk(); - $modules_installed = array(); - $result = Db::getInstance()->executeS(' + $modules_installed = array(); + $result = Db::getInstance()->executeS(' SELECT m.name, m.version, mp.interest, module_shop.enable_device FROM `'._DB_PREFIX_.'module` m '.Shop::addSqlAssociation('module', 'm').' LEFT JOIN `'._DB_PREFIX_.'module_preference` mp ON (mp.`module` = m.`name` AND mp.`id_employee` = '.(int)$id_employee.')'); - foreach ($result as $row) - $modules_installed[$row['name']] = $row; + foreach ($result as $row) { + $modules_installed[$row['name']] = $row; + } - foreach ($modules_dir as $module) - { - if (Module::useTooMuchMemory()) - { - $errors[] = Tools::displayError('All modules cannot be loaded due to memory limit restrictions, please increase your memory_limit value on your server configuration'); - break; - } + foreach ($modules_dir as $module) { + if (Module::useTooMuchMemory()) { + $errors[] = Tools::displayError('All modules cannot be loaded due to memory limit restrictions, please increase your memory_limit value on your server configuration'); + break; + } - $iso = substr(Context::getContext()->language->iso_code, 0, 2); + $iso = substr(Context::getContext()->language->iso_code, 0, 2); - // Check if config.xml module file exists and if it's not outdated + // Check if config.xml module file exists and if it's not outdated - if ($iso == 'en') - $config_file = _PS_MODULE_DIR_.$module.'/config.xml'; - else - $config_file = _PS_MODULE_DIR_.$module.'/config_'.$iso.'.xml'; + if ($iso == 'en') { + $config_file = _PS_MODULE_DIR_.$module.'/config.xml'; + } else { + $config_file = _PS_MODULE_DIR_.$module.'/config_'.$iso.'.xml'; + } - $xml_exist = (file_exists($config_file)); - $need_new_config_file = $xml_exist ? (@filemtime($config_file) < @filemtime(_PS_MODULE_DIR_.$module.'/'.$module.'.php')) : true; + $xml_exist = (file_exists($config_file)); + $need_new_config_file = $xml_exist ? (@filemtime($config_file) < @filemtime(_PS_MODULE_DIR_.$module.'/'.$module.'.php')) : true; - // If config.xml exists and that the use config flag is at true - if ($use_config && $xml_exist && !$need_new_config_file) - { - // Load config.xml - libxml_use_internal_errors(true); - $xml_module = simplexml_load_file($config_file); - foreach (libxml_get_errors() as $error) - $errors[] = '['.$module.'] '.Tools::displayError('Error found in config file:').' '.htmlentities($error->message); - libxml_clear_errors(); + // If config.xml exists and that the use config flag is at true + if ($use_config && $xml_exist && !$need_new_config_file) { + // Load config.xml + libxml_use_internal_errors(true); + $xml_module = @simplexml_load_file($config_file); + if (!$xml_module) { + $errors[] = Tools::displayError(sprintf('%1s could not be loaded.', $config_file)); + break; + } + foreach (libxml_get_errors() as $error) { + $errors[] = '['.$module.'] '.Tools::displayError('Error found in config file:').' '.htmlentities($error->message); + } + libxml_clear_errors(); - // If no errors in Xml, no need instand and no need new config.xml file, we load only translations - if (!count($errors) && (int)$xml_module->need_instance == 0) - { - $file = _PS_MODULE_DIR_.$module.'/'.Context::getContext()->language->iso_code.'.php'; - if (Tools::file_exists_cache($file) && include_once($file)) - if (isset($_MODULE) && is_array($_MODULE)) - $_MODULES = !empty($_MODULES) ? array_merge($_MODULES, $_MODULE) : $_MODULE; + // If no errors in Xml, no need instand and no need new config.xml file, we load only translations + if (!count($errors) && (int)$xml_module->need_instance == 0) { + $file = _PS_MODULE_DIR_.$module.'/'.Context::getContext()->language->iso_code.'.php'; + if (Tools::file_exists_cache($file) && include_once($file)) { + if (isset($_MODULE) && is_array($_MODULE)) { + $_MODULES = !empty($_MODULES) ? array_merge($_MODULES, $_MODULE) : $_MODULE; + } + } - $item = new stdClass(); - $item->id = 0; - $item->warning = ''; + $item = new stdClass(); + $item->id = 0; + $item->warning = ''; - foreach ($xml_module as $k => $v) - $item->$k = (string)$v; + foreach ($xml_module as $k => $v) { + $item->$k = (string)$v; + } - $item->displayName = stripslashes(Translate::getModuleTranslation((string)$xml_module->name, Module::configXmlStringFormat($xml_module->displayName), (string)$xml_module->name)); - $item->description = stripslashes(Translate::getModuleTranslation((string)$xml_module->name, Module::configXmlStringFormat($xml_module->description), (string)$xml_module->name)); - $item->author = stripslashes(Translate::getModuleTranslation((string)$xml_module->name, Module::configXmlStringFormat($xml_module->author), (string)$xml_module->name)); - $item->author_uri = (isset($xml_module->author_uri) && $xml_module->author_uri) ? stripslashes($xml_module->author_uri) : false; + $item->displayName = stripslashes(Translate::getModuleTranslation((string)$xml_module->name, Module::configXmlStringFormat($xml_module->displayName), (string)$xml_module->name)); + $item->description = stripslashes(Translate::getModuleTranslation((string)$xml_module->name, Module::configXmlStringFormat($xml_module->description), (string)$xml_module->name)); + $item->author = stripslashes(Translate::getModuleTranslation((string)$xml_module->name, Module::configXmlStringFormat($xml_module->author), (string)$xml_module->name)); + $item->author_uri = (isset($xml_module->author_uri) && $xml_module->author_uri) ? stripslashes($xml_module->author_uri) : false; - if (isset($xml_module->confirmUninstall)) - $item->confirmUninstall = Translate::getModuleTranslation((string)$xml_module->name, html_entity_decode(Module::configXmlStringFormat($xml_module->confirmUninstall)), (string)$xml_module->name); + if (isset($xml_module->confirmUninstall)) { + $item->confirmUninstall = Translate::getModuleTranslation((string)$xml_module->name, html_entity_decode(Module::configXmlStringFormat($xml_module->confirmUninstall)), (string)$xml_module->name); + } - $item->active = 0; - $item->onclick_option = false; - $item->trusted = Module::isModuleTrusted($item->name); + $item->active = 0; + $item->onclick_option = false; + $item->trusted = Module::isModuleTrusted($item->name); - $module_list[] = $item; + $module_list[] = $item; - $module_name_list[] = '\''.pSQL($item->name).'\''; - $modules_name_to_cursor[Tools::strtolower(strval($item->name))] = $item; - } - } + $module_name_list[] = '\''.pSQL($item->name).'\''; + $modules_name_to_cursor[Tools::strtolower(strval($item->name))] = $item; + } + } - // If use config flag is at false or config.xml does not exist OR need instance OR need a new config.xml file - if (!$use_config || !$xml_exist || (isset($xml_module->need_instance) && (int)$xml_module->need_instance == 1) || $need_new_config_file) - { - // If class does not exists, we include the file - if (!class_exists($module, false)) - { - // Get content from php file - $file_path = _PS_MODULE_DIR_.$module.'/'.$module.'.php'; - $file = trim(file_get_contents(_PS_MODULE_DIR_.$module.'/'.$module.'.php')); + // If use config flag is at false or config.xml does not exist OR need instance OR need a new config.xml file + if (!$use_config || !$xml_exist || (isset($xml_module->need_instance) && (int)$xml_module->need_instance == 1) || $need_new_config_file) { + // If class does not exists, we include the file + if (!class_exists($module, false)) { + // Get content from php file + $file_path = _PS_MODULE_DIR_.$module.'/'.$module.'.php'; + $file = trim(file_get_contents(_PS_MODULE_DIR_.$module.'/'.$module.'.php')); - if (substr($file, 0, 5) == '<?php') - $file = substr($file, 5); + if (substr($file, 0, 5) == '<?php') { + $file = substr($file, 5); + } - if (substr($file, -2) == '?>') - $file = substr($file, 0, -2); + if (substr($file, -2) == '?>') { + $file = substr($file, 0, -2); + } - // If (false) is a trick to not load the class with "eval". - // This way require_once will works correctly - if (eval('if (false){ '.$file.' }') !== false) - require_once( _PS_MODULE_DIR_.$module.'/'.$module.'.php' ); - else - $errors[] = sprintf(Tools::displayError('%1$s (parse error in %2$s)'), $module, substr($file_path, strlen(_PS_ROOT_DIR_))); - } + // If (false) is a trick to not load the class with "eval". + // This way require_once will works correctly + if (eval('if (false){ '.$file.' }') !== false) { + require_once(_PS_MODULE_DIR_.$module.'/'.$module.'.php'); + } else { + $errors[] = sprintf(Tools::displayError('%1$s (parse error in %2$s)'), $module, substr($file_path, strlen(_PS_ROOT_DIR_))); + } + } - // If class exists, we just instanciate it - if (class_exists($module, false)) - { - $tmp_module = Adapter_ServiceLocator::get($module); - - $item = new stdClass(); - $item->id = $tmp_module->id; - $item->warning = $tmp_module->warning; - $item->name = $tmp_module->name; - $item->version = $tmp_module->version; - $item->tab = $tmp_module->tab; - $item->displayName = $tmp_module->displayName; - $item->description = stripslashes($tmp_module->description); - $item->author = $tmp_module->author; - $item->author_uri = (isset($tmp_module->author_uri) && $tmp_module->author_uri) ? $tmp_module->author_uri : false; - $item->limited_countries = $tmp_module->limited_countries; - $item->parent_class = get_parent_class($module); - $item->is_configurable = $tmp_module->is_configurable = method_exists($tmp_module, 'getContent') ? 1 : 0; - $item->need_instance = isset($tmp_module->need_instance) ? $tmp_module->need_instance : 0; - $item->active = $tmp_module->active; - $item->trusted = Module::isModuleTrusted($tmp_module->name); - $item->currencies = isset($tmp_module->currencies) ? $tmp_module->currencies : null; - $item->currencies_mode = isset($tmp_module->currencies_mode) ? $tmp_module->currencies_mode : null; - $item->confirmUninstall = isset($tmp_module->confirmUninstall) ? html_entity_decode($tmp_module->confirmUninstall) : null; - $item->description_full = stripslashes($tmp_module->description_full); - $item->additional_description = isset($tmp_module->additional_description) ? stripslashes($tmp_module->additional_description) : null; - $item->compatibility = isset($tmp_module->compatibility) ? (array)$tmp_module->compatibility : null; - $item->nb_rates = isset($tmp_module->nb_rates) ? (array)$tmp_module->nb_rates : null; - $item->avg_rate = isset($tmp_module->avg_rate) ? (array)$tmp_module->avg_rate : null; - $item->badges = isset($tmp_module->badges) ? (array)$tmp_module->badges : null; - $item->url = isset($tmp_module->url) ? $tmp_module->url : null; - $item->onclick_option = method_exists($module, 'onclickOption') ? true : false; + // If class exists, we just instanciate it + if (class_exists($module, false)) { + $tmp_module = Adapter_ServiceLocator::get($module); - if ($item->onclick_option) - { - $href = Context::getContext()->link->getAdminLink('Module', true).'&module_name='.$tmp_module->name.'&tab_module='.$tmp_module->tab; - $item->onclick_option_content = array(); - $option_tab = array('desactive', 'reset', 'configure', 'delete'); + $item = new stdClass(); + $item->id = $tmp_module->id; + $item->warning = $tmp_module->warning; + $item->name = $tmp_module->name; + $item->version = $tmp_module->version; + $item->tab = $tmp_module->tab; + $item->displayName = $tmp_module->displayName; + $item->description = stripslashes($tmp_module->description); + $item->author = $tmp_module->author; + $item->author_uri = (isset($tmp_module->author_uri) && $tmp_module->author_uri) ? $tmp_module->author_uri : false; + $item->limited_countries = $tmp_module->limited_countries; + $item->parent_class = get_parent_class($module); + $item->is_configurable = $tmp_module->is_configurable = method_exists($tmp_module, 'getContent') ? 1 : 0; + $item->need_instance = isset($tmp_module->need_instance) ? $tmp_module->need_instance : 0; + $item->active = $tmp_module->active; + $item->trusted = Module::isModuleTrusted($tmp_module->name); + $item->currencies = isset($tmp_module->currencies) ? $tmp_module->currencies : null; + $item->currencies_mode = isset($tmp_module->currencies_mode) ? $tmp_module->currencies_mode : null; + $item->confirmUninstall = isset($tmp_module->confirmUninstall) ? html_entity_decode($tmp_module->confirmUninstall) : null; + $item->description_full = stripslashes($tmp_module->description_full); + $item->additional_description = isset($tmp_module->additional_description) ? stripslashes($tmp_module->additional_description) : null; + $item->compatibility = isset($tmp_module->compatibility) ? (array)$tmp_module->compatibility : null; + $item->nb_rates = isset($tmp_module->nb_rates) ? (array)$tmp_module->nb_rates : null; + $item->avg_rate = isset($tmp_module->avg_rate) ? (array)$tmp_module->avg_rate : null; + $item->badges = isset($tmp_module->badges) ? (array)$tmp_module->badges : null; + $item->url = isset($tmp_module->url) ? $tmp_module->url : null; + $item->onclick_option = method_exists($module, 'onclickOption') ? true : false; - foreach ($option_tab as $opt) - $item->onclick_option_content[$opt] = $tmp_module->onclickOption($opt, $href); - } + if ($item->onclick_option) { + $href = Context::getContext()->link->getAdminLink('Module', true).'&module_name='.$tmp_module->name.'&tab_module='.$tmp_module->tab; + $item->onclick_option_content = array(); + $option_tab = array('desactive', 'reset', 'configure', 'delete'); - $module_list[] = $item; + foreach ($option_tab as $opt) { + $item->onclick_option_content[$opt] = $tmp_module->onclickOption($opt, $href); + } + } - if (!$xml_exist || $need_new_config_file) - { - self::$_generate_config_xml_mode = true; - $tmp_module->_generateConfigXml(); - self::$_generate_config_xml_mode = false; - } + $module_list[] = $item; - unset($tmp_module); - } - else - $errors[] = sprintf(Tools::displayError('%1$s (class missing in %2$s)'), $module, substr($file_path, strlen(_PS_ROOT_DIR_))); - } - } + if (!$xml_exist || $need_new_config_file) { + self::$_generate_config_xml_mode = true; + $tmp_module->_generateConfigXml(); + self::$_generate_config_xml_mode = false; + } - // Get modules information from database - if (!empty($module_name_list)) - { - $list = Shop::getContextListShopID(); - $sql = 'SELECT m.id_module, m.name, ( + unset($tmp_module); + } else { + $errors[] = sprintf(Tools::displayError('%1$s (class missing in %2$s)'), $module, substr($file_path, strlen(_PS_ROOT_DIR_))); + } + } + } + + // Get modules information from database + if (!empty($module_name_list)) { + $list = Shop::getContextListShopID(); + $sql = 'SELECT m.id_module, m.name, ( SELECT COUNT(*) FROM '._DB_PREFIX_.'module_shop ms WHERE m.id_module = ms.id_module AND ms.id_shop IN ('.implode(',', $list).') ) as total FROM '._DB_PREFIX_.'module m WHERE LOWER(m.name) IN ('.Tools::strtolower(implode(',', $module_name_list)).')'; - $results = Db::getInstance()->executeS($sql); + $results = Db::getInstance()->executeS($sql); - foreach ($results as $result) - { - if (isset($modules_name_to_cursor[Tools::strtolower($result['name'])])) - { - $module_cursor = $modules_name_to_cursor[Tools::strtolower($result['name'])]; - $module_cursor->id = (int)$result['id_module']; - $module_cursor->active = ($result['total'] == count($list)) ? 1 : 0; - } - } - } + foreach ($results as $result) { + if (isset($modules_name_to_cursor[Tools::strtolower($result['name'])])) { + $module_cursor = $modules_name_to_cursor[Tools::strtolower($result['name'])]; + $module_cursor->id = (int)$result['id_module']; + $module_cursor->active = ($result['total'] == count($list)) ? 1 : 0; + } + } + } - // Get Default Country Modules and customer module - $files_list = array( - array('type' => 'addonsNative', 'file' => _PS_ROOT_DIR_.self::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 'loggedOnAddons' => 0), - array('type' => 'addonsBought', 'file' => _PS_ROOT_DIR_.self::CACHE_FILE_CUSTOMER_MODULES_LIST, 'loggedOnAddons' => 1), - array('type' => 'addonsMustHave', 'file' => _PS_ROOT_DIR_.self::CACHE_FILE_MUST_HAVE_MODULES_LIST, 'loggedOnAddons' => 0), - ); - foreach ($files_list as $f) - if (file_exists($f['file']) && ($f['loggedOnAddons'] == 0 || $logged_on_addons)) - { - if (Module::useTooMuchMemory()) - { - $errors[] = Tools::displayError('All modules cannot be loaded due to memory limit restrictions, please increase your memory_limit value on your server configuration'); - break; - } + // Get Default Country Modules and customer module + $files_list = array( + array('type' => 'addonsNative', 'file' => _PS_ROOT_DIR_.self::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 'loggedOnAddons' => 0), + array('type' => 'addonsMustHave', 'file' => _PS_ROOT_DIR_.self::CACHE_FILE_MUST_HAVE_MODULES_LIST, 'loggedOnAddons' => 0), + array('type' => 'addonsBought', 'file' => _PS_ROOT_DIR_.self::CACHE_FILE_CUSTOMER_MODULES_LIST, 'loggedOnAddons' => 1), + ); + foreach ($files_list as $f) { + if (file_exists($f['file']) && ($f['loggedOnAddons'] == 0 || $logged_on_addons)) { + if (Module::useTooMuchMemory()) { + $errors[] = Tools::displayError('All modules cannot be loaded due to memory limit restrictions, please increase your memory_limit value on your server configuration'); + break; + } - $file = $f['file']; - $content = Tools::file_get_contents($file); - $xml = @simplexml_load_string($content, null, LIBXML_NOCDATA); + $file = $f['file']; + $content = Tools::file_get_contents($file); + $xml = @simplexml_load_string($content, null, LIBXML_NOCDATA); - if ($xml && isset($xml->module)) - foreach ($xml->module as $modaddons) - { - $flag_found = 0; + if ($xml && isset($xml->module)) { + foreach ($xml->module as $modaddons) { + $flag_found = 0; - foreach ($module_list as $k => &$m) - if (Tools::strtolower($m->name) == Tools::strtolower($modaddons->name) && !isset($m->available_on_addons)) - { - $flag_found = 1; - if ($m->version != $modaddons->version && version_compare($m->version, $modaddons->version) === -1) - $module_list[$k]->version_addons = $modaddons->version; - } + foreach ($module_list as $k => &$m) { + if (Tools::strtolower($m->name) == Tools::strtolower($modaddons->name) && !isset($m->available_on_addons)) { + $flag_found = 1; + if ($m->version != $modaddons->version && version_compare($m->version, $modaddons->version) === -1) { + $module_list[$k]->version_addons = $modaddons->version; + } + } + } - if ($flag_found == 0) - { - $item = new stdClass(); - $item->id = 0; - $item->warning = ''; - $item->type = strip_tags((string)$f['type']); - $item->name = strip_tags((string)$modaddons->name); - $item->version = strip_tags((string)$modaddons->version); - $item->tab = strip_tags((string)$modaddons->tab); - $item->displayName = strip_tags((string)$modaddons->displayName); - $item->description = stripslashes(strip_tags((string)$modaddons->description)); - $item->description_full = stripslashes(strip_tags((string)$modaddons->description_full)); - $item->author = strip_tags((string)$modaddons->author); - $item->limited_countries = array(); - $item->parent_class = ''; - $item->onclick_option = false; - $item->is_configurable = 0; - $item->need_instance = 0; - $item->not_on_disk = 1; - $item->available_on_addons = 1; - $item->trusted = Module::isModuleTrusted($item->name); - $item->active = 0; - $item->description_full = stripslashes($modaddons->description_full); - $item->additional_description = isset($modaddons->additional_description) ? stripslashes($modaddons->additional_description) : null; - $item->compatibility = isset($modaddons->compatibility) ? (array)$modaddons->compatibility : null; - $item->nb_rates = isset($modaddons->nb_rates) ? (array)$modaddons->nb_rates : null; - $item->avg_rate = isset($modaddons->avg_rate) ? (array)$modaddons->avg_rate : null; - $item->badges = isset($modaddons->badges) ? (array)$modaddons->badges : null; - $item->url = isset($modaddons->url) ? $modaddons->url : null; + if ($flag_found == 0) { + $item = new stdClass(); + $item->id = 0; + $item->warning = ''; + $item->type = strip_tags((string)$f['type']); + $item->name = strip_tags((string)$modaddons->name); + $item->version = strip_tags((string)$modaddons->version); + $item->tab = strip_tags((string)$modaddons->tab); + $item->displayName = strip_tags((string)$modaddons->displayName); + $item->description = stripslashes(strip_tags((string)$modaddons->description)); + $item->description_full = stripslashes(strip_tags((string)$modaddons->description_full)); + $item->author = strip_tags((string)$modaddons->author); + $item->limited_countries = array(); + $item->parent_class = ''; + $item->onclick_option = false; + $item->is_configurable = 0; + $item->need_instance = 0; + $item->not_on_disk = 1; + $item->available_on_addons = 1; + $item->trusted = Module::isModuleTrusted($item->name); + $item->active = 0; + $item->description_full = stripslashes($modaddons->description_full); + $item->additional_description = isset($modaddons->additional_description) ? stripslashes($modaddons->additional_description) : null; + $item->compatibility = isset($modaddons->compatibility) ? (array)$modaddons->compatibility : null; + $item->nb_rates = isset($modaddons->nb_rates) ? (array)$modaddons->nb_rates : null; + $item->avg_rate = isset($modaddons->avg_rate) ? (array)$modaddons->avg_rate : null; + $item->badges = isset($modaddons->badges) ? (array)$modaddons->badges : null; + $item->url = isset($modaddons->url) ? $modaddons->url : null; - if (isset($modaddons->img)) - { - if (!file_exists(_PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg')) - if (!file_put_contents(_PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg', Tools::file_get_contents($modaddons->img))) - copy(_PS_IMG_DIR_.'404.gif', _PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg'); + if (isset($modaddons->img)) { + if (!file_exists(_PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg')) { + if (!file_put_contents(_PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg', Tools::file_get_contents($modaddons->img))) { + copy(_PS_IMG_DIR_.'404.gif', _PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg'); + } + } - if (file_exists(_PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg')) - $item->image = '../img/tmp/'.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg'; - } + if (file_exists(_PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg')) { + $item->image = '../img/tmp/'.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg'; + } + } - if ($item->type == 'addonsMustHave') - { - $item->addons_buy_url = strip_tags((string)$modaddons->url); - $prices = (array)$modaddons->price; - $id_default_currency = Configuration::get('PS_CURRENCY_DEFAULT'); + if ($item->type == 'addonsMustHave') { + $item->addons_buy_url = strip_tags((string)$modaddons->url); + $prices = (array)$modaddons->price; + $id_default_currency = Configuration::get('PS_CURRENCY_DEFAULT'); - foreach ($prices as $currency => $price) - if ($id_currency = Currency::getIdByIsoCode($currency)) - { - $item->price = (float)$price; - $item->id_currency = (int)$id_currency; + foreach ($prices as $currency => $price) { + if ($id_currency = Currency::getIdByIsoCode($currency)) { + $item->price = (float)$price; + $item->id_currency = (int)$id_currency; - if ($id_default_currency == $id_currency) - break; - } - } + if ($id_default_currency == $id_currency) { + break; + } + } + } + } - $module_list[] = $item; - } - } - } + $module_list[$modaddons->id.'-'.$item->name] = $item; + } + } + } + } + } - foreach ($module_list as $key => &$module) - if (defined('_PS_HOST_MODE_') && in_array($module->name, self::$hosted_modules_blacklist)) - unset($module_list[$key]); - elseif (isset($modules_installed[$module->name])) - { - $module->installed = true; - $module->database_version = $modules_installed[$module->name]['version']; - $module->interest = $modules_installed[$module->name]['interest']; - $module->enable_device = $modules_installed[$module->name]['enable_device']; - } - else - { - $module->installed = false; - $module->database_version = 0; - $module->interest = 0; - } + foreach ($module_list as $key => &$module) { + if (defined('_PS_HOST_MODE_') && in_array($module->name, self::$hosted_modules_blacklist)) { + unset($module_list[$key]); + } elseif (isset($modules_installed[$module->name])) { + $module->installed = true; + $module->database_version = $modules_installed[$module->name]['version']; + $module->interest = $modules_installed[$module->name]['interest']; + $module->enable_device = $modules_installed[$module->name]['enable_device']; + } else { + $module->installed = false; + $module->database_version = 0; + $module->interest = 0; + } + } - usort($module_list, create_function('$a,$b', 'return strnatcasecmp($a->displayName, $b->displayName);')); - if ($errors) - { - if (!isset(Context::getContext()->controller) && !Context::getContext()->controller->controller_name) - { - echo '<div class="alert error"><h3>'.Tools::displayError('The following module(s) could not be loaded').':</h3><ol>'; - foreach ($errors as $error) - echo '<li>'.$error.'</li>'; - echo '</ol></div>'; - } - else - foreach ($errors as $error) - Context::getContext()->controller->errors[] = $error; - } + usort($module_list, create_function('$a,$b', 'return strnatcasecmp($a->displayName, $b->displayName);')); + if ($errors) { + if (!isset(Context::getContext()->controller) && !Context::getContext()->controller->controller_name) { + echo '<div class="alert error"><h3>'.Tools::displayError('The following module(s) could not be loaded').':</h3><ol>'; + foreach ($errors as $error) { + echo '<li>'.$error.'</li>'; + } + echo '</ol></div>'; + } else { + foreach ($errors as $error) { + Context::getContext()->controller->errors[] = $error; + } + } + } - return $module_list; - } + return $module_list; + } - /** - * Return modules directory list - * - * @return array Modules Directory List - */ - public static function getModulesDirOnDisk() - { - $module_list = array(); - $modules = scandir(_PS_MODULE_DIR_); - foreach ($modules as $name) - { - if (is_file(_PS_MODULE_DIR_.$name)) - continue; - elseif (is_dir(_PS_MODULE_DIR_.$name.DIRECTORY_SEPARATOR) && Tools::file_exists_cache(_PS_MODULE_DIR_.$name.'/'.$name.'.php')) - { - if (!Validate::isModuleName($name)) - throw new PrestaShopException(sprintf('Module %s is not a valid module name', $name)); - $module_list[] = $name; - } - } + /** + * Return modules directory list + * + * @return array Modules Directory List + */ + public static function getModulesDirOnDisk() + { + $module_list = array(); + $modules = scandir(_PS_MODULE_DIR_); + foreach ($modules as $name) { + if (is_file(_PS_MODULE_DIR_.$name)) { + continue; + } elseif (is_dir(_PS_MODULE_DIR_.$name.DIRECTORY_SEPARATOR) && Tools::file_exists_cache(_PS_MODULE_DIR_.$name.'/'.$name.'.php')) { + if (!Validate::isModuleName($name)) { + throw new PrestaShopException(sprintf('Module %s is not a valid module name', $name)); + } + $module_list[] = $name; + } + } - return $module_list; - } + return $module_list; + } - /** - * Return non native module - * - * @param int $position Take only positionnables modules - * @return array Modules - */ - public static function getNonNativeModuleList() - { - $db = Db::getInstance(); + /** + * Return non native module + * + * @param int $position Take only positionnables modules + * @return array Modules + */ + public static function getNonNativeModuleList() + { + $db = Db::getInstance(); + $module_list_xml = _PS_ROOT_DIR_.self::CACHE_FILE_MODULES_LIST; + $native_modules = @simplexml_load_file($module_list_xml); + if ($native_modules) { + $native_modules = $native_modules->modules; + } - $module_list_xml = _PS_ROOT_DIR_.self::CACHE_FILE_MODULES_LIST; - $native_modules = simplexml_load_file($module_list_xml); - $native_modules = $native_modules->modules; - foreach ($native_modules as $native_modules_type) - if (in_array($native_modules_type['type'], array('native', 'partner'))) - { - $arr_native_modules[] = '""'; - foreach ($native_modules_type->module as $module) - $arr_native_modules[] = '"'.pSQL($module['name']).'"'; - } + $arr_native_modules = array(); + if (is_array($native_modules)) { + foreach ($native_modules as $native_modules_type) { + if (in_array($native_modules_type['type'], array('native', 'partner'))) { + $arr_native_modules[] = '""'; + foreach ($native_modules_type->module as $module) { + $arr_native_modules[] = '"'.pSQL($module['name']).'"'; + } + } + } + } - return $db->executeS('SELECT * FROM `'._DB_PREFIX_.'module` m WHERE `name` NOT IN ('.implode(',', $arr_native_modules).') '); - } + if ($arr_native_modules) { + return $db->executeS('SELECT * FROM `'._DB_PREFIX_.'module` m WHERE `name` NOT IN ('.implode(',', $arr_native_modules).') '); + } + return false; + } - public static function getNativeModuleList() - { - $module_list_xml = _PS_ROOT_DIR_.self::CACHE_FILE_MODULES_LIST; - if (!file_exists($module_list_xml)) - return false; + public static function getNativeModuleList() + { + $module_list_xml = _PS_ROOT_DIR_.self::CACHE_FILE_MODULES_LIST; + if (!file_exists($module_list_xml)) { + return false; + } - $native_modules = simplexml_load_file($module_list_xml); - $native_modules = $native_modules->modules; - $modules = array(); - foreach ($native_modules as $native_modules_type) - if (in_array($native_modules_type['type'], array('native', 'partner'))) - { - foreach ($native_modules_type->module as $module) - $modules[] = $module['name']; - } + $native_modules = @simplexml_load_file($module_list_xml); - return $modules; - } + if ($native_modules) { + $native_modules = $native_modules->modules; + } - /** - * Return installed modules - * - * @param int $position Take only positionnables modules - * @return array Modules - */ - public static function getModulesInstalled($position = 0) - { - $sql = 'SELECT m.* FROM `'._DB_PREFIX_.'module` m '; - if ($position) - $sql .= 'LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON m.`id_module` = hm.`id_module` + $modules = array(); + if (is_array($native_modules)) { + foreach ($native_modules as $native_modules_type) { + if (in_array($native_modules_type['type'], array('native', 'partner'))) { + foreach ($native_modules_type->module as $module) { + $modules[] = $module['name']; + } + } + } + } + if ($modules) { + return $modules; + } + return false; + } + + /** + * Return installed modules + * + * @param int $position Take only positionnables modules + * @return array Modules + */ + public static function getModulesInstalled($position = 0) + { + $sql = 'SELECT m.* FROM `'._DB_PREFIX_.'module` m '; + if ($position) { + $sql .= 'LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON m.`id_module` = hm.`id_module` LEFT JOIN `'._DB_PREFIX_.'hook` k ON hm.`id_hook` = k.`id_hook` WHERE k.`position` = 1 GROUP BY m.id_module'; - return Db::getInstance()->executeS($sql); - } + } + return Db::getInstance()->executeS($sql); + } - /** - * Return if the module is provided by addons.prestashop.com or not - * - * @param string $name The module name (the folder name) - * @param string $key The key provided by addons - * @return int - */ - final public static function isModuleTrusted($module_name) - { - static $trusted_modules_list_content = null; - static $modules_list_content = null; - static $default_country_modules_list_content = null; - static $untrusted_modules_list_content = null; + /** + * Return if the module is provided by addons.prestashop.com or not + * + * @param string $name The module name (the folder name) + * @param string $key The key provided by addons + * @return int + */ + final public static function isModuleTrusted($module_name) + { + static $trusted_modules_list_content = null; + static $modules_list_content = null; + static $default_country_modules_list_content = null; + static $untrusted_modules_list_content = null; - $context = Context::getContext(); + $context = Context::getContext(); - // If the xml file exist, isn't empty, isn't too old - // and if the theme hadn't change - // we use the file, otherwise we regenerate it - if (!(file_exists(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST) - && filesize(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST) > 0 - && ((time() - filemtime(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST)) < 86400) - )) - self::generateTrustedXml(); + // If the xml file exist, isn't empty, isn't too old + // and if the theme hadn't change + // we use the file, otherwise we regenerate it + if (!(file_exists(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST) + && filesize(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST) > 0 + && ((time() - filemtime(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST)) < 86400) + )) { + self::generateTrustedXml(); + } - if ($trusted_modules_list_content === null) - { - $trusted_modules_list_content = Tools::file_get_contents(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST); - if (strpos($trusted_modules_list_content, $context->theme->name) === false) - self::generateTrustedXml(); - } + if ($trusted_modules_list_content === null) { + $trusted_modules_list_content = Tools::file_get_contents(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST); + if (strpos($trusted_modules_list_content, $context->theme->name) === false) { + self::generateTrustedXml(); + } + } - if ($modules_list_content === null) - $modules_list_content = Tools::file_get_contents(_PS_ROOT_DIR_.self::CACHE_FILE_MODULES_LIST); + if ($modules_list_content === null) { + $modules_list_content = Tools::file_get_contents(_PS_ROOT_DIR_.self::CACHE_FILE_MODULES_LIST); + } - if ($default_country_modules_list_content === null) - $default_country_modules_list_content = Tools::file_get_contents(_PS_ROOT_DIR_.self::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST); + if ($default_country_modules_list_content === null) { + $default_country_modules_list_content = Tools::file_get_contents(_PS_ROOT_DIR_.self::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST); + } - if ($untrusted_modules_list_content === null) - $untrusted_modules_list_content = Tools::file_get_contents(_PS_ROOT_DIR_.self::CACHE_FILE_UNTRUSTED_MODULES_LIST); + if ($untrusted_modules_list_content === null) { + $untrusted_modules_list_content = Tools::file_get_contents(_PS_ROOT_DIR_.self::CACHE_FILE_UNTRUSTED_MODULES_LIST); + } - // If the module is trusted, which includes both partner modules and modules bought on Addons + // If the module is trusted, which includes both partner modules and modules bought on Addons - if (strpos($trusted_modules_list_content, $module_name) !== false) - { - // If the module is not a partner, then return 1 (which means the module is "trusted") - if (strpos($modules_list_content, '<module name="'.$module_name.'"/>') == false) - return 1; - // The module is a parter. If the module is in the file that contains module for this country then return 1 (which means the module is "trusted") - elseif (strpos($default_country_modules_list_content, '<name><![CDATA['.$module_name.']]></name>') !== false) - return 1; - // The module seems to be trusted, but it does not seem to be dedicated to this country - return 2; - } - // If the module is already in the untrusted list, then return 0 (untrusted) - elseif (strpos($untrusted_modules_list_content, $module_name) !== false) - return 0; - else - { - // If the module isn't in one of the xml files - // It might have been uploaded recenlty so we check - // Addons API and clear XML files to be regenerated next time - Tools::deleteFile(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST); - Tools::deleteFile(_PS_ROOT_DIR_.self::CACHE_FILE_UNTRUSTED_MODULES_LIST); + if (strpos($trusted_modules_list_content, $module_name) !== false) { + // If the module is not a partner, then return 1 (which means the module is "trusted") + if (strpos($modules_list_content, '<module name="'.$module_name.'"/>') == false) { + return 1; + } elseif (strpos($default_country_modules_list_content, '<name><![CDATA['.$module_name.']]></name>') !== false) { + // The module is a parter. If the module is in the file that contains module for this country then return 1 (which means the module is "trusted") + return 1; + } + // The module seems to be trusted, but it does not seem to be dedicated to this country + return 2; + } elseif (strpos($untrusted_modules_list_content, $module_name) !== false) { + // If the module is already in the untrusted list, then return 0 (untrusted) + return 0; + } else { + // If the module isn't in one of the xml files + // It might have been uploaded recenlty so we check + // Addons API and clear XML files to be regenerated next time + Tools::deleteFile(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST); + Tools::deleteFile(_PS_ROOT_DIR_.self::CACHE_FILE_UNTRUSTED_MODULES_LIST); - return (int)Module::checkModuleFromAddonsApi($module_name); - } - } + return (int)Module::checkModuleFromAddonsApi($module_name); + } + } - /** - * Generate XML files for trusted and untrusted modules - * - */ - final public static function generateTrustedXml() - { - $modules_on_disk = Module::getModulesDirOnDisk(); - $trusted = array(); - $untrusted = array(); + /** + * Generate XML files for trusted and untrusted modules + * + */ + final public static function generateTrustedXml() + { + $modules_on_disk = Module::getModulesDirOnDisk(); + $trusted = array(); + $untrusted = array(); - $trusted_modules_xml = array( - _PS_ROOT_DIR_.self::CACHE_FILE_ALL_COUNTRY_MODULES_LIST, - _PS_ROOT_DIR_.self::CACHE_FILE_MUST_HAVE_MODULES_LIST, - ); + $trusted_modules_xml = array( + _PS_ROOT_DIR_.self::CACHE_FILE_ALL_COUNTRY_MODULES_LIST, + _PS_ROOT_DIR_.self::CACHE_FILE_MUST_HAVE_MODULES_LIST, + ); - if (file_exists(_PS_ROOT_DIR_.self::CACHE_FILE_CUSTOMER_MODULES_LIST)) - $trusted_modules_xml[] = _PS_ROOT_DIR_.self::CACHE_FILE_CUSTOMER_MODULES_LIST; + if (file_exists(_PS_ROOT_DIR_.self::CACHE_FILE_CUSTOMER_MODULES_LIST)) { + $trusted_modules_xml[] = _PS_ROOT_DIR_.self::CACHE_FILE_CUSTOMER_MODULES_LIST; + } - // Create 2 arrays with trusted and untrusted modules - foreach ($trusted_modules_xml as $file) - { - $content = Tools::file_get_contents($file); - $xml = @simplexml_load_string($content, null, LIBXML_NOCDATA); + // Create 2 arrays with trusted and untrusted modules + foreach ($trusted_modules_xml as $file) { + $content = Tools::file_get_contents($file); + $xml = @simplexml_load_string($content, null, LIBXML_NOCDATA); - if ($xml && isset($xml->module)) - foreach ($xml->module as $modaddons) - $trusted[] = Tools::strtolower((string)$modaddons->name); - } + if ($xml && isset($xml->module)) { + foreach ($xml->module as $modaddons) { + $trusted[] = Tools::strtolower((string)$modaddons->name); + } + } + } - foreach (glob(_PS_ROOT_DIR_.'/config/xml/themes/*.xml') as $theme_xml) - if (file_exists($theme_xml)) - { - $content = Tools::file_get_contents($theme_xml); - $xml = @simplexml_load_string($content, null, LIBXML_NOCDATA); - foreach ($xml->modules->module as $modaddons) - if ((string)$modaddons['action'] == 'install') - $trusted[] = Tools::strtolower((string)$modaddons['name']); - } + foreach (glob(_PS_ROOT_DIR_.'/config/xml/themes/*.xml') as $theme_xml) { + if (file_exists($theme_xml)) { + $content = Tools::file_get_contents($theme_xml); + $xml = @simplexml_load_string($content, null, LIBXML_NOCDATA); - foreach ($modules_on_disk as $name) - { - if (!in_array($name, $trusted)) - { - if (Module::checkModuleFromAddonsApi($name)) - $trusted[] = Tools::strtolower($name); - else - $untrusted[] = Tools::strtolower($name); - } - } + if ($xml) { + foreach ($xml->modules->module as $modaddons) { + if ((string)$modaddons['action'] == 'install') { + $trusted[] = Tools::strtolower((string)$modaddons['name']); + } + } + } + } + } - $context = Context::getContext(); - $theme = new Theme($context->shop->id_theme); + foreach ($modules_on_disk as $name) { + if (!in_array($name, $trusted)) { + if (Module::checkModuleFromAddonsApi($name)) { + $trusted[] = Tools::strtolower($name); + } else { + $untrusted[] = Tools::strtolower($name); + } + } + } - // Save the 2 arrays into XML files - $trusted_xml = new SimpleXMLElement('<modules_list/>'); - $trusted_xml->addAttribute('theme', $theme->name); - $modules = $trusted_xml->addChild('modules'); - $modules->addAttribute('type', 'trusted'); - foreach ($trusted as $key => $name) - { - $module = $modules->addChild('module'); - $module->addAttribute('name', $name); - } - $success = file_put_contents( _PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST, $trusted_xml->asXML()); + $context = Context::getContext(); + $theme = new Theme($context->shop->id_theme); - $untrusted_xml = new SimpleXMLElement('<modules_list/>'); - $modules = $untrusted_xml->addChild('modules'); - $modules->addAttribute('type', 'untrusted'); - foreach ($untrusted as $key => $name) - { - $module = $modules->addChild('module'); - $module->addAttribute('name', $name); - } - $success &= file_put_contents( _PS_ROOT_DIR_.self::CACHE_FILE_UNTRUSTED_MODULES_LIST, $untrusted_xml->asXML()); + // Save the 2 arrays into XML files + $trusted_xml = new SimpleXMLElement('<modules_list/>'); + $trusted_xml->addAttribute('theme', $theme->name); + $modules = $trusted_xml->addChild('modules'); + $modules->addAttribute('type', 'trusted'); + foreach ($trusted as $key => $name) { + $module = $modules->addChild('module'); + $module->addAttribute('name', $name); + } + $success = file_put_contents(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST, $trusted_xml->asXML()); - if ($success) - return true; - else - Tools::displayError('Trusted and Untrusted XML have not been generated properly'); - } + $untrusted_xml = new SimpleXMLElement('<modules_list/>'); + $modules = $untrusted_xml->addChild('modules'); + $modules->addAttribute('type', 'untrusted'); + foreach ($untrusted as $key => $name) { + $module = $modules->addChild('module'); + $module->addAttribute('name', $name); + } + $success &= file_put_contents(_PS_ROOT_DIR_.self::CACHE_FILE_UNTRUSTED_MODULES_LIST, $untrusted_xml->asXML()); - /** - * Create the Addons API call from the module name only - * - * @param string $name Module dir name - * @return bool Returns if the module is trusted by addons.prestashop.com - */ - final public static function checkModuleFromAddonsApi($module_name) - { - $obj = Module::getInstanceByName($module_name); + if ($success) { + return true; + } else { + Tools::displayError('Trusted and Untrusted XML have not been generated properly'); + } + } - if (!is_object($obj)) - return false; - elseif ($obj->module_key === '') - return false; - else - { - $params = array( - 'module_name' => $obj->name, - 'module_key' => $obj->module_key, - ); - $xml = Tools::addonsRequest('check_module', $params); - return (bool)(strpos($xml, 'success') !== false); - } - } + /** + * Create the Addons API call from the module name only + * + * @param string $name Module dir name + * @return bool Returns if the module is trusted by addons.prestashop.com + */ + final public static function checkModuleFromAddonsApi($module_name) + { + $obj = Module::getInstanceByName($module_name); - /** - * Execute modules for specified hook - * - * @deprecated 1.5.3.0 - * @param string $hook_name Hook Name - * @param array $hook_args Parameters for the functions - * @return string modules output - */ - public static function hookExec($hook_name, $hook_args = array(), $id_module = null) - { - Tools::displayAsDeprecated(); - return Hook::exec($hook_name, $hook_args, $id_module); - } + if (!is_object($obj)) { + return false; + } elseif ($obj->module_key === '') { + return false; + } else { + $params = array( + 'module_name' => $obj->name, + 'module_key' => $obj->module_key, + ); + $xml = Tools::addonsRequest('check_module', $params); + return (bool)(strpos($xml, 'success') !== false); + } + } - /** - * @deprecated 1.5.3.0 - * @return string - * @throws PrestaShopException - */ - public static function hookExecPayment() - { - Tools::displayAsDeprecated(); - return Hook::exec('displayPayment'); - } + /** + * Execute modules for specified hook + * + * @deprecated 1.5.3.0 + * @param string $hook_name Hook Name + * @param array $hook_args Parameters for the functions + * @return string modules output + */ + public static function hookExec($hook_name, $hook_args = array(), $id_module = null) + { + Tools::displayAsDeprecated(); + return Hook::exec($hook_name, $hook_args, $id_module); + } - public static function preCall($module_name) - { - return true; - } + /** + * @deprecated 1.5.3.0 + * @return string + * @throws PrestaShopException + */ + public static function hookExecPayment() + { + Tools::displayAsDeprecated(); + return Hook::exec('displayPayment'); + } - /** - * @deprecated since 1.6.0.2 - */ - public static function getPaypalIgnore() - { - Tools::displayAsDeprecated(); - } + public static function preCall($module_name) + { + return true; + } - /** - * Returns the list of the payment module associated to the current customer - * @see PaymentModule::getInstalledPaymentModules() if you don't care about the context - * - * @return array module informations - */ - public static function getPaymentModules() - { - $context = Context::getContext(); - if (isset($context->cart)) - $billing = new Address((int)$context->cart->id_address_invoice); + /** + * @deprecated since 1.6.0.2 + */ + public static function getPaypalIgnore() + { + Tools::displayAsDeprecated(); + } - $use_groups = Group::isFeatureActive(); + /** + * Returns the list of the payment module associated to the current customer + * @see PaymentModule::getInstalledPaymentModules() if you don't care about the context + * + * @return array module informations + */ + public static function getPaymentModules() + { + $context = Context::getContext(); + if (isset($context->cart)) { + $billing = new Address((int)$context->cart->id_address_invoice); + } - $frontend = true; - $groups = array(); - if (isset($context->employee)) - $frontend = false; - elseif (isset($context->customer) && $use_groups) - { - $groups = $context->customer->getGroups(); - if (!count($groups)) - $groups = array(Configuration::get('PS_UNIDENTIFIED_GROUP')); - } + $use_groups = Group::isFeatureActive(); - $hook_payment = 'Payment'; - if (Db::getInstance()->getValue('SELECT `id_hook` FROM `'._DB_PREFIX_.'hook` WHERE `name` = \'displayPayment\'')) - $hook_payment = 'displayPayment'; + $frontend = true; + $groups = array(); + if (isset($context->employee)) { + $frontend = false; + } elseif (isset($context->customer) && $use_groups) { + $groups = $context->customer->getGroups(); + if (!count($groups)) { + $groups = array(Configuration::get('PS_UNIDENTIFIED_GROUP')); + } + } - $list = Shop::getContextListShopID(); + $hook_payment = 'Payment'; + if (Db::getInstance()->getValue('SELECT `id_hook` FROM `'._DB_PREFIX_.'hook` WHERE `name` = \'displayPayment\'')) { + $hook_payment = 'displayPayment'; + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT DISTINCT m.`id_module`, h.`id_hook`, m.`name`, hm.`position` + $list = Shop::getContextListShopID(); + + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT DISTINCT m.`id_module`, h.`id_hook`, m.`name`, hm.`position` FROM `'._DB_PREFIX_.'module` m '.($frontend ? 'LEFT JOIN `'._DB_PREFIX_.'module_country` mc ON (m.`id_module` = mc.`id_module` AND mc.id_shop = '.(int)$context->shop->id.')' : '').' '.($frontend && $use_groups ? 'INNER JOIN `'._DB_PREFIX_.'module_group` mg ON (m.`id_module` = mg.`id_module` AND mg.id_shop = '.(int)$context->shop->id.')' : '').' @@ -1887,1118 +1940,1147 @@ abstract class ModuleCore '.((count($groups) && $frontend && $use_groups) ? 'AND (mg.`id_group` IN ('.implode(', ', $groups).'))' : '').' GROUP BY hm.id_hook, hm.id_module ORDER BY hm.`position`, m.`name` DESC'); - } + } - /** - * @deprecated 1.5.0 Use Translate::getModuleTranslation() - */ - public static function findTranslation($name, $string, $source) - { - return Translate::getModuleTranslation($name, $string, $source); - } + /** + * @deprecated 1.5.0 Use Translate::getModuleTranslation() + */ + public static function findTranslation($name, $string, $source) + { + return Translate::getModuleTranslation($name, $string, $source); + } - /** - * Get translation for a given module text - * - * Note: $specific parameter is mandatory for library files. - * Otherwise, translation key will not match for Module library - * when module is loaded with eval() Module::getModulesOnDisk() - * - * @param string $string String to translate - * @param bool|string $specific filename to use in translation key - * @return string Translation - */ - public function l($string, $specific = false) - { - if (self::$_generate_config_xml_mode) - return $string; + /** + * Get translation for a given module text + * + * Note: $specific parameter is mandatory for library files. + * Otherwise, translation key will not match for Module library + * when module is loaded with eval() Module::getModulesOnDisk() + * + * @param string $string String to translate + * @param bool|string $specific filename to use in translation key + * @return string Translation + */ + public function l($string, $specific = false) + { + if (self::$_generate_config_xml_mode) { + return $string; + } - return Translate::getModuleTranslation($this, $string, ($specific) ? $specific : $this->name); - } + return Translate::getModuleTranslation($this, $string, ($specific) ? $specific : $this->name); + } - /* - * Reposition module - * - * @param bool $id_hook Hook ID - * @param bool $way Up (0) or Down (1) - * @param int $position - */ - public function updatePosition($id_hook, $way, $position = null) - { - foreach (Shop::getContextListShopID() as $shop_id) - { - $sql = 'SELECT hm.`id_module`, hm.`position`, hm.`id_hook` + /* + * Reposition module + * + * @param bool $id_hook Hook ID + * @param bool $way Up (0) or Down (1) + * @param int $position + */ + public function updatePosition($id_hook, $way, $position = null) + { + foreach (Shop::getContextListShopID() as $shop_id) { + $sql = 'SELECT hm.`id_module`, hm.`position`, hm.`id_hook` FROM `'._DB_PREFIX_.'hook_module` hm WHERE hm.`id_hook` = '.(int)$id_hook.' AND hm.`id_shop` = '.$shop_id.' ORDER BY hm.`position` '.($way ? 'ASC' : 'DESC'); - if (!$res = Db::getInstance()->executeS($sql)) - continue; + if (!$res = Db::getInstance()->executeS($sql)) { + continue; + } - foreach ($res as $key => $values) - if ((int)$values[$this->identifier] == (int)$this->id) - { - $k = $key; - break; - } - if (!isset($k) || !isset($res[$k]) || !isset($res[$k + 1])) - return false; + foreach ($res as $key => $values) { + if ((int)$values[$this->identifier] == (int)$this->id) { + $k = $key; + break; + } + } + if (!isset($k) || !isset($res[$k]) || !isset($res[$k + 1])) { + return false; + } - $from = $res[$k]; - $to = $res[$k + 1]; + $from = $res[$k]; + $to = $res[$k + 1]; - if (isset($position) && !empty($position)) - $to['position'] = (int)$position; + if (isset($position) && !empty($position)) { + $to['position'] = (int)$position; + } - $sql = 'UPDATE `'._DB_PREFIX_.'hook_module` + $sql = 'UPDATE `'._DB_PREFIX_.'hook_module` SET `position`= position '.($way ? '-1' : '+1').' WHERE position between '.(int)(min(array($from['position'], $to['position']))).' AND '.max(array($from['position'], $to['position'])).' AND `id_hook` = '.(int)$from['id_hook'].' AND `id_shop` = '.$shop_id; - if (!Db::getInstance()->execute($sql)) - return false; + if (!Db::getInstance()->execute($sql)) { + return false; + } - $sql = 'UPDATE `'._DB_PREFIX_.'hook_module` + $sql = 'UPDATE `'._DB_PREFIX_.'hook_module` SET `position`='.(int)$to['position'].' WHERE `'.pSQL($this->identifier).'` = '.(int)$from[$this->identifier].' AND `id_hook` = '.(int)$to['id_hook'].' AND `id_shop` = '.$shop_id; - if (!Db::getInstance()->execute($sql)) - return false; - } - return true; - } + if (!Db::getInstance()->execute($sql)) { + return false; + } + } + return true; + } - /* - * Reorder modules position - * - * @param bool $id_hook Hook ID - * @param array $shop_list List of shop - */ - public function cleanPositions($id_hook, $shop_list = null) - { - $sql = 'SELECT `id_module`, `id_shop` + /* + * Reorder modules position + * + * @param bool $id_hook Hook ID + * @param array $shop_list List of shop + */ + public function cleanPositions($id_hook, $shop_list = null) + { + $sql = 'SELECT `id_module`, `id_shop` FROM `'._DB_PREFIX_.'hook_module` WHERE `id_hook` = '.(int)$id_hook.' '.((!is_null($shop_list) && $shop_list) ? ' AND `id_shop` IN('.implode(', ', array_map('intval', $shop_list)).')' : '').' ORDER BY `position`'; - $results = Db::getInstance()->executeS($sql); - $position = array(); - foreach ($results as $row) - { - if (!isset($position[$row['id_shop']])) - $position[$row['id_shop']] = 1; + $results = Db::getInstance()->executeS($sql); + $position = array(); + foreach ($results as $row) { + if (!isset($position[$row['id_shop']])) { + $position[$row['id_shop']] = 1; + } - $sql = 'UPDATE `'._DB_PREFIX_.'hook_module` + $sql = 'UPDATE `'._DB_PREFIX_.'hook_module` SET `position` = '.$position[$row['id_shop']].' WHERE `id_hook` = '.(int)$id_hook.' AND `id_module` = '.$row['id_module'].' AND `id_shop` = '.$row['id_shop']; - Db::getInstance()->execute($sql); - $position[$row['id_shop']]++; - } + Db::getInstance()->execute($sql); + $position[$row['id_shop']]++; + } - return true; - } + return true; + } - /** - * Helper displaying error message(s) - * @param string|array $error - * @return string - */ - public function displayError($error) - { - - $output = ' + /** + * Helper displaying error message(s) + * @param string|array $error + * @return string + */ + public function displayError($error) + { + $output = ' <div class="bootstrap"> <div class="module_error alert alert-danger" > <button type="button" class="close" data-dismiss="alert">×</button>'; - if (is_array($error)) - { - $output .= '<ul>'; - foreach ($error as $msg) - $output .= '<li>'.$msg.'</li>'; - $output .= '</ul>'; - } - else - $output .= $error; + if (is_array($error)) { + $output .= '<ul>'; + foreach ($error as $msg) { + $output .= '<li>'.$msg.'</li>'; + } + $output .= '</ul>'; + } else { + $output .= $error; + } - // Close div openned previously - $output .= '</div></div>'; + // Close div openned previously + $output .= '</div></div>'; - $this->error = true; - return $output; - } + $this->error = true; + return $output; + } - /** - * Helper displaying warning message(s) - * @param string|array $error - * @return string - */ - public function displayWarning($warning) - { - $output = ' + /** + * Helper displaying warning message(s) + * @param string|array $error + * @return string + */ + public function displayWarning($warning) + { + $output = ' <div class="bootstrap"> <div class="module_warning alert alert-warning" > <button type="button" class="close" data-dismiss="alert">×</button>'; - if (is_array($warning)) - { - $output .= '<ul>'; - foreach ($warning as $msg) - $output .= '<li>'.$msg.'</li>'; - $output .= '</ul>'; - } - else - $output .= $warning; + if (is_array($warning)) { + $output .= '<ul>'; + foreach ($warning as $msg) { + $output .= '<li>'.$msg.'</li>'; + } + $output .= '</ul>'; + } else { + $output .= $warning; + } - // Close div openned previously - $output .= '</div></div>'; + // Close div openned previously + $output .= '</div></div>'; - return $output; - } + return $output; + } - public function displayConfirmation($string) - { - $output = ' + public function displayConfirmation($string) + { + $output = ' <div class="bootstrap"> <div class="module_confirmation conf confirm alert alert-success"> <button type="button" class="close" data-dismiss="alert">×</button> '.$string.' </div> </div>'; - return $output; - } + return $output; + } - /* - * Return exceptions for module in hook - * - * @param int $id_module Module ID - * @param int $id_hook Hook ID - * @return array Exceptions - */ - public static function getExceptionsStatic($id_module, $id_hook, $dispatch = false) - { - $cache_id = 'exceptionsCache'; - if (!Cache::isStored($cache_id)) - { - $exceptions_cache = array(); - $sql = 'SELECT * FROM `'._DB_PREFIX_.'hook_module_exceptions` + /* + * Return exceptions for module in hook + * + * @param int $id_module Module ID + * @param int $id_hook Hook ID + * @return array Exceptions + */ + public static function getExceptionsStatic($id_module, $id_hook, $dispatch = false) + { + $cache_id = 'exceptionsCache'; + if (!Cache::isStored($cache_id)) { + $exceptions_cache = array(); + $sql = 'SELECT * FROM `'._DB_PREFIX_.'hook_module_exceptions` WHERE `id_shop` IN ('.implode(', ', Shop::getContextListShopID()).')'; - $db = Db::getInstance(); - $result = $db->executeS($sql, false); - while ($row = $db->nextRow($result)) - { - if (!$row['file_name']) - continue; - $key = $row['id_hook'].'-'.$row['id_module']; - if (!isset($exceptions_cache[$key])) - $exceptions_cache[$key] = array(); - if (!isset($exceptions_cache[$key][$row['id_shop']])) - $exceptions_cache[$key][$row['id_shop']] = array(); - $exceptions_cache[$key][$row['id_shop']][] = $row['file_name']; - } - Cache::store($cache_id, $exceptions_cache); - } - else - $exceptions_cache = Cache::retrieve($cache_id); + $db = Db::getInstance(); + $result = $db->executeS($sql, false); + while ($row = $db->nextRow($result)) { + if (!$row['file_name']) { + continue; + } + $key = $row['id_hook'].'-'.$row['id_module']; + if (!isset($exceptions_cache[$key])) { + $exceptions_cache[$key] = array(); + } + if (!isset($exceptions_cache[$key][$row['id_shop']])) { + $exceptions_cache[$key][$row['id_shop']] = array(); + } + $exceptions_cache[$key][$row['id_shop']][] = $row['file_name']; + } + Cache::store($cache_id, $exceptions_cache); + } else { + $exceptions_cache = Cache::retrieve($cache_id); + } - $key = $id_hook.'-'.$id_module; - $array_return = array(); - if ($dispatch) - { - foreach (Shop::getContextListShopID() as $shop_id) - if (isset($exceptions_cache[$key], $exceptions_cache[$key][$shop_id])) - $array_return[$shop_id] = $exceptions_cache[$key][$shop_id]; - } - else - { - foreach (Shop::getContextListShopID() as $shop_id) - if (isset($exceptions_cache[$key], $exceptions_cache[$key][$shop_id])) - foreach ($exceptions_cache[$key][$shop_id] as $file) - if (!in_array($file, $array_return)) - $array_return[] = $file; - } - return $array_return; - } - /* - * Return exceptions for module in hook - * - * @param int $id_hook Hook ID - * @return array Exceptions - */ - public function getExceptions($id_hook, $dispatch = false) - { - return Module::getExceptionsStatic($this->id, $id_hook, $dispatch); - } + $key = $id_hook.'-'.$id_module; + $array_return = array(); + if ($dispatch) { + foreach (Shop::getContextListShopID() as $shop_id) { + if (isset($exceptions_cache[$key], $exceptions_cache[$key][$shop_id])) { + $array_return[$shop_id] = $exceptions_cache[$key][$shop_id]; + } + } + } else { + foreach (Shop::getContextListShopID() as $shop_id) { + if (isset($exceptions_cache[$key], $exceptions_cache[$key][$shop_id])) { + foreach ($exceptions_cache[$key][$shop_id] as $file) { + if (!in_array($file, $array_return)) { + $array_return[] = $file; + } + } + } + } + } + return $array_return; + } + /* + * Return exceptions for module in hook + * + * @param int $id_hook Hook ID + * @return array Exceptions + */ + public function getExceptions($id_hook, $dispatch = false) + { + return Module::getExceptionsStatic($this->id, $id_hook, $dispatch); + } - public static function isInstalled($module_name) - { - if (!Cache::isStored('Module::isInstalled'.$module_name)) - { - $id_module = Module::getModuleIdByName($module_name); - Cache::store('Module::isInstalled'.$module_name, (bool)$id_module); - return (bool)$id_module; - } - return Cache::retrieve('Module::isInstalled'.$module_name); - } + public static function isInstalled($module_name) + { + if (!Cache::isStored('Module::isInstalled'.$module_name)) { + $id_module = Module::getModuleIdByName($module_name); + Cache::store('Module::isInstalled'.$module_name, (bool)$id_module); + return (bool)$id_module; + } + return Cache::retrieve('Module::isInstalled'.$module_name); + } - public function isEnabledForShopContext() - { - return (bool)Db::getInstance()->getValue(' + public function isEnabledForShopContext() + { + return (bool)Db::getInstance()->getValue(' SELECT COUNT(*) n FROM `'._DB_PREFIX_.'module_shop` WHERE id_module='.(int)$this->id.' AND id_shop IN ('.implode(',', array_map('intval', Shop::getContextListShopID())).') GROUP BY id_module HAVING n='.(int)count(Shop::getContextListShopID()) - ); - } + ); + } - public static function isEnabled($module_name) - { - if (!Cache::isStored('Module::isEnabled'.$module_name)) - { - $active = false; - $id_module = Module::getModuleIdByName($module_name); - if (Db::getInstance()->getValue('SELECT `id_module` FROM `'._DB_PREFIX_.'module_shop` WHERE `id_module` = '.(int)$id_module.' AND `id_shop` = '.(int)Context::getContext()->shop->id)) - $active = true; - Cache::store('Module::isEnabled'.$module_name, (bool)$active); - return (bool)$active; - } - return Cache::retrieve('Module::isEnabled'.$module_name); - } + public static function isEnabled($module_name) + { + if (!Cache::isStored('Module::isEnabled'.$module_name)) { + $active = false; + $id_module = Module::getModuleIdByName($module_name); + if (Db::getInstance()->getValue('SELECT `id_module` FROM `'._DB_PREFIX_.'module_shop` WHERE `id_module` = '.(int)$id_module.' AND `id_shop` = '.(int)Context::getContext()->shop->id)) { + $active = true; + } + Cache::store('Module::isEnabled'.$module_name, (bool)$active); + return (bool)$active; + } + return Cache::retrieve('Module::isEnabled'.$module_name); + } - public function isRegisteredInHook($hook) - { - if (!$this->id) - return false; + public function isRegisteredInHook($hook) + { + if (!$this->id) { + return false; + } - $sql = 'SELECT COUNT(*) + $sql = 'SELECT COUNT(*) FROM `'._DB_PREFIX_.'hook_module` hm LEFT JOIN `'._DB_PREFIX_.'hook` h ON (h.`id_hook` = hm.`id_hook`) WHERE h.`name` = \''.pSQL($hook).'\' AND hm.`id_module` = '.(int)$this->id; - return Db::getInstance()->getValue($sql); - } + return Db::getInstance()->getValue($sql); + } - /* - ** Template management (display, overload, cache) - */ - protected static function _isTemplateOverloadedStatic($module_name, $template) - { - if (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$module_name.'/'.$template)) - return _PS_THEME_DIR_.'modules/'.$module_name.'/'.$template; - elseif (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$module_name.'/views/templates/hook/'.$template)) - return _PS_THEME_DIR_.'modules/'.$module_name.'/views/templates/hook/'.$template; - elseif (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$module_name.'/views/templates/front/'.$template)) - return _PS_THEME_DIR_.'modules/'.$module_name.'/views/templates/front/'.$template; - elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$module_name.'/views/templates/hook/'.$template)) - return false; - elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$module_name.'/views/templates/front/'.$template)) - return false; - elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$module_name.'/'.$template)) - return false; - return null; - } + /* + ** Template management (display, overload, cache) + */ + protected static function _isTemplateOverloadedStatic($module_name, $template) + { + if (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$module_name.'/'.$template)) { + return _PS_THEME_DIR_.'modules/'.$module_name.'/'.$template; + } elseif (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$module_name.'/views/templates/hook/'.$template)) { + return _PS_THEME_DIR_.'modules/'.$module_name.'/views/templates/hook/'.$template; + } elseif (Tools::file_exists_cache(_PS_THEME_DIR_.'modules/'.$module_name.'/views/templates/front/'.$template)) { + return _PS_THEME_DIR_.'modules/'.$module_name.'/views/templates/front/'.$template; + } elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$module_name.'/views/templates/hook/'.$template)) { + return false; + } elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$module_name.'/views/templates/front/'.$template)) { + return false; + } elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$module_name.'/'.$template)) { + return false; + } + return null; + } - protected function _isTemplateOverloaded($template) - { - return Module::_isTemplateOverloadedStatic($this->name, $template); - } + protected function _isTemplateOverloaded($template) + { + return Module::_isTemplateOverloadedStatic($this->name, $template); + } - protected function getCacheId($name = null) - { - $cache_array = array(); - $cache_array[] = $name !== null ? $name : $this->name; - if (Configuration::get('PS_SSL_ENABLED')) - $cache_array[] = (int)Tools::usingSecureMode(); - if (Shop::isFeatureActive()) - $cache_array[] = (int)$this->context->shop->id; - if (Group::isFeatureActive() && isset($this->context->customer)) - { - $cache_array[] = (int)Group::getCurrent()->id; - $cache_array[] = implode('_', Customer::getGroupsStatic($this->context->customer->id)); - } - if (Language::isMultiLanguageActivated()) - $cache_array[] = (int)$this->context->language->id; - if (Currency::isMultiCurrencyActivated()) - $cache_array[] = (int)$this->context->currency->id; - $cache_array[] = (int)$this->context->country->id; - return implode('|', $cache_array); - } + protected function getCacheId($name = null) + { + $cache_array = array(); + $cache_array[] = $name !== null ? $name : $this->name; + if (Configuration::get('PS_SSL_ENABLED')) { + $cache_array[] = (int)Tools::usingSecureMode(); + } + if (Shop::isFeatureActive()) { + $cache_array[] = (int)$this->context->shop->id; + } + if (Group::isFeatureActive() && isset($this->context->customer)) { + $cache_array[] = (int)Group::getCurrent()->id; + $cache_array[] = implode('_', Customer::getGroupsStatic($this->context->customer->id)); + } + if (Language::isMultiLanguageActivated()) { + $cache_array[] = (int)$this->context->language->id; + } + if (Currency::isMultiCurrencyActivated()) { + $cache_array[] = (int)$this->context->currency->id; + } + $cache_array[] = (int)$this->context->country->id; + return implode('|', $cache_array); + } - public function display($file, $template, $cache_id = null, $compile_id = null) - { - if (($overloaded = Module::_isTemplateOverloadedStatic(basename($file, '.php'), $template)) === null) - return Tools::displayError('No template found for module').' '.basename($file, '.php'); - else - { - if (Tools::getIsset('live_edit') || Tools::getIsset('live_configurator_token')) - $cache_id = null; + public function display($file, $template, $cache_id = null, $compile_id = null) + { + if (($overloaded = Module::_isTemplateOverloadedStatic(basename($file, '.php'), $template)) === null) { + return Tools::displayError('No template found for module').' '.basename($file, '.php'); + } else { + if (Tools::getIsset('live_edit') || Tools::getIsset('live_configurator_token')) { + $cache_id = null; + } - $this->smarty->assign(array( - 'module_dir' => __PS_BASE_URI__.'modules/'.basename($file, '.php').'/', - 'module_template_dir' => ($overloaded ? _THEME_DIR_ : __PS_BASE_URI__).'modules/'.basename($file, '.php').'/', - 'allow_push' => $this->allow_push - )); + $this->smarty->assign(array( + 'module_dir' => __PS_BASE_URI__.'modules/'.basename($file, '.php').'/', + 'module_template_dir' => ($overloaded ? _THEME_DIR_ : __PS_BASE_URI__).'modules/'.basename($file, '.php').'/', + 'allow_push' => $this->allow_push + )); - if ($cache_id !== null) - Tools::enableCache(); + if ($cache_id !== null) { + Tools::enableCache(); + } - $result = $this->getCurrentSubTemplate($template, $cache_id, $compile_id)->fetch(); + $result = $this->getCurrentSubTemplate($template, $cache_id, $compile_id)->fetch(); - if ($cache_id !== null) - Tools::restoreCacheSettings(); + if ($cache_id !== null) { + Tools::restoreCacheSettings(); + } - $this->resetCurrentSubTemplate($template, $cache_id, $compile_id); + $this->resetCurrentSubTemplate($template, $cache_id, $compile_id); - return $result; - } - } + return $result; + } + } - /** - * @param string $template - * @param string|null $cache_id - * @param string|null $compile_id - * @return Smarty_Internal_Template - */ - protected function getCurrentSubTemplate($template, $cache_id = null, $compile_id = null) - { - if (!isset($this->current_subtemplate[$template.'_'.$cache_id.'_'.$compile_id])) - { - $this->current_subtemplate[$template.'_'.$cache_id.'_'.$compile_id] = $this->context->smarty->createTemplate( - $this->getTemplatePath($template), - $cache_id, - $compile_id, - $this->smarty - ); - } - return $this->current_subtemplate[$template.'_'.$cache_id.'_'.$compile_id]; - } + /** + * @param string $template + * @param string|null $cache_id + * @param string|null $compile_id + * @return Smarty_Internal_Template + */ + protected function getCurrentSubTemplate($template, $cache_id = null, $compile_id = null) + { + if (!isset($this->current_subtemplate[$template.'_'.$cache_id.'_'.$compile_id])) { + $this->current_subtemplate[$template.'_'.$cache_id.'_'.$compile_id] = $this->context->smarty->createTemplate( + $this->getTemplatePath($template), + $cache_id, + $compile_id, + $this->smarty + ); + } + return $this->current_subtemplate[$template.'_'.$cache_id.'_'.$compile_id]; + } - protected function resetCurrentSubTemplate($template, $cache_id, $compile_id) - { - $this->current_subtemplate[$template.'_'.$cache_id.'_'.$compile_id] = null; - } + protected function resetCurrentSubTemplate($template, $cache_id, $compile_id) + { + $this->current_subtemplate[$template.'_'.$cache_id.'_'.$compile_id] = null; + } - /** - * Get realpath of a template of current module (check if template is overriden too) - * - * @since 1.5.0 - * @param string $template - * @return string - */ - public function getTemplatePath($template) - { - $overloaded = $this->_isTemplateOverloaded($template); - if ($overloaded === null) - return null; + /** + * Get realpath of a template of current module (check if template is overriden too) + * + * @since 1.5.0 + * @param string $template + * @return string + */ + public function getTemplatePath($template) + { + $overloaded = $this->_isTemplateOverloaded($template); + if ($overloaded === null) { + return null; + } - if ($overloaded) - return $overloaded; - elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$this->name.'/views/templates/hook/'.$template)) - return _PS_MODULE_DIR_.$this->name.'/views/templates/hook/'.$template; - elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$this->name.'/views/templates/front/'.$template)) - return _PS_MODULE_DIR_.$this->name.'/views/templates/front/'.$template; - elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$this->name.'/'.$template)) - return _PS_MODULE_DIR_.$this->name.'/'.$template; - else - return null; - } + if ($overloaded) { + return $overloaded; + } elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$this->name.'/views/templates/hook/'.$template)) { + return _PS_MODULE_DIR_.$this->name.'/views/templates/hook/'.$template; + } elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$this->name.'/views/templates/front/'.$template)) { + return _PS_MODULE_DIR_.$this->name.'/views/templates/front/'.$template; + } elseif (Tools::file_exists_cache(_PS_MODULE_DIR_.$this->name.'/'.$template)) { + return _PS_MODULE_DIR_.$this->name.'/'.$template; + } else { + return null; + } + } - protected function _getApplicableTemplateDir($template) - { - return $this->_isTemplateOverloaded($template) ? _PS_THEME_DIR_ : _PS_MODULE_DIR_.$this->name.'/'; - } + protected function _getApplicableTemplateDir($template) + { + return $this->_isTemplateOverloaded($template) ? _PS_THEME_DIR_ : _PS_MODULE_DIR_.$this->name.'/'; + } - public function isCached($template, $cache_id = null, $compile_id = null) - { - if (Tools::getIsset('live_edit') || Tools::getIsset('live_configurator_token')) - return false; - Tools::enableCache(); - $new_tpl = $this->getTemplatePath($template); - $is_cached = $this->getCurrentSubTemplate($template, $cache_id, $compile_id)->isCached($new_tpl, $cache_id, $compile_id); - Tools::restoreCacheSettings(); - return $is_cached; - } + public function isCached($template, $cache_id = null, $compile_id = null) + { + if (Tools::getIsset('live_edit') || Tools::getIsset('live_configurator_token')) { + return false; + } + Tools::enableCache(); + $new_tpl = $this->getTemplatePath($template); + $is_cached = $this->getCurrentSubTemplate($template, $cache_id, $compile_id)->isCached($new_tpl, $cache_id, $compile_id); + Tools::restoreCacheSettings(); + return $is_cached; + } - /* - * Clear template cache - * - * @param string $template Template name - * @param int null $cache_id - * @param int null $compile_id - * @return int Number of template cleared - */ - protected function _clearCache($template, $cache_id = null, $compile_id = null) - { - static $ps_smarty_clear_cache = null; - if ($ps_smarty_clear_cache === null) - $ps_smarty_clear_cache = Configuration::get('PS_SMARTY_CLEAR_CACHE'); + /* + * Clear template cache + * + * @param string $template Template name + * @param int null $cache_id + * @param int null $compile_id + * @return int Number of template cleared + */ + protected function _clearCache($template, $cache_id = null, $compile_id = null) + { + static $ps_smarty_clear_cache = null; + if ($ps_smarty_clear_cache === null) { + $ps_smarty_clear_cache = Configuration::get('PS_SMARTY_CLEAR_CACHE'); + } - if (self::$_batch_mode) - { - if ($ps_smarty_clear_cache == 'never') - return 0; + if (self::$_batch_mode) { + if ($ps_smarty_clear_cache == 'never') { + return 0; + } - if ($cache_id === null) - $cache_id = $this->name; + if ($cache_id === null) { + $cache_id = $this->name; + } - $key = $template.'-'.$cache_id.'-'.$compile_id; - if (!isset(self::$_defered_clearCache[$key])) - self::$_defered_clearCache[$key] = array($this->getTemplatePath($template), $cache_id, $compile_id); - } - else - { - if ($ps_smarty_clear_cache == 'never') - return 0; + $key = $template.'-'.$cache_id.'-'.$compile_id; + if (!isset(self::$_defered_clearCache[$key])) { + self::$_defered_clearCache[$key] = array($this->getTemplatePath($template), $cache_id, $compile_id); + } + } else { + if ($ps_smarty_clear_cache == 'never') { + return 0; + } - if ($cache_id === null) - $cache_id = $this->name; + if ($cache_id === null) { + $cache_id = $this->name; + } - Tools::enableCache(); - $number_of_template_cleared = Tools::clearCache(Context::getContext()->smarty, $this->getTemplatePath($template), $cache_id, $compile_id); - Tools::restoreCacheSettings(); + Tools::enableCache(); + $number_of_template_cleared = Tools::clearCache(Context::getContext()->smarty, $this->getTemplatePath($template), $cache_id, $compile_id); + Tools::restoreCacheSettings(); - return $number_of_template_cleared; - } - } + return $number_of_template_cleared; + } + } - /* - * Clear defered template cache - * - * @param string $template_path Template path - * @param int null $cache_id - * @param int null $compile_id - * @return int Number of template cleared - */ - static public function _deferedClearCache($template_path, $cache_id, $compile_id) - { - Tools::enableCache(); - $number_of_template_cleared = Tools::clearCache(Context::getContext()->smarty, $template_path, $cache_id, $compile_id); - Tools::restoreCacheSettings(); + /* + * Clear defered template cache + * + * @param string $template_path Template path + * @param int null $cache_id + * @param int null $compile_id + * @return int Number of template cleared + */ + public static function _deferedClearCache($template_path, $cache_id, $compile_id) + { + Tools::enableCache(); + $number_of_template_cleared = Tools::clearCache(Context::getContext()->smarty, $template_path, $cache_id, $compile_id); + Tools::restoreCacheSettings(); - return $number_of_template_cleared; - } + return $number_of_template_cleared; + } - protected function _generateConfigXml() - { - $author_uri = ''; - if (isset($this->author_uri) && $this->author_uri) - $author_uri = '<author_uri><![CDATA['.Tools::htmlentitiesUTF8($this->author_uri).']]></author_uri>'; + protected function _generateConfigXml() + { + $author_uri = ''; + if (isset($this->author_uri) && $this->author_uri) { + $author_uri = '<author_uri><![CDATA['.Tools::htmlentitiesUTF8($this->author_uri).']]></author_uri>'; + } - $xml = '<?xml version="1.0" encoding="UTF-8" ?> + $xml = '<?xml version="1.0" encoding="UTF-8" ?> <module> <name>'.$this->name.'</name> - <displayName><![CDATA['.str_replace('&' , '&', Tools::htmlentitiesUTF8($this->displayName)).']]></displayName> + <displayName><![CDATA['.str_replace('&', '&', Tools::htmlentitiesUTF8($this->displayName)).']]></displayName> <version><![CDATA['.$this->version.']]></version> - <description><![CDATA['.str_replace('&' , '&', Tools::htmlentitiesUTF8($this->description)).']]></description> - <author><![CDATA['.str_replace('&' , '&', Tools::htmlentitiesUTF8($this->author)).']]></author>' - .$author_uri.' + <description><![CDATA['.str_replace('&', '&', Tools::htmlentitiesUTF8($this->description)).']]></description> + <author><![CDATA['.str_replace('&', '&', Tools::htmlentitiesUTF8($this->author)).']]></author>' + .$author_uri.' <tab><![CDATA['.Tools::htmlentitiesUTF8($this->tab).']]></tab>'.(isset($this->confirmUninstall) ? "\n\t".'<confirmUninstall><![CDATA['.$this->confirmUninstall.']]></confirmUninstall>' : '').' <is_configurable>'.(isset($this->is_configurable) ? (int)$this->is_configurable : 0).'</is_configurable> <need_instance>'.(int)$this->need_instance.'</need_instance>'.(isset($this->limited_countries) ? "\n\t".'<limited_countries>'.(count($this->limited_countries) == 1 ? $this->limited_countries[0] : '').'</limited_countries>' : '').' </module>'; - if (is_writable(_PS_MODULE_DIR_.$this->name.'/')) - { - $iso = substr(Context::getContext()->language->iso_code, 0, 2); - $file = _PS_MODULE_DIR_.$this->name.'/'.($iso == 'en' ? 'config.xml' : 'config_'.$iso.'.xml'); - if (!@file_put_contents($file, $xml)) - if (!is_writable($file)) - { - @unlink($file); - @file_put_contents($file, $xml); - } - @chmod($file, 0664); - } - } + if (is_writable(_PS_MODULE_DIR_.$this->name.'/')) { + $iso = substr(Context::getContext()->language->iso_code, 0, 2); + $file = _PS_MODULE_DIR_.$this->name.'/'.($iso == 'en' ? 'config.xml' : 'config_'.$iso.'.xml'); + if (!@file_put_contents($file, $xml)) { + if (!is_writable($file)) { + @unlink($file); + @file_put_contents($file, $xml); + } + } + @chmod($file, 0664); + } + } - /** - * Check if the module is transplantable on the hook in parameter - * @param string $hook_name - * @return bool if module can be transplanted on hook - */ - public function isHookableOn($hook_name) - { - $retro_hook_name = Hook::getRetroHookName($hook_name); - return (is_callable(array($this, 'hook'.ucfirst($hook_name))) || is_callable(array($this, 'hook'.ucfirst($retro_hook_name)))); - } + /** + * Check if the module is transplantable on the hook in parameter + * @param string $hook_name + * @return bool if module can be transplanted on hook + */ + public function isHookableOn($hook_name) + { + $retro_hook_name = Hook::getRetroHookName($hook_name); + return (is_callable(array($this, 'hook'.ucfirst($hook_name))) || is_callable(array($this, 'hook'.ucfirst($retro_hook_name)))); + } - /** - * Check employee permission for module - * @param array $variable (action) - * @param object $employee - * @return bool if module can be transplanted on hook - */ - public function getPermission($variable, $employee = null) - { - return Module::getPermissionStatic($this->id, $variable, $employee); - } + /** + * Check employee permission for module + * @param array $variable (action) + * @param object $employee + * @return bool if module can be transplanted on hook + */ + public function getPermission($variable, $employee = null) + { + return Module::getPermissionStatic($this->id, $variable, $employee); + } - /** - * Check employee permission for module (static method) - * @param int $id_module - * @param array $variable (action) - * @param object $employee - * @return bool if module can be transplanted on hook - */ - public static function getPermissionStatic($id_module, $variable, $employee = null) - { - if (!in_array($variable, array('view', 'configure', 'uninstall'))) - return false; + /** + * Check employee permission for module (static method) + * @param int $id_module + * @param array $variable (action) + * @param object $employee + * @return bool if module can be transplanted on hook + */ + public static function getPermissionStatic($id_module, $variable, $employee = null) + { + if (!in_array($variable, array('view', 'configure', 'uninstall'))) { + return false; + } - if (!$employee) - $employee = Context::getContext()->employee; + if (!$employee) { + $employee = Context::getContext()->employee; + } - if ($employee->id_profile == _PS_ADMIN_PROFILE_) - return true; + if ($employee->id_profile == _PS_ADMIN_PROFILE_) { + return true; + } - if (!isset(self::$cache_permissions[$employee->id_profile])) - { - self::$cache_permissions[$employee->id_profile] = array(); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT `id_module`, `view`, `configure`, `uninstall` FROM `'._DB_PREFIX_.'module_access` WHERE `id_profile` = '.(int)$employee->id_profile); - foreach ($result as $row) - { - self::$cache_permissions[$employee->id_profile][$row['id_module']]['view'] = $row['view']; - self::$cache_permissions[$employee->id_profile][$row['id_module']]['configure'] = $row['configure']; - self::$cache_permissions[$employee->id_profile][$row['id_module']]['uninstall'] = $row['uninstall']; - } - } + if (!isset(self::$cache_permissions[$employee->id_profile])) { + self::$cache_permissions[$employee->id_profile] = array(); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT `id_module`, `view`, `configure`, `uninstall` FROM `'._DB_PREFIX_.'module_access` WHERE `id_profile` = '.(int)$employee->id_profile); + foreach ($result as $row) { + self::$cache_permissions[$employee->id_profile][$row['id_module']]['view'] = $row['view']; + self::$cache_permissions[$employee->id_profile][$row['id_module']]['configure'] = $row['configure']; + self::$cache_permissions[$employee->id_profile][$row['id_module']]['uninstall'] = $row['uninstall']; + } + } - if (!isset(self::$cache_permissions[$employee->id_profile][$id_module])) - throw new PrestaShopException('No access reference in table module_access for id_module '.$id_module.'.'); + if (!isset(self::$cache_permissions[$employee->id_profile][$id_module])) { + throw new PrestaShopException('No access reference in table module_access for id_module '.$id_module.'.'); + } - return (bool)self::$cache_permissions[$employee->id_profile][$id_module][$variable]; - } + return (bool)self::$cache_permissions[$employee->id_profile][$id_module][$variable]; + } - /** - * Get Unauthorized modules for a client group - * - * @param int $group_id - * @return array|null - */ - public static function getAuthorizedModules($group_id) - { - return Db::getInstance()->executeS(' + /** + * Get Unauthorized modules for a client group + * + * @param int $group_id + * @return array|null + */ + public static function getAuthorizedModules($group_id) + { + return Db::getInstance()->executeS(' SELECT m.`id_module`, m.`name` FROM `'._DB_PREFIX_.'module_group` mg LEFT JOIN `'._DB_PREFIX_.'module` m ON (m.`id_module` = mg.`id_module`) WHERE mg.`id_group` = '.(int)$group_id); - } + } - /** - * Get ID module by name - * - * @param string $name - * @return int Module ID - */ - public static function getModuleIdByName($name) - { - $cache_id = 'Module::getModuleIdByName_'.pSQL($name); - if (!Cache::isStored($cache_id)) - { - $result = (int)Db::getInstance()->getValue('SELECT `id_module` FROM `'._DB_PREFIX_.'module` WHERE `name` = "'.pSQL($name).'"'); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + /** + * Get ID module by name + * + * @param string $name + * @return int Module ID + */ + public static function getModuleIdByName($name) + { + $cache_id = 'Module::getModuleIdByName_'.pSQL($name); + if (!Cache::isStored($cache_id)) { + $result = (int)Db::getInstance()->getValue('SELECT `id_module` FROM `'._DB_PREFIX_.'module` WHERE `name` = "'.pSQL($name).'"'); + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Get module errors - * - * @since 1.5.0 - * @return array errors - */ - public function getErrors() - { - return $this->_errors; - } + /** + * Get module errors + * + * @since 1.5.0 + * @return array errors + */ + public function getErrors() + { + return $this->_errors; + } - /** - * Get module messages confirmation - * - * @since 1.5.0 - * @return array conf - */ - public function getConfirmations() - { - return $this->_confirmations; - } + /** + * Get module messages confirmation + * + * @since 1.5.0 + * @return array conf + */ + public function getConfirmations() + { + return $this->_confirmations; + } - /** - * Get local path for module - * - * @since 1.5.0 - * @return string - */ - public function getLocalPath() - { - return $this->local_path; - } + /** + * Get local path for module + * + * @since 1.5.0 + * @return string + */ + public function getLocalPath() + { + return $this->local_path; + } - /** - * Get uri path for module - * - * @since 1.5.0 - * @return string - */ - public function getPathUri() - { - return $this->_path; - } + /** + * Get uri path for module + * + * @since 1.5.0 + * @return string + */ + public function getPathUri() + { + return $this->_path; + } - /* - * Return module position for a given hook - * - * @param bool $id_hook Hook ID - * @return int position - */ - public function getPosition($id_hook) - { - if (isset(Hook::$preloadModulesFromHooks)) - if (isset(Hook::$preloadModulesFromHooks[$id_hook])) - if (isset(Hook::$preloadModulesFromHooks[$id_hook]['module_position'][$this->id])) - return Hook::$preloadModulesFromHooks[$id_hook]['module_position'][$this->id]; - else - return 0; - $result = Db::getInstance()->getRow(' + /* + * Return module position for a given hook + * + * @param bool $id_hook Hook ID + * @return int position + */ + public function getPosition($id_hook) + { + if (isset(Hook::$preloadModulesFromHooks)) { + if (isset(Hook::$preloadModulesFromHooks[$id_hook])) { + if (isset(Hook::$preloadModulesFromHooks[$id_hook]['module_position'][$this->id])) { + return Hook::$preloadModulesFromHooks[$id_hook]['module_position'][$this->id]; + } else { + return 0; + } + } + } + $result = Db::getInstance()->getRow(' SELECT `position` FROM `'._DB_PREFIX_.'hook_module` WHERE `id_hook` = '.(int)$id_hook.' AND `id_module` = '.(int)$this->id.' AND `id_shop` = '.(int)Context::getContext()->shop->id); - return $result['position']; - } - - /** - * add a warning message to display at the top of the admin page - * - * @param string $msg - */ - public function adminDisplayWarning($msg) - { - if (!($this->context->controller instanceof AdminController)) - return false; - $this->context->controller->warnings[] = $msg; - } - - /** - * add a info message to display at the top of the admin page - * - * @param string $msg - */ - protected function adminDisplayInformation($msg) - { - if (!($this->context->controller instanceof AdminController)) - return false; - $this->context->controller->informations[] = $msg; - } - - /** - * Install module's controllers using public property $controllers - * @return bool - */ - private function installControllers() - { - $themes = Theme::getThemes(); - $theme_meta_value = array(); - foreach ($this->controllers as $controller) - { - $page = 'module-'.$this->name.'-'.$controller; - $result = Db::getInstance()->getValue('SELECT * FROM '._DB_PREFIX_.'meta WHERE page="'.pSQL($page).'"'); - if ((int)$result > 0) - continue; - - $meta = New Meta(); - $meta->page = $page; - $meta->configurable = 1; - $meta->save(); - if ((int)$meta->id > 0) - { - foreach ($themes as $theme) - { - /** @var Theme $theme */ - $theme_meta_value[] = array( - 'id_theme' => $theme->id, - 'id_meta' => $meta->id, - 'left_column' => (int)$theme->default_left_column, - 'right_column' => (int)$theme->default_right_column - ); - - } - } - else - $this->_errors[] = sprintf(Tools::displayError('Unable to install controller: %s'), $controller); - - } - if (count($theme_meta_value) > 0) - return Db::getInstance()->insert('theme_meta', $theme_meta_value); - - return true; - } - - /** - * Install overrides files for the module - * - * @return bool - */ - public function installOverrides() - { - if (!is_dir($this->getLocalPath().'override')) - return true; - - $result = true; - foreach (Tools::scandir($this->getLocalPath().'override', 'php', '', true) as $file) - { - $class = basename($file, '.php'); - if (PrestaShopAutoload::getInstance()->getClassPath($class.'Core') || Module::getModuleIdByName($class)) - $result &= $this->addOverride($class); - } - - return $result; - } - - /** - * Uninstall overrides files for the module - * - * @return bool - */ - public function uninstallOverrides() - { - if (!is_dir($this->getLocalPath().'override')) - return true; - - $result = true; - foreach (Tools::scandir($this->getLocalPath().'override', 'php', '', true) as $file) - { - $class = basename($file, '.php'); - if (PrestaShopAutoload::getInstance()->getClassPath($class.'Core') || Module::getModuleIdByName($class)) - $result &= $this->removeOverride($class); - } - - return $result; - } - - /** - * Add all methods in a module override to the override class - * - * @param string $classname - * @return bool - */ - public function addOverride($classname) - { - $orig_path = $path = PrestaShopAutoload::getInstance()->getClassPath($classname.'Core'); - if (!$path) - $path = 'modules'.DIRECTORY_SEPARATOR.$classname.DIRECTORY_SEPARATOR.$classname.'.php'; - $path_override = $this->getLocalPath().'override'.DIRECTORY_SEPARATOR.$path; - - if (!file_exists($path_override)) - return false; - else - file_put_contents($path_override, preg_replace('#(\r\n|\r)#ism', "\n", file_get_contents($path_override))); - - $pattern_escape_com = '#(^\s*?\/\/.*?\n|\/\*(?!\n\s+\* module:.*?\* date:.*?\* version:.*?\*\/).*?\*\/)#ism'; - // Check if there is already an override file, if not, we just need to copy the file - if ($file = PrestaShopAutoload::getInstance()->getClassPath($classname)) - { - // Check if override file is writable - $override_path = _PS_ROOT_DIR_.'/'.$file; - - if ((!file_exists($override_path) && !is_writable(dirname($override_path))) || (file_exists($override_path) && !is_writable($override_path))) - throw new Exception(sprintf(Tools::displayError('file (%s) not writable'), $override_path)); - - // Get a uniq id for the class, because you can override a class (or remove the override) twice in the same session and we need to avoid redeclaration - do $uniq = uniqid(); - while (class_exists($classname.'OverrideOriginal_remove', false)); - - // Make a reflection of the override class and the module override class - $override_file = file($override_path); - $override_file = array_diff($override_file, array("\n")); - eval(preg_replace(array('#^\s*<\?(?:php)?#', '#class\s+'.$classname.'\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?#i'), array(' ', 'class '.$classname.'OverrideOriginal'.$uniq), implode('', $override_file))); - $override_class = new ReflectionClass($classname.'OverrideOriginal'.$uniq); - - $module_file = file($path_override); - $module_file = array_diff($module_file, array("\n")); - eval(preg_replace(array('#^\s*<\?(?:php)?#', '#class\s+'.$classname.'(\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?)?#i'), array(' ', 'class '.$classname.'Override'.$uniq), implode('', $module_file))); - $module_class = new ReflectionClass($classname.'Override'.$uniq); - - // Check if none of the methods already exists in the override class - foreach ($module_class->getMethods() as $method) - { - if ($override_class->hasMethod($method->getName())) - { - $method_override = $override_class->getMethod($method->getName()); - if (preg_match('/module: (.*)/ism', $override_file[$method_override->getStartLine() - 5], $name) && preg_match('/date: (.*)/ism', $override_file[$method_override->getStartLine() - 4], $date) && preg_match('/version: ([0-9.]+)/ism', $override_file[$method_override->getStartLine() - 3], $version)) - throw new Exception(sprintf(Tools::displayError('The method %1$s in the class %2$s is already overridden by the module %3$s version %4$s at %5$s.'), $method->getName(), $classname, $name[1], $version[1], $date[1])); - throw new Exception(sprintf(Tools::displayError('The method %1$s in the class %2$s is already overridden.'), $method->getName(), $classname)); - } - - $module_file = preg_replace('/((:?public|private|protected)\s+(static\s+)?function\s+(?:\b'.$method->getName().'\b))/ism', "/*\n\t* module: ".$this->name."\n\t* date: ".date('Y-m-d H:i:s')."\n\t* version: ".$this->version."\n\t*/\n\t$1", $module_file); - if ($module_file === NULL) - throw new Exception(sprintf(Tools::displayError('Failed to override method %1$s in class %2$s.'), $method->getName(), $classname)); - } - - // Check if none of the properties already exists in the override class - foreach ($module_class->getProperties() as $property) - { - if ($override_class->hasProperty($property->getName())) - throw new Exception(sprintf(Tools::displayError('The property %1$s in the class %2$s is already defined.'), $property->getName(), $classname)); - - $module_file = preg_replace('/((?:public|private|protected)\s)\s*(static\s)?\s*(\$\b'.$property->getName().'\b)/ism', "/*\n\t* module: ".$this->name."\n\t* date: ".date('Y-m-d H:i:s')."\n\t* version: ".$this->version."\n\t*/\n\t$1$2$3", $module_file); - if ($module_file === NULL) - throw new Exception(sprintf(Tools::displayError('Failed to override property %1$s in class %2$s.'), $property->getName(), $classname)); - } - - foreach ($module_class->getConstants() as $constant => $value) - { - if ($override_class->hasConstant($constant)) - throw new Exception(sprintf(Tools::displayError('The constant %1$s in the class %2$s is already defined.'), $constant, $classname)); - - $module_file = preg_replace('/(const\s)\s*(\b'.$constant.'\b)/ism', "/*\n\t* module: ".$this->name."\n\t* date: ".date('Y-m-d H:i:s')."\n\t* version: ".$this->version."\n\t*/\n\t$1$2", $module_file); - if ($module_file === NULL) - throw new Exception(sprintf(Tools::displayError('Failed to override constant %1$s in class %2$s.'), $constant, $classname)); - } - - // Insert the methods from module override in override - $copy_from = array_slice($module_file, $module_class->getStartLine() + 1, $module_class->getEndLine() - $module_class->getStartLine() - 2); - array_splice($override_file, $override_class->getEndLine() - 1, 0, $copy_from); - $code = implode('', $override_file); - - file_put_contents($override_path, preg_replace($pattern_escape_com, '', $code)); - } - else - { - $override_src = $path_override; - - $override_dest = _PS_ROOT_DIR_.DIRECTORY_SEPARATOR.'override'.DIRECTORY_SEPARATOR.$path; - $dir_name = dirname($override_dest); - - if (!$orig_path && !is_dir($dir_name)) - { - $oldumask = umask(0000); - @mkdir($dir_name, 0777); - umask($oldumask); - } - - if (!is_writable($dir_name)) - throw new Exception(sprintf(Tools::displayError('directory (%s) not writable'), $dir_name)); - $module_file = file($override_src); - $module_file = array_diff($module_file, array("\n")); - - if ($orig_path) - { - do $uniq = uniqid(); - while (class_exists($classname.'OverrideOriginal_remove', false)); - eval(preg_replace(array('#^\s*<\?(?:php)?#', '#class\s+'.$classname.'(\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?)?#i'), array(' ', 'class '.$classname.'Override'.$uniq), implode('', $module_file))); - $module_class = new ReflectionClass($classname.'Override'.$uniq); - - // For each method found in the override, prepend a comment with the module name and version - foreach ($module_class->getMethods() as $method) - { - $module_file = preg_replace('/((:?public|private|protected)\s+(static\s+)?function\s+(?:\b'.$method->getName().'\b))/ism', "/*\n\t* module: ".$this->name."\n\t* date: ".date('Y-m-d H:i:s')."\n\t* version: ".$this->version."\n\t*/\n\t$1", $module_file); - if ($module_file === NULL) - throw new Exception(sprintf(Tools::displayError('Failed to override method %1$s in class %2$s.'), $method->getName(), $classname)); - } - - // Same loop for properties - foreach ($module_class->getProperties() as $property) - { - $module_file = preg_replace('/((?:public|private|protected)\s)\s*(static\s)?\s*(\$\b'.$property->getName().'\b)/ism', "/*\n\t* module: ".$this->name."\n\t* date: ".date('Y-m-d H:i:s')."\n\t* version: ".$this->version."\n\t*/\n\t$1$2$3", $module_file); - if ($module_file === NULL) - throw new Exception(sprintf(Tools::displayError('Failed to override property %1$s in class %2$s.'), $property->getName(), $classname)); - } - - // Same loop for constants - foreach ($module_class->getConstants() as $constant => $value) - { - $module_file = preg_replace('/(const\s)\s*(\b'.$constant.'\b)/ism', "/*\n\t* module: ".$this->name."\n\t* date: ".date('Y-m-d H:i:s')."\n\t* version: ".$this->version."\n\t*/\n\t$1$2", $module_file); - if ($module_file === NULL) - throw new Exception(sprintf(Tools::displayError('Failed to override constant %1$s in class %2$s.'), $constant, $classname)); - } - } - - file_put_contents($override_dest, preg_replace($pattern_escape_com, '', $module_file)); - - // Re-generate the class index - Tools::generateIndex(); - } - return true; - } - - /** - * Remove all methods in a module override from the override class - * - * @param string $classname - * @return bool - */ - public function removeOverride($classname) - { - $orig_path = $path = PrestaShopAutoload::getInstance()->getClassPath($classname.'Core'); - - if ($orig_path && !$file = PrestaShopAutoload::getInstance()->getClassPath($classname)) - return true; - else if (!$orig_path && Module::getModuleIdByName($classname)) - $path = 'modules'.DIRECTORY_SEPARATOR.$classname.DIRECTORY_SEPARATOR.$classname.'.php'; - - // Check if override file is writable - if ($orig_path) - $override_path = _PS_ROOT_DIR_.'/'.$file; - else - $override_path = _PS_OVERRIDE_DIR_.$path; - - if (!is_file($override_path) || !is_writable($override_path)) - return false; - - file_put_contents($override_path, preg_replace('#(\r\n|\r)#ism', "\n", file_get_contents($override_path))); - - if ($orig_path) - { - // Get a uniq id for the class, because you can override a class (or remove the override) twice in the same session and we need to avoid redeclaration - do $uniq = uniqid(); - while (class_exists($classname.'OverrideOriginal_remove', false)); - - // Make a reflection of the override class and the module override class - $override_file = file($override_path); - - eval(preg_replace(array('#^\s*<\?(?:php)?#', '#class\s+'.$classname.'\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?#i'), array(' ', 'class '.$classname.'OverrideOriginal_remove'.$uniq), implode('', $override_file))); - $override_class = new ReflectionClass($classname.'OverrideOriginal_remove'.$uniq); - - $module_file = file($this->getLocalPath().'override/'.$path); - eval(preg_replace(array('#^\s*<\?(?:php)?#', '#class\s+'.$classname.'(\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?)?#i'), array(' ', 'class '.$classname.'Override_remove'.$uniq), implode('', $module_file))); - $module_class = new ReflectionClass($classname.'Override_remove'.$uniq); - - // Remove methods from override file - foreach ($module_class->getMethods() as $method) - { - if (!$override_class->hasMethod($method->getName())) - continue; - - $method = $override_class->getMethod($method->getName()); - $length = $method->getEndLine() - $method->getStartLine() + 1; - - $module_method = $module_class->getMethod($method->getName()); - $module_length = $module_method->getEndLine() - $module_method->getStartLine() + 1; - - $override_file_orig = $override_file; - - $orig_content = preg_replace('/\s/', '', implode('', array_splice($override_file, $method->getStartLine() - 1, $length, array_pad(array(), $length, '#--remove--#')))); - $module_content = preg_replace('/\s/', '', implode('', array_splice($module_file, $module_method->getStartLine() - 1, $length, array_pad(array(), $length, '#--remove--#')))); - - $replace = true; - if (preg_match('/\* module: ('.$this->name.')/ism', $override_file[$method->getStartLine() - 5])) - { - $override_file[$method->getStartLine() - 6] = $override_file[$method->getStartLine() - 5] = $override_file[$method->getStartLine() - 4] = $override_file[$method->getStartLine() - 3] = $override_file[$method->getStartLine() - 2] = '#--remove--#'; - $replace = false; - } - - if (md5($module_content) != md5($orig_content) && $replace) - $override_file = $override_file_orig; - } - - // Remove properties from override file - foreach ($module_class->getProperties() as $property) - { - if (!$override_class->hasProperty($property->getName())) - continue; - - // Replace the declaration line by #--remove--# - foreach ($override_file as $line_number => &$line_content) - { - if (preg_match('/(public|private|protected)\s+(static\s+)?(\$)?'.$property->getName().'/i', $line_content)) - { - if (preg_match('/\* module: ('.$this->name.')/ism', $override_file[$line_number - 4])) - $override_file[$line_number - 5] = $override_file[$line_number - 4] = $override_file[$line_number - 3] = $override_file[$line_number - 2] = $override_file[$line_number - 1] = '#--remove--#'; - $line_content = '#--remove--#'; - break; - } - } - } - - // Remove properties from override file - foreach ($module_class->getConstants() as $constant => $value) - { - if (!$override_class->hasConstant($constant)) - continue; - - // Replace the declaration line by #--remove--# - foreach ($override_file as $line_number => &$line_content) - { - if (preg_match('/(const)\s+(static\s+)?(\$)?'.$constant.'/i', $line_content)) - { - if (preg_match('/\* module: ('.$this->name.')/ism', $override_file[$line_number - 4])) - $override_file[$line_number - 5] = $override_file[$line_number - 4] = $override_file[$line_number - 3] = $override_file[$line_number - 2] = $override_file[$line_number - 1] = '#--remove--#'; - $line_content = '#--remove--#'; - break; - } - } - } - - $count = count($override_file); - for ($i = 0; $i < $count; ++$i) - { - if (preg_match('/(\/\/.*)/i', $override_file[$i])) - $override_file[$i] = '#--remove--#'; - elseif (preg_match('/(^\s*\/\*)/i', $override_file[$i])) - if (!preg_match('/(^\s*\* module:)/i', $override_file[$i + 1]) - && !preg_match('/(^\s*\* date:)/i', $override_file[$i + 2]) - && !preg_match('/(^\s*\* version:)/i', $override_file[$i + 3]) - && !preg_match('/(^\s*\*\/)/i', $override_file[$i + 4])) - { - for (; $override_file[$i] && !preg_match('/(.*?\*\/)/i', $override_file[$i]); ++$i) - $override_file[$i] = '#--remove--#'; - $override_file[$i] = '#--remove--#'; - } - } - - // Rewrite nice code - $code = ''; - foreach ($override_file as $line) - { - if ($line == '#--remove--#') - continue; - - $code .= $line; - } - - $to_delete = preg_match('/<\?(?:php)?\s+(?:abstract|interface)?\s*?class\s+'.$classname.'\s+extends\s+'.$classname.'Core\s*?[{]\s*?[}]/ism', $code); - } - - if (!isset($to_delete) || $to_delete) - unlink($override_path); - else - file_put_contents($override_path, $code); - - // Re-generate the class index - Tools::generateIndex(); - - return true; - } - - /** - * Return the hooks list where this module can be hooked. - * - * @return array Hooks list. - */ - public function getPossibleHooksList() - { - $hooks_list = Hook::getHooks(); - $possible_hooks_list = array(); - foreach ($hooks_list as &$current_hook) - { - $hook_name = $current_hook['name']; - $retro_hook_name = Hook::getRetroHookName($hook_name); - - if (is_callable(array($this, 'hook'.ucfirst($hook_name))) || is_callable(array($this, 'hook'.ucfirst($retro_hook_name)))) - $possible_hooks_list[] = array( - 'id_hook' => $current_hook['id_hook'], - 'name' => $hook_name, - 'title' => $current_hook['title'], - ); - } - - return $possible_hooks_list; - } + return $result['position']; + } + + /** + * add a warning message to display at the top of the admin page + * + * @param string $msg + */ + public function adminDisplayWarning($msg) + { + if (!($this->context->controller instanceof AdminController)) { + return false; + } + $this->context->controller->warnings[] = $msg; + } + + /** + * add a info message to display at the top of the admin page + * + * @param string $msg + */ + protected function adminDisplayInformation($msg) + { + if (!($this->context->controller instanceof AdminController)) { + return false; + } + $this->context->controller->informations[] = $msg; + } + + /** + * Install module's controllers using public property $controllers + * @return bool + */ + private function installControllers() + { + $themes = Theme::getThemes(); + $theme_meta_value = array(); + foreach ($this->controllers as $controller) { + $page = 'module-'.$this->name.'-'.$controller; + $result = Db::getInstance()->getValue('SELECT * FROM '._DB_PREFIX_.'meta WHERE page="'.pSQL($page).'"'); + if ((int)$result > 0) { + continue; + } + + $meta = new Meta(); + $meta->page = $page; + $meta->configurable = 1; + $meta->save(); + if ((int)$meta->id > 0) { + foreach ($themes as $theme) { + /** @var Theme $theme */ + $theme_meta_value[] = array( + 'id_theme' => $theme->id, + 'id_meta' => $meta->id, + 'left_column' => (int)$theme->default_left_column, + 'right_column' => (int)$theme->default_right_column + ); + } + } else { + $this->_errors[] = sprintf(Tools::displayError('Unable to install controller: %s'), $controller); + } + } + if (count($theme_meta_value) > 0) { + return Db::getInstance()->insert('theme_meta', $theme_meta_value); + } + + return true; + } + + /** + * Install overrides files for the module + * + * @return bool + */ + public function installOverrides() + { + if (!is_dir($this->getLocalPath().'override')) { + return true; + } + + $result = true; + foreach (Tools::scandir($this->getLocalPath().'override', 'php', '', true) as $file) { + $class = basename($file, '.php'); + if (PrestaShopAutoload::getInstance()->getClassPath($class.'Core') || Module::getModuleIdByName($class)) { + $result &= $this->addOverride($class); + } + } + + return $result; + } + + /** + * Uninstall overrides files for the module + * + * @return bool + */ + public function uninstallOverrides() + { + if (!is_dir($this->getLocalPath().'override')) { + return true; + } + + $result = true; + foreach (Tools::scandir($this->getLocalPath().'override', 'php', '', true) as $file) { + $class = basename($file, '.php'); + if (PrestaShopAutoload::getInstance()->getClassPath($class.'Core') || Module::getModuleIdByName($class)) { + $result &= $this->removeOverride($class); + } + } + + return $result; + } + + /** + * Add all methods in a module override to the override class + * + * @param string $classname + * @return bool + */ + public function addOverride($classname) + { + $orig_path = $path = PrestaShopAutoload::getInstance()->getClassPath($classname.'Core'); + if (!$path) { + $path = 'modules'.DIRECTORY_SEPARATOR.$classname.DIRECTORY_SEPARATOR.$classname.'.php'; + } + $path_override = $this->getLocalPath().'override'.DIRECTORY_SEPARATOR.$path; + + if (!file_exists($path_override)) { + return false; + } else { + file_put_contents($path_override, preg_replace('#(\r\n|\r)#ism', "\n", file_get_contents($path_override))); + } + + $pattern_escape_com = '#(^\s*?\/\/.*?\n|\/\*(?!\n\s+\* module:.*?\* date:.*?\* version:.*?\*\/).*?\*\/)#ism'; + // Check if there is already an override file, if not, we just need to copy the file + if ($file = PrestaShopAutoload::getInstance()->getClassPath($classname)) { + // Check if override file is writable + $override_path = _PS_ROOT_DIR_.'/'.$file; + + if ((!file_exists($override_path) && !is_writable(dirname($override_path))) || (file_exists($override_path) && !is_writable($override_path))) { + throw new Exception(sprintf(Tools::displayError('file (%s) not writable'), $override_path)); + } + + // Get a uniq id for the class, because you can override a class (or remove the override) twice in the same session and we need to avoid redeclaration + do { + $uniq = uniqid(); + } while (class_exists($classname.'OverrideOriginal_remove', false)); + + // Make a reflection of the override class and the module override class + $override_file = file($override_path); + $override_file = array_diff($override_file, array("\n")); + eval(preg_replace(array('#^\s*<\?(?:php)?#', '#class\s+'.$classname.'\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?#i'), array(' ', 'class '.$classname.'OverrideOriginal'.$uniq), implode('', $override_file))); + $override_class = new ReflectionClass($classname.'OverrideOriginal'.$uniq); + + $module_file = file($path_override); + $module_file = array_diff($module_file, array("\n")); + eval(preg_replace(array('#^\s*<\?(?:php)?#', '#class\s+'.$classname.'(\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?)?#i'), array(' ', 'class '.$classname.'Override'.$uniq), implode('', $module_file))); + $module_class = new ReflectionClass($classname.'Override'.$uniq); + + // Check if none of the methods already exists in the override class + foreach ($module_class->getMethods() as $method) { + if ($override_class->hasMethod($method->getName())) { + $method_override = $override_class->getMethod($method->getName()); + if (preg_match('/module: (.*)/ism', $override_file[$method_override->getStartLine() - 5], $name) && preg_match('/date: (.*)/ism', $override_file[$method_override->getStartLine() - 4], $date) && preg_match('/version: ([0-9.]+)/ism', $override_file[$method_override->getStartLine() - 3], $version)) { + throw new Exception(sprintf(Tools::displayError('The method %1$s in the class %2$s is already overridden by the module %3$s version %4$s at %5$s.'), $method->getName(), $classname, $name[1], $version[1], $date[1])); + } + throw new Exception(sprintf(Tools::displayError('The method %1$s in the class %2$s is already overridden.'), $method->getName(), $classname)); + } + + $module_file = preg_replace('/((:?public|private|protected)\s+(static\s+)?function\s+(?:\b'.$method->getName().'\b))/ism', "/*\n * module: ".$this->name."\n * date: ".date('Y-m-d H:i:s')."\n * version: ".$this->version."\n */\n $1", $module_file); + if ($module_file === null) { + throw new Exception(sprintf(Tools::displayError('Failed to override method %1$s in class %2$s.'), $method->getName(), $classname)); + } + } + + // Check if none of the properties already exists in the override class + foreach ($module_class->getProperties() as $property) { + if ($override_class->hasProperty($property->getName())) { + throw new Exception(sprintf(Tools::displayError('The property %1$s in the class %2$s is already defined.'), $property->getName(), $classname)); + } + + $module_file = preg_replace('/((?:public|private|protected)\s)\s*(static\s)?\s*(\$\b'.$property->getName().'\b)/ism', "/*\n * module: ".$this->name."\n * date: ".date('Y-m-d H:i:s')."\n * version: ".$this->version."\n */\n $1$2$3", $module_file); + if ($module_file === null) { + throw new Exception(sprintf(Tools::displayError('Failed to override property %1$s in class %2$s.'), $property->getName(), $classname)); + } + } + + foreach ($module_class->getConstants() as $constant => $value) { + if ($override_class->hasConstant($constant)) { + throw new Exception(sprintf(Tools::displayError('The constant %1$s in the class %2$s is already defined.'), $constant, $classname)); + } + + $module_file = preg_replace('/(const\s)\s*(\b'.$constant.'\b)/ism', "/*\n * module: ".$this->name."\n * date: ".date('Y-m-d H:i:s')."\n * version: ".$this->version."\n */\n $1$2", $module_file); + if ($module_file === null) { + throw new Exception(sprintf(Tools::displayError('Failed to override constant %1$s in class %2$s.'), $constant, $classname)); + } + } + + // Insert the methods from module override in override + $copy_from = array_slice($module_file, $module_class->getStartLine() + 1, $module_class->getEndLine() - $module_class->getStartLine() - 2); + array_splice($override_file, $override_class->getEndLine() - 1, 0, $copy_from); + $code = implode('', $override_file); + + file_put_contents($override_path, preg_replace($pattern_escape_com, '', $code)); + } else { + $override_src = $path_override; + + $override_dest = _PS_ROOT_DIR_.DIRECTORY_SEPARATOR.'override'.DIRECTORY_SEPARATOR.$path; + $dir_name = dirname($override_dest); + + if (!$orig_path && !is_dir($dir_name)) { + $oldumask = umask(0000); + @mkdir($dir_name, 0777); + umask($oldumask); + } + + if (!is_writable($dir_name)) { + throw new Exception(sprintf(Tools::displayError('directory (%s) not writable'), $dir_name)); + } + $module_file = file($override_src); + $module_file = array_diff($module_file, array("\n")); + + if ($orig_path) { + do { + $uniq = uniqid(); + } while (class_exists($classname.'OverrideOriginal_remove', false)); + eval(preg_replace(array('#^\s*<\?(?:php)?#', '#class\s+'.$classname.'(\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?)?#i'), array(' ', 'class '.$classname.'Override'.$uniq), implode('', $module_file))); + $module_class = new ReflectionClass($classname.'Override'.$uniq); + + // For each method found in the override, prepend a comment with the module name and version + foreach ($module_class->getMethods() as $method) { + $module_file = preg_replace('/((:?public|private|protected)\s+(static\s+)?function\s+(?:\b'.$method->getName().'\b))/ism', "/*\n * module: ".$this->name."\n * date: ".date('Y-m-d H:i:s')."\n * version: ".$this->version."\n */\n $1", $module_file); + if ($module_file === null) { + throw new Exception(sprintf(Tools::displayError('Failed to override method %1$s in class %2$s.'), $method->getName(), $classname)); + } + } + + // Same loop for properties + foreach ($module_class->getProperties() as $property) { + $module_file = preg_replace('/((?:public|private|protected)\s)\s*(static\s)?\s*(\$\b'.$property->getName().'\b)/ism', "/*\n * module: ".$this->name."\n * date: ".date('Y-m-d H:i:s')."\n * version: ".$this->version."\n */\n $1$2$3", $module_file); + if ($module_file === null) { + throw new Exception(sprintf(Tools::displayError('Failed to override property %1$s in class %2$s.'), $property->getName(), $classname)); + } + } + + // Same loop for constants + foreach ($module_class->getConstants() as $constant => $value) { + $module_file = preg_replace('/(const\s)\s*(\b'.$constant.'\b)/ism', "/*\n * module: ".$this->name."\n * date: ".date('Y-m-d H:i:s')."\n * version: ".$this->version."\n */\n $1$2", $module_file); + if ($module_file === null) { + throw new Exception(sprintf(Tools::displayError('Failed to override constant %1$s in class %2$s.'), $constant, $classname)); + } + } + } + + file_put_contents($override_dest, preg_replace($pattern_escape_com, '', $module_file)); + + // Re-generate the class index + Tools::generateIndex(); + } + return true; + } + + /** + * Remove all methods in a module override from the override class + * + * @param string $classname + * @return bool + */ + public function removeOverride($classname) + { + $orig_path = $path = PrestaShopAutoload::getInstance()->getClassPath($classname.'Core'); + + if ($orig_path && !$file = PrestaShopAutoload::getInstance()->getClassPath($classname)) { + return true; + } elseif (!$orig_path && Module::getModuleIdByName($classname)) { + $path = 'modules'.DIRECTORY_SEPARATOR.$classname.DIRECTORY_SEPARATOR.$classname.'.php'; + } + + // Check if override file is writable + if ($orig_path) { + $override_path = _PS_ROOT_DIR_.'/'.$file; + } else { + $override_path = _PS_OVERRIDE_DIR_.$path; + } + + if (!is_file($override_path) || !is_writable($override_path)) { + return false; + } + + file_put_contents($override_path, preg_replace('#(\r\n|\r)#ism', "\n", file_get_contents($override_path))); + + if ($orig_path) { + // Get a uniq id for the class, because you can override a class (or remove the override) twice in the same session and we need to avoid redeclaration + do { + $uniq = uniqid(); + } while (class_exists($classname.'OverrideOriginal_remove', false)); + + // Make a reflection of the override class and the module override class + $override_file = file($override_path); + + eval(preg_replace(array('#^\s*<\?(?:php)?#', '#class\s+'.$classname.'\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?#i'), array(' ', 'class '.$classname.'OverrideOriginal_remove'.$uniq), implode('', $override_file))); + $override_class = new ReflectionClass($classname.'OverrideOriginal_remove'.$uniq); + + $module_file = file($this->getLocalPath().'override/'.$path); + eval(preg_replace(array('#^\s*<\?(?:php)?#', '#class\s+'.$classname.'(\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?)?#i'), array(' ', 'class '.$classname.'Override_remove'.$uniq), implode('', $module_file))); + $module_class = new ReflectionClass($classname.'Override_remove'.$uniq); + + // Remove methods from override file + foreach ($module_class->getMethods() as $method) { + if (!$override_class->hasMethod($method->getName())) { + continue; + } + + $method = $override_class->getMethod($method->getName()); + $length = $method->getEndLine() - $method->getStartLine() + 1; + + $module_method = $module_class->getMethod($method->getName()); + $module_length = $module_method->getEndLine() - $module_method->getStartLine() + 1; + + $override_file_orig = $override_file; + + $orig_content = preg_replace('/\s/', '', implode('', array_splice($override_file, $method->getStartLine() - 1, $length, array_pad(array(), $length, '#--remove--#')))); + $module_content = preg_replace('/\s/', '', implode('', array_splice($module_file, $module_method->getStartLine() - 1, $length, array_pad(array(), $length, '#--remove--#')))); + + $replace = true; + if (preg_match('/\* module: ('.$this->name.')/ism', $override_file[$method->getStartLine() - 5])) { + $override_file[$method->getStartLine() - 6] = $override_file[$method->getStartLine() - 5] = $override_file[$method->getStartLine() - 4] = $override_file[$method->getStartLine() - 3] = $override_file[$method->getStartLine() - 2] = '#--remove--#'; + $replace = false; + } + + if (md5($module_content) != md5($orig_content) && $replace) { + $override_file = $override_file_orig; + } + } + + // Remove properties from override file + foreach ($module_class->getProperties() as $property) { + if (!$override_class->hasProperty($property->getName())) { + continue; + } + + // Replace the declaration line by #--remove--# + foreach ($override_file as $line_number => &$line_content) { + if (preg_match('/(public|private|protected)\s+(static\s+)?(\$)?'.$property->getName().'/i', $line_content)) { + if (preg_match('/\* module: ('.$this->name.')/ism', $override_file[$line_number - 4])) { + $override_file[$line_number - 5] = $override_file[$line_number - 4] = $override_file[$line_number - 3] = $override_file[$line_number - 2] = $override_file[$line_number - 1] = '#--remove--#'; + } + $line_content = '#--remove--#'; + break; + } + } + } + + // Remove properties from override file + foreach ($module_class->getConstants() as $constant => $value) { + if (!$override_class->hasConstant($constant)) { + continue; + } + + // Replace the declaration line by #--remove--# + foreach ($override_file as $line_number => &$line_content) { + if (preg_match('/(const)\s+(static\s+)?(\$)?'.$constant.'/i', $line_content)) { + if (preg_match('/\* module: ('.$this->name.')/ism', $override_file[$line_number - 4])) { + $override_file[$line_number - 5] = $override_file[$line_number - 4] = $override_file[$line_number - 3] = $override_file[$line_number - 2] = $override_file[$line_number - 1] = '#--remove--#'; + } + $line_content = '#--remove--#'; + break; + } + } + } + + $count = count($override_file); + for ($i = 0; $i < $count; ++$i) { + if (preg_match('/(^\s*\/\/.*)/i', $override_file[$i])) { + $override_file[$i] = '#--remove--#'; + } elseif (preg_match('/(^\s*\/\*)/i', $override_file[$i])) { + if (!preg_match('/(^\s*\* module:)/i', $override_file[$i + 1]) + && !preg_match('/(^\s*\* date:)/i', $override_file[$i + 2]) + && !preg_match('/(^\s*\* version:)/i', $override_file[$i + 3]) + && !preg_match('/(^\s*\*\/)/i', $override_file[$i + 4])) { + for (; $override_file[$i] && !preg_match('/(.*?\*\/)/i', $override_file[$i]); ++$i) { + $override_file[$i] = '#--remove--#'; + } + $override_file[$i] = '#--remove--#'; + } + } + } + + // Rewrite nice code + $code = ''; + foreach ($override_file as $line) { + if ($line == '#--remove--#') { + continue; + } + + $code .= $line; + } + + $to_delete = preg_match('/<\?(?:php)?\s+(?:abstract|interface)?\s*?class\s+'.$classname.'\s+extends\s+'.$classname.'Core\s*?[{]\s*?[}]/ism', $code); + } + + if (!isset($to_delete) || $to_delete) { + unlink($override_path); + } else { + file_put_contents($override_path, $code); + } + + // Re-generate the class index + Tools::generateIndex(); + + return true; + } + + /** + * Return the hooks list where this module can be hooked. + * + * @return array Hooks list. + */ + public function getPossibleHooksList() + { + $hooks_list = Hook::getHooks(); + $possible_hooks_list = array(); + foreach ($hooks_list as &$current_hook) { + $hook_name = $current_hook['name']; + $retro_hook_name = Hook::getRetroHookName($hook_name); + + if (is_callable(array($this, 'hook'.ucfirst($hook_name))) || is_callable(array($this, 'hook'.ucfirst($retro_hook_name)))) { + $possible_hooks_list[] = array( + 'id_hook' => $current_hook['id_hook'], + 'name' => $hook_name, + 'title' => $current_hook['title'], + ); + } + } + + return $possible_hooks_list; + } } function ps_module_version_sort($a, $b) { - return version_compare($a['version'], $b['version']); + return version_compare($a['version'], $b['version']); } diff --git a/classes/module/ModuleGraph.php b/classes/module/ModuleGraph.php index dc1a4862..91b29f44 100644 --- a/classes/module/ModuleGraph.php +++ b/classes/module/ModuleGraph.php @@ -26,309 +26,332 @@ abstract class ModuleGraphCore extends Module { - protected $_employee; + protected $_employee; - /** @var array of integers graph data */ - protected $_values = array(); + /** @var array of integers graph data */ + protected $_values = array(); - /** @var array of strings graph legends (X axis) */ - protected $_legend = array(); + /** @var array of strings graph legends (X axis) */ + protected $_legend = array(); - /**@var array string graph titles */ - protected $_titles = array('main' => null, 'x' => null, 'y' => null); + /**@var array string graph titles */ + protected $_titles = array('main' => null, 'x' => null, 'y' => null); - /** @var ModuleGraphEngine graph engine */ - protected $_render; + /** @var ModuleGraphEngine graph engine */ + protected $_render; - abstract protected function getData($layers); + abstract protected function getData($layers); - public function setEmployee($id_employee) - { - $this->_employee = new Employee($id_employee); - } + public function setEmployee($id_employee) + { + $this->_employee = new Employee($id_employee); + } - public function setLang($id_lang) - { - $this->_id_lang = $id_lang; - } + public function setLang($id_lang) + { + $this->_id_lang = $id_lang; + } - protected function setDateGraph($layers, $legend = false) - { - // Get dates in a manageable format - $from_array = getdate(strtotime($this->_employee->stats_date_from)); - $to_array = getdate(strtotime($this->_employee->stats_date_to)); + protected function setDateGraph($layers, $legend = false) + { + // Get dates in a manageable format + $from_array = getdate(strtotime($this->_employee->stats_date_from)); + $to_array = getdate(strtotime($this->_employee->stats_date_to)); - // If the granularity is inferior to 1 day - if ($this->_employee->stats_date_from == $this->_employee->stats_date_to) - { - if ($legend) - for ($i = 0; $i < 24; $i++) - { - if ($layers == 1) - $this->_values[$i] = 0; - else - for ($j = 0; $j < $layers; $j++) - $this->_values[$j][$i] = 0; - $this->_legend[$i] = ($i % 2) ? '' : sprintf('%02dh', $i); - } - if (is_callable(array($this, 'setDayValues'))) - $this->setDayValues($layers); - } - // If the granularity is inferior to 1 month - // @TODO : change to manage 28 to 31 days - elseif (strtotime($this->_employee->stats_date_to) - strtotime($this->_employee->stats_date_from) <= 2678400) - { - if ($legend) - { - $days = array(); - if ($from_array['mon'] == $to_array['mon']) - for ($i = $from_array['mday']; $i <= $to_array['mday']; ++$i) - $days[] = $i; - else - { - $imax = date('t', mktime(0, 0, 0, $from_array['mon'], 1, $from_array['year'])); - for ($i = $from_array['mday']; $i <= $imax; ++$i) - $days[] = $i; - for ($i = 1; $i <= $to_array['mday']; ++$i) - $days[] = $i; - } - foreach ($days as $i) - { - if ($layers == 1) - $this->_values[$i] = 0; - else - for ($j = 0; $j < $layers; $j++) - $this->_values[$j][$i] = 0; - $this->_legend[$i] = ($i % 2) ? '' : sprintf('%02d', $i); - } - } - if (is_callable(array($this, 'setMonthValues'))) - $this->setMonthValues($layers); - } - // If the granularity is less than 1 year - elseif (strtotime('-1 year', strtotime($this->_employee->stats_date_to)) < strtotime($this->_employee->stats_date_from)) - { - if ($legend) - { - $months = array(); - if ($from_array['year'] == $to_array['year']) - for ($i = $from_array['mon']; $i <= $to_array['mon']; ++$i) - $months[] = $i; - else - { - for ($i = $from_array['mon']; $i <= 12; ++$i) - $months[] = $i; - for ($i = 1; $i <= $to_array['mon']; ++$i) - $months[] = $i; - } - foreach ($months as $i) - { - if ($layers == 1) - $this->_values[$i] = 0; - else - for ($j = 0; $j < $layers; $j++) - $this->_values[$j][$i] = 0; - $this->_legend[$i] = sprintf('%02d', $i); - } - } - if (is_callable(array($this, 'setYearValues'))) - $this->setYearValues($layers); - } - // If the granularity is greater than 1 year - else - { - if ($legend) - { - $years = array(); - for ($i = $from_array['year']; $i <= $to_array['year']; ++$i) - $years[] = $i; - foreach ($years as $i) - { - if ($layers == 1) - $this->_values[$i] = 0; - else - for ($j = 0; $j < $layers; $j++) - $this->_values[$j][$i] = 0; - $this->_legend[$i] = sprintf('%04d', $i); - } - } - if (is_callable(array($this, 'setAllTimeValues'))) - $this->setAllTimeValues($layers); - } - } + // If the granularity is inferior to 1 day + if ($this->_employee->stats_date_from == $this->_employee->stats_date_to) { + if ($legend) { + for ($i = 0; $i < 24; $i++) { + if ($layers == 1) { + $this->_values[$i] = 0; + } else { + for ($j = 0; $j < $layers; $j++) { + $this->_values[$j][$i] = 0; + } + } + $this->_legend[$i] = ($i % 2) ? '' : sprintf('%02dh', $i); + } + } + if (is_callable(array($this, 'setDayValues'))) { + $this->setDayValues($layers); + } + } + // If the granularity is inferior to 1 month + // @TODO : change to manage 28 to 31 days + elseif (strtotime($this->_employee->stats_date_to) - strtotime($this->_employee->stats_date_from) <= 2678400) { + if ($legend) { + $days = array(); + if ($from_array['mon'] == $to_array['mon']) { + for ($i = $from_array['mday']; $i <= $to_array['mday']; ++$i) { + $days[] = $i; + } + } else { + $imax = date('t', mktime(0, 0, 0, $from_array['mon'], 1, $from_array['year'])); + for ($i = $from_array['mday']; $i <= $imax; ++$i) { + $days[] = $i; + } + for ($i = 1; $i <= $to_array['mday']; ++$i) { + $days[] = $i; + } + } + foreach ($days as $i) { + if ($layers == 1) { + $this->_values[$i] = 0; + } else { + for ($j = 0; $j < $layers; $j++) { + $this->_values[$j][$i] = 0; + } + } + $this->_legend[$i] = ($i % 2) ? '' : sprintf('%02d', $i); + } + } + if (is_callable(array($this, 'setMonthValues'))) { + $this->setMonthValues($layers); + } + } + // If the granularity is less than 1 year + elseif (strtotime('-1 year', strtotime($this->_employee->stats_date_to)) < strtotime($this->_employee->stats_date_from)) { + if ($legend) { + $months = array(); + if ($from_array['year'] == $to_array['year']) { + for ($i = $from_array['mon']; $i <= $to_array['mon']; ++$i) { + $months[] = $i; + } + } else { + for ($i = $from_array['mon']; $i <= 12; ++$i) { + $months[] = $i; + } + for ($i = 1; $i <= $to_array['mon']; ++$i) { + $months[] = $i; + } + } + foreach ($months as $i) { + if ($layers == 1) { + $this->_values[$i] = 0; + } else { + for ($j = 0; $j < $layers; $j++) { + $this->_values[$j][$i] = 0; + } + } + $this->_legend[$i] = sprintf('%02d', $i); + } + } + if (is_callable(array($this, 'setYearValues'))) { + $this->setYearValues($layers); + } + } + // If the granularity is greater than 1 year + else { + if ($legend) { + $years = array(); + for ($i = $from_array['year']; $i <= $to_array['year']; ++$i) { + $years[] = $i; + } + foreach ($years as $i) { + if ($layers == 1) { + $this->_values[$i] = 0; + } else { + for ($j = 0; $j < $layers; $j++) { + $this->_values[$j][$i] = 0; + } + } + $this->_legend[$i] = sprintf('%04d', $i); + } + } + if (is_callable(array($this, 'setAllTimeValues'))) { + $this->setAllTimeValues($layers); + } + } + } - protected function csvExport($datas) - { - $context = Context::getContext(); + protected function csvExport($datas) + { + $context = Context::getContext(); - $this->setEmployee($context->employee->id); - $this->setLang($context->language->id); + $this->setEmployee($context->employee->id); + $this->setLang($context->language->id); - $layers = isset($datas['layers']) ? $datas['layers'] : 1; - if (isset($datas['option'])) - $this->setOption($datas['option'], $layers); - $this->getData($layers); + $layers = isset($datas['layers']) ? $datas['layers'] : 1; + if (isset($datas['option'])) { + $this->setOption($datas['option'], $layers); + } + $this->getData($layers); - // @todo use native CSV PHP functions ? - // Generate first line (column titles) - if (is_array($this->_titles['main'])) - for ($i = 0, $total_main = count($this->_titles['main']); $i <= $total_main; $i++) - { - if ($i > 0) - $this->_csv .= ';'; - if (isset($this->_titles['main'][$i])) - $this->_csv .= $this->_titles['main'][$i]; - } - else // If there is only one column title, there is in fast two column (the first without title) - $this->_csv .= ';'.$this->_titles['main']; - $this->_csv .= "\n"; - if (count($this->_legend)) - { - $total = 0; - if ($datas['type'] == 'pie') - foreach ($this->_legend as $key => $legend) - for ($i = 0, $total_main = (is_array($this->_titles['main']) ? count($this->_values) : 1); $i < $total_main; ++$i) - $total += (is_array($this->_values[$i]) ? $this->_values[$i][$key] : $this->_values[$key]); - foreach ($this->_legend as $key => $legend) - { - $this->_csv .= $legend.';'; - for ($i = 0, $total_main = (is_array($this->_titles['main']) ? count($this->_values) : 1); $i < $total_main; ++$i) - { - if (!isset($this->_values[$i]) || !is_array($this->_values[$i])) - if (isset($this->_values[$key])) - { - // We don't want strings to be divided. Example: product name - if (is_numeric($this->_values[$key])) - $this->_csv .= $this->_values[$key] / (($datas['type'] == 'pie') ? $total : 1); - else - $this->_csv .= $this->_values[$key]; - } - else - $this->_csv .= '0'; - else - { - // We don't want strings to be divided. Example: product name - if (is_numeric($this->_values[$i][$key])) - $this->_csv .= $this->_values[$i][$key] / (($datas['type'] == 'pie') ? $total : 1); - else - $this->_csv .= $this->_values[$i][$key]; - } - $this->_csv .= ';'; - } - $this->_csv .= "\n"; - } - } - $this->_displayCsv(); - } + // @todo use native CSV PHP functions ? + // Generate first line (column titles) + if (is_array($this->_titles['main'])) { + for ($i = 0, $total_main = count($this->_titles['main']); $i <= $total_main; $i++) { + if ($i > 0) { + $this->_csv .= ';'; + } + if (isset($this->_titles['main'][$i])) { + $this->_csv .= $this->_titles['main'][$i]; + } + } + } else { // If there is only one column title, there is in fast two column (the first without title) + $this->_csv .= ';'.$this->_titles['main']; + } + $this->_csv .= "\n"; + if (count($this->_legend)) { + $total = 0; + if ($datas['type'] == 'pie') { + foreach ($this->_legend as $key => $legend) { + for ($i = 0, $total_main = (is_array($this->_titles['main']) ? count($this->_values) : 1); $i < $total_main; ++$i) { + $total += (is_array($this->_values[$i]) ? $this->_values[$i][$key] : $this->_values[$key]); + } + } + } + foreach ($this->_legend as $key => $legend) { + $this->_csv .= $legend.';'; + for ($i = 0, $total_main = (is_array($this->_titles['main']) ? count($this->_values) : 1); $i < $total_main; ++$i) { + if (!isset($this->_values[$i]) || !is_array($this->_values[$i])) { + if (isset($this->_values[$key])) { + // We don't want strings to be divided. Example: product name + if (is_numeric($this->_values[$key])) { + $this->_csv .= $this->_values[$key] / (($datas['type'] == 'pie') ? $total : 1); + } else { + $this->_csv .= $this->_values[$key]; + } + } else { + $this->_csv .= '0'; + } + } else { + // We don't want strings to be divided. Example: product name + if (is_numeric($this->_values[$i][$key])) { + $this->_csv .= $this->_values[$i][$key] / (($datas['type'] == 'pie') ? $total : 1); + } else { + $this->_csv .= $this->_values[$i][$key]; + } + } + $this->_csv .= ';'; + } + $this->_csv .= "\n"; + } + } + $this->_displayCsv(); + } - protected function _displayCsv() - { - if (ob_get_level() && ob_get_length() > 0) - ob_end_clean(); - header('Content-Type: application/octet-stream'); - header('Content-Disposition: attachment; filename="'.$this->displayName.' - '.time().'.csv"'); - echo $this->_csv; - exit; - } + protected function _displayCsv() + { + if (ob_get_level() && ob_get_length() > 0) { + ob_end_clean(); + } + header('Content-Type: application/octet-stream'); + header('Content-Disposition: attachment; filename="'.$this->displayName.' - '.time().'.csv"'); + echo $this->_csv; + exit; + } - public function create($render, $type, $width, $height, $layers) - { - if (!Validate::isModuleName($render)) - die(Tools::displayError()); - if (!Tools::file_exists_cache($file = _PS_ROOT_DIR_.'/modules/'.$render.'/'.$render.'.php')) - die(Tools::displayError()); - require_once($file); - $this->_render = new $render($type); + public function create($render, $type, $width, $height, $layers) + { + if (!Validate::isModuleName($render)) { + die(Tools::displayError()); + } + if (!Tools::file_exists_cache($file = _PS_ROOT_DIR_.'/modules/'.$render.'/'.$render.'.php')) { + die(Tools::displayError()); + } + require_once($file); + $this->_render = new $render($type); - $this->getData($layers); - $this->_render->createValues($this->_values); - $this->_render->setSize($width, $height); - $this->_render->setLegend($this->_legend); - $this->_render->setTitles($this->_titles); - } + $this->getData($layers); + $this->_render->createValues($this->_values); + $this->_render->setSize($width, $height); + $this->_render->setLegend($this->_legend); + $this->_render->setTitles($this->_titles); + } - public function draw() - { - $this->_render->draw(); - } + public function draw() + { + $this->_render->draw(); + } - /** - * @todo Set this method as abstracted ? Quid of module compatibility. - */ - public function setOption($option, $layers = 1) - { - } + /** + * @todo Set this method as abstracted ? Quid of module compatibility. + */ + public function setOption($option, $layers = 1) + { + } - public function engine($params) - { - $context = Context::getContext(); - if (!($render = Configuration::get('PS_STATS_RENDER'))) - return Tools::displayError('No graph engine selected'); - if (!Validate::isModuleName($render)) - die(Tools::displayError()); - if (!file_exists(_PS_ROOT_DIR_.'/modules/'.$render.'/'.$render.'.php')) - return Tools::displayError('Graph engine selected is unavailable.'); + public function engine($params) + { + $context = Context::getContext(); + if (!($render = Configuration::get('PS_STATS_RENDER'))) { + return Tools::displayError('No graph engine selected'); + } + if (!Validate::isModuleName($render)) { + die(Tools::displayError()); + } + if (!file_exists(_PS_ROOT_DIR_.'/modules/'.$render.'/'.$render.'.php')) { + return Tools::displayError('Graph engine selected is unavailable.'); + } - $id_employee = (int)$context->employee->id; - $id_lang = (int)$context->language->id; + $id_employee = (int)$context->employee->id; + $id_lang = (int)$context->language->id; - if (!isset($params['layers'])) - $params['layers'] = 1; - if (!isset($params['type'])) - $params['type'] = 'column'; - if (!isset($params['width'])) - $params['width'] = '100%'; - if (!isset($params['height'])) - $params['height'] = 270; + if (!isset($params['layers'])) { + $params['layers'] = 1; + } + if (!isset($params['type'])) { + $params['type'] = 'column'; + } + if (!isset($params['width'])) { + $params['width'] = '100%'; + } + if (!isset($params['height'])) { + $params['height'] = 270; + } - $url_params = $params; - $url_params['render'] = $render; - $url_params['module'] = Tools::getValue('module'); - $url_params['id_employee'] = $id_employee; - $url_params['id_lang'] = $id_lang; - $drawer = 'drawer.php?'.http_build_query(array_map('Tools::safeOutput', $url_params), '', '&'); + $url_params = $params; + $url_params['render'] = $render; + $url_params['module'] = Tools::getValue('module'); + $url_params['id_employee'] = $id_employee; + $url_params['id_lang'] = $id_lang; + $drawer = 'drawer.php?'.http_build_query(array_map('Tools::safeOutput', $url_params), '', '&'); - require_once(_PS_ROOT_DIR_.'/modules/'.$render.'/'.$render.'.php'); - return call_user_func(array($render, 'hookGraphEngine'), $params, $drawer); - } + require_once(_PS_ROOT_DIR_.'/modules/'.$render.'/'.$render.'.php'); + return call_user_func(array($render, 'hookGraphEngine'), $params, $drawer); + } - protected static function getEmployee($employee = null, Context $context = null) - { - if (!Validate::isLoadedObject($employee)) - { - if (!$context) - $context = Context::getContext(); - if (!Validate::isLoadedObject($context->employee)) - return false; - $employee = $context->employee; - } + protected static function getEmployee($employee = null, Context $context = null) + { + if (!Validate::isLoadedObject($employee)) { + if (!$context) { + $context = Context::getContext(); + } + if (!Validate::isLoadedObject($context->employee)) { + return false; + } + $employee = $context->employee; + } - if (empty($employee->stats_date_from) || empty($employee->stats_date_to) - || $employee->stats_date_from == '0000-00-00' || $employee->stats_date_to == '0000-00-00') - { - if (empty($employee->stats_date_from) || $employee->stats_date_from == '0000-00-00') - $employee->stats_date_from = date('Y').'-01-01'; - if (empty($employee->stats_date_to) || $employee->stats_date_to == '0000-00-00') - $employee->stats_date_to = date('Y').'-12-31'; - $employee->update(); - } - return $employee; - } + if (empty($employee->stats_date_from) || empty($employee->stats_date_to) + || $employee->stats_date_from == '0000-00-00' || $employee->stats_date_to == '0000-00-00') { + if (empty($employee->stats_date_from) || $employee->stats_date_from == '0000-00-00') { + $employee->stats_date_from = date('Y').'-01-01'; + } + if (empty($employee->stats_date_to) || $employee->stats_date_to == '0000-00-00') { + $employee->stats_date_to = date('Y').'-12-31'; + } + $employee->update(); + } + return $employee; + } - public function getDate() - { - return ModuleGraph::getDateBetween($this->_employee); - } + public function getDate() + { + return ModuleGraph::getDateBetween($this->_employee); + } - public static function getDateBetween($employee = null) - { - if ($employee = ModuleGraph::getEmployee($employee)) - return ' \''.$employee->stats_date_from.' 00:00:00\' AND \''.$employee->stats_date_to.' 23:59:59\' '; - return ' \''.date('Y-m').'-01 00:00:00\' AND \''.date('Y-m-t').' 23:59:59\' '; - } + public static function getDateBetween($employee = null) + { + if ($employee = ModuleGraph::getEmployee($employee)) { + return ' \''.$employee->stats_date_from.' 00:00:00\' AND \''.$employee->stats_date_to.' 23:59:59\' '; + } + return ' \''.date('Y-m').'-01 00:00:00\' AND \''.date('Y-m-t').' 23:59:59\' '; + } - public function getLang() - { - return $this->_id_lang; - } -} \ No newline at end of file + public function getLang() + { + return $this->_id_lang; + } +} diff --git a/classes/module/ModuleGraphEngine.php b/classes/module/ModuleGraphEngine.php index 6f01cb76..905752d0 100644 --- a/classes/module/ModuleGraphEngine.php +++ b/classes/module/ModuleGraphEngine.php @@ -26,23 +26,24 @@ abstract class ModuleGraphEngineCore extends Module { - protected $_type; + protected $_type; - public function __construct($type) - { - $this->_type = $type; - } + public function __construct($type) + { + $this->_type = $type; + } - public function install() - { - if (!parent::install()) - return false; - return Configuration::updateValue('PS_STATS_RENDER', $this->name); - } + public function install() + { + if (!parent::install()) { + return false; + } + return Configuration::updateValue('PS_STATS_RENDER', $this->name); + } - public static function getGraphEngines() - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getGraphEngines() + { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT m.`name` FROM `'._DB_PREFIX_.'module` m LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_module` = m.`id_module` @@ -50,21 +51,21 @@ abstract class ModuleGraphEngineCore extends Module WHERE h.`name` = \'displayAdminStatsGraphEngine\' '); - $array_engines = array(); - foreach ($result as $module) - { - $instance = Module::getInstanceByName($module['name']); - if (!$instance) - continue; - $array_engines[$module['name']] = array($instance->displayName, $instance->description); - } + $array_engines = array(); + foreach ($result as $module) { + $instance = Module::getInstanceByName($module['name']); + if (!$instance) { + continue; + } + $array_engines[$module['name']] = array($instance->displayName, $instance->description); + } - return $array_engines; - } + return $array_engines; + } - abstract public function createValues($values); - abstract public function setSize($width, $height); - abstract public function setLegend($legend); - abstract public function setTitles($titles); - abstract public function draw(); -} \ No newline at end of file + abstract public function createValues($values); + abstract public function setSize($width, $height); + abstract public function setLegend($legend); + abstract public function setTitles($titles); + abstract public function draw(); +} diff --git a/classes/module/ModuleGrid.php b/classes/module/ModuleGrid.php index 28803af9..980dba57 100644 --- a/classes/module/ModuleGrid.php +++ b/classes/module/ModuleGrid.php @@ -26,159 +26,176 @@ abstract class ModuleGridCore extends Module { - protected $_employee; + protected $_employee; - /** @var array of strings graph data */ - protected $_values = array(); + /** @var array of strings graph data */ + protected $_values = array(); - /** @var int total number of values **/ - protected $_totalCount = 0; + /** @var int total number of values **/ + protected $_totalCount = 0; - /**@var string graph titles */ - protected $_title; + /**@var string graph titles */ + protected $_title; - /**@var int start */ - protected $_start; + /**@var int start */ + protected $_start; - /**@var int limit */ - protected $_limit; + /**@var int limit */ + protected $_limit; - /**@var string column name on which to sort */ - protected $_sort = null; + /**@var string column name on which to sort */ + protected $_sort = null; - /**@var string sort direction DESC/ASC */ - protected $_direction = null; + /**@var string sort direction DESC/ASC */ + protected $_direction = null; - /** @var ModuleGridEngine grid engine */ - protected $_render; + /** @var ModuleGridEngine grid engine */ + protected $_render; - abstract protected function getData(); + abstract protected function getData(); - public function setEmployee($id_employee) - { - $this->_employee = new Employee($id_employee); - } + public function setEmployee($id_employee) + { + $this->_employee = new Employee($id_employee); + } - public function setLang($id_lang) - { - $this->_id_lang = $id_lang; - } + public function setLang($id_lang) + { + $this->_id_lang = $id_lang; + } - public function create($render, $type, $width, $height, $start, $limit, $sort, $dir) - { - if (!Validate::isModuleName($render)) - die(Tools::displayError()); - if (!Tools::file_exists_cache($file = _PS_ROOT_DIR_.'/modules/'.$render.'/'.$render.'.php')) - die(Tools::displayError()); - require_once($file); - $this->_render = new $render($type); + public function create($render, $type, $width, $height, $start, $limit, $sort, $dir) + { + if (!Validate::isModuleName($render)) { + die(Tools::displayError()); + } + if (!Tools::file_exists_cache($file = _PS_ROOT_DIR_.'/modules/'.$render.'/'.$render.'.php')) { + die(Tools::displayError()); + } + require_once($file); + $this->_render = new $render($type); - $this->_start = $start; - $this->_limit = $limit; - $this->_sort = $sort; - $this->_direction = $dir; + $this->_start = $start; + $this->_limit = $limit; + $this->_sort = $sort; + $this->_direction = $dir; - $this->getData(); + $this->getData(); - $this->_render->setTitle($this->_title); - $this->_render->setSize($width, $height); - $this->_render->setValues($this->_values); - $this->_render->setTotalCount($this->_totalCount); - $this->_render->setLimit($this->_start, $this->_limit); - } + $this->_render->setTitle($this->_title); + $this->_render->setSize($width, $height); + $this->_render->setValues($this->_values); + $this->_render->setTotalCount($this->_totalCount); + $this->_render->setLimit($this->_start, $this->_limit); + } - public function render() - { - $this->_render->render(); - } + public function render() + { + $this->_render->render(); + } - public function engine($params) - { - if (!($render = Configuration::get('PS_STATS_GRID_RENDER'))) - return Tools::displayError('No grid engine selected'); - if (!Validate::isModuleName($render)) - die(Tools::displayError()); - if (!file_exists(_PS_ROOT_DIR_.'/modules/'.$render.'/'.$render.'.php')) - return Tools::displayError('Grid engine selected is unavailable.'); + public function engine($params) + { + if (!($render = Configuration::get('PS_STATS_GRID_RENDER'))) { + return Tools::displayError('No grid engine selected'); + } + if (!Validate::isModuleName($render)) { + die(Tools::displayError()); + } + if (!file_exists(_PS_ROOT_DIR_.'/modules/'.$render.'/'.$render.'.php')) { + return Tools::displayError('Grid engine selected is unavailable.'); + } - $grider = 'grider.php?render='.$render.'&module='.Tools::safeOutput(Tools::getValue('module')); + $grider = 'grider.php?render='.$render.'&module='.Tools::safeOutput(Tools::getValue('module')); - $context = Context::getContext(); - $grider .= '&id_employee='.(int)$context->employee->id; - $grider .= '&id_lang='.(int)$context->language->id; + $context = Context::getContext(); + $grider .= '&id_employee='.(int)$context->employee->id; + $grider .= '&id_lang='.(int)$context->language->id; - if (!isset($params['width']) || !Validate::IsUnsignedInt($params['width'])) - $params['width'] = 600; - if (!isset($params['height']) || !Validate::IsUnsignedInt($params['height'])) - $params['height'] = 920; - if (!isset($params['start']) || !Validate::IsUnsignedInt($params['start'])) - $params['start'] = 0; - if (!isset($params['limit']) || !Validate::IsUnsignedInt($params['limit'])) - $params['limit'] = 40; + if (!isset($params['width']) || !Validate::IsUnsignedInt($params['width'])) { + $params['width'] = 600; + } + if (!isset($params['height']) || !Validate::IsUnsignedInt($params['height'])) { + $params['height'] = 920; + } + if (!isset($params['start']) || !Validate::IsUnsignedInt($params['start'])) { + $params['start'] = 0; + } + if (!isset($params['limit']) || !Validate::IsUnsignedInt($params['limit'])) { + $params['limit'] = 40; + } - $grider .= '&width='.$params['width']; - $grider .= '&height='.$params['height']; - if (isset($params['start']) && Validate::IsUnsignedInt($params['start'])) - $grider .= '&start='.$params['start']; - if (isset($params['limit']) && Validate::IsUnsignedInt($params['limit'])) - $grider .= '&limit='.$params['limit']; - if (isset($params['type']) && Validate::IsName($params['type'])) - $grider .= '&type='.$params['type']; - if (isset($params['option']) && Validate::IsGenericName($params['option'])) - $grider .= '&option='.$params['option']; - if (isset($params['sort']) && Validate::IsName($params['sort'])) - $grider .= '&sort='.$params['sort']; - if (isset($params['dir']) && Validate::isSortDirection($params['dir'])) - $grider .= '&dir='.$params['dir']; + $grider .= '&width='.$params['width']; + $grider .= '&height='.$params['height']; + if (isset($params['start']) && Validate::IsUnsignedInt($params['start'])) { + $grider .= '&start='.$params['start']; + } + if (isset($params['limit']) && Validate::IsUnsignedInt($params['limit'])) { + $grider .= '&limit='.$params['limit']; + } + if (isset($params['type']) && Validate::IsName($params['type'])) { + $grider .= '&type='.$params['type']; + } + if (isset($params['option']) && Validate::IsGenericName($params['option'])) { + $grider .= '&option='.$params['option']; + } + if (isset($params['sort']) && Validate::IsName($params['sort'])) { + $grider .= '&sort='.$params['sort']; + } + if (isset($params['dir']) && Validate::isSortDirection($params['dir'])) { + $grider .= '&dir='.$params['dir']; + } - require_once(_PS_ROOT_DIR_.'/modules/'.$render.'/'.$render.'.php'); - return call_user_func(array($render, 'hookGridEngine'), $params, $grider); - } + require_once(_PS_ROOT_DIR_.'/modules/'.$render.'/'.$render.'.php'); + return call_user_func(array($render, 'hookGridEngine'), $params, $grider); + } - protected function csvExport($datas) - { - $this->_sort = $datas['defaultSortColumn']; - $this->setLang(Context::getContext()->language->id); - $this->getData(); + protected function csvExport($datas) + { + $this->_sort = $datas['defaultSortColumn']; + $this->setLang(Context::getContext()->language->id); + $this->getData(); - $layers = isset($datas['layers']) ? $datas['layers'] : 1; + $layers = isset($datas['layers']) ? $datas['layers'] : 1; - if (isset($datas['option'])) - $this->setOption($datas['option'], $layers); + if (isset($datas['option'])) { + $this->setOption($datas['option'], $layers); + } - if (count($datas['columns'])) - { - foreach ($datas['columns'] as $column) - $this->_csv .= $column['header'].';'; - $this->_csv = rtrim($this->_csv, ';')."\n"; + if (count($datas['columns'])) { + foreach ($datas['columns'] as $column) { + $this->_csv .= $column['header'].';'; + } + $this->_csv = rtrim($this->_csv, ';')."\n"; - foreach ($this->_values as $value) - { - foreach ($datas['columns'] as $column) - $this->_csv .= $value[$column['dataIndex']].';'; - $this->_csv = rtrim($this->_csv, ';')."\n"; - } - } - $this->_displayCsv(); - } + foreach ($this->_values as $value) { + foreach ($datas['columns'] as $column) { + $this->_csv .= $value[$column['dataIndex']].';'; + } + $this->_csv = rtrim($this->_csv, ';')."\n"; + } + } + $this->_displayCsv(); + } - protected function _displayCsv() - { - if (ob_get_level() && ob_get_length() > 0) - ob_end_clean(); - header('Content-Type: application/octet-stream'); - header('Content-Disposition: attachment; filename="'.$this->displayName.' - '.time().'.csv"'); - echo $this->_csv; - exit; - } + protected function _displayCsv() + { + if (ob_get_level() && ob_get_length() > 0) { + ob_end_clean(); + } + header('Content-Type: application/octet-stream'); + header('Content-Disposition: attachment; filename="'.$this->displayName.' - '.time().'.csv"'); + echo $this->_csv; + exit; + } - public function getDate() - { - return ModuleGraph::getDateBetween($this->_employee); - } + public function getDate() + { + return ModuleGraph::getDateBetween($this->_employee); + } - public function getLang() - { - return $this->_id_lang; - } -} \ No newline at end of file + public function getLang() + { + return $this->_id_lang; + } +} diff --git a/classes/module/ModuleGridEngine.php b/classes/module/ModuleGridEngine.php index 2cc5872e..a3febaaf 100644 --- a/classes/module/ModuleGridEngine.php +++ b/classes/module/ModuleGridEngine.php @@ -26,23 +26,24 @@ abstract class ModuleGridEngineCore extends Module { - protected $_type; + protected $_type; - public function __construct($type) - { - $this->_type = $type; - } + public function __construct($type) + { + $this->_type = $type; + } - public function install() - { - if (!parent::install()) - return false; - return Configuration::updateValue('PS_STATS_GRID_RENDER', $this->name); - } + public function install() + { + if (!parent::install()) { + return false; + } + return Configuration::updateValue('PS_STATS_GRID_RENDER', $this->name); + } - public static function getGridEngines() - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getGridEngines() + { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT m.`name` FROM `'._DB_PREFIX_.'module` m LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_module` = m.`id_module` @@ -50,22 +51,22 @@ abstract class ModuleGridEngineCore extends Module WHERE h.`name` = \'displayAdminStatsGridEngine\' '); - $array_engines = array(); - foreach ($result as $module) - { - $instance = Module::getInstanceByName($module['name']); - if (!$instance) - continue; - $array_engines[$module['name']] = array($instance->displayName, $instance->description); - } + $array_engines = array(); + foreach ($result as $module) { + $instance = Module::getInstanceByName($module['name']); + if (!$instance) { + continue; + } + $array_engines[$module['name']] = array($instance->displayName, $instance->description); + } - return $array_engines; - } + return $array_engines; + } - abstract public function setValues($values); - abstract public function setTitle($title); - abstract public function setSize($width, $height); - abstract public function setTotalCount($total_count); - abstract public function setLimit($start, $limit); - abstract public function render(); -} \ No newline at end of file + abstract public function setValues($values); + abstract public function setTitle($title); + abstract public function setSize($width, $height); + abstract public function setTotalCount($total_count); + abstract public function setLimit($start, $limit); + abstract public function render(); +} diff --git a/classes/module/index.php b/classes/module/index.php index c642967a..91fa49fb 100644 --- a/classes/module/index.php +++ b/classes/module/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/classes/order/Order.php b/classes/order/Order.php index 33761fb5..a4713367 100644 --- a/classes/order/Order.php +++ b/classes/order/Order.php @@ -26,492 +26,499 @@ class OrderCore extends ObjectModel { - const ROUND_ITEM = 1; - const ROUND_LINE = 2; - const ROUND_TOTAL = 3; + const ROUND_ITEM = 1; + const ROUND_LINE = 2; + const ROUND_TOTAL = 3; - /** @var int Delivery address id */ - public $id_address_delivery; + /** @var int Delivery address id */ + public $id_address_delivery; - /** @var int Invoice address id */ - public $id_address_invoice; + /** @var int Invoice address id */ + public $id_address_invoice; - public $id_shop_group; + public $id_shop_group; - public $id_shop; + public $id_shop; - /** @var int Cart id */ - public $id_cart; + /** @var int Cart id */ + public $id_cart; - /** @var int Currency id */ - public $id_currency; + /** @var int Currency id */ + public $id_currency; - /** @var int Language id */ - public $id_lang; + /** @var int Language id */ + public $id_lang; - /** @var int Customer id */ - public $id_customer; + /** @var int Customer id */ + public $id_customer; - /** @var int Carrier id */ - public $id_carrier; + /** @var int Carrier id */ + public $id_carrier; - /** @var int Order Status id */ - public $current_state; + /** @var int Order Status id */ + public $current_state; - /** @var string Secure key */ - public $secure_key; + /** @var string Secure key */ + public $secure_key; - /** @var string Payment method */ - public $payment; + /** @var string Payment method */ + public $payment; - /** @var string Payment module */ - public $module; + /** @var string Payment module */ + public $module; - /** @var float Currency exchange rate */ - public $conversion_rate; + /** @var float Currency exchange rate */ + public $conversion_rate; - /** @var bool Customer is ok for a recyclable package */ - public $recyclable = 1; + /** @var bool Customer is ok for a recyclable package */ + public $recyclable = 1; - /** @var bool True if the customer wants a gift wrapping */ - public $gift = 0; + /** @var bool True if the customer wants a gift wrapping */ + public $gift = 0; - /** @var string Gift message if specified */ - public $gift_message; + /** @var string Gift message if specified */ + public $gift_message; - /** @var bool Mobile Theme */ - public $mobile_theme; + /** @var bool Mobile Theme */ + public $mobile_theme; - /** - * @var string Shipping number - * @deprecated 1.5.0.4 - * @see OrderCarrier->tracking_number - */ - public $shipping_number; + /** + * @var string Shipping number + * @deprecated 1.5.0.4 + * @see OrderCarrier->tracking_number + */ + public $shipping_number; - /** @var float Discounts total */ - public $total_discounts; + /** @var float Discounts total */ + public $total_discounts; - public $total_discounts_tax_incl; - public $total_discounts_tax_excl; + public $total_discounts_tax_incl; + public $total_discounts_tax_excl; - /** @var float Total to pay */ - public $total_paid; + /** @var float Total to pay */ + public $total_paid; - /** @var float Total to pay tax included */ - public $total_paid_tax_incl; + /** @var float Total to pay tax included */ + public $total_paid_tax_incl; - /** @var float Total to pay tax excluded */ - public $total_paid_tax_excl; + /** @var float Total to pay tax excluded */ + public $total_paid_tax_excl; - /** @var float Total really paid @deprecated 1.5.0.1 */ - public $total_paid_real; + /** @var float Total really paid @deprecated 1.5.0.1 */ + public $total_paid_real; - /** @var float Products total */ - public $total_products; + /** @var float Products total */ + public $total_products; - /** @var float Products total tax included */ - public $total_products_wt; - - /** @var float Shipping total */ - public $total_shipping; - - /** @var float Shipping total tax included */ - public $total_shipping_tax_incl; - - /** @var float Shipping total tax excluded */ - public $total_shipping_tax_excl; - - /** @var float Shipping tax rate */ - public $carrier_tax_rate; - - /** @var float Wrapping total */ - public $total_wrapping; - - /** @var float Wrapping total tax included */ - public $total_wrapping_tax_incl; - - /** @var float Wrapping total tax excluded */ - public $total_wrapping_tax_excl; - - /** @var int Invoice number */ - public $invoice_number; - - /** @var int Delivery number */ - public $delivery_number; - - /** @var string Invoice creation date */ - public $invoice_date; - - /** @var string Delivery creation date */ - public $delivery_date; - - /** @var bool Order validity: current order status is logable (usually paid and not canceled) */ - public $valid; - - /** @var string Object creation date */ - public $date_add; - - /** @var string Object last modification date */ - public $date_upd; - - /** - * @var string Order reference, this reference is not unique, but unique for a payment - */ - public $reference; - - /** - * @var int Round mode method used for this order - */ - public $round_mode; - - /** - * @var int Round type method used for this order - */ - public $round_type; - - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'orders', - 'primary' => 'id_order', - 'fields' => array( - 'id_address_delivery' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_address_invoice' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_cart' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_shop_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_carrier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'current_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'secure_key' => array('type' => self::TYPE_STRING, 'validate' => 'isMd5'), - 'payment' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true), - 'module' => array('type' => self::TYPE_STRING, 'validate' => 'isModuleName', 'required' => true), - 'recyclable' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'gift' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'gift_message' => array('type' => self::TYPE_STRING, 'validate' => 'isMessage'), - 'mobile_theme' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'total_discounts' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_discounts_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_discounts_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_paid' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'total_paid_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_paid_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_paid_real' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'total_products' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'total_products_wt' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'total_shipping' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_shipping_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_shipping_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'carrier_tax_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'total_wrapping' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_wrapping_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_wrapping_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'round_mode' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'round_type' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'shipping_number' => array('type' => self::TYPE_STRING, 'validate' => 'isTrackingNumber'), - 'conversion_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), - 'invoice_number' => array('type' => self::TYPE_INT), - 'delivery_number' => array('type' => self::TYPE_INT), - 'invoice_date' => array('type' => self::TYPE_DATE), - 'delivery_date' => array('type' => self::TYPE_DATE), - 'valid' => array('type' => self::TYPE_BOOL), - 'reference' => array('type' => self::TYPE_STRING), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); - - protected $webserviceParameters = array( - 'objectMethods' => array('add' => 'addWs'), - 'objectNodeName' => 'order', - 'objectsNodeName' => 'orders', - 'fields' => array( - 'id_address_delivery' => array('xlink_resource'=> 'addresses'), - 'id_address_invoice' => array('xlink_resource'=> 'addresses'), - 'id_cart' => array('xlink_resource'=> 'carts'), - 'id_currency' => array('xlink_resource'=> 'currencies'), - 'id_lang' => array('xlink_resource'=> 'languages'), - 'id_customer' => array('xlink_resource'=> 'customers'), - 'id_carrier' => array('xlink_resource'=> 'carriers'), - 'current_state' => array( - 'xlink_resource'=> 'order_states', - 'getter' => 'getWsCurrentState', - 'setter' => 'setWsCurrentState' - ), - 'module' => array('required' => true), - 'invoice_number' => array(), - 'invoice_date' => array(), - 'delivery_number' => array(), - 'delivery_date' => array(), - 'valid' => array(), - 'date_add' => array(), - 'date_upd' => array(), - 'shipping_number' => array( - 'getter' => 'getWsShippingNumber', - 'setter' => 'setWsShippingNumber' - ), - ), - 'associations' => array( - 'order_rows' => array('resource' => 'order_row', 'setter' => false, 'virtual_entity' => true, - 'fields' => array( - 'id' => array(), - 'product_id' => array('required' => true), - 'product_attribute_id' => array('required' => true), - 'product_quantity' => array('required' => true), - 'product_name' => array('setter' => false), - 'product_reference' => array('setter' => false), - 'product_ean13' => array('setter' => false), - 'product_upc' => array('setter' => false), - 'product_price' => array('setter' => false), - 'unit_price_tax_incl' => array('setter' => false), - 'unit_price_tax_excl' => array('setter' => false), - )), - ), - - ); - - protected $_taxCalculationMethod = PS_TAX_EXC; - - protected static $_historyCache = array(); - - public function __construct($id = null, $id_lang = null) - { - parent::__construct($id, $id_lang); - - $is_admin = (is_object(Context::getContext()->controller) && Context::getContext()->controller->controller_type == 'admin'); - if ($this->id_customer && !$is_admin) - { - $customer = new Customer((int)$this->id_customer); - $this->_taxCalculationMethod = Group::getPriceDisplayMethod((int)$customer->id_default_group); - } - else - $this->_taxCalculationMethod = Group::getDefaultPriceDisplayMethod(); - } - - /** - * @see ObjectModel::getFields() - * @return array - */ - public function getFields() - { - if (!$this->id_lang) - $this->id_lang = Configuration::get('PS_LANG_DEFAULT', null, null, $this->id_shop); - - return parent::getFields(); - } - - public function add($autodate = true, $null_values = true) - { - if (parent::add($autodate, $null_values)) - return SpecificPrice::deleteByIdCart($this->id_cart); - return false; - } - - public function getTaxCalculationMethod() - { - return (int)$this->_taxCalculationMethod; - } - - /** - * Does NOT delete a product but "cancel" it (which means return/refund/delete it depending of the case) - * - * @param $order - * @param OrderDetail $order_detail - * @param int $quantity - * @return bool - * @throws PrestaShopException - */ - public function deleteProduct($order, $order_detail, $quantity) - { - if (!(int)$this->getCurrentState() || !validate::isLoadedObject($order_detail)) - return false; - - if ($this->hasBeenDelivered()) - { - if (!Configuration::get('PS_ORDER_RETURN', null, null, $this->id_shop)) - throw new PrestaShopException('PS_ORDER_RETURN is not defined in table configuration'); - $order_detail->product_quantity_return += (int)$quantity; - return $order_detail->update(); - } - elseif ($this->hasBeenPaid()) - { - $order_detail->product_quantity_refunded += (int)$quantity; - return $order_detail->update(); - } - return $this->_deleteProduct($order_detail, (int)$quantity); - } - - /** - * This function return products of the orders - * It's similar to Order::getProducts but with similar outputs of Cart::getProducts - * - * @return array - */ - public function getCartProducts() - { - $product_id_list = array(); - $products = $this->getProducts(); - foreach ($products as &$product) - { - $product['id_product_attribute'] = $product['product_attribute_id']; - $product['cart_quantity'] = $product['product_quantity']; - $product_id_list[] = $this->id_address_delivery.'_' - .$product['product_id'].'_' - .$product['product_attribute_id'].'_' - .(isset($product['id_customization']) ? $product['id_customization'] : '0'); - } - unset($product); - - $product_list = array(); - foreach ($products as $product) - { - $key = $this->id_address_delivery.'_' - .$product['id_product'].'_' - .(isset($product['id_product_attribute']) ? $product['id_product_attribute'] : '0').'_' - .(isset($product['id_customization']) ? $product['id_customization'] : '0'); - - if (in_array($key, $product_id_list)) - $product_list[] = $product; - } - return $product_list; - } - - /** - * DOES delete the product - * - * @param OrderDetail $order_detail - * @param int $quantity - * @return bool - * @throws PrestaShopException - */ - protected function _deleteProduct($order_detail, $quantity) - { - $product_price_tax_excl = $order_detail->unit_price_tax_excl * $quantity; - $product_price_tax_incl = $order_detail->unit_price_tax_incl * $quantity; - - /* Update cart */ - $cart = new Cart($this->id_cart); - $cart->updateQty($quantity, $order_detail->product_id, $order_detail->product_attribute_id, false, 'down'); // customization are deleted in deleteCustomization - $cart->update(); - - /* Update order */ - $shipping_diff_tax_incl = $this->total_shipping_tax_incl - $cart->getPackageShippingCost($this->id_carrier, true, null, $this->getCartProducts()); - $shipping_diff_tax_excl = $this->total_shipping_tax_excl - $cart->getPackageShippingCost($this->id_carrier, false, null, $this->getCartProducts()); - $this->total_shipping -= $shipping_diff_tax_incl; - $this->total_shipping_tax_excl -= $shipping_diff_tax_excl; - $this->total_shipping_tax_incl -= $shipping_diff_tax_incl; - $this->total_products -= $product_price_tax_excl; - $this->total_products_wt -= $product_price_tax_incl; - $this->total_paid -= $product_price_tax_incl + $shipping_diff_tax_incl; - $this->total_paid_tax_incl -= $product_price_tax_incl + $shipping_diff_tax_incl; - $this->total_paid_tax_excl -= $product_price_tax_excl + $shipping_diff_tax_excl; - $this->total_paid_real -= $product_price_tax_incl + $shipping_diff_tax_incl; - - $fields = array( - 'total_shipping', - 'total_shipping_tax_excl', - 'total_shipping_tax_incl', - 'total_products', - 'total_products_wt', - 'total_paid', - 'total_paid_tax_incl', - 'total_paid_tax_excl', - 'total_paid_real' - ); - - /* Prevent from floating precision issues */ - foreach ($fields as $field) - if ($this->{$field} < 0) - $this->{$field} = 0; - - /* Prevent from floating precision issues */ - foreach ($fields as $field) - $this->{$field} = number_format($this->{$field}, _PS_PRICE_COMPUTE_PRECISION_, '.', ''); - - /* Update order detail */ - $order_detail->product_quantity -= (int)$quantity; - if ($order_detail->product_quantity == 0) - { - if (!$order_detail->delete()) - return false; - if (count($this->getProductsDetail()) == 0) - { - $history = new OrderHistory(); - $history->id_order = (int)$this->id; - $history->changeIdOrderState(Configuration::get('PS_OS_CANCELED'), $this); - if (!$history->addWithemail()) - return false; - } - return $this->update(); - } - else - { - $order_detail->total_price_tax_incl -= $product_price_tax_incl; - $order_detail->total_price_tax_excl -= $product_price_tax_excl; - $order_detail->total_shipping_price_tax_incl -= $shipping_diff_tax_incl; - $order_detail->total_shipping_price_tax_excl -= $shipping_diff_tax_excl; - } - return $order_detail->update() && $this->update(); - } - - public function deleteCustomization($id_customization, $quantity, $order_detail) - { - if (!(int)$this->getCurrentState()) - return false; - - if ($this->hasBeenDelivered()) - return Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'customization` SET `quantity_returned` = `quantity_returned` + '.(int)$quantity.' WHERE `id_customization` = '.(int)$id_customization.' AND `id_cart` = '.(int)$this->id_cart.' AND `id_product` = '.(int)$order_detail->product_id); - elseif ($this->hasBeenPaid()) - return Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'customization` SET `quantity_refunded` = `quantity_refunded` + '.(int)$quantity.' WHERE `id_customization` = '.(int)$id_customization.' AND `id_cart` = '.(int)$this->id_cart.' AND `id_product` = '.(int)$order_detail->product_id); - if (!Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'customization` SET `quantity` = `quantity` - '.(int)$quantity.' WHERE `id_customization` = '.(int)$id_customization.' AND `id_cart` = '.(int)$this->id_cart.' AND `id_product` = '.(int)$order_detail->product_id)) - return false; - if (!Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'customization` WHERE `quantity` = 0')) - return false; - return $this->_deleteProduct($order_detail, (int)$quantity); - } - - /** - * Get order history - * - * @param int $id_lang Language id - * @param int $id_order_state Filter a specific order status - * @param int $no_hidden Filter no hidden status - * @param int $filters Flag to use specific field filter - * - * @return array History entries ordered by date DESC - */ - public function getHistory($id_lang, $id_order_state = false, $no_hidden = false, $filters = 0) - { - if (!$id_order_state) - $id_order_state = 0; - - $logable = false; - $delivery = false; - $paid = false; - $shipped = false; - if ($filters > 0) - { - if ($filters & OrderState::FLAG_NO_HIDDEN) - $no_hidden = true; - if ($filters & OrderState::FLAG_DELIVERY) - $delivery = true; - if ($filters & OrderState::FLAG_LOGABLE) - $logable = true; - if ($filters & OrderState::FLAG_PAID) - $paid = true; - if ($filters & OrderState::FLAG_SHIPPED) - $shipped = true; - } - - if (!isset(self::$_historyCache[$this->id.'_'.$id_order_state.'_'.$filters]) || $no_hidden) - { - $id_lang = $id_lang ? (int)$id_lang : 'o.`id_lang`'; - $result = Db::getInstance()->executeS(' + /** @var float Products total tax included */ + public $total_products_wt; + + /** @var float Shipping total */ + public $total_shipping; + + /** @var float Shipping total tax included */ + public $total_shipping_tax_incl; + + /** @var float Shipping total tax excluded */ + public $total_shipping_tax_excl; + + /** @var float Shipping tax rate */ + public $carrier_tax_rate; + + /** @var float Wrapping total */ + public $total_wrapping; + + /** @var float Wrapping total tax included */ + public $total_wrapping_tax_incl; + + /** @var float Wrapping total tax excluded */ + public $total_wrapping_tax_excl; + + /** @var int Invoice number */ + public $invoice_number; + + /** @var int Delivery number */ + public $delivery_number; + + /** @var string Invoice creation date */ + public $invoice_date; + + /** @var string Delivery creation date */ + public $delivery_date; + + /** @var bool Order validity: current order status is logable (usually paid and not canceled) */ + public $valid; + + /** @var string Object creation date */ + public $date_add; + + /** @var string Object last modification date */ + public $date_upd; + + /** + * @var string Order reference, this reference is not unique, but unique for a payment + */ + public $reference; + + /** + * @var int Round mode method used for this order + */ + public $round_mode; + + /** + * @var int Round type method used for this order + */ + public $round_type; + + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'orders', + 'primary' => 'id_order', + 'fields' => array( + 'id_address_delivery' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_address_invoice' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_cart' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_shop_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_carrier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'current_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'secure_key' => array('type' => self::TYPE_STRING, 'validate' => 'isMd5'), + 'payment' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true), + 'module' => array('type' => self::TYPE_STRING, 'validate' => 'isModuleName', 'required' => true), + 'recyclable' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'gift' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'gift_message' => array('type' => self::TYPE_STRING, 'validate' => 'isMessage'), + 'mobile_theme' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'total_discounts' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_discounts_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_discounts_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_paid' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'total_paid_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_paid_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_paid_real' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'total_products' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'total_products_wt' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'total_shipping' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_shipping_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_shipping_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'carrier_tax_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'total_wrapping' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_wrapping_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_wrapping_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'round_mode' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'round_type' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'shipping_number' => array('type' => self::TYPE_STRING, 'validate' => 'isTrackingNumber'), + 'conversion_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), + 'invoice_number' => array('type' => self::TYPE_INT), + 'delivery_number' => array('type' => self::TYPE_INT), + 'invoice_date' => array('type' => self::TYPE_DATE), + 'delivery_date' => array('type' => self::TYPE_DATE), + 'valid' => array('type' => self::TYPE_BOOL), + 'reference' => array('type' => self::TYPE_STRING), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); + + protected $webserviceParameters = array( + 'objectMethods' => array('add' => 'addWs'), + 'objectNodeName' => 'order', + 'objectsNodeName' => 'orders', + 'fields' => array( + 'id_address_delivery' => array('xlink_resource'=> 'addresses'), + 'id_address_invoice' => array('xlink_resource'=> 'addresses'), + 'id_cart' => array('xlink_resource'=> 'carts'), + 'id_currency' => array('xlink_resource'=> 'currencies'), + 'id_lang' => array('xlink_resource'=> 'languages'), + 'id_customer' => array('xlink_resource'=> 'customers'), + 'id_carrier' => array('xlink_resource'=> 'carriers'), + 'current_state' => array( + 'xlink_resource'=> 'order_states', + 'setter' => 'setWsCurrentState' + ), + 'module' => array('required' => true), + 'invoice_number' => array(), + 'invoice_date' => array(), + 'delivery_number' => array(), + 'delivery_date' => array(), + 'valid' => array(), + 'date_add' => array(), + 'date_upd' => array(), + 'shipping_number' => array( + 'getter' => 'getWsShippingNumber', + 'setter' => 'setWsShippingNumber' + ), + ), + 'associations' => array( + 'order_rows' => array('resource' => 'order_row', 'setter' => false, 'virtual_entity' => true, + 'fields' => array( + 'id' => array(), + 'product_id' => array('required' => true), + 'product_attribute_id' => array('required' => true), + 'product_quantity' => array('required' => true), + 'product_name' => array('setter' => false), + 'product_reference' => array('setter' => false), + 'product_ean13' => array('setter' => false), + 'product_upc' => array('setter' => false), + 'product_price' => array('setter' => false), + 'unit_price_tax_incl' => array('setter' => false), + 'unit_price_tax_excl' => array('setter' => false), + )), + ), + + ); + + protected $_taxCalculationMethod = PS_TAX_EXC; + + protected static $_historyCache = array(); + + public function __construct($id = null, $id_lang = null) + { + parent::__construct($id, $id_lang); + + $is_admin = (is_object(Context::getContext()->controller) && Context::getContext()->controller->controller_type == 'admin'); + if ($this->id_customer && !$is_admin) { + $customer = new Customer((int)$this->id_customer); + $this->_taxCalculationMethod = Group::getPriceDisplayMethod((int)$customer->id_default_group); + } else { + $this->_taxCalculationMethod = Group::getDefaultPriceDisplayMethod(); + } + } + + /** + * @see ObjectModel::getFields() + * @return array + */ + public function getFields() + { + if (!$this->id_lang) { + $this->id_lang = Configuration::get('PS_LANG_DEFAULT', null, null, $this->id_shop); + } + + return parent::getFields(); + } + + public function add($autodate = true, $null_values = true) + { + if (parent::add($autodate, $null_values)) { + return SpecificPrice::deleteByIdCart($this->id_cart); + } + return false; + } + + public function getTaxCalculationMethod() + { + return (int)$this->_taxCalculationMethod; + } + + /** + * Does NOT delete a product but "cancel" it (which means return/refund/delete it depending of the case) + * + * @param $order + * @param OrderDetail $order_detail + * @param int $quantity + * @return bool + * @throws PrestaShopException + */ + public function deleteProduct($order, $order_detail, $quantity) + { + if (!(int)$this->getCurrentState() || !validate::isLoadedObject($order_detail)) { + return false; + } + + if ($this->hasBeenDelivered()) { + if (!Configuration::get('PS_ORDER_RETURN', null, null, $this->id_shop)) { + throw new PrestaShopException('PS_ORDER_RETURN is not defined in table configuration'); + } + $order_detail->product_quantity_return += (int)$quantity; + return $order_detail->update(); + } elseif ($this->hasBeenPaid()) { + $order_detail->product_quantity_refunded += (int)$quantity; + return $order_detail->update(); + } + return $this->_deleteProduct($order_detail, (int)$quantity); + } + + /** + * This function return products of the orders + * It's similar to Order::getProducts but with similar outputs of Cart::getProducts + * + * @return array + */ + public function getCartProducts() + { + $product_id_list = array(); + $products = $this->getProducts(); + foreach ($products as &$product) { + $product['id_product_attribute'] = $product['product_attribute_id']; + $product['cart_quantity'] = $product['product_quantity']; + $product_id_list[] = $this->id_address_delivery.'_' + .$product['product_id'].'_' + .$product['product_attribute_id'].'_' + .(isset($product['id_customization']) ? $product['id_customization'] : '0'); + } + unset($product); + + $product_list = array(); + foreach ($products as $product) { + $key = $this->id_address_delivery.'_' + .$product['id_product'].'_' + .(isset($product['id_product_attribute']) ? $product['id_product_attribute'] : '0').'_' + .(isset($product['id_customization']) ? $product['id_customization'] : '0'); + + if (in_array($key, $product_id_list)) { + $product_list[] = $product; + } + } + return $product_list; + } + + /** + * DOES delete the product + * + * @param OrderDetail $order_detail + * @param int $quantity + * @return bool + * @throws PrestaShopException + */ + protected function _deleteProduct($order_detail, $quantity) + { + $product_price_tax_excl = $order_detail->unit_price_tax_excl * $quantity; + $product_price_tax_incl = $order_detail->unit_price_tax_incl * $quantity; + + /* Update cart */ + $cart = new Cart($this->id_cart); + $cart->updateQty($quantity, $order_detail->product_id, $order_detail->product_attribute_id, false, 'down'); // customization are deleted in deleteCustomization + $cart->update(); + + /* Update order */ + $shipping_diff_tax_incl = $this->total_shipping_tax_incl - $cart->getPackageShippingCost($this->id_carrier, true, null, $this->getCartProducts()); + $shipping_diff_tax_excl = $this->total_shipping_tax_excl - $cart->getPackageShippingCost($this->id_carrier, false, null, $this->getCartProducts()); + $this->total_shipping -= $shipping_diff_tax_incl; + $this->total_shipping_tax_excl -= $shipping_diff_tax_excl; + $this->total_shipping_tax_incl -= $shipping_diff_tax_incl; + $this->total_products -= $product_price_tax_excl; + $this->total_products_wt -= $product_price_tax_incl; + $this->total_paid -= $product_price_tax_incl + $shipping_diff_tax_incl; + $this->total_paid_tax_incl -= $product_price_tax_incl + $shipping_diff_tax_incl; + $this->total_paid_tax_excl -= $product_price_tax_excl + $shipping_diff_tax_excl; + $this->total_paid_real -= $product_price_tax_incl + $shipping_diff_tax_incl; + + $fields = array( + 'total_shipping', + 'total_shipping_tax_excl', + 'total_shipping_tax_incl', + 'total_products', + 'total_products_wt', + 'total_paid', + 'total_paid_tax_incl', + 'total_paid_tax_excl', + 'total_paid_real' + ); + + /* Prevent from floating precision issues */ + foreach ($fields as $field) { + if ($this->{$field} < 0) { + $this->{$field} = 0; + } + } + + /* Prevent from floating precision issues */ + foreach ($fields as $field) { + $this->{$field} = number_format($this->{$field}, _PS_PRICE_COMPUTE_PRECISION_, '.', ''); + } + + /* Update order detail */ + $order_detail->product_quantity -= (int)$quantity; + if ($order_detail->product_quantity == 0) { + if (!$order_detail->delete()) { + return false; + } + if (count($this->getProductsDetail()) == 0) { + $history = new OrderHistory(); + $history->id_order = (int)$this->id; + $history->changeIdOrderState(Configuration::get('PS_OS_CANCELED'), $this); + if (!$history->addWithemail()) { + return false; + } + } + return $this->update(); + } else { + $order_detail->total_price_tax_incl -= $product_price_tax_incl; + $order_detail->total_price_tax_excl -= $product_price_tax_excl; + $order_detail->total_shipping_price_tax_incl -= $shipping_diff_tax_incl; + $order_detail->total_shipping_price_tax_excl -= $shipping_diff_tax_excl; + } + return $order_detail->update() && $this->update(); + } + + public function deleteCustomization($id_customization, $quantity, $order_detail) + { + if (!(int)$this->getCurrentState()) { + return false; + } + + if ($this->hasBeenDelivered()) { + return Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'customization` SET `quantity_returned` = `quantity_returned` + '.(int)$quantity.' WHERE `id_customization` = '.(int)$id_customization.' AND `id_cart` = '.(int)$this->id_cart.' AND `id_product` = '.(int)$order_detail->product_id); + } elseif ($this->hasBeenPaid()) { + return Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'customization` SET `quantity_refunded` = `quantity_refunded` + '.(int)$quantity.' WHERE `id_customization` = '.(int)$id_customization.' AND `id_cart` = '.(int)$this->id_cart.' AND `id_product` = '.(int)$order_detail->product_id); + } + if (!Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'customization` SET `quantity` = `quantity` - '.(int)$quantity.' WHERE `id_customization` = '.(int)$id_customization.' AND `id_cart` = '.(int)$this->id_cart.' AND `id_product` = '.(int)$order_detail->product_id)) { + return false; + } + if (!Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'customization` WHERE `quantity` = 0')) { + return false; + } + return $this->_deleteProduct($order_detail, (int)$quantity); + } + + /** + * Get order history + * + * @param int $id_lang Language id + * @param int $id_order_state Filter a specific order status + * @param int $no_hidden Filter no hidden status + * @param int $filters Flag to use specific field filter + * + * @return array History entries ordered by date DESC + */ + public function getHistory($id_lang, $id_order_state = false, $no_hidden = false, $filters = 0) + { + if (!$id_order_state) { + $id_order_state = 0; + } + + $logable = false; + $delivery = false; + $paid = false; + $shipped = false; + if ($filters > 0) { + if ($filters & OrderState::FLAG_NO_HIDDEN) { + $no_hidden = true; + } + if ($filters & OrderState::FLAG_DELIVERY) { + $delivery = true; + } + if ($filters & OrderState::FLAG_LOGABLE) { + $logable = true; + } + if ($filters & OrderState::FLAG_PAID) { + $paid = true; + } + if ($filters & OrderState::FLAG_SHIPPED) { + $shipped = true; + } + } + + if (!isset(self::$_historyCache[$this->id.'_'.$id_order_state.'_'.$filters]) || $no_hidden) { + $id_lang = $id_lang ? (int)$id_lang : 'o.`id_lang`'; + $result = Db::getInstance()->executeS(' SELECT os.*, oh.*, e.`firstname` as employee_firstname, e.`lastname` as employee_lastname, osl.`name` as ostate_name FROM `'._DB_PREFIX_.'orders` o LEFT JOIN `'._DB_PREFIX_.'order_history` oh ON o.`id_order` = oh.`id_order` @@ -526,117 +533,121 @@ class OrderCore extends ObjectModel '.($shipped ? ' AND os.shipped = 1' : '').' '.((int)$id_order_state ? ' AND oh.`id_order_state` = '.(int)$id_order_state : '').' ORDER BY oh.date_add DESC, oh.id_order_history DESC'); - if ($no_hidden) - return $result; - self::$_historyCache[$this->id.'_'.$id_order_state.'_'.$filters] = $result; - } - return self::$_historyCache[$this->id.'_'.$id_order_state.'_'.$filters]; - } + if ($no_hidden) { + return $result; + } + self::$_historyCache[$this->id.'_'.$id_order_state.'_'.$filters] = $result; + } + return self::$_historyCache[$this->id.'_'.$id_order_state.'_'.$filters]; + } - public function getProductsDetail() - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public function getProductsDetail() + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'order_detail` od LEFT JOIN `'._DB_PREFIX_.'product` p ON (p.id_product = od.product_id) LEFT JOIN `'._DB_PREFIX_.'product_shop` ps ON (ps.id_product = p.id_product AND ps.id_shop = od.id_shop) WHERE od.`id_order` = '.(int)$this->id); - } + } - public function getFirstMessage() - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public function getFirstMessage() + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `message` FROM `'._DB_PREFIX_.'message` WHERE `id_order` = '.(int)$this->id.' ORDER BY `id_message` '); - } + } - /** - * Marked as deprecated but should not throw any "deprecated" message - * This function is used in order to keep front office backward compatibility 14 -> 1.5 - * (Order History) - * - * @deprecated - */ - public function setProductPrices(&$row) - { - $tax_calculator = OrderDetail::getTaxCalculatorStatic((int)$row['id_order_detail']); - $row['tax_calculator'] = $tax_calculator; - $row['tax_rate'] = $tax_calculator->getTotalRate(); + /** + * Marked as deprecated but should not throw any "deprecated" message + * This function is used in order to keep front office backward compatibility 14 -> 1.5 + * (Order History) + * + * @deprecated + */ + public function setProductPrices(&$row) + { + $tax_calculator = OrderDetail::getTaxCalculatorStatic((int)$row['id_order_detail']); + $row['tax_calculator'] = $tax_calculator; + $row['tax_rate'] = $tax_calculator->getTotalRate(); - $row['product_price'] = Tools::ps_round($row['unit_price_tax_excl'], 2); - $row['product_price_wt'] = Tools::ps_round($row['unit_price_tax_incl'], 2); + $row['product_price'] = Tools::ps_round($row['unit_price_tax_excl'], 2); + $row['product_price_wt'] = Tools::ps_round($row['unit_price_tax_incl'], 2); - $group_reduction = 1; - if ($row['group_reduction'] > 0) - $group_reduction = 1 - $row['group_reduction'] / 100; + $group_reduction = 1; + if ($row['group_reduction'] > 0) { + $group_reduction = 1 - $row['group_reduction'] / 100; + } - $row['product_price_wt_but_ecotax'] = $row['product_price_wt'] - $row['ecotax']; + $row['product_price_wt_but_ecotax'] = $row['product_price_wt'] - $row['ecotax']; - $row['total_wt'] = $row['total_price_tax_incl']; - $row['total_price'] = $row['total_price_tax_excl']; - } + $row['total_wt'] = $row['total_price_tax_incl']; + $row['total_price'] = $row['total_price_tax_excl']; + } - /** - * Get order products - * - * @return array Products with price, quantity (with taxe and without) - */ - public function getProducts($products = false, $selected_products = false, $selected_qty = false) - { - if (!$products) - $products = $this->getProductsDetail(); + /** + * Get order products + * + * @return array Products with price, quantity (with taxe and without) + */ + public function getProducts($products = false, $selected_products = false, $selected_qty = false) + { + if (!$products) { + $products = $this->getProductsDetail(); + } - $customized_datas = Product::getAllCustomizedDatas($this->id_cart); + $customized_datas = Product::getAllCustomizedDatas($this->id_cart); - $result_array = array(); - foreach ($products as $row) - { - // Change qty if selected - if ($selected_qty) - { - $row['product_quantity'] = 0; - foreach ($selected_products as $key => $id_product) - if ($row['id_order_detail'] == $id_product) - $row['product_quantity'] = (int)$selected_qty[$key]; - if (!$row['product_quantity']) - continue; - } + $result_array = array(); + foreach ($products as $row) { + // Change qty if selected + if ($selected_qty) { + $row['product_quantity'] = 0; + foreach ($selected_products as $key => $id_product) { + if ($row['id_order_detail'] == $id_product) { + $row['product_quantity'] = (int)$selected_qty[$key]; + } + } + if (!$row['product_quantity']) { + continue; + } + } - $this->setProductImageInformations($row); - $this->setProductCurrentStock($row); + $this->setProductImageInformations($row); + $this->setProductCurrentStock($row); - // Backward compatibility 1.4 -> 1.5 - $this->setProductPrices($row); + // Backward compatibility 1.4 -> 1.5 + $this->setProductPrices($row); - $this->setProductCustomizedDatas($row, $customized_datas); + $this->setProductCustomizedDatas($row, $customized_datas); - // Add information for virtual product - if ($row['download_hash'] && !empty($row['download_hash'])) - { - $row['filename'] = ProductDownload::getFilenameFromIdProduct((int)$row['product_id']); - // Get the display filename - $row['display_filename'] = ProductDownload::getFilenameFromFilename($row['filename']); - } + // Add information for virtual product + if ($row['download_hash'] && !empty($row['download_hash'])) { + $row['filename'] = ProductDownload::getFilenameFromIdProduct((int)$row['product_id']); + // Get the display filename + $row['display_filename'] = ProductDownload::getFilenameFromFilename($row['filename']); + } - $row['id_address_delivery'] = $this->id_address_delivery; + $row['id_address_delivery'] = $this->id_address_delivery; - /* Stock product */ - $result_array[(int)$row['id_order_detail']] = $row; - } + /* Stock product */ + $result_array[(int)$row['id_order_detail']] = $row; + } - if ($customized_datas) - Product::addCustomizationPrice($result_array, $customized_datas); + if ($customized_datas) { + Product::addCustomizationPrice($result_array, $customized_datas); + } - return $result_array; - } + return $result_array; + } - public static function getIdOrderProduct($id_customer, $id_product) - { - return (int)Db::getInstance()->getValue(' + public static function getIdOrderProduct($id_customer, $id_product) + { + return (int)Db::getInstance()->getValue(' SELECT o.id_order FROM '._DB_PREFIX_.'orders o LEFT JOIN '._DB_PREFIX_.'order_detail od @@ -645,181 +656,185 @@ class OrderCore extends ObjectModel AND od.product_id = '.(int)$id_product.' ORDER BY o.date_add DESC '); - } + } - protected function setProductCustomizedDatas(&$product, $customized_datas) - { - $product['customizedDatas'] = null; - if (isset($customized_datas[$product['product_id']][$product['product_attribute_id']])) - $product['customizedDatas'] = $customized_datas[$product['product_id']][$product['product_attribute_id']]; - else - $product['customizationQuantityTotal'] = 0; - } + protected function setProductCustomizedDatas(&$product, $customized_datas) + { + $product['customizedDatas'] = null; + if (isset($customized_datas[$product['product_id']][$product['product_attribute_id']])) { + $product['customizedDatas'] = $customized_datas[$product['product_id']][$product['product_attribute_id']]; + } else { + $product['customizationQuantityTotal'] = 0; + } + } - /** - * - * This method allow to add stock information on a product detail - * - * If advanced stock management is active, get physical stock of this product in the warehouse associated to the ptoduct for the current order - * Else get the available quantity of the product in fucntion of the shop associated to the order - * - * @param array &$product - */ - protected function setProductCurrentStock(&$product) - { - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') - && (int)$product['advanced_stock_management'] == 1 - && (int)$product['id_warehouse'] > 0) - $product['current_stock'] = StockManagerFactory::getManager()->getProductPhysicalQuantities($product['product_id'], $product['product_attribute_id'], (int)$product['id_warehouse'], true); - else - $product['current_stock'] = StockAvailable::getQuantityAvailableByProduct($product['product_id'], $product['product_attribute_id'], (int)$this->id_shop); - } + /** + * + * This method allow to add stock information on a product detail + * + * If advanced stock management is active, get physical stock of this product in the warehouse associated to the ptoduct for the current order + * Else get the available quantity of the product in fucntion of the shop associated to the order + * + * @param array &$product + */ + protected function setProductCurrentStock(&$product) + { + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') + && (int)$product['advanced_stock_management'] == 1 + && (int)$product['id_warehouse'] > 0) { + $product['current_stock'] = StockManagerFactory::getManager()->getProductPhysicalQuantities($product['product_id'], $product['product_attribute_id'], (int)$product['id_warehouse'], true); + } else { + $product['current_stock'] = StockAvailable::getQuantityAvailableByProduct($product['product_id'], $product['product_attribute_id'], (int)$this->id_shop); + } + } - /** - * - * This method allow to add image information on a product detail - * @param array &$product - */ - protected function setProductImageInformations(&$product) - { - if (isset($product['product_attribute_id']) && $product['product_attribute_id']) - $id_image = Db::getInstance()->getValue(' + /** + * + * This method allow to add image information on a product detail + * @param array &$product + */ + protected function setProductImageInformations(&$product) + { + if (isset($product['product_attribute_id']) && $product['product_attribute_id']) { + $id_image = Db::getInstance()->getValue(' SELECT `image_shop`.id_image FROM `'._DB_PREFIX_.'product_attribute_image` pai'. - Shop::addSqlAssociation('image', 'pai', true).' + Shop::addSqlAssociation('image', 'pai', true).' LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_image` = pai.`id_image`) WHERE id_product_attribute = '.(int)$product['product_attribute_id']. ' ORDER by i.position ASC'); + } - if (!isset($id_image) || !$id_image) - $id_image = Db::getInstance()->getValue(' + if (!isset($id_image) || !$id_image) { + $id_image = Db::getInstance()->getValue(' SELECT `image_shop`.id_image FROM `'._DB_PREFIX_.'image` i'. - Shop::addSqlAssociation('image', 'i', true, 'image_shop.cover=1').' + Shop::addSqlAssociation('image', 'i', true, 'image_shop.cover=1').' WHERE i.id_product = '.(int)$product['product_id'] - ); + ); + } - $product['image'] = null; - $product['image_size'] = null; + $product['image'] = null; + $product['image_size'] = null; - if ($id_image) - $product['image'] = new Image($id_image); - } + if ($id_image) { + $product['image'] = new Image($id_image); + } + } - public function getTaxesAverageUsed() - { - return Cart::getTaxesAverageUsed((int)$this->id_cart); - } + public function getTaxesAverageUsed() + { + return Cart::getTaxesAverageUsed((int)$this->id_cart); + } - /** - * Count virtual products in order - * - * @return int number of virtual products - */ - public function getVirtualProducts() - { - $sql = ' + /** + * Count virtual products in order + * + * @return int number of virtual products + */ + public function getVirtualProducts() + { + $sql = ' SELECT `product_id`, `product_attribute_id`, `download_hash`, `download_deadline` FROM `'._DB_PREFIX_.'order_detail` od WHERE od.`id_order` = '.(int)$this->id.' AND `download_hash` <> \'\''; - return Db::getInstance()->executeS($sql); - } + return Db::getInstance()->executeS($sql); + } - /** - * Check if order contains (only) virtual products - * - * @param bool $strict If false return true if there are at least one product virtual - * @return bool true if is a virtual order or false - * - */ - public function isVirtual($strict = true) - { - $products = $this->getProducts(); - if (count($products) < 1) - return false; - $virtual = true; - foreach ($products as $product) - { - $pd = ProductDownload::getIdFromIdProduct((int)$product['product_id']); - if ($pd && Validate::isUnsignedInt($pd) && $product['download_hash'] && $product['display_filename'] != '') - { - if ($strict === false) - return true; - } - else - $virtual &= false; - } - return $virtual; - } + /** + * Check if order contains (only) virtual products + * + * @param bool $strict If false return true if there are at least one product virtual + * @return bool true if is a virtual order or false + * + */ + public function isVirtual($strict = true) + { + $products = $this->getProducts(); + if (count($products) < 1) { + return false; + } + $virtual = true; + foreach ($products as $product) { + $pd = ProductDownload::getIdFromIdProduct((int)$product['product_id']); + if ($pd && Validate::isUnsignedInt($pd) && $product['download_hash'] && $product['display_filename'] != '') { + if ($strict === false) { + return true; + } + } else { + $virtual &= false; + } + } + return $virtual; + } - /** - * @deprecated 1.5.0.1 - */ - public function getDiscounts($details = false) - { - Tools::displayAsDeprecated(); - return Order::getCartRules(); - } + /** + * @deprecated 1.5.0.1 + */ + public function getDiscounts($details = false) + { + Tools::displayAsDeprecated(); + return Order::getCartRules(); + } - public function getCartRules() - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public function getCartRules() + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'order_cart_rule` ocr WHERE ocr.`id_order` = '.(int)$this->id); - } + } - public static function getDiscountsCustomer($id_customer, $id_cart_rule) - { - $cache_id = 'Order::getDiscountsCustomer_'.(int)$id_customer.'-'.(int)$id_cart_rule; - if (!Cache::isStored($cache_id)) - { - $result = (int)Db::getInstance()->getValue(' + public static function getDiscountsCustomer($id_customer, $id_cart_rule) + { + $cache_id = 'Order::getDiscountsCustomer_'.(int)$id_customer.'-'.(int)$id_cart_rule; + if (!Cache::isStored($cache_id)) { + $result = (int)Db::getInstance()->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'orders` o LEFT JOIN '._DB_PREFIX_.'order_cart_rule ocr ON (ocr.id_order = o.id_order) WHERE o.id_customer = '.(int)$id_customer.' AND ocr.id_cart_rule = '.(int)$id_cart_rule); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Get current order status (eg. Awaiting payment, Delivered...) - * - * @return int Order status id - */ - public function getCurrentState() - { - return $this->current_state; - } + /** + * Get current order status (eg. Awaiting payment, Delivered...) + * + * @return int Order status id + */ + public function getCurrentState() + { + return $this->current_state; + } - /** - * Get current order status name (eg. Awaiting payment, Delivered...) - * - * @return array Order status details - */ - public function getCurrentStateFull($id_lang) - { - return Db::getInstance()->getRow(' + /** + * Get current order status name (eg. Awaiting payment, Delivered...) + * + * @return array Order status details + */ + public function getCurrentStateFull($id_lang) + { + return Db::getInstance()->getRow(' SELECT os.`id_order_state`, osl.`name`, os.`logable`, os.`shipped` FROM `'._DB_PREFIX_.'order_state` os LEFT JOIN `'._DB_PREFIX_.'order_state_lang` osl ON (osl.`id_order_state` = os.`id_order_state`) WHERE osl.`id_lang` = '.(int)$id_lang.' AND os.`id_order_state` = '.(int)$this->current_state); - } + } - public function hasBeenDelivered() - { - return count($this->getHistory((int)$this->id_lang, false, false, OrderState::FLAG_DELIVERY)); - } + public function hasBeenDelivered() + { + return count($this->getHistory((int)$this->id_lang, false, false, OrderState::FLAG_DELIVERY)); + } - /** - * Has products returned by the merchant or by the customer? - */ - public function hasProductReturned() - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Has products returned by the merchant or by the customer? + */ + public function hasProductReturned() + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT IFNULL(SUM(ord.product_quantity), SUM(product_quantity_return)) FROM `'._DB_PREFIX_.'orders` o INNER JOIN `'._DB_PREFIX_.'order_detail` od @@ -827,60 +842,62 @@ class OrderCore extends ObjectModel LEFT JOIN `'._DB_PREFIX_.'order_return_detail` ord ON ord.id_order_detail = od.id_order_detail WHERE o.id_order = '.(int)$this->id); - } + } - public function hasBeenPaid() - { - return count($this->getHistory((int)$this->id_lang, false, false, OrderState::FLAG_PAID)); - } + public function hasBeenPaid() + { + return count($this->getHistory((int)$this->id_lang, false, false, OrderState::FLAG_PAID)); + } - public function hasBeenShipped() - { - return count($this->getHistory((int)$this->id_lang, false, false, OrderState::FLAG_SHIPPED)); - } + public function hasBeenShipped() + { + return count($this->getHistory((int)$this->id_lang, false, false, OrderState::FLAG_SHIPPED)); + } - public function isInPreparation() - { - return count($this->getHistory((int)$this->id_lang, Configuration::get('PS_OS_PREPARATION'))); - } + public function isInPreparation() + { + return count($this->getHistory((int)$this->id_lang, Configuration::get('PS_OS_PREPARATION'))); + } - /** - * Checks if the current order status is paid and shipped - * - * @return bool - */ - public function isPaidAndShipped() - { - $order_state = $this->getCurrentOrderState(); - if ($order_state && $order_state->paid && $order_state->shipped) - return true; - return false; - } + /** + * Checks if the current order status is paid and shipped + * + * @return bool + */ + public function isPaidAndShipped() + { + $order_state = $this->getCurrentOrderState(); + if ($order_state && $order_state->paid && $order_state->shipped) { + return true; + } + return false; + } - /** - * Get customer orders - * - * @param int $id_customer Customer id - * @param bool $show_hidden_status Display or not hidden order statuses - * @return array Customer orders - */ - public static function getCustomerOrders($id_customer, $show_hidden_status = false, Context $context = null) - { - if (!$context) - $context = Context::getContext(); + /** + * Get customer orders + * + * @param int $id_customer Customer id + * @param bool $show_hidden_status Display or not hidden order statuses + * @return array Customer orders + */ + public static function getCustomerOrders($id_customer, $show_hidden_status = false, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT o.*, (SELECT SUM(od.`product_quantity`) FROM `'._DB_PREFIX_.'order_detail` od WHERE od.`id_order` = o.`id_order`) nb_products FROM `'._DB_PREFIX_.'orders` o WHERE o.`id_customer` = '.(int)$id_customer.' GROUP BY o.`id_order` ORDER BY o.`date_add` DESC'); - if (!$res) - return array(); + if (!$res) { + return array(); + } - foreach ($res as $key => $val) - { - $res2 = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + foreach ($res as $key => $val) { + $res2 = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT os.`id_order_state`, osl.`name` AS order_state, os.`invoice`, os.`color` as order_state_color FROM `'._DB_PREFIX_.'order_history` oh LEFT JOIN `'._DB_PREFIX_.'order_state` os ON (os.`id_order_state` = oh.`id_order_state`) @@ -889,35 +906,37 @@ class OrderCore extends ObjectModel ORDER BY oh.`date_add` DESC, oh.`id_order_history` DESC LIMIT 1'); - if ($res2) - $res[$key] = array_merge($res[$key], $res2[0]); + if ($res2) { + $res[$key] = array_merge($res[$key], $res2[0]); + } + } + return $res; + } - } - return $res; - } - - public static function getOrdersIdByDate($date_from, $date_to, $id_customer = null, $type = null) - { - $sql = 'SELECT `id_order` + public static function getOrdersIdByDate($date_from, $date_to, $id_customer = null, $type = null) + { + $sql = 'SELECT `id_order` FROM `'._DB_PREFIX_.'orders` WHERE DATE_ADD(date_upd, INTERVAL -1 DAY) <= \''.pSQL($date_to).'\' AND date_upd >= \''.pSQL($date_from).'\' '.Shop::addSqlRestriction() - .($type ? ' AND `'.bqSQL($type).'_number` != 0' : '') - .($id_customer ? ' AND id_customer = '.(int)$id_customer : ''); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + .($type ? ' AND `'.bqSQL($type).'_number` != 0' : '') + .($id_customer ? ' AND id_customer = '.(int)$id_customer : ''); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - $orders = array(); - foreach ($result as $order) - $orders[] = (int)$order['id_order']; - return $orders; - } + $orders = array(); + foreach ($result as $order) { + $orders[] = (int)$order['id_order']; + } + return $orders; + } - public static function getOrdersWithInformations($limit = null, Context $context = null) - { - if (!$context) - $context = Context::getContext(); + public static function getOrdersWithInformations($limit = null, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } - $sql = 'SELECT *, ( + $sql = 'SELECT *, ( SELECT osl.`name` FROM `'._DB_PREFIX_.'order_state_lang` osl WHERE osl.`id_order_state` = o.`current_state` @@ -930,549 +949,576 @@ class OrderCore extends ObjectModel '.Shop::addSqlRestriction(false, 'o').' ORDER BY o.`date_add` DESC '.((int)$limit ? 'LIMIT 0, '.(int)$limit : ''); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + } - /** - * @deprecated since 1.5.0.2 - * - * @param $date_from - * @param $date_to - * @param $id_customer - * @param $type - * - * @return array - */ - public static function getOrdersIdInvoiceByDate($date_from, $date_to, $id_customer = null, $type = null) - { - Tools::displayAsDeprecated(); - $sql = 'SELECT `id_order` + /** + * @deprecated since 1.5.0.2 + * + * @param $date_from + * @param $date_to + * @param $id_customer + * @param $type + * + * @return array + */ + public static function getOrdersIdInvoiceByDate($date_from, $date_to, $id_customer = null, $type = null) + { + Tools::displayAsDeprecated(); + $sql = 'SELECT `id_order` FROM `'._DB_PREFIX_.'orders` WHERE DATE_ADD(invoice_date, INTERVAL -1 DAY) <= \''.pSQL($date_to).'\' AND invoice_date >= \''.pSQL($date_from).'\' '.Shop::addSqlRestriction() - .($type ? ' AND `'.bqSQL($type).'_number` != 0' : '') - .($id_customer ? ' AND id_customer = '.(int)$id_customer : ''). - ' ORDER BY invoice_date ASC'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + .($type ? ' AND `'.bqSQL($type).'_number` != 0' : '') + .($id_customer ? ' AND id_customer = '.(int)$id_customer : ''). + ' ORDER BY invoice_date ASC'; + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - $orders = array(); - foreach ($result as $order) - $orders[] = (int)$order['id_order']; - return $orders; - } + $orders = array(); + foreach ($result as $order) { + $orders[] = (int)$order['id_order']; + } + return $orders; + } - /** - * @deprecated 1.5.0.3 - * - * @param $id_order_state - * @return array - */ - public static function getOrderIdsByStatus($id_order_state) - { - Tools::displayAsDeprecated(); - $sql = 'SELECT id_order + /** + * @deprecated 1.5.0.3 + * + * @param $id_order_state + * @return array + */ + public static function getOrderIdsByStatus($id_order_state) + { + Tools::displayAsDeprecated(); + $sql = 'SELECT id_order FROM '._DB_PREFIX_.'orders o WHERE o.`current_state` = '.(int)$id_order_state.' '.Shop::addSqlRestriction(false, 'o').' ORDER BY invoice_date ASC'; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - $orders = array(); - foreach ($result as $order) - $orders[] = (int)$order['id_order']; - return $orders; - } + $orders = array(); + foreach ($result as $order) { + $orders[] = (int)$order['id_order']; + } + return $orders; + } - /** - * Get product total without taxes - * - * @return Product total without taxes - */ - public function getTotalProductsWithoutTaxes($products = false) - { - return $this->total_products; - } + /** + * Get product total without taxes + * + * @return Product total without taxes + */ + public function getTotalProductsWithoutTaxes($products = false) + { + return $this->total_products; + } - /** - * Get product total with taxes - * - * @return Product total with taxes - */ - public function getTotalProductsWithTaxes($products = false) - { - if ($this->total_products_wt != '0.00' && !$products) - return $this->total_products_wt; - /* Retro-compatibility (now set directly on the validateOrder() method) */ + /** + * Get product total with taxes + * + * @return Product total with taxes + */ + public function getTotalProductsWithTaxes($products = false) + { + if ($this->total_products_wt != '0.00' && !$products) { + return $this->total_products_wt; + } + /* Retro-compatibility (now set directly on the validateOrder() method) */ - if (!$products) - $products = $this->getProductsDetail(); + if (!$products) { + $products = $this->getProductsDetail(); + } - $return = 0; - foreach ($products as $row) - $return += $row['total_price_tax_incl']; + $return = 0; + foreach ($products as $row) { + $return += $row['total_price_tax_incl']; + } - if (!$products) - { - $this->total_products_wt = $return; - $this->update(); - } - return $return; - } + if (!$products) { + $this->total_products_wt = $return; + $this->update(); + } + return $return; + } - /** - * used to cache order customer - */ - protected $cacheCustomer = null; + /** + * used to cache order customer + */ + protected $cacheCustomer = null; - /** - * Get order customer - * - * @return Customer $customer - */ - public function getCustomer() - { - if (is_null($this->cacheCustomer)) - $this->cacheCustomer = new Customer((int)$this->id_customer); + /** + * Get order customer + * + * @return Customer $customer + */ + public function getCustomer() + { + if (is_null($this->cacheCustomer)) { + $this->cacheCustomer = new Customer((int)$this->id_customer); + } - return $this->cacheCustomer; - } + return $this->cacheCustomer; + } - /** - * Get customer orders number - * - * @param int $id_customer Customer id - * @return array Customer orders number - */ - public static function getCustomerNbOrders($id_customer) - { - $sql = 'SELECT COUNT(`id_order`) AS nb + /** + * Get customer orders number + * + * @param int $id_customer Customer id + * @return array Customer orders number + */ + public static function getCustomerNbOrders($id_customer) + { + $sql = 'SELECT COUNT(`id_order`) AS nb FROM `'._DB_PREFIX_.'orders` WHERE `id_customer` = '.(int)$id_customer - .Shop::addSqlRestriction(); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + .Shop::addSqlRestriction(); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); - return isset($result['nb']) ? $result['nb'] : 0; - } + return isset($result['nb']) ? $result['nb'] : 0; + } - /** - * Get an order by its cart id - * - * @param int $id_cart Cart id - * @return array Order details - */ - public static function getOrderByCartId($id_cart) - { - $sql = 'SELECT `id_order` + /** + * Get an order by its cart id + * + * @param int $id_cart Cart id + * @return array Order details + */ + public static function getOrderByCartId($id_cart) + { + $sql = 'SELECT `id_order` FROM `'._DB_PREFIX_.'orders` WHERE `id_cart` = '.(int)$id_cart - .Shop::addSqlRestriction(); - $result = Db::getInstance()->getRow($sql); + .Shop::addSqlRestriction(); + $result = Db::getInstance()->getRow($sql); - return isset($result['id_order']) ? $result['id_order'] : false; - } + return isset($result['id_order']) ? $result['id_order'] : false; + } - /** - * @deprecated 1.5.0.1 - * @see Order::addCartRule() - * @param int $id_cart_rule - * @param string $name - * @param float $value - * @return bool - */ - public function addDiscount($id_cart_rule, $name, $value) - { - Tools::displayAsDeprecated(); - return Order::addCartRule($id_cart_rule, $name, array('tax_incl' => $value, 'tax_excl' => '0.00')); - } + /** + * @deprecated 1.5.0.1 + * @see Order::addCartRule() + * @param int $id_cart_rule + * @param string $name + * @param float $value + * @return bool + */ + public function addDiscount($id_cart_rule, $name, $value) + { + Tools::displayAsDeprecated(); + return Order::addCartRule($id_cart_rule, $name, array('tax_incl' => $value, 'tax_excl' => '0.00')); + } - /** - * @since 1.5.0.1 - * @param int $id_cart_rule - * @param string $name - * @param array $values - * @param int $id_order_invoice - * @return bool - */ - public function addCartRule($id_cart_rule, $name, $values, $id_order_invoice = 0, $free_shipping = null) - { - $order_cart_rule = new OrderCartRule(); - $order_cart_rule->id_order = $this->id; - $order_cart_rule->id_cart_rule = $id_cart_rule; - $order_cart_rule->id_order_invoice = $id_order_invoice; - $order_cart_rule->name = $name; - $order_cart_rule->value = $values['tax_incl']; - $order_cart_rule->value_tax_excl = $values['tax_excl']; - if ($free_shipping === null) - { - $cart_rule = new CartRule($id_cart_rule); - $free_shipping = $cart_rule->free_shipping; - } - $order_cart_rule->free_shipping = (int)$free_shipping; - $order_cart_rule->add(); - } + /** + * @since 1.5.0.1 + * @param int $id_cart_rule + * @param string $name + * @param array $values + * @param int $id_order_invoice + * @return bool + */ + public function addCartRule($id_cart_rule, $name, $values, $id_order_invoice = 0, $free_shipping = null) + { + $order_cart_rule = new OrderCartRule(); + $order_cart_rule->id_order = $this->id; + $order_cart_rule->id_cart_rule = $id_cart_rule; + $order_cart_rule->id_order_invoice = $id_order_invoice; + $order_cart_rule->name = $name; + $order_cart_rule->value = $values['tax_incl']; + $order_cart_rule->value_tax_excl = $values['tax_excl']; + if ($free_shipping === null) { + $cart_rule = new CartRule($id_cart_rule); + $free_shipping = $cart_rule->free_shipping; + } + $order_cart_rule->free_shipping = (int)$free_shipping; + $order_cart_rule->add(); + } - public function getNumberOfDays() - { - $nb_return_days = (int)Configuration::get('PS_ORDER_RETURN_NB_DAYS', null, null, $this->id_shop); - if (!$nb_return_days) - return true; - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + public function getNumberOfDays() + { + $nb_return_days = (int)Configuration::get('PS_ORDER_RETURN_NB_DAYS', null, null, $this->id_shop); + if (!$nb_return_days) { + return true; + } + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT TO_DAYS("'.date('Y-m-d').' 00:00:00") - TO_DAYS(`delivery_date`) AS days FROM `'._DB_PREFIX_.'orders` WHERE `id_order` = '.(int)$this->id); - if ($result['days'] <= $nb_return_days) - return true; - return false; - } + if ($result['days'] <= $nb_return_days) { + return true; + } + return false; + } - /** - * Can this order be returned by the client? - * - * @return bool - */ - public function isReturnable() - { - if (Configuration::get('PS_ORDER_RETURN', null, null, $this->id_shop) && $this->isPaidAndShipped()) - return $this->getNumberOfDays(); + /** + * Can this order be returned by the client? + * + * @return bool + */ + public function isReturnable() + { + if (Configuration::get('PS_ORDER_RETURN', null, null, $this->id_shop) && $this->isPaidAndShipped()) { + return $this->getNumberOfDays(); + } - return false; - } + return false; + } - public static function getLastInvoiceNumber() - { - return Db::getInstance()->getValue(' + public static function getLastInvoiceNumber() + { + return Db::getInstance()->getValue(' SELECT MAX(`number`) FROM `'._DB_PREFIX_.'order_invoice` '); - } + } - public static function setLastInvoiceNumber($order_invoice_id, $id_shop) - { - if (!$order_invoice_id) - return false; + public static function setLastInvoiceNumber($order_invoice_id, $id_shop) + { + if (!$order_invoice_id) { + return false; + } - $number = Configuration::get('PS_INVOICE_START_NUMBER', null, null, $id_shop); - // If invoice start number has been set, you clean the value of this configuration - if ($number) - Configuration::updateValue('PS_INVOICE_START_NUMBER', false, false, null, $id_shop); + $number = Configuration::get('PS_INVOICE_START_NUMBER', null, null, $id_shop); + // If invoice start number has been set, you clean the value of this configuration + if ($number) { + Configuration::updateValue('PS_INVOICE_START_NUMBER', false, false, null, $id_shop); + } - $sql = 'UPDATE `'._DB_PREFIX_.'order_invoice` SET number ='; + $sql = 'UPDATE `'._DB_PREFIX_.'order_invoice` SET number ='; - if ($number) - $sql .= (int)$number; - else - $sql .= '(SELECT new_number FROM (SELECT (MAX(`number`) + 1) AS new_number + if ($number) { + $sql .= (int)$number; + } else { + $sql .= '(SELECT new_number FROM (SELECT (MAX(`number`) + 1) AS new_number FROM `'._DB_PREFIX_.'order_invoice`) AS result)'; + } - $sql .= ' WHERE `id_order_invoice` = '.(int)$order_invoice_id; + $sql .= ' WHERE `id_order_invoice` = '.(int)$order_invoice_id; - return Db::getInstance()->execute($sql); - } + return Db::getInstance()->execute($sql); + } - public function getInvoiceNumber($order_invoice_id) - { - if (!$order_invoice_id) - return false; + public function getInvoiceNumber($order_invoice_id) + { + if (!$order_invoice_id) { + return false; + } - return Db::getInstance()->getValue(' + return Db::getInstance()->getValue(' SELECT `number` FROM `'._DB_PREFIX_.'order_invoice` WHERE `id_order_invoice` = '.(int)$order_invoice_id - ); - } + ); + } - /** - * This method allows to generate first invoice of the current order - */ - public function setInvoice($use_existing_payment = false) - { - if (!$this->hasInvoice()) - { - if ($id = (int)$this->hasDelivery()) - $order_invoice = new OrderInvoice($id); - else - $order_invoice = new OrderInvoice(); - $order_invoice->id_order = $this->id; - if (!$id) - $order_invoice->number = 0; - $address = new Address((int)$this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); - $carrier = new Carrier((int)$this->id_carrier); - $tax_calculator = $carrier->getTaxCalculator($address, $this->id, Configuration::get('PS_ATCP_SHIPWRAP')); - $order_invoice->total_discount_tax_excl = $this->total_discounts_tax_excl; - $order_invoice->total_discount_tax_incl = $this->total_discounts_tax_incl; - $order_invoice->total_paid_tax_excl = $this->total_paid_tax_excl; - $order_invoice->total_paid_tax_incl = $this->total_paid_tax_incl; - $order_invoice->total_products = $this->total_products; - $order_invoice->total_products_wt = $this->total_products_wt; - $order_invoice->total_shipping_tax_excl = $this->total_shipping_tax_excl; - $order_invoice->total_shipping_tax_incl = $this->total_shipping_tax_incl; - $order_invoice->shipping_tax_computation_method = $tax_calculator->computation_method; - $order_invoice->total_wrapping_tax_excl = $this->total_wrapping_tax_excl; - $order_invoice->total_wrapping_tax_incl = $this->total_wrapping_tax_incl; + /** + * This method allows to generate first invoice of the current order + */ + public function setInvoice($use_existing_payment = false) + { + if (!$this->hasInvoice()) { + if ($id = (int)$this->hasDelivery()) { + $order_invoice = new OrderInvoice($id); + } else { + $order_invoice = new OrderInvoice(); + } + $order_invoice->id_order = $this->id; + if (!$id) { + $order_invoice->number = 0; + } - // Save Order invoice + // Save Order invoice - $order_invoice->save(); - if (Configuration::get('PS_INVOICE')) - $this->setLastInvoiceNumber($order_invoice->id, $this->id_shop); + $this->setInvoiceDetails($order_invoice); - if (Configuration::get('PS_ATCP_SHIPWRAP')) - { - $wrapping_tax_calculator = Adapter_ServiceLocator::get('AverageTaxOfProductsTaxCalculator')->setIdOrder($this->id); - } - else - { - $wrapping_tax_manager = TaxManagerFactory::getManager($address, (int)Configuration::get('PS_GIFT_WRAPPING_TAX_RULES_GROUP')); - $wrapping_tax_calculator = $wrapping_tax_manager->getTaxCalculator(); - } + if (Configuration::get('PS_INVOICE')) { + $this->setLastInvoiceNumber($order_invoice->id, $this->id_shop); + } - $order_invoice->saveCarrierTaxCalculator( - $tax_calculator->getTaxesAmount( - $order_invoice->total_shipping_tax_excl, - $order_invoice->total_shipping_tax_incl, - _PS_PRICE_COMPUTE_PRECISION_, - $this->round_mode - ) - ); - $order_invoice->saveWrappingTaxCalculator( - $wrapping_tax_calculator->getTaxesAmount( - $order_invoice->total_wrapping_tax_excl, - $order_invoice->total_wrapping_tax_incl, - _PS_PRICE_COMPUTE_PRECISION_, - $this->round_mode - ) - ); - // Update order_carrier - $id_order_carrier = Db::getInstance()->getValue(' + + // Update order_carrier + $id_order_carrier = Db::getInstance()->getValue(' SELECT `id_order_carrier` FROM `'._DB_PREFIX_.'order_carrier` WHERE `id_order` = '.(int)$order_invoice->id_order.' AND (`id_order_invoice` IS NULL OR `id_order_invoice` = 0)'); - if ($id_order_carrier) - { - $order_carrier = new OrderCarrier($id_order_carrier); - $order_carrier->id_order_invoice = (int)$order_invoice->id; - $order_carrier->update(); - } + if ($id_order_carrier) { + $order_carrier = new OrderCarrier($id_order_carrier); + $order_carrier->id_order_invoice = (int)$order_invoice->id; + $order_carrier->update(); + } - // Update order detail - Db::getInstance()->execute(' + // Update order detail + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'order_detail` SET `id_order_invoice` = '.(int)$order_invoice->id.' WHERE `id_order` = '.(int)$order_invoice->id_order); - // Update order payment - if ($use_existing_payment) - { - $id_order_payments = Db::getInstance()->executeS(' + // Update order payment + if ($use_existing_payment) { + $id_order_payments = Db::getInstance()->executeS(' SELECT DISTINCT op.id_order_payment FROM `'._DB_PREFIX_.'order_payment` op INNER JOIN `'._DB_PREFIX_.'orders` o ON (o.reference = op.order_reference) LEFT JOIN `'._DB_PREFIX_.'order_invoice_payment` oip ON (oip.id_order_payment = op.id_order_payment) WHERE (oip.id_order != '.(int)$order_invoice->id_order.' OR oip.id_order IS NULL) AND o.id_order = '.(int)$order_invoice->id_order); - if (count($id_order_payments)) - { - foreach ($id_order_payments as $order_payment) - Db::getInstance()->execute(' + if (count($id_order_payments)) { + foreach ($id_order_payments as $order_payment) { + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'order_invoice_payment` SET `id_order_invoice` = '.(int)$order_invoice->id.', `id_order_payment` = '.(int)$order_payment['id_order_payment'].', `id_order` = '.(int)$order_invoice->id_order); - // Clear cache - Cache::clean('order_invoice_paid_*'); - } - } + } + // Clear cache + Cache::clean('order_invoice_paid_*'); + } + } - // Update order cart rule - Db::getInstance()->execute(' + // Update order cart rule + Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'order_cart_rule` SET `id_order_invoice` = '.(int)$order_invoice->id.' WHERE `id_order` = '.(int)$order_invoice->id_order); - // Keep it for backward compatibility, to remove on 1.6 version - $this->invoice_date = $order_invoice->date_add; + // Keep it for backward compatibility, to remove on 1.6 version + $this->invoice_date = $order_invoice->date_add; - if (Configuration::get('PS_INVOICE')) - { - $this->invoice_number = $this->getInvoiceNumber($order_invoice->id); - $invoice_number = Hook::exec('actionSetInvoice', array( - get_class($this) => $this, - get_class($order_invoice) => $order_invoice, - 'use_existing_payment' => (bool)$use_existing_payment - )); + if (Configuration::get('PS_INVOICE')) { + $this->invoice_number = $this->getInvoiceNumber($order_invoice->id); + $invoice_number = Hook::exec('actionSetInvoice', array( + get_class($this) => $this, + get_class($order_invoice) => $order_invoice, + 'use_existing_payment' => (bool)$use_existing_payment + )); - if (is_numeric($invoice_number)) - $this->invoice_number = (int)$invoice_number; - else - $this->invoice_number = $this->getInvoiceNumber($order_invoice->id); - } + if (is_numeric($invoice_number)) { + $this->invoice_number = (int)$invoice_number; + } else { + $this->invoice_number = $this->getInvoiceNumber($order_invoice->id); + } + } - $this->update(); - } - } + $this->update(); + } + } - /** - * This method allows to generate first delivery slip of the current order - */ - public function setDeliverySlip() - { - if (!$this->hasInvoice()) - { - $order_invoice = new OrderInvoice(); - $order_invoice->id_order = $this->id; - $order_invoice->number = 0; - $order_invoice->add(); - $this->delivery_date = $order_invoice->date_add; - $this->delivery_number = $this->getDeliveryNumber($order_invoice->id); - $this->update(); - } - } + /** + * This method allows to fulfill the object order_invoice with sales figures + */ + protected function setInvoiceDetails($order_invoice) + { + if (!$order_invoice || !is_object($order_invoice)) { + return; + } - public function setDeliveryNumber($order_invoice_id, $id_shop) - { - if (!$order_invoice_id) - return false; + $address = new Address((int)$this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); + $carrier = new Carrier((int)$this->id_carrier); + $tax_calculator = $carrier->getTaxCalculator($address); + $order_invoice->total_discount_tax_excl = $this->total_discounts_tax_excl; + $order_invoice->total_discount_tax_incl = $this->total_discounts_tax_incl; + $order_invoice->total_paid_tax_excl = $this->total_paid_tax_excl; + $order_invoice->total_paid_tax_incl = $this->total_paid_tax_incl; + $order_invoice->total_products = $this->total_products; + $order_invoice->total_products_wt = $this->total_products_wt; + $order_invoice->total_shipping_tax_excl = $this->total_shipping_tax_excl; + $order_invoice->total_shipping_tax_incl = $this->total_shipping_tax_incl; + $order_invoice->shipping_tax_computation_method = $tax_calculator->computation_method; + $order_invoice->total_wrapping_tax_excl = $this->total_wrapping_tax_excl; + $order_invoice->total_wrapping_tax_incl = $this->total_wrapping_tax_incl; + $order_invoice->save(); - $id_shop = shop::getTotalShops() > 1 ? $id_shop : null; + if (Configuration::get('PS_ATCP_SHIPWRAP')) { + $wrapping_tax_calculator = Adapter_ServiceLocator::get('AverageTaxOfProductsTaxCalculator')->setIdOrder($this->id); + } else { + $wrapping_tax_manager = TaxManagerFactory::getManager($address, (int)Configuration::get('PS_GIFT_WRAPPING_TAX_RULES_GROUP')); + $wrapping_tax_calculator = $wrapping_tax_manager->getTaxCalculator(); + } - $number = Configuration::get('PS_DELIVERY_NUMBER', null, null, $id_shop); - // If delivery slip start number has been set, you clean the value of this configuration - if ($number) - Configuration::updateValue('PS_DELIVERY_NUMBER', false, false, null, $id_shop); + $order_invoice->saveCarrierTaxCalculator( + $tax_calculator->getTaxesAmount( + $order_invoice->total_shipping_tax_excl, + $order_invoice->total_shipping_tax_incl, + _PS_PRICE_COMPUTE_PRECISION_, + $this->round_mode + ) + ); + $order_invoice->saveWrappingTaxCalculator( + $wrapping_tax_calculator->getTaxesAmount( + $order_invoice->total_wrapping_tax_excl, + $order_invoice->total_wrapping_tax_incl, + _PS_PRICE_COMPUTE_PRECISION_, + $this->round_mode + ) + ); + } - $sql = 'UPDATE `'._DB_PREFIX_.'order_invoice` SET delivery_number ='; + /** + * This method allows to generate first delivery slip of the current order + */ + public function setDeliverySlip() + { + if (!$this->hasInvoice()) { + $order_invoice = new OrderInvoice(); + $order_invoice->id_order = $this->id; + $order_invoice->number = 0; + $this->setInvoiceDetails($order_invoice); + $this->delivery_date = $order_invoice->date_add; + $this->delivery_number = $this->getDeliveryNumber($order_invoice->id); + $this->update(); + } + } - if ($number) - $sql .= (int)$number; - else - $sql .= '(SELECT new_number FROM (SELECT (MAX(`delivery_number`) + 1) AS new_number + public function setDeliveryNumber($order_invoice_id, $id_shop) + { + if (!$order_invoice_id) { + return false; + } + + $id_shop = shop::getTotalShops() > 1 ? $id_shop : null; + + $number = Configuration::get('PS_DELIVERY_NUMBER', null, null, $id_shop); + // If delivery slip start number has been set, you clean the value of this configuration + if ($number) { + Configuration::updateValue('PS_DELIVERY_NUMBER', false, false, null, $id_shop); + } + + $sql = 'UPDATE `'._DB_PREFIX_.'order_invoice` SET delivery_number ='; + + if ($number) { + $sql .= (int)$number; + } else { + $sql .= '(SELECT new_number FROM (SELECT (MAX(`delivery_number`) + 1) AS new_number FROM `'._DB_PREFIX_.'order_invoice`) AS result)'; + } - $sql .= ' WHERE `id_order_invoice` = '.(int)$order_invoice_id; + $sql .= ' WHERE `id_order_invoice` = '.(int)$order_invoice_id; - return Db::getInstance()->execute($sql); - } + return Db::getInstance()->execute($sql); + } - public function getDeliveryNumber($order_invoice_id) - { - if (!$order_invoice_id) - return false; + public function getDeliveryNumber($order_invoice_id) + { + if (!$order_invoice_id) { + return false; + } - return Db::getInstance()->getValue(' + return Db::getInstance()->getValue(' SELECT `delivery_number` FROM `'._DB_PREFIX_.'order_invoice` WHERE `id_order_invoice` = '.(int)$order_invoice_id - ); - } + ); + } - public function setDelivery() - { - // Get all invoice - $order_invoice_collection = $this->getInvoicesCollection(); - foreach ($order_invoice_collection as $order_invoice) - { - /** @var OrderInvoice $order_invoice */ - if ($order_invoice->delivery_number) - continue; + public function setDelivery() + { + // Get all invoice + $order_invoice_collection = $this->getInvoicesCollection(); + foreach ($order_invoice_collection as $order_invoice) { + /** @var OrderInvoice $order_invoice */ + if ($order_invoice->delivery_number) { + continue; + } - // Set delivery number on invoice - $order_invoice->delivery_number = 0; - $order_invoice->delivery_date = date('Y-m-d H:i:s'); - // Update Order Invoice - $order_invoice->update(); - $this->setDeliveryNumber($order_invoice->id, $this->id_shop); - $this->delivery_number = $this->getDeliveryNumber($order_invoice->id); - } + // Set delivery number on invoice + $order_invoice->delivery_number = 0; + $order_invoice->delivery_date = date('Y-m-d H:i:s'); + // Update Order Invoice + $order_invoice->update(); + $this->setDeliveryNumber($order_invoice->id, $this->id_shop); + $this->delivery_number = $this->getDeliveryNumber($order_invoice->id); + } - // Keep it for backward compatibility, to remove on 1.6 version - // Set delivery date - $this->delivery_date = date('Y-m-d H:i:s'); - // Update object - $this->update(); - } + // Keep it for backward compatibility, to remove on 1.6 version + // Set delivery date + $this->delivery_date = date('Y-m-d H:i:s'); + // Update object + $this->update(); + } - public static function getByDelivery($id_delivery) - { - $sql = 'SELECT id_order + public static function getByDelivery($id_delivery) + { + $sql = 'SELECT id_order FROM `'._DB_PREFIX_.'orders` WHERE `delivery_number` = '.(int)$id_delivery.' '.Shop::addSqlRestriction(); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); - return new Order((int)$res['id_order']); - } + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + return new Order((int)$res['id_order']); + } - /** - * Get a collection of orders using reference - * - * @since 1.5.0.14 - * - * @param string $reference - * @return PrestaShopCollection Collection of Order - */ - public static function getByReference($reference) - { - $orders = new PrestaShopCollection('Order'); - $orders->where('reference', '=', $reference); - return $orders; - } + /** + * Get a collection of orders using reference + * + * @since 1.5.0.14 + * + * @param string $reference + * @return PrestaShopCollection Collection of Order + */ + public static function getByReference($reference) + { + $orders = new PrestaShopCollection('Order'); + $orders->where('reference', '=', $reference); + return $orders; + } - public function getTotalWeight() - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public function getTotalWeight() + { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT SUM(product_weight * product_quantity) FROM '._DB_PREFIX_.'order_detail WHERE id_order = '.(int)$this->id); - return (float)$result; - } + return (float)$result; + } - /** - * - * @param int $id_invoice - * @deprecated 1.5.0.1 - */ - public static function getInvoice($id_invoice) - { - Tools::displayAsDeprecated(); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + /** + * + * @param int $id_invoice + * @deprecated 1.5.0.1 + */ + public static function getInvoice($id_invoice) + { + Tools::displayAsDeprecated(); + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT `invoice_number`, `id_order` FROM `'._DB_PREFIX_.'orders` WHERE invoice_number = '.(int)$id_invoice); - } + } - public function isAssociatedAtGuest($email) - { - if (!$email) - return false; - $sql = 'SELECT COUNT(*) + public function isAssociatedAtGuest($email) + { + if (!$email) { + return false; + } + $sql = 'SELECT COUNT(*) FROM `'._DB_PREFIX_.'orders` o LEFT JOIN `'._DB_PREFIX_.'customer` c ON (c.`id_customer` = o.`id_customer`) WHERE o.`id_order` = '.(int)$this->id.' AND c.`email` = \''.pSQL($email).'\' AND c.`is_guest` = 1 '.Shop::addSqlRestriction(false, 'c'); - return (bool)Db::getInstance()->getValue($sql); - } + return (bool)Db::getInstance()->getValue($sql); + } - /** - * @param int $id_order - * @param int $id_customer optionnal - * @return int id_cart - */ - public static function getCartIdStatic($id_order, $id_customer = 0) - { - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * @param int $id_order + * @param int $id_customer optionnal + * @return int id_cart + */ + public static function getCartIdStatic($id_order, $id_customer = 0) + { + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_cart` FROM `'._DB_PREFIX_.'orders` WHERE `id_order` = '.(int)$id_order.' '.($id_customer ? 'AND `id_customer` = '.(int)$id_customer : '')); - } + } - public function getWsOrderRows() - { - $query = ' + public function getWsOrderRows() + { + $query = ' SELECT `id_order_detail` as `id`, `product_id`, @@ -1488,238 +1534,245 @@ class OrderCore extends ObjectModel `unit_price_tax_excl` FROM `'._DB_PREFIX_.'order_detail` WHERE id_order = '.(int)$this->id; - $result = Db::getInstance()->executeS($query); - return $result; - } + $result = Db::getInstance()->executeS($query); + return $result; + } - /** Set current order status - * @param int $id_order_state - * @param int $id_employee (/!\ not optional except for Webservice. - */ - public function setCurrentState($id_order_state, $id_employee = 0) - { - if (empty($id_order_state)) - return false; - $history = new OrderHistory(); - $history->id_order = (int)$this->id; - $history->id_employee = (int)$id_employee; - $history->changeIdOrderState((int)$id_order_state, $this); - $res = Db::getInstance()->getRow(' + /** Set current order status + * @param int $id_order_state + * @param int $id_employee (/!\ not optional except for Webservice. + */ + public function setCurrentState($id_order_state, $id_employee = 0) + { + if (empty($id_order_state)) { + return false; + } + $history = new OrderHistory(); + $history->id_order = (int)$this->id; + $history->id_employee = (int)$id_employee; + $history->changeIdOrderState((int)$id_order_state, $this); + $res = Db::getInstance()->getRow(' SELECT `invoice_number`, `invoice_date`, `delivery_number`, `delivery_date` FROM `'._DB_PREFIX_.'orders` WHERE `id_order` = '.(int)$this->id); - $this->invoice_date = $res['invoice_date']; - $this->invoice_number = $res['invoice_number']; - $this->delivery_date = $res['delivery_date']; - $this->delivery_number = $res['delivery_number']; - $this->update(); + $this->invoice_date = $res['invoice_date']; + $this->invoice_number = $res['invoice_number']; + $this->delivery_date = $res['delivery_date']; + $this->delivery_number = $res['delivery_number']; + $this->update(); - $history->addWithemail(); - } + $history->addWithemail(); + } - public function addWs($autodate = true, $null_values = false) - { - /** @var PaymentModule $payment_module */ - $payment_module = Module::getInstanceByName($this->module); - $customer = new Customer($this->id_customer); - $payment_module->validateOrder($this->id_cart, Configuration::get('PS_OS_WS_PAYMENT'), $this->total_paid, $this->payment, null, array(), null, false, $customer->secure_key); - $this->id = $payment_module->currentOrder; - return true; - } + public function addWs($autodate = true, $null_values = false) + { + /** @var PaymentModule $payment_module */ + $payment_module = Module::getInstanceByName($this->module); + $customer = new Customer($this->id_customer); + $payment_module->validateOrder($this->id_cart, Configuration::get('PS_OS_WS_PAYMENT'), $this->total_paid, $this->payment, null, array(), null, false, $customer->secure_key); + $this->id = $payment_module->currentOrder; + return true; + } - public function deleteAssociations() - { - return (Db::getInstance()->execute(' + public function deleteAssociations() + { + return (Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'order_detail` WHERE `id_order` = '.(int)$this->id) !== false); - } + } - /** - * This method return the ID of the previous order - * @since 1.5.0.1 - * @return int - */ - public function getPreviousOrderId() - { - return Db::getInstance()->getValue(' + /** + * This method return the ID of the previous order + * @since 1.5.0.1 + * @return int + */ + public function getPreviousOrderId() + { + return Db::getInstance()->getValue(' SELECT id_order FROM '._DB_PREFIX_.'orders WHERE id_order < '.(int)$this->id - .Shop::addSqlRestriction().' + .Shop::addSqlRestriction().' ORDER BY id_order DESC'); - } + } - /** - * This method return the ID of the next order - * @since 1.5.0.1 - * @return int - */ - public function getNextOrderId() - { - return Db::getInstance()->getValue(' + /** + * This method return the ID of the next order + * @since 1.5.0.1 + * @return int + */ + public function getNextOrderId() + { + return Db::getInstance()->getValue(' SELECT id_order FROM '._DB_PREFIX_.'orders WHERE id_order > '.(int)$this->id - .Shop::addSqlRestriction().' + .Shop::addSqlRestriction().' ORDER BY id_order ASC'); - } + } - /** - * Get the an order detail list of the current order - * @return array - */ - public function getOrderDetailList() - { - return OrderDetail::getList($this->id); - } + /** + * Get the an order detail list of the current order + * @return array + */ + public function getOrderDetailList() + { + return OrderDetail::getList($this->id); + } - /** - * Gennerate a unique reference for orders generated with the same cart id - * This references, is usefull for check payment - * - * @return String - */ - public static function generateReference() - { - return strtoupper(Tools::passwdGen(9, 'NO_NUMERIC')); - } + /** + * Gennerate a unique reference for orders generated with the same cart id + * This references, is usefull for check payment + * + * @return String + */ + public static function generateReference() + { + return strtoupper(Tools::passwdGen(9, 'NO_NUMERIC')); + } - public function orderContainProduct($id_product) - { - $product_list = $this->getOrderDetailList(); - foreach ($product_list as $product) - if ($product['product_id'] == (int)$id_product) - return true; - return false; - } - /** - * This method returns true if at least one order details uses the - * One After Another tax computation method. - * - * @since 1.5.0.1 - * @return bool - */ - public function useOneAfterAnotherTaxComputationMethod() - { - // if one of the order details use the tax computation method the display will be different - return Db::getInstance()->getValue(' + public function orderContainProduct($id_product) + { + $product_list = $this->getOrderDetailList(); + foreach ($product_list as $product) { + if ($product['product_id'] == (int)$id_product) { + return true; + } + } + return false; + } + /** + * This method returns true if at least one order details uses the + * One After Another tax computation method. + * + * @since 1.5.0.1 + * @return bool + */ + public function useOneAfterAnotherTaxComputationMethod() + { + // if one of the order details use the tax computation method the display will be different + return Db::getInstance()->getValue(' SELECT od.`tax_computation_method` FROM `'._DB_PREFIX_.'order_detail_tax` odt LEFT JOIN `'._DB_PREFIX_.'order_detail` od ON (od.`id_order_detail` = odt.`id_order_detail`) WHERE od.`id_order` = '.(int)$this->id.' AND od.`tax_computation_method` = '.(int)TaxCalculator::ONE_AFTER_ANOTHER_METHOD - ); - } + ); + } - /** - * This method allows to get all Order Payment for the current order - * @since 1.5.0.1 - * @return PrestaShopCollection Collection of OrderPayment - */ - public function getOrderPaymentCollection() - { - $order_payments = new PrestaShopCollection('OrderPayment'); - $order_payments->where('order_reference', '=', $this->reference); - return $order_payments; - } + /** + * This method allows to get all Order Payment for the current order + * @since 1.5.0.1 + * @return PrestaShopCollection Collection of OrderPayment + */ + public function getOrderPaymentCollection() + { + $order_payments = new PrestaShopCollection('OrderPayment'); + $order_payments->where('order_reference', '=', $this->reference); + return $order_payments; + } - /** - * - * This method allows to add a payment to the current order - * @since 1.5.0.1 - * @param float $amount_paid - * @param string $payment_method - * @param string $payment_transaction_id - * @param Currency $currency - * @param string $date - * @param OrderInvoice $order_invoice - * @return bool - */ - public function addOrderPayment($amount_paid, $payment_method = null, $payment_transaction_id = null, $currency = null, $date = null, $order_invoice = null) - { - $order_payment = new OrderPayment(); - $order_payment->order_reference = $this->reference; - $order_payment->id_currency = ($currency ? $currency->id : $this->id_currency); - // we kept the currency rate for historization reasons - $order_payment->conversion_rate = ($currency ? $currency->conversion_rate : 1); - // if payment_method is define, we used this - $order_payment->payment_method = ($payment_method ? $payment_method : $this->payment); - $order_payment->transaction_id = $payment_transaction_id; - $order_payment->amount = $amount_paid; - $order_payment->date_add = ($date ? $date : null); + /** + * + * This method allows to add a payment to the current order + * @since 1.5.0.1 + * @param float $amount_paid + * @param string $payment_method + * @param string $payment_transaction_id + * @param Currency $currency + * @param string $date + * @param OrderInvoice $order_invoice + * @return bool + */ + public function addOrderPayment($amount_paid, $payment_method = null, $payment_transaction_id = null, $currency = null, $date = null, $order_invoice = null) + { + $order_payment = new OrderPayment(); + $order_payment->order_reference = $this->reference; + $order_payment->id_currency = ($currency ? $currency->id : $this->id_currency); + // we kept the currency rate for historization reasons + $order_payment->conversion_rate = ($currency ? $currency->conversion_rate : 1); + // if payment_method is define, we used this + $order_payment->payment_method = ($payment_method ? $payment_method : $this->payment); + $order_payment->transaction_id = $payment_transaction_id; + $order_payment->amount = $amount_paid; + $order_payment->date_add = ($date ? $date : null); - // Add time to the date if needed - if ($order_payment->date_add != null && preg_match('/^[0-9]+-[0-9]+-[0-9]+$/', $order_payment->date_add)) - $order_payment->date_add .= ' '.date('H:i:s'); + // Add time to the date if needed + if ($order_payment->date_add != null && preg_match('/^[0-9]+-[0-9]+-[0-9]+$/', $order_payment->date_add)) { + $order_payment->date_add .= ' '.date('H:i:s'); + } - // Update total_paid_real value for backward compatibility reasons - if ($order_payment->id_currency == $this->id_currency) - $this->total_paid_real += $order_payment->amount; - else - $this->total_paid_real += Tools::ps_round(Tools::convertPrice($order_payment->amount, $order_payment->id_currency, false), 2); + // Update total_paid_real value for backward compatibility reasons + if ($order_payment->id_currency == $this->id_currency) { + $this->total_paid_real += $order_payment->amount; + } else { + $this->total_paid_real += Tools::ps_round(Tools::convertPrice($order_payment->amount, $order_payment->id_currency, false), 2); + } - // We put autodate parameter of add method to true if date_add field is null - $res = $order_payment->add(is_null($order_payment->date_add)) && $this->update(); + // We put autodate parameter of add method to true if date_add field is null + $res = $order_payment->add(is_null($order_payment->date_add)) && $this->update(); - if (!$res) - return false; + if (!$res) { + return false; + } - if (!is_null($order_invoice)) - { - $res = Db::getInstance()->execute(' + if (!is_null($order_invoice)) { + $res = Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'order_invoice_payment` (`id_order_invoice`, `id_order_payment`, `id_order`) VALUES('.(int)$order_invoice->id.', '.(int)$order_payment->id.', '.(int)$this->id.')'); - // Clear cache - Cache::clean('order_invoice_paid_*'); - } + // Clear cache + Cache::clean('order_invoice_paid_*'); + } - return $res; - } + return $res; + } - /** - * Returns the correct product taxes breakdown. - * - * Get all documents linked to the current order - * - * @since 1.5.0.1 - * @return array - */ - public function getDocuments() - { - $invoices = $this->getInvoicesCollection()->getResults(); - foreach ($invoices as $key => $invoice) - if (!$invoice->number) - unset($invoices[$key]); - $delivery_slips = $this->getDeliverySlipsCollection()->getResults(); - // @TODO review - foreach ($delivery_slips as $key => $delivery) - { - $delivery->is_delivery = true; - $delivery->date_add = $delivery->delivery_date; - if (!$invoice->delivery_number) - unset($delivery_slips[$key]); - } - $order_slips = $this->getOrderSlipsCollection()->getResults(); + /** + * Returns the correct product taxes breakdown. + * + * Get all documents linked to the current order + * + * @since 1.5.0.1 + * @return array + */ + public function getDocuments() + { + $invoices = $this->getInvoicesCollection()->getResults(); + foreach ($invoices as $key => $invoice) { + if (!$invoice->number) { + unset($invoices[$key]); + } + } + $delivery_slips = $this->getDeliverySlipsCollection()->getResults(); + // @TODO review + foreach ($delivery_slips as $key => $delivery) { + $delivery->is_delivery = true; + $delivery->date_add = $delivery->delivery_date; + if (!$invoice->delivery_number) { + unset($delivery_slips[$key]); + } + } + $order_slips = $this->getOrderSlipsCollection()->getResults(); - $documents = array_merge($invoices, $order_slips, $delivery_slips); - usort($documents, array('Order', 'sortDocuments')); + $documents = array_merge($invoices, $order_slips, $delivery_slips); + usort($documents, array('Order', 'sortDocuments')); - return $documents; - } + return $documents; + } - public function getReturn() - { - return OrderReturn::getOrdersReturn($this->id_customer, $this->id); - } + public function getReturn() + { + return OrderReturn::getOrdersReturn($this->id_customer, $this->id); + } - /** - * @return array return all shipping method for the current order - * state_name sql var is now deprecated - use order_state_name for the state name and carrier_name for the carrier_name - */ - public function getShipping() - { - return Db::getInstance()->executeS(' + /** + * @return array return all shipping method for the current order + * state_name sql var is now deprecated - use order_state_name for the state name and carrier_name for the carrier_name + */ + public function getShipping() + { + return Db::getInstance()->executeS(' SELECT DISTINCT oc.`id_order_invoice`, oc.`weight`, oc.`shipping_cost_tax_excl`, oc.`shipping_cost_tax_incl`, c.`url`, oc.`id_carrier`, c.`name` as `carrier_name`, oc.`date_add`, "Delivery" as `type`, "true" as `can_edit`, oc.`tracking_number`, oc.`id_order_carrier`, osl.`name` as order_state_name, c.`name` as state_name FROM `'._DB_PREFIX_.'orders` o LEFT JOIN `'._DB_PREFIX_.'order_history` oh @@ -1732,152 +1785,152 @@ class OrderCore extends ObjectModel ON (oh.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = '.(int)Context::getContext()->language->id.') WHERE o.`id_order` = '.(int)$this->id.' GROUP BY c.id_carrier'); - } + } - /** - * - * Get all order_slips for the current order - * @since 1.5.0.2 - * @return PrestaShopCollection Collection of OrderSlip - */ - public function getOrderSlipsCollection() - { - $order_slips = new PrestaShopCollection('OrderSlip'); - $order_slips->where('id_order', '=', $this->id); - return $order_slips; - } + /** + * + * Get all order_slips for the current order + * @since 1.5.0.2 + * @return PrestaShopCollection Collection of OrderSlip + */ + public function getOrderSlipsCollection() + { + $order_slips = new PrestaShopCollection('OrderSlip'); + $order_slips->where('id_order', '=', $this->id); + return $order_slips; + } - /** - * - * Get all invoices for the current order - * @since 1.5.0.1 - * @return PrestaShopCollection Collection of OrderInvoice - */ - public function getInvoicesCollection() - { - $order_invoices = new PrestaShopCollection('OrderInvoice'); - $order_invoices->where('id_order', '=', $this->id); - return $order_invoices; - } + /** + * + * Get all invoices for the current order + * @since 1.5.0.1 + * @return PrestaShopCollection Collection of OrderInvoice + */ + public function getInvoicesCollection() + { + $order_invoices = new PrestaShopCollection('OrderInvoice'); + $order_invoices->where('id_order', '=', $this->id); + return $order_invoices; + } - /** - * - * Get all delivery slips for the current order - * @since 1.5.0.2 - * @return PrestaShopCollection Collection of OrderInvoice - */ - public function getDeliverySlipsCollection() - { - $order_invoices = new PrestaShopCollection('OrderInvoice'); - $order_invoices->where('id_order', '=', $this->id); - $order_invoices->where('delivery_number', '!=', '0'); - return $order_invoices; - } + /** + * + * Get all delivery slips for the current order + * @since 1.5.0.2 + * @return PrestaShopCollection Collection of OrderInvoice + */ + public function getDeliverySlipsCollection() + { + $order_invoices = new PrestaShopCollection('OrderInvoice'); + $order_invoices->where('id_order', '=', $this->id); + $order_invoices->where('delivery_number', '!=', '0'); + return $order_invoices; + } - /** - * Get all not paid invoices for the current order - * @since 1.5.0.2 - * @return PrestaShopCollection Collection of Order invoice not paid - */ - public function getNotPaidInvoicesCollection() - { - $invoices = $this->getInvoicesCollection(); - foreach ($invoices as $key => $invoice) - { - /** @var OrderInvoice $invoice */ - if ($invoice->isPaid()) - unset($invoices[$key]); - } + /** + * Get all not paid invoices for the current order + * @since 1.5.0.2 + * @return PrestaShopCollection Collection of Order invoice not paid + */ + public function getNotPaidInvoicesCollection() + { + $invoices = $this->getInvoicesCollection(); + foreach ($invoices as $key => $invoice) { + /** @var OrderInvoice $invoice */ + if ($invoice->isPaid()) { + unset($invoices[$key]); + } + } - return $invoices; - } + return $invoices; + } - /** - * Get total paid - * - * @since 1.5.0.1 - * @param Currency $currency currency used for the total paid of the current order - * @return float amount in the $currency - */ - public function getTotalPaid($currency = null) - { - if (!$currency) - $currency = new Currency($this->id_currency); + /** + * Get total paid + * + * @since 1.5.0.1 + * @param Currency $currency currency used for the total paid of the current order + * @return float amount in the $currency + */ + public function getTotalPaid($currency = null) + { + if (!$currency) { + $currency = new Currency($this->id_currency); + } - $total = 0; - // Retrieve all payments - $payments = $this->getOrderPaymentCollection(); - foreach ($payments as $payment) - { - /** @var OrderPayment $payment */ - if ($payment->id_currency == $currency->id) - $total += $payment->amount; - else - { - $amount = Tools::convertPrice($payment->amount, $payment->id_currency, false); - if ($currency->id == Configuration::get('PS_DEFAULT_CURRENCY', null, null, $this->id_shop)) - $total += $amount; - else - $total += Tools::convertPrice($amount, $currency->id, true); - } - } + $total = 0; + // Retrieve all payments + $payments = $this->getOrderPaymentCollection(); + foreach ($payments as $payment) { + /** @var OrderPayment $payment */ + if ($payment->id_currency == $currency->id) { + $total += $payment->amount; + } else { + $amount = Tools::convertPrice($payment->amount, $payment->id_currency, false); + if ($currency->id == Configuration::get('PS_CURRENCY_DEFAULT', null, null, $this->id_shop)) { + $total += $amount; + } else { + $total += Tools::convertPrice($amount, $currency->id, true); + } + } + } - return Tools::ps_round($total, 2); - } + return Tools::ps_round($total, 2); + } - /** - * Get the sum of total_paid_tax_incl of the orders with similar reference - * - * @since 1.5.0.1 - * @return float - */ - public function getOrdersTotalPaid() - { - return Db::getInstance()->getValue(' + /** + * Get the sum of total_paid_tax_incl of the orders with similar reference + * + * @since 1.5.0.1 + * @return float + */ + public function getOrdersTotalPaid() + { + return Db::getInstance()->getValue(' SELECT SUM(total_paid_tax_incl) FROM `'._DB_PREFIX_.'orders` WHERE `reference` = \''.pSQL($this->reference).'\' AND `id_cart` = '.(int)$this->id_cart - ); - } + ); + } - /** - * - * This method allows to change the shipping cost of the current order - * @since 1.5.0.1 - * @param float $amount - * @return bool - */ - public function updateShippingCost($amount) - { - $difference = $amount - $this->total_shipping; - // if the current amount is same as the new, we return true - if ($difference == 0) - return true; + /** + * + * This method allows to change the shipping cost of the current order + * @since 1.5.0.1 + * @param float $amount + * @return bool + */ + public function updateShippingCost($amount) + { + $difference = $amount - $this->total_shipping; + // if the current amount is same as the new, we return true + if ($difference == 0) { + return true; + } - // update the total_shipping value - $this->total_shipping = $amount; - // update the total of this order - $this->total_paid += $difference; + // update the total_shipping value + $this->total_shipping = $amount; + // update the total of this order + $this->total_paid += $difference; - // update database - return $this->update(); - } + // update database + return $this->update(); + } - /** - * Returns the correct product taxes breakdown. - * - * @since 1.5.0.1 - * @return array - */ - public function getProductTaxesBreakdown() - { - $tmp_tax_infos = array(); - if ($this->useOneAfterAnotherTaxComputationMethod()) - { - // sum by taxes - $taxes_by_tax = Db::getInstance()->executeS(' + /** + * Returns the correct product taxes breakdown. + * + * @since 1.5.0.1 + * @return array + */ + public function getProductTaxesBreakdown() + { + $tmp_tax_infos = array(); + if ($this->useOneAfterAnotherTaxComputationMethod()) { + // sum by taxes + $taxes_by_tax = Db::getInstance()->executeS(' SELECT odt.`id_order_detail`, t.`name`, t.`rate`, SUM(`total_amount`) AS `total_amount` FROM `'._DB_PREFIX_.'order_detail_tax` odt LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = odt.`id_tax`) @@ -1886,18 +1939,15 @@ class OrderCore extends ObjectModel GROUP BY odt.`id_tax` '); - // format response - $tmp_tax_infos = array(); - foreach ($taxes_by_tax as $tax_infos) - { - $tmp_tax_infos[$tax_infos['rate']]['total_amount'] = $tax_infos['tax_amount']; - $tmp_tax_infos[$tax_infos['rate']]['name'] = $tax_infos['name']; - } - } - else - { - // sum by order details in order to retrieve real taxes rate - $taxes_infos = Db::getInstance()->executeS(' + // format response + $tmp_tax_infos = array(); + foreach ($taxes_by_tax as $tax_infos) { + $tmp_tax_infos[$tax_infos['rate']]['total_amount'] = $tax_infos['tax_amount']; + $tmp_tax_infos[$tax_infos['rate']]['name'] = $tax_infos['name']; + } + } else { + // sum by order details in order to retrieve real taxes rate + $taxes_infos = Db::getInstance()->executeS(' SELECT odt.`id_order_detail`, t.`rate` AS `name`, SUM(od.`total_price_tax_excl`) AS total_price_tax_excl, SUM(t.`rate`) AS rate, SUM(`total_amount`) AS `total_amount` FROM `'._DB_PREFIX_.'order_detail_tax` odt LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = odt.`id_tax`) @@ -1906,456 +1956,474 @@ class OrderCore extends ObjectModel GROUP BY odt.`id_order_detail` '); - // sum by taxes - $tmp_tax_infos = array(); - foreach ($taxes_infos as $tax_infos) - { - if (!isset($tmp_tax_infos[$tax_infos['rate']])) - $tmp_tax_infos[$tax_infos['rate']] = array('total_amount' => 0, - 'name' => 0, - 'total_price_tax_excl' => 0); + // sum by taxes + $tmp_tax_infos = array(); + foreach ($taxes_infos as $tax_infos) { + if (!isset($tmp_tax_infos[$tax_infos['rate']])) { + $tmp_tax_infos[$tax_infos['rate']] = array('total_amount' => 0, + 'name' => 0, + 'total_price_tax_excl' => 0); + } - $tmp_tax_infos[$tax_infos['rate']]['total_amount'] += $tax_infos['total_amount']; - $tmp_tax_infos[$tax_infos['rate']]['name'] = $tax_infos['name']; - $tmp_tax_infos[$tax_infos['rate']]['total_price_tax_excl'] += $tax_infos['total_price_tax_excl']; - } - } + $tmp_tax_infos[$tax_infos['rate']]['total_amount'] += $tax_infos['total_amount']; + $tmp_tax_infos[$tax_infos['rate']]['name'] = $tax_infos['name']; + $tmp_tax_infos[$tax_infos['rate']]['total_price_tax_excl'] += $tax_infos['total_price_tax_excl']; + } + } - return $tmp_tax_infos; - } + return $tmp_tax_infos; + } - /** - * Returns the shipping taxes breakdown - * - * @since 1.5.0.1 - * @return array - */ - public function getShippingTaxesBreakdown() - { - $taxes_breakdown = array(); + /** + * Returns the shipping taxes breakdown + * + * @since 1.5.0.1 + * @return array + */ + public function getShippingTaxesBreakdown() + { + $taxes_breakdown = array(); - $shipping_tax_amount = $this->total_shipping_tax_incl - $this->total_shipping_tax_excl; + $shipping_tax_amount = $this->total_shipping_tax_incl - $this->total_shipping_tax_excl; - if ($shipping_tax_amount > 0) - $taxes_breakdown[] = array( - 'rate' => $this->carrier_tax_rate, - 'total_amount' => $shipping_tax_amount - ); + if ($shipping_tax_amount > 0) { + $taxes_breakdown[] = array( + 'rate' => $this->carrier_tax_rate, + 'total_amount' => $shipping_tax_amount + ); + } - return $taxes_breakdown; - } + return $taxes_breakdown; + } - /** - * Returns the wrapping taxes breakdown - * @todo + /** + * Returns the wrapping taxes breakdown + * @todo - * @since 1.5.0.1 - * @return array - */ - public function getWrappingTaxesBreakdown() - { - $taxes_breakdown = array(); - return $taxes_breakdown; - } + * @since 1.5.0.1 + * @return array + */ + public function getWrappingTaxesBreakdown() + { + $taxes_breakdown = array(); + return $taxes_breakdown; + } - /** - * Returns the ecotax taxes breakdown - * - * @since 1.5.0.1 - * @return array - */ - public function getEcoTaxTaxesBreakdown() - { - return Db::getInstance()->executeS(' + /** + * Returns the ecotax taxes breakdown + * + * @since 1.5.0.1 + * @return array + */ + public function getEcoTaxTaxesBreakdown() + { + return Db::getInstance()->executeS(' SELECT `ecotax_tax_rate`, SUM(`ecotax`) as `ecotax_tax_excl`, SUM(`ecotax`) as `ecotax_tax_incl` FROM `'._DB_PREFIX_.'order_detail` WHERE `id_order` = '.(int)$this->id - ); - } + ); + } - /** - * Has invoice return true if this order has already an invoice - * - * @return bool - */ - public function hasInvoice() - { - return (bool)Db::getInstance()->getValue(' + /** + * Has invoice return true if this order has already an invoice + * + * @return bool + */ + public function hasInvoice() + { + return (bool)Db::getInstance()->getValue(' SELECT `id_order_invoice` FROM `'._DB_PREFIX_.'order_invoice` WHERE `id_order` = '.(int)$this->id. - (Configuration::get('PS_INVOICE') ? ' AND `number` > 0' : '') - ); - } + (Configuration::get('PS_INVOICE') ? ' AND `number` > 0' : '') + ); + } - /** - * Has Delivery return true if this order has already a delivery slip - * - * @return bool - */ - public function hasDelivery() - { - return (bool)Db::getInstance()->getValue(' + /** + * Has Delivery return true if this order has already a delivery slip + * + * @return bool + */ + public function hasDelivery() + { + return (bool)Db::getInstance()->getValue(' SELECT `id_order_invoice` FROM `'._DB_PREFIX_.'order_invoice` WHERE `id_order` = '.(int)$this->id.' AND `delivery_number` > 0' - ); - } + ); + } - /** - * Get warehouse associated to the order - * - * return array List of warehouse - */ - public function getWarehouseList() - { - $results = Db::getInstance()->executeS(' + /** + * Get warehouse associated to the order + * + * return array List of warehouse + */ + public function getWarehouseList() + { + $results = Db::getInstance()->executeS(' SELECT id_warehouse FROM `'._DB_PREFIX_.'order_detail` WHERE `id_order` = '.(int)$this->id.' GROUP BY id_warehouse'); - if (!$results) - return array(); + if (!$results) { + return array(); + } - $warehouse_list = array(); - foreach ($results as $row) - $warehouse_list[] = $row['id_warehouse']; + $warehouse_list = array(); + foreach ($results as $row) { + $warehouse_list[] = $row['id_warehouse']; + } - return $warehouse_list; - } + return $warehouse_list; + } - /** - * @since 1.5.0.4 - * @return OrderState or null if Order haven't a state - */ - public function getCurrentOrderState() - { - if ($this->current_state) - return new OrderState($this->current_state); - return null; - } + /** + * @since 1.5.0.4 + * @return OrderState or null if Order haven't a state + */ + public function getCurrentOrderState() + { + if ($this->current_state) { + return new OrderState($this->current_state); + } + return null; + } - /** - * @see ObjectModel::getWebserviceObjectList() - */ - public function getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit) - { - $sql_filter .= Shop::addSqlRestriction(Shop::SHARE_ORDER, 'main'); - return parent::getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit); - } + /** + * @see ObjectModel::getWebserviceObjectList() + */ + public function getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit) + { + $sql_filter .= Shop::addSqlRestriction(Shop::SHARE_ORDER, 'main'); + return parent::getWebserviceObjectList($sql_join, $sql_filter, $sql_sort, $sql_limit); + } - /** - * Get all other orders with the same reference - * - * @since 1.5.0.13 - */ - public function getBrother() - { - $collection = new PrestaShopCollection('order'); - $collection->where('reference', '=', $this->reference); - $collection->where('id_order', '<>', $this->id); - return $collection; - } + /** + * Get all other orders with the same reference + * + * @since 1.5.0.13 + */ + public function getBrother() + { + $collection = new PrestaShopCollection('order'); + $collection->where('reference', '=', $this->reference); + $collection->where('id_order', '<>', $this->id); + return $collection; + } - /** - * Get a collection of order payments - * - * @since 1.5.0.13 - */ - public function getOrderPayments() - { - return OrderPayment::getByOrderReference($this->reference); - } + /** + * Get a collection of order payments + * + * @since 1.5.0.13 + */ + public function getOrderPayments() + { + return OrderPayment::getByOrderReference($this->reference); + } - /** - * Return a unique reference like : GWJTHMZUN#2 - * - * With multishipping, order reference are the same for all orders made with the same cart - * in this case this method suffix the order reference by a # and the order number - * - * @since 1.5.0.14 - */ - public function getUniqReference() - { - $query = new DbQuery(); - $query->select('MIN(id_order) as min, MAX(id_order) as max'); - $query->from('orders'); - $query->where('id_cart = '.(int)$this->id_cart); + /** + * Return a unique reference like : GWJTHMZUN#2 + * + * With multishipping, order reference are the same for all orders made with the same cart + * in this case this method suffix the order reference by a # and the order number + * + * @since 1.5.0.14 + */ + public function getUniqReference() + { + $query = new DbQuery(); + $query->select('MIN(id_order) as min, MAX(id_order) as max'); + $query->from('orders'); + $query->where('id_cart = '.(int)$this->id_cart); - $order = Db::getInstance()->getRow($query); + $order = Db::getInstance()->getRow($query); - if ($order['min'] == $order['max']) - return $this->reference; - else - return $this->reference.'#'.($this->id + 1 - $order['min']); - } + if ($order['min'] == $order['max']) { + return $this->reference; + } else { + return $this->reference.'#'.($this->id + 1 - $order['min']); + } + } - /** - * Return a unique reference like : GWJTHMZUN#2 - * - * With multishipping, order reference are the same for all orders made with the same cart - * in this case this method suffix the order reference by a # and the order number - * - * @since 1.5.0.14 - */ - public static function getUniqReferenceOf($id_order) - { - $order = new Order($id_order); - return $order->getUniqReference(); - } + /** + * Return a unique reference like : GWJTHMZUN#2 + * + * With multishipping, order reference are the same for all orders made with the same cart + * in this case this method suffix the order reference by a # and the order number + * + * @since 1.5.0.14 + */ + public static function getUniqReferenceOf($id_order) + { + $order = new Order($id_order); + return $order->getUniqReference(); + } - /** - * Return id of carrier - * - * Get id of the carrier used in order - * - * @since 1.5.5.0 - */ - public function getIdOrderCarrier() - { - return (int)Db::getInstance()->getValue(' + /** + * Return id of carrier + * + * Get id of the carrier used in order + * + * @since 1.5.5.0 + */ + public function getIdOrderCarrier() + { + return (int)Db::getInstance()->getValue(' SELECT `id_order_carrier` FROM `'._DB_PREFIX_.'order_carrier` WHERE `id_order` = '.(int)$this->id); - } + } - public static function sortDocuments($a, $b) - { - if ($a->date_add == $b->date_add) - return 0; - return ($a->date_add < $b->date_add) ? -1 : 1; - } + public static function sortDocuments($a, $b) + { + if ($a->date_add == $b->date_add) { + return 0; + } + return ($a->date_add < $b->date_add) ? -1 : 1; + } - public function getWsShippingNumber() - { - $id_order_carrier = Db::getInstance()->getValue(' + public function getWsShippingNumber() + { + $id_order_carrier = Db::getInstance()->getValue(' SELECT `id_order_carrier` FROM `'._DB_PREFIX_.'order_carrier` WHERE `id_order` = '.(int)$this->id); - if ($id_order_carrier) - { - $order_carrier = new OrderCarrier($id_order_carrier); - return $order_carrier->tracking_number; - } - return $this->shipping_number; - } + if ($id_order_carrier) { + $order_carrier = new OrderCarrier($id_order_carrier); + return $order_carrier->tracking_number; + } + return $this->shipping_number; + } - public function setWsShippingNumber($shipping_number) - { - $id_order_carrier = Db::getInstance()->getValue(' + public function setWsShippingNumber($shipping_number) + { + $id_order_carrier = Db::getInstance()->getValue(' SELECT `id_order_carrier` FROM `'._DB_PREFIX_.'order_carrier` WHERE `id_order` = '.(int)$this->id); - if ($id_order_carrier) - { - $order_carrier = new OrderCarrier($id_order_carrier); - $order_carrier->tracking_number = $shipping_number; - $order_carrier->update(); - } - else - $this->shipping_number = $shipping_number; - return true; - } + if ($id_order_carrier) { + $order_carrier = new OrderCarrier($id_order_carrier); + $order_carrier->tracking_number = $shipping_number; + $order_carrier->update(); + } else { + $this->shipping_number = $shipping_number; + } + return true; + } - public function getWsCurrentState() - { - return $this->getCurrentState(); - } + /** + * @deprecated since 1.6.1 + */ + public function getWsCurrentState() + { + return $this->getCurrentState(); + } - public function setWsCurrentState($state) - { - if ($this->id) - $this->setCurrentState($state); - return true; - } + public function setWsCurrentState($state) + { + if ($this->id) { + $this->setCurrentState($state); + } + return true; + } - public function getProductTaxesDetails() - { - $round_type = $this->round_type; - if ($round_type == 0) - { - // if this is 0, it means the field did not exist - // at the time the order was made. - // Set it to old type, which was closest to line. - $round_type = Order::ROUND_LINE; - } + + /** + * By default this function was made for invoice, to compute tax amounts and balance delta (because of computation made on round values). + * If you provide $limitToOrderDetails, only these item will be taken into account. This option is usefull for order slip for example, + * where only sublist of the order is refunded. + * + * @param $limitToOrderDetails Optional array of OrderDetails to take into account. False by default to take all OrderDetails from the current Order. + * @return array A list of tax rows applied to the given OrderDetails (or all OrderDetails linked to the current Order). + */ + public function getProductTaxesDetails($limitToOrderDetails = false) + { + $round_type = $this->round_type; + if ($round_type == 0) { + // if this is 0, it means the field did not exist + // at the time the order was made. + // Set it to old type, which was closest to line. + $round_type = Order::ROUND_LINE; + } - // compute products discount - $order_discount_tax_excl = $this->total_discounts_tax_excl; + // compute products discount + $order_discount_tax_excl = $this->total_discounts_tax_excl; - $free_shipping_tax = 0; - $product_specific_discounts = array(); + $free_shipping_tax = 0; + $product_specific_discounts = array(); - $expected_total_base = $this->total_products - $this->total_discounts_tax_excl; + $expected_total_base = $this->total_products - $this->total_discounts_tax_excl; - foreach ($this->getCartRules() as $order_cart_rule) - { - if ($order_cart_rule['free_shipping'] && $free_shipping_tax === 0) - { - $free_shipping_tax = $this->total_shipping_tax_incl - $this->total_shipping_tax_excl; - $order_discount_tax_excl -= $this->total_shipping_tax_excl; - $expected_total_base += $this->total_shipping_tax_excl; - } + foreach ($this->getCartRules() as $order_cart_rule) { + if ($order_cart_rule['free_shipping'] && $free_shipping_tax === 0) { + $free_shipping_tax = $this->total_shipping_tax_incl - $this->total_shipping_tax_excl; + $order_discount_tax_excl -= $this->total_shipping_tax_excl; + $expected_total_base += $this->total_shipping_tax_excl; + } - $cart_rule = new CartRule($order_cart_rule['id_cart_rule']); - if ($cart_rule->reduction_product > 0) - { - if (empty($product_specific_discounts[$cart_rule->reduction_product])) - $product_specific_discounts[$cart_rule->reduction_product] = 0; + $cart_rule = new CartRule($order_cart_rule['id_cart_rule']); + if ($cart_rule->reduction_product > 0) { + if (empty($product_specific_discounts[$cart_rule->reduction_product])) { + $product_specific_discounts[$cart_rule->reduction_product] = 0; + } - $product_specific_discounts[$cart_rule->reduction_product] += $order_cart_rule['value_tax_excl']; - $order_discount_tax_excl -= $order_cart_rule['value_tax_excl']; - } - } + $product_specific_discounts[$cart_rule->reduction_product] += $order_cart_rule['value_tax_excl']; + $order_discount_tax_excl -= $order_cart_rule['value_tax_excl']; + } + } - $products_tax = $this->total_products_wt - $this->total_products; - $discounts_tax = $this->total_discounts_tax_incl - $this->total_discounts_tax_excl; + $products_tax = $this->total_products_wt - $this->total_products; + $discounts_tax = $this->total_discounts_tax_incl - $this->total_discounts_tax_excl; - // We add $free_shipping_tax because when there is free shipping, the tax that would - // be paid if there wasn't is included in $discounts_tax. - $expected_total_tax = $products_tax - $discounts_tax + $free_shipping_tax; - $actual_total_tax = 0; - $actual_total_base = 0; + // We add $free_shipping_tax because when there is free shipping, the tax that would + // be paid if there wasn't is included in $discounts_tax. + $expected_total_tax = $products_tax - $discounts_tax + $free_shipping_tax; + $actual_total_tax = 0; + $actual_total_base = 0; - $order_detail_tax_rows = array(); + $order_detail_tax_rows = array(); - $breakdown = array(); + $breakdown = array(); - // Get order_details - $order_details = $this->getOrderDetailList(); + // Get order_details + $order_details = $limitToOrderDetails ? $limitToOrderDetails : $this->getOrderDetailList(); - $order_ecotax_tax = 0; + $order_ecotax_tax = 0; - $tax_rates = array(); + $tax_rates = array(); - foreach ($order_details as $order_detail) - { - $id_order_detail = $order_detail['id_order_detail']; - $tax_calculator = OrderDetail::getTaxCalculatorStatic($id_order_detail); + foreach ($order_details as $order_detail) { + $id_order_detail = $order_detail['id_order_detail']; + $tax_calculator = OrderDetail::getTaxCalculatorStatic($id_order_detail); - // TODO: probably need to make an ecotax tax breakdown here instead, - // but it seems unlikely there will be different tax rates applied to the - // ecotax in the same order in the real world - $unit_ecotax_tax = $order_detail['ecotax'] * $order_detail['ecotax_tax_rate'] / 100.0; - $order_ecotax_tax += $order_detail['product_quantity'] * $unit_ecotax_tax; + // TODO: probably need to make an ecotax tax breakdown here instead, + // but it seems unlikely there will be different tax rates applied to the + // ecotax in the same order in the real world + $unit_ecotax_tax = $order_detail['ecotax'] * $order_detail['ecotax_tax_rate'] / 100.0; + $order_ecotax_tax += $order_detail['product_quantity'] * $unit_ecotax_tax; - $discount_ratio = ($order_detail['unit_price_tax_excl'] + $order_detail['ecotax']) / $this->total_products; + $discount_ratio = 0; - // share of global discount - $discounted_price_tax_excl = $order_detail['unit_price_tax_excl'] - $discount_ratio * $order_discount_tax_excl; - // specific discount - if (!empty($product_specific_discounts[$order_detail['product_id']])) - $discounted_price_tax_excl -= $product_specific_discounts[$order_detail['product_id']]; + if ($this->total_products > 0) { + $discount_ratio = ($order_detail['unit_price_tax_excl'] + $order_detail['ecotax']) / $this->total_products; + } - $quantity = $order_detail['product_quantity']; + // share of global discount + $discounted_price_tax_excl = $order_detail['unit_price_tax_excl'] - $discount_ratio * $order_discount_tax_excl; + // specific discount + if (!empty($product_specific_discounts[$order_detail['product_id']])) { + $discounted_price_tax_excl -= $product_specific_discounts[$order_detail['product_id']]; + } - foreach ($tax_calculator->taxes as $tax) - $tax_rates[$tax->id] = $tax->rate; + $quantity = $order_detail['product_quantity']; - foreach ($tax_calculator->getTaxesAmount($discounted_price_tax_excl) as $id_tax => $unit_amount) - { - $total_tax_base = 0; - switch ($round_type) - { - case Order::ROUND_ITEM: - $total_tax_base = $quantity * Tools::ps_round($discounted_price_tax_excl, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); - $total_amount = $quantity * Tools::ps_round($unit_amount, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); - break; - case Order::ROUND_LINE: - $total_tax_base = Tools::ps_round($quantity * $discounted_price_tax_excl, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); - $total_amount = Tools::ps_round($quantity * $unit_amount, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); - break; - case Order::ROUND_TOTAL: - $total_tax_base = $quantity * $discounted_price_tax_excl; - $total_amount = $quantity * $unit_amount; - break; - } + foreach ($tax_calculator->taxes as $tax) { + $tax_rates[$tax->id] = $tax->rate; + } - if (!isset($breakdown[$id_tax])) - $breakdown[$id_tax] = array('tax_base' => 0, 'tax_amount' => 0); + foreach ($tax_calculator->getTaxesAmount($discounted_price_tax_excl) as $id_tax => $unit_amount) { + $total_tax_base = 0; + switch ($round_type) { + case Order::ROUND_ITEM: + $total_tax_base = $quantity * Tools::ps_round($discounted_price_tax_excl, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); + $total_amount = $quantity * Tools::ps_round($unit_amount, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); + break; + case Order::ROUND_LINE: + $total_tax_base = Tools::ps_round($quantity * $discounted_price_tax_excl, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); + $total_amount = Tools::ps_round($quantity * $unit_amount, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); + break; + case Order::ROUND_TOTAL: + $total_tax_base = $quantity * $discounted_price_tax_excl; + $total_amount = $quantity * $unit_amount; + break; + } - $breakdown[$id_tax]['tax_base'] += $total_tax_base; - $breakdown[$id_tax]['tax_amount'] += $total_amount; + if (!isset($breakdown[$id_tax])) { + $breakdown[$id_tax] = array('tax_base' => 0, 'tax_amount' => 0); + } - $order_detail_tax_rows[] = array( - 'id_order_detail' => $id_order_detail, - 'id_tax' => $id_tax, - 'tax_rate' => $tax_rates[$id_tax], - 'unit_tax_base' => $discounted_price_tax_excl, - 'total_tax_base' => $total_tax_base, - 'unit_amount' => $unit_amount, - 'total_amount' => $total_amount - ); - } - } + $breakdown[$id_tax]['tax_base'] += $total_tax_base; + $breakdown[$id_tax]['tax_amount'] += $total_amount; - if (!empty($order_detail_tax_rows)) - { - foreach ($breakdown as $data) - { - $actual_total_tax += Tools::ps_round($data['tax_amount'], _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); - $actual_total_base += Tools::ps_round($data['tax_base'], _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); - } + $order_detail_tax_rows[] = array( + 'id_order_detail' => $id_order_detail, + 'id_tax' => $id_tax, + 'tax_rate' => $tax_rates[$id_tax], + 'unit_tax_base' => $discounted_price_tax_excl, + 'total_tax_base' => $total_tax_base, + 'unit_amount' => $unit_amount, + 'total_amount' => $total_amount + ); + } + } - $order_ecotax_tax = Tools::ps_round($order_ecotax_tax, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); + if (!empty($order_detail_tax_rows)) { + foreach ($breakdown as $data) { + $actual_total_tax += Tools::ps_round($data['tax_amount'], _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); + $actual_total_base += Tools::ps_round($data['tax_base'], _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); + } - $tax_rounding_error = $expected_total_tax - $actual_total_tax - $order_ecotax_tax; - if ($tax_rounding_error !== 0) - Tools::spreadAmount($tax_rounding_error, _PS_PRICE_COMPUTE_PRECISION_, $order_detail_tax_rows, 'total_amount'); + $order_ecotax_tax = Tools::ps_round($order_ecotax_tax, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode); - $base_rounding_error = $expected_total_base - $actual_total_base; - if ($base_rounding_error !== 0) - Tools::spreadAmount($base_rounding_error, _PS_PRICE_COMPUTE_PRECISION_, $order_detail_tax_rows, 'total_tax_base'); - } + $tax_rounding_error = $expected_total_tax - $actual_total_tax - $order_ecotax_tax; + if ($tax_rounding_error !== 0) { + Tools::spreadAmount($tax_rounding_error, _PS_PRICE_COMPUTE_PRECISION_, $order_detail_tax_rows, 'total_amount'); + } - return $order_detail_tax_rows; - } + $base_rounding_error = $expected_total_base - $actual_total_base; + if ($base_rounding_error !== 0) { + Tools::spreadAmount($base_rounding_error, _PS_PRICE_COMPUTE_PRECISION_, $order_detail_tax_rows, 'total_tax_base'); + } + } - /** - * The primary purpose of this method is to be - * called at the end of the generation of each order - * in PaymentModule::validateOrder, to fill in - * the order_detail_tax table with taxes - * that will add up in such a way that - * the sum of the tax amounts in the product tax breakdown - * is equal to the difference between products with tax and - * products without tax. - */ - public function updateOrderDetailTax() - { - $order_detail_tax_rows_to_insert = $this->getProductTaxesDetails(); + return $order_detail_tax_rows; + } - if (empty($order_detail_tax_rows_to_insert)) - return; + /** + * The primary purpose of this method is to be + * called at the end of the generation of each order + * in PaymentModule::validateOrder, to fill in + * the order_detail_tax table with taxes + * that will add up in such a way that + * the sum of the tax amounts in the product tax breakdown + * is equal to the difference between products with tax and + * products without tax. + */ + public function updateOrderDetailTax() + { + $order_detail_tax_rows_to_insert = $this->getProductTaxesDetails(); - $old_id_order_details = array(); - $values = array(); - foreach ($order_detail_tax_rows_to_insert as $row) - { - $old_id_order_details[] = (int)$row['id_order_detail']; - $values[] = '('.(int)$row['id_order_detail'].', '.(int)$row['id_tax'].', '.(float)$row['unit_amount'].', '.(float)$row['total_amount'].')'; - } + if (empty($order_detail_tax_rows_to_insert)) { + return; + } - // Remove current order_detail_tax'es - Db::getInstance()->execute( - 'DELETE FROM `'._DB_PREFIX_.'order_detail_tax` WHERE id_order_detail IN ('.implode(', ', $old_id_order_details).')' - ); + $old_id_order_details = array(); + $values = array(); + foreach ($order_detail_tax_rows_to_insert as $row) { + $old_id_order_details[] = (int)$row['id_order_detail']; + $values[] = '('.(int)$row['id_order_detail'].', '.(int)$row['id_tax'].', '.(float)$row['unit_amount'].', '.(float)$row['total_amount'].')'; + } - // Insert the adjusted ones instead - Db::getInstance()->execute( - 'INSERT INTO `'._DB_PREFIX_.'order_detail_tax` (id_order_detail, id_tax, unit_amount, total_amount) VALUES '.implode(', ', $values) - ); - } + // Remove current order_detail_tax'es + Db::getInstance()->execute( + 'DELETE FROM `'._DB_PREFIX_.'order_detail_tax` WHERE id_order_detail IN ('.implode(', ', $old_id_order_details).')' + ); - public function getOrderDetailTaxes() - { - return Db::getInstance()->executeS( - 'SELECT od.id_tax_rules_group, od.product_quantity, odt.*, t.* FROM '._DB_PREFIX_.'orders o '. - 'INNER JOIN '._DB_PREFIX_.'order_detail od ON od.id_order = o.id_order '. - 'INNER JOIN '._DB_PREFIX_.'order_detail_tax odt ON odt.id_order_detail = od.id_order_detail '. - 'INNER JOIN '._DB_PREFIX_.'tax t ON t.id_tax = odt.id_tax '. - 'WHERE o.id_order = '.(int)$this->id - ); - } + // Insert the adjusted ones instead + Db::getInstance()->execute( + 'INSERT INTO `'._DB_PREFIX_.'order_detail_tax` (id_order_detail, id_tax, unit_amount, total_amount) VALUES '.implode(', ', $values) + ); + } + + public function getOrderDetailTaxes() + { + return Db::getInstance()->executeS( + 'SELECT od.id_tax_rules_group, od.product_quantity, odt.*, t.* FROM '._DB_PREFIX_.'orders o '. + 'INNER JOIN '._DB_PREFIX_.'order_detail od ON od.id_order = o.id_order '. + 'INNER JOIN '._DB_PREFIX_.'order_detail_tax odt ON odt.id_order_detail = od.id_order_detail '. + 'INNER JOIN '._DB_PREFIX_.'tax t ON t.id_tax = odt.id_tax '. + 'WHERE o.id_order = '.(int)$this->id + ); + } } diff --git a/classes/order/OrderCarrier.php b/classes/order/OrderCarrier.php index 214c402e..ecc924a1 100644 --- a/classes/order/OrderCarrier.php +++ b/classes/order/OrderCarrier.php @@ -26,55 +26,55 @@ class OrderCarrierCore extends ObjectModel { - /** @var int */ - public $id_order_carrier; + /** @var int */ + public $id_order_carrier; - /** @var int */ - public $id_order; + /** @var int */ + public $id_order; - /** @var int */ - public $id_carrier; + /** @var int */ + public $id_carrier; - /** @var int */ - public $id_order_invoice; + /** @var int */ + public $id_order_invoice; - /** @var float */ - public $weight; + /** @var float */ + public $weight; - /** @var float */ - public $shipping_cost_tax_excl; + /** @var float */ + public $shipping_cost_tax_excl; - /** @var float */ - public $shipping_cost_tax_incl; + /** @var float */ + public $shipping_cost_tax_incl; - /** @var int */ - public $tracking_number; + /** @var int */ + public $tracking_number; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'order_carrier', - 'primary' => 'id_order_carrier', - 'fields' => array( - 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_carrier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_order_invoice' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'weight' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'shipping_cost_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'shipping_cost_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'tracking_number' => array('type' => self::TYPE_STRING, 'validate' => 'isTrackingNumber'), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'order_carrier', + 'primary' => 'id_order_carrier', + 'fields' => array( + 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_carrier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_order_invoice' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'weight' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'shipping_cost_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'shipping_cost_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'tracking_number' => array('type' => self::TYPE_STRING, 'validate' => 'isTrackingNumber'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_order' => array('xlink_resource' => 'orders'), - 'id_carrier' => array('xlink_resource' => 'carriers'), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_order' => array('xlink_resource' => 'orders'), + 'id_carrier' => array('xlink_resource' => 'carriers'), + ), + ); } diff --git a/classes/order/OrderCartRule.php b/classes/order/OrderCartRule.php index 0ea13dcd..e8deac7c 100644 --- a/classes/order/OrderCartRule.php +++ b/classes/order/OrderCartRule.php @@ -26,50 +26,50 @@ class OrderCartRuleCore extends ObjectModel { - /** @var int */ - public $id_order_cart_rule; + /** @var int */ + public $id_order_cart_rule; - /** @var int */ - public $id_order; + /** @var int */ + public $id_order; - /** @var int */ - public $id_cart_rule; + /** @var int */ + public $id_cart_rule; - /** @var int */ - public $id_order_invoice; + /** @var int */ + public $id_order_invoice; - /** @var string */ - public $name; + /** @var string */ + public $name; - /** @var float value (tax incl.) of voucher */ - public $value; + /** @var float value (tax incl.) of voucher */ + public $value; - /** @var float value (tax excl.) of voucher */ - public $value_tax_excl; + /** @var float value (tax excl.) of voucher */ + public $value_tax_excl; - /** @var bool value : voucher gives free shipping or not */ - public $free_shipping; + /** @var bool value : voucher gives free shipping or not */ + public $free_shipping; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'order_cart_rule', - 'primary' => 'id_order_cart_rule', - 'fields' => array( - 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_cart_rule' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_order_invoice' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'required' => true), - 'value' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), - 'value_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), - 'free_shipping' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool') - ) - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'order_cart_rule', + 'primary' => 'id_order_cart_rule', + 'fields' => array( + 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_cart_rule' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_order_invoice' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'required' => true), + 'value' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), + 'value_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), + 'free_shipping' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool') + ) + ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_order' => array('xlink_resource' => 'orders'), - ), - ); -} \ No newline at end of file + protected $webserviceParameters = array( + 'fields' => array( + 'id_order' => array('xlink_resource' => 'orders'), + ), + ); +} diff --git a/classes/order/OrderDetail.php b/classes/order/OrderDetail.php index fcad3665..9608bc54 100644 --- a/classes/order/OrderDetail.php +++ b/classes/order/OrderDetail.php @@ -26,710 +26,733 @@ class OrderDetailCore extends ObjectModel { - /** @var int */ - public $id_order_detail; + /** @var int */ + public $id_order_detail; - /** @var int */ - public $id_order; + /** @var int */ + public $id_order; - /** @var int */ - public $id_order_invoice; + /** @var int */ + public $id_order_invoice; - /** @var int */ - public $product_id; + /** @var int */ + public $product_id; - /** @var int */ - public $id_shop; + /** @var int */ + public $id_shop; - /** @var int */ - public $product_attribute_id; + /** @var int */ + public $product_attribute_id; - /** @var string */ - public $product_name; + /** @var string */ + public $product_name; - /** @var int */ - public $product_quantity; + /** @var int */ + public $product_quantity; - /** @var int */ - public $product_quantity_in_stock; + /** @var int */ + public $product_quantity_in_stock; - /** @var int */ - public $product_quantity_return; + /** @var int */ + public $product_quantity_return; - /** @var int */ - public $product_quantity_refunded; + /** @var int */ + public $product_quantity_refunded; - /** @var int */ - public $product_quantity_reinjected; + /** @var int */ + public $product_quantity_reinjected; - /** @var float */ - public $product_price; + /** @var float */ + public $product_price; - /** @var float */ - public $original_product_price; + /** @var float */ + public $original_product_price; - /** @var float */ - public $unit_price_tax_incl; + /** @var float */ + public $unit_price_tax_incl; - /** @var float */ - public $unit_price_tax_excl; + /** @var float */ + public $unit_price_tax_excl; - /** @var float */ - public $total_price_tax_incl; + /** @var float */ + public $total_price_tax_incl; - /** @var float */ - public $total_price_tax_excl; + /** @var float */ + public $total_price_tax_excl; - /** @var float */ - public $reduction_percent; + /** @var float */ + public $reduction_percent; - /** @var float */ - public $reduction_amount; + /** @var float */ + public $reduction_amount; - /** @var float */ - public $reduction_amount_tax_excl; + /** @var float */ + public $reduction_amount_tax_excl; - /** @var float */ - public $reduction_amount_tax_incl; + /** @var float */ + public $reduction_amount_tax_incl; - /** @var float */ - public $group_reduction; + /** @var float */ + public $group_reduction; - /** @var float */ - public $product_quantity_discount; + /** @var float */ + public $product_quantity_discount; - /** @var string */ - public $product_ean13; + /** @var string */ + public $product_ean13; - /** @var string */ - public $product_upc; + /** @var string */ + public $product_upc; - /** @var string */ - public $product_reference; + /** @var string */ + public $product_reference; - /** @var string */ - public $product_supplier_reference; + /** @var string */ + public $product_supplier_reference; - /** @var float */ - public $product_weight; + /** @var float */ + public $product_weight; - /** @var float */ - public $ecotax; + /** @var float */ + public $ecotax; - /** @var float */ - public $ecotax_tax_rate; + /** @var float */ + public $ecotax_tax_rate; - /** @var int */ - public $discount_quantity_applied; + /** @var int */ + public $discount_quantity_applied; - /** @var string */ - public $download_hash; + /** @var string */ + public $download_hash; - /** @var int */ - public $download_nb; + /** @var int */ + public $download_nb; - /** @var datetime */ - public $download_deadline; + /** @var datetime */ + public $download_deadline; - /** @var string $tax_name **/ - public $tax_name; + /** @var string $tax_name **/ + public $tax_name; - /** @var float $tax_rate **/ - public $tax_rate; + /** @var float $tax_rate **/ + public $tax_rate; - /** @var float $tax_computation_method **/ - public $tax_computation_method; + /** @var float $tax_computation_method **/ + public $tax_computation_method; - /** @var int Id tax rules group */ - public $id_tax_rules_group; + /** @var int Id tax rules group */ + public $id_tax_rules_group; - /** @var int Id warehouse */ - public $id_warehouse; + /** @var int Id warehouse */ + public $id_warehouse; - /** @var float additional shipping price tax excl */ - public $total_shipping_price_tax_excl; + /** @var float additional shipping price tax excl */ + public $total_shipping_price_tax_excl; - /** @var float additional shipping price tax incl */ - public $total_shipping_price_tax_incl; + /** @var float additional shipping price tax incl */ + public $total_shipping_price_tax_incl; - /** @var float */ - public $purchase_supplier_price; + /** @var float */ + public $purchase_supplier_price; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'order_detail', - 'primary' => 'id_order_detail', - 'fields' => array( - 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_order_invoice' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_warehouse' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'product_id' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'product_attribute_id' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'product_name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true), - 'product_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), - 'product_quantity_in_stock' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'product_quantity_return' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'product_quantity_refunded' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'product_quantity_reinjected' =>array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'product_price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'reduction_percent' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'reduction_amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'reduction_amount_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'reduction_amount_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'group_reduction' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'product_quantity_discount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'product_ean13' => array('type' => self::TYPE_STRING, 'validate' => 'isEan13'), - 'product_upc' => array('type' => self::TYPE_STRING, 'validate' => 'isUpc'), - 'product_reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference'), - 'product_supplier_reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference'), - 'product_weight' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'tax_name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'), - 'tax_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'tax_computation_method' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_tax_rules_group' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'ecotax' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'ecotax_tax_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'discount_quantity_applied' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'download_hash' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'), - 'download_nb' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - 'download_deadline' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat'), - 'unit_price_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'unit_price_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_price_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_price_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'purchase_supplier_price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'original_product_price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice') - ), - ); + /** @var float */ + public $original_wholesale_price; - protected $webserviceParameters = array( - 'fields' => array ( - 'id_order' => array('xlink_resource' => 'orders'), - 'product_id' => array('xlink_resource' => 'products'), - 'product_attribute_id' => array('xlink_resource' => 'combinations'), - 'product_quantity_reinjected' => array(), - 'group_reduction' => array(), - 'discount_quantity_applied' => array(), - 'download_hash' => array(), - 'download_deadline' => array() - ), - 'hidden_fields' => array('tax_rate', 'tax_name'), - 'associations' => array( - 'taxes' => array('resource' => 'tax', 'getter' => 'getWsTaxes', 'setter' => false, - 'fields' => array('id' => array(), ), - ), - )); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'order_detail', + 'primary' => 'id_order_detail', + 'fields' => array( + 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_order_invoice' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_warehouse' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'product_id' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'product_attribute_id' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'product_name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true), + 'product_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), + 'product_quantity_in_stock' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'product_quantity_return' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'product_quantity_refunded' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'product_quantity_reinjected' =>array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'product_price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'reduction_percent' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'reduction_amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'reduction_amount_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'reduction_amount_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'group_reduction' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'product_quantity_discount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'product_ean13' => array('type' => self::TYPE_STRING, 'validate' => 'isEan13'), + 'product_upc' => array('type' => self::TYPE_STRING, 'validate' => 'isUpc'), + 'product_reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference'), + 'product_supplier_reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference'), + 'product_weight' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'tax_name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'), + 'tax_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'tax_computation_method' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_tax_rules_group' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'ecotax' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'ecotax_tax_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'discount_quantity_applied' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'download_hash' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'), + 'download_nb' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + 'download_deadline' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat'), + 'unit_price_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'unit_price_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_price_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_price_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_shipping_price_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_shipping_price_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'purchase_supplier_price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'original_product_price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'original_wholesale_price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice') + ), + ); - /** @var bool */ - protected $outOfStock = false; + protected $webserviceParameters = array( + 'fields' => array( + 'id_order' => array('xlink_resource' => 'orders'), + 'product_id' => array('xlink_resource' => 'products'), + 'product_attribute_id' => array('xlink_resource' => 'combinations'), + 'product_quantity_reinjected' => array(), + 'group_reduction' => array(), + 'discount_quantity_applied' => array(), + 'download_hash' => array(), + 'download_deadline' => array() + ), + 'hidden_fields' => array('tax_rate', 'tax_name'), + 'associations' => array( + 'taxes' => array('resource' => 'tax', 'getter' => 'getWsTaxes', 'setter' => false, + 'fields' => array('id' => array(), ), + ), + )); - /** @var TaxCalculator object */ - protected $tax_calculator = null; + /** @var bool */ + protected $outOfStock = false; - /** @var Address object */ - protected $vat_address = null; + /** @var TaxCalculator object */ + protected $tax_calculator = null; - /** @var Address object */ - protected $specificPrice = null; + /** @var Address object */ + protected $vat_address = null; - /** @var Customer object */ - protected $customer = null; + /** @var Address object */ + protected $specificPrice = null; - /** @var Context object */ - protected $context = null; + /** @var Customer object */ + protected $customer = null; - public function __construct($id = null, $id_lang = null, $context = null) - { - $this->context = $context; - $id_shop = null; - if ($this->context != null && isset($this->context->shop)) - $id_shop = $this->context->shop->id; - parent::__construct($id, $id_lang, $id_shop); + /** @var Context object */ + protected $context = null; - if ($context == null) - $context = Context::getContext(); - $this->context = $context->cloneContext(); - } + public function __construct($id = null, $id_lang = null, $context = null) + { + $this->context = $context; + $id_shop = null; + if ($this->context != null && isset($this->context->shop)) { + $id_shop = $this->context->shop->id; + } + parent::__construct($id, $id_lang, $id_shop); - public function delete() - { - if (!$res = parent::delete()) - return false; + if ($context == null) { + $context = Context::getContext(); + } + $this->context = $context->cloneContext(); + } - Db::getInstance()->delete('order_detail_tax', 'id_order_detail='.(int)$this->id); + public function delete() + { + if (!$res = parent::delete()) { + return false; + } - return $res; - } + Db::getInstance()->delete('order_detail_tax', 'id_order_detail='.(int)$this->id); - protected function setContext($id_shop) - { - if ($this->context->shop->id != $id_shop) - $this->context->shop = new Shop((int)$id_shop); - } + return $res; + } - public static function getDownloadFromHash($hash) - { - if ($hash == '') return false; - $sql = 'SELECT * + protected function setContext($id_shop) + { + if ($this->context->shop->id != $id_shop) { + $this->context->shop = new Shop((int)$id_shop); + } + } + + public static function getDownloadFromHash($hash) + { + if ($hash == '') { + return false; + } + $sql = 'SELECT * FROM `'._DB_PREFIX_.'order_detail` od LEFT JOIN `'._DB_PREFIX_.'product_download` pd ON (od.`product_id`=pd.`id_product`) WHERE od.`download_hash` = \''.pSQL(strval($hash)).'\' AND pd.`active` = 1'; - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); + } - public static function incrementDownload($id_order_detail, $increment = 1) - { - $sql = 'UPDATE `'._DB_PREFIX_.'order_detail` + public static function incrementDownload($id_order_detail, $increment = 1) + { + $sql = 'UPDATE `'._DB_PREFIX_.'order_detail` SET `download_nb` = `download_nb` + '.(int)$increment.' WHERE `id_order_detail`= '.(int)$id_order_detail.' LIMIT 1'; - return Db::getInstance()->execute($sql); - } + return Db::getInstance()->execute($sql); + } - /** - * Returns the tax calculator associated to this order detail. - * @since 1.5.0.1 - * @return TaxCalculator - */ - public function getTaxCalculator() - { - return OrderDetail::getTaxCalculatorStatic($this->id); - } + /** + * Returns the tax calculator associated to this order detail. + * @since 1.5.0.1 + * @return TaxCalculator + */ + public function getTaxCalculator() + { + return OrderDetail::getTaxCalculatorStatic($this->id); + } - /** - * Return the tax calculator associated to this order_detail - * @since 1.5.0.1 - * @param int $id_order_detail - * @return TaxCalculator - */ - public static function getTaxCalculatorStatic($id_order_detail) - { - $sql = 'SELECT t.*, d.`tax_computation_method` + /** + * Return the tax calculator associated to this order_detail + * @since 1.5.0.1 + * @param int $id_order_detail + * @return TaxCalculator + */ + public static function getTaxCalculatorStatic($id_order_detail) + { + $sql = 'SELECT t.*, d.`tax_computation_method` FROM `'._DB_PREFIX_.'order_detail_tax` t LEFT JOIN `'._DB_PREFIX_.'order_detail` d ON (d.`id_order_detail` = t.`id_order_detail`) WHERE d.`id_order_detail` = '.(int)$id_order_detail; - $computation_method = 1; - $taxes = array(); - if ($results = Db::getInstance()->executeS($sql)) - { - foreach ($results as $result) - $taxes[] = new Tax((int)$result['id_tax']); + $computation_method = 1; + $taxes = array(); + if ($results = Db::getInstance()->executeS($sql)) { + foreach ($results as $result) { + $taxes[] = new Tax((int)$result['id_tax']); + } - $computation_method = $result['tax_computation_method']; - } + $computation_method = $result['tax_computation_method']; + } - return new TaxCalculator($taxes, $computation_method); - } + return new TaxCalculator($taxes, $computation_method); + } - /** - * Save the tax calculator - * @since 1.5.0.1 - * @deprecated Functionality moved to Order::updateOrderDetailTax - * because we need the full order object to do a good job here. - * Will no longer be supported after 1.6.1 - * @return bool - */ - public function saveTaxCalculator(Order $order, $replace = false) - { - // Nothing to save - if ($this->tax_calculator == null) - return true; + /** + * Save the tax calculator + * @since 1.5.0.1 + * @deprecated Functionality moved to Order::updateOrderDetailTax + * because we need the full order object to do a good job here. + * Will no longer be supported after 1.6.1 + * @return bool + */ + public function saveTaxCalculator(Order $order, $replace = false) + { + // Nothing to save + if ($this->tax_calculator == null) { + return true; + } - if (!($this->tax_calculator instanceOf TaxCalculator)) - return false; + if (!($this->tax_calculator instanceof TaxCalculator)) { + return false; + } - if (count($this->tax_calculator->taxes) == 0) - return true; + if (count($this->tax_calculator->taxes) == 0) { + return true; + } - if ($order->total_products <= 0) - return true; + if ($order->total_products <= 0) { + return true; + } - $shipping_tax_amount = 0; + $shipping_tax_amount = 0; - foreach ($order->getCartRules() as $cart_rule) - if ($cart_rule['free_shipping']) - { - $shipping_tax_amount = $order->total_shipping_tax_excl; - break; - } + foreach ($order->getCartRules() as $cart_rule) { + if ($cart_rule['free_shipping']) { + $shipping_tax_amount = $order->total_shipping_tax_excl; + break; + } + } - $ratio = $this->unit_price_tax_excl / $order->total_products; - $order_reduction_amount = ($order->total_discounts_tax_excl - $shipping_tax_amount) * $ratio; - $discounted_price_tax_excl = $this->unit_price_tax_excl - $order_reduction_amount; + $ratio = $this->unit_price_tax_excl / $order->total_products; + $order_reduction_amount = ($order->total_discounts_tax_excl - $shipping_tax_amount) * $ratio; + $discounted_price_tax_excl = $this->unit_price_tax_excl - $order_reduction_amount; - $values = ''; - foreach ($this->tax_calculator->getTaxesAmount($discounted_price_tax_excl) as $id_tax => $amount) - { - switch (Configuration::get('PS_ROUND_TYPE')) - { - case Order::ROUND_ITEM: - $unit_amount = (float)Tools::ps_round($amount, _PS_PRICE_COMPUTE_PRECISION_); - $total_amount = $unit_amount * $this->product_quantity; - break; - case Order::ROUND_LINE: - $unit_amount = $amount; - $total_amount = Tools::ps_round($unit_amount * $this->product_quantity, _PS_PRICE_COMPUTE_PRECISION_); - break; - case Order::ROUND_TOTAL: - $unit_amount = $amount; - $total_amount = $unit_amount * $this->product_quantity; - break; - } + $values = ''; + foreach ($this->tax_calculator->getTaxesAmount($discounted_price_tax_excl) as $id_tax => $amount) { + switch (Configuration::get('PS_ROUND_TYPE')) { + case Order::ROUND_ITEM: + $unit_amount = (float)Tools::ps_round($amount, _PS_PRICE_COMPUTE_PRECISION_); + $total_amount = $unit_amount * $this->product_quantity; + break; + case Order::ROUND_LINE: + $unit_amount = $amount; + $total_amount = Tools::ps_round($unit_amount * $this->product_quantity, _PS_PRICE_COMPUTE_PRECISION_); + break; + case Order::ROUND_TOTAL: + $unit_amount = $amount; + $total_amount = $unit_amount * $this->product_quantity; + break; + } - $values .= '('.(int)$this->id.','.(int)$id_tax.','.(float)$unit_amount.','.(float)$total_amount.'),'; - } + $values .= '('.(int)$this->id.','.(int)$id_tax.','.(float)$unit_amount.','.(float)$total_amount.'),'; + } - if ($replace) - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'order_detail_tax` WHERE id_order_detail='.(int)$this->id); + if ($replace) { + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'order_detail_tax` WHERE id_order_detail='.(int)$this->id); + } - $values = rtrim($values, ','); - $sql = 'INSERT INTO `'._DB_PREFIX_.'order_detail_tax` (id_order_detail, id_tax, unit_amount, total_amount) + $values = rtrim($values, ','); + $sql = 'INSERT INTO `'._DB_PREFIX_.'order_detail_tax` (id_order_detail, id_tax, unit_amount, total_amount) VALUES '.$values; - return Db::getInstance()->execute($sql); - } + return Db::getInstance()->execute($sql); + } - public function updateTaxAmount($order) - { - $this->setContext((int)$this->id_shop); - $address = new Address((int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); - $tax_manager = TaxManagerFactory::getManager($address, (int)Product::getIdTaxRulesGroupByIdProduct((int)$this->product_id, $this->context)); - $this->tax_calculator = $tax_manager->getTaxCalculator(); + public function updateTaxAmount($order) + { + $this->setContext((int)$this->id_shop); + $address = new Address((int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); + $tax_manager = TaxManagerFactory::getManager($address, (int)Product::getIdTaxRulesGroupByIdProduct((int)$this->product_id, $this->context)); + $this->tax_calculator = $tax_manager->getTaxCalculator(); - return $this->saveTaxCalculator($order, true); - } + return $this->saveTaxCalculator($order, true); + } - /** - * Get a detailed order list of an id_order - * @param int $id_order - * @return array - */ - public static function getList($id_order) - { - return Db::getInstance()->executeS('SELECT * FROM `'._DB_PREFIX_.'order_detail` WHERE `id_order` = '.(int)$id_order); - } + /** + * Get a detailed order list of an id_order + * @param int $id_order + * @return array + */ + public static function getList($id_order) + { + return Db::getInstance()->executeS('SELECT * FROM `'._DB_PREFIX_.'order_detail` WHERE `id_order` = '.(int)$id_order); + } - public function getTaxList() - { - return self::getTaxList($this->id); - } + public function getTaxList() + { + return self::getTaxList($this->id); + } - public static function getTaxListStatic($id_order_detail) - { - $sql = 'SELECT * FROM `'._DB_PREFIX_.'order_detail_tax` + public static function getTaxListStatic($id_order_detail) + { + $sql = 'SELECT * FROM `'._DB_PREFIX_.'order_detail_tax` WHERE `id_order_detail` = '.(int)$id_order_detail; - return Db::getInstance()->executeS($sql); - } + return Db::getInstance()->executeS($sql); + } - /* - * Set virtual product information - * @param array $product - */ - protected function setVirtualProductInformation($product) - { - // Add some informations for virtual products - $this->download_deadline = '0000-00-00 00:00:00'; - $this->download_hash = null; + /* + * Set virtual product information + * @param array $product + */ + protected function setVirtualProductInformation($product) + { + // Add some informations for virtual products + $this->download_deadline = '0000-00-00 00:00:00'; + $this->download_hash = null; - if ($id_product_download = ProductDownload::getIdFromIdProduct((int)$product['id_product'])) - { - $product_download = new ProductDownload((int)$id_product_download); - $this->download_deadline = $product_download->getDeadLine(); - $this->download_hash = $product_download->getHash(); + if ($id_product_download = ProductDownload::getIdFromIdProduct((int)$product['id_product'])) { + $product_download = new ProductDownload((int)$id_product_download); + $this->download_deadline = $product_download->getDeadLine(); + $this->download_hash = $product_download->getHash(); - unset($product_download); - } - } + unset($product_download); + } + } - /** - * Check the order status - * @param array $product - * @param int $id_order_state - */ - protected function checkProductStock($product, $id_order_state) - { - if ($id_order_state != Configuration::get('PS_OS_CANCELED') && $id_order_state != Configuration::get('PS_OS_ERROR')) - { - $update_quantity = true; - if (!StockAvailable::dependsOnStock($product['id_product'])) - $update_quantity = StockAvailable::updateQuantity($product['id_product'], $product['id_product_attribute'], -(int)$product['cart_quantity']); + /** + * Check the order status + * @param array $product + * @param int $id_order_state + */ + protected function checkProductStock($product, $id_order_state) + { + if ($id_order_state != Configuration::get('PS_OS_CANCELED') && $id_order_state != Configuration::get('PS_OS_ERROR')) { + $update_quantity = true; + if (!StockAvailable::dependsOnStock($product['id_product'])) { + $update_quantity = StockAvailable::updateQuantity($product['id_product'], $product['id_product_attribute'], -(int)$product['cart_quantity']); + } - if ($update_quantity) - $product['stock_quantity'] -= $product['cart_quantity']; + if ($update_quantity) { + $product['stock_quantity'] -= $product['cart_quantity']; + } - if ($product['stock_quantity'] < 0 && Configuration::get('PS_STOCK_MANAGEMENT')) - $this->outOfStock = true; - Product::updateDefaultAttribute($product['id_product']); - } - } + if ($product['stock_quantity'] < 0 && Configuration::get('PS_STOCK_MANAGEMENT')) { + $this->outOfStock = true; + } + Product::updateDefaultAttribute($product['id_product']); + } + } - /** - * Apply tax to the product - * @param object $order - * @param array $product - */ - protected function setProductTax(Order $order, $product) - { - $this->ecotax = Tools::convertPrice(floatval($product['ecotax']), intval($order->id_currency)); + /** + * Apply tax to the product + * @param object $order + * @param array $product + */ + protected function setProductTax(Order $order, $product) + { + $this->ecotax = Tools::convertPrice(floatval($product['ecotax']), intval($order->id_currency)); - // Exclude VAT - if (!Tax::excludeTaxeOption()) - { - $this->setContext((int)$product['id_shop']); - $this->id_tax_rules_group = (int)Product::getIdTaxRulesGroupByIdProduct((int)$product['id_product'], $this->context); + // Exclude VAT + if (!Tax::excludeTaxeOption()) { + $this->setContext((int)$product['id_shop']); + $this->id_tax_rules_group = (int)Product::getIdTaxRulesGroupByIdProduct((int)$product['id_product'], $this->context); - $tax_manager = TaxManagerFactory::getManager($this->vat_address, $this->id_tax_rules_group); - $this->tax_calculator = $tax_manager->getTaxCalculator(); - $this->tax_computation_method = (int)$this->tax_calculator->computation_method; - } + $tax_manager = TaxManagerFactory::getManager($this->vat_address, $this->id_tax_rules_group); + $this->tax_calculator = $tax_manager->getTaxCalculator(); + $this->tax_computation_method = (int)$this->tax_calculator->computation_method; + } - $this->ecotax_tax_rate = 0; - if (!empty($product['ecotax'])) - $this->ecotax_tax_rate = Tax::getProductEcotaxRate($order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); - } + $this->ecotax_tax_rate = 0; + if (!empty($product['ecotax'])) { + $this->ecotax_tax_rate = Tax::getProductEcotaxRate($order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); + } + } - /** - * Set specific price of the product - * @param object $order - */ - protected function setSpecificPrice(Order $order, $product = null) - { - $this->reduction_amount = 0.00; - $this->reduction_percent = 0.00; - $this->reduction_amount_tax_incl = 0.00; - $this->reduction_amount_tax_excl = 0.00; + /** + * Set specific price of the product + * @param object $order + */ + protected function setSpecificPrice(Order $order, $product = null) + { + $this->reduction_amount = 0.00; + $this->reduction_percent = 0.00; + $this->reduction_amount_tax_incl = 0.00; + $this->reduction_amount_tax_excl = 0.00; - if ($this->specificPrice) - switch ($this->specificPrice['reduction_type']) - { - case 'percentage': - $this->reduction_percent = (float)$this->specificPrice['reduction'] * 100; - break; + if ($this->specificPrice) { + switch ($this->specificPrice['reduction_type']) { + case 'percentage': + $this->reduction_percent = (float)$this->specificPrice['reduction'] * 100; + break; - case 'amount': - $price = Tools::convertPrice($this->specificPrice['reduction'], $order->id_currency); - $this->reduction_amount = !$this->specificPrice['id_currency'] ? (float)$price : (float)$this->specificPrice['reduction']; - if ($product !== null) - $this->setContext((int)$product['id_shop']); - $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct((int)$this->specificPrice['id_product'], $this->context); - $tax_manager = TaxManagerFactory::getManager($this->vat_address, $id_tax_rules); - $this->tax_calculator = $tax_manager->getTaxCalculator(); + case 'amount': + $price = Tools::convertPrice($this->specificPrice['reduction'], $order->id_currency); + $this->reduction_amount = !$this->specificPrice['id_currency'] ? (float)$price : (float)$this->specificPrice['reduction']; + if ($product !== null) { + $this->setContext((int)$product['id_shop']); + } + $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct((int)$this->specificPrice['id_product'], $this->context); + $tax_manager = TaxManagerFactory::getManager($this->vat_address, $id_tax_rules); + $this->tax_calculator = $tax_manager->getTaxCalculator(); - if ($this->reduction_tax) - { - $this->reduction_amount_tax_incl = $this->reduction_amount; - $this->reduction_amount_tax_excl = Tools::ps_round($this->tax_calculator->removeTaxes($this->reduction_amount), _PS_PRICE_COMPUTE_PRECISION_); - } - else - { - $this->reduction_amount_tax_incl = Tools::ps_round($this->tax_calculator->addTaxes($this->reduction_amount), _PS_PRICE_COMPUTE_PRECISION_); - $this->reduction_amount_tax_excl = $this->reduction_amount; - } - break; - } - } + if ($this->specificPrice['reduction_tax']) { + $this->reduction_amount_tax_incl = $this->reduction_amount; + $this->reduction_amount_tax_excl = Tools::ps_round($this->tax_calculator->removeTaxes($this->reduction_amount), _PS_PRICE_COMPUTE_PRECISION_); + } else { + $this->reduction_amount_tax_incl = Tools::ps_round($this->tax_calculator->addTaxes($this->reduction_amount), _PS_PRICE_COMPUTE_PRECISION_); + $this->reduction_amount_tax_excl = $this->reduction_amount; + } + break; + } + } + } - /** - * Set detailed product price to the order detail - * @param object $order - * @param object $cart - * @param array $product - */ - protected function setDetailProductPrice(Order $order, Cart $cart, $product) - { - $this->setContext((int)$product['id_shop']); - Product::getPriceStatic((int)$product['id_product'], true, (int)$product['id_product_attribute'], 6, null, false, true, $product['cart_quantity'], false, (int)$order->id_customer, (int)$order->id_cart, (int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}, $specific_price, true, true, $this->context); - $this->specificPrice = $specific_price; - $this->original_product_price = Product::getPriceStatic($product['id_product'], false, (int)$product['id_product_attribute'], 6, null, false, false, 1, false, null, null, null, $null, true, true, $this->context); - $this->product_price = $this->original_product_price; - $this->unit_price_tax_incl = (float)$product['price_wt']; - $this->unit_price_tax_excl = (float)$product['price']; - $this->total_price_tax_incl = (float)$product['total_wt']; - $this->total_price_tax_excl = (float)$product['total']; + /** + * Set detailed product price to the order detail + * @param object $order + * @param object $cart + * @param array $product + */ + protected function setDetailProductPrice(Order $order, Cart $cart, $product) + { + $this->setContext((int)$product['id_shop']); + Product::getPriceStatic((int)$product['id_product'], true, (int)$product['id_product_attribute'], 6, null, false, true, $product['cart_quantity'], false, (int)$order->id_customer, (int)$order->id_cart, (int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}, $specific_price, true, true, $this->context); + $this->specificPrice = $specific_price; + $this->original_product_price = Product::getPriceStatic($product['id_product'], false, (int)$product['id_product_attribute'], 6, null, false, false, 1, false, null, null, null, $null, true, true, $this->context); + $this->product_price = $this->original_product_price; + $this->unit_price_tax_incl = (float)$product['price_wt']; + $this->unit_price_tax_excl = (float)$product['price']; + $this->total_price_tax_incl = (float)$product['total_wt']; + $this->total_price_tax_excl = (float)$product['total']; - $this->purchase_supplier_price = (float)$product['wholesale_price']; - if ($product['id_supplier'] > 0 && ($supplier_price = ProductSupplier::getProductPrice((int)$product['id_supplier'], $product['id_product'], $product['id_product_attribute'], true)) > 0) - $this->purchase_supplier_price = (float)$supplier_price; + $this->purchase_supplier_price = (float)$product['wholesale_price']; + if ($product['id_supplier'] > 0 && ($supplier_price = ProductSupplier::getProductPrice((int)$product['id_supplier'], $product['id_product'], $product['id_product_attribute'], true)) > 0) { + $this->purchase_supplier_price = (float)$supplier_price; + } - $this->setSpecificPrice($order, $product); + $this->setSpecificPrice($order, $product); - $this->group_reduction = (float)Group::getReduction((int)$order->id_customer); + $this->group_reduction = (float)Group::getReduction((int)$order->id_customer); - $shop_id = $this->context->shop->id; + $shop_id = $this->context->shop->id; - $quantity_discount = SpecificPrice::getQuantityDiscount((int)$product['id_product'], $shop_id, - (int)$cart->id_currency, (int)$this->vat_address->id_country, - (int)$this->customer->id_default_group, (int)$product['cart_quantity'], false, null, null, $null, true, true, $this->context); + $quantity_discount = SpecificPrice::getQuantityDiscount((int)$product['id_product'], $shop_id, + (int)$cart->id_currency, (int)$this->vat_address->id_country, + (int)$this->customer->id_default_group, (int)$product['cart_quantity'], false, null, null, $null, true, true, $this->context); - $unit_price = Product::getPriceStatic((int)$product['id_product'], true, - ($product['id_product_attribute'] ? intval($product['id_product_attribute']) : null), - 2, null, false, true, 1, false, (int)$order->id_customer, null, (int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}, $null, true, true, $this->context); - $this->product_quantity_discount = 0.00; - if ($quantity_discount) - { - $this->product_quantity_discount = $unit_price; - if (Product::getTaxCalculationMethod((int)$order->id_customer) == PS_TAX_EXC) - $this->product_quantity_discount = Tools::ps_round($unit_price, 2); + $unit_price = Product::getPriceStatic((int)$product['id_product'], true, + ($product['id_product_attribute'] ? intval($product['id_product_attribute']) : null), + 2, null, false, true, 1, false, (int)$order->id_customer, null, (int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}, $null, true, true, $this->context); + $this->product_quantity_discount = 0.00; + if ($quantity_discount) { + $this->product_quantity_discount = $unit_price; + if (Product::getTaxCalculationMethod((int)$order->id_customer) == PS_TAX_EXC) { + $this->product_quantity_discount = Tools::ps_round($unit_price, 2); + } - if (isset($this->tax_calculator)) - $this->product_quantity_discount -= $this->tax_calculator->addTaxes($quantity_discount['price']); - } + if (isset($this->tax_calculator)) { + $this->product_quantity_discount -= $this->tax_calculator->addTaxes($quantity_discount['price']); + } + } - $this->discount_quantity_applied = (($this->specificPrice && $this->specificPrice['from_quantity'] > 1) ? 1 : 0); - } + $this->discount_quantity_applied = (($this->specificPrice && $this->specificPrice['from_quantity'] > 1) ? 1 : 0); + } - /** - * Create an order detail liable to an id_order - * @param object $order - * @param object $cart - * @param array $product - * @param int $id_order_status - * @param int $id_order_invoice - * @param bool $use_taxes set to false if you don't want to use taxes - */ - protected function create(Order $order, Cart $cart, $product, $id_order_state, $id_order_invoice, $use_taxes = true, $id_warehouse = 0) - { - if ($use_taxes) - $this->tax_calculator = new TaxCalculator(); + /** + * Create an order detail liable to an id_order + * @param object $order + * @param object $cart + * @param array $product + * @param int $id_order_status + * @param int $id_order_invoice + * @param bool $use_taxes set to false if you don't want to use taxes + */ + protected function create(Order $order, Cart $cart, $product, $id_order_state, $id_order_invoice, $use_taxes = true, $id_warehouse = 0) + { + if ($use_taxes) { + $this->tax_calculator = new TaxCalculator(); + } - $this->id = null; + $this->id = null; - $this->product_id = (int)$product['id_product']; - $this->product_attribute_id = $product['id_product_attribute'] ? (int)$product['id_product_attribute'] : 0; - $this->product_name = $product['name']. - ((isset($product['attributes']) && $product['attributes'] != null) ? - ' - '.$product['attributes'] : ''); + $this->product_id = (int)$product['id_product']; + $this->product_attribute_id = $product['id_product_attribute'] ? (int)$product['id_product_attribute'] : 0; + $this->product_name = $product['name']. + ((isset($product['attributes']) && $product['attributes'] != null) ? + ' - '.$product['attributes'] : ''); - $this->product_quantity = (int)$product['cart_quantity']; - $this->product_ean13 = empty($product['ean13']) ? null : pSQL($product['ean13']); - $this->product_upc = empty($product['upc']) ? null : pSQL($product['upc']); - $this->product_reference = empty($product['reference']) ? null : pSQL($product['reference']); - $this->product_supplier_reference = empty($product['supplier_reference']) ? null : pSQL($product['supplier_reference']); - $this->product_weight = $product['id_product_attribute'] ? (float)$product['weight_attribute'] : (float)$product['weight']; - $this->id_warehouse = $id_warehouse; + $this->product_quantity = (int)$product['cart_quantity']; + $this->product_ean13 = empty($product['ean13']) ? null : pSQL($product['ean13']); + $this->product_upc = empty($product['upc']) ? null : pSQL($product['upc']); + $this->product_reference = empty($product['reference']) ? null : pSQL($product['reference']); + $this->product_supplier_reference = empty($product['supplier_reference']) ? null : pSQL($product['supplier_reference']); + $this->product_weight = $product['id_product_attribute'] ? (float)$product['weight_attribute'] : (float)$product['weight']; + $this->id_warehouse = $id_warehouse; - $product_quantity = (int)Product::getQuantity($this->product_id, $this->product_attribute_id); - $this->product_quantity_in_stock = ($product_quantity - (int)$product['cart_quantity'] < 0) ? - $product_quantity : (int)$product['cart_quantity']; + $product_quantity = (int)Product::getQuantity($this->product_id, $this->product_attribute_id); + $this->product_quantity_in_stock = ($product_quantity - (int)$product['cart_quantity'] < 0) ? + $product_quantity : (int)$product['cart_quantity']; - $this->setVirtualProductInformation($product); - $this->checkProductStock($product, $id_order_state); + $this->setVirtualProductInformation($product); + $this->checkProductStock($product, $id_order_state); - if ($use_taxes) - $this->setProductTax($order, $product); - $this->setShippingCost($order, $product); - $this->setDetailProductPrice($order, $cart, $product); + if ($use_taxes) { + $this->setProductTax($order, $product); + } + $this->setShippingCost($order, $product); + $this->setDetailProductPrice($order, $cart, $product); - // Set order invoice id - $this->id_order_invoice = (int)$id_order_invoice; + // Set order invoice id + $this->id_order_invoice = (int)$id_order_invoice; - // Set shop id - $this->id_shop = (int)$product['id_shop']; + // Set shop id + $this->id_shop = (int)$product['id_shop']; - // Add new entry to the table - $this->save(); + // Add new entry to the table + $this->save(); - if ($use_taxes) - $this->saveTaxCalculator($order); - unset($this->tax_calculator); - } + if ($use_taxes) { + $this->saveTaxCalculator($order); + } + unset($this->tax_calculator); + } - /** - * Create a list of order detail for a specified id_order using cart - * @param object $order - * @param object $cart - * @param int $id_order_status - * @param int $id_order_invoice - * @param bool $use_taxes set to false if you don't want to use taxes - */ - public function createList(Order $order, Cart $cart, $id_order_state, $product_list, $id_order_invoice = 0, $use_taxes = true, $id_warehouse = 0) - { - $this->vat_address = new Address((int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); - $this->customer = new Customer((int)$order->id_customer); + /** + * Create a list of order detail for a specified id_order using cart + * @param object $order + * @param object $cart + * @param int $id_order_status + * @param int $id_order_invoice + * @param bool $use_taxes set to false if you don't want to use taxes + */ + public function createList(Order $order, Cart $cart, $id_order_state, $product_list, $id_order_invoice = 0, $use_taxes = true, $id_warehouse = 0) + { + $this->vat_address = new Address((int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); + $this->customer = new Customer((int)$order->id_customer); - $this->id_order = $order->id; - $this->outOfStock = false; + $this->id_order = $order->id; + $this->outOfStock = false; - foreach ($product_list as $product) - $this->create($order, $cart, $product, $id_order_state, $id_order_invoice, $use_taxes, $id_warehouse); + foreach ($product_list as $product) { + $this->create($order, $cart, $product, $id_order_state, $id_order_invoice, $use_taxes, $id_warehouse); + } - unset($this->vat_address); - unset($products); - unset($this->customer); - } + unset($this->vat_address); + unset($products); + unset($this->customer); + } - /** - * Get the state of the current stock product - * @return array - */ - public function getStockState() - { - return $this->outOfStock; - } + /** + * Get the state of the current stock product + * @return array + */ + public function getStockState() + { + return $this->outOfStock; + } - /** - * Set the additional shipping information - * - * @param Order $order - * @param $product - */ - public function setShippingCost(Order $order, $product) - { - $tax_rate = 0; + /** + * Set the additional shipping information + * + * @param Order $order + * @param $product + */ + public function setShippingCost(Order $order, $product) + { + $tax_rate = 0; - $carrier = OrderInvoice::getCarrier((int)$this->id_order_invoice); - if (isset($carrier) && Validate::isLoadedObject($carrier)) - $tax_rate = $carrier->getTaxesRate(new Address((int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')})); + $carrier = OrderInvoice::getCarrier((int)$this->id_order_invoice); + if (isset($carrier) && Validate::isLoadedObject($carrier)) { + $tax_rate = $carrier->getTaxesRate(new Address((int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')})); + } - $this->total_shipping_price_tax_excl = (float)$product['additional_shipping_cost']; - $this->total_shipping_price_tax_incl = (float)($this->total_shipping_price_tax_excl * (1 + ($tax_rate / 100))); - $this->total_shipping_price_tax_incl = Tools::ps_round($this->total_shipping_price_tax_incl, 2); - } + $this->total_shipping_price_tax_excl = (float)$product['additional_shipping_cost']; + $this->total_shipping_price_tax_incl = (float)($this->total_shipping_price_tax_excl * (1 + ($tax_rate / 100))); + $this->total_shipping_price_tax_incl = Tools::ps_round($this->total_shipping_price_tax_incl, 2); + } - public function getWsTaxes() - { - $query = new DbQuery(); - $query->select('id_tax as id'); - $query->from('order_detail_tax', 'tax'); - $query->join('LEFT JOIN `'._DB_PREFIX_.'order_detail` od ON (tax.`id_order_detail` = od.`id_order_detail`)'); - $query->where('od.`id_order_detail` = '.(int)$this->id_order_detail); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + public function getWsTaxes() + { + $query = new DbQuery(); + $query->select('id_tax as id'); + $query->from('order_detail_tax', 'tax'); + $query->leftJoin('order_detail', 'od', 'tax.`id_order_detail` = od.`id_order_detail`'); + $query->where('od.`id_order_detail` = '.(int)$this->id_order_detail); + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } - public static function getCrossSells($id_product, $id_lang, $limit = 12) - { - if (!$id_product || !$id_lang) - return; + public static function getCrossSells($id_product, $id_lang, $limit = 12) + { + if (!$id_product || !$id_lang) { + return; + } - $front = true; - if (!in_array(Context::getContext()->controller->controller_type, array('front', 'modulefront'))) - $front = false; + $front = true; + if (!in_array(Context::getContext()->controller->controller_type, array('front', 'modulefront'))) { + $front = false; + } - $orders = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $orders = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT o.id_order FROM '._DB_PREFIX_.'orders o LEFT JOIN '._DB_PREFIX_.'order_detail od ON (od.id_order = o.id_order) WHERE o.valid = 1 AND od.product_id = '.(int)$id_product); - if (count($orders)) - { - $list = ''; - foreach ($orders as $order) - $list .= (int)$order['id_order'].','; - $list = rtrim($list, ','); + if (count($orders)) { + $list = ''; + foreach ($orders as $order) { + $list .= (int)$order['id_order'].','; + } + $list = rtrim($list, ','); - $order_products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $order_products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT DISTINCT od.product_id, p.id_product, pl.name, pl.link_rewrite, p.reference, i.id_image, product_shop.show_price, cl.link_rewrite category, p.ean13, p.out_of_stock, p.id_category_default '.(Combination::isFeatureActive() ? ', IFNULL(product_attribute_shop.id_product_attribute,0) id_product_attribute' : '').' FROM '._DB_PREFIX_.'order_detail od LEFT JOIN '._DB_PREFIX_.'product p ON (p.id_product = od.product_id) '.Shop::addSqlAssociation('product', 'p'). - (Combination::isFeatureActive() ? 'LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop + (Combination::isFeatureActive() ? 'LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop ON (p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='.(int)Context::getContext()->shop->id.')':'').' LEFT JOIN '._DB_PREFIX_.'product_lang pl ON (pl.id_product = od.product_id'.Shop::addSqlRestrictionOnLang('pl').') LEFT JOIN '._DB_PREFIX_.'category_lang cl ON (cl.id_category = product_shop.id_category_default'.Shop::addSqlRestrictionOnLang('cl').') @@ -740,39 +763,58 @@ class OrderDetailCore extends ObjectModel AND od.product_id != '.(int)$id_product.' AND i.cover = 1 AND product_shop.active = 1' - .($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').' + .($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').' ORDER BY RAND() LIMIT '.(int)$limit.' ', true, false); - $tax_calc = Product::getTaxCalculationMethod(); - if (is_array($order_products)) - { - foreach ($order_products as &$order_product) - { - $order_product['image'] = Context::getContext()->link->getImageLink($order_product['link_rewrite'], - (int)$order_product['product_id'].'-'.(int)$order_product['id_image'], ImageType::getFormatedName('medium')); - $order_product['link'] = Context::getContext()->link->getProductLink((int)$order_product['product_id'], - $order_product['link_rewrite'], $order_product['category'], $order_product['ean13']); - if ($tax_calc == 0 || $tax_calc == 2) - $order_product['displayed_price'] = Product::getPriceStatic((int)$order_product['product_id'], true, null); - elseif ($tax_calc == 1) - $order_product['displayed_price'] = Product::getPriceStatic((int)$order_product['product_id'], false, null); - } - return Product::getProductsProperties($id_lang, $order_products); - } - } - } + $tax_calc = Product::getTaxCalculationMethod(); + if (is_array($order_products)) { + foreach ($order_products as &$order_product) { + $order_product['image'] = Context::getContext()->link->getImageLink($order_product['link_rewrite'], + (int)$order_product['product_id'].'-'.(int)$order_product['id_image'], ImageType::getFormatedName('medium')); + $order_product['link'] = Context::getContext()->link->getProductLink((int)$order_product['product_id'], + $order_product['link_rewrite'], $order_product['category'], $order_product['ean13']); + if ($tax_calc == 0 || $tax_calc == 2) { + $order_product['displayed_price'] = Product::getPriceStatic((int)$order_product['product_id'], true, null); + } elseif ($tax_calc == 1) { + $order_product['displayed_price'] = Product::getPriceStatic((int)$order_product['product_id'], false, null); + } + } + return Product::getProductsProperties($id_lang, $order_products); + } + } + } - public function add($autodate = true, $null_values = false) - { - foreach ($this->def['fields'] as $field => $data) - { - if (!empty($data['required']) || !empty($data['lang'])) - continue; - if ($this->validateField($field, $this->$field) !== true) - $this->$field = ''; - } - return parent::add($autodate = true, $null_values = false); - } + public function add($autodate = true, $null_values = false) + { + foreach ($this->def['fields'] as $field => $data) { + if (!empty($data['required']) || !empty($data['lang'])) { + continue; + } + if ($this->validateField($field, $this->$field) !== true) { + $this->$field = ''; + } + } + + $this->original_wholesale_price = $this->getWholeSalePrice(); + + return parent::add($autodate = true, $null_values = false); + } + + //return the product OR product attribute whole sale price + public function getWholeSalePrice() + { + $product = new Product($this->product_id); + $wholesale_price = $product->wholesale_price; + + if($this->product_attribute_id){ + $combination = new Combination((int)$this->product_attribute_id); + if ($combination && $combination->wholesale_price != '0.000000') { + $wholesale_price = $combination->wholesale_price; + } + } + + return $wholesale_price; + } } diff --git a/classes/order/OrderDiscount.php b/classes/order/OrderDiscount.php index 28cd1560..221981a3 100644 --- a/classes/order/OrderDiscount.php +++ b/classes/order/OrderDiscount.php @@ -29,29 +29,33 @@ */ class OrderDiscountCore extends OrderCartRule { - public function __get($key) - { - Tools::displayAsDeprecated(); - if ($key == 'id_order_discount') - return $this->id_order_cart_rule; - if ($key == 'id_discount') - return $this->id_cart_rule; - return $this->{$key}; - } + public function __get($key) + { + Tools::displayAsDeprecated(); + if ($key == 'id_order_discount') { + return $this->id_order_cart_rule; + } + if ($key == 'id_discount') { + return $this->id_cart_rule; + } + return $this->{$key}; + } - public function __set($key, $value) - { - Tools::displayAsDeprecated(); - if ($key == 'id_order_discount') - $this->id_order_cart_rule = $value; - if ($key == 'id_discount') - $this->id_cart_rule = $value; - $this->{$key} = $value; - } + public function __set($key, $value) + { + Tools::displayAsDeprecated(); + if ($key == 'id_order_discount') { + $this->id_order_cart_rule = $value; + } + if ($key == 'id_discount') { + $this->id_cart_rule = $value; + } + $this->{$key} = $value; + } - public function __call($method, $args) - { - Tools::displayAsDeprecated(); - return call_user_func_array(array($this->parent, $method), $args); - } -} \ No newline at end of file + public function __call($method, $args) + { + Tools::displayAsDeprecated(); + return call_user_func_array(array($this->parent, $method), $args); + } +} diff --git a/classes/order/OrderHistory.php b/classes/order/OrderHistory.php index a71e008f..5e347231 100644 --- a/classes/order/OrderHistory.php +++ b/classes/order/OrderHistory.php @@ -26,373 +26,390 @@ class OrderHistoryCore extends ObjectModel { - /** @var int Order id */ - public $id_order; + /** @var int Order id */ + public $id_order; - /** @var int Order status id */ - public $id_order_state; + /** @var int Order status id */ + public $id_order_state; - /** @var int Employee id for this history entry */ - public $id_employee; + /** @var int Employee id for this history entry */ + public $id_employee; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** @var string Object last modification date */ - public $date_upd; + /** @var string Object last modification date */ + public $date_upd; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'order_history', - 'primary' => 'id_order_history', - 'fields' => array( - 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_order_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'order_history', + 'primary' => 'id_order_history', + 'fields' => array( + 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_order_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - /** - * @see ObjectModel::$webserviceParameters - */ - protected $webserviceParameters = array( - 'objectsNodeName' => 'order_histories', - 'fields' => array( - 'id_employee' => array('xlink_resource'=> 'employees'), - 'id_order_state' => array('required' => true, 'xlink_resource'=> 'order_states'), - 'id_order' => array('xlink_resource' => 'orders'), - ), - 'objectMethods' => array( - 'add' => 'addWs', - ), - ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'objectsNodeName' => 'order_histories', + 'fields' => array( + 'id_employee' => array('xlink_resource'=> 'employees'), + 'id_order_state' => array('required' => true, 'xlink_resource'=> 'order_states'), + 'id_order' => array('xlink_resource' => 'orders'), + ), + 'objectMethods' => array( + 'add' => 'addWs', + ), + ); - /** - * Sets the new state of the given order - * - * @param int $new_order_state - * @param int/object $id_order - * @param bool $use_existing_payment - */ - public function changeIdOrderState($new_order_state, $id_order, $use_existing_payment = false) - { - if (!$new_order_state || !$id_order) - return; + /** + * Sets the new state of the given order + * + * @param int $new_order_state + * @param int/object $id_order + * @param bool $use_existing_payment + */ + public function changeIdOrderState($new_order_state, $id_order, $use_existing_payment = false) + { + if (!$new_order_state || !$id_order) { + return; + } - if (!is_object($id_order) && is_numeric($id_order)) - $order = new Order((int)$id_order); - elseif (is_object($id_order)) - $order = $id_order; - else - return; + if (!is_object($id_order) && is_numeric($id_order)) { + $order = new Order((int)$id_order); + } elseif (is_object($id_order)) { + $order = $id_order; + } else { + return; + } - ShopUrl::cacheMainDomainForShop($order->id_shop); + ShopUrl::cacheMainDomainForShop($order->id_shop); - $new_os = new OrderState((int)$new_order_state, $order->id_lang); - $old_os = $order->getCurrentOrderState(); + $new_os = new OrderState((int)$new_order_state, $order->id_lang); + $old_os = $order->getCurrentOrderState(); - // executes hook - if (in_array($new_os->id, array(Configuration::get('PS_OS_PAYMENT'), Configuration::get('PS_OS_WS_PAYMENT')))) - Hook::exec('actionPaymentConfirmation', array('id_order' => (int)$order->id), null, false, true, false, $order->id_shop); + // executes hook + if (in_array($new_os->id, array(Configuration::get('PS_OS_PAYMENT'), Configuration::get('PS_OS_WS_PAYMENT')))) { + Hook::exec('actionPaymentConfirmation', array('id_order' => (int)$order->id), null, false, true, false, $order->id_shop); + } - // executes hook - Hook::exec('actionOrderStatusUpdate', array('newOrderStatus' => $new_os, 'id_order' => (int)$order->id), null, false, true, false, $order->id_shop); + // executes hook + Hook::exec('actionOrderStatusUpdate', array('newOrderStatus' => $new_os, 'id_order' => (int)$order->id), null, false, true, false, $order->id_shop); - if (Validate::isLoadedObject($order) && ($new_os instanceof OrderState)) - { - // An email is sent the first time a virtual item is validated - $virtual_products = $order->getVirtualProducts(); - if ($virtual_products && (!$old_os || !$old_os->logable) && $new_os && $new_os->logable) - { - $context = Context::getContext(); - $assign = array(); - foreach ($virtual_products as $key => $virtual_product) - { - $id_product_download = ProductDownload::getIdFromIdProduct($virtual_product['product_id']); - $product_download = new ProductDownload($id_product_download); - // If this virtual item has an associated file, we'll provide the link to download the file in the email - if ($product_download->display_filename != '') - { - $assign[$key]['name'] = $product_download->display_filename; - $dl_link = $product_download->getTextLink(false, $virtual_product['download_hash']) - .'&id_order='.(int)$order->id - .'&secure_key='.$order->secure_key; - $assign[$key]['link'] = $dl_link; - if (isset($virtual_product['download_deadline']) && $virtual_product['download_deadline'] != '0000-00-00 00:00:00') - $assign[$key]['deadline'] = Tools::displayDate($virtual_product['download_deadline']); - if ($product_download->nb_downloadable != 0) - $assign[$key]['downloadable'] = (int)$product_download->nb_downloadable; - } - } + if (Validate::isLoadedObject($order) && ($new_os instanceof OrderState)) { + $context = Context::getContext(); - $customer = new Customer((int)$order->id_customer); + // An email is sent the first time a virtual item is validated + $virtual_products = $order->getVirtualProducts(); + if ($virtual_products && (!$old_os || !$old_os->logable) && $new_os && $new_os->logable) { + $assign = array(); + foreach ($virtual_products as $key => $virtual_product) { + $id_product_download = ProductDownload::getIdFromIdProduct($virtual_product['product_id']); + $product_download = new ProductDownload($id_product_download); + // If this virtual item has an associated file, we'll provide the link to download the file in the email + if ($product_download->display_filename != '') { + $assign[$key]['name'] = $product_download->display_filename; + $dl_link = $product_download->getTextLink(false, $virtual_product['download_hash']) + .'&id_order='.(int)$order->id + .'&secure_key='.$order->secure_key; + $assign[$key]['link'] = $dl_link; + if (isset($virtual_product['download_deadline']) && $virtual_product['download_deadline'] != '0000-00-00 00:00:00') { + $assign[$key]['deadline'] = Tools::displayDate($virtual_product['download_deadline']); + } + if ($product_download->nb_downloadable != 0) { + $assign[$key]['downloadable'] = (int)$product_download->nb_downloadable; + } + } + } - $links = '<ul>'; - foreach ($assign as $product) - { - $links .= '<li>'; - $links .= '<a href="'.$product['link'].'">'.Tools::htmlentitiesUTF8($product['name']).'</a>'; - if (isset($product['deadline'])) - $links .= ' '.Tools::htmlentitiesUTF8(Tools::displayError('expires on', false)).' '.$product['deadline']; - if (isset($product['downloadable'])) - $links .= ' '.Tools::htmlentitiesUTF8(sprintf(Tools::displayError('downloadable %d time(s)', false), (int)$product['downloadable'])); - $links .= '</li>'; - } - $links .= '</ul>'; - $data = array( - '{lastname}' => $customer->lastname, - '{firstname}' => $customer->firstname, - '{id_order}' => (int)$order->id, - '{order_name}' => $order->getUniqReference(), - '{nbProducts}' => count($virtual_products), - '{virtualProducts}' => $links - ); - // If there is at least one downloadable file - if (!empty($assign)) - Mail::Send((int)$order->id_lang, 'download_product', Mail::l('The virtual product that you bought is available for download', $order->id_lang), $data, $customer->email, $customer->firstname.' '.$customer->lastname, - null, null, null, null, _PS_MAIL_DIR_, false, (int)$order->id_shop); - } + $customer = new Customer((int)$order->id_customer); - // @since 1.5.0 : gets the stock manager - $manager = null; - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - $manager = StockManagerFactory::getManager(); + $links = '<ul>'; + foreach ($assign as $product) { + $links .= '<li>'; + $links .= '<a href="'.$product['link'].'">'.Tools::htmlentitiesUTF8($product['name']).'</a>'; + if (isset($product['deadline'])) { + $links .= ' '.Tools::htmlentitiesUTF8(Tools::displayError('expires on', false)).' '.$product['deadline']; + } + if (isset($product['downloadable'])) { + $links .= ' '.Tools::htmlentitiesUTF8(sprintf(Tools::displayError('downloadable %d time(s)', false), (int)$product['downloadable'])); + } + $links .= '</li>'; + } + $links .= '</ul>'; + $data = array( + '{lastname}' => $customer->lastname, + '{firstname}' => $customer->firstname, + '{id_order}' => (int)$order->id, + '{order_name}' => $order->getUniqReference(), + '{nbProducts}' => count($virtual_products), + '{virtualProducts}' => $links + ); + // If there is at least one downloadable file + if (!empty($assign)) { + Mail::Send((int)$order->id_lang, 'download_product', Mail::l('The virtual product that you bought is available for download', $order->id_lang), $data, $customer->email, $customer->firstname.' '.$customer->lastname, + null, null, null, null, _PS_MAIL_DIR_, false, (int)$order->id_shop); + } + } - $error_or_canceled_statuses = array(Configuration::get('PS_OS_ERROR'), Configuration::get('PS_OS_CANCELED')); + // @since 1.5.0 : gets the stock manager + $manager = null; + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $manager = StockManagerFactory::getManager(); + } - // foreach products of the order - if (Validate::isLoadedObject($old_os)) - foreach ($order->getProductsDetail() as $product) - { - // if becoming logable => adds sale - if ($new_os->logable && !$old_os->logable) - { - ProductSale::addProductSale($product['product_id'], $product['product_quantity']); - // @since 1.5.0 - Stock Management - if (!Pack::isPack($product['product_id']) && - in_array($old_os->id, $error_or_canceled_statuses) && - !StockAvailable::dependsOnStock($product['id_product'], (int)$order->id_shop)) - StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], -(int)$product['product_quantity'], $order->id_shop); - } - // if becoming unlogable => removes sale - elseif (!$new_os->logable && $old_os->logable) - { - ProductSale::removeProductSale($product['product_id'], $product['product_quantity']); + $error_or_canceled_statuses = array(Configuration::get('PS_OS_ERROR'), Configuration::get('PS_OS_CANCELED')); - // @since 1.5.0 - Stock Management - if (!Pack::isPack($product['product_id']) && - in_array($new_os->id, $error_or_canceled_statuses) && - !StockAvailable::dependsOnStock($product['id_product'])) - StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], (int)$product['product_quantity'], $order->id_shop); - } - // if waiting for payment => payment error/canceled - elseif (!$new_os->logable && !$old_os->logable && - in_array($new_os->id, $error_or_canceled_statuses) && - !in_array($old_os->id, $error_or_canceled_statuses) && - !StockAvailable::dependsOnStock($product['id_product'])) - StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], (int)$product['product_quantity'], $order->id_shop); + $employee = null; + if (!(int)$this->id_employee || !Validate::isLoadedObject(($employee = new Employee((int)$this->id_employee)))) { + if (!Validate::isLoadedObject($old_os) && $context != null) { + // First OrderHistory, there is no $old_os, so $employee is null before here + $employee = $context->employee; // filled if from BO and order created (because no old_os) + if ($employee) { + $this->id_employee = $employee->id; + } + } else { + $employee = null; + } + } + - if ((int)$this->id_employee && !Validate::isLoadedObject(($employee = new Employee((int)$this->id_employee)))) - $employee = null; + // foreach products of the order + foreach ($order->getProductsDetail() as $product) { + if (Validate::isLoadedObject($old_os)) { + // if becoming logable => adds sale + if ($new_os->logable && !$old_os->logable) { + ProductSale::addProductSale($product['product_id'], $product['product_quantity']); + // @since 1.5.0 - Stock Management + if (!Pack::isPack($product['product_id']) && + in_array($old_os->id, $error_or_canceled_statuses) && + !StockAvailable::dependsOnStock($product['id_product'], (int)$order->id_shop)) { + StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], -(int)$product['product_quantity'], $order->id_shop); + } + } + // if becoming unlogable => removes sale + elseif (!$new_os->logable && $old_os->logable) { + ProductSale::removeProductSale($product['product_id'], $product['product_quantity']); - // @since 1.5.0 : if the order is being shipped and this products uses the advanced stock management : - // decrements the physical stock using $id_warehouse - if ($new_os->shipped == 1 && $old_os->shipped == 0 && - Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && - Warehouse::exists($product['id_warehouse']) && - $manager != null && - (int)$product['advanced_stock_management'] == 1) - { - // gets the warehouse - $warehouse = new Warehouse($product['id_warehouse']); + // @since 1.5.0 - Stock Management + if (!Pack::isPack($product['product_id']) && + in_array($new_os->id, $error_or_canceled_statuses) && + !StockAvailable::dependsOnStock($product['id_product'])) { + StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], (int)$product['product_quantity'], $order->id_shop); + } + } + // if waiting for payment => payment error/canceled + elseif (!$new_os->logable && !$old_os->logable && + in_array($new_os->id, $error_or_canceled_statuses) && + !in_array($old_os->id, $error_or_canceled_statuses) && + !StockAvailable::dependsOnStock($product['id_product'])) { + StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], (int)$product['product_quantity'], $order->id_shop); + } + } + // From here, there is 2 cases : $old_os exists, and we can test shipped state evolution, + // Or old_os does not exists, and we should consider that initial shipped state is 0 (to allow decrease of stocks) - // decrements the stock (if it's a pack, the StockManager does what is needed) - $manager->removeProduct( - $product['product_id'], - $product['product_attribute_id'], - $warehouse, - ($product['product_quantity'] - $product['product_quantity_refunded'] - $product['product_quantity_return']), - Configuration::get('PS_STOCK_CUSTOMER_ORDER_REASON'), - true, - (int)$order->id, - 0, - $employee - ); - } - // @since.1.5.0 : if the order was shipped, and is not anymore, we need to restock products - elseif ($new_os->shipped == 0 && $old_os->shipped == 1 && - Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && - Warehouse::exists($product['id_warehouse']) && - $manager != null && - (int)$product['advanced_stock_management'] == 1) - { - // if the product is a pack, we restock every products in the pack using the last negative stock mvts - if (Pack::isPack($product['product_id'])) - { - $pack_products = Pack::getItems($product['product_id'], Configuration::get('PS_LANG_DEFAULT', null, null, $order->id_shop)); - foreach ($pack_products as $pack_product) - { - if ($pack_product->advanced_stock_management == 1) - { - $mvts = StockMvt::getNegativeStockMvts($order->id, $pack_product->id, 0, $pack_product->pack_quantity * $product['product_quantity']); - foreach ($mvts as $mvt) - { - $manager->addProduct( - $pack_product->id, - 0, - new Warehouse($mvt['id_warehouse']), - $mvt['physical_quantity'], - null, - $mvt['price_te'], - true, - $employee - ); - } - if (!StockAvailable::dependsOnStock($product['id_product'])) - StockAvailable::updateQuantity($pack_product->id, 0, (int)$pack_product->pack_quantity * $product['product_quantity'], $order->id_shop); - } - } - } - // else, it's not a pack, re-stock using the last negative stock mvts - else - { - $mvts = StockMvt::getNegativeStockMvts($order->id, $product['product_id'], - $product['product_attribute_id'], - ($product['product_quantity'] - $product['product_quantity_refunded'] - $product['product_quantity_return'])); + // @since 1.5.0 : if the order is being shipped and this products uses the advanced stock management : + // decrements the physical stock using $id_warehouse + if ($new_os->shipped == 1 && (!Validate::isLoadedObject($old_os) || $old_os->shipped == 0) && + Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && + Warehouse::exists($product['id_warehouse']) && + $manager != null && + (int)$product['advanced_stock_management'] == 1) { + // gets the warehouse + $warehouse = new Warehouse($product['id_warehouse']); - foreach ($mvts as $mvt) - { - $manager->addProduct( - $product['product_id'], - $product['product_attribute_id'], - new Warehouse($mvt['id_warehouse']), - $mvt['physical_quantity'], - null, - $mvt['price_te'], - true - ); - } - } - } - } - } + // decrements the stock (if it's a pack, the StockManager does what is needed) + $manager->removeProduct( + $product['product_id'], + $product['product_attribute_id'], + $warehouse, + ($product['product_quantity'] - $product['product_quantity_refunded'] - $product['product_quantity_return']), + Configuration::get('PS_STOCK_CUSTOMER_ORDER_REASON'), + true, + (int)$order->id, + 0, + $employee + ); + } + // @since.1.5.0 : if the order was shipped, and is not anymore, we need to restock products + elseif ($new_os->shipped == 0 && Validate::isLoadedObject($old_os) && $old_os->shipped == 1 && + Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && + Warehouse::exists($product['id_warehouse']) && + $manager != null && + (int)$product['advanced_stock_management'] == 1) { + // if the product is a pack, we restock every products in the pack using the last negative stock mvts + if (Pack::isPack($product['product_id'])) { + $pack_products = Pack::getItems($product['product_id'], Configuration::get('PS_LANG_DEFAULT', null, null, $order->id_shop)); + foreach ($pack_products as $pack_product) { + if ($pack_product->advanced_stock_management == 1) { + $mvts = StockMvt::getNegativeStockMvts($order->id, $pack_product->id, 0, $pack_product->pack_quantity * $product['product_quantity']); + foreach ($mvts as $mvt) { + $manager->addProduct( + $pack_product->id, + 0, + new Warehouse($mvt['id_warehouse']), + $mvt['physical_quantity'], + null, + $mvt['price_te'], + true, + null, + $employee + ); + } + if (!StockAvailable::dependsOnStock($product['id_product'])) { + StockAvailable::updateQuantity($pack_product->id, 0, (int)$pack_product->pack_quantity * $product['product_quantity'], $order->id_shop); + } + } + } + } + // else, it's not a pack, re-stock using the last negative stock mvts + else { + $mvts = StockMvt::getNegativeStockMvts($order->id, $product['product_id'], + $product['product_attribute_id'], + ($product['product_quantity'] - $product['product_quantity_refunded'] - $product['product_quantity_return'])); - $this->id_order_state = (int)$new_order_state; + foreach ($mvts as $mvt) { + $manager->addProduct( + $product['product_id'], + $product['product_attribute_id'], + new Warehouse($mvt['id_warehouse']), + $mvt['physical_quantity'], + null, + $mvt['price_te'], + true + ); + } + } + } + } + } - // changes invoice number of order ? - if (!Validate::isLoadedObject($new_os) || !Validate::isLoadedObject($order)) - die(Tools::displayError('Invalid new order status')); + $this->id_order_state = (int)$new_order_state; - // the order is valid if and only if the invoice is available and the order is not cancelled - $order->current_state = $this->id_order_state; - $order->valid = $new_os->logable; - $order->update(); + // changes invoice number of order ? + if (!Validate::isLoadedObject($new_os) || !Validate::isLoadedObject($order)) { + die(Tools::displayError('Invalid new order status')); + } - if ($new_os->invoice && !$order->invoice_number) - $order->setInvoice($use_existing_payment); - elseif ($new_os->delivery && !$order->delivery_number) - $order->setDeliverySlip(); + // the order is valid if and only if the invoice is available and the order is not cancelled + $order->current_state = $this->id_order_state; + $order->valid = $new_os->logable; + $order->update(); - // set orders as paid - if ($new_os->paid == 1) - { - $invoices = $order->getInvoicesCollection(); - if ($order->total_paid != 0) - $payment_method = Module::getInstanceByName($order->module); + if ($new_os->invoice && !$order->invoice_number) { + $order->setInvoice($use_existing_payment); + } elseif ($new_os->delivery && !$order->delivery_number) { + $order->setDeliverySlip(); + } - foreach ($invoices as $invoice) - { - /** @var OrderInvoice $invoice */ - $rest_paid = $invoice->getRestPaid(); - if ($rest_paid > 0) - { - $payment = new OrderPayment(); - $payment->order_reference = Tools::substr($order->reference, 0, 9); - $payment->id_currency = $order->id_currency; - $payment->amount = $rest_paid; + // set orders as paid + if ($new_os->paid == 1) { + $invoices = $order->getInvoicesCollection(); + if ($order->total_paid != 0) { + $payment_method = Module::getInstanceByName($order->module); + } - if ($order->total_paid != 0) - $payment->payment_method = $payment_method->displayName; - else - $payment->payment_method = null; + foreach ($invoices as $invoice) { + /** @var OrderInvoice $invoice */ + $rest_paid = $invoice->getRestPaid(); + if ($rest_paid > 0) { + $payment = new OrderPayment(); + $payment->order_reference = Tools::substr($order->reference, 0, 9); + $payment->id_currency = $order->id_currency; + $payment->amount = $rest_paid; - // Update total_paid_real value for backward compatibility reasons - if ($payment->id_currency == $order->id_currency) - $order->total_paid_real += $payment->amount; - else - $order->total_paid_real += Tools::ps_round(Tools::convertPrice($payment->amount, $payment->id_currency, false), 2); - $order->save(); + if ($order->total_paid != 0) { + $payment->payment_method = $payment_method->displayName; + } else { + $payment->payment_method = null; + } - $payment->conversion_rate = 1; - $payment->save(); - Db::getInstance()->execute(' + // Update total_paid_real value for backward compatibility reasons + if ($payment->id_currency == $order->id_currency) { + $order->total_paid_real += $payment->amount; + } else { + $order->total_paid_real += Tools::ps_round(Tools::convertPrice($payment->amount, $payment->id_currency, false), 2); + } + $order->save(); + + $payment->conversion_rate = 1; + $payment->save(); + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'order_invoice_payment` (`id_order_invoice`, `id_order_payment`, `id_order`) VALUES('.(int)$invoice->id.', '.(int)$payment->id.', '.(int)$order->id.')'); - } - } - } + } + } + } - // updates delivery date even if it was already set by another state change - if ($new_os->delivery) - $order->setDelivery(); + // updates delivery date even if it was already set by another state change + if ($new_os->delivery) { + $order->setDelivery(); + } - // executes hook - Hook::exec('actionOrderStatusPostUpdate', array('newOrderStatus' => $new_os,'id_order' => (int)$order->id,), null, false, true, false, $order->id_shop); + // executes hook + Hook::exec('actionOrderStatusPostUpdate', array('newOrderStatus' => $new_os, 'id_order' => (int)$order->id, ), null, false, true, false, $order->id_shop); - ShopUrl::resetMainDomainCache(); - } + ShopUrl::resetMainDomainCache(); + } - /** - * Returns the last order status - * @param int $id_order - * @return OrderState|bool - * @deprecated 1.5.0.4 - * @see Order->current_state - */ - public static function getLastOrderState($id_order) - { - Tools::displayAsDeprecated(); - $id_order_state = Db::getInstance()->getValue(' + /** + * Returns the last order status + * @param int $id_order + * @return OrderState|bool + * @deprecated 1.5.0.4 + * @see Order->current_state + */ + public static function getLastOrderState($id_order) + { + Tools::displayAsDeprecated(); + $id_order_state = Db::getInstance()->getValue(' SELECT `id_order_state` FROM `'._DB_PREFIX_.'order_history` WHERE `id_order` = '.(int)$id_order.' ORDER BY `date_add` DESC, `id_order_history` DESC'); - // returns false if there is no state - if (!$id_order_state) - return false; + // returns false if there is no state + if (!$id_order_state) { + return false; + } - // else, returns an OrderState object - return new OrderState($id_order_state, Configuration::get('PS_LANG_DEFAULT')); - } + // else, returns an OrderState object + return new OrderState($id_order_state, Configuration::get('PS_LANG_DEFAULT')); + } - /** - * @param bool $autodate Optional - * @param array $template_vars Optional - * @param Context $context Optional - * @return bool - */ - public function addWithemail($autodate = true, $template_vars = false, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - $order = new Order($this->id_order); + /** + * @param bool $autodate Optional + * @param array $template_vars Optional + * @param Context $context Deprecated + * @return bool + */ + public function addWithemail($autodate = true, $template_vars = false, Context $context = null) + { + $order = new Order($this->id_order); - if (!$this->add($autodate)) - return false; + if (!$this->add($autodate)) { + return false; + } - if (!$this->sendEmail($order, $template_vars)) - return false; + if (!$this->sendEmail($order, $template_vars)) { + return false; + } - return true; - } + return true; + } - public function sendEmail($order, $template_vars = false) - { - $result = Db::getInstance()->getRow(' + public function sendEmail($order, $template_vars = false) + { + $result = Db::getInstance()->getRow(' SELECT osl.`template`, c.`lastname`, c.`firstname`, osl.`name` AS osname, c.`email`, os.`module_name`, os.`id_order_state`, os.`pdf_invoice`, os.`pdf_delivery` FROM `'._DB_PREFIX_.'order_history` oh LEFT JOIN `'._DB_PREFIX_.'orders` o ON oh.`id_order` = o.`id_order` @@ -400,120 +417,116 @@ class OrderHistoryCore extends ObjectModel LEFT JOIN `'._DB_PREFIX_.'order_state` os ON oh.`id_order_state` = os.`id_order_state` LEFT JOIN `'._DB_PREFIX_.'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = o.`id_lang`) WHERE oh.`id_order_history` = '.(int)$this->id.' AND os.`send_email` = 1'); - if (isset($result['template']) && Validate::isEmail($result['email'])) - { - ShopUrl::cacheMainDomainForShop($order->id_shop); + if (isset($result['template']) && Validate::isEmail($result['email'])) { + ShopUrl::cacheMainDomainForShop($order->id_shop); - $topic = $result['osname']; - $data = array( - '{lastname}' => $result['lastname'], - '{firstname}' => $result['firstname'], - '{id_order}' => (int)$this->id_order, - '{order_name}' => $order->getUniqReference() - ); + $topic = $result['osname']; + $data = array( + '{lastname}' => $result['lastname'], + '{firstname}' => $result['firstname'], + '{id_order}' => (int)$this->id_order, + '{order_name}' => $order->getUniqReference() + ); - if ($result['module_name']) - { - $module = Module::getInstanceByName($result['module_name']); - if (Validate::isLoadedObject($module) && isset($module->extra_mail_vars) && is_array($module->extra_mail_vars)) - $data = array_merge($data, $module->extra_mail_vars); - } + if ($result['module_name']) { + $module = Module::getInstanceByName($result['module_name']); + if (Validate::isLoadedObject($module) && isset($module->extra_mail_vars) && is_array($module->extra_mail_vars)) { + $data = array_merge($data, $module->extra_mail_vars); + } + } - if ($template_vars) - $data = array_merge($data, $template_vars); + if ($template_vars) { + $data = array_merge($data, $template_vars); + } - $data['{total_paid}'] = Tools::displayPrice((float)$order->total_paid, new Currency((int)$order->id_currency), false); + $data['{total_paid}'] = Tools::displayPrice((float)$order->total_paid, new Currency((int)$order->id_currency), false); - if (Validate::isLoadedObject($order)) - { - // Attach invoice and / or delivery-slip if they exists and status is set to attach them - if (($result['pdf_invoice'] || $result['pdf_delivery'])) - { - $context = Context::getContext(); - $invoice = $order->getInvoicesCollection(); - $file_attachement = array(); + if (Validate::isLoadedObject($order)) { + // Attach invoice and / or delivery-slip if they exists and status is set to attach them + if (($result['pdf_invoice'] || $result['pdf_delivery'])) { + $context = Context::getContext(); + $invoice = $order->getInvoicesCollection(); + $file_attachement = array(); - if ($result['pdf_invoice'] && (int)Configuration::get('PS_INVOICE') && $order->invoice_number) - { - Hook::exec('actionPDFInvoiceRender', array('order_invoice_list' => $invoice)); - $pdf = new PDF($invoice, PDF::TEMPLATE_INVOICE, $context->smarty); - $file_attachement['invoice']['content'] = $pdf->render(false); - $file_attachement['invoice']['name'] = Configuration::get('PS_INVOICE_PREFIX', (int)$order->id_lang, null, $order->id_shop).sprintf('%06d', $order->invoice_number).'.pdf'; - $file_attachement['invoice']['mime'] = 'application/pdf'; - } - if ($result['pdf_delivery'] && $order->delivery_number) - { - $pdf = new PDF($invoice, PDF::TEMPLATE_DELIVERY_SLIP, $context->smarty); - $file_attachement['delivery']['content'] = $pdf->render(false); - $file_attachement['delivery']['name'] = Configuration::get('PS_DELIVERY_PREFIX', Context::getContext()->language->id, null, $order->id_shop).sprintf('%06d', $order->delivery_number).'.pdf'; - $file_attachement['delivery']['mime'] = 'application/pdf'; - } - } - else - $file_attachement = null; + if ($result['pdf_invoice'] && (int)Configuration::get('PS_INVOICE') && $order->invoice_number) { + Hook::exec('actionPDFInvoiceRender', array('order_invoice_list' => $invoice)); + $pdf = new PDF($invoice, PDF::TEMPLATE_INVOICE, $context->smarty); + $file_attachement['invoice']['content'] = $pdf->render(false); + $file_attachement['invoice']['name'] = Configuration::get('PS_INVOICE_PREFIX', (int)$order->id_lang, null, $order->id_shop).sprintf('%06d', $order->invoice_number).'.pdf'; + $file_attachement['invoice']['mime'] = 'application/pdf'; + } + if ($result['pdf_delivery'] && $order->delivery_number) { + $pdf = new PDF($invoice, PDF::TEMPLATE_DELIVERY_SLIP, $context->smarty); + $file_attachement['delivery']['content'] = $pdf->render(false); + $file_attachement['delivery']['name'] = Configuration::get('PS_DELIVERY_PREFIX', Context::getContext()->language->id, null, $order->id_shop).sprintf('%06d', $order->delivery_number).'.pdf'; + $file_attachement['delivery']['mime'] = 'application/pdf'; + } + } else { + $file_attachement = null; + } - if(!Mail::Send((int)$order->id_lang, $result['template'], $topic, $data, $result['email'], $result['firstname'].' '.$result['lastname'], - null, null, $file_attachement, null, _PS_MAIL_DIR_, false, (int)$order->id_shop)) - return false; - } + if (!Mail::Send((int)$order->id_lang, $result['template'], $topic, $data, $result['email'], $result['firstname'].' '.$result['lastname'], + null, null, $file_attachement, null, _PS_MAIL_DIR_, false, (int)$order->id_shop)) { + return false; + } + } - ShopUrl::resetMainDomainCache(); - } + ShopUrl::resetMainDomainCache(); + } - return true; - } + return true; + } - public function add($autodate = true, $null_values = false) - { - if (!parent::add($autodate)) - return false; + public function add($autodate = true, $null_values = false) + { + if (!parent::add($autodate)) { + return false; + } - $order = new Order((int)$this->id_order); - // Update id_order_state attribute in Order - $order->current_state = $this->id_order_state; - $order->update(); + $order = new Order((int)$this->id_order); + // Update id_order_state attribute in Order + $order->current_state = $this->id_order_state; + $order->update(); - Hook::exec('actionOrderHistoryAddAfter', array('order_history' => $this), null, false, true, false, $order->id_shop); + Hook::exec('actionOrderHistoryAddAfter', array('order_history' => $this), null, false, true, false, $order->id_shop); - return true; - } + return true; + } - /** - * @return int - */ - public function isValidated() - { - return Db::getInstance()->getValue(' + /** + * @return int + */ + public function isValidated() + { + return Db::getInstance()->getValue(' SELECT COUNT(oh.`id_order_history`) AS nb FROM `'._DB_PREFIX_.'order_state` os LEFT JOIN `'._DB_PREFIX_.'order_history` oh ON (os.`id_order_state` = oh.`id_order_state`) WHERE oh.`id_order` = '.(int)$this->id_order.' AND os.`logable` = 1'); - } + } - /** - * Add method for webservice create resource Order History - * If sendemail=1 GET parameter is present sends email to customer otherwise does not - * @return bool - */ - public function addWs() - { - $sendemail = (bool)Tools::getValue('sendemail', false); - $this->changeIdOrderState($this->id_order_state, $this->id_order); + /** + * Add method for webservice create resource Order History + * If sendemail=1 GET parameter is present sends email to customer otherwise does not + * @return bool + */ + public function addWs() + { + $sendemail = (bool)Tools::getValue('sendemail', false); + $this->changeIdOrderState($this->id_order_state, $this->id_order); - if ($sendemail) - { - //Mail::Send requires link object on context and is not set when getting here - $context = Context::getContext(); - if ($context->link == null) - { - $protocol_link = (Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) ? 'https://' : 'http://'; - $protocol_content = (Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) ? 'https://' : 'http://'; - $context->link = new Link($protocol_link, $protocol_content); - } - return $this->addWithemail(); - } - else - return $this->add(); - } + if ($sendemail) { + //Mail::Send requires link object on context and is not set when getting here + $context = Context::getContext(); + if ($context->link == null) { + $protocol_link = (Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) ? 'https://' : 'http://'; + $protocol_content = (Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) ? 'https://' : 'http://'; + $context->link = new Link($protocol_link, $protocol_content); + } + return $this->addWithemail(); + } else { + return $this->add(); + } + } } diff --git a/classes/order/OrderInvoice.php b/classes/order/OrderInvoice.php index 57506e4f..5a6add5c 100644 --- a/classes/order/OrderInvoice.php +++ b/classes/order/OrderInvoice.php @@ -26,135 +26,126 @@ class OrderInvoiceCore extends ObjectModel { - const TAX_EXCL = 0; - const TAX_INCL = 1; - const DETAIL = 2; + const TAX_EXCL = 0; + const TAX_INCL = 1; + const DETAIL = 2; - /** @var int */ - public $id_order; + /** @var int */ + public $id_order; - /** @var int */ - public $number; + /** @var int */ + public $number; - /** @var int */ - public $delivery_number; + /** @var int */ + public $delivery_number; - /** @var int */ - public $delivery_date = '0000-00-00 00:00:00'; + /** @var int */ + public $delivery_date = '0000-00-00 00:00:00'; - /** @var float */ - public $total_discount_tax_excl; + /** @var float */ + public $total_discount_tax_excl; - /** @var float */ - public $total_discount_tax_incl; + /** @var float */ + public $total_discount_tax_incl; - /** @var float */ - public $total_paid_tax_excl; + /** @var float */ + public $total_paid_tax_excl; - /** @var float */ - public $total_paid_tax_incl; + /** @var float */ + public $total_paid_tax_incl; - /** @var float */ - public $total_products; + /** @var float */ + public $total_products; - /** @var float */ - public $total_products_wt; + /** @var float */ + public $total_products_wt; - /** @var float */ - public $total_shipping_tax_excl; + /** @var float */ + public $total_shipping_tax_excl; - /** @var float */ - public $total_shipping_tax_incl; + /** @var float */ + public $total_shipping_tax_incl; - /** @var int */ - public $shipping_tax_computation_method; + /** @var int */ + public $shipping_tax_computation_method; - /** @var float */ - public $total_wrapping_tax_excl; + /** @var float */ + public $total_wrapping_tax_excl; - /** @var float */ - public $total_wrapping_tax_incl; + /** @var float */ + public $total_wrapping_tax_incl; - /** @var string shop address */ - public $shop_address; + /** @var string shop address */ + public $shop_address; - /** @var string invoice address */ - public $invoice_address; + /** @var string invoice address */ + public $invoice_address; - /** @var string delivery address */ - public $delivery_address; + /** @var string delivery address */ + public $delivery_address; - /** @var string note */ - public $note; + /** @var string note */ + public $note; - /** @var int */ - public $date_add; + /** @var int */ + public $date_add; - /** @var array Total paid cache */ - protected static $_total_paid_cache = array(); + /** @var array Total paid cache */ + protected static $_total_paid_cache = array(); - /** @var Order **/ - private $order; + /** @var Order **/ + private $order; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'order_invoice', - 'primary' => 'id_order_invoice', - 'fields' => array( - 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'number' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'delivery_number' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'delivery_date' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat'), - 'total_discount_tax_excl' =>array('type' => self::TYPE_FLOAT), - 'total_discount_tax_incl' =>array('type' => self::TYPE_FLOAT), - 'total_paid_tax_excl' => array('type' => self::TYPE_FLOAT), - 'total_paid_tax_incl' => array('type' => self::TYPE_FLOAT), - 'total_products' => array('type' => self::TYPE_FLOAT), - 'total_products_wt' => array('type' => self::TYPE_FLOAT), - 'total_shipping_tax_excl' =>array('type' => self::TYPE_FLOAT), - 'total_shipping_tax_incl' =>array('type' => self::TYPE_FLOAT), - 'shipping_tax_computation_method' => array('type' => self::TYPE_INT), - 'total_wrapping_tax_excl' =>array('type' => self::TYPE_FLOAT), - 'total_wrapping_tax_incl' =>array('type' => self::TYPE_FLOAT), - 'shop_address' => array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml', 'size' => 1000), - 'invoice_address' => array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml', 'size' => 1000), - 'delivery_address' => array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml', 'size' => 1000), - 'note' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 65000), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'order_invoice', + 'primary' => 'id_order_invoice', + 'fields' => array( + 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'number' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'delivery_number' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'delivery_date' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat'), + 'total_discount_tax_excl' =>array('type' => self::TYPE_FLOAT), + 'total_discount_tax_incl' =>array('type' => self::TYPE_FLOAT), + 'total_paid_tax_excl' => array('type' => self::TYPE_FLOAT), + 'total_paid_tax_incl' => array('type' => self::TYPE_FLOAT), + 'total_products' => array('type' => self::TYPE_FLOAT), + 'total_products_wt' => array('type' => self::TYPE_FLOAT), + 'total_shipping_tax_excl' =>array('type' => self::TYPE_FLOAT), + 'total_shipping_tax_incl' =>array('type' => self::TYPE_FLOAT), + 'shipping_tax_computation_method' => array('type' => self::TYPE_INT), + 'total_wrapping_tax_excl' =>array('type' => self::TYPE_FLOAT), + 'total_wrapping_tax_incl' =>array('type' => self::TYPE_FLOAT), + 'shop_address' => array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml', 'size' => 1000), + 'invoice_address' => array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml', 'size' => 1000), + 'delivery_address' => array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml', 'size' => 1000), + 'note' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 65000), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - public function add($autodate = true, $null_values = false) - { - $address = new Address(); - $address->company = Configuration::get('PS_SHOP_NAME'); - $address->address1 = Configuration::get('PS_SHOP_ADDR1'); - $address->address2 = Configuration::get('PS_SHOP_ADDR2'); - $address->postcode = Configuration::get('PS_SHOP_CODE'); - $address->city = Configuration::get('PS_SHOP_CITY'); - $address->phone = Configuration::get('PS_SHOP_PHONE'); - $address->id_country = Configuration::get('PS_SHOP_COUNTRY_ID'); + public function add($autodate = true, $null_values = false) + { + $order = new Order($this->id_order); + + $this->shop_address = self::getCurrentFormattedShopAddress($order->id_shop); - $this->shop_address = AddressFormat::generateAddress($address, array(), '<br />', ' '); - - $order = new Order($this->id_order); - - $invoice_address = new Address((int)$order->id_address_invoice); + $invoice_address = new Address((int)$order->id_address_invoice); $invoiceAddressPatternRules = Tools::jsonDecode(Configuration::get('PS_INVCE_INVOICE_ADDR_RULES'), true); $this->invoice_address = AddressFormat::generateAddress($invoice_address, $invoiceAddressPatternRules, '<br />', ' '); - $delivery_address = new Address((int)$order->id_address_delivery); + $delivery_address = new Address((int)$order->id_address_delivery); $deliveryAddressPatternRules = Tools::jsonDecode(Configuration::get('PS_INVCE_DELIVERY_ADDR_RULES'), true); $this->delivery_address = AddressFormat::generateAddress($delivery_address, $deliveryAddressPatternRules, '<br />', ' '); - return parent::add(); - } + return parent::add(); + } - public function getProductsDetail() - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public function getProductsDetail() + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'order_detail` od LEFT JOIN `'._DB_PREFIX_.'product` p @@ -162,224 +153,233 @@ class OrderInvoiceCore extends ObjectModel LEFT JOIN `'._DB_PREFIX_.'product_shop` ps ON (ps.id_product = p.id_product AND ps.id_shop = od.id_shop) WHERE od.`id_order` = '.(int)$this->id_order.' '.($this->id && $this->number ? ' AND od.`id_order_invoice` = '.(int)$this->id : '')); - } + } - public static function getInvoiceByNumber($id_invoice) - { - if (is_numeric($id_invoice)) - $id_invoice = (int)$id_invoice; - elseif (is_string($id_invoice)) - { - $matches = array(); - if (preg_match('/^(?:'.Configuration::get('PS_INVOICE_PREFIX', Context::getContext()->language->id).')\s*([0-9]+)$/i', $id_invoice, $matches)) - $id_invoice = $matches[1]; - } - if (!$id_invoice) - return false; + public static function getInvoiceByNumber($id_invoice) + { + if (is_numeric($id_invoice)) { + $id_invoice = (int)$id_invoice; + } elseif (is_string($id_invoice)) { + $matches = array(); + if (preg_match('/^(?:'.Configuration::get('PS_INVOICE_PREFIX', Context::getContext()->language->id).')\s*([0-9]+)$/i', $id_invoice, $matches)) { + $id_invoice = $matches[1]; + } + } + if (!$id_invoice) { + return false; + } - $id_order_invoice = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + $id_order_invoice = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_order_invoice` FROM `'._DB_PREFIX_.'order_invoice` WHERE number = '.(int)$id_invoice - ); + ); - return ($id_order_invoice ? new OrderInvoice($id_order_invoice) : false); - } + return ($id_order_invoice ? new OrderInvoice($id_order_invoice) : false); + } - /** - * Get order products - * - * @return array Products with price, quantity (with taxe and without) - */ - public function getProducts($products = false, $selected_products = false, $selected_qty = false) - { - if (!$products) - $products = $this->getProductsDetail(); + /** + * Get order products + * + * @return array Products with price, quantity (with taxe and without) + */ + public function getProducts($products = false, $selected_products = false, $selected_qty = false) + { + if (!$products) { + $products = $this->getProductsDetail(); + } - $order = new Order($this->id_order); - $customized_datas = Product::getAllCustomizedDatas($order->id_cart); + $order = new Order($this->id_order); + $customized_datas = Product::getAllCustomizedDatas($order->id_cart); - $result_array = array(); - foreach ($products as $row) - { - // Change qty if selected - if ($selected_qty) - { - $row['product_quantity'] = 0; - foreach ($selected_products as $key => $id_product) - if ($row['id_order_detail'] == $id_product) - $row['product_quantity'] = (int)$selected_qty[$key]; - if (!$row['product_quantity']) - continue; - } + $result_array = array(); + foreach ($products as $row) { + // Change qty if selected + if ($selected_qty) { + $row['product_quantity'] = 0; + foreach ($selected_products as $key => $id_product) { + if ($row['id_order_detail'] == $id_product) { + $row['product_quantity'] = (int)$selected_qty[$key]; + } + } + if (!$row['product_quantity']) { + continue; + } + } - $this->setProductImageInformations($row); - $this->setProductCurrentStock($row); - $this->setProductCustomizedDatas($row, $customized_datas); + $this->setProductImageInformations($row); + $this->setProductCurrentStock($row); + $this->setProductCustomizedDatas($row, $customized_datas); - // Add information for virtual product - if ($row['download_hash'] && !empty($row['download_hash'])) - { - $row['filename'] = ProductDownload::getFilenameFromIdProduct((int)$row['product_id']); - // Get the display filename - $row['display_filename'] = ProductDownload::getFilenameFromFilename($row['filename']); - } + // Add information for virtual product + if ($row['download_hash'] && !empty($row['download_hash'])) { + $row['filename'] = ProductDownload::getFilenameFromIdProduct((int)$row['product_id']); + // Get the display filename + $row['display_filename'] = ProductDownload::getFilenameFromFilename($row['filename']); + } - $row['id_address_delivery'] = $order->id_address_delivery; + $row['id_address_delivery'] = $order->id_address_delivery; - /* Ecotax */ - $round_mode = $order->round_mode; + /* Ecotax */ + $round_mode = $order->round_mode; - $row['ecotax_tax_excl'] = $row['ecotax']; // alias for coherence - $row['ecotax_tax_incl'] = $row['ecotax'] * (100 + $row['ecotax_tax_rate']) / 100; - $row['ecotax_tax'] = $row['ecotax_tax_incl'] - $row['ecotax_tax_excl']; + $row['ecotax_tax_excl'] = $row['ecotax']; // alias for coherence + $row['ecotax_tax_incl'] = $row['ecotax'] * (100 + $row['ecotax_tax_rate']) / 100; + $row['ecotax_tax'] = $row['ecotax_tax_incl'] - $row['ecotax_tax_excl']; - if ($round_mode == Order::ROUND_ITEM) - $row['ecotax_tax_incl'] = Tools::ps_round($row['ecotax_tax_incl'], _PS_PRICE_COMPUTE_PRECISION_, $round_mode); + if ($round_mode == Order::ROUND_ITEM) { + $row['ecotax_tax_incl'] = Tools::ps_round($row['ecotax_tax_incl'], _PS_PRICE_COMPUTE_PRECISION_, $round_mode); + } - $row['total_ecotax_tax_excl'] = $row['ecotax_tax_excl'] * $row['product_quantity']; - $row['total_ecotax_tax_incl'] = $row['ecotax_tax_incl'] * $row['product_quantity']; + $row['total_ecotax_tax_excl'] = $row['ecotax_tax_excl'] * $row['product_quantity']; + $row['total_ecotax_tax_incl'] = $row['ecotax_tax_incl'] * $row['product_quantity']; - $row['total_ecotax_tax'] = $row['total_ecotax_tax_incl'] - $row['total_ecotax_tax_excl']; + $row['total_ecotax_tax'] = $row['total_ecotax_tax_incl'] - $row['total_ecotax_tax_excl']; - foreach (array( - 'ecotax_tax_excl', - 'ecotax_tax_incl', - 'ecotax_tax', - 'total_ecotax_tax_excl', - 'total_ecotax_tax_incl', - 'total_ecotax_tax' - ) as $ecotax_field) - $row[$ecotax_field] = Tools::ps_round($row[$ecotax_field], _PS_PRICE_COMPUTE_PRECISION_, $round_mode); + foreach (array( + 'ecotax_tax_excl', + 'ecotax_tax_incl', + 'ecotax_tax', + 'total_ecotax_tax_excl', + 'total_ecotax_tax_incl', + 'total_ecotax_tax' + ) as $ecotax_field) { + $row[$ecotax_field] = Tools::ps_round($row[$ecotax_field], _PS_PRICE_COMPUTE_PRECISION_, $round_mode); + } - // Aliases - $row['unit_price_tax_excl_including_ecotax'] = $row['unit_price_tax_excl']; - $row['unit_price_tax_incl_including_ecotax'] = $row['unit_price_tax_incl']; - $row['total_price_tax_excl_including_ecotax'] = $row['total_price_tax_excl']; - $row['total_price_tax_incl_including_ecotax'] = $row['total_price_tax_incl']; + // Aliases + $row['unit_price_tax_excl_including_ecotax'] = $row['unit_price_tax_excl']; + $row['unit_price_tax_incl_including_ecotax'] = $row['unit_price_tax_incl']; + $row['total_price_tax_excl_including_ecotax'] = $row['total_price_tax_excl']; + $row['total_price_tax_incl_including_ecotax'] = $row['total_price_tax_incl']; - /* Stock product */ - $result_array[(int)$row['id_order_detail']] = $row; - } + /* Stock product */ + $result_array[(int)$row['id_order_detail']] = $row; + } - if ($customized_datas) - Product::addCustomizationPrice($result_array, $customized_datas); + if ($customized_datas) { + Product::addCustomizationPrice($result_array, $customized_datas); + } - return $result_array; - } + return $result_array; + } - protected function setProductCustomizedDatas(&$product, $customized_datas) - { - $product['customizedDatas'] = null; - if (isset($customized_datas[$product['product_id']][$product['product_attribute_id']])) - $product['customizedDatas'] = $customized_datas[$product['product_id']][$product['product_attribute_id']]; - else - $product['customizationQuantityTotal'] = 0; - } + protected function setProductCustomizedDatas(&$product, $customized_datas) + { + $product['customizedDatas'] = null; + if (isset($customized_datas[$product['product_id']][$product['product_attribute_id']])) { + $product['customizedDatas'] = $customized_datas[$product['product_id']][$product['product_attribute_id']]; + } else { + $product['customizationQuantityTotal'] = 0; + } + } - /** - * - * This method allow to add stock information on a product detail - * @param array &$product - */ - protected function setProductCurrentStock(&$product) - { - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') - && (int)$product['advanced_stock_management'] == 1 - && (int)$product['id_warehouse'] > 0) - $product['current_stock'] = StockManagerFactory::getManager()->getProductPhysicalQuantities($product['product_id'], $product['product_attribute_id'], null, true); - else - $product['current_stock'] = '--'; - } + /** + * + * This method allow to add stock information on a product detail + * @param array &$product + */ + protected function setProductCurrentStock(&$product) + { + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') + && (int)$product['advanced_stock_management'] == 1 + && (int)$product['id_warehouse'] > 0) { + $product['current_stock'] = StockManagerFactory::getManager()->getProductPhysicalQuantities($product['product_id'], $product['product_attribute_id'], null, true); + } else { + $product['current_stock'] = '--'; + } + } - /** - * - * This method allow to add image information on a product detail - * @param array &$product - */ - protected function setProductImageInformations(&$product) - { - if (isset($product['product_attribute_id']) && $product['product_attribute_id']) - $id_image = Db::getInstance()->getValue(' + /** + * + * This method allow to add image information on a product detail + * @param array &$product + */ + protected function setProductImageInformations(&$product) + { + if (isset($product['product_attribute_id']) && $product['product_attribute_id']) { + $id_image = Db::getInstance()->getValue(' SELECT image_shop.id_image FROM '._DB_PREFIX_.'product_attribute_image pai'. - Shop::addSqlAssociation('image', 'pai', true).' + Shop::addSqlAssociation('image', 'pai', true).' WHERE id_product_attribute = '.(int)$product['product_attribute_id']); + } - if (!isset($id_image) || !$id_image) - $id_image = Db::getInstance()->getValue(' + if (!isset($id_image) || !$id_image) { + $id_image = Db::getInstance()->getValue(' SELECT image_shop.id_image FROM '._DB_PREFIX_.'image i'. - Shop::addSqlAssociation('image', 'i', true, 'image_shop.cover=1').' + Shop::addSqlAssociation('image', 'i', true, 'image_shop.cover=1').' WHERE i.id_product = '.(int)$product['product_id']); + } - $product['image'] = null; - $product['image_size'] = null; + $product['image'] = null; + $product['image_size'] = null; - if ($id_image) - $product['image'] = new Image($id_image); - } + if ($id_image) { + $product['image'] = new Image($id_image); + } + } - /** - * This method returns true if at least one order details uses the - * One After Another tax computation method. - * - * @since 1.5 - * @return bool - */ - public function useOneAfterAnotherTaxComputationMethod() - { - // if one of the order details use the tax computation method the display will be different - return Db::getInstance()->getValue(' + /** + * This method returns true if at least one order details uses the + * One After Another tax computation method. + * + * @since 1.5 + * @return bool + */ + public function useOneAfterAnotherTaxComputationMethod() + { + // if one of the order details use the tax computation method the display will be different + return Db::getInstance()->getValue(' SELECT od.`tax_computation_method` FROM `'._DB_PREFIX_.'order_detail_tax` odt LEFT JOIN `'._DB_PREFIX_.'order_detail` od ON (od.`id_order_detail` = odt.`id_order_detail`) WHERE od.`id_order` = '.(int)$this->id_order.' AND od.`id_order_invoice` = '.(int)$this->id.' AND od.`tax_computation_method` = '.(int)TaxCalculator::ONE_AFTER_ANOTHER_METHOD - ) || Configuration::get('PS_INVOICE_TAXES_BREAKDOWN'); - } + ) || Configuration::get('PS_INVOICE_TAXES_BREAKDOWN'); + } - public function displayTaxBasesInProductTaxesBreakdown() - { - return !$this->useOneAfterAnotherTaxComputationMethod(); - } + public function displayTaxBasesInProductTaxesBreakdown() + { + return !$this->useOneAfterAnotherTaxComputationMethod(); + } - public function getOrder() - { - if (!$this->order) - $this->order = new Order($this->id_order); + public function getOrder() + { + if (!$this->order) { + $this->order = new Order($this->id_order); + } - return $this->order; - } + return $this->order; + } - public function getProductTaxesBreakdown($order = null) - { - if (!$order) - $order = $this->getOrder(); + public function getProductTaxesBreakdown($order = null) + { + if (!$order) { + $order = $this->getOrder(); + } - $sum_composite_taxes = !$this->useOneAfterAnotherTaxComputationMethod(); + $sum_composite_taxes = !$this->useOneAfterAnotherTaxComputationMethod(); - // $breakdown will be an array with tax rates as keys and at least the columns: - // - 'total_price_tax_excl' - // - 'total_amount' - $breakdown = array(); + // $breakdown will be an array with tax rates as keys and at least the columns: + // - 'total_price_tax_excl' + // - 'total_amount' + $breakdown = array(); - $details = $order->getProductTaxesDetails(); + $details = $order->getProductTaxesDetails(); - if ($sum_composite_taxes) - { + if ($sum_composite_taxes) { $grouped_details = array(); - foreach ($details as $row) - { - if (!isset($grouped_details[$row['id_order_detail']])) - { + foreach ($details as $row) { + if (!isset($grouped_details[$row['id_order_detail']])) { $grouped_details[$row['id_order_detail']] = array( - 'tax_rate' => 0, - 'total_tax_base' => 0, - 'total_amount' => 0, + 'tax_rate' => 0, + 'total_tax_base' => 0, + 'total_amount' => 0, 'id_tax' => $row['id_tax'], - ); + ); } $grouped_details[$row['id_order_detail']]['tax_rate'] += $row['tax_rate']; @@ -390,208 +390,201 @@ class OrderInvoiceCore extends ObjectModel $details = $grouped_details; } - foreach ($details as $row) - { - $rate = sprintf('%.3f', $row['tax_rate']); - if (!isset($breakdown[$rate])) - { - $breakdown[$rate] = array( - 'total_price_tax_excl' => 0, - 'total_amount' => 0, + foreach ($details as $row) { + $rate = sprintf('%.3f', $row['tax_rate']); + if (!isset($breakdown[$rate])) { + $breakdown[$rate] = array( + 'total_price_tax_excl' => 0, + 'total_amount' => 0, 'id_tax' => $row['id_tax'], - 'rate' =>$rate, - ); - } + 'rate' =>$rate, + ); + } - $breakdown[$rate]['total_price_tax_excl'] += $row['total_tax_base']; - $breakdown[$rate]['total_amount'] += $row['total_amount']; - } + $breakdown[$rate]['total_price_tax_excl'] += $row['total_tax_base']; + $breakdown[$rate]['total_amount'] += $row['total_amount']; + } - foreach ($breakdown as $rate => $data) - { - $breakdown[$rate]['total_price_tax_excl'] = Tools::ps_round($data['total_price_tax_excl'], _PS_PRICE_COMPUTE_PRECISION_, $order->round_mode); - $breakdown[$rate]['total_amount'] = Tools::ps_round($data['total_amount'], _PS_PRICE_COMPUTE_PRECISION_, $order->round_mode); - } + foreach ($breakdown as $rate => $data) { + $breakdown[$rate]['total_price_tax_excl'] = Tools::ps_round($data['total_price_tax_excl'], _PS_PRICE_COMPUTE_PRECISION_, $order->round_mode); + $breakdown[$rate]['total_amount'] = Tools::ps_round($data['total_amount'], _PS_PRICE_COMPUTE_PRECISION_, $order->round_mode); + } - ksort($breakdown); + ksort($breakdown); - return $breakdown; - } + return $breakdown; + } - /** - * Returns the shipping taxes breakdown - * - * @since 1.5 - * @param Order $order - * @return array - */ - public function getShippingTaxesBreakdown($order) - { - // No shipping breakdown if no shipping! - if ($this->total_shipping_tax_excl == 0) - return array(); + /** + * Returns the shipping taxes breakdown + * + * @since 1.5 + * @param Order $order + * @return array + */ + public function getShippingTaxesBreakdown($order) + { + // No shipping breakdown if no shipping! + if ($this->total_shipping_tax_excl == 0) { + return array(); + } - // No shipping breakdown if it's free! - foreach ($order->getCartRules() as $cart_rule) - if ($cart_rule['free_shipping']) - return array(); + // No shipping breakdown if it's free! + foreach ($order->getCartRules() as $cart_rule) { + if ($cart_rule['free_shipping']) { + return array(); + } + } - $shipping_tax_amount = $this->total_shipping_tax_incl - $this->total_shipping_tax_excl; + $shipping_tax_amount = $this->total_shipping_tax_incl - $this->total_shipping_tax_excl; - if (Configuration::get('PS_INVOICE_TAXES_BREAKDOWN') || Configuration::get('PS_ATCP_SHIPWRAP')) - { - $shipping_breakdown = Db::getInstance()->executeS( - 'SELECT t.id_tax, t.rate, oit.amount as total_amount + if (Configuration::get('PS_INVOICE_TAXES_BREAKDOWN') || Configuration::get('PS_ATCP_SHIPWRAP')) { + $shipping_breakdown = Db::getInstance()->executeS( + 'SELECT t.id_tax, t.rate, oit.amount as total_amount FROM `'._DB_PREFIX_.'tax` t INNER JOIN `'._DB_PREFIX_.'order_invoice_tax` oit ON oit.id_tax = t.id_tax WHERE oit.type = "shipping" AND oit.id_order_invoice = '.(int)$this->id - ); + ); - $sum_of_split_taxes = 0; - $sum_of_tax_bases = 0; - foreach ($shipping_breakdown as &$row) - { - if (Configuration::get('PS_ATCP_SHIPWRAP')) - { - $row['total_tax_excl'] = Tools::ps_round($row['total_amount'] / $row['rate'] * 100, _PS_PRICE_COMPUTE_PRECISION_, $this->getOrder()->round_mode); - $sum_of_tax_bases += $row['total_tax_excl']; - } - else - { - $row['total_tax_excl'] = $this->total_shipping_tax_excl; - } + $sum_of_split_taxes = 0; + $sum_of_tax_bases = 0; + foreach ($shipping_breakdown as &$row) { + if (Configuration::get('PS_ATCP_SHIPWRAP')) { + $row['total_tax_excl'] = Tools::ps_round($row['total_amount'] / $row['rate'] * 100, _PS_PRICE_COMPUTE_PRECISION_, $this->getOrder()->round_mode); + $sum_of_tax_bases += $row['total_tax_excl']; + } else { + $row['total_tax_excl'] = $this->total_shipping_tax_excl; + } - $row['total_amount'] = Tools::ps_round($row['total_amount'], _PS_PRICE_COMPUTE_PRECISION_, $this->getOrder()->round_mode); - $sum_of_split_taxes += $row['total_amount']; - } - unset($row); + $row['total_amount'] = Tools::ps_round($row['total_amount'], _PS_PRICE_COMPUTE_PRECISION_, $this->getOrder()->round_mode); + $sum_of_split_taxes += $row['total_amount']; + } + unset($row); - $delta_amount = $shipping_tax_amount - $sum_of_split_taxes; + $delta_amount = $shipping_tax_amount - $sum_of_split_taxes; - if ($delta_amount != 0) - Tools::spreadAmount($delta_amount, _PS_PRICE_COMPUTE_PRECISION_, $shipping_breakdown, 'total_amount'); + if ($delta_amount != 0) { + Tools::spreadAmount($delta_amount, _PS_PRICE_COMPUTE_PRECISION_, $shipping_breakdown, 'total_amount'); + } - $delta_base = $this->total_shipping_tax_excl - $sum_of_tax_bases; + $delta_base = $this->total_shipping_tax_excl - $sum_of_tax_bases; - if ($delta_base != 0) - Tools::spreadAmount($delta_base, _PS_PRICE_COMPUTE_PRECISION_, $shipping_breakdown, 'total_tax_excl'); - } - else - { - $shipping_breakdown = array( - array( - 'total_tax_excl' => $this->total_shipping_tax_excl, - 'rate' => $order->carrier_tax_rate, - 'total_amount' => $shipping_tax_amount, + if ($delta_base != 0) { + Tools::spreadAmount($delta_base, _PS_PRICE_COMPUTE_PRECISION_, $shipping_breakdown, 'total_tax_excl'); + } + } else { + $shipping_breakdown = array( + array( + 'total_tax_excl' => $this->total_shipping_tax_excl, + 'rate' => $order->carrier_tax_rate, + 'total_amount' => $shipping_tax_amount, 'id_tax' => null, - ) - ); - } + ) + ); + } - return $shipping_breakdown; - } + return $shipping_breakdown; + } - /** - * Returns the wrapping taxes breakdown - * - * @return array - */ - public function getWrappingTaxesBreakdown() - { - if ($this->total_wrapping_tax_excl == 0) - return array(); + /** + * Returns the wrapping taxes breakdown + * + * @return array + */ + public function getWrappingTaxesBreakdown() + { + if ($this->total_wrapping_tax_excl == 0) { + return array(); + } - $wrapping_tax_amount = $this->total_wrapping_tax_incl - $this->total_wrapping_tax_excl; + $wrapping_tax_amount = $this->total_wrapping_tax_incl - $this->total_wrapping_tax_excl; - $wrapping_breakdown = Db::getInstance()->executeS( - 'SELECT t.id_tax, t.rate, oit.amount as total_amount + $wrapping_breakdown = Db::getInstance()->executeS( + 'SELECT t.id_tax, t.rate, oit.amount as total_amount FROM `'._DB_PREFIX_.'tax` t INNER JOIN `'._DB_PREFIX_.'order_invoice_tax` oit ON oit.id_tax = t.id_tax WHERE oit.type = "wrapping" AND oit.id_order_invoice = '.(int)$this->id - ); + ); - $sum_of_split_taxes = 0; - $sum_of_tax_bases = 0; - $total_tax_rate = 0; - foreach ($wrapping_breakdown as &$row) - { - if (Configuration::get('PS_ATCP_SHIPWRAP')) - { - $row['total_tax_excl'] = Tools::ps_round($row['total_amount'] / $row['rate'] * 100, _PS_PRICE_COMPUTE_PRECISION_, $this->getOrder()->round_mode); - $sum_of_tax_bases += $row['total_tax_excl']; - } - else - { - $row['total_tax_excl'] = $this->total_wrapping_tax_excl; - } + $sum_of_split_taxes = 0; + $sum_of_tax_bases = 0; + $total_tax_rate = 0; + foreach ($wrapping_breakdown as &$row) { + if (Configuration::get('PS_ATCP_SHIPWRAP')) { + $row['total_tax_excl'] = Tools::ps_round($row['total_amount'] / $row['rate'] * 100, _PS_PRICE_COMPUTE_PRECISION_, $this->getOrder()->round_mode); + $sum_of_tax_bases += $row['total_tax_excl']; + } else { + $row['total_tax_excl'] = $this->total_wrapping_tax_excl; + } - $row['total_amount'] = Tools::ps_round($row['total_amount'], _PS_PRICE_COMPUTE_PRECISION_, $this->getOrder()->round_mode); - $sum_of_split_taxes += $row['total_amount']; - $total_tax_rate += (float)$row['rate']; - } - unset($row); + $row['total_amount'] = Tools::ps_round($row['total_amount'], _PS_PRICE_COMPUTE_PRECISION_, $this->getOrder()->round_mode); + $sum_of_split_taxes += $row['total_amount']; + $total_tax_rate += (float)$row['rate']; + } + unset($row); - $delta_amount = $wrapping_tax_amount - $sum_of_split_taxes; + $delta_amount = $wrapping_tax_amount - $sum_of_split_taxes; - if ($delta_amount != 0) - Tools::spreadAmount($delta_amount, _PS_PRICE_COMPUTE_PRECISION_, $wrapping_breakdown, 'total_amount'); + if ($delta_amount != 0) { + Tools::spreadAmount($delta_amount, _PS_PRICE_COMPUTE_PRECISION_, $wrapping_breakdown, 'total_amount'); + } - $delta_base = $this->total_wrapping_tax_excl - $sum_of_tax_bases; + $delta_base = $this->total_wrapping_tax_excl - $sum_of_tax_bases; - if ($delta_base != 0) - Tools::spreadAmount($delta_base, _PS_PRICE_COMPUTE_PRECISION_, $wrapping_breakdown, 'total_tax_excl'); + if ($delta_base != 0) { + Tools::spreadAmount($delta_base, _PS_PRICE_COMPUTE_PRECISION_, $wrapping_breakdown, 'total_tax_excl'); + } - if (!Configuration::get('PS_INVOICE_TAXES_BREAKDOWN') && !Configuration::get('PS_ATCP_SHIPWRAP')) - { - $wrapping_breakdown = array( - array( - 'total_tax_excl' => $this->total_wrapping_tax_excl, - 'rate' => $total_tax_rate, - 'total_amount' => $wrapping_tax_amount, - ) - ); - } + if (!Configuration::get('PS_INVOICE_TAXES_BREAKDOWN') && !Configuration::get('PS_ATCP_SHIPWRAP')) { + $wrapping_breakdown = array( + array( + 'total_tax_excl' => $this->total_wrapping_tax_excl, + 'rate' => $total_tax_rate, + 'total_amount' => $wrapping_tax_amount, + ) + ); + } - return $wrapping_breakdown; - } + return $wrapping_breakdown; + } - /** - * Returns the ecotax taxes breakdown - * - * @since 1.5 - * @return array - */ - public function getEcoTaxTaxesBreakdown() - { - $result = Db::getInstance()->executeS(' + /** + * Returns the ecotax taxes breakdown + * + * @since 1.5 + * @return array + */ + public function getEcoTaxTaxesBreakdown() + { + $result = Db::getInstance()->executeS(' SELECT `ecotax_tax_rate` as `rate`, SUM(`ecotax` * `product_quantity`) as `ecotax_tax_excl`, SUM(`ecotax` * `product_quantity`) as `ecotax_tax_incl` FROM `'._DB_PREFIX_.'order_detail` WHERE `id_order` = '.(int)$this->id_order.' AND `id_order_invoice` = '.(int)$this->id.' GROUP BY `ecotax_tax_rate`'); - $taxes = array(); - foreach ($result as $row) - if ($row['ecotax_tax_excl'] > 0) - { - $row['ecotax_tax_incl'] = Tools::ps_round($row['ecotax_tax_excl'] + ($row['ecotax_tax_excl'] * $row['rate'] / 100), _PS_PRICE_DISPLAY_PRECISION_); - $row['ecotax_tax_excl'] = Tools::ps_round($row['ecotax_tax_excl'], _PS_PRICE_DISPLAY_PRECISION_); - $taxes[] = $row; - } - return $taxes; - } + $taxes = array(); + foreach ($result as $row) { + if ($row['ecotax_tax_excl'] > 0) { + $row['ecotax_tax_incl'] = Tools::ps_round($row['ecotax_tax_excl'] + ($row['ecotax_tax_excl'] * $row['rate'] / 100), _PS_PRICE_DISPLAY_PRECISION_); + $row['ecotax_tax_excl'] = Tools::ps_round($row['ecotax_tax_excl'], _PS_PRICE_DISPLAY_PRECISION_); + $taxes[] = $row; + } + } + return $taxes; + } - /** - * Returns all the order invoice that match the date interval - * - * @since 1.5 - * @param $date_from - * @param $date_to - * @return array collection of OrderInvoice - */ - public static function getByDateInterval($date_from, $date_to) - { - $order_invoice_list = Db::getInstance()->executeS(' + /** + * Returns all the order invoice that match the date interval + * + * @since 1.5 + * @param $date_from + * @param $date_to + * @return array collection of OrderInvoice + */ + public static function getByDateInterval($date_from, $date_to) + { + $order_invoice_list = Db::getInstance()->executeS(' SELECT oi.* FROM `'._DB_PREFIX_.'order_invoice` oi LEFT JOIN `'._DB_PREFIX_.'orders` o ON (o.`id_order` = oi.`id_order`) @@ -602,17 +595,17 @@ class OrderInvoiceCore extends ObjectModel ORDER BY oi.date_add ASC '); - return ObjectModel::hydrateCollection('OrderInvoice', $order_invoice_list); - } + return ObjectModel::hydrateCollection('OrderInvoice', $order_invoice_list); + } - /** - * @since 1.5.0.3 - * @param $id_order_state - * @return array collection of OrderInvoice - */ - public static function getByStatus($id_order_state) - { - $order_invoice_list = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * @since 1.5.0.3 + * @param $id_order_state + * @return array collection of OrderInvoice + */ + public static function getByStatus($id_order_state) + { + $order_invoice_list = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT oi.* FROM `'._DB_PREFIX_.'order_invoice` oi LEFT JOIN `'._DB_PREFIX_.'orders` o ON (o.`id_order` = oi.`id_order`) @@ -622,18 +615,18 @@ class OrderInvoiceCore extends ObjectModel ORDER BY oi.`date_add` ASC '); - return ObjectModel::hydrateCollection('OrderInvoice', $order_invoice_list); - } + return ObjectModel::hydrateCollection('OrderInvoice', $order_invoice_list); + } - /** - * @since 1.5.0.3 - * @param $date_from - * @param $date_to - * @return array collection of invoice - */ - public static function getByDeliveryDateInterval($date_from, $date_to) - { - $order_invoice_list = Db::getInstance()->executeS(' + /** + * @since 1.5.0.3 + * @param $date_from + * @param $date_to + * @return array collection of invoice + */ + public static function getByDeliveryDateInterval($date_from, $date_to) + { + $order_invoice_list = Db::getInstance()->executeS(' SELECT oi.* FROM `'._DB_PREFIX_.'order_invoice` oi LEFT JOIN `'._DB_PREFIX_.'orders` o ON (o.`id_order` = oi.`id_order`) @@ -643,155 +636,155 @@ class OrderInvoiceCore extends ObjectModel ORDER BY oi.delivery_date ASC '); - return ObjectModel::hydrateCollection('OrderInvoice', $order_invoice_list); - } + return ObjectModel::hydrateCollection('OrderInvoice', $order_invoice_list); + } - /** - * @since 1.5 - * @param $id_order_invoice - */ - public static function getCarrier($id_order_invoice) - { - $carrier = false; - if ($id_carrier = OrderInvoice::getCarrierId($id_order_invoice)) - $carrier = new Carrier((int)$id_carrier); + /** + * @since 1.5 + * @param $id_order_invoice + */ + public static function getCarrier($id_order_invoice) + { + $carrier = false; + if ($id_carrier = OrderInvoice::getCarrierId($id_order_invoice)) { + $carrier = new Carrier((int)$id_carrier); + } - return $carrier; - } + return $carrier; + } - /** - * @since 1.5 - * @param $id_order_invoice - */ - public static function getCarrierId($id_order_invoice) - { - $sql = 'SELECT `id_carrier` + /** + * @since 1.5 + * @param $id_order_invoice + */ + public static function getCarrierId($id_order_invoice) + { + $sql = 'SELECT `id_carrier` FROM `'._DB_PREFIX_.'order_carrier` WHERE `id_order_invoice` = '.(int)$id_order_invoice; - return Db::getInstance()->getValue($sql); - } + return Db::getInstance()->getValue($sql); + } - /** - * @param int $id - * @return OrderInvoice - * @throws PrestaShopException - */ - public static function retrieveOneById($id) - { - $order_invoice = new OrderInvoice($id); - if (!Validate::isLoadedObject($order_invoice)) - throw new PrestaShopException('Can\'t load Order Invoice object for id: '.$id); - return $order_invoice; - } + /** + * @param int $id + * @return OrderInvoice + * @throws PrestaShopException + */ + public static function retrieveOneById($id) + { + $order_invoice = new OrderInvoice($id); + if (!Validate::isLoadedObject($order_invoice)) { + throw new PrestaShopException('Can\'t load Order Invoice object for id: '.$id); + } + return $order_invoice; + } - /** - * Amounts of payments - * @since 1.5.0.2 - * @return float Total paid - */ - public function getTotalPaid() - { - $cache_id = 'order_invoice_paid_'.(int)$this->id; - if (!Cache::isStored($cache_id)) - { - $amount = 0; - $payments = OrderPayment::getByInvoiceId($this->id); - foreach ($payments as $payment) - { - /** @var OrderPayment $payment */ - $amount += $payment->amount; - } - Cache::store($cache_id, $amount); - return $amount; - } - return Cache::retrieve($cache_id); - } + /** + * Amounts of payments + * @since 1.5.0.2 + * @return float Total paid + */ + public function getTotalPaid() + { + $cache_id = 'order_invoice_paid_'.(int)$this->id; + if (!Cache::isStored($cache_id)) { + $amount = 0; + $payments = OrderPayment::getByInvoiceId($this->id); + foreach ($payments as $payment) { + /** @var OrderPayment $payment */ + $amount += $payment->amount; + } + Cache::store($cache_id, $amount); + return $amount; + } + return Cache::retrieve($cache_id); + } - /** - * Rest Paid - * @since 1.5.0.2 - * @return float Rest Paid - */ - public function getRestPaid() - { - return round($this->total_paid_tax_incl + $this->getSiblingTotal() - $this->getTotalPaid(), 2); - } + /** + * Rest Paid + * @since 1.5.0.2 + * @return float Rest Paid + */ + public function getRestPaid() + { + return round($this->total_paid_tax_incl + $this->getSiblingTotal() - $this->getTotalPaid(), 2); + } - /** - * Return collection of order invoice object linked to the payments of the current order invoice object - * - * @since 1.5.0.14 - * @return PrestaShopCollection|array Collection of OrderInvoice or empty array - */ - public function getSibling() - { - $query = new DbQuery(); - $query->select('oip2.id_order_invoice'); - $query->from('order_invoice_payment', 'oip1'); - $query->innerJoin('order_invoice_payment', 'oip2', - 'oip2.id_order_payment = oip1.id_order_payment AND oip2.id_order_invoice <> oip1.id_order_invoice'); - $query->where('oip1.id_order_invoice = '.$this->id); + /** + * Return collection of order invoice object linked to the payments of the current order invoice object + * + * @since 1.5.0.14 + * @return PrestaShopCollection|array Collection of OrderInvoice or empty array + */ + public function getSibling() + { + $query = new DbQuery(); + $query->select('oip2.id_order_invoice'); + $query->from('order_invoice_payment', 'oip1'); + $query->innerJoin('order_invoice_payment', 'oip2', + 'oip2.id_order_payment = oip1.id_order_payment AND oip2.id_order_invoice <> oip1.id_order_invoice'); + $query->where('oip1.id_order_invoice = '.$this->id); - $invoices = Db::getInstance()->executeS($query); - if (!$invoices) - return array(); + $invoices = Db::getInstance()->executeS($query); + if (!$invoices) { + return array(); + } - $invoice_list = array(); - foreach ($invoices as $invoice) - $invoice_list[] = $invoice['id_order_invoice']; + $invoice_list = array(); + foreach ($invoices as $invoice) { + $invoice_list[] = $invoice['id_order_invoice']; + } - $payments = new PrestaShopCollection('OrderInvoice'); - $payments->where('id_order_invoice', 'IN', $invoice_list); + $payments = new PrestaShopCollection('OrderInvoice'); + $payments->where('id_order_invoice', 'IN', $invoice_list); - return $payments; - } + return $payments; + } - /** - * Return total to paid of sibling invoices - * - * @param int $mod TAX_EXCL, TAX_INCL, DETAIL - * - * @since 1.5.0.14 - */ - public function getSiblingTotal($mod = OrderInvoice::TAX_INCL) - { - $query = new DbQuery(); - $query->select('SUM(oi.total_paid_tax_incl) as total_paid_tax_incl, SUM(oi.total_paid_tax_excl) as total_paid_tax_excl'); - $query->from('order_invoice_payment', 'oip1'); - $query->innerJoin('order_invoice_payment', 'oip2', - 'oip2.id_order_payment = oip1.id_order_payment AND oip2.id_order_invoice <> oip1.id_order_invoice'); - $query->leftJoin('order_invoice', 'oi', - 'oi.id_order_invoice = oip2.id_order_invoice'); - $query->where('oip1.id_order_invoice = '.$this->id); + /** + * Return total to paid of sibling invoices + * + * @param int $mod TAX_EXCL, TAX_INCL, DETAIL + * + * @since 1.5.0.14 + */ + public function getSiblingTotal($mod = OrderInvoice::TAX_INCL) + { + $query = new DbQuery(); + $query->select('SUM(oi.total_paid_tax_incl) as total_paid_tax_incl, SUM(oi.total_paid_tax_excl) as total_paid_tax_excl'); + $query->from('order_invoice_payment', 'oip1'); + $query->innerJoin('order_invoice_payment', 'oip2', + 'oip2.id_order_payment = oip1.id_order_payment AND oip2.id_order_invoice <> oip1.id_order_invoice'); + $query->leftJoin('order_invoice', 'oi', + 'oi.id_order_invoice = oip2.id_order_invoice'); + $query->where('oip1.id_order_invoice = '.$this->id); - $row = Db::getInstance()->getRow($query); + $row = Db::getInstance()->getRow($query); - switch ($mod) - { - case OrderInvoice::TAX_EXCL: - return $row['total_paid_tax_excl']; - case OrderInvoice::TAX_INCL: - return $row['total_paid_tax_incl']; - default: - return $row; - } - } + switch ($mod) { + case OrderInvoice::TAX_EXCL: + return $row['total_paid_tax_excl']; + case OrderInvoice::TAX_INCL: + return $row['total_paid_tax_incl']; + default: + return $row; + } + } - /** - * Get global rest to paid - * This method will return something different of the method getRestPaid if - * there is an other invoice linked to the payments of the current invoice - * @since 1.5.0.13 - */ - public function getGlobalRestPaid() - { - static $cache; + /** + * Get global rest to paid + * This method will return something different of the method getRestPaid if + * there is an other invoice linked to the payments of the current invoice + * @since 1.5.0.13 + */ + public function getGlobalRestPaid() + { + static $cache; - if (!isset($cache[$this->id])) - { - $res = Db::getInstance()->getRow(' + if (!isset($cache[$this->id])) { + $res = Db::getInstance()->getRow(' SELECT SUM(sub.paid) paid, SUM(sub.to_paid) to_paid FROM ( SELECT @@ -806,76 +799,108 @@ class OrderInvoiceCore extends ObjectModel WHERE oip1.id_order_invoice = '.(int)$this->id.' GROUP BY op.id_order_payment ) sub'); - $cache[$this->id] = round($res['to_paid'] - $res['paid'], 2); - } + $cache[$this->id] = round($res['to_paid'] - $res['paid'], 2); + } - return $cache[$this->id]; - } + return $cache[$this->id]; + } - /** - * @since 1.5.0.2 - * @return bool Is paid ? - */ - public function isPaid() - { - return $this->getTotalPaid() == $this->total_paid_tax_incl; - } + /** + * @since 1.5.0.2 + * @return bool Is paid ? + */ + public function isPaid() + { + return $this->getTotalPaid() == $this->total_paid_tax_incl; + } - /** - * @since 1.5.0.2 - * @return PrestaShopCollection Collection of Order payment - */ - public function getOrderPaymentCollection() - { - return OrderPayment::getByInvoiceId($this->id); - } + /** + * @since 1.5.0.2 + * @return PrestaShopCollection Collection of Order payment + */ + public function getOrderPaymentCollection() + { + return OrderPayment::getByInvoiceId($this->id); + } - /** - * Get the formatted number of invoice - * @since 1.5.0.2 - * @param int $id_lang for invoice_prefix - * @return string - */ - public function getInvoiceNumberFormatted($id_lang, $id_shop = null) - { - $invoice_formatted_number = Hook::exec('actionInvoiceNumberFormatted', array( - get_class($this) => $this, - 'id_lang' => (int)$id_lang, - 'id_shop' => (int)$id_shop, - 'number' => (int)$this->number - )); + /** + * Get the formatted number of invoice + * @since 1.5.0.2 + * @param int $id_lang for invoice_prefix + * @return string + */ + public function getInvoiceNumberFormatted($id_lang, $id_shop = null) + { + $invoice_formatted_number = Hook::exec('actionInvoiceNumberFormatted', array( + get_class($this) => $this, + 'id_lang' => (int)$id_lang, + 'id_shop' => (int)$id_shop, + 'number' => (int)$this->number + )); - if (!empty($invoice_formatted_number)) - return $invoice_formatted_number; + if (!empty($invoice_formatted_number)) { + return $invoice_formatted_number; + } - return sprintf('%1$s%2$06d', Configuration::get('PS_INVOICE_PREFIX', $id_lang, null, $id_shop), $this->number); - } + return sprintf('%1$s%2$06d', Configuration::get('PS_INVOICE_PREFIX', $id_lang, null, $id_shop), $this->number); + } - public function saveCarrierTaxCalculator(array $taxes_amount) - { - $is_correct = true; - foreach ($taxes_amount as $id_tax => $amount) - { - $sql = 'INSERT INTO `'._DB_PREFIX_.'order_invoice_tax` (`id_order_invoice`, `type`, `id_tax`, `amount`) + public function saveCarrierTaxCalculator(array $taxes_amount) + { + $is_correct = true; + foreach ($taxes_amount as $id_tax => $amount) { + $sql = 'INSERT INTO `'._DB_PREFIX_.'order_invoice_tax` (`id_order_invoice`, `type`, `id_tax`, `amount`) VALUES ('.(int)$this->id.', \'shipping\', '.(int)$id_tax.', '.(float)$amount.')'; - $is_correct &= Db::getInstance()->execute($sql); - } + $is_correct &= Db::getInstance()->execute($sql); + } - return $is_correct; - } + return $is_correct; + } - public function saveWrappingTaxCalculator(array $taxes_amount) - { - $is_correct = true; - foreach ($taxes_amount as $id_tax => $amount) - { - $sql = 'INSERT INTO `'._DB_PREFIX_.'order_invoice_tax` (`id_order_invoice`, `type`, `id_tax`, `amount`) + public function saveWrappingTaxCalculator(array $taxes_amount) + { + $is_correct = true; + foreach ($taxes_amount as $id_tax => $amount) { + $sql = 'INSERT INTO `'._DB_PREFIX_.'order_invoice_tax` (`id_order_invoice`, `type`, `id_tax`, `amount`) VALUES ('.(int)$this->id.', \'wrapping\', '.(int)$id_tax.', '.(float)$amount.')'; - $is_correct &= Db::getInstance()->execute($sql); - } + $is_correct &= Db::getInstance()->execute($sql); + } - return $is_correct; - } + return $is_correct; + } + + public static function getCurrentFormattedShopAddress($id_shop = null) { + $address = new Address(); + $address->company = Configuration::get('PS_SHOP_NAME', null, null, $id_shop); + $address->address1 = Configuration::get('PS_SHOP_ADDR1', null, null, $id_shop); + $address->address2 = Configuration::get('PS_SHOP_ADDR2', null, null, $id_shop); + $address->postcode = Configuration::get('PS_SHOP_CODE', null, null, $id_shop); + $address->city = Configuration::get('PS_SHOP_CITY', null, null, $id_shop); + $address->phone = Configuration::get('PS_SHOP_PHONE', null, null, $id_shop); + $address->id_country = Configuration::get('PS_SHOP_COUNTRY_ID', null, null, $id_shop); + + return AddressFormat::generateAddress($address, array(), '<br />', ' '); + } + + /** + * This method is used to fix shop addresses that cannot be fixed during upgrade process + * (because uses the whole environnement of PS classes that is not available during upgrade). + * This method should execute once on an upgraded PrestaShop to fix all OrderInvoices in one shot. + * This method is triggered once during a (non bulk) creation of a PDF from an OrderInvoice that is not fixed yet. + * + * @since 1.6.1.1 + */ + public static function fixAllShopAddresses() { + $shop_ids = Shop::getShops(false, null, true); + $db = Db::getInstance(); + foreach($shop_ids as $id_shop) { + $address = self::getCurrentFormattedShopAddress($id_shop); + $escaped_address = $db->escape($address, true, true); + + $db->execute('UPDATE `'._DB_PREFIX_.'order_invoice` INNER JOIN `'._DB_PREFIX_.'orders` USING (`id_order`) + SET `shop_address` = \''.$escaped_address.'\' WHERE `shop_address` IS NULL AND `id_shop` = '.$id_shop); + } + } } diff --git a/classes/order/OrderMessage.php b/classes/order/OrderMessage.php index 1d00150d..47e4c472 100644 --- a/classes/order/OrderMessage.php +++ b/classes/order/OrderMessage.php @@ -26,45 +26,45 @@ class OrderMessageCore extends ObjectModel { - /** @var string name name */ - public $name; + /** @var string name name */ + public $name; - /** @var string message content */ - public $message; + /** @var string message content */ + public $message; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'order_message', - 'primary' => 'id_order_message', - 'multilang' => true, - 'fields' => array( - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'order_message', + 'primary' => 'id_order_message', + 'multilang' => true, + 'fields' => array( + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), - 'message' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isMessage', 'required' => true, 'size' => 1200), - ), - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), + 'message' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isMessage', 'required' => true, 'size' => 1200), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'id' => array('sqlId' => 'id_discount_type', 'xlink_resource' => 'order_message_lang'), - 'date_add' => array('sqlId' => 'date_add') - ) - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id' => array('sqlId' => 'id_discount_type', 'xlink_resource' => 'order_message_lang'), + 'date_add' => array('sqlId' => 'date_add') + ) + ); - public static function getOrderMessages($id_lang) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getOrderMessages($id_lang) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT om.id_order_message, oml.name, oml.message FROM '._DB_PREFIX_.'order_message om LEFT JOIN '._DB_PREFIX_.'order_message_lang oml ON (oml.id_order_message = om.id_order_message) WHERE oml.id_lang = '.(int)$id_lang.' ORDER BY name ASC'); - } + } } diff --git a/classes/order/OrderPayment.php b/classes/order/OrderPayment.php index d5468889..9030f9ac 100644 --- a/classes/order/OrderPayment.php +++ b/classes/order/OrderPayment.php @@ -26,118 +26,120 @@ class OrderPaymentCore extends ObjectModel { - public $order_reference; - public $id_currency; - public $amount; - public $payment_method; - public $conversion_rate; - public $transaction_id; - public $card_number; - public $card_brand; - public $card_expiration; - public $card_holder; - public $date_add; + public $order_reference; + public $id_currency; + public $amount; + public $payment_method; + public $conversion_rate; + public $transaction_id; + public $card_number; + public $card_brand; + public $card_expiration; + public $card_holder; + public $date_add; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'order_payment', - 'primary' => 'id_order_payment', - 'fields' => array( - 'order_reference' => array('type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 9), - 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isNegativePrice', 'required' => true), - 'payment_method' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'), - 'conversion_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'transaction_id' => array('type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254), - 'card_number' => array('type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254), - 'card_brand' => array('type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254), - 'card_expiration' => array('type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254), - 'card_holder' => array('type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'order_payment', + 'primary' => 'id_order_payment', + 'fields' => array( + 'order_reference' => array('type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 9), + 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isNegativePrice', 'required' => true), + 'payment_method' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'), + 'conversion_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'transaction_id' => array('type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254), + 'card_number' => array('type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254), + 'card_brand' => array('type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254), + 'card_expiration' => array('type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254), + 'card_holder' => array('type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - public function add($autodate = true, $nullValues = false) - { - if (parent::add($autodate, $nullValues)) - { - Hook::exec('actionPaymentCCAdd', array('paymentCC' => $this)); - return true; - } - return false; - } + public function add($autodate = true, $nullValues = false) + { + if (parent::add($autodate, $nullValues)) { + Hook::exec('actionPaymentCCAdd', array('paymentCC' => $this)); + return true; + } + return false; + } - /** - * Get the detailed payment of an order - * - * @deprecated 1.5.3.0 - * @param int $id_order - * @return array - */ - public static function getByOrderId($id_order) - { - Tools::displayAsDeprecated(); - $order = new Order($id_order); - return OrderPayment::getByOrderReference($order->reference); - } + /** + * Get the detailed payment of an order + * + * @deprecated 1.5.3.0 + * @param int $id_order + * @return array + */ + public static function getByOrderId($id_order) + { + Tools::displayAsDeprecated(); + $order = new Order($id_order); + return OrderPayment::getByOrderReference($order->reference); + } - /** - * Get the detailed payment of an order - * @param int $order_reference - * @return array - * @since 1.5.0.13 - */ - public static function getByOrderReference($order_reference) - { - return ObjectModel::hydrateCollection('OrderPayment', - Db::getInstance()->executeS(' + /** + * Get the detailed payment of an order + * @param int $order_reference + * @return array + * @since 1.5.0.13 + */ + public static function getByOrderReference($order_reference) + { + return ObjectModel::hydrateCollection('OrderPayment', + Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'order_payment` WHERE `order_reference` = \''.pSQL($order_reference).'\'') - ); - } + ); + } - /** - * Get Order Payments By Invoice ID - * - * @param int $id_invoice Invoice ID - * @return PrestaShopCollection Collection of OrderPayment - */ - public static function getByInvoiceId($id_invoice) - { - $payments = Db::getInstance()->executeS('SELECT id_order_payment FROM `'._DB_PREFIX_.'order_invoice_payment` WHERE id_order_invoice = '.(int)$id_invoice); - if (!$payments) - return array(); + /** + * Get Order Payments By Invoice ID + * + * @param int $id_invoice Invoice ID + * @return PrestaShopCollection Collection of OrderPayment + */ + public static function getByInvoiceId($id_invoice) + { + $payments = Db::getInstance()->executeS('SELECT id_order_payment FROM `'._DB_PREFIX_.'order_invoice_payment` WHERE id_order_invoice = '.(int)$id_invoice); + if (!$payments) { + return array(); + } - $payment_list = array(); - foreach ($payments as $payment) - $payment_list[] = $payment['id_order_payment']; + $payment_list = array(); + foreach ($payments as $payment) { + $payment_list[] = $payment['id_order_payment']; + } - $payments = new PrestaShopCollection('OrderPayment'); - $payments->where('id_order_payment', 'IN', $payment_list); - return $payments; - } + $payments = new PrestaShopCollection('OrderPayment'); + $payments->where('id_order_payment', 'IN', $payment_list); + return $payments; + } - /** - * Return order invoice object linked to the payment - * - * @param int $id_order Order Id - * - * @since 1.5.0.13 - */ - public function getOrderInvoice($id_order) - { - $res = Db::getInstance()->getValue(' + /** + * Return order invoice object linked to the payment + * + * @param int $id_order Order Id + * + * @since 1.5.0.13 + */ + public function getOrderInvoice($id_order) + { + $res = Db::getInstance()->getValue(' SELECT id_order_invoice FROM `'._DB_PREFIX_.'order_invoice_payment` WHERE id_order_payment = '.(int)$this->id.' AND id_order = '.(int)$id_order); - if (!$res) - return false; + if (!$res) { + return false; + } - return new OrderInvoice((int)$res); - } + return new OrderInvoice((int)$res); + } } diff --git a/classes/order/OrderReturn.php b/classes/order/OrderReturn.php index d876a1d6..64a4b4aa 100644 --- a/classes/order/OrderReturn.php +++ b/classes/order/OrderReturn.php @@ -26,195 +26,208 @@ class OrderReturnCore extends ObjectModel { - /** @var int */ - public $id; + /** @var int */ + public $id; - /** @var int */ - public $id_customer; + /** @var int */ + public $id_customer; - /** @var int */ - public $id_order; + /** @var int */ + public $id_order; - /** @var int */ - public $state; + /** @var int */ + public $state; - /** @var string message content */ - public $question; + /** @var string message content */ + public $question; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** @var string Object last modification date */ - public $date_upd; + /** @var string Object last modification date */ + public $date_upd; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'order_return', - 'primary' => 'id_order_return', - 'fields' => array( - 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'question' => array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'), - 'state' => array('type' => self::TYPE_STRING), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'order_return', + 'primary' => 'id_order_return', + 'fields' => array( + 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'question' => array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'), + 'state' => array('type' => self::TYPE_STRING), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - public function addReturnDetail($order_detail_list, $product_qty_list, $customization_ids, $customization_qty_input) - { - /* Classic product return */ - if ($order_detail_list) - foreach ($order_detail_list as $key => $order_detail) - if ($qty = (int)$product_qty_list[$key]) - Db::getInstance()->insert('order_return_detail', array('id_order_return' => (int)$this->id, 'id_order_detail' => (int)$order_detail, 'product_quantity' => $qty, 'id_customization' => 0)); - /* Customized product return */ - if ($customization_ids) - foreach ($customization_ids as $order_detail_id => $customizations) - foreach ($customizations as $customization_id) - if ($quantity = (int)$customization_qty_input[(int)$customization_id]) - Db::getInstance()->insert('order_return_detail', array('id_order_return' => (int)$this->id, 'id_order_detail' => (int)$order_detail_id, 'product_quantity' => $quantity, 'id_customization' => (int)$customization_id)); - } + public function addReturnDetail($order_detail_list, $product_qty_list, $customization_ids, $customization_qty_input) + { + /* Classic product return */ + if ($order_detail_list) { + foreach ($order_detail_list as $key => $order_detail) { + if ($qty = (int)$product_qty_list[$key]) { + Db::getInstance()->insert('order_return_detail', array('id_order_return' => (int)$this->id, 'id_order_detail' => (int)$order_detail, 'product_quantity' => $qty, 'id_customization' => 0)); + } + } + } + /* Customized product return */ + if ($customization_ids) { + foreach ($customization_ids as $order_detail_id => $customizations) { + foreach ($customizations as $customization_id) { + if ($quantity = (int)$customization_qty_input[(int)$customization_id]) { + Db::getInstance()->insert('order_return_detail', array('id_order_return' => (int)$this->id, 'id_order_detail' => (int)$order_detail_id, 'product_quantity' => $quantity, 'id_customization' => (int)$customization_id)); + } + } + } + } + } - public function checkEnoughProduct($order_detail_list, $product_qty_list, $customization_ids, $customization_qty_input) - { - $order = new Order((int)$this->id_order); - if (!Validate::isLoadedObject($order)) - die(Tools::displayError()); - $products = $order->getProducts(); - /* Products already returned */ - $order_return = OrderReturn::getOrdersReturn($order->id_customer, $order->id, true); - foreach ($order_return as $or) - { - $order_return_products = OrderReturn::getOrdersReturnProducts($or['id_order_return'], $order); - foreach ($order_return_products as $key => $orp) - $products[$key]['product_quantity'] -= (int)$orp['product_quantity']; - } - /* Quantity check */ - if ($order_detail_list) - foreach (array_keys($order_detail_list) as $key) - if ($qty = (int)$product_qty_list[$key]) - if ($products[$key]['product_quantity'] - $qty < 0) - return false; - /* Customization quantity check */ - if ($customization_ids) - { - $ordered_customizations = Customization::getOrderedCustomizations((int)$order->id_cart); - foreach ($customization_ids as $customizations) - foreach ($customizations as $customization_id) - { - $customization_id = (int)$customization_id; - if (!isset($ordered_customizations[$customization_id])) - return false; - $quantity = (isset($customization_qty_input[$customization_id]) ? (int)$customization_qty_input[$customization_id] : 0); - if ((int)$ordered_customizations[$customization_id]['quantity'] - $quantity < 0) - return false; - } - } - return true; - } + public function checkEnoughProduct($order_detail_list, $product_qty_list, $customization_ids, $customization_qty_input) + { + $order = new Order((int)$this->id_order); + if (!Validate::isLoadedObject($order)) { + die(Tools::displayError()); + } + $products = $order->getProducts(); + /* Products already returned */ + $order_return = OrderReturn::getOrdersReturn($order->id_customer, $order->id, true); + foreach ($order_return as $or) { + $order_return_products = OrderReturn::getOrdersReturnProducts($or['id_order_return'], $order); + foreach ($order_return_products as $key => $orp) { + $products[$key]['product_quantity'] -= (int)$orp['product_quantity']; + } + } + /* Quantity check */ + if ($order_detail_list) { + foreach (array_keys($order_detail_list) as $key) { + if ($qty = (int)$product_qty_list[$key]) { + if ($products[$key]['product_quantity'] - $qty < 0) { + return false; + } + } + } + } + /* Customization quantity check */ + if ($customization_ids) { + $ordered_customizations = Customization::getOrderedCustomizations((int)$order->id_cart); + foreach ($customization_ids as $customizations) { + foreach ($customizations as $customization_id) { + $customization_id = (int)$customization_id; + if (!isset($ordered_customizations[$customization_id])) { + return false; + } + $quantity = (isset($customization_qty_input[$customization_id]) ? (int)$customization_qty_input[$customization_id] : 0); + if ((int)$ordered_customizations[$customization_id]['quantity'] - $quantity < 0) { + return false; + } + } + } + } + return true; + } - public function countProduct() - { - if (!$data = Db::getInstance()->getRow(' + public function countProduct() + { + if (!$data = Db::getInstance()->getRow(' SELECT COUNT(`id_order_return`) AS total FROM `'._DB_PREFIX_.'order_return_detail` - WHERE `id_order_return` = '.(int)$this->id)) - return false; - return (int)($data['total']); - } + WHERE `id_order_return` = '.(int)$this->id)) { + return false; + } + return (int)($data['total']); + } - public static function getOrdersReturn($customer_id, $order_id = false, $no_denied = false, Context $context = null) - { - if (!$context) - $context = Context::getContext(); - $data = Db::getInstance()->executeS(' + public static function getOrdersReturn($customer_id, $order_id = false, $no_denied = false, Context $context = null) + { + if (!$context) { + $context = Context::getContext(); + } + $data = Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'order_return` WHERE `id_customer` = '.(int)$customer_id. - ($order_id ? ' AND `id_order` = '.(int)$order_id : ''). - ($no_denied ? ' AND `state` != 4' : '').' + ($order_id ? ' AND `id_order` = '.(int)$order_id : ''). + ($no_denied ? ' AND `state` != 4' : '').' ORDER BY `date_add` DESC'); - foreach ($data as $k => $or) - { - $state = new OrderReturnState($or['state']); - $data[$k]['state_name'] = $state->name[$context->language->id]; - $data[$k]['type'] = 'Return'; - $data[$k]['tracking_number'] = $or['id_order_return']; - $data[$k]['can_edit'] = false; - $data[$k]['reference'] = Order::getUniqReferenceOf($or['id_order']); - } - return $data; - } + foreach ($data as $k => $or) { + $state = new OrderReturnState($or['state']); + $data[$k]['state_name'] = $state->name[$context->language->id]; + $data[$k]['type'] = 'Return'; + $data[$k]['tracking_number'] = $or['id_order_return']; + $data[$k]['can_edit'] = false; + $data[$k]['reference'] = Order::getUniqReferenceOf($or['id_order']); + } + return $data; + } - public static function getOrdersReturnDetail($id_order_return) - { - return Db::getInstance()->executeS(' + public static function getOrdersReturnDetail($id_order_return) + { + return Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'order_return_detail` WHERE `id_order_return` = '.(int)$id_order_return); - } + } - /** - * @param int $order_return_id - * @param Order $order - * @return array - */ - public static function getOrdersReturnProducts($order_return_id, $order) - { - $products_ret = OrderReturn::getOrdersReturnDetail($order_return_id); - $products = $order->getProducts(); - $tmp = array(); - foreach ($products_ret as $return_detail) - { - $tmp[$return_detail['id_order_detail']]['quantity'] = isset($tmp[$return_detail['id_order_detail']]['quantity']) ? $tmp[$return_detail['id_order_detail']]['quantity'] + (int)$return_detail['product_quantity'] : (int)$return_detail['product_quantity']; - $tmp[$return_detail['id_order_detail']]['customizations'] = (int)$return_detail['id_customization']; - } - $res_tab = array(); - foreach ($products as $key => $product) - if (isset($tmp[$product['id_order_detail']])) - { - $res_tab[$key] = $product; - $res_tab[$key]['product_quantity'] = $tmp[$product['id_order_detail']]['quantity']; - $res_tab[$key]['customizations'] = $tmp[$product['id_order_detail']]['customizations']; - } - return $res_tab; - } + /** + * @param int $order_return_id + * @param Order $order + * @return array + */ + public static function getOrdersReturnProducts($order_return_id, $order) + { + $products_ret = OrderReturn::getOrdersReturnDetail($order_return_id); + $products = $order->getProducts(); + $tmp = array(); + foreach ($products_ret as $return_detail) { + $tmp[$return_detail['id_order_detail']]['quantity'] = isset($tmp[$return_detail['id_order_detail']]['quantity']) ? $tmp[$return_detail['id_order_detail']]['quantity'] + (int)$return_detail['product_quantity'] : (int)$return_detail['product_quantity']; + $tmp[$return_detail['id_order_detail']]['customizations'] = (int)$return_detail['id_customization']; + } + $res_tab = array(); + foreach ($products as $key => $product) { + if (isset($tmp[$product['id_order_detail']])) { + $res_tab[$key] = $product; + $res_tab[$key]['product_quantity'] = $tmp[$product['id_order_detail']]['quantity']; + $res_tab[$key]['customizations'] = $tmp[$product['id_order_detail']]['customizations']; + } + } + return $res_tab; + } - public static function getReturnedCustomizedProducts($id_order) - { - $returns = Customization::getReturnedCustomizations($id_order); - $order = new Order((int)$id_order); - if (!Validate::isLoadedObject($order)) - die(Tools::displayError()); - $products = $order->getProducts(); + public static function getReturnedCustomizedProducts($id_order) + { + $returns = Customization::getReturnedCustomizations($id_order); + $order = new Order((int)$id_order); + if (!Validate::isLoadedObject($order)) { + die(Tools::displayError()); + } + $products = $order->getProducts(); - foreach ($returns as &$return) - { - $return['product_id'] = (int)$products[(int)$return['id_order_detail']]['product_id']; - $return['product_attribute_id'] = (int)$products[(int)$return['id_order_detail']]['product_attribute_id']; - $return['name'] = $products[(int)$return['id_order_detail']]['product_name']; - $return['reference'] = $products[(int)$return['id_order_detail']]['product_reference']; - $return['id_address_delivery'] = $products[(int)$return['id_order_detail']]['id_address_delivery']; - } - return $returns; - } + foreach ($returns as &$return) { + $return['product_id'] = (int)$products[(int)$return['id_order_detail']]['product_id']; + $return['product_attribute_id'] = (int)$products[(int)$return['id_order_detail']]['product_attribute_id']; + $return['name'] = $products[(int)$return['id_order_detail']]['product_name']; + $return['reference'] = $products[(int)$return['id_order_detail']]['product_reference']; + $return['id_address_delivery'] = $products[(int)$return['id_order_detail']]['id_address_delivery']; + } + return $returns; + } - public static function deleteOrderReturnDetail($id_order_return, $id_order_detail, $id_customization = 0) - { - return Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'order_return_detail` WHERE `id_order_detail` = '.(int)$id_order_detail.' AND `id_order_return` = '.(int)$id_order_return.' AND `id_customization` = '.(int)$id_customization); - } + public static function deleteOrderReturnDetail($id_order_return, $id_order_detail, $id_customization = 0) + { + return Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'order_return_detail` WHERE `id_order_detail` = '.(int)$id_order_detail.' AND `id_order_return` = '.(int)$id_order_return.' AND `id_customization` = '.(int)$id_customization); + } - /** - * - * Get return details for one product line - * @param $id_order_detail - */ - public static function getProductReturnDetail($id_order_detail) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * + * Get return details for one product line + * @param $id_order_detail + */ + public static function getProductReturnDetail($id_order_detail) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT product_quantity, date_add, orsl.name as state FROM `'._DB_PREFIX_.'order_return_detail` ord LEFT JOIN `'._DB_PREFIX_.'order_return` o @@ -222,33 +235,37 @@ class OrderReturnCore extends ObjectModel LEFT JOIN `'._DB_PREFIX_.'order_return_state_lang` orsl ON orsl.id_order_return_state = o.state AND orsl.id_lang = '.(int)Context::getContext()->language->id.' WHERE ord.`id_order_detail` = '.(int)$id_order_detail); - } + } - /** - * - * Add returned quantity to products list - * @param array $products - * @param int $id_order - */ - public static function addReturnedQuantity(&$products, $id_order) - { - $details = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * + * Add returned quantity to products list + * @param array $products + * @param int $id_order + */ + public static function addReturnedQuantity(&$products, $id_order) + { + $details = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT od.id_order_detail, GREATEST(od.product_quantity_return, IFNULL(SUM(ord.product_quantity),0)) as qty_returned FROM '._DB_PREFIX_.'order_detail od LEFT JOIN '._DB_PREFIX_.'order_return_detail ord ON ord.id_order_detail = od.id_order_detail WHERE od.id_order = '.(int)$id_order.' GROUP BY od.id_order_detail' - ); - if (!$details) - return; + ); + if (!$details) { + return; + } - $detail_list = array(); - foreach ($details as $detail) - $detail_list[$detail['id_order_detail']] = $detail; + $detail_list = array(); + foreach ($details as $detail) { + $detail_list[$detail['id_order_detail']] = $detail; + } - foreach ($products as &$product) - if (isset($detail_list[$product['id_order_detail']]['qty_returned'])) - $product['qty_returned'] = $detail_list[$product['id_order_detail']]['qty_returned']; - } -} \ No newline at end of file + foreach ($products as &$product) { + if (isset($detail_list[$product['id_order_detail']]['qty_returned'])) { + $product['qty_returned'] = $detail_list[$product['id_order_detail']]['qty_returned']; + } + } + } +} diff --git a/classes/order/OrderReturnState.php b/classes/order/OrderReturnState.php index ac9c5529..a79efc48 100644 --- a/classes/order/OrderReturnState.php +++ b/classes/order/OrderReturnState.php @@ -26,39 +26,39 @@ class OrderReturnStateCore extends ObjectModel { - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var string Display state in the specified color */ - public $color; + /** @var string Display state in the specified color */ + public $color; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'order_return_state', - 'primary' => 'id_order_return_state', - 'multilang' => true, - 'fields' => array( - 'color' => array('type' => self::TYPE_STRING, 'validate' => 'isColor'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'order_return_state', + 'primary' => 'id_order_return_state', + 'multilang' => true, + 'fields' => array( + 'color' => array('type' => self::TYPE_STRING, 'validate' => 'isColor'), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), - ), - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), + ), + ); - /** - * Get all available order statuses - * - * @param int $id_lang Language id for status name - * @return array Order statuses - */ - public static function getOrderReturnStates($id_lang) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * Get all available order statuses + * + * @param int $id_lang Language id for status name + * @return array Order statuses + */ + public static function getOrderReturnStates($id_lang) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'order_return_state` ors LEFT JOIN `'._DB_PREFIX_.'order_return_state_lang` orsl ON (ors.`id_order_return_state` = orsl.`id_order_return_state` AND orsl.`id_lang` = '.(int)$id_lang.') ORDER BY ors.`id_order_return_state` ASC'); - } -} \ No newline at end of file + } +} diff --git a/classes/order/OrderSlip.php b/classes/order/OrderSlip.php index 9cda9e17..33fe5d02 100644 --- a/classes/order/OrderSlip.php +++ b/classes/order/OrderSlip.php @@ -26,195 +26,206 @@ class OrderSlipCore extends ObjectModel { - /** @var int */ - public $id; + /** @var int */ + public $id; - /** @var int */ - public $id_customer; + /** @var int */ + public $id_customer; - /** @var int */ - public $id_order; + /** @var int */ + public $id_order; - /** @var float */ - public $conversion_rate; + /** @var float */ + public $conversion_rate; - /** @var int */ - public $amount; + /** @var float */ + public $total_products_tax_excl; - /** @var int */ - public $shipping_cost; + /** @var float */ + public $total_products_tax_incl; - /** @var int */ - public $shipping_cost_amount; + /** @var float */ + public $total_shipping_tax_excl; - /** @var int */ - public $partial; + /** @var float */ + public $total_shipping_tax_incl; - /** @var string Object creation date */ - public $date_add; + /** @var int */ + public $amount; - /** @var string Object last modification date */ - public $date_upd; + /** @var int */ + public $shipping_cost; - /** @var int */ - public $order_slip_type = 0; + /** @var int */ + public $shipping_cost_amount; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'order_slip', - 'primary' => 'id_order_slip', - 'fields' => array( - 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'conversion_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), - 'total_products_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), - 'total_products_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), - 'total_shipping_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), - 'total_shipping_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), - 'amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'shipping_cost' => array('type' => self::TYPE_INT), - 'shipping_cost_amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), - 'partial' => array('type' => self::TYPE_INT), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'order_slip_type' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), - ), - ); + /** @var int */ + public $partial; - protected $webserviceParameters = array( - 'objectNodeName' => 'order_slip', - 'objectsNodeName' => 'order_slips', - 'fields' => array( - 'id_customer' => array('xlink_resource'=> 'customers'), - 'id_order' => array('xlink_resource'=> 'orders'), - ), - 'associations' => array( - 'order_slip_details' => array('resource' => 'order_slip_detail', 'setter' => false, 'virtual_entity' => true, - 'fields' => array( - 'id' => array(), - 'id_order_detail' => array('required' => true), - 'product_quantity' => array('required' => true), - 'amount_tax_excl' => array('required' => true), - 'amount_tax_incl' => array('required' => true), - )), - ), - ); + /** @var string Object creation date */ + public $date_add; - public function addSlipDetail($orderDetailList, $productQtyList) - { - foreach ($orderDetailList as $key => $id_order_detail) - { - if ($qty = (int)($productQtyList[$key])) - { - $order_detail = new OrderDetail((int)$id_order_detail); + /** @var string Object last modification date */ + public $date_upd; - if (Validate::isLoadedObject($order_detail)) - Db::getInstance()->insert('order_slip_detail', array( - 'id_order_slip' => (int)$this->id, - 'id_order_detail' => (int)$id_order_detail, - 'product_quantity' => $qty, - 'amount_tax_excl' => $order_detail->unit_price_tax_excl * $qty, - 'amount_tax_incl' => $order_detail->unit_price_tax_incl * $qty - )); - } - } - } + /** @var int */ + public $order_slip_type = 0; - public static function getOrdersSlip($customer_id, $order_id = false) - { - return Db::getInstance()->executeS(' + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'order_slip', + 'primary' => 'id_order_slip', + 'fields' => array( + 'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'conversion_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), + 'total_products_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), + 'total_products_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), + 'total_shipping_tax_excl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), + 'total_shipping_tax_incl' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), + 'amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'shipping_cost' => array('type' => self::TYPE_INT), + 'shipping_cost_amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), + 'partial' => array('type' => self::TYPE_INT), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'order_slip_type' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), + ), + ); + + protected $webserviceParameters = array( + 'objectNodeName' => 'order_slip', + 'objectsNodeName' => 'order_slips', + 'fields' => array( + 'id_customer' => array('xlink_resource'=> 'customers'), + 'id_order' => array('xlink_resource'=> 'orders'), + ), + 'associations' => array( + 'order_slip_details' => array('resource' => 'order_slip_detail', 'setter' => false, 'virtual_entity' => true, + 'fields' => array( + 'id' => array(), + 'id_order_detail' => array('required' => true), + 'product_quantity' => array('required' => true), + 'amount_tax_excl' => array('required' => true), + 'amount_tax_incl' => array('required' => true), + )), + ), + ); + + public function addSlipDetail($orderDetailList, $productQtyList) + { + foreach ($orderDetailList as $key => $id_order_detail) { + if ($qty = (int)($productQtyList[$key])) { + $order_detail = new OrderDetail((int)$id_order_detail); + + if (Validate::isLoadedObject($order_detail)) { + Db::getInstance()->insert('order_slip_detail', array( + 'id_order_slip' => (int)$this->id, + 'id_order_detail' => (int)$id_order_detail, + 'product_quantity' => $qty, + 'amount_tax_excl' => $order_detail->unit_price_tax_excl * $qty, + 'amount_tax_incl' => $order_detail->unit_price_tax_incl * $qty + )); + } + } + } + } + + public static function getOrdersSlip($customer_id, $order_id = false) + { + return Db::getInstance()->executeS(' SELECT * FROM `'._DB_PREFIX_.'order_slip` WHERE `id_customer` = '.(int)($customer_id). - ($order_id ? ' AND `id_order` = '.(int)($order_id) : '').' + ($order_id ? ' AND `id_order` = '.(int)($order_id) : '').' ORDER BY `date_add` DESC'); - } + } - public static function getOrdersSlipDetail($id_order_slip = false, $id_order_detail = false) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS( - ($id_order_detail ? 'SELECT SUM(`product_quantity`) AS `total`' : 'SELECT *'). - 'FROM `'._DB_PREFIX_.'order_slip_detail`' - .($id_order_slip ? ' WHERE `id_order_slip` = '.(int)($id_order_slip) : '') - .($id_order_detail ? ' WHERE `id_order_detail` = '.(int)($id_order_detail) : '')); - } + public static function getOrdersSlipDetail($id_order_slip = false, $id_order_detail = false) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS( + ($id_order_detail ? 'SELECT SUM(`product_quantity`) AS `total`' : 'SELECT *'). + 'FROM `'._DB_PREFIX_.'order_slip_detail`' + .($id_order_slip ? ' WHERE `id_order_slip` = '.(int)($id_order_slip) : '') + .($id_order_detail ? ' WHERE `id_order_detail` = '.(int)($id_order_detail) : '')); + } - /** - * @param int $orderSlipId - * @param Order $order - * @return array - */ - public static function getOrdersSlipProducts($orderSlipId, $order) - { - $cart_rules = $order->getCartRules(true); - $productsRet = OrderSlip::getOrdersSlipDetail($orderSlipId); - $order_details = $order->getProductsDetail(); + /** + * @param int $orderSlipId + * @param Order $order + * @return array + */ + public static function getOrdersSlipProducts($orderSlipId, $order) + { + $cart_rules = $order->getCartRules(true); + $productsRet = OrderSlip::getOrdersSlipDetail($orderSlipId); + $order_details = $order->getProductsDetail(); - $slip_quantity = array(); - foreach ($productsRet as $slip_detail) - $slip_quantity[$slip_detail['id_order_detail']] = $slip_detail; + $slip_quantity = array(); + foreach ($productsRet as $slip_detail) { + $slip_quantity[$slip_detail['id_order_detail']] = $slip_detail; + } - $products = array(); - foreach ($order_details as $key => $product) - if (isset($slip_quantity[$product['id_order_detail']]) && $slip_quantity[$product['id_order_detail']]['product_quantity']) - { - $products[$key] = $product; - $products[$key] = array_merge($products[$key], $slip_quantity[$product['id_order_detail']]); - } - return $order->getProducts($products); - } + $products = array(); + foreach ($order_details as $key => $product) { + if (isset($slip_quantity[$product['id_order_detail']]) && $slip_quantity[$product['id_order_detail']]['product_quantity']) { + $products[$key] = $product; + $products[$key] = array_merge($products[$key], $slip_quantity[$product['id_order_detail']]); + } + } + return $order->getProducts($products); + } - /** - * - * Get resume of all refund for one product line - * @param $id_order_detail - */ - public static function getProductSlipResume($id_order_detail) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + /** + * + * Get resume of all refund for one product line + * @param $id_order_detail + */ + public static function getProductSlipResume($id_order_detail) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT SUM(product_quantity) product_quantity, SUM(amount_tax_excl) amount_tax_excl, SUM(amount_tax_incl) amount_tax_incl FROM `'._DB_PREFIX_.'order_slip_detail` WHERE `id_order_detail` = '.(int)$id_order_detail); - } + } - /** - * - * Get refund details for one product line - * @param $id_order_detail - */ - public static function getProductSlipDetail($id_order_detail) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * + * Get refund details for one product line + * @param $id_order_detail + */ + public static function getProductSlipDetail($id_order_detail) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT product_quantity, amount_tax_excl, amount_tax_incl, date_add FROM `'._DB_PREFIX_.'order_slip_detail` osd LEFT JOIN `'._DB_PREFIX_.'order_slip` os ON os.id_order_slip = osd.id_order_slip WHERE osd.`id_order_detail` = '.(int)$id_order_detail); - } + } - public function getProducts() - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public function getProducts() + { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT *, osd.product_quantity FROM `'._DB_PREFIX_.'order_slip_detail` osd INNER JOIN `'._DB_PREFIX_.'order_detail` od ON osd.id_order_detail = od.id_order_detail WHERE osd.`id_order_slip` = '.(int)$this->id); - $order = new Order($this->id_order); - $products = array(); - foreach ($result as $row) - { - $order->setProductPrices($row); - $products[] = $row; - } - return $products; - } + $order = new Order($this->id_order); + $products = array(); + foreach ($result as $row) { + $order->setProductPrices($row); + $products[] = $row; + } + return $products; + } - public static function getSlipsIdByDate($dateFrom, $dateTo) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getSlipsIdByDate($dateFrom, $dateTo) + { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT `id_order_slip` FROM `'._DB_PREFIX_.'order_slip` os LEFT JOIN `'._DB_PREFIX_.'orders` o ON (o.`id_order` = os.`id_order`) @@ -222,311 +233,310 @@ class OrderSlipCore extends ObjectModel '.Shop::addSqlRestriction(Shop::SHARE_ORDER, 'o').' ORDER BY os.`date_add` ASC'); - $slips = array(); - foreach ($result as $slip) - $slips[] = (int)$slip['id_order_slip']; - return $slips; - } + $slips = array(); + foreach ($result as $slip) { + $slips[] = (int)$slip['id_order_slip']; + } + return $slips; + } - /** - * @deprecated since 1.6.0.10 use OrderSlip::create() instead - * - */ - public static function createOrderSlip($order, $productList, $qtyList, $shipping_cost = false) - { - Tools::displayAsDeprecated(); + /** + * @deprecated since 1.6.0.10 use OrderSlip::create() instead + * + */ + public static function createOrderSlip($order, $productList, $qtyList, $shipping_cost = false) + { + Tools::displayAsDeprecated(); - $product_list = array(); - foreach ($productList as $id_order_detail) - { - $order_detail = new OrderDetail((int)$id_order_detail); - $product_list[$id_order_detail] = array( - 'id_order_detail' => $id_order_detail, - 'quantity' => $qtyList[$id_order_detail], - 'unit_price' => $order_detail->unit_price_tax_excl, - 'amount' => $order_detail->unit_price_tax_incl * $qtyList[$id_order_detail], - ); + $product_list = array(); + foreach ($productList as $id_order_detail) { + $order_detail = new OrderDetail((int)$id_order_detail); + $product_list[$id_order_detail] = array( + 'id_order_detail' => $id_order_detail, + 'quantity' => $qtyList[$id_order_detail], + 'unit_price' => $order_detail->unit_price_tax_excl, + 'amount' => $order_detail->unit_price_tax_incl * $qtyList[$id_order_detail], + ); - $shipping = $shipping_cost ? null : false; - } + $shipping = $shipping_cost ? null : false; + } - return OrderSlip::create($order, $product_list, $shipping); - } + return OrderSlip::create($order, $product_list, $shipping); + } - public static function create(Order $order, $product_list, $shipping_cost = false, $amount = 0, $amount_choosen = false, $add_tax = true) - { - $currency = new Currency((int)$order->id_currency); - $order_slip = new OrderSlip(); - $order_slip->id_customer = (int)$order->id_customer; - $order_slip->id_order = (int)$order->id; - $order_slip->conversion_rate = $currency->conversion_rate; + public static function create(Order $order, $product_list, $shipping_cost = false, $amount = 0, $amount_choosen = false, $add_tax = true) + { + $currency = new Currency((int)$order->id_currency); + $order_slip = new OrderSlip(); + $order_slip->id_customer = (int)$order->id_customer; + $order_slip->id_order = (int)$order->id; + $order_slip->conversion_rate = $currency->conversion_rate; - if ($add_tax) - { - $add_or_remove = 'add'; - $inc_or_ex_1 = 'excl'; - $inc_or_ex_2 = 'incl'; - } - else - { - $add_or_remove = 'remove'; - $inc_or_ex_1 = 'incl'; - $inc_or_ex_2 = 'excl'; - } + if ($add_tax) { + $add_or_remove = 'add'; + $inc_or_ex_1 = 'excl'; + $inc_or_ex_2 = 'incl'; + } else { + $add_or_remove = 'remove'; + $inc_or_ex_1 = 'incl'; + $inc_or_ex_2 = 'excl'; + } - $order_slip->{'total_shipping_tax_'.$inc_or_ex_1} = 0; - $order_slip->{'total_shipping_tax_'.$inc_or_ex_2} = 0; - $order_slip->partial = 0; + $order_slip->{'total_shipping_tax_'.$inc_or_ex_1} = 0; + $order_slip->{'total_shipping_tax_'.$inc_or_ex_2} = 0; + $order_slip->partial = 0; - if ($shipping_cost !== false) - { - $order_slip->shipping_cost = true; - $carrier = new Carrier((int)$order->id_carrier); - $address = Address::initialize($order->id_address_delivery, false); - $tax_calculator = $carrier->getTaxCalculator($address); - $order_slip->{'total_shipping_tax_'.$inc_or_ex_1} = ($shipping_cost === null ? $order->{'total_shipping_tax_'.$inc_or_ex_1} : (float)$shipping_cost); + if ($shipping_cost !== false) { + $order_slip->shipping_cost = true; + $carrier = new Carrier((int)$order->id_carrier); + $address = Address::initialize($order->id_address_delivery, false); + $tax_calculator = $carrier->getTaxCalculator($address); + $order_slip->{'total_shipping_tax_'.$inc_or_ex_1} = ($shipping_cost === null ? $order->{'total_shipping_tax_'.$inc_or_ex_1} : (float)$shipping_cost); - if ($tax_calculator instanceof TaxCalculator) - $order_slip->{'total_shipping_tax_'.$inc_or_ex_2} = Tools::ps_round($tax_calculator->{$add_or_remove.'Taxes'}($order_slip->{'total_shipping_tax_'.$inc_or_ex_1}), _PS_PRICE_COMPUTE_PRECISION_); - else - $order_slip->{'total_shipping_tax_'.$inc_or_ex_2} = $order_slip->{'total_shipping_tax_'.$inc_or_ex_1}; - } - else - $order_slip->shipping_cost = false; + if ($tax_calculator instanceof TaxCalculator) { + $order_slip->{'total_shipping_tax_'.$inc_or_ex_2} = Tools::ps_round($tax_calculator->{$add_or_remove.'Taxes'}($order_slip->{'total_shipping_tax_'.$inc_or_ex_1}), _PS_PRICE_COMPUTE_PRECISION_); + } else { + $order_slip->{'total_shipping_tax_'.$inc_or_ex_2} = $order_slip->{'total_shipping_tax_'.$inc_or_ex_1}; + } + } else { + $order_slip->shipping_cost = false; + } - $order_slip->amount = 0; - $order_slip->{'total_products_tax_'.$inc_or_ex_1} = 0; - $order_slip->{'total_products_tax_'.$inc_or_ex_2} = 0; + $order_slip->amount = 0; + $order_slip->{'total_products_tax_'.$inc_or_ex_1} = 0; + $order_slip->{'total_products_tax_'.$inc_or_ex_2} = 0; - foreach ($product_list as &$product) - { - $order_detail = new OrderDetail((int)$product['id_order_detail']); - $price = (float)$product['unit_price']; - $quantity = (int)$product['quantity']; - $order_slip_resume = OrderSlip::getProductSlipResume((int)$order_detail->id); + foreach ($product_list as &$product) { + $order_detail = new OrderDetail((int)$product['id_order_detail']); + $price = (float)$product['unit_price']; + $quantity = (int)$product['quantity']; + $order_slip_resume = OrderSlip::getProductSlipResume((int)$order_detail->id); - if ($quantity + $order_slip_resume['product_quantity'] > $order_detail->product_quantity) - $quantity = $order_detail->product_quantity - $order_slip_resume['product_quantity']; + if ($quantity + $order_slip_resume['product_quantity'] > $order_detail->product_quantity) { + $quantity = $order_detail->product_quantity - $order_slip_resume['product_quantity']; + } - if ($quantity == 0) - continue; + if ($quantity == 0) { + continue; + } - if (!Tools::isSubmit('cancelProduct') && $order->hasBeenPaid()) - $order_detail->product_quantity_refunded += $quantity; + if (!Tools::isSubmit('cancelProduct') && $order->hasBeenPaid()) { + $order_detail->product_quantity_refunded += $quantity; + } - $order_detail->save(); + $order_detail->save(); - $address = Address::initialize($order->id_address_invoice, false); - $id_address = (int)$address->id; - $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int)$order_detail->product_id); - $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator(); + $address = Address::initialize($order->id_address_invoice, false); + $id_address = (int)$address->id; + $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int)$order_detail->product_id); + $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator(); - $order_slip->{'total_products_tax_'.$inc_or_ex_1} += $price * $quantity; + $order_slip->{'total_products_tax_'.$inc_or_ex_1} += $price * $quantity; - if (in_array(Configuration::get('PS_ROUND_TYPE'), array(Order::ROUND_ITEM, Order::ROUND_LINE))) - { - if (!isset($total_products[$id_tax_rules_group])) - $total_products[$id_tax_rules_group] = 0; - } - else - { - if (!isset($total_products[$id_tax_rules_group.'_'.$id_address])) - $total_products[$id_tax_rules_group.'_'.$id_address] = 0; - } + if (in_array(Configuration::get('PS_ROUND_TYPE'), array(Order::ROUND_ITEM, Order::ROUND_LINE))) { + if (!isset($total_products[$id_tax_rules_group])) { + $total_products[$id_tax_rules_group] = 0; + } + } else { + if (!isset($total_products[$id_tax_rules_group.'_'.$id_address])) { + $total_products[$id_tax_rules_group.'_'.$id_address] = 0; + } + } - $product_tax_incl_line = Tools::ps_round($tax_calculator->{$add_or_remove.'Taxes'}($price) * $quantity, _PS_PRICE_COMPUTE_PRECISION_); + $product_tax_incl_line = Tools::ps_round($tax_calculator->{$add_or_remove.'Taxes'}($price) * $quantity, _PS_PRICE_COMPUTE_PRECISION_); - switch (Configuration::get('PS_ROUND_TYPE')) - { - case Order::ROUND_ITEM: - $product_tax_incl = Tools::ps_round($tax_calculator->{$add_or_remove.'Taxes'}($price), _PS_PRICE_COMPUTE_PRECISION_) * $quantity; - $total_products[$id_tax_rules_group] += $product_tax_incl; - break; - case Order::ROUND_LINE: - $product_tax_incl = $product_tax_incl_line; - $total_products[$id_tax_rules_group] += $product_tax_incl; - break; - case Order::ROUND_TOTAL: - $product_tax_incl = $product_tax_incl_line; - $total_products[$id_tax_rules_group.'_'.$id_address] += $price * $quantity; - break; - } + switch (Configuration::get('PS_ROUND_TYPE')) { + case Order::ROUND_ITEM: + $product_tax_incl = Tools::ps_round($tax_calculator->{$add_or_remove.'Taxes'}($price), _PS_PRICE_COMPUTE_PRECISION_) * $quantity; + $total_products[$id_tax_rules_group] += $product_tax_incl; + break; + case Order::ROUND_LINE: + $product_tax_incl = $product_tax_incl_line; + $total_products[$id_tax_rules_group] += $product_tax_incl; + break; + case Order::ROUND_TOTAL: + $product_tax_incl = $product_tax_incl_line; + $total_products[$id_tax_rules_group.'_'.$id_address] += $price * $quantity; + break; + } - $product['unit_price_tax_'.$inc_or_ex_1] = $price; - $product['unit_price_tax_'.$inc_or_ex_2] = Tools::ps_round($tax_calculator->{$add_or_remove.'Taxes'}($price), _PS_PRICE_COMPUTE_PRECISION_); - $product['total_price_tax_'.$inc_or_ex_1] = Tools::ps_round($price * $quantity, _PS_PRICE_COMPUTE_PRECISION_); - $product['total_price_tax_'.$inc_or_ex_2] = Tools::ps_round($product_tax_incl, _PS_PRICE_COMPUTE_PRECISION_); - } + $product['unit_price_tax_'.$inc_or_ex_1] = $price; + $product['unit_price_tax_'.$inc_or_ex_2] = Tools::ps_round($tax_calculator->{$add_or_remove.'Taxes'}($price), _PS_PRICE_COMPUTE_PRECISION_); + $product['total_price_tax_'.$inc_or_ex_1] = Tools::ps_round($price * $quantity, _PS_PRICE_COMPUTE_PRECISION_); + $product['total_price_tax_'.$inc_or_ex_2] = Tools::ps_round($product_tax_incl, _PS_PRICE_COMPUTE_PRECISION_); + } - unset($product); + unset($product); - foreach ($total_products as $key => $price) - { - if (Configuration::get('PS_ROUND_TYPE') == Order::ROUND_TOTAL) - { - $tmp = explode('_', $key); - $address = Address::initialize((int)$tmp[1], true); - $tax_calculator = TaxManagerFactory::getManager($address, $tmp[0])->getTaxCalculator(); - $order_slip->{'total_products_tax_'.$inc_or_ex_2} += Tools::ps_round($tax_calculator->{$add_or_remove.'Taxes'}($price), _PS_PRICE_COMPUTE_PRECISION_); - } - else - $order_slip->{'total_products_tax_'.$inc_or_ex_2} += $price; - } + foreach ($total_products as $key => $price) { + if (Configuration::get('PS_ROUND_TYPE') == Order::ROUND_TOTAL) { + $tmp = explode('_', $key); + $address = Address::initialize((int)$tmp[1], true); + $tax_calculator = TaxManagerFactory::getManager($address, $tmp[0])->getTaxCalculator(); + $order_slip->{'total_products_tax_'.$inc_or_ex_2} += Tools::ps_round($tax_calculator->{$add_or_remove.'Taxes'}($price), _PS_PRICE_COMPUTE_PRECISION_); + } else { + $order_slip->{'total_products_tax_'.$inc_or_ex_2} += $price; + } + } - $order_slip->{'total_products_tax_'.$inc_or_ex_2} -= (float)$amount && !$amount_choosen ? (float)$amount : 0; - $order_slip->amount = $amount_choosen ? (float)$amount : $order_slip->{'total_products_tax_'.$inc_or_ex_1}; - $order_slip->shipping_cost_amount = $order_slip->{'total_shipping_tax_'.$inc_or_ex_1}; + $order_slip->{'total_products_tax_'.$inc_or_ex_2} -= (float)$amount && !$amount_choosen ? (float)$amount : 0; + $order_slip->amount = $amount_choosen ? (float)$amount : $order_slip->{'total_products_tax_'.$inc_or_ex_1}; + $order_slip->shipping_cost_amount = $order_slip->{'total_shipping_tax_'.$inc_or_ex_1}; - if ((float)$amount && !$amount_choosen) - $order_slip->order_slip_type = 1; - if (((float)$amount && $amount_choosen) || $order_slip->shipping_cost_amount > 0) - $order_slip->order_slip_type = 2; + if ((float)$amount && !$amount_choosen) { + $order_slip->order_slip_type = 1; + } + if (((float)$amount && $amount_choosen) || $order_slip->shipping_cost_amount > 0) { + $order_slip->order_slip_type = 2; + } - if (!$order_slip->add()) - return false; + if (!$order_slip->add()) { + return false; + } - $res = true; + $res = true; - foreach ($product_list as $product) - $res &= $order_slip->addProductOrderSlip($product); + foreach ($product_list as $product) { + $res &= $order_slip->addProductOrderSlip($product); + } - return $res; - } + return $res; + } - protected function addProductOrderSlip($product) - { - return Db::getInstance()->insert('order_slip_detail', array( - 'id_order_slip' => (int)$this->id, - 'id_order_detail' => (int)$product['id_order_detail'], - 'product_quantity' => $product['quantity'], - 'unit_price_tax_excl' => $product['unit_price_tax_excl'], - 'unit_price_tax_incl' => $product['unit_price_tax_incl'], - 'total_price_tax_excl' => $product['total_price_tax_excl'], - 'total_price_tax_incl' => $product['total_price_tax_incl'], - 'amount_tax_excl' => $product['total_price_tax_excl'], - 'amount_tax_incl' => $product['total_price_tax_incl'] - )); - } + protected function addProductOrderSlip($product) + { + return Db::getInstance()->insert('order_slip_detail', array( + 'id_order_slip' => (int)$this->id, + 'id_order_detail' => (int)$product['id_order_detail'], + 'product_quantity' => $product['quantity'], + 'unit_price_tax_excl' => $product['unit_price_tax_excl'], + 'unit_price_tax_incl' => $product['unit_price_tax_incl'], + 'total_price_tax_excl' => $product['total_price_tax_excl'], + 'total_price_tax_incl' => $product['total_price_tax_incl'], + 'amount_tax_excl' => $product['total_price_tax_excl'], + 'amount_tax_incl' => $product['total_price_tax_incl'] + )); + } - public static function createPartialOrderSlip($order, $amount, $shipping_cost_amount, $order_detail_list) - { - $currency = new Currency($order->id_currency); - $orderSlip = new OrderSlip(); - $orderSlip->id_customer = (int)$order->id_customer; - $orderSlip->id_order = (int)$order->id; - $orderSlip->amount = (float)$amount; - $orderSlip->shipping_cost = false; - $orderSlip->shipping_cost_amount = (float)$shipping_cost_amount; - $orderSlip->conversion_rate = $currency->conversion_rate; - $orderSlip->partial = 1; - if (!$orderSlip->add()) - return false; + public static function createPartialOrderSlip($order, $amount, $shipping_cost_amount, $order_detail_list) + { + $currency = new Currency($order->id_currency); + $orderSlip = new OrderSlip(); + $orderSlip->id_customer = (int)$order->id_customer; + $orderSlip->id_order = (int)$order->id; + $orderSlip->amount = (float)$amount; + $orderSlip->shipping_cost = false; + $orderSlip->shipping_cost_amount = (float)$shipping_cost_amount; + $orderSlip->conversion_rate = $currency->conversion_rate; + $orderSlip->partial = 1; + if (!$orderSlip->add()) { + return false; + } - $orderSlip->addPartialSlipDetail($order_detail_list); - return true; - } + $orderSlip->addPartialSlipDetail($order_detail_list); + return true; + } - public function addPartialSlipDetail($order_detail_list) - { - foreach ($order_detail_list as $id_order_detail => $tab) - { - $order_detail = new OrderDetail($id_order_detail); - $order_slip_resume = OrderSlip::getProductSlipResume($id_order_detail); + public function addPartialSlipDetail($order_detail_list) + { + foreach ($order_detail_list as $id_order_detail => $tab) { + $order_detail = new OrderDetail($id_order_detail); + $order_slip_resume = OrderSlip::getProductSlipResume($id_order_detail); - if ($tab['amount'] + $order_slip_resume['amount_tax_incl'] > $order_detail->total_price_tax_incl) - $tab['amount'] = $order_detail->total_price_tax_incl - $order_slip_resume['amount_tax_incl']; + if ($tab['amount'] + $order_slip_resume['amount_tax_incl'] > $order_detail->total_price_tax_incl) { + $tab['amount'] = $order_detail->total_price_tax_incl - $order_slip_resume['amount_tax_incl']; + } - if ($tab['amount'] == 0) - continue; + if ($tab['amount'] == 0) { + continue; + } - if ($tab['quantity'] + $order_slip_resume['product_quantity'] > $order_detail->product_quantity) - $tab['quantity'] = $order_detail->product_quantity - $order_slip_resume['product_quantity']; + if ($tab['quantity'] + $order_slip_resume['product_quantity'] > $order_detail->product_quantity) { + $tab['quantity'] = $order_detail->product_quantity - $order_slip_resume['product_quantity']; + } - $tab['amount_tax_excl'] = $tab['amount_tax_incl'] = $tab['amount']; + $tab['amount_tax_excl'] = $tab['amount_tax_incl'] = $tab['amount']; - $id_tax = (int)Db::getInstance()->getValue(' + $id_tax = (int)Db::getInstance()->getValue(' SELECT `id_tax` FROM `'._DB_PREFIX_.'order_detail_tax` WHERE `id_order_detail` = '.(int)$id_order_detail - ); + ); - if ($id_tax > 0) - { - $rate = (float)Db::getInstance()->getValue(' + if ($id_tax > 0) { + $rate = (float)Db::getInstance()->getValue(' SELECT `rate` FROM `'._DB_PREFIX_.'tax` WHERE `id_tax` = '.(int)$id_tax - ); + ); - if ($rate > 0) - { - $rate = 1 + ($rate / 100); - $tab['amount_tax_excl'] = $tab['amount_tax_excl'] / $rate; - } - } + if ($rate > 0) { + $rate = 1 + ($rate / 100); + $tab['amount_tax_excl'] = $tab['amount_tax_excl'] / $rate; + } + } - if ($tab['quantity'] > 0 && $tab['quantity'] > $order_detail->product_quantity_refunded) - { - $order_detail->product_quantity_refunded = $tab['quantity']; - $order_detail->save(); - } + if ($tab['quantity'] > 0 && $tab['quantity'] > $order_detail->product_quantity_refunded) { + $order_detail->product_quantity_refunded = $tab['quantity']; + $order_detail->save(); + } - $insert_order_slip = array( - 'id_order_slip' => (int)$this->id, - 'id_order_detail' => (int)$id_order_detail, - 'product_quantity' => (int)$tab['quantity'], - 'amount_tax_excl' => (float)$tab['amount_tax_excl'], - 'amount_tax_incl' => (float)$tab['amount_tax_incl'], - ); + $insert_order_slip = array( + 'id_order_slip' => (int)$this->id, + 'id_order_detail' => (int)$id_order_detail, + 'product_quantity' => (int)$tab['quantity'], + 'amount_tax_excl' => (float)$tab['amount_tax_excl'], + 'amount_tax_incl' => (float)$tab['amount_tax_incl'], + ); - Db::getInstance()->insert('order_slip_detail', $insert_order_slip); - } - } + Db::getInstance()->insert('order_slip_detail', $insert_order_slip); + } + } - public function getEcoTaxTaxesBreakdown() - { - $ecotax_detail = array(); - foreach ($this->getOrdersSlipDetail((int)$this->id) as $order_slip_details) - { - $row = Db::getInstance()->getRow(' + public function getEcoTaxTaxesBreakdown() + { + $ecotax_detail = array(); + foreach ($this->getOrdersSlipDetail((int)$this->id) as $order_slip_details) { + $row = Db::getInstance()->getRow(' SELECT `ecotax_tax_rate` as `rate`, `ecotax` as `ecotax_tax_excl`, `ecotax` as `ecotax_tax_incl`, `product_quantity` FROM `'._DB_PREFIX_.'order_detail` WHERE `id_order_detail` = '.(int)$order_slip_details['id_order_detail'] - ); + ); - if (!isset($ecotax_detail[$row['rate']])) - $ecotax_detail[$row['rate']] = array('ecotax_tax_incl' => 0, 'ecotax_tax_excl' => 0, 'rate' => $row['rate']); + if (!isset($ecotax_detail[$row['rate']])) { + $ecotax_detail[$row['rate']] = array('ecotax_tax_incl' => 0, 'ecotax_tax_excl' => 0, 'rate' => $row['rate']); + } - $ecotax_detail[$row['rate']]['ecotax_tax_incl'] += Tools::ps_round(($row['ecotax_tax_excl'] * $order_slip_details['product_quantity']) + ($row['ecotax_tax_excl'] * $order_slip_details['product_quantity'] * $row['rate'] / 100), 2); - $ecotax_detail[$row['rate']]['ecotax_tax_excl'] += Tools::ps_round($row['ecotax_tax_excl'] * $order_slip_details['product_quantity'], 2); - } + $ecotax_detail[$row['rate']]['ecotax_tax_incl'] += Tools::ps_round(($row['ecotax_tax_excl'] * $order_slip_details['product_quantity']) + ($row['ecotax_tax_excl'] * $order_slip_details['product_quantity'] * $row['rate'] / 100), 2); + $ecotax_detail[$row['rate']]['ecotax_tax_excl'] += Tools::ps_round($row['ecotax_tax_excl'] * $order_slip_details['product_quantity'], 2); + } - return $ecotax_detail; - } + return $ecotax_detail; + } - public function getWsOrderSlipDetails() - { - $query = 'SELECT id_order_slip as id, id_order_detail, product_quantity, amount_tax_excl, amount_tax_incl + public function getWsOrderSlipDetails() + { + $query = 'SELECT id_order_slip as id, id_order_detail, product_quantity, amount_tax_excl, amount_tax_incl FROM `'._DB_PREFIX_.'order_slip_detail` WHERE id_order_slip = '.(int)$this->id; - $result = Db::getInstance()->executeS($query); - return $result; - } + $result = Db::getInstance()->executeS($query); + return $result; + } - public function setWsOrderSlipDetails($values) - { - if (Db::getInstance()->execute('DELETE from `'._DB_PREFIX_.'order_slip_detail` where id_order_slip = '.(int)$this->id)) - { - $query = 'INSERT INTO `'._DB_PREFIX_.'order_slip_detail`(`id_order_slip`, `id_order_detail`, `product_quantity`, `amount_tax_excl`, `amount_tax_incl`) VALUES '; + public function setWsOrderSlipDetails($values) + { + if (Db::getInstance()->execute('DELETE from `'._DB_PREFIX_.'order_slip_detail` where id_order_slip = '.(int)$this->id)) { + $query = 'INSERT INTO `'._DB_PREFIX_.'order_slip_detail`(`id_order_slip`, `id_order_detail`, `product_quantity`, `amount_tax_excl`, `amount_tax_incl`) VALUES '; - foreach ($values as $value) - $query .= '('.(int)$this->id.', '.(int)$value['id_order_detail'].', '.(int)$value['product_quantity'].', '. - (isset($value['amount_tax_excl']) ? (float)$value['amount_tax_excl'] : 'NULL').', '. - (isset($value['amount_tax_incl']) ? (float)$value['amount_tax_incl'] : 'NULL'). - '),'; - $query = rtrim($query, ','); - Db::getInstance()->execute($query); - } - return true; - } + foreach ($values as $value) { + $query .= '('.(int)$this->id.', '.(int)$value['id_order_detail'].', '.(int)$value['product_quantity'].', '. + (isset($value['amount_tax_excl']) ? (float)$value['amount_tax_excl'] : 'NULL').', '. + (isset($value['amount_tax_incl']) ? (float)$value['amount_tax_incl'] : 'NULL'). + '),'; + } + $query = rtrim($query, ','); + Db::getInstance()->execute($query); + } + return true; + } } diff --git a/classes/order/OrderState.php b/classes/order/OrderState.php index cd9a4d0d..1704a717 100644 --- a/classes/order/OrderState.php +++ b/classes/order/OrderState.php @@ -26,133 +26,133 @@ class OrderStateCore extends ObjectModel { - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var string Template name if there is any e-mail to send */ - public $template; + /** @var string Template name if there is any e-mail to send */ + public $template; - /** @var bool Send an e-mail to customer ? */ - public $send_email; + /** @var bool Send an e-mail to customer ? */ + public $send_email; - public $module_name; + public $module_name; - /** @var bool Allow customer to view and download invoice when order is at this state */ - public $invoice; + /** @var bool Allow customer to view and download invoice when order is at this state */ + public $invoice; - /** @var string Display state in the specified color */ - public $color; + /** @var string Display state in the specified color */ + public $color; - public $unremovable; + public $unremovable; - /** @var bool Log authorization */ - public $logable; + /** @var bool Log authorization */ + public $logable; - /** @var bool Delivery */ - public $delivery; + /** @var bool Delivery */ + public $delivery; - /** @var bool Hidden */ - public $hidden; + /** @var bool Hidden */ + public $hidden; - /** @var bool Shipped */ - public $shipped; + /** @var bool Shipped */ + public $shipped; - /** @var bool Paid */ - public $paid; + /** @var bool Paid */ + public $paid; - /** @var bool Attach PDF Invoice */ - public $pdf_invoice; + /** @var bool Attach PDF Invoice */ + public $pdf_invoice; - /** @var bool Attach PDF Delivery Slip */ - public $pdf_delivery; + /** @var bool Attach PDF Delivery Slip */ + public $pdf_delivery; - /** @var bool True if carrier has been deleted (staying in database as deleted) */ - public $deleted = 0; + /** @var bool True if carrier has been deleted (staying in database as deleted) */ + public $deleted = 0; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'order_state', - 'primary' => 'id_order_state', - 'multilang' => true, - 'fields' => array( - 'send_email' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'module_name' => array('type' => self::TYPE_STRING, 'validate' => 'isModuleName'), - 'invoice' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'color' => array('type' => self::TYPE_STRING, 'validate' => 'isColor'), - 'logable' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'shipped' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'unremovable' =>array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'delivery' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'hidden' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'paid' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'pdf_delivery' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'pdf_invoice' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'order_state', + 'primary' => 'id_order_state', + 'multilang' => true, + 'fields' => array( + 'send_email' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'module_name' => array('type' => self::TYPE_STRING, 'validate' => 'isModuleName'), + 'invoice' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'color' => array('type' => self::TYPE_STRING, 'validate' => 'isColor'), + 'logable' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'shipped' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'unremovable' =>array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'delivery' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'hidden' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'paid' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'pdf_delivery' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'pdf_invoice' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), - 'template' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isTplName', 'size' => 64), - ), - ); + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), + 'template' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isTplName', 'size' => 64), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'unremovable' => array(), - 'delivery' => array(), - 'hidden' => array(), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'unremovable' => array(), + 'delivery' => array(), + 'hidden' => array(), + ), + ); - const FLAG_NO_HIDDEN = 1; /* 00001 */ - const FLAG_LOGABLE = 2; /* 00010 */ - const FLAG_DELIVERY = 4; /* 00100 */ - const FLAG_SHIPPED = 8; /* 01000 */ - const FLAG_PAID = 16; /* 10000 */ + const FLAG_NO_HIDDEN = 1; /* 00001 */ + const FLAG_LOGABLE = 2; /* 00010 */ + const FLAG_DELIVERY = 4; /* 00100 */ + const FLAG_SHIPPED = 8; /* 01000 */ + const FLAG_PAID = 16; /* 10000 */ - /** - * Get all available order statuses - * - * @param int $id_lang Language id for status name - * @return array Order statuses - */ - public static function getOrderStates($id_lang) - { - $cache_id = 'OrderState::getOrderStates_'.(int)$id_lang; - if (!Cache::isStored($cache_id)) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + /** + * Get all available order statuses + * + * @param int $id_lang Language id for status name + * @return array Order statuses + */ + public static function getOrderStates($id_lang) + { + $cache_id = 'OrderState::getOrderStates_'.(int)$id_lang; + if (!Cache::isStored($cache_id)) { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT * FROM `'._DB_PREFIX_.'order_state` os LEFT JOIN `'._DB_PREFIX_.'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = '.(int)$id_lang.') WHERE deleted = 0 ORDER BY `name` ASC'); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * Check if we can make a invoice when order is in this state - * - * @param int $id_order_state State ID - * @return bool availability - */ - public static function invoiceAvailable($id_order_state) - { - $result = false; - if (Configuration::get('PS_INVOICE')) - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + /** + * Check if we can make a invoice when order is in this state + * + * @param int $id_order_state State ID + * @return bool availability + */ + public static function invoiceAvailable($id_order_state) + { + $result = false; + if (Configuration::get('PS_INVOICE')) { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `invoice` FROM `'._DB_PREFIX_.'order_state` WHERE `id_order_state` = '.(int)$id_order_state); - return (bool)$result; - } + } + return (bool)$result; + } - public function isRemovable() - { - return !($this->unremovable); - } -} \ No newline at end of file + public function isRemovable() + { + return !($this->unremovable); + } +} diff --git a/classes/order/index.php b/classes/order/index.php index c642967a..91fa49fb 100644 --- a/classes/order/index.php +++ b/classes/order/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/classes/pdf/HTMLTemplate.php b/classes/pdf/HTMLTemplate.php index c0e1c28b..ae088667 100644 --- a/classes/pdf/HTMLTemplate.php +++ b/classes/pdf/HTMLTemplate.php @@ -29,202 +29,207 @@ */ abstract class HTMLTemplateCore { - public $title; - public $date; - public $available_in_your_account = true; + public $title; + public $date; + public $available_in_your_account = true; - /** @var Smarty */ - public $smarty; + /** @var Smarty */ + public $smarty; - /** @var Shop */ - public $shop; + /** @var Shop */ + public $shop; - /** - * Returns the template's HTML header - * - * @return string HTML header - */ - public function getHeader() - { - $this->assignCommonHeaderData(); + /** + * Returns the template's HTML header + * + * @return string HTML header + */ + public function getHeader() + { + $this->assignCommonHeaderData(); - return $this->smarty->fetch($this->getTemplate('header')); - } + return $this->smarty->fetch($this->getTemplate('header')); + } - /** - * Returns the template's HTML footer - * - * @return string HTML footer - */ - public function getFooter() - { - $shop_address = $this->getShopAddress(); + /** + * Returns the template's HTML footer + * + * @return string HTML footer + */ + public function getFooter() + { + $shop_address = $this->getShopAddress(); - $id_shop = (int)$this->shop->id; + $id_shop = (int)$this->shop->id; - $this->smarty->assign(array( - 'available_in_your_account' => $this->available_in_your_account, - 'shop_address' => $shop_address, - 'shop_fax' => Configuration::get('PS_SHOP_FAX', null, null, $id_shop), - 'shop_phone' => Configuration::get('PS_SHOP_PHONE', null, null, $id_shop), - 'shop_email' => Configuration::get('PS_SHOP_EMAIL', null, null, $id_shop), - 'free_text' => Configuration::get('PS_INVOICE_FREE_TEXT', (int)Context::getContext()->language->id, null, $id_shop) - )); + $this->smarty->assign(array( + 'available_in_your_account' => $this->available_in_your_account, + 'shop_address' => $shop_address, + 'shop_fax' => Configuration::get('PS_SHOP_FAX', null, null, $id_shop), + 'shop_phone' => Configuration::get('PS_SHOP_PHONE', null, null, $id_shop), + 'shop_email' => Configuration::get('PS_SHOP_EMAIL', null, null, $id_shop), + 'free_text' => Configuration::get('PS_INVOICE_FREE_TEXT', (int)Context::getContext()->language->id, null, $id_shop) + )); - return $this->smarty->fetch($this->getTemplate('footer')); - } + return $this->smarty->fetch($this->getTemplate('footer')); + } - /** - * Returns the shop address - * - * @return string - */ - protected function getShopAddress() - { - $shop_address = ''; + /** + * Returns the shop address + * + * @return string + */ + protected function getShopAddress() + { + $shop_address = ''; - $shop_address_obj = $this->shop->getAddress(); - if (isset($shop_address_obj) && $shop_address_obj instanceof Address) - $shop_address = AddressFormat::generateAddress($shop_address_obj, array(), ' - ', ' '); + $shop_address_obj = $this->shop->getAddress(); + if (isset($shop_address_obj) && $shop_address_obj instanceof Address) { + $shop_address = AddressFormat::generateAddress($shop_address_obj, array(), ' - ', ' '); + } - return $shop_address; - } + return $shop_address; + } - /** - * Returns the invoice logo - */ - protected function getLogo() - { - $logo = ''; + /** + * Returns the invoice logo + */ + protected function getLogo() + { + $logo = ''; - $id_shop = (int)$this->shop->id; + $id_shop = (int)$this->shop->id; - if (Configuration::get('PS_LOGO_INVOICE', null, null, $id_shop) != false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_INVOICE', null, null, $id_shop))) - $logo = _PS_IMG_DIR_.Configuration::get('PS_LOGO_INVOICE', null, null, $id_shop); - elseif (Configuration::get('PS_LOGO', null, null, $id_shop) != false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO', null, null, $id_shop))) - $logo = _PS_IMG_DIR_.Configuration::get('PS_LOGO', null, null, $id_shop); - return $logo; - } + if (Configuration::get('PS_LOGO_INVOICE', null, null, $id_shop) != false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_INVOICE', null, null, $id_shop))) { + $logo = _PS_IMG_DIR_.Configuration::get('PS_LOGO_INVOICE', null, null, $id_shop); + } elseif (Configuration::get('PS_LOGO', null, null, $id_shop) != false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO', null, null, $id_shop))) { + $logo = _PS_IMG_DIR_.Configuration::get('PS_LOGO', null, null, $id_shop); + } + return $logo; + } - /** - * Assign common header data to smarty variables - */ + /** + * Assign common header data to smarty variables + */ - public function assignCommonHeaderData() - { - $this->setShopId(); - $id_shop = (int)$this->shop->id; - $shop_name = Configuration::get('PS_SHOP_NAME', null, null, $id_shop); + public function assignCommonHeaderData() + { + $this->setShopId(); + $id_shop = (int)$this->shop->id; + $shop_name = Configuration::get('PS_SHOP_NAME', null, null, $id_shop); - $path_logo = $this->getLogo(); + $path_logo = $this->getLogo(); - $width = 0; - $height = 0; - if (!empty($path_logo)) - list($width, $height) = getimagesize($path_logo); + $width = 0; + $height = 0; + if (!empty($path_logo)) { + list($width, $height) = getimagesize($path_logo); + } - // Limit the height of the logo for the PDF render - $maximum_height = 100; - if ($height > $maximum_height) - { - $ratio = $maximum_height / $height; - $height *= $ratio; - $width *= $ratio; - } + // Limit the height of the logo for the PDF render + $maximum_height = 100; + if ($height > $maximum_height) { + $ratio = $maximum_height / $height; + $height *= $ratio; + $width *= $ratio; + } - $this->smarty->assign(array( - 'logo_path' => $path_logo, - 'img_ps_dir' => 'http://'.Tools::getMediaServer(_PS_IMG_)._PS_IMG_, - 'img_update_time' => Configuration::get('PS_IMG_UPDATE_TIME'), - 'date' => $this->date, - 'title' => $this->title, - 'shop_name' => $shop_name, - 'shop_details' => Configuration::get('PS_SHOP_DETAILS', null, null, (int)$id_shop), - 'width_logo' => $width, - 'height_logo' => $height - )); - } + $this->smarty->assign(array( + 'logo_path' => $path_logo, + 'img_ps_dir' => 'http://'.Tools::getMediaServer(_PS_IMG_)._PS_IMG_, + 'img_update_time' => Configuration::get('PS_IMG_UPDATE_TIME'), + 'date' => $this->date, + 'title' => $this->title, + 'shop_name' => $shop_name, + 'shop_details' => Configuration::get('PS_SHOP_DETAILS', null, null, (int)$id_shop), + 'width_logo' => $width, + 'height_logo' => $height + )); + } - /** - * Assign hook data - * - * @param ObjectModel $object generally the object used in the constructor - */ - public function assignHookData($object) - { - $template = ucfirst(str_replace('HTMLTemplate', '', get_class($this))); - $hook_name = 'displayPDF'.$template; + /** + * Assign hook data + * + * @param ObjectModel $object generally the object used in the constructor + */ + public function assignHookData($object) + { + $template = ucfirst(str_replace('HTMLTemplate', '', get_class($this))); + $hook_name = 'displayPDF'.$template; - $this->smarty->assign(array( - 'HOOK_DISPLAY_PDF' => Hook::exec($hook_name, array('object' => $object)) - )); - } + $this->smarty->assign(array( + 'HOOK_DISPLAY_PDF' => Hook::exec($hook_name, array('object' => $object)) + )); + } - /** - * Returns the template's HTML content - * - * @return string HTML content - */ - abstract public function getContent(); + /** + * Returns the template's HTML content + * + * @return string HTML content + */ + abstract public function getContent(); - /** - * Returns the template filename - * - * @return string filename - */ - abstract public function getFilename(); + /** + * Returns the template filename + * + * @return string filename + */ + abstract public function getFilename(); - /** - * Returns the template filename when using bulk rendering - * - * @return string filename - */ - abstract public function getBulkFilename(); + /** + * Returns the template filename when using bulk rendering + * + * @return string filename + */ + abstract public function getBulkFilename(); - /** - * If the template is not present in the theme directory, it will return the default template - * in _PS_PDF_DIR_ directory - * - * @param $template_name - * - * @return string - */ - protected function getTemplate($template_name) - { - $template = false; - $default_template = rtrim(_PS_PDF_DIR_, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$template_name.'.tpl'; - $overridden_template = _PS_ALL_THEMES_DIR_.$this->shop->getTheme().DIRECTORY_SEPARATOR.'pdf'.DIRECTORY_SEPARATOR.$template_name.'.tpl'; - if (file_exists($overridden_template)) - $template = $overridden_template; - elseif (file_exists($default_template)) - $template = $default_template; + /** + * If the template is not present in the theme directory, it will return the default template + * in _PS_PDF_DIR_ directory + * + * @param $template_name + * + * @return string + */ + protected function getTemplate($template_name) + { + $template = false; + $default_template = rtrim(_PS_PDF_DIR_, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$template_name.'.tpl'; + $overridden_template = _PS_ALL_THEMES_DIR_.$this->shop->getTheme().DIRECTORY_SEPARATOR.'pdf'.DIRECTORY_SEPARATOR.$template_name.'.tpl'; + if (file_exists($overridden_template)) { + $template = $overridden_template; + } elseif (file_exists($default_template)) { + $template = $default_template; + } - return $template; - } + return $template; + } - /** - * Translation method - * - * @param string $string - * - * @return string translated text - */ - protected static function l($string) - { - return Translate::getPdfTranslation($string); - } + /** + * Translation method + * + * @param string $string + * + * @return string translated text + */ + protected static function l($string) + { + return Translate::getPdfTranslation($string); + } - protected function setShopId() - { - if (isset($this->order) && Validate::isLoadedObject($this->order)) - $id_shop = (int)$this->order->id_shop; - else - $id_shop = (int)Context::getContext()->shop->id; + protected function setShopId() + { + if (isset($this->order) && Validate::isLoadedObject($this->order)) { + $id_shop = (int)$this->order->id_shop; + } else { + $id_shop = (int)Context::getContext()->shop->id; + } - $this->shop = new Shop($id_shop); - if (Validate::isLoadedObject($this->shop)) - Shop::setContext(Shop::CONTEXT_SHOP, (int)$this->shop->id); - } + $this->shop = new Shop($id_shop); + if (Validate::isLoadedObject($this->shop)) { + Shop::setContext(Shop::CONTEXT_SHOP, (int)$this->shop->id); + } + } } diff --git a/classes/pdf/HTMLTemplateDeliverySlip.php b/classes/pdf/HTMLTemplateDeliverySlip.php index c4518fe3..b1a2d2fc 100644 --- a/classes/pdf/HTMLTemplateDeliverySlip.php +++ b/classes/pdf/HTMLTemplateDeliverySlip.php @@ -18,9 +18,9 @@ * versions in the future. If you wish to customize PrestaShop for your * needs please refer to http://www.prestashop.com for more information. * - * @author PrestaShop SA <contact@prestashop.com> - * @copyright 2007-2015 PrestaShop SA - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @author PrestaShop SA <contact@prestashop.com> + * @copyright 2007-2015 PrestaShop SA + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * International Registered Trademark & Property of PrestaShop SA */ @@ -29,125 +29,132 @@ */ class HTMLTemplateDeliverySlipCore extends HTMLTemplate { - public $order; + public $order; - /** - * @param OrderInvoice $order_invoice - * @param $smarty - * @throws PrestaShopException - */ - public function __construct(OrderInvoice $order_invoice, $smarty) - { - $this->order_invoice = $order_invoice; - $this->order = new Order($this->order_invoice->id_order); - $this->smarty = $smarty; + /** + * @param OrderInvoice $order_invoice + * @param $smarty + * @throws PrestaShopException + */ + public function __construct(OrderInvoice $order_invoice, $smarty, $bulk_mode = false) + { + $this->order_invoice = $order_invoice; + $this->order = new Order($this->order_invoice->id_order); + $this->smarty = $smarty; - // header informations - $this->date = Tools::displayDate($this->order->invoice_date); - $prefix = Configuration::get('PS_DELIVERY_PREFIX', Context::getContext()->language->id); - $this->title = sprintf(HTMLTemplateDeliverySlip::l('%1$s%2$06d'), $prefix, $this->order_invoice->delivery_number); + // If shop_address is null, then update it with current one. + // But no DB save required here to avoid massive updates for bulk PDF generation case. + // (DB: bug fixed in 1.6.1.1 with upgrade SQL script to avoid null shop_address in old orderInvoices) + if (!isset($this->order_invoice->shop_address) || !$this->order_invoice->shop_address) { + $this->order_invoice->shop_address = OrderInvoice::getCurrentFormattedShopAddress((int)$this->order->id_shop); + if (!$bulk_mode) { + OrderInvoice::fixAllShopAddresses(); + } + } - // footer informations - $this->shop = new Shop((int)$this->order->id_shop); - } + // header informations + $this->date = Tools::displayDate($order_invoice->date_add); + $prefix = Configuration::get('PS_DELIVERY_PREFIX', Context::getContext()->language->id); + $this->title = sprintf(HTMLTemplateDeliverySlip::l('%1$s%2$06d'), $prefix, $this->order_invoice->delivery_number); - /** - * Returns the template's HTML header - * - * @return string HTML header - */ - public function getHeader() - { - $this->assignCommonHeaderData(); - $this->smarty->assign(array( - 'header' => $this->l('DELIVERY'), - )); - - return $this->smarty->fetch($this->getTemplate('header')); - } - - /** - * Returns the template's HTML content - * - * @return string HTML content - */ - public function getContent() - { - $delivery_address = new Address((int)$this->order->id_address_delivery); - $formatted_delivery_address = AddressFormat::generateAddress($delivery_address, array(), '<br />', ' '); - $formatted_invoice_address = ''; + // footer informations + $this->shop = new Shop((int)$this->order->id_shop); + } - if ($this->order->id_address_delivery != $this->order->id_address_invoice) - { - $invoice_address = new Address((int)$this->order->id_address_invoice); - $formatted_invoice_address = AddressFormat::generateAddress($invoice_address, array(), '<br />', ' '); - } + /** + * Returns the template's HTML header + * + * @return string HTML header + */ + public function getHeader() + { + $this->assignCommonHeaderData(); + $this->smarty->assign(array('header' => HTMLTemplateDeliverySlip::l('Delivery'))); - $carrier = new Carrier($this->order->id_carrier); - $carrier->name = ($carrier->name == '0' ? Configuration::get('PS_SHOP_NAME') : $carrier->name); + return $this->smarty->fetch($this->getTemplate('header')); + } - $order_details = $this->order_invoice->getProducts(); - if (Configuration::get('PS_PDF_IMG_DELIVERY')) - foreach ($order_details as &$order_detail) - { - if ($order_detail['image'] != null) - { - $name = 'product_mini_'.(int)$order_detail['product_id'].(isset($order_detail['product_attribute_id']) ? '_'.(int)$order_detail['product_attribute_id'] : '').'.jpg'; - $path = _PS_PROD_IMG_DIR_.$order_detail['image']->getExistingImgPath().'.jpg'; + /** + * Returns the template's HTML content + * + * @return string HTML content + */ + public function getContent() + { + $delivery_address = new Address((int)$this->order->id_address_delivery); + $formatted_delivery_address = AddressFormat::generateAddress($delivery_address, array(), '<br />', ' '); + $formatted_invoice_address = ''; - $order_detail['image_tag'] = preg_replace( - '/\.*'.preg_quote(__PS_BASE_URI__, '/').'/', - _PS_ROOT_DIR_.DIRECTORY_SEPARATOR, - ImageManager::thumbnail($path, $name, 45, 'jpg', false), - 1 - ); + if ($this->order->id_address_delivery != $this->order->id_address_invoice) { + $invoice_address = new Address((int)$this->order->id_address_invoice); + $formatted_invoice_address = AddressFormat::generateAddress($invoice_address, array(), '<br />', ' '); + } - if (file_exists(_PS_TMP_IMG_DIR_.$name)) - $order_detail['image_size'] = getimagesize(_PS_TMP_IMG_DIR_.$name); - else - $order_detail['image_size'] = false; - } - } + $carrier = new Carrier($this->order->id_carrier); + $carrier->name = ($carrier->name == '0' ? Configuration::get('PS_SHOP_NAME') : $carrier->name); - $this->smarty->assign(array( - 'order' => $this->order, - 'order_details' => $order_details, - 'delivery_address' => $formatted_delivery_address, - 'invoice_address' => $formatted_invoice_address, - 'order_invoice' => $this->order_invoice, - 'carrier' => $carrier, - 'display_product_images' => Configuration::get('PS_PDF_IMG_DELIVERY') - )); - - $tpls = array( - 'style_tab' => $this->smarty->fetch($this->getTemplate('delivery-slip.style-tab')), - 'addresses_tab' => $this->smarty->fetch($this->getTemplate('delivery-slip.addresses-tab')), - 'summary_tab' => $this->smarty->fetch($this->getTemplate('delivery-slip.summary-tab')), - 'product_tab' => $this->smarty->fetch($this->getTemplate('delivery-slip.product-tab')), - 'payment_tab' => $this->smarty->fetch($this->getTemplate('delivery-slip.payment-tab')), - ); - $this->smarty->assign($tpls); + $order_details = $this->order_invoice->getProducts(); + if (Configuration::get('PS_PDF_IMG_DELIVERY')) { + foreach ($order_details as &$order_detail) { + if ($order_detail['image'] != null) { + $name = 'product_mini_'.(int)$order_detail['product_id'].(isset($order_detail['product_attribute_id']) ? '_'.(int)$order_detail['product_attribute_id'] : '').'.jpg'; + $path = _PS_PROD_IMG_DIR_.$order_detail['image']->getExistingImgPath().'.jpg'; - return $this->smarty->fetch($this->getTemplate('delivery-slip')); - } + $order_detail['image_tag'] = preg_replace( + '/\.*'.preg_quote(__PS_BASE_URI__, '/').'/', + _PS_ROOT_DIR_.DIRECTORY_SEPARATOR, + ImageManager::thumbnail($path, $name, 45, 'jpg', false), + 1 + ); - /** - * Returns the template filename when using bulk rendering - * - * @return string filename - */ - public function getBulkFilename() - { - return 'deliveries.pdf'; - } + if (file_exists(_PS_TMP_IMG_DIR_.$name)) { + $order_detail['image_size'] = getimagesize(_PS_TMP_IMG_DIR_.$name); + } else { + $order_detail['image_size'] = false; + } + } + } + } - /** - * Returns the template filename - * - * @return string filename - */ - public function getFilename() - { - return Configuration::get('PS_DELIVERY_PREFIX', Context::getContext()->language->id, null, $this->order->id_shop).sprintf('%06d', $this->order->delivery_number).'.pdf'; - } + $this->smarty->assign(array( + 'order' => $this->order, + 'order_details' => $order_details, + 'delivery_address' => $formatted_delivery_address, + 'invoice_address' => $formatted_invoice_address, + 'order_invoice' => $this->order_invoice, + 'carrier' => $carrier, + 'display_product_images' => Configuration::get('PS_PDF_IMG_DELIVERY') + )); + + $tpls = array( + 'style_tab' => $this->smarty->fetch($this->getTemplate('delivery-slip.style-tab')), + 'addresses_tab' => $this->smarty->fetch($this->getTemplate('delivery-slip.addresses-tab')), + 'summary_tab' => $this->smarty->fetch($this->getTemplate('delivery-slip.summary-tab')), + 'product_tab' => $this->smarty->fetch($this->getTemplate('delivery-slip.product-tab')), + 'payment_tab' => $this->smarty->fetch($this->getTemplate('delivery-slip.payment-tab')), + ); + $this->smarty->assign($tpls); + + return $this->smarty->fetch($this->getTemplate('delivery-slip')); + } + + /** + * Returns the template filename when using bulk rendering + * + * @return string filename + */ + public function getBulkFilename() + { + return 'deliveries.pdf'; + } + + /** + * Returns the template filename + * + * @return string filename + */ + public function getFilename() + { + return Configuration::get('PS_DELIVERY_PREFIX', Context::getContext()->language->id, null, $this->order->id_shop).sprintf('%06d', $this->order->delivery_number).'.pdf'; + } } diff --git a/classes/pdf/HTMLTemplateInvoice.php b/classes/pdf/HTMLTemplateInvoice.php index 187dd345..6603118e 100644 --- a/classes/pdf/HTMLTemplateInvoice.php +++ b/classes/pdf/HTMLTemplateInvoice.php @@ -18,9 +18,9 @@ * versions in the future. If you wish to customize PrestaShop for your * needs please refer to http://www.prestashop.com for more information. * - * @author PrestaShop SA <contact@prestashop.com> - * @copyright 2007-2015 PrestaShop SA - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @author PrestaShop SA <contact@prestashop.com> + * @copyright 2007-2015 PrestaShop SA + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * International Registered Trademark & Property of PrestaShop SA */ @@ -29,466 +29,470 @@ */ class HTMLTemplateInvoiceCore extends HTMLTemplate { - public $order; - public $available_in_your_account = false; + public $order; + public $order_invoice; + public $available_in_your_account = false; - /** - * @param OrderInvoice $order_invoice - * @param $smarty - * @throws PrestaShopException - */ - public function __construct(OrderInvoice $order_invoice, $smarty) - { - $this->order_invoice = $order_invoice; - $this->order = new Order((int)$this->order_invoice->id_order); - $this->smarty = $smarty; + /** + * @param OrderInvoice $order_invoice + * @param $smarty + * @throws PrestaShopException + */ + public function __construct(OrderInvoice $order_invoice, $smarty, $bulk_mode = false) + { + $this->order_invoice = $order_invoice; + $this->order = new Order((int)$this->order_invoice->id_order); + $this->smarty = $smarty; - // header informations - $this->date = Tools::displayDate($order_invoice->date_add); + // If shop_address is null, then update it with current one. + // But no DB save required here to avoid massive updates for bulk PDF generation case. + // (DB: bug fixed in 1.6.1.1 with upgrade SQL script to avoid null shop_address in old orderInvoices) + if (!isset($this->order_invoice->shop_address) || !$this->order_invoice->shop_address) { + $this->order_invoice->shop_address = OrderInvoice::getCurrentFormattedShopAddress((int)$this->order->id_shop); + if (!$bulk_mode) { + OrderInvoice::fixAllShopAddresses(); + } + } + + // header informations + $this->date = Tools::displayDate($order_invoice->date_add); - $id_lang = Context::getContext()->language->id; - $this->title = $order_invoice->getInvoiceNumberFormatted($id_lang); + $id_lang = Context::getContext()->language->id; + $this->title = $order_invoice->getInvoiceNumberFormatted($id_lang); - $this->shop = new Shop((int)$this->order->id_shop); - } + $this->shop = new Shop((int)$this->order->id_shop); + } - /** - * Returns the template's HTML header - * - * @return string HTML header - */ - public function getHeader() - { - $this->assignCommonHeaderData(); - $this->smarty->assign(array( - 'header' => $this->l('INVOICE'), - )); + /** + * Returns the template's HTML header + * + * @return string HTML header + */ + public function getHeader() + { + $this->assignCommonHeaderData(); + $this->smarty->assign(array('header' => HTMLTemplateInvoice::l('Invoice'))); - return $this->smarty->fetch($this->getTemplate('header')); - } + return $this->smarty->fetch($this->getTemplate('header')); + } - /** - * Compute layout elements size - * - * @params $params Array Layout elements - * - * @return Array Layout elements columns size - */ + /** + * Compute layout elements size + * + * @param $params Array Layout elements + * + * @return Array Layout elements columns size + */ + private function computeLayout($params) + { + $layout = array( + 'reference' => array( + 'width' => 15, + ), + 'product' => array( + 'width' => 40, + ), + 'quantity' => array( + 'width' => 8, + ), + 'tax_code' => array( + 'width' => 8, + ), + 'unit_price_tax_excl' => array( + 'width' => 0, + ), + 'total_tax_excl' => array( + 'width' => 0, + ) + ); - private function computeLayout($params) - { - $layout = array( - 'reference' => array( - 'width' => 15, - ), - 'product' => array( - 'width' => 40, - ), - 'quantity' => array( - 'width' => 8, - ), - 'tax_code' => array( - 'width' => 8, - ), - 'unit_price_tax_excl' => array( - 'width' => 0, - ), - 'total_tax_excl' => array( - 'width' => 0, - ) - ); + if (isset($params['has_discount']) && $params['has_discount']) { + $layout['before_discount'] = array('width' => 0); + $layout['product']['width'] -= 7; + $layout['reference']['width'] -= 3; + } - if (isset($params['has_discount']) && $params['has_discount']) - { - $layout['before_discount'] = array('width' => 0); - $layout['product']['width'] -= 7; - $layout['reference']['width'] -= 3; - } + $total_width = 0; + $free_columns_count = 0; + foreach ($layout as $data) { + if ($data['width'] === 0) { + ++$free_columns_count; + } - $total_width = 0; - $free_columns_count = 0; - foreach ($layout as $data) - { - if ($data['width'] === 0) - ++$free_columns_count; + $total_width += $data['width']; + } - $total_width += $data['width']; - } + $delta = 100 - $total_width; - $delta = 100 - $total_width; + foreach ($layout as $row => $data) { + if ($data['width'] === 0) { + $layout[$row]['width'] = $delta / $free_columns_count; + } + } - foreach ($layout as $row => $data) - if ($data['width'] === 0) - $layout[$row]['width'] = $delta / $free_columns_count; + $layout['_colCount'] = count($layout); - $layout['_colCount'] = count($layout); + return $layout; + } - return $layout; - } - - /** - * Returns the template's HTML content - * - * @return string HTML content - */ - public function getContent() - { + /** + * Returns the template's HTML content + * + * @return string HTML content + */ + public function getContent() + { $invoiceAddressPatternRules = Tools::jsonDecode(Configuration::get('PS_INVCE_INVOICE_ADDR_RULES'), true); $deliveryAddressPatternRules = Tools::jsonDecode(Configuration::get('PS_INVCE_DELIVERY_ADDR_RULES'), true); - $invoice_address = new Address((int)$this->order->id_address_invoice); - $country = new Country((int)$invoice_address->id_country); + $invoice_address = new Address((int)$this->order->id_address_invoice); + $country = new Country((int)$invoice_address->id_country); - if ($this->order_invoice->invoice_address) - $formatted_invoice_address = $this->order_invoice->invoice_address; - else - $formatted_invoice_address = AddressFormat::generateAddress($invoice_address, $invoiceAddressPatternRules, '<br />', ' '); + if ($this->order_invoice->invoice_address) { + $formatted_invoice_address = $this->order_invoice->invoice_address; + } else { + $formatted_invoice_address = AddressFormat::generateAddress($invoice_address, $invoiceAddressPatternRules, '<br />', ' '); + } - $delivery_address = null; - $formatted_delivery_address = ''; - if (isset($this->order->id_address_delivery) && $this->order->id_address_delivery) - { - if ($this->order_invoice->delivery_address) - $formatted_delivery_address = $this->order_invoice->delivery_address; - else - { - $delivery_address = new Address((int)$this->order->id_address_delivery); - $formatted_delivery_address = AddressFormat::generateAddress($delivery_address, $deliveryAddressPatternRules, '<br />', ' '); - } - } + $delivery_address = null; + $formatted_delivery_address = ''; + if (isset($this->order->id_address_delivery) && $this->order->id_address_delivery) { + if ($this->order_invoice->delivery_address) { + $formatted_delivery_address = $this->order_invoice->delivery_address; + } else { + $delivery_address = new Address((int)$this->order->id_address_delivery); + $formatted_delivery_address = AddressFormat::generateAddress($delivery_address, $deliveryAddressPatternRules, '<br />', ' '); + } + } - $customer = new Customer((int)$this->order->id_customer); + $customer = new Customer((int)$this->order->id_customer); - $order_details = $this->order_invoice->getProducts(); + $order_details = $this->order_invoice->getProducts(); - $has_discount = false; - foreach ($order_details as $id => &$order_detail) - { - // Find out if column 'price before discount' is required - if ($order_detail['reduction_amount_tax_excl'] > 0) - { - $has_discount = true; - $order_detail['unit_price_tax_excl_before_specific_price'] = $order_detail['unit_price_tax_excl_including_ecotax'] + $order_detail['reduction_amount_tax_excl']; - } - elseif ($order_detail['reduction_percent'] > 0) - { - $has_discount = true; - $order_detail['unit_price_tax_excl_before_specific_price'] = (100 * $order_detail['unit_price_tax_excl_including_ecotax']) / (100 - 15); - } - - // Set tax_code - $taxes = OrderDetail::getTaxListStatic($id); - $tax_temp = array(); - foreach ($taxes as $tax) - { - $obj = new Tax($tax['id_tax']); - $tax_temp[] = sprintf($this->l('%1$s%2$s%%'), ($obj->rate + 0), ' '); + $has_discount = false; + foreach ($order_details as $id => &$order_detail) { + // Find out if column 'price before discount' is required + if ($order_detail['reduction_amount_tax_excl'] > 0) { + $has_discount = true; + $order_detail['unit_price_tax_excl_before_specific_price'] = $order_detail['unit_price_tax_excl_including_ecotax'] + $order_detail['reduction_amount_tax_excl']; + } elseif ($order_detail['reduction_percent'] > 0) { + $has_discount = true; + $order_detail['unit_price_tax_excl_before_specific_price'] = (100 * $order_detail['unit_price_tax_excl_including_ecotax']) / (100 - $order_detail['reduction_percent']); } - $order_detail['order_detail_tax'] = $taxes; - $order_detail['order_detail_tax_label'] = implode(', ', $tax_temp); - } - unset($tax_temp); - unset($order_detail); + // Set tax_code + $taxes = OrderDetail::getTaxListStatic($id); + $tax_temp = array(); + foreach ($taxes as $tax) { + $obj = new Tax($tax['id_tax']); + $tax_temp[] = sprintf($this->l('%1$s%2$s%%'), ($obj->rate + 0), ' '); + } - if (Configuration::get('PS_PDF_IMG_INVOICE')) - { - foreach ($order_details as &$order_detail) - { - if ($order_detail['image'] != null) - { - $name = 'product_mini_'.(int)$order_detail['product_id'].(isset($order_detail['product_attribute_id']) ? '_'.(int)$order_detail['product_attribute_id'] : '').'.jpg'; - $path = _PS_PROD_IMG_DIR_.$order_detail['image']->getExistingImgPath().'.jpg'; + $order_detail['order_detail_tax'] = $taxes; + $order_detail['order_detail_tax_label'] = implode(', ', $tax_temp); + } + unset($tax_temp); + unset($order_detail); - $order_detail['image_tag'] = preg_replace( - '/\.*'.preg_quote(__PS_BASE_URI__, '/').'/', - _PS_ROOT_DIR_.DIRECTORY_SEPARATOR, - ImageManager::thumbnail($path, $name, 45, 'jpg', false), - 1 - ); + if (Configuration::get('PS_PDF_IMG_INVOICE')) { + foreach ($order_details as &$order_detail) { + if ($order_detail['image'] != null) { + $name = 'product_mini_'.(int)$order_detail['product_id'].(isset($order_detail['product_attribute_id']) ? '_'.(int)$order_detail['product_attribute_id'] : '').'.jpg'; + $path = _PS_PROD_IMG_DIR_.$order_detail['image']->getExistingImgPath().'.jpg'; - if (file_exists(_PS_TMP_IMG_DIR_.$name)) - $order_detail['image_size'] = getimagesize(_PS_TMP_IMG_DIR_.$name); - else - $order_detail['image_size'] = false; - } - } - unset($order_detail); // don't overwrite the last order_detail later - } + $order_detail['image_tag'] = preg_replace( + '/\.*'.preg_quote(__PS_BASE_URI__, '/').'/', + _PS_ROOT_DIR_.DIRECTORY_SEPARATOR, + ImageManager::thumbnail($path, $name, 45, 'jpg', false), + 1 + ); - $cart_rules = $this->order->getCartRules($this->order_invoice->id); - $free_shipping = false; - foreach ($cart_rules as $key => $cart_rule) - { - if ($cart_rule['free_shipping']) - { - $free_shipping = true; - /** - * Adjust cart rule value to remove the amount of the shipping. - * We're not interested in displaying the shipping discount as it is already shown as "Free Shipping". - */ - $cart_rules[$key]['value_tax_excl'] -= $this->order_invoice->total_shipping_tax_excl; - $cart_rules[$key]['value'] -= $this->order_invoice->total_shipping_tax_incl; + if (file_exists(_PS_TMP_IMG_DIR_.$name)) { + $order_detail['image_size'] = getimagesize(_PS_TMP_IMG_DIR_.$name); + } else { + $order_detail['image_size'] = false; + } + } + } + unset($order_detail); // don't overwrite the last order_detail later + } - /** - * Don't display cart rules that are only about free shipping and don't create - * a discount on products. - */ - if ($cart_rules[$key]['value'] == 0) - unset($cart_rules[$key]); - } - } + $cart_rules = $this->order->getCartRules($this->order_invoice->id); + $free_shipping = false; + foreach ($cart_rules as $key => $cart_rule) { + if ($cart_rule['free_shipping']) { + $free_shipping = true; + /** + * Adjust cart rule value to remove the amount of the shipping. + * We're not interested in displaying the shipping discount as it is already shown as "Free Shipping". + */ + $cart_rules[$key]['value_tax_excl'] -= $this->order_invoice->total_shipping_tax_excl; + $cart_rules[$key]['value'] -= $this->order_invoice->total_shipping_tax_incl; - $product_taxes = 0; - foreach ($this->order_invoice->getProductTaxesBreakdown($this->order) as $details) - $product_taxes += $details['total_amount']; + /** + * Don't display cart rules that are only about free shipping and don't create + * a discount on products. + */ + if ($cart_rules[$key]['value'] == 0) { + unset($cart_rules[$key]); + } + } + } - $product_discounts_tax_excl = $this->order_invoice->total_discount_tax_excl; - $product_discounts_tax_incl = $this->order_invoice->total_discount_tax_incl; - if ($free_shipping) - { - $product_discounts_tax_excl -= $this->order_invoice->total_shipping_tax_excl; - $product_discounts_tax_incl -= $this->order_invoice->total_shipping_tax_incl; - } + $product_taxes = 0; + foreach ($this->order_invoice->getProductTaxesBreakdown($this->order) as $details) { + $product_taxes += $details['total_amount']; + } - $products_after_discounts_tax_excl = $this->order_invoice->total_products - $product_discounts_tax_excl; - $products_after_discounts_tax_incl = $this->order_invoice->total_products_wt - $product_discounts_tax_incl; + $product_discounts_tax_excl = $this->order_invoice->total_discount_tax_excl; + $product_discounts_tax_incl = $this->order_invoice->total_discount_tax_incl; + if ($free_shipping) { + $product_discounts_tax_excl -= $this->order_invoice->total_shipping_tax_excl; + $product_discounts_tax_incl -= $this->order_invoice->total_shipping_tax_incl; + } - $shipping_tax_excl = $free_shipping ? 0 : $this->order_invoice->total_shipping_tax_excl; - $shipping_tax_incl = $free_shipping ? 0 : $this->order_invoice->total_shipping_tax_incl; - $shipping_taxes = $shipping_tax_incl - $shipping_tax_excl; + $products_after_discounts_tax_excl = $this->order_invoice->total_products - $product_discounts_tax_excl; + $products_after_discounts_tax_incl = $this->order_invoice->total_products_wt - $product_discounts_tax_incl; - $wrapping_taxes = $this->order_invoice->total_wrapping_tax_incl - $this->order_invoice->total_wrapping_tax_excl; + $shipping_tax_excl = $free_shipping ? 0 : $this->order_invoice->total_shipping_tax_excl; + $shipping_tax_incl = $free_shipping ? 0 : $this->order_invoice->total_shipping_tax_incl; + $shipping_taxes = $shipping_tax_incl - $shipping_tax_excl; - $total_taxes = $this->order_invoice->total_paid_tax_incl - $this->order_invoice->total_paid_tax_excl; + $wrapping_taxes = $this->order_invoice->total_wrapping_tax_incl - $this->order_invoice->total_wrapping_tax_excl; - $footer = array( - 'products_before_discounts_tax_excl' => $this->order_invoice->total_products, - 'product_discounts_tax_excl' => $product_discounts_tax_excl, - 'products_after_discounts_tax_excl' => $products_after_discounts_tax_excl, - 'products_before_discounts_tax_incl' => $this->order_invoice->total_products_wt, - 'product_discounts_tax_incl' => $product_discounts_tax_incl, - 'products_after_discounts_tax_incl' => $products_after_discounts_tax_incl, - 'product_taxes' => $product_taxes, - 'shipping_tax_excl' => $shipping_tax_excl, - 'shipping_taxes' => $shipping_taxes, - 'shipping_tax_incl' => $shipping_tax_incl, - 'wrapping_tax_excl' => $this->order_invoice->total_wrapping_tax_excl, - 'wrapping_taxes' => $wrapping_taxes, - 'wrapping_tax_incl' => $this->order_invoice->total_wrapping_tax_incl, - 'ecotax_taxes' => $total_taxes - $product_taxes - $wrapping_taxes - $shipping_taxes, - 'total_taxes' => $total_taxes, - 'total_paid_tax_excl' => $this->order_invoice->total_paid_tax_excl, - 'total_paid_tax_incl' => $this->order_invoice->total_paid_tax_incl - ); + $total_taxes = $this->order_invoice->total_paid_tax_incl - $this->order_invoice->total_paid_tax_excl; - foreach ($footer as $key => $value) - $footer[$key] = Tools::ps_round($value, _PS_PRICE_COMPUTE_PRECISION_, $this->order->round_mode); + $footer = array( + 'products_before_discounts_tax_excl' => $this->order_invoice->total_products, + 'product_discounts_tax_excl' => $product_discounts_tax_excl, + 'products_after_discounts_tax_excl' => $products_after_discounts_tax_excl, + 'products_before_discounts_tax_incl' => $this->order_invoice->total_products_wt, + 'product_discounts_tax_incl' => $product_discounts_tax_incl, + 'products_after_discounts_tax_incl' => $products_after_discounts_tax_incl, + 'product_taxes' => $product_taxes, + 'shipping_tax_excl' => $shipping_tax_excl, + 'shipping_taxes' => $shipping_taxes, + 'shipping_tax_incl' => $shipping_tax_incl, + 'wrapping_tax_excl' => $this->order_invoice->total_wrapping_tax_excl, + 'wrapping_taxes' => $wrapping_taxes, + 'wrapping_tax_incl' => $this->order_invoice->total_wrapping_tax_incl, + 'ecotax_taxes' => $total_taxes - $product_taxes - $wrapping_taxes - $shipping_taxes, + 'total_taxes' => $total_taxes, + 'total_paid_tax_excl' => $this->order_invoice->total_paid_tax_excl, + 'total_paid_tax_incl' => $this->order_invoice->total_paid_tax_incl + ); - /** - * Need the $round_mode for the tests. - */ - $round_type = null; - switch ($this->order->round_type) - { - case Order::ROUND_TOTAL: - $round_type = 'total'; - break; - case Order::ROUND_LINE; - $round_type = 'line'; - break; - case Order::ROUND_ITEM: - $round_type = 'item'; - break; - default: - $round_type = 'line'; - break; - } + foreach ($footer as $key => $value) { + $footer[$key] = Tools::ps_round($value, _PS_PRICE_COMPUTE_PRECISION_, $this->order->round_mode); + } - $display_product_images = Configuration::get('PS_PDF_IMG_INVOICE'); - $tax_excluded_display = Group::getPriceDisplayMethod($customer->id_default_group); + /** + * Need the $round_mode for the tests. + */ + $round_type = null; + switch ($this->order->round_type) { + case Order::ROUND_TOTAL: + $round_type = 'total'; + break; + case Order::ROUND_LINE; + $round_type = 'line'; + break; + case Order::ROUND_ITEM: + $round_type = 'item'; + break; + default: + $round_type = 'line'; + break; + } - $layout = $this->computeLayout(array('has_discount' => $has_discount)); + $display_product_images = Configuration::get('PS_PDF_IMG_INVOICE'); + $tax_excluded_display = Group::getPriceDisplayMethod($customer->id_default_group); - $legal_free_text = Hook::exec('displayInvoiceLegalFreeText', array('order' => $this->order)); - if (!$legal_free_text) - $legal_free_text = Configuration::get('PS_INVOICE_LEGAL_FREE_TEXT', (int)Context::getContext()->language->id, null, (int)$this->order->id_shop); + $layout = $this->computeLayout(array('has_discount' => $has_discount)); - $data = array( - 'order' => $this->order, + $legal_free_text = Hook::exec('displayInvoiceLegalFreeText', array('order' => $this->order)); + if (!$legal_free_text) { + $legal_free_text = Configuration::get('PS_INVOICE_LEGAL_FREE_TEXT', (int)Context::getContext()->language->id, null, (int)$this->order->id_shop); + } + + $data = array( + 'order' => $this->order, 'order_invoice' => $this->order_invoice, 'order_details' => $order_details, - 'cart_rules' => $cart_rules, - 'delivery_address' => $formatted_delivery_address, - 'invoice_address' => $formatted_invoice_address, - 'addresses' => array('invoice' => $invoice_address, 'delivery' => $delivery_address), - 'tax_excluded_display' => $tax_excluded_display, - 'display_product_images' => $display_product_images, - 'layout' => $layout, - 'tax_tab' => $this->getTaxTabContent(), - 'customer' => $customer, - 'footer' => $footer, - 'ps_price_compute_precision' => _PS_PRICE_COMPUTE_PRECISION_, - 'round_type' => $round_type, - 'legal_free_text' => $legal_free_text, - ); + 'cart_rules' => $cart_rules, + 'delivery_address' => $formatted_delivery_address, + 'invoice_address' => $formatted_invoice_address, + 'addresses' => array('invoice' => $invoice_address, 'delivery' => $delivery_address), + 'tax_excluded_display' => $tax_excluded_display, + 'display_product_images' => $display_product_images, + 'layout' => $layout, + 'tax_tab' => $this->getTaxTabContent(), + 'customer' => $customer, + 'footer' => $footer, + 'ps_price_compute_precision' => _PS_PRICE_COMPUTE_PRECISION_, + 'round_type' => $round_type, + 'legal_free_text' => $legal_free_text, + ); - if (Tools::getValue('debug')) - die(json_encode($data)); + if (Tools::getValue('debug')) { + die(json_encode($data)); + } - $this->smarty->assign($data); + $this->smarty->assign($data); - $tpls = array( - 'style_tab' => $this->smarty->fetch($this->getTemplate('invoice.style-tab')), - 'addresses_tab' => $this->smarty->fetch($this->getTemplate('invoice.addresses-tab')), - 'summary_tab' => $this->smarty->fetch($this->getTemplate('invoice.summary-tab')), - 'product_tab' => $this->smarty->fetch($this->getTemplate('invoice.product-tab')), - 'tax_tab' => $this->getTaxTabContent(), - 'payment_tab' => $this->smarty->fetch($this->getTemplate('invoice.payment-tab')), - 'total_tab' => $this->smarty->fetch($this->getTemplate('invoice.total-tab')), - ); - $this->smarty->assign($tpls); + $tpls = array( + 'style_tab' => $this->smarty->fetch($this->getTemplate('invoice.style-tab')), + 'addresses_tab' => $this->smarty->fetch($this->getTemplate('invoice.addresses-tab')), + 'summary_tab' => $this->smarty->fetch($this->getTemplate('invoice.summary-tab')), + 'product_tab' => $this->smarty->fetch($this->getTemplate('invoice.product-tab')), + 'tax_tab' => $this->getTaxTabContent(), + 'payment_tab' => $this->smarty->fetch($this->getTemplate('invoice.payment-tab')), + 'total_tab' => $this->smarty->fetch($this->getTemplate('invoice.total-tab')), + ); + $this->smarty->assign($tpls); + return $this->smarty->fetch($this->getTemplateByCountry($country->iso_code)); + } - return $this->smarty->fetch($this->getTemplateByCountry($country->iso_code)); - } + /** + * Returns the tax tab content + * + * @return String Tax tab html content + */ + public function getTaxTabContent() + { + $debug = Tools::getValue('debug'); - /** - * Returns the tax tab content - * - * @return String Tax tab html content - */ - public function getTaxTabContent() - { - $debug = Tools::getValue('debug'); + $address = new Address((int)$this->order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); + $tax_exempt = Configuration::get('VATNUMBER_MANAGEMENT') + && !empty($address->vat_number) + && $address->id_country != Configuration::get('VATNUMBER_COUNTRY'); + $carrier = new Carrier($this->order->id_carrier); - $address = new Address((int)$this->order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); - $tax_exempt = Configuration::get('VATNUMBER_MANAGEMENT') - && !empty($address->vat_number) - && $address->id_country != Configuration::get('VATNUMBER_COUNTRY'); - $carrier = new Carrier($this->order->id_carrier); + $tax_breakdowns = $this->getTaxBreakdown(); - $tax_breakdowns = $this->getTaxBreakdown(); + $data = array( + 'tax_exempt' => $tax_exempt, + 'use_one_after_another_method' => $this->order_invoice->useOneAfterAnotherTaxComputationMethod(), + 'display_tax_bases_in_breakdowns' => $this->order_invoice->displayTaxBasesInProductTaxesBreakdown(), + 'product_tax_breakdown' => $this->order_invoice->getProductTaxesBreakdown($this->order), + 'shipping_tax_breakdown' => $this->order_invoice->getShippingTaxesBreakdown($this->order), + 'ecotax_tax_breakdown' => $this->order_invoice->getEcoTaxTaxesBreakdown(), + 'wrapping_tax_breakdown' => $this->order_invoice->getWrappingTaxesBreakdown(), + 'tax_breakdowns' => $tax_breakdowns, + 'order' => $debug ? null : $this->order, + 'order_invoice' => $debug ? null : $this->order_invoice, + 'carrier' => $debug ? null : $carrier + ); - $data = array( - 'tax_exempt' => $tax_exempt, - 'use_one_after_another_method' => $this->order_invoice->useOneAfterAnotherTaxComputationMethod(), - 'display_tax_bases_in_breakdowns' => $this->order_invoice->displayTaxBasesInProductTaxesBreakdown(), - 'product_tax_breakdown' => $this->order_invoice->getProductTaxesBreakdown($this->order), - 'shipping_tax_breakdown' => $this->order_invoice->getShippingTaxesBreakdown($this->order), - 'ecotax_tax_breakdown' => $this->order_invoice->getEcoTaxTaxesBreakdown(), - 'wrapping_tax_breakdown' => $this->order_invoice->getWrappingTaxesBreakdown(), - 'tax_breakdowns' => $tax_breakdowns, - 'order' => $debug ? null : $this->order, - 'order_invoice' => $debug ? null : $this->order_invoice, - 'carrier' => $debug ? null : $carrier - ); + if ($debug) { + return $data; + } - if ($debug) - return $data; + $this->smarty->assign($data); - $this->smarty->assign($data); + return $this->smarty->fetch($this->getTemplate('invoice.tax-tab')); + } - return $this->smarty->fetch($this->getTemplate('invoice.tax-tab')); - } + /** + * Returns different tax breakdown elements + * + * @return Array Different tax breakdown elements + */ + protected function getTaxBreakdown() + { + $breakdowns = array( + 'product_tax' => $this->order_invoice->getProductTaxesBreakdown($this->order), + 'shipping_tax' => $this->order_invoice->getShippingTaxesBreakdown($this->order), + 'ecotax_tax' => $this->order_invoice->getEcoTaxTaxesBreakdown(), + 'wrapping_tax' => $this->order_invoice->getWrappingTaxesBreakdown(), + ); - /** - * Returns different tax breakdown elements - * - * @return Array Different tax breakdown elements - */ - protected function getTaxBreakdown() - { - $breakdowns = array( - 'product_tax' => $this->order_invoice->getProductTaxesBreakdown($this->order), - 'shipping_tax' => $this->order_invoice->getShippingTaxesBreakdown($this->order), - 'ecotax_tax' => $this->order_invoice->getEcoTaxTaxesBreakdown(), - 'wrapping_tax' => $this->order_invoice->getWrappingTaxesBreakdown(), - ); + foreach ($breakdowns as $type => $bd) { + if (empty($bd)) { + unset($breakdowns[$type]); + } + } - foreach ($breakdowns as $type => $bd) - { - if (empty($bd)) - unset($breakdowns[$type]); - } + if (empty($breakdowns)) { + $breakdowns = false; + } - if (empty($breakdowns)) - $breakdowns = false; + if (isset($breakdowns['product_tax'])) { + foreach ($breakdowns['product_tax'] as &$bd) { + $bd['total_tax_excl'] = $bd['total_price_tax_excl']; + } + } - if (isset($breakdowns['product_tax'])) - { - foreach ($breakdowns['product_tax'] as &$bd) - $bd['total_tax_excl'] = $bd['total_price_tax_excl']; - } + if (isset($breakdowns['ecotax_tax'])) { + foreach ($breakdowns['ecotax_tax'] as &$bd) { + $bd['total_tax_excl'] = $bd['ecotax_tax_excl']; + $bd['total_amount'] = $bd['ecotax_tax_incl'] - $bd['ecotax_tax_excl']; + } + } - if (isset($breakdowns['ecotax_tax'])) { - foreach ($breakdowns['ecotax_tax'] as &$bd) { - $bd['total_tax_excl'] = $bd['ecotax_tax_excl']; - $bd['total_amount'] = $bd['ecotax_tax_incl'] - $bd['ecotax_tax_excl']; - } - } - - return $breakdowns; - } + return $breakdowns; + } /* - protected function getTaxLabel($tax_breakdowns) - { - $tax_label = ''; - $all_taxes = array(); + protected function getTaxLabel($tax_breakdowns) + { + $tax_label = ''; + $all_taxes = array(); - foreach ($tax_breakdowns as $type => $bd) - foreach ($bd as $line) - if(isset($line['id_tax'])) - $all_taxes[] = $line['id_tax']; + foreach ($tax_breakdowns as $type => $bd) + foreach ($bd as $line) + if(isset($line['id_tax'])) + $all_taxes[] = $line['id_tax']; - $taxes = array_unique($all_taxes); + $taxes = array_unique($all_taxes); - foreach ($taxes as $id_tax) { - $tax = new Tax($id_tax); - $tax_label .= $tax->id.': '.$tax->name[$this->order->id_lang].' ('.$tax->rate.'%) '; - } + foreach ($taxes as $id_tax) { + $tax = new Tax($id_tax); + $tax_label .= $tax->id.': '.$tax->name[$this->order->id_lang].' ('.$tax->rate.'%) '; + } - return $tax_label; - } + return $tax_label; + } */ - /** - * Returns the invoice template associated to the country iso_code - * - * @param string $iso_country - */ - protected function getTemplateByCountry($iso_country) - { - $file = Configuration::get('PS_INVOICE_MODEL'); + /** + * Returns the invoice template associated to the country iso_code + * + * @param string $iso_country + */ + protected function getTemplateByCountry($iso_country) + { + $file = Configuration::get('PS_INVOICE_MODEL'); - // try to fetch the iso template - $template = $this->getTemplate($file.'.'.$iso_country); + // try to fetch the iso template + $template = $this->getTemplate($file.'.'.$iso_country); - // else use the default one - if (!$template) - $template = $this->getTemplate($file); + // else use the default one + if (!$template) { + $template = $this->getTemplate($file); + } - return $template; - } + return $template; + } - /** - * Returns the template filename when using bulk rendering - * - * @return string filename - */ - public function getBulkFilename() - { - return 'invoices.pdf'; - } + /** + * Returns the template filename when using bulk rendering + * + * @return string filename + */ + public function getBulkFilename() + { + return 'invoices.pdf'; + } - /** - * Returns the template filename - * - * @return string filename - */ - public function getFilename() - { - return Configuration::get('PS_INVOICE_PREFIX', Context::getContext()->language->id, null, $this->order->id_shop).sprintf('%06d', $this->order_invoice->number).'.pdf'; - } + /** + * Returns the template filename + * + * @return string filename + */ + public function getFilename() + { + return Configuration::get('PS_INVOICE_PREFIX', Context::getContext()->language->id, null, $this->order->id_shop).sprintf('%06d', $this->order_invoice->number).'.pdf'; + } } diff --git a/classes/pdf/HTMLTemplateOrderReturn.php b/classes/pdf/HTMLTemplateOrderReturn.php index 056f2914..525d6bee 100644 --- a/classes/pdf/HTMLTemplateOrderReturn.php +++ b/classes/pdf/HTMLTemplateOrderReturn.php @@ -29,98 +29,97 @@ */ class HTMLTemplateOrderReturnCore extends HTMLTemplate { - public $order_return; - public $order; + public $order_return; + public $order; - /** - * @param OrderReturn $order_return - * @param $smarty - * @throws PrestaShopException - */ - public function __construct(OrderReturn $order_return, $smarty) - { - $this->order_return = $order_return; - $this->smarty = $smarty; - $this->order = new Order($order_return->id_order); + /** + * @param OrderReturn $order_return + * @param $smarty + * @throws PrestaShopException + */ + public function __construct(OrderReturn $order_return, $smarty) + { + $this->order_return = $order_return; + $this->smarty = $smarty; + $this->order = new Order($order_return->id_order); - // header informations - $this->date = Tools::displayDate($this->order->invoice_date); - $prefix = Configuration::get('PS_RETURN_PREFIX', Context::getContext()->language->id); - $this->title = sprintf(HTMLTemplateOrderReturn::l('%1$s%2$06d'), $prefix, $this->order_return->id); + // header informations + $this->date = Tools::displayDate($this->order->invoice_date); + $prefix = Configuration::get('PS_RETURN_PREFIX', Context::getContext()->language->id); + $this->title = sprintf(HTMLTemplateOrderReturn::l('%1$s%2$06d'), $prefix, $this->order_return->id); - $this->shop = new Shop((int)$this->order->id_shop); - } + $this->shop = new Shop((int)$this->order->id_shop); + } - /** - * Returns the template's HTML content - * - * @return string HTML content - */ - public function getContent() - { - $delivery_address = new Address((int)$this->order->id_address_delivery); - $formatted_delivery_address = AddressFormat::generateAddress($delivery_address, array(), '<br />', ' '); - $formatted_invoice_address = ''; + /** + * Returns the template's HTML content + * + * @return string HTML content + */ + public function getContent() + { + $delivery_address = new Address((int)$this->order->id_address_delivery); + $formatted_delivery_address = AddressFormat::generateAddress($delivery_address, array(), '<br />', ' '); + $formatted_invoice_address = ''; - if ($this->order->id_address_delivery != $this->order->id_address_invoice) - { - $invoice_address = new Address((int)$this->order->id_address_invoice); - $formatted_invoice_address = AddressFormat::generateAddress($invoice_address, array(), '<br />', ' '); - } + if ($this->order->id_address_delivery != $this->order->id_address_invoice) { + $invoice_address = new Address((int)$this->order->id_address_invoice); + $formatted_invoice_address = AddressFormat::generateAddress($invoice_address, array(), '<br />', ' '); + } - $this->smarty->assign(array( - 'order_return' => $this->order_return, - 'return_nb_days' => (int)Configuration::get('PS_ORDER_RETURN_NB_DAYS'), - 'products' => OrderReturn::getOrdersReturnProducts((int)$this->order_return->id, $this->order), - 'delivery_address' => $formatted_delivery_address, - 'invoice_address' => $formatted_invoice_address, - 'shop_address' => AddressFormat::generateAddress($this->shop->getAddress(), array(), '<br />', ' ') - )); - - $tpls = array( - 'style_tab' => $this->smarty->fetch($this->getTemplate('invoice.style-tab')), - 'addresses_tab' => $this->smarty->fetch($this->getTemplate('order-return.addresses-tab')), - 'summary_tab' => $this->smarty->fetch($this->getTemplate('order-return.summary-tab')), - 'product_tab' => $this->smarty->fetch($this->getTemplate('order-return.product-tab')), - 'conditions_tab' => $this->smarty->fetch($this->getTemplate('order-return.conditions-tab')), - ); - $this->smarty->assign($tpls); - - return $this->smarty->fetch($this->getTemplate('order-return')); - } + $this->smarty->assign(array( + 'order_return' => $this->order_return, + 'return_nb_days' => (int)Configuration::get('PS_ORDER_RETURN_NB_DAYS'), + 'products' => OrderReturn::getOrdersReturnProducts((int)$this->order_return->id, $this->order), + 'delivery_address' => $formatted_delivery_address, + 'invoice_address' => $formatted_invoice_address, + 'shop_address' => AddressFormat::generateAddress($this->shop->getAddress(), array(), '<br />', ' ') + )); + + $tpls = array( + 'style_tab' => $this->smarty->fetch($this->getTemplate('invoice.style-tab')), + 'addresses_tab' => $this->smarty->fetch($this->getTemplate('order-return.addresses-tab')), + 'summary_tab' => $this->smarty->fetch($this->getTemplate('order-return.summary-tab')), + 'product_tab' => $this->smarty->fetch($this->getTemplate('order-return.product-tab')), + 'conditions_tab' => $this->smarty->fetch($this->getTemplate('order-return.conditions-tab')), + ); + $this->smarty->assign($tpls); + + return $this->smarty->fetch($this->getTemplate('order-return')); + } - /** - * Returns the template filename - * - * @return string filename - */ - public function getFilename() - { - return sprintf('%06d', $this->order_return->id).'.pdf'; - } + /** + * Returns the template filename + * + * @return string filename + */ + public function getFilename() + { + return sprintf('%06d', $this->order_return->id).'.pdf'; + } - /** - * Returns the template filename when using bulk rendering - * - * @return string filename - */ - public function getBulkFilename() - { - return 'invoices.pdf'; - } - - /** - * Returns the template's HTML header - * - * @return string HTML header - */ - public function getHeader() - { - $this->assignCommonHeaderData(); - $this->smarty->assign(array( - 'header' => $this->l('ORDER RETURN'), - )); - - return $this->smarty->fetch($this->getTemplate('header')); - } + /** + * Returns the template filename when using bulk rendering + * + * @return string filename + */ + public function getBulkFilename() + { + return 'invoices.pdf'; + } + + /** + * Returns the template's HTML header + * + * @return string HTML header + */ + public function getHeader() + { + $this->assignCommonHeaderData(); + $this->smarty->assign(array( + 'header' => $this->l('Order return'), + )); + + return $this->smarty->fetch($this->getTemplate('header')); + } } diff --git a/classes/pdf/HTMLTemplateOrderSlip.php b/classes/pdf/HTMLTemplateOrderSlip.php index 8cb1a8d6..8f3c6315 100644 --- a/classes/pdf/HTMLTemplateOrderSlip.php +++ b/classes/pdf/HTMLTemplateOrderSlip.php @@ -29,340 +29,307 @@ */ class HTMLTemplateOrderSlipCore extends HTMLTemplateInvoice { - public $order; - public $order_slip; + public $order; + public $order_slip; - /** - * @param OrderSlip $order_slip - * @param $smarty - * @throws PrestaShopException - */ - public function __construct(OrderSlip $order_slip, $smarty) - { - $this->order_slip = $order_slip; - $this->order = new Order((int)$order_slip->id_order); + /** + * @param OrderSlip $order_slip + * @param $smarty + * @throws PrestaShopException + */ + public function __construct(OrderSlip $order_slip, $smarty) + { + $this->order_slip = $order_slip; + $this->order = new Order((int)$order_slip->id_order); - $products = OrderSlip::getOrdersSlipProducts($this->order_slip->id, $this->order); - $customized_datas = Product::getAllCustomizedDatas((int)$this->order->id_cart); - Product::addCustomizationPrice($products, $customized_datas); + $products = OrderSlip::getOrdersSlipProducts($this->order_slip->id, $this->order); + $customized_datas = Product::getAllCustomizedDatas((int)$this->order->id_cart); + Product::addCustomizationPrice($products, $customized_datas); - $this->order->products = $products; - $this->smarty = $smarty; + $this->order->products = $products; + $this->smarty = $smarty; - // header informations - $this->date = Tools::displayDate($this->order_slip->date_add); - $prefix = Configuration::get('PS_CREDIT_SLIP_PREFIX', Context::getContext()->language->id); - $this->title = sprintf(HTMLTemplateOrderSlip::l('%1$s%2$06d'), $prefix, (int)$this->order_slip->id); + // header informations + $this->date = Tools::displayDate($this->order_slip->date_add); + $prefix = Configuration::get('PS_CREDIT_SLIP_PREFIX', Context::getContext()->language->id); + $this->title = sprintf(HTMLTemplateOrderSlip::l('%1$s%2$06d'), $prefix, (int)$this->order_slip->id); - $this->shop = new Shop((int)$this->order->id_shop); - } - - /** - * Returns the template's HTML header - * - * @return string HTML header - */ - public function getHeader() - { - $this->assignCommonHeaderData(); - $this->smarty->assign(array( - 'header' => $this->l('CREDIT SLIP'), - )); - - return $this->smarty->fetch($this->getTemplate('header')); - } + $this->shop = new Shop((int)$this->order->id_shop); + } + + /** + * Returns the template's HTML header + * + * @return string HTML header + */ + public function getHeader() + { + $this->assignCommonHeaderData(); + $this->smarty->assign(array( + 'header' => $this->l('Credit slip'), + )); - /** - * Returns the template's HTML content - * - * @return string HTML content - */ - public function getContent() - { - $invoice_address = new Address((int)$this->order->id_address_invoice); - $formatted_invoice_address = AddressFormat::generateAddress($invoice_address, array(), '<br />', ' '); - $formatted_delivery_address = ''; + return $this->smarty->fetch($this->getTemplate('header')); + } - if ($this->order->id_address_delivery != $this->order->id_address_invoice) - { - $delivery_address = new Address((int)$this->order->id_address_delivery); - $formatted_delivery_address = AddressFormat::generateAddress($delivery_address, array(), '<br />', ' '); - } + /** + * Returns the template's HTML content + * + * @return string HTML content + */ + public function getContent() + { + $invoice_address = new Address((int)$this->order->id_address_invoice); + $formatted_invoice_address = AddressFormat::generateAddress($invoice_address, array(), '<br />', ' '); + $formatted_delivery_address = ''; - $customer = new Customer((int)$this->order->id_customer); - $this->order->total_paid_tax_excl = $this->order->total_paid_tax_incl = $this->order->total_products = $this->order->total_products_wt = 0; + if ($this->order->id_address_delivery != $this->order->id_address_invoice) { + $delivery_address = new Address((int)$this->order->id_address_delivery); + $formatted_delivery_address = AddressFormat::generateAddress($delivery_address, array(), '<br />', ' '); + } - if ($this->order_slip->amount > 0) - { - foreach ($this->order->products as &$product) - { - $product['total_price_tax_excl'] = $product['unit_price_tax_excl'] * $product['product_quantity']; - $product['total_price_tax_incl'] = $product['unit_price_tax_incl'] * $product['product_quantity']; + $customer = new Customer((int)$this->order->id_customer); + $this->order->total_paid_tax_excl = $this->order->total_paid_tax_incl = $this->order->total_products = $this->order->total_products_wt = 0; - if ($this->order_slip->partial == 1) - { - $order_slip_detail = Db::getInstance()->getRow(' + if ($this->order_slip->amount > 0) { + foreach ($this->order->products as &$product) { + $product['total_price_tax_excl'] = $product['unit_price_tax_excl'] * $product['product_quantity']; + $product['total_price_tax_incl'] = $product['unit_price_tax_incl'] * $product['product_quantity']; + + if ($this->order_slip->partial == 1) { + $order_slip_detail = Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.'order_slip_detail` WHERE `id_order_slip` = '.(int)$this->order_slip->id.' AND `id_order_detail` = '.(int)$product['id_order_detail']); - $product['total_price_tax_excl'] = $order_slip_detail['amount_tax_excl']; - $product['total_price_tax_incl'] = $order_slip_detail['amount_tax_incl']; - } + $product['total_price_tax_excl'] = $order_slip_detail['amount_tax_excl']; + $product['total_price_tax_incl'] = $order_slip_detail['amount_tax_incl']; + } - $this->order->total_products += $product['total_price_tax_excl']; - $this->order->total_products_wt += $product['total_price_tax_incl']; - $this->order->total_paid_tax_excl = $this->order->total_products; - $this->order->total_paid_tax_incl = $this->order->total_products_wt; - } - } - else - $this->order->products = null; + $this->order->total_products += $product['total_price_tax_excl']; + $this->order->total_products_wt += $product['total_price_tax_incl']; + $this->order->total_paid_tax_excl = $this->order->total_products; + $this->order->total_paid_tax_incl = $this->order->total_products_wt; + } + } else { + $this->order->products = null; + } - unset($product); // remove reference + unset($product); // remove reference - if ($this->order_slip->shipping_cost == 0) - $this->order->total_shipping_tax_incl = $this->order->total_shipping_tax_excl = 0; + if ($this->order_slip->shipping_cost == 0) { + $this->order->total_shipping_tax_incl = $this->order->total_shipping_tax_excl = 0; + } - $tax = new Tax(); - $tax->rate = $this->order->carrier_tax_rate; - $tax_calculator = new TaxCalculator(array($tax)); - $tax_excluded_display = Group::getPriceDisplayMethod((int)$customer->id_default_group); + $tax = new Tax(); + $tax->rate = $this->order->carrier_tax_rate; + $tax_calculator = new TaxCalculator(array($tax)); + $tax_excluded_display = Group::getPriceDisplayMethod((int)$customer->id_default_group); - if (/*$this->order_slip->partial == 1 && */$this->order_slip->shipping_cost_amount > 0) - { - if ($tax_excluded_display) - $this->order->total_shipping_tax_incl = Tools::ps_round($tax_calculator->addTaxes($this->order_slip->shipping_cost_amount), 2); - else - $this->order->total_shipping_tax_incl = $this->order_slip->shipping_cost_amount; - } + if (/*$this->order_slip->partial == 1 && */$this->order_slip->shipping_cost_amount > 0) { + if ($tax_excluded_display) { + $this->order->total_shipping_tax_incl = Tools::ps_round($tax_calculator->addTaxes($this->order_slip->shipping_cost_amount), 2); + } else { + $this->order->total_shipping_tax_incl = $this->order_slip->shipping_cost_amount; + } + } - if ($tax_excluded_display) - $this->order->total_shipping_tax_excl = $this->order_slip->shipping_cost_amount; - else - $this->order->total_shipping_tax_excl = Tools::ps_round($tax_calculator->removeTaxes($this->order_slip->shipping_cost_amount), 2); + if ($tax_excluded_display) { + $this->order->total_shipping_tax_excl = $this->order_slip->shipping_cost_amount; + } else { + $this->order->total_shipping_tax_excl = Tools::ps_round($tax_calculator->removeTaxes($this->order_slip->shipping_cost_amount), 2); + } - $this->order->total_paid_tax_incl += $this->order->total_shipping_tax_incl; - $this->order->total_paid_tax_excl += $this->order->total_shipping_tax_excl; - $this->smarty->assign(array( - 'order' => $this->order, - 'order_slip' => $this->order_slip, - 'order_details' => $this->order->products, - 'cart_rules' => $this->order_slip->order_slip_type == 1 ? $this->order->getCartRules($this->order_invoice->id) : false, - 'amount_choosen' => $this->order_slip->order_slip_type == 2 ? true : false, - 'delivery_address' => $formatted_delivery_address, - 'invoice_address' => $formatted_invoice_address, - 'addresses' => array('invoice' => $invoice_address, 'delivery' => $delivery_address), - 'tax_excluded_display' => $tax_excluded_display, - )); + $this->order->total_paid_tax_incl += $this->order->total_shipping_tax_incl; + $this->order->total_paid_tax_excl += $this->order->total_shipping_tax_excl; + + $total_cart_rule = 0; + if ($this->order_slip->order_slip_type == 1 && is_array($cart_rules = $this->order->getCartRules($this->order_invoice->id))) { + foreach($cart_rules as $cart_rule) { + if ($tax_excluded_display) { + $total_cart_rule += $cart_rule['value_tax_excl']; + } else { + $total_cart_rule += $cart_rule['value']; + } + } + } + + $this->smarty->assign(array( + 'order' => $this->order, + 'order_slip' => $this->order_slip, + 'order_details' => $this->order->products, + 'cart_rules' => $this->order_slip->order_slip_type == 1 ? $this->order->getCartRules($this->order_invoice->id) : false, + 'amount_choosen' => $this->order_slip->order_slip_type == 2 ? true : false, + 'delivery_address' => $formatted_delivery_address, + 'invoice_address' => $formatted_invoice_address, + 'addresses' => array('invoice' => $invoice_address, 'delivery' => $delivery_address), + 'tax_excluded_display' => $tax_excluded_display, + 'total_cart_rule' => $total_cart_rule + )); - $tpls = array( - 'style_tab' => $this->smarty->fetch($this->getTemplate('invoice.style-tab')), - 'addresses_tab' => $this->smarty->fetch($this->getTemplate('invoice.addresses-tab')), - 'summary_tab' => $this->smarty->fetch($this->getTemplate('order-slip.summary-tab')), - 'product_tab' => $this->smarty->fetch($this->getTemplate('order-slip.product-tab')), - 'total_tab' => $this->smarty->fetch($this->getTemplate('order-slip.total-tab')), - 'payment_tab' => $this->smarty->fetch($this->getTemplate('order-slip.payment-tab')), - 'tax_tab' => $this->getTaxTabContent(), - ); - $this->smarty->assign($tpls); - - return $this->smarty->fetch($this->getTemplate('order-slip')); - } + $tpls = array( + 'style_tab' => $this->smarty->fetch($this->getTemplate('invoice.style-tab')), + 'addresses_tab' => $this->smarty->fetch($this->getTemplate('invoice.addresses-tab')), + 'summary_tab' => $this->smarty->fetch($this->getTemplate('order-slip.summary-tab')), + 'product_tab' => $this->smarty->fetch($this->getTemplate('order-slip.product-tab')), + 'total_tab' => $this->smarty->fetch($this->getTemplate('order-slip.total-tab')), + 'payment_tab' => $this->smarty->fetch($this->getTemplate('order-slip.payment-tab')), + 'tax_tab' => $this->getTaxTabContent(), + ); + $this->smarty->assign($tpls); + + return $this->smarty->fetch($this->getTemplate('order-slip')); + } - /** - * Returns the template filename when using bulk rendering - * - * @return string filename - */ - public function getBulkFilename() - { - return 'order-slips.pdf'; - } + /** + * Returns the template filename when using bulk rendering + * + * @return string filename + */ + public function getBulkFilename() + { + return 'order-slips.pdf'; + } - /** - * Returns the template filename - * - * @return string filename - */ - public function getFilename() - { - return 'order-slip-'.sprintf('%06d', $this->order_slip->id).'.pdf'; - } + /** + * Returns the template filename + * + * @return string filename + */ + public function getFilename() + { + return 'order-slip-'.sprintf('%06d', $this->order_slip->id).'.pdf'; + } - /** - * Returns the tax tab content - * - * @return String Tax tab html content - */ - public function getTaxTabContent() - { - $address = new Address((int)$this->order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); - $tax_exempt = Configuration::get('VATNUMBER_MANAGEMENT') - && !empty($address->vat_number) - && $address->id_country != Configuration::get('VATNUMBER_COUNTRY'); + /** + * Returns the tax tab content + * + * @return String Tax tab html content + */ + public function getTaxTabContent() + { + $address = new Address((int)$this->order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); + $tax_exempt = Configuration::get('VATNUMBER_MANAGEMENT') + && !empty($address->vat_number) + && $address->id_country != Configuration::get('VATNUMBER_COUNTRY'); - $this->smarty->assign(array( - 'tax_exempt' => $tax_exempt, - 'use_one_after_another_method' => $this->order->useOneAfterAnotherTaxComputationMethod(), - 'product_tax_breakdown' => $this->getProductTaxesBreakdown(), - 'shipping_tax_breakdown' => $this->getShippingTaxesBreakdown(), - 'order' => $this->order, - 'ecotax_tax_breakdown' => $this->order_slip->getEcoTaxTaxesBreakdown(), - 'is_order_slip' => true, - 'tax_breakdowns' => $this->getTaxBreakdown(), - )); + $this->smarty->assign(array( + 'tax_exempt' => $tax_exempt, + 'product_tax_breakdown' => $this->getProductTaxesBreakdown(), + 'shipping_tax_breakdown' => $this->getShippingTaxesBreakdown(), + 'order' => $this->order, + 'ecotax_tax_breakdown' => $this->order_slip->getEcoTaxTaxesBreakdown(), + 'is_order_slip' => true, + 'tax_breakdowns' => $this->getTaxBreakdown(), + 'display_tax_bases_in_breakdowns' => false + )); - return $this->smarty->fetch($this->getTemplate('invoice.tax-tab')); - } + return $this->smarty->fetch($this->getTemplate('invoice.tax-tab')); + } - /** - * Returns different tax breakdown elements - * - * @return Array Different tax breakdown elements - */ - protected function getTaxBreakdown() - { - $breakdowns = array( - 'product_tax' => $this->getProductTaxesBreakdown(), - 'shipping_tax' => $this->getShippingTaxesBreakdown(), - 'ecotax_tax' => $this->order_slip->getEcoTaxTaxesBreakdown(), - ); + /** + * Returns different tax breakdown elements + * + * @return Array Different tax breakdown elements + */ + protected function getTaxBreakdown() + { + $breakdowns = array( + 'product_tax' => $this->getProductTaxesBreakdown(), + 'shipping_tax' => $this->getShippingTaxesBreakdown(), + 'ecotax_tax' => $this->order_slip->getEcoTaxTaxesBreakdown(), + ); - foreach ($breakdowns as $type => $bd) - { - if (empty($bd)) - unset($breakdowns[$type]); - } + foreach ($breakdowns as $type => $bd) { + if (empty($bd)) { + unset($breakdowns[$type]); + } + } - if (empty($breakdowns)) - $breakdowns = false; + if (empty($breakdowns)) { + $breakdowns = false; + } - if (isset($breakdowns['product_tax'])) - { - foreach ($breakdowns['product_tax'] as &$bd) - $bd['total_tax_excl'] = $bd['total_price_tax_excl']; - } + if (isset($breakdowns['product_tax'])) { + foreach ($breakdowns['product_tax'] as &$bd) { + $bd['total_tax_excl'] = $bd['total_price_tax_excl']; + } + } - if (isset($breakdowns['ecotax_tax'])) - { - foreach ($breakdowns['ecotax_tax'] as &$bd) - { - $bd['total_tax_excl'] = $bd['ecotax_tax_excl']; - $bd['total_amount'] = $bd['ecotax_tax_incl'] - $bd['ecotax_tax_excl']; - } - } + if (isset($breakdowns['ecotax_tax'])) { + foreach ($breakdowns['ecotax_tax'] as &$bd) { + $bd['total_tax_excl'] = $bd['ecotax_tax_excl']; + $bd['total_amount'] = $bd['ecotax_tax_incl'] - $bd['ecotax_tax_excl']; + } + } - return $breakdowns; - } + return $breakdowns; + } - public function getProductTaxesBreakdown() - { - $sum_composite_taxes = !$this->useOneAfterAnotherTaxComputationMethod(); + public function getProductTaxesBreakdown() + { + // $breakdown will be an array with tax rates as keys and at least the columns: + // - 'total_price_tax_excl' + // - 'total_amount' + $breakdown = array(); - // $breakdown will be an array with tax rates as keys and at least the columns: - // - 'total_price_tax_excl' - // - 'total_amount' - $breakdown = array(); + $details = $this->order->getProductTaxesDetails($this->order->products); - $details = $this->order->getProductTaxesDetails(); + foreach ($details as $row) { + $rate = sprintf('%.3f', $row['tax_rate']); + if (!isset($breakdown[$rate])) { + $breakdown[$rate] = array( + 'total_price_tax_excl' => 0, + 'total_amount' => 0, + 'id_tax' => $row['id_tax'], + 'rate' =>$rate, + ); + } - if ($sum_composite_taxes) - { - $grouped_details = array(); - foreach ($details as $row) - { - if (!isset($grouped_details[$row['id_order_detail']])) - { - $grouped_details[$row['id_order_detail']] = array( - 'tax_rate' => 0, - 'total_tax_base' => 0, - 'total_amount' => 0, - 'id_tax' => $row['id_tax'], - ); - } + $breakdown[$rate]['total_price_tax_excl'] += $row['total_tax_base']; + $breakdown[$rate]['total_amount'] += $row['total_amount']; + } - $grouped_details[$row['id_order_detail']]['tax_rate'] += $row['tax_rate']; - $grouped_details[$row['id_order_detail']]['total_tax_base'] += $row['total_tax_base']; - $grouped_details[$row['id_order_detail']]['total_amount'] += $row['total_amount']; - } + foreach ($breakdown as $rate => $data) { + $breakdown[$rate]['total_price_tax_excl'] = Tools::ps_round($data['total_price_tax_excl'], _PS_PRICE_COMPUTE_PRECISION_, $this->order->round_mode); + $breakdown[$rate]['total_amount'] = Tools::ps_round($data['total_amount'], _PS_PRICE_COMPUTE_PRECISION_, $this->order->round_mode); + } - $details = $grouped_details; - } + ksort($breakdown); - foreach ($details as $row) - { - $rate = sprintf('%.3f', $row['tax_rate']); - if (!isset($breakdown[$rate])) - { - $breakdown[$rate] = array( - 'total_price_tax_excl' => 0, - 'total_amount' => 0, - 'id_tax' => $row['id_tax'], - 'rate' =>$rate, - ); - } + return $breakdown; + } - $breakdown[$rate]['total_price_tax_excl'] += $row['total_tax_base']; - $breakdown[$rate]['total_amount'] += $row['total_amount']; - } + /** + * Returns Shipping tax breakdown elements + * + * @return Array Shipping tax breakdown elements + */ + public function getShippingTaxesBreakdown() + { + $taxes_breakdown = array(); + $tax = new Tax(); + $tax->rate = $this->order->carrier_tax_rate; + $tax_calculator = new TaxCalculator(array($tax)); + $customer = new Customer((int)$this->order->id_customer); + $tax_excluded_display = Group::getPriceDisplayMethod((int)$customer->id_default_group); - foreach ($breakdown as $rate => $data) - { - $breakdown[$rate]['total_price_tax_excl'] = Tools::ps_round($data['total_price_tax_excl'], _PS_PRICE_COMPUTE_PRECISION_, $order->round_mode); - $breakdown[$rate]['total_amount'] = Tools::ps_round($data['total_amount'], _PS_PRICE_COMPUTE_PRECISION_, $order->round_mode); - } + if ($tax_excluded_display) { + $total_tax_excl = $this->order_slip->shipping_cost_amount; + $shipping_tax_amount = $tax_calculator->addTaxes($this->order_slip->shipping_cost_amount) - $total_tax_excl; + } else { + $total_tax_excl = $tax_calculator->removeTaxes($this->order_slip->shipping_cost_amount); + $shipping_tax_amount = $this->order_slip->shipping_cost_amount - $total_tax_excl; + } - ksort($breakdown); + if ($shipping_tax_amount > 0) { + $taxes_breakdown[] = array( + 'rate' => $this->order->carrier_tax_rate, + 'total_amount' => $shipping_tax_amount, + 'total_tax_excl' => $total_tax_excl + ); + } - return $breakdown; - } - - public function useOneAfterAnotherTaxComputationMethod() - { - // if one of the order details use the tax computation method the display will be different - return Db::getInstance()->getValue(' - SELECT od.`tax_computation_method` - FROM `'._DB_PREFIX_.'order_detail_tax` odt - LEFT JOIN `'._DB_PREFIX_.'order_detail` od ON (od.`id_order_detail` = odt.`id_order_detail`) - WHERE od.`id_order` = '.(int)$this->id_order.' - AND od.`id_order_invoice` = '.(int)$this->id.' - AND od.`tax_computation_method` = '.(int)TaxCalculator::ONE_AFTER_ANOTHER_METHOD - ) || Configuration::get('PS_INVOICE_TAXES_BREAKDOWN'); - } - - /** - * Returns Shipping tax breakdown elements - * - * @return Array Shipping tax breakdown elements - */ - public function getShippingTaxesBreakdown() - { - $taxes_breakdown = array(); - $tax = new Tax(); - $tax->rate = $this->order->carrier_tax_rate; - $tax_calculator = new TaxCalculator(array($tax)); - $customer = new Customer((int)$this->order->id_customer); - $tax_excluded_display = Group::getPriceDisplayMethod((int)$customer->id_default_group); - - if ($tax_excluded_display) - { - $total_tax_excl = $this->order_slip->shipping_cost_amount; - $shipping_tax_amount = $tax_calculator->addTaxes($this->order_slip->shipping_cost_amount) - $total_tax_excl; - } - else - { - $total_tax_excl = $tax_calculator->removeTaxes($this->order_slip->shipping_cost_amount); - $shipping_tax_amount = $this->order_slip->shipping_cost_amount - $total_tax_excl; - } - - if ($shipping_tax_amount > 0) - $taxes_breakdown[] = array( - 'rate' => $this->order->carrier_tax_rate, - 'total_amount' => $shipping_tax_amount, - 'total_tax_excl' => $total_tax_excl - ); - - return $taxes_breakdown; - } + return $taxes_breakdown; + } } diff --git a/classes/pdf/HTMLTemplateSupplyOrderForm.php b/classes/pdf/HTMLTemplateSupplyOrderForm.php index fe047645..3ecf41bc 100644 --- a/classes/pdf/HTMLTemplateSupplyOrderForm.php +++ b/classes/pdf/HTMLTemplateSupplyOrderForm.php @@ -29,211 +29,211 @@ */ class HTMLTemplateSupplyOrderFormCore extends HTMLTemplate { - public $supply_order; - public $warehouse; - public $address_warehouse; - public $address_supplier; - public $context; + public $supply_order; + public $warehouse; + public $address_warehouse; + public $address_supplier; + public $context; - /** - * @param SupplyOrder $supply_order - * @param $smarty - * @throws PrestaShopException - */ - public function __construct(SupplyOrder $supply_order, $smarty) - { - $this->supply_order = $supply_order; - $this->smarty = $smarty; - $this->context = Context::getContext(); - $this->warehouse = new Warehouse((int)$supply_order->id_warehouse); - $this->address_warehouse = new Address((int)$this->warehouse->id_address); - $this->address_supplier = new Address(Address::getAddressIdBySupplierId((int)$supply_order->id_supplier)); + /** + * @param SupplyOrder $supply_order + * @param $smarty + * @throws PrestaShopException + */ + public function __construct(SupplyOrder $supply_order, $smarty) + { + $this->supply_order = $supply_order; + $this->smarty = $smarty; + $this->context = Context::getContext(); + $this->warehouse = new Warehouse((int)$supply_order->id_warehouse); + $this->address_warehouse = new Address((int)$this->warehouse->id_address); + $this->address_supplier = new Address(Address::getAddressIdBySupplierId((int)$supply_order->id_supplier)); - // header informations - $this->date = Tools::displayDate($supply_order->date_add); - $this->title = HTMLTemplateSupplyOrderForm::l('Supply order form'); + // header informations + $this->date = Tools::displayDate($supply_order->date_add); + $this->title = HTMLTemplateSupplyOrderForm::l('Supply order form'); - $this->shop = new Shop((int)$this->order->id_shop); - } + $this->shop = new Shop((int)$this->order->id_shop); + } - /** - * @see HTMLTemplate::getContent() - */ - public function getContent() - { - $supply_order_details = $this->supply_order->getEntriesCollection((int)$this->supply_order->id_lang); - $this->roundSupplyOrderDetails($supply_order_details); + /** + * @see HTMLTemplate::getContent() + */ + public function getContent() + { + $supply_order_details = $this->supply_order->getEntriesCollection((int)$this->supply_order->id_lang); + $this->roundSupplyOrderDetails($supply_order_details); - $this->roundSupplyOrder($this->supply_order); + $this->roundSupplyOrder($this->supply_order); - $tax_order_summary = $this->getTaxOrderSummary(); - $currency = new Currency((int)$this->supply_order->id_currency); + $tax_order_summary = $this->getTaxOrderSummary(); + $currency = new Currency((int)$this->supply_order->id_currency); - $this->smarty->assign(array( - 'warehouse' => $this->warehouse, - 'address_warehouse' => $this->address_warehouse, - 'address_supplier' => $this->address_supplier, - 'supply_order' => $this->supply_order, - 'supply_order_details' => $supply_order_details, - 'tax_order_summary' => $tax_order_summary, - 'currency' => $currency, - )); - - $tpls = array( - 'style_tab' => $this->smarty->fetch($this->getTemplate('invoice.style-tab')), - 'addresses_tab' => $this->smarty->fetch($this->getTemplate('supply-order.addresses-tab')), - 'product_tab' => $this->smarty->fetch($this->getTemplate('supply-order.product-tab')), - 'tax_tab' => $this->smarty->fetch($this->getTemplate('supply-order.tax-tab')), - 'total_tab' => $this->smarty->fetch($this->getTemplate('supply-order.total-tab')), - ); - $this->smarty->assign($tpls); + $this->smarty->assign(array( + 'warehouse' => $this->warehouse, + 'address_warehouse' => $this->address_warehouse, + 'address_supplier' => $this->address_supplier, + 'supply_order' => $this->supply_order, + 'supply_order_details' => $supply_order_details, + 'tax_order_summary' => $tax_order_summary, + 'currency' => $currency, + )); + + $tpls = array( + 'style_tab' => $this->smarty->fetch($this->getTemplate('invoice.style-tab')), + 'addresses_tab' => $this->smarty->fetch($this->getTemplate('supply-order.addresses-tab')), + 'product_tab' => $this->smarty->fetch($this->getTemplate('supply-order.product-tab')), + 'tax_tab' => $this->smarty->fetch($this->getTemplate('supply-order.tax-tab')), + 'total_tab' => $this->smarty->fetch($this->getTemplate('supply-order.total-tab')), + ); + $this->smarty->assign($tpls); - return $this->smarty->fetch($this->getTemplate('supply-order')); - } + return $this->smarty->fetch($this->getTemplate('supply-order')); + } - /** - * Returns the invoice logo - * - * @return String Logo path - */ - protected function getLogo() - { - $logo = ''; + /** + * Returns the invoice logo + * + * @return String Logo path + */ + protected function getLogo() + { + $logo = ''; - if (Configuration::get('PS_LOGO_INVOICE', null, null, (int)Shop::getContextShopID()) != false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_INVOICE', null, null, (int)Shop::getContextShopID()))) - $logo = _PS_IMG_DIR_.Configuration::get('PS_LOGO_INVOICE', null, null, (int)Shop::getContextShopID()); - elseif (Configuration::get('PS_LOGO', null, null, (int)Shop::getContextShopID()) != false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO', null, null, (int)Shop::getContextShopID()))) - $logo = _PS_IMG_DIR_.Configuration::get('PS_LOGO', null, null, (int)Shop::getContextShopID()); + if (Configuration::get('PS_LOGO_INVOICE', null, null, (int)Shop::getContextShopID()) != false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_INVOICE', null, null, (int)Shop::getContextShopID()))) { + $logo = _PS_IMG_DIR_.Configuration::get('PS_LOGO_INVOICE', null, null, (int)Shop::getContextShopID()); + } elseif (Configuration::get('PS_LOGO', null, null, (int)Shop::getContextShopID()) != false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO', null, null, (int)Shop::getContextShopID()))) { + $logo = _PS_IMG_DIR_.Configuration::get('PS_LOGO', null, null, (int)Shop::getContextShopID()); + } - return $logo; - } + return $logo; + } - /** - * @see HTMLTemplate::getBulkFilename() - */ - public function getBulkFilename() - { - return 'supply_order.pdf'; - } + /** + * @see HTMLTemplate::getBulkFilename() + */ + public function getBulkFilename() + { + return 'supply_order.pdf'; + } - /** - * @see HTMLTemplate::getFileName() - */ - public function getFilename() - { - return self::l('SupplyOrderForm').sprintf('_%s', $this->supply_order->reference).'.pdf'; - } + /** + * @see HTMLTemplate::getFileName() + */ + public function getFilename() + { + return self::l('SupplyOrderForm').sprintf('_%s', $this->supply_order->reference).'.pdf'; + } - /** - * Get order taxes summary - * - * @return array|false|mysqli_result|null|PDOStatement|resource - * @throws PrestaShopDatabaseException - */ + /** + * Get order taxes summary + * + * @return array|false|mysqli_result|null|PDOStatement|resource + * @throws PrestaShopDatabaseException + */ - protected function getTaxOrderSummary() - { - $query = new DbQuery(); - $query->select(' + protected function getTaxOrderSummary() + { + $query = new DbQuery(); + $query->select(' SUM(price_with_order_discount_te) as base_te, tax_rate, SUM(tax_value_with_order_discount) as total_tax_value '); - $query->from('supply_order_detail'); - $query->where('id_supply_order = '.(int)$this->supply_order->id); - $query->groupBy('tax_rate'); + $query->from('supply_order_detail'); + $query->where('id_supply_order = '.(int)$this->supply_order->id); + $query->groupBy('tax_rate'); - $results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + $results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - foreach ($results as &$result) - { - $result['base_te'] = Tools::ps_round($result['base_te'], 2); - $result['tax_rate'] = Tools::ps_round($result['tax_rate'], 2); - $result['total_tax_value'] = Tools::ps_round($result['total_tax_value'], 2); - } + foreach ($results as &$result) { + $result['base_te'] = Tools::ps_round($result['base_te'], 2); + $result['tax_rate'] = Tools::ps_round($result['tax_rate'], 2); + $result['total_tax_value'] = Tools::ps_round($result['total_tax_value'], 2); + } - unset($result); // remove reference + unset($result); // remove reference - return $results; - } + return $results; + } - /** - * @see HTMLTemplate::getHeader() - */ - public function getHeader() - { - $shop_name = Configuration::get('PS_SHOP_NAME'); - $path_logo = $this->getLogo(); - $width = $height = 0; + /** + * @see HTMLTemplate::getHeader() + */ + public function getHeader() + { + $shop_name = Configuration::get('PS_SHOP_NAME'); + $path_logo = $this->getLogo(); + $width = $height = 0; - if (!empty($path_logo)) - list($width, $height) = getimagesize($path_logo); + if (!empty($path_logo)) { + list($width, $height) = getimagesize($path_logo); + } - $this->smarty->assign(array( - 'logo_path' => $path_logo, - 'img_ps_dir' => 'http://'.Tools::getMediaServer(_PS_IMG_)._PS_IMG_, - 'img_update_time' => Configuration::get('PS_IMG_UPDATE_TIME'), - 'title' => $this->title, - 'reference' => $this->supply_order->reference, - 'date' => $this->date, - 'shop_name' => $shop_name, - 'width_logo' => $width, - 'height_logo' => $height - )); + $this->smarty->assign(array( + 'logo_path' => $path_logo, + 'img_ps_dir' => 'http://'.Tools::getMediaServer(_PS_IMG_)._PS_IMG_, + 'img_update_time' => Configuration::get('PS_IMG_UPDATE_TIME'), + 'title' => $this->title, + 'reference' => $this->supply_order->reference, + 'date' => $this->date, + 'shop_name' => $shop_name, + 'width_logo' => $width, + 'height_logo' => $height + )); - return $this->smarty->fetch($this->getTemplate('supply-order-header')); - } + return $this->smarty->fetch($this->getTemplate('supply-order-header')); + } - /** - * @see HTMLTemplate::getFooter() - */ - public function getFooter() - { - $this->address = $this->address_warehouse; - $free_text = array(); - $free_text[] = HTMLTemplateSupplyOrderForm::l('TE: Tax excluded'); - $free_text[] = HTMLTemplateSupplyOrderForm::l('TI: Tax included'); + /** + * @see HTMLTemplate::getFooter() + */ + public function getFooter() + { + $this->address = $this->address_warehouse; + $free_text = array(); + $free_text[] = HTMLTemplateSupplyOrderForm::l('TE: Tax excluded'); + $free_text[] = HTMLTemplateSupplyOrderForm::l('TI: Tax included'); - $this->smarty->assign(array( - 'shop_address' => $this->getShopAddress(), - 'shop_fax' => Configuration::get('PS_SHOP_FAX'), - 'shop_phone' => Configuration::get('PS_SHOP_PHONE'), - 'shop_details' => Configuration::get('PS_SHOP_DETAILS'), - 'free_text' => $free_text, - )); - return $this->smarty->fetch($this->getTemplate('supply-order-footer')); - } + $this->smarty->assign(array( + 'shop_address' => $this->getShopAddress(), + 'shop_fax' => Configuration::get('PS_SHOP_FAX'), + 'shop_phone' => Configuration::get('PS_SHOP_PHONE'), + 'shop_details' => Configuration::get('PS_SHOP_DETAILS'), + 'free_text' => $free_text, + )); + return $this->smarty->fetch($this->getTemplate('supply-order-footer')); + } - /** - * Rounds values of a SupplyOrderDetail object - * - * @param array|PrestaShopCollection $collection - */ - protected function roundSupplyOrderDetails(&$collection) - { - foreach ($collection as $supply_order_detail) - { - /** @var SupplyOrderDetail $supply_order_detail */ - $supply_order_detail->unit_price_te = Tools::ps_round($supply_order_detail->unit_price_te, 2); - $supply_order_detail->price_te = Tools::ps_round($supply_order_detail->price_te, 2); - $supply_order_detail->discount_rate = Tools::ps_round($supply_order_detail->discount_rate, 2); - $supply_order_detail->price_with_discount_te = Tools::ps_round($supply_order_detail->price_with_discount_te, 2); - $supply_order_detail->tax_rate = Tools::ps_round($supply_order_detail->tax_rate, 2); - $supply_order_detail->price_ti = Tools::ps_round($supply_order_detail->price_ti, 2); - } - } + /** + * Rounds values of a SupplyOrderDetail object + * + * @param array|PrestaShopCollection $collection + */ + protected function roundSupplyOrderDetails(&$collection) + { + foreach ($collection as $supply_order_detail) { + /** @var SupplyOrderDetail $supply_order_detail */ + $supply_order_detail->unit_price_te = Tools::ps_round($supply_order_detail->unit_price_te, 2); + $supply_order_detail->price_te = Tools::ps_round($supply_order_detail->price_te, 2); + $supply_order_detail->discount_rate = Tools::ps_round($supply_order_detail->discount_rate, 2); + $supply_order_detail->price_with_discount_te = Tools::ps_round($supply_order_detail->price_with_discount_te, 2); + $supply_order_detail->tax_rate = Tools::ps_round($supply_order_detail->tax_rate, 2); + $supply_order_detail->price_ti = Tools::ps_round($supply_order_detail->price_ti, 2); + } + } - /** - * Rounds values of a SupplyOrder object - * - * @param SupplyOrder $supply_order - */ - protected function roundSupplyOrder(SupplyOrder &$supply_order) - { - $supply_order->total_te = Tools::ps_round($supply_order->total_te, 2); - $supply_order->discount_value_te = Tools::ps_round($supply_order->discount_value_te, 2); - $supply_order->total_with_discount_te = Tools::ps_round($supply_order->total_with_discount_te, 2); - $supply_order->total_tax = Tools::ps_round($supply_order->total_tax, 2); - $supply_order->total_ti = Tools::ps_round($supply_order->total_ti, 2); - } + /** + * Rounds values of a SupplyOrder object + * + * @param SupplyOrder $supply_order + */ + protected function roundSupplyOrder(SupplyOrder &$supply_order) + { + $supply_order->total_te = Tools::ps_round($supply_order->total_te, 2); + $supply_order->discount_value_te = Tools::ps_round($supply_order->discount_value_te, 2); + $supply_order->total_with_discount_te = Tools::ps_round($supply_order->total_with_discount_te, 2); + $supply_order->total_tax = Tools::ps_round($supply_order->total_tax, 2); + $supply_order->total_ti = Tools::ps_round($supply_order->total_ti, 2); + } } diff --git a/classes/pdf/PDF.php b/classes/pdf/PDF.php index c6bac40a..50764cbe 100644 --- a/classes/pdf/PDF.php +++ b/classes/pdf/PDF.php @@ -29,98 +29,106 @@ */ class PDFCore { - public $filename; - public $pdf_renderer; - public $objects; - public $template; + public $filename; + public $pdf_renderer; + public $objects; + public $template; + public $send_bulk_flag = false; - const TEMPLATE_INVOICE = 'Invoice'; - const TEMPLATE_ORDER_RETURN = 'OrderReturn'; - const TEMPLATE_ORDER_SLIP = 'OrderSlip'; - const TEMPLATE_DELIVERY_SLIP = 'DeliverySlip'; - const TEMPLATE_SUPPLY_ORDER_FORM = 'SupplyOrderForm'; + const TEMPLATE_INVOICE = 'Invoice'; + const TEMPLATE_ORDER_RETURN = 'OrderReturn'; + const TEMPLATE_ORDER_SLIP = 'OrderSlip'; + const TEMPLATE_DELIVERY_SLIP = 'DeliverySlip'; + const TEMPLATE_SUPPLY_ORDER_FORM = 'SupplyOrderForm'; - /** - * @param $objects - * @param $template - * @param $smarty - * @param string $orientation - */ - public function __construct($objects, $template, $smarty, $orientation = 'P') - { - $this->pdf_renderer = new PDFGenerator((bool)Configuration::get('PS_PDF_USE_CACHE'), $orientation); - $this->template = $template; - $this->smarty = $smarty; + /** + * @param $objects + * @param $template + * @param $smarty + * @param string $orientation + */ + public function __construct($objects, $template, $smarty, $orientation = 'P') + { + $this->pdf_renderer = new PDFGenerator((bool)Configuration::get('PS_PDF_USE_CACHE'), $orientation); + $this->template = $template; + $this->smarty = $smarty; - $this->objects = $objects; - if (!($objects instanceof Iterator) && !is_array($objects)) - $this->objects = array($objects); - } + $this->objects = $objects; + if (!($objects instanceof Iterator) && !is_array($objects)) { + $this->objects = array($objects); + } + + if (count($this->objects)>1) { // when bulk mode only + $this->send_bulk_flag = true; + } + } - /** - * Render PDF - * - * @param bool $display - * @return mixed - * @throws PrestaShopException - */ - public function render($display = true) - { - $render = false; - $this->pdf_renderer->setFontForLang(Context::getContext()->language->iso_code); - foreach ($this->objects as $object) - { - $template = $this->getTemplateObject($object); - if (!$template) - continue; + /** + * Render PDF + * + * @param bool $display + * @return mixed + * @throws PrestaShopException + */ + public function render($display = true) + { + $render = false; + $this->pdf_renderer->setFontForLang(Context::getContext()->language->iso_code); + foreach ($this->objects as $object) { + $template = $this->getTemplateObject($object); + if (!$template) { + continue; + } - if (empty($this->filename)) - { - $this->filename = $template->getFilename(); - if (count($this->objects) > 1) - $this->filename = $template->getBulkFilename(); - } + if (empty($this->filename)) { + $this->filename = $template->getFilename(); + if (count($this->objects) > 1) { + $this->filename = $template->getBulkFilename(); + } + } - $template->assignHookData($object); + $template->assignHookData($object); - $this->pdf_renderer->createHeader($template->getHeader()); - $this->pdf_renderer->createFooter($template->getFooter()); - $this->pdf_renderer->createContent($template->getContent()); - $this->pdf_renderer->writePage(); - $render = true; + $this->pdf_renderer->createHeader($template->getHeader()); + $this->pdf_renderer->createFooter($template->getFooter()); + $this->pdf_renderer->createContent($template->getContent()); + $this->pdf_renderer->writePage(); + $render = true; - unset($template); - } + unset($template); + } - if ($render) - { - // clean the output buffer - if (ob_get_level() && ob_get_length() > 0) - ob_clean(); - return $this->pdf_renderer->render($this->filename, $display); - } - } + if ($render) { + // clean the output buffer + if (ob_get_level() && ob_get_length() > 0) { + ob_clean(); + } + return $this->pdf_renderer->render($this->filename, $display); + } + } - /** - * Get correct PDF template classes - * - * @param mixed $object - * @return HTMLTemplate|false - * @throws PrestaShopException - */ - public function getTemplateObject($object) - { - $class = false; - $class_name = 'HTMLTemplate'.$this->template; + /** + * Get correct PDF template classes + * + * @param mixed $object + * @return HTMLTemplate|false + * @throws PrestaShopException + */ + public function getTemplateObject($object) + { + $class = false; + $class_name = 'HTMLTemplate'.$this->template; - if (class_exists($class_name)) - { - $class = new $class_name($object, $this->smarty); + if (class_exists($class_name)) { + // Some HTMLTemplateXYZ implementations won't use the third param but this is not a problem (no warning in PHP), + // the third param is then ignored if not added to the method signature. + $class = new $class_name($object, $this->smarty, $this->send_bulk_flag); - if (!($class instanceof HTMLTemplate)) - throw new PrestaShopException('Invalid class. It should be an instance of HTMLTemplate'); - } + if (!($class instanceof HTMLTemplate)) { + throw new PrestaShopException('Invalid class. It should be an instance of HTMLTemplate'); + } + } - return $class; - } -} \ No newline at end of file + return $class; + } +} diff --git a/classes/pdf/PDFGenerator.php b/classes/pdf/PDFGenerator.php index 2ab2b3d7..32f31744 100644 --- a/classes/pdf/PDFGenerator.php +++ b/classes/pdf/PDFGenerator.php @@ -32,212 +32,222 @@ require_once(_PS_TOOL_DIR_.'tcpdf/tcpdf.php'); */ class PDFGeneratorCore extends TCPDF { - const DEFAULT_FONT = 'helvetica'; + const DEFAULT_FONT = 'helvetica'; - public $header; - public $footer; - public $content; - public $font; + public $header; + public $footer; + public $content; + public $font; - public $font_by_lang = array( - 'ja' => 'cid0jp', - 'bg' => 'freeserif', - 'ru' => 'freeserif', - 'uk' => 'freeserif', - 'mk' => 'freeserif', - 'el' => 'freeserif', - 'vn' => 'dejavusans', - 'pl' => 'dejavusans', - 'ar' => 'dejavusans', - 'fa' => 'dejavusans', - 'ur' => 'dejavusans', - 'az' => 'dejavusans', - 'ca' => 'dejavusans', - 'gl' => 'dejavusans', - 'hr' => 'dejavusans', - 'sr' => 'dejavusans', - 'si' => 'dejavusans', - 'cs' => 'dejavusans', - 'sk' => 'dejavusans', - 'ka' => 'dejavusans', - 'he' => 'dejavusans', - 'lo' => 'dejavusans', - 'lt' => 'dejavusans', - 'lv' => 'dejavusans', - 'tr' => 'dejavusans', - 'ko' => 'cid0kr', - 'zh' => 'cid0cs', - 'tw' => 'cid0cs', - 'th' => 'freeserif' - ); + public $font_by_lang = array( + 'ja' => 'cid0jp', + 'bg' => 'freeserif', + 'ru' => 'freeserif', + 'uk' => 'freeserif', + 'mk' => 'freeserif', + 'el' => 'freeserif', + 'en' => 'dejavusans', + 'vn' => 'dejavusans', + 'pl' => 'dejavusans', + 'ar' => 'dejavusans', + 'fa' => 'dejavusans', + 'ur' => 'dejavusans', + 'az' => 'dejavusans', + 'ca' => 'dejavusans', + 'gl' => 'dejavusans', + 'hr' => 'dejavusans', + 'sr' => 'dejavusans', + 'si' => 'dejavusans', + 'cs' => 'dejavusans', + 'sk' => 'dejavusans', + 'ka' => 'dejavusans', + 'he' => 'dejavusans', + 'lo' => 'dejavusans', + 'lt' => 'dejavusans', + 'lv' => 'dejavusans', + 'tr' => 'dejavusans', + 'ko' => 'cid0kr', + 'zh' => 'cid0cs', + 'tw' => 'cid0cs', + 'th' => 'freeserif' + ); - /** - * @param bool $use_cache - * @param string $orientation - */ - public function __construct($use_cache = false, $orientation = 'P') - { - parent::__construct($orientation, 'mm', 'A4', true, 'UTF-8', $use_cache, false); - $this->setRTL(Context::getContext()->language->is_rtl); - } + /** + * @param bool $use_cache + * @param string $orientation + */ + public function __construct($use_cache = false, $orientation = 'P') + { + parent::__construct($orientation, 'mm', 'A4', true, 'UTF-8', $use_cache, false); + $this->setRTL(Context::getContext()->language->is_rtl); + } - /** - * set the PDF encoding - * - * @param string $encoding - */ - public function setEncoding($encoding) - { - $this->encoding = $encoding; - } + /** + * set the PDF encoding + * + * @param string $encoding + */ + public function setEncoding($encoding) + { + $this->encoding = $encoding; + } - /** - * - * set the PDF header - * - * @param string $header HTML - */ - public function createHeader($header) - { - $this->header = $header; - } + /** + * + * set the PDF header + * + * @param string $header HTML + */ + public function createHeader($header) + { + $this->header = $header; + } - /** - * - * set the PDF footer - * - * @param string $footer HTML - */ - public function createFooter($footer) - { - $this->footer = $footer; - } + /** + * + * set the PDF footer + * + * @param string $footer HTML + */ + public function createFooter($footer) + { + $this->footer = $footer; + } - /** - * - * create the PDF content - * - * @param string $content HTML - */ - public function createContent($content) - { - $this->content = $content; - } + /** + * + * create the PDF content + * + * @param string $content HTML + */ + public function createContent($content) + { + $this->content = $content; + } - /** - * Change the font - * - * @param string $iso_lang - */ - public function setFontForLang($iso_lang) - { - $this->font = PDFGenerator::DEFAULT_FONT; - if (array_key_exists($iso_lang, $this->font_by_lang)) - $this->font = $this->font_by_lang[$iso_lang]; + /** + * Change the font + * + * @param string $iso_lang + */ + public function setFontForLang($iso_lang) + { + $this->font = PDFGenerator::DEFAULT_FONT; + if (array_key_exists($iso_lang, $this->font_by_lang)) { + $this->font = $this->font_by_lang[$iso_lang]; + } - $this->setHeaderFont(array($this->font, '', PDF_FONT_SIZE_MAIN)); - $this->setFooterFont(array($this->font, '', PDF_FONT_SIZE_MAIN)); + $this->setHeaderFont(array($this->font, '', PDF_FONT_SIZE_MAIN)); + $this->setFooterFont(array($this->font, '', PDF_FONT_SIZE_MAIN)); - $this->setFont($this->font); - } + $this->setFont($this->font); + } - /** - * @see TCPDF::Header() - */ - public function Header() - { - $this->writeHTML($this->header); - } + /** + * @see TCPDF::Header() + */ + public function Header() + { + $this->writeHTML($this->header); + } - /** - * @see TCPDF::Footer() - */ - public function Footer() - { - $this->writeHTML($this->footer); - } + /** + * @see TCPDF::Footer() + */ + public function Footer() + { + $this->writeHTML($this->footer); + } - /** - * Render HTML template - * @param string $filename - * @param bool $display true:display to user, false:save, 'I','D','S' as fpdf display - * @throws PrestaShopException - * - * @return string HTML rendered - */ - public function render($filename, $display = true) - { - if (empty($filename)) - throw new PrestaShopException('Missing filename.'); + /** + * Render HTML template + * @param string $filename + * @param bool $display true:display to user, false:save, 'I','D','S' as fpdf display + * @throws PrestaShopException + * + * @return string HTML rendered + */ + public function render($filename, $display = true) + { + if (empty($filename)) { + throw new PrestaShopException('Missing filename.'); + } - $this->lastPage(); + $this->lastPage(); - if ($display === true) - $output = 'D'; - elseif ($display === false) - $output = 'S'; - elseif ($display == 'D') - $output = 'D'; - elseif ($display == 'S') - $output = 'S'; - elseif ($display == 'F') - $output = 'F'; - else - $output = 'I'; + if ($display === true) { + $output = 'D'; + } elseif ($display === false) { + $output = 'S'; + } elseif ($display == 'D') { + $output = 'D'; + } elseif ($display == 'S') { + $output = 'S'; + } elseif ($display == 'F') { + $output = 'F'; + } else { + $output = 'I'; + } - return $this->output($filename, $output); - } + return $this->output($filename, $output); + } - /** - * Write a PDF page - */ - public function writePage() - { - $this->SetHeaderMargin(5); - $this->SetFooterMargin(18); - $this->setMargins(10, 40, 10); - $this->AddPage(); - $this->writeHTML($this->content, true, false, true, false, ''); - } + /** + * Write a PDF page + */ + public function writePage() + { + $this->SetHeaderMargin(5); + $this->SetFooterMargin(18); + $this->setMargins(10, 40, 10); + $this->AddPage(); + $this->writeHTML($this->content, true, false, true, false, ''); + } - /** - * Override of TCPDF::getRandomSeed() - getmypid() is blocked on several hosting - */ - protected function getRandomSeed($seed = '') - { - $seed .= microtime(); + /** + * Override of TCPDF::getRandomSeed() - getmypid() is blocked on several hosting + */ + protected function getRandomSeed($seed = '') + { + $seed .= microtime(); - if (function_exists('openssl_random_pseudo_bytes') && (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) - { - // this is not used on windows systems because it is very slow for a know bug - $seed .= openssl_random_pseudo_bytes(512); - } - else - for ($i = 0; $i < 23; ++$i) - $seed .= uniqid('', true); + if (function_exists('openssl_random_pseudo_bytes') && (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { + // this is not used on windows systems because it is very slow for a know bug + $seed .= openssl_random_pseudo_bytes(512); + } else { + for ($i = 0; $i < 23; ++$i) { + $seed .= uniqid('', true); + } + } - $seed .= uniqid('', true); - $seed .= rand(); - $seed .= __FILE__; - $seed .= $this->bufferlen; + $seed .= uniqid('', true); + $seed .= rand(); + $seed .= __FILE__; + $seed .= $this->bufferlen; - if (isset($_SERVER['REMOTE_ADDR'])) - $seed .= $_SERVER['REMOTE_ADDR']; - if (isset($_SERVER['HTTP_USER_AGENT'])) - $seed .= $_SERVER['HTTP_USER_AGENT']; - if (isset($_SERVER['HTTP_ACCEPT'])) - $seed .= $_SERVER['HTTP_ACCEPT']; - if (isset($_SERVER['HTTP_ACCEPT_ENCODING'])) - $seed .= $_SERVER['HTTP_ACCEPT_ENCODING']; - if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) - $seed .= $_SERVER['HTTP_ACCEPT_LANGUAGE']; - if (isset($_SERVER['HTTP_ACCEPT_CHARSET'])) - $seed .= $_SERVER['HTTP_ACCEPT_CHARSET']; + if (isset($_SERVER['REMOTE_ADDR'])) { + $seed .= $_SERVER['REMOTE_ADDR']; + } + if (isset($_SERVER['HTTP_USER_AGENT'])) { + $seed .= $_SERVER['HTTP_USER_AGENT']; + } + if (isset($_SERVER['HTTP_ACCEPT'])) { + $seed .= $_SERVER['HTTP_ACCEPT']; + } + if (isset($_SERVER['HTTP_ACCEPT_ENCODING'])) { + $seed .= $_SERVER['HTTP_ACCEPT_ENCODING']; + } + if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { + $seed .= $_SERVER['HTTP_ACCEPT_LANGUAGE']; + } + if (isset($_SERVER['HTTP_ACCEPT_CHARSET'])) { + $seed .= $_SERVER['HTTP_ACCEPT_CHARSET']; + } - $seed .= rand(); - $seed .= uniqid('', true); - $seed .= microtime(); + $seed .= rand(); + $seed .= uniqid('', true); + $seed .= microtime(); - return $seed; - } + return $seed; + } } diff --git a/classes/pdf/index.php b/classes/pdf/index.php index c642967a..91fa49fb 100644 --- a/classes/pdf/index.php +++ b/classes/pdf/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/classes/range/RangePrice.php b/classes/range/RangePrice.php index a1411c74..ce169cae 100644 --- a/classes/range/RangePrice.php +++ b/classes/range/RangePrice.php @@ -26,85 +26,87 @@ class RangePriceCore extends ObjectModel { - public $id_carrier; - public $delimiter1; - public $delimiter2; + public $id_carrier; + public $delimiter1; + public $delimiter2; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'range_price', - 'primary' => 'id_range_price', - 'fields' => array( - 'id_carrier' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), - 'delimiter1' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => true), - 'delimiter2' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'range_price', + 'primary' => 'id_range_price', + 'fields' => array( + 'id_carrier' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), + 'delimiter1' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => true), + 'delimiter2' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => true), + ), + ); - protected $webserviceParameters = array( - 'objectsNodeName' => 'price_ranges', - 'objectNodeName' => 'price_range', - 'fields' => array( - 'id_carrier' => array('xlink_resource' => 'carriers'), - ) - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'price_ranges', + 'objectNodeName' => 'price_range', + 'fields' => array( + 'id_carrier' => array('xlink_resource' => 'carriers'), + ) + ); - /** - * Override add to create delivery value for all zones - * @see classes/ObjectModelCore::add() - * - * @param bool $null_values - * @param bool $autodate - * @return bool Insertion result - */ - public function add($autodate = true, $null_values = false) - { - if (!parent::add($autodate, $null_values) || !Validate::isLoadedObject($this)) - return false; + /** + * Override add to create delivery value for all zones + * @see classes/ObjectModelCore::add() + * + * @param bool $null_values + * @param bool $autodate + * @return bool Insertion result + */ + public function add($autodate = true, $null_values = false) + { + if (!parent::add($autodate, $null_values) || !Validate::isLoadedObject($this)) { + return false; + } - $carrier = new Carrier((int)$this->id_carrier); - $price_list = array(); - foreach ($carrier->getZones() as $zone) - $price_list[] = array( - 'id_range_price' => (int)$this->id, - 'id_range_weight' => 0, - 'id_carrier' => (int)$this->id_carrier, - 'id_zone' => (int)$zone['id_zone'], - 'price' => 0, - ); - $carrier->addDeliveryPrice($price_list); + $carrier = new Carrier((int)$this->id_carrier); + $price_list = array(); + foreach ($carrier->getZones() as $zone) { + $price_list[] = array( + 'id_range_price' => (int)$this->id, + 'id_range_weight' => 0, + 'id_carrier' => (int)$this->id_carrier, + 'id_zone' => (int)$zone['id_zone'], + 'price' => 0, + ); + } + $carrier->addDeliveryPrice($price_list); - return true; - } + return true; + } - /** - * Get all available price ranges - * - * @return array Ranges - */ - public static function getRanges($id_carrier) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' - SELECT * - FROM `'._DB_PREFIX_.'range_price` + /** + * Get all available price ranges + * + * @return array Ranges + */ + public static function getRanges($id_carrier) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + SELECT * + FROM `'._DB_PREFIX_.'range_price` WHERE `id_carrier` = '.(int)$id_carrier.' ORDER BY `delimiter1` ASC'); - } + } - public static function rangeExist($id_carrier, $delimiter1, $delimiter2) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function rangeExist($id_carrier, $delimiter1, $delimiter2) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT count(*) FROM `'._DB_PREFIX_.'range_price` WHERE `id_carrier` = '.(int)$id_carrier.' AND `delimiter1` = '.(float)$delimiter1.' AND `delimiter2`='.(float)$delimiter2); - } + } - public static function isOverlapping($id_carrier, $delimiter1, $delimiter2, $id_rang = null) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function isOverlapping($id_carrier, $delimiter1, $delimiter2, $id_rang = null) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT count(*) FROM `'._DB_PREFIX_.'range_price` WHERE `id_carrier` = '.(int)$id_carrier.' @@ -114,5 +116,5 @@ class RangePriceCore extends ObjectModel OR ('.(float)$delimiter2.' < `delimiter1` AND '.(float)$delimiter2.' > `delimiter2`) ) '.(!is_null($id_rang) ? ' AND `id_range_price` != '.(int)$id_rang : '')); - } -} \ No newline at end of file + } +} diff --git a/classes/range/RangeWeight.php b/classes/range/RangeWeight.php index 9cc32c74..a25c3678 100644 --- a/classes/range/RangeWeight.php +++ b/classes/range/RangeWeight.php @@ -26,85 +26,87 @@ class RangeWeightCore extends ObjectModel { - public $id_carrier; - public $delimiter1; - public $delimiter2; + public $id_carrier; + public $delimiter1; + public $delimiter2; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'range_weight', - 'primary' => 'id_range_weight', - 'fields' => array( - 'id_carrier' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), - 'delimiter1' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => true), - 'delimiter2' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'range_weight', + 'primary' => 'id_range_weight', + 'fields' => array( + 'id_carrier' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), + 'delimiter1' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => true), + 'delimiter2' => array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat', 'required' => true), + ), + ); - protected $webserviceParameters = array( - 'objectNodeName' => 'weight_range', - 'objectsNodeName' => 'weight_ranges', - 'fields' => array( - 'id_carrier' => array('xlink_resource' => 'carriers'), - ) - ); + protected $webserviceParameters = array( + 'objectNodeName' => 'weight_range', + 'objectsNodeName' => 'weight_ranges', + 'fields' => array( + 'id_carrier' => array('xlink_resource' => 'carriers'), + ) + ); - /** - * Override add to create delivery value for all zones - * @see classes/ObjectModelCore::add() - * - * @param bool $null_values - * @param bool $autodate - * @return bool Insertion result - */ - public function add($autodate = true, $null_values = false) - { - if (!parent::add($autodate, $null_values) || !Validate::isLoadedObject($this)) - return false; + /** + * Override add to create delivery value for all zones + * @see classes/ObjectModelCore::add() + * + * @param bool $null_values + * @param bool $autodate + * @return bool Insertion result + */ + public function add($autodate = true, $null_values = false) + { + if (!parent::add($autodate, $null_values) || !Validate::isLoadedObject($this)) { + return false; + } - $carrier = new Carrier((int)$this->id_carrier); - $price_list = array(); - foreach ($carrier->getZones() as $zone) - $price_list[] = array( - 'id_range_price' => 0, - 'id_range_weight' => (int)$this->id, - 'id_carrier' => (int)$this->id_carrier, - 'id_zone' => (int)$zone['id_zone'], - 'price' => 0, - ); - $carrier->addDeliveryPrice($price_list); + $carrier = new Carrier((int)$this->id_carrier); + $price_list = array(); + foreach ($carrier->getZones() as $zone) { + $price_list[] = array( + 'id_range_price' => 0, + 'id_range_weight' => (int)$this->id, + 'id_carrier' => (int)$this->id_carrier, + 'id_zone' => (int)$zone['id_zone'], + 'price' => 0, + ); + } + $carrier->addDeliveryPrice($price_list); - return true; - } + return true; + } - /** - * Get all available price ranges - * - * @return array Ranges - */ - public static function getRanges($id_carrier) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' - SELECT * - FROM `'._DB_PREFIX_.'range_weight` + /** + * Get all available price ranges + * + * @return array Ranges + */ + public static function getRanges($id_carrier) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + SELECT * + FROM `'._DB_PREFIX_.'range_weight` WHERE `id_carrier` = '.(int)$id_carrier.' ORDER BY `delimiter1` ASC'); - } + } - public static function rangeExist($id_carrier, $delimiter1, $delimiter2) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function rangeExist($id_carrier, $delimiter1, $delimiter2) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT count(*) FROM `'._DB_PREFIX_.'range_weight` WHERE `id_carrier` = '.(int)$id_carrier.' AND `delimiter1` = '.(float)$delimiter1.' AND `delimiter2`='.(float)$delimiter2); - } + } - public static function isOverlapping($id_carrier, $delimiter1, $delimiter2, $id_rang = null) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function isOverlapping($id_carrier, $delimiter1, $delimiter2, $id_rang = null) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT count(*) FROM `'._DB_PREFIX_.'range_weight` WHERE `id_carrier` = '.(int)$id_carrier.' @@ -114,5 +116,5 @@ class RangeWeightCore extends ObjectModel OR ('.(float)$delimiter2.' < `delimiter1` AND '.(float)$delimiter2.' > `delimiter2`) ) '.(!is_null($id_rang) ? ' AND `id_range_weight` != '.(int)$id_rang : '')); - } + } } diff --git a/classes/range/index.php b/classes/range/index.php index c642967a..91fa49fb 100644 --- a/classes/range/index.php +++ b/classes/range/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/classes/shop/Shop.php b/classes/shop/Shop.php index 98237514..6fef4384 100644 --- a/classes/shop/Shop.php +++ b/classes/shop/Shop.php @@ -29,300 +29,301 @@ */ class ShopCore extends ObjectModel { - /** @var int ID of shop group */ - public $id_shop_group; + /** @var int ID of shop group */ + public $id_shop_group; - /** @var int ID of shop category */ - public $id_category; + /** @var int ID of shop category */ + public $id_category; - /** @var int ID of shop theme */ - public $id_theme; + /** @var int ID of shop theme */ + public $id_theme; - /** @var string Shop name */ - public $name; + /** @var string Shop name */ + public $name; - public $active = true; - public $deleted; + public $active = true; + public $deleted; - /** @var string Shop theme name (read only) */ - public $theme_name; + /** @var string Shop theme name (read only) */ + public $theme_name; - /** @var string Shop theme directory (read only) */ - public $theme_directory; + /** @var string Shop theme directory (read only) */ + public $theme_directory; - /** @var string Physical uri of main url (read only) */ - public $physical_uri; + /** @var string Physical uri of main url (read only) */ + public $physical_uri; - /** @var string Virtual uri of main url (read only) */ - public $virtual_uri; + /** @var string Virtual uri of main url (read only) */ + public $virtual_uri; - /** @var string Domain of main url (read only) */ - public $domain; + /** @var string Domain of main url (read only) */ + public $domain; - /** @var string Domain SSL of main url (read only) */ - public $domain_ssl; + /** @var string Domain SSL of main url (read only) */ + public $domain_ssl; - /** @var ShopGroup Shop group object */ - protected $group; + /** @var ShopGroup Shop group object */ + protected $group; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'shop', - 'primary' => 'id_shop', - 'fields' => array( - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), - 'id_theme' => array('type' => self::TYPE_INT, 'required' => true), - 'id_category' => array('type' => self::TYPE_INT, 'required' => true), - 'id_shop_group' => array('type' => self::TYPE_INT, 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'shop', + 'primary' => 'id_shop', + 'fields' => array( + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), + 'id_theme' => array('type' => self::TYPE_INT, 'required' => true), + 'id_category' => array('type' => self::TYPE_INT, 'required' => true), + 'id_shop_group' => array('type' => self::TYPE_INT, 'required' => true), + ), + ); - /** @var array List of shops cached */ - protected static $shops; + /** @var array List of shops cached */ + protected static $shops; - protected static $asso_tables = array(); - protected static $id_shop_default_tables = array(); - protected static $initialized = false; + protected static $asso_tables = array(); + protected static $id_shop_default_tables = array(); + protected static $initialized = false; - protected $webserviceParameters = array( - 'fields' => array( - 'id_shop_group' => array('xlink_resource' => 'shop_groups'), - 'id_category' => array(), - 'id_theme' => array(), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_shop_group' => array('xlink_resource' => 'shop_groups'), + 'id_category' => array(), + 'id_theme' => array(), + ), + ); - /** @var int Store the current context of shop (CONTEXT_ALL, CONTEXT_GROUP, CONTEXT_SHOP) */ - protected static $context; + /** @var int Store the current context of shop (CONTEXT_ALL, CONTEXT_GROUP, CONTEXT_SHOP) */ + protected static $context; - /** @var int ID shop in the current context (will be empty if context is not CONTEXT_SHOP) */ - protected static $context_id_shop; + /** @var int ID shop in the current context (will be empty if context is not CONTEXT_SHOP) */ + protected static $context_id_shop; - /** @var int ID shop group in the current context (will be empty if context is CONTEXT_ALL) */ - protected static $context_id_shop_group; + /** @var int ID shop group in the current context (will be empty if context is CONTEXT_ALL) */ + protected static $context_id_shop_group; - /** - * There are 3 kinds of shop context : shop, group shop and general - */ - const CONTEXT_SHOP = 1; - const CONTEXT_GROUP = 2; - const CONTEXT_ALL = 4; + /** + * There are 3 kinds of shop context : shop, group shop and general + */ + const CONTEXT_SHOP = 1; + const CONTEXT_GROUP = 2; + const CONTEXT_ALL = 4; - /** - * Some data can be shared between shops, like customers or orders - */ - const SHARE_CUSTOMER = 'share_customer'; - const SHARE_ORDER = 'share_order'; - const SHARE_STOCK = 'share_stock'; + /** + * Some data can be shared between shops, like customers or orders + */ + const SHARE_CUSTOMER = 'share_customer'; + const SHARE_ORDER = 'share_order'; + const SHARE_STOCK = 'share_stock'; - /** - * On shop instance, get its theme and URL data too - * - * @param int $id - * @param int $id_lang - * @param int $id_shop - */ - public function __construct($id = null, $id_lang = null, $id_shop = null) - { - parent::__construct($id, $id_lang, $id_shop); - if ($this->id) - $this->setUrl(); - } + /** + * On shop instance, get its theme and URL data too + * + * @param int $id + * @param int $id_lang + * @param int $id_shop + */ + public function __construct($id = null, $id_lang = null, $id_shop = null) + { + parent::__construct($id, $id_lang, $id_shop); + if ($this->id) { + $this->setUrl(); + } + } - /** - * Initialize an array with all the multistore associations in the database - */ - protected static function init() - { - Shop::$id_shop_default_tables = array('product', 'category'); + /** + * Initialize an array with all the multistore associations in the database + */ + protected static function init() + { + Shop::$id_shop_default_tables = array('product', 'category'); - $asso_tables = array( - 'carrier' => array('type' => 'shop'), - 'carrier_lang' => array('type' => 'fk_shop'), - 'category' => array('type' => 'shop'), - 'category_lang' => array('type' => 'fk_shop'), - 'cms' => array('type' => 'shop'), - 'cms_lang' => array('type' => 'fk_shop'), - 'cms_category' => array('type' => 'shop'), - 'cms_category_lang' => array('type' => 'fk_shop'), - 'contact' => array('type' => 'shop'), - 'country' => array('type' => 'shop'), - 'currency' => array('type' => 'shop'), - 'employee' => array('type' => 'shop'), - 'hook_module' => array('type' => 'fk_shop'), - 'hook_module_exceptions' => array('type' => 'fk_shop', 'primary' => 'id_hook_module_exceptions'), - 'image' => array('type' => 'shop'), - 'lang' => array('type' => 'shop'), - 'meta_lang' => array('type' => 'fk_shop'), - 'module' => array('type' => 'shop'), - 'module_currency' => array('type' => 'fk_shop'), - 'module_country' => array('type' => 'fk_shop'), - 'module_group' => array('type' => 'fk_shop'), - 'product' => array('type' => 'shop'), - 'product_attribute' => array('type' => 'shop'), - 'product_lang' => array('type' => 'fk_shop'), - 'referrer' => array('type' => 'shop'), - 'scene' => array('type' => 'shop'), - 'store' => array('type' => 'shop'), - 'webservice_account' => array('type' => 'shop'), - 'warehouse' => array('type' => 'shop'), - 'stock_available' => array('type' => 'fk_shop', 'primary' => 'id_stock_available'), - 'carrier_tax_rules_group_shop' => array('type' => 'fk_shop'), - 'attribute' => array('type' => 'shop'), - 'feature' => array('type' => 'shop'), - 'group' => array('type' => 'shop'), - 'attribute_group' => array('type' => 'shop'), - 'tax_rules_group' => array('type' => 'shop'), - 'zone' => array('type' => 'shop'), - 'manufacturer' => array('type' => 'shop'), - 'supplier' => array('type' => 'shop'), - ); + $asso_tables = array( + 'carrier' => array('type' => 'shop'), + 'carrier_lang' => array('type' => 'fk_shop'), + 'category' => array('type' => 'shop'), + 'category_lang' => array('type' => 'fk_shop'), + 'cms' => array('type' => 'shop'), + 'cms_lang' => array('type' => 'fk_shop'), + 'cms_category' => array('type' => 'shop'), + 'cms_category_lang' => array('type' => 'fk_shop'), + 'contact' => array('type' => 'shop'), + 'country' => array('type' => 'shop'), + 'currency' => array('type' => 'shop'), + 'employee' => array('type' => 'shop'), + 'hook_module' => array('type' => 'fk_shop'), + 'hook_module_exceptions' => array('type' => 'fk_shop', 'primary' => 'id_hook_module_exceptions'), + 'image' => array('type' => 'shop'), + 'lang' => array('type' => 'shop'), + 'meta_lang' => array('type' => 'fk_shop'), + 'module' => array('type' => 'shop'), + 'module_currency' => array('type' => 'fk_shop'), + 'module_country' => array('type' => 'fk_shop'), + 'module_group' => array('type' => 'fk_shop'), + 'product' => array('type' => 'shop'), + 'product_attribute' => array('type' => 'shop'), + 'product_lang' => array('type' => 'fk_shop'), + 'referrer' => array('type' => 'shop'), + 'scene' => array('type' => 'shop'), + 'store' => array('type' => 'shop'), + 'webservice_account' => array('type' => 'shop'), + 'warehouse' => array('type' => 'shop'), + 'stock_available' => array('type' => 'fk_shop', 'primary' => 'id_stock_available'), + 'carrier_tax_rules_group_shop' => array('type' => 'fk_shop'), + 'attribute' => array('type' => 'shop'), + 'feature' => array('type' => 'shop'), + 'group' => array('type' => 'shop'), + 'attribute_group' => array('type' => 'shop'), + 'tax_rules_group' => array('type' => 'shop'), + 'zone' => array('type' => 'shop'), + 'manufacturer' => array('type' => 'shop'), + 'supplier' => array('type' => 'shop'), + ); - foreach ($asso_tables as $table_name => $table_details) - Shop::addTableAssociation($table_name, $table_details); + foreach ($asso_tables as $table_name => $table_details) { + Shop::addTableAssociation($table_name, $table_details); + } - Shop::$initialized = true; - } + Shop::$initialized = true; + } - public function setUrl() - { - $cache_id = 'Shop::setUrl_'.(int)$this->id; - if (!Cache::isStored($cache_id)) - { - $row = Db::getInstance()->getRow(' + public function setUrl() + { + $cache_id = 'Shop::setUrl_'.(int)$this->id; + if (!Cache::isStored($cache_id)) { + $row = Db::getInstance()->getRow(' SELECT su.physical_uri, su.virtual_uri, su.domain, su.domain_ssl, t.id_theme, t.name, t.directory FROM '._DB_PREFIX_.'shop s LEFT JOIN '._DB_PREFIX_.'shop_url su ON (s.id_shop = su.id_shop) LEFT JOIN '._DB_PREFIX_.'theme t ON (t.id_theme = s.id_theme) WHERE s.id_shop = '.(int)$this->id.' AND s.active = 1 AND s.deleted = 0 AND su.main = 1'); - Cache::store($cache_id, $row); - } - else - $row = Cache::retrieve($cache_id); - if (!$row) - return false; + Cache::store($cache_id, $row); + } else { + $row = Cache::retrieve($cache_id); + } + if (!$row) { + return false; + } - $this->theme_id = $row['id_theme']; - $this->theme_name = $row['name']; - $this->theme_directory = $row['directory']; - $this->physical_uri = $row['physical_uri']; - $this->virtual_uri = $row['virtual_uri']; - $this->domain = $row['domain']; - $this->domain_ssl = $row['domain_ssl']; + $this->theme_id = $row['id_theme']; + $this->theme_name = $row['name']; + $this->theme_directory = $row['directory']; + $this->physical_uri = $row['physical_uri']; + $this->virtual_uri = $row['virtual_uri']; + $this->domain = $row['domain']; + $this->domain_ssl = $row['domain_ssl']; - return true; - } + return true; + } - /** - * Add a shop, and clear the cache - * - * @param bool $autodate - * @param bool $null_values - * @return bool - */ - public function add($autodate = true, $null_values = false) - { - $res = parent::add($autodate, $null_values); - Shop::cacheShops(true); - return $res; - } + /** + * Add a shop, and clear the cache + * + * @param bool $autodate + * @param bool $null_values + * @return bool + */ + public function add($autodate = true, $null_values = false) + { + $res = parent::add($autodate, $null_values); + Shop::cacheShops(true); + return $res; + } - public function associateSuperAdmins() - { - $super_admins = Employee::getEmployeesByProfile(_PS_ADMIN_PROFILE_); - foreach ($super_admins as $super_admin) - { - $employee = new Employee((int)$super_admin['id_employee']); - $employee->associateTo((int)$this->id); - } - } + public function associateSuperAdmins() + { + $super_admins = Employee::getEmployeesByProfile(_PS_ADMIN_PROFILE_); + foreach ($super_admins as $super_admin) { + $employee = new Employee((int)$super_admin['id_employee']); + $employee->associateTo((int)$this->id); + } + } - /** - * Remove a shop only if it has no dependencies, and remove its associations - * - * @return bool - */ - public function delete() - { - if (Shop::hasDependency($this->id) || !$res = parent::delete()) - return false; + /** + * Remove a shop only if it has no dependencies, and remove its associations + * + * @return bool + */ + public function delete() + { + if (Shop::hasDependency($this->id) || !$res = parent::delete()) { + return false; + } - foreach (Shop::getAssoTables() as $table_name => $row) - { - $id = 'id_'.$row['type']; - if ($row['type'] == 'fk_shop') - $id = 'id_shop'; - else - $table_name .= '_'.$row['type']; - $res &= Db::getInstance()->execute(' + foreach (Shop::getAssoTables() as $table_name => $row) { + $id = 'id_'.$row['type']; + if ($row['type'] == 'fk_shop') { + $id = 'id_shop'; + } else { + $table_name .= '_'.$row['type']; + } + $res &= Db::getInstance()->execute(' DELETE FROM `'.bqSQL(_DB_PREFIX_.$table_name).'` WHERE `'.bqSQL($id).'`='.(int)$this->id - ); - } + ); + } - // removes stock available - $res &= Db::getInstance()->delete('stock_available', 'id_shop = '.(int)$this->id); + // removes stock available + $res &= Db::getInstance()->delete('stock_available', 'id_shop = '.(int)$this->id); - // Remove urls - $res &= Db::getInstance()->delete('shop_url', 'id_shop = '.(int)$this->id); + // Remove urls + $res &= Db::getInstance()->delete('shop_url', 'id_shop = '.(int)$this->id); - Shop::cacheShops(true); + Shop::cacheShops(true); - return $res; - } + return $res; + } - /** - * Detect dependency with customer or orders - * - * @param int $id_shop - * @return bool - */ - public static function hasDependency($id_shop) - { - $has_dependency = false; - $nbr_customer = (int)Db::getInstance()->getValue(' + /** + * Detect dependency with customer or orders + * + * @param int $id_shop + * @return bool + */ + public static function hasDependency($id_shop) + { + $has_dependency = false; + $nbr_customer = (int)Db::getInstance()->getValue(' SELECT count(*) FROM `'._DB_PREFIX_.'customer` WHERE `id_shop`='.(int)$id_shop - ); - if ($nbr_customer) - $has_dependency = true; - else - { - $nbr_order = (int)Db::getInstance()->getValue(' + ); + if ($nbr_customer) { + $has_dependency = true; + } else { + $nbr_order = (int)Db::getInstance()->getValue(' SELECT count(*) FROM `'._DB_PREFIX_.'orders` WHERE `id_shop`='.(int)$id_shop - ); - if ($nbr_order) - $has_dependency = true; - } + ); + if ($nbr_order) { + $has_dependency = true; + } + } - return $has_dependency; - } + return $has_dependency; + } - /** - * Find the shop from current domain / uri and get an instance of this shop - * if INSTALL_VERSION is defined, will return an empty shop object - * - * @return Shop - */ - public static function initialize() - { - // Find current shop from URL - if (!($id_shop = Tools::getValue('id_shop')) || defined('_PS_ADMIN_DIR_')) - { - $found_uri = ''; - $is_main_uri = false; - $host = Tools::getHttpHost(); - $request_uri = rawurldecode($_SERVER['REQUEST_URI']); + /** + * Find the shop from current domain / uri and get an instance of this shop + * if INSTALL_VERSION is defined, will return an empty shop object + * + * @return Shop + */ + public static function initialize() + { + // Find current shop from URL + if (!($id_shop = Tools::getValue('id_shop')) || defined('_PS_ADMIN_DIR_')) { + $found_uri = ''; + $is_main_uri = false; + $host = Tools::getHttpHost(); + $request_uri = rawurldecode($_SERVER['REQUEST_URI']); - $sql = 'SELECT s.id_shop, CONCAT(su.physical_uri, su.virtual_uri) AS uri, su.domain, su.main + $sql = 'SELECT s.id_shop, CONCAT(su.physical_uri, su.virtual_uri) AS uri, su.domain, su.main FROM '._DB_PREFIX_.'shop_url su LEFT JOIN '._DB_PREFIX_.'shop s ON (s.id_shop = su.id_shop) WHERE (su.domain = \''.pSQL($host).'\' OR su.domain_ssl = \''.pSQL($host).'\') @@ -330,316 +331,324 @@ class ShopCore extends ObjectModel AND s.deleted = 0 ORDER BY LENGTH(CONCAT(su.physical_uri, su.virtual_uri)) DESC'; - $result = Db::getInstance()->executeS($sql); + $result = Db::getInstance()->executeS($sql); - $through = false; - foreach ($result as $row) - // An URL matching current shop was found - if (preg_match('#^'.preg_quote($row['uri'], '#').'#i', $request_uri)) - { - $through = true; - $id_shop = $row['id_shop']; - $found_uri = $row['uri']; - if ($row['main']) - $is_main_uri = true; - break; - } + $through = false; + foreach ($result as $row) { + // An URL matching current shop was found + if (preg_match('#^'.preg_quote($row['uri'], '#').'#i', $request_uri)) { + $through = true; + $id_shop = $row['id_shop']; + $found_uri = $row['uri']; + if ($row['main']) { + $is_main_uri = true; + } + break; + } + } - // If an URL was found but is not the main URL, redirect to main URL - if ($through && $id_shop && !$is_main_uri) - foreach ($result as $row) - if ($row['id_shop'] == $id_shop && $row['main']) - { - $request_uri = substr($request_uri, strlen($found_uri)); - $url = str_replace('//', '/', $row['domain'].$row['uri'].$request_uri); - $redirect_type = Configuration::get('PS_CANONICAL_REDIRECT'); - $redirect_code = ($redirect_type == 1 ? '302' : '301'); - $redirect_header = ($redirect_type == 1 ? 'Found' : 'Moved Permanently'); - header('HTTP/1.0 '.$redirect_code.' '.$redirect_header); - header('Cache-Control: no-cache'); - header('Location: http://'.$url); - exit; - } - } + // If an URL was found but is not the main URL, redirect to main URL + if ($through && $id_shop && !$is_main_uri) { + foreach ($result as $row) { + if ($row['id_shop'] == $id_shop && $row['main']) { + $request_uri = substr($request_uri, strlen($found_uri)); + $url = str_replace('//', '/', $row['domain'].$row['uri'].$request_uri); + $redirect_type = Configuration::get('PS_CANONICAL_REDIRECT'); + $redirect_code = ($redirect_type == 1 ? '302' : '301'); + $redirect_header = ($redirect_type == 1 ? 'Found' : 'Moved Permanently'); + header('HTTP/1.0 '.$redirect_code.' '.$redirect_header); + header('Cache-Control: no-cache'); + header('Location: http://'.$url); + exit; + } + } + } + } - $http_host = Tools::getHttpHost(); - $all_media = array_merge(Configuration::getMultiShopValues('PS_MEDIA_SERVER_1'), Configuration::getMultiShopValues('PS_MEDIA_SERVER_2'), Configuration::getMultiShopValues('PS_MEDIA_SERVER_3')); + $http_host = Tools::getHttpHost(); + $all_media = array_merge(Configuration::getMultiShopValues('PS_MEDIA_SERVER_1'), Configuration::getMultiShopValues('PS_MEDIA_SERVER_2'), Configuration::getMultiShopValues('PS_MEDIA_SERVER_3')); - if ((!$id_shop && defined('_PS_ADMIN_DIR_')) || Tools::isPHPCLI() || in_array($http_host, $all_media)) - { - // If in admin, we can access to the shop without right URL - if ((!$id_shop && Tools::isPHPCLI()) || defined('_PS_ADMIN_DIR_')) - $id_shop = (int)Configuration::get('PS_SHOP_DEFAULT'); + if ((!$id_shop && defined('_PS_ADMIN_DIR_')) || Tools::isPHPCLI() || in_array($http_host, $all_media)) { + // If in admin, we can access to the shop without right URL + if ((!$id_shop && Tools::isPHPCLI()) || defined('_PS_ADMIN_DIR_')) { + $id_shop = (int)Configuration::get('PS_SHOP_DEFAULT'); + } - $shop = new Shop((int)$id_shop); - if (!Validate::isLoadedObject($shop)) - $shop = new Shop((int)Configuration::get('PS_SHOP_DEFAULT')); + $shop = new Shop((int)$id_shop); + if (!Validate::isLoadedObject($shop)) { + $shop = new Shop((int)Configuration::get('PS_SHOP_DEFAULT')); + } - $shop->virtual_uri = ''; + $shop->virtual_uri = ''; - // Define some $_SERVER variables like HTTP_HOST if PHP is launched with php-cli - if (Tools::isPHPCLI()) - { - if (!isset($_SERVER['HTTP_HOST']) || empty($_SERVER['HTTP_HOST'])) - $_SERVER['HTTP_HOST'] = $shop->domain; - if (!isset($_SERVER['SERVER_NAME']) || empty($_SERVER['SERVER_NAME'])) - $_SERVER['SERVER_NAME'] = $shop->domain; - if (!isset($_SERVER['REMOTE_ADDR']) || empty($_SERVER['REMOTE_ADDR'])) - $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; - } - } - else - { - $shop = new Shop($id_shop); - if (!Validate::isLoadedObject($shop) || !$shop->active) - { - // No shop found ... too bad, let's redirect to default shop - $default_shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); + // Define some $_SERVER variables like HTTP_HOST if PHP is launched with php-cli + if (Tools::isPHPCLI()) { + if (!isset($_SERVER['HTTP_HOST']) || empty($_SERVER['HTTP_HOST'])) { + $_SERVER['HTTP_HOST'] = $shop->domain; + } + if (!isset($_SERVER['SERVER_NAME']) || empty($_SERVER['SERVER_NAME'])) { + $_SERVER['SERVER_NAME'] = $shop->domain; + } + if (!isset($_SERVER['REMOTE_ADDR']) || empty($_SERVER['REMOTE_ADDR'])) { + $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; + } + } + } else { + $shop = new Shop($id_shop); + if (!Validate::isLoadedObject($shop) || !$shop->active) { + // No shop found ... too bad, let's redirect to default shop + $default_shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); - // Hmm there is something really bad in your Prestashop ! - if (!Validate::isLoadedObject($default_shop)) - throw new PrestaShopException('Shop not found'); + // Hmm there is something really bad in your Prestashop ! + if (!Validate::isLoadedObject($default_shop)) { + throw new PrestaShopException('Shop not found'); + } - $params = $_GET; - unset($params['id_shop']); - $url = $default_shop->domain; - if (!Configuration::get('PS_REWRITING_SETTINGS')) - $url .= $default_shop->getBaseURI().'index.php?'.http_build_query($params); - else - { - // Catch url with subdomain "www" - if (strpos($url, 'www.') === 0 && 'www.'.$_SERVER['HTTP_HOST'] === $url || $_SERVER['HTTP_HOST'] === 'www.'.$url) - $url .= $_SERVER['REQUEST_URI']; - else - $url .= $default_shop->getBaseURI(); + $params = $_GET; + unset($params['id_shop']); + $url = $default_shop->domain; + if (!Configuration::get('PS_REWRITING_SETTINGS')) { + $url .= $default_shop->getBaseURI().'index.php?'.http_build_query($params); + } else { + // Catch url with subdomain "www" + if (strpos($url, 'www.') === 0 && 'www.'.$_SERVER['HTTP_HOST'] === $url || $_SERVER['HTTP_HOST'] === 'www.'.$url) { + $url .= $_SERVER['REQUEST_URI']; + } else { + $url .= $default_shop->getBaseURI(); + } - if (count($params)) - $url .= '?'.http_build_query($params); - } + if (count($params)) { + $url .= '?'.http_build_query($params); + } + } - $redirect_type = Configuration::get('PS_CANONICAL_REDIRECT'); - $redirect_code = ($redirect_type == 1 ? '302' : '301'); - $redirect_header = ($redirect_type == 1 ? 'Found' : 'Moved Permanently'); - header('HTTP/1.0 '.$redirect_code.' '.$redirect_header); - header('Location: http://'.$url); - exit; + $redirect_type = Configuration::get('PS_CANONICAL_REDIRECT'); + $redirect_code = ($redirect_type == 1 ? '302' : '301'); + $redirect_header = ($redirect_type == 1 ? 'Found' : 'Moved Permanently'); + header('HTTP/1.0 '.$redirect_code.' '.$redirect_header); + header('Location: http://'.$url); + exit; + } elseif (defined('_PS_ADMIN_DIR_') && empty($shop->physical_uri)) { + $shop_default = new Shop((int)Configuration::get('PS_SHOP_DEFAULT')); + $shop->physical_uri = $shop_default->physical_uri; + $shop->virtual_uri = $shop_default->virtual_uri; + } + } - } - elseif (defined('_PS_ADMIN_DIR_') && empty($shop->physical_uri)) - { - $shop_default = new Shop((int)Configuration::get('PS_SHOP_DEFAULT')); - $shop->physical_uri = $shop_default->physical_uri; - $shop->virtual_uri = $shop_default->virtual_uri; - } - } + self::$context_id_shop = $shop->id; + self::$context_id_shop_group = $shop->id_shop_group; + self::$context = self::CONTEXT_SHOP; - self::$context_id_shop = $shop->id; - self::$context_id_shop_group = $shop->id_shop_group; - self::$context = self::CONTEXT_SHOP; + return $shop; + } - return $shop; - } + /** + * @return Address the current shop address + */ + public function getAddress() + { + if (!isset($this->address)) { + $address = new Address(); + $address->company = Configuration::get('PS_SHOP_NAME'); + $address->id_country = Configuration::get('PS_SHOP_COUNTRY_ID') ? Configuration::get('PS_SHOP_COUNTRY_ID') : Configuration::get('PS_COUNTRY_DEFAULT'); + $address->id_state = Configuration::get('PS_SHOP_STATE_ID'); + $address->address1 = Configuration::get('PS_SHOP_ADDR1'); + $address->address2 = Configuration::get('PS_SHOP_ADDR2'); + $address->postcode = Configuration::get('PS_SHOP_CODE'); + $address->city = Configuration::get('PS_SHOP_CITY'); - /** - * @return Address the current shop address - */ - public function getAddress() - { - if (!isset($this->address)) - { - $address = new Address(); - $address->company = Configuration::get('PS_SHOP_NAME'); - $address->id_country = Configuration::get('PS_SHOP_COUNTRY_ID') ? Configuration::get('PS_SHOP_COUNTRY_ID') : Configuration::get('PS_COUNTRY_DEFAULT'); - $address->id_state = Configuration::get('PS_SHOP_STATE_ID'); - $address->address1 = Configuration::get('PS_SHOP_ADDR1'); - $address->address2 = Configuration::get('PS_SHOP_ADDR2'); - $address->postcode = Configuration::get('PS_SHOP_CODE'); - $address->city = Configuration::get('PS_SHOP_CITY'); + $this->address = $address; + } - $this->address = $address; - } + return $this->address; + } - return $this->address; - } + /** + * Get shop theme name + * + * @return string + */ + public function getTheme() + { + return $this->theme_directory; + } - /** - * Get shop theme name - * - * @return string - */ - public function getTheme() - { - return $this->theme_directory; - } + /** + * Get shop URI + * + * @return string + */ + public function getBaseURI() + { + return $this->physical_uri.$this->virtual_uri; + } - /** - * Get shop URI - * - * @return string - */ - public function getBaseURI() - { - return $this->physical_uri.$this->virtual_uri; - } + /** + * Get shop URL + * + * @param string $auto_secure_mode if set to true, secure mode will be checked + * @param string $add_base_uri if set to true, shop base uri will be added + * @return string complete base url of current shop + */ + public function getBaseURL($auto_secure_mode = false, $add_base_uri = true) + { + if (($auto_secure_mode && Tools::usingSecureMode() && !$this->domain_ssl) || !$this->domain) { + return false; + } - /** - * Get shop URL - * - * @param string $auto_secure_mode if set to true, secure mode will be checked - * @param string $add_base_uri if set to true, shop base uri will be added - * @return string complete base url of current shop - */ - public function getBaseURL($auto_secure_mode = false, $add_base_uri = true) - { - if (($auto_secure_mode && Tools::usingSecureMode() && !$this->domain_ssl) || !$this->domain) - return false; + $url = array(); + $url['protocol'] = $auto_secure_mode && Tools::usingSecureMode() ? 'https://' : 'http://'; + $url['domain'] = $auto_secure_mode && Tools::usingSecureMode() ? $this->domain_ssl : $this->domain; - $url = array(); - $url['protocol'] = $auto_secure_mode && Tools::usingSecureMode() ? 'https://' : 'http://'; - $url['domain'] = $auto_secure_mode && Tools::usingSecureMode() ? $this->domain_ssl : $this->domain; + if ($add_base_uri) { + $url['base_uri'] = $this->getBaseURI(); + } - if ($add_base_uri) - $url['base_uri'] = $this->getBaseURI(); + return implode('', $url); + } - return implode('', $url); - } + /** + * Get group of current shop + * + * @return ShopGroup + */ + public function getGroup() + { + if (!$this->group) { + $this->group = new ShopGroup($this->id_shop_group); + } + return $this->group; + } - /** - * Get group of current shop - * - * @return ShopGroup - */ - public function getGroup() - { - if (!$this->group) - $this->group = new ShopGroup($this->id_shop_group); - return $this->group; - } + /** + * Get root category of current shop + * + * @return int + */ + public function getCategory() + { + return (int)($this->id_category ? $this->id_category : Configuration::get('PS_ROOT_CATEGORY')); + } - /** - * Get root category of current shop - * - * @return int - */ - public function getCategory() - { - return (int)($this->id_category ? $this->id_category : Configuration::get('PS_ROOT_CATEGORY')); - } - - /** - * Get list of shop's urls - * - * @return array - */ - public function getUrls() - { - $sql = 'SELECT * + /** + * Get list of shop's urls + * + * @return array + */ + public function getUrls() + { + $sql = 'SELECT * FROM '._DB_PREFIX_.'shop_url WHERE active = 1 AND id_shop = '.(int)$this->id; - return Db::getInstance()->executeS($sql); - } + return Db::getInstance()->executeS($sql); + } - /** - * Check if current shop ID is the same as default shop in configuration - * - * @return bool - */ - public function isDefaultShop() - { - return $this->id == Configuration::get('PS_SHOP_DEFAULT'); - } + /** + * Check if current shop ID is the same as default shop in configuration + * + * @return bool + */ + public function isDefaultShop() + { + return $this->id == Configuration::get('PS_SHOP_DEFAULT'); + } - /** - * Get the associated table if available - * - * @return array - */ - public static function getAssoTable($table) - { - if (!Shop::$initialized) - Shop::init(); - return (isset(Shop::$asso_tables[$table]) ? Shop::$asso_tables[$table] : false); - } + /** + * Get the associated table if available + * + * @return array + */ + public static function getAssoTable($table) + { + if (!Shop::$initialized) { + Shop::init(); + } + return (isset(Shop::$asso_tables[$table]) ? Shop::$asso_tables[$table] : false); + } - /** - * check if the table has an id_shop_default - * - * @return bool - */ - public static function checkIdShopDefault($table) - { - if (!Shop::$initialized) - Shop::init(); - return in_array($table, self::$id_shop_default_tables); - } + /** + * check if the table has an id_shop_default + * + * @return bool + */ + public static function checkIdShopDefault($table) + { + if (!Shop::$initialized) { + Shop::init(); + } + return in_array($table, self::$id_shop_default_tables); + } - /** - * Get list of associated tables to shop - * - * @return array - */ - public static function getAssoTables() - { - if (!Shop::$initialized) - Shop::init(); - return Shop::$asso_tables; - } + /** + * Get list of associated tables to shop + * + * @return array + */ + public static function getAssoTables() + { + if (!Shop::$initialized) { + Shop::init(); + } + return Shop::$asso_tables; + } - /** - * Add table associated to shop - * - * @param string $table_name - * @param array $table_details - * @return bool - */ - public static function addTableAssociation($table_name, $table_details) - { - if (!isset(Shop::$asso_tables[$table_name])) - Shop::$asso_tables[$table_name] = $table_details; - else - return false; - return true; - } + /** + * Add table associated to shop + * + * @param string $table_name + * @param array $table_details + * @return bool + */ + public static function addTableAssociation($table_name, $table_details) + { + if (!isset(Shop::$asso_tables[$table_name])) { + Shop::$asso_tables[$table_name] = $table_details; + } else { + return false; + } + return true; + } - /** - * Check if given table is associated to shop - * - * @param string $table - * @return bool - */ - public static function isTableAssociated($table) - { - if (!Shop::$initialized) - Shop::init(); - return isset(Shop::$asso_tables[$table]) && Shop::$asso_tables[$table]['type'] == 'shop'; - } + /** + * Check if given table is associated to shop + * + * @param string $table + * @return bool + */ + public static function isTableAssociated($table) + { + if (!Shop::$initialized) { + Shop::init(); + } + return isset(Shop::$asso_tables[$table]) && Shop::$asso_tables[$table]['type'] == 'shop'; + } - /** - * Load list of groups and shops, and cache it - * - * @param bool $refresh - */ - public static function cacheShops($refresh = false) - { - if (!is_null(self::$shops) && !$refresh) - return; + /** + * Load list of groups and shops, and cache it + * + * @param bool $refresh + */ + public static function cacheShops($refresh = false) + { + if (!is_null(self::$shops) && !$refresh) { + return; + } - self::$shops = array(); + self::$shops = array(); - $from = ''; - $where = ''; + $from = ''; + $where = ''; - $employee = Context::getContext()->employee; + $employee = Context::getContext()->employee; - // If the profile isn't a superAdmin - if (Validate::isLoadedObject($employee) && $employee->id_profile != _PS_ADMIN_PROFILE_) - { - $from .= 'LEFT JOIN '._DB_PREFIX_.'employee_shop es ON es.id_shop = s.id_shop'; - $where .= 'AND es.id_employee = '.(int)$employee->id; - } + // If the profile isn't a superAdmin + if (Validate::isLoadedObject($employee) && $employee->id_profile != _PS_ADMIN_PROFILE_) { + $from .= 'LEFT JOIN '._DB_PREFIX_.'employee_shop es ON es.id_shop = s.id_shop'; + $where .= 'AND es.id_employee = '.(int)$employee->id; + } - $sql = 'SELECT gs.*, s.*, gs.name AS group_name, s.name AS shop_name, s.active, su.domain, su.domain_ssl, su.physical_uri, su.virtual_uri + $sql = 'SELECT gs.*, s.*, gs.name AS group_name, s.name AS shop_name, s.active, su.domain, su.domain_ssl, su.physical_uri, su.virtual_uri FROM '._DB_PREFIX_.'shop_group gs LEFT JOIN '._DB_PREFIX_.'shop s ON s.id_shop_group = gs.id_shop_group @@ -651,547 +660,576 @@ class ShopCore extends ObjectModel '.$where.' ORDER BY gs.name, s.name'; - if ($results = Db::getInstance()->executeS($sql)) - { - foreach ($results as $row) - { - if (!isset(self::$shops[$row['id_shop_group']])) - self::$shops[$row['id_shop_group']] = array( - 'id' => $row['id_shop_group'], - 'name' => $row['group_name'], - 'share_customer' => $row['share_customer'], - 'share_order' => $row['share_order'], - 'share_stock' => $row['share_stock'], - 'shops' => array(), - ); + if ($results = Db::getInstance()->executeS($sql)) { + foreach ($results as $row) { + if (!isset(self::$shops[$row['id_shop_group']])) { + self::$shops[$row['id_shop_group']] = array( + 'id' => $row['id_shop_group'], + 'name' => $row['group_name'], + 'share_customer' => $row['share_customer'], + 'share_order' => $row['share_order'], + 'share_stock' => $row['share_stock'], + 'shops' => array(), + ); + } - self::$shops[$row['id_shop_group']]['shops'][$row['id_shop']] = array( - 'id_shop' => $row['id_shop'], - 'id_shop_group' => $row['id_shop_group'], - 'name' => $row['shop_name'], - 'id_theme' => $row['id_theme'], - 'id_category' => $row['id_category'], - 'domain' => $row['domain'], - 'domain_ssl' => $row['domain_ssl'], - 'uri' => $row['physical_uri'].$row['virtual_uri'], - 'active' => $row['active'], - ); - } - } - } + self::$shops[$row['id_shop_group']]['shops'][$row['id_shop']] = array( + 'id_shop' => $row['id_shop'], + 'id_shop_group' => $row['id_shop_group'], + 'name' => $row['shop_name'], + 'id_theme' => $row['id_theme'], + 'id_category' => $row['id_category'], + 'domain' => $row['domain'], + 'domain_ssl' => $row['domain_ssl'], + 'uri' => $row['physical_uri'].$row['virtual_uri'], + 'active' => $row['active'], + ); + } + } + } - public static function getCompleteListOfShopsID() - { - $cache_id = 'Shop::getCompleteListOfShopsID'; - if (!Cache::isStored($cache_id)) - { - $list = array(); - $sql = 'SELECT id_shop FROM '._DB_PREFIX_.'shop'; - foreach (Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql) as $row) - $list[] = $row['id_shop']; + public static function getCompleteListOfShopsID() + { + $cache_id = 'Shop::getCompleteListOfShopsID'; + if (!Cache::isStored($cache_id)) { + $list = array(); + $sql = 'SELECT id_shop FROM '._DB_PREFIX_.'shop'; + foreach (Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql) as $row) { + $list[] = $row['id_shop']; + } - Cache::store($cache_id, $list); - return $list; - } - return Cache::retrieve($cache_id); - } + Cache::store($cache_id, $list); + return $list; + } + return Cache::retrieve($cache_id); + } - /** - * Get shops list - * - * @param bool $active - * @param int $id_shop_group - * @param bool $get_as_list_id - * @return array - */ - public static function getShops($active = true, $id_shop_group = null, $get_as_list_id = false) - { - Shop::cacheShops(); + /** + * Get shops list + * + * @param bool $active + * @param int $id_shop_group + * @param bool $get_as_list_id + * @return array + */ + public static function getShops($active = true, $id_shop_group = null, $get_as_list_id = false) + { + Shop::cacheShops(); - $results = array(); - foreach (self::$shops as $group_id => $group_data) - foreach ($group_data['shops'] as $id => $shop_data) - if ((!$active || $shop_data['active']) && (!$id_shop_group || $id_shop_group == $group_id)) - { - if ($get_as_list_id) - $results[$id] = $id; - else - $results[$id] = $shop_data; - } + $results = array(); + foreach (self::$shops as $group_id => $group_data) { + foreach ($group_data['shops'] as $id => $shop_data) { + if ((!$active || $shop_data['active']) && (!$id_shop_group || $id_shop_group == $group_id)) { + if ($get_as_list_id) { + $results[$id] = $id; + } else { + $results[$id] = $shop_data; + } + } + } + } - return $results; - } + return $results; + } - public function getUrlsSharedCart() - { - if (!$this->getGroup()->share_order) - return false; + public function getUrlsSharedCart() + { + if (!$this->getGroup()->share_order) { + return false; + } - $query = new DbQuery(); - $query->select('domain'); - $query->from('shop_url'); - $query->where('main = 1'); - $query->where('active = 1'); - $query .= $this->addSqlRestriction(Shop::SHARE_ORDER); - $domains = array(); - foreach (Db::getInstance()->executeS($query) as $row) - $domains[] = $row['domain']; + $query = new DbQuery(); + $query->select('domain'); + $query->from('shop_url'); + $query->where('main = 1'); + $query->where('active = 1'); + $query .= $this->addSqlRestriction(Shop::SHARE_ORDER); + $domains = array(); + foreach (Db::getInstance()->executeS($query) as $row) { + $domains[] = $row['domain']; + } - return $domains; - } + return $domains; + } - /** - * Get a collection of shops - * - * @param bool $active - * @param int $id_shop_group - * @return PrestaShopCollection Collection of Shop - */ - public static function getShopsCollection($active = true, $id_shop_group = null) - { - $shops = new PrestaShopCollection('Shop'); - if ($active) - $shops->where('active', '=', 1); + /** + * Get a collection of shops + * + * @param bool $active + * @param int $id_shop_group + * @return PrestaShopCollection Collection of Shop + */ + public static function getShopsCollection($active = true, $id_shop_group = null) + { + $shops = new PrestaShopCollection('Shop'); + if ($active) { + $shops->where('active', '=', 1); + } - if ($id_shop_group) - $shops->where('id_shop_group', '=', (int)$id_shop_group); + if ($id_shop_group) { + $shops->where('id_shop_group', '=', (int)$id_shop_group); + } - return $shops; - } + return $shops; + } - /** - * Return some informations cached for one shop - * - * @param int $shop_id - * @return array - */ - public static function getShop($shop_id) - { - Shop::cacheShops(); - foreach (self::$shops as $group_id => $group_data) - if (array_key_exists($shop_id, $group_data['shops'])) - return $group_data['shops'][$shop_id]; - return false; - } + /** + * Return some informations cached for one shop + * + * @param int $shop_id + * @return array + */ + public static function getShop($shop_id) + { + Shop::cacheShops(); + foreach (self::$shops as $group_id => $group_data) { + if (array_key_exists($shop_id, $group_data['shops'])) { + return $group_data['shops'][$shop_id]; + } + } + return false; + } - /** - * Return a shop ID from shop name - * - * @param string $name - * @return int - */ - public static function getIdByName($name) - { - Shop::cacheShops(); - foreach (self::$shops as $group_data) - foreach ($group_data['shops'] as $shop_id => $shop_data) - if (Tools::strtolower($shop_data['name']) == Tools::strtolower($name)) - return $shop_id; - return false; - } + /** + * Return a shop ID from shop name + * + * @param string $name + * @return int + */ + public static function getIdByName($name) + { + Shop::cacheShops(); + foreach (self::$shops as $group_data) { + foreach ($group_data['shops'] as $shop_id => $shop_data) { + if (Tools::strtolower($shop_data['name']) == Tools::strtolower($name)) { + return $shop_id; + } + } + } + return false; + } - /** - * @param bool $active - * @param int $id_shop_group - * @return int Total of shops - */ - public static function getTotalShops($active = true, $id_shop_group = null) - { - return count(Shop::getShops($active, $id_shop_group)); - } + /** + * @param bool $active + * @param int $id_shop_group + * @return int Total of shops + */ + public static function getTotalShops($active = true, $id_shop_group = null) + { + return count(Shop::getShops($active, $id_shop_group)); + } - /** - * Retrieve group ID of a shop - * - * @param int $shop_id Shop ID - * @return int Group ID - */ - public static function getGroupFromShop($shop_id, $as_id = true) - { - Shop::cacheShops(); - foreach (self::$shops as $group_id => $group_data) - if (array_key_exists($shop_id, $group_data['shops'])) - return ($as_id) ? $group_id : $group_data; - return false; - } + /** + * Retrieve group ID of a shop + * + * @param int $shop_id Shop ID + * @return int Group ID + */ + public static function getGroupFromShop($shop_id, $as_id = true) + { + Shop::cacheShops(); + foreach (self::$shops as $group_id => $group_data) { + if (array_key_exists($shop_id, $group_data['shops'])) { + return ($as_id) ? $group_id : $group_data; + } + } + return false; + } - /** - * If the shop group has the option $type activated, get all shops ID of this group, else get current shop ID - * - * @param int $shop_id - * @param int $type Shop::SHARE_CUSTOMER | Shop::SHARE_ORDER - * @return array - */ - public static function getSharedShops($shop_id, $type) - { - if (!in_array($type, array(Shop::SHARE_CUSTOMER, Shop::SHARE_ORDER, SHOP::SHARE_STOCK))) - die('Wrong argument ($type) in Shop::getSharedShops() method'); + /** + * If the shop group has the option $type activated, get all shops ID of this group, else get current shop ID + * + * @param int $shop_id + * @param int $type Shop::SHARE_CUSTOMER | Shop::SHARE_ORDER + * @return array + */ + public static function getSharedShops($shop_id, $type) + { + if (!in_array($type, array(Shop::SHARE_CUSTOMER, Shop::SHARE_ORDER, SHOP::SHARE_STOCK))) { + die('Wrong argument ($type) in Shop::getSharedShops() method'); + } - Shop::cacheShops(); - foreach (self::$shops as $group_data) - if (array_key_exists($shop_id, $group_data['shops']) && $group_data[$type]) - return array_keys($group_data['shops']); - return array($shop_id); - } + Shop::cacheShops(); + foreach (self::$shops as $group_data) { + if (array_key_exists($shop_id, $group_data['shops']) && $group_data[$type]) { + return array_keys($group_data['shops']); + } + } + return array($shop_id); + } - /** - * Get a list of ID concerned by the shop context (E.g. if context is shop group, get list of children shop ID) - * - * @param string $share If false, dont check share datas from group. Else can take a Shop::SHARE_* constant value - * @return array - */ - public static function getContextListShopID($share = false) - { - if (Shop::getContext() == Shop::CONTEXT_SHOP) - $list = ($share) ? Shop::getSharedShops(Shop::getContextShopID(), $share) : array(Shop::getContextShopID()); - elseif (Shop::getContext() == Shop::CONTEXT_GROUP) - $list = Shop::getShops(true, Shop::getContextShopGroupID(), true); - else - $list = Shop::getShops(true, null, true); + /** + * Get a list of ID concerned by the shop context (E.g. if context is shop group, get list of children shop ID) + * + * @param string $share If false, dont check share datas from group. Else can take a Shop::SHARE_* constant value + * @return array + */ + public static function getContextListShopID($share = false) + { + if (Shop::getContext() == Shop::CONTEXT_SHOP) { + $list = ($share) ? Shop::getSharedShops(Shop::getContextShopID(), $share) : array(Shop::getContextShopID()); + } elseif (Shop::getContext() == Shop::CONTEXT_GROUP) { + $list = Shop::getShops(true, Shop::getContextShopGroupID(), true); + } else { + $list = Shop::getShops(true, null, true); + } - return $list; - } + return $list; + } - /** - * Return the list of shop by id - * - * @param int $id - * @param string $identifier - * @param string $table - * @return array - */ - public static function getShopById($id, $identifier, $table) - { - return Db::getInstance()->executeS(' + /** + * Return the list of shop by id + * + * @param int $id + * @param string $identifier + * @param string $table + * @return array + */ + public static function getShopById($id, $identifier, $table) + { + return Db::getInstance()->executeS(' SELECT `id_shop`, `'.bqSQL($identifier).'` FROM `'._DB_PREFIX_.bqSQL($table).'_shop` WHERE `'.bqSQL($identifier).'` = '.(int)$id - ); - } + ); + } - /** - * Change the current shop context - * - * @param int $type Shop::CONTEXT_ALL | Shop::CONTEXT_GROUP | Shop::CONTEXT_SHOP - * @param int $id ID shop if CONTEXT_SHOP or id shop group if CONTEXT_GROUP - */ - public static function setContext($type, $id = null) - { - switch ($type) - { - case self::CONTEXT_ALL : - self::$context_id_shop = null; - self::$context_id_shop_group = null; - break; + /** + * Change the current shop context + * + * @param int $type Shop::CONTEXT_ALL | Shop::CONTEXT_GROUP | Shop::CONTEXT_SHOP + * @param int $id ID shop if CONTEXT_SHOP or id shop group if CONTEXT_GROUP + */ + public static function setContext($type, $id = null) + { + switch ($type) { + case self::CONTEXT_ALL : + self::$context_id_shop = null; + self::$context_id_shop_group = null; + break; - case self::CONTEXT_GROUP : - self::$context_id_shop = null; - self::$context_id_shop_group = (int)$id; - break; + case self::CONTEXT_GROUP : + self::$context_id_shop = null; + self::$context_id_shop_group = (int)$id; + break; - case self::CONTEXT_SHOP : - self::$context_id_shop = (int)$id; - self::$context_id_shop_group = Shop::getGroupFromShop($id); - break; + case self::CONTEXT_SHOP : + self::$context_id_shop = (int)$id; + self::$context_id_shop_group = Shop::getGroupFromShop($id); + break; - default : - throw new PrestaShopException('Unknown context for shop'); - } + default : + throw new PrestaShopException('Unknown context for shop'); + } - self::$context = $type; - } + self::$context = $type; + } - /** - * Get current context of shop - * - * @return int - */ - public static function getContext() - { - return self::$context; - } + /** + * Get current context of shop + * + * @return int + */ + public static function getContext() + { + return self::$context; + } - /** - * Get current ID of shop if context is CONTEXT_SHOP - * - * @return int - */ - public static function getContextShopID($null_value_without_multishop = false) - { - if ($null_value_without_multishop && !Shop::isFeatureActive()) - return null; - return self::$context_id_shop; - } + /** + * Get current ID of shop if context is CONTEXT_SHOP + * + * @return int + */ + public static function getContextShopID($null_value_without_multishop = false) + { + if ($null_value_without_multishop && !Shop::isFeatureActive()) { + return null; + } + return self::$context_id_shop; + } - /** - * Get current ID of shop group if context is CONTEXT_SHOP or CONTEXT_GROUP - * - * @return int - */ - public static function getContextShopGroupID($null_value_without_multishop = false) - { - if ($null_value_without_multishop && !Shop::isFeatureActive()) - return null; + /** + * Get current ID of shop group if context is CONTEXT_SHOP or CONTEXT_GROUP + * + * @return int + */ + public static function getContextShopGroupID($null_value_without_multishop = false) + { + if ($null_value_without_multishop && !Shop::isFeatureActive()) { + return null; + } - return self::$context_id_shop_group; - } + return self::$context_id_shop_group; + } - public static function getContextShopGroup() - { - static $context_shop_group = null; - if ($context_shop_group === null) - $context_shop_group = new ShopGroup((int)self::$context_id_shop_group); - return $context_shop_group; - } + public static function getContextShopGroup() + { + static $context_shop_group = null; + if ($context_shop_group === null) { + $context_shop_group = new ShopGroup((int)self::$context_id_shop_group); + } + return $context_shop_group; + } - /** - * Add an sql restriction for shops fields - * - * @param int $share If false, dont check share datas from group. Else can take a Shop::SHARE_* constant value - * @param string $alias - */ - public static function addSqlRestriction($share = false, $alias = null) - { - if ($alias) - $alias .= '.'; + /** + * Add an sql restriction for shops fields + * + * @param int $share If false, dont check share datas from group. Else can take a Shop::SHARE_* constant value + * @param string $alias + */ + public static function addSqlRestriction($share = false, $alias = null) + { + if ($alias) { + $alias .= '.'; + } - $group = Shop::getGroupFromShop(Shop::getContextShopID(), false); - if ($share == Shop::SHARE_CUSTOMER && Shop::getContext() == Shop::CONTEXT_SHOP && $group['share_customer']) - $restriction = ' AND '.$alias.'id_shop_group = '.(int)Shop::getContextShopGroupID().' '; - else - $restriction = ' AND '.$alias.'id_shop IN ('.implode(', ', Shop::getContextListShopID($share)).') '; + $group = Shop::getGroupFromShop(Shop::getContextShopID(), false); + if ($share == Shop::SHARE_CUSTOMER && Shop::getContext() == Shop::CONTEXT_SHOP && $group['share_customer']) { + $restriction = ' AND '.$alias.'id_shop_group = '.(int)Shop::getContextShopGroupID().' '; + } else { + $restriction = ' AND '.$alias.'id_shop IN ('.implode(', ', Shop::getContextListShopID($share)).') '; + } - return $restriction; - } + return $restriction; + } - /** - * Add an SQL JOIN in query between a table and its associated table in multishop - * - * @param string $table Table name (E.g. product, module, etc.) - * @param string $alias Alias of table - * @param bool $inner_join Use or not INNER JOIN - * @param string $on - * @return string - */ - public static function addSqlAssociation($table, $alias, $inner_join = true, $on = null, $force_not_default = false) - { - $table_alias = $table.'_shop'; - if (strpos($table, '.') !== false) - list($table_alias, $table) = explode('.', $table); + /** + * Add an SQL JOIN in query between a table and its associated table in multishop + * + * @param string $table Table name (E.g. product, module, etc.) + * @param string $alias Alias of table + * @param bool $inner_join Use or not INNER JOIN + * @param string $on + * @return string + */ + public static function addSqlAssociation($table, $alias, $inner_join = true, $on = null, $force_not_default = false) + { + $table_alias = $table.'_shop'; + if (strpos($table, '.') !== false) { + list($table_alias, $table) = explode('.', $table); + } - $asso_table = Shop::getAssoTable($table); - if ($asso_table === false || $asso_table['type'] != 'shop') - return; - $sql = (($inner_join) ? ' INNER' : ' LEFT').' JOIN '._DB_PREFIX_.$table.'_shop '.$table_alias.' + $asso_table = Shop::getAssoTable($table); + if ($asso_table === false || $asso_table['type'] != 'shop') { + return; + } + $sql = (($inner_join) ? ' INNER' : ' LEFT').' JOIN '._DB_PREFIX_.$table.'_shop '.$table_alias.' ON ('.$table_alias.'.id_'.$table.' = '.$alias.'.id_'.$table; - if ((int)self::$context_id_shop) - $sql .= ' AND '.$table_alias.'.id_shop = '.(int)self::$context_id_shop; - elseif (Shop::checkIdShopDefault($table) && !$force_not_default) - $sql .= ' AND '.$table_alias.'.id_shop = '.$alias.'.id_shop_default'; - else - $sql .= ' AND '.$table_alias.'.id_shop IN ('.implode(', ', Shop::getContextListShopID()).')'; - $sql .= (($on) ? ' AND '.$on : '').')'; - return $sql; - } + if ((int)self::$context_id_shop) { + $sql .= ' AND '.$table_alias.'.id_shop = '.(int)self::$context_id_shop; + } elseif (Shop::checkIdShopDefault($table) && !$force_not_default) { + $sql .= ' AND '.$table_alias.'.id_shop = '.$alias.'.id_shop_default'; + } else { + $sql .= ' AND '.$table_alias.'.id_shop IN ('.implode(', ', Shop::getContextListShopID()).')'; + } + $sql .= (($on) ? ' AND '.$on : '').')'; + return $sql; + } - /** - * Add a restriction on id_shop for multishop lang table - * - * @param string $alias - * @param Context $context - * @return string - */ - public static function addSqlRestrictionOnLang($alias = null, $id_shop = null) - { - if (isset(Context::getContext()->shop) && is_null($id_shop)) - $id_shop = (int)Context::getContext()->shop->id; - if (!$id_shop) - $id_shop = (int)Configuration::get('PS_SHOP_DEFAULT'); + /** + * Add a restriction on id_shop for multishop lang table + * + * @param string $alias + * @param Context $context + * @return string + */ + public static function addSqlRestrictionOnLang($alias = null, $id_shop = null) + { + if (isset(Context::getContext()->shop) && is_null($id_shop)) { + $id_shop = (int)Context::getContext()->shop->id; + } + if (!$id_shop) { + $id_shop = (int)Configuration::get('PS_SHOP_DEFAULT'); + } - return ' AND '.(($alias) ? $alias.'.' : '').'id_shop = '.$id_shop.' '; - } + return ' AND '.(($alias) ? $alias.'.' : '').'id_shop = '.$id_shop.' '; + } - /** - * Get all groups and associated shops as subarrays - * - * @return array - */ - public static function getTree() - { - Shop::cacheShops(); - return self::$shops; - } + /** + * Get all groups and associated shops as subarrays + * + * @return array + */ + public static function getTree() + { + Shop::cacheShops(); + return self::$shops; + } - /** - * @return bool Return true if multishop feature is active and at last 2 shops have been created - */ - public static function isFeatureActive() - { - static $feature_active = null; + /** + * @return bool Return true if multishop feature is active and at last 2 shops have been created + */ + public static function isFeatureActive() + { + static $feature_active = null; - if ($feature_active === null) - $feature_active = (bool)Db::getInstance()->getValue('SELECT value FROM `'._DB_PREFIX_.'configuration` WHERE `name` = "PS_MULTISHOP_FEATURE_ACTIVE"') - && (Db::getInstance()->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'shop') > 1); + if ($feature_active === null) { + $feature_active = (bool)Db::getInstance()->getValue('SELECT value FROM `'._DB_PREFIX_.'configuration` WHERE `name` = "PS_MULTISHOP_FEATURE_ACTIVE"') + && (Db::getInstance()->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'shop') > 1); + } - return $feature_active; - } + return $feature_active; + } - public function copyShopData($old_id, $tables_import = false, $deleted = false) - { - // If we duplicate some specific data, automatically duplicate other data linked to the first - // E.g. if carriers are duplicated for the shop, duplicate carriers langs too + public function copyShopData($old_id, $tables_import = false, $deleted = false) + { + // If we duplicate some specific data, automatically duplicate other data linked to the first + // E.g. if carriers are duplicated for the shop, duplicate carriers langs too - if (!$old_id) - $old_id = Configuration::get('PS_SHOP_DEFAULT'); + if (!$old_id) { + $old_id = Configuration::get('PS_SHOP_DEFAULT'); + } - if (isset($tables_import['carrier'])) - { - $tables_import['carrier_tax_rules_group_shop'] = true; - $tables_import['carrier_lang'] = true; - } + if (isset($tables_import['carrier'])) { + $tables_import['carrier_tax_rules_group_shop'] = true; + $tables_import['carrier_lang'] = true; + } - if (isset($tables_import['cms'])) - { - $tables_import['cms_lang'] = true; - $tables_import['cms_category'] = true; - $tables_import['cms_category_lang'] = true; - } + if (isset($tables_import['cms'])) { + $tables_import['cms_lang'] = true; + $tables_import['cms_category'] = true; + $tables_import['cms_category_lang'] = true; + } - $tables_import['category_lang'] = true; - if (isset($tables_import['product'])) - $tables_import['product_lang'] = true; + $tables_import['category_lang'] = true; + if (isset($tables_import['product'])) { + $tables_import['product_lang'] = true; + } - if (isset($tables_import['module'])) - { - $tables_import['module_currency'] = true; - $tables_import['module_country'] = true; - $tables_import['module_group'] = true; - } + if (isset($tables_import['module'])) { + $tables_import['module_currency'] = true; + $tables_import['module_country'] = true; + $tables_import['module_group'] = true; + } - if (isset($tables_import['hook_module'])) - $tables_import['hook_module_exceptions'] = true; + if (isset($tables_import['hook_module'])) { + $tables_import['hook_module_exceptions'] = true; + } - if (isset($tables_import['attribute_group'])) - $tables_import['attribute'] = true; + if (isset($tables_import['attribute_group'])) { + $tables_import['attribute'] = true; + } - // Browse and duplicate data - foreach (Shop::getAssoTables() as $table_name => $row) - { - if ($tables_import && !isset($tables_import[$table_name])) - continue; + // Browse and duplicate data + foreach (Shop::getAssoTables() as $table_name => $row) { + if ($tables_import && !isset($tables_import[$table_name])) { + continue; + } - // Special case for stock_available if current shop is in a share stock group - if ($table_name == 'stock_available') - { - $group = new ShopGroup($this->id_shop_group); - if ($group->share_stock && $group->haveShops()) - continue; - } + // Special case for stock_available if current shop is in a share stock group + if ($table_name == 'stock_available') { + $group = new ShopGroup($this->id_shop_group); + if ($group->share_stock && $group->haveShops()) { + continue; + } + } - $id = 'id_'.$row['type']; - if ($row['type'] == 'fk_shop') - $id = 'id_shop'; - else - $table_name .= '_'.$row['type']; + $id = 'id_'.$row['type']; + if ($row['type'] == 'fk_shop') { + $id = 'id_shop'; + } else { + $table_name .= '_'.$row['type']; + } - if (!$deleted) - { - $res = Db::getInstance()->getRow('SELECT * FROM `'._DB_PREFIX_.$table_name.'` WHERE `'.$id.'` = '.(int)$old_id); - if ($res) - { - unset($res[$id]); - if (isset($row['primary'])) - unset($res[$row['primary']]); + if (!$deleted) { + $res = Db::getInstance()->getRow('SELECT * FROM `'._DB_PREFIX_.$table_name.'` WHERE `'.$id.'` = '.(int)$old_id); + if ($res) { + unset($res[$id]); + if (isset($row['primary'])) { + unset($res[$row['primary']]); + } - $categories = Tools::getValue('categoryBox'); - if ($table_name == 'product_shop' && count($categories) == 1) - { - unset($res['id_category_default']); - $keys = implode('`, `', array_keys($res)); - $sql = 'INSERT IGNORE INTO `'._DB_PREFIX_.$table_name.'` (`'.$keys.'`, `id_category_default`, '.$id.') + $categories = Tools::getValue('categoryBox'); + if ($table_name == 'product_shop' && count($categories) == 1) { + unset($res['id_category_default']); + $keys = implode('`, `', array_keys($res)); + $sql = 'INSERT IGNORE INTO `'._DB_PREFIX_.$table_name.'` (`'.$keys.'`, `id_category_default`, '.$id.') (SELECT `'.$keys.'`, '.(int)$categories[0].', '.(int)$this->id.' FROM '._DB_PREFIX_.$table_name.' WHERE `'.$id.'` = '.(int)$old_id.')'; - } - else - { - $keys = implode('`, `', array_keys($res)); - $sql = 'INSERT IGNORE INTO `'._DB_PREFIX_.$table_name.'` (`'.$keys.'`, '.$id.') + } else { + $keys = implode('`, `', array_keys($res)); + $sql = 'INSERT IGNORE INTO `'._DB_PREFIX_.$table_name.'` (`'.$keys.'`, '.$id.') (SELECT `'.$keys.'`, '.(int)$this->id.' FROM '._DB_PREFIX_.$table_name.' WHERE `'.$id.'` = '.(int)$old_id.')'; - } - Db::getInstance()->execute($sql); - } - } - } + } + Db::getInstance()->execute($sql); + } + } + } - // Hook for duplication of shop data - $modules_list = Hook::getHookModuleExecList('actionShopDataDuplication'); - if (is_array($modules_list) && count($modules_list) > 0) - foreach ($modules_list as $m) - if (!$tables_import || isset($tables_import['Module'.ucfirst($m['module'])])) - Hook::exec('actionShopDataDuplication', array( - 'old_id_shop' => (int)$old_id, - 'new_id_shop' => (int)$this->id, - ), $m['id_module']); - } + // Hook for duplication of shop data + $modules_list = Hook::getHookModuleExecList('actionShopDataDuplication'); + if (is_array($modules_list) && count($modules_list) > 0) { + foreach ($modules_list as $m) { + if (!$tables_import || isset($tables_import['Module'.ucfirst($m['module'])])) { + Hook::exec('actionShopDataDuplication', array( + 'old_id_shop' => (int)$old_id, + 'new_id_shop' => (int)$this->id, + ), $m['id_module']); + } + } + } + } - /** - * @param int $id - * @return array - */ - public static function getCategories($id = 0, $only_id = true) - { - // build query - $query = new DbQuery(); - if ($only_id) - $query->select('cs.`id_category`'); - else - $query->select('DISTINCT cs.`id_category`, cl.`name`, cl.`link_rewrite`'); - $query->from('category_shop', 'cs'); - $query->leftJoin('category_lang', 'cl', 'cl.`id_category` = cs.`id_category` AND cl.`id_lang` = '.(int)Context::getContext()->language->id); - $query->where('cs.`id_shop` = '.(int)$id); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + /** + * @param int $id + * @return array + */ + public static function getCategories($id = 0, $only_id = true) + { + // build query + $query = new DbQuery(); + if ($only_id) { + $query->select('cs.`id_category`'); + } else { + $query->select('DISTINCT cs.`id_category`, cl.`name`, cl.`link_rewrite`'); + } + $query->from('category_shop', 'cs'); + $query->leftJoin('category_lang', 'cl', 'cl.`id_category` = cs.`id_category` AND cl.`id_lang` = '.(int)Context::getContext()->language->id); + $query->where('cs.`id_shop` = '.(int)$id); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - if ($only_id) - { - $array = array(); - foreach ($result as $row) - $array[] = $row['id_category']; - $array = array_unique($array); - } - else - return $result; + if ($only_id) { + $array = array(); + foreach ($result as $row) { + $array[] = $row['id_category']; + } + $array = array_unique($array); + } else { + return $result; + } - return $array; - } + return $array; + } - /** - * @deprecated 1.5.0 Use shop->id - */ - public static function getCurrentShop() - { - Tools::displayAsDeprecated(); - return Context::getContext()->shop->id; - } + /** + * @deprecated 1.5.0 Use shop->id + */ + public static function getCurrentShop() + { + Tools::displayAsDeprecated(); + return Context::getContext()->shop->id; + } - /** - * @param string $entity - * @param int $id_shop - * @return array|bool - */ - public static function getEntityIds($entity, $id_shop, $active = false, $delete = false) - { - if (!Shop::isTableAssociated($entity)) - return false; + /** + * @param string $entity + * @param int $id_shop + * @return array|bool + */ + public static function getEntityIds($entity, $id_shop, $active = false, $delete = false) + { + if (!Shop::isTableAssociated($entity)) { + return false; + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT entity.`id_'.pSQL($entity).'` FROM `'._DB_PREFIX_.pSQL($entity).'_shop`es LEFT JOIN '._DB_PREFIX_.pSQL($entity).' entity ON (entity.`id_'.pSQL($entity).'` = es.`id_'.pSQL($entity).'`) WHERE es.`id_shop` = '.(int)$id_shop. - ($active ? ' AND entity.`active` = 1' : ''). - ($delete ? ' AND entity.deleted = 0' : '') - ); - } -} \ No newline at end of file + ($active ? ' AND entity.`active` = 1' : ''). + ($delete ? ' AND entity.deleted = 0' : '') + ); + } +} diff --git a/classes/shop/ShopGroup.php b/classes/shop/ShopGroup.php index aec07357..96c4008a 100644 --- a/classes/shop/ShopGroup.php +++ b/classes/shop/ShopGroup.php @@ -29,139 +29,142 @@ */ class ShopGroupCore extends ObjectModel { - public $name; - public $active = true; - public $share_customer; - public $share_stock; - public $share_order; - public $deleted; + public $name; + public $active = true; + public $share_customer; + public $share_stock; + public $share_order; + public $deleted; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'shop_group', - 'primary' => 'id_shop_group', - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), - 'share_customer' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'share_order' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'share_stock' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'shop_group', + 'primary' => 'id_shop_group', + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), + 'share_customer' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'share_order' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'share_stock' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + ), + ); - /** - * @see ObjectModel::getFields() - * @return array - */ - public function getFields() - { - if (!$this->share_customer || !$this->share_stock) - $this->share_order = false; + /** + * @see ObjectModel::getFields() + * @return array + */ + public function getFields() + { + if (!$this->share_customer || !$this->share_stock) { + $this->share_order = false; + } - return parent::getFields(); - } + return parent::getFields(); + } - public static function getShopGroups($active = true) - { - $groups = new PrestaShopCollection('ShopGroup'); - $groups->where('deleted', '=', false); - if ($active) - $groups->where('active', '=', true); - return $groups; - } + public static function getShopGroups($active = true) + { + $groups = new PrestaShopCollection('ShopGroup'); + $groups->where('deleted', '=', false); + if ($active) { + $groups->where('active', '=', true); + } + return $groups; + } - /** - * @return int Total of shop groups - */ - public static function getTotalShopGroup($active = true) - { - return count(ShopGroup::getShopGroups($active)); - } + /** + * @return int Total of shop groups + */ + public static function getTotalShopGroup($active = true) + { + return count(ShopGroup::getShopGroups($active)); + } - public function haveShops() - { - return (bool)$this->getTotalShops(); - } + public function haveShops() + { + return (bool)$this->getTotalShops(); + } - public function getTotalShops() - { - $sql = 'SELECT COUNT(*) + public function getTotalShops() + { + $sql = 'SELECT COUNT(*) FROM '._DB_PREFIX_.'shop s WHERE id_shop_group='.(int)$this->id; - return (int)Db::getInstance()->getValue($sql); - } + return (int)Db::getInstance()->getValue($sql); + } - public static function getShopsFromGroup($id_group) - { - $sql = 'SELECT s.`id_shop` + public static function getShopsFromGroup($id_group) + { + $sql = 'SELECT s.`id_shop` FROM '._DB_PREFIX_.'shop s WHERE id_shop_group='.(int)$id_group; - return Db::getInstance()->executeS($sql); - } + return Db::getInstance()->executeS($sql); + } - /** - * Return a group shop ID from group shop name - * - * @param string $name - * @return int - */ - public static function getIdByName($name) - { - $sql = 'SELECT id_shop_group + /** + * Return a group shop ID from group shop name + * + * @param string $name + * @return int + */ + public static function getIdByName($name) + { + $sql = 'SELECT id_shop_group FROM '._DB_PREFIX_.'shop_group WHERE name = \''.pSQL($name).'\''; - return (int)Db::getInstance()->getValue($sql); - } + return (int)Db::getInstance()->getValue($sql); + } - /** - * Detect dependency with customer or orders - * - * @param int $id_shop_group - * @param string $check all|customer|order - * @return bool - */ - public static function hasDependency($id_shop_group, $check = 'all') - { - $list_shops = Shop::getShops(false, $id_shop_group, true); - if (!$list_shops) - return false; + /** + * Detect dependency with customer or orders + * + * @param int $id_shop_group + * @param string $check all|customer|order + * @return bool + */ + public static function hasDependency($id_shop_group, $check = 'all') + { + $list_shops = Shop::getShops(false, $id_shop_group, true); + if (!$list_shops) { + return false; + } - if ($check == 'all' || $check == 'customer') - { - $total_customer = (int)Db::getInstance()->getValue(' + if ($check == 'all' || $check == 'customer') { + $total_customer = (int)Db::getInstance()->getValue(' SELECT count(*) FROM `'._DB_PREFIX_.'customer` WHERE `id_shop` IN ('.implode(', ', $list_shops).')' - ); - if ($total_customer) - return true; - } + ); + if ($total_customer) { + return true; + } + } - if ($check == 'all' || $check == 'order') - { - $total_order = (int)Db::getInstance()->getValue(' + if ($check == 'all' || $check == 'order') { + $total_order = (int)Db::getInstance()->getValue(' SELECT count(*) FROM `'._DB_PREFIX_.'orders` WHERE `id_shop` IN ('.implode(', ', $list_shops).')' - ); - if ($total_order) - return true; - } + ); + if ($total_order) { + return true; + } + } - return false; - } + return false; + } - public function shopNameExists($name, $id_shop = false) - { - return Db::getInstance()->getValue(' + public function shopNameExists($name, $id_shop = false) + { + return Db::getInstance()->getValue(' SELECT id_shop FROM '._DB_PREFIX_.'shop WHERE name = "'.pSQL($name).'" AND id_shop_group = '.(int)$this->id.' '.($id_shop ? 'AND id_shop != '.(int)$id_shop : '') - ); - } -} \ No newline at end of file + ); + } +} diff --git a/classes/shop/ShopUrl.php b/classes/shop/ShopUrl.php index 30ad4cbe..fd9dfc09 100644 --- a/classes/shop/ShopUrl.php +++ b/classes/shop/ShopUrl.php @@ -26,161 +26,167 @@ class ShopUrlCore extends ObjectModel { - public $id_shop; - public $domain; - public $domain_ssl; - public $physical_uri; - public $virtual_uri; - public $main; - public $active; + public $id_shop; + public $domain; + public $domain_ssl; + public $physical_uri; + public $virtual_uri; + public $main; + public $active; - protected static $main_domain = array(); - protected static $main_domain_ssl = array(); + protected static $main_domain = array(); + protected static $main_domain_ssl = array(); - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'shop_url', - 'primary' => 'id_shop_url', - 'fields' => array( - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'main' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'domain' => array('type' => self::TYPE_STRING, 'required' => true, 'size' => 255, 'validate' => 'isCleanHtml'), - 'domain_ssl' => array('type' => self::TYPE_STRING, 'size' => 255, 'validate' => 'isCleanHtml'), - 'id_shop' => array('type' => self::TYPE_INT, 'required' => true), - 'physical_uri' => array('type' => self::TYPE_STRING, 'size' => 64), - 'virtual_uri' => array('type' => self::TYPE_STRING, 'size' => 64), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'shop_url', + 'primary' => 'id_shop_url', + 'fields' => array( + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'main' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'domain' => array('type' => self::TYPE_STRING, 'required' => true, 'size' => 255, 'validate' => 'isCleanHtml'), + 'domain_ssl' => array('type' => self::TYPE_STRING, 'size' => 255, 'validate' => 'isCleanHtml'), + 'id_shop' => array('type' => self::TYPE_INT, 'required' => true), + 'physical_uri' => array('type' => self::TYPE_STRING, 'size' => 64), + 'virtual_uri' => array('type' => self::TYPE_STRING, 'size' => 64), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_shop' => array('xlink_resource' => 'shops'), - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_shop' => array('xlink_resource' => 'shops'), + ), + ); - /** - * @see ObjectModel::getFields() - * @return array - */ - public function getFields() - { - $this->domain = trim($this->domain); - $this->domain_ssl = trim($this->domain_ssl); - $this->physical_uri = trim(str_replace(' ', '', $this->physical_uri), '/'); + /** + * @see ObjectModel::getFields() + * @return array + */ + public function getFields() + { + $this->domain = trim($this->domain); + $this->domain_ssl = trim($this->domain_ssl); + $this->physical_uri = trim(str_replace(' ', '', $this->physical_uri), '/'); - if ($this->physical_uri) - $this->physical_uri = preg_replace('#/+#', '/', '/'.$this->physical_uri.'/'); - else - $this->physical_uri = '/'; + if ($this->physical_uri) { + $this->physical_uri = preg_replace('#/+#', '/', '/'.$this->physical_uri.'/'); + } else { + $this->physical_uri = '/'; + } - $this->virtual_uri = trim(str_replace(' ', '', $this->virtual_uri), '/'); - if ($this->virtual_uri) - $this->virtual_uri = preg_replace('#/+#', '/', trim($this->virtual_uri, '/')).'/'; + $this->virtual_uri = trim(str_replace(' ', '', $this->virtual_uri), '/'); + if ($this->virtual_uri) { + $this->virtual_uri = preg_replace('#/+#', '/', trim($this->virtual_uri, '/')).'/'; + } - return parent::getFields(); - } + return parent::getFields(); + } - public function getBaseURI() - { - return $this->physical_uri.$this->virtual_uri; - } + public function getBaseURI() + { + return $this->physical_uri.$this->virtual_uri; + } - public function getURL($ssl = false) - { - if (!$this->id) - return; + public function getURL($ssl = false) + { + if (!$this->id) { + return; + } - $url = ($ssl) ? 'https://'.$this->domain_ssl : 'http://'.$this->domain; - return $url.$this->getBaseUri(); - } + $url = ($ssl) ? 'https://'.$this->domain_ssl : 'http://'.$this->domain; + return $url.$this->getBaseUri(); + } - /** - * Get list of shop urls - * - * @param bool $id_shop - * @return PrestaShopCollection Collection of ShopUrl - */ - public static function getShopUrls($id_shop = false) - { - $urls = new PrestaShopCollection('ShopUrl'); - if ($id_shop) - $urls->where('id_shop', '=', $id_shop); - return $urls; - } + /** + * Get list of shop urls + * + * @param bool $id_shop + * @return PrestaShopCollection Collection of ShopUrl + */ + public static function getShopUrls($id_shop = false) + { + $urls = new PrestaShopCollection('ShopUrl'); + if ($id_shop) { + $urls->where('id_shop', '=', $id_shop); + } + return $urls; + } - public function setMain() - { - $res = Db::getInstance()->update('shop_url', array('main' => 0), 'id_shop = '.(int)$this->id_shop); - $res &= Db::getInstance()->update('shop_url', array('main' => 1), 'id_shop_url = '.(int)$this->id); - $this->main = true; + public function setMain() + { + $res = Db::getInstance()->update('shop_url', array('main' => 0), 'id_shop = '.(int)$this->id_shop); + $res &= Db::getInstance()->update('shop_url', array('main' => 1), 'id_shop_url = '.(int)$this->id); + $this->main = true; - // Reset main URL for all shops to prevent problems - $sql = 'SELECT s1.id_shop_url FROM '._DB_PREFIX_.'shop_url s1 + // Reset main URL for all shops to prevent problems + $sql = 'SELECT s1.id_shop_url FROM '._DB_PREFIX_.'shop_url s1 WHERE ( SELECT COUNT(*) FROM '._DB_PREFIX_.'shop_url s2 WHERE s2.main = 1 AND s2.id_shop = s1.id_shop ) = 0 GROUP BY s1.id_shop'; - foreach (Db::getInstance()->executeS($sql) as $row) - Db::getInstance()->update('shop_url', array('main' => 1), 'id_shop_url = '.$row['id_shop_url']); + foreach (Db::getInstance()->executeS($sql) as $row) { + Db::getInstance()->update('shop_url', array('main' => 1), 'id_shop_url = '.$row['id_shop_url']); + } - return $res; - } + return $res; + } - public function canAddThisUrl($domain, $domain_ssl, $physical_uri, $virtual_uri) - { - $physical_uri = trim($physical_uri, '/'); + public function canAddThisUrl($domain, $domain_ssl, $physical_uri, $virtual_uri) + { + $physical_uri = trim($physical_uri, '/'); - if ($physical_uri) - $physical_uri = preg_replace('#/+#', '/', '/'.$physical_uri.'/'); - else - $physical_uri = '/'; + if ($physical_uri) { + $physical_uri = preg_replace('#/+#', '/', '/'.$physical_uri.'/'); + } else { + $physical_uri = '/'; + } - $virtual_uri = trim($virtual_uri, '/'); - if ($virtual_uri) - $virtual_uri = preg_replace('#/+#', '/', trim($virtual_uri, '/')).'/'; + $virtual_uri = trim($virtual_uri, '/'); + if ($virtual_uri) { + $virtual_uri = preg_replace('#/+#', '/', trim($virtual_uri, '/')).'/'; + } - $sql = 'SELECT id_shop_url + $sql = 'SELECT id_shop_url FROM '._DB_PREFIX_.'shop_url WHERE physical_uri = \''.pSQL($physical_uri).'\' AND virtual_uri = \''.pSQL($virtual_uri).'\' AND (domain = \''.pSQL($domain).'\' '.(($domain_ssl) ? ' OR domain_ssl = \''.pSQL($domain_ssl).'\'' : '').')' - .($this->id ? ' AND id_shop_url != '.(int)$this->id : ''); - return Db::getInstance()->getValue($sql); - } + .($this->id ? ' AND id_shop_url != '.(int)$this->id : ''); + return Db::getInstance()->getValue($sql); + } - public static function cacheMainDomainForShop($id_shop) - { - if (!isset(self::$main_domain_ssl[(int)$id_shop]) || !isset(self::$main_domain[(int)$id_shop])) - { - $row = Db::getInstance()->getRow(' + public static function cacheMainDomainForShop($id_shop) + { + if (!isset(self::$main_domain_ssl[(int)$id_shop]) || !isset(self::$main_domain[(int)$id_shop])) { + $row = Db::getInstance()->getRow(' SELECT domain, domain_ssl FROM '._DB_PREFIX_.'shop_url WHERE main = 1 AND id_shop = '.($id_shop !== null ? (int)$id_shop : (int)Context::getContext()->shop->id)); - self::$main_domain[(int)$id_shop] = $row['domain']; - self::$main_domain_ssl[(int)$id_shop] = $row['domain_ssl']; - } - } + self::$main_domain[(int)$id_shop] = $row['domain']; + self::$main_domain_ssl[(int)$id_shop] = $row['domain_ssl']; + } + } - public static function resetMainDomainCache() - { - self::$main_domain = array(); - self::$main_domain_ssl = array(); - } + public static function resetMainDomainCache() + { + self::$main_domain = array(); + self::$main_domain_ssl = array(); + } - public static function getMainShopDomain($id_shop = null) - { - ShopUrl::cacheMainDomainForShop($id_shop); - return self::$main_domain[(int)$id_shop]; - } + public static function getMainShopDomain($id_shop = null) + { + ShopUrl::cacheMainDomainForShop($id_shop); + return self::$main_domain[(int)$id_shop]; + } - public static function getMainShopDomainSSL($id_shop = null) - { - ShopUrl::cacheMainDomainForShop($id_shop); - return self::$main_domain_ssl[(int)$id_shop]; - } -} \ No newline at end of file + public static function getMainShopDomainSSL($id_shop = null) + { + ShopUrl::cacheMainDomainForShop($id_shop); + return self::$main_domain_ssl[(int)$id_shop]; + } +} diff --git a/classes/shop/index.php b/classes/shop/index.php index c642967a..91fa49fb 100644 --- a/classes/shop/index.php +++ b/classes/shop/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/classes/stock/Stock.php b/classes/stock/Stock.php index c099b2dd..116b767b 100644 --- a/classes/stock/Stock.php +++ b/classes/stock/Stock.php @@ -31,150 +31,150 @@ */ class StockCore extends ObjectModel { - /** @var int identifier of the warehouse */ - public $id_warehouse; + /** @var int identifier of the warehouse */ + public $id_warehouse; - /** @var int identifier of the product */ - public $id_product; + /** @var int identifier of the product */ + public $id_product; - /** @var int identifier of the product attribute if necessary */ - public $id_product_attribute; + /** @var int identifier of the product attribute if necessary */ + public $id_product_attribute; - /** @var string Product reference */ - public $reference; + /** @var string Product reference */ + public $reference; - /** @var int Product EAN13 */ - public $ean13; + /** @var int Product EAN13 */ + public $ean13; - /** @var string UPC */ - public $upc; + /** @var string UPC */ + public $upc; - /** @var int the physical quantity in stock for the current product in the current warehouse */ - public $physical_quantity; + /** @var int the physical quantity in stock for the current product in the current warehouse */ + public $physical_quantity; - /** @var int the usable quantity (for sale) of the current physical quantity */ - public $usable_quantity; + /** @var int the usable quantity (for sale) of the current physical quantity */ + public $usable_quantity; - /** @var int the unit price without tax forthe current product */ - public $price_te; + /** @var int the unit price without tax forthe current product */ + public $price_te; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'stock', - 'primary' => 'id_stock', - 'fields' => array( - 'id_warehouse' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference'), - 'ean13' => array('type' => self::TYPE_STRING, 'validate' => 'isEan13'), - 'upc' => array('type' => self::TYPE_STRING, 'validate' => 'isUpc'), - 'physical_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), - 'usable_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), - 'price_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'stock', + 'primary' => 'id_stock', + 'fields' => array( + 'id_warehouse' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference'), + 'ean13' => array('type' => self::TYPE_STRING, 'validate' => 'isEan13'), + 'upc' => array('type' => self::TYPE_STRING, 'validate' => 'isUpc'), + 'physical_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), + 'usable_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), + 'price_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + ), + ); - /** - * @see ObjectModel::$webserviceParameters - */ - protected $webserviceParameters = array( - 'fields' => array( - 'id_warehouse' => array('xlink_resource' => 'warehouses'), - 'id_product' => array('xlink_resource' => 'products'), - 'id_product_attribute' => array('xlink_resource' => 'combinations'), - 'real_quantity' => array('getter' => 'getWsRealQuantity', 'setter' => false), - ), - 'hidden_fields' => array( - ), - ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'fields' => array( + 'id_warehouse' => array('xlink_resource' => 'warehouses'), + 'id_product' => array('xlink_resource' => 'products'), + 'id_product_attribute' => array('xlink_resource' => 'combinations'), + 'real_quantity' => array('getter' => 'getWsRealQuantity', 'setter' => false), + ), + 'hidden_fields' => array( + ), + ); - /** - * @see ObjectModel::update() - */ - public function update($null_values = false) - { - $this->getProductInformations(); + /** + * @see ObjectModel::update() + */ + public function update($null_values = false) + { + $this->getProductInformations(); - return parent::update($null_values); - } + return parent::update($null_values); + } - /** - * @see ObjectModel::add() - */ - public function add($autodate = true, $null_values = false) - { - $this->getProductInformations(); + /** + * @see ObjectModel::add() + */ + public function add($autodate = true, $null_values = false) + { + $this->getProductInformations(); - return parent::add($autodate, $null_values); - } + return parent::add($autodate, $null_values); + } - /** - * Gets reference, ean13 and upc of the current product - * Stores it in stock for stock_mvt integrity and history purposes - */ - protected function getProductInformations() - { - // if combinations - if ((int)$this->id_product_attribute > 0) - { - $query = new DbQuery(); - $query->select('reference, ean13, upc'); - $query->from('product_attribute'); - $query->where('id_product = '.(int)$this->id_product); - $query->where('id_product_attribute = '.(int)$this->id_product_attribute); - $rows = Db::getInstance()->executeS($query); + /** + * Gets reference, ean13 and upc of the current product + * Stores it in stock for stock_mvt integrity and history purposes + */ + protected function getProductInformations() + { + // if combinations + if ((int)$this->id_product_attribute > 0) { + $query = new DbQuery(); + $query->select('reference, ean13, upc'); + $query->from('product_attribute'); + $query->where('id_product = '.(int)$this->id_product); + $query->where('id_product_attribute = '.(int)$this->id_product_attribute); + $rows = Db::getInstance()->executeS($query); - if (!is_array($rows)) - return; + if (!is_array($rows)) { + return; + } - foreach ($rows as $row) - { - $this->reference = $row['reference']; - $this->ean13 = $row['ean13']; - $this->upc = $row['upc']; - } - } - else // else, simple product - { - $product = new Product((int)$this->id_product); - if (Validate::isLoadedObject($product)) - { - $this->reference = $product->reference; - $this->ean13 = $product->ean13; - $this->upc = $product->upc; - } - } - } + foreach ($rows as $row) { + $this->reference = $row['reference']; + $this->ean13 = $row['ean13']; + $this->upc = $row['upc']; + } + } else { + // else, simple product - /** - * Webservice : used to get the real quantity of a product - */ - public function getWsRealQuantity() - { - $manager = StockManagerFactory::getManager(); - $quantity = $manager->getProductRealQuantities($this->id_product, $this->id_product_attribute, $this->id_warehouse, true); - return $quantity; - } + $product = new Product((int)$this->id_product); + if (Validate::isLoadedObject($product)) { + $this->reference = $product->reference; + $this->ean13 = $product->ean13; + $this->upc = $product->upc; + } + } + } - public static function deleteStockByIds($id_product = null, $id_product_attribute = null) - { - if (!$id_product || !$id_product_attribute) - return false; + /** + * Webservice : used to get the real quantity of a product + */ + public function getWsRealQuantity() + { + $manager = StockManagerFactory::getManager(); + $quantity = $manager->getProductRealQuantities($this->id_product, $this->id_product_attribute, $this->id_warehouse, true); + return $quantity; + } - return Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'stock WHERE `id_product` = '.(int)$id_product.' AND `id_product_attribute` = '.(int)$id_product_attribute); - } + public static function deleteStockByIds($id_product = null, $id_product_attribute = null) + { + if (!$id_product || !$id_product_attribute) { + return false; + } - public static function productIsPresentInStock($id_product = 0, $id_product_attribute = 0, $id_warehouse = 0) - { - if (!(int)$id_product && !is_int($id_product_attribute) && !(int)$id_warehouse) - return false; + return Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'stock WHERE `id_product` = '.(int)$id_product.' AND `id_product_attribute` = '.(int)$id_product_attribute); + } - $result = Db::getInstance()->executeS('SELECT `id_stock` FROM '._DB_PREFIX_.'stock + public static function productIsPresentInStock($id_product = 0, $id_product_attribute = 0, $id_warehouse = 0) + { + if (!(int)$id_product && !is_int($id_product_attribute) && !(int)$id_warehouse) { + return false; + } + + $result = Db::getInstance()->executeS('SELECT `id_stock` FROM '._DB_PREFIX_.'stock WHERE `id_warehouse` = '.(int)$id_warehouse.' AND `id_product` = '.(int)$id_product.((int)$id_product_attribute ? ' AND `id_product_attribute` = '.$id_product_attribute : '')); - return (is_array($result) && !empty($result) ? true : false); - } -} \ No newline at end of file + return (is_array($result) && !empty($result) ? true : false); + } +} diff --git a/classes/stock/StockAvailable.php b/classes/stock/StockAvailable.php index 7f0fc0e8..5357d77a 100644 --- a/classes/stock/StockAvailable.php +++ b/classes/stock/StockAvailable.php @@ -32,825 +32,756 @@ */ class StockAvailableCore extends ObjectModel { - /** @var int identifier of the current product */ - public $id_product; + /** @var int identifier of the current product */ + public $id_product; - /** @var int identifier of product attribute if necessary */ - public $id_product_attribute; + /** @var int identifier of product attribute if necessary */ + public $id_product_attribute; - /** @var int the shop associated to the current product and corresponding quantity */ - public $id_shop; + /** @var int the shop associated to the current product and corresponding quantity */ + public $id_shop; - /** @var int the group shop associated to the current product and corresponding quantity */ - public $id_shop_group; + /** @var int the group shop associated to the current product and corresponding quantity */ + public $id_shop_group; - /** @var int the quantity available for sale */ - public $quantity = 0; + /** @var int the quantity available for sale */ + public $quantity = 0; - /** @var bool determine if the available stock value depends on physical stock */ - public $depends_on_stock = false; + /** @var bool determine if the available stock value depends on physical stock */ + public $depends_on_stock = false; - /** @var bool determine if a product is out of stock - it was previously in Product class */ - public $out_of_stock = false; + /** @var bool determine if a product is out of stock - it was previously in Product class */ + public $out_of_stock = false; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'stock_available', - 'primary' => 'id_stock_available', - 'fields' => array( - 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_shop_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'quantity' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), - 'depends_on_stock' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), - 'out_of_stock' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'stock_available', + 'primary' => 'id_stock_available', + 'fields' => array( + 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_shop_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'quantity' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), + 'depends_on_stock' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => true), + 'out_of_stock' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), + ), + ); - /** - * @see ObjectModel::$webserviceParameters - */ - protected $webserviceParameters = array( - 'fields' => array( - 'id_product' => array('xlink_resource' => 'products'), - 'id_product_attribute' => array('xlink_resource' => 'combinations'), - 'id_shop' => array('xlink_resource' => 'shops'), - 'id_shop_group' => array('xlink_resource' => 'shop_groups'), - ), - 'hidden_fields' => array( - ), - 'objectMethods' => array( - 'add' => 'addWs', - 'update' => 'updateWs', - ), - ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'fields' => array( + 'id_product' => array('xlink_resource' => 'products'), + 'id_product_attribute' => array('xlink_resource' => 'combinations'), + 'id_shop' => array('xlink_resource' => 'shops'), + 'id_shop_group' => array('xlink_resource' => 'shop_groups'), + ), + 'hidden_fields' => array( + ), + 'objectMethods' => array( + 'add' => 'addWs', + 'update' => 'updateWs', + ), + ); - /** - * For a given {id_product, id_product_attribute and id_shop}, gets the stock available id associated - * - * @param int $id_product - * @param int $id_product_attribute Optional - * @param int $id_shop Optional - * @return int - */ + /** + * For a given {id_product, id_product_attribute and id_shop}, gets the stock available id associated + * + * @param int $id_product + * @param int $id_product_attribute Optional + * @param int $id_shop Optional + * @return int + */ - public function updateWs() - { - if ($this->depends_on_stock) - return WebserviceRequest::getInstance()->setError(500, Tools::displayError('You cannot update the available stock when it depends on stock.'), 133); - return $this->update(); - } + public function updateWs() + { + if ($this->depends_on_stock) { + return WebserviceRequest::getInstance()->setError(500, Tools::displayError('You cannot update the available stock when it depends on stock.'), 133); + } + return $this->update(); + } - public static function getStockAvailableIdByProductId($id_product, $id_product_attribute = null, $id_shop = null) - { - if (!Validate::isUnsignedId($id_product)) - return false; + public static function getStockAvailableIdByProductId($id_product, $id_product_attribute = null, $id_shop = null) + { + if (!Validate::isUnsignedId($id_product)) { + return false; + } - $query = new DbQuery(); - $query->select('id_stock_available'); - $query->from('stock_available'); - $query->where('id_product = '.(int)$id_product); + $query = new DbQuery(); + $query->select('id_stock_available'); + $query->from('stock_available'); + $query->where('id_product = '.(int)$id_product); - if ($id_product_attribute !== null) - $query->where('id_product_attribute = '.(int)$id_product_attribute); + if ($id_product_attribute !== null) { + $query->where('id_product_attribute = '.(int)$id_product_attribute); + } - $query = StockAvailable::addSqlShopRestriction($query, $id_shop); - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + $query = StockAvailable::addSqlShopRestriction($query, $id_shop); + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } - /** - * For a given id_product, synchronizes StockAvailable::quantity with Stock::usable_quantity - * - * @param int $id_product - */ - public static function synchronize($id_product, $order_id_shop = null) - { - if (!Validate::isUnsignedId($id_product)) - return false; + /** + * For a given id_product, synchronizes StockAvailable::quantity with Stock::usable_quantity + * + * @param int $id_product + */ + public static function synchronize($id_product, $order_id_shop = null) + { + if (!Validate::isUnsignedId($id_product)) { + return false; + } - //if product is pack sync recursivly product in pack - if (Pack::isPack($id_product)) - { - if (Validate::isLoadedObject($product = new Product((int)$id_product))) - { - if ($product->pack_stock_type == 1 || $product->pack_stock_type == 2 || ($product->pack_stock_type == 3 && Configuration::get('PS_PACK_STOCK_TYPE') > 0)) - { - $products_pack = Pack::getItems($id_product, (int)Configuration::get('PS_LANG_DEFAULT')); - foreach ($products_pack as $product_pack) - StockAvailable::synchronize($product_pack->id, $order_id_shop); - } - } - else - return false; - } + //if product is pack sync recursivly product in pack + if (Pack::isPack($id_product)) { + if (Validate::isLoadedObject($product = new Product((int)$id_product))) { + if ($product->pack_stock_type == 1 || $product->pack_stock_type == 2 || ($product->pack_stock_type == 3 && Configuration::get('PS_PACK_STOCK_TYPE') > 0)) { + $products_pack = Pack::getItems($id_product, (int)Configuration::get('PS_LANG_DEFAULT')); + foreach ($products_pack as $product_pack) { + StockAvailable::synchronize($product_pack->id, $order_id_shop); + } + } + } else { + return false; + } + } - // gets warehouse ids grouped by shops - $ids_warehouse = Warehouse::getWarehousesGroupedByShops(); - if ($order_id_shop !== null) - { - $order_warehouses = array(); - $wh = Warehouse::getWarehouses(false, (int)$order_id_shop); - foreach ($wh as $warehouse) - $order_warehouses[] = $warehouse['id_warehouse']; - } + // gets warehouse ids grouped by shops + $ids_warehouse = Warehouse::getWarehousesGroupedByShops(); + if ($order_id_shop !== null) { + $order_warehouses = array(); + $wh = Warehouse::getWarehouses(false, (int)$order_id_shop); + foreach ($wh as $warehouse) { + $order_warehouses[] = $warehouse['id_warehouse']; + } + } - // gets all product attributes ids - $ids_product_attribute = array(); - foreach (Product::getProductAttributesIds($id_product) as $id_product_attribute) - $ids_product_attribute[] = $id_product_attribute['id_product_attribute']; + // gets all product attributes ids + $ids_product_attribute = array(); + foreach (Product::getProductAttributesIds($id_product) as $id_product_attribute) { + $ids_product_attribute[] = $id_product_attribute['id_product_attribute']; + } - // Allow to order the product when out of stock? - $out_of_stock = StockAvailable::outOfStock($id_product); + // Allow to order the product when out of stock? + $out_of_stock = StockAvailable::outOfStock($id_product); - $manager = StockManagerFactory::getManager(); - // loops on $ids_warehouse to synchronize quantities - foreach ($ids_warehouse as $id_shop => $warehouses) - { - // first, checks if the product depends on stock for the given shop $id_shop - if (StockAvailable::dependsOnStock($id_product, $id_shop)) - { - // init quantity - $product_quantity = 0; + $manager = StockManagerFactory::getManager(); + // loops on $ids_warehouse to synchronize quantities + foreach ($ids_warehouse as $id_shop => $warehouses) { + // first, checks if the product depends on stock for the given shop $id_shop + if (StockAvailable::dependsOnStock($id_product, $id_shop)) { + // init quantity + $product_quantity = 0; - // if it's a simple product - if (empty($ids_product_attribute)) - { - $allowed_warehouse_for_product = WareHouse::getProductWarehouseList((int)$id_product, 0, (int)$id_shop); - $allowed_warehouse_for_product_clean = array(); - foreach ($allowed_warehouse_for_product as $warehouse) - $allowed_warehouse_for_product_clean[] = (int)$warehouse['id_warehouse']; - $allowed_warehouse_for_product_clean = array_intersect($allowed_warehouse_for_product_clean, $warehouses); - if ($order_id_shop != null && !count(array_intersect($allowed_warehouse_for_product_clean, $order_warehouses))) - continue; + // if it's a simple product + if (empty($ids_product_attribute)) { + $allowed_warehouse_for_product = WareHouse::getProductWarehouseList((int)$id_product, 0, (int)$id_shop); + $allowed_warehouse_for_product_clean = array(); + foreach ($allowed_warehouse_for_product as $warehouse) { + $allowed_warehouse_for_product_clean[] = (int)$warehouse['id_warehouse']; + } + $allowed_warehouse_for_product_clean = array_intersect($allowed_warehouse_for_product_clean, $warehouses); + if ($order_id_shop != null && !count(array_intersect($allowed_warehouse_for_product_clean, $order_warehouses))) { + continue; + } - $product_quantity = $manager->getProductRealQuantities($id_product, null, $allowed_warehouse_for_product_clean, true); + $product_quantity = $manager->getProductRealQuantities($id_product, null, $allowed_warehouse_for_product_clean, true); - Hook::exec('actionUpdateQuantity', - array( - 'id_product' => $id_product, - 'id_product_attribute' => 0, - 'quantity' => $product_quantity, - 'id_shop' => $id_shop - ) - ); - } - // else this product has attributes, hence loops on $ids_product_attribute - else - { - foreach ($ids_product_attribute as $id_product_attribute) - { + Hook::exec('actionUpdateQuantity', + array( + 'id_product' => $id_product, + 'id_product_attribute' => 0, + 'quantity' => $product_quantity, + 'id_shop' => $id_shop + ) + ); + } + // else this product has attributes, hence loops on $ids_product_attribute + else { + foreach ($ids_product_attribute as $id_product_attribute) { + $allowed_warehouse_for_combination = WareHouse::getProductWarehouseList((int)$id_product, (int)$id_product_attribute, (int)$id_shop); + $allowed_warehouse_for_combination_clean = array(); + foreach ($allowed_warehouse_for_combination as $warehouse) { + $allowed_warehouse_for_combination_clean[] = (int)$warehouse['id_warehouse']; + } + $allowed_warehouse_for_combination_clean = array_intersect($allowed_warehouse_for_combination_clean, $warehouses); + if ($order_id_shop != null && !count(array_intersect($allowed_warehouse_for_combination_clean, $order_warehouses))) { + continue; + } - $allowed_warehouse_for_combination = WareHouse::getProductWarehouseList((int)$id_product, (int)$id_product_attribute, (int)$id_shop); - $allowed_warehouse_for_combination_clean = array(); - foreach ($allowed_warehouse_for_combination as $warehouse) - $allowed_warehouse_for_combination_clean[] = (int)$warehouse['id_warehouse']; - $allowed_warehouse_for_combination_clean = array_intersect($allowed_warehouse_for_combination_clean, $warehouses); - if ($order_id_shop != null && !count(array_intersect($allowed_warehouse_for_combination_clean, $order_warehouses))) - continue; + $quantity = $manager->getProductRealQuantities($id_product, $id_product_attribute, $allowed_warehouse_for_combination_clean, true); - $quantity = $manager->getProductRealQuantities($id_product, $id_product_attribute, $allowed_warehouse_for_combination_clean, true); + $query = new DbQuery(); + $query->select('COUNT(*)'); + $query->from('stock_available'); + $query->where('id_product = '.(int)$id_product.' AND id_product_attribute = '.(int)$id_product_attribute. + StockAvailable::addSqlShopRestriction(null, $id_shop)); - $query = new DbQuery(); - $query->select('COUNT(*)'); - $query->from('stock_available'); - $query->where('id_product = '.(int)$id_product.' AND id_product_attribute = '.(int)$id_product_attribute. - StockAvailable::addSqlShopRestriction(null, $id_shop)); + if ((int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query)) { + $query = array( + 'table' => 'stock_available', + 'data' => array('quantity' => $quantity), + 'where' => 'id_product = '.(int)$id_product.' AND id_product_attribute = '.(int)$id_product_attribute. + StockAvailable::addSqlShopRestriction(null, $id_shop) + ); + Db::getInstance()->update($query['table'], $query['data'], $query['where']); + } else { + $query = array( + 'table' => 'stock_available', + 'data' => array( + 'quantity' => $quantity, + 'depends_on_stock' => 1, + 'out_of_stock' => $out_of_stock, + 'id_product' => (int)$id_product, + 'id_product_attribute' => (int)$id_product_attribute, + ) + ); + StockAvailable::addSqlShopParams($query['data']); + Db::getInstance()->insert($query['table'], $query['data']); + } - if ((int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query)) - { - $query = array( - 'table' => 'stock_available', - 'data' => array('quantity' => $quantity), - 'where' => 'id_product = '.(int)$id_product.' AND id_product_attribute = '.(int)$id_product_attribute. - StockAvailable::addSqlShopRestriction(null, $id_shop) - ); - Db::getInstance()->update($query['table'], $query['data'], $query['where']); - } - else - { - $query = array( - 'table' => 'stock_available', - 'data' => array( - 'quantity' => $quantity, - 'depends_on_stock' => 1, - 'out_of_stock' => $out_of_stock, - 'id_product' => (int)$id_product, - 'id_product_attribute' => (int)$id_product_attribute, - ) - ); - StockAvailable::addSqlShopParams($query['data']); - Db::getInstance()->insert($query['table'], $query['data']); - } + $product_quantity += $quantity; - $product_quantity += $quantity; + Hook::exec('actionUpdateQuantity', + array( + 'id_product' => $id_product, + 'id_product_attribute' => $id_product_attribute, + 'quantity' => $quantity, + 'id_shop' => $id_shop + ) + ); + } + } + // updates + // if $id_product has attributes, it also updates the sum for all attributes + if (($order_id_shop != null && array_intersect($warehouses, $order_warehouses)) || $order_id_shop == null) { + $query = array( + 'table' => 'stock_available', + 'data' => array('quantity' => $product_quantity), + 'where' => 'id_product = '.(int)$id_product.' AND id_product_attribute = 0'. + StockAvailable::addSqlShopRestriction(null, $id_shop) + ); + Db::getInstance()->update($query['table'], $query['data'], $query['where']); + } + } + } + // In case there are no warehouses, removes product from StockAvailable + if (count($ids_warehouse) == 0 && StockAvailable::dependsOnStock((int)$id_product)) { + Db::getInstance()->update('stock_available', array('quantity' => 0 ), 'id_product = '.(int)$id_product); + } - Hook::exec('actionUpdateQuantity', - array( - 'id_product' => $id_product, - 'id_product_attribute' => $id_product_attribute, - 'quantity' => $quantity, - 'id_shop' => $id_shop - ) - ); - } - } - // updates - // if $id_product has attributes, it also updates the sum for all attributes - $query = array( - 'table' => 'stock_available', - 'data' => array('quantity' => $product_quantity), - 'where' => 'id_product = '.(int)$id_product.' AND id_product_attribute = 0'. - StockAvailable::addSqlShopRestriction(null, $id_shop) - ); - Db::getInstance()->update($query['table'], $query['data'], $query['where']); - } - } - // In case there are no warehouses, removes product from StockAvailable - if (count($ids_warehouse) == 0 && StockAvailable::dependsOnStock((int)$id_product)) - Db::getInstance()->update('stock_available', array('quantity' => 0 ), 'id_product = '.(int)$id_product); + Cache::clean('StockAvailable::getQuantityAvailableByProduct_'.(int)$id_product.'*'); + } - Cache::clean('StockAvailable::getQuantityAvailableByProduct_'.(int)$id_product.'*'); - } + /** + * For a given id_product, sets if stock available depends on stock + * + * @param int $id_product + * @param int $depends_on_stock Optional : true by default + * @param int $id_shop Optional : gets context by default + */ + public static function setProductDependsOnStock($id_product, $depends_on_stock = true, $id_shop = null, $id_product_attribute = 0) + { + if (!Validate::isUnsignedId($id_product)) { + return false; + } - /** - * For a given id_product, sets if stock available depends on stock - * - * @param int $id_product - * @param int $depends_on_stock Optional : true by default - * @param int $id_shop Optional : gets context by default - */ - public static function setProductDependsOnStock($id_product, $depends_on_stock = true, $id_shop = null, $id_product_attribute = 0) - { - if (!Validate::isUnsignedId($id_product)) - return false; + $existing_id = StockAvailable::getStockAvailableIdByProductId((int)$id_product, (int)$id_product_attribute, $id_shop); + if ($existing_id > 0) { + Db::getInstance()->update('stock_available', array( + 'depends_on_stock' => (int)$depends_on_stock + ), 'id_stock_available = '.(int)$existing_id); + } else { + $params = array( + 'depends_on_stock' => (int)$depends_on_stock, + 'id_product' => (int)$id_product, + 'id_product_attribute' => (int)$id_product_attribute + ); - $existing_id = StockAvailable::getStockAvailableIdByProductId((int)$id_product, (int)$id_product_attribute, $id_shop); - if ($existing_id > 0) - { - Db::getInstance()->update('stock_available', array( - 'depends_on_stock' => (int)$depends_on_stock - ), 'id_stock_available = '.(int)$existing_id); - } - else - { - $params = array( - 'depends_on_stock' => (int)$depends_on_stock, - 'id_product' => (int)$id_product, - 'id_product_attribute' => (int)$id_product_attribute - ); + StockAvailable::addSqlShopParams($params, $id_shop); - StockAvailable::addSqlShopParams($params, $id_shop); + Db::getInstance()->insert('stock_available', $params); + } - Db::getInstance()->insert('stock_available', $params); - } + // depends on stock.. hence synchronizes + if ($depends_on_stock) { + StockAvailable::synchronize($id_product); + } + } - // depends on stock.. hence synchronizes - if ($depends_on_stock) - StockAvailable::synchronize($id_product); - } + /** + * For a given id_product, sets if product is available out of stocks + * + * @param int $id_product + * @param int $out_of_stock Optional false by default + * @param int $id_shop Optional gets context by default + */ + public static function setProductOutOfStock($id_product, $out_of_stock = false, $id_shop = null, $id_product_attribute = 0) + { + if (!Validate::isUnsignedId($id_product)) { + return false; + } - /** - * For a given id_product, sets if product is available out of stocks - * - * @param int $id_product - * @param int $out_of_stock Optional false by default - * @param int $id_shop Optional gets context by default - */ - public static function setProductOutOfStock($id_product, $out_of_stock = false, $id_shop = null, $id_product_attribute = 0) - { - if (!Validate::isUnsignedId($id_product)) - return false; + $existing_id = (int)StockAvailable::getStockAvailableIdByProductId((int)$id_product, (int)$id_product_attribute, $id_shop); - $existing_id = (int)StockAvailable::getStockAvailableIdByProductId((int)$id_product, (int)$id_product_attribute, $id_shop); + if ($existing_id > 0) { + Db::getInstance()->update( + 'stock_available', + array('out_of_stock' => (int)$out_of_stock), + 'id_product = '.(int)$id_product. + (($id_product_attribute) ? ' AND id_product_attribute = '.(int)$id_product_attribute : ''). + StockAvailable::addSqlShopRestriction(null, $id_shop) + ); + } else { + $params = array( + 'out_of_stock' => (int)$out_of_stock, + 'id_product' => (int)$id_product, + 'id_product_attribute' => (int)$id_product_attribute + ); - if ($existing_id > 0) - { - Db::getInstance()->update( - 'stock_available', - array('out_of_stock' => (int)$out_of_stock), - 'id_product = '.(int)$id_product. - (($id_product_attribute) ? ' AND id_product_attribute = '.(int)$id_product_attribute : ''). - StockAvailable::addSqlShopRestriction(null, $id_shop) - ); - } - else - { - $params = array( - 'out_of_stock' => (int)$out_of_stock, - 'id_product' => (int)$id_product, - 'id_product_attribute' => (int)$id_product_attribute - ); + StockAvailable::addSqlShopParams($params, $id_shop); + Db::getInstance()->insert('stock_available', $params, false, true, Db::ON_DUPLICATE_KEY); + } + } - StockAvailable::addSqlShopParams($params, $id_shop); - Db::getInstance()->insert('stock_available', $params, false, true, Db::ON_DUPLICATE_KEY); - } - } + /** + * For a given id_product and id_product_attribute, gets its stock available + * + * @param int $id_product + * @param int $id_product_attribute Optional + * @param int $id_shop Optional : gets context by default + * @return int Quantity + */ + public static function getQuantityAvailableByProduct($id_product = null, $id_product_attribute = null, $id_shop = null) + { + // if null, it's a product without attributes + if ($id_product_attribute === null) { + $id_product_attribute = 0; + } - /** - * For a given id_product and id_product_attribute, gets its stock available - * - * @param int $id_product - * @param int $id_product_attribute Optional - * @param int $id_shop Optional : gets context by default - * @return int Quantity - */ - public static function getQuantityAvailableByProduct($id_product = null, $id_product_attribute = null, $id_shop = null) - { - // if null, it's a product without attributes - if ($id_product_attribute === null) - $id_product_attribute = 0; + $key = 'StockAvailable::getQuantityAvailableByProduct_'.(int)$id_product.'-'.(int)$id_product_attribute.'-'.(int)$id_shop; + if (!Cache::isStored($key)) { + $query = new DbQuery(); + $query->select('SUM(quantity)'); + $query->from('stock_available'); - $key = 'StockAvailable::getQuantityAvailableByProduct_'.(int)$id_product.'-'.(int)$id_product_attribute.'-'.(int)$id_shop; - if (!Cache::isStored($key)) - { - $query = new DbQuery(); - $query->select('SUM(quantity)'); - $query->from('stock_available'); + // if null, it's a product without attributes + if ($id_product !== null) { + $query->where('id_product = '.(int)$id_product); + } - // if null, it's a product without attributes - if ($id_product !== null) - $query->where('id_product = '.(int)$id_product); + $query->where('id_product_attribute = '.(int)$id_product_attribute); + $query = StockAvailable::addSqlShopRestriction($query, $id_shop); + $result = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + Cache::store($key, $result); + return $result; + } - $query->where('id_product_attribute = '.(int)$id_product_attribute); - $query = StockAvailable::addSqlShopRestriction($query, $id_shop); - $result = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - Cache::store($key, $result); - return $result; - } + return Cache::retrieve($key); + } - return Cache::retrieve($key); - } + /** + * Upgrades total_quantity_available after having saved + * @see ObjectModel::add() + */ + public function add($autodate = true, $null_values = false) + { + if (!$result = parent::add($autodate, $null_values)) { + return false; + } - /** - * Upgrades total_quantity_available after having saved - * @see ObjectModel::add() - */ - public function add($autodate = true, $null_values = false) - { - if (!$result = parent::add($autodate, $null_values)) - return false; + $result &= $this->postSave(); + return $result; + } - $result &= $this->postSave(); - return $result; - } + /** + * Upgrades total_quantity_available after having update + * @see ObjectModel::update() + */ + public function update($null_values = false) + { + if (!$result = parent::update($null_values)) { + return false; + } - /** - * Upgrades total_quantity_available after having update - * @see ObjectModel::update() - */ - public function update($null_values = false) - { - if (!$result = parent::update($null_values)) - return false; + $result &= $this->postSave(); + return $result; + } - $result &= $this->postSave(); - return $result; - } + /** + * Upgrades total_quantity_available after having saved + * @see StockAvailableCore::update() + * @see StockAvailableCore::add() + */ + public function postSave() + { + if ($this->id_product_attribute == 0) { + return true; + } - /** - * Upgrades total_quantity_available after having saved - * @see StockAvailableCore::update() - * @see StockAvailableCore::add() - */ - public function postSave() - { - if ($this->id_product_attribute == 0) - return true; + $id_shop = (Shop::getContext() != Shop::CONTEXT_GROUP && $this->id_shop ? $this->id_shop : null); - $id_shop = (Shop::getContext() != Shop::CONTEXT_GROUP && $this->id_shop ? $this->id_shop : null); + if (!Configuration::get('PS_DISP_UNAVAILABLE_ATTR')) { + $combination = new Combination((int)$this->id_product_attribute); + if ($colors = $combination->getColorsAttributes()) { + $product = new Product((int)$this->id_product); + foreach ($colors as $color) { + if ($product->isColorUnavailable((int)$color['id_attribute'], (int)$this->id_shop)) { + Tools::clearColorListCache($product->id); + break; + } + } + } + } - if (!Configuration::get('PS_DISP_UNAVAILABLE_ATTR')) - { - $combination = new Combination((int)$this->id_product_attribute); - if ($colors = $combination->getColorsAttributes()) - { - $product = new Product((int)$this->id_product); - foreach ($colors as $color) - { - if ($product->isColorUnavailable((int)$color['id_attribute'], (int)$this->id_shop)) - { - Tools::clearColorListCache($product->id); - break; - } - } - } - } - - $total_quantity = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + $total_quantity = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT SUM(quantity) as quantity FROM '._DB_PREFIX_.'stock_available WHERE id_product = '.(int)$this->id_product.' AND id_product_attribute <> 0 '. - StockAvailable::addSqlShopRestriction(null, $id_shop) - ); - $this->setQuantity($this->id_product, 0, $total_quantity, $id_shop); + StockAvailable::addSqlShopRestriction(null, $id_shop) + ); + $this->setQuantity($this->id_product, 0, $total_quantity, $id_shop); - return true; - } + return true; + } - /** - * For a given id_product and id_product_attribute updates the quantity available - * - * @param int $id_product - * @param int $id_product_attribute Optional - * @param int $delta_quantity The delta quantity to update - * @param int $id_shop Optional - */ - public static function updateQuantity($id_product, $id_product_attribute, $delta_quantity, $id_shop = null) - { - if (!Validate::isUnsignedId($id_product)) - return false; + /** + * For a given id_product and id_product_attribute updates the quantity available + * If $avoid_parent_pack_update is true, then packs containing the given product won't be updated + * + * @param int $id_product + * @param int $id_product_attribute Optional + * @param int $delta_quantity The delta quantity to update + * @param int $id_shop Optional + */ + public static function updateQuantity($id_product, $id_product_attribute, $delta_quantity, $id_shop = null) + { + if (!Validate::isUnsignedId($id_product)) { + return false; + } + $product = new Product((int)$id_product); + if (!Validate::isLoadedObject($product)) { + return false; + } - $id_stock_available = StockAvailable::getStockAvailableIdByProductId($id_product, $id_product_attribute, $id_shop); + $stockManager = Adapter_ServiceLocator::get('Core_Business_Stock_StockManager'); + $stockManager->updateQuantity($product, $id_product_attribute, $delta_quantity, $id_shop = null); + return true; + } - if (!$id_stock_available) - return false; + /** + * For a given id_product and id_product_attribute sets the quantity available + * + * @param int $id_product + * @param int $id_product_attribute Optional + * @param int $delta_quantity The delta quantity to update + * @param int $id_shop Optional + */ + public static function setQuantity($id_product, $id_product_attribute, $quantity, $id_shop = null) + { + if (!Validate::isUnsignedId($id_product)) { + return false; + } - // Update quantity of the pack products - if (Pack::isPack($id_product)) - { - if (Validate::isLoadedObject($product = new Product((int)$id_product))) - { - if ($product->pack_stock_type == 1 || $product->pack_stock_type == 2 || ($product->pack_stock_type == 3 && Configuration::get('PS_PACK_STOCK_TYPE') > 0)) - { - $products_pack = Pack::getItems($id_product, (int)Configuration::get('PS_LANG_DEFAULT')); - foreach ($products_pack as $product_pack) - StockAvailable::updateQuantity($product_pack->id, $product_pack->id_pack_product_attribute, $product_pack->pack_quantity * $delta_quantity, $id_shop); - } + $context = Context::getContext(); + // if there is no $id_shop, gets the context one + if ($id_shop === null && Shop::getContext() != Shop::CONTEXT_GROUP) { + $id_shop = (int)$context->shop->id; + } - $stock_available = new StockAvailable($id_stock_available); - $stock_available->quantity = $stock_available->quantity + $delta_quantity; + $depends_on_stock = StockAvailable::dependsOnStock($id_product); - if ($product->pack_stock_type == 0 || $product->pack_stock_type == 2 || - ($product->pack_stock_type == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 0 || Configuration::get('PS_PACK_STOCK_TYPE') == 2))) - $stock_available->update(); - } - else - return false; - } - else - { - $stock_available = new StockAvailable($id_stock_available); - $stock_available->quantity = $stock_available->quantity + $delta_quantity; - $stock_available->update(); - } + //Try to set available quantity if product does not depend on physical stock + if (!$depends_on_stock) { + $id_stock_available = (int)StockAvailable::getStockAvailableIdByProductId($id_product, $id_product_attribute, $id_shop); + if ($id_stock_available) { + $stock_available = new StockAvailable($id_stock_available); + $stock_available->quantity = (int)$quantity; + $stock_available->update(); + } else { + $out_of_stock = StockAvailable::outOfStock($id_product, $id_shop); + $stock_available = new StockAvailable(); + $stock_available->out_of_stock = (int)$out_of_stock; + $stock_available->id_product = (int)$id_product; + $stock_available->id_product_attribute = (int)$id_product_attribute; + $stock_available->quantity = (int)$quantity; - Cache::clean('StockAvailable::getQuantityAvailableByProduct_'.(int)$id_product.'*'); + if ($id_shop === null) { + $shop_group = Shop::getContextShopGroup(); + } else { + $shop_group = new ShopGroup((int)Shop::getGroupFromShop((int)$id_shop)); + } - Hook::exec('actionUpdateQuantity', - array( - 'id_product' => $id_product, - 'id_product_attribute' => $id_product_attribute, - 'quantity' => $stock_available->quantity - ) - ); + // if quantities are shared between shops of the group + if ($shop_group->share_stock) { + $stock_available->id_shop = 0; + $stock_available->id_shop_group = (int)$shop_group->id; + } else { + $stock_available->id_shop = (int)$id_shop; + $stock_available->id_shop_group = 0; + } + $stock_available->add(); + } - return true; - } + Hook::exec('actionUpdateQuantity', + array( + 'id_product' => $id_product, + 'id_product_attribute' => $id_product_attribute, + 'quantity' => $stock_available->quantity + ) + ); + } - /** - * For a given id_product and id_product_attribute sets the quantity available - * - * @param int $id_product - * @param int $id_product_attribute Optional - * @param int $delta_quantity The delta quantity to update - * @param int $id_shop Optional - */ - public static function setQuantity($id_product, $id_product_attribute, $quantity, $id_shop = null) - { - if (!Validate::isUnsignedId($id_product)) - return false; + Cache::clean('StockAvailable::getQuantityAvailableByProduct_'.(int)$id_product.'*'); + } - $context = Context::getContext(); + /** + * Removes a given product from the stock available + * + * @param int $id_product + * @param int|null $id_product_attribute Optional + * @param Shop|null $shop Shop id or shop object Optional + * + * @return bool + */ + public static function removeProductFromStockAvailable($id_product, $id_product_attribute = null, $shop = null) + { + if (!Validate::isUnsignedId($id_product)) { + return false; + } - // if there is no $id_shop, gets the context one - if ($id_shop === null && Shop::getContext() != Shop::CONTEXT_GROUP) - $id_shop = (int)$context->shop->id; + if (Shop::getContext() == SHOP::CONTEXT_SHOP) { + if (Shop::getContextShopGroup()->share_stock == 1) { + $pa_sql = ''; + if ($id_product_attribute !== null) { + $pa_sql = '_attribute'; + $id_product_attribute_sql = $id_product_attribute; + } else { + $id_product_attribute_sql = $id_product; + } - $depends_on_stock = StockAvailable::dependsOnStock($id_product); - - //Try to set available quantity if product does not depend on physical stock - if (!$depends_on_stock) - { - $id_stock_available = (int)StockAvailable::getStockAvailableIdByProductId($id_product, $id_product_attribute, $id_shop); - if ($id_stock_available) - { - $stock_available = new StockAvailable($id_stock_available); - $stock_available->quantity = (int)$quantity; - $stock_available->update(); - } - else - { - $out_of_stock = StockAvailable::outOfStock($id_product, $id_shop); - $stock_available = new StockAvailable(); - $stock_available->out_of_stock = (int)$out_of_stock; - $stock_available->id_product = (int)$id_product; - $stock_available->id_product_attribute = (int)$id_product_attribute; - $stock_available->quantity = (int)$quantity; - - if ($id_shop === null) - $shop_group = Shop::getContextShopGroup(); - else - $shop_group = new ShopGroup((int)Shop::getGroupFromShop((int)$id_shop)); - - // if quantities are shared between shops of the group - if ($shop_group->share_stock) - { - $stock_available->id_shop = 0; - $stock_available->id_shop_group = (int)$shop_group->id; - } - else - { - $stock_available->id_shop = (int)$id_shop; - $stock_available->id_shop_group = 0; - } - $stock_available->add(); - } - - Hook::exec('actionUpdateQuantity', - array( - 'id_product' => $id_product, - 'id_product_attribute' => $id_product_attribute, - 'quantity' => $stock_available->quantity - ) - ); - } - - Cache::clean('StockAvailable::getQuantityAvailableByProduct_'.(int)$id_product.'*'); - - } - - /** - * Removes a given product from the stock available - * - * @param int $id_product - * @param int|null $id_product_attribute Optional - * @param Shop|null $shop Shop id or shop object Optional - * - * @return bool - */ - public static function removeProductFromStockAvailable($id_product, $id_product_attribute = null, $shop = null) - { - if (!Validate::isUnsignedId($id_product)) - return false; - - if (Shop::getContext() == SHOP::CONTEXT_SHOP) - if (Shop::getContextShopGroup()->share_stock == 1) - { - $pa_sql = ''; - if ($id_product_attribute !== null) - { - $pa_sql = '_attribute'; - $id_product_attribute_sql = $id_product_attribute; - } - else - $id_product_attribute_sql = $id_product; - - if ((int)Db::getInstance()->getValue('SELECT COUNT(*) + if ((int)Db::getInstance()->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'product'.$pa_sql.'_shop WHERE id_product'.$pa_sql.'='.(int)$id_product_attribute_sql.' - AND id_shop IN ('.implode(',', array_map('intval', Shop::getContextListShopID(SHOP::SHARE_STOCK))).')')) - return true; - } + AND id_shop IN ('.implode(',', array_map('intval', Shop::getContextListShopID(SHOP::SHARE_STOCK))).')')) { + return true; + } + } + } - $res = Db::getInstance()->execute(' + $res = Db::getInstance()->execute(' DELETE FROM '._DB_PREFIX_.'stock_available WHERE id_product = '.(int)$id_product. - ($id_product_attribute ? ' AND id_product_attribute = '.(int)$id_product_attribute : ''). - StockAvailable::addSqlShopRestriction(null, $shop)); + ($id_product_attribute ? ' AND id_product_attribute = '.(int)$id_product_attribute : ''). + StockAvailable::addSqlShopRestriction(null, $shop)); - if ($id_product_attribute) - { - if ($shop === null || !Validate::isLoadedObject($shop)) - { - $shop_datas = array(); - StockAvailable::addSqlShopParams($shop_datas); - $id_shop = (int)$shop_datas['id_shop']; - } - else - $id_shop = (int)$shop->id; + if ($id_product_attribute) { + if ($shop === null || !Validate::isLoadedObject($shop)) { + $shop_datas = array(); + StockAvailable::addSqlShopParams($shop_datas); + $id_shop = (int)$shop_datas['id_shop']; + } else { + $id_shop = (int)$shop->id; + } - $stock_available = new StockAvailable(); - $stock_available->id_product = (int)$id_product; - $stock_available->id_product_attribute = (int)$id_product_attribute; - $stock_available->id_shop = (int)$id_shop; - $stock_available->postSave(); - } + $stock_available = new StockAvailable(); + $stock_available->id_product = (int)$id_product; + $stock_available->id_product_attribute = (int)$id_product_attribute; + $stock_available->id_shop = (int)$id_shop; + $stock_available->postSave(); + } - Cache::clean('StockAvailable::getQuantityAvailableByProduct_'.(int)$id_product.'*'); + Cache::clean('StockAvailable::getQuantityAvailableByProduct_'.(int)$id_product.'*'); - return $res; - } + return $res; + } - /** - * Removes all product quantities from all a group of shops - * If stocks are shared, remoe all old available quantities for all shops of the group - * Else remove all available quantities for the current group - * - * @param ShopGroup $shop_group the ShopGroup object - */ - public static function resetProductFromStockAvailableByShopGroup(ShopGroup $shop_group) - { - if ($shop_group->share_stock) - { - $shop_list = Shop::getShops(false, $shop_group->id, true); + /** + * Removes all product quantities from all a group of shops + * If stocks are shared, remoe all old available quantities for all shops of the group + * Else remove all available quantities for the current group + * + * @param ShopGroup $shop_group the ShopGroup object + */ + public static function resetProductFromStockAvailableByShopGroup(ShopGroup $shop_group) + { + if ($shop_group->share_stock) { + $shop_list = Shop::getShops(false, $shop_group->id, true); + } - if (count($shop_list) > 0) - { - $id_shops_list = implode(', ', $shop_list); + if (count($shop_list) > 0) { + $id_shops_list = implode(', ', $shop_list); + return Db::getInstance()->update('stock_available', array('quantity' => 0), 'id_shop IN ('.$id_shops_list.')'); + } else { + return Db::getInstance()->update('stock_available', array('quantity' => 0), 'id_shop_group = '.$shop_group->id); + } + } - return Db::getInstance()->execute(' - DELETE FROM '._DB_PREFIX_.'stock_available - WHERE id_shop IN ('.$id_shops_list.')' - ); - } - } - else - { - return Db::getInstance()->execute(' - DELETE FROM '._DB_PREFIX_.'stock_available - WHERE id_shop_group = '.$shop_group->id - ); - } - } + /** + * For a given product, tells if it depends on the physical (usable) stock + * + * @param int $id_product + * @param int $id_shop Optional : gets context if null @see Context::getContext() + * @return bool : depends on stock @see $depends_on_stock + */ + public static function dependsOnStock($id_product, $id_shop = null) + { + if (!Validate::isUnsignedId($id_product)) { + return false; + } - /** - * For a given product, tells if it depends on the physical (usable) stock - * - * @param int $id_product - * @param int $id_shop Optional : gets context if null @see Context::getContext() - * @return bool : depends on stock @see $depends_on_stock - */ - public static function dependsOnStock($id_product, $id_shop = null) - { - if (!Validate::isUnsignedId($id_product)) - return false; + $query = new DbQuery(); + $query->select('depends_on_stock'); + $query->from('stock_available'); + $query->where('id_product = '.(int)$id_product); + $query->where('id_product_attribute = 0'); - $query = new DbQuery(); - $query->select('depends_on_stock'); - $query->from('stock_available'); - $query->where('id_product = '.(int)$id_product); - $query->where('id_product_attribute = 0'); + $query = StockAvailable::addSqlShopRestriction($query, $id_shop); - $query = StockAvailable::addSqlShopRestriction($query, $id_shop); + return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } - return (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + /** + * For a given product, get its "out of stock" flag + * + * @param int $id_product + * @param int $id_shop Optional : gets context if null @see Context::getContext() + * @return bool : depends on stock @see $depends_on_stock + */ + public static function outOfStock($id_product, $id_shop = null) + { + if (!Validate::isUnsignedId($id_product)) { + return false; + } - /** - * For a given product, get its "out of stock" flag - * - * @param int $id_product - * @param int $id_shop Optional : gets context if null @see Context::getContext() - * @return bool : depends on stock @see $depends_on_stock - */ - public static function outOfStock($id_product, $id_shop = null) - { - if (!Validate::isUnsignedId($id_product)) - return false; + $query = new DbQuery(); + $query->select('out_of_stock'); + $query->from('stock_available'); + $query->where('id_product = '.(int)$id_product); + $query->where('id_product_attribute = 0'); - $query = new DbQuery(); - $query->select('out_of_stock'); - $query->from('stock_available'); - $query->where('id_product = '.(int)$id_product); - $query->where('id_product_attribute = 0'); + $query = StockAvailable::addSqlShopRestriction($query, $id_shop); - $query = StockAvailable::addSqlShopRestriction($query, $id_shop); + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + /** + * Add an sql restriction for shops fields - specific to StockAvailable + * + * @param DbQuery|string|null $sql Reference to the query object + * @param Shop|int|null $shop Optional : The shop ID + * @param string|null $alias Optional : The current table alias + * + * @return string|DbQuery DbQuery object or the sql restriction string + */ + public static function addSqlShopRestriction($sql = null, $shop = null, $alias = null) + { + $context = Context::getContext(); - /** - * Add an sql restriction for shops fields - specific to StockAvailable - * - * @param DbQuery|string|null $sql Reference to the query object - * @param Shop|int|null $shop Optional : The shop ID - * @param string|null $alias Optional : The current table alias - * - * @return string|DbQuery DbQuery object or the sql restriction string - */ - public static function addSqlShopRestriction($sql = null, $shop = null, $alias = null) - { - $context = Context::getContext(); + if (!empty($alias)) { + $alias .= '.'; + } - if (!empty($alias)) - $alias .= '.'; + // if there is no $id_shop, gets the context one + // get shop group too + if ($shop === null || $shop === $context->shop->id) { + if (Shop::getContext() == Shop::CONTEXT_GROUP) { + $shop_group = Shop::getContextShopGroup(); + } else { + $shop_group = $context->shop->getGroup(); + } + $shop = $context->shop; + } elseif (is_object($shop)) { + /** @var Shop $shop */ + $shop_group = $shop->getGroup(); + } else { + $shop = new Shop($shop); + $shop_group = $shop->getGroup(); + } - // if there is no $id_shop, gets the context one - // get shop group too - if ($shop === null || $shop === $context->shop->id) - { - if (Shop::getContext() == Shop::CONTEXT_GROUP) - $shop_group = Shop::getContextShopGroup(); - else - $shop_group = $context->shop->getGroup(); - $shop = $context->shop; - } - elseif (is_object($shop)) - { - /** @var Shop $shop */ - $shop_group = $shop->getGroup(); - } - else - { - $shop = new Shop($shop); - $shop_group = $shop->getGroup(); - } + // if quantities are shared between shops of the group + if ($shop_group->share_stock) { + if (is_object($sql)) { + $sql->where(pSQL($alias).'id_shop_group = '.(int)$shop_group->id); + $sql->where(pSQL($alias).'id_shop = 0'); + } else { + $sql = ' AND '.pSQL($alias).'id_shop_group = '.(int)$shop_group->id.' '; + $sql .= ' AND '.pSQL($alias).'id_shop = 0 '; + } + } else { + if (is_object($sql)) { + $sql->where(pSQL($alias).'id_shop = '.(int)$shop->id); + $sql->where(pSQL($alias).'id_shop_group = 0'); + } else { + $sql = ' AND '.pSQL($alias).'id_shop = '.(int)$shop->id.' '; + $sql .= ' AND '.pSQL($alias).'id_shop_group = 0 '; + } + } - // if quantities are shared between shops of the group - if ($shop_group->share_stock) - { - if (is_object($sql)) - { - $sql->where(pSQL($alias).'id_shop_group = '.(int)$shop_group->id); - $sql->where(pSQL($alias).'id_shop = 0'); - } - else - { - $sql = ' AND '.pSQL($alias).'id_shop_group = '.(int)$shop_group->id.' '; - $sql .= ' AND '.pSQL($alias).'id_shop = 0 '; - } - } - else - { - if (is_object($sql)) - { - $sql->where(pSQL($alias).'id_shop = '.(int)$shop->id); - $sql->where(pSQL($alias).'id_shop_group = 0'); - } - else - { - $sql = ' AND '.pSQL($alias).'id_shop = '.(int)$shop->id.' '; - $sql .= ' AND '.pSQL($alias).'id_shop_group = 0 '; - } - } + return $sql; + } - return $sql; - } + /** + * Add sql params for shops fields - specific to StockAvailable + * + * @param array $params Reference to the params array + * @param int $id_shop Optional : The shop ID + * + */ + public static function addSqlShopParams(&$params, $id_shop = null) + { + $context = Context::getContext(); + $group_ok = false; - /** - * Add sql params for shops fields - specific to StockAvailable - * - * @param array $params Reference to the params array - * @param int $id_shop Optional : The shop ID - * - */ - public static function addSqlShopParams(&$params, $id_shop = null) - { - $context = Context::getContext(); - $group_ok = false; + // if there is no $id_shop, gets the context one + // get shop group too + if ($id_shop === null) { + if (Shop::getContext() == Shop::CONTEXT_GROUP) { + $shop_group = Shop::getContextShopGroup(); + } else { + $shop_group = $context->shop->getGroup(); + $id_shop = $context->shop->id; + } + } else { + $shop = new Shop($id_shop); + $shop_group = $shop->getGroup(); + } - // if there is no $id_shop, gets the context one - // get shop group too - if ($id_shop === null) - { - if (Shop::getContext() == Shop::CONTEXT_GROUP) - $shop_group = Shop::getContextShopGroup(); - else - { - $shop_group = $context->shop->getGroup(); - $id_shop = $context->shop->id; - } - } - else - { - $shop = new Shop($id_shop); - $shop_group = $shop->getGroup(); - } + // if quantities are shared between shops of the group + if ($shop_group->share_stock) { + $params['id_shop_group'] = (int)$shop_group->id; + $params['id_shop'] = 0; - // if quantities are shared between shops of the group - if ($shop_group->share_stock) - { - $params['id_shop_group'] = (int)$shop_group->id; - $params['id_shop'] = 0; + $group_ok = true; + } else { + $params['id_shop_group'] = 0; + } - $group_ok = true; - } - else - $params['id_shop_group'] = 0; + // if no group specific restriction, set simple shop restriction + if (!$group_ok) { + $params['id_shop'] = (int)$id_shop; + } + } - // if no group specific restriction, set simple shop restriction - if (!$group_ok) - $params['id_shop'] = (int)$id_shop; - } + /** + * Copies stock available content table + * + * @param int $src_shop_id + * @param int $dst_shop_id + * @return bool + */ + public static function copyStockAvailableFromShopToShop($src_shop_id, $dst_shop_id) + { + if (!$src_shop_id || !$dst_shop_id) { + return false; + } - /** - * Copies stock available content table - * - * @param int $src_shop_id - * @param int $dst_shop_id - * @return bool - */ - public static function copyStockAvailableFromShopToShop($src_shop_id, $dst_shop_id) - { - if (!$src_shop_id || !$dst_shop_id) - return false; - - $query = ' + $query = ' INSERT INTO '._DB_PREFIX_.'stock_available ( id_product, @@ -865,8 +796,8 @@ class StockAvailableCore extends ObjectModel SELECT id_product, id_product_attribute, '.(int)$dst_shop_id.', 0, quantity, depends_on_stock, out_of_stock FROM '._DB_PREFIX_.'stock_available WHERE id_shop = '.(int)$src_shop_id. - ')'; + ')'; - return Db::getInstance()->execute($query); - } + return Db::getInstance()->execute($query); + } } diff --git a/classes/stock/StockManager.php b/classes/stock/StockManager.php index ec5ea91e..ec831dac 100644 --- a/classes/stock/StockManager.php +++ b/classes/stock/StockManager.php @@ -30,328 +30,326 @@ */ class StockManagerCore implements StockManagerInterface { + /** + * @see StockManagerInterface::isAvailable() + */ + public static function isAvailable() + { + // Default Manager : always available + return true; + } - /** - * @see StockManagerInterface::isAvailable() - */ - public static function isAvailable() - { - // Default Manager : always available - return true; - } + /** + * @see StockManagerInterface::addProduct() + * + * @param int $id_product + * @param int $id_product_attribute + * @param Warehouse $warehouse + * @param int $quantity + * @param int $id_stock_mvt_reason + * @param float $price_te + * @param bool $is_usable + * @param int|null $id_supply_order + * @param Employee|null $employee + * + * @return bool + * @throws PrestaShopException + */ + public function addProduct( + $id_product, + $id_product_attribute = 0, + Warehouse $warehouse, + $quantity, + $id_stock_mvt_reason, + $price_te, + $is_usable = true, + $id_supply_order = null, + $employee = null + ) { + if (!Validate::isLoadedObject($warehouse) || (!is_int($price_te) && !is_float($price_te)) + || !$quantity || !$id_product) { + return false; + } - /** - * @see StockManagerInterface::addProduct() - * - * @param int $id_product - * @param int $id_product_attribute - * @param Warehouse $warehouse - * @param int $quantity - * @param int $id_stock_mvt_reason - * @param float $price_te - * @param bool $is_usable - * @param int|null $id_supply_order - * @param Employee|null $employee - * - * @return bool - * @throws PrestaShopException - */ - public function addProduct($id_product, - $id_product_attribute = 0, - Warehouse $warehouse, - $quantity, - $id_stock_mvt_reason, - $price_te, - $is_usable = true, - $id_supply_order = null, - $employee = null - ) - { - if (!Validate::isLoadedObject($warehouse) || !$price_te || !$quantity || !$id_product) - return false; + $price_te = (float)round($price_te, 6); - $price_te = (float)round($price_te, 6); + if (!StockMvtReason::exists($id_stock_mvt_reason)) { + $id_stock_mvt_reason = Configuration::get('PS_STOCK_MVT_INC_REASON_DEFAULT'); + } - if (!StockMvtReason::exists($id_stock_mvt_reason)) - $id_stock_mvt_reason = Configuration::get('PS_STOCK_MVT_INC_REASON_DEFAULT'); + $context = Context::getContext(); - $context = Context::getContext(); + $mvt_params = array( + 'id_stock' => null, + 'physical_quantity' => $quantity, + 'id_stock_mvt_reason' => $id_stock_mvt_reason, + 'id_supply_order' => $id_supply_order, + 'price_te' => $price_te, + 'last_wa' => null, + 'current_wa' => null, + 'id_employee' => (int)$context->employee->id ? (int)$context->employee->id : $employee->id, + 'employee_firstname' => $context->employee->firstname ? $context->employee->firstname : $employee->firstname, + 'employee_lastname' => $context->employee->lastname ? $context->employee->lastname : $employee->lastname, + 'sign' => 1 + ); - $mvt_params = array( - 'id_stock' => null, - 'physical_quantity' => $quantity, - 'id_stock_mvt_reason' => $id_stock_mvt_reason, - 'id_supply_order' => $id_supply_order, - 'price_te' => $price_te, - 'last_wa' => null, - 'current_wa' => null, - 'id_employee' => (int)$context->employee->id ? (int)$context->employee->id : $employee->id, - 'employee_firstname' => $context->employee->firstname ? $context->employee->firstname : $employee->firstname, - 'employee_lastname' => $context->employee->lastname ? $context->employee->lastname : $employee->lastname, - 'sign' => 1 - ); + $stock_exists = false; - $stock_exists = false; + // switch on MANAGEMENT_TYPE + switch ($warehouse->management_type) { + // case CUMP mode + case 'WA': - // switch on MANAGEMENT_TYPE - switch ($warehouse->management_type) - { - // case CUMP mode - case 'WA': + $stock_collection = $this->getStockCollection($id_product, $id_product_attribute, $warehouse->id); - $stock_collection = $this->getStockCollection($id_product, $id_product_attribute, $warehouse->id); + // if this product is already in stock + if (count($stock_collection) > 0) { + $stock_exists = true; - // if this product is already in stock - if (count($stock_collection) > 0) - { - $stock_exists = true; + /** @var Stock $stock */ + // for a warehouse using WA, there is one and only one stock for a given product + $stock = $stock_collection->current(); - /** @var Stock $stock */ - // for a warehouse using WA, there is one and only one stock for a given product - $stock = $stock_collection->current(); + // calculates WA price + $last_wa = $stock->price_te; + $current_wa = $this->calculateWA($stock, $quantity, $price_te); - // calculates WA price - $last_wa = $stock->price_te; - $current_wa = $this->calculateWA($stock, $quantity, $price_te); + $mvt_params['id_stock'] = $stock->id; + $mvt_params['last_wa'] = $last_wa; + $mvt_params['current_wa'] = $current_wa; - $mvt_params['id_stock'] = $stock->id; - $mvt_params['last_wa'] = $last_wa; - $mvt_params['current_wa'] = $current_wa; + $stock_params = array( + 'physical_quantity' => ($stock->physical_quantity + $quantity), + 'price_te' => $current_wa, + 'usable_quantity' => ($is_usable ? ($stock->usable_quantity + $quantity) : $stock->usable_quantity), + 'id_warehouse' => $warehouse->id, + ); - $stock_params = array( - 'physical_quantity' => ($stock->physical_quantity + $quantity), - 'price_te' => $current_wa, - 'usable_quantity' => ($is_usable ? ($stock->usable_quantity + $quantity) : $stock->usable_quantity), - 'id_warehouse' => $warehouse->id, - ); + // saves stock in warehouse + $stock->hydrate($stock_params); + $stock->update(); + } else { + // else, the product is not in sock - // saves stock in warehouse - $stock->hydrate($stock_params); - $stock->update(); - } - else // else, the product is not in sock - { - $mvt_params['last_wa'] = 0; - $mvt_params['current_wa'] = $price_te; - } - break; + $mvt_params['last_wa'] = 0; + $mvt_params['current_wa'] = $price_te; + } + break; - // case FIFO / LIFO mode - case 'FIFO': - case 'LIFO': + // case FIFO / LIFO mode + case 'FIFO': + case 'LIFO': - $stock_collection = $this->getStockCollection($id_product, $id_product_attribute, $warehouse->id, $price_te); + $stock_collection = $this->getStockCollection($id_product, $id_product_attribute, $warehouse->id, $price_te); - // if this product is already in stock - if (count($stock_collection) > 0) - { - $stock_exists = true; + // if this product is already in stock + if (count($stock_collection) > 0) { + $stock_exists = true; - /** @var Stock $stock */ - // there is one and only one stock for a given product in a warehouse and at the current unit price - $stock = $stock_collection->current(); + /** @var Stock $stock */ + // there is one and only one stock for a given product in a warehouse and at the current unit price + $stock = $stock_collection->current(); - $stock_params = array( - 'physical_quantity' => ($stock->physical_quantity + $quantity), - 'usable_quantity' => ($is_usable ? ($stock->usable_quantity + $quantity) : $stock->usable_quantity), - ); + $stock_params = array( + 'physical_quantity' => ($stock->physical_quantity + $quantity), + 'usable_quantity' => ($is_usable ? ($stock->usable_quantity + $quantity) : $stock->usable_quantity), + ); - // updates stock in warehouse - $stock->hydrate($stock_params); - $stock->update(); + // updates stock in warehouse + $stock->hydrate($stock_params); + $stock->update(); - // sets mvt_params - $mvt_params['id_stock'] = $stock->id; + // sets mvt_params + $mvt_params['id_stock'] = $stock->id; + } - } + break; - break; + default: + return false; + break; + } - default: - return false; - break; - } + if (!$stock_exists) { + $stock = new Stock(); - if (!$stock_exists) - { - $stock = new Stock(); + $stock_params = array( + 'id_product_attribute' => $id_product_attribute, + 'id_product' => $id_product, + 'physical_quantity' => $quantity, + 'price_te' => $price_te, + 'usable_quantity' => ($is_usable ? $quantity : 0), + 'id_warehouse' => $warehouse->id + ); - $stock_params = array( - 'id_product_attribute' => $id_product_attribute, - 'id_product' => $id_product, - 'physical_quantity' => $quantity, - 'price_te' => $price_te, - 'usable_quantity' => ($is_usable ? $quantity : 0), - 'id_warehouse' => $warehouse->id - ); + // saves stock in warehouse + $stock->hydrate($stock_params); + $stock->add(); + $mvt_params['id_stock'] = $stock->id; + } - // saves stock in warehouse - $stock->hydrate($stock_params); - $stock->add(); - $mvt_params['id_stock'] = $stock->id; - } + // saves stock mvt + $stock_mvt = new StockMvt(); + $stock_mvt->hydrate($mvt_params); + $stock_mvt->add(); - // saves stock mvt - $stock_mvt = new StockMvt(); - $stock_mvt->hydrate($mvt_params); - $stock_mvt->add(); + return true; + } - return true; - } + /** + * @see StockManagerInterface::removeProduct() + * + * @param int $id_product + * @param int|null $id_product_attribute + * @param Warehouse $warehouse + * @param int $quantity + * @param int $id_stock_mvt_reason + * @param bool $is_usable + * @param int|null $id_order + * @param int $ignore_pack + * @param Employee|null $employee + * + * @return array + * @throws PrestaShopException + */ + public function removeProduct($id_product, + $id_product_attribute = null, + Warehouse $warehouse, + $quantity, + $id_stock_mvt_reason, + $is_usable = true, + $id_order = null, + $ignore_pack = 0, + $employee = null) + { + $return = array(); - /** - * @see StockManagerInterface::removeProduct() - * - * @param int $id_product - * @param int|null $id_product_attribute - * @param Warehouse $warehouse - * @param int $quantity - * @param int $id_stock_mvt_reason - * @param bool $is_usable - * @param int|null $id_order - * @param int $ignore_pack - * @param Employee|null $employee - * - * @return array - * @throws PrestaShopException - */ - public function removeProduct($id_product, - $id_product_attribute = null, - Warehouse $warehouse, - $quantity, - $id_stock_mvt_reason, - $is_usable = true, - $id_order = null, - $ignore_pack = 0, - $employee = null) - { - $return = array(); + if (!Validate::isLoadedObject($warehouse) || !$quantity || !$id_product) { + return $return; + } - if (!Validate::isLoadedObject($warehouse) || !$quantity || !$id_product) - return $return; + if (!StockMvtReason::exists($id_stock_mvt_reason)) { + $id_stock_mvt_reason = Configuration::get('PS_STOCK_MVT_DEC_REASON_DEFAULT'); + } - if (!StockMvtReason::exists($id_stock_mvt_reason)) - $id_stock_mvt_reason = Configuration::get('PS_STOCK_MVT_DEC_REASON_DEFAULT'); + $context = Context::getContext(); - $context = Context::getContext(); + // Special case of a pack + if (Pack::isPack((int)$id_product) && !$ignore_pack) { + if (Validate::isLoadedObject($product = new Product((int)$id_product))) { + // Gets items + if ($product->pack_stock_type == 1 || $product->pack_stock_type == 2 || ($product->pack_stock_type == 3 && Configuration::get('PS_PACK_STOCK_TYPE') > 0)) { + $products_pack = Pack::getItems((int)$id_product, (int)Configuration::get('PS_LANG_DEFAULT')); + // Foreach item + foreach ($products_pack as $product_pack) { + if ($product_pack->advanced_stock_management == 1) { + $product_warehouses = Warehouse::getProductWarehouseList($product_pack->id, $product_pack->id_pack_product_attribute); + $warehouse_stock_found = false; + foreach ($product_warehouses as $product_warehouse) { + if (!$warehouse_stock_found) { + if (Warehouse::exists($product_warehouse['id_warehouse'])) { + $current_warehouse = new Warehouse($product_warehouse['id_warehouse']); + $return[] = $this->removeProduct($product_pack->id, $product_pack->id_pack_product_attribute, $current_warehouse, $product_pack->pack_quantity * $quantity, $id_stock_mvt_reason, $is_usable, $id_order); - // Special case of a pack - if (Pack::isPack((int)$id_product) && !$ignore_pack) - { - if (Validate::isLoadedObject($product = new Product((int)$id_product))) - { - // Gets items - if ($product->pack_stock_type == 1 || $product->pack_stock_type == 2 || ($product->pack_stock_type == 3 && Configuration::get('PS_PACK_STOCK_TYPE') > 0)) - { - $products_pack = Pack::getItems((int)$id_product, (int)Configuration::get('PS_LANG_DEFAULT')); - // Foreach item - foreach ($products_pack as $product_pack) - if ($product_pack->advanced_stock_management == 1) - { - $product_warehouses = Warehouse::getProductWarehouseList($product_pack->id); - $warehouse_stock_found = false; - foreach ($product_warehouses as $product_warehouse) - if (!$warehouse_stock_found) - if (Warehouse::exists($product_warehouse['id_warehouse'])) - { - $current_warehouse = new Warehouse($product_warehouse['id_warehouse']); - $return[] = $this->removeProduct($product_pack->id, $product_pack->id_pack_product_attribute, $current_warehouse, $product_pack->pack_quantity * $quantity, $id_stock_mvt_reason, $is_usable, $id_order); + // The product was found on this warehouse. Stop the stock searching. + $warehouse_stock_found = !empty($return[count($return) - 1]); + } + } + } + } + } + } + if ($product->pack_stock_type == 0 || $product->pack_stock_type == 2 || + ($product->pack_stock_type == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 0 || Configuration::get('PS_PACK_STOCK_TYPE') == 2))) { + $return = array_merge($return, $this->removeProduct($id_product, $id_product_attribute, $warehouse, $quantity, $id_stock_mvt_reason, $is_usable, $id_order, 1)); + } + } else { + return false; + } + } else { + // gets total quantities in stock for the current product + $physical_quantity_in_stock = (int)$this->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id), false); + $usable_quantity_in_stock = (int)$this->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id), true); - // The product was found on this warehouse. Stop the stock searching. - $warehouse_stock_found = !empty($return[count($return) - 1]); - } - } - } - if ($product->pack_stock_type == 0 || $product->pack_stock_type == 2 || - ($product->pack_stock_type == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 0 || Configuration::get('PS_PACK_STOCK_TYPE') == 2))) - $return = array_merge($return, $this->removeProduct($id_product, $id_product_attribute, $warehouse, $quantity, $id_stock_mvt_reason, $is_usable, $id_order, 1)); - } - else - return false; - } - else - { - // gets total quantities in stock for the current product - $physical_quantity_in_stock = (int)$this->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id), false); - $usable_quantity_in_stock = (int)$this->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id), true); + // check quantity if we want to decrement unusable quantity + if (!$is_usable) { + $quantity_in_stock = $physical_quantity_in_stock - $usable_quantity_in_stock; + } else { + $quantity_in_stock = $usable_quantity_in_stock; + } - // check quantity if we want to decrement unusable quantity - if (!$is_usable) - $quantity_in_stock = $physical_quantity_in_stock - $usable_quantity_in_stock; - else - $quantity_in_stock = $usable_quantity_in_stock; + // checks if it's possible to remove the given quantity + if ($quantity_in_stock < $quantity) { + return $return; + } - // checks if it's possible to remove the given quantity - if ($quantity_in_stock < $quantity) - return $return; + $stock_collection = $this->getStockCollection($id_product, $id_product_attribute, $warehouse->id); + $stock_collection->getAll(); - $stock_collection = $this->getStockCollection($id_product, $id_product_attribute, $warehouse->id); - $stock_collection->getAll(); + // check if the collection is loaded + if (count($stock_collection) <= 0) { + return $return; + } - // check if the collection is loaded - if (count($stock_collection) <= 0) - return $return; + $stock_history_qty_available = array(); + $mvt_params = array(); + $stock_params = array(); + $quantity_to_decrement_by_stock = array(); + $global_quantity_to_decrement = $quantity; - $stock_history_qty_available = array(); - $mvt_params = array(); - $stock_params = array(); - $quantity_to_decrement_by_stock = array(); - $global_quantity_to_decrement = $quantity; + // switch on MANAGEMENT_TYPE + switch ($warehouse->management_type) { + // case CUMP mode + case 'WA': + /** @var Stock $stock */ + // There is one and only one stock for a given product in a warehouse in this mode + $stock = $stock_collection->current(); - // switch on MANAGEMENT_TYPE - switch ($warehouse->management_type) - { - // case CUMP mode - case 'WA': - /** @var Stock $stock */ - // There is one and only one stock for a given product in a warehouse in this mode - $stock = $stock_collection->current(); + $mvt_params = array( + 'id_stock' => $stock->id, + 'physical_quantity' => $quantity, + 'id_stock_mvt_reason' => $id_stock_mvt_reason, + 'id_order' => $id_order, + 'price_te' => $stock->price_te, + 'last_wa' => $stock->price_te, + 'current_wa' => $stock->price_te, + 'id_employee' => (int)$context->employee->id ? (int)$context->employee->id : $employee->id, + 'employee_firstname' => $context->employee->firstname ? $context->employee->firstname : $employee->firstname, + 'employee_lastname' => $context->employee->lastname ? $context->employee->lastname : $employee->lastname, + 'sign' => -1 + ); + $stock_params = array( + 'physical_quantity' => ($stock->physical_quantity - $quantity), + 'usable_quantity' => ($is_usable ? ($stock->usable_quantity - $quantity) : $stock->usable_quantity) + ); - $mvt_params = array( - 'id_stock' => $stock->id, - 'physical_quantity' => $quantity, - 'id_stock_mvt_reason' => $id_stock_mvt_reason, - 'id_order' => $id_order, - 'price_te' => $stock->price_te, - 'last_wa' => $stock->price_te, - 'current_wa' => $stock->price_te, - 'id_employee' => (int)$context->employee->id ? (int)$context->employee->id : $employee->id, - 'employee_firstname' => $context->employee->firstname ? $context->employee->firstname : $employee->firstname, - 'employee_lastname' => $context->employee->lastname ? $context->employee->lastname : $employee->lastname, - 'sign' => -1 - ); - $stock_params = array( - 'physical_quantity' => ($stock->physical_quantity - $quantity), - 'usable_quantity' => ($is_usable ? ($stock->usable_quantity - $quantity) : $stock->usable_quantity) - ); + // saves stock in warehouse + $stock->hydrate($stock_params); + $stock->update(); - // saves stock in warehouse - $stock->hydrate($stock_params); - $stock->update(); + // saves stock mvt + $stock_mvt = new StockMvt(); + $stock_mvt->hydrate($mvt_params); + $stock_mvt->save(); - // saves stock mvt - $stock_mvt = new StockMvt(); - $stock_mvt->hydrate($mvt_params); - $stock_mvt->save(); + $return[$stock->id]['quantity'] = $quantity; + $return[$stock->id]['price_te'] = $stock->price_te; - $return[$stock->id]['quantity'] = $quantity; - $return[$stock->id]['price_te'] = $stock->price_te; + break; - break; + case 'LIFO': + case 'FIFO': - case 'LIFO': - case 'FIFO': + // for each stock, parse its mvts history to calculate the quantities left for each positive mvt, + // according to the instant available quantities for this stock + foreach ($stock_collection as $stock) { + /** @var Stock $stock */ + $left_quantity_to_check = $stock->physical_quantity; + if ($left_quantity_to_check <= 0) { + continue; + } - // for each stock, parse its mvts history to calculate the quantities left for each positive mvt, - // according to the instant available quantities for this stock - foreach ($stock_collection as $stock) - { - /** @var Stock $stock */ - $left_quantity_to_check = $stock->physical_quantity; - if ($left_quantity_to_check <= 0) - continue; - - $resource = Db::getInstance(_PS_USE_SQL_SLAVE_)->query(' + $resource = Db::getInstance(_PS_USE_SQL_SLAVE_)->query(' SELECT sm.`id_stock_mvt`, sm.`date_add`, sm.`physical_quantity`, IF ((sm2.`physical_quantity` is null), sm.`physical_quantity`, (sm.`physical_quantity` - SUM(sm2.`physical_quantity`))) as qty FROM `'._DB_PREFIX_.'stock_mvt` sm @@ -360,329 +358,381 @@ class StockManagerCore implements StockManagerInterface AND sm.`id_stock` = '.(int)$stock->id.' GROUP BY sm.`id_stock_mvt` ORDER BY sm.`date_add` DESC' - ); + ); - while ($row = Db::getInstance()->nextRow($resource)) - { - // break - in FIFO mode, we have to retreive the oldest positive mvts for which there are left quantities - if ($warehouse->management_type == 'FIFO') - if ($row['qty'] == 0) - break; + while ($row = Db::getInstance()->nextRow($resource)) { + // break - in FIFO mode, we have to retreive the oldest positive mvts for which there are left quantities + if ($warehouse->management_type == 'FIFO') { + if ($row['qty'] == 0) { + break; + } + } - // converts date to timestamp - $date = new DateTime($row['date_add']); - $timestamp = $date->format('U'); + // converts date to timestamp + $date = new DateTime($row['date_add']); + $timestamp = $date->format('U'); - // history of the mvt - $stock_history_qty_available[$timestamp] = array( - 'id_stock' => $stock->id, - 'id_stock_mvt' => (int)$row['id_stock_mvt'], - 'qty' => (int)$row['qty'] - ); + // history of the mvt + $stock_history_qty_available[$timestamp] = array( + 'id_stock' => $stock->id, + 'id_stock_mvt' => (int)$row['id_stock_mvt'], + 'qty' => (int)$row['qty'] + ); - // break - in LIFO mode, checks only the necessary history to handle the global quantity for the current stock - if ($warehouse->management_type == 'LIFO') - { - $left_quantity_to_check -= (int)$row['qty']; - if ($left_quantity_to_check <= 0) - break; - } - } - } + // break - in LIFO mode, checks only the necessary history to handle the global quantity for the current stock + if ($warehouse->management_type == 'LIFO') { + $left_quantity_to_check -= (int)$row['qty']; + if ($left_quantity_to_check <= 0) { + break; + } + } + } + } - if ($warehouse->management_type == 'LIFO') - // orders stock history by timestamp to get newest history first - krsort($stock_history_qty_available); - else - // orders stock history by timestamp to get oldest history first - ksort($stock_history_qty_available); + if ($warehouse->management_type == 'LIFO') { + // orders stock history by timestamp to get newest history first + krsort($stock_history_qty_available); + } else { + // orders stock history by timestamp to get oldest history first + ksort($stock_history_qty_available); + } - // checks each stock to manage the real quantity to decrement for each of them - foreach ($stock_history_qty_available as $entry) - { - if ($entry['qty'] >= $global_quantity_to_decrement) - { - $quantity_to_decrement_by_stock[$entry['id_stock']][$entry['id_stock_mvt']] = $global_quantity_to_decrement; - $global_quantity_to_decrement = 0; - } - else - { - $quantity_to_decrement_by_stock[$entry['id_stock']][$entry['id_stock_mvt']] = $entry['qty']; - $global_quantity_to_decrement -= $entry['qty']; - } + // checks each stock to manage the real quantity to decrement for each of them + foreach ($stock_history_qty_available as $entry) { + if ($entry['qty'] >= $global_quantity_to_decrement) { + $quantity_to_decrement_by_stock[$entry['id_stock']][$entry['id_stock_mvt']] = $global_quantity_to_decrement; + $global_quantity_to_decrement = 0; + } else { + $quantity_to_decrement_by_stock[$entry['id_stock']][$entry['id_stock_mvt']] = $entry['qty']; + $global_quantity_to_decrement -= $entry['qty']; + } - if ($global_quantity_to_decrement <= 0) - break; - } + if ($global_quantity_to_decrement <= 0) { + break; + } + } - // for each stock, decrements it and logs the mvts - foreach ($stock_collection as $stock) - { - if (array_key_exists($stock->id, $quantity_to_decrement_by_stock) && is_array($quantity_to_decrement_by_stock[$stock->id])) - { - $total_quantity_for_current_stock = 0; + // for each stock, decrements it and logs the mvts + foreach ($stock_collection as $stock) { + if (array_key_exists($stock->id, $quantity_to_decrement_by_stock) && is_array($quantity_to_decrement_by_stock[$stock->id])) { + $total_quantity_for_current_stock = 0; - foreach ($quantity_to_decrement_by_stock[$stock->id] as $id_mvt_referrer => $qte) - { - $mvt_params = array( - 'id_stock' => $stock->id, - 'physical_quantity' => $qte, - 'id_stock_mvt_reason' => $id_stock_mvt_reason, - 'id_order' => $id_order, - 'price_te' => $stock->price_te, - 'sign' => -1, - 'referer' => $id_mvt_referrer, - 'id_employee' => (int)$context->employee->id ? (int)$context->employee->id : $employee->id, - ); + foreach ($quantity_to_decrement_by_stock[$stock->id] as $id_mvt_referrer => $qte) { + $mvt_params = array( + 'id_stock' => $stock->id, + 'physical_quantity' => $qte, + 'id_stock_mvt_reason' => $id_stock_mvt_reason, + 'id_order' => $id_order, + 'price_te' => $stock->price_te, + 'sign' => -1, + 'referer' => $id_mvt_referrer, + 'id_employee' => (int)$context->employee->id ? (int)$context->employee->id : $employee->id, + ); - // saves stock mvt - $stock_mvt = new StockMvt(); - $stock_mvt->hydrate($mvt_params); - $stock_mvt->save(); + // saves stock mvt + $stock_mvt = new StockMvt(); + $stock_mvt->hydrate($mvt_params); + $stock_mvt->save(); - $total_quantity_for_current_stock += $qte; - } + $total_quantity_for_current_stock += $qte; + } - $stock_params = array( - 'physical_quantity' => ($stock->physical_quantity - $total_quantity_for_current_stock), - 'usable_quantity' => ($is_usable ? ($stock->usable_quantity - $total_quantity_for_current_stock) : $stock->usable_quantity) - ); + $stock_params = array( + 'physical_quantity' => ($stock->physical_quantity - $total_quantity_for_current_stock), + 'usable_quantity' => ($is_usable ? ($stock->usable_quantity - $total_quantity_for_current_stock) : $stock->usable_quantity) + ); - $return[$stock->id]['quantity'] = $total_quantity_for_current_stock; - $return[$stock->id]['price_te'] = $stock->price_te; + $return[$stock->id]['quantity'] = $total_quantity_for_current_stock; + $return[$stock->id]['price_te'] = $stock->price_te; - // saves stock in warehouse - $stock->hydrate($stock_params); - $stock->update(); - } - } - break; - } - } + // saves stock in warehouse + $stock->hydrate($stock_params); + $stock->update(); + } + } + break; + } - // if we remove a usable quantity, exec hook - if ($is_usable) - Hook::exec('actionProductCoverage', - array( - 'id_product' => $id_product, - 'id_product_attribute' => $id_product_attribute, - 'warehouse' => $warehouse - ) - ); + if (Pack::isPacked($id_product, $id_product_attribute)) { + $packs = Pack::getPacksContainingItem($id_product, $id_product_attribute, (int)Configuration::get('PS_LANG_DEFAULT')); + foreach($packs as $pack) { + // Decrease stocks of the pack only if pack is in linked stock mode (option called 'Decrement both') + if (!((int)$pack->pack_stock_type == 2) && + !((int)$pack->pack_stock_type == 3 && (int)Configuration::get('PS_PACK_STOCK_TYPE') == 2) + ) { + continue; + } - return $return; - } + // Decrease stocks of the pack only if there is not enough items to constituate the actual pack stocks. + + // How many packs can be constituated with the remaining product stocks + $quantity_by_pack = $pack->pack_item_quantity; + $stock_available_quantity = $quantity_in_stock - $quantity; + $max_pack_quantity = max(array(0, floor($stock_available_quantity / $quantity_by_pack))); + $quantity_delta = Pack::getQuantity($pack->id) - $max_pack_quantity; - /** - * @see StockManagerInterface::getProductPhysicalQuantities() - */ - public function getProductPhysicalQuantities($id_product, $id_product_attribute, $ids_warehouse = null, $usable = false) - { - if (!is_null($ids_warehouse)) - { - // in case $ids_warehouse is not an array - if (!is_array($ids_warehouse)) - $ids_warehouse = array($ids_warehouse); + if ($pack->advanced_stock_management == 1 && $quantity_delta > 0) { + $product_warehouses = Warehouse::getPackWarehouses($pack->id); + $warehouse_stock_found = false; + foreach ($product_warehouses as $product_warehouse) { - // casts for security reason - $ids_warehouse = array_map('intval', $ids_warehouse); - if (!count($ids_warehouse)) - return 0; - } - else - $ids_warehouse = array(); + if (!$warehouse_stock_found) { + if (Warehouse::exists($product_warehouse)) { + $current_warehouse = new Warehouse($product_warehouse); + $return[] = $this->removeProduct($pack->id, null, $current_warehouse, $quantity_delta, $id_stock_mvt_reason, $is_usable, $id_order, 1); + // The product was found on this warehouse. Stop the stock searching. + $warehouse_stock_found = !empty($return[count($return) - 1]); + } + } + } + } + } + } + + + } + - $query = new DbQuery(); - $query->select('SUM('.($usable ? 's.usable_quantity' : 's.physical_quantity').')'); - $query->from('stock', 's'); - $query->where('s.id_product = '.(int)$id_product); - if (0 != $id_product_attribute) - $query->where('s.id_product_attribute = '.(int)$id_product_attribute); - if (count($ids_warehouse)) - $query->where('s.id_warehouse IN('.implode(', ', $ids_warehouse).')'); + // if we remove a usable quantity, exec hook + if ($is_usable) { + Hook::exec('actionProductCoverage', + array( + 'id_product' => $id_product, + 'id_product_attribute' => $id_product_attribute, + 'warehouse' => $warehouse + ) + ); + } - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + return $return; + } - /** - * @see StockManagerInterface::getProductRealQuantities() - */ - public function getProductRealQuantities($id_product, $id_product_attribute, $ids_warehouse = null, $usable = false) - { - if (!is_null($ids_warehouse)) - { - // in case $ids_warehouse is not an array - if (!is_array($ids_warehouse)) - $ids_warehouse = array($ids_warehouse); + /** + * @see StockManagerInterface::getProductPhysicalQuantities() + */ + public function getProductPhysicalQuantities($id_product, $id_product_attribute, $ids_warehouse = null, $usable = false) + { + if (!is_null($ids_warehouse)) { + // in case $ids_warehouse is not an array + if (!is_array($ids_warehouse)) { + $ids_warehouse = array($ids_warehouse); + } - // casts for security reason - $ids_warehouse = array_map('intval', $ids_warehouse); - } + // casts for security reason + $ids_warehouse = array_map('intval', $ids_warehouse); + if (!count($ids_warehouse)) { + return 0; + } + } else { + $ids_warehouse = array(); + } - $client_orders_qty = 0; + $query = new DbQuery(); + $query->select('SUM('.($usable ? 's.usable_quantity' : 's.physical_quantity').')'); + $query->from('stock', 's'); + $query->where('s.id_product = '.(int)$id_product); + if (0 != $id_product_attribute) { + $query->where('s.id_product_attribute = '.(int)$id_product_attribute); + } - // check if product is present in a pack - if (!Pack::isPack($id_product) && $in_pack = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS( - 'SELECT id_product_pack, quantity FROM '._DB_PREFIX_.'pack + if (count($ids_warehouse)) { + $query->where('s.id_warehouse IN('.implode(', ', $ids_warehouse).')'); + } + + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } + + /** + * @see StockManagerInterface::getProductRealQuantities() + */ + public function getProductRealQuantities($id_product, $id_product_attribute, $ids_warehouse = null, $usable = false) + { + if (!is_null($ids_warehouse)) { + // in case $ids_warehouse is not an array + if (!is_array($ids_warehouse)) { + $ids_warehouse = array($ids_warehouse); + } + + // casts for security reason + $ids_warehouse = array_map('intval', $ids_warehouse); + } + + $client_orders_qty = 0; + + // check if product is present in a pack + if (!Pack::isPack($id_product) && $in_pack = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS( + 'SELECT id_product_pack, quantity FROM '._DB_PREFIX_.'pack WHERE id_product_item = '.(int)$id_product.' - AND id_product_attribute_item = '.($id_product_attribute ? (int)$id_product_attribute : '0'))) - { - foreach ($in_pack as $value) - { - if (Validate::isLoadedObject($product = new Product((int)$value['id_product_pack'])) && - ($product->pack_stock_type == 1 || $product->pack_stock_type == 2 || ($product->pack_stock_type == 3 && Configuration::get('PS_PACK_STOCK_TYPE') > 0))) - { - $query = new DbQuery(); - $query->select('od.product_quantity, od.product_quantity_refunded'); - $query->from('order_detail', 'od'); - $query->leftjoin('orders', 'o', 'o.id_order = od.id_order'); - $query->where('od.product_id = '.(int)$value['id_product_pack']); - $query->leftJoin('order_history', 'oh', 'oh.id_order = o.id_order AND oh.id_order_state = o.current_state'); - $query->leftJoin('order_state', 'os', 'os.id_order_state = oh.id_order_state'); - $query->where('os.shipped != 1'); - $query->where('o.valid = 1 OR (os.id_order_state != '.(int)Configuration::get('PS_OS_ERROR').' + AND id_product_attribute_item = '.($id_product_attribute ? (int)$id_product_attribute : '0'))) { + foreach ($in_pack as $value) { + if (Validate::isLoadedObject($product = new Product((int)$value['id_product_pack'])) && + ($product->pack_stock_type == 1 || $product->pack_stock_type == 2 || ($product->pack_stock_type == 3 && Configuration::get('PS_PACK_STOCK_TYPE') > 0))) { + $query = new DbQuery(); + $query->select('od.product_quantity, od.product_quantity_refunded, pk.quantity'); + $query->from('order_detail', 'od'); + $query->leftjoin('orders', 'o', 'o.id_order = od.id_order'); + $query->where('od.product_id = '.(int)$value['id_product_pack']); + $query->leftJoin('order_history', 'oh', 'oh.id_order = o.id_order AND oh.id_order_state = o.current_state'); + $query->leftJoin('order_state', 'os', 'os.id_order_state = oh.id_order_state'); + $query->leftJoin('pack', 'pk', 'pk.id_product_item = '.(int)$id_product.' AND pk.id_product_attribute_item = '.($id_product_attribute ? (int)$id_product_attribute : '0').' AND id_product_pack = od.product_id'); + $query->where('os.shipped != 1'); + $query->where('o.valid = 1 OR (os.id_order_state != '.(int)Configuration::get('PS_OS_ERROR').' AND os.id_order_state != '.(int)Configuration::get('PS_OS_CANCELED').')'); - $query->groupBy('od.id_order_detail'); - if (count($ids_warehouse)) - $query->where('od.id_warehouse IN('.implode(', ', $ids_warehouse).')'); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - if (count($res)) - foreach ($res as $row) - $client_orders_qty += ($row['product_quantity'] - $row['product_quantity_refunded']); - } - } - } + $query->groupBy('od.id_order_detail'); + if (count($ids_warehouse)) { + $query->where('od.id_warehouse IN('.implode(', ', $ids_warehouse).')'); + } + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + if (count($res)) { + foreach ($res as $row) { + $client_orders_qty += ($row['product_quantity'] - $row['product_quantity_refunded']) * $row['quantity']; + } + } + } + } + } - // skip if product is a pack without - if (!Pack::isPack($id_product) || (Pack::isPack($id_product) && Validate::isLoadedObject($product = new Product((int)$id_product)) - && $product->pack_stock_type == 0 || $product->pack_stock_type == 2 || - ($product->pack_stock_type == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 0 || Configuration::get('PS_PACK_STOCK_TYPE') == 2)))) - { - // Gets client_orders_qty - $query = new DbQuery(); - $query->select('od.product_quantity, od.product_quantity_refunded'); - $query->from('order_detail', 'od'); - $query->leftjoin('orders', 'o', 'o.id_order = od.id_order'); - $query->where('od.product_id = '.(int)$id_product); - if (0 != $id_product_attribute) - $query->where('od.product_attribute_id = '.(int)$id_product_attribute); - $query->leftJoin('order_history', 'oh', 'oh.id_order = o.id_order AND oh.id_order_state = o.current_state'); - $query->leftJoin('order_state', 'os', 'os.id_order_state = oh.id_order_state'); - $query->where('os.shipped != 1'); - $query->where('o.valid = 1 OR (os.id_order_state != '.(int)Configuration::get('PS_OS_ERROR').' + // skip if product is a pack without + if (!Pack::isPack($id_product) || (Pack::isPack($id_product) && Validate::isLoadedObject($product = new Product((int)$id_product)) + && $product->pack_stock_type == 0 || $product->pack_stock_type == 2 || + ($product->pack_stock_type == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 0 || Configuration::get('PS_PACK_STOCK_TYPE') == 2)))) { + // Gets client_orders_qty + $query = new DbQuery(); + $query->select('od.product_quantity, od.product_quantity_refunded'); + $query->from('order_detail', 'od'); + $query->leftjoin('orders', 'o', 'o.id_order = od.id_order'); + $query->where('od.product_id = '.(int)$id_product); + if (0 != $id_product_attribute) { + $query->where('od.product_attribute_id = '.(int)$id_product_attribute); + } + $query->leftJoin('order_history', 'oh', 'oh.id_order = o.id_order AND oh.id_order_state = o.current_state'); + $query->leftJoin('order_state', 'os', 'os.id_order_state = oh.id_order_state'); + $query->where('os.shipped != 1'); + $query->where('o.valid = 1 OR (os.id_order_state != '.(int)Configuration::get('PS_OS_ERROR').' AND os.id_order_state != '.(int)Configuration::get('PS_OS_CANCELED').')'); - $query->groupBy('od.id_order_detail'); - if (count($ids_warehouse)) - $query->where('od.id_warehouse IN('.implode(', ', $ids_warehouse).')'); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - if (count($res)) - foreach ($res as $row) - $client_orders_qty += ($row['product_quantity'] - $row['product_quantity_refunded']); - } - // Gets supply_orders_qty - $query = new DbQuery(); + $query->groupBy('od.id_order_detail'); + if (count($ids_warehouse)) { + $query->where('od.id_warehouse IN('.implode(', ', $ids_warehouse).')'); + } + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + if (count($res)) { + foreach ($res as $row) { + $client_orders_qty += ($row['product_quantity'] - $row['product_quantity_refunded']); + } + } + } + // Gets supply_orders_qty + $query = new DbQuery(); - $query->select('sod.quantity_expected, sod.quantity_received'); - $query->from('supply_order', 'so'); - $query->leftjoin('supply_order_detail', 'sod', 'sod.id_supply_order = so.id_supply_order'); - $query->leftjoin('supply_order_state', 'sos', 'sos.id_supply_order_state = so.id_supply_order_state'); - $query->where('sos.pending_receipt = 1'); - $query->where('sod.id_product = '.(int)$id_product.' AND sod.id_product_attribute = '.(int)$id_product_attribute); - if (!is_null($ids_warehouse) && count($ids_warehouse)) - $query->where('so.id_warehouse IN('.implode(', ', $ids_warehouse).')'); + $query->select('sod.quantity_expected, sod.quantity_received'); + $query->from('supply_order', 'so'); + $query->leftjoin('supply_order_detail', 'sod', 'sod.id_supply_order = so.id_supply_order'); + $query->leftjoin('supply_order_state', 'sos', 'sos.id_supply_order_state = so.id_supply_order_state'); + $query->where('sos.pending_receipt = 1'); + $query->where('sod.id_product = '.(int)$id_product.' AND sod.id_product_attribute = '.(int)$id_product_attribute); + if (!is_null($ids_warehouse) && count($ids_warehouse)) { + $query->where('so.id_warehouse IN('.implode(', ', $ids_warehouse).')'); + } - $supply_orders_qties = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + $supply_orders_qties = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - $supply_orders_qty = 0; - foreach ($supply_orders_qties as $qty) - if ($qty['quantity_expected'] > $qty['quantity_received']) - $supply_orders_qty += ($qty['quantity_expected'] - $qty['quantity_received']); + $supply_orders_qty = 0; + foreach ($supply_orders_qties as $qty) { + if ($qty['quantity_expected'] > $qty['quantity_received']) { + $supply_orders_qty += ($qty['quantity_expected'] - $qty['quantity_received']); + } + } - // Gets {physical OR usable}_qty - $qty = $this->getProductPhysicalQuantities($id_product, $id_product_attribute, $ids_warehouse, $usable); + // Gets {physical OR usable}_qty + $qty = $this->getProductPhysicalQuantities($id_product, $id_product_attribute, $ids_warehouse, $usable); - //real qty = actual qty in stock - current client orders + current supply orders - return ($qty - $client_orders_qty + $supply_orders_qty); - } + //real qty = actual qty in stock - current client orders + current supply orders + return ($qty - $client_orders_qty + $supply_orders_qty); + } - /** - * @see StockManagerInterface::transferBetweenWarehouses() - */ - public function transferBetweenWarehouses($id_product, - $id_product_attribute, - $quantity, - $id_warehouse_from, - $id_warehouse_to, - $usable_from = true, - $usable_to = true) - { - // Checks if this transfer is possible - if ($this->getProductPhysicalQuantities($id_product, $id_product_attribute, array($id_warehouse_from), $usable_from) < $quantity) - return false; + /** + * @see StockManagerInterface::transferBetweenWarehouses() + */ + public function transferBetweenWarehouses($id_product, + $id_product_attribute, + $quantity, + $id_warehouse_from, + $id_warehouse_to, + $usable_from = true, + $usable_to = true) + { + // Checks if this transfer is possible + if ($this->getProductPhysicalQuantities($id_product, $id_product_attribute, array($id_warehouse_from), $usable_from) < $quantity) { + return false; + } - if ($id_warehouse_from == $id_warehouse_to && $usable_from == $usable_to) - return false; + if ($id_warehouse_from == $id_warehouse_to && $usable_from == $usable_to) { + return false; + } - // Checks if the given warehouses are available - $warehouse_from = new Warehouse($id_warehouse_from); - $warehouse_to = new Warehouse($id_warehouse_to); - if (!Validate::isLoadedObject($warehouse_from) || - !Validate::isLoadedObject($warehouse_to)) - return false; + // Checks if the given warehouses are available + $warehouse_from = new Warehouse($id_warehouse_from); + $warehouse_to = new Warehouse($id_warehouse_to); + if (!Validate::isLoadedObject($warehouse_from) || + !Validate::isLoadedObject($warehouse_to)) { + return false; + } - // Removes from warehouse_from - $stocks = $this->removeProduct($id_product, - $id_product_attribute, - $warehouse_from, - $quantity, - Configuration::get('PS_STOCK_MVT_TRANSFER_FROM'), - $usable_from); - if (!count($stocks)) - return false; + // Removes from warehouse_from + $stocks = $this->removeProduct($id_product, + $id_product_attribute, + $warehouse_from, + $quantity, + Configuration::get('PS_STOCK_MVT_TRANSFER_FROM'), + $usable_from); + if (!count($stocks)) { + return false; + } - // Adds in warehouse_to - foreach ($stocks as $stock) - { - $price = $stock['price_te']; + // Adds in warehouse_to + foreach ($stocks as $stock) { + $price = $stock['price_te']; - // convert product price to destination warehouse currency if needed - if ($warehouse_from->id_currency != $warehouse_to->id_currency) - { - // First convert price to the default currency - $price_converted_to_default_currency = Tools::convertPrice($price, $warehouse_from->id_currency, false); + // convert product price to destination warehouse currency if needed + if ($warehouse_from->id_currency != $warehouse_to->id_currency) { + // First convert price to the default currency + $price_converted_to_default_currency = Tools::convertPrice($price, $warehouse_from->id_currency, false); - // Convert the new price from default currency to needed currency - $price = Tools::convertPrice($price_converted_to_default_currency, $warehouse_to->id_currency, true); - } + // Convert the new price from default currency to needed currency + $price = Tools::convertPrice($price_converted_to_default_currency, $warehouse_to->id_currency, true); + } - if (!$this->addProduct($id_product, - $id_product_attribute, - $warehouse_to, - $stock['quantity'], - Configuration::get('PS_STOCK_MVT_TRANSFER_TO'), - $price, - $usable_to)) - return false; - } - return true; - } + if (!$this->addProduct($id_product, + $id_product_attribute, + $warehouse_to, + $stock['quantity'], + Configuration::get('PS_STOCK_MVT_TRANSFER_TO'), + $price, + $usable_to)) { + return false; + } + } + return true; + } - /** - * @see StockManagerInterface::getProductCoverage() - * Here, $coverage is a number of days - * @return int number of days left (-1 if infinite) - */ - public function getProductCoverage($id_product, $id_product_attribute, $coverage, $id_warehouse = null) - { - if (!$id_product_attribute) - $id_product_attribute = 0; + /** + * @see StockManagerInterface::getProductCoverage() + * Here, $coverage is a number of days + * @return int number of days left (-1 if infinite) + */ + public function getProductCoverage($id_product, $id_product_attribute, $coverage, $id_warehouse = null) + { + if (!$id_product_attribute) { + $id_product_attribute = 0; + } - if ($coverage == 0 || !$coverage) - $coverage = 7; // Week by default + if ($coverage == 0 || !$coverage) { + $coverage = 7; + } // Week by default - // gets all stock_mvt for the given coverage period - $query = ' + // gets all stock_mvt for the given coverage period + $query = ' SELECT SUM(view.quantity) as quantity_out FROM ( SELECT sm.`physical_quantity` as quantity @@ -697,95 +747,99 @@ class StockManagerCore implements StockManagerInterface AND TO_DAYS("'.date('Y-m-d').' 00:00:00") - TO_DAYS(sm.`date_add`) <= '.(int)$coverage.' AND s.`id_product` = '.(int)$id_product.' AND s.`id_product_attribute` = '.(int)$id_product_attribute. - ($id_warehouse ? ' AND s.`id_warehouse` = '.(int)$id_warehouse : '').' + ($id_warehouse ? ' AND s.`id_warehouse` = '.(int)$id_warehouse : '').' GROUP BY sm.`id_stock_mvt` ) as view'; - $quantity_out = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - if (!$quantity_out) - return -1; + $quantity_out = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + if (!$quantity_out) { + return -1; + } - $quantity_per_day = Tools::ps_round($quantity_out / $coverage); - $physical_quantity = $this->getProductPhysicalQuantities($id_product, - $id_product_attribute, - ($id_warehouse ? array($id_warehouse) : null), - true); - $time_left = ($quantity_per_day == 0) ? (-1) : Tools::ps_round($physical_quantity / $quantity_per_day); + $quantity_per_day = Tools::ps_round($quantity_out / $coverage); + $physical_quantity = $this->getProductPhysicalQuantities($id_product, + $id_product_attribute, + ($id_warehouse ? array($id_warehouse) : null), + true); + $time_left = ($quantity_per_day == 0) ? (-1) : Tools::ps_round($physical_quantity / $quantity_per_day); - return $time_left; - } + return $time_left; + } - /** - * For a given stock, calculates its new WA(Weighted Average) price based on the new quantities and price - * Formula : (physicalStock * lastCump + quantityToAdd * unitPrice) / (physicalStock + quantityToAdd) - * - * @param Stock|PrestaShopCollection $stock - * @param int $quantity - * @param float $price_te - * @return int WA - */ - protected function calculateWA(Stock $stock, $quantity, $price_te) - { - return (float)Tools::ps_round(((($stock->physical_quantity * $stock->price_te) + ($quantity * $price_te)) / ($stock->physical_quantity + $quantity)), 6); - } + /** + * For a given stock, calculates its new WA(Weighted Average) price based on the new quantities and price + * Formula : (physicalStock * lastCump + quantityToAdd * unitPrice) / (physicalStock + quantityToAdd) + * + * @param Stock|PrestaShopCollection $stock + * @param int $quantity + * @param float $price_te + * @return int WA + */ + protected function calculateWA(Stock $stock, $quantity, $price_te) + { + return (float)Tools::ps_round(((($stock->physical_quantity * $stock->price_te) + ($quantity * $price_te)) / ($stock->physical_quantity + $quantity)), 6); + } - /** - * For a given product, retrieves the stock collection - * - * @param int $id_product - * @param int $id_product_attribute - * @param int $id_warehouse Optional - * @param int $price_te Optional - * @return PrestaShopCollection Collection of Stock - */ - protected function getStockCollection($id_product, $id_product_attribute, $id_warehouse = null, $price_te = null) - { - $stocks = new PrestaShopCollection('Stock'); - $stocks->where('id_product', '=', $id_product); - $stocks->where('id_product_attribute', '=', $id_product_attribute); - if ($id_warehouse) - $stocks->where('id_warehouse', '=', $id_warehouse); - if ($price_te) - $stocks->where('price_te', '=', $price_te); + /** + * For a given product, retrieves the stock collection + * + * @param int $id_product + * @param int $id_product_attribute + * @param int $id_warehouse Optional + * @param int $price_te Optional + * @return PrestaShopCollection Collection of Stock + */ + protected function getStockCollection($id_product, $id_product_attribute, $id_warehouse = null, $price_te = null) + { + $stocks = new PrestaShopCollection('Stock'); + $stocks->where('id_product', '=', $id_product); + $stocks->where('id_product_attribute', '=', $id_product_attribute); + if ($id_warehouse) { + $stocks->where('id_warehouse', '=', $id_warehouse); + } + if ($price_te) { + $stocks->where('price_te', '=', $price_te); + } - return $stocks; - } + return $stocks; + } - /** - * For a given product, retrieves the stock in function of the delivery option - * - * @param int $id_product - * @param int $id_product_attribute optional - * @param array $delivery_option - * @return int quantity - */ - public static function getStockByCarrier($id_product = 0, $id_product_attribute = 0, $delivery_option = null) - { - if (!(int)$id_product || !is_array($delivery_option) || !is_int($id_product_attribute)) - return false; + /** + * For a given product, retrieves the stock in function of the delivery option + * + * @param int $id_product + * @param int $id_product_attribute optional + * @param array $delivery_option + * @return int quantity + */ + public static function getStockByCarrier($id_product = 0, $id_product_attribute = 0, $delivery_option = null) + { + if (!(int)$id_product || !is_array($delivery_option) || !is_int($id_product_attribute)) { + return false; + } - $results = Warehouse::getWarehousesByProductId($id_product, $id_product_attribute); - $stock_quantity = 0; + $results = Warehouse::getWarehousesByProductId($id_product, $id_product_attribute); + $stock_quantity = 0; - foreach ($results as $result) - if (isset($result['id_warehouse']) && (int)$result['id_warehouse']) - { - $ws = new Warehouse((int)$result['id_warehouse']); - $carriers = $ws->getWsCarriers(); + foreach ($results as $result) { + if (isset($result['id_warehouse']) && (int)$result['id_warehouse']) { + $ws = new Warehouse((int)$result['id_warehouse']); + $carriers = $ws->getWsCarriers(); - if (is_array($carriers) && !empty($carriers)) - $stock_quantity += Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT SUM(s.`usable_quantity`) as quantity + if (is_array($carriers) && !empty($carriers)) { + $stock_quantity += Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT SUM(s.`usable_quantity`) as quantity FROM '._DB_PREFIX_.'stock s LEFT JOIN '._DB_PREFIX_.'warehouse_carrier wc ON wc.`id_warehouse` = s.`id_warehouse` LEFT JOIN '._DB_PREFIX_.'carrier c ON wc.`id_carrier` = c.`id_reference` WHERE s.`id_product` = '.(int)$id_product.' AND s.`id_product_attribute` = '.(int)$id_product_attribute.' AND s.`id_warehouse` = '.$result['id_warehouse'].' AND c.`id_carrier` IN ('.rtrim($delivery_option[(int)Context::getContext()->cart->id_address_delivery], ',').') GROUP BY s.`id_product`'); - else - $stock_quantity += Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT SUM(s.`usable_quantity`) as quantity + } else { + $stock_quantity += Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT SUM(s.`usable_quantity`) as quantity FROM '._DB_PREFIX_.'stock s WHERE s.`id_product` = '.(int)$id_product.' AND s.`id_product_attribute` = '.(int)$id_product_attribute.' AND s.`id_warehouse` = '.$result['id_warehouse'].' GROUP BY s.`id_product`'); - } - - return $stock_quantity; - } + } + } + } + return $stock_quantity; + } } diff --git a/classes/stock/StockManagerFactory.php b/classes/stock/StockManagerFactory.php index 6e9f2f6b..4793f86e 100644 --- a/classes/stock/StockManagerFactory.php +++ b/classes/stock/StockManagerFactory.php @@ -30,49 +30,50 @@ */ class StockManagerFactoryCore { - /** - * @var $stock_manager : instance of the current StockManager. - */ - protected static $stock_manager; + /** + * @var $stock_manager : instance of the current StockManager. + */ + protected static $stock_manager; - /** - * Returns a StockManager - * - * @return StockManagerInterface - */ - public static function getManager() - { - if (!isset(StockManagerFactory::$stock_manager)) - { - $stock_manager = StockManagerFactory::execHookStockManagerFactory(); - if (!($stock_manager instanceof StockManagerInterface)) - $stock_manager = new StockManager(); - StockManagerFactory::$stock_manager = $stock_manager; - } - return StockManagerFactory::$stock_manager; - } + /** + * Returns a StockManager + * + * @return StockManagerInterface + */ + public static function getManager() + { + if (!isset(StockManagerFactory::$stock_manager)) { + $stock_manager = StockManagerFactory::execHookStockManagerFactory(); + if (!($stock_manager instanceof StockManagerInterface)) { + $stock_manager = new StockManager(); + } + StockManagerFactory::$stock_manager = $stock_manager; + } + return StockManagerFactory::$stock_manager; + } - /** - * Looks for a StockManager in the modules list. - * - * @return StockManagerInterface - */ - public static function execHookStockManagerFactory() - { - $modules_infos = Hook::getModulesFromHook(Hook::getIdByName('stockManager')); - $stock_manager = false; + /** + * Looks for a StockManager in the modules list. + * + * @return StockManagerInterface + */ + public static function execHookStockManagerFactory() + { + $modules_infos = Hook::getModulesFromHook(Hook::getIdByName('stockManager')); + $stock_manager = false; - foreach ($modules_infos as $module_infos) - { - $module_instance = Module::getInstanceByName($module_infos['name']); + foreach ($modules_infos as $module_infos) { + $module_instance = Module::getInstanceByName($module_infos['name']); - if (is_callable(array($module_instance, 'hookStockManager'))) - $stock_manager = $module_instance->hookStockManager(); + if (is_callable(array($module_instance, 'hookStockManager'))) { + $stock_manager = $module_instance->hookStockManager(); + } - if ($stock_manager) - break; - } + if ($stock_manager) { + break; + } + } - return $stock_manager; - } -} \ No newline at end of file + return $stock_manager; + } +} diff --git a/classes/stock/StockManagerInterface.php b/classes/stock/StockManagerInterface.php index b07e6570..43ba4805 100644 --- a/classes/stock/StockManagerInterface.php +++ b/classes/stock/StockManagerInterface.php @@ -30,96 +30,94 @@ */ interface StockManagerInterface { + /** + * Checks if the StockManager is available + * + * @return StockManagerInterface + */ + public static function isAvailable(); - /** - * Checks if the StockManager is available - * - * @return StockManagerInterface - */ - public static function isAvailable(); + /** + * For a given product, adds a given quantity + * + * @param int $id_product + * @param int $id_product_attribute + * @param Warehouse $warehouse + * @param int $quantity + * @param int $id_stock_movement_reason + * @param float $price_te + * @param bool $is_usable + * @param int $id_supply_order optionnal + * @return bool + */ + public function addProduct($id_product, $id_product_attribute, Warehouse $warehouse, $quantity, $id_stock_movement_reason, $price_te, $is_usable = true, $id_supply_order = null); - /** - * For a given product, adds a given quantity - * - * @param int $id_product - * @param int $id_product_attribute - * @param Warehouse $warehouse - * @param int $quantity - * @param int $id_stock_movement_reason - * @param float $price_te - * @param bool $is_usable - * @param int $id_supply_order optionnal - * @return bool - */ - public function addProduct($id_product, $id_product_attribute, Warehouse $warehouse, $quantity, $id_stock_movement_reason, $price_te, $is_usable = true, $id_supply_order = null); + /** + * For a given product, removes a given quantity + * + * @param int $id_product + * @param int $id_product_attribute + * @param Warehouse $warehouse + * @param int $quantity + * @param int $id_stock_movement_reason + * @param bool $is_usable + * @param int $id_order Optionnal + * @return array - empty if an error occurred | details of removed products quantities with corresponding prices otherwise + */ + public function removeProduct($id_product, $id_product_attribute, Warehouse $warehouse, $quantity, $id_stock_movement_reason, $is_usable = true, $id_order = null); - /** - * For a given product, removes a given quantity - * - * @param int $id_product - * @param int $id_product_attribute - * @param Warehouse $warehouse - * @param int $quantity - * @param int $id_stock_movement_reason - * @param bool $is_usable - * @param int $id_order Optionnal - * @return array - empty if an error occurred | details of removed products quantities with corresponding prices otherwise - */ - public function removeProduct($id_product, $id_product_attribute, Warehouse $warehouse, $quantity, $id_stock_movement_reason, $is_usable = true, $id_order = null); + /** + * For a given product, returns its physical quantity + * If the given product has combinations and $id_product_attribute is null, returns the sum for all combinations + * + * @param int $id_product + * @param int $id_product_attribute + * @param array|int $ids_warehouse optional + * @param bool $usable false default - in this case we retrieve all physical quantities, otherwise we retrieve physical quantities flagged as usable + * @return int + */ + public function getProductPhysicalQuantities($id_product, $id_product_attribute, $ids_warehouse = null, $usable = false); - /** - * For a given product, returns its physical quantity - * If the given product has combinations and $id_product_attribute is null, returns the sum for all combinations - * - * @param int $id_product - * @param int $id_product_attribute - * @param array|int $ids_warehouse optional - * @param bool $usable false default - in this case we retrieve all physical quantities, otherwise we retrieve physical quantities flagged as usable - * @return int - */ - public function getProductPhysicalQuantities($id_product, $id_product_attribute, $ids_warehouse = null, $usable = false); + /** + * For a given product, returns its real quantity + * If the given product has combinations and $id_product_attribute is null, returns the sum for all combinations + * Real quantity : (physical_qty + supply_orders_qty - client_orders_qty) + * If $usable is defined, real quantity: usable_qty + supply_orders_qty - client_orders_qty + * + * @param int $id_product + * @param int $id_product_attribute + * @param array|int $ids_warehouse optional + * @param bool $usable false by default + * @return int + */ + public function getProductRealQuantities($id_product, $id_product_attribute, $ids_warehouse = null, $usable = false); - /** - * For a given product, returns its real quantity - * If the given product has combinations and $id_product_attribute is null, returns the sum for all combinations - * Real quantity : (physical_qty + supply_orders_qty - client_orders_qty) - * If $usable is defined, real quantity: usable_qty + supply_orders_qty - client_orders_qty - * - * @param int $id_product - * @param int $id_product_attribute - * @param array|int $ids_warehouse optional - * @param bool $usable false by default - * @return int - */ - public function getProductRealQuantities($id_product, $id_product_attribute, $ids_warehouse = null, $usable = false); - - /** - * For a given product, transfers quantities between two warehouses - * By default, it manages usable quantities - * It is also possible to transfer a usable quantity from warehouse 1 in an unusable quantity to warehouse 2 - * It is also possible to transfer a usable quantity from warehouse 1 in an unusable quantity to warehouse 1 - * - * @param int $id_product - * @param int $id_product_attribute - * @param int $quantity - * @param int $warehouse_from - * @param int $warehouse_to - * @param bool $usable_from Optional, true by default - * @param bool $usable_to Optional, true by default - * @return bool - */ - public function transferBetweenWarehouses($id_product, $id_product_attribute, $quantity, $warehouse_from, $warehouse_to, $usable_from = true, $usable_to = true); - - /** - * For a given product, returns the time left before being out of stock. - * By default, for the given product, it will use sum(quantities removed in all warehouses) - * - * @param int $id_product - * @param int $id_product_attribute - * @param int $coverage - * @param int $id_warehouse Optional - * @return int time - */ - public function getProductCoverage($id_product, $id_product_attribute, $coverage, $id_warehouse = null); + /** + * For a given product, transfers quantities between two warehouses + * By default, it manages usable quantities + * It is also possible to transfer a usable quantity from warehouse 1 in an unusable quantity to warehouse 2 + * It is also possible to transfer a usable quantity from warehouse 1 in an unusable quantity to warehouse 1 + * + * @param int $id_product + * @param int $id_product_attribute + * @param int $quantity + * @param int $warehouse_from + * @param int $warehouse_to + * @param bool $usable_from Optional, true by default + * @param bool $usable_to Optional, true by default + * @return bool + */ + public function transferBetweenWarehouses($id_product, $id_product_attribute, $quantity, $warehouse_from, $warehouse_to, $usable_from = true, $usable_to = true); + /** + * For a given product, returns the time left before being out of stock. + * By default, for the given product, it will use sum(quantities removed in all warehouses) + * + * @param int $id_product + * @param int $id_product_attribute + * @param int $coverage + * @param int $id_warehouse Optional + * @return int time + */ + public function getProductCoverage($id_product, $id_product_attribute, $coverage, $id_warehouse = null); } diff --git a/classes/stock/StockManagerModule.php b/classes/stock/StockManagerModule.php index 50ba90e3..4ea50012 100644 --- a/classes/stock/StockManagerModule.php +++ b/classes/stock/StockManagerModule.php @@ -29,29 +29,32 @@ */ abstract class StockManagerModuleCore extends Module { - public $stock_manager_class; + public $stock_manager_class; - public function install() - { - return (parent::install() && $this->registerHook('stockManager') ); - } + public function install() + { + return (parent::install() && $this->registerHook('stockManager')); + } - public function hookStockManager() - { - $class_file = _PS_MODULE_DIR_.'/'.$this->name.'/'.$this->stock_manager_class.'.php'; + public function hookStockManager() + { + $class_file = _PS_MODULE_DIR_.'/'.$this->name.'/'.$this->stock_manager_class.'.php'; - if (!isset($this->stock_manager_class) || !file_exists($class_file)) - die(sprintf(Tools::displayError('Incorrect Stock Manager class [%s]'), $this->stock_manager_class)); + if (!isset($this->stock_manager_class) || !file_exists($class_file)) { + die(sprintf(Tools::displayError('Incorrect Stock Manager class [%s]'), $this->stock_manager_class)); + } - require_once($class_file); + require_once($class_file); - if (!class_exists($this->stock_manager_class)) - die(sprintf(Tools::displayError('Stock Manager class not found [%s]'), $this->stock_manager_class)); + if (!class_exists($this->stock_manager_class)) { + die(sprintf(Tools::displayError('Stock Manager class not found [%s]'), $this->stock_manager_class)); + } - $class = $this->stock_manager_class; - if (call_user_func(array($class, 'isAvailable'))) - return new $class(); + $class = $this->stock_manager_class; + if (call_user_func(array($class, 'isAvailable'))) { + return new $class(); + } - return false; - } -} \ No newline at end of file + return false; + } +} diff --git a/classes/stock/StockMvt.php b/classes/stock/StockMvt.php index 7922817c..2a5b17e0 100644 --- a/classes/stock/StockMvt.php +++ b/classes/stock/StockMvt.php @@ -29,224 +29,226 @@ */ class StockMvtCore extends ObjectModel { - public $id; + public $id; - /** - * @var string The creation date of the movement - */ - public $date_add; + /** + * @var string The creation date of the movement + */ + public $date_add; - /** - * @var int The employee id, responsible of the movement - */ - public $id_employee; + /** + * @var int The employee id, responsible of the movement + */ + public $id_employee; - /** - * @since 1.5.0 - * @var string The first name of the employee responsible of the movement - */ - public $employee_firstname; + /** + * @since 1.5.0 + * @var string The first name of the employee responsible of the movement + */ + public $employee_firstname; - /** - * @since 1.5.0 - * @var string The last name of the employee responsible of the movement - */ - public $employee_lastname; + /** + * @since 1.5.0 + * @var string The last name of the employee responsible of the movement + */ + public $employee_lastname; - /** - * @since 1.5.0 - * @var int The stock id on wtich the movement is applied - */ - public $id_stock; + /** + * @since 1.5.0 + * @var int The stock id on wtich the movement is applied + */ + public $id_stock; - /** - * @since 1.5.0 - * @var int the quantity of product with is moved - */ - public $physical_quantity; + /** + * @since 1.5.0 + * @var int the quantity of product with is moved + */ + public $physical_quantity; - /** - * @var int id of the movement reason assoiated to the movement - */ - public $id_stock_mvt_reason; + /** + * @var int id of the movement reason assoiated to the movement + */ + public $id_stock_mvt_reason; - /** - * @var int Used when the movement is due to a customer order - */ - public $id_order = null; + /** + * @var int Used when the movement is due to a customer order + */ + public $id_order = null; - /** - * @since 1.5.0 - * @var int detrmine if the movement is a positive or negative operation - */ - public $sign; + /** + * @since 1.5.0 + * @var int detrmine if the movement is a positive or negative operation + */ + public $sign; - /** - * @since 1.5.0 - * @var int Used when the movement is due to a supplier order - */ - public $id_supply_order = null; + /** + * @since 1.5.0 + * @var int Used when the movement is due to a supplier order + */ + public $id_supply_order = null; - /** - * @since 1.5.0 - * @var float Last value of the weighted-average method - */ - public $last_wa = null; + /** + * @since 1.5.0 + * @var float Last value of the weighted-average method + */ + public $last_wa = null; - /** - * @since 1.5.0 - * @var float Current value of the weighted-average method - */ - public $current_wa = null; + /** + * @since 1.5.0 + * @var float Current value of the weighted-average method + */ + public $current_wa = null; - /** - * @since 1.5.0 - * @var float The unit price without tax of the product associated to the movement - */ - public $price_te; + /** + * @since 1.5.0 + * @var float The unit price without tax of the product associated to the movement + */ + public $price_te; - /** - * @since 1.5.0 - * @var int Refers to an other id_stock_mvt : used for LIFO/FIFO implementation in StockManager - */ - public $referer; + /** + * @since 1.5.0 + * @var int Refers to an other id_stock_mvt : used for LIFO/FIFO implementation in StockManager + */ + public $referer; - /** - * @deprecated since 1.5.0 - * @deprecated stock movement will not be updated anymore - */ - public $date_upd; + /** + * @deprecated since 1.5.0 + * @deprecated stock movement will not be updated anymore + */ + public $date_upd; - /** - * @deprecated since 1.5.0 - * @see physical_quantity - * @var int - */ - public $quantity; + /** + * @deprecated since 1.5.0 + * @see physical_quantity + * @var int + */ + public $quantity; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'stock_mvt', - 'primary' => 'id_stock_mvt', - 'fields' => array( - 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'employee_firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), - 'employee_lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), - 'id_stock' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'physical_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), - 'id_stock_mvt_reason' =>array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_supply_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'sign' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), - 'last_wa' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'current_wa' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'price_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'referer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'stock_mvt', + 'primary' => 'id_stock_mvt', + 'fields' => array( + 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'employee_firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), + 'employee_lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), + 'id_stock' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'physical_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), + 'id_stock_mvt_reason' =>array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_supply_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'sign' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), + 'last_wa' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'current_wa' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'price_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'referer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), + ), + ); - protected $webserviceParameters = array( - 'objectsNodeName' => 'stock_movements', - 'objectNodeName' => 'stock_movement', - 'fields' => array( - 'id_employee' => array('xlink_resource'=> 'employees'), - 'id_stock' => array('xlink_resource'=> 'stock'), - 'id_stock_mvt_reason' => array('xlink_resource'=> 'stock_movement_reasons'), - 'id_order' => array('xlink_resource'=> 'orders'), - 'id_supply_order' => array('xlink_resource'=> 'supply_order'), - ), - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'stock_movements', + 'objectNodeName' => 'stock_movement', + 'fields' => array( + 'id_employee' => array('xlink_resource'=> 'employees'), + 'id_stock' => array('xlink_resource'=> 'stock'), + 'id_stock_mvt_reason' => array('xlink_resource'=> 'stock_movement_reasons'), + 'id_order' => array('xlink_resource'=> 'orders'), + 'id_supply_order' => array('xlink_resource'=> 'supply_order'), + ), + ); - /** - * @deprecated since 1.5.0 - * - * This method no longer exists. - * There is no equivalent or replacement, considering that this should be handled by inventories. - */ - public static function addMissingMvt($id_employee) - { - // display that this method is deprecated - Tools::displayAsDeprecated(); - } + /** + * @deprecated since 1.5.0 + * + * This method no longer exists. + * There is no equivalent or replacement, considering that this should be handled by inventories. + */ + public static function addMissingMvt($id_employee) + { + // display that this method is deprecated + Tools::displayAsDeprecated(); + } - /** - * Gets the negative (decrements the stock) stock mvts that correspond to the given order, for : - * the given product, in the given quantity. - * - * @since 1.5.0 - * @param int $id_order - * @param int $id_product - * @param int $id_product_attribute Use 0 if the product does not have attributes - * @param int $quantity - * @param int $id_warehouse Optional - * @return Array mvts - */ - public static function getNegativeStockMvts($id_order, $id_product, $id_product_attribute, $quantity, $id_warehouse = null) - { - $movements = array(); - $quantity_total = 0; + /** + * Gets the negative (decrements the stock) stock mvts that correspond to the given order, for : + * the given product, in the given quantity. + * + * @since 1.5.0 + * @param int $id_order + * @param int $id_product + * @param int $id_product_attribute Use 0 if the product does not have attributes + * @param int $quantity + * @param int $id_warehouse Optional + * @return Array mvts + */ + public static function getNegativeStockMvts($id_order, $id_product, $id_product_attribute, $quantity, $id_warehouse = null) + { + $movements = array(); + $quantity_total = 0; - // preps query - $query = new DbQuery(); - $query->select('sm.*, s.id_warehouse'); - $query->from('stock_mvt', 'sm'); - $query->innerJoin('stock', 's', 's.id_stock = sm.id_stock'); - $query->where('sm.sign = -1'); - $query->where('sm.id_order = '.(int)$id_order); - $query->where('s.id_product = '.(int)$id_product.' AND s.id_product_attribute = '.(int)$id_product_attribute); + // preps query + $query = new DbQuery(); + $query->select('sm.*, s.id_warehouse'); + $query->from('stock_mvt', 'sm'); + $query->innerJoin('stock', 's', 's.id_stock = sm.id_stock'); + $query->where('sm.sign = -1'); + $query->where('sm.id_order = '.(int)$id_order); + $query->where('s.id_product = '.(int)$id_product.' AND s.id_product_attribute = '.(int)$id_product_attribute); - // if filer by warehouse - if (!is_null($id_warehouse)) - $query->where('s.id_warehouse = '.(int)$id_warehouse); + // if filer by warehouse + if (!is_null($id_warehouse)) { + $query->where('s.id_warehouse = '.(int)$id_warehouse); + } - // orders the movements by date - $query->orderBy('date_add DESC'); + // orders the movements by date + $query->orderBy('date_add DESC'); - // gets the result - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->query($query); + // gets the result + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->query($query); - // fills the movements array - while ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->nextRow($res)) - { - if ($quantity_total >= $quantity) - break; - $quantity_total += (int)$row['physical_quantity']; - $movements[] = $row; - } + // fills the movements array + while ($row = Db::getInstance(_PS_USE_SQL_SLAVE_)->nextRow($res)) { + if ($quantity_total >= $quantity) { + break; + } + $quantity_total += (int)$row['physical_quantity']; + $movements[] = $row; + } - return $movements; - } + return $movements; + } - /** - * For a given product, gets the last positive stock mvt - * - * @since 1.5.0 - * @param int $id_product - * @param int $id_product_attribute Use 0 if the product does not have attributes - * @return bool|array - */ - public static function getLastPositiveStockMvt($id_product, $id_product_attribute) - { - $query = new DbQuery(); - $query->select('sm.*, w.id_currency, (s.usable_quantity = sm.physical_quantity) as is_usable'); - $query->from('stock_mvt', 'sm'); - $query->innerJoin('stock', 's', 's.id_stock = sm.id_stock'); - $query->innerJoin('warehouse', 'w', 'w.id_warehouse = s.id_warehouse'); - $query->where('sm.sign = 1'); - if ($id_product_attribute) - $query->where('s.id_product = '.(int)$id_product.' AND s.id_product_attribute = '.(int)$id_product_attribute); - else - $query->where('s.id_product = '.(int)$id_product); - $query->orderBy('date_add DESC'); + /** + * For a given product, gets the last positive stock mvt + * + * @since 1.5.0 + * @param int $id_product + * @param int $id_product_attribute Use 0 if the product does not have attributes + * @return bool|array + */ + public static function getLastPositiveStockMvt($id_product, $id_product_attribute) + { + $query = new DbQuery(); + $query->select('sm.*, w.id_currency, (s.usable_quantity = sm.physical_quantity) as is_usable'); + $query->from('stock_mvt', 'sm'); + $query->innerJoin('stock', 's', 's.id_stock = sm.id_stock'); + $query->innerJoin('warehouse', 'w', 'w.id_warehouse = s.id_warehouse'); + $query->where('sm.sign = 1'); + if ($id_product_attribute) { + $query->where('s.id_product = '.(int)$id_product.' AND s.id_product_attribute = '.(int)$id_product_attribute); + } else { + $query->where('s.id_product = '.(int)$id_product); + } + $query->orderBy('date_add DESC'); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - - if ($res != false) - return $res['0']; - return false; - } + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + if ($res != false) { + return $res['0']; + } + return false; + } } diff --git a/classes/stock/StockMvtReason.php b/classes/stock/StockMvtReason.php index 7c1ed08a..5c2c2d9e 100644 --- a/classes/stock/StockMvtReason.php +++ b/classes/stock/StockMvtReason.php @@ -26,116 +26,117 @@ class StockMvtReasonCore extends ObjectModel { - /** @var int identifier of the movement reason */ - public $id; + /** @var int identifier of the movement reason */ + public $id; - /** @var string the name of the movement reason */ - public $name; + /** @var string the name of the movement reason */ + public $name; - /** @var int detrmine if the movement reason correspond to a positive or negative operation */ - public $sign; + /** @var int detrmine if the movement reason correspond to a positive or negative operation */ + public $sign; - /** @var string the creation date of the movement reason */ - public $date_add; + /** @var string the creation date of the movement reason */ + public $date_add; - /** @var string the last update date of the movement reason */ - public $date_upd; + /** @var string the last update date of the movement reason */ + public $date_upd; - /** @var bool True if the movement reason has been deleted (staying in database as deleted) */ - public $deleted = 0; + /** @var bool True if the movement reason has been deleted (staying in database as deleted) */ + public $deleted = 0; - /** - * @since 1.5.0 - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'stock_mvt_reason', - 'primary' => 'id_stock_mvt_reason', - 'multilang' => true, - 'fields' => array( - 'sign' => array('type' => self::TYPE_INT), - 'deleted' => array('type' => self::TYPE_BOOL), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 255), - ), - ); + /** + * @since 1.5.0 + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'stock_mvt_reason', + 'primary' => 'id_stock_mvt_reason', + 'multilang' => true, + 'fields' => array( + 'sign' => array('type' => self::TYPE_INT), + 'deleted' => array('type' => self::TYPE_BOOL), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 255), + ), + ); - /** - * @see ObjectModel::$webserviceParameters - */ - protected $webserviceParameters = array( - 'objectsNodeName' => 'stock_movement_reasons', - 'objectNodeName' => 'stock_movement_reason', - 'fields' => array( - 'sign' => array(), - ), - ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'objectsNodeName' => 'stock_movement_reasons', + 'objectNodeName' => 'stock_movement_reason', + 'fields' => array( + 'sign' => array(), + ), + ); - /** - * Gets Stock Mvt Reasons - * - * @param int $id_lang - * @param int $sign Optionnal - * @return array - */ - public static function getStockMvtReasons($id_lang, $sign = null) - { - $query = new DbQuery(); - $query->select('smrl.name, smr.id_stock_mvt_reason, smr.sign'); - $query->from('stock_mvt_reason', 'smr'); - $query->leftjoin('stock_mvt_reason_lang', 'smrl', 'smr.id_stock_mvt_reason = smrl.id_stock_mvt_reason AND smrl.id_lang='.(int)$id_lang); - $query->where('smr.deleted = 0'); + /** + * Gets Stock Mvt Reasons + * + * @param int $id_lang + * @param int $sign Optionnal + * @return array + */ + public static function getStockMvtReasons($id_lang, $sign = null) + { + $query = new DbQuery(); + $query->select('smrl.name, smr.id_stock_mvt_reason, smr.sign'); + $query->from('stock_mvt_reason', 'smr'); + $query->leftjoin('stock_mvt_reason_lang', 'smrl', 'smr.id_stock_mvt_reason = smrl.id_stock_mvt_reason AND smrl.id_lang='.(int)$id_lang); + $query->where('smr.deleted = 0'); - if ($sign != null) - $query->where('smr.sign = '.(int)$sign); + if ($sign != null) { + $query->where('smr.sign = '.(int)$sign); + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } - /** - * Same as StockMvtReason::getStockMvtReasons(), ignoring a specific lists of ids - * - * @since 1.5.0 - * @param int $id_lang - * @param array $ids_ignore - * @param int $sign optional - */ - public static function getStockMvtReasonsWithFilter($id_lang, $ids_ignore, $sign = null) - { - $query = new DbQuery(); - $query->select('smrl.name, smr.id_stock_mvt_reason, smr.sign'); - $query->from('stock_mvt_reason', 'smr'); - $query->leftjoin('stock_mvt_reason_lang', 'smrl', 'smr.id_stock_mvt_reason = smrl.id_stock_mvt_reason AND smrl.id_lang='.(int)$id_lang); - $query->where('smr.deleted = 0'); + /** + * Same as StockMvtReason::getStockMvtReasons(), ignoring a specific lists of ids + * + * @since 1.5.0 + * @param int $id_lang + * @param array $ids_ignore + * @param int $sign optional + */ + public static function getStockMvtReasonsWithFilter($id_lang, $ids_ignore, $sign = null) + { + $query = new DbQuery(); + $query->select('smrl.name, smr.id_stock_mvt_reason, smr.sign'); + $query->from('stock_mvt_reason', 'smr'); + $query->leftjoin('stock_mvt_reason_lang', 'smrl', 'smr.id_stock_mvt_reason = smrl.id_stock_mvt_reason AND smrl.id_lang='.(int)$id_lang); + $query->where('smr.deleted = 0'); - if ($sign != null) - $query->where('smr.sign = '.(int)$sign); + if ($sign != null) { + $query->where('smr.sign = '.(int)$sign); + } - if (count($ids_ignore)) - { - $ids_ignore = array_map('intval', $ids_ignore); - $query->where('smr.id_stock_mvt_reason NOT IN('.implode(', ', $ids_ignore).')'); - } + if (count($ids_ignore)) { + $ids_ignore = array_map('intval', $ids_ignore); + $query->where('smr.id_stock_mvt_reason NOT IN('.implode(', ', $ids_ignore).')'); + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } - /** - * For a given id_stock_mvt_reason, tells if it exists - * - * @since 1.5.0 - * @param int $id_stock_mvt_reason - * @return bool - */ - public static function exists($id_stock_mvt_reason) - { - $query = new DbQuery(); - $query->select('smr.id_stock_mvt_reason'); - $query->from('stock_mvt_reason', 'smr'); - $query->where('smr.id_stock_mvt_reason = '.(int)$id_stock_mvt_reason); - $query->where('smr.deleted = 0'); + /** + * For a given id_stock_mvt_reason, tells if it exists + * + * @since 1.5.0 + * @param int $id_stock_mvt_reason + * @return bool + */ + public static function exists($id_stock_mvt_reason) + { + $query = new DbQuery(); + $query->select('smr.id_stock_mvt_reason'); + $query->from('stock_mvt_reason', 'smr'); + $query->where('smr.id_stock_mvt_reason = '.(int)$id_stock_mvt_reason); + $query->where('smr.deleted = 0'); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } } diff --git a/classes/stock/StockMvtWS.php b/classes/stock/StockMvtWS.php index c270639c..a7ca1b1f 100644 --- a/classes/stock/StockMvtWS.php +++ b/classes/stock/StockMvtWS.php @@ -30,261 +30,266 @@ */ class StockMvtWSCore extends ObjectModelCore { - public $id; + public $id; - /** - * @var string The creation date of the movement - */ - public $date_add; + /** + * @var string The creation date of the movement + */ + public $date_add; - /** - * @var int The employee id, responsible of the movement - */ - public $id_employee; + /** + * @var int The employee id, responsible of the movement + */ + public $id_employee; - /** - * @var string The first name of the employee responsible of the movement - */ - public $employee_firstname; + /** + * @var string The first name of the employee responsible of the movement + */ + public $employee_firstname; - /** - * @var string The last name of the employee responsible of the movement - */ - public $employee_lastname; + /** + * @var string The last name of the employee responsible of the movement + */ + public $employee_lastname; - /** - * @var int The stock id on wtich the movement is applied - */ - public $id_stock; + /** + * @var int The stock id on wtich the movement is applied + */ + public $id_stock; - /** - * @var int the quantity of product with is moved - */ - public $physical_quantity; + /** + * @var int the quantity of product with is moved + */ + public $physical_quantity; - /** - * @var int id of the movement reason assoiated to the movement - */ - public $id_stock_mvt_reason; + /** + * @var int id of the movement reason assoiated to the movement + */ + public $id_stock_mvt_reason; - /** - * @var int Used when the movement is due to a customer order - */ - public $id_order = null; + /** + * @var int Used when the movement is due to a customer order + */ + public $id_order = null; - /** - * @var int detrmine if the movement is a positive or negative operation - */ - public $sign; + /** + * @var int detrmine if the movement is a positive or negative operation + */ + public $sign; - /** - * @var int Used when the movement is due to a supplier order - */ - public $id_supply_order = null; + /** + * @var int Used when the movement is due to a supplier order + */ + public $id_supply_order = null; - /** - * @var float Last value of the weighted-average method - */ - public $last_wa = null; + /** + * @var float Last value of the weighted-average method + */ + public $last_wa = null; - /** - * @var float Current value of the weighted-average method - */ - public $current_wa = null; + /** + * @var float Current value of the weighted-average method + */ + public $current_wa = null; - /** - * @var float The unit price without tax of the product associated to the movement - */ - public $price_te; + /** + * @var float The unit price without tax of the product associated to the movement + */ + public $price_te; - /** - * @var int Refers to an other id_stock_mvt : used for LIFO/FIFO implementation in StockManager - */ - public $referer; + /** + * @var int Refers to an other id_stock_mvt : used for LIFO/FIFO implementation in StockManager + */ + public $referer; - /** - * @var int id_product (@see Stock::id_product) - */ - public $id_product; + /** + * @var int id_product (@see Stock::id_product) + */ + public $id_product; - /** - * @var int id_product_attribute (@see Stock::id_product_attribute) - */ - public $id_product_attribute; + /** + * @var int id_product_attribute (@see Stock::id_product_attribute) + */ + public $id_product_attribute; - /** - * @var int id_warehouse (@see Stock::id_warehouse) - */ - public $id_warehouse; + /** + * @var int id_warehouse (@see Stock::id_warehouse) + */ + public $id_warehouse; - /** - * @var int id_currency (@see Warehouse::id_currency) - */ - public $id_currency; + /** + * @var int id_currency (@see Warehouse::id_currency) + */ + public $id_currency; - /** - * @var string management_type (@see Warehouse::management_type) - */ - public $management_type; + /** + * @var string management_type (@see Warehouse::management_type) + */ + public $management_type; - /* - * @var string : Name of the product (@see Product::getProductName) - */ - public $product_name; + /* + * @var string : Name of the product (@see Product::getProductName) + */ + public $product_name; - /** - * @var string EAN13 of the product (@see Stock::product_ean13) - */ - public $ean13; + /** + * @var string EAN13 of the product (@see Stock::product_ean13) + */ + public $ean13; - /** - * @var string UPC of the product (@see Stock::product_upc) - */ - public $upc; + /** + * @var string UPC of the product (@see Stock::product_upc) + */ + public $upc; - /** - * @var string Reference of the product (@see Stock::product_reference) - */ - public $reference; + /** + * @var string Reference of the product (@see Stock::product_reference) + */ + public $reference; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'stock_mvt', - 'primary' => 'id_stock_mvt', - 'fields' => array( - 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'employee_firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), - 'employee_lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), - 'id_stock' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'physical_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), - 'id_stock_mvt_reason' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_supply_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'sign' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), - 'last_wa' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'current_wa' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'price_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'referer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'stock_mvt', + 'primary' => 'id_stock_mvt', + 'fields' => array( + 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'employee_firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), + 'employee_lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), + 'id_stock' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'physical_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), + 'id_stock_mvt_reason' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_supply_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'sign' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), + 'last_wa' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'current_wa' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'price_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'referer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), + ), + ); - /** - * @see ObjectModel::$webserviceParameters - */ - protected $webserviceParameters = array( - 'fields' => array( - 'id_product' => array('xlink_resource' => 'products'), - 'id_product_attribute' => array('xlink_resource' => 'combinations'), - 'id_warehouse' => array('xlink_resource' => 'warehouses'), - 'id_currency' => array('xlink_resource' => 'currencies'), - 'management_type' => array(), - 'id_employee' => array('xlink_resource' => 'employees'), - 'id_stock' => array('xlink_resource' => 'stocks'), - 'id_stock_mvt_reason' => array('xlink_resource' => 'stock_movement_reasons'), - 'id_order' => array('xlink_resource' => 'orders'), - 'id_supply_order' => array('xlink_resource' => 'supply_orders'), - 'product_name' => array('getter' => 'getWSProductName', 'i18n' => true), - 'ean13' => array(), - 'upc' => array(), - 'reference' => array(), - ), - 'hidden_fields' => array( - 'referer', - 'employee_firstname', - 'employee_lastname', - ), - ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'fields' => array( + 'id_product' => array('xlink_resource' => 'products'), + 'id_product_attribute' => array('xlink_resource' => 'combinations'), + 'id_warehouse' => array('xlink_resource' => 'warehouses'), + 'id_currency' => array('xlink_resource' => 'currencies'), + 'management_type' => array(), + 'id_employee' => array('xlink_resource' => 'employees'), + 'id_stock' => array('xlink_resource' => 'stocks'), + 'id_stock_mvt_reason' => array('xlink_resource' => 'stock_movement_reasons'), + 'id_order' => array('xlink_resource' => 'orders'), + 'id_supply_order' => array('xlink_resource' => 'supply_orders'), + 'product_name' => array('getter' => 'getWSProductName', 'i18n' => true), + 'ean13' => array(), + 'upc' => array(), + 'reference' => array(), + ), + 'hidden_fields' => array( + 'referer', + 'employee_firstname', + 'employee_lastname', + ), + ); - /** - * Associations tables for attributes that require different tables than stated in ObjectModel::definition - * @var Array - */ - protected $tables_assoc = array( - 'id_product' => array('table' => 's'), - 'id_product_attribute' => array('table' => 's'), - 'id_warehouse' => array('table' => 's'), - 'id_currency' => array('table' => 's'), - 'management_type' => array('table' => 'w'), - 'ean13' => array('table' => 's'), - 'upc' => array('table' => 's'), - 'reference' => array('table' => 's'), - ); + /** + * Associations tables for attributes that require different tables than stated in ObjectModel::definition + * @var Array + */ + protected $tables_assoc = array( + 'id_product' => array('table' => 's'), + 'id_product_attribute' => array('table' => 's'), + 'id_warehouse' => array('table' => 's'), + 'id_currency' => array('table' => 's'), + 'management_type' => array('table' => 'w'), + 'ean13' => array('table' => 's'), + 'upc' => array('table' => 's'), + 'reference' => array('table' => 's'), + ); - /** - * @see ObjectModel - */ - public function __construct($id = null, $id_lang = null, $id_shop = null) - { - // calls parent - parent::__construct($id, $id_lang, $id_shop); + /** + * @see ObjectModel + */ + public function __construct($id = null, $id_lang = null, $id_shop = null) + { + // calls parent + parent::__construct($id, $id_lang, $id_shop); - if ((int)$this->id != 0) - { - $res = $this->getWebserviceObjectList(null, (' AND '.$this->def['primary'].' = '.(int)$this->id), null, null, true); - if (isset($res[0])) - { - foreach ($this->tables_assoc as $key => $param) - $this->{$key} = $res[0][$key]; - } - } - } + if ((int)$this->id != 0) { + $res = $this->getWebserviceObjectList(null, (' AND '.$this->def['primary'].' = '.(int)$this->id), null, null, true); + if (isset($res[0])) { + foreach ($this->tables_assoc as $key => $param) { + $this->{$key} = $res[0][$key]; + } + } + } + } - /** - * @see ObjectModel::getWebserviceObjectList() - * Added $full for this specific object - */ - public function getWebserviceObjectList($join, $filter, $sort, $limit, $full = false) - { - $query = 'SELECT DISTINCT main.'.$this->def['primary'].' '; + /** + * @see ObjectModel::getWebserviceObjectList() + * Added $full for this specific object + */ + public function getWebserviceObjectList($join, $filter, $sort, $limit, $full = false) + { + $query = 'SELECT DISTINCT main.'.$this->def['primary'].' '; - if ($full) - $query .= ', s.id_product, s.id_product_attribute, s.id_warehouse, w.id_currency, w.management_type, + if ($full) { + $query .= ', s.id_product, s.id_product_attribute, s.id_warehouse, w.id_currency, w.management_type, s.ean13, s.upc, s.reference '; + } - $old_filter = $filter; - if ($filter) - foreach ($this->tables_assoc as $key => $value) - $filter = str_replace('main.`'.$key.'`', $value['table'].'.`'.$key.'`', $filter); + $old_filter = $filter; + if ($filter) { + foreach ($this->tables_assoc as $key => $value) { + $filter = str_replace('main.`'.$key.'`', $value['table'].'.`'.$key.'`', $filter); + } + } - $query .= 'FROM '._DB_PREFIX_.$this->def['table'].' as main '; + $query .= 'FROM '._DB_PREFIX_.$this->def['table'].' as main '; - if ($filter !== $old_filter || $full) - { - $query .= 'LEFT JOIN '._DB_PREFIX_.'stock s ON (s.id_stock = main.id_stock) '; - $query .= 'LEFT JOIN '._DB_PREFIX_.'warehouse w ON (w.id_warehouse = s.id_warehouse) '; - $query .= 'LEFT JOIN '._DB_PREFIX_.'currency c ON (c.id_currency = w.id_currency) '; - } + if ($filter !== $old_filter || $full) { + $query .= 'LEFT JOIN '._DB_PREFIX_.'stock s ON (s.id_stock = main.id_stock) '; + $query .= 'LEFT JOIN '._DB_PREFIX_.'warehouse w ON (w.id_warehouse = s.id_warehouse) '; + $query .= 'LEFT JOIN '._DB_PREFIX_.'currency c ON (c.id_currency = w.id_currency) '; + } - if ($join) - $query .= $join; + if ($join) { + $query .= $join; + } - $query .= 'WHERE 1 '; + $query .= 'WHERE 1 '; - if ($filter) - $query .= $filter.' '; + if ($filter) { + $query .= $filter.' '; + } - if ($sort) - $query .= $sort.' '; + if ($sort) { + $query .= $sort.' '; + } - if ($limit) - $query .= $limit.' '; + if ($limit) { + $query .= $limit.' '; + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } - /** - * Webservice : getter for the product name - */ - public function getWSProductName() - { - $res = array(); - foreach (Language::getIDs(true) as $id_lang) - $res[$id_lang] = Product::getProductName($this->id_product, $this->id_product_attribute, $id_lang); + /** + * Webservice : getter for the product name + */ + public function getWSProductName() + { + $res = array(); + foreach (Language::getIDs(true) as $id_lang) { + $res[$id_lang] = Product::getProductName($this->id_product, $this->id_product_attribute, $id_lang); + } - return $res; - } - -} \ No newline at end of file + return $res; + } +} diff --git a/classes/stock/SupplyOrder.php b/classes/stock/SupplyOrder.php index eb2b777c..01f83555 100644 --- a/classes/stock/SupplyOrder.php +++ b/classes/stock/SupplyOrder.php @@ -29,532 +29,543 @@ */ class SupplyOrderCore extends ObjectModel { - /** - * @var int Supplier - */ - public $id_supplier; + /** + * @var int Supplier + */ + public $id_supplier; - /** - * @var string Supplier Name - */ - public $supplier_name; + /** + * @var string Supplier Name + */ + public $supplier_name; - /** - * @var int The language id used on the delivery note - */ - public $id_lang; + /** + * @var int The language id used on the delivery note + */ + public $id_lang; - /** - * @var int Warehouse where products will be delivered - */ - public $id_warehouse; + /** + * @var int Warehouse where products will be delivered + */ + public $id_warehouse; - /** - * @var int Current state of the order - */ - public $id_supply_order_state; + /** + * @var int Current state of the order + */ + public $id_supply_order_state; - /** - * @var int Currency used for the order - */ - public $id_currency; + /** + * @var int Currency used for the order + */ + public $id_currency; - /** - * @var int Currency used by default in main global configuration (i.e. by default for all shops) - */ - public $id_ref_currency; + /** + * @var int Currency used by default in main global configuration (i.e. by default for all shops) + */ + public $id_ref_currency; - /** - * @var string Reference of the order - */ - public $reference; + /** + * @var string Reference of the order + */ + public $reference; - /** - * @var string Date when added - */ - public $date_add; + /** + * @var string Date when added + */ + public $date_add; - /** - * @var string Date when updated - */ - public $date_upd; + /** + * @var string Date when updated + */ + public $date_upd; - /** - * @var string Expected delivery date - */ - public $date_delivery_expected; + /** + * @var string Expected delivery date + */ + public $date_delivery_expected; - /** - * @var float Total price without tax - */ - public $total_te = 0; + /** + * @var float Total price without tax + */ + public $total_te = 0; - /** - * @var float Total price after discount, without tax - */ - public $total_with_discount_te = 0; + /** + * @var float Total price after discount, without tax + */ + public $total_with_discount_te = 0; - /** - * @var float Total price with tax - */ - public $total_ti = 0; + /** + * @var float Total price with tax + */ + public $total_ti = 0; - /** - * @var float Total tax value - */ - public $total_tax = 0; + /** + * @var float Total tax value + */ + public $total_tax = 0; - /** - * @var float Supplier discount rate (for the whole order) - */ - public $discount_rate = 0; + /** + * @var float Supplier discount rate (for the whole order) + */ + public $discount_rate = 0; - /** - * @var float Supplier discount value without tax (for the whole order) - */ - public $discount_value_te = 0; + /** + * @var float Supplier discount value without tax (for the whole order) + */ + public $discount_value_te = 0; - /** - * @var int Tells if this order is a template - */ - public $is_template = 0; + /** + * @var int Tells if this order is a template + */ + public $is_template = 0; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'supply_order', - 'primary' => 'id_supply_order', - 'fields' => array( - 'id_supplier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'supplier_name' => array('type' => self::TYPE_STRING, 'validate' => 'isCatalogName', 'required' => false), - 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_warehouse' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_supply_order_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_ref_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'reference' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true), - 'date_delivery_expected' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), - 'total_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_with_discount_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_ti' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'total_tax' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'discount_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => false), - 'discount_value_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), - 'is_template' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'supply_order', + 'primary' => 'id_supply_order', + 'fields' => array( + 'id_supplier' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'supplier_name' => array('type' => self::TYPE_STRING, 'validate' => 'isCatalogName', 'required' => false), + 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_warehouse' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_supply_order_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_ref_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'reference' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true), + 'date_delivery_expected' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), + 'total_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_with_discount_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_ti' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'total_tax' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'discount_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => false), + 'discount_value_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'is_template' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - /** - * @see ObjectModel::$webserviceParameters - */ - protected $webserviceParameters = array( - 'fields' => array( - 'id_supplier' => array('xlink_resource' => 'suppliers'), - 'id_lang' => array('xlink_resource' => 'languages'), - 'id_warehouse' => array('xlink_resource' => 'warehouses'), - 'id_supply_order_state' => array('xlink_resource' => 'supply_order_states'), - 'id_currency' => array('xlink_resource' => 'currencies'), - ), - 'hidden_fields' => array( - 'id_ref_currency', - ), - 'associations' => array( - 'supply_order_details' => array( - 'resource' => 'supply_order_detail', - 'fields' => array( - 'id' => array(), - 'id_product' => array(), - 'id_product_attribute' => array(), - 'supplier_reference' => array(), - 'product_name' => array(), - ), - ), - ), - ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'fields' => array( + 'id_supplier' => array('xlink_resource' => 'suppliers'), + 'id_lang' => array('xlink_resource' => 'languages'), + 'id_warehouse' => array('xlink_resource' => 'warehouses'), + 'id_supply_order_state' => array('xlink_resource' => 'supply_order_states'), + 'id_currency' => array('xlink_resource' => 'currencies'), + ), + 'hidden_fields' => array( + 'id_ref_currency', + ), + 'associations' => array( + 'supply_order_details' => array( + 'resource' => 'supply_order_detail', + 'fields' => array( + 'id' => array(), + 'id_product' => array(), + 'id_product_attribute' => array(), + 'supplier_reference' => array(), + 'product_name' => array(), + ), + ), + ), + ); - /** - * @see ObjectModel::update() - */ - public function update($null_values = false) - { - $this->calculatePrices(); + /** + * @see ObjectModel::update() + */ + public function update($null_values = false) + { + $this->calculatePrices(); - $res = parent::update($null_values); + $res = parent::update($null_values); - if ($res && !$this->is_template) - $this->addHistory(); + if ($res && !$this->is_template) { + $this->addHistory(); + } - return $res; - } + return $res; + } - /** - * @see ObjectModel::add() - */ - public function add($autodate = true, $null_values = false) - { - $this->calculatePrices(); + /** + * @see ObjectModel::add() + */ + public function add($autodate = true, $null_values = false) + { + $this->calculatePrices(); - $res = parent::add($autodate, $null_values); + $res = parent::add($autodate, $null_values); - if ($res && !$this->is_template) - $this->addHistory(); + if ($res && !$this->is_template) { + $this->addHistory(); + } - return $res; - } + return $res; + } - /** - * Checks all products in this order and calculate prices - * Applies the global discount if necessary - */ - protected function calculatePrices() - { - $this->total_te = 0; - $this->total_with_discount_te = 0; - $this->total_tax = 0; - $this->total_ti = 0; - $is_discount = false; + /** + * Checks all products in this order and calculate prices + * Applies the global discount if necessary + */ + protected function calculatePrices() + { + $this->total_te = 0; + $this->total_with_discount_te = 0; + $this->total_tax = 0; + $this->total_ti = 0; + $is_discount = false; - if (is_numeric($this->discount_rate) && (float)$this->discount_rate >= 0) - $is_discount = true; + if (is_numeric($this->discount_rate) && (float)$this->discount_rate >= 0) { + $is_discount = true; + } - // gets all product entries in this order - $entries = $this->getEntriesCollection(); + // gets all product entries in this order + $entries = $this->getEntriesCollection(); - foreach ($entries as $entry) - { - /** @var SupplyOrderDetail $entry */ - // applys global discount rate on each product if possible - if ($is_discount) - $entry->applyGlobalDiscount((float)$this->discount_rate); + foreach ($entries as $entry) { + /** @var SupplyOrderDetail $entry */ + // applys global discount rate on each product if possible + if ($is_discount) { + $entry->applyGlobalDiscount((float)$this->discount_rate); + } - // adds new prices to the total - $this->total_te += $entry->price_with_discount_te; - $this->total_with_discount_te += $entry->price_with_order_discount_te; - $this->total_tax += $entry->tax_value_with_order_discount; - $this->total_ti = $this->total_tax + $this->total_with_discount_te; - } + // adds new prices to the total + $this->total_te += $entry->price_with_discount_te; + $this->total_with_discount_te += $entry->price_with_order_discount_te; + $this->total_tax += $entry->tax_value_with_order_discount; + $this->total_ti = $this->total_tax + $this->total_with_discount_te; + } - // applies global discount rate if possible - if ($is_discount) - $this->discount_value_te = $this->total_te - $this->total_with_discount_te; - } + // applies global discount rate if possible + if ($is_discount) { + $this->discount_value_te = $this->total_te - $this->total_with_discount_te; + } + } - /** - * Retrieves the product entries for the current order - * - * @param int $id_lang Optional Id Lang - Uses Context::language::id by default - * @return array - */ - public function getEntries($id_lang = null) - { - if ($id_lang == null) - $id_lang = Context::getContext()->language->id; + /** + * Retrieves the product entries for the current order + * + * @param int $id_lang Optional Id Lang - Uses Context::language::id by default + * @return array + */ + public function getEntries($id_lang = null) + { + if ($id_lang == null) { + $id_lang = Context::getContext()->language->id; + } - // build query - $query = new DbQuery(); + // build query + $query = new DbQuery(); - $query->select(' + $query->select(' s.*, IFNULL(CONCAT(pl.name, \' : \', GROUP_CONCAT(agl.name, \' - \', al.name SEPARATOR \', \')), pl.name) as name_displayed'); - $query->from('supply_order_detail', 's'); + $query->from('supply_order_detail', 's'); - $query->innerjoin('product_lang', 'pl', 'pl.id_product = s.id_product AND pl.id_lang = '.$id_lang); + $query->innerjoin('product_lang', 'pl', 'pl.id_product = s.id_product AND pl.id_lang = '.$id_lang); - $query->leftjoin('product', 'p', 'p.id_product = s.id_product'); - $query->leftjoin('product_attribute_combination', 'pac', 'pac.id_product_attribute = s.id_product_attribute'); - $query->leftjoin('attribute', 'atr', 'atr.id_attribute = pac.id_attribute'); - $query->leftjoin('attribute_lang', 'al', 'al.id_attribute = atr.id_attribute AND al.id_lang = '.$id_lang); - $query->leftjoin('attribute_group_lang', 'agl', 'agl.id_attribute_group = atr.id_attribute_group AND agl.id_lang = '.$id_lang); + $query->leftjoin('product', 'p', 'p.id_product = s.id_product'); + $query->leftjoin('product_attribute_combination', 'pac', 'pac.id_product_attribute = s.id_product_attribute'); + $query->leftjoin('attribute', 'atr', 'atr.id_attribute = pac.id_attribute'); + $query->leftjoin('attribute_lang', 'al', 'al.id_attribute = atr.id_attribute AND al.id_lang = '.$id_lang); + $query->leftjoin('attribute_group_lang', 'agl', 'agl.id_attribute_group = atr.id_attribute_group AND agl.id_lang = '.$id_lang); - $query->where('s.id_supply_order = '.(int)$this->id); + $query->where('s.id_supply_order = '.(int)$this->id); - $query->groupBy('s.id_supply_order_detail'); + $query->groupBy('s.id_supply_order_detail'); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } - /** - * Retrieves the details entries (i.e. products) collection for the current order - * - * @return PrestaShopCollection Collection of SupplyOrderDetail - */ - public function getEntriesCollection() - { - $details = new PrestaShopCollection('SupplyOrderDetail'); - $details->where('id_supply_order', '=', $this->id); - return $details; - } + /** + * Retrieves the details entries (i.e. products) collection for the current order + * + * @return PrestaShopCollection Collection of SupplyOrderDetail + */ + public function getEntriesCollection() + { + $details = new PrestaShopCollection('SupplyOrderDetail'); + $details->where('id_supply_order', '=', $this->id); + return $details; + } - /** - * Check if the order has entries - * - * @return bool Has/Has not - */ - public function hasEntries() - { - $query = new DbQuery(); - $query->select('COUNT(*)'); - $query->from('supply_order_detail', 's'); - $query->where('s.id_supply_order = '.(int)$this->id); + /** + * Check if the order has entries + * + * @return bool Has/Has not + */ + public function hasEntries() + { + $query = new DbQuery(); + $query->select('COUNT(*)'); + $query->from('supply_order_detail', 's'); + $query->where('s.id_supply_order = '.(int)$this->id); - return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query) > 0); - } + return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query) > 0); + } - /** - * Check if the current state allows to edit the current order - * - * @return bool - */ - public function isEditable() - { - $query = new DbQuery(); - $query->select('s.editable'); - $query->from('supply_order_state', 's'); - $query->where('s.id_supply_order_state = '.(int)$this->id_supply_order_state); + /** + * Check if the current state allows to edit the current order + * + * @return bool + */ + public function isEditable() + { + $query = new DbQuery(); + $query->select('s.editable'); + $query->from('supply_order_state', 's'); + $query->where('s.id_supply_order_state = '.(int)$this->id_supply_order_state); - return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query) == 1); - } + return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query) == 1); + } - /** - * Checks if the current state allows to generate a delivery note for this order - * - * @return bool - */ - public function isDeliveryNoteAvailable() - { - $query = new DbQuery(); - $query->select('s.delivery_note'); - $query->from('supply_order_state', 's'); - $query->where('s.id_supply_order_state = '.(int)$this->id_supply_order_state); + /** + * Checks if the current state allows to generate a delivery note for this order + * + * @return bool + */ + public function isDeliveryNoteAvailable() + { + $query = new DbQuery(); + $query->select('s.delivery_note'); + $query->from('supply_order_state', 's'); + $query->where('s.id_supply_order_state = '.(int)$this->id_supply_order_state); - return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query) == 1); - } + return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query) == 1); + } - /** - * Checks if the current state allows to add products in stock - * - * @return bool - */ - public function isInReceiptState() - { - $query = new DbQuery(); - $query->select('s.receipt_state'); - $query->from('supply_order_state', 's'); - $query->where('s.id_supply_order_state = '.(int)$this->id_supply_order_state); + /** + * Checks if the current state allows to add products in stock + * + * @return bool + */ + public function isInReceiptState() + { + $query = new DbQuery(); + $query->select('s.receipt_state'); + $query->from('supply_order_state', 's'); + $query->where('s.id_supply_order_state = '.(int)$this->id_supply_order_state); - return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query) == 1); - } + return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query) == 1); + } - /** - * Historizes the order : its id, its state, and the employee responsible for the current action - */ - protected function addHistory() - { - $context = Context::getContext(); - $history = new SupplyOrderHistory(); - $history->id_supply_order = $this->id; - $history->id_state = $this->id_supply_order_state; - $history->id_employee = (int)$context->employee->id; - $history->employee_firstname = pSQL($context->employee->firstname); - $history->employee_lastname = pSQL($context->employee->lastname); + /** + * Historizes the order : its id, its state, and the employee responsible for the current action + */ + protected function addHistory() + { + $context = Context::getContext(); + $history = new SupplyOrderHistory(); + $history->id_supply_order = $this->id; + $history->id_state = $this->id_supply_order_state; + $history->id_employee = (int)$context->employee->id; + $history->employee_firstname = pSQL($context->employee->firstname); + $history->employee_lastname = pSQL($context->employee->lastname); - $history->save(); - } + $history->save(); + } - /** - * Removes all products from the order - */ - public function resetProducts() - { - $products = $this->getEntriesCollection(); + /** + * Removes all products from the order + */ + public function resetProducts() + { + $products = $this->getEntriesCollection(); - foreach ($products as $p) - $p->delete(); - } + foreach ($products as $p) { + $p->delete(); + } + } - /** - * For a given $id_warehouse, tells if it has pending supply orders - * - * @param int $id_warehouse - * @return bool - */ - public static function warehouseHasPendingOrders($id_warehouse) - { - if (!$id_warehouse) - return false; + /** + * For a given $id_warehouse, tells if it has pending supply orders + * + * @param int $id_warehouse + * @return bool + */ + public static function warehouseHasPendingOrders($id_warehouse) + { + if (!$id_warehouse) { + return false; + } - $query = new DbQuery(); - $query->select('COUNT(so.id_supply_order) as supply_orders'); - $query->from('supply_order', 'so'); - $query->leftJoin('supply_order_state', 'sos', 'so.id_supply_order_state = sos.id_supply_order_state'); - $query->where('sos.enclosed != 1'); - $query->where('so.id_warehouse = '.(int)$id_warehouse); + $query = new DbQuery(); + $query->select('COUNT(so.id_supply_order) as supply_orders'); + $query->from('supply_order', 'so'); + $query->leftJoin('supply_order_state', 'sos', 'so.id_supply_order_state = sos.id_supply_order_state'); + $query->where('sos.enclosed != 1'); + $query->where('so.id_warehouse = '.(int)$id_warehouse); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - return ($res > 0); - } + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + return ($res > 0); + } - /** - * For a given $id_supplier, tells if it has pending supply orders - * - * @param int $id_supplier Id Supplier - * @return bool - */ - public static function supplierHasPendingOrders($id_supplier) - { - if (!$id_supplier) - return false; + /** + * For a given $id_supplier, tells if it has pending supply orders + * + * @param int $id_supplier Id Supplier + * @return bool + */ + public static function supplierHasPendingOrders($id_supplier) + { + if (!$id_supplier) { + return false; + } - $query = new DbQuery(); - $query->select('COUNT(so.id_supply_order) as supply_orders'); - $query->from('supply_order', 'so'); - $query->leftJoin('supply_order_state', 'sos', 'so.id_supply_order_state = sos.id_supply_order_state'); - $query->where('sos.enclosed != 1'); - $query->where('so.id_supplier = '.(int)$id_supplier); + $query = new DbQuery(); + $query->select('COUNT(so.id_supply_order) as supply_orders'); + $query->from('supply_order', 'so'); + $query->leftJoin('supply_order_state', 'sos', 'so.id_supply_order_state = sos.id_supply_order_state'); + $query->where('sos.enclosed != 1'); + $query->where('so.id_supplier = '.(int)$id_supplier); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - return ($res > 0); - } + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + return ($res > 0); + } - /** - * For a given id or reference, tells if the supply order exists - * - * @param int|string $match Either the reference of the order, or the Id of the order - * @return int SupplyOrder Id - */ - public static function exists($match) - { - if (!$match) - return false; + /** + * For a given id or reference, tells if the supply order exists + * + * @param int|string $match Either the reference of the order, or the Id of the order + * @return int SupplyOrder Id + */ + public static function exists($match) + { + if (!$match) { + return false; + } - $query = new DbQuery(); - $query->select('id_supply_order'); - $query->from('supply_order', 'so'); - $query->where('so.id_supply_order = '.(int)$match.' OR so.reference = "'.pSQL($match).'"'); + $query = new DbQuery(); + $query->select('id_supply_order'); + $query->from('supply_order', 'so'); + $query->where('so.id_supply_order = '.(int)$match.' OR so.reference = "'.pSQL($match).'"'); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - return ((int)$res); - } + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + return ((int)$res); + } - /** - * For a given reference, returns the corresponding supply order - * - * @param string $reference Reference of the order - * @return bool|SupplyOrder - */ - public static function getSupplyOrderByReference($reference) - { - if (!$reference) - return false; + /** + * For a given reference, returns the corresponding supply order + * + * @param string $reference Reference of the order + * @return bool|SupplyOrder + */ + public static function getSupplyOrderByReference($reference) + { + if (!$reference) { + return false; + } - $query = new DbQuery(); - $query->select('id_supply_order'); - $query->from('supply_order', 'so'); - $query->where('so.reference = "'.pSQL($reference).'"'); - $id_supply_order = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + $query = new DbQuery(); + $query->select('id_supply_order'); + $query->from('supply_order', 'so'); + $query->where('so.reference = "'.pSQL($reference).'"'); + $id_supply_order = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - if (!$id_supply_order) - return false; + if (!$id_supply_order) { + return false; + } - $supply_order = new SupplyOrder($id_supply_order); - return $supply_order; - } + $supply_order = new SupplyOrder($id_supply_order); + return $supply_order; + } - /** - * @see ObjectModel::hydrate() - */ - public function hydrate(array $data, $id_lang = null) - { - $this->id_lang = $id_lang; - if (isset($data[$this->def['primary']])) - $this->id = $data[$this->def['primary']]; - foreach ($data as $key => $value) - { - if (array_key_exists($key, $this)) - { - // formats prices and floats - if ($this->def['fields'][$key]['validate'] == 'isFloat' || - $this->def['fields'][$key]['validate'] == 'isPrice') - $value = Tools::ps_round($value, 6); - $this->$key = $value; - } - } - } + /** + * @see ObjectModel::hydrate() + */ + public function hydrate(array $data, $id_lang = null) + { + $this->id_lang = $id_lang; + if (isset($data[$this->def['primary']])) { + $this->id = $data[$this->def['primary']]; + } + foreach ($data as $key => $value) { + if (array_key_exists($key, $this)) { + // formats prices and floats + if ($this->def['fields'][$key]['validate'] == 'isFloat' || + $this->def['fields'][$key]['validate'] == 'isPrice') { + $value = Tools::ps_round($value, 6); + } + $this->$key = $value; + } + } + } - /** - * Gets the reference of a given order - * - * @param int $id_supply_order - * @return bool|string - */ - public static function getReferenceById($id_supply_order) - { - if (!$id_supply_order) - return false; + /** + * Gets the reference of a given order + * + * @param int $id_supply_order + * @return bool|string + */ + public static function getReferenceById($id_supply_order) + { + if (!$id_supply_order) { + return false; + } - $query = new DbQuery(); - $query->select('so.reference'); - $query->from('supply_order', 'so'); - $query->where('so.id_supply_order = '.(int)$id_supply_order); - $ref = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + $query = new DbQuery(); + $query->select('so.reference'); + $query->from('supply_order', 'so'); + $query->where('so.id_supply_order = '.(int)$id_supply_order); + $ref = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - return (pSQL($ref)); - } + return (pSQL($ref)); + } - public function getAllExpectedQuantity() - { - return Db::getInstance()->getValue(' + public function getAllExpectedQuantity() + { + return Db::getInstance()->getValue(' SELECT SUM(`quantity_expected`) FROM `'._DB_PREFIX_.'supply_order_detail` WHERE `id_supply_order` = '.(int)$this->id - ); - } + ); + } - public function getAllReceivedQuantity() - { - return Db::getInstance()->getValue(' + public function getAllReceivedQuantity() + { + return Db::getInstance()->getValue(' SELECT SUM(`quantity_received`) FROM `'._DB_PREFIX_.'supply_order_detail` WHERE `id_supply_order` = '.(int)$this->id - ); - } + ); + } - public function getAllPendingQuantity() - { - return Db::getInstance()->getValue(' + public function getAllPendingQuantity() + { + return Db::getInstance()->getValue(' SELECT (SUM(`quantity_expected`) - SUM(`quantity_received`)) FROM `'._DB_PREFIX_.'supply_order_detail` WHERE `id_supply_order` = '.(int)$this->id - ); - } + ); + } - /*********************************\ - * - * Webservices Specific Methods - * - *********************************/ + /*********************************\ + * + * Webservices Specific Methods + * + *********************************/ - /** - * Webservice : gets the ids supply_order_detail associated to this order - * - * @return array - */ - public function getWsSupplyOrderDetails() - { - $query = new DbQuery(); - $query->select('sod.id_supply_order_detail as id, sod.id_product, + /** + * Webservice : gets the ids supply_order_detail associated to this order + * + * @return array + */ + public function getWsSupplyOrderDetails() + { + $query = new DbQuery(); + $query->select('sod.id_supply_order_detail as id, sod.id_product, sod.id_product_attribute, sod.name as product_name, supplier_reference'); - $query->from('supply_order_detail', 'sod'); - $query->where('id_supply_order = '.(int)$this->id); - - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + $query->from('supply_order_detail', 'sod'); + $query->where('id_supply_order = '.(int)$this->id); + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } } diff --git a/classes/stock/SupplyOrderDetail.php b/classes/stock/SupplyOrderDetail.php index 3243e45f..cc45e800 100644 --- a/classes/stock/SupplyOrderDetail.php +++ b/classes/stock/SupplyOrderDetail.php @@ -30,311 +30,322 @@ */ class SupplyOrderDetailCore extends ObjectModel { - /** - * @var int Supply order - */ - public $id_supply_order; + /** + * @var int Supply order + */ + public $id_supply_order; - /** - * @var int Product ordered - */ - public $id_product; + /** + * @var int Product ordered + */ + public $id_product; - /** - * @var int Product attribute ordered - */ - public $id_product_attribute; + /** + * @var int Product attribute ordered + */ + public $id_product_attribute; - /** - * @var string Product reference - */ - public $reference; + /** + * @var string Product reference + */ + public $reference; - /** - * @var string Product supplier reference - */ - public $supplier_reference; + /** + * @var string Product supplier reference + */ + public $supplier_reference; - /** - * @var int Product name - */ - public $name; + /** + * @var int Product name + */ + public $name; - /** - * @var int Product EAN13 - */ - public $ean13; + /** + * @var int Product EAN13 + */ + public $ean13; - /** - * @var string UPC - */ - public $upc; + /** + * @var string UPC + */ + public $upc; - /** - * @var int Currency used to buy this particular product - */ - public $id_currency; + /** + * @var int Currency used to buy this particular product + */ + public $id_currency; - /** - * @var float Exchange rate between $id_currency and SupplyOrder::$id_ref_currency, at the time - */ - public $exchange_rate; + /** + * @var float Exchange rate between $id_currency and SupplyOrder::$id_ref_currency, at the time + */ + public $exchange_rate; - /** - * @var float Unit price without discount, without tax - */ - public $unit_price_te = 0; + /** + * @var float Unit price without discount, without tax + */ + public $unit_price_te = 0; - /** - * @var int Quantity ordered - */ - public $quantity_expected = 0; + /** + * @var int Quantity ordered + */ + public $quantity_expected = 0; - /** - * @var int Quantity received - */ - public $quantity_received = 0; + /** + * @var int Quantity received + */ + public $quantity_received = 0; - /** - * @var float This defines the price of the product, considering the number of units to buy. - * ($unit_price_te * $quantity), without discount, without tax - */ - public $price_te = 0; + /** + * @var float This defines the price of the product, considering the number of units to buy. + * ($unit_price_te * $quantity), without discount, without tax + */ + public $price_te = 0; - /** - * @var float Supplier discount rate for a given product - */ - public $discount_rate = 0; + /** + * @var float Supplier discount rate for a given product + */ + public $discount_rate = 0; - /** - * @var float Supplier discount value (($discount_rate / 100) * $price_te), without tax - */ - public $discount_value_te = 0; + /** + * @var float Supplier discount value (($discount_rate / 100) * $price_te), without tax + */ + public $discount_value_te = 0; - /** - * @var float ($price_te - $discount_value_te), with discount, without tax - */ - public $price_with_discount_te = 0; + /** + * @var float ($price_te - $discount_value_te), with discount, without tax + */ + public $price_with_discount_te = 0; - /** - * @var int Tax rate for the given product - */ - public $tax_rate = 0; + /** + * @var int Tax rate for the given product + */ + public $tax_rate = 0; - /** - * @var float Tax value for the given product - */ - public $tax_value = 0; + /** + * @var float Tax value for the given product + */ + public $tax_value = 0; - /** - * @var float ($price_with_discount_te + $tax_value) - */ - public $price_ti = 0; + /** + * @var float ($price_with_discount_te + $tax_value) + */ + public $price_ti = 0; - /** - * @var float Tax value of the given product after applying the global order discount (i.e. if SupplyOrder::discount_rate is set) - */ - public $tax_value_with_order_discount = 0; + /** + * @var float Tax value of the given product after applying the global order discount (i.e. if SupplyOrder::discount_rate is set) + */ + public $tax_value_with_order_discount = 0; - /** - * @var float This is like $price_with_discount_te, considering the global order discount. - * (i.e. if SupplyOrder::discount_rate is set) - */ - public $price_with_order_discount_te = 0; + /** + * @var float This is like $price_with_discount_te, considering the global order discount. + * (i.e. if SupplyOrder::discount_rate is set) + */ + public $price_with_order_discount_te = 0; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'supply_order_detail', - 'primary' => 'id_supply_order_detail', - 'fields' => array( - 'id_supply_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference'), - 'supplier_reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference'), - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true), - 'ean13' => array('type' => self::TYPE_STRING, 'validate' => 'isEan13'), - 'upc' => array('type' => self::TYPE_STRING, 'validate' => 'isUpc'), - 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'exchange_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), - 'unit_price_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'quantity_expected' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), - 'quantity_received' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'price_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'discount_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), - 'discount_value_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'price_with_discount_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'tax_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), - 'tax_value' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'price_ti' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - 'tax_value_with_order_discount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), - 'price_with_order_discount_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'supply_order_detail', + 'primary' => 'id_supply_order_detail', + 'fields' => array( + 'id_supply_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference'), + 'supplier_reference' => array('type' => self::TYPE_STRING, 'validate' => 'isReference'), + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true), + 'ean13' => array('type' => self::TYPE_STRING, 'validate' => 'isEan13'), + 'upc' => array('type' => self::TYPE_STRING, 'validate' => 'isUpc'), + 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'exchange_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), + 'unit_price_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'quantity_expected' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), + 'quantity_received' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'price_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'discount_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), + 'discount_value_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'price_with_discount_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'tax_rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), + 'tax_value' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'price_ti' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'tax_value_with_order_discount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), + 'price_with_order_discount_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + ), + ); - /** - * @see ObjectModel::$webserviceParameters - */ - protected $webserviceParameters = array( - 'objectsNodeName' => 'supply_order_details', - 'objectNodeName' => 'supply_order_detail', - 'fields' => array( - 'id_supply_order' => array('xlink_resource' => 'supply_orders'), - 'id_product' => array('xlink_resource' => 'products'), - 'id_product_attribute' => array('xlink_resource' => 'combinations'), - ), - 'hidden_fields' => array( - 'id_currency', - ), - ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'objectsNodeName' => 'supply_order_details', + 'objectNodeName' => 'supply_order_detail', + 'fields' => array( + 'id_supply_order' => array('xlink_resource' => 'supply_orders'), + 'id_product' => array('xlink_resource' => 'products'), + 'id_product_attribute' => array('xlink_resource' => 'combinations'), + ), + 'hidden_fields' => array( + 'id_currency', + ), + ); - /** - * @see ObjectModel::update() - */ - public function update($null_values = false) - { - $this->calculatePrices(); + /** + * @see ObjectModel::update() + */ + public function update($null_values = false) + { + $this->calculatePrices(); - parent::update($null_values); - } + parent::update($null_values); + } - /** - * @see ObjectModel::add() - */ - public function add($autodate = true, $null_values = false) - { - $this->calculatePrices(); + /** + * @see ObjectModel::add() + */ + public function add($autodate = true, $null_values = false) + { + $this->calculatePrices(); - parent::add($autodate, $null_values); - } + parent::add($autodate, $null_values); + } - /** - * Calculates all prices for this product based on its quantity and unit price - * Applies discount if necessary - * Calculates tax value, function of tax rate - */ - protected function calculatePrices() - { - // calculates entry price - $this->price_te = Tools::ps_round((float)$this->unit_price_te * (int)$this->quantity_expected, 6); + /** + * Calculates all prices for this product based on its quantity and unit price + * Applies discount if necessary + * Calculates tax value, function of tax rate + */ + protected function calculatePrices() + { + // calculates entry price + $this->price_te = Tools::ps_round((float)$this->unit_price_te * (int)$this->quantity_expected, 6); - // calculates entry discount value - if ($this->discount_rate != null && (is_float($this->discount_rate) || is_numeric($this->discount_rate)) && $this->discount_rate > 0) - $this->discount_value_te = Tools::ps_round((float)$this->price_te * ($this->discount_rate / 100), 6); + // calculates entry discount value + if ($this->discount_rate != null && (is_float($this->discount_rate) || is_numeric($this->discount_rate)) && $this->discount_rate > 0) { + $this->discount_value_te = Tools::ps_round((float)$this->price_te * ($this->discount_rate / 100), 6); + } - // calculates entry price with discount - $this->price_with_discount_te = Tools::ps_round($this->price_te - $this->discount_value_te, 6); + // calculates entry price with discount + $this->price_with_discount_te = Tools::ps_round($this->price_te - $this->discount_value_te, 6); - // calculates tax value - $this->tax_value = Tools::ps_round($this->price_with_discount_te * ((float)$this->tax_rate / 100), 6); - $this->price_ti = Tools::ps_round($this->price_with_discount_te + $this->tax_value, 6); + // calculates tax value + $this->tax_value = Tools::ps_round($this->price_with_discount_te * ((float)$this->tax_rate / 100), 6); + $this->price_ti = Tools::ps_round($this->price_with_discount_te + $this->tax_value, 6); - // defines default values for order discount fields - $this->tax_value_with_order_discount = Tools::ps_round($this->tax_value, 6); - $this->price_with_order_discount_te = Tools::ps_round($this->price_with_discount_te, 6); - } + // defines default values for order discount fields + $this->tax_value_with_order_discount = Tools::ps_round($this->tax_value, 6); + $this->price_with_order_discount_te = Tools::ps_round($this->price_with_discount_te, 6); + } - /** - * Applies a global order discount rate, for the current product (i.e detail) - * Calls ObjectModel::update() - * - * @param float|int $discount_rate The discount rate in percent (Ex. 5 for 5 percents) - */ - public function applyGlobalDiscount($discount_rate) - { - if ($discount_rate != null && is_numeric($discount_rate) && (float)$discount_rate > 0) - { - // calculates new price, with global order discount, tax ecluded - $discount_value = $this->price_with_discount_te - (($this->price_with_discount_te * (float)$discount_rate) / 100); + /** + * Applies a global order discount rate, for the current product (i.e detail) + * Calls ObjectModel::update() + * + * @param float|int $discount_rate The discount rate in percent (Ex. 5 for 5 percents) + */ + public function applyGlobalDiscount($discount_rate) + { + if ($discount_rate != null && is_numeric($discount_rate) && (float)$discount_rate > 0) { + // calculates new price, with global order discount, tax ecluded + $discount_value = $this->price_with_discount_te - (($this->price_with_discount_te * (float)$discount_rate) / 100); - $this->price_with_order_discount_te = Tools::ps_round($discount_value, 6); + $this->price_with_order_discount_te = Tools::ps_round($discount_value, 6); - // calculates new tax value, with global order discount - $this->tax_value_with_order_discount = Tools::ps_round($this->price_with_order_discount_te * ((float)$this->tax_rate / 100), 6); + // calculates new tax value, with global order discount + $this->tax_value_with_order_discount = Tools::ps_round($this->price_with_order_discount_te * ((float)$this->tax_rate / 100), 6); - parent::update(); - } - } + parent::update(); + } + } - /** - * @see ObjectModel::validateController() - * - * @param bool $htmlentities Optional - * @return array Errors, if any.. - */ - public function validateController($htmlentities = true) - { - $errors = array(); + /** + * @see ObjectModel::validateController() + * + * @param bool $htmlentities Optional + * @return array Errors, if any.. + */ + public function validateController($htmlentities = true) + { + $errors = array(); - /* required fields */ - $fields_required = $this->fieldsRequired; + /* required fields */ + $fields_required = $this->fieldsRequired; - if (isset(self::$fieldsRequiredDatabase[get_class($this)])) - $fields_required = array_merge( - $this->fieldsRequired, - self::$fieldsRequiredDatabase[get_class($this)] - ); + if (isset(self::$fieldsRequiredDatabase[get_class($this)])) { + $fields_required = array_merge( + $this->fieldsRequired, + self::$fieldsRequiredDatabase[get_class($this)] + ); + } - foreach ($fields_required as $field) - if (($value = $this->{$field}) == false && (string)$value != '0') - if (!$this->id || $field != 'passwd') - $errors[] = '<b>'.SupplyOrderDetail::displayFieldName($field, get_class($this), $htmlentities) - .'</b> '.Tools::displayError('is required.'); + foreach ($fields_required as $field) { + if (($value = $this->{$field}) == false && (string)$value != '0') { + if (!$this->id || $field != 'passwd') { + $errors[] = '<b>'.SupplyOrderDetail::displayFieldName($field, get_class($this), $htmlentities) + .'</b> '.Tools::displayError('is required.'); + } + } + } - /* Checks maximum fields sizes */ - foreach ($this->fieldsSize as $field => $max_length) - if ($value = $this->{$field} && Tools::strlen($value) > $max_length) - $errors[] = sprintf( - Tools::displayError('%1$s is too long. Maximum length: %2$d'), - SupplyOrderDetail::displayFieldName($field, get_class($this), $htmlentities), - $max_length - ); + /* Checks maximum fields sizes */ + foreach ($this->fieldsSize as $field => $max_length) { + if ($value = $this->{$field} && Tools::strlen($value) > $max_length) { + $errors[] = sprintf( + Tools::displayError('%1$s is too long. Maximum length: %2$d'), + SupplyOrderDetail::displayFieldName($field, get_class($this), $htmlentities), + $max_length + ); + } + } - /* Checks fields validity */ - foreach ($this->fieldsValidate as $field => $function) - if ($value = $this->{$field}) - if (!Validate::$function($value) && (!empty($value) || in_array($field, $this->fieldsRequired))) - $errors[] = '<b>'.SupplyOrderDetail::displayFieldName($field, get_class($this), $htmlentities).'</b> '.Tools::displayError('is invalid.'); - else - if ($field == 'passwd') - if ($value = Tools::getValue($field)) - $this->{$field} = Tools::encrypt($value); - else - $this->{$field} = $value; + /* Checks fields validity */ + foreach ($this->fieldsValidate as $field => $function) { + if ($value = $this->{$field}) { + if (!Validate::$function($value) && (!empty($value) || in_array($field, $this->fieldsRequired))) { + $errors[] = '<b>'.SupplyOrderDetail::displayFieldName($field, get_class($this), $htmlentities).'</b> '.Tools::displayError('is invalid.'); + } elseif ($field == 'passwd') { + if ($value = Tools::getValue($field)) { + $this->{$field} = Tools::encrypt($value); + } else { + $this->{$field} = $value; + } + } + } + } - if ($this->quantity_expected <= 0) - $errors[] = '<b>'.SupplyOrderDetail::displayFieldName('quantity_expected', get_class($this)).'</b> '.Tools::displayError('is invalid.'); + if ($this->quantity_expected <= 0) { + $errors[] = '<b>'.SupplyOrderDetail::displayFieldName('quantity_expected', get_class($this)).'</b> '.Tools::displayError('is invalid.'); + } - if ($this->tax_rate < 0 || $this->tax_rate > 100) - $errors[] = '<b>'.SupplyOrderDetail::displayFieldName('tax_rate', get_class($this)).'</b> '.Tools::displayError('is invalid.'); + if ($this->tax_rate < 0 || $this->tax_rate > 100) { + $errors[] = '<b>'.SupplyOrderDetail::displayFieldName('tax_rate', get_class($this)).'</b> '.Tools::displayError('is invalid.'); + } - if ($this->discount_rate < 0 || $this->discount_rate > 100) - $errors[] = '<b>'.SupplyOrderDetail::displayFieldName('discount_rate', get_class($this)).'</b> '.Tools::displayError('is invalid.'); + if ($this->discount_rate < 0 || $this->discount_rate > 100) { + $errors[] = '<b>'.SupplyOrderDetail::displayFieldName('discount_rate', get_class($this)).'</b> '.Tools::displayError('is invalid.'); + } - return $errors; - } - - /** - * @see ObjectModel::hydrate() - */ - public function hydrate(array $data, $id_lang = null) - { - $this->id_lang = $id_lang; - if (isset($data[$this->def['primary']])) - $this->id = $data[$this->def['primary']]; - foreach ($data as $key => $value) - { - if (array_key_exists($key, $this)) - { - // formats prices and floats - if ($this->def['fields'][$key]['validate'] == 'isFloat' || - $this->def['fields'][$key]['validate'] == 'isPrice') - $value = Tools::ps_round($value, 6); - $this->$key = $value; - } - } - } + return $errors; + } + /** + * @see ObjectModel::hydrate() + */ + public function hydrate(array $data, $id_lang = null) + { + $this->id_lang = $id_lang; + if (isset($data[$this->def['primary']])) { + $this->id = $data[$this->def['primary']]; + } + foreach ($data as $key => $value) { + if (array_key_exists($key, $this)) { + // formats prices and floats + if ($this->def['fields'][$key]['validate'] == 'isFloat' || + $this->def['fields'][$key]['validate'] == 'isPrice') { + $value = Tools::ps_round($value, 6); + } + $this->$key = $value; + } + } + } } diff --git a/classes/stock/SupplyOrderHistory.php b/classes/stock/SupplyOrderHistory.php index 062e7d5c..fdf825d1 100644 --- a/classes/stock/SupplyOrderHistory.php +++ b/classes/stock/SupplyOrderHistory.php @@ -29,63 +29,62 @@ */ class SupplyOrderHistoryCore extends ObjectModel { - /** - * @var int Supply order Id - */ - public $id_supply_order; + /** + * @var int Supply order Id + */ + public $id_supply_order; - /** - * @var int Employee Id - */ - public $id_employee; + /** + * @var int Employee Id + */ + public $id_employee; - /** - * @var string The first name of the employee responsible of the movement - */ - public $employee_firstname; + /** + * @var string The first name of the employee responsible of the movement + */ + public $employee_firstname; - /** - * @var string The last name of the employee responsible of the movement - */ - public $employee_lastname; + /** + * @var string The last name of the employee responsible of the movement + */ + public $employee_lastname; - /** - * @var int State of the supply order - */ - public $id_state; + /** + * @var int State of the supply order + */ + public $id_state; - /** - * @var string Date - */ - public $date_add; + /** + * @var string Date + */ + public $date_add; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'supply_order_history', - 'primary' => 'id_supply_order_history', - 'fields' => array( - 'id_supply_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'employee_firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), - 'employee_lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), - 'id_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), - ), - ); - - /** - * @see ObjectModel::$webserviceParameters - */ - protected $webserviceParameters = array( - 'objectsNodeName' => 'supply_order_histories', - 'objectNodeName' => 'supply_order_history', - 'fields' => array( - 'id_supply_order' => array('xlink_resource' => 'supply_orders'), - 'id_employee' => array('xlink_resource' => 'employees'), - 'id_state' => array('xlink_resource' => 'supply_order_states'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'supply_order_history', + 'primary' => 'id_supply_order_history', + 'fields' => array( + 'id_supply_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'employee_firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), + 'employee_lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), + 'id_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), + ), + ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'objectsNodeName' => 'supply_order_histories', + 'objectNodeName' => 'supply_order_history', + 'fields' => array( + 'id_supply_order' => array('xlink_resource' => 'supply_orders'), + 'id_employee' => array('xlink_resource' => 'employees'), + 'id_state' => array('xlink_resource' => 'supply_order_states'), + ), + ); } diff --git a/classes/stock/SupplyOrderReceiptHistory.php b/classes/stock/SupplyOrderReceiptHistory.php index eaac3c65..7265019a 100644 --- a/classes/stock/SupplyOrderReceiptHistory.php +++ b/classes/stock/SupplyOrderReceiptHistory.php @@ -30,68 +30,68 @@ */ class SupplyOrderReceiptHistoryCore extends ObjectModel { - /** - * @var int Detail of the supply order (i.e. One particular product) - */ - public $id_supply_order_detail; + /** + * @var int Detail of the supply order (i.e. One particular product) + */ + public $id_supply_order_detail; - /** - * @var int Employee - */ - public $id_employee; + /** + * @var int Employee + */ + public $id_employee; - /** - * @var string The first name of the employee responsible of the movement - */ - public $employee_firstname; + /** + * @var string The first name of the employee responsible of the movement + */ + public $employee_firstname; - /** - * @var string The last name of the employee responsible of the movement - */ - public $employee_lastname; + /** + * @var string The last name of the employee responsible of the movement + */ + public $employee_lastname; - /** - * @var int State - */ - public $id_supply_order_state; + /** + * @var int State + */ + public $id_supply_order_state; - /** - * @var int Quantity delivered - */ - public $quantity; + /** + * @var int Quantity delivered + */ + public $quantity; - /** - * @var string Date of delivery - */ - public $date_add; + /** + * @var string Date of delivery + */ + public $date_add; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'supply_order_receipt_history', - 'primary' => 'id_supply_order_receipt_history', - 'fields' => array( - 'id_supply_order_detail' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_supply_order_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'employee_firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), - 'employee_lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), - 'quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'supply_order_receipt_history', + 'primary' => 'id_supply_order_receipt_history', + 'fields' => array( + 'id_supply_order_detail' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_supply_order_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'employee_firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), + 'employee_lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), + 'quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - /** - * @see ObjectModel::$webserviceParameters - */ - protected $webserviceParameters = array( - 'objectsNodeName' => 'supply_order_receipt_histories', - 'objectNodeName' => 'supply_order_receipt_history', - 'fields' => array( - 'id_supply_order_detail' => array('xlink_resource' => 'supply_order_details'), - 'id_employee' => array('xlink_resource' => 'employees'), - 'id_supply_order_state' => array('xlink_resource' => 'supply_order_states'), - ), - ); -} \ No newline at end of file + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'objectsNodeName' => 'supply_order_receipt_histories', + 'objectNodeName' => 'supply_order_receipt_history', + 'fields' => array( + 'id_supply_order_detail' => array('xlink_resource' => 'supply_order_details'), + 'id_employee' => array('xlink_resource' => 'employees'), + 'id_supply_order_state' => array('xlink_resource' => 'supply_order_states'), + ), + ); +} diff --git a/classes/stock/SupplyOrderState.php b/classes/stock/SupplyOrderState.php index 75ede5af..0163206f 100644 --- a/classes/stock/SupplyOrderState.php +++ b/classes/stock/SupplyOrderState.php @@ -29,144 +29,148 @@ */ class SupplyOrderStateCore extends ObjectModel { - /** - * @var string Name of the state - */ - public $name; + /** + * @var string Name of the state + */ + public $name; - /** - * @var bool Tells if a delivery note can be issued (i.e. the order has been validated) - */ - public $delivery_note; + /** + * @var bool Tells if a delivery note can be issued (i.e. the order has been validated) + */ + public $delivery_note; - /** - * @var bool Tells if the order is still editable by an employee (i.e. you can add products) - */ - public $editable; + /** + * @var bool Tells if the order is still editable by an employee (i.e. you can add products) + */ + public $editable; - /** - * @var bool Tells if the the order has been delivered - */ - public $receipt_state; + /** + * @var bool Tells if the the order has been delivered + */ + public $receipt_state; - /** - * @var bool Tells if the the order is in a state corresponding to a product pending receipt - */ - public $pending_receipt; + /** + * @var bool Tells if the the order is in a state corresponding to a product pending receipt + */ + public $pending_receipt; - /** - * @var bool Tells if the the order is in an enclosed state (i.e. terminated, canceled) - */ - public $enclosed; + /** + * @var bool Tells if the the order is in an enclosed state (i.e. terminated, canceled) + */ + public $enclosed; - /** - * @var string Color used to display the state in the specified color (Ex. #FFFF00) - */ - public $color; + /** + * @var string Color used to display the state in the specified color (Ex. #FFFF00) + */ + public $color; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'supply_order_state', - 'primary' => 'id_supply_order_state', - 'multilang' => true, - 'fields' => array( - 'delivery_note' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'editable' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'receipt_state' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'pending_receipt' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'enclosed' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'color' => array('type' => self::TYPE_STRING, 'validate' => 'isColor'), - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'supply_order_state', + 'primary' => 'id_supply_order_state', + 'multilang' => true, + 'fields' => array( + 'delivery_note' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'editable' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'receipt_state' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'pending_receipt' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'enclosed' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'color' => array('type' => self::TYPE_STRING, 'validate' => 'isColor'), + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128), + ), + ); - /** - * @see ObjectModel::$webserviceParameters - */ - protected $webserviceParameters = array( - 'objectsNodeName' => 'supply_order_states', - 'objectNodeName' => 'supply_order_state', - 'fields' => array( - ), - ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'objectsNodeName' => 'supply_order_states', + 'objectNodeName' => 'supply_order_state', + 'fields' => array( + ), + ); - /** - * Gets the list of supply order statuses - * - * @param int $id_state_referrer Optional, used to know what state is available after this one - * @param int $id_lang Optional Id Language - * @return array States - */ - public static function getSupplyOrderStates($id_state_referrer = null, $id_lang = null) - { - if ($id_lang == null) - $id_lang = Context::getContext()->language->id; + /** + * Gets the list of supply order statuses + * + * @param int $id_state_referrer Optional, used to know what state is available after this one + * @param int $id_lang Optional Id Language + * @return array States + */ + public static function getSupplyOrderStates($id_state_referrer = null, $id_lang = null) + { + if ($id_lang == null) { + $id_lang = Context::getContext()->language->id; + } - $query = new DbQuery(); - $query->select('sl.name, s.id_supply_order_state'); - $query->from('supply_order_state', 's'); - $query->leftjoin('supply_order_state_lang', 'sl', 's.id_supply_order_state = sl.id_supply_order_state AND sl.id_lang='.(int)$id_lang); + $query = new DbQuery(); + $query->select('sl.name, s.id_supply_order_state'); + $query->from('supply_order_state', 's'); + $query->leftjoin('supply_order_state_lang', 'sl', 's.id_supply_order_state = sl.id_supply_order_state AND sl.id_lang='.(int)$id_lang); - if (!is_null($id_state_referrer)) - { - $is_receipt_state = false; - $is_editable = false; - $is_delivery_note = false; - $is_pending_receipt = false; + if (!is_null($id_state_referrer)) { + $is_receipt_state = false; + $is_editable = false; + $is_delivery_note = false; + $is_pending_receipt = false; - //check current state to see what state is available - $state = new SupplyOrderState((int)$id_state_referrer); - if (Validate::isLoadedObject($state)) - { - $is_receipt_state = $state->receipt_state; - $is_editable = $state->editable; - $is_delivery_note = $state->delivery_note; - $is_pending_receipt = $state->pending_receipt; - } + //check current state to see what state is available + $state = new SupplyOrderState((int)$id_state_referrer); + if (Validate::isLoadedObject($state)) { + $is_receipt_state = $state->receipt_state; + $is_editable = $state->editable; + $is_delivery_note = $state->delivery_note; + $is_pending_receipt = $state->pending_receipt; + } - $query->where('s.id_supply_order_state <> '.(int)$id_state_referrer); + $query->where('s.id_supply_order_state <> '.(int)$id_state_referrer); - //check first if the order is editable - if ($is_editable) - $query->where('s.editable = 1 OR s.delivery_note = 1 OR s.enclosed = 1'); - //check if the delivery note is available or if the state correspond to a pending receipt state - elseif ($is_delivery_note || $is_pending_receipt) - $query->where('(s.delivery_note = 0 AND s.editable = 0) OR s.enclosed = 1'); - //check if the state correspond to a receipt state - elseif ($is_receipt_state) - $query->where('s.receipt_state = 1'); - } + //check first if the order is editable + if ($is_editable) { + $query->where('s.editable = 1 OR s.delivery_note = 1 OR s.enclosed = 1'); + } + //check if the delivery note is available or if the state correspond to a pending receipt state + elseif ($is_delivery_note || $is_pending_receipt) { + $query->where('(s.delivery_note = 0 AND s.editable = 0) OR s.enclosed = 1'); + } + //check if the state correspond to a receipt state + elseif ($is_receipt_state) { + $query->where('s.receipt_state = 1'); + } + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } - /** - * Gets the list of supply order statuses - * - * @param array $ids Optional Do not include these ids in the result - * @param int $id_lang Optional - * @return array - */ - public static function getStates($ids = null, $id_lang = null) - { - if ($id_lang == null) - $id_lang = Context::getContext()->language->id; + /** + * Gets the list of supply order statuses + * + * @param array $ids Optional Do not include these ids in the result + * @param int $id_lang Optional + * @return array + */ + public static function getStates($ids = null, $id_lang = null) + { + if ($id_lang == null) { + $id_lang = Context::getContext()->language->id; + } - if ($ids && !is_array($ids)) - $ids = array(); + if ($ids && !is_array($ids)) { + $ids = array(); + } - $query = new DbQuery(); - $query->select('sl.name, s.id_supply_order_state'); - $query->from('supply_order_state', 's'); - $query->leftjoin('supply_order_state_lang', 'sl', 's.id_supply_order_state = sl.id_supply_order_state AND sl.id_lang='.(int)$id_lang); - if ($ids) - $query->where('s.id_supply_order_state NOT IN('.implode(',', array_map('intval', $ids)).')'); + $query = new DbQuery(); + $query->select('sl.name, s.id_supply_order_state'); + $query->from('supply_order_state', 's'); + $query->leftjoin('supply_order_state_lang', 'sl', 's.id_supply_order_state = sl.id_supply_order_state AND sl.id_lang='.(int)$id_lang); + if ($ids) { + $query->where('s.id_supply_order_state NOT IN('.implode(',', array_map('intval', $ids)).')'); + } - $query->orderBy('sl.name ASC'); - - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + $query->orderBy('sl.name ASC'); + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } } diff --git a/classes/stock/Warehouse.php b/classes/stock/Warehouse.php index 0e301498..22e75246 100644 --- a/classes/stock/Warehouse.php +++ b/classes/stock/Warehouse.php @@ -31,357 +31,365 @@ */ class WarehouseCore extends ObjectModel { - /** @var int identifier of the warehouse */ - public $id; + /** @var int identifier of the warehouse */ + public $id; - /** @var int Id of the address associated to the warehouse */ - public $id_address; + /** @var int Id of the address associated to the warehouse */ + public $id_address; - /** @var string Reference of the warehouse */ - public $reference; + /** @var string Reference of the warehouse */ + public $reference; - /** @var string Name of the warehouse */ - public $name; + /** @var string Name of the warehouse */ + public $name; - /** @var int Id of the employee who manages the warehouse */ - public $id_employee; + /** @var int Id of the employee who manages the warehouse */ + public $id_employee; - /** @var int Id of the valuation currency of the warehouse */ - public $id_currency; + /** @var int Id of the valuation currency of the warehouse */ + public $id_currency; - /** @var bool True if warehouse has been deleted (hence, no deletion in DB) */ - public $deleted = 0; + /** @var bool True if warehouse has been deleted (hence, no deletion in DB) */ + public $deleted = 0; - /** - * Describes the way a Warehouse is managed - * - * @var string enum WA|LIFO|FIFO - */ - public $management_type; + /** + * Describes the way a Warehouse is managed + * + * @var string enum WA|LIFO|FIFO + */ + public $management_type; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'warehouse', - 'primary' => 'id_warehouse', - 'fields' => array( - 'id_address' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'reference' => array('type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true, 'size' => 45), - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true, 'size' => 45), - 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'management_type' => array('type' => self::TYPE_STRING, 'validate' => 'isStockManagement', 'required' => true), - 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'deleted' => array('type' => self::TYPE_BOOL), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'warehouse', + 'primary' => 'id_warehouse', + 'fields' => array( + 'id_address' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'reference' => array('type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true, 'size' => 45), + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true, 'size' => 45), + 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'management_type' => array('type' => self::TYPE_STRING, 'validate' => 'isStockManagement', 'required' => true), + 'id_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'deleted' => array('type' => self::TYPE_BOOL), + ), + ); - /** - * @see ObjectModel::$webserviceParameters - */ - protected $webserviceParameters = array( - 'fields' => array( - 'id_address' => array('xlink_resource' => 'addresses'), - 'id_employee' => array('xlink_resource' => 'employees'), - 'id_currency' => array('xlink_resource' => 'currencies'), - 'valuation' => array('getter' => 'getWsStockValue', 'setter' => false), - 'deleted' => array(), - ), - 'associations' => array( - 'stocks' => array( - 'resource' => 'stock', - 'fields' => array( - 'id' => array(), - ), - ), - 'carriers' => array( - 'resource' => 'carrier', - 'fields' => array( - 'id' => array(), - ), - ), - 'shops' => array( - 'resource' => 'shop', - 'fields' => array( - 'id' => array(), - 'name' => array(), - ), - ), - ), - ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'fields' => array( + 'id_address' => array('xlink_resource' => 'addresses'), + 'id_employee' => array('xlink_resource' => 'employees'), + 'id_currency' => array('xlink_resource' => 'currencies'), + 'valuation' => array('getter' => 'getWsStockValue', 'setter' => false), + 'deleted' => array(), + ), + 'associations' => array( + 'stocks' => array( + 'resource' => 'stock', + 'fields' => array( + 'id' => array(), + ), + ), + 'carriers' => array( + 'resource' => 'carrier', + 'fields' => array( + 'id' => array(), + ), + ), + 'shops' => array( + 'resource' => 'shop', + 'fields' => array( + 'id' => array(), + 'name' => array(), + ), + ), + ), + ); - /** - * Gets the shops associated to the current warehouse - * - * @return array Shops (id, name) - */ - public function getShops() - { - $query = new DbQuery(); - $query->select('ws.id_shop, s.name'); - $query->from('warehouse_shop', 'ws'); - $query->leftJoin('shop', 's', 's.id_shop = ws.id_shop'); - $query->where($this->def['primary'].' = '.(int)$this->id); + /** + * Gets the shops associated to the current warehouse + * + * @return array Shops (id, name) + */ + public function getShops() + { + $query = new DbQuery(); + $query->select('ws.id_shop, s.name'); + $query->from('warehouse_shop', 'ws'); + $query->leftJoin('shop', 's', 's.id_shop = ws.id_shop'); + $query->where($this->def['primary'].' = '.(int)$this->id); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - return $res; - } + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + return $res; + } - /** - * Gets the carriers associated to the current warehouse - * - * @return array Ids of the associated carriers - */ - public function getCarriers($return_reference = false) - { - $ids_carrier = array(); + /** + * Gets the carriers associated to the current warehouse + * + * @return array Ids of the associated carriers + */ + public function getCarriers($return_reference = false) + { + $ids_carrier = array(); - $query = new DbQuery(); - if ($return_reference) - $query->select('wc.id_carrier'); - else - $query->select('c.id_carrier'); - $query->from('warehouse_carrier', 'wc'); - $query->innerJoin('carrier', 'c', 'c.id_reference = wc.id_carrier'); - $query->where($this->def['primary'].' = '.(int)$this->id); - $query->where('c.deleted = 0'); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + $query = new DbQuery(); + if ($return_reference) { + $query->select('wc.id_carrier'); + } else { + $query->select('c.id_carrier'); + } + $query->from('warehouse_carrier', 'wc'); + $query->innerJoin('carrier', 'c', 'c.id_reference = wc.id_carrier'); + $query->where($this->def['primary'].' = '.(int)$this->id); + $query->where('c.deleted = 0'); + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - if (!is_array($res)) - return $ids_carrier; + if (!is_array($res)) { + return $ids_carrier; + } - foreach ($res as $carriers) - foreach ($carriers as $carrier) - $ids_carrier[$carrier] = $carrier; + foreach ($res as $carriers) { + foreach ($carriers as $carrier) { + $ids_carrier[$carrier] = $carrier; + } + } - return $ids_carrier; - } + return $ids_carrier; + } - /** - * Sets the carriers associated to the current warehouse - * - * @param array $ids_carriers - */ - public function setCarriers($ids_carriers) - { - if (!is_array($ids_carriers)) - $ids_carriers = array(); + /** + * Sets the carriers associated to the current warehouse + * + * @param array $ids_carriers + */ + public function setCarriers($ids_carriers) + { + if (!is_array($ids_carriers)) { + $ids_carriers = array(); + } - $row_to_insert = array(); - foreach ($ids_carriers as $id_carrier) - $row_to_insert[] = array($this->def['primary'] => $this->id, 'id_carrier' => (int)$id_carrier); + $row_to_insert = array(); + foreach ($ids_carriers as $id_carrier) { + $row_to_insert[] = array($this->def['primary'] => $this->id, 'id_carrier' => (int)$id_carrier); + } - Db::getInstance()->execute(' + Db::getInstance()->execute(' DELETE FROM '._DB_PREFIX_.'warehouse_carrier WHERE '.$this->def['primary'].' = '.(int)$this->id); - if ($row_to_insert) - Db::getInstance()->insert('warehouse_carrier', $row_to_insert); - } + if ($row_to_insert) { + Db::getInstance()->insert('warehouse_carrier', $row_to_insert); + } + } - /** - * For a given carrier, removes it from the warehouse/carrier association - * If $id_warehouse is set, it only removes the carrier for this warehouse - * - * @param int $id_carrier Id of the carrier to remove - * @param int $id_warehouse optional Id of the warehouse to filter - */ - public static function removeCarrier($id_carrier, $id_warehouse = null) - { - Db::getInstance()->execute(' + /** + * For a given carrier, removes it from the warehouse/carrier association + * If $id_warehouse is set, it only removes the carrier for this warehouse + * + * @param int $id_carrier Id of the carrier to remove + * @param int $id_warehouse optional Id of the warehouse to filter + */ + public static function removeCarrier($id_carrier, $id_warehouse = null) + { + Db::getInstance()->execute(' DELETE FROM '._DB_PREFIX_.'warehouse_carrier WHERE id_carrier = '.(int)$id_carrier. - ($id_warehouse ? ' AND id_warehouse = '.(int)$id_warehouse : '')); - } + ($id_warehouse ? ' AND id_warehouse = '.(int)$id_warehouse : '')); + } - /** - * Checks if a warehouse is empty - i.e. has no stock - * - * @return bool - */ - public function isEmpty() - { - $query = new DbQuery(); - $query->select('SUM(s.physical_quantity)'); - $query->from('stock', 's'); - $query->where($this->def['primary'].' = '.(int)$this->id); - return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query) == 0); - } + /** + * Checks if a warehouse is empty - i.e. has no stock + * + * @return bool + */ + public function isEmpty() + { + $query = new DbQuery(); + $query->select('SUM(s.physical_quantity)'); + $query->from('stock', 's'); + $query->where($this->def['primary'].' = '.(int)$this->id); + return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query) == 0); + } - /** - * Checks if the given warehouse exists - * - * @param int $id_warehouse - * @return bool Exists/Does not exist - */ - public static function exists($id_warehouse) - { - $query = new DbQuery(); - $query->select('id_warehouse'); - $query->from('warehouse'); - $query->where('id_warehouse = '.(int)$id_warehouse); - $query->where('deleted = 0'); - return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query)); - } + /** + * Checks if the given warehouse exists + * + * @param int $id_warehouse + * @return bool Exists/Does not exist + */ + public static function exists($id_warehouse) + { + $query = new DbQuery(); + $query->select('id_warehouse'); + $query->from('warehouse'); + $query->where('id_warehouse = '.(int)$id_warehouse); + $query->where('deleted = 0'); + return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query)); + } - /** - * For a given {product, product attribute} sets its location in the given warehouse - * First, for the given parameters, it cleans the database before updating - * - * @param int $id_product ID of the product - * @param int $id_product_attribute Use 0 if this product does not have attributes - * @param int $id_warehouse ID of the warehouse - * @param string $location Describes the location (no lang id required) - * @return bool Success/Failure - */ - public static function setProductLocation($id_product, $id_product_attribute, $id_warehouse, $location) - { - Db::getInstance()->execute(' + /** + * For a given {product, product attribute} sets its location in the given warehouse + * First, for the given parameters, it cleans the database before updating + * + * @param int $id_product ID of the product + * @param int $id_product_attribute Use 0 if this product does not have attributes + * @param int $id_warehouse ID of the warehouse + * @param string $location Describes the location (no lang id required) + * @return bool Success/Failure + */ + public static function setProductLocation($id_product, $id_product_attribute, $id_warehouse, $location) + { + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'warehouse_product_location` WHERE `id_product` = '.(int)$id_product.' AND `id_product_attribute` = '.(int)$id_product_attribute.' AND `id_warehouse` = '.(int)$id_warehouse); - $row_to_insert = array( - 'id_product' => (int)$id_product, - 'id_product_attribute' => (int)$id_product_attribute, - 'id_warehouse' => (int)$id_warehouse, - 'location' => pSQL($location), - ); + $row_to_insert = array( + 'id_product' => (int)$id_product, + 'id_product_attribute' => (int)$id_product_attribute, + 'id_warehouse' => (int)$id_warehouse, + 'location' => pSQL($location), + ); - return Db::getInstance()->insert('warehouse_product_location', $row_to_insert); - } + return Db::getInstance()->insert('warehouse_product_location', $row_to_insert); + } - /** - * Resets all product locations for this warehouse - */ - public function resetProductsLocations() - { - Db::getInstance()->execute(' + /** + * Resets all product locations for this warehouse + */ + public function resetProductsLocations() + { + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'warehouse_product_location` WHERE `id_warehouse` = '.(int)$this->id); - } + } - /** - * For a given {product, product attribute} gets its location in the given warehouse - * - * @param int $id_product ID of the product - * @param int $id_product_attribute Use 0 if this product does not have attributes - * @param int $id_warehouse ID of the warehouse - * @return string Location of the product - */ - public static function getProductLocation($id_product, $id_product_attribute, $id_warehouse) - { - $query = new DbQuery(); - $query->select('location'); - $query->from('warehouse_product_location'); - $query->where('id_warehouse = '.(int)$id_warehouse); - $query->where('id_product = '.(int)$id_product); - $query->where('id_product_attribute = '.(int)$id_product_attribute); + /** + * For a given {product, product attribute} gets its location in the given warehouse + * + * @param int $id_product ID of the product + * @param int $id_product_attribute Use 0 if this product does not have attributes + * @param int $id_warehouse ID of the warehouse + * @return string Location of the product + */ + public static function getProductLocation($id_product, $id_product_attribute, $id_warehouse) + { + $query = new DbQuery(); + $query->select('location'); + $query->from('warehouse_product_location'); + $query->where('id_warehouse = '.(int)$id_warehouse); + $query->where('id_product = '.(int)$id_product); + $query->where('id_product_attribute = '.(int)$id_product_attribute); - return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query)); - } + return (Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query)); + } - /** - * For a given {product, product attribute} gets warehouse list - * - * @param int $id_product ID of the product - * @param int $id_product_attribute Optional, uses 0 if this product does not have attributes - * @param int $id_shop Optional, ID of the shop. Uses the context shop id (@see Context::shop) - * @return array Warehouses (ID, reference/name concatenated) - */ - public static function getProductWarehouseList($id_product, $id_product_attribute = 0, $id_shop = null) - { - // if it's a pack, returns warehouses if and only if some products use the advanced stock management - $share_stock = false; - if ($id_shop === null) - { - if (Shop::getContext() == Shop::CONTEXT_GROUP) - $shop_group = Shop::getContextShopGroup(); - else - { - $shop_group = Context::getContext()->shop->getGroup(); - $id_shop = (int)Context::getContext()->shop->id; - } - $share_stock = $shop_group->share_stock; - } - else - { - $shop_group = Shop::getGroupFromShop($id_shop); - $share_stock = $shop_group['share_stock']; - } + /** + * For a given {product, product attribute} gets warehouse list + * + * @param int $id_product ID of the product + * @param int $id_product_attribute Optional, uses 0 if this product does not have attributes + * @param int $id_shop Optional, ID of the shop. Uses the context shop id (@see Context::shop) + * @return array Warehouses (ID, reference/name concatenated) + */ + public static function getProductWarehouseList($id_product, $id_product_attribute = 0, $id_shop = null) + { + // if it's a pack, returns warehouses if and only if some products use the advanced stock management + $share_stock = false; + if ($id_shop === null) { + if (Shop::getContext() == Shop::CONTEXT_GROUP) { + $shop_group = Shop::getContextShopGroup(); + } else { + $shop_group = Context::getContext()->shop->getGroup(); + $id_shop = (int)Context::getContext()->shop->id; + } + $share_stock = $shop_group->share_stock; + } else { + $shop_group = Shop::getGroupFromShop($id_shop); + $share_stock = $shop_group['share_stock']; + } - if ($share_stock) - $ids_shop = Shop::getShops(true, (int)$shop_group->id, true); - else - $ids_shop = array((int)$id_shop); + if ($share_stock) { + $ids_shop = Shop::getShops(true, (int)$shop_group->id, true); + } else { + $ids_shop = array((int)$id_shop); + } - $query = new DbQuery(); - $query->select('wpl.id_warehouse, CONCAT(w.reference, " - ", w.name) as name'); - $query->from('warehouse_product_location', 'wpl'); - $query->innerJoin('warehouse_shop', 'ws', 'ws.id_warehouse = wpl.id_warehouse AND id_shop IN ('.implode(',', array_map('intval', $ids_shop)).')'); - $query->innerJoin('warehouse', 'w', 'ws.id_warehouse = w.id_warehouse'); - $query->where('id_product = '.(int)$id_product); - $query->where('id_product_attribute = '.(int)$id_product_attribute); - $query->where('w.deleted = 0'); - $query->groupBy('wpl.id_warehouse'); + $query = new DbQuery(); + $query->select('wpl.id_warehouse, CONCAT(w.reference, " - ", w.name) as name'); + $query->from('warehouse_product_location', 'wpl'); + $query->innerJoin('warehouse_shop', 'ws', 'ws.id_warehouse = wpl.id_warehouse AND id_shop IN ('.implode(',', array_map('intval', $ids_shop)).')'); + $query->innerJoin('warehouse', 'w', 'ws.id_warehouse = w.id_warehouse'); + $query->where('id_product = '.(int)$id_product); + $query->where('id_product_attribute = '.(int)$id_product_attribute); + $query->where('w.deleted = 0'); + $query->groupBy('wpl.id_warehouse'); - return (Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query)); - } + return (Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query)); + } - /** - * Gets available warehouses - * It is possible via ignore_shop and id_shop to filter the list with shop id - * - * @param bool $ignore_shop Optional, false by default - Allows to get only the warehouses that are associated to one/some shops (@see $id_shop) - * @param int $id_shop Optional, Context::shop::Id by default - Allows to define a specific shop to filter. - * @return array Warehouses (ID, reference/name concatenated) - */ - public static function getWarehouses($ignore_shop = false, $id_shop = null) - { - if (!$ignore_shop) - if (is_null($id_shop)) - $id_shop = Context::getContext()->shop->id; + /** + * Gets available warehouses + * It is possible via ignore_shop and id_shop to filter the list with shop id + * + * @param bool $ignore_shop Optional, false by default - Allows to get only the warehouses that are associated to one/some shops (@see $id_shop) + * @param int $id_shop Optional, Context::shop::Id by default - Allows to define a specific shop to filter. + * @return array Warehouses (ID, reference/name concatenated) + */ + public static function getWarehouses($ignore_shop = false, $id_shop = null) + { + if (!$ignore_shop) { + if (is_null($id_shop)) { + $id_shop = Context::getContext()->shop->id; + } + } - $query = new DbQuery(); - $query->select('w.id_warehouse, CONCAT(reference, \' - \', name) as name'); - $query->from('warehouse', 'w'); - $query->where('deleted = 0'); - $query->orderBy('reference ASC'); - if (!$ignore_shop) - $query->innerJoin('warehouse_shop', 'ws', 'ws.id_warehouse = w.id_warehouse AND ws.id_shop = '.(int)$id_shop); + $query = new DbQuery(); + $query->select('w.id_warehouse, CONCAT(reference, \' - \', name) as name'); + $query->from('warehouse', 'w'); + $query->where('deleted = 0'); + $query->orderBy('reference ASC'); + if (!$ignore_shop) { + $query->innerJoin('warehouse_shop', 'ws', 'ws.id_warehouse = w.id_warehouse AND ws.id_shop = '.(int)$id_shop); + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } - /** - * Gets warehouses grouped by shops - * - * @return array (of array) Warehouses ID are grouped by shops ID - */ - public static function getWarehousesGroupedByShops() - { - $ids_warehouse = array(); - $query = new DbQuery(); - $query->select('id_warehouse, id_shop'); - $query->from('warehouse_shop'); - $query->orderBy('id_shop'); + /** + * Gets warehouses grouped by shops + * + * @return array (of array) Warehouses ID are grouped by shops ID + */ + public static function getWarehousesGroupedByShops() + { + $ids_warehouse = array(); + $query = new DbQuery(); + $query->select('id_warehouse, id_shop'); + $query->from('warehouse_shop'); + $query->orderBy('id_shop'); - // queries to get warehouse ids grouped by shops - foreach (Db::getInstance()->executeS($query) as $row) - $ids_warehouse[$row['id_shop']][] = $row['id_warehouse']; + // queries to get warehouse ids grouped by shops + foreach (Db::getInstance()->executeS($query) as $row) { + $ids_warehouse[$row['id_shop']][] = $row['id_warehouse']; + } - return $ids_warehouse; - } + return $ids_warehouse; + } - /** - * Gets the number of products in the current warehouse - * - * @return int Number of different id_stock - */ - public function getNumberOfProducts() - { - $query = ' + /** + * Gets the number of products in the current warehouse + * + * @return int Number of different id_stock + */ + public function getNumberOfProducts() + { + $query = ' SELECT COUNT(t.id_stock) FROM ( @@ -391,222 +399,229 @@ class WarehouseCore extends ObjectModel GROUP BY s.id_product, s.id_product_attribute ) as t'; - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } - /** - * Gets the number of quantities - for all products - in the current warehouse - * - * @return int Total Quantity - */ - public function getQuantitiesOfProducts() - { - $query = ' + /** + * Gets the number of quantities - for all products - in the current warehouse + * + * @return int Total Quantity + */ + public function getQuantitiesOfProducts() + { + $query = ' SELECT SUM(s.physical_quantity) FROM '._DB_PREFIX_.'stock s WHERE s.id_warehouse = '.(int)$this->id; - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - return ($res ? $res : 0); - } + return ($res ? $res : 0); + } - /** - * Gets the value of the stock in the current warehouse - * - * @return int Value of the stock - */ - public function getStockValue() - { - $query = new DbQuery(); - $query->select('SUM(s.`price_te` * s.`physical_quantity`)'); - $query->from('stock', 's'); - $query->where('s.`id_warehouse` = '.(int)$this->id); + /** + * Gets the value of the stock in the current warehouse + * + * @return int Value of the stock + */ + public function getStockValue() + { + $query = new DbQuery(); + $query->select('SUM(s.`price_te` * s.`physical_quantity`)'); + $query->from('stock', 's'); + $query->where('s.`id_warehouse` = '.(int)$this->id); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } - /** - * For a given employee, gets the warehouse(s) he/she manages - * - * @param int $id_employee Manager ID - * @return array ids_warehouse Ids of the warehouses - */ - public static function getWarehousesByEmployee($id_employee) - { - $query = new DbQuery(); - $query->select('w.id_warehouse'); - $query->from('warehouse', 'w'); - $query->where('w.id_employee = '.(int)$id_employee); + /** + * For a given employee, gets the warehouse(s) he/she manages + * + * @param int $id_employee Manager ID + * @return array ids_warehouse Ids of the warehouses + */ + public static function getWarehousesByEmployee($id_employee) + { + $query = new DbQuery(); + $query->select('w.id_warehouse'); + $query->from('warehouse', 'w'); + $query->where('w.id_employee = '.(int)$id_employee); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } - /** - * For a given product, returns the warehouses it is stored in - * - * @param int $id_product Product Id - * @param int $id_product_attribute Optional, Product Attribute Id - 0 by default (no attribues) - * @return array Warehouses Ids and names - */ - public static function getWarehousesByProductId($id_product, $id_product_attribute = 0) - { - if (!$id_product && !$id_product_attribute) - return array(); + /** + * For a given product, returns the warehouses it is stored in + * + * @param int $id_product Product Id + * @param int $id_product_attribute Optional, Product Attribute Id - 0 by default (no attribues) + * @return array Warehouses Ids and names + */ + public static function getWarehousesByProductId($id_product, $id_product_attribute = 0) + { + if (!$id_product && !$id_product_attribute) { + return array(); + } - $query = new DbQuery(); - $query->select('DISTINCT w.id_warehouse, CONCAT(w.reference, " - ", w.name) as name'); - $query->from('warehouse', 'w'); - $query->leftJoin('warehouse_product_location', 'wpl', 'wpl.id_warehouse = w.id_warehouse'); - if ($id_product) - $query->where('wpl.id_product = '.(int)$id_product); - if ($id_product_attribute) - $query->where('wpl.id_product_attribute = '.(int)$id_product_attribute); - $query->orderBy('w.reference ASC'); + $query = new DbQuery(); + $query->select('DISTINCT w.id_warehouse, CONCAT(w.reference, " - ", w.name) as name'); + $query->from('warehouse', 'w'); + $query->leftJoin('warehouse_product_location', 'wpl', 'wpl.id_warehouse = w.id_warehouse'); + if ($id_product) { + $query->where('wpl.id_product = '.(int)$id_product); + } + if ($id_product_attribute) { + $query->where('wpl.id_product_attribute = '.(int)$id_product_attribute); + } + $query->orderBy('w.reference ASC'); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } - /** - * For a given $id_warehouse, returns its name - * - * @param int $id_warehouse Warehouse Id - * @return string Name - */ - public static function getWarehouseNameById($id_warehouse) - { - $query = new DbQuery(); - $query->select('name'); - $query->from('warehouse'); - $query->where('id_warehouse = '.(int)$id_warehouse); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + /** + * For a given $id_warehouse, returns its name + * + * @param int $id_warehouse Warehouse Id + * @return string Name + */ + public static function getWarehouseNameById($id_warehouse) + { + $query = new DbQuery(); + $query->select('name'); + $query->from('warehouse'); + $query->where('id_warehouse = '.(int)$id_warehouse); + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } - /** - * For a given pack, returns the warehouse it can be shipped from - * - * @param int $id_product - * @return array|bool id_warehouse or false - */ - public static function getPackWarehouses($id_product, $id_shop = null) - { - if (!Pack::isPack($id_product)) - return false; + /** + * For a given pack, returns the warehouse it can be shipped from + * + * @param int $id_product + * @return array|bool id_warehouse or false + */ + public static function getPackWarehouses($id_product, $id_shop = null) + { + if (!Pack::isPack($id_product)) { + return false; + } - if (is_null($id_shop)) - $id_shop = Context::getContext()->shop->id; + if (is_null($id_shop)) { + $id_shop = Context::getContext()->shop->id; + } - // warehouses of the pack - $pack_warehouses = WarehouseProductLocation::getCollection((int)$id_product); - // products in the pack - $products = Pack::getItems((int)$id_product, Configuration::get('PS_LANG_DEFAULT')); + // warehouses of the pack + $pack_warehouses = WarehouseProductLocation::getCollection((int)$id_product); + // products in the pack + $products = Pack::getItems((int)$id_product, Configuration::get('PS_LANG_DEFAULT')); - // array with all warehouses id to check - $list = array(); + // array with all warehouses id to check + $list = array(); - // fills $list - foreach ($pack_warehouses as $pack_warehouse) - { - /** @var WarehouseProductLocation $pack_warehouse */ - $list['pack_warehouses'][] = (int)$pack_warehouse->id_warehouse; - } + // fills $list + foreach ($pack_warehouses as $pack_warehouse) { + /** @var WarehouseProductLocation $pack_warehouse */ + $list['pack_warehouses'][] = (int)$pack_warehouse->id_warehouse; + } - // for each products in the pack - foreach ($products as $product) - { - if ($product->advanced_stock_management) - { - // gets the warehouses of one product - $product_warehouses = Warehouse::getProductWarehouseList((int)$product->id, (int)$product->cache_default_attribute, (int)$id_shop); - $list[(int)$product->id] = array(); - // fills array with warehouses for this product - foreach ($product_warehouses as $product_warehouse) - $list[(int)$product->id][] = $product_warehouse['id_warehouse']; - } - } + // for each products in the pack + foreach ($products as $product) { + if ($product->advanced_stock_management) { + // gets the warehouses of one product + $product_warehouses = Warehouse::getProductWarehouseList((int)$product->id, (int)$product->cache_default_attribute, (int)$id_shop); + $list[(int)$product->id] = array(); + // fills array with warehouses for this product + foreach ($product_warehouses as $product_warehouse) { + $list[(int)$product->id][] = $product_warehouse['id_warehouse']; + } + } + } - $res = false; - // returns final list - if (count($list) > 1) - $res = call_user_func_array('array_intersect', $list); - return $res; - } + $res = false; + // returns final list + if (count($list) > 1) { + $res = call_user_func_array('array_intersect', $list); + } + return $res; + } - public function resetStockAvailable() - { - $products = WarehouseProductLocation::getProducts((int)$this->id); - foreach ($products as $product) - StockAvailable::synchronize((int)$product['id_product']); - } + public function resetStockAvailable() + { + $products = WarehouseProductLocation::getProducts((int)$this->id); + foreach ($products as $product) { + StockAvailable::synchronize((int)$product['id_product']); + } + } - /*********************************\ - * - * Webservices Specific Methods - * - *********************************/ + /*********************************\ + * + * Webservices Specific Methods + * + *********************************/ - /** - * Webservice : gets the value of the warehouse - * @return int - */ - public function getWsStockValue() - { - return $this->getStockValue(); - } + /** + * Webservice : gets the value of the warehouse + * @return int + */ + public function getWsStockValue() + { + return $this->getStockValue(); + } - /** - * Webservice : gets the ids stock associated to this warehouse - * @return array - */ - public function getWsStocks() - { - $query = new DbQuery(); - $query->select('s.id_stock as id'); - $query->from('stock', 's'); - $query->where('s.id_warehouse ='.(int)$this->id); + /** + * Webservice : gets the ids stock associated to this warehouse + * @return array + */ + public function getWsStocks() + { + $query = new DbQuery(); + $query->select('s.id_stock as id'); + $query->from('stock', 's'); + $query->where('s.id_warehouse ='.(int)$this->id); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } - /** - * Webservice : gets the ids shops associated to this warehouse - * @return array - */ - public function getWsShops() - { - $query = new DbQuery(); - $query->select('ws.id_shop as id, s.name'); - $query->from('warehouse_shop', 'ws'); - $query->leftJoin('shop', 's', 's.id_shop = ws.id_shop'); - $query->where($this->def['primary'].' = '.(int)$this->id); + /** + * Webservice : gets the ids shops associated to this warehouse + * @return array + */ + public function getWsShops() + { + $query = new DbQuery(); + $query->select('ws.id_shop as id, s.name'); + $query->from('warehouse_shop', 'ws'); + $query->leftJoin('shop', 's', 's.id_shop = ws.id_shop'); + $query->where($this->def['primary'].' = '.(int)$this->id); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - return $res; - } + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + return $res; + } - /** - * Webservice : gets the ids carriers associated to this warehouse - * @return array - */ - public function getWsCarriers() - { - $ids_carrier = array(); + /** + * Webservice : gets the ids carriers associated to this warehouse + * @return array + */ + public function getWsCarriers() + { + $ids_carrier = array(); - $query = new DbQuery(); - $query->select('wc.id_carrier as id'); - $query->from('warehouse_carrier', 'wc'); - $query->where($this->def['primary'].' = '.(int)$this->id); + $query = new DbQuery(); + $query->select('wc.id_carrier as id'); + $query->from('warehouse_carrier', 'wc'); + $query->where($this->def['primary'].' = '.(int)$this->id); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - if (!is_array($res)) - return $ids_carrier; + if (!is_array($res)) { + return $ids_carrier; + } - foreach ($res as $carriers) - foreach ($carriers as $carrier) - $ids_carrier[] = $carrier; - - return $ids_carrier; - } + foreach ($res as $carriers) { + foreach ($carriers as $carrier) { + $ids_carrier[] = $carrier; + } + } + return $ids_carrier; + } } diff --git a/classes/stock/WarehouseProductLocation.php b/classes/stock/WarehouseProductLocation.php index 9dc5593f..5db2eddb 100644 --- a/classes/stock/WarehouseProductLocation.php +++ b/classes/stock/WarehouseProductLocation.php @@ -28,112 +28,112 @@ */ class WarehouseProductLocationCore extends ObjectModel { - /** - * @var int product ID - * */ - public $id_product; + /** + * @var int product ID + * */ + public $id_product; - /** - * @var int product attribute ID - * */ - public $id_product_attribute; + /** + * @var int product attribute ID + * */ + public $id_product_attribute; - /** - * @var int warehouse ID - * */ - public $id_warehouse; + /** + * @var int warehouse ID + * */ + public $id_warehouse; - /** - * @var string location of the product - * */ - public $location; + /** + * @var string location of the product + * */ + public $location; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'warehouse_product_location', - 'primary' => 'id_warehouse_product_location', - 'fields' => array( - 'location' => array('type' => self::TYPE_STRING, 'validate' => 'isReference', 'size' => 64), - 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_warehouse' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'warehouse_product_location', + 'primary' => 'id_warehouse_product_location', + 'fields' => array( + 'location' => array('type' => self::TYPE_STRING, 'validate' => 'isReference', 'size' => 64), + 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_warehouse' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + ), + ); - /** - * @see ObjectModel::$webserviceParameters - */ - protected $webserviceParameters = array( - 'fields' => array( - 'id_product' => array('xlink_resource' => 'products'), - 'id_product_attribute' => array('xlink_resource' => 'combinations'), - 'id_warehouse' => array('xlink_resource' => 'warehouses'), - ), - 'hidden_fields' => array( - ), - ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'fields' => array( + 'id_product' => array('xlink_resource' => 'products'), + 'id_product_attribute' => array('xlink_resource' => 'combinations'), + 'id_warehouse' => array('xlink_resource' => 'warehouses'), + ), + 'hidden_fields' => array( + ), + ); - /** - * For a given product and warehouse, gets the location - * - * @param int $id_product product ID - * @param int $id_product_attribute product attribute ID - * @param int $id_warehouse warehouse ID - * @return string $location Location of the product - */ - public static function getProductLocation($id_product, $id_product_attribute, $id_warehouse) - { - // build query - $query = new DbQuery(); - $query->select('wpl.location'); - $query->from('warehouse_product_location', 'wpl'); - $query->where('wpl.id_product = '.(int)$id_product.' + /** + * For a given product and warehouse, gets the location + * + * @param int $id_product product ID + * @param int $id_product_attribute product attribute ID + * @param int $id_warehouse warehouse ID + * @return string $location Location of the product + */ + public static function getProductLocation($id_product, $id_product_attribute, $id_warehouse) + { + // build query + $query = new DbQuery(); + $query->select('wpl.location'); + $query->from('warehouse_product_location', 'wpl'); + $query->where('wpl.id_product = '.(int)$id_product.' AND wpl.id_product_attribute = '.(int)$id_product_attribute.' AND wpl.id_warehouse = '.(int)$id_warehouse - ); + ); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } - /** - * For a given product and warehouse, gets the WarehouseProductLocation corresponding ID - * - * @param int $id_product - * @param int $id_product_attribute - * @param int $id_supplier - * @return int $id_warehouse_product_location ID of the WarehouseProductLocation - */ - public static function getIdByProductAndWarehouse($id_product, $id_product_attribute, $id_warehouse) - { - // build query - $query = new DbQuery(); - $query->select('wpl.id_warehouse_product_location'); - $query->from('warehouse_product_location', 'wpl'); - $query->where('wpl.id_product = '.(int)$id_product.' + /** + * For a given product and warehouse, gets the WarehouseProductLocation corresponding ID + * + * @param int $id_product + * @param int $id_product_attribute + * @param int $id_supplier + * @return int $id_warehouse_product_location ID of the WarehouseProductLocation + */ + public static function getIdByProductAndWarehouse($id_product, $id_product_attribute, $id_warehouse) + { + // build query + $query = new DbQuery(); + $query->select('wpl.id_warehouse_product_location'); + $query->from('warehouse_product_location', 'wpl'); + $query->where('wpl.id_product = '.(int)$id_product.' AND wpl.id_product_attribute = '.(int)$id_product_attribute.' AND wpl.id_warehouse = '.(int)$id_warehouse - ); + ); - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } - /** - * For a given product, gets its warehouses - * - * @param int $id_product - * @return PrestaShopCollection The type of the collection is WarehouseProductLocation - */ - public static function getCollection($id_product) - { - $collection = new PrestaShopCollection('WarehouseProductLocation'); - $collection->where('id_product', '=', (int)$id_product); - return $collection; - } + /** + * For a given product, gets its warehouses + * + * @param int $id_product + * @return PrestaShopCollection The type of the collection is WarehouseProductLocation + */ + public static function getCollection($id_product) + { + $collection = new PrestaShopCollection('WarehouseProductLocation'); + $collection->where('id_product', '=', (int)$id_product); + return $collection; + } - public static function getProducts($id_warehouse) - { - return Db::getInstance()->executeS('SELECT DISTINCT id_product FROM '._DB_PREFIX_.'warehouse_product_location WHERE id_warehouse='.(int)$id_warehouse); - } -} \ No newline at end of file + public static function getProducts($id_warehouse) + { + return Db::getInstance()->executeS('SELECT DISTINCT id_product FROM '._DB_PREFIX_.'warehouse_product_location WHERE id_warehouse='.(int)$id_warehouse); + } +} diff --git a/classes/stock/index.php b/classes/stock/index.php index c642967a..91fa49fb 100644 --- a/classes/stock/index.php +++ b/classes/stock/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/classes/tax/AverageTaxOfProductsTaxCalculator.php b/classes/tax/AverageTaxOfProductsTaxCalculator.php index c05c350a..27293592 100644 --- a/classes/tax/AverageTaxOfProductsTaxCalculator.php +++ b/classes/tax/AverageTaxOfProductsTaxCalculator.php @@ -38,10 +38,8 @@ class AverageTaxOfProductsTaxCalculator $amounts = array(); $total_base = 0; - foreach ($this->getProductTaxes() as $row) - { - if (!array_key_exists($row['id_tax'], $amounts)) - { + foreach ($this->getProductTaxes() as $row) { + if (!array_key_exists($row['id_tax'], $amounts)) { $amounts[$row['id_tax']] = array( 'rate' => $row['rate'], 'base' => 0 @@ -53,8 +51,7 @@ class AverageTaxOfProductsTaxCalculator } $actual_tax = 0; - foreach ($amounts as &$data) - { + foreach ($amounts as &$data) { $data = Tools::ps_round( $price_before_tax * ($data['base'] / $total_base) * $data['rate'] / 100, $round_precision, @@ -64,8 +61,7 @@ class AverageTaxOfProductsTaxCalculator } unset($data); - if ($price_after_tax) - { + if ($price_after_tax) { Tools::spreadAmount( $price_after_tax - $price_before_tax - $actual_tax, $round_precision, diff --git a/classes/tax/Tax.php b/classes/tax/Tax.php index cac933b0..b3b0128c 100644 --- a/classes/tax/Tax.php +++ b/classes/tax/Tax.php @@ -27,236 +27,238 @@ class TaxCore extends ObjectModel { - /** @var string Name */ - public $name; + /** @var string Name */ + public $name; - /** @var float Rate (%) */ - public $rate; + /** @var float Rate (%) */ + public $rate; - /** @var bool active state */ - public $active; + /** @var bool active state */ + public $active; - /** @var bool true if the tax has been historized */ - public $deleted = 0; + /** @var bool true if the tax has been historized */ + public $deleted = 0; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'tax', - 'primary' => 'id_tax', - 'multilang' => true, - 'fields' => array( - 'rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), - 'active' => array('type' => self::TYPE_BOOL), - 'deleted' => array('type' => self::TYPE_BOOL), - /* Lang fields */ - 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'tax', + 'primary' => 'id_tax', + 'multilang' => true, + 'fields' => array( + 'rate' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true), + 'active' => array('type' => self::TYPE_BOOL), + 'deleted' => array('type' => self::TYPE_BOOL), + /* Lang fields */ + 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 32), + ), + ); - protected static $_product_country_tax = array(); - protected static $_product_tax_via_rules = array(); + protected static $_product_country_tax = array(); + protected static $_product_tax_via_rules = array(); - protected $webserviceParameters = array( - 'objectsNodeName' => 'taxes', - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'taxes', + ); - public function delete() - { - /* Clean associations */ - TaxRule::deleteTaxRuleByIdTax((int)$this->id); + public function delete() + { + /* Clean associations */ + TaxRule::deleteTaxRuleByIdTax((int)$this->id); - if ($this->isUsed()) - return $this->historize(); - else - return parent::delete(); - } + if ($this->isUsed()) { + return $this->historize(); + } else { + return parent::delete(); + } + } - /** - * Save the object with the field deleted to true - * - * @return bool - */ - public function historize() - { - $this->deleted = true; - return parent::update(); - } + /** + * Save the object with the field deleted to true + * + * @return bool + */ + public function historize() + { + $this->deleted = true; + return parent::update(); + } - public function toggleStatus() - { - if (parent::toggleStatus()) - return $this->_onStatusChange(); + public function toggleStatus() + { + if (parent::toggleStatus()) { + return $this->_onStatusChange(); + } - return false; - } + return false; + } - public function update($null_values = false) - { - if (!$this->deleted && $this->isUsed()) - { - $historized_tax = new Tax($this->id); - $historized_tax->historize(); + public function update($null_values = false) + { + if (!$this->deleted && $this->isUsed()) { + $historized_tax = new Tax($this->id); + $historized_tax->historize(); - // remove the id in order to create a new object - $this->id = 0; - $res = $this->add(); + // remove the id in order to create a new object + $this->id = 0; + $res = $this->add(); - // change tax id in the tax rule table - $res &= TaxRule::swapTaxId($historized_tax->id, $this->id); - return $res; - } - elseif (parent::update($null_values)) - return $this->_onStatusChange(); + // change tax id in the tax rule table + $res &= TaxRule::swapTaxId($historized_tax->id, $this->id); + return $res; + } elseif (parent::update($null_values)) { + return $this->_onStatusChange(); + } - return false; - } + return false; + } - protected function _onStatusChange() - { - if (!$this->active) - return TaxRule::deleteTaxRuleByIdTax($this->id); + protected function _onStatusChange() + { + if (!$this->active) { + return TaxRule::deleteTaxRuleByIdTax($this->id); + } - return true; - } + return true; + } - /** - * Returns true if the tax is used in an order details - * - * @return bool - */ - public function isUsed() - { - return Db::getInstance()->getValue(' + /** + * Returns true if the tax is used in an order details + * + * @return bool + */ + public function isUsed() + { + return Db::getInstance()->getValue(' SELECT `id_tax` FROM `'._DB_PREFIX_.'order_detail_tax` WHERE `id_tax` = '.(int)$this->id - ); - } + ); + } - /** - * Get all available taxes - * - * @return array Taxes - */ - public static function getTaxes($id_lang = false, $active_only = true) - { - $sql = new DbQuery(); - $sql->select('t.id_tax, t.rate'); - $sql->from('tax', 't'); - $sql->where('t.`deleted` != 1'); + /** + * Get all available taxes + * + * @return array Taxes + */ + public static function getTaxes($id_lang = false, $active_only = true) + { + $sql = new DbQuery(); + $sql->select('t.id_tax, t.rate'); + $sql->from('tax', 't'); + $sql->where('t.`deleted` != 1'); - if ($id_lang) - { - $sql->select('tl.name, tl.id_lang'); - $sql->leftJoin('tax_lang', 'tl', 't.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)$id_lang); - $sql->orderBy('`name` ASC'); - } + if ($id_lang) { + $sql->select('tl.name, tl.id_lang'); + $sql->leftJoin('tax_lang', 'tl', 't.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)$id_lang); + $sql->orderBy('`name` ASC'); + } - if ($active_only) - $sql->where('t.`active` = 1'); + if ($active_only) { + $sql->where('t.`active` = 1'); + } - return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - } + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + } - public static function excludeTaxeOption() - { - return !Configuration::get('PS_TAX'); - } + public static function excludeTaxeOption() + { + return !Configuration::get('PS_TAX'); + } - /** - * Return the tax id associated to the specified name - * - * @param string $tax_name - * @param bool $active (true by default) - */ - public static function getTaxIdByName($tax_name, $active = 1) - { - $tax = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + /** + * Return the tax id associated to the specified name + * + * @param string $tax_name + * @param bool $active (true by default) + */ + public static function getTaxIdByName($tax_name, $active = 1) + { + $tax = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT t.`id_tax` FROM `'._DB_PREFIX_.'tax` t LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (tl.id_tax = t.id_tax) WHERE tl.`name` = \''.pSQL($tax_name).'\' '. - ($active == 1 ? ' AND t.`active` = 1' : '')); + ($active == 1 ? ' AND t.`active` = 1' : '')); - return $tax ? (int)$tax['id_tax'] : false; - } + return $tax ? (int)$tax['id_tax'] : false; + } - /** - * Returns the ecotax tax rate - * - * @param id_address - * @return float $tax_rate - */ - public static function getProductEcotaxRate($id_address = null) - { - $address = Address::initialize($id_address); + /** + * Returns the ecotax tax rate + * + * @param id_address + * @return float $tax_rate + */ + public static function getProductEcotaxRate($id_address = null) + { + $address = Address::initialize($id_address); - $tax_manager = TaxManagerFactory::getManager($address, (int)Configuration::get('PS_ECOTAX_TAX_RULES_GROUP_ID')); - $tax_calculator = $tax_manager->getTaxCalculator(); + $tax_manager = TaxManagerFactory::getManager($address, (int)Configuration::get('PS_ECOTAX_TAX_RULES_GROUP_ID')); + $tax_calculator = $tax_manager->getTaxCalculator(); - return $tax_calculator->getTotalRate(); - } + return $tax_calculator->getTotalRate(); + } - /** - * Returns the carrier tax rate - * - * @param id_address - * @return float $tax_rate - */ - public static function getCarrierTaxRate($id_carrier, $id_address = null) - { - $address = Address::initialize($id_address); - $id_tax_rules = (int)Carrier::getIdTaxRulesGroupByIdCarrier((int)$id_carrier); + /** + * Returns the carrier tax rate + * + * @param id_address + * @return float $tax_rate + */ + public static function getCarrierTaxRate($id_carrier, $id_address = null) + { + $address = Address::initialize($id_address); + $id_tax_rules = (int)Carrier::getIdTaxRulesGroupByIdCarrier((int)$id_carrier); - $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules); - $tax_calculator = $tax_manager->getTaxCalculator(); + $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules); + $tax_calculator = $tax_manager->getTaxCalculator(); - return $tax_calculator->getTotalRate(); - } + return $tax_calculator->getTotalRate(); + } - /** - * Return the product tax rate using the tax rules system - * - * @param int $id_product - * @param int $id_country - * @return Tax - * - * @deprecated since 1.5 - */ - public static function getProductTaxRateViaRules($id_product, $id_country, $id_state, $zipcode) - { - Tools::displayAsDeprecated(); + /** + * Return the product tax rate using the tax rules system + * + * @param int $id_product + * @param int $id_country + * @return Tax + * + * @deprecated since 1.5 + */ + public static function getProductTaxRateViaRules($id_product, $id_country, $id_state, $zipcode) + { + Tools::displayAsDeprecated(); - if (!isset(self::$_product_tax_via_rules[$id_product.'-'.$id_country.'-'.$id_state.'-'.$zipcode])) - { - $tax_rate = TaxRulesGroup::getTaxesRate((int)Product::getIdTaxRulesGroupByIdProduct((int)$id_product), (int)$id_country, (int)$id_state, $zipcode); - self::$_product_tax_via_rules[$id_product.'-'.$id_country.'-'.$zipcode] = $tax_rate; - } + if (!isset(self::$_product_tax_via_rules[$id_product.'-'.$id_country.'-'.$id_state.'-'.$zipcode])) { + $tax_rate = TaxRulesGroup::getTaxesRate((int)Product::getIdTaxRulesGroupByIdProduct((int)$id_product), (int)$id_country, (int)$id_state, $zipcode); + self::$_product_tax_via_rules[$id_product.'-'.$id_country.'-'.$zipcode] = $tax_rate; + } - return self::$_product_tax_via_rules[$id_product.'-'.$id_country.'-'.$zipcode]; - } + return self::$_product_tax_via_rules[$id_product.'-'.$id_country.'-'.$zipcode]; + } - /** - * Returns the product tax - * - * @param int $id_product - * @param int $id_country - * @return Tax - */ - public static function getProductTaxRate($id_product, $id_address = null, Context $context = null) - { - if ($context == null) - $context = Context::getContext(); + /** + * Returns the product tax + * + * @param int $id_product + * @param int $id_country + * @return Tax + */ + public static function getProductTaxRate($id_product, $id_address = null, Context $context = null) + { + if ($context == null) { + $context = Context::getContext(); + } - $address = Address::initialize($id_address); - $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context); + $address = Address::initialize($id_address); + $id_tax_rules = (int)Product::getIdTaxRulesGroupByIdProduct($id_product, $context); - $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules); - $tax_calculator = $tax_manager->getTaxCalculator(); + $tax_manager = TaxManagerFactory::getManager($address, $id_tax_rules); + $tax_calculator = $tax_manager->getTaxCalculator(); - return $tax_calculator->getTotalRate(); - } + return $tax_calculator->getTotalRate(); + } } diff --git a/classes/tax/TaxCalculator.php b/classes/tax/TaxCalculator.php index ce65ce25..1ff1865e 100644 --- a/classes/tax/TaxCalculator.php +++ b/classes/tax/TaxCalculator.php @@ -31,140 +31,141 @@ */ class TaxCalculatorCore { - /** - * COMBINE_METHOD sum taxes - * eg: 100€ * (10% + 15%) - */ - const COMBINE_METHOD = 1; + /** + * COMBINE_METHOD sum taxes + * eg: 100€ * (10% + 15%) + */ + const COMBINE_METHOD = 1; - /** - * ONE_AFTER_ANOTHER_METHOD apply taxes one after another - * eg: (100€ * 10%) * 15% - */ - const ONE_AFTER_ANOTHER_METHOD = 2; + /** + * ONE_AFTER_ANOTHER_METHOD apply taxes one after another + * eg: (100€ * 10%) * 15% + */ + const ONE_AFTER_ANOTHER_METHOD = 2; - /** - * @var array $taxes - */ - public $taxes; + /** + * @var array $taxes + */ + public $taxes; - /** - * @var int $computation_method (COMBINE_METHOD | ONE_AFTER_ANOTHER_METHOD) - */ - public $computation_method; + /** + * @var int $computation_method (COMBINE_METHOD | ONE_AFTER_ANOTHER_METHOD) + */ + public $computation_method; - /** - * @param array $taxes - * @param int $computation_method (COMBINE_METHOD | ONE_AFTER_ANOTHER_METHOD) - */ - public function __construct(array $taxes = array(), $computation_method = TaxCalculator::COMBINE_METHOD) - { - // sanity check - foreach ($taxes as $tax) - if (!($tax instanceof Tax)) - throw new Exception('Invalid Tax Object'); + /** + * @param array $taxes + * @param int $computation_method (COMBINE_METHOD | ONE_AFTER_ANOTHER_METHOD) + */ + public function __construct(array $taxes = array(), $computation_method = TaxCalculator::COMBINE_METHOD) + { + // sanity check + foreach ($taxes as $tax) { + if (!($tax instanceof Tax)) { + throw new Exception('Invalid Tax Object'); + } + } - $this->taxes = $taxes; - $this->computation_method = (int)$computation_method; - } + $this->taxes = $taxes; + $this->computation_method = (int)$computation_method; + } - /** - * Compute and add the taxes to the specified price - * - * @param float $price_te price tax excluded - * @return float price with taxes - */ - public function addTaxes($price_te) - { - return $price_te * (1 + ($this->getTotalRate() / 100)); - } + /** + * Compute and add the taxes to the specified price + * + * @param float $price_te price tax excluded + * @return float price with taxes + */ + public function addTaxes($price_te) + { + return $price_te * (1 + ($this->getTotalRate() / 100)); + } - /** - * Compute and remove the taxes to the specified price - * - * @param float $price_ti price tax inclusive - * @return float price without taxes - */ - public function removeTaxes($price_ti) - { - return $price_ti / (1 + $this->getTotalRate() / 100); - } + /** + * Compute and remove the taxes to the specified price + * + * @param float $price_ti price tax inclusive + * @return float price without taxes + */ + public function removeTaxes($price_ti) + { + return $price_ti / (1 + $this->getTotalRate() / 100); + } - /** - * @return float total taxes rate - */ - public function getTotalRate() - { - $taxes = 0; - if ($this->computation_method == TaxCalculator::ONE_AFTER_ANOTHER_METHOD) - { - $taxes = 1; - foreach ($this->taxes as $tax) - $taxes *= (1 + (abs($tax->rate) / 100)); + /** + * @return float total taxes rate + */ + public function getTotalRate() + { + $taxes = 0; + if ($this->computation_method == TaxCalculator::ONE_AFTER_ANOTHER_METHOD) { + $taxes = 1; + foreach ($this->taxes as $tax) { + $taxes *= (1 + (abs($tax->rate) / 100)); + } - $taxes = $taxes - 1; - $taxes = $taxes * 100; - } - else - { - foreach ($this->taxes as $tax) - $taxes += abs($tax->rate); - } + $taxes = $taxes - 1; + $taxes = $taxes * 100; + } else { + foreach ($this->taxes as $tax) { + $taxes += abs($tax->rate); + } + } - return (float)$taxes; - } + return (float)$taxes; + } - public function getTaxesName() - { - $name = ''; - foreach ($this->taxes as $tax) - $name .= $tax->name[(int)Context::getContext()->language->id].' - '; + public function getTaxesName() + { + $name = ''; + foreach ($this->taxes as $tax) { + $name .= $tax->name[(int)Context::getContext()->language->id].' - '; + } - $name = rtrim($name, ' - '); + $name = rtrim($name, ' - '); - return $name; - } + return $name; + } - /** - * Return the tax amount associated to each taxes of the TaxCalculator - * - * @param float $price_te - * @return array $taxes_amount - */ - public function getTaxesAmount($price_te) - { - $taxes_amounts = array(); + /** + * Return the tax amount associated to each taxes of the TaxCalculator + * + * @param float $price_te + * @return array $taxes_amount + */ + public function getTaxesAmount($price_te) + { + $taxes_amounts = array(); - foreach ($this->taxes as $tax) - { - if ($this->computation_method == TaxCalculator::ONE_AFTER_ANOTHER_METHOD) - { - $taxes_amounts[$tax->id] = $price_te * (abs($tax->rate) / 100); - $price_te = $price_te + $taxes_amounts[$tax->id]; - } - else - $taxes_amounts[$tax->id] = ($price_te * (abs($tax->rate) / 100)); - } + foreach ($this->taxes as $tax) { + if ($this->computation_method == TaxCalculator::ONE_AFTER_ANOTHER_METHOD) { + $taxes_amounts[$tax->id] = $price_te * (abs($tax->rate) / 100); + $price_te = $price_te + $taxes_amounts[$tax->id]; + } else { + $taxes_amounts[$tax->id] = ($price_te * (abs($tax->rate) / 100)); + } + } - return $taxes_amounts; - } + return $taxes_amounts; + } - /** - * Return the total taxes amount - * - * @param float $price_te - * @return float $amount - */ - public function getTaxesTotalAmount($price_te) - { - $amount = 0; + /** + * Return the total taxes amount + * + * @param float $price_te + * @return float $amount + */ + public function getTaxesTotalAmount($price_te) + { + $amount = 0; - $taxes = $this->getTaxesAmount($price_te); - foreach ($taxes as $tax) - $amount += $tax; + $taxes = $this->getTaxesAmount($price_te); + foreach ($taxes as $tax) { + $amount += $tax; + } - return $amount; - } -} \ No newline at end of file + return $amount; + } +} diff --git a/classes/tax/TaxManagerFactory.php b/classes/tax/TaxManagerFactory.php index d2e1716e..9c8cf1a6 100644 --- a/classes/tax/TaxManagerFactory.php +++ b/classes/tax/TaxManagerFactory.php @@ -29,73 +29,72 @@ */ class TaxManagerFactoryCore { - protected static $cache_tax_manager; + protected static $cache_tax_manager; - /** - * Returns a tax manager able to handle this address - * - * @param Address $address - * @param string $type - * - * @return TaxManagerInterface - */ - public static function getManager(Address $address, $type) - { - $cache_id = TaxManagerFactory::getCacheKey($address).'-'.$type; - if (!isset(TaxManagerFactory::$cache_tax_manager[$cache_id])) - { - $tax_manager = TaxManagerFactory::execHookTaxManagerFactory($address, $type); - if (!($tax_manager instanceof TaxManagerInterface)) - $tax_manager = new TaxRulesTaxManager($address, $type); + /** + * Returns a tax manager able to handle this address + * + * @param Address $address + * @param string $type + * + * @return TaxManagerInterface + */ + public static function getManager(Address $address, $type) + { + $cache_id = TaxManagerFactory::getCacheKey($address).'-'.$type; + if (!isset(TaxManagerFactory::$cache_tax_manager[$cache_id])) { + $tax_manager = TaxManagerFactory::execHookTaxManagerFactory($address, $type); + if (!($tax_manager instanceof TaxManagerInterface)) { + $tax_manager = new TaxRulesTaxManager($address, $type); + } - TaxManagerFactory::$cache_tax_manager[$cache_id] = $tax_manager; - } + TaxManagerFactory::$cache_tax_manager[$cache_id] = $tax_manager; + } - return TaxManagerFactory::$cache_tax_manager[$cache_id]; - } + return TaxManagerFactory::$cache_tax_manager[$cache_id]; + } - /** - * Check for a tax manager able to handle this type of address in the module list - * - * @param Address $address - * @param string $type - * - * @return TaxManagerInterface|false - */ - public static function execHookTaxManagerFactory(Address $address, $type) - { - $modules_infos = Hook::getModulesFromHook(Hook::getIdByName('taxManager')); - $tax_manager = false; + /** + * Check for a tax manager able to handle this type of address in the module list + * + * @param Address $address + * @param string $type + * + * @return TaxManagerInterface|false + */ + public static function execHookTaxManagerFactory(Address $address, $type) + { + $modules_infos = Hook::getModulesFromHook(Hook::getIdByName('taxManager')); + $tax_manager = false; - foreach ($modules_infos as $module_infos) - { - $module_instance = Module::getInstanceByName($module_infos['name']); - if (is_callable(array($module_instance, 'hookTaxManager'))) - { - $tax_manager = $module_instance->hookTaxManager(array( - 'address' => $address, - 'params' => $type - )); - } + foreach ($modules_infos as $module_infos) { + $module_instance = Module::getInstanceByName($module_infos['name']); + if (is_callable(array($module_instance, 'hookTaxManager'))) { + $tax_manager = $module_instance->hookTaxManager(array( + 'address' => $address, + 'params' => $type + )); + } - if ($tax_manager) - break; - } + if ($tax_manager) { + break; + } + } - return $tax_manager; - } + return $tax_manager; + } - /** - * Create a unique identifier for the address - * @param Address - */ - protected static function getCacheKey(Address $address) - { - return $address->id_country.'-' - .(int)$address->id_state.'-' - .$address->postcode.'-' - .$address->vat_number.'-' - .$address->dni; - } + /** + * Create a unique identifier for the address + * @param Address + */ + protected static function getCacheKey(Address $address) + { + return $address->id_country.'-' + .(int)$address->id_state.'-' + .$address->postcode.'-' + .$address->vat_number.'-' + .$address->dni; + } } diff --git a/classes/tax/TaxManagerInterface.php b/classes/tax/TaxManagerInterface.php index e0d55c22..09e139f9 100644 --- a/classes/tax/TaxManagerInterface.php +++ b/classes/tax/TaxManagerInterface.php @@ -30,19 +30,19 @@ */ interface TaxManagerInterface { - /** - * This method determine if the tax manager is available for the specified address. - * - * @param Address $address - * - * @return bool - */ - public static function isAvailableForThisAddress(Address $address); + /** + * This method determine if the tax manager is available for the specified address. + * + * @param Address $address + * + * @return bool + */ + public static function isAvailableForThisAddress(Address $address); - /** - * Return the tax calculator associated to this address - * - * @return TaxCalculator - */ - public function getTaxCalculator(); -} \ No newline at end of file + /** + * Return the tax calculator associated to this address + * + * @return TaxCalculator + */ + public function getTaxCalculator(); +} diff --git a/classes/tax/TaxManagerModule.php b/classes/tax/TaxManagerModule.php index 1eeea128..b17ae7e4 100644 --- a/classes/tax/TaxManagerModule.php +++ b/classes/tax/TaxManagerModule.php @@ -26,29 +26,32 @@ abstract class TaxManagerModuleCore extends Module { - public $tax_manager_class; + public $tax_manager_class; - public function install() - { - return (parent::install() && $this->registerHook('taxManager') ); - } + public function install() + { + return (parent::install() && $this->registerHook('taxManager')); + } - public function hookTaxManager($args) - { - $class_file = _PS_MODULE_DIR_.'/'.$this->name.'/'.$this->tax_manager_class.'.php'; + public function hookTaxManager($args) + { + $class_file = _PS_MODULE_DIR_.'/'.$this->name.'/'.$this->tax_manager_class.'.php'; - if (!isset($this->tax_manager_class) || !file_exists($class_file)) - die(sprintf(Tools::displayError('Incorrect Tax Manager class [%s]'), $this->tax_manager_class)); + if (!isset($this->tax_manager_class) || !file_exists($class_file)) { + die(sprintf(Tools::displayError('Incorrect Tax Manager class [%s]'), $this->tax_manager_class)); + } - require_once($class_file); + require_once($class_file); - if (!class_exists($this->tax_manager_class)) - die(sprintf(Tools::displayError('Tax Manager class not found [%s]'), $this->tax_manager_class)); + if (!class_exists($this->tax_manager_class)) { + die(sprintf(Tools::displayError('Tax Manager class not found [%s]'), $this->tax_manager_class)); + } - $class = $this->tax_manager_class; - if (call_user_func(array($class, 'isAvailableForThisAddress'), $args['address'])) - return new $class(); + $class = $this->tax_manager_class; + if (call_user_func(array($class, 'isAvailableForThisAddress'), $args['address'])) { + return new $class(); + } - return false; - } -} \ No newline at end of file + return false; + } +} diff --git a/classes/tax/TaxRule.php b/classes/tax/TaxRule.php index 89f76886..5690394a 100644 --- a/classes/tax/TaxRule.php +++ b/classes/tax/TaxRule.php @@ -26,62 +26,63 @@ class TaxRuleCore extends ObjectModel { - public $id_tax_rules_group; - public $id_country; - public $id_state; - public $zipcode_from; - public $zipcode_to; - public $id_tax; - public $behavior; - public $description; + public $id_tax_rules_group; + public $id_country; + public $id_state; + public $zipcode_from; + public $zipcode_to; + public $id_tax; + public $behavior; + public $description; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'tax_rule', - 'primary' => 'id_tax_rule', - 'fields' => array( - 'id_tax_rules_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_country' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'id_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'zipcode_from' => array('type' => self::TYPE_STRING, 'validate' => 'isPostCode'), - 'zipcode_to' => array('type' => self::TYPE_STRING, 'validate' => 'isPostCode'), - 'id_tax' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'behavior' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), - 'description' => array('type' => self::TYPE_STRING, 'validate' => 'isString'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'tax_rule', + 'primary' => 'id_tax_rule', + 'fields' => array( + 'id_tax_rules_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_country' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_state' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'zipcode_from' => array('type' => self::TYPE_STRING, 'validate' => 'isPostCode'), + 'zipcode_to' => array('type' => self::TYPE_STRING, 'validate' => 'isPostCode'), + 'id_tax' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'behavior' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), + 'description' => array('type' => self::TYPE_STRING, 'validate' => 'isString'), + ), + ); - protected $webserviceParameters = array( - 'fields' => array( - 'id_tax_rules_group' => array('xlink_resource'=> 'tax_rule_groups'), - 'id_state' => array('xlink_resource'=> 'states'), - 'id_country' => array('xlink_resource'=> 'countries') - ), - ); + protected $webserviceParameters = array( + 'fields' => array( + 'id_tax_rules_group' => array('xlink_resource'=> 'tax_rule_groups'), + 'id_state' => array('xlink_resource'=> 'states'), + 'id_country' => array('xlink_resource'=> 'countries') + ), + ); - public static function deleteByGroupId($id_group) - { - if (empty($id_group)) - die(Tools::displayError()); + public static function deleteByGroupId($id_group) + { + if (empty($id_group)) { + die(Tools::displayError()); + } - return Db::getInstance()->execute(' + return Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'tax_rule` WHERE `id_tax_rules_group` = '.(int)$id_group - ); - } + ); + } - public static function retrieveById($id_tax_rule) - { - return Db::getInstance()->getRow(' + public static function retrieveById($id_tax_rule) + { + return Db::getInstance()->getRow(' SELECT * FROM `'._DB_PREFIX_.'tax_rule` WHERE `id_tax_rule` = '.(int)$id_tax_rule); - } + } - public static function getTaxRulesByGroupId($id_lang, $id_group) - { - return Db::getInstance()->executeS(' + public static function getTaxRulesByGroupId($id_lang, $id_group) + { + return Db::getInstance()->executeS(' SELECT g.`id_tax_rule`, c.`name` AS country_name, s.`name` AS state_name, @@ -97,89 +98,82 @@ class TaxRuleCore extends ObjectModel LEFT JOIN `'._DB_PREFIX_.'tax` t ON (g.`id_tax` = t.`id_tax`) WHERE `id_tax_rules_group` = '.(int)$id_group.' ORDER BY `country_name` ASC, `state_name` ASC, `zipcode_from` ASC, `zipcode_to` ASC' - ); - } + ); + } - public static function deleteTaxRuleByIdTax($id_tax) - { - return Db::getInstance()->execute(' + public static function deleteTaxRuleByIdTax($id_tax) + { + return Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'tax_rule` WHERE `id_tax` = '.(int)$id_tax - ); - } + ); + } - /** - * @deprecated since 1.5 - */ - public static function deleteTaxRuleByIdCounty($id_county) - { - Tools::displayAsDeprecated(); - return true; - } + /** + * @deprecated since 1.5 + */ + public static function deleteTaxRuleByIdCounty($id_county) + { + Tools::displayAsDeprecated(); + return true; + } - /** - * @param int $id_tax - * @return bool - */ - public static function isTaxInUse($id_tax) - { - $cache_id = 'TaxRule::isTaxInUse_'.(int)$id_tax; - if (!Cache::isStored($cache_id)) - { - $result = (int)Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'tax_rule` WHERE `id_tax` = '.(int)$id_tax); - Cache::store($cache_id, $result); - return $result; - } - return Cache::retrieve($cache_id); - } + /** + * @param int $id_tax + * @return bool + */ + public static function isTaxInUse($id_tax) + { + $cache_id = 'TaxRule::isTaxInUse_'.(int)$id_tax; + if (!Cache::isStored($cache_id)) { + $result = (int)Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'tax_rule` WHERE `id_tax` = '.(int)$id_tax); + Cache::store($cache_id, $result); + return $result; + } + return Cache::retrieve($cache_id); + } - /** - * @param string $zipcode a range of zipcode (eg: 75000 / 75000-75015) - * @return array an array containing two zipcode ordered by zipcode - */ - public function breakDownZipCode($zip_codes) - { - $zip_codes = preg_split('/-/', $zip_codes); + /** + * @param string $zipcode a range of zipcode (eg: 75000 / 75000-75015) + * @return array an array containing two zipcode ordered by zipcode + */ + public function breakDownZipCode($zip_codes) + { + $zip_codes = preg_split('/-/', $zip_codes); - $from = $zip_codes[0]; - $to = isset($zip_codes[1]) ? $zip_codes[1]: 0; - if (count($zip_codes) == 2) - { - $from = $zip_codes[0]; - $to = $zip_codes[1]; - if ($zip_codes[0] > $zip_codes[1]) - { - $from = $zip_codes[1]; - $to = $zip_codes[0]; - } - elseif ($zip_codes[0] == $zip_codes[1]) - { - $from = $zip_codes[0]; - $to = 0; - } - } - elseif (count($zip_codes) == 1) - { - $from = $zip_codes[0]; - $to = 0; - } + $from = $zip_codes[0]; + $to = isset($zip_codes[1]) ? $zip_codes[1]: 0; + if (count($zip_codes) == 2) { + $from = $zip_codes[0]; + $to = $zip_codes[1]; + if ($zip_codes[0] > $zip_codes[1]) { + $from = $zip_codes[1]; + $to = $zip_codes[0]; + } elseif ($zip_codes[0] == $zip_codes[1]) { + $from = $zip_codes[0]; + $to = 0; + } + } elseif (count($zip_codes) == 1) { + $from = $zip_codes[0]; + $to = 0; + } - return array($from, $to); - } + return array($from, $to); + } - /** - * Replace a tax_rule id by an other one in the tax_rule table - * - * @param int $old_id - * @param int $new_id - */ - public static function swapTaxId($old_id, $new_id) - { - return Db::getInstance()->execute(' + /** + * Replace a tax_rule id by an other one in the tax_rule table + * + * @param int $old_id + * @param int $new_id + */ + public static function swapTaxId($old_id, $new_id) + { + return Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'tax_rule` SET `id_tax` = '.(int)$new_id.' WHERE `id_tax` = '.(int)$old_id - ); - } -} \ No newline at end of file + ); + } +} diff --git a/classes/tax/TaxRulesGroup.php b/classes/tax/TaxRulesGroup.php index 88ffcfaa..dbcd270f 100644 --- a/classes/tax/TaxRulesGroup.php +++ b/classes/tax/TaxRulesGroup.php @@ -27,69 +27,69 @@ class TaxRulesGroupCore extends ObjectModel { - public $name; + public $name; - /** @var bool active state */ - public $active; + /** @var bool active state */ + public $active; - public $deleted = 0; + public $deleted = 0; - /** @var string Object creation date */ - public $date_add; + /** @var string Object creation date */ + public $date_add; - /** @var string Object last modification date */ - public $date_upd; + /** @var string Object last modification date */ + public $date_upd; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'tax_rules_group', - 'primary' => 'id_tax_rules_group', - 'fields' => array( - 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'tax_rules_group', + 'primary' => 'id_tax_rules_group', + 'fields' => array( + 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64), + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + ), + ); - protected $webserviceParameters = array( - 'objectsNodeName' => 'tax_rule_groups', - 'objectNodeName' => 'tax_rule_group', - 'fields' => array( - ), - ); + protected $webserviceParameters = array( + 'objectsNodeName' => 'tax_rule_groups', + 'objectNodeName' => 'tax_rule_group', + 'fields' => array( + ), + ); - protected static $_taxes = array(); + protected static $_taxes = array(); - public function update($null_values = false) - { - if (!$this->deleted && $this->isUsed()) - { - $current_tax_rules_group = new TaxRulesGroup((int)$this->id); - if ((!$new_tax_rules_group = $current_tax_rules_group->duplicateObject()) || !$current_tax_rules_group->historize($new_tax_rules_group)) - return false; + public function update($null_values = false) + { + if (!$this->deleted && $this->isUsed()) { + $current_tax_rules_group = new TaxRulesGroup((int)$this->id); + if ((!$new_tax_rules_group = $current_tax_rules_group->duplicateObject()) || !$current_tax_rules_group->historize($new_tax_rules_group)) { + return false; + } - $this->id = (int)$new_tax_rules_group->id; - } + $this->id = (int)$new_tax_rules_group->id; + } - return parent::update($null_values); - } + return parent::update($null_values); + } - /** - * Save the object with the field deleted to true - * - * @return bool - */ - public function historize(TaxRulesGroup $tax_rules_group) - { - $this->deleted = true; + /** + * Save the object with the field deleted to true + * + * @return bool + */ + public function historize(TaxRulesGroup $tax_rules_group) + { + $this->deleted = true; - return parent::update() && - Db::getInstance()->execute(' + return parent::update() && + Db::getInstance()->execute(' INSERT INTO '._DB_PREFIX_.'tax_rule (id_tax_rules_group, id_country, id_state, zipcode_from, zipcode_to, id_tax, behavior, description) ( @@ -97,74 +97,72 @@ class TaxRulesGroupCore extends ObjectModel FROM '._DB_PREFIX_.'tax_rule WHERE id_tax_rules_group='.(int)$this->id.' )') && - Db::getInstance()->execute(' + Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'product SET id_tax_rules_group='.(int)$tax_rules_group->id.' WHERE id_tax_rules_group='.(int)$this->id) && - Db::getInstance()->execute(' + Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'product_shop SET id_tax_rules_group='.(int)$tax_rules_group->id.' WHERE id_tax_rules_group='.(int)$this->id) && - Db::getInstance()->execute(' + Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'carrier SET id_tax_rules_group='.(int)$tax_rules_group->id.' WHERE id_tax_rules_group='.(int)$this->id) && - Db::getInstance()->execute(' + Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'carrier_tax_rules_group_shop SET id_tax_rules_group='.(int)$tax_rules_group->id.' WHERE id_tax_rules_group='.(int)$this->id); + } - } - - public function getIdTaxRuleGroupFromHistorizedId($id_tax_rule) - { - $params = Db::getInstance()->getRow(' + public function getIdTaxRuleGroupFromHistorizedId($id_tax_rule) + { + $params = Db::getInstance()->getRow(' SELECT id_country, id_state, zipcode_from, zipcode_to, id_tax, behavior FROM '._DB_PREFIX_.'tax_rule WHERE id_tax_rule='.(int)$id_tax_rule - ); + ); - return Db::getInstance()->getValue(' + return Db::getInstance()->getValue(' SELECT id_tax_rule FROM '._DB_PREFIX_.'tax_rule WHERE id_tax_rules_group = '.(int)$this->id.' AND id_country='.(int)$params['id_country'].' AND id_state='.(int)$params['id_state'].' AND id_tax='.(int)$params['id_tax'].' AND zipcode_from=\''.pSQL($params['zipcode_from']).'\' AND zipcode_to=\''.pSQL($params['zipcode_to']).'\' AND behavior='.(int)$params['behavior'] - ); - } + ); + } - public static function getTaxRulesGroups($only_active = true) - { - return Db::getInstance()->executeS(' + public static function getTaxRulesGroups($only_active = true) + { + return Db::getInstance()->executeS(' SELECT DISTINCT g.id_tax_rules_group, g.name, g.active FROM `'._DB_PREFIX_.'tax_rules_group` g' - .Shop::addSqlAssociation('tax_rules_group', 'g').' WHERE deleted = 0' - .($only_active ? ' AND g.`active` = 1' : '').' + .Shop::addSqlAssociation('tax_rules_group', 'g').' WHERE deleted = 0' + .($only_active ? ' AND g.`active` = 1' : '').' ORDER BY name ASC'); + } - } + /** + * @return array an array of tax rules group formatted as $id => $name + */ + public static function getTaxRulesGroupsForOptions() + { + $tax_rules[] = array('id_tax_rules_group' => 0, 'name' => Tools::displayError('No tax')); + return array_merge($tax_rules, TaxRulesGroup::getTaxRulesGroups()); + } - /** - * @return array an array of tax rules group formatted as $id => $name - */ - public static function getTaxRulesGroupsForOptions() - { - $tax_rules[] = array('id_tax_rules_group' => 0, 'name' => Tools::displayError('No tax')); - return array_merge($tax_rules, TaxRulesGroup::getTaxRulesGroups()); - } - - public function delete() - { - $res = Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'tax_rule` WHERE `id_tax_rules_group`='.(int)$this->id); - return (parent::delete() && $res); - } - /** - * @return array - */ - public static function getAssociatedTaxRatesByIdCountry($id_country) - { - $rows = Db::getInstance()->executeS(' + public function delete() + { + $res = Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'tax_rule` WHERE `id_tax_rules_group`='.(int)$this->id); + return (parent::delete() && $res); + } + /** + * @return array + */ + public static function getAssociatedTaxRatesByIdCountry($id_country) + { + $rows = Db::getInstance()->executeS(' SELECT rg.`id_tax_rules_group`, t.`rate` FROM `'._DB_PREFIX_.'tax_rules_group` rg LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (tr.`id_tax_rules_group` = rg.`id_tax_rules_group`) @@ -172,69 +170,73 @@ class TaxRulesGroupCore extends ObjectModel WHERE tr.`id_country` = '.(int)$id_country.' AND tr.`id_state` = 0 AND 0 between `zipcode_from` AND `zipcode_to`' - ); + ); - $res = array(); - foreach ($rows as $row) - $res[$row['id_tax_rules_group']] = $row['rate']; + $res = array(); + foreach ($rows as $row) { + $res[$row['id_tax_rules_group']] = $row['rate']; + } - return $res; - } + return $res; + } - /** - * Returns the tax rules group id corresponding to the name - * - * @param string $name - * @return int id of the tax rules - */ - public static function getIdByName($name) - { - return Db::getInstance()->getValue( - 'SELECT `id_tax_rules_group` + /** + * Returns the tax rules group id corresponding to the name + * + * @param string $name + * @return int id of the tax rules + */ + public static function getIdByName($name) + { + return Db::getInstance()->getValue( + 'SELECT `id_tax_rules_group` FROM `'._DB_PREFIX_.'tax_rules_group` rg WHERE `name` = \''.pSQL($name).'\'' - ); - } + ); + } - public function hasUniqueTaxRuleForCountry($id_country, $id_state, $id_tax_rule = false) - { - $rules = TaxRule::getTaxRulesByGroupId((int)Context::getContext()->language->id, (int)$this->id); - foreach ($rules as $rule) - if ($rule['id_country'] == $id_country && $id_state == $rule['id_state'] && !$rule['behavior'] && (int)$id_tax_rule != $rule['id_tax_rule']) - return true; + public function hasUniqueTaxRuleForCountry($id_country, $id_state, $id_tax_rule = false) + { + $rules = TaxRule::getTaxRulesByGroupId((int)Context::getContext()->language->id, (int)$this->id); + foreach ($rules as $rule) { + if ($rule['id_country'] == $id_country && $id_state == $rule['id_state'] && !$rule['behavior'] && (int)$id_tax_rule != $rule['id_tax_rule']) { + return true; + } + } - return false; - } + return false; + } - public function isUsed() - { - return Db::getInstance()->getValue(' + public function isUsed() + { + return Db::getInstance()->getValue(' SELECT `id_tax_rules_group` FROM `'._DB_PREFIX_.'order_detail` WHERE `id_tax_rules_group` = '.(int)$this->id - ); - } + ); + } - /** - * @deprecated since 1.5 - */ - public static function getTaxesRate($id_tax_rules_group, $id_country, $id_state, $zipcode) - { - Tools::displayAsDeprecated(); - $rate = 0; - foreach (TaxRulesGroup::getTaxes($id_tax_rules_group, $id_country, $id_state, $zipcode) as $tax) - $rate += (float)$tax->rate; + /** + * @deprecated since 1.5 + */ + public static function getTaxesRate($id_tax_rules_group, $id_country, $id_state, $zipcode) + { + Tools::displayAsDeprecated(); + $rate = 0; + foreach (TaxRulesGroup::getTaxes($id_tax_rules_group, $id_country, $id_state, $zipcode) as $tax) { + $rate += (float)$tax->rate; + } - return $rate; - } + return $rate; + } - /** - * Return taxes associated to this para - * @deprecated since 1.5 - */ - public static function getTaxes($id_tax_rules_group, $id_country, $id_state, $id_county) - { - Tools::displayAsDeprecated(); - return array(); - } -} \ No newline at end of file + /** + * Return taxes associated to this para + * @deprecated since 1.5 + */ + public static function getTaxes($id_tax_rules_group, $id_country, $id_state, $id_county) + { + Tools::displayAsDeprecated(); + return array(); + } +} diff --git a/classes/tax/TaxRulesTaxManager.php b/classes/tax/TaxRulesTaxManager.php index aa726054..7d89bf4d 100644 --- a/classes/tax/TaxRulesTaxManager.php +++ b/classes/tax/TaxRulesTaxManager.php @@ -29,70 +29,74 @@ */ class TaxRulesTaxManagerCore implements TaxManagerInterface { - public $address; - public $type; - public $tax_calculator; + public $address; + public $type; + public $tax_calculator; - /** - * @var Core_Business_ConfigurationInterface - */ - private $configurationManager; + /** + * @var Core_Business_ConfigurationInterface + */ + private $configurationManager; - /** - * - * @param Address $address - * @param mixed $type An additional parameter for the tax manager (ex: tax rules id for TaxRuleTaxManager) - */ - public function __construct(Address $address, $type, Core_Business_ConfigurationInterface $configurationManager = null) - { - if ($configurationManager === null) - $this->configurationManager = Adapter_ServiceLocator::get('Core_Business_ConfigurationInterface'); - else - $this->configurationManager = $configurationManager; + /** + * + * @param Address $address + * @param mixed $type An additional parameter for the tax manager (ex: tax rules id for TaxRuleTaxManager) + */ + public function __construct(Address $address, $type, Core_Business_ConfigurationInterface $configurationManager = null) + { + if ($configurationManager === null) { + $this->configurationManager = Adapter_ServiceLocator::get('Core_Business_ConfigurationInterface'); + } else { + $this->configurationManager = $configurationManager; + } - $this->address = $address; - $this->type = $type; - } + $this->address = $address; + $this->type = $type; + } - /** - * Returns true if this tax manager is available for this address - * - * @return bool - */ - public static function isAvailableForThisAddress(Address $address) - { - return true; // default manager, available for all addresses - } + /** + * Returns true if this tax manager is available for this address + * + * @return bool + */ + public static function isAvailableForThisAddress(Address $address) + { + return true; // default manager, available for all addresses + } - /** - * Return the tax calculator associated to this address - * - * @return TaxCalculator - */ - public function getTaxCalculator() - { - static $tax_enabled = null; + /** + * Return the tax calculator associated to this address + * + * @return TaxCalculator + */ + public function getTaxCalculator() + { + static $tax_enabled = null; - if (isset($this->tax_calculator)) - return $this->tax_calculator; + if (isset($this->tax_calculator)) { + return $this->tax_calculator; + } - if ($tax_enabled === null) - $tax_enabled = $this->configurationManager->get('PS_TAX'); + if ($tax_enabled === null) { + $tax_enabled = $this->configurationManager->get('PS_TAX'); + } - if (!$tax_enabled) - return new TaxCalculator(array()); + if (!$tax_enabled) { + return new TaxCalculator(array()); + } - $taxes = array(); - $postcode = 0; + $taxes = array(); + $postcode = 0; - if (!empty($this->address->postcode)) - $postcode = $this->address->postcode; + if (!empty($this->address->postcode)) { + $postcode = $this->address->postcode; + } - $cache_id = (int)$this->address->id_country.'-'.(int)$this->address->id_state.'-'.$postcode.'-'.(int)$this->type; + $cache_id = (int)$this->address->id_country.'-'.(int)$this->address->id_state.'-'.$postcode.'-'.(int)$this->type; - if (!Cache::isStored($cache_id)) - { - $rows = Db::getInstance()->executeS(' + if (!Cache::isStored($cache_id)) { + $rows = Db::getInstance()->executeS(' SELECT tr.* FROM `'._DB_PREFIX_.'tax_rule` tr JOIN `'._DB_PREFIX_.'tax_rules_group` trg ON (tr.`id_tax_rules_group` = trg.`id_tax_rules_group`) @@ -104,30 +108,29 @@ class TaxRulesTaxManagerCore implements TaxManagerInterface OR (tr.`zipcode_to` = 0 AND tr.`zipcode_from` IN(0, \''.pSQL($postcode).'\'))) ORDER BY tr.`zipcode_from` DESC, tr.`zipcode_to` DESC, tr.`id_state` DESC, tr.`id_country` DESC'); - $behavior = 0; - $first_row = true; + $behavior = 0; + $first_row = true; - foreach ($rows as $row) - { - $tax = new Tax((int)$row['id_tax']); + foreach ($rows as $row) { + $tax = new Tax((int)$row['id_tax']); - $taxes[] = $tax; + $taxes[] = $tax; - // the applied behavior correspond to the most specific rules - if ($first_row) - { - $behavior = $row['behavior']; - $first_row = false; - } + // the applied behavior correspond to the most specific rules + if ($first_row) { + $behavior = $row['behavior']; + $first_row = false; + } - if ($row['behavior'] == 0) - break; - } - $result = new TaxCalculator($taxes, $behavior); - Cache::store($cache_id, $result); - return $result; - } + if ($row['behavior'] == 0) { + break; + } + } + $result = new TaxCalculator($taxes, $behavior); + Cache::store($cache_id, $result); + return $result; + } - return Cache::retrieve($cache_id); - } -} \ No newline at end of file + return Cache::retrieve($cache_id); + } +} diff --git a/classes/tax/index.php b/classes/tax/index.php index c642967a..91fa49fb 100644 --- a/classes/tax/index.php +++ b/classes/tax/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/classes/tree/ITreeToolbar.php b/classes/tree/ITreeToolbar.php index 29d7f379..49cba685 100644 --- a/classes/tree/ITreeToolbar.php +++ b/classes/tree/ITreeToolbar.php @@ -26,18 +26,18 @@ interface ITreeToolbarCore { - public function __toString(); - public function setActions($value); - public function getActions(); - public function setContext($value); - public function getContext(); - public function setData($value); - public function getData(); - public function setTemplate($value); - public function getTemplate(); - public function setTemplateDirectory($value); - public function getTemplateDirectory(); - public function addAction($action); - public function removeActions(); - public function render(); -} \ No newline at end of file + public function __toString(); + public function setActions($value); + public function getActions(); + public function setContext($value); + public function getContext(); + public function setData($value); + public function getData(); + public function setTemplate($value); + public function getTemplate(); + public function setTemplateDirectory($value); + public function getTemplateDirectory(); + public function addAction($action); + public function removeActions(); + public function render(); +} diff --git a/classes/tree/ITreeToolbarButton.php b/classes/tree/ITreeToolbarButton.php index 197ea3d5..65708db1 100644 --- a/classes/tree/ITreeToolbarButton.php +++ b/classes/tree/ITreeToolbarButton.php @@ -26,25 +26,25 @@ interface ITreeToolbarButtonCore { - public function __toString(); - public function setAttribute($name, $value); - public function getAttribute($name); - public function setAttributes($value); - public function getAttributes(); - public function setClass($value); - public function getClass(); - public function setContext($value); - public function getContext(); - public function setId($value); - public function getId(); - public function setLabel($value); - public function getLabel(); - public function setName($value); - public function getName(); - public function setTemplate($value); - public function getTemplate(); - public function setTemplateDirectory($value); - public function getTemplateDirectory(); - public function hasAttribute($name); - public function render(); -} \ No newline at end of file + public function __toString(); + public function setAttribute($name, $value); + public function getAttribute($name); + public function setAttributes($value); + public function getAttributes(); + public function setClass($value); + public function getClass(); + public function setContext($value); + public function getContext(); + public function setId($value); + public function getId(); + public function setLabel($value); + public function getLabel(); + public function setName($value); + public function getName(); + public function setTemplate($value); + public function getTemplate(); + public function setTemplateDirectory($value); + public function getTemplateDirectory(); + public function hasAttribute($name); + public function render(); +} diff --git a/classes/tree/Tree.php b/classes/tree/Tree.php index 7e280054..2658a3b1 100644 --- a/classes/tree/Tree.php +++ b/classes/tree/Tree.php @@ -26,430 +26,466 @@ class TreeCore { - const DEFAULT_TEMPLATE_DIRECTORY = 'helpers/tree'; - const DEFAULT_TEMPLATE = 'tree.tpl'; - const DEFAULT_HEADER_TEMPLATE = 'tree_header.tpl'; - const DEFAULT_NODE_FOLDER_TEMPLATE = 'tree_node_folder.tpl'; - const DEFAULT_NODE_ITEM_TEMPLATE = 'tree_node_item.tpl'; - - protected $_attributes; - private $_context; - protected $_data; - protected $_data_search; - protected $_headerTemplate; - private $_id; - protected $_node_folder_template; - protected $_node_item_template; - protected $_template; - - /** @var string */ - private $_template_directory; - private $_title; - private $_no_js; - - /** @var TreeToolbar|ITreeToolbar */ - private $_toolbar; - - public function __construct($id, $data = null) - { - $this->setId($id); - - if (isset($data)) - $this->setData($data); - } - - public function __toString() - { - return $this->render(); - } - - public function setActions($value) - { - if (!isset($this->_toolbar)) - $this->setToolbar(new TreeToolbarCore()); - - $this->getToolbar()->setTemplateDirectory($this->getTemplateDirectory())->setActions($value); - return $this; - } - - public function getActions() - { - if (!isset($this->_toolbar)) - $this->setToolbar(new TreeToolbarCore()); - - return $this->getToolbar()->setTemplateDirectory($this->getTemplateDirectory())->getActions(); - } - - public function setAttribute($name, $value) - { - if (!isset($this->_attributes)) - $this->_attributes = array(); - - $this->_attributes[$name] = $value; - return $this; - } - - public function getAttribute($name) - { - return $this->hasAttribute($name) ? $this->_attributes[$name] : null; - } - - public function setAttributes($value) - { - if (!is_array($value) && !$value instanceof Traversable) - throw new PrestaShopException('Data value must be an traversable array'); - - $this->_attributes = $value; - return $this; - } - - public function getAttributes() - { - if (!isset($this->_attributes)) - $this->_attributes = array(); - - return $this->_attributes; - } - - public function setContext($value) - { - $this->_context = $value; - return $this; - } - - public function getContext() - { - if (!isset($this->_context)) - $this->_context = Context::getContext(); - - return $this->_context; - } - - public function setDataSearch($value) - { - if (!is_array($value) && !$value instanceof Traversable) - throw new PrestaShopException('Data value must be an traversable array'); - - $this->_data_search = $value; - return $this; - } - - public function getDataSearch() - { - if (!isset($this->_data_search)) - $this->_data_search = array(); - - return $this->_data_search; - } - - public function setData($value) - { - if (!is_array($value) && !$value instanceof Traversable) - throw new PrestaShopException('Data value must be an traversable array'); - - $this->_data = $value; - return $this; - } - - public function getData() - { - if (!isset($this->_data)) - $this->_data = array(); - - return $this->_data; - } - - public function setHeaderTemplate($value) - { - $this->_headerTemplate = $value; - return $this; - } - - public function getHeaderTemplate() - { - if (!isset($this->_headerTemplate)) - $this->setHeaderTemplate(self::DEFAULT_HEADER_TEMPLATE); - - return $this->_headerTemplate; - } - - public function setId($value) - { - $this->_id = $value; - return $this; - } - - public function getId() - { - return $this->_id; - } - - public function setNodeFolderTemplate($value) - { - $this->_node_folder_template = $value; - return $this; - } - - public function getNodeFolderTemplate() - { - if (!isset($this->_node_folder_template)) - $this->setNodeFolderTemplate(self::DEFAULT_NODE_FOLDER_TEMPLATE); - - return $this->_node_folder_template; - } - - public function setNodeItemTemplate($value) - { - $this->_node_item_template = $value; - return $this; - } - - public function getNodeItemTemplate() - { - if (!isset($this->_node_item_template)) - $this->setNodeItemTemplate(self::DEFAULT_NODE_ITEM_TEMPLATE); - - return $this->_node_item_template; - } - - public function setTemplate($value) - { - $this->_template = $value; - return $this; - } - - public function getTemplate() - { - if (!isset($this->_template)) - $this->setTemplate(self::DEFAULT_TEMPLATE); - - return $this->_template; - } - - /** - * @param $value - * - * @return Tree - */ - public function setTemplateDirectory($value) - { - $this->_template_directory = $this->_normalizeDirectory($value); - return $this; - } - - /** - * @return string - */ - public function getTemplateDirectory() - { - if (!isset($this->_template_directory)) - $this->_template_directory = $this->_normalizeDirectory( - self::DEFAULT_TEMPLATE_DIRECTORY); - - return $this->_template_directory; - } - - public function getTemplateFile($template) - { - if (preg_match_all('/((?:^|[A-Z])[a-z]+)/', get_class($this->getContext()->controller), $matches) !== false) - $controller_name = strtolower($matches[0][1]); - - if ($this->getContext()->controller instanceof ModuleAdminController && isset($controller_name) && file_exists($this->_normalizeDirectory( - $this->getContext()->controller->getTemplatePath()).$controller_name.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->controller->getTemplatePath()). - $controller_name.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template; - elseif ($this->getContext()->controller instanceof ModuleAdminController && file_exists($this->_normalizeDirectory( - $this->getContext()->controller->getTemplatePath()).$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->controller->getTemplatePath()) - .$this->getTemplateDirectory().$template; - elseif ($this->getContext()->controller instanceof AdminController && isset($controller_name) - && file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' - .DIRECTORY_SEPARATOR.$controller_name.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' - .DIRECTORY_SEPARATOR.$controller_name.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template; - elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) - .$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) - .$this->getTemplateDirectory().$template; - elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) - .$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) - .$this->getTemplateDirectory().$template; - else - return $this->getTemplateDirectory().$template; - } - - public function setNoJS($value) - { - $this->_no_js = $value; - return $this; - } - - public function setTitle($value) - { - $this->_title = $value; - return $this; - } - - public function getTitle() - { - return $this->_title; - } - - public function setToolbar($value) - { - if (!is_object($value)) - throw new PrestaShopException('Toolbar must be a class object'); - - $reflection = new ReflectionClass($value); - - if (!$reflection->implementsInterface('ITreeToolbarCore')) - throw new PrestaShopException('Toolbar class must implements ITreeToolbarCore interface'); - - $this->_toolbar = $value; - return $this; - } - - public function getToolbar() - { - if (isset($this->_toolbar)) - { - if ($this->getDataSearch()) - $this->_toolbar->setData($this->getDataSearch()); - else - $this->_toolbar->setData($this->getData()); - } - - return $this->_toolbar; - } - - public function addAction($action) - { - if (!isset($this->_toolbar)) - $this->setToolbar(new TreeToolbarCore()); - - $this->getToolbar()->setTemplateDirectory($this->getTemplateDirectory())->addAction($action); - return $this; - } - - public function removeActions() - { - if (!isset($this->_toolbar)) - $this->setToolbar(new TreeToolbarCore()); - - $this->getToolbar()->setTemplateDirectory($this->getTemplateDirectory())->removeActions(); - return $this; - } - - public function render($data = null) - { - //Adding tree.js - $admin_webpath = str_ireplace(_PS_CORE_DIR_, '', _PS_ADMIN_DIR_); - $admin_webpath = preg_replace('/^'.preg_quote(DIRECTORY_SEPARATOR, '/').'/', '', $admin_webpath); - $bo_theme = ((Validate::isLoadedObject($this->getContext()->employee) - && $this->getContext()->employee->bo_theme) ? $this->getContext()->employee->bo_theme : 'default'); - - if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR.'template')) - $bo_theme = 'default'; - - $js_path = __PS_BASE_URI__.$admin_webpath.'/themes/'.$bo_theme.'/js/tree.js'; - if ($this->getContext()->controller->ajax) - { - if (!$this->_no_js) - $html = '<script type="text/javascript" src="'.$js_path.'"></script>'; - } - else - $this->getContext()->controller->addJs($js_path); - - //Create Tree Template - $template = $this->getContext()->smarty->createTemplate( - $this->getTemplateFile($this->getTemplate()), - $this->getContext()->smarty - ); - - if (trim($this->getTitle()) != '' || $this->useToolbar()) - { - //Create Tree Header Template - $headerTemplate = $this->getContext()->smarty->createTemplate( - $this->getTemplateFile($this->getHeaderTemplate()), - $this->getContext()->smarty - ); - $headerTemplate->assign($this->getAttributes()) - ->assign(array( - 'title' => $this->getTitle(), - 'toolbar' => $this->useToolbar() ? $this->renderToolbar() : null - )); - $template->assign('header', $headerTemplate->fetch()); - } - - //Assign Tree nodes - $template->assign($this->getAttributes())->assign(array( - 'id' => $this->getId(), - 'nodes' => $this->renderNodes($data) - )); - - return (isset($html) ? $html : '').$template->fetch(); - } - - public function renderNodes($data = null) - { - if (!isset($data)) - $data = $this->getData(); - - if (!is_array($data) && !$data instanceof Traversable) - throw new PrestaShopException('Data value must be an traversable array'); - - $html = ''; - - foreach ($data as $item) - { - if (array_key_exists('children', $item) - && !empty($item['children'])) - $html .= $this->getContext()->smarty->createTemplate( - $this->getTemplateFile($this->getNodeFolderTemplate()), - $this->getContext()->smarty - )->assign(array( - 'children' => $this->renderNodes($item['children']), - 'node' => $item - ))->fetch(); - else - $html .= $this->getContext()->smarty->createTemplate( - $this->getTemplateFile($this->getNodeItemTemplate()), - $this->getContext()->smarty - )->assign(array( - 'node' => $item - ))->fetch(); - } - - return $html; - } - - public function renderToolbar() - { - return $this->getToolbar()->render(); - } - - public function useInput() - { - return isset($this->_input_type); - } - - public function useToolbar() - { - return isset($this->_toolbar); - } - - private function _normalizeDirectory($directory) - { - $last = $directory[strlen($directory) - 1]; - - if (in_array($last, array('/', '\\'))) - { - $directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR; - return $directory; - } - - $directory .= DIRECTORY_SEPARATOR; - return $directory; - } -} \ No newline at end of file + const DEFAULT_TEMPLATE_DIRECTORY = 'helpers/tree'; + const DEFAULT_TEMPLATE = 'tree.tpl'; + const DEFAULT_HEADER_TEMPLATE = 'tree_header.tpl'; + const DEFAULT_NODE_FOLDER_TEMPLATE = 'tree_node_folder.tpl'; + const DEFAULT_NODE_ITEM_TEMPLATE = 'tree_node_item.tpl'; + + protected $_attributes; + private $_context; + protected $_data; + protected $_data_search; + protected $_headerTemplate; + protected $_id_tree; + private $_id; + protected $_node_folder_template; + protected $_node_item_template; + protected $_template; + + /** @var string */ + private $_template_directory; + private $_title; + private $_no_js; + + /** @var TreeToolbar|ITreeToolbar */ + private $_toolbar; + + public function __construct($id, $data = null) + { + $this->setId($id); + + if (isset($data)) { + $this->setData($data); + } + } + + public function __toString() + { + return $this->render(); + } + + public function setActions($value) + { + if (!isset($this->_toolbar)) { + $this->setToolbar(new TreeToolbarCore()); + } + + $this->getToolbar()->setTemplateDirectory($this->getTemplateDirectory())->setActions($value); + return $this; + } + + public function getActions() + { + if (!isset($this->_toolbar)) { + $this->setToolbar(new TreeToolbarCore()); + } + + return $this->getToolbar()->setTemplateDirectory($this->getTemplateDirectory())->getActions(); + } + + public function setAttribute($name, $value) + { + if (!isset($this->_attributes)) { + $this->_attributes = array(); + } + + $this->_attributes[$name] = $value; + return $this; + } + + public function getAttribute($name) + { + return $this->hasAttribute($name) ? $this->_attributes[$name] : null; + } + + public function setAttributes($value) + { + if (!is_array($value) && !$value instanceof Traversable) { + throw new PrestaShopException('Data value must be an traversable array'); + } + + $this->_attributes = $value; + return $this; + } + + public function setIdTree($id_tree) + { + $this->_id_tree = $id_tree; + return $this; + } + + public function getIdTree() + { + return $this->_id_tree; + } + + public function getAttributes() + { + if (!isset($this->_attributes)) { + $this->_attributes = array(); + } + + return $this->_attributes; + } + + public function setContext($value) + { + $this->_context = $value; + return $this; + } + + public function getContext() + { + if (!isset($this->_context)) { + $this->_context = Context::getContext(); + } + + return $this->_context; + } + + public function setDataSearch($value) + { + if (!is_array($value) && !$value instanceof Traversable) { + throw new PrestaShopException('Data value must be an traversable array'); + } + + $this->_data_search = $value; + return $this; + } + + public function getDataSearch() + { + if (!isset($this->_data_search)) { + $this->_data_search = array(); + } + + return $this->_data_search; + } + + public function setData($value) + { + if (!is_array($value) && !$value instanceof Traversable) { + throw new PrestaShopException('Data value must be an traversable array'); + } + + $this->_data = $value; + return $this; + } + + public function getData() + { + if (!isset($this->_data)) { + $this->_data = array(); + } + + return $this->_data; + } + + public function setHeaderTemplate($value) + { + $this->_headerTemplate = $value; + return $this; + } + + public function getHeaderTemplate() + { + if (!isset($this->_headerTemplate)) { + $this->setHeaderTemplate(self::DEFAULT_HEADER_TEMPLATE); + } + + return $this->_headerTemplate; + } + + public function setId($value) + { + $this->_id = $value; + return $this; + } + + public function getId() + { + return $this->_id; + } + + public function setNodeFolderTemplate($value) + { + $this->_node_folder_template = $value; + return $this; + } + + public function getNodeFolderTemplate() + { + if (!isset($this->_node_folder_template)) { + $this->setNodeFolderTemplate(self::DEFAULT_NODE_FOLDER_TEMPLATE); + } + + return $this->_node_folder_template; + } + + public function setNodeItemTemplate($value) + { + $this->_node_item_template = $value; + return $this; + } + + public function getNodeItemTemplate() + { + if (!isset($this->_node_item_template)) { + $this->setNodeItemTemplate(self::DEFAULT_NODE_ITEM_TEMPLATE); + } + + return $this->_node_item_template; + } + + public function setTemplate($value) + { + $this->_template = $value; + return $this; + } + + public function getTemplate() + { + if (!isset($this->_template)) { + $this->setTemplate(self::DEFAULT_TEMPLATE); + } + + return $this->_template; + } + + /** + * @param $value + * + * @return Tree + */ + public function setTemplateDirectory($value) + { + $this->_template_directory = $this->_normalizeDirectory($value); + return $this; + } + + /** + * @return string + */ + public function getTemplateDirectory() + { + if (!isset($this->_template_directory)) { + $this->_template_directory = $this->_normalizeDirectory( + self::DEFAULT_TEMPLATE_DIRECTORY); + } + + return $this->_template_directory; + } + + public function getTemplateFile($template) + { + if (preg_match_all('/((?:^|[A-Z])[a-z]+)/', get_class($this->getContext()->controller), $matches) !== false) { + $controller_name = strtolower($matches[0][1]); + } + + if ($this->getContext()->controller instanceof ModuleAdminController && isset($controller_name) && file_exists($this->_normalizeDirectory( + $this->getContext()->controller->getTemplatePath()).$controller_name.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->controller->getTemplatePath()). + $controller_name.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template; + } elseif ($this->getContext()->controller instanceof ModuleAdminController && file_exists($this->_normalizeDirectory( + $this->getContext()->controller->getTemplatePath()).$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->controller->getTemplatePath()) + .$this->getTemplateDirectory().$template; + } elseif ($this->getContext()->controller instanceof AdminController && isset($controller_name) + && file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' + .DIRECTORY_SEPARATOR.$controller_name.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' + .DIRECTORY_SEPARATOR.$controller_name.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template; + } elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) + .$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) + .$this->getTemplateDirectory().$template; + } elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) + .$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) + .$this->getTemplateDirectory().$template; + } else { + return $this->getTemplateDirectory().$template; + } + } + + public function setNoJS($value) + { + $this->_no_js = $value; + return $this; + } + + public function setTitle($value) + { + $this->_title = $value; + return $this; + } + + public function getTitle() + { + return $this->_title; + } + + public function setToolbar($value) + { + if (!is_object($value)) { + throw new PrestaShopException('Toolbar must be a class object'); + } + + $reflection = new ReflectionClass($value); + + if (!$reflection->implementsInterface('ITreeToolbarCore')) { + throw new PrestaShopException('Toolbar class must implements ITreeToolbarCore interface'); + } + + $this->_toolbar = $value; + return $this; + } + + public function getToolbar() + { + if (isset($this->_toolbar)) { + if ($this->getDataSearch()) { + $this->_toolbar->setData($this->getDataSearch()); + } else { + $this->_toolbar->setData($this->getData()); + } + } + + return $this->_toolbar; + } + + public function addAction($action) + { + if (!isset($this->_toolbar)) { + $this->setToolbar(new TreeToolbarCore()); + } + + $this->getToolbar()->setTemplateDirectory($this->getTemplateDirectory())->addAction($action); + return $this; + } + + public function removeActions() + { + if (!isset($this->_toolbar)) { + $this->setToolbar(new TreeToolbarCore()); + } + + $this->getToolbar()->setTemplateDirectory($this->getTemplateDirectory())->removeActions(); + return $this; + } + + public function render($data = null) + { + //Adding tree.js + $admin_webpath = str_ireplace(_PS_CORE_DIR_, '', _PS_ADMIN_DIR_); + $admin_webpath = preg_replace('/^'.preg_quote(DIRECTORY_SEPARATOR, '/').'/', '', $admin_webpath); + $bo_theme = ((Validate::isLoadedObject($this->getContext()->employee) + && $this->getContext()->employee->bo_theme) ? $this->getContext()->employee->bo_theme : 'default'); + + if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR.'template')) { + $bo_theme = 'default'; + } + + $js_path = __PS_BASE_URI__.$admin_webpath.'/themes/'.$bo_theme.'/js/tree.js'; + if ($this->getContext()->controller->ajax) { + if (!$this->_no_js) { + $html = '<script type="text/javascript" src="'.$js_path.'"></script>'; + } + } else { + $this->getContext()->controller->addJs($js_path); + } + + //Create Tree Template + $template = $this->getContext()->smarty->createTemplate( + $this->getTemplateFile($this->getTemplate()), + $this->getContext()->smarty + ); + + if (trim($this->getTitle()) != '' || $this->useToolbar()) { + //Create Tree Header Template + $headerTemplate = $this->getContext()->smarty->createTemplate( + $this->getTemplateFile($this->getHeaderTemplate()), + $this->getContext()->smarty + ); + $headerTemplate->assign($this->getAttributes()) + ->assign(array( + 'title' => $this->getTitle(), + 'toolbar' => $this->useToolbar() ? $this->renderToolbar() : null + )); + $template->assign('header', $headerTemplate->fetch()); + } + + //Assign Tree nodes + $template->assign($this->getAttributes())->assign(array( + 'id' => $this->getId(), + 'nodes' => $this->renderNodes($data), + 'id_tree' => $this->getIdTree() + )); + + return (isset($html) ? $html : '').$template->fetch(); + } + + public function renderNodes($data = null) + { + if (!isset($data)) { + $data = $this->getData(); + } + + if (!is_array($data) && !$data instanceof Traversable) { + throw new PrestaShopException('Data value must be an traversable array'); + } + + $html = ''; + + foreach ($data as $item) { + if (array_key_exists('children', $item) + && !empty($item['children'])) { + $html .= $this->getContext()->smarty->createTemplate( + $this->getTemplateFile($this->getNodeFolderTemplate()), + $this->getContext()->smarty + )->assign(array( + 'children' => $this->renderNodes($item['children']), + 'node' => $item + ))->fetch(); + } else { + $html .= $this->getContext()->smarty->createTemplate( + $this->getTemplateFile($this->getNodeItemTemplate()), + $this->getContext()->smarty + )->assign(array( + 'node' => $item + ))->fetch(); + } + } + + return $html; + } + + public function renderToolbar() + { + return $this->getToolbar()->render(); + } + + public function useInput() + { + return isset($this->_input_type); + } + + public function useToolbar() + { + return isset($this->_toolbar); + } + + private function _normalizeDirectory($directory) + { + $last = $directory[strlen($directory) - 1]; + + if (in_array($last, array('/', '\\'))) { + $directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR; + return $directory; + } + + $directory .= DIRECTORY_SEPARATOR; + return $directory; + } +} diff --git a/classes/tree/TreeToolbar.php b/classes/tree/TreeToolbar.php index 5c392799..4682d0ef 100644 --- a/classes/tree/TreeToolbar.php +++ b/classes/tree/TreeToolbar.php @@ -26,177 +26,188 @@ class TreeToolbarCore implements ITreeToolbarCore { - const DEFAULT_TEMPLATE_DIRECTORY = 'helpers/tree'; - const DEFAULT_TEMPLATE = 'tree_toolbar.tpl'; + const DEFAULT_TEMPLATE_DIRECTORY = 'helpers/tree'; + const DEFAULT_TEMPLATE = 'tree_toolbar.tpl'; - private $_actions; - private $_context; - private $_data; - private $_template; - private $_template_directory; + private $_actions; + private $_context; + private $_data; + private $_template; + private $_template_directory; - public function __toString() - { - return $this->render(); - } + public function __toString() + { + return $this->render(); + } - public function setActions($actions) - { - if (!is_array($actions) && !$actions instanceof Traversable) - throw new PrestaShopException('Action value must be an traversable array'); + public function setActions($actions) + { + if (!is_array($actions) && !$actions instanceof Traversable) { + throw new PrestaShopException('Action value must be an traversable array'); + } - foreach ($actions as $action) - $this->addAction($action); - } + foreach ($actions as $action) { + $this->addAction($action); + } + } - public function getActions() - { - if (!isset($this->_actions)) - $this->_actions = array(); + public function getActions() + { + if (!isset($this->_actions)) { + $this->_actions = array(); + } - return $this->_actions; - } + return $this->_actions; + } - public function setContext($value) - { - $this->_context = $value; - return $this; - } + public function setContext($value) + { + $this->_context = $value; + return $this; + } - public function getContext() - { - if (!isset($this->_context)) - $this->_context = Context::getContext(); + public function getContext() + { + if (!isset($this->_context)) { + $this->_context = Context::getContext(); + } - return $this->_context; - } + return $this->_context; + } - public function setData($value) - { - if (!is_array($value) && !$value instanceof Traversable) - throw new PrestaShopException('Data value must be an traversable array'); + public function setData($value) + { + if (!is_array($value) && !$value instanceof Traversable) { + throw new PrestaShopException('Data value must be an traversable array'); + } - $this->_data = $value; - return $this; - } + $this->_data = $value; + return $this; + } - public function getData() - { - return $this->_data; - } + public function getData() + { + return $this->_data; + } - public function setTemplate($value) - { - $this->_template = $value; - return $this; - } + public function setTemplate($value) + { + $this->_template = $value; + return $this; + } - public function getTemplate() - { - if (!isset($this->_template)) - $this->setTemplate(self::DEFAULT_TEMPLATE); + public function getTemplate() + { + if (!isset($this->_template)) { + $this->setTemplate(self::DEFAULT_TEMPLATE); + } - return $this->_template; - } + return $this->_template; + } - public function setTemplateDirectory($value) - { - $this->_template_directory = $this->_normalizeDirectory($value); - return $this; - } + public function setTemplateDirectory($value) + { + $this->_template_directory = $this->_normalizeDirectory($value); + return $this; + } - public function getTemplateDirectory() - { - if (!isset($this->_template_directory)) - $this->_template_directory = $this->_normalizeDirectory( - self::DEFAULT_TEMPLATE_DIRECTORY); + public function getTemplateDirectory() + { + if (!isset($this->_template_directory)) { + $this->_template_directory = $this->_normalizeDirectory( + self::DEFAULT_TEMPLATE_DIRECTORY); + } - return $this->_template_directory; - } + return $this->_template_directory; + } - public function getTemplateFile($template) - { - if (preg_match_all('/((?:^|[A-Z])[a-z]+)/', get_class($this->getContext()->controller), $matches) !== false) - $controllerName = strtolower($matches[0][1]); + public function getTemplateFile($template) + { + if (preg_match_all('/((?:^|[A-Z])[a-z]+)/', get_class($this->getContext()->controller), $matches) !== false) { + $controllerName = strtolower($matches[0][1]); + } - if ($this->getContext()->controller instanceof ModuleAdminController && file_exists($this->_normalizeDirectory( - $this->getContext()->controller->getTemplatePath()).$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->controller->getTemplatePath()) - .$this->getTemplateDirectory().$template; - elseif ($this->getContext()->controller instanceof AdminController && isset($controllerName) - && file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' - .DIRECTORY_SEPARATOR.$controllerName.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' - .DIRECTORY_SEPARATOR.$controllerName.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template; - elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) - .$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) - .$this->getTemplateDirectory().$template; - elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) - .$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) - .$this->getTemplateDirectory().$template; - else - return $this->getTemplateDirectory().$template; - } + if ($this->getContext()->controller instanceof ModuleAdminController && file_exists($this->_normalizeDirectory( + $this->getContext()->controller->getTemplatePath()).$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->controller->getTemplatePath()) + .$this->getTemplateDirectory().$template; + } elseif ($this->getContext()->controller instanceof AdminController && isset($controllerName) + && file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' + .DIRECTORY_SEPARATOR.$controllerName.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' + .DIRECTORY_SEPARATOR.$controllerName.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template; + } elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) + .$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) + .$this->getTemplateDirectory().$template; + } elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) + .$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) + .$this->getTemplateDirectory().$template; + } else { + return $this->getTemplateDirectory().$template; + } + } - /** - * @param ITreeToolbarButton $action - * - * @return TreeToolbar - * @throws PrestaShopException - */ - public function addAction($action) - { - if (!is_object($action)) - throw new PrestaShopException('Action must be a class object'); + /** + * @param ITreeToolbarButton $action + * + * @return TreeToolbar + * @throws PrestaShopException + */ + public function addAction($action) + { + if (!is_object($action)) { + throw new PrestaShopException('Action must be a class object'); + } - $reflection = new ReflectionClass($action); + $reflection = new ReflectionClass($action); - if (!$reflection->implementsInterface('ITreeToolbarButtonCore')) - throw new PrestaShopException('Action class must implements ITreeToolbarButtonCore interface'); + if (!$reflection->implementsInterface('ITreeToolbarButtonCore')) { + throw new PrestaShopException('Action class must implements ITreeToolbarButtonCore interface'); + } - if (!isset($this->_actions)) - $this->_actions = array(); + if (!isset($this->_actions)) { + $this->_actions = array(); + } - if (isset($this->_template_directory)) - $action->setTemplateDirectory($this->getTemplateDirectory()); + if (isset($this->_template_directory)) { + $action->setTemplateDirectory($this->getTemplateDirectory()); + } - $this->_actions[] = $action; - return $this; - } + $this->_actions[] = $action; + return $this; + } - public function removeActions() - { - $this->_actions = null; - return $this; - } + public function removeActions() + { + $this->_actions = null; + return $this; + } - public function render() - { - foreach ($this->getActions() as $action) - { - /** @var ITreeToolbarButton $action */ - $action->setAttribute('data', $this->getData()); - } + public function render() + { + foreach ($this->getActions() as $action) { + /** @var ITreeToolbarButton $action */ + $action->setAttribute('data', $this->getData()); + } - return $this->getContext()->smarty->createTemplate( - $this->getTemplateFile($this->getTemplate()), - $this->getContext()->smarty - )->assign('actions', $this->getActions())->fetch(); - } + return $this->getContext()->smarty->createTemplate( + $this->getTemplateFile($this->getTemplate()), + $this->getContext()->smarty + )->assign('actions', $this->getActions())->fetch(); + } - private function _normalizeDirectory($directory) - { - $last = $directory[strlen($directory) - 1]; + private function _normalizeDirectory($directory) + { + $last = $directory[strlen($directory) - 1]; - if (in_array($last, array('/', '\\'))) - { - $directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR; - return $directory; - } + if (in_array($last, array('/', '\\'))) { + $directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR; + return $directory; + } - $directory .= DIRECTORY_SEPARATOR; - return $directory; - } -} \ No newline at end of file + $directory .= DIRECTORY_SEPARATOR; + return $directory; + } +} diff --git a/classes/tree/TreeToolbarButton.php b/classes/tree/TreeToolbarButton.php index 3c3e05fe..546a4602 100644 --- a/classes/tree/TreeToolbarButton.php +++ b/classes/tree/TreeToolbarButton.php @@ -26,191 +26,197 @@ abstract class TreeToolbarButtonCore { - const DEFAULT_TEMPLATE_DIRECTORY = 'helpers/tree'; + const DEFAULT_TEMPLATE_DIRECTORY = 'helpers/tree'; - protected $_attributes; - private $_class; - private $_context; - private $_id; - private $_label; - private $_name; - protected $_template; - protected $_template_directory; + protected $_attributes; + private $_class; + private $_context; + private $_id; + private $_label; + private $_name; + protected $_template; + protected $_template_directory; - public function __construct($label, $id = null, $name = null, $class = null) - { - $this->setLabel($label); - $this->setId($id); - $this->setName($name); - $this->setClass($class); - } + public function __construct($label, $id = null, $name = null, $class = null) + { + $this->setLabel($label); + $this->setId($id); + $this->setName($name); + $this->setClass($class); + } - public function __toString() - { - return $this->render(); - } + public function __toString() + { + return $this->render(); + } - public function setAttribute($name, $value) - { - if (!isset($this->_attributes)) - $this->_attributes = array(); + public function setAttribute($name, $value) + { + if (!isset($this->_attributes)) { + $this->_attributes = array(); + } - $this->_attributes[$name] = $value; - return $this; - } + $this->_attributes[$name] = $value; + return $this; + } - public function getAttribute($name) - { - return $this->hasAttribute($name) ? $this->_attributes[$name] : null; - } + public function getAttribute($name) + { + return $this->hasAttribute($name) ? $this->_attributes[$name] : null; + } - public function setAttributes($value) - { - if (!is_array($value) && !$value instanceof Traversable) - throw new PrestaShopException('Data value must be an traversable array'); + public function setAttributes($value) + { + if (!is_array($value) && !$value instanceof Traversable) { + throw new PrestaShopException('Data value must be an traversable array'); + } - $this->_attributes = $value; - return $this; - } + $this->_attributes = $value; + return $this; + } - public function getAttributes() - { - if (!isset($this->_attributes)) - $this->_attributes = array(); + public function getAttributes() + { + if (!isset($this->_attributes)) { + $this->_attributes = array(); + } - return $this->_attributes; - } + return $this->_attributes; + } - public function setClass($value) - { - return $this->setAttribute('class', $value); - } + public function setClass($value) + { + return $this->setAttribute('class', $value); + } - public function getClass() - { - return $this->getAttribute('class'); - } + public function getClass() + { + return $this->getAttribute('class'); + } - public function setContext($value) - { - $this->_context = $value; - return $this; - } + public function setContext($value) + { + $this->_context = $value; + return $this; + } - public function getContext() - { - if (!isset($this->_context)) - $this->_context = Context::getContext(); + public function getContext() + { + if (!isset($this->_context)) { + $this->_context = Context::getContext(); + } - return $this->_context; - } + return $this->_context; + } - public function setId($value) - { - return $this->setAttribute('id', $value); - } + public function setId($value) + { + return $this->setAttribute('id', $value); + } - public function getId() - { - return $this->getAttribute('id'); - } + public function getId() + { + return $this->getAttribute('id'); + } - public function setLabel($value) - { - return $this->setAttribute('label', $value); - } + public function setLabel($value) + { + return $this->setAttribute('label', $value); + } - public function getLabel() - { - return $this->getAttribute('label'); - } + public function getLabel() + { + return $this->getAttribute('label'); + } - public function setName($value) - { - return $this->setAttribute('name', $value); - } + public function setName($value) + { + return $this->setAttribute('name', $value); + } - public function getName() - { - return $this->getAttribute('name'); - } + public function getName() + { + return $this->getAttribute('name'); + } - public function setTemplate($value) - { - $this->_template = $value; - return $this; - } + public function setTemplate($value) + { + $this->_template = $value; + return $this; + } - public function getTemplate() - { - return $this->_template; - } + public function getTemplate() + { + return $this->_template; + } - public function setTemplateDirectory($value) - { - $this->_template_directory = $this->_normalizeDirectory($value); - return $this; - } + public function setTemplateDirectory($value) + { + $this->_template_directory = $this->_normalizeDirectory($value); + return $this; + } - public function getTemplateDirectory() - { - if (!isset($this->_template_directory)) - $this->_template_directory = $this->_normalizeDirectory(self::DEFAULT_TEMPLATE_DIRECTORY); + public function getTemplateDirectory() + { + if (!isset($this->_template_directory)) { + $this->_template_directory = $this->_normalizeDirectory(self::DEFAULT_TEMPLATE_DIRECTORY); + } - return $this->_template_directory; - } + return $this->_template_directory; + } - public function getTemplateFile($template) - { - if (preg_match_all('/((?:^|[A-Z])[a-z]+)/', get_class($this->getContext()->controller), $matches) !== false) - $controllerName = strtolower($matches[0][1]); + public function getTemplateFile($template) + { + if (preg_match_all('/((?:^|[A-Z])[a-z]+)/', get_class($this->getContext()->controller), $matches) !== false) { + $controllerName = strtolower($matches[0][1]); + } - if ($this->getContext()->controller instanceof ModuleAdminController && file_exists($this->_normalizeDirectory( - $this->getContext()->controller->getTemplatePath()).$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->controller->getTemplatePath()) - .$this->getTemplateDirectory().$template; - elseif ($this->getContext()->controller instanceof AdminController && isset($controllerName) - && file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' - .DIRECTORY_SEPARATOR.$controllerName.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' - .DIRECTORY_SEPARATOR.$controllerName.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template; - elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) - .$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) - .$this->getTemplateDirectory().$template; - elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) - .$this->getTemplateDirectory().$template)) - return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) - .$this->getTemplateDirectory().$template; - else - return $this->getTemplateDirectory().$template; - } + if ($this->getContext()->controller instanceof ModuleAdminController && file_exists($this->_normalizeDirectory( + $this->getContext()->controller->getTemplatePath()).$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->controller->getTemplatePath()) + .$this->getTemplateDirectory().$template; + } elseif ($this->getContext()->controller instanceof AdminController && isset($controllerName) + && file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' + .DIRECTORY_SEPARATOR.$controllerName.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)).'controllers' + .DIRECTORY_SEPARATOR.$controllerName.DIRECTORY_SEPARATOR.$this->getTemplateDirectory().$template; + } elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) + .$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(1)) + .$this->getTemplateDirectory().$template; + } elseif (file_exists($this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) + .$this->getTemplateDirectory().$template)) { + return $this->_normalizeDirectory($this->getContext()->smarty->getTemplateDir(0)) + .$this->getTemplateDirectory().$template; + } else { + return $this->getTemplateDirectory().$template; + } + } - public function hasAttribute($name) - { - return (isset($this->_attributes) - && array_key_exists($name, $this->_attributes)); - } + public function hasAttribute($name) + { + return (isset($this->_attributes) + && array_key_exists($name, $this->_attributes)); + } - public function render() - { - return $this->getContext()->smarty->createTemplate( - $this->getTemplateFile($this->getTemplate()), - $this->getContext()->smarty - )->assign($this->getAttributes())->fetch(); - } + public function render() + { + return $this->getContext()->smarty->createTemplate( + $this->getTemplateFile($this->getTemplate()), + $this->getContext()->smarty + )->assign($this->getAttributes())->fetch(); + } - private function _normalizeDirectory($directory) - { - $last = $directory[strlen($directory) - 1]; + private function _normalizeDirectory($directory) + { + $last = $directory[strlen($directory) - 1]; - if (in_array($last, array('/', '\\'))) - { - $directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR; - return $directory; - } + if (in_array($last, array('/', '\\'))) { + $directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR; + return $directory; + } - $directory .= DIRECTORY_SEPARATOR; - return $directory; - } -} \ No newline at end of file + $directory .= DIRECTORY_SEPARATOR; + return $directory; + } +} diff --git a/classes/tree/TreeToolbarLink.php b/classes/tree/TreeToolbarLink.php index 873a037a..5c058c25 100644 --- a/classes/tree/TreeToolbarLink.php +++ b/classes/tree/TreeToolbarLink.php @@ -25,49 +25,49 @@ */ class TreeToolbarLinkCore extends TreeToolbarButtonCore implements - ITreeToolbarButtonCore + ITreeToolbarButtonCore { - private $_action; - private $_icon_class; - private $_link; - protected $_template = 'tree_toolbar_link.tpl'; + private $_action; + private $_icon_class; + private $_link; + protected $_template = 'tree_toolbar_link.tpl'; - public function __construct($label, $link, $action = null, $iconClass = null) - { - parent::__construct($label); + public function __construct($label, $link, $action = null, $iconClass = null) + { + parent::__construct($label); - $this->setLink($link); - $this->setAction($action); - $this->setIconClass($iconClass); - } + $this->setLink($link); + $this->setAction($action); + $this->setIconClass($iconClass); + } - public function setAction($value) - { - return $this->setAttribute('action', $value); - } + public function setAction($value) + { + return $this->setAttribute('action', $value); + } - public function getAction() - { - return $this->getAttribute('action'); - } + public function getAction() + { + return $this->getAttribute('action'); + } - public function setIconClass($value) - { - return $this->setAttribute('icon_class', $value); - } + public function setIconClass($value) + { + return $this->setAttribute('icon_class', $value); + } - public function getIconClass() - { - return $this->getAttribute('icon_class'); - } + public function getIconClass() + { + return $this->getAttribute('icon_class'); + } - public function setLink($value) - { - return $this->setAttribute('link', $value); - } + public function setLink($value) + { + return $this->setAttribute('link', $value); + } - public function getLink() - { - return $this->getAttribute('link'); - } -} \ No newline at end of file + public function getLink() + { + return $this->getAttribute('link'); + } +} diff --git a/classes/tree/TreeToolbarSearch.php b/classes/tree/TreeToolbarSearch.php index 0e212f7c..ab7a3a8a 100644 --- a/classes/tree/TreeToolbarSearch.php +++ b/classes/tree/TreeToolbarSearch.php @@ -25,58 +25,62 @@ */ class TreeToolbarSearchCore extends TreeToolbarButtonCore implements - ITreeToolbarButtonCore + ITreeToolbarButtonCore { - protected $_template = 'tree_toolbar_search.tpl'; + protected $_template = 'tree_toolbar_search.tpl'; - public function __construct($label, $id, $name = null, $class = null) - { - parent::__construct($label); + public function __construct($label, $id, $name = null, $class = null) + { + parent::__construct($label); - $this->setId($id); - $this->setName($name); - $this->setClass($class); - } + $this->setId($id); + $this->setName($name); + $this->setClass($class); + } - public function render() - { - if ($this->hasAttribute('data_search')) - $this->setAttribute('typeahead_source', - $this->_renderData($this->getAttribute('data_search'))); - else if ($this->hasAttribute('data')) - $this->setAttribute('typeahead_source', - $this->_renderData($this->getAttribute('data'))); + public function render() + { + if ($this->hasAttribute('data_search')) { + $this->setAttribute('typeahead_source', + $this->_renderData($this->getAttribute('data_search'))); + } elseif ($this->hasAttribute('data')) { + $this->setAttribute('typeahead_source', + $this->_renderData($this->getAttribute('data'))); + } - $admin_webpath = str_ireplace(_PS_CORE_DIR_, '', _PS_ADMIN_DIR_); - $admin_webpath = preg_replace('/^'.preg_quote(DIRECTORY_SEPARATOR, '/').'/', '', $admin_webpath); - $bo_theme = ((Validate::isLoadedObject($this->getContext()->employee) - && $this->getContext()->employee->bo_theme) ? $this->getContext()->employee->bo_theme : 'default'); + $admin_webpath = str_ireplace(_PS_CORE_DIR_, '', _PS_ADMIN_DIR_); + $admin_webpath = preg_replace('/^'.preg_quote(DIRECTORY_SEPARATOR, '/').'/', '', $admin_webpath); + $bo_theme = ((Validate::isLoadedObject($this->getContext()->employee) + && $this->getContext()->employee->bo_theme) ? $this->getContext()->employee->bo_theme : 'default'); - if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR.'template')) - $bo_theme = 'default'; + if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR.'template')) { + $bo_theme = 'default'; + } - if ($this->getContext()->controller->ajax) - $html = '<script type="text/javascript" src="'.__PS_BASE_URI__.$admin_webpath.'/themes/'.$bo_theme.'/js/vendor/typeahead.min.js"></script>'; - else - $this->getContext()->controller->addJs(__PS_BASE_URI__.$admin_webpath.'/themes/'.$bo_theme.'/js/vendor/typeahead.min.js'); + if ($this->getContext()->controller->ajax) { + $html = '<script type="text/javascript" src="'.__PS_BASE_URI__.$admin_webpath.'/themes/'.$bo_theme.'/js/vendor/typeahead.min.js"></script>'; + } else { + $this->getContext()->controller->addJs(__PS_BASE_URI__.$admin_webpath.'/themes/'.$bo_theme.'/js/vendor/typeahead.min.js'); + } - return (isset($html) ? $html : '').parent::render(); - } + return (isset($html) ? $html : '').parent::render(); + } - private function _renderData($data) - { - if (!is_array($data) && !$data instanceof Traversable) - throw new PrestaShopException('Data value must be a traversable array'); + private function _renderData($data) + { + if (!is_array($data) && !$data instanceof Traversable) { + throw new PrestaShopException('Data value must be a traversable array'); + } - $html = ''; + $html = ''; - foreach ($data as $item) - { - $html .= Tools::jsonEncode($item).','; - if (array_key_exists('children', $item) && !empty($item['children'])) - $html .= $this->_renderData($item['children']); - } + foreach ($data as $item) { + $html .= Tools::jsonEncode($item).','; + if (array_key_exists('children', $item) && !empty($item['children'])) { + $html .= $this->_renderData($item['children']); + } + } - return $html; - } -} \ No newline at end of file + return $html; + } +} diff --git a/classes/tree/TreeToolbarSearchCategories.php b/classes/tree/TreeToolbarSearchCategories.php index 1afc3053..4c47744d 100644 --- a/classes/tree/TreeToolbarSearchCategories.php +++ b/classes/tree/TreeToolbarSearchCategories.php @@ -25,55 +25,59 @@ */ class TreeToolbarSearchCategoriesCore extends TreeToolbarButtonCore implements - ITreeToolbarButtonCore + ITreeToolbarButtonCore { - protected $_template = 'tree_toolbar_search.tpl'; + protected $_template = 'tree_toolbar_search.tpl'; - public function __construct($label, $id, $name = null, $class = null) - { - parent::__construct($label); + public function __construct($label, $id, $name = null, $class = null) + { + parent::__construct($label); - $this->setId($id); - $this->setName($name); - $this->setClass($class); - } + $this->setId($id); + $this->setName($name); + $this->setClass($class); + } - public function render() - { - if ($this->hasAttribute('data')) - $this->setAttribute('typeahead_source', - $this->_renderData($this->getAttribute('data'))); + public function render() + { + if ($this->hasAttribute('data')) { + $this->setAttribute('typeahead_source', + $this->_renderData($this->getAttribute('data'))); + } - $admin_webpath = str_ireplace(_PS_CORE_DIR_, '', _PS_ADMIN_DIR_); - $admin_webpath = preg_replace('/^'.preg_quote(DIRECTORY_SEPARATOR, '/').'/', '', $admin_webpath); - $bo_theme = ((Validate::isLoadedObject($this->getContext()->employee) - && $this->getContext()->employee->bo_theme) ? $this->getContext()->employee->bo_theme : 'default'); + $admin_webpath = str_ireplace(_PS_CORE_DIR_, '', _PS_ADMIN_DIR_); + $admin_webpath = preg_replace('/^'.preg_quote(DIRECTORY_SEPARATOR, '/').'/', '', $admin_webpath); + $bo_theme = ((Validate::isLoadedObject($this->getContext()->employee) + && $this->getContext()->employee->bo_theme) ? $this->getContext()->employee->bo_theme : 'default'); - if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR.'template')) - $bo_theme = 'default'; + if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR.'template')) { + $bo_theme = 'default'; + } - if ($this->getContext()->controller->ajax) - $html = '<script type="text/javascript" src="'.__PS_BASE_URI__.$admin_webpath.'/themes/'.$bo_theme.'/js/vendor/typeahead.min.js"></script>'; - else - $this->getContext()->controller->addJs(__PS_BASE_URI__.$admin_webpath.'/themes/'.$bo_theme.'/js/vendor/typeahead.min.js'); + if ($this->getContext()->controller->ajax) { + $html = '<script type="text/javascript" src="'.__PS_BASE_URI__.$admin_webpath.'/themes/'.$bo_theme.'/js/vendor/typeahead.min.js"></script>'; + } else { + $this->getContext()->controller->addJs(__PS_BASE_URI__.$admin_webpath.'/themes/'.$bo_theme.'/js/vendor/typeahead.min.js'); + } - return (isset($html) ? $html : '').parent::render(); - } + return (isset($html) ? $html : '').parent::render(); + } - private function _renderData($data) - { - if (!is_array($data) && !$data instanceof Traversable) - throw new PrestaShopException('Data value must be a traversable array'); + private function _renderData($data) + { + if (!is_array($data) && !$data instanceof Traversable) { + throw new PrestaShopException('Data value must be a traversable array'); + } - $html = ''; + $html = ''; - foreach ($data as $item) - { - $html .= Tools::jsonEncode($item).','; - if (array_key_exists('children', $item) && !empty($item['children'])) - $html .= $this->_renderData($item['children']); - } + foreach ($data as $item) { + $html .= Tools::jsonEncode($item).','; + if (array_key_exists('children', $item) && !empty($item['children'])) { + $html .= $this->_renderData($item['children']); + } + } - return $html; - } -} \ No newline at end of file + return $html; + } +} diff --git a/classes/tree/index.php b/classes/tree/index.php index c642967a..91fa49fb 100644 --- a/classes/tree/index.php +++ b/classes/tree/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/classes/webservice/WebserviceException.php b/classes/webservice/WebserviceException.php index 8f4fc68f..d85c5719 100644 --- a/classes/webservice/WebserviceException.php +++ b/classes/webservice/WebserviceException.php @@ -26,57 +26,57 @@ class WebserviceExceptionCore extends Exception { - protected $status; - protected $wrong_value; - protected $available_values; - protected $type; + protected $status; + protected $wrong_value; + protected $available_values; + protected $type; - const SIMPLE = 0; - const DID_YOU_MEAN = 1; + const SIMPLE = 0; + const DID_YOU_MEAN = 1; - public function __construct($message, $code) - { - $exception_code = $code; - if (is_array($code)) - { - $exception_code = $code[0]; - $this->setStatus($code[1]); - } - parent::__construct($message, $exception_code); - $this->type = self::SIMPLE; - } - public function getType() - { - return $this->type; - } - public function setType($type) - { - $this->type = $type; - return $this; - } - public function setStatus($status) - { - if (Validate::isInt($status)) - $this->status = $status; - return $this; - } - public function getStatus() - { - return $this->status; - } - public function getWrongValue() - { - return $this->wrong_value; - } - public function setDidYouMean($wrong_value, $available_values) - { - $this->type = self::DID_YOU_MEAN; - $this->wrong_value = $wrong_value; - $this->available_values = $available_values; - return $this; - } - public function getAvailableValues() - { - return $this->available_values; - } -} \ No newline at end of file + public function __construct($message, $code) + { + $exception_code = $code; + if (is_array($code)) { + $exception_code = $code[0]; + $this->setStatus($code[1]); + } + parent::__construct($message, $exception_code); + $this->type = self::SIMPLE; + } + public function getType() + { + return $this->type; + } + public function setType($type) + { + $this->type = $type; + return $this; + } + public function setStatus($status) + { + if (Validate::isInt($status)) { + $this->status = $status; + } + return $this; + } + public function getStatus() + { + return $this->status; + } + public function getWrongValue() + { + return $this->wrong_value; + } + public function setDidYouMean($wrong_value, $available_values) + { + $this->type = self::DID_YOU_MEAN; + $this->wrong_value = $wrong_value; + $this->available_values = $available_values; + return $this; + } + public function getAvailableValues() + { + return $this->available_values; + } +} diff --git a/classes/webservice/WebserviceKey.php b/classes/webservice/WebserviceKey.php index 6d1f0a38..172700dd 100644 --- a/classes/webservice/WebserviceKey.php +++ b/classes/webservice/WebserviceKey.php @@ -26,111 +26,119 @@ class WebserviceKeyCore extends ObjectModel { - /** @var string Key */ - public $key; + /** @var string Key */ + public $key; - /** @var bool Webservice Account statuts */ - public $active = true; + /** @var bool Webservice Account statuts */ + public $active = true; - /** @var string Webservice Account description */ - public $description; + /** @var string Webservice Account description */ + public $description; - /** - * @see ObjectModel::$definition - */ - public static $definition = array( - 'table' => 'webservice_account', - 'primary' => 'id_webservice_account', - 'fields' => array( - 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), - 'key' => array('type' => self::TYPE_STRING, 'required' => true, 'size' => 32), - 'description' => array('type' => self::TYPE_STRING), - ), - ); + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'webservice_account', + 'primary' => 'id_webservice_account', + 'fields' => array( + 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), + 'key' => array('type' => self::TYPE_STRING, 'required' => true, 'size' => 32), + 'description' => array('type' => self::TYPE_STRING), + ), + ); - public function add($autodate = true, $nullValues = false) - { - if (WebserviceKey::keyExists($this->key)) - return false; - return parent::add($autodate = true, $nullValues = false); - } + public function add($autodate = true, $nullValues = false) + { + if (WebserviceKey::keyExists($this->key)) { + return false; + } + return parent::add($autodate = true, $nullValues = false); + } - public static function keyExists($key) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function keyExists($key) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `key` FROM '._DB_PREFIX_.'webservice_account WHERE `key` = "'.pSQL($key).'"'); - } + } - public function delete() - { - return (parent::delete() && ($this->deleteAssociations() !== false)); - } + public function delete() + { + return (parent::delete() && ($this->deleteAssociations() !== false)); + } - public function deleteAssociations() - { - return Db::getInstance()->delete('webservice_permission', 'id_webservice_account = '.(int)$this->id); - } + public function deleteAssociations() + { + return Db::getInstance()->delete('webservice_permission', 'id_webservice_account = '.(int)$this->id); + } - public static function getPermissionForAccount($auth_key) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getPermissionForAccount($auth_key) + { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT p.* FROM `'._DB_PREFIX_.'webservice_permission` p LEFT JOIN `'._DB_PREFIX_.'webservice_account` a ON (a.id_webservice_account = p.id_webservice_account) WHERE a.key = \''.pSQL($auth_key).'\' '); - $permissions = array(); - if ($result) - foreach ($result as $row) - $permissions[$row['resource']][] = $row['method']; - return $permissions; - } + $permissions = array(); + if ($result) { + foreach ($result as $row) { + $permissions[$row['resource']][] = $row['method']; + } + } + return $permissions; + } - public static function isKeyActive($auth_key) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function isKeyActive($auth_key) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT active FROM `'._DB_PREFIX_.'webservice_account` WHERE `key` = "'.pSQL($auth_key).'"'); - } + } - public static function getClassFromKey($auth_key) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getClassFromKey($auth_key) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT class_name FROM `'._DB_PREFIX_.'webservice_account` WHERE `key` = "'.pSQL($auth_key).'"'); - } + } - public static function setPermissionForAccount($id_account, $permissions_to_set) - { - $ok = true; - $sql = 'DELETE FROM `'._DB_PREFIX_.'webservice_permission` WHERE `id_webservice_account` = '.(int)$id_account; - if (!Db::getInstance()->execute($sql)) - $ok = false; - if (isset($permissions_to_set)) - { - $permissions = array(); - $resources = WebserviceRequest::getResources(); - $methods = array('GET', 'PUT', 'POST', 'DELETE', 'HEAD'); - foreach ($permissions_to_set as $resource_name => $resource_methods) - if (in_array($resource_name, array_keys($resources))) - foreach (array_keys($resource_methods) as $method_name) - if (in_array($method_name, $methods)) - $permissions[] = array($method_name, $resource_name); - $account = new WebserviceKey($id_account); - if ($account->deleteAssociations() && $permissions) - { - $sql = 'INSERT INTO `'._DB_PREFIX_.'webservice_permission` (`id_webservice_permission` ,`resource` ,`method` ,`id_webservice_account`) VALUES '; - foreach ($permissions as $permission) - $sql .= '(NULL , \''.pSQL($permission[1]).'\', \''.pSQL($permission[0]).'\', '.(int)$id_account.'), '; - $sql = rtrim($sql, ', '); - if (!Db::getInstance()->execute($sql)) - $ok = false; - } - } - return $ok; - } + public static function setPermissionForAccount($id_account, $permissions_to_set) + { + $ok = true; + $sql = 'DELETE FROM `'._DB_PREFIX_.'webservice_permission` WHERE `id_webservice_account` = '.(int)$id_account; + if (!Db::getInstance()->execute($sql)) { + $ok = false; + } + if (isset($permissions_to_set)) { + $permissions = array(); + $resources = WebserviceRequest::getResources(); + $methods = array('GET', 'PUT', 'POST', 'DELETE', 'HEAD'); + foreach ($permissions_to_set as $resource_name => $resource_methods) { + if (in_array($resource_name, array_keys($resources))) { + foreach (array_keys($resource_methods) as $method_name) { + if (in_array($method_name, $methods)) { + $permissions[] = array($method_name, $resource_name); + } + } + } + } + $account = new WebserviceKey($id_account); + if ($account->deleteAssociations() && $permissions) { + $sql = 'INSERT INTO `'._DB_PREFIX_.'webservice_permission` (`id_webservice_permission` ,`resource` ,`method` ,`id_webservice_account`) VALUES '; + foreach ($permissions as $permission) { + $sql .= '(NULL , \''.pSQL($permission[1]).'\', \''.pSQL($permission[0]).'\', '.(int)$id_account.'), '; + } + $sql = rtrim($sql, ', '); + if (!Db::getInstance()->execute($sql)) { + $ok = false; + } + } + } + return $ok; + } } diff --git a/classes/webservice/WebserviceOutputBuilder.php b/classes/webservice/WebserviceOutputBuilder.php index 2c69600b..a25c2beb 100644 --- a/classes/webservice/WebserviceOutputBuilder.php +++ b/classes/webservice/WebserviceOutputBuilder.php @@ -29,784 +29,789 @@ */ class WebserviceOutputBuilderCore { - /** - * @var int constant - */ - const VIEW_LIST = 1; - const VIEW_DETAILS = 2; - - protected $wsUrl; - protected $output; - - /** @var WebserviceOutputInterface|WebserviceOutputXML|WebserviceOutputJSON */ - public $objectRender; - protected $wsResource; - protected $depth = 0; - protected $schemaToDisplay; - protected $fieldsToDisplay; - protected $specificFields = array(); - protected $virtualFields = array(); - protected $statusInt; - protected $wsParamOverrides; - - protected static $_cache_ws_parameters = array(); - - /* Header properties */ - protected $headerParams = array( - 'Access-Time' => 0, - 'X-Powered-By' => 0, - 'PSWS-Version' => 0, - 'Content-Type' => 0, - ); - - /** - * @var string Status header sent at return - */ - protected $status; - - public function __construct($ws_url) - { - $this->statusInt = 200; - $this->status = $_SERVER['SERVER_PROTOCOL'].' 200 OK'; - $this->wsUrl = $ws_url; - $this->wsParamOverrides = array(); - } - - /** - * Set the render object for set the output format. - * Set the Content-type for the http header. - * - * @param WebserviceOutputInterface $obj_render - * @throw WebserviceException if the object render is not an instance of WebserviceOutputInterface - * - * @return WebserviceOutputBuilder - * @throws WebserviceException - */ - public function setObjectRender(WebserviceOutputInterface $obj_render) - { - if (!$obj_render instanceof WebserviceOutputInterface) - throw new WebserviceException('Obj_render param must be an WebserviceOutputInterface object type', array(83, 500)); - - $this->objectRender = $obj_render; - $this->objectRender->setWsUrl($this->wsUrl); - if ($this->objectRender->getContentType()) - $this->setHeaderParams('Content-Type', $this->objectRender->getContentType()); - return $this; - } - - /** - * getter - * @return WebserviceOutputInterface - */ - public function getObjectRender() - { - return $this->objectRender; - } - - /** - * Need to have the resource list to get the class name for an entity, - * To build - * - * @param array $resources - * - * @return WebserviceOutputBuilder - */ - public function setWsResources($resources) - { - $this->wsResource = $resources; - return $this; - } - - /** - * This method return an array with each http header params for a content. - * This check each required params. - * - * If this method is overrided don't forget to check required specific params (for xml etc...) - * - * @return array - */ - public function buildHeader() - { - $return = array(); - $return[] = $this->status; - foreach ($this->headerParams as $key => $param) - $return[] = trim($key).': '.$param; - return $return; - } - - /** - * @param string $key The normalized key expected for an http response - * @param string $value - * - * @return WebserviceOutputBuilder - * @throws WebserviceException If the key or the value are corrupted (use Validate::isCleanHtml method) - */ - public function setHeaderParams($key, $value) - { - if (!Validate::isCleanHtml($key) || !Validate::isCleanHtml($value)) - throw new WebserviceException('the key or your value is corrupted.', array(94, 500)); - $this->headerParams[$key] = $value; - return $this; - } - - /** - * @param null|string $key if null get all header params otherwise the params specified by the key - * @throw WebserviceException if the key is corrupted (use Validate::isCleanHtml method) - * @throw WebserviceException if the asked key does'nt exists. - * @return array|string - */ - public function getHeaderParams($key = null) - { - $return = ''; - - if (!is_null($key)) - { - if (!Validate::isCleanHtml($key)) - throw new WebserviceException('the key you write is a corrupted text.', array(95, 500)); - if (!array_key_exists($key, $this->headerParams)) - throw new WebserviceException(sprintf('The key %s does\'nt exist', $key), array(96, 500)); - $return = $this->headerParams[$key]; - } - else - $return = $this->headerParams; - - return $return; - } - - /** - * Delete all Header parameters previously set. - * - * @return WebserviceOutputBuilder - */ - public function resetHeaderParams() - { - $this->headerParams = array(); - return $this; - } - - /** - * @return string the normalized status for http request - */ - public function getStatus() - { - return $this->status; - } - - public function getStatusInt() - { - return $this->statusInt; - } - /** - * Set the return header status - * - * @param int $num the Http status code - * @return void - */ - public function setStatus($num) - { - $this->statusInt = (int)$num; - switch ($num) - { - case 200 : - $this->status = $_SERVER['SERVER_PROTOCOL'].' 200 OK'; - break; - case 201 : - $this->status = $_SERVER['SERVER_PROTOCOL'].' 201 Created'; - break; - case 204 : - $this->status = $_SERVER['SERVER_PROTOCOL'].' 204 No Content'; - break; - case 304 : - $this->status = $_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'; - break; - case 400 : - $this->status = $_SERVER['SERVER_PROTOCOL'].' 400 Bad Request'; - break; - case 401 : - $this->status = $_SERVER['SERVER_PROTOCOL'].' 401 Unauthorized'; - break; - case 403 : - $this->status = $_SERVER['SERVER_PROTOCOL'].' 403 Forbidden'; - break; - case 404 : - $this->status = $_SERVER['SERVER_PROTOCOL'].' 404 Not Found'; - break; - case 405 : - $this->status = $_SERVER['SERVER_PROTOCOL'].' 405 Method Not Allowed'; - break; - case 500 : - $this->status = $_SERVER['SERVER_PROTOCOL'].' 500 Internal Server Error'; - break; - case 501 : - $this->status = $_SERVER['SERVER_PROTOCOL'].' 501 Not Implemented'; - break; - case 503 : - $this->status = $_SERVER['SERVER_PROTOCOL'].' 503 Service Unavailable'; - break; - } - } - - /** - * Build errors output using an error array - * - * @param array $errors - * @return string output in the format specified by WebserviceOutputBuilder::objectRender - */ - public function getErrors($errors) - { - if (!empty($errors)) - { - if (isset($this->objectRender)) - { - $str_output = $this->objectRender->renderErrorsHeader(); - foreach ($errors as $error) - { - if (is_array($error)) - $str_output .= $this->objectRender->renderErrors($error[1], $error[0]); - else - $str_output .= $this->objectRender->renderErrors($error); - } - $str_output .= $this->objectRender->renderErrorsFooter(); - $str_output = $this->objectRender->overrideContent($str_output); - } - else - $str_output = '<pre>'.print_r($errors, true).'</pre>'; - } - return $str_output; - } - - /** - * Build the resource list in the output format specified by WebserviceOutputBuilder::objectRender - * @param $key_permissions - * @return string - */ - public function getResourcesList($key_permissions) - { - if (is_null($this->wsResource)) - throw new WebserviceException ('You must set web service resource for get the resources list.', array(82, 500)); - $output = ''; - $more_attr = array('shopName' => htmlspecialchars(Configuration::get('PS_SHOP_NAME'))); - $output .= $this->objectRender->renderNodeHeader('api', array(), $more_attr); - foreach ($this->wsResource as $resourceName => $resource) - { - if (in_array($resourceName, array_keys($key_permissions))) - { - $more_attr = array( - 'xlink_resource' => $this->wsUrl.$resourceName, - 'get' => (in_array('GET', $key_permissions[$resourceName]) ? 'true' : 'false'), - 'put' => (in_array('PUT', $key_permissions[$resourceName]) ? 'true' : 'false'), - 'post' => (in_array('POST', $key_permissions[$resourceName]) ? 'true' : 'false'), - 'delete' => (in_array('DELETE', $key_permissions[$resourceName]) ? 'true' : 'false'), - 'head' => (in_array('HEAD', $key_permissions[$resourceName]) ? 'true' : 'false'), - ); - $output .= $this->objectRender->renderNodeHeader($resourceName, array(), $more_attr); - - $output .= $this->objectRender->renderNodeHeader('description', array(), $more_attr); - $output .= $resource['description']; - $output .= $this->objectRender->renderNodeFooter('description', array()); - - if (!isset($resource['specific_management']) || !$resource['specific_management']) - { - $more_attr_schema = array( - 'xlink_resource' => $this->wsUrl.$resourceName.'?schema=blank', - 'type' => 'blank', - ); - $output .= $this->objectRender->renderNodeHeader('schema', array(), $more_attr_schema, false); - $more_attr_schema = array( - 'xlink_resource' => $this->wsUrl.$resourceName.'?schema=synopsis', - 'type' => 'synopsis', - ); - $output .= $this->objectRender->renderNodeHeader('schema', array(), $more_attr_schema, false); - } - $output .= $this->objectRender->renderNodeFooter($resourceName, array()); - } - } - $output .= $this->objectRender->renderNodeFooter('api', array()); - $output = $this->objectRender->overrideContent($output); - return $output; - } - - public function registerOverrideWSParameters($wsrObject, $method) - { - $this->wsParamOverrides[] = array('object' => $wsrObject, 'method' => $method); - } - - /** - * Method is used for each content type - * Different content types are : - * - list of entities, - * - tree diagram of entity details (full or minimum), - * - schema (synopsis & blank), - * - * @param array $objects each object created by entity asked - * @see WebserviceOutputBuilder::executeEntityGetAndHead - * @param null|string $schema_to_display if null display the entities list or entity details. - * @param string|array $fields_to_display the fields allow for the output - * @param int $depth depth for the tree diagram output. - * @param int $type_of_view use the 2 constants WebserviceOutputBuilder::VIEW_LIST WebserviceOutputBuilder::VIEW_DETAILS - * @return string in the output format specified by WebserviceOutputBuilder::objectRender - */ - public function getContent($objects, $schema_to_display = null, $fields_to_display = 'minimum', $depth = 0, $type_of_view = self::VIEW_LIST, $override = true) - { - $this->fieldsToDisplay = $fields_to_display; - $this->depth = $depth; - $output = ''; - - if ($schema_to_display != null) - { - $this->schemaToDisplay = $schema_to_display; - $this->objectRender->setSchemaToDisplay($this->schemaToDisplay); - - // If a shema is asked the view must be an details type - $type_of_view = self::VIEW_DETAILS; - } - - $class = get_class($objects['empty']); - if (!isset(WebserviceOutputBuilder::$_cache_ws_parameters[$class])) - WebserviceOutputBuilder::$_cache_ws_parameters[$class] = $objects['empty']->getWebserviceParameters(); - $ws_params = WebserviceOutputBuilder::$_cache_ws_parameters[$class]; - - foreach ($this->wsParamOverrides as $p) - { - $object = $p['object']; - $ws_params = $object->{$p['method']}($ws_params); - } - - // If a list is asked, need to wrap with a plural node - if ($type_of_view === self::VIEW_LIST) - $output .= $this->setIndent($depth).$this->objectRender->renderNodeHeader($ws_params['objectsNodeName'], $ws_params); - - if (is_null($this->schemaToDisplay)) - { - foreach ($objects as $key => $object) - { - if ($key !== 'empty') - { - if ($this->fieldsToDisplay === 'minimum') - $output .= $this->renderEntityMinimum($object, $depth); - else - $output .= $this->renderEntity($object, $depth); - } - } - } - else - $output .= $this->renderSchema($objects['empty'], $ws_params); - - // If a list is asked, need to wrap with a plural node - if ($type_of_view === self::VIEW_LIST) - $output .= $this->setIndent($depth).$this->objectRender->renderNodeFooter($ws_params['objectsNodeName'], $ws_params); - - if ($override) - $output = $this->objectRender->overrideContent($output); - return $output; - } - - /** - * Create the tree diagram with no details - * - * @param ObjectModel $object create by the entity - * @param int $depth the depth for the tree diagram - * @return string - */ - public function renderEntityMinimum($object, $depth) - { - $class = get_class($object); - if (!isset(WebserviceOutputBuilder::$_cache_ws_parameters[$class])) - WebserviceOutputBuilder::$_cache_ws_parameters[$class] = $object->getWebserviceParameters(); - $ws_params = WebserviceOutputBuilder::$_cache_ws_parameters[$class]; - - $more_attr['id'] = $object->id; - $more_attr['xlink_resource'] = $this->wsUrl.$ws_params['objectsNodeName'].'/'.$object->id; - $output = $this->setIndent($depth).$this->objectRender->renderNodeHeader($ws_params['objectNodeName'], $ws_params, $more_attr, false); - return $output; - } - - /** - * Build a schema blank or synopsis - * - * @param ObjectModel $object create by the entity - * @param array $ws_params webserviceParams from the entity - * @return string - */ - protected function renderSchema($object, $ws_params) - { - $output = $this->objectRender->renderNodeHeader($ws_params['objectNodeName'], $ws_params); - foreach ($ws_params['fields'] as $field_name => $field) - $output .= $this->renderField($object, $ws_params, $field_name, $field, 0); - if (isset($ws_params['associations']) && count($ws_params['associations']) > 0) - { - $this->fieldsToDisplay = 'full'; - $output .= $this->renderAssociations($object, 0, $ws_params['associations'], $ws_params); - } - $output .= $this->objectRender->renderNodeFooter($ws_params['objectNodeName'], $ws_params); - return $output; - } - - /** - * Build the entity detail. - * - * @param ObjectModel $object create by the entity - * @param int $depth the depth for the tree diagram - * @return string - */ - public function renderEntity($object, $depth) - { - $output = ''; - - $class = get_class($object); - if (!isset(WebserviceOutputBuilder::$_cache_ws_parameters[$class])) - WebserviceOutputBuilder::$_cache_ws_parameters[$class] = $object->getWebserviceParameters(); - $ws_params = WebserviceOutputBuilder::$_cache_ws_parameters[$class]; - - foreach ($this->wsParamOverrides as $p) - { - $o = $p['object']; - $ws_params = $o->{$p['method']}($ws_params); - } - $output .= $this->setIndent($depth).$this->objectRender->renderNodeHeader($ws_params['objectNodeName'], $ws_params); - - if ($object->id != 0) - { - // This to add virtual Fields for a particular entity. - $virtual_fields = $this->addVirtualFields($ws_params['objectsNodeName'], $object); - if (!empty($virtual_fields)) - $ws_params['fields'] = array_merge($ws_params['fields'], $virtual_fields); - - foreach ($ws_params['fields'] as $field_name => $field) - { - if ($this->fieldsToDisplay === 'full' || array_key_exists($field_name, $this->fieldsToDisplay)) - { - $field['object_id'] = $object->id; - $field['entity_name'] = $ws_params['objectNodeName']; - $field['entities_name'] = $ws_params['objectsNodeName']; - $output .= $this->renderField($object, $ws_params, $field_name, $field, $depth); - } - } - } - $subexists = false; - if (is_array($this->fieldsToDisplay)) - foreach ($this->fieldsToDisplay as $fields) - if (is_array($fields)) - $subexists = true; - - if (isset($ws_params['associations']) - && ($this->fieldsToDisplay == 'full' - || $subexists)) - $output .= $this->renderAssociations($object, $depth, $ws_params['associations'], $ws_params); - - $output .= $this->setIndent($depth).$this->objectRender->renderNodeFooter($ws_params['objectNodeName'], $ws_params); - return $output; - } - - /** - * Build a field and use recursivity depend on the depth parameter. - * - * @param ObjectModel $object create by the entity - * @param array $ws_params webserviceParams from the entity - * @param string $field_name - * @param array $field - * @param int $depth - * @return string - */ - protected function renderField($object, $ws_params, $field_name, $field, $depth) - { - $output = ''; - $show_field = true; - - if (isset($ws_params['hidden_fields']) && in_array($field_name, $ws_params['hidden_fields'])) - return; - - if ($this->schemaToDisplay === 'synopsis') - { - $field['synopsis_details'] = $this->getSynopsisDetails($field); - if ($field_name === 'id') - $show_field = false; - } - if ($this->schemaToDisplay === 'blank') - if (isset($field['setter']) && !$field['setter']) - $show_field = false; - - // don't set any value for a schema - if (isset($field['synopsis_details']) || $this->schemaToDisplay === 'blank') - { - $field['value'] = ''; - if (isset($field['xlink_resource'])) - unset($field['xlink_resource']); - } - elseif (isset($field['getter']) && $object != null && method_exists($object, $field['getter'])) - $field['value'] = $object->$field['getter'](); - elseif (!isset($field['value'])) - $field['value'] = $object->$field_name; - - // this apply specific function for a particular field on a choosen entity - $field = $this->overrideSpecificField($ws_params['objectsNodeName'], $field_name, $field, $object, $ws_params); - - // don't display informations for a not existant id - if (substr($field['sqlId'], 0, 3) == 'id_' && !$field['value']) - { - if ($field['value'] === null) - $field['value'] = ''; - // delete the xlink except for schemas - if (isset($field['xlink_resource']) && is_null($this->schemaToDisplay)) - unset($field['xlink_resource']); - } - // set "id" for each node name which display the id of the entity - if ($field_name === 'id') - $field['sqlId'] = 'id'; - - // don't display the node id for a synopsis schema - if ($show_field) - $output .= $this->setIndent($depth - 1).$this->objectRender->renderField($field); - return $output; - } - - /** - * - * - * @param $object - * @param $depth - * @param $associations - * @param $ws_params - * @return string - */ - protected function renderAssociations($object, $depth, $associations, $ws_params) - { - $output = $this->objectRender->renderAssociationWrapperHeader(); - foreach ($associations as $assoc_name => $association) - { - if ($this->fieldsToDisplay == 'full' || is_array($this->fieldsToDisplay) && array_key_exists($assoc_name, $this->fieldsToDisplay)) - { - $getter = $association['getter']; - $objects_assoc = array(); - - $fields_assoc = array(); - if (isset($association['fields'])) - $fields_assoc = $association['fields']; - - $parent_details = array( - 'object_id' => $object->id, - 'entity_name' => $ws_params['objectNodeName'], - 'entities_name' => $ws_params['objectsNodeName'], - ); - - if (is_array($getter)) - { - $association_resources = call_user_func($getter, $object); - if (is_array($association_resources) && !empty($association_resources)) - foreach ($association_resources as $association_resource) - $objects_assoc[] = $association_resource; - } - else - { - if (method_exists($object, $getter) && is_null($this->schemaToDisplay)) - { - $association_resources = $object->$getter(); - if (is_array($association_resources) && !empty($association_resources)) - foreach ($association_resources as $association_resource) - $objects_assoc[] = $association_resource; - } - else - $objects_assoc[] = ''; - } - - $class_name = null; - if (isset($this->wsResource[$assoc_name]['class']) && class_exists($this->wsResource[$assoc_name]['class'], true)) - $class_name = $this->wsResource[$assoc_name]['class']; - $output_details = ''; - foreach ($objects_assoc as $object_assoc) - { - if ($depth == 0 || $class_name === null) - { - $value = null; - if (!empty($object_assoc)) - $value = $object_assoc; - if (empty($fields_assoc)) - $fields_assoc = array(array('id' => $value['id'])); - $output_details .= $this->renderFlatAssociation($object, $depth, $assoc_name, $association['resource'], $fields_assoc, $value, $parent_details); - } - else - { - foreach ($object_assoc as $id) - { - if ($class_name !== null) - { - $child_object = new $class_name($id); - $output_details .= $this->renderEntity($child_object, ($depth - 2 ? 0 : $depth - 2)); - } - } - } - } - if ($output_details != '') - { - $output .= $this->setIndent($depth).$this->objectRender->renderAssociationHeader($object, $ws_params, $assoc_name); - $output .= $output_details; - $output .= $this->setIndent($depth).$this->objectRender->renderAssociationFooter($object, $ws_params, $assoc_name); - } - else - $output .= $this->setIndent($depth).$this->objectRender->renderAssociationHeader($object, $ws_params, $assoc_name, true); - } - } - $output .= $this->objectRender->renderAssociationWrapperFooter(); - return $output; - } - - protected function renderFlatAssociation($object, $depth, $assoc_name, $resource_name, $fields_assoc, $object_assoc, $parent_details) - { - $output = ''; - $more_attr = array(); - if (isset($this->wsResource[$assoc_name]) && is_null($this->schemaToDisplay)) - { - if ($assoc_name == 'images') - { - if ($parent_details['entities_name'] == 'combinations') - $more_attr['xlink_resource'] = $this->wsUrl.$assoc_name.'/products/'.$object->id_product.'/'.$object_assoc['id']; - else - $more_attr['xlink_resource'] = $this->wsUrl.$assoc_name.'/'.$parent_details['entities_name'].'/'.$parent_details['object_id'].'/'.$object_assoc['id']; - } - else - $more_attr['xlink_resource'] = $this->wsUrl.$assoc_name.'/'.$object_assoc['id']; - } - $output .= $this->setIndent($depth - 1).$this->objectRender->renderNodeHeader($resource_name, array(), $more_attr); - - foreach ($fields_assoc as $field_name => $field) - { - if (!is_array($this->fieldsToDisplay) || in_array($field_name, $this->fieldsToDisplay[$assoc_name])) - { - if ($field_name == 'id' && !isset($field['sqlId'])) - { - $field['sqlId'] = 'id'; - $field['value'] = $object_assoc['id']; - } - elseif (!isset($field['sqlId'])) - { - $field['sqlId'] = $field_name; - $field['value'] = $object_assoc[$field_name]; - } - $field['entities_name'] = $assoc_name; - $field['entity_name'] = $resource_name; - - if (!is_null($this->schemaToDisplay)) - $field['synopsis_details'] = $this->getSynopsisDetails($field); - $field['is_association'] = true; - $output .= $this->setIndent($depth - 1).$this->objectRender->renderField($field); - } - } - $output .= $this->setIndent($depth - 1).$this->objectRender->renderNodeFooter($resource_name, array()); - return $output; - } - - public function setIndent($depth) - { - $string = ''; - $number_of_tabs = $this->depth - $depth; - for ($i = 0; $i < $number_of_tabs; $i++) - $string .= "\t"; - return $string; - } - - public function getSynopsisDetails($field) - { - $arr_details = ''; - if (array_key_exists('required', $field) && $field['required']) - $arr_details['required'] = 'true'; - if (array_key_exists('maxSize', $field) && $field['maxSize']) - $arr_details['maxSize'] = $field['maxSize']; - if (array_key_exists('validateMethod', $field) && $field['validateMethod']) - $arr_details['format'] = $field['validateMethod']; - if (array_key_exists('setter', $field) && !$field['setter']) - $arr_details['readOnly'] = 'true'; - return $arr_details; - } - - /** - * @param string|object $object - * @param string $method - * @param $field_name - * @param $entity_name - * - * @return WebserviceOutputBuilder - * @throws Exception - * @throws WebserviceException - */ - public function setSpecificField($object, $method, $field_name, $entity_name) - { - try { - $this->validateObjectAndMethod($object, $method); - } catch (WebserviceException $e) { - throw $e; - } - - $this->specificFields[$field_name] = array('entity'=>$entity_name, 'object' => $object, 'method' => $method, 'type' => gettype($object)); - return $this; - } - protected function validateObjectAndMethod($object, $method) - { - if (is_string($object) && !class_exists($object)) - throw new WebserviceException ('The object you want to set in '.__METHOD__.' is not allowed.', array(98, 500)); - if (!method_exists($object, $method)) - throw new WebserviceException ('The method you want to set in '.__METHOD__.' is not allowed.', array(99, 500)); - } - public function getSpecificField() - { - return $this->specificFields; - } - protected function overrideSpecificField($entity_name, $field_name, $field, $entity_object, $ws_params) - { - if (array_key_exists($field_name, $this->specificFields) && $this->specificFields[$field_name]['entity'] == $entity_name) - { - if ($this->specificFields[$field_name]['type'] == 'string') - $object = new $this->specificFields[$field_name]['object'](); - elseif ($this->specificFields[$field_name]['type'] == 'object') - $object = $this->specificFields[$field_name]['object']; - - $field = $object->{$this->specificFields[$field_name]['method']}($field, $entity_object, $ws_params); - } - return $field; - } - public function setVirtualField($object, $method, $entity_name, $parameters) - { - try { - $this->validateObjectAndMethod($object, $method); - } catch (WebserviceException $e) { - throw $e; - } - - $this->virtualFields[$entity_name][] = array('parameters' => $parameters, 'object' => $object, 'method' => $method, 'type' => gettype($object)); - } - - public function getVirtualFields() - { - return $this->virtualFields; - } - - public function addVirtualFields($entity_name, $entity_object) - { - $arr_return = array(); - $virtual_fields = $this->getVirtualFields(); - if (array_key_exists($entity_name, $virtual_fields)) - { - foreach ($virtual_fields[$entity_name] as $function_infos) - { - if ($function_infos['type'] == 'string') - $object = new $function_infos['object'](); - elseif ($function_infos['type'] == 'object') - $object = $function_infos['object']; - - $return_fields = $object->{$function_infos['method']}($entity_object, $function_infos['parameters']); - foreach ($return_fields as $field_name => $value) - { - if (Validate::isConfigName($field_name)) - $arr_return[$field_name] = $value; - else - throw new WebserviceException('Name for the virtual field is not allow', array(128, 400)); - } - } - } - return $arr_return; - } - - public function setFieldsToDisplay($fields) - { - $this->fieldsToDisplay = $fields; - } + /** + * @var int constant + */ + const VIEW_LIST = 1; + const VIEW_DETAILS = 2; + + protected $wsUrl; + protected $output; + + /** @var WebserviceOutputInterface|WebserviceOutputXML|WebserviceOutputJSON */ + public $objectRender; + protected $wsResource; + protected $depth = 0; + protected $schemaToDisplay; + protected $fieldsToDisplay; + protected $specificFields = array(); + protected $virtualFields = array(); + protected $statusInt; + protected $wsParamOverrides; + + protected static $_cache_ws_parameters = array(); + + /* Header properties */ + protected $headerParams = array( + 'Access-Time' => 0, + 'X-Powered-By' => 0, + 'PSWS-Version' => 0, + 'Content-Type' => 0, + ); + + /** + * @var string Status header sent at return + */ + protected $status; + + public function __construct($ws_url) + { + $this->statusInt = 200; + $this->status = $_SERVER['SERVER_PROTOCOL'].' 200 OK'; + $this->wsUrl = $ws_url; + $this->wsParamOverrides = array(); + } + + /** + * Set the render object for set the output format. + * Set the Content-type for the http header. + * + * @param WebserviceOutputInterface $obj_render + * @throw WebserviceException if the object render is not an instance of WebserviceOutputInterface + * + * @return WebserviceOutputBuilder + * @throws WebserviceException + */ + public function setObjectRender(WebserviceOutputInterface $obj_render) + { + if (!$obj_render instanceof WebserviceOutputInterface) { + throw new WebserviceException('Obj_render param must be an WebserviceOutputInterface object type', array(83, 500)); + } + + $this->objectRender = $obj_render; + $this->objectRender->setWsUrl($this->wsUrl); + if ($this->objectRender->getContentType()) { + $this->setHeaderParams('Content-Type', $this->objectRender->getContentType()); + } + return $this; + } + + /** + * getter + * @return WebserviceOutputInterface + */ + public function getObjectRender() + { + return $this->objectRender; + } + + /** + * Need to have the resource list to get the class name for an entity, + * To build + * + * @param array $resources + * + * @return WebserviceOutputBuilder + */ + public function setWsResources($resources) + { + $this->wsResource = $resources; + return $this; + } + + /** + * This method return an array with each http header params for a content. + * This check each required params. + * + * If this method is overrided don't forget to check required specific params (for xml etc...) + * + * @return array + */ + public function buildHeader() + { + $return = array(); + $return[] = $this->status; + foreach ($this->headerParams as $key => $param) { + $return[] = trim($key).': '.$param; + } + return $return; + } + + /** + * @param string $key The normalized key expected for an http response + * @param string $value + * + * @return WebserviceOutputBuilder + * @throws WebserviceException If the key or the value are corrupted (use Validate::isCleanHtml method) + */ + public function setHeaderParams($key, $value) + { + if (!Validate::isCleanHtml($key) || !Validate::isCleanHtml($value)) { + throw new WebserviceException('the key or your value is corrupted.', array(94, 500)); + } + $this->headerParams[$key] = $value; + return $this; + } + + /** + * @param null|string $key if null get all header params otherwise the params specified by the key + * @throw WebserviceException if the key is corrupted (use Validate::isCleanHtml method) + * @throw WebserviceException if the asked key does'nt exists. + * @return array|string + */ + public function getHeaderParams($key = null) + { + $return = ''; + + if (!is_null($key)) { + if (!Validate::isCleanHtml($key)) { + throw new WebserviceException('the key you write is a corrupted text.', array(95, 500)); + } + if (!array_key_exists($key, $this->headerParams)) { + throw new WebserviceException(sprintf('The key %s does\'nt exist', $key), array(96, 500)); + } + $return = $this->headerParams[$key]; + } else { + $return = $this->headerParams; + } + + return $return; + } + + /** + * Delete all Header parameters previously set. + * + * @return WebserviceOutputBuilder + */ + public function resetHeaderParams() + { + $this->headerParams = array(); + return $this; + } + + /** + * @return string the normalized status for http request + */ + public function getStatus() + { + return $this->status; + } + + public function getStatusInt() + { + return $this->statusInt; + } + /** + * Set the return header status + * + * @param int $num the Http status code + * @return void + */ + public function setStatus($num) + { + $this->statusInt = (int)$num; + switch ($num) { + case 200 : + $this->status = $_SERVER['SERVER_PROTOCOL'].' 200 OK'; + break; + case 201 : + $this->status = $_SERVER['SERVER_PROTOCOL'].' 201 Created'; + break; + case 204 : + $this->status = $_SERVER['SERVER_PROTOCOL'].' 204 No Content'; + break; + case 304 : + $this->status = $_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'; + break; + case 400 : + $this->status = $_SERVER['SERVER_PROTOCOL'].' 400 Bad Request'; + break; + case 401 : + $this->status = $_SERVER['SERVER_PROTOCOL'].' 401 Unauthorized'; + break; + case 403 : + $this->status = $_SERVER['SERVER_PROTOCOL'].' 403 Forbidden'; + break; + case 404 : + $this->status = $_SERVER['SERVER_PROTOCOL'].' 404 Not Found'; + break; + case 405 : + $this->status = $_SERVER['SERVER_PROTOCOL'].' 405 Method Not Allowed'; + break; + case 500 : + $this->status = $_SERVER['SERVER_PROTOCOL'].' 500 Internal Server Error'; + break; + case 501 : + $this->status = $_SERVER['SERVER_PROTOCOL'].' 501 Not Implemented'; + break; + case 503 : + $this->status = $_SERVER['SERVER_PROTOCOL'].' 503 Service Unavailable'; + break; + } + } + + /** + * Build errors output using an error array + * + * @param array $errors + * @return string output in the format specified by WebserviceOutputBuilder::objectRender + */ + public function getErrors($errors) + { + if (!empty($errors)) { + if (isset($this->objectRender)) { + $str_output = $this->objectRender->renderErrorsHeader(); + foreach ($errors as $error) { + if (is_array($error)) { + $str_output .= $this->objectRender->renderErrors($error[1], $error[0]); + } else { + $str_output .= $this->objectRender->renderErrors($error); + } + } + $str_output .= $this->objectRender->renderErrorsFooter(); + $str_output = $this->objectRender->overrideContent($str_output); + } else { + $str_output = '<pre>'.print_r($errors, true).'</pre>'; + } + } + return $str_output; + } + + /** + * Build the resource list in the output format specified by WebserviceOutputBuilder::objectRender + * @param $key_permissions + * @return string + */ + public function getResourcesList($key_permissions) + { + if (is_null($this->wsResource)) { + throw new WebserviceException('You must set web service resource for get the resources list.', array(82, 500)); + } + $output = ''; + $more_attr = array('shopName' => htmlspecialchars(Configuration::get('PS_SHOP_NAME'))); + $output .= $this->objectRender->renderNodeHeader('api', array(), $more_attr); + foreach ($this->wsResource as $resourceName => $resource) { + if (in_array($resourceName, array_keys($key_permissions))) { + $more_attr = array( + 'xlink_resource' => $this->wsUrl.$resourceName, + 'get' => (in_array('GET', $key_permissions[$resourceName]) ? 'true' : 'false'), + 'put' => (in_array('PUT', $key_permissions[$resourceName]) ? 'true' : 'false'), + 'post' => (in_array('POST', $key_permissions[$resourceName]) ? 'true' : 'false'), + 'delete' => (in_array('DELETE', $key_permissions[$resourceName]) ? 'true' : 'false'), + 'head' => (in_array('HEAD', $key_permissions[$resourceName]) ? 'true' : 'false'), + ); + $output .= $this->objectRender->renderNodeHeader($resourceName, array(), $more_attr); + + $output .= $this->objectRender->renderNodeHeader('description', array(), $more_attr); + $output .= $resource['description']; + $output .= $this->objectRender->renderNodeFooter('description', array()); + + if (!isset($resource['specific_management']) || !$resource['specific_management']) { + $more_attr_schema = array( + 'xlink_resource' => $this->wsUrl.$resourceName.'?schema=blank', + 'type' => 'blank', + ); + $output .= $this->objectRender->renderNodeHeader('schema', array(), $more_attr_schema, false); + $more_attr_schema = array( + 'xlink_resource' => $this->wsUrl.$resourceName.'?schema=synopsis', + 'type' => 'synopsis', + ); + $output .= $this->objectRender->renderNodeHeader('schema', array(), $more_attr_schema, false); + } + $output .= $this->objectRender->renderNodeFooter($resourceName, array()); + } + } + $output .= $this->objectRender->renderNodeFooter('api', array()); + $output = $this->objectRender->overrideContent($output); + return $output; + } + + public function registerOverrideWSParameters($wsrObject, $method) + { + $this->wsParamOverrides[] = array('object' => $wsrObject, 'method' => $method); + } + + /** + * Method is used for each content type + * Different content types are : + * - list of entities, + * - tree diagram of entity details (full or minimum), + * - schema (synopsis & blank), + * + * @param array $objects each object created by entity asked + * @see WebserviceOutputBuilder::executeEntityGetAndHead + * @param null|string $schema_to_display if null display the entities list or entity details. + * @param string|array $fields_to_display the fields allow for the output + * @param int $depth depth for the tree diagram output. + * @param int $type_of_view use the 2 constants WebserviceOutputBuilder::VIEW_LIST WebserviceOutputBuilder::VIEW_DETAILS + * @return string in the output format specified by WebserviceOutputBuilder::objectRender + */ + public function getContent($objects, $schema_to_display = null, $fields_to_display = 'minimum', $depth = 0, $type_of_view = self::VIEW_LIST, $override = true) + { + $this->fieldsToDisplay = $fields_to_display; + $this->depth = $depth; + $output = ''; + + if ($schema_to_display != null) { + $this->schemaToDisplay = $schema_to_display; + $this->objectRender->setSchemaToDisplay($this->schemaToDisplay); + + // If a shema is asked the view must be an details type + $type_of_view = self::VIEW_DETAILS; + } + + $class = get_class($objects['empty']); + if (!isset(WebserviceOutputBuilder::$_cache_ws_parameters[$class])) { + WebserviceOutputBuilder::$_cache_ws_parameters[$class] = $objects['empty']->getWebserviceParameters(); + } + $ws_params = WebserviceOutputBuilder::$_cache_ws_parameters[$class]; + + foreach ($this->wsParamOverrides as $p) { + $object = $p['object']; + $ws_params = $object->{$p['method']}($ws_params); + } + + // If a list is asked, need to wrap with a plural node + if ($type_of_view === self::VIEW_LIST) { + $output .= $this->setIndent($depth).$this->objectRender->renderNodeHeader($ws_params['objectsNodeName'], $ws_params); + } + + if (is_null($this->schemaToDisplay)) { + foreach ($objects as $key => $object) { + if ($key !== 'empty') { + if ($this->fieldsToDisplay === 'minimum') { + $output .= $this->renderEntityMinimum($object, $depth); + } else { + $output .= $this->renderEntity($object, $depth); + } + } + } + } else { + $output .= $this->renderSchema($objects['empty'], $ws_params); + } + + // If a list is asked, need to wrap with a plural node + if ($type_of_view === self::VIEW_LIST) { + $output .= $this->setIndent($depth).$this->objectRender->renderNodeFooter($ws_params['objectsNodeName'], $ws_params); + } + + if ($override) { + $output = $this->objectRender->overrideContent($output); + } + return $output; + } + + /** + * Create the tree diagram with no details + * + * @param ObjectModel $object create by the entity + * @param int $depth the depth for the tree diagram + * @return string + */ + public function renderEntityMinimum($object, $depth) + { + $class = get_class($object); + if (!isset(WebserviceOutputBuilder::$_cache_ws_parameters[$class])) { + WebserviceOutputBuilder::$_cache_ws_parameters[$class] = $object->getWebserviceParameters(); + } + $ws_params = WebserviceOutputBuilder::$_cache_ws_parameters[$class]; + + $more_attr['id'] = $object->id; + $more_attr['xlink_resource'] = $this->wsUrl.$ws_params['objectsNodeName'].'/'.$object->id; + $output = $this->setIndent($depth).$this->objectRender->renderNodeHeader($ws_params['objectNodeName'], $ws_params, $more_attr, false); + return $output; + } + + /** + * Build a schema blank or synopsis + * + * @param ObjectModel $object create by the entity + * @param array $ws_params webserviceParams from the entity + * @return string + */ + protected function renderSchema($object, $ws_params) + { + $output = $this->objectRender->renderNodeHeader($ws_params['objectNodeName'], $ws_params); + foreach ($ws_params['fields'] as $field_name => $field) { + $output .= $this->renderField($object, $ws_params, $field_name, $field, 0); + } + if (isset($ws_params['associations']) && count($ws_params['associations']) > 0) { + $this->fieldsToDisplay = 'full'; + $output .= $this->renderAssociations($object, 0, $ws_params['associations'], $ws_params); + } + $output .= $this->objectRender->renderNodeFooter($ws_params['objectNodeName'], $ws_params); + return $output; + } + + /** + * Build the entity detail. + * + * @param ObjectModel $object create by the entity + * @param int $depth the depth for the tree diagram + * @return string + */ + public function renderEntity($object, $depth) + { + $output = ''; + + $class = get_class($object); + if (!isset(WebserviceOutputBuilder::$_cache_ws_parameters[$class])) { + WebserviceOutputBuilder::$_cache_ws_parameters[$class] = $object->getWebserviceParameters(); + } + $ws_params = WebserviceOutputBuilder::$_cache_ws_parameters[$class]; + + foreach ($this->wsParamOverrides as $p) { + $o = $p['object']; + $ws_params = $o->{$p['method']}($ws_params); + } + $output .= $this->setIndent($depth).$this->objectRender->renderNodeHeader($ws_params['objectNodeName'], $ws_params); + + if ($object->id != 0) { + // This to add virtual Fields for a particular entity. + $virtual_fields = $this->addVirtualFields($ws_params['objectsNodeName'], $object); + if (!empty($virtual_fields)) { + $ws_params['fields'] = array_merge($ws_params['fields'], $virtual_fields); + } + + foreach ($ws_params['fields'] as $field_name => $field) { + if ($this->fieldsToDisplay === 'full' || array_key_exists($field_name, $this->fieldsToDisplay)) { + $field['object_id'] = $object->id; + $field['entity_name'] = $ws_params['objectNodeName']; + $field['entities_name'] = $ws_params['objectsNodeName']; + $output .= $this->renderField($object, $ws_params, $field_name, $field, $depth); + } + } + } + $subexists = false; + if (is_array($this->fieldsToDisplay)) { + foreach ($this->fieldsToDisplay as $fields) { + if (is_array($fields)) { + $subexists = true; + } + } + } + + if (isset($ws_params['associations']) + && ($this->fieldsToDisplay == 'full' + || $subexists)) { + $output .= $this->renderAssociations($object, $depth, $ws_params['associations'], $ws_params); + } + + $output .= $this->setIndent($depth).$this->objectRender->renderNodeFooter($ws_params['objectNodeName'], $ws_params); + return $output; + } + + /** + * Build a field and use recursivity depend on the depth parameter. + * + * @param ObjectModel $object create by the entity + * @param array $ws_params webserviceParams from the entity + * @param string $field_name + * @param array $field + * @param int $depth + * @return string + */ + protected function renderField($object, $ws_params, $field_name, $field, $depth) + { + $output = ''; + $show_field = true; + + if (isset($ws_params['hidden_fields']) && in_array($field_name, $ws_params['hidden_fields'])) { + return; + } + + if ($this->schemaToDisplay === 'synopsis') { + $field['synopsis_details'] = $this->getSynopsisDetails($field); + if ($field_name === 'id') { + $show_field = false; + } + } + if ($this->schemaToDisplay === 'blank') { + if (isset($field['setter']) && !$field['setter']) { + $show_field = false; + } + } + + // don't set any value for a schema + if (isset($field['synopsis_details']) || $this->schemaToDisplay === 'blank') { + $field['value'] = ''; + if (isset($field['xlink_resource'])) { + unset($field['xlink_resource']); + } + } elseif (isset($field['getter']) && $object != null && method_exists($object, $field['getter'])) { + $field['value'] = $object->$field['getter'](); + } elseif (!isset($field['value'])) { + $field['value'] = $object->$field_name; + } + + // this apply specific function for a particular field on a choosen entity + $field = $this->overrideSpecificField($ws_params['objectsNodeName'], $field_name, $field, $object, $ws_params); + + // don't display informations for a not existant id + if (substr($field['sqlId'], 0, 3) == 'id_' && !$field['value']) { + if ($field['value'] === null) { + $field['value'] = ''; + } + // delete the xlink except for schemas + if (isset($field['xlink_resource']) && is_null($this->schemaToDisplay)) { + unset($field['xlink_resource']); + } + } + // set "id" for each node name which display the id of the entity + if ($field_name === 'id') { + $field['sqlId'] = 'id'; + } + + // don't display the node id for a synopsis schema + if ($show_field) { + $output .= $this->setIndent($depth - 1).$this->objectRender->renderField($field); + } + return $output; + } + + /** + * + * + * @param $object + * @param $depth + * @param $associations + * @param $ws_params + * @return string + */ + protected function renderAssociations($object, $depth, $associations, $ws_params) + { + $output = $this->objectRender->renderAssociationWrapperHeader(); + foreach ($associations as $assoc_name => $association) { + if ($this->fieldsToDisplay == 'full' || is_array($this->fieldsToDisplay) && array_key_exists($assoc_name, $this->fieldsToDisplay)) { + $getter = $association['getter']; + $objects_assoc = array(); + + $fields_assoc = array(); + if (isset($association['fields'])) { + $fields_assoc = $association['fields']; + } + + $parent_details = array( + 'object_id' => $object->id, + 'entity_name' => $ws_params['objectNodeName'], + 'entities_name' => $ws_params['objectsNodeName'], + ); + + if (is_array($getter)) { + $association_resources = call_user_func($getter, $object); + if (is_array($association_resources) && !empty($association_resources)) { + foreach ($association_resources as $association_resource) { + $objects_assoc[] = $association_resource; + } + } + } else { + if (method_exists($object, $getter) && is_null($this->schemaToDisplay)) { + $association_resources = $object->$getter(); + if (is_array($association_resources) && !empty($association_resources)) { + foreach ($association_resources as $association_resource) { + $objects_assoc[] = $association_resource; + } + } + } else { + $objects_assoc[] = ''; + } + } + + $class_name = null; + if (isset($this->wsResource[$assoc_name]['class']) && class_exists($this->wsResource[$assoc_name]['class'], true)) { + $class_name = $this->wsResource[$assoc_name]['class']; + } + $output_details = ''; + foreach ($objects_assoc as $object_assoc) { + if ($depth == 0 || $class_name === null) { + $value = null; + if (!empty($object_assoc)) { + $value = $object_assoc; + } + if (empty($fields_assoc)) { + $fields_assoc = array(array('id' => $value['id'])); + } + $output_details .= $this->renderFlatAssociation($object, $depth, $assoc_name, $association['resource'], $fields_assoc, $value, $parent_details); + } else { + foreach ($object_assoc as $id) { + if ($class_name !== null) { + $child_object = new $class_name($id); + $output_details .= $this->renderEntity($child_object, ($depth - 2 ? 0 : $depth - 2)); + } + } + } + } + if ($output_details != '') { + $output .= $this->setIndent($depth).$this->objectRender->renderAssociationHeader($object, $ws_params, $assoc_name); + $output .= $output_details; + $output .= $this->setIndent($depth).$this->objectRender->renderAssociationFooter($object, $ws_params, $assoc_name); + } else { + $output .= $this->setIndent($depth).$this->objectRender->renderAssociationHeader($object, $ws_params, $assoc_name, true); + } + } + } + $output .= $this->objectRender->renderAssociationWrapperFooter(); + return $output; + } + + protected function renderFlatAssociation($object, $depth, $assoc_name, $resource_name, $fields_assoc, $object_assoc, $parent_details) + { + $output = ''; + $more_attr = array(); + if (isset($this->wsResource[$assoc_name]) && is_null($this->schemaToDisplay)) { + if ($assoc_name == 'images') { + if ($parent_details['entities_name'] == 'combinations') { + $more_attr['xlink_resource'] = $this->wsUrl.$assoc_name.'/products/'.$object->id_product.'/'.$object_assoc['id']; + } else { + $more_attr['xlink_resource'] = $this->wsUrl.$assoc_name.'/'.$parent_details['entities_name'].'/'.$parent_details['object_id'].'/'.$object_assoc['id']; + } + } else { + $more_attr['xlink_resource'] = $this->wsUrl.$assoc_name.'/'.$object_assoc['id']; + } + } + $output .= $this->setIndent($depth - 1).$this->objectRender->renderNodeHeader($resource_name, array(), $more_attr); + + foreach ($fields_assoc as $field_name => $field) { + if (!is_array($this->fieldsToDisplay) || in_array($field_name, $this->fieldsToDisplay[$assoc_name])) { + if ($field_name == 'id' && !isset($field['sqlId'])) { + $field['sqlId'] = 'id'; + $field['value'] = $object_assoc['id']; + } elseif (!isset($field['sqlId'])) { + $field['sqlId'] = $field_name; + $field['value'] = $object_assoc[$field_name]; + } + $field['entities_name'] = $assoc_name; + $field['entity_name'] = $resource_name; + + if (!is_null($this->schemaToDisplay)) { + $field['synopsis_details'] = $this->getSynopsisDetails($field); + } + $field['is_association'] = true; + $output .= $this->setIndent($depth - 1).$this->objectRender->renderField($field); + } + } + $output .= $this->setIndent($depth - 1).$this->objectRender->renderNodeFooter($resource_name, array()); + return $output; + } + + public function setIndent($depth) + { + $string = ''; + $number_of_tabs = $this->depth - $depth; + for ($i = 0; $i < $number_of_tabs; $i++) { + $string .= "\t"; + } + return $string; + } + + public function getSynopsisDetails($field) + { + $arr_details = ''; + if (array_key_exists('required', $field) && $field['required']) { + $arr_details['required'] = 'true'; + } + if (array_key_exists('maxSize', $field) && $field['maxSize']) { + $arr_details['maxSize'] = $field['maxSize']; + } + if (array_key_exists('validateMethod', $field) && $field['validateMethod']) { + $arr_details['format'] = $field['validateMethod']; + } + if (array_key_exists('setter', $field) && !$field['setter']) { + $arr_details['readOnly'] = 'true'; + } + return $arr_details; + } + + /** + * @param string|object $object + * @param string $method + * @param $field_name + * @param $entity_name + * + * @return WebserviceOutputBuilder + * @throws Exception + * @throws WebserviceException + */ + public function setSpecificField($object, $method, $field_name, $entity_name) + { + try { + $this->validateObjectAndMethod($object, $method); + } catch (WebserviceException $e) { + throw $e; + } + + $this->specificFields[$field_name] = array('entity'=>$entity_name, 'object' => $object, 'method' => $method, 'type' => gettype($object)); + return $this; + } + protected function validateObjectAndMethod($object, $method) + { + if (is_string($object) && !class_exists($object)) { + throw new WebserviceException('The object you want to set in '.__METHOD__.' is not allowed.', array(98, 500)); + } + if (!method_exists($object, $method)) { + throw new WebserviceException('The method you want to set in '.__METHOD__.' is not allowed.', array(99, 500)); + } + } + public function getSpecificField() + { + return $this->specificFields; + } + protected function overrideSpecificField($entity_name, $field_name, $field, $entity_object, $ws_params) + { + if (array_key_exists($field_name, $this->specificFields) && $this->specificFields[$field_name]['entity'] == $entity_name) { + if ($this->specificFields[$field_name]['type'] == 'string') { + $object = new $this->specificFields[$field_name]['object'](); + } elseif ($this->specificFields[$field_name]['type'] == 'object') { + $object = $this->specificFields[$field_name]['object']; + } + + $field = $object->{$this->specificFields[$field_name]['method']}($field, $entity_object, $ws_params); + } + return $field; + } + public function setVirtualField($object, $method, $entity_name, $parameters) + { + try { + $this->validateObjectAndMethod($object, $method); + } catch (WebserviceException $e) { + throw $e; + } + + $this->virtualFields[$entity_name][] = array('parameters' => $parameters, 'object' => $object, 'method' => $method, 'type' => gettype($object)); + } + + public function getVirtualFields() + { + return $this->virtualFields; + } + + public function addVirtualFields($entity_name, $entity_object) + { + $arr_return = array(); + $virtual_fields = $this->getVirtualFields(); + if (array_key_exists($entity_name, $virtual_fields)) { + foreach ($virtual_fields[$entity_name] as $function_infos) { + if ($function_infos['type'] == 'string') { + $object = new $function_infos['object'](); + } elseif ($function_infos['type'] == 'object') { + $object = $function_infos['object']; + } + + $return_fields = $object->{$function_infos['method']}($entity_object, $function_infos['parameters']); + foreach ($return_fields as $field_name => $value) { + if (Validate::isConfigName($field_name)) { + $arr_return[$field_name] = $value; + } else { + throw new WebserviceException('Name for the virtual field is not allow', array(128, 400)); + } + } + } + } + return $arr_return; + } + + public function setFieldsToDisplay($fields) + { + $this->fieldsToDisplay = $fields; + } } diff --git a/classes/webservice/WebserviceOutputInterface.php b/classes/webservice/WebserviceOutputInterface.php index 0f43c00d..a9f7d07d 100644 --- a/classes/webservice/WebserviceOutputInterface.php +++ b/classes/webservice/WebserviceOutputInterface.php @@ -26,19 +26,19 @@ interface WebserviceOutputInterface { - public function __construct($languages = array()); - public function setWsUrl($url); - public function getWsUrl(); - public function getContentType(); - public function setSchemaToDisplay($schema); - public function getSchemaToDisplay(); - public function renderField($field); - public function renderNodeHeader($obj, $params, $more_attr = null); - public function renderNodeFooter($obj, $params); - public function renderAssociationHeader($obj, $params, $assoc_name); - public function renderAssociationFooter($obj, $params, $assoc_name); - public function overrideContent($content); - public function renderErrorsHeader(); - public function renderErrorsFooter(); - public function renderErrors($message, $code = null); -} \ No newline at end of file + public function __construct($languages = array()); + public function setWsUrl($url); + public function getWsUrl(); + public function getContentType(); + public function setSchemaToDisplay($schema); + public function getSchemaToDisplay(); + public function renderField($field); + public function renderNodeHeader($obj, $params, $more_attr = null); + public function renderNodeFooter($obj, $params); + public function renderAssociationHeader($obj, $params, $assoc_name); + public function renderAssociationFooter($obj, $params, $assoc_name); + public function overrideContent($content); + public function renderErrorsHeader(); + public function renderErrorsFooter(); + public function renderErrors($message, $code = null); +} diff --git a/classes/webservice/WebserviceOutputJSON.php b/classes/webservice/WebserviceOutputJSON.php index ca60b100..89b7558a 100644 --- a/classes/webservice/WebserviceOutputJSON.php +++ b/classes/webservice/WebserviceOutputJSON.php @@ -27,149 +27,180 @@ class WebserviceOutputJSON implements WebserviceOutputInterface { - public $docUrl = ''; - public $languages = array(); - protected $wsUrl; - protected $schemaToDisplay; + public $docUrl = ''; + public $languages = array(); + protected $wsUrl; + protected $schemaToDisplay; - /** - * Current entity - */ - protected $currentEntity; + /** + * Current entity + */ + protected $currentEntity; - /** - * Current association - */ - protected $currentAssociatedEntity; + /** + * Current association + */ + protected $currentAssociatedEntity; - /** - * Json content - */ - protected $content = array(); + /** + * Json content + */ + protected $content = array(); - public function __construct($languages = array()) - { - $this->languages = $languages; - } + public function __construct($languages = array()) + { + $this->languages = $languages; + } - public function setSchemaToDisplay($schema) - { - if (is_string($schema)) - $this->schemaToDisplay = $schema; - return $this; - } + public function setSchemaToDisplay($schema) + { + if (is_string($schema)) { + $this->schemaToDisplay = $schema; + } + return $this; + } - public function getSchemaToDisplay() - { - return $this->schemaToDisplay; - } + public function getSchemaToDisplay() + { + return $this->schemaToDisplay; + } - public function setWsUrl($url) - { - $this->wsUrl = $url; - return $this; - } + public function setWsUrl($url) + { + $this->wsUrl = $url; + return $this; + } - public function getWsUrl() - { - return $this->wsUrl; - } + public function getWsUrl() + { + return $this->wsUrl; + } - public function getContentType() - { - return 'application/json'; - } + public function getContentType() + { + return 'application/json'; + } - public function renderErrors($message, $code = null) - { - $this->content['errors'][] = array('code' => $code, 'message' => $message); - return ''; - } + public function renderErrors($message, $code = null) + { + $this->content['errors'][] = array('code' => $code, 'message' => $message); + return ''; + } - public function renderField($field) - { - $is_association = (isset($field['is_association']) && $field['is_association'] == true); + public function renderField($field) + { + $is_association = (isset($field['is_association']) && $field['is_association'] == true); - if (is_array($field['value'])) - { - $tmp = array(); - foreach ($this->languages as $id_lang) - $tmp[] = array('id' => $id_lang, 'value' => $field['value'][$id_lang]); - if (count($tmp) == 1) - $field['value'] = $tmp[0]['value']; - else - $field['value'] = $tmp; - } - // Case 1 : fields of the current entity (not an association) - if (!$is_association) - $this->currentEntity[$field['sqlId']] = $field['value']; - else // Case 2 : fields of an associated entity to the current one - $this->currentAssociatedEntity[] = array('name' => $field['entities_name'], 'key' => $field['sqlId'], 'value' => $field['value']); - return ''; - } + if (is_array($field['value'])) { + $tmp = array(); + foreach ($this->languages as $id_lang) { + $tmp[] = array('id' => $id_lang, 'value' => $field['value'][$id_lang]); + } + if (count($tmp) == 1) { + $field['value'] = $tmp[0]['value']; + } else { + $field['value'] = $tmp; + } + } + // Case 1 : fields of the current entity (not an association) + if (!$is_association) { + $this->currentEntity[$field['sqlId']] = $field['value']; + } else { // Case 2 : fields of an associated entity to the current one + $this->currentAssociatedEntity[] = array('name' => $field['entities_name'], 'key' => $field['sqlId'], 'value' => $field['value']); + } + return ''; + } - public function renderNodeHeader($node_name, $params, $more_attr = null, $has_child = true) - { - // api ? - static $isAPICall = false; - if ($node_name == 'api' && ($isAPICall == false)) - $isAPICall = true; - if ($isAPICall && !in_array($node_name, array('description', 'schema', 'api'))) - $this->content[] = $node_name; - if (isset($more_attr, $more_attr['id'])) - $this->content[$params['objectsNodeName']][] = array('id' => $more_attr['id']); - return ''; - } + public function renderNodeHeader($node_name, $params, $more_attr = null, $has_child = true) + { + // api ? + static $isAPICall = false; + if ($node_name == 'api' && ($isAPICall == false)) { + $isAPICall = true; + } + if ($isAPICall && !in_array($node_name, array('description', 'schema', 'api'))) { + $this->content[] = $node_name; + } + if (isset($more_attr, $more_attr['id'])) { + $this->content[$params['objectsNodeName']][] = array('id' => $more_attr['id']); + } + return ''; + } - public function getNodeName($params) - { - $node_name = ''; - if (isset($params['objectNodeName'])) - $node_name = $params['objectNodeName']; - return $node_name; - } + public function getNodeName($params) + { + $node_name = ''; + if (isset($params['objectNodeName'])) { + $node_name = $params['objectNodeName']; + } + return $node_name; + } - public function renderNodeFooter($node_name, $params) - { - if (isset($params['objectNodeName']) && $params['objectNodeName'] == $node_name) - { - if (array_key_exists('display', $_GET)) - $this->content[$params['objectsNodeName']][] = $this->currentEntity; - else - $this->content[$params['objectNodeName']] = $this->currentEntity; - $this->currentEntity = array(); - } - if (count($this->currentAssociatedEntity)) - { - $current = array(); - foreach ($this->currentAssociatedEntity as $element) - $current[$element['key']] = $element['value']; - //$this->currentEntity['associations'][$element['name']][][$element['key']] = $element['value']; - $this->currentEntity['associations'][$element['name']][] = $current; - $this->currentAssociatedEntity = array(); - } - } + public function renderNodeFooter($node_name, $params) + { + if (isset($params['objectNodeName']) && $params['objectNodeName'] == $node_name) { + if (array_key_exists('display', $_GET)) { + $this->content[$params['objectsNodeName']][] = $this->currentEntity; + } else { + $this->content[$params['objectNodeName']] = $this->currentEntity; + } + $this->currentEntity = array(); + } + if (count($this->currentAssociatedEntity)) { + $current = array(); + foreach ($this->currentAssociatedEntity as $element) { + $current[$element['key']] = $element['value']; + } + //$this->currentEntity['associations'][$element['name']][][$element['key']] = $element['value']; + $this->currentEntity['associations'][$element['name']][] = $current; + $this->currentAssociatedEntity = array(); + } + } - public function overrideContent($content) - { - $content = ''; - $content .= json_encode($this->content); - $content = preg_replace("/\\\\u([a-f0-9]{4})/e", "iconv('UCS-4LE','UTF-8',pack('V', hexdec('U$1')))", $content); - return $content; - } + public function overrideContent($content) + { + $content = ''; + $content .= json_encode($this->content); + $content = preg_replace("/\\\\u([a-f0-9]{4})/e", "iconv('UCS-4LE','UTF-8',pack('V', hexdec('U$1')))", $content); + return $content; + } - public function setLanguages($languages) - { - $this->languages = $languages; - return $this; - } + public function setLanguages($languages) + { + $this->languages = $languages; + return $this; + } - public function renderAssociationWrapperHeader() { return ''; } - public function renderAssociationWrapperFooter() { return ''; } - public function renderAssociationHeader($obj, $params, $assoc_name, $closed_tags = false) { return ''; } - public function renderAssociationFooter($obj, $params, $assoc_name) { return; } - public function renderErrorsHeader() { return ''; } - public function renderErrorsFooter() { return ''; } - public function renderAssociationField($field) { return ''; } - public function renderi18nField($field) { return ''; } + public function renderAssociationWrapperHeader() + { + return ''; + } + public function renderAssociationWrapperFooter() + { + return ''; + } + public function renderAssociationHeader($obj, $params, $assoc_name, $closed_tags = false) + { + return ''; + } + public function renderAssociationFooter($obj, $params, $assoc_name) + { + return; + } + public function renderErrorsHeader() + { + return ''; + } + public function renderErrorsFooter() + { + return ''; + } + public function renderAssociationField($field) + { + return ''; + } + public function renderi18nField($field) + { + return ''; + } } diff --git a/classes/webservice/WebserviceOutputXML.php b/classes/webservice/WebserviceOutputXML.php index 60054c9a..843e91e9 100644 --- a/classes/webservice/WebserviceOutputXML.php +++ b/classes/webservice/WebserviceOutputXML.php @@ -26,186 +26,190 @@ class WebserviceOutputXMLCore implements WebserviceOutputInterface { - public $docUrl = ''; - public $languages = array(); - protected $wsUrl; - protected $schemaToDisplay; + public $docUrl = ''; + public $languages = array(); + protected $wsUrl; + protected $schemaToDisplay; - public function setSchemaToDisplay($schema) - { - if (is_string($schema)) - $this->schemaToDisplay = $schema; - return $this; - } + public function setSchemaToDisplay($schema) + { + if (is_string($schema)) { + $this->schemaToDisplay = $schema; + } + return $this; + } - public function getSchemaToDisplay() - { - return $this->schemaToDisplay; - } + public function getSchemaToDisplay() + { + return $this->schemaToDisplay; + } - public function setWsUrl($url) - { - $this->wsUrl = $url; - return $this; - } - public function getWsUrl() - { - return $this->wsUrl; - } - public function getContentType() - { - return 'text/xml'; - } - public function __construct($languages = array()) - { - $this->languages = $languages; - } - public function setLanguages($languages) - { - $this->languages = $languages; - return $this; - } - public function renderErrorsHeader() - { - return '<errors>'."\n"; - } - public function renderErrorsFooter() - { - return '</errors>'."\n"; - } - public function renderErrors($message, $code = null) - { - $str_output = '<error>'."\n"; - if ($code !== null) - $str_output .= '<code><![CDATA['.$code.']]></code>'."\n"; - $str_output .= '<message><![CDATA['.$message.']]></message>'."\n"; - $str_output .= '</error>'."\n"; - return $str_output; - } - public function renderField($field) - { - $ret = ''; - $node_content = ''; - $ret .= '<'.$field['sqlId']; - // display i18n fields - if (isset($field['i18n']) && $field['i18n']) - { - foreach ($this->languages as $language) - { - $more_attr = ''; - if (isset($field['synopsis_details']) || (isset($field['value']) && is_array($field['value']))) - { - $more_attr .= ' xlink:href="'.$this->getWsUrl().'languages/'.$language.'"'; - if (isset($field['synopsis_details']) && $this->schemaToDisplay != 'blank') - $more_attr .= ' format="isUnsignedId" '; - } - $node_content .= '<language id="'.$language.'"'.$more_attr.'>'; - if (isset($field['value']) && is_array($field['value']) && isset($field['value'][$language])) - $node_content .= '<![CDATA['.$field['value'][$language].']]>'; - $node_content .= '</language>'; - } - } - // display not i18n fields value - else - { - if (array_key_exists('xlink_resource', $field) && $this->schemaToDisplay != 'blank') - { - if (!is_array($field['xlink_resource'])) - $ret .= ' xlink:href="'.$this->getWsUrl().$field['xlink_resource'].'/'.$field['value'].'"'; - else - $ret .= ' xlink:href="'.$this->getWsUrl().$field['xlink_resource']['resourceName'].'/'. - (isset($field['xlink_resource']['subResourceName']) ? $field['xlink_resource']['subResourceName'].'/'.$field['object_id'].'/' : '').$field['value'].'"'; - } + public function setWsUrl($url) + { + $this->wsUrl = $url; + return $this; + } + public function getWsUrl() + { + return $this->wsUrl; + } + public function getContentType() + { + return 'text/xml'; + } + public function __construct($languages = array()) + { + $this->languages = $languages; + } + public function setLanguages($languages) + { + $this->languages = $languages; + return $this; + } + public function renderErrorsHeader() + { + return '<errors>'."\n"; + } + public function renderErrorsFooter() + { + return '</errors>'."\n"; + } + public function renderErrors($message, $code = null) + { + $str_output = '<error>'."\n"; + if ($code !== null) { + $str_output .= '<code><![CDATA['.$code.']]></code>'."\n"; + } + $str_output .= '<message><![CDATA['.$message.']]></message>'."\n"; + $str_output .= '</error>'."\n"; + return $str_output; + } + public function renderField($field) + { + $ret = ''; + $node_content = ''; + $ret .= '<'.$field['sqlId']; + // display i18n fields + if (isset($field['i18n']) && $field['i18n']) { + foreach ($this->languages as $language) { + $more_attr = ''; + if (isset($field['synopsis_details']) || (isset($field['value']) && is_array($field['value']))) { + $more_attr .= ' xlink:href="'.$this->getWsUrl().'languages/'.$language.'"'; + if (isset($field['synopsis_details']) && $this->schemaToDisplay != 'blank') { + $more_attr .= ' format="isUnsignedId" '; + } + } + $node_content .= '<language id="'.$language.'"'.$more_attr.'>'; + if (isset($field['value']) && is_array($field['value']) && isset($field['value'][$language])) { + $node_content .= '<![CDATA['.$field['value'][$language].']]>'; + } + $node_content .= '</language>'; + } + } + // display not i18n fields value + else { + if (array_key_exists('xlink_resource', $field) && $this->schemaToDisplay != 'blank') { + if (!is_array($field['xlink_resource'])) { + $ret .= ' xlink:href="'.$this->getWsUrl().$field['xlink_resource'].'/'.$field['value'].'"'; + } else { + $ret .= ' xlink:href="'.$this->getWsUrl().$field['xlink_resource']['resourceName'].'/'. + (isset($field['xlink_resource']['subResourceName']) ? $field['xlink_resource']['subResourceName'].'/'.$field['object_id'].'/' : '').$field['value'].'"'; + } + } - if (isset($field['getter']) && $this->schemaToDisplay != 'blank') - $ret .= ' notFilterable="true"'; + if (isset($field['getter']) && $this->schemaToDisplay != 'blank') { + $ret .= ' notFilterable="true"'; + } - if (isset($field['setter']) && $field['setter'] == false && $this->schemaToDisplay == 'synopsis') - $ret .= ' read_only="true"'; + if (isset($field['setter']) && $field['setter'] == false && $this->schemaToDisplay == 'synopsis') { + $ret .= ' read_only="true"'; + } - if ($field['value'] != '') - $node_content .= '<![CDATA['.$field['value'].']]>'; - } + if ($field['value'] != '') { + $node_content .= '<![CDATA['.$field['value'].']]>'; + } + } - if (isset($field['encode'])) - $ret .= ' encode="'.$field['encode'].'"'; + if (isset($field['encode'])) { + $ret .= ' encode="'.$field['encode'].'"'; + } - if (isset($field['synopsis_details']) && !empty($field['synopsis_details']) && $this->schemaToDisplay !== 'blank') - { - foreach ($field['synopsis_details'] as $name => $detail) - $ret .= ' '.$name.'="'.(is_array($detail) ? implode(' ', $detail) : $detail).'"'; - } - $ret .= '>'; - $ret .= $node_content; - $ret .= '</'.$field['sqlId'].'>'."\n"; - return $ret; - } - public function renderNodeHeader($node_name, $params, $more_attr = null, $has_child = true) - { - $string_attr = ''; - if (is_array($more_attr)) - { - foreach ($more_attr as $key => $attr) - { - if ($key === 'xlink_resource') - $string_attr .= ' xlink:href="'.$attr.'"'; - else - $string_attr .= ' '.$key.'="'.$attr.'"'; - } - } - $end_tag = (!$has_child) ? '/>' : '>'; - return '<'.$node_name.$string_attr.$end_tag."\n"; - } - public function getNodeName($params) - { - $node_name = ''; - if (isset($params['objectNodeName'])) - $node_name = $params['objectNodeName']; - return $node_name; - } - public function renderNodeFooter($node_name, $params) - { - return '</'.$node_name.'>'."\n"; - } - public function overrideContent($content) - { - $xml = '<?xml version="1.0" encoding="UTF-8"?>'."\n"; - $xml .= '<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">'."\n"; - $xml .= $content; - $xml .= '</prestashop>'."\n"; - return $xml; - } - public function renderAssociationWrapperHeader() - { - return '<associations>'."\n"; - } - public function renderAssociationWrapperFooter() - { - return '</associations>'."\n"; - } - public function renderAssociationHeader($obj, $params, $assoc_name, $closed_tags = false) - { - $end_tag = ($closed_tags) ? '/>' : '>'; - $more = ''; - if ($this->schemaToDisplay != 'blank') - { - if (array_key_exists('setter', $params['associations'][$assoc_name]) && !$params['associations'][$assoc_name]['setter']) - $more .= ' readOnly="true"'; - $more .= ' nodeType="'.$params['associations'][$assoc_name]['resource'].'"'; - if (isset($params['associations'][$assoc_name]['virtual_entity']) && $params['associations'][$assoc_name]['virtual_entity']) - $more .= ' virtualEntity="true"'; - else - { - if (isset($params['associations'][$assoc_name]['api'])) - $more .= ' api="'.$params['associations'][$assoc_name]['api'].'"'; - else - $more .= ' api="'.$assoc_name.'"'; - } - } - return '<'.$assoc_name.$more.$end_tag."\n"; - } - public function renderAssociationFooter($obj, $params, $assoc_name) - { - return '</'.$assoc_name.'>'."\n"; - } + if (isset($field['synopsis_details']) && !empty($field['synopsis_details']) && $this->schemaToDisplay !== 'blank') { + foreach ($field['synopsis_details'] as $name => $detail) { + $ret .= ' '.$name.'="'.(is_array($detail) ? implode(' ', $detail) : $detail).'"'; + } + } + $ret .= '>'; + $ret .= $node_content; + $ret .= '</'.$field['sqlId'].'>'."\n"; + return $ret; + } + public function renderNodeHeader($node_name, $params, $more_attr = null, $has_child = true) + { + $string_attr = ''; + if (is_array($more_attr)) { + foreach ($more_attr as $key => $attr) { + if ($key === 'xlink_resource') { + $string_attr .= ' xlink:href="'.$attr.'"'; + } else { + $string_attr .= ' '.$key.'="'.$attr.'"'; + } + } + } + $end_tag = (!$has_child) ? '/>' : '>'; + return '<'.$node_name.$string_attr.$end_tag."\n"; + } + public function getNodeName($params) + { + $node_name = ''; + if (isset($params['objectNodeName'])) { + $node_name = $params['objectNodeName']; + } + return $node_name; + } + public function renderNodeFooter($node_name, $params) + { + return '</'.$node_name.'>'."\n"; + } + public function overrideContent($content) + { + $xml = '<?xml version="1.0" encoding="UTF-8"?>'."\n"; + $xml .= '<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">'."\n"; + $xml .= $content; + $xml .= '</prestashop>'."\n"; + return $xml; + } + public function renderAssociationWrapperHeader() + { + return '<associations>'."\n"; + } + public function renderAssociationWrapperFooter() + { + return '</associations>'."\n"; + } + public function renderAssociationHeader($obj, $params, $assoc_name, $closed_tags = false) + { + $end_tag = ($closed_tags) ? '/>' : '>'; + $more = ''; + if ($this->schemaToDisplay != 'blank') { + if (array_key_exists('setter', $params['associations'][$assoc_name]) && !$params['associations'][$assoc_name]['setter']) { + $more .= ' readOnly="true"'; + } + $more .= ' nodeType="'.$params['associations'][$assoc_name]['resource'].'"'; + if (isset($params['associations'][$assoc_name]['virtual_entity']) && $params['associations'][$assoc_name]['virtual_entity']) { + $more .= ' virtualEntity="true"'; + } else { + if (isset($params['associations'][$assoc_name]['api'])) { + $more .= ' api="'.$params['associations'][$assoc_name]['api'].'"'; + } else { + $more .= ' api="'.$assoc_name.'"'; + } + } + } + return '<'.$assoc_name.$more.$end_tag."\n"; + } + public function renderAssociationFooter($obj, $params, $assoc_name) + { + return '</'.$assoc_name.'>'."\n"; + } } diff --git a/classes/webservice/WebserviceRequest.php b/classes/webservice/WebserviceRequest.php index 0b0de571..3ef8ee72 100644 --- a/classes/webservice/WebserviceRequest.php +++ b/classes/webservice/WebserviceRequest.php @@ -26,1843 +26,1736 @@ class WebserviceRequestCore { - const HTTP_GET = 1; - const HTTP_POST = 2; - const HTTP_PUT = 4; + const HTTP_GET = 1; + const HTTP_POST = 2; + const HTTP_PUT = 4; - protected $_available_languages = null; - /** - * Errors triggered at execution - * @var array - */ - public $errors = array(); + protected $_available_languages = null; + /** + * Errors triggered at execution + * @var array + */ + public $errors = array(); - /** - * Set if return should display content or not - * @var bool - */ - protected $_outputEnabled = true; + /** + * Set if return should display content or not + * @var bool + */ + protected $_outputEnabled = true; - /** - * Set if the management is specific or if it is classic (entity management) - * @var WebserviceSpecificManagementImages|WebserviceSpecificManagementSearch|false - */ - protected $objectSpecificManagement = false; + /** + * Set if the management is specific or if it is classic (entity management) + * @var WebserviceSpecificManagementImages|WebserviceSpecificManagementSearch|false + */ + protected $objectSpecificManagement = false; - /** - * Base PrestaShop webservice URL - * @var string - */ - public $wsUrl; + /** + * Base PrestaShop webservice URL + * @var string + */ + public $wsUrl; - /** - * PrestaShop Webservice Documentation URL - * @var string - */ - protected $_docUrl = 'http://doc.prestashop.com/display/PS16/Using+the+PrestaShop+Web+Service'; + /** + * PrestaShop Webservice Documentation URL + * @var string + */ + protected $_docUrl = 'http://doc.prestashop.com/display/PS16/Using+the+PrestaShop+Web+Service'; - /** - * Set if the authentication key was checked - * @var bool - */ - protected $_authenticated = false; + /** + * Set if the authentication key was checked + * @var bool + */ + protected $_authenticated = false; - /** - * HTTP Method to support - * @var string - */ - public $method; + /** + * HTTP Method to support + * @var string + */ + public $method; - /** - * The segment of the URL - * @var array - */ - public $urlSegment = array(); + /** + * The segment of the URL + * @var array + */ + public $urlSegment = array(); - /** - * The segment list of the URL after the "api" segment - * @var array - */ - public $urlFragments = array(); + /** + * The segment list of the URL after the "api" segment + * @var array + */ + public $urlFragments = array(); - /** - * The time in microseconds of the start of the execution of the web service request - * @var int - */ - protected $_startTime = 0; + /** + * The time in microseconds of the start of the execution of the web service request + * @var int + */ + protected $_startTime = 0; - /** - * The list of each resources manageable via web service - * @var array - */ - public $resourceList; + /** + * The list of each resources manageable via web service + * @var array + */ + public $resourceList; - /** - * The configuration parameters of the current resource - * @var array - */ - public $resourceConfiguration; + /** + * The configuration parameters of the current resource + * @var array + */ + public $resourceConfiguration; - /** - * The permissions for the current key - * @var array - */ - public $keyPermissions; + /** + * The permissions for the current key + * @var array + */ + public $keyPermissions; - /** - * The XML string to display if web service call succeed - * @var string - */ - protected $specificOutput = ''; + /** + * The XML string to display if web service call succeed + * @var string + */ + protected $specificOutput = ''; - /** - * The list of objects to display - * @var array - */ - public $objects; + /** + * The list of objects to display + * @var array + */ + public $objects; - /** - * The current object to support, it extends the PrestaShop ObjectModel - * @var ObjectModel - */ - protected $_object; + /** + * The current object to support, it extends the PrestaShop ObjectModel + * @var ObjectModel + */ + protected $_object; - /** - * The schema to display. - * If null, no schema have to be displayed and normal management has to be performed - * @var string - */ - public $schemaToDisplay; + /** + * The schema to display. + * If null, no schema have to be displayed and normal management has to be performed + * @var string + */ + public $schemaToDisplay; - /** - * The fields to display. These fields will be displayed when retrieving objects - * @var string - */ - public $fieldsToDisplay = 'minimum'; + /** + * The fields to display. These fields will be displayed when retrieving objects + * @var string + */ + public $fieldsToDisplay = 'minimum'; - /** - * If we are in PUT or POST case, we use this attribute to store the xml string value during process - * @var string - */ - protected $_inputXml; + /** + * If we are in PUT or POST case, we use this attribute to store the xml string value during process + * @var string + */ + protected $_inputXml; - /** - * Object instance for singleton - * @var WebserviceRequest - */ - protected static $_instance; + /** + * Object instance for singleton + * @var WebserviceRequest + */ + protected static $_instance; - /** - * Key used for authentication - * @var string - */ - protected $_key; + /** + * Key used for authentication + * @var string + */ + protected $_key; - /** - * This is used to have a deeper tree diagram. - * @var int - */ - public $depth = 0; + /** + * This is used to have a deeper tree diagram. + * @var int + */ + public $depth = 0; - /** - * Name of the output format - * @var string - */ - protected $outputFormat = 'xml'; + /** + * Name of the output format + * @var string + */ + protected $outputFormat = 'xml'; - /** - * The object to build the output. - * @var WebserviceOutputBuilder - */ - protected $objOutput; + /** + * The object to build the output. + * @var WebserviceOutputBuilder + */ + protected $objOutput; - /** - * Save the class name for override used in getInstance() - * @var string - */ - public static $ws_current_classname; + /** + * Save the class name for override used in getInstance() + * @var string + */ + public static $ws_current_classname; - public static $shopIDs; + public static $shopIDs; - public function getOutputEnabled() - { - return $this->_outputEnabled; - } + public function getOutputEnabled() + { + return $this->_outputEnabled; + } - public function setOutputEnabled($bool) - { - if (Validate::isBool($bool)) - $this->_outputEnabled = $bool; - return $this; - } + public function setOutputEnabled($bool) + { + if (Validate::isBool($bool)) { + $this->_outputEnabled = $bool; + } + return $this; + } - /** - * Get WebserviceRequest object instance (Singleton) - * - * @return object WebserviceRequest instance - */ - public static function getInstance() - { - if (!isset(self::$_instance)) - self::$_instance = new WebserviceRequest::$ws_current_classname(); - return self::$_instance; - } + /** + * Get WebserviceRequest object instance (Singleton) + * + * @return object WebserviceRequest instance + */ + public static function getInstance() + { + if (!isset(self::$_instance)) { + self::$_instance = new WebserviceRequest::$ws_current_classname(); + } + return self::$_instance; + } - /* - protected function getOutputObject($type) - { - switch ($type) - { - case 'XML' : - default : - $obj_render = new WebserviceOutputXML(); - break; - } - return $obj_render; - } - */ - protected function getOutputObject($type) - { - // set header param in header or as get param - $headers = self::getallheaders(); - if (isset($headers['Io-Format'])) - $type = $headers['Io-Format']; - elseif (isset($headers['Output-Format'])) - $type = $headers['Output-Format']; - elseif (isset($_GET['output_format'])) - $type = $_GET['output_format']; - elseif (isset($_GET['io_format'])) - $type = $_GET['io_format']; - $this->outputFormat = $type; - switch ($type) - { - case 'JSON' : - require_once dirname(__FILE__).'/WebserviceOutputJSON.php'; - $obj_render = new WebserviceOutputJSON(); - break; - case 'XML' : - default : - $obj_render = new WebserviceOutputXML(); - break; - } - return $obj_render; - } + /* + protected function getOutputObject($type) + { + switch ($type) + { + case 'XML' : + default : + $obj_render = new WebserviceOutputXML(); + break; + } + return $obj_render; + } + */ + protected function getOutputObject($type) + { + // set header param in header or as get param + $headers = self::getallheaders(); + if (isset($headers['Io-Format'])) { + $type = $headers['Io-Format']; + } elseif (isset($headers['Output-Format'])) { + $type = $headers['Output-Format']; + } elseif (isset($_GET['output_format'])) { + $type = $_GET['output_format']; + } elseif (isset($_GET['io_format'])) { + $type = $_GET['io_format']; + } + $this->outputFormat = $type; + switch ($type) { + case 'JSON' : + require_once dirname(__FILE__).'/WebserviceOutputJSON.php'; + $obj_render = new WebserviceOutputJSON(); + break; + case 'XML' : + default : + $obj_render = new WebserviceOutputXML(); + break; + } + return $obj_render; + } - public static function getResources() - { - $resources = array( - 'addresses' => array('description' => 'The Customer, Manufacturer and Customer addresses','class' => 'Address'), - 'carriers' => array('description' => 'The Carriers','class' => 'Carrier'), - 'carts' => array('description' => 'Customer\'s carts', 'class' => 'Cart'), - 'cart_rules' => array('description' => 'Cart rules management', 'class' => 'CartRule'), - 'categories' => array('description' => 'The product categories','class' => 'Category'), - 'combinations' => array('description' => 'The product combinations','class' => 'Combination'), - 'configurations' => array('description' => 'Shop configuration', 'class' => 'Configuration'), - 'contacts' => array('description' => 'Shop contacts','class' => 'Contact'), - 'countries' => array('description' => 'The countries','class' => 'Country'), - 'currencies' => array('description' => 'The currencies', 'class' => 'Currency'), - 'customers' => array('description' => 'The e-shop\'s customers','class' => 'Customer'), - 'customer_threads' => array('description' => 'Customer services threads','class' => 'CustomerThread'), - 'customer_messages' => array('description' => 'Customer services messages','class' => 'CustomerMessage'), - 'deliveries' => array('description' => 'Product delivery', 'class' => 'Delivery'), - 'groups' => array('description' => 'The customer\'s groups','class' => 'Group'), - 'guests' => array('description' => 'The guests', 'class' => 'Guest'), - 'images' => array('description' => 'The images', 'specific_management' => true), - 'image_types' => array('description' => 'The image types', 'class' => 'ImageType'), - 'languages' => array('description' => 'Shop languages', 'class' => 'Language'), - 'manufacturers' => array('description' => 'The product manufacturers','class' => 'Manufacturer'), - 'order_carriers' => array('description' => 'The Order carriers','class' => 'OrderCarrier'), - 'order_details' => array('description' => 'Details of an order', 'class' => 'OrderDetail'), - 'order_discounts' => array('description' => 'Discounts of an order', 'class' => 'OrderDiscount'), - 'order_histories' => array('description' => 'The Order histories','class' => 'OrderHistory'), - 'order_invoices' => array('description' => 'The Order invoices','class' => 'OrderInvoice'), - 'orders' => array('description' => 'The Customers orders','class' => 'Order'), - 'order_payments' => array('description' => 'The Order payments','class' => 'OrderPayment'), - 'order_states' => array('description' => 'The Order statuses','class' => 'OrderState'), - 'order_slip' => array('description' => 'The Order slips', 'class' => 'OrderSlip'), - 'price_ranges' => array('description' => 'Price ranges', 'class' => 'RangePrice'), - 'product_features' => array('description' => 'The product features','class' => 'Feature'), - 'product_feature_values' => array('description' => 'The product feature values','class' => 'FeatureValue'), - 'product_options' => array('description' => 'The product options','class' => 'AttributeGroup'), - 'product_option_values' => array('description' => 'The product options value','class' => 'Attribute'), - 'products' => array('description' => 'The products','class' => 'Product'), - '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'), - 'tags' => array('description' => 'The Products tags','class' => 'Tag'), - 'translated_configurations' => array('description' => 'Shop configuration', 'class' => 'TranslatedConfiguration'), - 'weight_ranges' => array('description' => 'Weight ranges', 'class' => 'RangeWeight'), - 'zones' => array('description' => 'The Countries zones','class' => 'Zone'), - 'employees' => array('description' => 'The Employees', 'class' => 'Employee'), - 'search' => array('description' => 'Search', 'specific_management' => true, 'forbidden_method' => array('PUT', 'POST', 'DELETE')), - 'content_management_system' => array('description' => 'Content management system', 'class' => 'CMS'), - 'shops' => array('description' => 'Shops from multi-shop feature', 'class' => 'Shop'), - 'shop_groups' => array('description' => 'Shop groups from multi-shop feature', 'class' => 'ShopGroup'), - 'taxes' => array('description' => 'The tax rate', 'class' => 'Tax'), - 'stock_movements' => array('description' => 'Stock movements', 'class' => 'StockMvtWS', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), - 'stock_movement_reasons' => array('description' => 'Stock movement reason', 'class' => 'StockMvtReason'), - 'warehouses' => array('description' => 'Warehouses', 'class' => 'Warehouse', 'forbidden_method' => array('DELETE')), - 'stocks' => array('description' => 'Stocks', 'class' => 'Stock', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), - 'stock_availables' => array('description' => 'Available quantities', 'class' => 'StockAvailable', 'forbidden_method' => array('POST', 'DELETE')), - 'warehouse_product_locations' => array('description' => 'Location of products in warehouses', 'class' => 'WarehouseProductLocation', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), - 'supply_orders' => array('description' => 'Supply Orders', 'class' => 'SupplyOrder', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), - 'supply_order_details' => array('description' => 'Supply Order Details', 'class' => 'SupplyOrderDetail', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), - 'supply_order_states' => array('description' => 'Supply Order Statuses', 'class' => 'SupplyOrderState', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), - 'supply_order_histories' => array('description' => 'Supply Order Histories', 'class' => 'SupplyOrderHistory', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), - 'supply_order_receipt_histories' => array('description' => 'Supply Order Receipt Histories', 'class' => 'SupplyOrderReceiptHistory', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), - 'product_suppliers' => array('description' => 'Product Suppliers', 'class' => 'ProductSupplier'), - 'tax_rules' => array('description' => 'Tax rules entity', 'class' => 'TaxRule'), - 'tax_rule_groups' => array('description' => 'Tax rule groups', 'class' => 'TaxRulesGroup'), - 'specific_prices' => array('description' => 'Specific price management', 'class' => 'SpecificPrice'), - 'specific_price_rules' => array('description' => 'Specific price management', 'class' => 'SpecificPriceRule'), - 'shop_urls' => array('description' => 'Shop URLs from multi-shop feature', 'class' => 'ShopUrl'), - 'product_customization_fields' => array('description' => 'Customization Field', 'class' => 'CustomizationField'), - 'customizations' => array('description' => 'Customization values', 'class' => 'Customization'), - ); - ksort($resources); - return $resources; - } + public static function getResources() + { + $resources = array( + 'addresses' => array('description' => 'The Customer, Manufacturer and Customer addresses','class' => 'Address'), + 'carriers' => array('description' => 'The Carriers','class' => 'Carrier'), + 'carts' => array('description' => 'Customer\'s carts', 'class' => 'Cart'), + 'cart_rules' => array('description' => 'Cart rules management', 'class' => 'CartRule'), + 'categories' => array('description' => 'The product categories','class' => 'Category'), + 'combinations' => array('description' => 'The product combinations','class' => 'Combination'), + 'configurations' => array('description' => 'Shop configuration', 'class' => 'Configuration'), + 'contacts' => array('description' => 'Shop contacts','class' => 'Contact'), + 'countries' => array('description' => 'The countries','class' => 'Country'), + 'currencies' => array('description' => 'The currencies', 'class' => 'Currency'), + 'customers' => array('description' => 'The e-shop\'s customers','class' => 'Customer'), + 'customer_threads' => array('description' => 'Customer services threads','class' => 'CustomerThread'), + 'customer_messages' => array('description' => 'Customer services messages','class' => 'CustomerMessage'), + 'deliveries' => array('description' => 'Product delivery', 'class' => 'Delivery'), + 'groups' => array('description' => 'The customer\'s groups','class' => 'Group'), + 'guests' => array('description' => 'The guests', 'class' => 'Guest'), + 'images' => array('description' => 'The images', 'specific_management' => true), + 'image_types' => array('description' => 'The image types', 'class' => 'ImageType'), + 'languages' => array('description' => 'Shop languages', 'class' => 'Language'), + 'manufacturers' => array('description' => 'The product manufacturers','class' => 'Manufacturer'), + 'order_carriers' => array('description' => 'The Order carriers','class' => 'OrderCarrier'), + 'order_details' => array('description' => 'Details of an order', 'class' => 'OrderDetail'), + 'order_discounts' => array('description' => 'Discounts of an order', 'class' => 'OrderDiscount'), + 'order_histories' => array('description' => 'The Order histories','class' => 'OrderHistory'), + 'order_invoices' => array('description' => 'The Order invoices','class' => 'OrderInvoice'), + 'orders' => array('description' => 'The Customers orders','class' => 'Order'), + 'order_payments' => array('description' => 'The Order payments','class' => 'OrderPayment'), + 'order_states' => array('description' => 'The Order statuses','class' => 'OrderState'), + 'order_slip' => array('description' => 'The Order slips', 'class' => 'OrderSlip'), + 'price_ranges' => array('description' => 'Price ranges', 'class' => 'RangePrice'), + 'product_features' => array('description' => 'The product features','class' => 'Feature'), + 'product_feature_values' => array('description' => 'The product feature values','class' => 'FeatureValue'), + 'product_options' => array('description' => 'The product options','class' => 'AttributeGroup'), + 'product_option_values' => array('description' => 'The product options value','class' => 'Attribute'), + 'products' => array('description' => 'The products','class' => 'Product'), + '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'), + 'tags' => array('description' => 'The Products tags','class' => 'Tag'), + 'translated_configurations' => array('description' => 'Shop configuration', 'class' => 'TranslatedConfiguration'), + 'weight_ranges' => array('description' => 'Weight ranges', 'class' => 'RangeWeight'), + 'zones' => array('description' => 'The Countries zones','class' => 'Zone'), + 'employees' => array('description' => 'The Employees', 'class' => 'Employee'), + 'search' => array('description' => 'Search', 'specific_management' => true, 'forbidden_method' => array('PUT', 'POST', 'DELETE')), + 'content_management_system' => array('description' => 'Content management system', 'class' => 'CMS'), + 'shops' => array('description' => 'Shops from multi-shop feature', 'class' => 'Shop'), + 'shop_groups' => array('description' => 'Shop groups from multi-shop feature', 'class' => 'ShopGroup'), + 'taxes' => array('description' => 'The tax rate', 'class' => 'Tax'), + 'stock_movements' => array('description' => 'Stock movements', 'class' => 'StockMvtWS', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), + 'stock_movement_reasons' => array('description' => 'Stock movement reason', 'class' => 'StockMvtReason'), + 'warehouses' => array('description' => 'Warehouses', 'class' => 'Warehouse', 'forbidden_method' => array('DELETE')), + 'stocks' => array('description' => 'Stocks', 'class' => 'Stock', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), + 'stock_availables' => array('description' => 'Available quantities', 'class' => 'StockAvailable', 'forbidden_method' => array('POST', 'DELETE')), + 'warehouse_product_locations' => array('description' => 'Location of products in warehouses', 'class' => 'WarehouseProductLocation', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), + 'supply_orders' => array('description' => 'Supply Orders', 'class' => 'SupplyOrder', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), + 'supply_order_details' => array('description' => 'Supply Order Details', 'class' => 'SupplyOrderDetail', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), + 'supply_order_states' => array('description' => 'Supply Order Statuses', 'class' => 'SupplyOrderState', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), + 'supply_order_histories' => array('description' => 'Supply Order Histories', 'class' => 'SupplyOrderHistory', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), + 'supply_order_receipt_histories' => array('description' => 'Supply Order Receipt Histories', 'class' => 'SupplyOrderReceiptHistory', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), + 'product_suppliers' => array('description' => 'Product Suppliers', 'class' => 'ProductSupplier'), + 'tax_rules' => array('description' => 'Tax rules entity', 'class' => 'TaxRule'), + 'tax_rule_groups' => array('description' => 'Tax rule groups', 'class' => 'TaxRulesGroup'), + 'specific_prices' => array('description' => 'Specific price management', 'class' => 'SpecificPrice'), + 'specific_price_rules' => array('description' => 'Specific price management', 'class' => 'SpecificPriceRule'), + 'shop_urls' => array('description' => 'Shop URLs from multi-shop feature', 'class' => 'ShopUrl'), + 'product_customization_fields' => array('description' => 'Customization Field', 'class' => 'CustomizationField'), + 'customizations' => array('description' => 'Customization values', 'class' => 'Customization'), + ); + ksort($resources); + return $resources; + } - /* @todo Check how get parameters */ - /* @todo : set this method out */ - /** - * This method is used for calculate the price for products on the output details - * - * @param $field - * @param $entity_object - * @param $ws_params - * @return array field parameters. - */ - public function getPriceForProduct($field, $entity_object, $ws_params) - { - if (is_int($entity_object->id)) - { - $arr_return = $this->specificPriceForProduct($entity_object, array('default_price'=>'')); - $field['value'] = $arr_return['default_price']['value']; - } - return $field; - } + /* @todo Check how get parameters */ + /* @todo : set this method out */ + /** + * This method is used for calculate the price for products on the output details + * + * @param $field + * @param $entity_object + * @param $ws_params + * @return array field parameters. + */ + public function getPriceForProduct($field, $entity_object, $ws_params) + { + if (is_int($entity_object->id)) { + $arr_return = $this->specificPriceForProduct($entity_object, array('default_price'=>'')); + $field['value'] = $arr_return['default_price']['value']; + } + return $field; + } - /* @todo : set this method out */ - /** - * This method is used for calculate the price for products on a virtual fields - * - * @param $entity_object - * @param array $parameters - * @return array - */ - public function specificPriceForProduct($entity_object, $parameters) - { - foreach (array_keys($parameters) as $name) - $parameters[$name]['object_id'] = $entity_object->id; - $arr_return = $this->specificPriceCalculation($parameters); - return $arr_return; - } + /* @todo : set this method out */ + /** + * This method is used for calculate the price for products on a virtual fields + * + * @param $entity_object + * @param array $parameters + * @return array + */ + public function specificPriceForProduct($entity_object, $parameters) + { + foreach (array_keys($parameters) as $name) { + $parameters[$name]['object_id'] = $entity_object->id; + } + $arr_return = $this->specificPriceCalculation($parameters); + return $arr_return; + } - public function specificPriceCalculation($parameters) - { - $arr_return = array(); - foreach ($parameters as $name => $value) - { - $id_shop = (int)Context::getContext()->shop->id; - $id_country = (int)(isset($value['country']) ? $value['country'] : (Configuration::get('PS_COUNTRY_DEFAULT'))); - $id_state = (int)(isset($value['state']) ? $value['state'] : 0); - $id_currency = (int)(isset($value['currency']) ? $value['currency'] : Configuration::get('PS_CURRENCY_DEFAULT')); - $id_group = (int)(isset($value['group']) ? $value['group'] : (int)Configuration::get('PS_CUSTOMER_GROUP')); - $quantity = (int)(isset($value['quantity']) ? $value['quantity'] : 1); - $use_tax = (int)(isset($value['use_tax']) ? $value['use_tax'] : Configuration::get('PS_TAX')); - $decimals = (int)(isset($value['decimals']) ? $value['decimals'] : Configuration::get('PS_PRICE_ROUND_MODE')); - $id_product_attribute = (int)(isset($value['product_attribute']) ? $value['product_attribute'] : null); - $only_reduc = (int)(isset($value['only_reduction']) ? $value['only_reduction'] : false); - $use_reduc = (int)(isset($value['use_reduction']) ? $value['use_reduction'] : true); - $use_ecotax = (int)(isset($value['use_ecotax']) ? $value['use_ecotax'] : Configuration::get('PS_USE_ECOTAX')); - $specific_price_output = null; - $id_county = (int)(isset($value['county']) ? $value['county'] : 0); - $return_value = Product::priceCalculation($id_shop, $value['object_id'], $id_product_attribute, $id_country, $id_state, $id_county, $id_currency, $id_group, $quantity, - $use_tax, $decimals, $only_reduc, $use_reduc, $use_ecotax, $specific_price_output, null); - $arr_return[$name] = array('sqlId'=>strtolower($name), 'value'=>sprintf('%f', $return_value)); - } - return $arr_return; - } - /* @todo : set this method out */ - /** - * This method is used for calculate the price for products on a virtual fields - * - * @param $entity_object - * @param array $parameters - * @return array - */ - public function specificPriceForCombination($entity_object, $parameters) - { - foreach (array_keys($parameters) as $name) - { - $parameters[$name]['object_id'] = $entity_object->id_product; - $parameters[$name]['product_attribute'] = $entity_object->id; - } - $arr_return = $this->specificPriceCalculation($parameters); - return $arr_return; - } + public function specificPriceCalculation($parameters) + { + $arr_return = array(); + foreach ($parameters as $name => $value) { + $id_shop = (int)Context::getContext()->shop->id; + $id_country = (int)(isset($value['country']) ? $value['country'] : (Configuration::get('PS_COUNTRY_DEFAULT'))); + $id_state = (int)(isset($value['state']) ? $value['state'] : 0); + $id_currency = (int)(isset($value['currency']) ? $value['currency'] : Configuration::get('PS_CURRENCY_DEFAULT')); + $id_group = (int)(isset($value['group']) ? $value['group'] : (int)Configuration::get('PS_CUSTOMER_GROUP')); + $quantity = (int)(isset($value['quantity']) ? $value['quantity'] : 1); + $use_tax = (int)(isset($value['use_tax']) ? $value['use_tax'] : Configuration::get('PS_TAX')); + $decimals = (int)(isset($value['decimals']) ? $value['decimals'] : Configuration::get('PS_PRICE_ROUND_MODE')); + $id_product_attribute = (int)(isset($value['product_attribute']) ? $value['product_attribute'] : null); + $only_reduc = (int)(isset($value['only_reduction']) ? $value['only_reduction'] : false); + $use_reduc = (int)(isset($value['use_reduction']) ? $value['use_reduction'] : true); + $use_ecotax = (int)(isset($value['use_ecotax']) ? $value['use_ecotax'] : Configuration::get('PS_USE_ECOTAX')); + $specific_price_output = null; + $id_county = (int)(isset($value['county']) ? $value['county'] : 0); + $return_value = Product::priceCalculation($id_shop, $value['object_id'], $id_product_attribute, $id_country, $id_state, $id_county, $id_currency, $id_group, $quantity, + $use_tax, $decimals, $only_reduc, $use_reduc, $use_ecotax, $specific_price_output, null); + $arr_return[$name] = array('sqlId'=>strtolower($name), 'value'=>sprintf('%f', $return_value)); + } + return $arr_return; + } + /* @todo : set this method out */ + /** + * This method is used for calculate the price for products on a virtual fields + * + * @param $entity_object + * @param array $parameters + * @return array + */ + public function specificPriceForCombination($entity_object, $parameters) + { + foreach (array_keys($parameters) as $name) { + $parameters[$name]['object_id'] = $entity_object->id_product; + $parameters[$name]['product_attribute'] = $entity_object->id; + } + $arr_return = $this->specificPriceCalculation($parameters); + return $arr_return; + } - /** - * Start Webservice request - * Check webservice activation - * Check autentication - * Check resource - * Check HTTP Method - * Execute the action - * Display the result - * - * @param string $key - * @param string $method - * @param string $url - * @param string $params - * @param string $inputXml - * - * @return array Returns an array of results (headers, content, type of resource...) - */ - public function fetch($key, $method, $url, $params, $bad_class_name, $inputXml = null) - { - // Time logger - $this->_startTime = microtime(true); - $this->objects = array(); + /** + * Start Webservice request + * Check webservice activation + * Check autentication + * Check resource + * Check HTTP Method + * Execute the action + * Display the result + * + * @param string $key + * @param string $method + * @param string $url + * @param string $params + * @param string $inputXml + * + * @return array Returns an array of results (headers, content, type of resource...) + */ + public function fetch($key, $method, $url, $params, $bad_class_name, $inputXml = null) + { + // Time logger + $this->_startTime = microtime(true); + $this->objects = array(); - // Error handler - set_error_handler(array($this, 'webserviceErrorHandler')); - ini_set('html_errors', 'off'); + // Error handler + set_error_handler(array($this, 'webserviceErrorHandler')); + ini_set('html_errors', 'off'); - // Two global vars, for compatibility with the PS core... - global $webservice_call, $display_errors; - $webservice_call = true; - $display_errors = strtolower(ini_get('display_errors')) != 'off'; - // __PS_BASE_URI__ is from Shop::$current_base_uri - $this->wsUrl = Tools::getHttpHost(true).__PS_BASE_URI__.'api/'; - // set the output object which manage the content and header structure and informations - $this->objOutput = new WebserviceOutputBuilder($this->wsUrl); + // Two global vars, for compatibility with the PS core... + global $webservice_call, $display_errors; + $webservice_call = true; + $display_errors = strtolower(ini_get('display_errors')) != 'off'; + // __PS_BASE_URI__ is from Shop::$current_base_uri + $this->wsUrl = Tools::getHttpHost(true).__PS_BASE_URI__.'api/'; + // set the output object which manage the content and header structure and informations + $this->objOutput = new WebserviceOutputBuilder($this->wsUrl); - $this->_key = trim($key); + $this->_key = trim($key); - $this->outputFormat = isset($params['output_format']) ? $params['output_format'] : $this->outputFormat; - // Set the render object to build the output on the asked format (XML, JSON, CSV, ...) - $this->objOutput->setObjectRender($this->getOutputObject($this->outputFormat)); - $this->params = $params; - // Check webservice activation and request authentication - if ($this->webserviceChecks()) - { - if ($bad_class_name) - $this->setError(500, 'Class "'.htmlspecialchars($bad_class_name).'" not found. Please update the class_name field in the webservice_account table.', 126); - // parse request url - $this->method = $method; - $this->urlSegment = explode('/', $url); - $this->urlFragments = $params; - $this->_inputXml = $inputXml; - $this->depth = isset($this->urlFragments['depth']) ? (int)$this->urlFragments['depth'] : $this->depth; + $this->outputFormat = isset($params['output_format']) ? $params['output_format'] : $this->outputFormat; + // Set the render object to build the output on the asked format (XML, JSON, CSV, ...) + $this->objOutput->setObjectRender($this->getOutputObject($this->outputFormat)); + $this->params = $params; + // Check webservice activation and request authentication + if ($this->webserviceChecks()) { + if ($bad_class_name) { + $this->setError(500, 'Class "'.htmlspecialchars($bad_class_name).'" not found. Please update the class_name field in the webservice_account table.', 126); + } + // parse request url + $this->method = $method; + $this->urlSegment = explode('/', $url); + $this->urlFragments = $params; + $this->_inputXml = $inputXml; + $this->depth = isset($this->urlFragments['depth']) ? (int)$this->urlFragments['depth'] : $this->depth; - try { - // Method below set a particular fonction to use on the price field for products entity - // @see WebserviceRequest::getPriceForProduct() method - // @see WebserviceOutputBuilder::setSpecificField() method - //$this->objOutput->setSpecificField($this, 'getPriceForProduct', 'price', 'products'); - if (isset($this->urlFragments['price'])) - { - $this->objOutput->setVirtualField($this, 'specificPriceForCombination', 'combinations', $this->urlFragments['price']); - $this->objOutput->setVirtualField($this, 'specificPriceForProduct', 'products', $this->urlFragments['price']); - } - } catch (Exception $e) { - $this->setError(500, $e->getMessage(), $e->getCode()); - } + try { + // Method below set a particular fonction to use on the price field for products entity + // @see WebserviceRequest::getPriceForProduct() method + // @see WebserviceOutputBuilder::setSpecificField() method + //$this->objOutput->setSpecificField($this, 'getPriceForProduct', 'price', 'products'); + if (isset($this->urlFragments['price'])) { + $this->objOutput->setVirtualField($this, 'specificPriceForCombination', 'combinations', $this->urlFragments['price']); + $this->objOutput->setVirtualField($this, 'specificPriceForProduct', 'products', $this->urlFragments['price']); + } + } catch (Exception $e) { + $this->setError(500, $e->getMessage(), $e->getCode()); + } - if (isset($this->urlFragments['language'])) - $this->_available_languages = $this->filterLanguage(); - else - $this->_available_languages = Language::getIDs(); + if (isset($this->urlFragments['language'])) { + $this->_available_languages = $this->filterLanguage(); + } else { + $this->_available_languages = Language::getIDs(); + } - if (empty($this->_available_languages)) - $this->setError(400, 'language is not available', 81); + if (empty($this->_available_languages)) { + $this->setError(400, 'language is not available', 81); + } - // Need to set available languages for the render object. - // Thus we can filter i18n field for the output - // @see WebserviceOutputXML::renderField() method for example - $this->objOutput->objectRender->setLanguages($this->_available_languages); + // Need to set available languages for the render object. + // Thus we can filter i18n field for the output + // @see WebserviceOutputXML::renderField() method for example + $this->objOutput->objectRender->setLanguages($this->_available_languages); - // check method and resource - if (empty($this->errors) && $this->checkResource() && $this->checkHTTPMethod()) - { - // The resource list is necessary for build the output - $this->objOutput->setWsResources($this->resourceList); + // check method and resource + if (empty($this->errors) && $this->checkResource() && $this->checkHTTPMethod()) { + // The resource list is necessary for build the output + $this->objOutput->setWsResources($this->resourceList); - // if the resource is a core entity... - if (!isset($this->resourceList[$this->urlSegment[0]]['specific_management']) || !$this->resourceList[$this->urlSegment[0]]['specific_management']) - { + // if the resource is a core entity... + if (!isset($this->resourceList[$this->urlSegment[0]]['specific_management']) || !$this->resourceList[$this->urlSegment[0]]['specific_management']) { - // load resource configuration - if ($this->urlSegment[0] != '') - { - /** @var ObjectModel $object */ - $object = new $this->resourceList[$this->urlSegment[0]]['class'](); - if (isset($this->resourceList[$this->urlSegment[0]]['parameters_attribute'])) - $this->resourceConfiguration = $object->getWebserviceParameters($this->resourceList[$this->urlSegment[0]]['parameters_attribute']); - else - $this->resourceConfiguration = $object->getWebserviceParameters(); - } - $success = false; - // execute the action - switch ($this->method) - { - case 'GET': - case 'HEAD': - if ($this->executeEntityGetAndHead()) - $success = true; - break; - case 'POST': - if ($this->executeEntityPost()) - $success = true; - break; - case 'PUT': - if ($this->executeEntityPut()) - $success = true; - break; - case 'DELETE': - $this->executeEntityDelete(); - break; - } - // Need to set an object for the WebserviceOutputBuilder object in any case - // because schema need to get webserviceParameters of this object - if (isset($object)) - $this->objects['empty'] = $object; - } - // if the management is specific - else - { - $specificObjectName = 'WebserviceSpecificManagement'.ucfirst(Tools::toCamelCase($this->urlSegment[0])); - if (!class_exists($specificObjectName)) - $this->setError(501, sprintf('The specific management class is not implemented for the "%s" entity.', $this->urlSegment[0]), 124); - else - { - $this->objectSpecificManagement = new $specificObjectName(); - $this->objectSpecificManagement->setObjectOutput($this->objOutput) - ->setWsObject($this); + // load resource configuration + if ($this->urlSegment[0] != '') { + /** @var ObjectModel $object */ + $object = new $this->resourceList[$this->urlSegment[0]]['class'](); + if (isset($this->resourceList[$this->urlSegment[0]]['parameters_attribute'])) { + $this->resourceConfiguration = $object->getWebserviceParameters($this->resourceList[$this->urlSegment[0]]['parameters_attribute']); + } else { + $this->resourceConfiguration = $object->getWebserviceParameters(); + } + } + $success = false; + // execute the action + switch ($this->method) { + case 'GET': + case 'HEAD': + if ($this->executeEntityGetAndHead()) { + $success = true; + } + break; + case 'POST': + if ($this->executeEntityPost()) { + $success = true; + } + break; + case 'PUT': + if ($this->executeEntityPut()) { + $success = true; + } + break; + case 'DELETE': + $this->executeEntityDelete(); + break; + } + // Need to set an object for the WebserviceOutputBuilder object in any case + // because schema need to get webserviceParameters of this object + if (isset($object)) { + $this->objects['empty'] = $object; + } + } + // if the management is specific + else { + $specificObjectName = 'WebserviceSpecificManagement'.ucfirst(Tools::toCamelCase($this->urlSegment[0])); + if (!class_exists($specificObjectName)) { + $this->setError(501, sprintf('The specific management class is not implemented for the "%s" entity.', $this->urlSegment[0]), 124); + } else { + $this->objectSpecificManagement = new $specificObjectName(); + $this->objectSpecificManagement->setObjectOutput($this->objOutput) + ->setWsObject($this); - try { - $this->objectSpecificManagement->manage(); - } catch (WebserviceException $e) { - if ($e->getType() == WebserviceException::DID_YOU_MEAN) - $this->setErrorDidYouMean($e->getStatus(), $e->getMessage(), $e->getWrongValue(), $e->getAvailableValues(), $e->getCode()); - elseif ($e->getType() == WebserviceException::SIMPLE) - $this->setError($e->getStatus(), $e->getMessage(), $e->getCode()); - } - } - } - } - } - $return = $this->returnOutput(); - unset($webservice_call); - unset($display_errors); - return $return; - } + try { + $this->objectSpecificManagement->manage(); + } catch (WebserviceException $e) { + if ($e->getType() == WebserviceException::DID_YOU_MEAN) { + $this->setErrorDidYouMean($e->getStatus(), $e->getMessage(), $e->getWrongValue(), $e->getAvailableValues(), $e->getCode()); + } elseif ($e->getType() == WebserviceException::SIMPLE) { + $this->setError($e->getStatus(), $e->getMessage(), $e->getCode()); + } + } + } + } + } + } + $return = $this->returnOutput(); + unset($webservice_call); + unset($display_errors); + return $return; + } - protected function webserviceChecks() - { - return ($this->isActivated() && $this->authenticate() && $this->groupShopExists($this->params) && $this->shopExists($this->params) && $this->shopHasRight($this->_key)); - } + protected function webserviceChecks() + { + return ($this->isActivated() && $this->authenticate() && $this->groupShopExists($this->params) && $this->shopExists($this->params) && $this->shopHasRight($this->_key)); + } - /** - * Set a webservice error - * - * @param int $status - * @param string $label - * @param int $code - * @return void - */ - public function setError($status, $label, $code) - { - global $display_errors; - if (!isset($display_errors)) - $display_errors = strtolower(ini_get('display_errors')) != 'off'; - if (isset($this->objOutput)) - $this->objOutput->setStatus($status); - $this->errors[] = $display_errors ? array($code, $label) : 'Internal error. To see this error please display the PHP errors.'; - } + /** + * Set a webservice error + * + * @param int $status + * @param string $label + * @param int $code + * @return void + */ + public function setError($status, $label, $code) + { + global $display_errors; + if (!isset($display_errors)) { + $display_errors = strtolower(ini_get('display_errors')) != 'off'; + } + if (isset($this->objOutput)) { + $this->objOutput->setStatus($status); + } + $this->errors[] = $display_errors ? array($code, $label) : 'Internal error. To see this error please display the PHP errors.'; + } - /** - * Set a webservice error and propose a new value near from the available values - * - * @param int $num - * @param string $label - * @param array $value - * @param array $values - * @param int $code - * @return void - */ - public function setErrorDidYouMean($num, $label, $value, $available_values, $code) - { - $this->setError($num, $label.'. Did you mean: "'.$this->getClosest($value, $available_values).'"?'.(count($available_values) > 1 ? ' The full list is: "'.implode('", "', $available_values).'"' : ''), $code); - } + /** + * Set a webservice error and propose a new value near from the available values + * + * @param int $num + * @param string $label + * @param array $value + * @param array $values + * @param int $code + * @return void + */ + public function setErrorDidYouMean($num, $label, $value, $available_values, $code) + { + $this->setError($num, $label.'. Did you mean: "'.$this->getClosest($value, $available_values).'"?'.(count($available_values) > 1 ? ' The full list is: "'.implode('", "', $available_values).'"' : ''), $code); + } - /** - * Return the nearest value picked in the values list - * - * @param string $input - * @param array $words - * @return string - */ - protected function getClosest($input, $words) - { - $shortest = -1; - foreach ($words as $word) - { - $lev = levenshtein($input, $word); - if ($lev == 0) - { - $closest = $word; - $shortest = 0; - break; - } - if ($lev <= $shortest || $shortest < 0) - { - $closest = $word; - $shortest = $lev; - } - } - return $closest; - } + /** + * Return the nearest value picked in the values list + * + * @param string $input + * @param array $words + * @return string + */ + protected function getClosest($input, $words) + { + $shortest = -1; + foreach ($words as $word) { + $lev = levenshtein($input, $word); + if ($lev == 0) { + $closest = $word; + $shortest = 0; + break; + } + if ($lev <= $shortest || $shortest < 0) { + $closest = $word; + $shortest = $lev; + } + } + return $closest; + } - /** - * Used to replace the default PHP error handler, in order to display PHP errors in a XML format - * - * @param string $errno contains the level of the error raised, as an integer - * @param array $errstr contains the error message, as a string - * @param array $errfile errfile, which contains the filename that the error was raised in, as a string - * @param array $errline errline, which contains the line number the error was raised at, as an integer - * @return bool Always return true to avoid the default PHP error handler - */ - public function webserviceErrorHandler($errno, $errstr, $errfile, $errline) - { - $display_errors = strtolower(ini_get('display_errors')) != 'off'; - if (!(error_reporting() & $errno) || $display_errors) - return; + /** + * Used to replace the default PHP error handler, in order to display PHP errors in a XML format + * + * @param string $errno contains the level of the error raised, as an integer + * @param array $errstr contains the error message, as a string + * @param array $errfile errfile, which contains the filename that the error was raised in, as a string + * @param array $errline errline, which contains the line number the error was raised at, as an integer + * @return bool Always return true to avoid the default PHP error handler + */ + public function webserviceErrorHandler($errno, $errstr, $errfile, $errline) + { + $display_errors = strtolower(ini_get('display_errors')) != 'off'; + if (!(error_reporting() & $errno) || $display_errors) { + return; + } - $errortype = array ( - E_ERROR => 'Error', - E_WARNING => 'Warning', - E_PARSE => 'Parse', - E_NOTICE => 'Notice', - E_CORE_ERROR => 'Core Error', - E_CORE_WARNING => 'Core Warning', - E_COMPILE_ERROR => 'Compile Error', - E_COMPILE_WARNING => 'Compile Warning', - E_USER_ERROR => 'Error', - E_USER_WARNING => 'User warning', - E_USER_NOTICE => 'User notice', - E_STRICT => 'Runtime Notice', - E_RECOVERABLE_ERROR => 'Recoverable error' - ); - $type = (isset($errortype[$errno]) ? $errortype[$errno] : 'Unknown error'); - Tools::error_log('[PHP '.$type.' #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'); + $errortype = array( + E_ERROR => 'Error', + E_WARNING => 'Warning', + E_PARSE => 'Parse', + E_NOTICE => 'Notice', + E_CORE_ERROR => 'Core Error', + E_CORE_WARNING => 'Core Warning', + E_COMPILE_ERROR => 'Compile Error', + E_COMPILE_WARNING => 'Compile Warning', + E_USER_ERROR => 'Error', + E_USER_WARNING => 'User warning', + E_USER_NOTICE => 'User notice', + E_STRICT => 'Runtime Notice', + E_RECOVERABLE_ERROR => 'Recoverable error' + ); + $type = (isset($errortype[$errno]) ? $errortype[$errno] : 'Unknown error'); + Tools::error_log('[PHP '.$type.' #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')'); - switch ($errno) - { - case E_ERROR: - WebserviceRequest::getInstance()->setError(500, '[PHP Error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 2); - break; - case E_WARNING: - WebserviceRequest::getInstance()->setError(500, '[PHP Warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 3); - break; - case E_PARSE: - WebserviceRequest::getInstance()->setError(500, '[PHP Parse #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 4); - break; - case E_NOTICE: - WebserviceRequest::getInstance()->setError(500, '[PHP Notice #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 5); - break; - case E_CORE_ERROR: - WebserviceRequest::getInstance()->setError(500, '[PHP Core #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 6); - break; - case E_CORE_WARNING: - WebserviceRequest::getInstance()->setError(500, '[PHP Core warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 7); - break; - case E_COMPILE_ERROR: - WebserviceRequest::getInstance()->setError(500, '[PHP Compile #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 8); - break; - case E_COMPILE_WARNING: - WebserviceRequest::getInstance()->setError(500, '[PHP Compile warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 9); - break; - case E_USER_ERROR: - WebserviceRequest::getInstance()->setError(500, '[PHP Error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 10); - break; - case E_USER_WARNING: - WebserviceRequest::getInstance()->setError(500, '[PHP User warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 11); - break; - case E_USER_NOTICE: - WebserviceRequest::getInstance()->setError(500, '[PHP User notice #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 12); - break; - case E_STRICT: - WebserviceRequest::getInstance()->setError(500, '[PHP Strict #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 13); - break; - case E_RECOVERABLE_ERROR: - WebserviceRequest::getInstance()->setError(500, '[PHP Recoverable error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 14); - break; - default: - WebserviceRequest::getInstance()->setError(500, '[PHP Unknown error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 15); - } - return true; - } + switch ($errno) { + case E_ERROR: + WebserviceRequest::getInstance()->setError(500, '[PHP Error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 2); + break; + case E_WARNING: + WebserviceRequest::getInstance()->setError(500, '[PHP Warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 3); + break; + case E_PARSE: + WebserviceRequest::getInstance()->setError(500, '[PHP Parse #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 4); + break; + case E_NOTICE: + WebserviceRequest::getInstance()->setError(500, '[PHP Notice #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 5); + break; + case E_CORE_ERROR: + WebserviceRequest::getInstance()->setError(500, '[PHP Core #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 6); + break; + case E_CORE_WARNING: + WebserviceRequest::getInstance()->setError(500, '[PHP Core warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 7); + break; + case E_COMPILE_ERROR: + WebserviceRequest::getInstance()->setError(500, '[PHP Compile #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 8); + break; + case E_COMPILE_WARNING: + WebserviceRequest::getInstance()->setError(500, '[PHP Compile warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 9); + break; + case E_USER_ERROR: + WebserviceRequest::getInstance()->setError(500, '[PHP Error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 10); + break; + case E_USER_WARNING: + WebserviceRequest::getInstance()->setError(500, '[PHP User warning #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 11); + break; + case E_USER_NOTICE: + WebserviceRequest::getInstance()->setError(500, '[PHP User notice #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 12); + break; + case E_STRICT: + WebserviceRequest::getInstance()->setError(500, '[PHP Strict #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 13); + break; + case E_RECOVERABLE_ERROR: + WebserviceRequest::getInstance()->setError(500, '[PHP Recoverable error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 14); + break; + default: + WebserviceRequest::getInstance()->setError(500, '[PHP Unknown error #'.$errno.'] '.$errstr.' ('.$errfile.', line '.$errline.')', 15); + } + return true; + } - /** - * Check if there is one or more error - * - * @return bool - */ - protected function hasErrors() - { - return (bool)$this->errors; - } + /** + * Check if there is one or more error + * + * @return bool + */ + protected function hasErrors() + { + return (bool)$this->errors; + } - /** - * Check request authentication - * - * @return bool - */ - protected function authenticate() - { - if (!$this->hasErrors()) - { - if (is_null($this->_key)) - $this->setError(401, 'Please enter the authentication key as the login. No password required', 16); - else - { - if (empty($this->_key)) - $this->setError(401, 'Authentication key is empty', 17); - elseif (strlen($this->_key) != '32') - $this->setError(401, 'Invalid authentication key format', 18); - else - { - if (WebserviceKey::isKeyActive($this->_key)) - $this->keyPermissions = WebserviceKey::getPermissionForAccount($this->_key); - else - $this->setError(401, 'Authentification key is not active', 20); + /** + * Check request authentication + * + * @return bool + */ + protected function authenticate() + { + if (!$this->hasErrors()) { + if (is_null($this->_key)) { + $this->setError(401, 'Please enter the authentication key as the login. No password required', 16); + } else { + if (empty($this->_key)) { + $this->setError(401, 'Authentication key is empty', 17); + } elseif (strlen($this->_key) != '32') { + $this->setError(401, 'Invalid authentication key format', 18); + } else { + if (WebserviceKey::isKeyActive($this->_key)) { + $this->keyPermissions = WebserviceKey::getPermissionForAccount($this->_key); + } else { + $this->setError(401, 'Authentification key is not active', 20); + } - if (!$this->keyPermissions) - $this->setError(401, 'No permission for this authentication key', 21); - } - } - if ($this->hasErrors()) - { - header('WWW-Authenticate: Basic realm="Welcome to PrestaShop Webservice, please enter the authentication key as the login. No password required."'); - $this->objOutput->setStatus(401); - return false; - } - else - { - // only now we can say the access is authenticated - $this->_authenticated = true; - return true; - } - } - } + if (!$this->keyPermissions) { + $this->setError(401, 'No permission for this authentication key', 21); + } + } + } + if ($this->hasErrors()) { + header('WWW-Authenticate: Basic realm="Welcome to PrestaShop Webservice, please enter the authentication key as the login. No password required."'); + $this->objOutput->setStatus(401); + return false; + } else { + // only now we can say the access is authenticated + $this->_authenticated = true; + return true; + } + } + } - /** - * Check webservice activation - * - * @return bool - */ - protected function isActivated() - { - if (!Configuration::get('PS_WEBSERVICE')) - { - $this->setError(503, 'The PrestaShop webservice is disabled. Please activate it in the PrestaShop Back Office', 22); - return false; - } - return true; - } + /** + * Check webservice activation + * + * @return bool + */ + protected function isActivated() + { + if (!Configuration::get('PS_WEBSERVICE')) { + $this->setError(503, 'The PrestaShop webservice is disabled. Please activate it in the PrestaShop Back Office', 22); + return false; + } + return true; + } - protected function shopHasRight($key) - { - $sql = 'SELECT 1 + protected function shopHasRight($key) + { + $sql = 'SELECT 1 FROM '._DB_PREFIX_.'webservice_account wsa LEFT JOIN '._DB_PREFIX_.'webservice_account_shop wsas ON (wsa.id_webservice_account = wsas.id_webservice_account) WHERE wsa.key = \''.pSQL($key).'\''; - foreach (self::$shopIDs as $id_shop) - $OR[] = ' wsas.id_shop = '.(int)$id_shop.' '; - $sql .= ' AND ('.implode('OR', $OR).') '; - if (!Db::getInstance()->getValue($sql)) - { - $this->setError(403, 'No permission for this key on this shop', 132); - return false; - } - return true; - } + foreach (self::$shopIDs as $id_shop) { + $OR[] = ' wsas.id_shop = '.(int)$id_shop.' '; + } + $sql .= ' AND ('.implode('OR', $OR).') '; + if (!Db::getInstance()->getValue($sql)) { + $this->setError(403, 'No permission for this key on this shop', 132); + return false; + } + return true; + } - protected function shopExists($params) - { - if (count(self::$shopIDs)) - return true; + protected function shopExists($params) + { + if (count(self::$shopIDs)) { + return true; + } - if (isset($params['id_shop'])) - { - if ($params['id_shop'] != 'all' && is_numeric($params['id_shop'])) - { - Shop::setContext(Shop::CONTEXT_SHOP, (int)$params['id_shop']); - self::$shopIDs[] = (int)$params['id_shop']; - return true; - } - elseif ($params['id_shop'] == 'all') - { - Shop::setContext(Shop::CONTEXT_ALL); - self::$shopIDs = Shop::getShops(true, null, true); - return true; - } - } - else - { - self::$shopIDs[] = Context::getContext()->shop->id; - return true; - } - $this->setError(404, 'This shop id does not exist', 999); - return false; - } + if (isset($params['id_shop'])) { + if ($params['id_shop'] != 'all' && is_numeric($params['id_shop'])) { + Shop::setContext(Shop::CONTEXT_SHOP, (int)$params['id_shop']); + self::$shopIDs[] = (int)$params['id_shop']; + return true; + } elseif ($params['id_shop'] == 'all') { + Shop::setContext(Shop::CONTEXT_ALL); + self::$shopIDs = Shop::getShops(true, null, true); + return true; + } + } else { + self::$shopIDs[] = Context::getContext()->shop->id; + return true; + } + $this->setError(404, 'This shop id does not exist', 999); + return false; + } - protected function groupShopExists($params) - { - if (isset($params['id_group_shop']) && is_numeric($params['id_group_shop'])) - { - Shop::setContext(Shop::CONTEXT_GROUP, (int)$params['id_group_shop']); - self::$shopIDs = Shop::getShops(true, (int)$params['id_group_shop'], true); - if (count(self::$shopIDs) == 0) - { - // @FIXME Set ErrorCode ! - $this->setError(500, 'This group shop doesn\'t have shops', 999); - return false; - } - } - // id_group_shop isn't mandatory - return true; - } + protected function groupShopExists($params) + { + if (isset($params['id_group_shop']) && is_numeric($params['id_group_shop'])) { + Shop::setContext(Shop::CONTEXT_GROUP, (int)$params['id_group_shop']); + self::$shopIDs = Shop::getShops(true, (int)$params['id_group_shop'], true); + if (count(self::$shopIDs) == 0) { + // @FIXME Set ErrorCode ! + $this->setError(500, 'This group shop doesn\'t have shops', 999); + return false; + } + } + // id_group_shop isn't mandatory + return true; + } - /** - * Check HTTP method - * - * @return bool - */ - protected function checkHTTPMethod() - { - if (!in_array($this->method, array('GET', 'POST', 'PUT', 'DELETE', 'HEAD'))) - $this->setError(405, 'Method '.$this->method.' is not valid', 23); - elseif (isset($this->urlSegment[0]) && isset($this->resourceList[$this->urlSegment[0]]['forbidden_method']) && in_array($this->method, $this->resourceList[$this->urlSegment[0]]['forbidden_method'])) - $this->setError(405, 'Method '.$this->method.' is not allowed for the resource '.$this->urlSegment[0], 101); - elseif ($this->urlSegment[0] && !in_array($this->method, $this->keyPermissions[$this->urlSegment[0]])) - $this->setError(405, 'Method '.$this->method.' is not allowed for the resource '.$this->urlSegment[0].' with this authentication key', 25); - else - return true; - return false; - } + /** + * Check HTTP method + * + * @return bool + */ + protected function checkHTTPMethod() + { + if (!in_array($this->method, array('GET', 'POST', 'PUT', 'DELETE', 'HEAD'))) { + $this->setError(405, 'Method '.$this->method.' is not valid', 23); + } elseif (isset($this->urlSegment[0]) && isset($this->resourceList[$this->urlSegment[0]]['forbidden_method']) && in_array($this->method, $this->resourceList[$this->urlSegment[0]]['forbidden_method'])) { + $this->setError(405, 'Method '.$this->method.' is not allowed for the resource '.$this->urlSegment[0], 101); + } elseif ($this->urlSegment[0] && !in_array($this->method, $this->keyPermissions[$this->urlSegment[0]])) { + $this->setError(405, 'Method '.$this->method.' is not allowed for the resource '.$this->urlSegment[0].' with this authentication key', 25); + } else { + return true; + } + return false; + } - /** - * Check resource validity - * - * @return bool - */ - protected function checkResource() - { - $this->resourceList = $this->getResources(); - $resourceNames = array_keys($this->resourceList); - if ($this->urlSegment[0] == '') - $this->resourceConfiguration['objectsNodeName'] = 'resources'; - elseif (in_array($this->urlSegment[0], $resourceNames)) - { - if (!in_array($this->urlSegment[0], array_keys($this->keyPermissions))) - { - $this->setError(401, 'Resource of type "'.$this->urlSegment[0].'" is not allowed with this authentication key', 26); - return false; - } - } - else - { - $this->setErrorDidYouMean(400, 'Resource of type "'.$this->urlSegment[0].'" does not exists', $this->urlSegment[0], $resourceNames, 27); - return false; - } - return true; - } + /** + * Check resource validity + * + * @return bool + */ + protected function checkResource() + { + $this->resourceList = $this->getResources(); + $resourceNames = array_keys($this->resourceList); + if ($this->urlSegment[0] == '') { + $this->resourceConfiguration['objectsNodeName'] = 'resources'; + } elseif (in_array($this->urlSegment[0], $resourceNames)) { + if (!in_array($this->urlSegment[0], array_keys($this->keyPermissions))) { + $this->setError(401, 'Resource of type "'.$this->urlSegment[0].'" is not allowed with this authentication key', 26); + return false; + } + } else { + $this->setErrorDidYouMean(400, 'Resource of type "'.$this->urlSegment[0].'" does not exists', $this->urlSegment[0], $resourceNames, 27); + return false; + } + return true; + } - protected function setObjects() - { - $objects = array(); - $arr_avoid_id = array(); - $ids = array(); - if (isset($this->urlFragments['id'])) - { - preg_match('#^\[(.*)\]$#Ui', $this->urlFragments['id'], $matches); - if (count($matches) > 1) - $ids = explode(',', $matches[1]); - } - else - $ids[] = (int)$this->urlSegment[1]; - if (!empty($ids)) - { - foreach ($ids as $id) - { - $object = new $this->resourceConfiguration['retrieveData']['className']((int)$id); - if (!$object->id) - $arr_avoid_id[] = $id; - else - $objects[] = $object; - } - } + protected function setObjects() + { + $objects = array(); + $arr_avoid_id = array(); + $ids = array(); + if (isset($this->urlFragments['id'])) { + preg_match('#^\[(.*)\]$#Ui', $this->urlFragments['id'], $matches); + if (count($matches) > 1) { + $ids = explode(',', $matches[1]); + } + } else { + $ids[] = (int)$this->urlSegment[1]; + } + if (!empty($ids)) { + foreach ($ids as $id) { + $object = new $this->resourceConfiguration['retrieveData']['className']((int)$id); + if (!$object->id) { + $arr_avoid_id[] = $id; + } else { + $objects[] = $object; + } + } + } - if (!empty($arr_avoid_id) || empty($ids)) - { - $this->setError(404, 'Id(s) not exists: '.implode(', ', $arr_avoid_id), 87); - $this->_outputEnabled = true; - } - } + if (!empty($arr_avoid_id) || empty($ids)) { + $this->setError(404, 'Id(s) not exists: '.implode(', ', $arr_avoid_id), 87); + $this->_outputEnabled = true; + } + } - protected function parseDisplayFields($str) - { - $bracket_level = 0; - $part = array(); - $tmp = ''; - $str_len = strlen($str); - for ($i = 0; $i < $str_len; $i++) - { - if ($str[$i] == ',' && $bracket_level == 0) - { - $part[] = $tmp; - $tmp = ''; - } - else - $tmp .= $str[$i]; - if ($str[$i] == '[') - $bracket_level++; - if ($str[$i] == ']') - $bracket_level--; - } - if ($tmp != '') - $part[] = $tmp; - $fields = array(); - foreach ($part as $str) - { - $field_name = trim(substr($str, 0, (strpos($str, '[') === false ? strlen($str) : strpos($str, '[')))); - if (!isset($fields[$field_name])) - $fields[$field_name] = null; - if (strpos($str, '[') !== false) - { - $sub_fields = substr($str, strpos($str, '[') + 1, strlen($str) - strpos($str, '[') - 2); - $tmp_array = array(); - if (strpos($sub_fields, ',') !== false) - $tmp_array = explode(',', $sub_fields); - else - $tmp_array = array($sub_fields); - $fields[$field_name] = (is_array($fields[$field_name])) ? array_merge($fields[$field_name], $tmp_array) : $tmp_array; - } - } - return $fields; - } + protected function parseDisplayFields($str) + { + $bracket_level = 0; + $part = array(); + $tmp = ''; + $str_len = strlen($str); + for ($i = 0; $i < $str_len; $i++) { + if ($str[$i] == ',' && $bracket_level == 0) { + $part[] = $tmp; + $tmp = ''; + } else { + $tmp .= $str[$i]; + } + if ($str[$i] == '[') { + $bracket_level++; + } + if ($str[$i] == ']') { + $bracket_level--; + } + } + if ($tmp != '') { + $part[] = $tmp; + } + $fields = array(); + foreach ($part as $str) { + $field_name = trim(substr($str, 0, (strpos($str, '[') === false ? strlen($str) : strpos($str, '[')))); + if (!isset($fields[$field_name])) { + $fields[$field_name] = null; + } + if (strpos($str, '[') !== false) { + $sub_fields = substr($str, strpos($str, '[') + 1, strlen($str) - strpos($str, '[') - 2); + $tmp_array = array(); + if (strpos($sub_fields, ',') !== false) { + $tmp_array = explode(',', $sub_fields); + } else { + $tmp_array = array($sub_fields); + } + $fields[$field_name] = (is_array($fields[$field_name])) ? array_merge($fields[$field_name], $tmp_array) : $tmp_array; + } + } + return $fields; + } - public function setFieldsToDisplay() - { - // set the fields to display in the list : "full", "minimum", "field_1", "field_1,field_2,field_3" - if (isset($this->urlFragments['display'])) - { - $this->fieldsToDisplay = $this->urlFragments['display']; - if ($this->fieldsToDisplay != 'full' && $this->fieldsToDisplay != 'minimum') - { - preg_match('#^\[(.*)\]$#Ui', $this->fieldsToDisplay, $matches); - if (count($matches)) - { - $error = false; - $fieldsToTest = $this->parseDisplayFields($matches[1]); - foreach ($fieldsToTest as $field_name => $part) - { - // in case it is not an association - if (!is_array($part)) - { - // We have to allow new specific field for price calculation too - $error = (!isset($this->resourceConfiguration['fields'][$field_name]) && !isset($this->urlFragments['price'][$field_name])); - } - else - { - // if this association does not exists - if (!array_key_exists($field_name, $this->resourceConfiguration['associations'])) - $error = true; + public function setFieldsToDisplay() + { + // set the fields to display in the list : "full", "minimum", "field_1", "field_1,field_2,field_3" + if (isset($this->urlFragments['display'])) { + $this->fieldsToDisplay = $this->urlFragments['display']; + if ($this->fieldsToDisplay != 'full' && $this->fieldsToDisplay != 'minimum') { + preg_match('#^\[(.*)\]$#Ui', $this->fieldsToDisplay, $matches); + if (count($matches)) { + $error = false; + $fieldsToTest = $this->parseDisplayFields($matches[1]); + foreach ($fieldsToTest as $field_name => $part) { + // in case it is not an association + if (!is_array($part)) { + // We have to allow new specific field for price calculation too + $error = (!isset($this->resourceConfiguration['fields'][$field_name]) && !isset($this->urlFragments['price'][$field_name])); + } else { + // if this association does not exists + if (!array_key_exists($field_name, $this->resourceConfiguration['associations'])) { + $error = true; + } - foreach ($part as $field) - if ($field != 'id' && !array_key_exists($field, $this->resourceConfiguration['associations'][$field_name]['fields'])) - { - $error = true; - break; - } - } - if ($error) - { - $this->setError(400, 'Unable to display this field "'.$field_name.(is_array($part) ? ' (details : '.var_export($part, true).')' : '').'". However, these are available: '.implode(', ', array_keys($this->resourceConfiguration['fields'])), 35); - return false; - } - } - $this->fieldsToDisplay = $fieldsToTest; - } - else - { - $this->setError(400, 'The \'display\' syntax is wrong. You can set \'full\' or \'[field_1,field_2,field_3,...]\'. These are available: '.implode(', ', array_keys($this->resourceConfiguration['fields'])), 36); - return false; - } - } - } - return true; - } + foreach ($part as $field) { + if ($field != 'id' && !array_key_exists($field, $this->resourceConfiguration['associations'][$field_name]['fields'])) { + $error = true; + break; + } + } + } + if ($error) { + $this->setError(400, 'Unable to display this field "'.$field_name.(is_array($part) ? ' (details : '.var_export($part, true).')' : '').'". However, these are available: '.implode(', ', array_keys($this->resourceConfiguration['fields'])), 35); + return false; + } + } + $this->fieldsToDisplay = $fieldsToTest; + } else { + $this->setError(400, 'The \'display\' syntax is wrong. You can set \'full\' or \'[field_1,field_2,field_3,...]\'. These are available: '.implode(', ', array_keys($this->resourceConfiguration['fields'])), 36); + return false; + } + } + } + return true; + } - protected function manageFilters() - { - // filtered fields which can not use filters : hidden_fields - $available_filters = array(); - // filtered i18n fields which can use filters - $i18n_available_filters = array(); - foreach ($this->resourceConfiguration['fields'] as $fieldName => $field) - if ((!isset($this->resourceConfiguration['hidden_fields']) || - (isset($this->resourceConfiguration['hidden_fields']) && !in_array($fieldName, $this->resourceConfiguration['hidden_fields'])))) - if ((!isset($field['i18n']) || - (isset($field['i18n']) && !$field['i18n']))) - $available_filters[] = $fieldName; - else - $i18n_available_filters[] = $fieldName; + protected function manageFilters() + { + // filtered fields which can not use filters : hidden_fields + $available_filters = array(); + // filtered i18n fields which can use filters + $i18n_available_filters = array(); + foreach ($this->resourceConfiguration['fields'] as $fieldName => $field) { + if ((!isset($this->resourceConfiguration['hidden_fields']) || + (isset($this->resourceConfiguration['hidden_fields']) && !in_array($fieldName, $this->resourceConfiguration['hidden_fields'])))) { + if ((!isset($field['i18n']) || + (isset($field['i18n']) && !$field['i18n']))) { + $available_filters[] = $fieldName; + } else { + $i18n_available_filters[] = $fieldName; + } + } + } - // Date feature : date=1 - if (!empty($this->urlFragments['date']) && $this->urlFragments['date']) - { - if (!in_array('date_add', $available_filters)) - $available_filters[] = 'date_add'; - if (!in_array('date_upd', $available_filters)) - $available_filters[] = 'date_upd'; - if (!array_key_exists('date_add', $this->resourceConfiguration['fields'])) - $this->resourceConfiguration['fields']['date_add'] = array('sqlId' => 'date_add'); - if (!array_key_exists('date_upd', $this->resourceConfiguration['fields'])) - $this->resourceConfiguration['fields']['date_upd'] = array('sqlId' => 'date_upd'); - } - else - foreach ($available_filters as $key => $value) - if ($value == 'date_add' || $value == 'date_upd') - unset($available_filters[$key]); + // Date feature : date=1 + if (!empty($this->urlFragments['date']) && $this->urlFragments['date']) { + if (!in_array('date_add', $available_filters)) { + $available_filters[] = 'date_add'; + } + if (!in_array('date_upd', $available_filters)) { + $available_filters[] = 'date_upd'; + } + if (!array_key_exists('date_add', $this->resourceConfiguration['fields'])) { + $this->resourceConfiguration['fields']['date_add'] = array('sqlId' => 'date_add'); + } + if (!array_key_exists('date_upd', $this->resourceConfiguration['fields'])) { + $this->resourceConfiguration['fields']['date_upd'] = array('sqlId' => 'date_upd'); + } + } else { + foreach ($available_filters as $key => $value) { + if ($value == 'date_add' || $value == 'date_upd') { + unset($available_filters[$key]); + } + } + } - //construct SQL filter - $sql_filter = ''; - $sql_join = ''; - if ($this->urlFragments) - { - $schema = 'schema'; - // if we have to display the schema - if (isset($this->urlFragments[$schema])) - { - if ($this->urlFragments[$schema] == 'blank' || $this->urlFragments[$schema] == 'synopsis') - { - $this->schemaToDisplay = $this->urlFragments[$schema]; - return true; - } - else - { - $this->setError(400, 'Please select a schema of type \'synopsis\' to get the whole schema informations (which fields are required, which kind of content...) or \'blank\' to get an empty schema to fill before using POST request', 28); - return false; - } - } - else - { - // if there are filters - if (isset($this->urlFragments['filter'])) - foreach ($this->urlFragments['filter'] as $field => $url_param) - { - if ($field != 'sort' && $field != 'limit') - { - if (!in_array($field, $available_filters)) - { - // if there are linked tables - if (isset($this->resourceConfiguration['linked_tables']) && isset($this->resourceConfiguration['linked_tables'][$field])) - { - // contruct SQL join for linked tables - $sql_join .= 'LEFT JOIN `'.bqSQL(_DB_PREFIX_.$this->resourceConfiguration['linked_tables'][$field]['table']).'` '.bqSQL($field).' ON (main.`'.bqSQL($this->resourceConfiguration['fields']['id']['sqlId']).'` = '.bqSQL($field).'.`'.bqSQL($this->resourceConfiguration['fields']['id']['sqlId']).'`)'."\n"; + //construct SQL filter + $sql_filter = ''; + $sql_join = ''; + if ($this->urlFragments) { + $schema = 'schema'; + // if we have to display the schema + if (isset($this->urlFragments[$schema])) { + if ($this->urlFragments[$schema] == 'blank' || $this->urlFragments[$schema] == 'synopsis') { + $this->schemaToDisplay = $this->urlFragments[$schema]; + return true; + } else { + $this->setError(400, 'Please select a schema of type \'synopsis\' to get the whole schema informations (which fields are required, which kind of content...) or \'blank\' to get an empty schema to fill before using POST request', 28); + return false; + } + } else { + // if there are filters + if (isset($this->urlFragments['filter'])) { + foreach ($this->urlFragments['filter'] as $field => $url_param) { + if ($field != 'sort' && $field != 'limit') { + if (!in_array($field, $available_filters)) { + // if there are linked tables + if (isset($this->resourceConfiguration['linked_tables']) && isset($this->resourceConfiguration['linked_tables'][$field])) { + // contruct SQL join for linked tables + $sql_join .= 'LEFT JOIN `'.bqSQL(_DB_PREFIX_.$this->resourceConfiguration['linked_tables'][$field]['table']).'` '.bqSQL($field).' ON (main.`'.bqSQL($this->resourceConfiguration['fields']['id']['sqlId']).'` = '.bqSQL($field).'.`'.bqSQL($this->resourceConfiguration['fields']['id']['sqlId']).'`)'."\n"; - // construct SQL filter for linked tables - foreach ($url_param as $field2 => $value) - { - if (isset($this->resourceConfiguration['linked_tables'][$field]['fields'][$field2])) - { - $linked_field = $this->resourceConfiguration['linked_tables'][$field]['fields'][$field2]; - $sql_filter .= $this->getSQLRetrieveFilter($linked_field['sqlId'], $value, $field.'.'); - } - else - { - $list = array_keys($this->resourceConfiguration['linked_tables'][$field]['fields']); - $this->setErrorDidYouMean(400, 'This filter does not exist for this linked table', $field2, $list, 29); - return false; - } - } - } - elseif ($url_param != '' && in_array($field, $i18n_available_filters)) - { - if (!is_array($url_param)) - $url_param = array($url_param); - $sql_join .= 'LEFT JOIN `'.bqSQL(_DB_PREFIX_.$this->resourceConfiguration['retrieveData']['table']).'_lang` AS main_i18n ON (main.`'.pSQL($this->resourceConfiguration['fields']['id']['sqlId']).'` = main_i18n.`'.bqSQL($this->resourceConfiguration['fields']['id']['sqlId']).'`)'."\n"; - foreach ($url_param as $field2 => $value) - { - $linked_field = $this->resourceConfiguration['fields'][$field]; - $sql_filter .= $this->getSQLRetrieveFilter($linked_field['sqlId'], $value, 'main_i18n.'); - $language_filter = '['.implode('|', $this->_available_languages).']'; - $sql_filter .= $this->getSQLRetrieveFilter('id_lang', $language_filter, 'main_i18n.'); - } - } - // if there are filters on linked tables but there are no linked table - elseif (is_array($url_param)) - { - if (isset($this->resourceConfiguration['linked_tables'])) - $this->setErrorDidYouMean(400, 'This linked table does not exist', $field, array_keys($this->resourceConfiguration['linked_tables']), 30); - else - $this->setError(400, 'There is no existing linked table for this resource', 31); - return false; - } - else - { - $this->setErrorDidYouMean(400, 'This filter does not exist', $field, $available_filters, 32); - return false; - } - } - elseif ($url_param == '') - { - $this->setError(400, 'The filter "'.$field.'" is malformed.', 33); - return false; - } - else - { - if (isset($this->resourceConfiguration['fields'][$field]['getter'])) - { - $this->setError(400, 'The field "'.$field.'" is dynamic. It is not possible to filter GET query with this field.', 34); - return false; - } - else - { - if (isset($this->resourceConfiguration['retrieveData']['tableAlias'])) - $sql_filter .= $this->getSQLRetrieveFilter($this->resourceConfiguration['fields'][$field]['sqlId'], $url_param, $this->resourceConfiguration['retrieveData']['tableAlias'].'.'); - else - $sql_filter .= $this->getSQLRetrieveFilter($this->resourceConfiguration['fields'][$field]['sqlId'], $url_param); - } - } - } - } - } - } + // construct SQL filter for linked tables + foreach ($url_param as $field2 => $value) { + if (isset($this->resourceConfiguration['linked_tables'][$field]['fields'][$field2])) { + $linked_field = $this->resourceConfiguration['linked_tables'][$field]['fields'][$field2]; + $sql_filter .= $this->getSQLRetrieveFilter($linked_field['sqlId'], $value, $field.'.'); + } else { + $list = array_keys($this->resourceConfiguration['linked_tables'][$field]['fields']); + $this->setErrorDidYouMean(400, 'This filter does not exist for this linked table', $field2, $list, 29); + return false; + } + } + } elseif ($url_param != '' && in_array($field, $i18n_available_filters)) { + if (!is_array($url_param)) { + $url_param = array($url_param); + } + $sql_join .= 'LEFT JOIN `'.bqSQL(_DB_PREFIX_.$this->resourceConfiguration['retrieveData']['table']).'_lang` AS main_i18n ON (main.`'.pSQL($this->resourceConfiguration['fields']['id']['sqlId']).'` = main_i18n.`'.bqSQL($this->resourceConfiguration['fields']['id']['sqlId']).'`)'."\n"; + foreach ($url_param as $field2 => $value) { + $linked_field = $this->resourceConfiguration['fields'][$field]; + $sql_filter .= $this->getSQLRetrieveFilter($linked_field['sqlId'], $value, 'main_i18n.'); + $language_filter = '['.implode('|', $this->_available_languages).']'; + $sql_filter .= $this->getSQLRetrieveFilter('id_lang', $language_filter, 'main_i18n.'); + } + } + // if there are filters on linked tables but there are no linked table + elseif (is_array($url_param)) { + if (isset($this->resourceConfiguration['linked_tables'])) { + $this->setErrorDidYouMean(400, 'This linked table does not exist', $field, array_keys($this->resourceConfiguration['linked_tables']), 30); + } else { + $this->setError(400, 'There is no existing linked table for this resource', 31); + } + return false; + } else { + $this->setErrorDidYouMean(400, 'This filter does not exist', $field, $available_filters, 32); + return false; + } + } elseif ($url_param == '') { + $this->setError(400, 'The filter "'.$field.'" is malformed.', 33); + return false; + } else { + if (isset($this->resourceConfiguration['fields'][$field]['getter'])) { + $this->setError(400, 'The field "'.$field.'" is dynamic. It is not possible to filter GET query with this field.', 34); + return false; + } else { + if (isset($this->resourceConfiguration['retrieveData']['tableAlias'])) { + $sql_filter .= $this->getSQLRetrieveFilter($this->resourceConfiguration['fields'][$field]['sqlId'], $url_param, $this->resourceConfiguration['retrieveData']['tableAlias'].'.'); + } else { + $sql_filter .= $this->getSQLRetrieveFilter($this->resourceConfiguration['fields'][$field]['sqlId'], $url_param); + } + } + } + } + } + } + } + } - if (!$this->setFieldsToDisplay()) - return false; - // construct SQL Sort - $sql_sort = ''; - if (isset($this->urlFragments['sort'])) - { - preg_match('#^\[(.*)\]$#Ui', $this->urlFragments['sort'], $matches); - if (count($matches) > 1) - $sorts = explode(',', $matches[1]); - else - $sorts = array($this->urlFragments['sort']); + if (!$this->setFieldsToDisplay()) { + return false; + } + // construct SQL Sort + $sql_sort = ''; + if (isset($this->urlFragments['sort'])) { + preg_match('#^\[(.*)\]$#Ui', $this->urlFragments['sort'], $matches); + if (count($matches) > 1) { + $sorts = explode(',', $matches[1]); + } else { + $sorts = array($this->urlFragments['sort']); + } - $sql_sort .= ' ORDER BY '; + $sql_sort .= ' ORDER BY '; - foreach ($sorts as $sort) - { - $delimiterPosition = strrpos($sort, '_'); - if ($delimiterPosition !== false) - { - $fieldName = substr($sort, 0, $delimiterPosition); - $direction = strtoupper(substr($sort, $delimiterPosition + 1)); - } - if ($delimiterPosition === false || !in_array($direction, array('ASC', 'DESC'))) - { - $this->setError(400, 'The "sort" value has to be formed as this example: "field_ASC" or \'[field_1_DESC,field_2_ASC,field_3_ASC,...]\' ("field" has to be an available field)', 37); - return false; - } - elseif (!in_array($fieldName, $available_filters) && !in_array($fieldName, $i18n_available_filters)) - { - $this->setError(400, 'Unable to filter by this field. However, these are available: '.implode(', ', $available_filters).', for i18n fields:'.implode(', ', $i18n_available_filters), 38); - return false; - } - // for sort on i18n field - elseif (in_array($fieldName, $i18n_available_filters)) - { - if (!preg_match('#main_i18n#', $sql_join)) - $sql_join .= 'LEFT JOIN `'._DB_PREFIX_.pSQL($this->resourceConfiguration['retrieveData']['table']).'_lang` AS main_i18n ON (main.`'.pSQL($this->resourceConfiguration['fields']['id']['sqlId']).'` = main_i18n.`'.pSQL($this->resourceConfiguration['fields']['id']['sqlId']).'`)'."\n"; - $sql_sort .= 'main_i18n.`'.pSQL($this->resourceConfiguration['fields'][$fieldName]['sqlId']).'` '.$direction.', ';// ORDER BY main_i18n.`field` ASC|DESC - } - else - { - /** @var ObjectModel $object */ - $object = new $this->resourceConfiguration['retrieveData']['className'](); - $assoc = Shop::getAssoTable($this->resourceConfiguration['retrieveData']['table']); - if ($assoc !== false && $assoc['type'] == 'shop' && ($object->isMultiShopField($this->resourceConfiguration['fields'][$fieldName]['sqlId']) || $fieldName == 'id')) - $table_alias = 'multi_shop_'.$this->resourceConfiguration['retrieveData']['table']; - else - $table_alias = ''; - $sql_sort .= (isset($this->resourceConfiguration['retrieveData']['tableAlias']) ? '`'.bqSQL($this->resourceConfiguration['retrieveData']['tableAlias']).'`.' : '`'.bqSQL($table_alias).'`.').'`'.pSQL($this->resourceConfiguration['fields'][$fieldName]['sqlId']).'` '.$direction.', ';// ORDER BY `field` ASC|DESC - } - } - $sql_sort = rtrim($sql_sort, ', ')."\n"; - } + foreach ($sorts as $sort) { + $delimiterPosition = strrpos($sort, '_'); + if ($delimiterPosition !== false) { + $fieldName = substr($sort, 0, $delimiterPosition); + $direction = strtoupper(substr($sort, $delimiterPosition + 1)); + } + if ($delimiterPosition === false || !in_array($direction, array('ASC', 'DESC'))) { + $this->setError(400, 'The "sort" value has to be formed as this example: "field_ASC" or \'[field_1_DESC,field_2_ASC,field_3_ASC,...]\' ("field" has to be an available field)', 37); + return false; + } elseif (!in_array($fieldName, $available_filters) && !in_array($fieldName, $i18n_available_filters)) { + $this->setError(400, 'Unable to filter by this field. However, these are available: '.implode(', ', $available_filters).', for i18n fields:'.implode(', ', $i18n_available_filters), 38); + return false; + } + // for sort on i18n field + elseif (in_array($fieldName, $i18n_available_filters)) { + if (!preg_match('#main_i18n#', $sql_join)) { + $sql_join .= 'LEFT JOIN `'._DB_PREFIX_.pSQL($this->resourceConfiguration['retrieveData']['table']).'_lang` AS main_i18n ON (main.`'.pSQL($this->resourceConfiguration['fields']['id']['sqlId']).'` = main_i18n.`'.pSQL($this->resourceConfiguration['fields']['id']['sqlId']).'`)'."\n"; + } + $sql_sort .= 'main_i18n.`'.pSQL($this->resourceConfiguration['fields'][$fieldName]['sqlId']).'` '.$direction.', ';// ORDER BY main_i18n.`field` ASC|DESC + } else { + /** @var ObjectModel $object */ + $object = new $this->resourceConfiguration['retrieveData']['className'](); + $assoc = Shop::getAssoTable($this->resourceConfiguration['retrieveData']['table']); + if ($assoc !== false && $assoc['type'] == 'shop' && ($object->isMultiShopField($this->resourceConfiguration['fields'][$fieldName]['sqlId']) || $fieldName == 'id')) { + $table_alias = 'multi_shop_'.$this->resourceConfiguration['retrieveData']['table']; + } else { + $table_alias = ''; + } + $sql_sort .= (isset($this->resourceConfiguration['retrieveData']['tableAlias']) ? '`'.bqSQL($this->resourceConfiguration['retrieveData']['tableAlias']).'`.' : '`'.bqSQL($table_alias).'`.').'`'.pSQL($this->resourceConfiguration['fields'][$fieldName]['sqlId']).'` '.$direction.', ';// ORDER BY `field` ASC|DESC + } + } + $sql_sort = rtrim($sql_sort, ', ')."\n"; + } - //construct SQL Limit - $sql_limit = ''; - if (isset($this->urlFragments['limit'])) - { - $limitArgs = explode(',', $this->urlFragments['limit']); - if (count($limitArgs) > 2) - { - $this->setError(400, 'The "limit" value has to be formed as this example: "5,25" or "10"', 39); - return false; - } - else - { - $sql_limit .= ' LIMIT '.(int)($limitArgs[0]).(isset($limitArgs[1]) ? ', '.(int)($limitArgs[1]) : '')."\n";// LIMIT X|X, Y - } - } - $filters['sql_join'] = $sql_join; - $filters['sql_filter'] = $sql_filter; - $filters['sql_sort'] = $sql_sort; - $filters['sql_limit'] = $sql_limit; + //construct SQL Limit + $sql_limit = ''; + if (isset($this->urlFragments['limit'])) { + $limitArgs = explode(',', $this->urlFragments['limit']); + if (count($limitArgs) > 2) { + $this->setError(400, 'The "limit" value has to be formed as this example: "5,25" or "10"', 39); + return false; + } else { + $sql_limit .= ' LIMIT '.(int)($limitArgs[0]).(isset($limitArgs[1]) ? ', '.(int)($limitArgs[1]) : '')."\n";// LIMIT X|X, Y + } + } + $filters['sql_join'] = $sql_join; + $filters['sql_filter'] = $sql_filter; + $filters['sql_sort'] = $sql_sort; + $filters['sql_limit'] = $sql_limit; - return $filters; - } + return $filters; + } - public function getFilteredObjectList() - { - $objects = array(); - $filters = $this->manageFilters(); + public function getFilteredObjectList() + { + $objects = array(); + $filters = $this->manageFilters(); - /* If we only need to display the synopsis, analyzing the first row is sufficient */ - if (isset($this->urlFragments['schema']) && in_array($this->urlFragments['schema'], array('blank', 'synopsis'))) - $filters = array('sql_join' => '', 'sql_filter' => '', 'sql_sort' => '', 'sql_limit' => ' LIMIT 1'); + /* If we only need to display the synopsis, analyzing the first row is sufficient */ + if (isset($this->urlFragments['schema']) && in_array($this->urlFragments['schema'], array('blank', 'synopsis'))) { + $filters = array('sql_join' => '', 'sql_filter' => '', 'sql_sort' => '', 'sql_limit' => ' LIMIT 1'); + } - $this->resourceConfiguration['retrieveData']['params'][] = $filters['sql_join']; - $this->resourceConfiguration['retrieveData']['params'][] = $filters['sql_filter']; - $this->resourceConfiguration['retrieveData']['params'][] = $filters['sql_sort']; - $this->resourceConfiguration['retrieveData']['params'][] = $filters['sql_limit']; - //list entities + $this->resourceConfiguration['retrieveData']['params'][] = $filters['sql_join']; + $this->resourceConfiguration['retrieveData']['params'][] = $filters['sql_filter']; + $this->resourceConfiguration['retrieveData']['params'][] = $filters['sql_sort']; + $this->resourceConfiguration['retrieveData']['params'][] = $filters['sql_limit']; + //list entities - $tmp = new $this->resourceConfiguration['retrieveData']['className'](); - $sqlObjects = call_user_func_array(array($tmp, $this->resourceConfiguration['retrieveData']['retrieveMethod']), $this->resourceConfiguration['retrieveData']['params']); - if ($sqlObjects) - { - foreach ($sqlObjects as $sqlObject) - { - if ($this->fieldsToDisplay == 'minimum') - { - $obj = new $this->resourceConfiguration['retrieveData']['className'](); - $obj->id = (int)$sqlObject[$this->resourceConfiguration['fields']['id']['sqlId']]; - $objects[] = $obj; - } - else - $objects[] = new $this->resourceConfiguration['retrieveData']['className']((int)$sqlObject[$this->resourceConfiguration['fields']['id']['sqlId']]); - } - return $objects; - } - } + $tmp = new $this->resourceConfiguration['retrieveData']['className'](); + $sqlObjects = call_user_func_array(array($tmp, $this->resourceConfiguration['retrieveData']['retrieveMethod']), $this->resourceConfiguration['retrieveData']['params']); + if ($sqlObjects) { + foreach ($sqlObjects as $sqlObject) { + if ($this->fieldsToDisplay == 'minimum') { + $obj = new $this->resourceConfiguration['retrieveData']['className'](); + $obj->id = (int)$sqlObject[$this->resourceConfiguration['fields']['id']['sqlId']]; + $objects[] = $obj; + } else { + $objects[] = new $this->resourceConfiguration['retrieveData']['className']((int)$sqlObject[$this->resourceConfiguration['fields']['id']['sqlId']]); + } + } + return $objects; + } + } - public function getFilteredObjectDetails() - { - $objects = array(); - if (!isset($this->urlFragments['display'])) - $this->fieldsToDisplay = 'full'; + public function getFilteredObjectDetails() + { + $objects = array(); + if (!isset($this->urlFragments['display'])) { + $this->fieldsToDisplay = 'full'; + } - //get entity details - $object = new $this->resourceConfiguration['retrieveData']['className']((int)$this->urlSegment[1]); - if ($object->id) - { - $objects[] = $object; - // Check if Object is accessible for this/those id_shop - $assoc = Shop::getAssoTable($this->resourceConfiguration['retrieveData']['table']); - if ($assoc !== false) - { - $check_shop_group = false; + //get entity details + $object = new $this->resourceConfiguration['retrieveData']['className']((int)$this->urlSegment[1]); + if ($object->id) { + $objects[] = $object; + // Check if Object is accessible for this/those id_shop + $assoc = Shop::getAssoTable($this->resourceConfiguration['retrieveData']['table']); + if ($assoc !== false) { + $check_shop_group = false; - $sql = 'SELECT 1 + $sql = 'SELECT 1 FROM `'.bqSQL(_DB_PREFIX_.$this->resourceConfiguration['retrieveData']['table']); - if ($assoc['type'] != 'fk_shop') - $sql .= '_'.$assoc['type']; - else - { - $def = ObjectModel::getDefinition($this->resourceConfiguration['retrieveData']['className']); - if (isset($def['fields']) && isset($def['fields']['id_shop_group'])) - $check_shop_group = true; - } - $sql .= '`'; + if ($assoc['type'] != 'fk_shop') { + $sql .= '_'.$assoc['type']; + } else { + $def = ObjectModel::getDefinition($this->resourceConfiguration['retrieveData']['className']); + if (isset($def['fields']) && isset($def['fields']['id_shop_group'])) { + $check_shop_group = true; + } + } + $sql .= '`'; - foreach (self::$shopIDs as $id_shop) - $OR[] = ' (id_shop = '.(int)$id_shop.($check_shop_group ? ' OR (id_shop = 0 AND id_shop_group='.(int)Shop::getGroupFromShop((int)$id_shop).')' : '').') '; + foreach (self::$shopIDs as $id_shop) { + $OR[] = ' (id_shop = '.(int)$id_shop.($check_shop_group ? ' OR (id_shop = 0 AND id_shop_group='.(int)Shop::getGroupFromShop((int)$id_shop).')' : '').') '; + } - $check = ' WHERE ('.implode('OR', $OR).') AND `'.bqSQL($this->resourceConfiguration['fields']['id']['sqlId']).'` = '.(int)$this->urlSegment[1]; - if (!Db::getInstance()->getValue($sql.$check)) - $this->setError(404, 'This '.$this->resourceConfiguration['retrieveData']['className'].' ('.(int)$this->urlSegment[1].') does not exists on this shop', 131); - } - return $objects; - } - if (!count($this->errors)) - { - $this->objOutput->setStatus(404); - $this->_outputEnabled = false; - return false; - } - } + $check = ' WHERE ('.implode('OR', $OR).') AND `'.bqSQL($this->resourceConfiguration['fields']['id']['sqlId']).'` = '.(int)$this->urlSegment[1]; + if (!Db::getInstance()->getValue($sql.$check)) { + $this->setError(404, 'This '.$this->resourceConfiguration['retrieveData']['className'].' ('.(int)$this->urlSegment[1].') does not exists on this shop', 131); + } + } + return $objects; + } + if (!count($this->errors)) { + $this->objOutput->setStatus(404); + $this->_outputEnabled = false; + return false; + } + } - /** - * Execute GET and HEAD requests - * - * Build filter - * Build fields display - * Build sort - * Build limit - * - * @return bool - */ - public function executeEntityGetAndHead() - { - if ($this->resourceConfiguration['objectsNodeName'] != 'resources') - { - if (!isset($this->urlSegment[1]) || !strlen($this->urlSegment[1])) - $return = $this->getFilteredObjectList(); - else - $return = $this->getFilteredObjectDetails(); + /** + * Execute GET and HEAD requests + * + * Build filter + * Build fields display + * Build sort + * Build limit + * + * @return bool + */ + public function executeEntityGetAndHead() + { + if ($this->resourceConfiguration['objectsNodeName'] != 'resources') { + if (!isset($this->urlSegment[1]) || !strlen($this->urlSegment[1])) { + $return = $this->getFilteredObjectList(); + } else { + $return = $this->getFilteredObjectDetails(); + } - if (!$return) - return false; - else - $this->objects = $return; - } - return true; - } + if (!$return) { + return false; + } else { + $this->objects = $return; + } + } + return true; + } - /** - * Execute POST method on a PrestaShop entity - * - * @return bool - */ - protected function executeEntityPost() - { - return $this->saveEntityFromXml(201); - } + /** + * Execute POST method on a PrestaShop entity + * + * @return bool + */ + protected function executeEntityPost() + { + return $this->saveEntityFromXml(201); + } - /** - * Execute PUT method on a PrestaShop entity - * - * @return bool - */ - protected function executeEntityPut() - { - return $this->saveEntityFromXml(200); - } + /** + * Execute PUT method on a PrestaShop entity + * + * @return bool + */ + protected function executeEntityPut() + { + return $this->saveEntityFromXml(200); + } - /** - * Execute DELETE method on a PrestaShop entity - * - * @return bool - */ - protected function executeEntityDelete() - { - $objects = array(); - $arr_avoid_id = array(); - $ids = array(); - if (isset($this->urlFragments['id'])) - { - preg_match('#^\[(.*)\]$#Ui', $this->urlFragments['id'], $matches); - if (count($matches) > 1) - $ids = explode(',', $matches[1]); - } - else - $ids[] = (int)$this->urlSegment[1]; - if (!empty($ids)) - { - foreach ($ids as $id) - { - $object = new $this->resourceConfiguration['retrieveData']['className']((int)$id); - if (!$object->id) - $arr_avoid_id[] = $id; - else - $objects[] = $object; - } - } + /** + * Execute DELETE method on a PrestaShop entity + * + * @return bool + */ + protected function executeEntityDelete() + { + $objects = array(); + $arr_avoid_id = array(); + $ids = array(); + if (isset($this->urlFragments['id'])) { + preg_match('#^\[(.*)\]$#Ui', $this->urlFragments['id'], $matches); + if (count($matches) > 1) { + $ids = explode(',', $matches[1]); + } + } else { + $ids[] = (int)$this->urlSegment[1]; + } + if (!empty($ids)) { + foreach ($ids as $id) { + $object = new $this->resourceConfiguration['retrieveData']['className']((int)$id); + if (!$object->id) { + $arr_avoid_id[] = $id; + } else { + $objects[] = $object; + } + } + } - if (!empty($arr_avoid_id) || empty($ids)) - { - $this->setError(404, 'Id(s) not exists: '.implode(', ', $arr_avoid_id), 87); - $this->_outputEnabled = true; - } - else - { - foreach ($objects as $object) - { - /** @var ObjectModel $object */ - if (isset($this->resourceConfiguration['objectMethods']) && isset($this->resourceConfiguration['objectMethods']['delete'])) - $result = $object->{$this->resourceConfiguration['objectMethods']['delete']}(); - else - $result = $object->delete(); + if (!empty($arr_avoid_id) || empty($ids)) { + $this->setError(404, 'Id(s) not exists: '.implode(', ', $arr_avoid_id), 87); + $this->_outputEnabled = true; + } else { + foreach ($objects as $object) { + /** @var ObjectModel $object */ + if (isset($this->resourceConfiguration['objectMethods']) && isset($this->resourceConfiguration['objectMethods']['delete'])) { + $result = $object->{$this->resourceConfiguration['objectMethods']['delete']}(); + } else { + $result = $object->delete(); + } - if (!$result) - $arr_avoid_id[] = $object->id; - } - if (!empty($arr_avoid_id)) - { - $this->setError(500, 'Id(s) wasn\'t deleted: '.implode(', ', $arr_avoid_id), 88); - $this->_outputEnabled = true; - } - else - $this->_outputEnabled = false; - } - } + if (!$result) { + $arr_avoid_id[] = $object->id; + } + } + if (!empty($arr_avoid_id)) { + $this->setError(500, 'Id(s) wasn\'t deleted: '.implode(', ', $arr_avoid_id), 88); + $this->_outputEnabled = true; + } else { + $this->_outputEnabled = false; + } + } + } - /** - * save Entity Object from XML - * - * @param int $successReturnCode - * @return bool - */ - protected function saveEntityFromXml($successReturnCode) - { - try - { - $xml = new SimpleXMLElement($this->_inputXml); - } - catch (Exception $error) - { - $this->setError(500, 'XML error : '.$error->getMessage()."\n".'XML length : '.strlen($this->_inputXml)."\n".'Original XML : '.$this->_inputXml, 127); - return; - } + /** + * save Entity Object from XML + * + * @param int $successReturnCode + * @return bool + */ + protected function saveEntityFromXml($successReturnCode) + { + try { + $xml = new SimpleXMLElement($this->_inputXml); + } catch (Exception $error) { + $this->setError(500, 'XML error : '.$error->getMessage()."\n".'XML length : '.strlen($this->_inputXml)."\n".'Original XML : '.$this->_inputXml, 127); + return; + } - /** @var SimpleXMLElement|Countable $xmlEntities */ - $xmlEntities = $xml->children(); - $object = null; + /** @var SimpleXMLElement|Countable $xmlEntities */ + $xmlEntities = $xml->children(); + $object = null; - $ids = array(); - foreach ($xmlEntities as $entity) - { - // To cast in string allow to check null values - if ((string)$entity->id != '') - $ids[] = (int)$entity->id; - } - if ($this->method == 'PUT') - { - $ids2 = array(); - $ids2 = array_unique($ids); - if (count($ids2) != count($ids)) - { - $this->setError(400, 'id is duplicate in request', 89); - return false; - } - if (count($xmlEntities) != count($ids)) - { - $this->setError(400, 'id is required when modifying a resource', 90); - return false; - } - } - elseif ($this->method == 'POST' && count($ids) > 0) - { - $this->setError(400, 'id is forbidden when adding a new resource', 91); - return false; - } + $ids = array(); + foreach ($xmlEntities as $entity) { + // To cast in string allow to check null values + if ((string)$entity->id != '') { + $ids[] = (int)$entity->id; + } + } + if ($this->method == 'PUT') { + $ids2 = array(); + $ids2 = array_unique($ids); + if (count($ids2) != count($ids)) { + $this->setError(400, 'id is duplicate in request', 89); + return false; + } + if (count($xmlEntities) != count($ids)) { + $this->setError(400, 'id is required when modifying a resource', 90); + return false; + } + } elseif ($this->method == 'POST' && count($ids) > 0) { + $this->setError(400, 'id is forbidden when adding a new resource', 91); + return false; + } - foreach ($xmlEntities as $xmlEntity) - { - /** @var SimpleXMLElement $xmlEntity */ - $attributes = $xmlEntity->children(); + foreach ($xmlEntities as $xmlEntity) { + /** @var SimpleXMLElement $xmlEntity */ + $attributes = $xmlEntity->children(); - /** @var ObjectModel $object */ - if ($this->method == 'POST') - $object = new $this->resourceConfiguration['retrieveData']['className'](); - elseif ($this->method == 'PUT') - { - $object = new $this->resourceConfiguration['retrieveData']['className']((int)$attributes->id); - if (!$object->id) - { - $this->setError(404, 'Invalid ID', 92); - return false; - } - } - $this->objects[] = $object; - $i18n = false; - // attributes - foreach ($this->resourceConfiguration['fields'] as $fieldName => $fieldProperties) - { - $sqlId = $fieldProperties['sqlId']; + /** @var ObjectModel $object */ + if ($this->method == 'POST') { + $object = new $this->resourceConfiguration['retrieveData']['className'](); + } elseif ($this->method == 'PUT') { + $object = new $this->resourceConfiguration['retrieveData']['className']((int)$attributes->id); + if (!$object->id) { + $this->setError(404, 'Invalid ID', 92); + return false; + } + } + $this->objects[] = $object; + $i18n = false; + // attributes + foreach ($this->resourceConfiguration['fields'] as $fieldName => $fieldProperties) { + $sqlId = $fieldProperties['sqlId']; - if ($fieldName == 'id') - $sqlId = $fieldName; - if (isset($attributes->$fieldName) && isset($fieldProperties['sqlId']) && (!isset($fieldProperties['i18n']) || !$fieldProperties['i18n'])) - { - if (isset($fieldProperties['setter'])) - { - // if we have to use a specific setter - if (!$fieldProperties['setter']) - { - // if it's forbidden to set this field - $this->setError(400, 'parameter "'.$fieldName.'" not writable. Please remove this attribute of this XML', 93); - return false; - } - else - $object->$fieldProperties['setter']((string)$attributes->$fieldName); - } - elseif (property_exists($object, $sqlId)) - $object->$sqlId = (string)$attributes->$fieldName; - else - $this->setError(400, 'Parameter "'.$fieldName.'" can\'t be set to the object "'.$this->resourceConfiguration['retrieveData']['className'].'"', 123); + if ($fieldName == 'id') { + $sqlId = $fieldName; + } + if (isset($attributes->$fieldName) && isset($fieldProperties['sqlId']) && (!isset($fieldProperties['i18n']) || !$fieldProperties['i18n'])) { + if (isset($fieldProperties['setter'])) { + // if we have to use a specific setter + if (!$fieldProperties['setter']) { + // if it's forbidden to set this field + $this->setError(400, 'parameter "'.$fieldName.'" not writable. Please remove this attribute of this XML', 93); + return false; + } else { + $object->$fieldProperties['setter']((string)$attributes->$fieldName); + } + } elseif (property_exists($object, $sqlId)) { + $object->$sqlId = (string)$attributes->$fieldName; + } else { + $this->setError(400, 'Parameter "'.$fieldName.'" can\'t be set to the object "'.$this->resourceConfiguration['retrieveData']['className'].'"', 123); + } + } elseif (isset($fieldProperties['required']) && $fieldProperties['required'] && !$fieldProperties['i18n']) { + $this->setError(400, 'parameter "'.$fieldName.'" required', 41); + return false; + } elseif ((!isset($fieldProperties['required']) || !$fieldProperties['required']) && property_exists($object, $sqlId)) { + $object->$sqlId = null; + } + if (isset($fieldProperties['i18n']) && $fieldProperties['i18n']) { + $i18n = true; + if (isset($attributes->$fieldName, $attributes->$fieldName->language)) { + foreach ($attributes->$fieldName->language as $lang) { + /** @var SimpleXMLElement $lang */ + $object->{$fieldName}[(int)$lang->attributes()->id] = (string)$lang; + } + } else { + $object->{$fieldName} = (string)$attributes->$fieldName; + } + } + } - } - elseif (isset($fieldProperties['required']) && $fieldProperties['required'] && !$fieldProperties['i18n']) - { - $this->setError(400, 'parameter "'.$fieldName.'" required', 41); - return false; - } - elseif ((!isset($fieldProperties['required']) || !$fieldProperties['required']) && property_exists($object, $sqlId)) - $object->$sqlId = null; - if (isset($fieldProperties['i18n']) && $fieldProperties['i18n']) - { - $i18n = true; - if (isset($attributes->$fieldName, $attributes->$fieldName->language)) - foreach ($attributes->$fieldName->language as $lang) - { - /** @var SimpleXMLElement $lang */ - $object->{$fieldName}[(int)$lang->attributes()->id] = (string)$lang; - } - else - $object->{$fieldName} = (string)$attributes->$fieldName; - } - } + // Apply the modifiers if they exist + foreach ($this->resourceConfiguration['fields'] as $fieldName => $fieldProperties) { + if (isset($fieldProperties['modifier']) && isset($fieldProperties['modifier']['modifier']) && $fieldProperties['modifier']['http_method'] & constant('WebserviceRequest::HTTP_'.$this->method)) { + $object->{$fieldProperties['modifier']['modifier']}(); + } + } - // Apply the modifiers if they exist - foreach ($this->resourceConfiguration['fields'] as $fieldName => $fieldProperties) - { - if (isset($fieldProperties['modifier']) && isset($fieldProperties['modifier']['modifier']) && $fieldProperties['modifier']['http_method'] & constant('WebserviceRequest::HTTP_'.$this->method)) - $object->{$fieldProperties['modifier']['modifier']}(); - } + if (!$this->hasErrors()) { + if ($i18n && ($retValidateFieldsLang = $object->validateFieldsLang(false, true)) !== true) { + $this->setError(400, 'Validation error: "'.$retValidateFieldsLang.'"', 84); + return false; + } elseif (($retValidateFields = $object->validateFields(false, true)) !== true) { + $this->setError(400, 'Validation error: "'.$retValidateFields.'"', 85); + return false; + } else { + // Call alternative method for add/update + $objectMethod = ($this->method == 'POST' ? 'add' : 'update'); + if (isset($this->resourceConfiguration['objectMethods']) && array_key_exists($objectMethod, $this->resourceConfiguration['objectMethods'])) { + $objectMethod = $this->resourceConfiguration['objectMethods'][$objectMethod]; + } + $result = $object->{$objectMethod}(); + if ($result) { + if (isset($attributes->associations)) { + foreach ($attributes->associations->children() as $association) { + /** @var SimpleXMLElement $association */ + // associations + if (isset($this->resourceConfiguration['associations'][$association->getName()])) { + $assocItems = $association->children(); + $values = array(); + foreach ($assocItems as $assocItem) { + /** @var SimpleXMLElement $assocItem */ + $fields = $assocItem->children(); + $entry = array(); + foreach ($fields as $fieldName => $fieldValue) { + $entry[$fieldName] = (string)$fieldValue; + } + $values[] = $entry; + } + $setter = $this->resourceConfiguration['associations'][$association->getName()]['setter']; + if (!is_null($setter) && $setter && method_exists($object, $setter) && !$object->$setter($values)) { + $this->setError(500, 'Error occurred while setting the '.$association->getName().' value', 85); + return false; + } + } elseif ($association->getName() != 'i18n') { + $this->setError(400, 'The association "'.$association->getName().'" does not exists', 86); + return false; + } + } + } + $assoc = Shop::getAssoTable($this->resourceConfiguration['retrieveData']['table']); + if ($assoc !== false && $assoc['type'] != 'fk_shop') { + // PUT nor POST is destructive, no deletion + $sql = 'INSERT IGNORE INTO `'.bqSQL(_DB_PREFIX_.$this->resourceConfiguration['retrieveData']['table'].'_'.$assoc['type']).'` (id_shop, '.pSQL($this->resourceConfiguration['fields']['id']['sqlId']).') VALUES '; + foreach (self::$shopIDs as $id) { + $sql .= '('.(int)$id.','.(int)$object->id.')'; + if ($id != end(self::$shopIDs)) { + $sql .= ', '; + } + } + Db::getInstance()->execute($sql); + } + } else { + $this->setError(500, 'Unable to save resource', 46); + } + } + } + } + if (!$this->hasErrors()) { + $this->objOutput->setStatus($successReturnCode); + return true; + } + } - if (!$this->hasErrors()) - { - if ($i18n && ($retValidateFieldsLang = $object->validateFieldsLang(false, true)) !== true) - { - $this->setError(400, 'Validation error: "'.$retValidateFieldsLang.'"', 84); - return false; - } - elseif (($retValidateFields = $object->validateFields(false, true)) !== true) - { - $this->setError(400, 'Validation error: "'.$retValidateFields.'"', 85); - return false; - } - else - { - // Call alternative method for add/update - $objectMethod = ($this->method == 'POST' ? 'add' : 'update'); - if (isset($this->resourceConfiguration['objectMethods']) && array_key_exists($objectMethod, $this->resourceConfiguration['objectMethods'])) - $objectMethod = $this->resourceConfiguration['objectMethods'][$objectMethod]; - $result = $object->{$objectMethod}(); - if ($result) - { - if (isset($attributes->associations)) - foreach ($attributes->associations->children() as $association) - { - /** @var SimpleXMLElement $association */ - // associations - if (isset($this->resourceConfiguration['associations'][$association->getName()])) - { - $assocItems = $association->children(); - $values = array(); - foreach ($assocItems as $assocItem) - { - /** @var SimpleXMLElement $assocItem */ - $fields = $assocItem->children(); - $entry = array(); - foreach ($fields as $fieldName => $fieldValue) - $entry[$fieldName] = (string)$fieldValue; - $values[] = $entry; - } - $setter = $this->resourceConfiguration['associations'][$association->getName()]['setter']; - if (!is_null($setter) && $setter && method_exists($object, $setter) && !$object->$setter($values)) - { - $this->setError(500, 'Error occurred while setting the '.$association->getName().' value', 85); - return false; - } - } - elseif ($association->getName() != 'i18n') - { - $this->setError(400, 'The association "'.$association->getName().'" does not exists', 86); - return false; - } - } - $assoc = Shop::getAssoTable($this->resourceConfiguration['retrieveData']['table']); - if ($assoc !== false && $assoc['type'] != 'fk_shop') - { - // PUT nor POST is destructive, no deletion - $sql = 'INSERT IGNORE INTO `'.bqSQL(_DB_PREFIX_.$this->resourceConfiguration['retrieveData']['table'].'_'.$assoc['type']).'` (id_shop, '.pSQL($this->resourceConfiguration['fields']['id']['sqlId']).') VALUES '; - foreach (self::$shopIDs as $id) - { - $sql .= '('.(int)$id.','.(int)$object->id.')'; - if ($id != end(self::$shopIDs)) - $sql .= ', '; - } - Db::getInstance()->execute($sql); - } - } - else - $this->setError(500, 'Unable to save resource', 46); - } - } - } - if (!$this->hasErrors()) - { - $this->objOutput->setStatus($successReturnCode); - return true; - } - } + /** + * get SQL retrieve Filter + * + * @param string $sqlId + * @param string $filterValue + * @param string $tableAlias = 'main.' + * @return string + */ + protected function getSQLRetrieveFilter($sqlId, $filterValue, $tableAlias = 'main.') + { + $ret = ''; + preg_match('/^(.*)\[(.*)\](.*)$/', $filterValue, $matches); + if (count($matches) > 1) { + if ($matches[1] == '%' || $matches[3] == '%') { + $ret .= ' AND '.bqSQL($tableAlias).'`'.bqSQL($sqlId).'` LIKE "'.pSQL($matches[1].$matches[2].$matches[3])."\"\n"; + } elseif ($matches[1] == '' && $matches[3] == '') { + if (strpos($matches[2], '|') > 0) { + $values = explode('|', $matches[2]); + $ret .= ' AND ('; + $temp = ''; + foreach ($values as $value) { + $temp .= bqSQL($tableAlias).'`'.bqSQL($sqlId).'` = "'.bqSQL($value).'" OR '; + } + $ret .= rtrim($temp, 'OR ').')'."\n"; + } elseif (preg_match('/^([\d\.:\-\s]+),([\d\.:\-\s]+)$/', $matches[2], $matches3)) { + unset($matches3[0]); + if (count($matches3) > 0) { + sort($matches3); + $ret .= ' AND '.$tableAlias.'`'.bqSQL($sqlId).'` BETWEEN "'.pSQL($matches3[0]).'" AND "'.pSQL($matches3[1])."\"\n"; + } + } else { + $ret .= ' AND '.$tableAlias.'`'.bqSQL($sqlId).'`="'.pSQL($matches[2]).'"'."\n"; + } + } elseif ($matches[1] == '>') { + $ret .= ' AND '.$tableAlias.'`'.bqSQL($sqlId).'` > "'.pSQL($matches[2])."\"\n"; + } elseif ($matches[1] == '<') { + $ret .= ' AND '.$tableAlias.'`'.bqSQL($sqlId).'` < "'.pSQL($matches[2])."\"\n"; + } elseif ($matches[1] == '!') { + $ret .= ' AND '.$tableAlias.'`'.bqSQL($sqlId).'` != "'.pSQL($matches[2])."\"\n"; + } + } else { + $ret .= ' AND '.$tableAlias.'`'.bqSQL($sqlId).'` '.(Validate::isFloat(pSQL($filterValue)) ? 'LIKE' : '=').' "'.pSQL($filterValue)."\"\n"; + } + return $ret; + } - /** - * get SQL retrieve Filter - * - * @param string $sqlId - * @param string $filterValue - * @param string $tableAlias = 'main.' - * @return string - */ - protected function getSQLRetrieveFilter($sqlId, $filterValue, $tableAlias = 'main.') - { - $ret = ''; - preg_match('/^(.*)\[(.*)\](.*)$/', $filterValue, $matches); - if (count($matches) > 1) - { - if ($matches[1] == '%' || $matches[3] == '%') - $ret .= ' AND '.bqSQL($tableAlias).'`'.bqSQL($sqlId).'` LIKE "'.pSQL($matches[1].$matches[2].$matches[3])."\"\n"; - elseif ($matches[1] == '' && $matches[3] == '') - { - if (strpos($matches[2], '|') > 0) - { - $values = explode('|', $matches[2]); - $ret .= ' AND ('; - $temp = ''; - foreach ($values as $value) - $temp .= bqSQL($tableAlias).'`'.bqSQL($sqlId).'` = "'.bqSQL($value).'" OR '; - $ret .= rtrim($temp, 'OR ').')'."\n"; - } - elseif (preg_match('/^([\d\.:\-\s]+),([\d\.:\-\s]+)$/', $matches[2], $matches3)) - { - unset($matches3[0]); - if (count($matches3) > 0) - { - sort($matches3); - $ret .= ' AND '.$tableAlias.'`'.bqSQL($sqlId).'` BETWEEN "'.pSQL($matches3[0]).'" AND "'.pSQL($matches3[1])."\"\n"; - } - } - else - $ret .= ' AND '.$tableAlias.'`'.bqSQL($sqlId).'`="'.pSQL($matches[2]).'"'."\n"; - } - elseif ($matches[1] == '>') - $ret .= ' AND '.$tableAlias.'`'.bqSQL($sqlId).'` > "'.pSQL($matches[2])."\"\n"; - elseif ($matches[1] == '<') - $ret .= ' AND '.$tableAlias.'`'.bqSQL($sqlId).'` < "'.pSQL($matches[2])."\"\n"; - elseif ($matches[1] == '!') - $ret .= ' AND '.$tableAlias.'`'.bqSQL($sqlId).'` != "'.pSQL($matches[2])."\"\n"; - } - else - $ret .= ' AND '.$tableAlias.'`'.bqSQL($sqlId).'` '.(Validate::isFloat(pSQL($filterValue)) ? 'LIKE' : '=').' "'.pSQL($filterValue)."\"\n"; - return $ret; - } + public function filterLanguage() + { + $arr_languages = array(); + $length_values = strlen($this->urlFragments['language']); + // if just one language is asked + if (is_numeric($this->urlFragments['language'])) { + $arr_languages[] = (int)$this->urlFragments['language']; + } + // if a range or a list is asked + elseif (strpos($this->urlFragments['language'], '[') === 0 + && strpos($this->urlFragments['language'], ']') === $length_values - 1) { + if (strpos($this->urlFragments['language'], '|') !== false + xor strpos($this->urlFragments['language'], ',') !== false) { + $params_values = str_replace(array(']', '['), '', $this->urlFragments['language']); + // it's a list + if (strpos($params_values, '|') !== false) { + $list_enabled_lang = explode('|', $params_values); + $arr_languages = $list_enabled_lang; + } + // it's a range + elseif (strpos($params_values, ',') !== false) { + $range_enabled_lang = explode(',', $params_values); + if (count($range_enabled_lang) != 2) { + $this->setError(400, 'A range value for a language must contains only 2 values', 78); + return false; + } + for ($i = $range_enabled_lang[0]; $i <= $range_enabled_lang[1]; $i++) { + $arr_languages[] = $i; + } + } + } elseif (preg_match('#\[(\d)+\]#Ui', $this->urlFragments['language'], $match_lang)) { + $arr_languages[] = $match_lang[1]; + } + } else { + $this->setError(400, 'language value is wrong', 79); + return false; + } - public function filterLanguage() - { - $arr_languages = array(); - $length_values = strlen($this->urlFragments['language']); - // if just one language is asked - if (is_numeric($this->urlFragments['language'])) - $arr_languages[] = (int)$this->urlFragments['language']; - // if a range or a list is asked - elseif (strpos($this->urlFragments['language'], '[') === 0 - && strpos($this->urlFragments['language'], ']') === $length_values - 1) - { - if (strpos($this->urlFragments['language'], '|') !== false - XOR strpos($this->urlFragments['language'], ',') !== false) - { - $params_values = str_replace(array(']', '['), '', $this->urlFragments['language']); - // it's a list - if (strpos($params_values, '|') !== false) - { - $list_enabled_lang = explode('|', $params_values); - $arr_languages = $list_enabled_lang; - } - // it's a range - elseif (strpos($params_values, ',') !== false) - { - $range_enabled_lang = explode(',', $params_values); - if (count($range_enabled_lang) != 2) - { - $this->setError(400, 'A range value for a language must contains only 2 values', 78); - return false; - } - for ($i = $range_enabled_lang[0]; $i <= $range_enabled_lang[1]; $i++) - $arr_languages[] = $i; - } - } - elseif (preg_match('#\[(\d)+\]#Ui', $this->urlFragments['language'], $match_lang)) - $arr_languages[] = $match_lang[1]; - } - else - { - $this->setError(400, 'language value is wrong', 79); - return false; - } + $result = array_map('is_numeric', $arr_languages); + if (array_search(false, $result, true)) { + $this->setError(400, 'Language ID must be numeric', 80); + return false; + } - $result = array_map('is_numeric', $arr_languages); - if (array_search(false, $result, true)) - { - $this->setError(400, 'Language ID must be numeric', 80); - return false; - } + foreach ($arr_languages as $key => $id_lang) { + if (!Language::getLanguage($id_lang)) { + unset($arr_languages[$key]); + } + } - foreach ($arr_languages as $key => $id_lang) - if (!Language::getLanguage($id_lang)) - unset($arr_languages[$key]); + return $arr_languages; + } - return $arr_languages; - } + /** + * Thanks to the (WebserviceOutputBuilder) WebserviceKey::objOutput + * Method build the output depend on the WebserviceRequest::outputFormat + * and set HTTP header parameters. + * + * @return array with displaying informations (used in the dispatcher). + */ + protected function returnOutput() + { + $return = array(); - /** - * Thanks to the (WebserviceOutputBuilder) WebserviceKey::objOutput - * Method build the output depend on the WebserviceRequest::outputFormat - * and set HTTP header parameters. - * - * @return array with displaying informations (used in the dispatcher). - */ - protected function returnOutput() - { - $return = array(); + // write headers + $this->objOutput->setHeaderParams('Access-Time', time()) + ->setHeaderParams('X-Powered-By', 'PrestaShop Webservice') + ->setHeaderParams('PSWS-Version', _PS_VERSION_) + ->setHeaderParams('Execution-Time', round(microtime(true) - $this->_startTime, 3)); - // write headers - $this->objOutput->setHeaderParams('Access-Time', time()) - ->setHeaderParams('X-Powered-By', 'PrestaShop Webservice') - ->setHeaderParams('PSWS-Version', _PS_VERSION_) - ->setHeaderParams('Execution-Time', round(microtime(true) - $this->_startTime, 3)); + $return['type'] = strtolower($this->outputFormat); - $return['type'] = strtolower($this->outputFormat); + // write this header only now (avoid hackers happiness...) + if ($this->_authenticated) { + $this->objOutput->setHeaderParams('PSWS-Version', _PS_VERSION_); + } - // write this header only now (avoid hackers happiness...) - if ($this->_authenticated) - $this->objOutput->setHeaderParams('PSWS-Version', _PS_VERSION_); + // If Specific Management is asked + if ($this->objectSpecificManagement instanceof WebserviceSpecificManagementInterface) { + try { + $return['content'] = $this->objectSpecificManagement->getContent(); + } catch (WebserviceException $e) { + if ($e->getType() == WebserviceException::DID_YOU_MEAN) { + $this->setErrorDidYouMean($e->getStatus(), $e->getMessage(), $e->getWrongValue(), $e->getAvailableValues(), $e->getCode()); + } elseif ($e->getType() == WebserviceException::SIMPLE) { + $this->setError($e->getStatus(), $e->getMessage(), $e->getCode()); + } + } + } - // If Specific Management is asked - if ($this->objectSpecificManagement instanceof WebserviceSpecificManagementInterface) - { - try - { - $return['content'] = $this->objectSpecificManagement->getContent(); - } - catch (WebserviceException $e) - { - if ($e->getType() == WebserviceException::DID_YOU_MEAN) - $this->setErrorDidYouMean($e->getStatus(), $e->getMessage(), $e->getWrongValue(), $e->getAvailableValues(), $e->getCode()); - elseif ($e->getType() == WebserviceException::SIMPLE) - $this->setError($e->getStatus(), $e->getMessage(), $e->getCode()); - } - } + // for use a general output + if (!$this->hasErrors() && $this->objectSpecificManagement == null) { + if (empty($this->objects)) { + try { + $return['content'] = $this->objOutput->getResourcesList($this->keyPermissions); + } catch (WebserviceException $e) { + if ($e->getType() == WebserviceException::DID_YOU_MEAN) { + $this->setErrorDidYouMean($e->getStatus(), $e->getMessage(), $e->getWrongValue(), $e->getAvailableValues(), $e->getCode()); + } elseif ($e->getType() == WebserviceException::SIMPLE) { + $this->setError($e->getStatus(), $e->getMessage(), $e->getCode()); + } + } + } else { + try { + if (isset($this->urlSegment[1]) && !empty($this->urlSegment[1])) { + $type_of_view = WebserviceOutputBuilder::VIEW_DETAILS; + } else { + $type_of_view = WebserviceOutputBuilder::VIEW_LIST; + } - // for use a general output - if (!$this->hasErrors() && $this->objectSpecificManagement == null) - { - if (empty($this->objects)) - { - try - { - $return['content'] = $this->objOutput->getResourcesList($this->keyPermissions); - } - catch (WebserviceException $e) - { - if ($e->getType() == WebserviceException::DID_YOU_MEAN) - $this->setErrorDidYouMean($e->getStatus(), $e->getMessage(), $e->getWrongValue(), $e->getAvailableValues(), $e->getCode()); - elseif ($e->getType() == WebserviceException::SIMPLE) - $this->setError($e->getStatus(), $e->getMessage(), $e->getCode()); - } - } - else - { - try - { - if (isset($this->urlSegment[1]) && !empty($this->urlSegment[1])) - $type_of_view = WebserviceOutputBuilder::VIEW_DETAILS; - else - $type_of_view = WebserviceOutputBuilder::VIEW_LIST; + if (in_array($this->method, array('PUT', 'POST'))) { + $type_of_view = WebserviceOutputBuilder::VIEW_DETAILS; + $this->fieldsToDisplay = 'full'; + } - if (in_array($this->method, array('PUT', 'POST'))) - { - $type_of_view = WebserviceOutputBuilder::VIEW_DETAILS; - $this->fieldsToDisplay = 'full'; - } + $return['content'] = $this->objOutput->getContent($this->objects, $this->schemaToDisplay, $this->fieldsToDisplay, $this->depth, $type_of_view); + } catch (WebserviceException $e) { + if ($e->getType() == WebserviceException::DID_YOU_MEAN) { + $this->setErrorDidYouMean($e->getStatus(), $e->getMessage(), $e->getWrongValue(), $e->getAvailableValues(), $e->getCode()); + } elseif ($e->getType() == WebserviceException::SIMPLE) { + $this->setError($e->getStatus(), $e->getMessage(), $e->getCode()); + } + } catch (Exception $e) { + $this->setError(500, $e->getMessage(), $e->getCode()); + } + } + } - $return['content'] = $this->objOutput->getContent($this->objects, $this->schemaToDisplay, $this->fieldsToDisplay, $this->depth, $type_of_view); - } - catch (WebserviceException $e) - { - if ($e->getType() == WebserviceException::DID_YOU_MEAN) - $this->setErrorDidYouMean($e->getStatus(), $e->getMessage(), $e->getWrongValue(), $e->getAvailableValues(), $e->getCode()); - elseif ($e->getType() == WebserviceException::SIMPLE) - $this->setError($e->getStatus(), $e->getMessage(), $e->getCode()); - } - catch (Exception $e) - { - $this->setError(500, $e->getMessage(), $e->getCode()); - } - } - } + // if the output is not enable, delete the content + // the type content too + if (!$this->_outputEnabled) { + if (isset($return['type'])) { + unset($return['type']); + } + if (isset($return['content'])) { + unset($return['content']); + } + } elseif (isset($return['content'])) { + $this->objOutput->setHeaderParams('Content-Sha1', sha1($return['content'])); + } - // if the output is not enable, delete the content - // the type content too - if (!$this->_outputEnabled) - { - if (isset($return['type'])) - unset($return['type']); - if (isset($return['content'])) - unset($return['content']); - } + // if errors happends when creating returned xml, + // the usual xml content is replaced by the nice error handler content + if ($this->hasErrors()) { + $this->_outputEnabled = true; + $return['content'] = $this->objOutput->getErrors($this->errors); + } - elseif (isset($return['content'])) - $this->objOutput->setHeaderParams('Content-Sha1', sha1($return['content'])); + if (!isset($return['content']) || strlen($return['content']) <= 0) { + $this->objOutput->setHeaderParams('Content-Type', ''); + } - // if errors happends when creating returned xml, - // the usual xml content is replaced by the nice error handler content - if ($this->hasErrors()) - { - $this->_outputEnabled = true; - $return['content'] = $this->objOutput->getErrors($this->errors); - } + $return['headers'] = $this->objOutput->buildHeader(); + restore_error_handler(); + return $return; + } - if (!isset($return['content']) || strlen($return['content']) <= 0) - $this->objOutput->setHeaderParams('Content-Type', ''); + public static function getallheaders() + { + $retarr = array(); + $headers = array(); - $return['headers'] = $this->objOutput->buildHeader(); - restore_error_handler(); - return $return; - } - - public static function getallheaders() - { - $retarr = array(); - $headers = array(); - - if (function_exists('apache_request_headers')) - $headers = apache_request_headers(); - else - { - $headers = array_merge($_ENV, $_SERVER); - foreach ($headers as $key => $val) - { - //we need this header - if (strpos(strtolower($key), 'content-type') !== false) - continue; - if (strtoupper(substr($key, 0, 5)) != 'HTTP_') - unset($headers[$key]); - } - } - //Normalize this array to Cased-Like-This structure. - foreach ($headers as $key => $value) - { - $key = preg_replace('/^HTTP_/i', '', $key); - $key = str_replace(' ', '-', ucwords(strtolower(str_replace(array('-', '_'), ' ', $key)))); - $retarr[$key] = $value; - } - ksort($retarr); - return $retarr; - } + if (function_exists('apache_request_headers')) { + $headers = apache_request_headers(); + } else { + $headers = array_merge($_ENV, $_SERVER); + foreach ($headers as $key => $val) { + //we need this header + if (strpos(strtolower($key), 'content-type') !== false) { + continue; + } + if (strtoupper(substr($key, 0, 5)) != 'HTTP_') { + unset($headers[$key]); + } + } + } + //Normalize this array to Cased-Like-This structure. + foreach ($headers as $key => $value) { + $key = preg_replace('/^HTTP_/i', '', $key); + $key = str_replace(' ', '-', ucwords(strtolower(str_replace(array('-', '_'), ' ', $key)))); + $retarr[$key] = $value; + } + ksort($retarr); + return $retarr; + } } diff --git a/classes/webservice/WebserviceSpecificManagementImages.php b/classes/webservice/WebserviceSpecificManagementImages.php index c258f7c8..0a06d35b 100644 --- a/classes/webservice/WebserviceSpecificManagementImages.php +++ b/classes/webservice/WebserviceSpecificManagementImages.php @@ -26,1163 +26,1139 @@ class WebserviceSpecificManagementImagesCore implements WebserviceSpecificManagementInterface { - /** @var WebserviceOutputBuilder */ - protected $objOutput; - protected $output; + /** @var WebserviceOutputBuilder */ + protected $objOutput; + protected $output; - /** @var WebserviceRequest */ - protected $wsObject; + /** @var WebserviceRequest */ + protected $wsObject; - /** - * @var string The extension of the image to display - */ - protected $imgExtension; + /** + * @var string The extension of the image to display + */ + protected $imgExtension; - /** - * @var array The type of images (general, categories, manufacturers, suppliers, stores...) - */ - protected $imageTypes = array( - 'general' => array( - 'header' => array(), - 'mail' => array(), - 'invoice' => array(), - 'store_icon' => array(), - ), - 'products' => array(), - 'categories' => array(), - 'manufacturers' => array(), - 'suppliers' => array(), - 'stores' => array(), - 'customizations' => array(), - ); + /** + * @var array The type of images (general, categories, manufacturers, suppliers, stores...) + */ + protected $imageTypes = array( + 'general' => array( + 'header' => array(), + 'mail' => array(), + 'invoice' => array(), + 'store_icon' => array(), + ), + 'products' => array(), + 'categories' => array(), + 'manufacturers' => array(), + 'suppliers' => array(), + 'stores' => array(), + 'customizations' => array(), + ); - /** - * @var string The image type (product, category, general,...) - */ - protected $imageType = null; + /** + * @var string The image type (product, category, general,...) + */ + protected $imageType = null; - /** - * @var int The maximum size supported when uploading images, in bytes - */ - protected $imgMaxUploadSize = 3000000; + /** + * @var int The maximum size supported when uploading images, in bytes + */ + protected $imgMaxUploadSize = 3000000; - /** - * @var array The list of supported mime types - */ - protected $acceptedImgMimeTypes = array('image/gif', 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png'); + /** + * @var array The list of supported mime types + */ + protected $acceptedImgMimeTypes = array('image/gif', 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png'); - /** - * @var string The product image declination id - */ - protected $productImageDeclinationId = null; + /** + * @var string The product image declination id + */ + protected $productImageDeclinationId = null; - /** - * @var bool If the current image management has to manage a "default" image (i.e. "No product available") - */ - protected $defaultImage = false; + /** + * @var bool If the current image management has to manage a "default" image (i.e. "No product available") + */ + protected $defaultImage = false; - /** - * @var string The file path of the image to display. If not null, the image will be displayed, even if the XML output was not empty - */ - public $imgToDisplay = null; - public $imageResource = null; + /** + * @var string The file path of the image to display. If not null, the image will be displayed, even if the XML output was not empty + */ + public $imgToDisplay = null; + public $imageResource = null; - /* ------------------------------------------------ - * GETTERS & SETTERS - * ------------------------------------------------ */ + /* ------------------------------------------------ + * GETTERS & SETTERS + * ------------------------------------------------ */ - /** - * @param WebserviceOutputBuilderCore $obj - * @return WebserviceSpecificManagementInterface - */ - public function setObjectOutput(WebserviceOutputBuilderCore $obj) - { - $this->objOutput = $obj; - return $this; - } + /** + * @param WebserviceOutputBuilderCore $obj + * @return WebserviceSpecificManagementInterface + */ + public function setObjectOutput(WebserviceOutputBuilderCore $obj) + { + $this->objOutput = $obj; + return $this; + } - public function getObjectOutput() - { - return $this->objOutput; - } + public function getObjectOutput() + { + return $this->objOutput; + } - public function setWsObject(WebserviceRequestCore $obj) - { - $this->wsObject = $obj; - return $this; - } + public function setWsObject(WebserviceRequestCore $obj) + { + $this->wsObject = $obj; + return $this; + } - public function getWsObject() - { - return $this->wsObject; - } + public function getWsObject() + { + return $this->wsObject; + } - /* - * This method need $this->imgToDisplay to be set if output don't needs to be XML - */ - public function getContent() - { - if ($this->output != '') - return $this->objOutput->getObjectRender()->overrideContent($this->output); - // display image content if needed - elseif ($this->imgToDisplay) - { - if (empty($this->imgExtension)) - { - $imginfo = getimagesize($this->imgToDisplay); - $this->imgExtension = image_type_to_extension($imginfo[2], false); - } - $imageResource = false; - $types = array( - 'jpg' => array( - 'function' => 'imagecreatefromjpeg', - 'Content-Type' => 'image/jpeg' - ), - 'jpeg' => array( - 'function' => 'imagecreatefromjpeg', - 'Content-Type' => 'image/jpeg' - ), - 'png' => array('function' => - 'imagecreatefrompng', - 'Content-Type' => 'image/png' - ), - 'gif' => array( - 'function' => 'imagecreatefromgif', - 'Content-Type' => 'image/gif' - ) - ); - if (array_key_exists($this->imgExtension, $types)) - $imageResource = @$types[$this->imgExtension]['function']($this->imgToDisplay); + /* + * This method need $this->imgToDisplay to be set if output don't needs to be XML + */ + public function getContent() + { + if ($this->output != '') { + return $this->objOutput->getObjectRender()->overrideContent($this->output); + } + // display image content if needed + elseif ($this->imgToDisplay) { + if (empty($this->imgExtension)) { + $imginfo = getimagesize($this->imgToDisplay); + $this->imgExtension = image_type_to_extension($imginfo[2], false); + } + $imageResource = false; + $types = array( + 'jpg' => array( + 'function' => 'imagecreatefromjpeg', + 'Content-Type' => 'image/jpeg' + ), + 'jpeg' => array( + 'function' => 'imagecreatefromjpeg', + 'Content-Type' => 'image/jpeg' + ), + 'png' => array('function' => + 'imagecreatefrompng', + 'Content-Type' => 'image/png' + ), + 'gif' => array( + 'function' => 'imagecreatefromgif', + 'Content-Type' => 'image/gif' + ) + ); + if (array_key_exists($this->imgExtension, $types)) { + $imageResource = @$types[$this->imgExtension]['function']($this->imgToDisplay); + } - if (!$imageResource) - throw new WebserviceException(sprintf('Unable to load the image "%s"', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $this->imgToDisplay)), array(47, 500)); - else - { - if (array_key_exists($this->imgExtension, $types)) - $this->objOutput->setHeaderParams('Content-Type', $types[$this->imgExtension]['Content-Type']); - return file_get_contents($this->imgToDisplay); - } - } - } + if (!$imageResource) { + throw new WebserviceException(sprintf('Unable to load the image "%s"', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $this->imgToDisplay)), array(47, 500)); + } else { + if (array_key_exists($this->imgExtension, $types)) { + $this->objOutput->setHeaderParams('Content-Type', $types[$this->imgExtension]['Content-Type']); + } + return file_get_contents($this->imgToDisplay); + } + } + } - public function manage() - { - $this->manageImages(); - return $this->wsObject->getOutputEnabled(); - } + public function manage() + { + $this->manageImages(); + return $this->wsObject->getOutputEnabled(); + } - /** - * Management of images URL segment - * - * @return bool - * - * @throws WebserviceException - */ - protected function manageImages() - { - /* - * available cases api/... : - * - * images ("types_list") (N-1) - * GET (xml) - * images/general ("general_list") (N-2) - * GET (xml) - * images/general/[header,+] ("general") (N-3) - * GET (bin) - * PUT (bin) - * - * - * images/[categories,+] ("normal_list") (N-2) ([categories,+] = categories, manufacturers, ...) - * GET (xml) - * images/[categories,+]/[1,+] ("normal") (N-3) - * GET (bin) - * PUT (bin) - * DELETE - * POST (bin) (if image does not exists) - * images/[categories,+]/[1,+]/[small,+] ("normal_resized") (N-4) - * GET (bin) - * images/[categories,+]/default ("display_list_of_langs") (N-3) - * GET (xml) - * images/[categories,+]/default/[en,+] ("normal_default_i18n") (N-4) - * GET (bin) - * POST (bin) (if image does not exists) - * PUT (bin) - * DELETE - * images/[categories,+]/default/[en,+]/[small,+] ("normal_default_i18n_resized") (N-5) - * GET (bin) - * - * images/product ("product_list") (N-2) - * GET (xml) (list of image) - * images/product/[1,+] ("product_description") (N-3) - * GET (xml) (legend, declinations, xlink to images/product/[1,+]/bin) - * images/product/[1,+]/bin ("product_bin") (N-4) - * GET (bin) - * POST (bin) (if image does not exists) - * images/product/[1,+]/[1,+] ("product_declination") (N-4) - * GET (bin) - * POST (xml) (legend) - * PUT (xml) (legend) - * DELETE - * images/product/[1,+]/[1,+]/bin ("product_declination_bin") (N-5) - * POST (bin) (if image does not exists) - * GET (bin) - * PUT (bin) - * images/product/[1,+]/[1,+]/[small,+] ("product_declination_resized") (N-5) - * GET (bin) - * images/product/default ("product_default") (N-3) - * GET (bin) - * images/product/default/[en,+] ("product_default_i18n") (N-4) - * GET (bin) - * POST (bin) - * PUT (bin) - * DELETE - * images/product/default/[en,+]/[small,+] ("product_default_i18n_resized") (N-5) - * GET (bin) - * - */ + /** + * Management of images URL segment + * + * @return bool + * + * @throws WebserviceException + */ + protected function manageImages() + { + /* + * available cases api/... : + * + * images ("types_list") (N-1) + * GET (xml) + * images/general ("general_list") (N-2) + * GET (xml) + * images/general/[header,+] ("general") (N-3) + * GET (bin) + * PUT (bin) + * + * + * images/[categories,+] ("normal_list") (N-2) ([categories,+] = categories, manufacturers, ...) + * GET (xml) + * images/[categories,+]/[1,+] ("normal") (N-3) + * GET (bin) + * PUT (bin) + * DELETE + * POST (bin) (if image does not exists) + * images/[categories,+]/[1,+]/[small,+] ("normal_resized") (N-4) + * GET (bin) + * images/[categories,+]/default ("display_list_of_langs") (N-3) + * GET (xml) + * images/[categories,+]/default/[en,+] ("normal_default_i18n") (N-4) + * GET (bin) + * POST (bin) (if image does not exists) + * PUT (bin) + * DELETE + * images/[categories,+]/default/[en,+]/[small,+] ("normal_default_i18n_resized") (N-5) + * GET (bin) + * + * images/product ("product_list") (N-2) + * GET (xml) (list of image) + * images/product/[1,+] ("product_description") (N-3) + * GET (xml) (legend, declinations, xlink to images/product/[1,+]/bin) + * images/product/[1,+]/bin ("product_bin") (N-4) + * GET (bin) + * POST (bin) (if image does not exists) + * images/product/[1,+]/[1,+] ("product_declination") (N-4) + * GET (bin) + * POST (xml) (legend) + * PUT (xml) (legend) + * DELETE + * images/product/[1,+]/[1,+]/bin ("product_declination_bin") (N-5) + * POST (bin) (if image does not exists) + * GET (bin) + * PUT (bin) + * images/product/[1,+]/[1,+]/[small,+] ("product_declination_resized") (N-5) + * GET (bin) + * images/product/default ("product_default") (N-3) + * GET (bin) + * images/product/default/[en,+] ("product_default_i18n") (N-4) + * GET (bin) + * POST (bin) + * PUT (bin) + * DELETE + * images/product/default/[en,+]/[small,+] ("product_default_i18n_resized") (N-5) + * GET (bin) + * + */ - /* Declinated - *ok GET (bin) - *ok images/product ("product_list") (N-2) - *ok GET (xml) (list of image) - *ok images/product/[1,+] ("product_description") (N-3) - * GET (xml) (legend, declinations, xlink to images/product/[1,+]/bin) - *ok images/product/[1,+]/bin ("product_bin") (N-4) - *ok GET (bin) - * POST (bin) (if image does not exists) - *ok images/product/[1,+]/[1,+] ("product_declination") (N-4) - *ok GET (bin) - * POST (xml) (legend) - * PUT (xml) (legend) - * DELETE - *ok images/product/[1,+]/[1,+]/bin ("product_declination_bin") (N-5) - * POST (bin) (if image does not exists) - *ok GET (bin) - * PUT (bin) - * images/product/[1,+]/[1,+]/[small,+] ("product_declination_resized") (N-5) - *ok GET (bin) - *ok images/product/default ("product_default") (N-3) - *ok GET (bin) - *ok images/product/default/[en,+] ("product_default_i18n") (N-4) - *ok GET (bin) - * POST (bin) - * PUT (bin) - * DELETE - *ok images/product/default/[en,+]/[small,+] ("product_default_i18n_resized") (N-5) - *ok GET (bin) - * - * */ + /* Declinated + *ok GET (bin) + *ok images/product ("product_list") (N-2) + *ok GET (xml) (list of image) + *ok images/product/[1,+] ("product_description") (N-3) + * GET (xml) (legend, declinations, xlink to images/product/[1,+]/bin) + *ok images/product/[1,+]/bin ("product_bin") (N-4) + *ok GET (bin) + * POST (bin) (if image does not exists) + *ok images/product/[1,+]/[1,+] ("product_declination") (N-4) + *ok GET (bin) + * POST (xml) (legend) + * PUT (xml) (legend) + * DELETE + *ok images/product/[1,+]/[1,+]/bin ("product_declination_bin") (N-5) + * POST (bin) (if image does not exists) + *ok GET (bin) + * PUT (bin) + * images/product/[1,+]/[1,+]/[small,+] ("product_declination_resized") (N-5) + *ok GET (bin) + *ok images/product/default ("product_default") (N-3) + *ok GET (bin) + *ok images/product/default/[en,+] ("product_default_i18n") (N-4) + *ok GET (bin) + * POST (bin) + * PUT (bin) + * DELETE + *ok images/product/default/[en,+]/[small,+] ("product_default_i18n_resized") (N-5) + *ok GET (bin) + * + * */ - // Pre configuration... - if (isset($this->wsObject->urlSegment)) - for ($i = 1; $i < 6; $i++) - if (count($this->wsObject->urlSegment) == $i) - $this->wsObject->urlSegment[$i] = ''; + // Pre configuration... + if (isset($this->wsObject->urlSegment)) { + for ($i = 1; $i < 6; $i++) { + if (count($this->wsObject->urlSegment) == $i) { + $this->wsObject->urlSegment[$i] = ''; + } + } + } - $this->imageType = $this->wsObject->urlSegment[1]; + $this->imageType = $this->wsObject->urlSegment[1]; - switch ($this->wsObject->urlSegment[1]) - { - // general images management : like header's logo, invoice logo, etc... - case 'general': - return $this->manageGeneralImages(); - break; - // normal images management : like the most entity images (categories, manufacturers..)... - case 'categories': - case 'manufacturers': - case 'suppliers': - case 'stores': - switch ($this->wsObject->urlSegment[1]) - { - case 'categories': - $directory = _PS_CAT_IMG_DIR_; - break; - case 'manufacturers': - $directory = _PS_MANU_IMG_DIR_; - break; - case 'suppliers': - $directory = _PS_SUPP_IMG_DIR_; - break; - case 'stores': - $directory = _PS_STORE_IMG_DIR_; - break; - } - return $this->manageDeclinatedImages($directory); - break; + switch ($this->wsObject->urlSegment[1]) { + // general images management : like header's logo, invoice logo, etc... + case 'general': + return $this->manageGeneralImages(); + break; + // normal images management : like the most entity images (categories, manufacturers..)... + case 'categories': + case 'manufacturers': + case 'suppliers': + case 'stores': + switch ($this->wsObject->urlSegment[1]) { + case 'categories': + $directory = _PS_CAT_IMG_DIR_; + break; + case 'manufacturers': + $directory = _PS_MANU_IMG_DIR_; + break; + case 'suppliers': + $directory = _PS_SUPP_IMG_DIR_; + break; + case 'stores': + $directory = _PS_STORE_IMG_DIR_; + break; + } + return $this->manageDeclinatedImages($directory); + break; - // product image management : many image for one entity (product) - case 'products': - return $this->manageProductImages(); - break; - case 'customizations': - return $this->manageCustomizationImages(); - break; - // images root node management : many image for one entity (product) - case '': - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_types', array()); - foreach (array_keys($this->imageTypes) as $image_type_name) - { - $more_attr = array( - 'xlink_resource' => $this->wsObject->wsUrl.$this->wsObject->urlSegment[0].'/'.$image_type_name, - 'get' => 'true', 'put' => 'false', 'post' => 'false', 'delete' => 'false', 'head' => 'true', - 'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes) - ); - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader($image_type_name, array(), $more_attr, false); - } - $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image_types', array()); - return true; - break; - default: - $exception = new WebserviceException(sprintf('Image of type "%s" does not exist', $this->wsObject->urlSegment[1]), array(48, 400)); - throw $exception->setDidYouMean($this->wsObject->urlSegment[1], array_keys($this->imageTypes)); - } - } + // product image management : many image for one entity (product) + case 'products': + return $this->manageProductImages(); + break; + case 'customizations': + return $this->manageCustomizationImages(); + break; + // images root node management : many image for one entity (product) + case '': + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_types', array()); + foreach (array_keys($this->imageTypes) as $image_type_name) { + $more_attr = array( + 'xlink_resource' => $this->wsObject->wsUrl.$this->wsObject->urlSegment[0].'/'.$image_type_name, + 'get' => 'true', 'put' => 'false', 'post' => 'false', 'delete' => 'false', 'head' => 'true', + 'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes) + ); + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader($image_type_name, array(), $more_attr, false); + } + $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image_types', array()); + return true; + break; + default: + $exception = new WebserviceException(sprintf('Image of type "%s" does not exist', $this->wsObject->urlSegment[1]), array(48, 400)); + throw $exception->setDidYouMean($this->wsObject->urlSegment[1], array_keys($this->imageTypes)); + } + } - /** - * Management of general images - * - * @return bool - * - * @throws WebserviceException - */ - protected function manageGeneralImages() - { - $path = ''; - $alternative_path = ''; - switch ($this->wsObject->urlSegment[2]) - { - // Set the image path on display in relation to the header image - case 'header': - if (in_array($this->wsObject->method, array('GET','HEAD','PUT'))) - $path = _PS_IMG_DIR_.Configuration::get('PS_LOGO'); - else - throw new WebserviceException('This method is not allowed with general image resources.', array(49, 405)); - break; + /** + * Management of general images + * + * @return bool + * + * @throws WebserviceException + */ + protected function manageGeneralImages() + { + $path = ''; + $alternative_path = ''; + switch ($this->wsObject->urlSegment[2]) { + // Set the image path on display in relation to the header image + case 'header': + if (in_array($this->wsObject->method, array('GET', 'HEAD', 'PUT'))) { + $path = _PS_IMG_DIR_.Configuration::get('PS_LOGO'); + } else { + throw new WebserviceException('This method is not allowed with general image resources.', array(49, 405)); + } + break; - // Set the image path on display in relation to the mail image - case 'mail': - if (in_array($this->wsObject->method, array('GET','HEAD','PUT'))) - { - $path = _PS_IMG_DIR_.Configuration::get('PS_LOGO_MAIL'); - $alternative_path = _PS_IMG_DIR_.Configuration::get('PS_LOGO'); - } - else - throw new WebserviceException('This method is not allowed with general image resources.', array(50, 405)); - break; + // Set the image path on display in relation to the mail image + case 'mail': + if (in_array($this->wsObject->method, array('GET', 'HEAD', 'PUT'))) { + $path = _PS_IMG_DIR_.Configuration::get('PS_LOGO_MAIL'); + $alternative_path = _PS_IMG_DIR_.Configuration::get('PS_LOGO'); + } else { + throw new WebserviceException('This method is not allowed with general image resources.', array(50, 405)); + } + break; - // Set the image path on display in relation to the invoice image - case 'invoice': - if (in_array($this->wsObject->method, array('GET','HEAD','PUT'))) - { - $path = _PS_IMG_DIR_.Configuration::get('PS_LOGO_INVOICE'); - $alternative_path = _PS_IMG_DIR_.Configuration::get('PS_LOGO'); - } - else - throw new WebserviceException('This method is not allowed with general image resources.', array(51, 405)); - break; + // Set the image path on display in relation to the invoice image + case 'invoice': + if (in_array($this->wsObject->method, array('GET', 'HEAD', 'PUT'))) { + $path = _PS_IMG_DIR_.Configuration::get('PS_LOGO_INVOICE'); + $alternative_path = _PS_IMG_DIR_.Configuration::get('PS_LOGO'); + } else { + throw new WebserviceException('This method is not allowed with general image resources.', array(51, 405)); + } + break; - // Set the image path on display in relation to the icon store image - case 'store_icon': - if (in_array($this->wsObject->method, array('GET','HEAD','PUT'))) - { - $path = _PS_IMG_DIR_.Configuration::get('PS_STORES_ICON'); - $this->imgExtension = 'gif'; - } - else - throw new WebserviceException('This method is not allowed with general image resources.', array(52, 405)); - break; + // Set the image path on display in relation to the icon store image + case 'store_icon': + if (in_array($this->wsObject->method, array('GET', 'HEAD', 'PUT'))) { + $path = _PS_IMG_DIR_.Configuration::get('PS_STORES_ICON'); + $this->imgExtension = 'gif'; + } else { + throw new WebserviceException('This method is not allowed with general image resources.', array(52, 405)); + } + break; - // List the general image types - case '': - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('general_image_types', array()); - foreach (array_keys($this->imageTypes['general']) as $general_image_type_name) - { - $more_attr = array( - 'xlink_resource' => $this->wsObject->wsUrl.$this->wsObject->urlSegment[0].'/'.$this->wsObject->urlSegment[1].'/'.$general_image_type_name, - 'get' => 'true', 'put' => 'true', 'post' => 'false', 'delete' => 'false', 'head' => 'true', - 'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes) - ); - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader($general_image_type_name, array(), $more_attr, false); - } - $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('general_image_types', array()); - return true; - break; + // List the general image types + case '': + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('general_image_types', array()); + foreach (array_keys($this->imageTypes['general']) as $general_image_type_name) { + $more_attr = array( + 'xlink_resource' => $this->wsObject->wsUrl.$this->wsObject->urlSegment[0].'/'.$this->wsObject->urlSegment[1].'/'.$general_image_type_name, + 'get' => 'true', 'put' => 'true', 'post' => 'false', 'delete' => 'false', 'head' => 'true', + 'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes) + ); + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader($general_image_type_name, array(), $more_attr, false); + } + $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('general_image_types', array()); + return true; + break; - // If the image type does not exist... - default: - $exception = new WebserviceException(sprintf('General image of type "%s" does not exist', $this->wsObject->urlSegment[2]), array(53, 400)); - throw $exception->setDidYouMean($this->wsObject->urlSegment[2], array_keys($this->imageTypes['general'])); - } - // The general image type is valid, now we try to do action in relation to the method - switch ($this->wsObject->method) - { - case 'GET': - case 'HEAD': - $this->imgToDisplay = ($path != '' && file_exists($path) && is_file($path)) ? $path : $alternative_path; - return true; - break; - case 'PUT': + // If the image type does not exist... + default: + $exception = new WebserviceException(sprintf('General image of type "%s" does not exist', $this->wsObject->urlSegment[2]), array(53, 400)); + throw $exception->setDidYouMean($this->wsObject->urlSegment[2], array_keys($this->imageTypes['general'])); + } + // The general image type is valid, now we try to do action in relation to the method + switch ($this->wsObject->method) { + case 'GET': + case 'HEAD': + $this->imgToDisplay = ($path != '' && file_exists($path) && is_file($path)) ? $path : $alternative_path; + return true; + break; + case 'PUT': - if ($this->writePostedImageOnDisk($path, null, null)) - { - if ($this->wsObject->urlSegment[2] == 'header') - { - $logo_name = Configuration::get('PS_LOGO') ? Configuration::get('PS_LOGO') : 'logo.jpg'; - list($width, $height, $type, $attr) = getimagesize(_PS_IMG_DIR_.$logo_name); - Configuration::updateValue('SHOP_LOGO_WIDTH', (int)round($width)); - Configuration::updateValue('SHOP_LOGO_HEIGHT', (int)round($height)); - } - $this->imgToDisplay = $path; - return true; - } - else - throw new WebserviceException('Error while copying image to the directory', array(54, 400)); - break; - } - } + if ($this->writePostedImageOnDisk($path, null, null)) { + if ($this->wsObject->urlSegment[2] == 'header') { + $logo_name = Configuration::get('PS_LOGO') ? Configuration::get('PS_LOGO') : 'logo.jpg'; + list($width, $height, $type, $attr) = getimagesize(_PS_IMG_DIR_.$logo_name); + Configuration::updateValue('SHOP_LOGO_WIDTH', (int)round($width)); + Configuration::updateValue('SHOP_LOGO_HEIGHT', (int)round($height)); + } + $this->imgToDisplay = $path; + return true; + } else { + throw new WebserviceException('Error while copying image to the directory', array(54, 400)); + } + break; + } + } - protected function manageDefaultDeclinatedImages($directory, $normal_image_sizes) - { - $this->defaultImage = true; - // Get the language iso code list - $lang_list = Language::getIsoIds(true); - $langs = array(); - $default_lang = Configuration::get('PS_LANG_DEFAULT'); - foreach ($lang_list as $lang) - { - if ($lang['id_lang'] == $default_lang) - $default_lang = $lang['iso_code']; - $langs[] = $lang['iso_code']; - } + protected function manageDefaultDeclinatedImages($directory, $normal_image_sizes) + { + $this->defaultImage = true; + // Get the language iso code list + $lang_list = Language::getIsoIds(true); + $langs = array(); + $default_lang = Configuration::get('PS_LANG_DEFAULT'); + foreach ($lang_list as $lang) { + if ($lang['id_lang'] == $default_lang) { + $default_lang = $lang['iso_code']; + } + $langs[] = $lang['iso_code']; + } - // Display list of languages - if ($this->wsObject->urlSegment[3] == '' && $this->wsObject->method == 'GET') - { - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('languages', array()); - foreach ($lang_list as $lang) - { - $more_attr = array( - 'xlink_resource' => $this->wsObject->wsUrl.'images/'.$this->imageType.'/default/'.$lang['iso_code'], - 'get' => 'true', 'put' => 'true', 'post' => 'true', 'delete' => 'true', 'head' => 'true', - 'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes), - 'iso'=>$lang['iso_code'] - ); - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('language', array(), $more_attr, false); - } + // Display list of languages + if ($this->wsObject->urlSegment[3] == '' && $this->wsObject->method == 'GET') { + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('languages', array()); + foreach ($lang_list as $lang) { + $more_attr = array( + 'xlink_resource' => $this->wsObject->wsUrl.'images/'.$this->imageType.'/default/'.$lang['iso_code'], + 'get' => 'true', 'put' => 'true', 'post' => 'true', 'delete' => 'true', 'head' => 'true', + 'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes), + 'iso'=>$lang['iso_code'] + ); + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('language', array(), $more_attr, false); + } - $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('languages', array()); - return true; - } - else - { - $lang_iso = $this->wsObject->urlSegment[3]; - $image_size = $this->wsObject->urlSegment[4]; - if ($image_size != '') - $filename = $directory.$lang_iso.'-default-'.$image_size.'.jpg'; - else - $filename = $directory.$lang_iso.'.jpg'; - $filename_exists = file_exists($filename); - return $this->manageDeclinatedImagesCRUD($filename_exists, $filename, $normal_image_sizes, $directory);// @todo : [feature] @see todo#1 - } - } + $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('languages', array()); + return true; + } else { + $lang_iso = $this->wsObject->urlSegment[3]; + $image_size = $this->wsObject->urlSegment[4]; + if ($image_size != '') { + $filename = $directory.$lang_iso.'-default-'.$image_size.'.jpg'; + } else { + $filename = $directory.$lang_iso.'.jpg'; + } + $filename_exists = file_exists($filename); + return $this->manageDeclinatedImagesCRUD($filename_exists, $filename, $normal_image_sizes, $directory);// @todo : [feature] @see todo#1 + } + } - protected function manageListDeclinatedImages($directory, $normal_image_sizes) - { - // Check if method is allowed - if ($this->wsObject->method != 'GET') - throw new WebserviceException('This method is not allowed for listing category images.', array(55, 405)); + protected function manageListDeclinatedImages($directory, $normal_image_sizes) + { + // Check if method is allowed + if ($this->wsObject->method != 'GET') { + throw new WebserviceException('This method is not allowed for listing category images.', array(55, 405)); + } - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_types', array()); - foreach ($normal_image_sizes as $image_size) - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_type', array(), array('id' => $image_size['id_image_type'], 'name' => $image_size['name'], 'xlink_resource'=>$this->wsObject->wsUrl.'image_types/'.$image_size['id_image_type']), false); - $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image_types', array()); - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('images', array()); + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_types', array()); + foreach ($normal_image_sizes as $image_size) { + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_type', array(), array('id' => $image_size['id_image_type'], 'name' => $image_size['name'], 'xlink_resource'=>$this->wsObject->wsUrl.'image_types/'.$image_size['id_image_type']), false); + } + $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image_types', array()); + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('images', array()); - if ($this->imageType == 'products') - { - $ids = array(); - $images = Image::getAllImages(); - foreach ($images as $image) - $ids[] = $image['id_product']; - $ids = array_unique($ids, SORT_NUMERIC); - asort($ids); - foreach ($ids as $id) - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', array(), array('id' => $id, 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$id), false); - } - else - { - $nodes = scandir($directory); - foreach ($nodes as $node) - { - // avoid too much preg_match... - if ($node != '.' && $node != '..' && $node != '.svn') - { - if ($this->imageType != 'products') - { - preg_match('/^(\d+)\.jpg*$/Ui', $node, $matches); - if (isset($matches[1])) - { - $id = $matches[1]; - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', array(), array('id' => $id, 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$id), false); - } - } - } - } - } - $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('images', array()); - return true; - } + if ($this->imageType == 'products') { + $ids = array(); + $images = Image::getAllImages(); + foreach ($images as $image) { + $ids[] = $image['id_product']; + } + $ids = array_unique($ids, SORT_NUMERIC); + asort($ids); + foreach ($ids as $id) { + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', array(), array('id' => $id, 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$id), false); + } + } else { + $nodes = scandir($directory); + foreach ($nodes as $node) { + // avoid too much preg_match... + if ($node != '.' && $node != '..' && $node != '.svn') { + if ($this->imageType != 'products') { + preg_match('/^(\d+)\.jpg*$/Ui', $node, $matches); + if (isset($matches[1])) { + $id = $matches[1]; + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', array(), array('id' => $id, 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$id), false); + } + } + } + } + } + $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('images', array()); + return true; + } - protected function manageEntityDeclinatedImages($directory, $normal_image_sizes) - { - $normal_image_size_names = array(); - foreach ($normal_image_sizes as $normal_image_size) - $normal_image_size_names[] = $normal_image_size['name']; - // If id is detected - $object_id = $this->wsObject->urlSegment[2]; - if (!Validate::isUnsignedId($object_id)) - throw new WebserviceException('The image id is invalid. Please set a valid id or the "default" value', array(60, 400)); + protected function manageEntityDeclinatedImages($directory, $normal_image_sizes) + { + $normal_image_size_names = array(); + foreach ($normal_image_sizes as $normal_image_size) { + $normal_image_size_names[] = $normal_image_size['name']; + } + // If id is detected + $object_id = $this->wsObject->urlSegment[2]; + if (!Validate::isUnsignedId($object_id)) { + throw new WebserviceException('The image id is invalid. Please set a valid id or the "default" value', array(60, 400)); + } - // For the product case - if ($this->imageType == 'products') - { - // Get available image ids - $available_image_ids = array(); + // For the product case + if ($this->imageType == 'products') { + // Get available image ids + $available_image_ids = array(); - // New Behavior - foreach (Language::getIDs() as $id_lang) - foreach (Image::getImages($id_lang, $object_id) as $image) - $available_image_ids[] = $image['id_image']; - $available_image_ids = array_unique($available_image_ids, SORT_NUMERIC); + // New Behavior + foreach (Language::getIDs() as $id_lang) { + foreach (Image::getImages($id_lang, $object_id) as $image) { + $available_image_ids[] = $image['id_image']; + } + } + $available_image_ids = array_unique($available_image_ids, SORT_NUMERIC); - // If an image id is specified - if ($this->wsObject->urlSegment[3] != '') - { - if ($this->wsObject->urlSegment[3] == 'bin') - { - $current_product = new Product($object_id); - $this->wsObject->urlSegment[3] = $current_product->getCoverWs(); - } - if (!Validate::isUnsignedId($object_id) || !in_array($this->wsObject->urlSegment[3], $available_image_ids)) - throw new WebserviceException('This image id does not exist', array(57, 400)); - else - { + // If an image id is specified + if ($this->wsObject->urlSegment[3] != '') { + if ($this->wsObject->urlSegment[3] == 'bin') { + $current_product = new Product($object_id); + $this->wsObject->urlSegment[3] = $current_product->getCoverWs(); + } + if (!Validate::isUnsignedId($object_id) || !in_array($this->wsObject->urlSegment[3], $available_image_ids)) { + throw new WebserviceException('This image id does not exist', array(57, 400)); + } else { - // Check for new image system - $image_id = $this->wsObject->urlSegment[3]; - $path = implode('/', str_split((string)$image_id)); - $image_size = $this->wsObject->urlSegment[4]; + // Check for new image system + $image_id = $this->wsObject->urlSegment[3]; + $path = implode('/', str_split((string)$image_id)); + $image_size = $this->wsObject->urlSegment[4]; - if (file_exists($directory.$path.'/'.$image_id.(strlen($this->wsObject->urlSegment[4]) > 0 ? '-'.$this->wsObject->urlSegment[4] : '').'.jpg')) - { - $filename = $directory.$path.'/'.$image_id.(strlen($this->wsObject->urlSegment[4]) > 0 ? '-'.$this->wsObject->urlSegment[4] : '').'.jpg'; - $orig_filename = $directory.$path.'/'.$image_id.'.jpg'; - } - else // else old system or not exists - { - $orig_filename = $directory.$object_id.'-'.$image_id.'.jpg'; - $filename = $directory.$object_id.'-'.$image_id.'-'.$image_size.'.jpg'; - } - } - } - // display the list of declinated images - elseif ($this->wsObject->method == 'GET' || $this->wsObject->method == 'HEAD') - { - if ($available_image_ids) - { - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', array(), array('id'=>$object_id)); - foreach ($available_image_ids as $available_image_id) - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('declination', array(), array('id'=>$available_image_id, 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$object_id.'/'.$available_image_id), false); - $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image', array()); - } - else - { - $this->objOutput->setStatus(404); - $this->wsObject->setOutputEnabled(false); - } - } + if (file_exists($directory.$path.'/'.$image_id.(strlen($this->wsObject->urlSegment[4]) > 0 ? '-'.$this->wsObject->urlSegment[4] : '').'.jpg')) { + $filename = $directory.$path.'/'.$image_id.(strlen($this->wsObject->urlSegment[4]) > 0 ? '-'.$this->wsObject->urlSegment[4] : '').'.jpg'; + $orig_filename = $directory.$path.'/'.$image_id.'.jpg'; + } else { + // else old system or not exists - } - // for all other cases - else - { - $orig_filename = $directory.$object_id.'.jpg'; - $image_size = $this->wsObject->urlSegment[3]; - $filename = $directory.$object_id.'-'.$image_size.'.jpg'; - } + $orig_filename = $directory.$object_id.'-'.$image_id.'.jpg'; + $filename = $directory.$object_id.'-'.$image_id.'-'.$image_size.'.jpg'; + } + } + } + // display the list of declinated images + elseif ($this->wsObject->method == 'GET' || $this->wsObject->method == 'HEAD') { + if ($available_image_ids) { + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', array(), array('id'=>$object_id)); + foreach ($available_image_ids as $available_image_id) { + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('declination', array(), array('id'=>$available_image_id, 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$object_id.'/'.$available_image_id), false); + } + $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image', array()); + } else { + $this->objOutput->setStatus(404); + $this->wsObject->setOutputEnabled(false); + } + } + } + // for all other cases + else { + $orig_filename = $directory.$object_id.'.jpg'; + $image_size = $this->wsObject->urlSegment[3]; + $filename = $directory.$object_id.'-'.$image_size.'.jpg'; + } - // in case of declinated images list of a product is get - if ($this->output != '') - return true; + // in case of declinated images list of a product is get + if ($this->output != '') { + return true; + } - // If a size was given try to display it - elseif (isset($image_size) && $image_size != '') - { + // If a size was given try to display it + elseif (isset($image_size) && $image_size != '') { - // Check the given size - if ($this->imageType == 'products' && $image_size == 'bin') - $filename = $directory.$object_id.'-'.$image_id.'.jpg'; - elseif (!in_array($image_size, $normal_image_size_names)) - { - $exception = new WebserviceException('This image size does not exist', array(58, 400)); - throw $exception->setDidYouMean($image_size, $normal_image_size_names); - } - if (!file_exists($filename)) - throw new WebserviceException('This image does not exist on disk', array(59, 500)); + // Check the given size + if ($this->imageType == 'products' && $image_size == 'bin') { + $filename = $directory.$object_id.'-'.$image_id.'.jpg'; + } elseif (!in_array($image_size, $normal_image_size_names)) { + $exception = new WebserviceException('This image size does not exist', array(58, 400)); + throw $exception->setDidYouMean($image_size, $normal_image_size_names); + } + if (!file_exists($filename)) { + throw new WebserviceException('This image does not exist on disk', array(59, 500)); + } - // Display the resized specific image - $this->imgToDisplay = $filename; - return true; - } - // Management of the original image (GET, PUT, POST, DELETE) - elseif (isset($orig_filename)) - { - $orig_filename_exists = file_exists($orig_filename); - return $this->manageDeclinatedImagesCRUD($orig_filename_exists, $orig_filename, $normal_image_sizes, $directory); - } - else - return $this->manageDeclinatedImagesCRUD(false, '', $normal_image_sizes, $directory); - } + // Display the resized specific image + $this->imgToDisplay = $filename; + return true; + } + // Management of the original image (GET, PUT, POST, DELETE) + elseif (isset($orig_filename)) { + $orig_filename_exists = file_exists($orig_filename); + return $this->manageDeclinatedImagesCRUD($orig_filename_exists, $orig_filename, $normal_image_sizes, $directory); + } else { + return $this->manageDeclinatedImagesCRUD(false, '', $normal_image_sizes, $directory); + } + } - /** - * Management of normal images (as categories, suppliers, manufacturers and stores) - * - * @param string $directory the file path of the root of the images folder type - * @return bool - */ - protected function manageDeclinatedImages($directory) - { - // Get available image sizes for the current image type - $normal_image_sizes = ImageType::getImagesTypes($this->imageType); - switch ($this->wsObject->urlSegment[2]) - { - // Match the default images - case 'default': - return $this->manageDefaultDeclinatedImages($directory, $normal_image_sizes); - break; - // Display the list of images - case '': - return $this->manageListDeclinatedImages($directory, $normal_image_sizes); - break; - default: - return $this->manageEntityDeclinatedImages($directory, $normal_image_sizes); - break; - } - } + /** + * Management of normal images (as categories, suppliers, manufacturers and stores) + * + * @param string $directory the file path of the root of the images folder type + * @return bool + */ + protected function manageDeclinatedImages($directory) + { + // Get available image sizes for the current image type + $normal_image_sizes = ImageType::getImagesTypes($this->imageType); + switch ($this->wsObject->urlSegment[2]) { + // Match the default images + case 'default': + return $this->manageDefaultDeclinatedImages($directory, $normal_image_sizes); + break; + // Display the list of images + case '': + return $this->manageListDeclinatedImages($directory, $normal_image_sizes); + break; + default: + return $this->manageEntityDeclinatedImages($directory, $normal_image_sizes); + break; + } + } - protected function manageProductImages() - { - $this->manageDeclinatedImages(_PS_PROD_IMG_DIR_); - } + protected function manageProductImages() + { + $this->manageDeclinatedImages(_PS_PROD_IMG_DIR_); + } - protected function getCustomizations() - { - $customizations = array(); - if (!$results = Db::getInstance()->executeS(' + protected function getCustomizations() + { + $customizations = array(); + if (!$results = Db::getInstance()->executeS(' SELECT DISTINCT c.`id_customization` FROM `'._DB_PREFIX_.'customization` c NATURAL JOIN `'._DB_PREFIX_.'customization_field` cf WHERE c.`id_cart` = '.(int)$this->wsObject->urlSegment[2].' - AND type = 0')) - return array(); - foreach ($results as $result) - $customizations[] = $result['id_customization']; - return $customizations; - } + AND type = 0')) { + return array(); + } + foreach ($results as $result) { + $customizations[] = $result['id_customization']; + } + return $customizations; + } - protected function manageCustomizationImages() - { - $normal_image_sizes = ImageType::getImagesTypes($this->imageType); - if (empty($this->wsObject->urlSegment[2])) - { - $results = Db::getInstance()->executeS('SELECT DISTINCT `id_cart` FROM `'._DB_PREFIX_.'customization`'); - foreach ($results as $result) - $ids[] = $result['id_cart']; - asort($ids); - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('carts', array()); - foreach ($ids as $id) - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('cart', array(), array('id' => $id, 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$id), false); - $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('carts', array()); - return true; - } - elseif (empty($this->wsObject->urlSegment[3])) - { - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('customizations', array()); - $customizations = $this->getCustomizations(); - foreach ($customizations as $id) - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('customization', array(), array('id' => $id, 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$id), false); - $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('customizations', array()); - return true; - } - elseif (empty($this->wsObject->urlSegment[4])) - { - if ($this->wsObject->method == 'GET') - { - $results = Db::getInstance()->executeS( - 'SELECT * + protected function manageCustomizationImages() + { + $normal_image_sizes = ImageType::getImagesTypes($this->imageType); + if (empty($this->wsObject->urlSegment[2])) { + $results = Db::getInstance()->executeS('SELECT DISTINCT `id_cart` FROM `'._DB_PREFIX_.'customization`'); + foreach ($results as $result) { + $ids[] = $result['id_cart']; + } + asort($ids); + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('carts', array()); + foreach ($ids as $id) { + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('cart', array(), array('id' => $id, 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$id), false); + } + $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('carts', array()); + return true; + } elseif (empty($this->wsObject->urlSegment[3])) { + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('customizations', array()); + $customizations = $this->getCustomizations(); + foreach ($customizations as $id) { + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('customization', array(), array('id' => $id, 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$id), false); + } + $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('customizations', array()); + return true; + } elseif (empty($this->wsObject->urlSegment[4])) { + if ($this->wsObject->method == 'GET') { + $results = Db::getInstance()->executeS( + 'SELECT * FROM `'._DB_PREFIX_.'customized_data` WHERE id_customization = '.(int)$this->wsObject->urlSegment[3].' AND type = 0'); - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('images', array()); - foreach ($results as $result) - $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', array(), array('id' => $result['index'], 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$result['index']), false); - $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('images', array()); - return true; - } - } - else - { - if ($this->wsObject->method == 'GET') - { - $results = Db::getInstance()->executeS( - 'SELECT * + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('images', array()); + foreach ($results as $result) { + $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', array(), array('id' => $result['index'], 'xlink_resource'=>$this->wsObject->wsUrl.'images/'.$this->imageType.'/'.$result['index']), false); + } + $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('images', array()); + return true; + } + } else { + if ($this->wsObject->method == 'GET') { + $results = Db::getInstance()->executeS( + 'SELECT * FROM `'._DB_PREFIX_.'customized_data` WHERE id_customization = '.(int)$this->wsObject->urlSegment[3].' AND `index` = '.(int)$this->wsObject->urlSegment[4]); - if (empty($results[0]) || empty($results[0]['value'])) - throw new WebserviceException('This image does not exist on disk', array(61, 500)); - $this->imgToDisplay = _PS_UPLOAD_DIR_.$results[0]['value']; - return true; - } - if ($this->wsObject->method == 'POST') - { - $customizations = $this->getCustomizations(); - if (!in_array((int)$this->wsObject->urlSegment[3], $customizations)) - throw new WebserviceException('Customization does not exist', array(61, 500)); - $results = Db::getInstance()->executeS( - 'SELECT id_customization_field + if (empty($results[0]) || empty($results[0]['value'])) { + throw new WebserviceException('This image does not exist on disk', array(61, 500)); + } + $this->imgToDisplay = _PS_UPLOAD_DIR_.$results[0]['value']; + return true; + } + if ($this->wsObject->method == 'POST') { + $customizations = $this->getCustomizations(); + if (!in_array((int)$this->wsObject->urlSegment[3], $customizations)) { + throw new WebserviceException('Customization does not exist', array(61, 500)); + } + $results = Db::getInstance()->executeS( + 'SELECT id_customization_field FROM `'._DB_PREFIX_.'customization_field` WHERE id_customization_field = '.(int)$this->wsObject->urlSegment[4].' AND type = 0'); - if (empty($results)) - throw new WebserviceException('Customization field does not exist.', array(61, 500)); - $results = Db::getInstance()->executeS( - 'SELECT * + if (empty($results)) { + throw new WebserviceException('Customization field does not exist.', array(61, 500)); + } + $results = Db::getInstance()->executeS( + 'SELECT * FROM `'._DB_PREFIX_.'customized_data` WHERE id_customization = '.(int)$this->wsObject->urlSegment[3].' AND `index` = '.(int)$this->wsObject->urlSegment[4].' AND type = 0'); - if (!empty($results)) // customization field exists and has no value - throw new WebserviceException('Customization field already have a value, please use PUT method.', array(61, 500)); - return $this->manageDeclinatedImagesCRUD(false, '', $normal_image_sizes, _PS_UPLOAD_DIR_); - } - $results = Db::getInstance()->executeS( - 'SELECT * + if (!empty($results)) { // customization field exists and has no value + throw new WebserviceException('Customization field already have a value, please use PUT method.', array(61, 500)); + } + return $this->manageDeclinatedImagesCRUD(false, '', $normal_image_sizes, _PS_UPLOAD_DIR_); + } + $results = Db::getInstance()->executeS( + 'SELECT * FROM `'._DB_PREFIX_.'customized_data` WHERE id_customization = '.(int)$this->wsObject->urlSegment[3].' AND `index` = '.(int)$this->wsObject->urlSegment[4]); - if (empty($results[0]) || empty($results[0]['value'])) - throw new WebserviceException('This image does not exist on disk', array(61, 500)); - $this->imgToDisplay = _PS_UPLOAD_DIR_.$results[0]['value']; - $filename_exists = file_exists($this->imgToDisplay); + if (empty($results[0]) || empty($results[0]['value'])) { + throw new WebserviceException('This image does not exist on disk', array(61, 500)); + } + $this->imgToDisplay = _PS_UPLOAD_DIR_.$results[0]['value']; + $filename_exists = file_exists($this->imgToDisplay); - return $this->manageDeclinatedImagesCRUD($filename_exists, $this->imgToDisplay, $normal_image_sizes, _PS_UPLOAD_DIR_); - } - } + return $this->manageDeclinatedImagesCRUD($filename_exists, $this->imgToDisplay, $normal_image_sizes, _PS_UPLOAD_DIR_); + } + } - /** - * Management of normal images CRUD - * - * @param bool $filename_exists if the filename exists - * @param string $filename the image path - * @param array $image_sizes The - * @param string $directory - * @return bool - * - * @throws WebserviceException - */ - protected function manageDeclinatedImagesCRUD($filename_exists, $filename, $image_sizes, $directory) - { - switch ($this->wsObject->method) - { - // Display the image - case 'GET': - case 'HEAD': - if ($filename_exists) - $this->imgToDisplay = $filename; - else - throw new WebserviceException('This image does not exist on disk', array(61, 500)); - break; - // Modify the image - case 'PUT': - if ($filename_exists) - if ($this->writePostedImageOnDisk($filename, null, null, $image_sizes, $directory)) - { - $this->imgToDisplay = $filename; - return true; - } - else - throw new WebserviceException('Unable to save this image.', array(62, 500)); - else - throw new WebserviceException('This image does not exist on disk', array(63, 500)); - break; - // Delete the image - case 'DELETE': - // Delete products image in DB - if ($this->imageType == 'products') - { - $image = new Image((int)$this->wsObject->urlSegment[3]); - return $image->delete(); - } - elseif ($filename_exists) - { - if (in_array($this->imageType, array('categories', 'manufacturers', 'suppliers', 'stores'))) - { - /** @var ObjectModel $object */ - $object = new $this->wsObject->resourceList[$this->imageType]['class']((int)$this->wsObject->urlSegment[2]); - return $object->deleteImage(true); - } - else - return $this->deleteImageOnDisk($filename, $image_sizes, $directory); - } - else - throw new WebserviceException('This image does not exist on disk', array(64, 500)); - break; - // Add the image - case 'POST': + /** + * Management of normal images CRUD + * + * @param bool $filename_exists if the filename exists + * @param string $filename the image path + * @param array $image_sizes The + * @param string $directory + * @return bool + * + * @throws WebserviceException + */ + protected function manageDeclinatedImagesCRUD($filename_exists, $filename, $image_sizes, $directory) + { + switch ($this->wsObject->method) { + // Display the image + case 'GET': + case 'HEAD': + if ($filename_exists) { + $this->imgToDisplay = $filename; + } else { + throw new WebserviceException('This image does not exist on disk', array(61, 500)); + } + break; + // Modify the image + case 'PUT': + if ($filename_exists) { + if ($this->writePostedImageOnDisk($filename, null, null, $image_sizes, $directory)) { + $this->imgToDisplay = $filename; + return true; + } else { + throw new WebserviceException('Unable to save this image.', array(62, 500)); + } + } else { + throw new WebserviceException('This image does not exist on disk', array(63, 500)); + } + break; + // Delete the image + case 'DELETE': + // Delete products image in DB + if ($this->imageType == 'products') { + $image = new Image((int)$this->wsObject->urlSegment[3]); + return $image->delete(); + } elseif ($filename_exists) { + if (in_array($this->imageType, array('categories', 'manufacturers', 'suppliers', 'stores'))) { + /** @var ObjectModel $object */ + $object = new $this->wsObject->resourceList[$this->imageType]['class']((int)$this->wsObject->urlSegment[2]); + return $object->deleteImage(true); + } else { + return $this->deleteImageOnDisk($filename, $image_sizes, $directory); + } + } else { + throw new WebserviceException('This image does not exist on disk', array(64, 500)); + } + break; + // Add the image + case 'POST': - if ($filename_exists) - throw new WebserviceException('This image already exists. To modify it, please use the PUT method', array(65, 400)); - else - { + if ($filename_exists) { + throw new WebserviceException('This image already exists. To modify it, please use the PUT method', array(65, 400)); + } else { + if ($this->writePostedImageOnDisk($filename, null, null, $image_sizes, $directory)) { + return true; + } else { + throw new WebserviceException('Unable to save this image', array(66, 500)); + } + } + break; + default : + throw new WebserviceException('This method is not allowed', array(67, 405)); + } + } - if ($this->writePostedImageOnDisk($filename, null, null, $image_sizes, $directory)) - return true; - else - throw new WebserviceException('Unable to save this image', array(66, 500)); - } - break; - default : - throw new WebserviceException('This method is not allowed', array(67, 405)); - } - } + /** + * Delete the image on disk + * + * @param string $file_path the image file path + * @param array $image_types The different sizes + * @param string $parent_path The parent path + * @return bool + */ + protected function deleteImageOnDisk($file_path, $image_types = null, $parent_path = null) + { + $this->wsObject->setOutputEnabled(false); + if (file_exists($file_path)) { + // delete image on disk + @unlink($file_path); + // Delete declinated image if needed + if ($image_types) { + foreach ($image_types as $image_type) { + if ($this->defaultImage) { // @todo products images too !! + $declination_path = $parent_path.$this->wsObject->urlSegment[3].'-default-'.$image_type['name'].'.jpg'; + } else { + $declination_path = $parent_path.$this->wsObject->urlSegment[2].'-'.$image_type['name'].'.jpg'; + } + if (!@unlink($declination_path)) { + $this->objOutput->setStatus(204); + return false; + } + } + } + return true; + } else { + $this->objOutput->setStatus(204); + return false; + } + } - /** - * Delete the image on disk - * - * @param string $file_path the image file path - * @param array $image_types The different sizes - * @param string $parent_path The parent path - * @return bool - */ - protected function deleteImageOnDisk($file_path, $image_types = null, $parent_path = null) - { - $this->wsObject->setOutputEnabled(false); - if (file_exists($file_path)) - { - // delete image on disk - @unlink($file_path); - // Delete declinated image if needed - if ($image_types) - { - foreach ($image_types as $image_type) - { - if ($this->defaultImage) // @todo products images too !! - $declination_path = $parent_path.$this->wsObject->urlSegment[3].'-default-'.$image_type['name'].'.jpg'; - else - $declination_path = $parent_path.$this->wsObject->urlSegment[2].'-'.$image_type['name'].'.jpg'; - if (!@unlink($declination_path)) - { - $this->objOutput->setStatus(204); - return false; - } - } - } - return true; - } - else - { - $this->objOutput->setStatus(204); - return false; - } - } + /** + * Write the image on disk + * + * @param string $base_path + * @param string $new_path + * @param int $dest_width + * @param int $dest_height + * @param array $image_types + * @param string $parent_path + * @return string + * + * @throws WebserviceException + */ + protected function writeImageOnDisk($base_path, $new_path, $dest_width = null, $dest_height = null, $image_types = null, $parent_path = null) + { + list($source_width, $source_height, $type, $attr) = getimagesize($base_path); + if (!$source_width) { + throw new WebserviceException('Image width was null', array(68, 400)); + } + if ($dest_width == null) { + $dest_width = $source_width; + } + if ($dest_height == null) { + $dest_height = $source_height; + } + switch ($type) { + case 1: + $source_image = imagecreatefromgif($base_path); + break; + case 3: + $source_image = imagecreatefrompng($base_path); + break; + case 2: + default: + $source_image = imagecreatefromjpeg($base_path); + break; + } - /** - * Write the image on disk - * - * @param string $base_path - * @param string $new_path - * @param int $dest_width - * @param int $dest_height - * @param array $image_types - * @param string $parent_path - * @return string - * - * @throws WebserviceException - */ - protected function writeImageOnDisk($base_path, $new_path, $dest_width = null, $dest_height = null, $image_types = null, $parent_path = null) - { - list($source_width, $source_height, $type, $attr) = getimagesize($base_path); - if (!$source_width) - throw new WebserviceException('Image width was null', array(68, 400)); - if ($dest_width == null) $dest_width = $source_width; - if ($dest_height == null) $dest_height = $source_height; - switch ($type) - { - case 1: - $source_image = imagecreatefromgif($base_path); - break; - case 3: - $source_image = imagecreatefrompng($base_path); - break; - case 2: - default: - $source_image = imagecreatefromjpeg($base_path); - break; - } + $width_diff = $dest_width / $source_width; + $height_diff = $dest_height / $source_height; - $width_diff = $dest_width / $source_width; - $height_diff = $dest_height / $source_height; + if ($width_diff > 1 && $height_diff > 1) { + $next_width = $source_width; + $next_height = $source_height; + } else { + if ((int)(Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 2 || ((int)(Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 && $width_diff > $height_diff)) { + $next_height = $dest_height; + $next_width = (int)(($source_width * $next_height) / $source_height); + $dest_width = ((int)(Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 ? $dest_width : $next_width); + } else { + $next_width = $dest_width; + $next_height = (int)($source_height * $dest_width / $source_width); + $dest_height = ((int)(Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 ? $dest_height : $next_height); + } + } - if ($width_diff > 1 && $height_diff > 1) - { - $next_width = $source_width; - $next_height = $source_height; - } - else - { - if ((int)(Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 2 || ((int)(Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 && $width_diff > $height_diff)) - { - $next_height = $dest_height; - $next_width = (int)(($source_width * $next_height) / $source_height); - $dest_width = ((int)(Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 ? $dest_width : $next_width); - } - else - { - $next_width = $dest_width; - $next_height = (int)($source_height * $dest_width / $source_width); - $dest_height = ((int)(Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 ? $dest_height : $next_height); - } - } + $border_width = (int)(($dest_width - $next_width) / 2); + $border_height = (int)(($dest_height - $next_height) / 2); - $border_width = (int)(($dest_width - $next_width) / 2); - $border_height = (int)(($dest_height - $next_height) / 2); + // Build the image + if ( + !($dest_image = imagecreatetruecolor($dest_width, $dest_height)) || + !($white = imagecolorallocate($dest_image, 255, 255, 255)) || + !imagefill($dest_image, 0, 0, $white) || + !imagecopyresampled($dest_image, $source_image, $border_width, $border_height, 0, 0, $next_width, $next_height, $source_width, $source_height) || + !imagecolortransparent($dest_image, $white) + ) { + throw new WebserviceException(sprintf('Unable to build the image "%s".', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $new_path)), array(69, 500)); + } - // Build the image - if ( - !($dest_image = imagecreatetruecolor($dest_width, $dest_height)) || - !($white = imagecolorallocate($dest_image, 255, 255, 255)) || - !imagefill($dest_image, 0, 0, $white) || - !imagecopyresampled($dest_image, $source_image, $border_width, $border_height, 0, 0, $next_width, $next_height, $source_width, $source_height) || - !imagecolortransparent($dest_image, $white) - ) - throw new WebserviceException(sprintf('Unable to build the image "%s".', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $new_path)), array(69, 500)); + // Write it on disk - // Write it on disk + switch ($this->imgExtension) { + case 'gif': + $imaged = imagegif($dest_image, $new_path); + break; + case 'png': + $quality = (Configuration::get('PS_PNG_QUALITY') === false ? 7 : Configuration::get('PS_PNG_QUALITY')); + $imaged = imagepng($dest_image, $new_path, (int)$quality); + break; + case 'jpeg': + default: + $quality = (Configuration::get('PS_JPEG_QUALITY') === false ? 90 : Configuration::get('PS_JPEG_QUALITY')); + $imaged = imagejpeg($dest_image, $new_path, (int)$quality); + if ($this->wsObject->urlSegment[1] == 'customizations') { + // write smaller image in case of customization image + $product_picture_width = (int)Configuration::get('PS_PRODUCT_PICTURE_WIDTH'); + $product_picture_height = (int)Configuration::get('PS_PRODUCT_PICTURE_HEIGHT'); + if (!ImageManager::resize($new_path, $new_path.'_small', $product_picture_width, $product_picture_height)) { + $this->errors[] = Tools::displayError('An error occurred during the image upload process.'); + } + } + break; + } + imagedestroy($dest_image); + if (!$imaged) { + throw new WebserviceException(sprintf('Unable to write the image "%s".', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $new_path)), array(70, 500)); + } - switch ($this->imgExtension) - { - case 'gif': - $imaged = imagegif($dest_image, $new_path); - break; - case 'png': - $quality = (Configuration::get('PS_PNG_QUALITY') === false ? 7 : Configuration::get('PS_PNG_QUALITY')); - $imaged = imagepng($dest_image, $new_path, (int)$quality); - break; - case 'jpeg': - default: - $quality = (Configuration::get('PS_JPEG_QUALITY') === false ? 90 : Configuration::get('PS_JPEG_QUALITY')); - $imaged = imagejpeg($dest_image, $new_path, (int)$quality); - if ($this->wsObject->urlSegment[1] == 'customizations') - { - // write smaller image in case of customization image - $product_picture_width = (int)Configuration::get('PS_PRODUCT_PICTURE_WIDTH'); - $product_picture_height = (int)Configuration::get('PS_PRODUCT_PICTURE_HEIGHT'); - if (!ImageManager::resize($new_path, $new_path.'_small', $product_picture_width, $product_picture_height)) - $this->errors[] = Tools::displayError('An error occurred during the image upload process.'); - } - break; - } - imagedestroy($dest_image); - if (!$imaged) - throw new WebserviceException(sprintf('Unable to write the image "%s".', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $new_path)), array(70, 500)); + // Write image declinations if present + if ($image_types) { + foreach ($image_types as $image_type) { + if ($this->defaultImage) { + $declination_path = $parent_path.$this->wsObject->urlSegment[3].'-default-'.$image_type['name'].'.jpg'; + } else { + if ($this->imageType == 'products') { + $declination_path = $parent_path.chunk_split($this->wsObject->urlSegment[3], 1, '/').$this->wsObject->urlSegment[3].'-'.$image_type['name'].'.jpg'; + } else { + $declination_path = $parent_path.$this->wsObject->urlSegment[2].'-'.$image_type['name'].'.jpg'; + } + } + if (!$this->writeImageOnDisk($base_path, $declination_path, $image_type['width'], $image_type['height'])) { + throw new WebserviceException(sprintf('Unable to save the declination "%s" of this image.', $image_type['name']), array(71, 500)); + } + } + } - // Write image declinations if present - if ($image_types) - { - foreach ($image_types as $image_type) - { - if ($this->defaultImage) - $declination_path = $parent_path.$this->wsObject->urlSegment[3].'-default-'.$image_type['name'].'.jpg'; - else - { + Hook::exec('actionWatermark', array('id_image' => $this->wsObject->urlSegment[3], 'id_product' => $this->wsObject->urlSegment[2])); + return $new_path; + } - if ($this->image_type == 'products') - $declination_path = $parent_path.chunk_split($this->wsObject->urlSegment[3], 1, '/').$this->wsObject->urlSegment[3].'-'.$image_type['name'].'.jpg'; - else - $declination_path = $parent_path.$this->wsObject->urlSegment[2].'-'.$image_type['name'].'.jpg'; - } - if (!$this->writeImageOnDisk($base_path, $declination_path, $image_type['width'], $image_type['height'])) - throw new WebserviceException(sprintf('Unable to save the declination "%s" of this image.', $image_type['name']), array(71, 500)); - } - } + /** + * Write the posted image on disk + * + * @param string $reception_path + * @param int $dest_width + * @param int $dest_height + * @param array $image_types + * @param string $parent_path + * @return bool + * + * @throws WebserviceException + */ + protected function writePostedImageOnDisk($reception_path, $dest_width = null, $dest_height = null, $image_types = null, $parent_path = null) + { + if ($this->wsObject->method == 'PUT') { + if (isset($_FILES['image']['tmp_name']) && $_FILES['image']['tmp_name']) { + $file = $_FILES['image']; + if ($file['size'] > $this->imgMaxUploadSize) { + throw new WebserviceException(sprintf('The image size is too large (maximum allowed is %d KB)', ($this->imgMaxUploadSize / 1000)), array(72, 400)); + } + // Get mime content type + $mime_type = false; + if (Tools::isCallable('finfo_open')) { + $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME; + $finfo = finfo_open($const); + $mime_type = finfo_file($finfo, $file['tmp_name']); + finfo_close($finfo); + } elseif (Tools::isCallable('mime_content_type')) { + $mime_type = mime_content_type($file['tmp_name']); + } elseif (Tools::isCallable('exec')) { + $mime_type = trim(exec('file -b --mime-type '.escapeshellarg($file['tmp_name']))); + } + if (empty($mime_type) || $mime_type == 'regular file') { + $mime_type = $file['type']; + } + if (($pos = strpos($mime_type, ';')) !== false) { + $mime_type = substr($mime_type, 0, $pos); + } - Hook::exec('actionWatermark', array('id_image' => $this->wsObject->urlSegment[3], 'id_product' => $this->wsObject->urlSegment[2])); - return $new_path; - } + // Check mime content type + if (!$mime_type || !in_array($mime_type, $this->acceptedImgMimeTypes)) { + throw new WebserviceException('This type of image format is not recognized, allowed formats are: '.implode('", "', $this->acceptedImgMimeTypes), array(73, 400)); + } + // Check error while uploading + elseif ($file['error']) { + throw new WebserviceException('Error while uploading image. Please change your server\'s settings', array(74, 400)); + } - /** - * Write the posted image on disk - * - * @param string $reception_path - * @param int $dest_width - * @param int $dest_height - * @param array $image_types - * @param string $parent_path - * @return bool - * - * @throws WebserviceException - */ - protected function writePostedImageOnDisk($reception_path, $dest_width = null, $dest_height = null, $image_types = null, $parent_path = null) - { - if ($this->wsObject->method == 'PUT') - { - if (isset($_FILES['image']['tmp_name']) && $_FILES['image']['tmp_name']) - { - $file = $_FILES['image']; - if ($file['size'] > $this->imgMaxUploadSize) - throw new WebserviceException(sprintf('The image size is too large (maximum allowed is %d KB)', ($this->imgMaxUploadSize / 1000)), array(72, 400)); - // Get mime content type - $mime_type = false; - if (Tools::isCallable('finfo_open')) - { - $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME; - $finfo = finfo_open($const); - $mime_type = finfo_file($finfo, $file['tmp_name']); - finfo_close($finfo); - } - elseif (Tools::isCallable('mime_content_type')) - $mime_type = mime_content_type($file['tmp_name']); - elseif (Tools::isCallable('exec')) - $mime_type = trim(exec('file -b --mime-type '.escapeshellarg($file['tmp_name']))); - if (empty($mime_type) || $mime_type == 'regular file') - $mime_type = $file['type']; - if (($pos = strpos($mime_type, ';')) !== false) - $mime_type = substr($mime_type, 0, $pos); + // Try to copy image file to a temporary file + if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES['image']['tmp_name'], $tmp_name)) { + throw new WebserviceException('Error while copying image to the temporary directory', array(75, 400)); + } + // Try to copy image file to the image directory + else { + $result = $this->writeImageOnDisk($tmp_name, $reception_path, $dest_width, $dest_height, $image_types, $parent_path); + } - // Check mime content type - if (!$mime_type || !in_array($mime_type, $this->acceptedImgMimeTypes)) - throw new WebserviceException('This type of image format is not recognized, allowed formats are: '.implode('", "', $this->acceptedImgMimeTypes), array(73, 400)); - // Check error while uploading - elseif ($file['error']) - throw new WebserviceException('Error while uploading image. Please change your server\'s settings', array(74, 400)); + @unlink($tmp_name); + return $result; + } else { + throw new WebserviceException('Please set an "image" parameter with image data for value', array(76, 400)); + } + } elseif ($this->wsObject->method == 'POST') { + if (isset($_FILES['image']['tmp_name']) && $_FILES['image']['tmp_name']) { + $file = $_FILES['image']; + if ($file['size'] > $this->imgMaxUploadSize) { + throw new WebserviceException(sprintf('The image size is too large (maximum allowed is %d KB)', ($this->imgMaxUploadSize / 1000)), array(72, 400)); + } + require_once(_PS_CORE_DIR_.'/images.inc.php'); + if ($error = ImageManager::validateUpload($file)) { + throw new WebserviceException('Image upload error : '.$error, array(76, 400)); + } - // Try to copy image file to a temporary file - if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES['image']['tmp_name'], $tmp_name)) - throw new WebserviceException('Error while copying image to the temporary directory', array(75, 400)); - // Try to copy image file to the image directory - else - $result = $this->writeImageOnDisk($tmp_name, $reception_path, $dest_width, $dest_height, $image_types, $parent_path); + if (isset($file['tmp_name']) && $file['tmp_name'] != null) { + if ($this->imageType == 'products') { + $product = new Product((int)$this->wsObject->urlSegment[2]); + if (!Validate::isLoadedObject($product)) { + throw new WebserviceException('Product '.(int)$this->wsObject->urlSegment[2].' does not exist', array(76, 400)); + } + $image = new Image(); + $image->id_product = (int)($product->id); + $image->position = Image::getHighestPosition($product->id) + 1; - @unlink($tmp_name); - return $result; - } - else - throw new WebserviceException('Please set an "image" parameter with image data for value', array(76, 400)); - } - elseif ($this->wsObject->method == 'POST') - { - if (isset($_FILES['image']['tmp_name']) && $_FILES['image']['tmp_name']) - { + if (!Image::getCover((int)$product->id)) { + $image->cover = 1; + } else { + $image->cover = 0; + } - $file = $_FILES['image']; - if ($file['size'] > $this->imgMaxUploadSize) - throw new WebserviceException(sprintf('The image size is too large (maximum allowed is %d KB)', ($this->imgMaxUploadSize / 1000)), array(72, 400)); - require_once(_PS_CORE_DIR_.'/images.inc.php'); - if ($error = ImageManager::validateUpload($file)) - throw new WebserviceException('Image upload error : '.$error, array(76, 400)); + if (!$image->add()) { + throw new WebserviceException('Error while creating image', array(76, 400)); + } + if (!Validate::isLoadedObject($product)) { + throw new WebserviceException('Product '.(int)$this->wsObject->urlSegment[2].' does not exist', array(76, 400)); + } + Hook::exec('updateProduct', array('id_product' => (int)$this->wsObject->urlSegment[2])); + } - if (isset($file['tmp_name']) && $file['tmp_name'] != null) - { - if ($this->imageType == 'products') - { - $product = new Product((int)$this->wsObject->urlSegment[2]); - if (!Validate::isLoadedObject($product)) - throw new WebserviceException('Product '.(int)$this->wsObject->urlSegment[2].' does not exist', array(76, 400)); - $image = new Image(); - $image->id_product = (int)($product->id); - $image->position = Image::getHighestPosition($product->id) + 1; + // copy image + if (!isset($file['tmp_name'])) { + return false; + } + if ($error = ImageManager::validateUpload($file, $this->imgMaxUploadSize)) { + throw new WebserviceException('Bad image : '.$error, array(76, 400)); + } - if (!Image::getCover((int)$product->id)) - $image->cover = 1; - else - $image->cover = 0; + if ($this->imageType == 'products') { + $image = new Image($image->id); + if (!(Configuration::get('PS_OLD_FILESYSTEM') && file_exists(_PS_PROD_IMG_DIR_.$product->id.'-'.$image->id.'.jpg'))) { + $image->createImgFolder(); + } - if (!$image->add()) - throw new WebserviceException('Error while creating image', array(76, 400)); - if (!Validate::isLoadedObject($product)) - throw new WebserviceException('Product '.(int)$this->wsObject->urlSegment[2].' does not exist', array(76, 400)); - Hook::exec('updateProduct', array('id_product' => (int)$this->wsObject->urlSegment[2])); - } + if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmp_name)) { + throw new WebserviceException('An error occurred during the image upload', array(76, 400)); + } elseif (!ImageManager::resize($tmp_name, _PS_PROD_IMG_DIR_.$image->getExistingImgPath().'.'.$image->image_format)) { + throw new WebserviceException('An error occurred while copying image', array(76, 400)); + } else { + $images_types = ImageType::getImagesTypes('products'); + foreach ($images_types as $imageType) { + if (!ImageManager::resize($tmp_name, _PS_PROD_IMG_DIR_.$image->getExistingImgPath().'-'.stripslashes($imageType['name']).'.'.$image->image_format, $imageType['width'], $imageType['height'], $image->image_format)) { + $this->_errors[] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']); + } + } + } + @unlink($tmp_name); + $this->imgToDisplay = _PS_PROD_IMG_DIR_.$image->getExistingImgPath().'.'.$image->image_format; + $this->objOutput->setFieldsToDisplay('full'); + $this->output = $this->objOutput->renderEntity($image, 1); + $image_content = array('sqlId' => 'content', 'value' => base64_encode(file_get_contents($this->imgToDisplay)), 'encode' => 'base64'); + $this->output .= $this->objOutput->objectRender->renderField($image_content); + } elseif (in_array($this->imageType, array('categories', 'manufacturers', 'suppliers', 'stores'))) { + if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmp_name)) { + throw new WebserviceException('An error occurred during the image upload', array(76, 400)); + } elseif (!ImageManager::resize($tmp_name, $reception_path)) { + throw new WebserviceException('An error occurred while copying image', array(76, 400)); + } + $images_types = ImageType::getImagesTypes($this->imageType); + foreach ($images_types as $imageType) { + if (!ImageManager::resize($tmp_name, $parent_path.$this->wsObject->urlSegment[2].'-'.stripslashes($imageType['name']).'.jpg', $imageType['width'], $imageType['height'])) { + $this->_errors[] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']); + } + } + @unlink(_PS_TMP_IMG_DIR_.$tmp_name); + $this->imgToDisplay = $reception_path; + } elseif ($this->imageType == 'customizations') { + $filename = md5(uniqid(rand(), true)); + $this->imgToDisplay = _PS_UPLOAD_DIR_.$filename; + if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmp_name)) { + throw new WebserviceException('An error occurred during the image upload', array(76, 400)); + } elseif (!ImageManager::resize($tmp_name, $this->imgToDisplay)) { + throw new WebserviceException('An error occurred while copying image', array(76, 400)); + } + $product_picture_width = (int)Configuration::get('PS_PRODUCT_PICTURE_WIDTH'); + $product_picture_height = (int)Configuration::get('PS_PRODUCT_PICTURE_HEIGHT'); + if (!ImageManager::resize($this->imgToDisplay, $this->imgToDisplay.'_small', $product_picture_width, $product_picture_height)) { + throw new WebserviceException('An error occurred while resizing image', array(76, 400)); + } + @unlink(_PS_TMP_IMG_DIR_.$tmp_name); - // copy image - if (!isset($file['tmp_name'])) - return false; - if ($error = ImageManager::validateUpload($file, $this->imgMaxUploadSize)) - throw new WebserviceException('Bad image : '.$error, array(76, 400)); - - if ($this->imageType == 'products') - { - $image = new Image($image->id); - if (!(Configuration::get('PS_OLD_FILESYSTEM') && file_exists(_PS_PROD_IMG_DIR_.$product->id.'-'.$image->id.'.jpg'))) - $image->createImgFolder(); - - if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmp_name)) - throw new WebserviceException('An error occurred during the image upload', array(76, 400)); - elseif (!ImageManager::resize($tmp_name, _PS_PROD_IMG_DIR_.$image->getExistingImgPath().'.'.$image->image_format)) - throw new WebserviceException('An error occurred while copying image', array(76, 400)); - else - { - $images_types = ImageType::getImagesTypes('products'); - foreach ($images_types as $imageType) - if (!ImageManager::resize($tmp_name, _PS_PROD_IMG_DIR_.$image->getExistingImgPath().'-'.stripslashes($imageType['name']).'.'.$image->image_format, $imageType['width'], $imageType['height'], $image->image_format)) - $this->_errors[] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']); - } - @unlink($tmp_name); - $this->imgToDisplay = _PS_PROD_IMG_DIR_.$image->getExistingImgPath().'.'.$image->image_format; - $this->objOutput->setFieldsToDisplay('full'); - $this->output = $this->objOutput->renderEntity($image, 1); - $image_content = array('sqlId' => 'content', 'value' => base64_encode(file_get_contents($this->imgToDisplay)), 'encode' => 'base64'); - $this->output .= $this->objOutput->objectRender->renderField($image_content); - } - elseif (in_array($this->imageType, array('categories', 'manufacturers', 'suppliers', 'stores'))) - { - if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmp_name)) - throw new WebserviceException('An error occurred during the image upload', array(76, 400)); - elseif (!ImageManager::resize($tmp_name, $reception_path)) - throw new WebserviceException('An error occurred while copying image', array(76, 400)); - $images_types = ImageType::getImagesTypes($this->imageType); - foreach ($images_types as $imageType) - if (!ImageManager::resize($tmp_name, $parent_path.$this->wsObject->urlSegment[2].'-'.stripslashes($imageType['name']).'.jpg', $imageType['width'], $imageType['height'])) - $this->_errors[] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']); - @unlink(_PS_TMP_IMG_DIR_.$tmp_name); - $this->imgToDisplay = $reception_path; - } - elseif ($this->imageType == 'customizations') - { - $filename = md5(uniqid(rand(), true)); - $this->imgToDisplay = _PS_UPLOAD_DIR_.$filename; - if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmp_name)) - throw new WebserviceException('An error occurred during the image upload', array(76, 400)); - elseif (!ImageManager::resize($tmp_name, $this->imgToDisplay)) - throw new WebserviceException('An error occurred while copying image', array(76, 400)); - $product_picture_width = (int)Configuration::get('PS_PRODUCT_PICTURE_WIDTH'); - $product_picture_height = (int)Configuration::get('PS_PRODUCT_PICTURE_HEIGHT'); - if (!ImageManager::resize($this->imgToDisplay, $this->imgToDisplay.'_small', $product_picture_width, $product_picture_height)) - throw new WebserviceException('An error occurred while resizing image', array(76, 400)); - @unlink(_PS_TMP_IMG_DIR_.$tmp_name); - - $query = 'INSERT INTO `'._DB_PREFIX_.'customized_data` (`id_customization`, `type`, `index`, `value`) + $query = 'INSERT INTO `'._DB_PREFIX_.'customized_data` (`id_customization`, `type`, `index`, `value`) VALUES ('.(int)$this->wsObject->urlSegment[3].', 0, '.(int)$this->wsObject->urlSegment[4].', \''.$filename.'\')'; - if (!Db::getInstance()->execute($query)) - return false; - } - return true; - } - } - } - else - throw new WebserviceException('Method '.$this->wsObject->method.' is not allowed for an image resource', array(77, 405)); - } + if (!Db::getInstance()->execute($query)) { + return false; + } + } + return true; + } + } + } else { + throw new WebserviceException('Method '.$this->wsObject->method.' is not allowed for an image resource', array(77, 405)); + } + } } diff --git a/classes/webservice/WebserviceSpecificManagementInterface.php b/classes/webservice/WebserviceSpecificManagementInterface.php index c390cf90..ff87b256 100644 --- a/classes/webservice/WebserviceSpecificManagementInterface.php +++ b/classes/webservice/WebserviceSpecificManagementInterface.php @@ -26,17 +26,17 @@ interface WebserviceSpecificManagementInterface { - public function setObjectOutput(WebserviceOutputBuilderCore $obj); - public function getObjectOutput(); - public function setWsObject(WebserviceRequestCore $obj); - public function getWsObject(); + public function setObjectOutput(WebserviceOutputBuilderCore $obj); + public function getObjectOutput(); + public function setWsObject(WebserviceRequestCore $obj); + public function getWsObject(); - public function manage(); + public function manage(); - /** - * This must be return an array with specific values as WebserviceRequest expects. - * - * @return array - */ - public function getContent(); -} \ No newline at end of file + /** + * This must be return an array with specific values as WebserviceRequest expects. + * + * @return array + */ + public function getContent(); +} diff --git a/classes/webservice/WebserviceSpecificManagementSearch.php b/classes/webservice/WebserviceSpecificManagementSearch.php index 3d62dbee..d7f6a833 100644 --- a/classes/webservice/WebserviceSpecificManagementSearch.php +++ b/classes/webservice/WebserviceSpecificManagementSearch.php @@ -26,102 +26,106 @@ class WebserviceSpecificManagementSearchCore implements WebserviceSpecificManagementInterface { - /** @var WebserviceOutputBuilder */ - protected $objOutput; - protected $output; + /** @var WebserviceOutputBuilder */ + protected $objOutput; + protected $output; - /** @var WebserviceRequest */ - protected $wsObject; + /** @var WebserviceRequest */ + protected $wsObject; - /* ------------------------------------------------ - * GETTERS & SETTERS - * ------------------------------------------------ */ + /* ------------------------------------------------ + * GETTERS & SETTERS + * ------------------------------------------------ */ - /** - * @param WebserviceOutputBuilderCore $obj - * @return WebserviceSpecificManagementInterface - */ - public function setObjectOutput(WebserviceOutputBuilderCore $obj) - { - $this->objOutput = $obj; - return $this; - } + /** + * @param WebserviceOutputBuilderCore $obj + * @return WebserviceSpecificManagementInterface + */ + public function setObjectOutput(WebserviceOutputBuilderCore $obj) + { + $this->objOutput = $obj; + return $this; + } - public function setWsObject(WebserviceRequestCore $obj) - { - $this->wsObject = $obj; - return $this; - } + public function setWsObject(WebserviceRequestCore $obj) + { + $this->wsObject = $obj; + return $this; + } - public function getWsObject() - { - return $this->wsObject; - } - public function getObjectOutput() - { - return $this->objOutput; - } + public function getWsObject() + { + return $this->wsObject; + } + public function getObjectOutput() + { + return $this->objOutput; + } - public function setUrlSegment($segments) - { - $this->urlSegment = $segments; - return $this; - } + public function setUrlSegment($segments) + { + $this->urlSegment = $segments; + return $this; + } - public function getUrlSegment() - { - return $this->urlSegment; - } + public function getUrlSegment() + { + return $this->urlSegment; + } - /** - * Management of search - * - */ - public function manage() - { - if (!isset($this->wsObject->urlFragments['query']) || !isset($this->wsObject->urlFragments['language'])) - throw new WebserviceException('You have to set both the \'language\' and \'query\' parameters to get a result', array(100, 400)); - $objects_products = array(); - $objects_categories = array(); - $objects_products['empty'] = new Product(); - $objects_categories['empty'] = new Category(); + /** + * Management of search + * + */ + public function manage() + { + if (!isset($this->wsObject->urlFragments['query']) || !isset($this->wsObject->urlFragments['language'])) { + throw new WebserviceException('You have to set both the \'language\' and \'query\' parameters to get a result', array(100, 400)); + } + $objects_products = array(); + $objects_categories = array(); + $objects_products['empty'] = new Product(); + $objects_categories['empty'] = new Category(); - $this->_resourceConfiguration = $objects_products['empty']->getWebserviceParameters(); + $this->_resourceConfiguration = $objects_products['empty']->getWebserviceParameters(); - if (!$this->wsObject->setFieldsToDisplay()) - return false; + if (!$this->wsObject->setFieldsToDisplay()) { + return false; + } - $results = Search::find($this->wsObject->urlFragments['language'], $this->wsObject->urlFragments['query'], 1, 1, 'position', 'desc', true, false); - $categories = array(); - foreach ($results as $result) - { - $current = new Product($result['id_product']); - $objects_products[] = $current; - $categories_result = $current->getWsCategories(); - foreach ($categories_result as $category_result) - foreach ($category_result as $id) - $categories[] = $id; - } - $categories = array_unique($categories); - foreach ($categories as $id) - $objects_categories[] = new Category($id); + $results = Search::find($this->wsObject->urlFragments['language'], $this->wsObject->urlFragments['query'], 1, 1, 'position', 'desc', true, false); + $categories = array(); + foreach ($results as $result) { + $current = new Product($result['id_product']); + $objects_products[] = $current; + $categories_result = $current->getWsCategories(); + foreach ($categories_result as $category_result) { + foreach ($category_result as $id) { + $categories[] = $id; + } + } + } + $categories = array_unique($categories); + foreach ($categories as $id) { + $objects_categories[] = new Category($id); + } - $this->output .= $this->objOutput->getContent($objects_products, null, $this->wsObject->fieldsToDisplay, $this->wsObject->depth, WebserviceOutputBuilder::VIEW_LIST, false); - // @todo allow fields of type category and product - // $this->_resourceConfiguration = $objects_categories['empty']->getWebserviceParameters(); - // if (!$this->setFieldsToDisplay()) - // return false; + $this->output .= $this->objOutput->getContent($objects_products, null, $this->wsObject->fieldsToDisplay, $this->wsObject->depth, WebserviceOutputBuilder::VIEW_LIST, false); + // @todo allow fields of type category and product + // $this->_resourceConfiguration = $objects_categories['empty']->getWebserviceParameters(); + // if (!$this->setFieldsToDisplay()) + // return false; - $this->output .= $this->objOutput->getContent($objects_categories, null, $this->wsObject->fieldsToDisplay, $this->wsObject->depth, WebserviceOutputBuilder::VIEW_LIST, false); - } + $this->output .= $this->objOutput->getContent($objects_categories, null, $this->wsObject->fieldsToDisplay, $this->wsObject->depth, WebserviceOutputBuilder::VIEW_LIST, false); + } - /** - * This must be return a string with specific values as WebserviceRequest expects. - * - * @return string - */ - public function getContent() - { - return $this->objOutput->getObjectRender()->overrideContent($this->output); - } -} \ No newline at end of file + /** + * This must be return a string with specific values as WebserviceRequest expects. + * + * @return string + */ + public function getContent() + { + return $this->objOutput->getObjectRender()->overrideContent($this->output); + } +} diff --git a/classes/webservice/index.php b/classes/webservice/index.php index c642967a..91fa49fb 100644 --- a/classes/webservice/index.php +++ b/classes/webservice/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/config/xml/untrusted_modules_list.xml b/config/xml/untrusted_modules_list.xml index 4fe2f879..415863a6 100644 --- a/config/xml/untrusted_modules_list.xml +++ b/config/xml/untrusted_modules_list.xml @@ -1,2 +1,2 @@ <?xml version="1.0"?> -<modules_list><modules type="untrusted"><module name="bankwire"/><module name="blockadshooks"/><module name="blockadvertising"/><module name="blockbanner"/><module name="blockbestsellers"/><module name="blockcart"/><module name="blockcategories"/><module name="blockcms"/><module name="blockcmsinfo"/><module name="blockcontact"/><module name="blockcontactinfos"/><module name="blockcurrencies"/><module name="blockcustomerprivacy"/><module name="blocklanguages"/><module name="blocklink"/><module name="blockmanufacturer"/><module name="blockmyaccount"/><module name="blockmyaccountfooter"/><module name="blocknewproducts"/><module name="blocknewsletter"/><module name="blockpaymentlogo"/><module name="blockpermanentlinks"/><module name="blockreinsurance"/><module name="blockrss"/><module name="blocksearch"/><module name="blocksharefb"/><module name="blocksocial"/><module name="blockspecials"/><module name="blockstore"/><module name="blocksupplier"/><module name="blocktags"/><module name="blocktopmenu"/><module name="blockuserinfo"/><module name="blockviewed"/><module name="blockwishlist"/><module name="categorieshome"/><module name="cheque"/><module name="cms_comments"/><module name="cms_extrafields"/><module name="cms_menu"/><module name="cms_pack"/><module name="cmsps"/><module name="cronjobs"/><module name="crossselling"/><module name="dashactivity"/><module name="dashgoals"/><module name="dashproducts"/><module name="dashtrends"/><module name="graphnvd3"/><module name="gridhtml"/><module name="homefeatured"/><module name="homeproduct"/><module name="homeslider"/><module name="pagesnotfound"/><module name="productcomments"/><module name="productpaymentlogos"/><module name="productscategory"/><module name="producttooltip"/><module name="referralprogram"/><module name="sekeywords"/><module name="sendtoafriend"/><module name="seourl"/><module name="socialsharing"/><module name="vatnumber"/></modules></modules_list> +<modules_list><modules type="untrusted"><module name="bankwire"/><module name="blockadshooks"/><module name="blockadvertising"/><module name="blockbanner"/><module name="blockbestsellers"/><module name="blockcart"/><module name="blockcategories"/><module name="blockcms"/><module name="blockcmsinfo"/><module name="blockcontact"/><module name="blockcontactinfos"/><module name="blockcurrencies"/><module name="blockcustomerprivacy"/><module name="blocklanguages"/><module name="blocklink"/><module name="blockmanufacturer"/><module name="blockmyaccount"/><module name="blockmyaccountfooter"/><module name="blocknewproducts"/><module name="blocknewsletter"/><module name="blockpaymentlogo"/><module name="blockpermanentlinks"/><module name="blockreinsurance"/><module name="blockrss"/><module name="blocksearch"/><module name="blocksharefb"/><module name="blocksocial"/><module name="blockspecials"/><module name="blockstore"/><module name="blocksupplier"/><module name="blocktags"/><module name="blocktopmenu"/><module name="blockuserinfo"/><module name="blockviewed"/><module name="blockwishlist"/><module name="categorieshome"/><module name="cheque"/><module name="cms_comments"/><module name="cms_extrafields"/><module name="cms_menu"/><module name="cms_pack"/><module name="cmsps"/><module name="cronjobs"/><module name="crossselling"/><module name="dashactivity"/><module name="dashgoals"/><module name="dashproducts"/><module name="dashtrends"/><module name="graphnvd3"/><module name="gridhtml"/><module name="homefeatured"/><module name="homeproduct"/><module name="homeslider"/><module name="pagesnotfound"/><module name="paypal"/><module name="productcomments"/><module name="productpaymentlogos"/><module name="productscategory"/><module name="producttooltip"/><module name="referralprogram"/><module name="sekeywords"/><module name="sendtoafriend"/><module name="seourl"/><module name="socialsharing"/><module name="vatnumber"/></modules></modules_list> diff --git a/controllers/admin/AdminAccessController.php b/controllers/admin/AdminAccessController.php index 3b240434..0fb8580b 100644 --- a/controllers/admin/AdminAccessController.php +++ b/controllers/admin/AdminAccessController.php @@ -29,54 +29,56 @@ */ class AdminAccessControllerCore extends AdminController { - /* @var array : Black list of id_tab that do not have access */ - public $accesses_black_list = array(); + /* @var array : Black list of id_tab that do not have access */ + public $accesses_black_list = array(); - public function __construct() - { - $this->bootstrap = true; - $this->show_toolbar = false; - $this->table = 'access'; - $this->className = 'Profile'; - $this->multishop_context = Shop::CONTEXT_ALL; - $this->lang = false; - $this->context = Context::getContext(); + public function __construct() + { + $this->bootstrap = true; + $this->show_toolbar = false; + $this->table = 'access'; + $this->className = 'Profile'; + $this->multishop_context = Shop::CONTEXT_ALL; + $this->lang = false; + $this->context = Context::getContext(); - // Blacklist AdminLogin - $this->accesses_black_list[] = Tab::getIdFromClassName('AdminLogin'); + // Blacklist AdminLogin + $this->accesses_black_list[] = Tab::getIdFromClassName('AdminLogin'); - parent::__construct(); - } + parent::__construct(); + } - /** - * AdminController::renderForm() override - * @see AdminController::renderForm() - */ - public function renderForm() - { - $current_profile = (int)$this->getCurrentProfileId(); - $profiles = Profile::getProfiles($this->context->language->id); - $tabs = Tab::getTabs($this->context->language->id); - $accesses = array(); - foreach ($profiles as $profile) - $accesses[$profile['id_profile']] = Profile::getProfileAccesses($profile['id_profile']); + /** + * AdminController::renderForm() override + * @see AdminController::renderForm() + */ + public function renderForm() + { + $current_profile = (int)$this->getCurrentProfileId(); + $profiles = Profile::getProfiles($this->context->language->id); + $tabs = Tab::getTabs($this->context->language->id); + $accesses = array(); + foreach ($profiles as $profile) { + $accesses[$profile['id_profile']] = Profile::getProfileAccesses($profile['id_profile']); + } - // Deleted id_tab that do not have access - foreach ($tabs as $key => $tab) - { - // Don't allow permissions for unnamed tabs (ie. AdminLogin) - if (empty($tab['name'])) - unset($tabs[$key]); + // Deleted id_tab that do not have access + foreach ($tabs as $key => $tab) { + // Don't allow permissions for unnamed tabs (ie. AdminLogin) + if (empty($tab['name'])) { + unset($tabs[$key]); + } - foreach ($this->accesses_black_list as $id_tab) - if ($tab['id_tab'] == (int)$id_tab) - unset($tabs[$key]); - } + foreach ($this->accesses_black_list as $id_tab) { + if ($tab['id_tab'] == (int)$id_tab) { + unset($tabs[$key]); + } + } + } - $modules = array(); - foreach ($profiles as $profile) - { - $modules[$profile['id_profile']] = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $modules = array(); + foreach ($profiles as $profile) { + $modules[$profile['id_profile']] = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT ma.`id_module`, m.`name`, ma.`view`, ma.`configure`, ma.`uninstall` FROM '._DB_PREFIX_.'module_access ma LEFT JOIN '._DB_PREFIX_.'module m @@ -84,175 +86,179 @@ class AdminAccessControllerCore extends AdminController WHERE id_profile = '.(int)$profile['id_profile'].' ORDER BY m.name '); - foreach ($modules[$profile['id_profile']] as $k => &$module) - { - $m = Module::getInstanceById($module['id_module']); - // the following condition handles invalid modules - if ($m) - $module['name'] = $m->displayName; - else - unset($modules[$profile['id_profile']][$k]); - } + foreach ($modules[$profile['id_profile']] as $k => &$module) { + $m = Module::getInstanceById($module['id_module']); + // the following condition handles invalid modules + if ($m) { + $module['name'] = $m->displayName; + } else { + unset($modules[$profile['id_profile']][$k]); + } + } - uasort($modules[$profile['id_profile']], array($this, 'sortModuleByName')); - } + uasort($modules[$profile['id_profile']], array($this, 'sortModuleByName')); + } - $this->fields_form = array(''); - $this->tpl_form_vars = array( - 'profiles' => $profiles, - 'accesses' => $accesses, - 'id_tab_parentmodule' => (int)Tab::getIdFromClassName('AdminParentModules'), - 'id_tab_module' => (int)Tab::getIdFromClassName('AdminModules'), - 'tabs' => $tabs, - 'current_profile' => (int)$current_profile, - 'admin_profile' => (int)_PS_ADMIN_PROFILE_, - 'access_edit' => $this->tabAccess['edit'], - 'perms' => array('view', 'add', 'edit', 'delete'), - 'modules' => $modules, - 'link' => $this->context->link - ); + $this->fields_form = array(''); + $this->tpl_form_vars = array( + 'profiles' => $profiles, + 'accesses' => $accesses, + 'id_tab_parentmodule' => (int)Tab::getIdFromClassName('AdminParentModules'), + 'id_tab_module' => (int)Tab::getIdFromClassName('AdminModules'), + 'tabs' => $tabs, + 'current_profile' => (int)$current_profile, + 'admin_profile' => (int)_PS_ADMIN_PROFILE_, + 'access_edit' => $this->tabAccess['edit'], + 'perms' => array('view', 'add', 'edit', 'delete'), + 'modules' => $modules, + 'link' => $this->context->link + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - /** - * AdminController::initContent() override - * @see AdminController::initContent() - */ - public function initContent() - { - $this->display = 'edit'; - $this->initTabModuleList(); - if (!$this->loadObject(true)) - return; + /** + * AdminController::initContent() override + * @see AdminController::initContent() + */ + public function initContent() + { + $this->display = 'edit'; + $this->initTabModuleList(); + if (!$this->loadObject(true)) { + return; + } - $this->initPageHeaderToolbar(); + $this->initPageHeaderToolbar(); - $this->content .= $this->renderForm(); - $this->context->smarty->assign(array( - 'content' => $this->content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } + $this->content .= $this->renderForm(); + $this->context->smarty->assign(array( + 'content' => $this->content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } - public function initToolbarTitle() - { - $this->toolbar_title = array_unique($this->breadcrumbs); - } + public function initToolbarTitle() + { + $this->toolbar_title = array_unique($this->breadcrumbs); + } - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); - unset($this->page_header_toolbar_btn['cancel']); - } + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); + unset($this->page_header_toolbar_btn['cancel']); + } - public function ajaxProcessUpdateAccess() - { - if (_PS_MODE_DEMO_) - throw new PrestaShopException(Tools::displayError('This functionality has been disabled.')); - if ($this->tabAccess['edit'] != '1') - throw new PrestaShopException(Tools::displayError('You do not have permission to edit this.')); + public function ajaxProcessUpdateAccess() + { + if (_PS_MODE_DEMO_) { + throw new PrestaShopException(Tools::displayError('This functionality has been disabled.')); + } + if ($this->tabAccess['edit'] != '1') { + throw new PrestaShopException(Tools::displayError('You do not have permission to edit this.')); + } - if (Tools::isSubmit('submitAddAccess')) - { - $perm = Tools::getValue('perm'); - if (!in_array($perm, array('view', 'add', 'edit', 'delete', 'all'))) - throw new PrestaShopException('permission does not exist'); + if (Tools::isSubmit('submitAddAccess')) { + $perm = Tools::getValue('perm'); + if (!in_array($perm, array('view', 'add', 'edit', 'delete', 'all'))) { + throw new PrestaShopException('permission does not exist'); + } - $enabled = (int)Tools::getValue('enabled'); - $id_tab = (int)Tools::getValue('id_tab'); - $id_profile = (int)Tools::getValue('id_profile'); - $where = '`id_tab`'; - $join = ''; - if (Tools::isSubmit('addFromParent')) - { - $where = 't.`id_parent`'; - $join = 'LEFT JOIN `'._DB_PREFIX_.'tab` t ON (t.`id_tab` = a.`id_tab`)'; - } + $enabled = (int)Tools::getValue('enabled'); + $id_tab = (int)Tools::getValue('id_tab'); + $id_profile = (int)Tools::getValue('id_profile'); + $where = '`id_tab`'; + $join = ''; + if (Tools::isSubmit('addFromParent')) { + $where = 't.`id_parent`'; + $join = 'LEFT JOIN `'._DB_PREFIX_.'tab` t ON (t.`id_tab` = a.`id_tab`)'; + } - if ($id_tab == -1) - { - if ($perm == 'all') - $sql = ' + if ($id_tab == -1) { + if ($perm == 'all') { + $sql = ' UPDATE `'._DB_PREFIX_.'access` a SET `view` = '.(int)$enabled.', `add` = '.(int)$enabled.', `edit` = '.(int)$enabled.', `delete` = '.(int)$enabled.' WHERE `id_profile` = '.(int)$id_profile; - else - $sql = ' + } else { + $sql = ' UPDATE `'._DB_PREFIX_.'access` a SET `'.bqSQL($perm).'` = '.(int)$enabled.' WHERE `id_profile` = '.(int)$id_profile; - } - else - { - if ($perm == 'all') - $sql = ' + } + } else { + if ($perm == 'all') { + $sql = ' UPDATE `'._DB_PREFIX_.'access` a '.$join.' SET `view` = '.(int)$enabled.', `add` = '.(int)$enabled.', `edit` = '.(int)$enabled.', `delete` = '.(int)$enabled.' WHERE '.$where.' = '.(int)$id_tab.' AND `id_profile` = '.(int)$id_profile; - else - $sql = ' + } else { + $sql = ' UPDATE `'._DB_PREFIX_.'access` a '.$join.' SET `'.bqSQL($perm).'` = '.(int)$enabled.' WHERE '.$where.' = '.(int)$id_tab.' AND `id_profile` = '.(int)$id_profile; - } + } + } - $res = Db::getInstance()->execute($sql) ? 'ok' : 'error'; + $res = Db::getInstance()->execute($sql) ? 'ok' : 'error'; - die($res); - } - } + die($res); + } + } - public function ajaxProcessUpdateModuleAccess() - { - if (_PS_MODE_DEMO_) - throw new PrestaShopException(Tools::displayError('This functionality has been disabled.')); - if ($this->tabAccess['edit'] != '1') - throw new PrestaShopException(Tools::displayError('You do not have permission to edit this.')); + public function ajaxProcessUpdateModuleAccess() + { + if (_PS_MODE_DEMO_) { + throw new PrestaShopException(Tools::displayError('This functionality has been disabled.')); + } + if ($this->tabAccess['edit'] != '1') { + throw new PrestaShopException(Tools::displayError('You do not have permission to edit this.')); + } - if (Tools::isSubmit('changeModuleAccess')) - { - $perm = Tools::getValue('perm'); - $enabled = (int)Tools::getValue('enabled'); - $id_module = (int)Tools::getValue('id_module'); - $id_profile = (int)Tools::getValue('id_profile'); + if (Tools::isSubmit('changeModuleAccess')) { + $perm = Tools::getValue('perm'); + $enabled = (int)Tools::getValue('enabled'); + $id_module = (int)Tools::getValue('id_module'); + $id_profile = (int)Tools::getValue('id_profile'); - if (!in_array($perm, array('view', 'configure', 'uninstall'))) - throw new PrestaShopException('permission does not exist'); + if (!in_array($perm, array('view', 'configure', 'uninstall'))) { + throw new PrestaShopException('permission does not exist'); + } - if ($id_module == -1) - $sql = ' - UPDATE `'._DB_PREFIX_.'module_access` - SET `'.bqSQL($perm).'` = '.(int)$enabled.' + if ($id_module == -1) { + $sql = ' + UPDATE `'._DB_PREFIX_.'module_access` + SET `'.bqSQL($perm).'` = '.(int)$enabled.' WHERE `id_profile` = '.(int)$id_profile; - else - $sql = ' - UPDATE `'._DB_PREFIX_.'module_access` - SET `'.bqSQL($perm).'` = '.(int)$enabled.' - WHERE `id_module` = '.(int)$id_module.' + } else { + $sql = ' + UPDATE `'._DB_PREFIX_.'module_access` + SET `'.bqSQL($perm).'` = '.(int)$enabled.' + WHERE `id_module` = '.(int)$id_module.' AND `id_profile` = '.(int)$id_profile; + } - $res = Db::getInstance()->execute($sql) ? 'ok' : 'error'; + $res = Db::getInstance()->execute($sql) ? 'ok' : 'error'; - die($res); - } - } + die($res); + } + } - /** - * Get the current profile id - * - * @return int the $_GET['profile'] if valid, else 1 (the first profile id) - */ - public function getCurrentProfileId() - { - return (isset($_GET['id_profile']) && !empty($_GET['id_profile']) && is_numeric($_GET['id_profile'])) ? (int)$_GET['id_profile'] : 1; - } + /** + * Get the current profile id + * + * @return int the $_GET['profile'] if valid, else 1 (the first profile id) + */ + public function getCurrentProfileId() + { + return (isset($_GET['id_profile']) && !empty($_GET['id_profile']) && is_numeric($_GET['id_profile'])) ? (int)$_GET['id_profile'] : 1; + } - private function sortModuleByName($a, $b) - { - return strnatcmp($a['name'], $b['name']); - } + private function sortModuleByName($a, $b) + { + return strnatcmp($a['name'], $b['name']); + } } diff --git a/controllers/admin/AdminAddonsCatalogController.php b/controllers/admin/AdminAddonsCatalogController.php index de433581..3b4d0398 100644 --- a/controllers/admin/AdminAddonsCatalogController.php +++ b/controllers/admin/AdminAddonsCatalogController.php @@ -26,31 +26,31 @@ class AdminAddonsCatalogControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - parent::__construct(); - } + public function __construct() + { + $this->bootstrap = true; + parent::__construct(); + } - public function initContent() - { - $parent_domain = Tools::getHttpHost(true).substr($_SERVER['REQUEST_URI'], 0, -1 * strlen(basename($_SERVER['REQUEST_URI']))); - $iso_lang = $this->context->language->iso_code; - $iso_currency = $this->context->currency->iso_code; - $iso_country = $this->context->country->iso_code; - $activity = Configuration::get('PS_SHOP_ACTIVITY'); - $addons_url = 'http://addons.prestashop.com/iframe/search-1.6.php?psVersion='._PS_VERSION_.'&isoLang='.$iso_lang.'&isoCurrency='.$iso_currency.'&isoCountry='.$iso_country.'&activity='.(int)$activity.'&parentUrl='.$parent_domain; - $addons_content = Tools::file_get_contents($addons_url); + public function initContent() + { + $parent_domain = Tools::getHttpHost(true).substr($_SERVER['REQUEST_URI'], 0, -1 * strlen(basename($_SERVER['REQUEST_URI']))); + $iso_lang = $this->context->language->iso_code; + $iso_currency = $this->context->currency->iso_code; + $iso_country = $this->context->country->iso_code; + $activity = Configuration::get('PS_SHOP_ACTIVITY'); + $addons_url = 'http://addons.prestashop.com/iframe/search-1.6.php?psVersion='._PS_VERSION_.'&isoLang='.$iso_lang.'&isoCurrency='.$iso_currency.'&isoCountry='.$iso_country.'&activity='.(int)$activity.'&parentUrl='.$parent_domain; + $addons_content = Tools::file_get_contents($addons_url); - $this->context->smarty->assign(array( - 'iso_lang' => $iso_lang, - 'iso_currency' => $iso_currency, - 'iso_country' => $iso_country, - 'display_addons_content' => $addons_content !== false, - 'addons_content' => $addons_content, - 'parent_domain' => $parent_domain, - )); + $this->context->smarty->assign(array( + 'iso_lang' => $iso_lang, + 'iso_currency' => $iso_currency, + 'iso_country' => $iso_country, + 'display_addons_content' => $addons_content !== false, + 'addons_content' => $addons_content, + 'parent_domain' => $parent_domain, + )); - parent::initContent(); - } + parent::initContent(); + } } diff --git a/controllers/admin/AdminAddressesController.php b/controllers/admin/AdminAddressesController.php index de79e3f2..add54a33 100644 --- a/controllers/admin/AdminAddressesController.php +++ b/controllers/admin/AdminAddressesController.php @@ -29,511 +29,504 @@ */ class AdminAddressesControllerCore extends AdminController { - /** @var array countries list */ - protected $countries_array = array(); + /** @var array countries list */ + protected $countries_array = array(); - public function __construct() - { - $this->bootstrap = true; - $this->required_database = true; - $this->required_fields = array('company','address2', 'postcode', 'other', 'phone', 'phone_mobile', 'vat_number', 'dni'); - $this->table = 'address'; - $this->className = 'Address'; - $this->lang = false; - $this->addressType = 'customer'; - $this->explicitSelect = true; - $this->context = Context::getContext(); + public function __construct() + { + $this->bootstrap = true; + $this->required_database = true; + $this->required_fields = array('company','address2', 'postcode', 'other', 'phone', 'phone_mobile', 'vat_number', 'dni'); + $this->table = 'address'; + $this->className = 'Address'; + $this->lang = false; + $this->addressType = 'customer'; + $this->explicitSelect = true; + $this->context = Context::getContext(); - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->allow_export = true; + $this->allow_export = true; - if (!Tools::getValue('realedit')) - $this->deleted = true; + if (!Tools::getValue('realedit')) { + $this->deleted = true; + } - $countries = Country::getCountries($this->context->language->id); - foreach ($countries as $country) - $this->countries_array[$country['id_country']] = $country['name']; + $countries = Country::getCountries($this->context->language->id); + foreach ($countries as $country) { + $this->countries_array[$country['id_country']] = $country['name']; + } - $this->fields_list = array( - 'id_address' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'firstname' => array('title' => $this->l('First Name'), 'filter_key' => 'a!firstname'), - 'lastname' => array('title' => $this->l('Last Name'), 'filter_key' => 'a!lastname'), - 'address1' => array('title' => $this->l('Address')), - 'postcode' => array('title' => $this->l('Zip/Postal Code'), 'align' => 'right'), - 'city' => array('title' => $this->l('City')), - 'country' => array('title' => $this->l('Country'), 'type' => 'select', 'list' => $this->countries_array, 'filter_key' => 'cl!id_country')); + $this->fields_list = array( + 'id_address' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'firstname' => array('title' => $this->l('First Name'), 'filter_key' => 'a!firstname'), + 'lastname' => array('title' => $this->l('Last Name'), 'filter_key' => 'a!lastname'), + 'address1' => array('title' => $this->l('Address')), + 'postcode' => array('title' => $this->l('Zip/Postal Code'), 'align' => 'right'), + 'city' => array('title' => $this->l('City')), + 'country' => array('title' => $this->l('Country'), 'type' => 'select', 'list' => $this->countries_array, 'filter_key' => 'cl!id_country')); - parent::__construct(); + parent::__construct(); - $this->_select = 'cl.`name` as country'; - $this->_join = ' + $this->_select = 'cl.`name` as country'; + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'country_lang` cl ON (cl.`id_country` = a.`id_country` AND cl.`id_lang` = '.(int)$this->context->language->id.') LEFT JOIN `'._DB_PREFIX_.'customer` c ON a.id_customer = c.id_customer '; - $this->_where = 'AND a.id_customer != 0 '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER, 'c'); - $this->_use_found_rows = false; - } + $this->_where = 'AND a.id_customer != 0 '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER, 'c'); + $this->_use_found_rows = false; + } - public function initToolbar() - { - parent::initToolbar(); + public function initToolbar() + { + parent::initToolbar(); - if (!$this->display && $this->can_import) - $this->toolbar_btn['import'] = array( - 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=addresses', - 'desc' => $this->l('Import') - ); - } + if (!$this->display && $this->can_import) { + $this->toolbar_btn['import'] = array( + 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=addresses', + 'desc' => $this->l('Import') + ); + } + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_address'] = array( - 'href' => self::$currentIndex.'&addaddress&token='.$this->token, - 'desc' => $this->l('Add new address', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_address'] = array( + 'href' => self::$currentIndex.'&addaddress&token='.$this->token, + 'desc' => $this->l('Add new address', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Addresses'), - 'icon' => 'icon-envelope-alt' - ), - 'input' => array( - array( - 'type' => 'text_customer', - 'label' => $this->l('Customer'), - 'name' => 'id_customer', - 'required' => false, - ), - array( - 'type' => 'text', - 'label' => $this->l('Identification Number'), - 'name' => 'dni', - 'required' => false, - 'col' => '4', - 'hint' => $this->l('DNI / NIF / NIE') - ), - array( - 'type' => 'text', - 'label' => $this->l('Address alias'), - 'name' => 'alias', - 'required' => true, - 'col' => '4', - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Other'), - 'name' => 'other', - 'required' => false, - 'cols' => 15, - 'rows' => 3, - 'hint' => $this->l('Forbidden characters:').' <>;=#{}' - ), - array( - 'type' => 'hidden', - 'name' => 'id_order' - ), - array( - 'type' => 'hidden', - 'name' => 'address_type', - ), - array( - 'type' => 'hidden', - 'name' => 'back' - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Addresses'), + 'icon' => 'icon-envelope-alt' + ), + 'input' => array( + array( + 'type' => 'text_customer', + 'label' => $this->l('Customer'), + 'name' => 'id_customer', + 'required' => false, + ), + array( + 'type' => 'text', + 'label' => $this->l('Identification Number'), + 'name' => 'dni', + 'required' => false, + 'col' => '4', + 'hint' => $this->l('DNI / NIF / NIE') + ), + array( + 'type' => 'text', + 'label' => $this->l('Address alias'), + 'name' => 'alias', + 'required' => true, + 'col' => '4', + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Other'), + 'name' => 'other', + 'required' => false, + 'cols' => 15, + 'rows' => 3, + 'hint' => $this->l('Forbidden characters:').' <>;=#{}' + ), + array( + 'type' => 'hidden', + 'name' => 'id_order' + ), + array( + 'type' => 'hidden', + 'name' => 'address_type', + ), + array( + 'type' => 'hidden', + 'name' => 'back' + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - $this->fields_value['address_type'] = (int)Tools::getValue('address_type', 1); + $this->fields_value['address_type'] = (int)Tools::getValue('address_type', 1); - $id_customer = (int)Tools::getValue('id_customer'); - if (!$id_customer && Validate::isLoadedObject($this->object)) - $id_customer = $this->object->id_customer; - if ($id_customer) - { - $customer = new Customer((int)$id_customer); - $token_customer = Tools::getAdminToken('AdminCustomers'.(int)(Tab::getIdFromClassName('AdminCustomers')).(int)$this->context->employee->id); - } + $id_customer = (int)Tools::getValue('id_customer'); + if (!$id_customer && Validate::isLoadedObject($this->object)) { + $id_customer = $this->object->id_customer; + } + if ($id_customer) { + $customer = new Customer((int)$id_customer); + $token_customer = Tools::getAdminToken('AdminCustomers'.(int)(Tab::getIdFromClassName('AdminCustomers')).(int)$this->context->employee->id); + } - $this->tpl_form_vars = array( - 'customer' => isset($customer) ? $customer : null, - 'tokenCustomer' => isset ($token_customer) ? $token_customer : null, - 'back_url' => urldecode(Tools::getValue('back')) - ); + $this->tpl_form_vars = array( + 'customer' => isset($customer) ? $customer : null, + 'tokenCustomer' => isset($token_customer) ? $token_customer : null, + 'back_url' => urldecode(Tools::getValue('back')) + ); - // Order address fields depending on country format - $addresses_fields = $this->processAddressFormat(); - // we use delivery address - $addresses_fields = $addresses_fields['dlv_all_fields']; + // Order address fields depending on country format + $addresses_fields = $this->processAddressFormat(); + // we use delivery address + $addresses_fields = $addresses_fields['dlv_all_fields']; - // get required field - $required_fields = AddressFormat::getFieldsRequired(); + // get required field + $required_fields = AddressFormat::getFieldsRequired(); - // Merge with field required - $addresses_fields = array_unique(array_merge($addresses_fields, $required_fields)); + // Merge with field required + $addresses_fields = array_unique(array_merge($addresses_fields, $required_fields)); - $temp_fields = array(); + $temp_fields = array(); - foreach ($addresses_fields as $addr_field_item) - { - if ($addr_field_item == 'company') - { - $temp_fields[] = array( - 'type' => 'text', - 'label' => $this->l('Company'), - 'name' => 'company', - 'required' => in_array('company', $required_fields), - 'col' => '4', - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ); - $temp_fields[] = array( - 'type' => 'text', - 'label' => $this->l('VAT number'), - 'col' => '2', - 'name' => 'vat_number', - 'required' => in_array('vat_number', $required_fields) - ); - } - elseif ($addr_field_item == 'lastname') - { - if (isset($customer) && - !Tools::isSubmit('submit'.strtoupper($this->table)) && - Validate::isLoadedObject($customer) && - !Validate::isLoadedObject($this->object)) - $default_value = $customer->lastname; - else - $default_value = ''; + foreach ($addresses_fields as $addr_field_item) { + if ($addr_field_item == 'company') { + $temp_fields[] = array( + 'type' => 'text', + 'label' => $this->l('Company'), + 'name' => 'company', + 'required' => in_array('company', $required_fields), + 'col' => '4', + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ); + $temp_fields[] = array( + 'type' => 'text', + 'label' => $this->l('VAT number'), + 'col' => '2', + 'name' => 'vat_number', + 'required' => in_array('vat_number', $required_fields) + ); + } elseif ($addr_field_item == 'lastname') { + if (isset($customer) && + !Tools::isSubmit('submit'.strtoupper($this->table)) && + Validate::isLoadedObject($customer) && + !Validate::isLoadedObject($this->object)) { + $default_value = $customer->lastname; + } else { + $default_value = ''; + } - $temp_fields[] = array( - 'type' => 'text', - 'label' => $this->l('Last Name'), - 'name' => 'lastname', - 'required' => true, - 'col' => '4', - 'hint' => $this->l('Invalid characters:').' 0-9!&lt;&gt;,;?=+()@#"�{}_$%:', - 'default_value' => $default_value, - ); - } - elseif ($addr_field_item == 'firstname') - { - if (isset($customer) && - !Tools::isSubmit('submit'.strtoupper($this->table)) && - Validate::isLoadedObject($customer) && - !Validate::isLoadedObject($this->object)) - $default_value = $customer->firstname; - else - $default_value = ''; + $temp_fields[] = array( + 'type' => 'text', + 'label' => $this->l('Last Name'), + 'name' => 'lastname', + 'required' => true, + 'col' => '4', + 'hint' => $this->l('Invalid characters:').' 0-9!&lt;&gt;,;?=+()@#"�{}_$%:', + 'default_value' => $default_value, + ); + } elseif ($addr_field_item == 'firstname') { + if (isset($customer) && + !Tools::isSubmit('submit'.strtoupper($this->table)) && + Validate::isLoadedObject($customer) && + !Validate::isLoadedObject($this->object)) { + $default_value = $customer->firstname; + } else { + $default_value = ''; + } - $temp_fields[] = array( - 'type' => 'text', - 'label' => $this->l('First Name'), - 'name' => 'firstname', - 'required' => true, - 'col' => '4', - 'hint' => $this->l('Invalid characters:').' 0-9!&lt;&gt;,;?=+()@#"�{}_$%:', - 'default_value' => $default_value, - ); - } - elseif ($addr_field_item == 'address1') - { - $temp_fields[] = array( - 'type' => 'text', - 'label' => $this->l('Address'), - 'name' => 'address1', - 'col' => '6', - 'required' => true, - ); - } - elseif ($addr_field_item == 'address2') - { - $temp_fields[] = array( - 'type' => 'text', - 'label' => $this->l('Address').' (2)', - 'name' => 'address2', - 'col' => '6', - 'required' => in_array('address2', $required_fields), - ); - } - elseif ($addr_field_item == 'postcode') - { - $temp_fields[] = array( - 'type' => 'text', - 'label' => $this->l('Zip/Postal Code'), - 'name' => 'postcode', - 'col' => '2', - 'required' => true, - ); - } - elseif ($addr_field_item == 'city') - { - $temp_fields[] = array( - 'type' => 'text', - 'label' => $this->l('City'), - 'name' => 'city', - 'col' => '4', - 'required' => true, - ); - } - elseif ($addr_field_item == 'country' || $addr_field_item == 'Country:name') - { - $temp_fields[] = array( - 'type' => 'select', - 'label' => $this->l('Country'), - 'name' => 'id_country', - 'required' => in_array('Country:name', $required_fields) || in_array('country', $required_fields), - 'col' => '4', - 'default_value' => (int)$this->context->country->id, - 'options' => array( - 'query' => Country::getCountries($this->context->language->id), - 'id' => 'id_country', - 'name' => 'name' - ) - ); - $temp_fields[] = array( - 'type' => 'select', - 'label' => $this->l('State'), - 'name' => 'id_state', - 'required' => false, - 'col' => '4', - 'options' => array( - 'query' => array(), - 'id' => 'id_state', - 'name' => 'name' - ) - ); - } - elseif ($addr_field_item == 'phone') - { - $temp_fields[] = array( - 'type' => 'text', - 'label' => $this->l('Home phone'), - 'name' => 'phone', - 'required' => in_array('phone', $required_fields) || Configuration::get('PS_ONE_PHONE_AT_LEAST'), - 'col' => '4', - 'hint' => Configuration::get('PS_ONE_PHONE_AT_LEAST') ? sprintf($this->l('You must register at least one phone number.')) : '' - ); - } - elseif ($addr_field_item == 'phone_mobile') - { - $temp_fields[] = array( - 'type' => 'text', - 'label' => $this->l('Mobile phone'), - 'name' => 'phone_mobile', - 'required' => in_array('phone_mobile', $required_fields) || Configuration::get('PS_ONE_PHONE_AT_LEAST'), - 'col' => '4', - 'hint' => Configuration::get('PS_ONE_PHONE_AT_LEAST') ? sprintf($this->l('You must register at least one phone number.')) : '' - ); - } - } + $temp_fields[] = array( + 'type' => 'text', + 'label' => $this->l('First Name'), + 'name' => 'firstname', + 'required' => true, + 'col' => '4', + 'hint' => $this->l('Invalid characters:').' 0-9!&lt;&gt;,;?=+()@#"�{}_$%:', + 'default_value' => $default_value, + ); + } elseif ($addr_field_item == 'address1') { + $temp_fields[] = array( + 'type' => 'text', + 'label' => $this->l('Address'), + 'name' => 'address1', + 'col' => '6', + 'required' => true, + ); + } elseif ($addr_field_item == 'address2') { + $temp_fields[] = array( + 'type' => 'text', + 'label' => $this->l('Address').' (2)', + 'name' => 'address2', + 'col' => '6', + 'required' => in_array('address2', $required_fields), + ); + } elseif ($addr_field_item == 'postcode') { + $temp_fields[] = array( + 'type' => 'text', + 'label' => $this->l('Zip/Postal Code'), + 'name' => 'postcode', + 'col' => '2', + 'required' => true, + ); + } elseif ($addr_field_item == 'city') { + $temp_fields[] = array( + 'type' => 'text', + 'label' => $this->l('City'), + 'name' => 'city', + 'col' => '4', + 'required' => true, + ); + } elseif ($addr_field_item == 'country' || $addr_field_item == 'Country:name') { + $temp_fields[] = array( + 'type' => 'select', + 'label' => $this->l('Country'), + 'name' => 'id_country', + 'required' => in_array('Country:name', $required_fields) || in_array('country', $required_fields), + 'col' => '4', + 'default_value' => (int)$this->context->country->id, + 'options' => array( + 'query' => Country::getCountries($this->context->language->id), + 'id' => 'id_country', + 'name' => 'name' + ) + ); + $temp_fields[] = array( + 'type' => 'select', + 'label' => $this->l('State'), + 'name' => 'id_state', + 'required' => false, + 'col' => '4', + 'options' => array( + 'query' => array(), + 'id' => 'id_state', + 'name' => 'name' + ) + ); + } elseif ($addr_field_item == 'phone') { + $temp_fields[] = array( + 'type' => 'text', + 'label' => $this->l('Home phone'), + 'name' => 'phone', + 'required' => in_array('phone', $required_fields) || Configuration::get('PS_ONE_PHONE_AT_LEAST'), + 'col' => '4', + 'hint' => Configuration::get('PS_ONE_PHONE_AT_LEAST') ? sprintf($this->l('You must register at least one phone number.')) : '' + ); + } elseif ($addr_field_item == 'phone_mobile') { + $temp_fields[] = array( + 'type' => 'text', + 'label' => $this->l('Mobile phone'), + 'name' => 'phone_mobile', + 'required' => in_array('phone_mobile', $required_fields) || Configuration::get('PS_ONE_PHONE_AT_LEAST'), + 'col' => '4', + 'hint' => Configuration::get('PS_ONE_PHONE_AT_LEAST') ? sprintf($this->l('You must register at least one phone number.')) : '' + ); + } + } - // merge address format with the rest of the form - array_splice($this->fields_form['input'], 3, 0, $temp_fields); + // merge address format with the rest of the form + array_splice($this->fields_form['input'], 3, 0, $temp_fields); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function processSave() - { - if (Tools::getValue('submitFormAjax')) - $this->redirect_after = false; + public function processSave() + { + if (Tools::getValue('submitFormAjax')) { + $this->redirect_after = false; + } - // Transform e-mail in id_customer for parent processing - if (Validate::isEmail(Tools::getValue('email'))) - { - $customer = new Customer(); - $customer->getByEmail(Tools::getValue('email'), null, false); - if (Validate::isLoadedObject($customer)) - $_POST['id_customer'] = $customer->id; - else - $this->errors[] = Tools::displayError('This email address is not registered.'); - } - elseif ($id_customer = Tools::getValue('id_customer')) - { - $customer = new Customer((int)$id_customer); - if (Validate::isLoadedObject($customer)) - $_POST['id_customer'] = $customer->id; - else - $this->errors[] = Tools::displayError('This customer ID is not recognized.'); - } - else - $this->errors[] = Tools::displayError('This email address is not valid. Please use an address like bob@example.com.'); - if (Country::isNeedDniByCountryId(Tools::getValue('id_country')) && !Tools::getValue('dni')) - $this->errors[] = Tools::displayError('The identification number is incorrect or has already been used.'); + // Transform e-mail in id_customer for parent processing + if (Validate::isEmail(Tools::getValue('email'))) { + $customer = new Customer(); + $customer->getByEmail(Tools::getValue('email'), null, false); + if (Validate::isLoadedObject($customer)) { + $_POST['id_customer'] = $customer->id; + } else { + $this->errors[] = Tools::displayError('This email address is not registered.'); + } + } elseif ($id_customer = Tools::getValue('id_customer')) { + $customer = new Customer((int)$id_customer); + if (Validate::isLoadedObject($customer)) { + $_POST['id_customer'] = $customer->id; + } else { + $this->errors[] = Tools::displayError('This customer ID is not recognized.'); + } + } else { + $this->errors[] = Tools::displayError('This email address is not valid. Please use an address like bob@example.com.'); + } + if (Country::isNeedDniByCountryId(Tools::getValue('id_country')) && !Tools::getValue('dni')) { + $this->errors[] = Tools::displayError('The identification number is incorrect or has already been used.'); + } - /* If the selected country does not contain states */ - $id_state = (int)Tools::getValue('id_state'); - $id_country = (int)Tools::getValue('id_country'); - $country = new Country((int)$id_country); - if ($country && !(int)$country->contains_states && $id_state) - $this->errors[] = Tools::displayError('You have selected a state for a country that does not contain states.'); + /* If the selected country does not contain states */ + $id_state = (int)Tools::getValue('id_state'); + $id_country = (int)Tools::getValue('id_country'); + $country = new Country((int)$id_country); + if ($country && !(int)$country->contains_states && $id_state) { + $this->errors[] = Tools::displayError('You have selected a state for a country that does not contain states.'); + } - /* If the selected country contains states, then a state have to be selected */ - if ((int)$country->contains_states && !$id_state) - $this->errors[] = Tools::displayError('An address located in a country containing states must have a state selected.'); + /* If the selected country contains states, then a state have to be selected */ + if ((int)$country->contains_states && !$id_state) { + $this->errors[] = Tools::displayError('An address located in a country containing states must have a state selected.'); + } - $postcode = Tools::getValue('postcode'); - /* Check zip code format */ - if ($country->zip_code_format && !$country->checkZipCode($postcode)) - $this->errors[] = Tools::displayError('Your Zip/postal code is incorrect.').'<br />'.Tools::displayError('It must be entered as follows:').' '.str_replace('C', $country->iso_code, str_replace('N', '0', str_replace('L', 'A', $country->zip_code_format))); - elseif (empty($postcode) && $country->need_zip_code) - $this->errors[] = Tools::displayError('A Zip/postal code is required.'); - elseif ($postcode && !Validate::isPostCode($postcode)) - $this->errors[] = Tools::displayError('The Zip/postal code is invalid.'); + $postcode = Tools::getValue('postcode'); + /* Check zip code format */ + if ($country->zip_code_format && !$country->checkZipCode($postcode)) { + $this->errors[] = Tools::displayError('Your Zip/postal code is incorrect.').'<br />'.Tools::displayError('It must be entered as follows:').' '.str_replace('C', $country->iso_code, str_replace('N', '0', str_replace('L', 'A', $country->zip_code_format))); + } elseif (empty($postcode) && $country->need_zip_code) { + $this->errors[] = Tools::displayError('A Zip/postal code is required.'); + } elseif ($postcode && !Validate::isPostCode($postcode)) { + $this->errors[] = Tools::displayError('The Zip/postal code is invalid.'); + } - if (Configuration::get('PS_ONE_PHONE_AT_LEAST') && !Tools::getValue('phone') && !Tools::getValue('phone_mobile')) - $this->errors[] = Tools::displayError('You must register at least one phone number.'); + if (Configuration::get('PS_ONE_PHONE_AT_LEAST') && !Tools::getValue('phone') && !Tools::getValue('phone_mobile')) { + $this->errors[] = Tools::displayError('You must register at least one phone number.'); + } - /* If this address come from order's edition and is the same as the other one (invoice or delivery one) - ** we delete its id_address to force the creation of a new one */ - if ((int)Tools::getValue('id_order')) - { - $this->_redirect = false; - if (isset($_POST['address_type'])) - { - $_POST['id_address'] = ''; - $this->id_object = null; - } - } + /* If this address come from order's edition and is the same as the other one (invoice or delivery one) + ** we delete its id_address to force the creation of a new one */ + if ((int)Tools::getValue('id_order')) { + $this->_redirect = false; + if (isset($_POST['address_type'])) { + $_POST['id_address'] = ''; + $this->id_object = null; + } + } - // Check the requires fields which are settings in the BO - $address = new Address(); - $this->errors = array_merge($this->errors, $address->validateFieldsRequiredDatabase()); + // Check the requires fields which are settings in the BO + $address = new Address(); + $this->errors = array_merge($this->errors, $address->validateFieldsRequiredDatabase()); - $return = false; - if (empty($this->errors)) - $return = parent::processSave(); - else - // if we have errors, we stay on the form instead of going back to the list - $this->display = 'edit'; + $return = false; + if (empty($this->errors)) { + $return = parent::processSave(); + } else { + // if we have errors, we stay on the form instead of going back to the list + $this->display = 'edit'; + } - /* Reassignation of the order's new (invoice or delivery) address */ - $address_type = (int)Tools::getValue('address_type') == 2 ? 'invoice' : 'delivery'; + /* Reassignation of the order's new (invoice or delivery) address */ + $address_type = (int)Tools::getValue('address_type') == 2 ? 'invoice' : 'delivery'; - if ($this->action == 'save' && ($id_order = (int)Tools::getValue('id_order')) && !count($this->errors) && !empty($address_type)) - { - if (!Db::getInstance()->Execute('UPDATE '._DB_PREFIX_.'orders SET `id_address_'.bqSQL($address_type).'` = '.(int)$this->object->id.' WHERE `id_order` = '.(int)$id_order)) - $this->errors[] = Tools::displayError('An error occurred while linking this address to its order.'); - else - Tools::redirectAdmin(urldecode(Tools::getValue('back')).'&conf=4'); - } - return $return; - } + if ($this->action == 'save' && ($id_order = (int)Tools::getValue('id_order')) && !count($this->errors) && !empty($address_type)) { + if (!Db::getInstance()->Execute('UPDATE '._DB_PREFIX_.'orders SET `id_address_'.bqSQL($address_type).'` = '.(int)$this->object->id.' WHERE `id_order` = '.(int)$id_order)) { + $this->errors[] = Tools::displayError('An error occurred while linking this address to its order.'); + } else { + Tools::redirectAdmin(urldecode(Tools::getValue('back')).'&conf=4'); + } + } + return $return; + } - public function processAdd() - { - if (Tools::getValue('submitFormAjax')) - $this->redirect_after = false; + public function processAdd() + { + if (Tools::getValue('submitFormAjax')) { + $this->redirect_after = false; + } - return parent::processAdd(); - } + return parent::processAdd(); + } - /** - * Get Address formats used by the country where the address id retrieved from POST/GET is. - * - * @return array address formats - */ - protected function processAddressFormat() - { - $tmp_addr = new Address((int)Tools::getValue('id_address')); + /** + * Get Address formats used by the country where the address id retrieved from POST/GET is. + * + * @return array address formats + */ + protected function processAddressFormat() + { + $tmp_addr = new Address((int)Tools::getValue('id_address')); - $selected_country = ($tmp_addr && $tmp_addr->id_country) ? $tmp_addr->id_country : (int)Configuration::get('PS_COUNTRY_DEFAULT'); + $selected_country = ($tmp_addr && $tmp_addr->id_country) ? $tmp_addr->id_country : (int)Configuration::get('PS_COUNTRY_DEFAULT'); - $inv_adr_fields = AddressFormat::getOrderedAddressFields($selected_country, false, true); - $dlv_adr_fields = AddressFormat::getOrderedAddressFields($selected_country, false, true); + $inv_adr_fields = AddressFormat::getOrderedAddressFields($selected_country, false, true); + $dlv_adr_fields = AddressFormat::getOrderedAddressFields($selected_country, false, true); - $inv_all_fields = array(); - $dlv_all_fields = array(); + $inv_all_fields = array(); + $dlv_all_fields = array(); - $out = array(); + $out = array(); - foreach (array('inv','dlv') as $adr_type) - { - foreach (${$adr_type.'_adr_fields'} as $fields_line) - foreach (explode(' ', $fields_line) as $field_item) - ${$adr_type.'_all_fields'}[] = trim($field_item); + foreach (array('inv', 'dlv') as $adr_type) { + foreach (${$adr_type.'_adr_fields'} as $fields_line) { + foreach (explode(' ', $fields_line) as $field_item) { + ${$adr_type.'_all_fields'}[] = trim($field_item); + } + } - $out[$adr_type.'_adr_fields'] = ${$adr_type.'_adr_fields'}; - $out[$adr_type.'_all_fields'] = ${$adr_type.'_all_fields'}; - } + $out[$adr_type.'_adr_fields'] = ${$adr_type.'_adr_fields'}; + $out[$adr_type.'_all_fields'] = ${$adr_type.'_all_fields'}; + } - return $out; - } + return $out; + } - /** - * Method called when an ajax request is made - * @see AdminController::postProcess() - */ - public function ajaxProcess() - { - if (Tools::isSubmit('email')) - { - $email = pSQL(Tools::getValue('email')); - $customer = Customer::searchByName($email); - if (!empty($customer)) - { - $customer = $customer['0']; - echo Tools::jsonEncode(array('infos' => pSQL($customer['firstname']).'_'.pSQL($customer['lastname']).'_'.pSQL($customer['company']))); - } - } - die; - } + /** + * Method called when an ajax request is made + * @see AdminController::postProcess() + */ + public function ajaxProcess() + { + if (Tools::isSubmit('email')) { + $email = pSQL(Tools::getValue('email')); + $customer = Customer::searchByName($email); + if (!empty($customer)) { + $customer = $customer['0']; + echo Tools::jsonEncode(array('infos' => pSQL($customer['firstname']).'_'.pSQL($customer['lastname']).'_'.pSQL($customer['company']))); + } + } + die; + } - /** - * Object Delete - */ - public function processDelete() - { - if (Validate::isLoadedObject($object = $this->loadObject())) - { - /** @var Address $object */ - if (!$object->isUsed()) - $this->deleted = false; - } + /** + * Object Delete + */ + public function processDelete() + { + if (Validate::isLoadedObject($object = $this->loadObject())) { + /** @var Address $object */ + if (!$object->isUsed()) { + $this->deleted = false; + } + } - return parent::processDelete(); - } + $res = parent::processDelete(); - /** - * Delete multiple items - * - * @return bool true if succcess - */ - protected function processBulkDelete() - { - if (is_array($this->boxes) && !empty($this->boxes)) - { - $deleted = false; - foreach ($this->boxes as $id) - { - $to_delete = new Address((int)$id); - if ($to_delete->isUsed()) - { - $deleted = true; - break; - } - } - $this->deleted = $deleted; - } + if ($back = Tools::getValue('back')) { + $this->redirect_after = urldecode($back).'&conf=1'; + } - return parent::processBulkDelete(); - } + return $res; + } + + /** + * Delete multiple items + * + * @return bool true if succcess + */ + protected function processBulkDelete() + { + if (is_array($this->boxes) && !empty($this->boxes)) { + $deleted = false; + foreach ($this->boxes as $id) { + $to_delete = new Address((int)$id); + if ($to_delete->isUsed()) { + $deleted = true; + break; + } + } + $this->deleted = $deleted; + } + + return parent::processBulkDelete(); + } } diff --git a/controllers/admin/AdminAdminPreferencesController.php b/controllers/admin/AdminAdminPreferencesController.php index b24edac1..a785c1da 100644 --- a/controllers/admin/AdminAdminPreferencesController.php +++ b/controllers/admin/AdminAdminPreferencesController.php @@ -29,167 +29,168 @@ */ class AdminAdminPreferencesControllerCore extends AdminController { + public function __construct() + { + $this->bootstrap = true; + $this->className = 'Configuration'; + $this->table = 'configuration'; - public function __construct() - { - $this->bootstrap = true; - $this->className = 'Configuration'; - $this->table = 'configuration'; + parent::__construct(); - parent::__construct(); + // Upload quota + $max_upload = (int)ini_get('upload_max_filesize'); + $max_post = (int)ini_get('post_max_size'); + $upload_mb = min($max_upload, $max_post); - // Upload quota - $max_upload = (int)ini_get('upload_max_filesize'); - $max_post = (int)ini_get('post_max_size'); - $upload_mb = min($max_upload, $max_post); + // Options list + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('General'), + 'icon' => 'icon-cogs', + 'fields' => array( + 'PRESTASTORE_LIVE' => array( + 'title' => $this->l('Automatically check for module updates'), + 'hint' => $this->l('New modules and updates are displayed on the modules page.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'visibility' => Shop::CONTEXT_ALL + ), + 'PS_COOKIE_CHECKIP' => array( + 'title' => $this->l('Check the cookie\'s IP address'), + 'hint' => $this->l('Check the IP address of the cookie in order to prevent your cookie from being stolen.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'default' => '0', + 'visibility' => Shop::CONTEXT_ALL + ), + 'PS_COOKIE_LIFETIME_FO' => array( + 'title' => $this->l('Lifetime of front office cookies'), + 'hint' => $this->l('Set the amount of hours during which the front office cookies are valid. After that amount of time, the customer will have to log in again.'), + 'validation' => 'isInt', + 'cast' => 'intval', + 'type' => 'text', + 'suffix' => $this->l('hours'), + 'default' => '480', + 'visibility' => Shop::CONTEXT_ALL + ), + 'PS_COOKIE_LIFETIME_BO' => array( + 'title' => $this->l('Lifetime of back office cookies'), + 'hint' => $this->l('Set the amount of hours during which the back office cookies are valid. After that amount of time, the PrestaShop user will have to log in again.'), + 'validation' => 'isInt', + 'cast' => 'intval', + 'type' => 'text', + 'suffix' => $this->l('hours'), + 'default' => '480', + 'visibility' => Shop::CONTEXT_ALL + ), + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'upload' => array( + 'title' => $this->l('Upload quota'), + 'icon' => 'icon-cloud-upload', + 'fields' => array( + 'PS_ATTACHMENT_MAXIMUM_SIZE' => array( + 'title' => $this->l('Maximum size for attachment'), + 'hint' => sprintf($this->l('Set the maximum size allowed for attachment files (in megabytes). This value has to be lower or equal to the maximum file upload allotted by your server (currently: %s MB).'), $upload_mb), + 'validation' => 'isInt', + 'cast' => 'intval', + 'type' => 'text', + 'suffix' => $this->l('megabytes'), + 'default' => '2' + ), + 'PS_LIMIT_UPLOAD_FILE_VALUE' => array( + 'title' => $this->l('Maximum size for a downloadable product'), + 'hint' => sprintf($this->l('Define the upload limit for a downloadable product (in megabytes). This value has to be lower or equal to the maximum file upload allotted by your server (currently: %s MB).'), $upload_mb), + 'validation' => 'isInt', + 'cast' => 'intval', + 'type' => 'text', + 'suffix' => $this->l('megabytes'), + 'default' => '1' + ), + 'PS_LIMIT_UPLOAD_IMAGE_VALUE' => array( + 'title' => $this->l('Maximum size for a product\'s image'), + 'hint' => sprintf($this->l('Define the upload limit for an image (in megabytes). This value has to be lower or equal to the maximum file upload allotted by your server (currently: %s MB).'), $upload_mb), + 'validation' => 'isInt', + 'cast' => 'intval', + 'type' => 'text', + 'suffix' => $this->l('megabytes'), + 'default' => '1' + ), + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'notifications' => array( + 'title' => $this->l('Notifications'), + 'icon' => 'icon-list-alt', + 'description' => $this->l('Notifications are numbered bubbles displayed at the very top of your back office, right next to the shop\'s name. They display the number of new items since you last clicked on them.'), + 'fields' => array( + 'PS_SHOW_NEW_ORDERS' => array( + 'title' => $this->l('Show notifications for new orders'), + 'hint' => $this->l('This will display notifications when new orders are made in your shop.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_SHOW_NEW_CUSTOMERS' => array( + 'title' => $this->l('Show notifications for new customers'), + 'hint' => $this->l('This will display notifications every time a new customer registers in your shop.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_SHOW_NEW_MESSAGES' => array( + 'title' => $this->l('Show notifications for new messages'), + 'hint' => $this->l('This will display notifications when new messages are posted in your shop.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + ), + 'submit' => array('title' => $this->l('Save')) + ), + ); + } - // Options list - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('General'), - 'icon' => 'icon-cogs', - 'fields' => array( - 'PRESTASTORE_LIVE' => array( - 'title' => $this->l('Automatically check for module updates'), - 'hint' => $this->l('New modules and updates are displayed on the modules page.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'visibility' => Shop::CONTEXT_ALL - ), - 'PS_COOKIE_CHECKIP' => array( - 'title' => $this->l('Check the cookie\'s IP address'), - 'hint' => $this->l('Check the IP address of the cookie in order to prevent your cookie from being stolen.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'default' => '0', - 'visibility' => Shop::CONTEXT_ALL - ), - 'PS_COOKIE_LIFETIME_FO' => array( - 'title' => $this->l('Lifetime of front office cookies'), - 'hint' => $this->l('Set the amount of hours during which the front office cookies are valid. After that amount of time, the customer will have to log in again.'), - 'validation' => 'isInt', - 'cast' => 'intval', - 'type' => 'text', - 'suffix' => $this->l('hours'), - 'default' => '480', - 'visibility' => Shop::CONTEXT_ALL - ), - 'PS_COOKIE_LIFETIME_BO' => array( - 'title' => $this->l('Lifetime of back office cookies'), - 'hint' => $this->l('Set the amount of hours during which the back office cookies are valid. After that amount of time, the PrestaShop user will have to log in again.'), - 'validation' => 'isInt', - 'cast' => 'intval', - 'type' => 'text', - 'suffix' => $this->l('hours'), - 'default' => '480', - 'visibility' => Shop::CONTEXT_ALL - ), - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'upload' => array( - 'title' => $this->l('Upload quota'), - 'icon' => 'icon-cloud-upload', - 'fields' => array( - 'PS_ATTACHMENT_MAXIMUM_SIZE' => array( - 'title' => $this->l('Maximum size for attachment'), - 'hint' => sprintf($this->l('Set the maximum size allowed for attachment files (in megabytes). This value has to be lower or equal to the maximum file upload allotted by your server (currently: %s MB).'), $upload_mb), - 'validation' => 'isInt', - 'cast' => 'intval', - 'type' => 'text', - 'suffix' => $this->l('megabytes'), - 'default' => '2' - ), - 'PS_LIMIT_UPLOAD_FILE_VALUE' => array( - 'title' => $this->l('Maximum size for a downloadable product'), - 'hint' => sprintf($this->l('Define the upload limit for a downloadable product (in megabytes). This value has to be lower or equal to the maximum file upload allotted by your server (currently: %s MB).'), $upload_mb), - 'validation' => 'isInt', - 'cast' => 'intval', - 'type' => 'text', - 'suffix' => $this->l('megabytes'), - 'default' => '1' - ), - 'PS_LIMIT_UPLOAD_IMAGE_VALUE' => array( - 'title' => $this->l('Maximum size for a product\'s image'), - 'hint' => sprintf($this->l('Define the upload limit for an image (in megabytes). This value has to be lower or equal to the maximum file upload allotted by your server (currently: %s MB).'), $upload_mb), - 'validation' => 'isInt', - 'cast' => 'intval', - 'type' => 'text', - 'suffix' => $this->l('megabytes'), - 'default' => '1' - ), - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'notifications' => array( - 'title' => $this->l('Notifications'), - 'icon' => 'icon-list-alt', - 'description' => $this->l('Notifications are numbered bubbles displayed at the very top of your back office, right next to the shop\'s name. They display the number of new items since you last clicked on them.'), - 'fields' => array( - 'PS_SHOW_NEW_ORDERS' => array( - 'title' => $this->l('Show notifications for new orders'), - 'hint' => $this->l('This will display notifications when new orders are made in your shop.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_SHOW_NEW_CUSTOMERS' => array( - 'title' => $this->l('Show notifications for new customers'), - 'hint' => $this->l('This will display notifications every time a new customer registers in your shop.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_SHOW_NEW_MESSAGES' => array( - 'title' => $this->l('Show notifications for new messages'), - 'hint' => $this->l('This will display notifications when new messages are posted in your shop.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - ), - 'submit' => array('title' => $this->l('Save')) - ), - ); - } + public function postProcess() + { + $upload_max_size = (int)str_replace('M', '', ini_get('upload_max_filesize')); + $post_max_size = (int)str_replace('M', '', ini_get('post_max_size')); + $max_size = $upload_max_size < $post_max_size ? $upload_max_size : $post_max_size; - public function postProcess() - { - $upload_max_size = (int)str_replace('M', '', ini_get('upload_max_filesize')); - $post_max_size = (int)str_replace('M', '', ini_get('post_max_size')); - $max_size = $upload_max_size < $post_max_size ? $upload_max_size : $post_max_size; + if (Tools::getValue('PS_LIMIT_UPLOAD_FILE_VALUE') > $max_size || Tools::getValue('PS_LIMIT_UPLOAD_IMAGE_VALUE') > $max_size) { + $this->errors[] = Tools::displayError('The limit chosen is larger than the server\'s maximum upload limit. Please increase the limits of your server.'); + return; + } - if (Tools::getValue('PS_LIMIT_UPLOAD_FILE_VALUE') > $max_size || Tools::getValue('PS_LIMIT_UPLOAD_IMAGE_VALUE') > $max_size) - { - $this->errors[] = Tools::displayError('The limit chosen is larger than the server\'s maximum upload limit. Please increase the limits of your server.'); - return; - } + if (Tools::getIsset('PS_LIMIT_UPLOAD_FILE_VALUE') && !Tools::getValue('PS_LIMIT_UPLOAD_FILE_VALUE')) { + $_POST['PS_LIMIT_UPLOAD_FILE_VALUE'] = 1; + } - if (Tools::getIsset('PS_LIMIT_UPLOAD_FILE_VALUE') && !Tools::getValue('PS_LIMIT_UPLOAD_FILE_VALUE')) - $_POST['PS_LIMIT_UPLOAD_FILE_VALUE'] = 1; + if (Tools::getIsset('PS_LIMIT_UPLOAD_IMAGE_VALUE') && !Tools::getValue('PS_LIMIT_UPLOAD_IMAGE_VALUE')) { + $_POST['PS_LIMIT_UPLOAD_IMAGE_VALUE'] = 1; + } - if (Tools::getIsset('PS_LIMIT_UPLOAD_IMAGE_VALUE') && !Tools::getValue('PS_LIMIT_UPLOAD_IMAGE_VALUE')) - $_POST['PS_LIMIT_UPLOAD_IMAGE_VALUE'] = 1; + parent::postProcess(); + } - parent::postProcess(); - } + /** + * Update PS_ATTACHMENT_MAXIMUM_SIZE + * + * @param $value + */ + public function updateOptionPsAttachementMaximumSize($value) + { + if (!$value) { + return; + } - /** - * Update PS_ATTACHMENT_MAXIMUM_SIZE - * - * @param $value - */ - public function updateOptionPsAttachementMaximumSize($value) - { - if (!$value) - return; - - $upload_max_size = (int)str_replace('M', '', ini_get('upload_max_filesize')); - $post_max_size = (int)str_replace('M', '', ini_get('post_max_size')); - $max_size = $upload_max_size < $post_max_size ? $upload_max_size : $post_max_size; - $value = ($max_size < Tools::getValue('PS_ATTACHMENT_MAXIMUM_SIZE')) ? $max_size : Tools::getValue('PS_ATTACHMENT_MAXIMUM_SIZE'); - Configuration::updateValue('PS_ATTACHMENT_MAXIMUM_SIZE', $value); - } + $upload_max_size = (int)str_replace('M', '', ini_get('upload_max_filesize')); + $post_max_size = (int)str_replace('M', '', ini_get('post_max_size')); + $max_size = $upload_max_size < $post_max_size ? $upload_max_size : $post_max_size; + $value = ($max_size < Tools::getValue('PS_ATTACHMENT_MAXIMUM_SIZE')) ? $max_size : Tools::getValue('PS_ATTACHMENT_MAXIMUM_SIZE'); + Configuration::updateValue('PS_ATTACHMENT_MAXIMUM_SIZE', $value); + } } diff --git a/controllers/admin/AdminAttachmentsController.php b/controllers/admin/AdminAttachmentsController.php index 6acd2ce4..67cf24ef 100644 --- a/controllers/admin/AdminAttachmentsController.php +++ b/controllers/admin/AdminAttachmentsController.php @@ -29,233 +29,228 @@ */ class AdminAttachmentsControllerCore extends AdminController { - public $bootstrap = true ; + public $bootstrap = true ; - protected $product_attachements = array(); + protected $product_attachements = array(); - public function __construct() - { - $this->table = 'attachment'; - $this->className = 'Attachment'; - $this->lang = true; + public function __construct() + { + $this->table = 'attachment'; + $this->className = 'Attachment'; + $this->lang = true; - $this->addRowAction('edit'); - $this->addRowAction('view'); - $this->addRowAction('delete'); + $this->addRowAction('edit'); + $this->addRowAction('view'); + $this->addRowAction('delete'); - $this->_select = 'IFNULL(virtual.products, 0) as products'; - $this->_join = 'LEFT JOIN (SELECT id_attachment, COUNT(*) as products FROM '._DB_PREFIX_.'product_attachment GROUP BY id_attachment) virtual ON a.id_attachment = virtual.id_attachment'; - $this->_use_found_rows = false; + $this->_select = 'IFNULL(virtual.products, 0) as products'; + $this->_join = 'LEFT JOIN (SELECT id_attachment, COUNT(*) as products FROM '._DB_PREFIX_.'product_attachment GROUP BY id_attachment) virtual ON a.id_attachment = virtual.id_attachment'; + $this->_use_found_rows = false; - $this->fields_list = array( - 'id_attachment' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Name') - ), - 'file' => array( - 'title' => $this->l('File') - ), - 'file_size' => array( - 'title' => $this->l('Size'), - 'callback' => 'displayHumanReadableSize' - ), - 'products' => array( - 'title' => $this->l('Associated with'), - 'suffix' => $this->l('product(s)'), - 'filter_key' => 'virtual!products', - ), - ); + $this->fields_list = array( + 'id_attachment' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Name') + ), + 'file' => array( + 'title' => $this->l('File') + ), + 'file_size' => array( + 'title' => $this->l('Size'), + 'callback' => 'displayHumanReadableSize' + ), + 'products' => array( + 'title' => $this->l('Associated with'), + 'suffix' => $this->l('product(s)'), + 'filter_key' => 'virtual!products', + ), + ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'icon' => 'icon-trash', - 'confirm' => $this->l('Delete selected items?') - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'icon' => 'icon-trash', + 'confirm' => $this->l('Delete selected items?') + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function setMedia() - { - parent::setMedia(); + public function setMedia() + { + parent::setMedia(); - $this->addJs(_PS_JS_DIR_.'/admin/attachments.js'); - Media::addJsDefL('confirm_text', $this->l('This attachment is associated with the following products, do you really want to delete it?')); - } + $this->addJs(_PS_JS_DIR_.'/admin/attachments.js'); + Media::addJsDefL('confirm_text', $this->l('This attachment is associated with the following products, do you really want to delete it?', null, true, false)); + } - public static function displayHumanReadableSize($size) - { - return Tools::formatBytes($size); - } + public static function displayHumanReadableSize($size) + { + return Tools::formatBytes($size); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_attachment'] = array( - 'href' => self::$currentIndex.'&addattachment&token='.$this->token, - 'desc' => $this->l('Add new attachment', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_attachment'] = array( + 'href' => self::$currentIndex.'&addattachment&token='.$this->token, + 'desc' => $this->l('Add new attachment', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderView() - { - if (($obj = $this->loadObject(true)) && Validate::isLoadedObject($obj)) - { - $link = $this->context->link->getPageLink('attachment', true, NULL, 'id_attachment='.$obj->id); - Tools::redirectLink($link); - } - return $this->displayWarning($this->l('File not found')); - } + public function renderView() + { + if (($obj = $this->loadObject(true)) && Validate::isLoadedObject($obj)) { + $link = $this->context->link->getPageLink('attachment', true, null, 'id_attachment='.$obj->id); + Tools::redirectLink($link); + } + return $this->displayWarning($this->l('File not found')); + } - public function renderForm() - { - if (($obj = $this->loadObject(true)) && Validate::isLoadedObject($obj)) - { - /** @var Attachment $obj */ - $link = $this->context->link->getPageLink('attachment', true, NULL, 'id_attachment='.$obj->id); + public function renderForm() + { + if (($obj = $this->loadObject(true)) && Validate::isLoadedObject($obj)) { + /** @var Attachment $obj */ + $link = $this->context->link->getPageLink('attachment', true, null, 'id_attachment='.$obj->id); - if (file_exists(_PS_DOWNLOAD_DIR_.$obj->file)) - $size = round(filesize(_PS_DOWNLOAD_DIR_.$obj->file) / 1024); - } + if (file_exists(_PS_DOWNLOAD_DIR_.$obj->file)) { + $size = round(filesize(_PS_DOWNLOAD_DIR_.$obj->file) / 1024); + } + } - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Attachment'), - 'icon' => 'icon-paper-clip' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Filename'), - 'name' => 'name', - 'required' => true, - 'lang' => true, - 'col' => 4 - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Description'), - 'name' => 'description', - 'lang' => true, - 'col' => 6 - ), - array( - 'type' => 'file', - 'file' => isset($link) ? $link : null, - 'size' => isset($size) ? $size : null, - 'label' => $this->l('File'), - 'name' => 'file', - 'col' => 6 - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Attachment'), + 'icon' => 'icon-paper-clip' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Filename'), + 'name' => 'name', + 'required' => true, + 'lang' => true, + 'col' => 4 + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Description'), + 'name' => 'description', + 'lang' => true, + 'col' => 6 + ), + array( + 'type' => 'file', + 'file' => isset($link) ? $link : null, + 'size' => isset($size) ? $size : null, + 'label' => $this->l('File'), + 'name' => 'file', + 'required' => true, + 'col' => 6 + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList((int)$id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList((int)$id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - if (count($this->_list)) - { - $this->product_attachements = Attachment::getProductAttached((int)$id_lang, $this->_list); + if (count($this->_list)) { + $this->product_attachements = Attachment::getProductAttached((int)$id_lang, $this->_list); - $list_product_list = array(); - foreach ($this->_list as $list) - { - $product_list = ''; + $list_product_list = array(); + foreach ($this->_list as $list) { + $product_list = ''; - if (isset($this->product_attachements[$list['id_attachment']])) - { - foreach ($this->product_attachements[$list['id_attachment']] as $product) - $product_list .= $product.', '; + if (isset($this->product_attachements[$list['id_attachment']])) { + foreach ($this->product_attachements[$list['id_attachment']] as $product) { + $product_list .= $product.', '; + } - $product_list = rtrim($product_list, ', '); - } + $product_list = rtrim($product_list, ', '); + } - $list_product_list[$list['id_attachment']] = $product_list; - } + $list_product_list[$list['id_attachment']] = $product_list; + } - // Assign array in list_action_delete.tpl - $this->tpl_delete_link_vars = array( - 'product_list' => $list_product_list, - 'product_attachements' => $this->product_attachements - ); - } - } + // Assign array in list_action_delete.tpl + $this->tpl_delete_link_vars = array( + 'product_list' => $list_product_list, + 'product_attachements' => $this->product_attachements + ); + } + } - public function postProcess() - { - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } + public function postProcess() + { + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } - if (Tools::isSubmit('submitAdd'.$this->table)) - { - $id = (int)Tools::getValue('id_attachment'); - if ($id && $a = new Attachment($id)) - { - $_POST['file'] = $a->file; - $_POST['mime'] = $a->mime; - } - if (!count($this->errors)) - { - if (isset($_FILES['file']) && is_uploaded_file($_FILES['file']['tmp_name'])) - { - if ($_FILES['file']['size'] > (Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024 * 1024)) - $this->errors[] = sprintf( - $this->l('The file is too large. Maximum size allowed is: %1$d kB. The file you are trying to upload is %2$d kB.'), - (Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024), - number_format(($_FILES['file']['size'] / 1024), 2, '.', '') - ); - else - { - do $uniqid = sha1(microtime()); - while (file_exists(_PS_DOWNLOAD_DIR_.$uniqid)); - if (!move_uploaded_file($_FILES['file']['tmp_name'], _PS_DOWNLOAD_DIR_.$uniqid)) - $this->errors[] = $this->l('Failed to copy the file.'); - $_POST['file_name'] = $_FILES['file']['name']; - @unlink($_FILES['file']['tmp_name']); - if (!sizeof($this->errors) && isset($a) && file_exists(_PS_DOWNLOAD_DIR_.$a->file)) - unlink(_PS_DOWNLOAD_DIR_.$a->file); - $_POST['file'] = $uniqid; - $_POST['mime'] = $_FILES['file']['type']; - } - } - elseif (array_key_exists('file', $_FILES) && (int)$_FILES['file']['error'] === 1) - { - $max_upload = (int)ini_get('upload_max_filesize'); - $max_post = (int)ini_get('post_max_size'); - $upload_mb = min($max_upload, $max_post); - $this->errors[] = sprintf( - $this->l('The file %1$s exceeds the size allowed by the server. The limit is set to %2$d MB.'), - '<b>'.$_FILES['file']['name'].'</b> ', - '<b>'.$upload_mb.'</b>' - ); - } - elseif (!isset($a) || (isset($a) && !file_exists(_PS_DOWNLOAD_DIR_.$a->file))) - $this->errors[] = $this->l('Upload error. Please check your server configurations for the maximum upload size allowed.'); - } - $this->validateRules(); - } - $return = parent::postProcess(); - if (!$return && isset($uniqid) && file_exists(_PS_DOWNLOAD_DIR_.$uniqid)) - unlink(_PS_DOWNLOAD_DIR_.$uniqid); - return $return; - } + if (Tools::isSubmit('submitAdd'.$this->table)) { + $id = (int)Tools::getValue('id_attachment'); + if ($id && $a = new Attachment($id)) { + $_POST['file'] = $a->file; + $_POST['mime'] = $a->mime; + } + if (!count($this->errors)) { + if (isset($_FILES['file']) && is_uploaded_file($_FILES['file']['tmp_name'])) { + if ($_FILES['file']['size'] > (Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024 * 1024)) { + $this->errors[] = sprintf( + $this->l('The file is too large. Maximum size allowed is: %1$d kB. The file you are trying to upload is %2$d kB.'), + (Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024), + number_format(($_FILES['file']['size'] / 1024), 2, '.', '') + ); + } else { + do { + $uniqid = sha1(microtime()); + } while (file_exists(_PS_DOWNLOAD_DIR_.$uniqid)); + if (!move_uploaded_file($_FILES['file']['tmp_name'], _PS_DOWNLOAD_DIR_.$uniqid)) { + $this->errors[] = $this->l('Failed to copy the file.'); + } + $_POST['file_name'] = $_FILES['file']['name']; + @unlink($_FILES['file']['tmp_name']); + if (!sizeof($this->errors) && isset($a) && file_exists(_PS_DOWNLOAD_DIR_.$a->file)) { + unlink(_PS_DOWNLOAD_DIR_.$a->file); + } + $_POST['file'] = $uniqid; + $_POST['mime'] = $_FILES['file']['type']; + } + } elseif (array_key_exists('file', $_FILES) && (int)$_FILES['file']['error'] === 1) { + $max_upload = (int)ini_get('upload_max_filesize'); + $max_post = (int)ini_get('post_max_size'); + $upload_mb = min($max_upload, $max_post); + $this->errors[] = sprintf( + $this->l('The file %1$s exceeds the size allowed by the server. The limit is set to %2$d MB.'), + '<b>'.$_FILES['file']['name'].'</b> ', + '<b>'.$upload_mb.'</b>' + ); + } elseif (!isset($a) || (isset($a) && !file_exists(_PS_DOWNLOAD_DIR_.$a->file))) { + $this->errors[] = $this->l('Upload error. Please check your server configurations for the maximum upload size allowed.'); + } + } + $this->validateRules(); + } + $return = parent::postProcess(); + if (!$return && isset($uniqid) && file_exists(_PS_DOWNLOAD_DIR_.$uniqid)) { + unlink(_PS_DOWNLOAD_DIR_.$uniqid); + } + return $return; + } } diff --git a/controllers/admin/AdminAttributeGeneratorController.php b/controllers/admin/AdminAttributeGeneratorController.php index 9f7ab526..5fde78e9 100644 --- a/controllers/admin/AdminAttributeGeneratorController.php +++ b/controllers/admin/AdminAttributeGeneratorController.php @@ -31,240 +31,238 @@ */ class AdminAttributeGeneratorControllerCore extends AdminController { - protected $combinations = array(); + protected $combinations = array(); - /** @var Product */ - protected $product; + /** @var Product */ + protected $product; - public function __construct() - { - $this->bootstrap = true; - $this->table = 'product_attribute'; - $this->className = 'Product'; - $this->multishop_context_group = false; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'product_attribute'; + $this->className = 'Product'; + $this->multishop_context_group = false; - parent::__construct(); - } + parent::__construct(); + } - public function setMedia() - { - parent::setMedia(); - $this->addJS(_PS_JS_DIR_.'admin/attributes.js'); - } + public function setMedia() + { + parent::setMedia(); + $this->addJS(_PS_JS_DIR_.'admin/attributes.js'); + } - protected function addAttribute($attributes, $price = 0, $weight = 0) - { - foreach ($attributes as $attribute) - { - $price += (float)preg_replace('/[^0-9.-]/', '', str_replace(',', '.', Tools::getValue('price_impact_'.(int)$attribute))); - $weight += (float)preg_replace('/[^0-9.]/', '', str_replace(',', '.', Tools::getValue('weight_impact_'.(int)$attribute))); - } - if ($this->product->id) - { - return array( - 'id_product' => (int)$this->product->id, - 'price' => (float)$price, - 'weight' => (float)$weight, - 'ecotax' => 0, - 'quantity' => (int)Tools::getValue('quantity'), - 'reference' => pSQL($_POST['reference']), - 'default_on' => 0, - 'available_date' => '0000-00-00' - ); - } - return array(); - } + protected function addAttribute($attributes, $price = 0, $weight = 0) + { + foreach ($attributes as $attribute) { + $price += (float)preg_replace('/[^0-9.-]/', '', str_replace(',', '.', Tools::getValue('price_impact_'.(int)$attribute))); + $weight += (float)preg_replace('/[^0-9.]/', '', str_replace(',', '.', Tools::getValue('weight_impact_'.(int)$attribute))); + } + if ($this->product->id) { + return array( + 'id_product' => (int)$this->product->id, + 'price' => (float)$price, + 'weight' => (float)$weight, + 'ecotax' => 0, + 'quantity' => (int)Tools::getValue('quantity'), + 'reference' => pSQL($_POST['reference']), + 'default_on' => 0, + 'available_date' => '0000-00-00' + ); + } + return array(); + } - protected static function createCombinations($list) - { - if (count($list) <= 1) - return count($list) ? array_map(create_function('$v', 'return (array($v));'), $list[0]) : $list; - $res = array(); - $first = array_pop($list); - foreach ($first as $attribute) - { - $tab = AdminAttributeGeneratorController::createCombinations($list); - foreach ($tab as $to_add) - $res[] = is_array($to_add) ? array_merge($to_add, array($attribute)) : array($to_add, $attribute); - } - return $res; - } + protected static function createCombinations($list) + { + if (count($list) <= 1) { + return count($list) ? array_map(create_function('$v', 'return (array($v));'), $list[0]) : $list; + } + $res = array(); + $first = array_pop($list); + foreach ($first as $attribute) { + $tab = AdminAttributeGeneratorController::createCombinations($list); + foreach ($tab as $to_add) { + $res[] = is_array($to_add) ? array_merge($to_add, array($attribute)) : array($to_add, $attribute); + } + } + return $res; + } - public function initProcess() - { - if (!defined('PS_MASS_PRODUCT_CREATION')) - define('PS_MASS_PRODUCT_CREATION', true); + public function initProcess() + { + if (!defined('PS_MASS_PRODUCT_CREATION')) { + define('PS_MASS_PRODUCT_CREATION', true); + } - if (Tools::isSubmit('generate')) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'generate'; - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - parent::initProcess(); - } + if (Tools::isSubmit('generate')) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'generate'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } + parent::initProcess(); + } - public function postProcess() - { - $this->product = new Product((int)Tools::getValue('id_product')); - $this->product->loadStockData(); - parent::postProcess(); - } + public function postProcess() + { + $this->product = new Product((int)Tools::getValue('id_product')); + $this->product->loadStockData(); + parent::postProcess(); + } - public function processGenerate() - { - if (!is_array(Tools::getValue('options'))) - $this->errors[] = Tools::displayError('Please select at least one attribute.'); - else - { - $tab = array_values(Tools::getValue('options')); - if (count($tab) && Validate::isLoadedObject($this->product)) - { - AdminAttributeGeneratorController::setAttributesImpacts($this->product->id, $tab); - $this->combinations = array_values(AdminAttributeGeneratorController::createCombinations($tab)); - $values = array_values(array_map(array($this, 'addAttribute'), $this->combinations)); + public function processGenerate() + { + if (!is_array(Tools::getValue('options'))) { + $this->errors[] = Tools::displayError('Please select at least one attribute.'); + } else { + $tab = array_values(Tools::getValue('options')); + if (count($tab) && Validate::isLoadedObject($this->product)) { + AdminAttributeGeneratorController::setAttributesImpacts($this->product->id, $tab); + $this->combinations = array_values(AdminAttributeGeneratorController::createCombinations($tab)); + $values = array_values(array_map(array($this, 'addAttribute'), $this->combinations)); - // @since 1.5.0 - if ($this->product->depends_on_stock == 0) - { - $attributes = Product::getProductAttributesIds($this->product->id, true); - foreach ($attributes as $attribute) - StockAvailable::removeProductFromStockAvailable($this->product->id, $attribute['id_product_attribute'], Context::getContext()->shop); - } + // @since 1.5.0 + if ($this->product->depends_on_stock == 0) { + $attributes = Product::getProductAttributesIds($this->product->id, true); + foreach ($attributes as $attribute) { + StockAvailable::removeProductFromStockAvailable($this->product->id, $attribute['id_product_attribute'], Context::getContext()->shop); + } + } - SpecificPriceRule::disableAnyApplication(); + SpecificPriceRule::disableAnyApplication(); - $this->product->deleteProductAttributes(); - $this->product->generateMultipleCombinations($values, $this->combinations); + $this->product->deleteProductAttributes(); + $this->product->generateMultipleCombinations($values, $this->combinations); - // Reset cached default attribute for the product and get a new one - Product::getDefaultAttribute($this->product->id, 0, true); - Product::updateDefaultAttribute($this->product->id); + // Reset cached default attribute for the product and get a new one + Product::getDefaultAttribute($this->product->id, 0, true); + Product::updateDefaultAttribute($this->product->id); - // @since 1.5.0 - if ($this->product->depends_on_stock == 0) - { - $attributes = Product::getProductAttributesIds($this->product->id, true); - $quantity = (int)Tools::getValue('quantity'); - foreach ($attributes as $attribute) - if (Shop::getContext() == Shop::CONTEXT_ALL) - { - $shops_list = Shop::getShops(); - if (is_array($shops_list)) - foreach ($shops_list as $current_shop) - if (isset($current_shop['id_shop']) && (int)$current_shop['id_shop'] > 0) - StockAvailable::setQuantity($this->product->id, (int)$attribute['id_product_attribute'], $quantity, (int)$current_shop['id_shop']); - } - else - StockAvailable::setQuantity($this->product->id, (int)$attribute['id_product_attribute'], $quantity); - } - else - StockAvailable::synchronize($this->product->id); + // @since 1.5.0 + if ($this->product->depends_on_stock == 0) { + $attributes = Product::getProductAttributesIds($this->product->id, true); + $quantity = (int)Tools::getValue('quantity'); + foreach ($attributes as $attribute) { + if (Shop::getContext() == Shop::CONTEXT_ALL) { + $shops_list = Shop::getShops(); + if (is_array($shops_list)) { + foreach ($shops_list as $current_shop) { + if (isset($current_shop['id_shop']) && (int)$current_shop['id_shop'] > 0) { + StockAvailable::setQuantity($this->product->id, (int)$attribute['id_product_attribute'], $quantity, (int)$current_shop['id_shop']); + } + } + } + } else { + StockAvailable::setQuantity($this->product->id, (int)$attribute['id_product_attribute'], $quantity); + } + } + } else { + StockAvailable::synchronize($this->product->id); + } - SpecificPriceRule::enableAnyApplication(); - SpecificPriceRule::applyAllRules(array((int)$this->product->id)); + SpecificPriceRule::enableAnyApplication(); + SpecificPriceRule::applyAllRules(array((int)$this->product->id)); - Tools::redirectAdmin($this->context->link->getAdminLink('AdminProducts').'&id_product='.(int)Tools::getValue('id_product').'&updateproduct&key_tab=Combinations&conf=4'); - } - else - $this->errors[] = Tools::displayError('Unable to initialize these parameters. A combination is missing or an object cannot be loaded.'); - } - } + Tools::redirectAdmin($this->context->link->getAdminLink('AdminProducts').'&id_product='.(int)Tools::getValue('id_product').'&updateproduct&key_tab=Combinations&conf=4'); + } else { + $this->errors[] = Tools::displayError('Unable to initialize these parameters. A combination is missing or an object cannot be loaded.'); + } + } + } protected static function setAttributesImpacts($id_product, $tab) { $attributes = array(); - foreach ($tab as $group) - foreach ($group as $attribute) - { - $price = preg_replace('/[^0-9.]/', '', str_replace(',', '.', Tools::getValue('price_impact_'.(int)$attribute))); - $weight = preg_replace('/[^0-9.]/', '', str_replace(',', '.', Tools::getValue('weight_impact_'.(int)$attribute))); - $attributes[] = '('.(int)$id_product.', '.(int)$attribute.', '.(float)$price.', '.(float)$weight.')'; - } + foreach ($tab as $group) { + foreach ($group as $attribute) { + $price = preg_replace('/[^0-9.]/', '', str_replace(',', '.', Tools::getValue('price_impact_'.(int)$attribute))); + $weight = preg_replace('/[^0-9.]/', '', str_replace(',', '.', Tools::getValue('weight_impact_'.(int)$attribute))); + $attributes[] = '('.(int)$id_product.', '.(int)$attribute.', '.(float)$price.', '.(float)$weight.')'; + } + } - return Db::getInstance()->execute(' + return Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'attribute_impact` (`id_product`, `id_attribute`, `price`, `weight`) VALUES '.implode(',', $attributes).' ON DUPLICATE KEY UPDATE `price` = VALUES(price), `weight` = VALUES(weight)'); } - public function initGroupTable() - { - $combinations_groups = $this->product->getAttributesGroups($this->context->language->id); - $attributes = array(); - $impacts = Product::getAttributesImpacts($this->product->id); - foreach ($combinations_groups as &$combination) - { - $target = &$attributes[$combination['id_attribute_group']][$combination['id_attribute']]; - $target = $combination; - if (isset($impacts[$combination['id_attribute']])) - { - $target['price'] = $impacts[$combination['id_attribute']]['price']; - $target['weight'] = $impacts[$combination['id_attribute']]['weight']; - } - } + public function initGroupTable() + { + $combinations_groups = $this->product->getAttributesGroups($this->context->language->id); + $attributes = array(); + $impacts = Product::getAttributesImpacts($this->product->id); + foreach ($combinations_groups as &$combination) { + $target = &$attributes[$combination['id_attribute_group']][$combination['id_attribute']]; + $target = $combination; + if (isset($impacts[$combination['id_attribute']])) { + $target['price'] = $impacts[$combination['id_attribute']]['price']; + $target['weight'] = $impacts[$combination['id_attribute']]['weight']; + } + } $this->context->smarty->assign(array( - 'currency_sign' => $this->context->currency->sign, - 'weight_unit' => Configuration::get('PS_WEIGHT_UNIT'), - 'attributes' => $attributes, - )); - } + 'currency_sign' => $this->context->currency->sign, + 'weight_unit' => Configuration::get('PS_WEIGHT_UNIT'), + 'attributes' => $attributes, + )); + } - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); - $this->page_header_toolbar_title = $this->l('Attributes generator', null, null, false); - $this->page_header_toolbar_btn['back'] = array( - 'href' => $this->context->link->getAdminLink('AdminProducts').'&id_product='.(int)Tools::getValue('id_product').'&updateproduct&key_tab=Combinations', - 'desc' => $this->l('Back to the product', null, null, false) - ); - } + $this->page_header_toolbar_title = $this->l('Attributes generator', null, null, false); + $this->page_header_toolbar_btn['back'] = array( + 'href' => $this->context->link->getAdminLink('AdminProducts').'&id_product='.(int)Tools::getValue('id_product').'&updateproduct&key_tab=Combinations', + 'desc' => $this->l('Back to the product', null, null, false) + ); + } - public function initBreadcrumbs($tab_id = null, $tabs = null) - { - $this->display = 'generator'; - return parent::initBreadcrumbs(); - } + public function initBreadcrumbs($tab_id = null, $tabs = null) + { + $this->display = 'generator'; + return parent::initBreadcrumbs(); + } - public function initContent() - { - if (!Combination::isFeatureActive()) - { - $url = '<a href="index.php?tab=AdminPerformance&token='.Tools::getAdminTokenLite('AdminPerformance').'#featuresDetachables">'. - $this->l('Performance').'</a>'; - $this->displayWarning(sprintf($this->l('This feature has been disabled. You can activate it here: %s.'), $url)); - return; - } + public function initContent() + { + if (!Combination::isFeatureActive()) { + $url = '<a href="index.php?tab=AdminPerformance&token='.Tools::getAdminTokenLite('AdminPerformance').'#featuresDetachables">'. + $this->l('Performance').'</a>'; + $this->displayWarning(sprintf($this->l('This feature has been disabled. You can activate it here: %s.'), $url)); + return; + } - // Init toolbar - $this->initPageHeaderToolbar(); - $this->initGroupTable(); + // Init toolbar + $this->initPageHeaderToolbar(); + $this->initGroupTable(); - $attributes = Attribute::getAttributes(Context::getContext()->language->id, true); - $attribute_js = array(); + $attributes = Attribute::getAttributes(Context::getContext()->language->id, true); + $attribute_js = array(); - foreach ($attributes as $k => $attribute) - $attribute_js[$attribute['id_attribute_group']][$attribute['id_attribute']] = $attribute['name']; + foreach ($attributes as $k => $attribute) { + $attribute_js[$attribute['id_attribute_group']][$attribute['id_attribute']] = $attribute['name']; + } - $attribute_groups = AttributeGroup::getAttributesGroups($this->context->language->id); - $this->product = new Product((int)Tools::getValue('id_product')); + $attribute_groups = AttributeGroup::getAttributesGroups($this->context->language->id); + $this->product = new Product((int)Tools::getValue('id_product')); - $this->context->smarty->assign(array( - 'tax_rates' => $this->product->getTaxesRate(), - 'generate' => isset($_POST['generate']) && !count($this->errors), - 'combinations_size' => count($this->combinations), - 'product_name' => $this->product->name[$this->context->language->id], - 'product_reference' => $this->product->reference, - 'url_generator' => self::$currentIndex.'&id_product='.(int)Tools::getValue('id_product').'&attributegenerator&token='.Tools::getValue('token'), - 'attribute_groups' => $attribute_groups, - 'attribute_js' => $attribute_js, - 'toolbar_btn' => $this->toolbar_btn, - 'toolbar_scroll' => true, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } + $this->context->smarty->assign(array( + 'tax_rates' => $this->product->getTaxesRate(), + 'generate' => isset($_POST['generate']) && !count($this->errors), + 'combinations_size' => count($this->combinations), + 'product_name' => $this->product->name[$this->context->language->id], + 'product_reference' => $this->product->reference, + 'url_generator' => self::$currentIndex.'&id_product='.(int)Tools::getValue('id_product').'&attributegenerator&token='.Tools::getValue('token'), + 'attribute_groups' => $attribute_groups, + 'attribute_js' => $attribute_js, + 'toolbar_btn' => $this->toolbar_btn, + 'toolbar_scroll' => true, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } } diff --git a/controllers/admin/AdminAttributesGroupsController.php b/controllers/admin/AdminAttributesGroupsController.php index c42fad3d..01d487c3 100644 --- a/controllers/admin/AdminAttributesGroupsController.php +++ b/controllers/admin/AdminAttributesGroupsController.php @@ -29,915 +29,913 @@ */ class AdminAttributesGroupsControllerCore extends AdminController { - public $bootstrap = true; - protected $id_attribute; - protected $position_identifier = 'id_attribute_group'; - protected $attribute_name; - - public function __construct() - { - $this->bootstrap = true; - $this->context = Context::getContext(); - $this->table = 'attribute_group'; - $this->list_id = 'attribute_group'; - $this->identifier = 'id_attribute_group'; - $this->className = 'AttributeGroup'; - $this->lang = true; - $this->_defaultOrderBy = 'position'; - - $this->fields_list = array( - 'id_attribute_group' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Name'), - 'filter_key' => 'b!name', - 'align' => 'left' - ), - 'count_values' => array( - 'title' => $this->l('Values count'), - 'align' => 'center', - 'class' => 'fixed-width-xs', - 'orderby' => false, - 'search' => false - ), - 'position' => array( - 'title' => $this->l('Position'), - 'filter_key' => 'a!position', - 'position' => 'position', - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - ); - - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'icon' => 'icon-trash', - 'confirm' => $this->l('Delete selected items?') - ) - ); - $this->fieldImageSettings = array('name' => 'texture', 'dir' => 'co'); - - parent::__construct(); - } - - /** - * AdminController::renderList() override - * @see AdminController::renderList() - */ - public function renderList() - { - $this->addRowAction('view'); - $this->addRowAction('edit'); - $this->addRowAction('delete'); - - - return parent::renderList(); - } - - public function renderView() - { - if (($id = Tools::getValue('id_attribute_group'))) - { - $this->table = 'attribute'; - $this->className = 'Attribute'; - $this->identifier = 'id_attribute'; - $this->position_identifier = 'id_attribute'; - $this->position_group_identifier = 'id_attribute_group'; - $this->list_id = 'attribute_values'; - $this->lang = true; - - $this->context->smarty->assign(array( - 'current' => self::$currentIndex.'&id_attribute_group='.(int)$id.'&viewattribute_group' - )); - - if (!Validate::isLoadedObject($obj = new AttributeGroup((int)$id))) - { - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - return; - } - - $this->attribute_name = $obj->name; - $this->fields_list = array( - 'id_attribute' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Value'), - 'width' => 'auto', - 'filter_key' => 'b!name' - ) - ); - - if ($obj->group_type == 'color') - $this->fields_list['color'] = array( - 'title' => $this->l('Color'), - 'filter_key' => 'a!color', - ); - - $this->fields_list['position'] = array( - 'title' => $this->l('Position'), - 'filter_key' => 'a!position', - 'position' => 'position', - 'class' => 'fixed-width-md' - ); - - $this->addRowAction('edit'); - $this->addRowAction('delete'); - - $this->_where = 'AND a.`id_attribute_group` = '.(int)$id; - $this->_orderBy = 'position'; - - self::$currentIndex = self::$currentIndex.'&id_attribute_group='.(int)$id.'&viewattribute_group'; - $this->processFilter(); - return parent::renderList(); - } - } - - /** - * AdminController::renderForm() override - * @see AdminController::renderForm() - */ - public function renderForm() - { - $this->table = 'attribute_group'; - $this->identifier = 'id_attribute_group'; - - $group_type = array( - array( - 'id' => 'select', - 'name' => $this->l('Drop-down list') - ), - array( - 'id' => 'radio', - 'name' => $this->l('Radio buttons') - ), - array( - 'id' => 'color', - 'name' => $this->l('Color or texture') - ), - ); - - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Attributes'), - 'icon' => 'icon-info-sign' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'lang' => true, - 'required' => true, - 'col' => '4', - 'hint' => $this->l('Your internal name for this attribute.').' '.$this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'text', - 'label' => $this->l('Public name'), - 'name' => 'public_name', - 'lang' => true, - 'required' => true, - 'col' => '4', - 'hint' => $this->l('The public name for this attribute, displayed to the customers.').' '.$this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'select', - 'label' => $this->l('Attribute type'), - 'name' => 'group_type', - 'required' => true, - 'options' => array( - 'query' => $group_type, - 'id' => 'id', - 'name' => 'name' - ), - 'col' => '2', - 'hint' => $this->l('The way the attribute\'s values will be presented to the customers in the product\'s page.') - ) - ) - ); - - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } - - $this->fields_form['submit'] = array( - 'title' => $this->l('Save'), - ); - - if (!($obj = $this->loadObject(true))) - return; - - return parent::renderForm(); - } - - public function renderFormAttributes() - { - $attributes_groups = AttributeGroup::getAttributesGroups($this->context->language->id); - - $this->table = 'attribute'; - $this->identifier = 'id_attribute'; - - $this->show_form_cancel_button = true; - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Values'), - 'icon' => 'icon-info-sign' - ), - 'input' => array( - array( - 'type' => 'select', - 'label' => $this->l('Attribute group'), - 'name' => 'id_attribute_group', - 'required' => true, - 'options' => array( - 'query' => $attributes_groups, - 'id' => 'id_attribute_group', - 'name' => 'name' - ), - 'hint' => $this->l('Choose the attribute group for this value.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Value'), - 'name' => 'name', - 'lang' => true, - 'required' => true, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ) - ) - ); - - if (Shop::isFeatureActive()) - { - // We get all associated shops for all attribute groups, because we will disable group shops - // for attributes that the selected attribute group don't support - $sql = 'SELECT id_attribute_group, id_shop FROM '._DB_PREFIX_.'attribute_group_shop'; - $associations = array(); - foreach (Db::getInstance()->executeS($sql) as $row) - $associations[$row['id_attribute_group']][] = $row['id_shop']; - - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - 'values' => Shop::getTree() - ); - } - else - $associations = array(); - - $this->fields_form['shop_associations'] = Tools::jsonEncode($associations); - - $this->fields_form['input'][] = array( - 'type' => 'color', - 'label' => $this->l('Color'), - 'name' => 'color', - 'hint' => $this->l('Choose a color with the color picker, or enter an HTML color (e.g. "lightblue", "#CC6600").') - ); - - $this->fields_form['input'][] = array( - 'type' => 'file', - 'label' => $this->l('Texture'), - 'name' => 'texture', - 'hint' => array( - $this->l('Upload an image file containing the color texture from your computer.'), - $this->l('This will override the HTML color!') - ) - ); - - $this->fields_form['input'][] = array( - 'type' => 'current_texture', - 'label' => $this->l('Current texture'), - 'name' => 'current_texture' - ); - - $this->fields_form['input'][] = array( - 'type' => 'closediv', - 'name' => '' - ); - - $this->fields_form['submit'] = array( - 'title' => $this->l('Save'), - ); - - $this->fields_form['buttons'] = array( - 'save-and-stay' => array( - 'title' => $this->l('Save then add another value'), - 'name' => 'submitAdd'.$this->table.'AndStay', - 'type' => 'submit', - 'class' => 'btn btn-default pull-right', - 'icon' => 'process-icon-save' - ) - ); - - $this->fields_value['id_attribute_group'] = (int)Tools::getValue('id_attribute_group'); - - // Override var of Controller - $this->table = 'attribute'; - $this->className = 'Attribute'; - $this->identifier = 'id_attribute'; - $this->lang = true; - $this->tpl_folder = 'attributes/'; - - // Create object Attribute - if (!$obj = new Attribute((int)Tools::getValue($this->identifier))) - return; - - $str_attributes_groups = ''; - foreach ($attributes_groups as $attribute_group) - $str_attributes_groups .= '"'.$attribute_group['id_attribute_group'].'" : '.($attribute_group['group_type'] == 'color' ? '1' : '0' ).', '; - - $image = '../img/'.$this->fieldImageSettings['dir'].'/'.(int)$obj->id.'.jpg'; - - $this->tpl_form_vars = array( - 'strAttributesGroups' => $str_attributes_groups, - 'colorAttributeProperties' => Validate::isLoadedObject($obj) && $obj->isColorAttribute(), - 'imageTextureExists' => file_exists(_PS_IMG_DIR_.$this->fieldImageSettings['dir'].'/'.(int)$obj->id.'.jpg'), - 'imageTexture' => $image, - 'imageTextureUrl' => Tools::safeOutput($_SERVER['REQUEST_URI']).'&deleteImage=1' - ); - - return parent::renderForm(); - } - - /** - * AdminController::init() override - * @see AdminController::init() - */ - public function init() - { - if (Tools::isSubmit('updateattribute')) - $this->display = 'editAttributes'; - elseif (Tools::isSubmit('submitAddattribute')) - $this->display = 'editAttributes'; - elseif (Tools::isSubmit('submitAddattribute_group')) - $this->display = 'add'; - - parent::init(); - } - - /** - * Override processAdd to change SaveAndStay button action - * @see classes/AdminControllerCore::processUpdate() - */ - public function processAdd() - { - if ($this->table == 'attribute') - { - /** @var AttributeGroup $object */ - $object = new $this->className(); - foreach (Language::getLanguages(false) as $language) - if ($object->isAttribute((int)Tools::getValue('id_attribute_group'), - Tools::getValue('name_'.$language['id_lang']), $language['id_lang'])) - $this->errors['name_'.$language['id_lang']] = - sprintf(Tools::displayError('The attribute value "%1$s" already exist for %2$s language'), - Tools::getValue('name_'.$language['id_lang']), $language['name']); - - if (!empty($this->errors)) - return $object; - } - - $object = parent::processAdd(); - - if (Tools::isSubmit('submitAdd'.$this->table.'AndStay') && !count($this->errors)) - { - if ($this->display == 'add') - $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'=&conf=3&update'.$this->table.'&token='.$this->token; - else - $this->redirect_after = self::$currentIndex.'&id_attribute_group='.(int)Tools::getValue('id_attribute_group').'&conf=3&update'.$this->table.'&token='.$this->token; - } - - if (count($this->errors)) - $this->setTypeAttribute(); - - return $object; - } - - /** - * Override processUpdate to change SaveAndStay button action - * @see classes/AdminControllerCore::processUpdate() - */ - public function processUpdate() - { - $object = parent::processUpdate(); - - if (Tools::isSubmit('submitAdd'.$this->table.'AndStay') && !count($this->errors)) - { - if ($this->display == 'add') - $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'=&conf=3&update'.$this->table.'&token='.$this->token; - else - $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'=&id_attribute_group='.(int)Tools::getValue('id_attribute_group').'&conf=3&update'.$this->table.'&token='.$this->token; - } - - if (count($this->errors)) - $this->setTypeAttribute(); - - if (Tools::isSubmit('updateattribute') || Tools::isSubmit('deleteattribute') || Tools::isSubmit('submitAddattribute') || Tools::isSubmit('submitBulkdeleteattribute')) - Tools::clearColorListCache(); - - return $object; - } - - /** - * AdminController::initContent() override - * @see AdminController::initContent() - */ - public function initContent() - { - if (!Combination::isFeatureActive()) - { - $url = '<a href="index.php?tab=AdminPerformance&token='.Tools::getAdminTokenLite('AdminPerformance').'#featuresDetachables">'. - $this->l('Performance').'</a>'; - $this->displayWarning(sprintf($this->l('This feature has been disabled. You can activate it here: %s.'), $url)); - return; - } - - // toolbar (save, cancel, new, ..) - $this->initTabModuleList(); - $this->initToolbar(); - $this->initPageHeaderToolbar(); - if ($this->display == 'edit' || $this->display == 'add') - { - if (!($this->object = $this->loadObject(true))) - return; - $this->content .= $this->renderForm(); - } - elseif ($this->display == 'editAttributes') - { - if (!$this->object = new Attribute((int)Tools::getValue('id_attribute'))) - return; - - $this->content .= $this->renderFormAttributes(); - } - elseif ($this->display != 'view' && !$this->ajax) - { - $this->content .= $this->renderList(); - $this->content .= $this->renderOptions(); - } - elseif ($this->display == 'view' && !$this->ajax) - $this->content = $this->renderView(); - - $this->context->smarty->assign(array( - 'table' => $this->table, - 'current' => self::$currentIndex, - 'token' => $this->token, - 'content' => $this->content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } - - public function initPageHeaderToolbar() - { - if (empty($this->display)) - { - $this->page_header_toolbar_btn['new_attribute_group'] = array( - 'href' => self::$currentIndex.'&addattribute_group&token='.$this->token, - 'desc' => $this->l('Add new attribute', null, null, false), - 'icon' => 'process-icon-new' - ); - $this->page_header_toolbar_btn['new_value'] = array( - 'href' => self::$currentIndex.'&updateattribute&id_attribute_group='.(int)Tools::getValue('id_attribute_group').'&token='.$this->token, - 'desc' => $this->l('Add new value', null, null, false), - 'icon' => 'process-icon-new' - ); - } - - if ($this->display == 'view') - $this->page_header_toolbar_btn['new_value'] = array( - 'href' => self::$currentIndex.'&updateattribute&id_attribute_group='.(int)Tools::getValue('id_attribute_group').'&token='.$this->token, - 'desc' => $this->l('Add new value', null, null, false), - 'icon' => 'process-icon-new' - ); - - parent::initPageHeaderToolbar(); - } - - public function initToolbar() - { - switch ($this->display) - { - // @todo defining default buttons - case 'add': - case 'edit': - case 'editAttributes': - // Default save button - action dynamically handled in javascript - $this->toolbar_btn['save'] = array( - 'href' => '#', - 'desc' => $this->l('Save') - ); - - if ($this->display == 'editAttributes' && !$this->id_attribute) - $this->toolbar_btn['save-and-stay'] = array( - 'short' => 'SaveAndStay', - 'href' => '#', - 'desc' => $this->l('Save then add another value', null, null, false), - 'force_desc' => true, - ); - - $this->toolbar_btn['back'] = array( - 'href' => self::$currentIndex.'&token='.$this->token, - 'desc' => $this->l('Back to list', null, null, false) - ); - break; - case 'view': - $this->toolbar_btn['newAttributes'] = array( - 'href' => self::$currentIndex.'&updateattribute&id_attribute_group='.(int)Tools::getValue('id_attribute_group').'&token='.$this->token, - 'desc' => $this->l('Add New Values', null, null, false), - 'class' => 'toolbar-new' - ); - - $this->toolbar_btn['back'] = array( - 'href' => self::$currentIndex.'&token='.$this->token, - 'desc' => $this->l('Back to list', null, null, false) - ); - break; - default: // list - $this->toolbar_btn['new'] = array( - 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token, - 'desc' => $this->l('Add New Attributes', null, null, false) - ); - if ($this->can_import) - $this->toolbar_btn['import'] = array( - 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=combinations', - 'desc' => $this->l('Import', null, null, false) - ); - } - } - - public function initToolbarTitle() - { - $bread_extended = $this->breadcrumbs; - - switch ($this->display) - { - case 'edit': - $bread_extended[] = $this->l('Edit New Attribute'); - break; - - case 'add': - $bread_extended[] = $this->l('Add New Attribute'); - break; - - case 'view': - if (Tools::getIsset('viewattribute_group')) - { - if (($id = Tools::getValue('id_attribute_group'))) - if (Validate::isLoadedObject($obj = new AttributeGroup((int)$id))) - $bread_extended[] = $obj->name[$this->context->employee->id_lang]; - } - else - $bread_extended[] = $this->attribute_name[$this->context->employee->id_lang]; - break; - - case 'editAttributes': - if ($this->id_attribute) - { - if (($id = Tools::getValue('id_attribute_group'))) - { - if (Validate::isLoadedObject($obj = new AttributeGroup((int)$id))) - $bread_extended[] = '<a href="'.Context::getContext()->link->getAdminLink('AdminAttributesGroups').'&id_attribute_group='.$id.'&viewattribute_group">'.$obj->name[$this->context->employee->id_lang].'</a>'; - if (Validate::isLoadedObject($obj = new Attribute((int)$this->id_attribute))) - $bread_extended[] = sprintf($this->l('Edit: %s'), $obj->name[$this->context->employee->id_lang]); - } - else - $bread_extended[] = $this->l('Edit Value'); - } - else - $bread_extended[] = $this->l('Add New Value'); - break; - } - - if (count($bread_extended) > 0) - $this->addMetaTitle($bread_extended[count($bread_extended) - 1]); - - $this->toolbar_title = $bread_extended; - } - - public function initProcess() - { - $this->setTypeAttribute(); - - if (Tools::getIsset('viewattribute_group')) - { - $this->list_id = 'attribute_values'; - - if (isset($_POST['submitReset'.$this->list_id])) - $this->processResetFilters(); - } - else - $this->list_id = 'attribute_group'; - - parent::initProcess(); - - if ($this->table == 'attribute') - { - $this->display = 'editAttributes'; - $this->id_attribute = (int)Tools::getValue('id_attribute'); - } - } - - protected function setTypeAttribute() - { - if (Tools::isSubmit('updateattribute') || Tools::isSubmit('deleteattribute') || Tools::isSubmit('submitAddattribute') || Tools::isSubmit('submitBulkdeleteattribute')) - { - $this->table = 'attribute'; - $this->className = 'Attribute'; - $this->identifier = 'id_attribute'; - - if ($this->display == 'edit') - $this->display = 'editAttributes'; - } - } - - public function processPosition() - { - if (Tools::getIsset('viewattribute_group')) - { - $object = new Attribute((int)Tools::getValue('id_attribute')); - self::$currentIndex = self::$currentIndex.'&viewattribute_group'; - } - else - $object = new AttributeGroup((int)Tools::getValue('id_attribute_group')); - - if (!Validate::isLoadedObject($object)) - { - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.'). - ' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - } - elseif (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) - $this->errors[] = Tools::displayError('Failed to update the position.'); - else - { - $id_identifier_str = ($id_identifier = (int)Tools::getValue($this->identifier)) ? '&'.$this->identifier.'='.$id_identifier : ''; - $redirect = self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=5'.$id_identifier_str.'&token='.$this->token; - $this->redirect_after = $redirect; - } - return $object; - } - - /** - * Call the right method for creating or updating object - * - * @return mixed - */ - public function processSave() - { - if ($this->display == 'add' || $this->display == 'edit') - $this->identifier = 'id_attribute_group'; - - if (!$this->id_object) - return $this->processAdd(); - else - return $this->processUpdate(); - } - - public function postProcess() - { - if (!Combination::isFeatureActive()) - return; - - if (!Tools::getValue($this->identifier) && Tools::getValue('id_attribute') && !Tools::getValue('attributeOrderby')) - { - // Override var of Controller - $this->table = 'attribute'; - $this->className = 'Attribute'; - $this->identifier = 'id_attribute'; - } - - // If it's an attribute, load object Attribute() - if (Tools::getValue('updateattribute') || Tools::isSubmit('deleteattribute') || Tools::isSubmit('submitAddattribute')) - { - if ($this->tabAccess['edit'] !== '1') - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - elseif (!$object = new Attribute((int)Tools::getValue($this->identifier))) - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - - if (Tools::getValue('position') !== false && Tools::getValue('id_attribute')) - { - $_POST['id_attribute_group'] = $object->id_attribute_group; - if (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) - $this->errors[] = Tools::displayError('Failed to update the position.'); - else - Tools::redirectAdmin(self::$currentIndex.'&conf=5&token='.Tools::getAdminTokenLite('AdminAttributesGroups').'#details_details_'.$object->id_attribute_group); - } - elseif (Tools::isSubmit('deleteattribute') && Tools::getValue('id_attribute')) - { - if (!$object->delete()) - $this->errors[] = Tools::displayError('Failed to delete the attribute.'); - else - Tools::redirectAdmin(self::$currentIndex.'&conf=1&token='.Tools::getAdminTokenLite('AdminAttributesGroups')); - } - elseif (Tools::isSubmit('submitAddattribute')) - { - Hook::exec('actionObjectAttributeAddBefore'); - $this->action = 'save'; - $id_attribute = (int)Tools::getValue('id_attribute'); - // Adding last position to the attribute if not exist - if ($id_attribute <= 0) - { - $sql = 'SELECT `position`+1 + public $bootstrap = true; + protected $id_attribute; + protected $position_identifier = 'id_attribute_group'; + protected $attribute_name; + + public function __construct() + { + $this->bootstrap = true; + $this->context = Context::getContext(); + $this->table = 'attribute_group'; + $this->list_id = 'attribute_group'; + $this->identifier = 'id_attribute_group'; + $this->className = 'AttributeGroup'; + $this->lang = true; + $this->_defaultOrderBy = 'position'; + + $this->fields_list = array( + 'id_attribute_group' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Name'), + 'filter_key' => 'b!name', + 'align' => 'left' + ), + 'count_values' => array( + 'title' => $this->l('Values count'), + 'align' => 'center', + 'class' => 'fixed-width-xs', + 'orderby' => false, + 'search' => false + ), + 'position' => array( + 'title' => $this->l('Position'), + 'filter_key' => 'a!position', + 'position' => 'position', + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + ); + + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'icon' => 'icon-trash', + 'confirm' => $this->l('Delete selected items?') + ) + ); + $this->fieldImageSettings = array('name' => 'texture', 'dir' => 'co'); + + parent::__construct(); + } + + /** + * AdminController::renderList() override + * @see AdminController::renderList() + */ + public function renderList() + { + $this->addRowAction('view'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); + + + return parent::renderList(); + } + + public function renderView() + { + if (($id = Tools::getValue('id_attribute_group'))) { + $this->table = 'attribute'; + $this->className = 'Attribute'; + $this->identifier = 'id_attribute'; + $this->position_identifier = 'id_attribute'; + $this->position_group_identifier = 'id_attribute_group'; + $this->list_id = 'attribute_values'; + $this->lang = true; + + $this->context->smarty->assign(array( + 'current' => self::$currentIndex.'&id_attribute_group='.(int)$id.'&viewattribute_group' + )); + + if (!Validate::isLoadedObject($obj = new AttributeGroup((int)$id))) { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + return; + } + + $this->attribute_name = $obj->name; + $this->fields_list = array( + 'id_attribute' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Value'), + 'width' => 'auto', + 'filter_key' => 'b!name' + ) + ); + + if ($obj->group_type == 'color') { + $this->fields_list['color'] = array( + 'title' => $this->l('Color'), + 'filter_key' => 'a!color', + ); + } + + $this->fields_list['position'] = array( + 'title' => $this->l('Position'), + 'filter_key' => 'a!position', + 'position' => 'position', + 'class' => 'fixed-width-md' + ); + + $this->addRowAction('edit'); + $this->addRowAction('delete'); + + $this->_where = 'AND a.`id_attribute_group` = '.(int)$id; + $this->_orderBy = 'position'; + + self::$currentIndex = self::$currentIndex.'&id_attribute_group='.(int)$id.'&viewattribute_group'; + $this->processFilter(); + return parent::renderList(); + } + } + + /** + * AdminController::renderForm() override + * @see AdminController::renderForm() + */ + public function renderForm() + { + $this->table = 'attribute_group'; + $this->identifier = 'id_attribute_group'; + + $group_type = array( + array( + 'id' => 'select', + 'name' => $this->l('Drop-down list') + ), + array( + 'id' => 'radio', + 'name' => $this->l('Radio buttons') + ), + array( + 'id' => 'color', + 'name' => $this->l('Color or texture') + ), + ); + + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Attributes'), + 'icon' => 'icon-info-sign' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'lang' => true, + 'required' => true, + 'col' => '4', + 'hint' => $this->l('Your internal name for this attribute.').' '.$this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'text', + 'label' => $this->l('Public name'), + 'name' => 'public_name', + 'lang' => true, + 'required' => true, + 'col' => '4', + 'hint' => $this->l('The public name for this attribute, displayed to the customers.').' '.$this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'select', + 'label' => $this->l('Attribute type'), + 'name' => 'group_type', + 'required' => true, + 'options' => array( + 'query' => $group_type, + 'id' => 'id', + 'name' => 'name' + ), + 'col' => '2', + 'hint' => $this->l('The way the attribute\'s values will be presented to the customers in the product\'s page.') + ) + ) + ); + + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } + + $this->fields_form['submit'] = array( + 'title' => $this->l('Save'), + ); + + if (!($obj = $this->loadObject(true))) { + return; + } + + return parent::renderForm(); + } + + public function renderFormAttributes() + { + $attributes_groups = AttributeGroup::getAttributesGroups($this->context->language->id); + + $this->table = 'attribute'; + $this->identifier = 'id_attribute'; + + $this->show_form_cancel_button = true; + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Values'), + 'icon' => 'icon-info-sign' + ), + 'input' => array( + array( + 'type' => 'select', + 'label' => $this->l('Attribute group'), + 'name' => 'id_attribute_group', + 'required' => true, + 'options' => array( + 'query' => $attributes_groups, + 'id' => 'id_attribute_group', + 'name' => 'name' + ), + 'hint' => $this->l('Choose the attribute group for this value.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Value'), + 'name' => 'name', + 'lang' => true, + 'required' => true, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ) + ) + ); + + if (Shop::isFeatureActive()) { + // We get all associated shops for all attribute groups, because we will disable group shops + // for attributes that the selected attribute group don't support + $sql = 'SELECT id_attribute_group, id_shop FROM '._DB_PREFIX_.'attribute_group_shop'; + $associations = array(); + foreach (Db::getInstance()->executeS($sql) as $row) { + $associations[$row['id_attribute_group']][] = $row['id_shop']; + } + + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + 'values' => Shop::getTree() + ); + } else { + $associations = array(); + } + + $this->fields_form['shop_associations'] = Tools::jsonEncode($associations); + + $this->fields_form['input'][] = array( + 'type' => 'color', + 'label' => $this->l('Color'), + 'name' => 'color', + 'hint' => $this->l('Choose a color with the color picker, or enter an HTML color (e.g. "lightblue", "#CC6600").') + ); + + $this->fields_form['input'][] = array( + 'type' => 'file', + 'label' => $this->l('Texture'), + 'name' => 'texture', + 'hint' => array( + $this->l('Upload an image file containing the color texture from your computer.'), + $this->l('This will override the HTML color!') + ) + ); + + $this->fields_form['input'][] = array( + 'type' => 'current_texture', + 'label' => $this->l('Current texture'), + 'name' => 'current_texture' + ); + + $this->fields_form['input'][] = array( + 'type' => 'closediv', + 'name' => '' + ); + + $this->fields_form['submit'] = array( + 'title' => $this->l('Save'), + ); + + $this->fields_form['buttons'] = array( + 'save-and-stay' => array( + 'title' => $this->l('Save then add another value'), + 'name' => 'submitAdd'.$this->table.'AndStay', + 'type' => 'submit', + 'class' => 'btn btn-default pull-right', + 'icon' => 'process-icon-save' + ) + ); + + $this->fields_value['id_attribute_group'] = (int)Tools::getValue('id_attribute_group'); + + // Override var of Controller + $this->table = 'attribute'; + $this->className = 'Attribute'; + $this->identifier = 'id_attribute'; + $this->lang = true; + $this->tpl_folder = 'attributes/'; + + // Create object Attribute + if (!$obj = new Attribute((int)Tools::getValue($this->identifier))) { + return; + } + + $str_attributes_groups = ''; + foreach ($attributes_groups as $attribute_group) { + $str_attributes_groups .= '"'.$attribute_group['id_attribute_group'].'" : '.($attribute_group['group_type'] == 'color' ? '1' : '0').', '; + } + + $image = '../img/'.$this->fieldImageSettings['dir'].'/'.(int)$obj->id.'.jpg'; + + $this->tpl_form_vars = array( + 'strAttributesGroups' => $str_attributes_groups, + 'colorAttributeProperties' => Validate::isLoadedObject($obj) && $obj->isColorAttribute(), + 'imageTextureExists' => file_exists(_PS_IMG_DIR_.$this->fieldImageSettings['dir'].'/'.(int)$obj->id.'.jpg'), + 'imageTexture' => $image, + 'imageTextureUrl' => Tools::safeOutput($_SERVER['REQUEST_URI']).'&deleteImage=1' + ); + + return parent::renderForm(); + } + + /** + * AdminController::init() override + * @see AdminController::init() + */ + public function init() + { + if (Tools::isSubmit('updateattribute')) { + $this->display = 'editAttributes'; + } elseif (Tools::isSubmit('submitAddattribute')) { + $this->display = 'editAttributes'; + } elseif (Tools::isSubmit('submitAddattribute_group')) { + $this->display = 'add'; + } + + parent::init(); + } + + /** + * Override processAdd to change SaveAndStay button action + * @see classes/AdminControllerCore::processUpdate() + */ + public function processAdd() + { + if ($this->table == 'attribute') { + /** @var AttributeGroup $object */ + $object = new $this->className(); + foreach (Language::getLanguages(false) as $language) { + if ($object->isAttribute((int)Tools::getValue('id_attribute_group'), + Tools::getValue('name_'.$language['id_lang']), $language['id_lang'])) { + $this->errors['name_'.$language['id_lang']] = + sprintf(Tools::displayError('The attribute value "%1$s" already exist for %2$s language'), + Tools::getValue('name_'.$language['id_lang']), $language['name']); + } + } + + if (!empty($this->errors)) { + return $object; + } + } + + $object = parent::processAdd(); + + if (Tools::isSubmit('submitAdd'.$this->table.'AndStay') && !count($this->errors)) { + if ($this->display == 'add') { + $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'=&conf=3&update'.$this->table.'&token='.$this->token; + } else { + $this->redirect_after = self::$currentIndex.'&id_attribute_group='.(int)Tools::getValue('id_attribute_group').'&conf=3&update'.$this->table.'&token='.$this->token; + } + } + + if (count($this->errors)) { + $this->setTypeAttribute(); + } + + return $object; + } + + /** + * Override processUpdate to change SaveAndStay button action + * @see classes/AdminControllerCore::processUpdate() + */ + public function processUpdate() + { + $object = parent::processUpdate(); + + if (Tools::isSubmit('submitAdd'.$this->table.'AndStay') && !count($this->errors)) { + if ($this->display == 'add') { + $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'=&conf=3&update'.$this->table.'&token='.$this->token; + } else { + $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'=&id_attribute_group='.(int)Tools::getValue('id_attribute_group').'&conf=3&update'.$this->table.'&token='.$this->token; + } + } + + if (count($this->errors)) { + $this->setTypeAttribute(); + } + + if (Tools::isSubmit('updateattribute') || Tools::isSubmit('deleteattribute') || Tools::isSubmit('submitAddattribute') || Tools::isSubmit('submitBulkdeleteattribute')) { + Tools::clearColorListCache(); + } + + return $object; + } + + /** + * AdminController::initContent() override + * @see AdminController::initContent() + */ + public function initContent() + { + if (!Combination::isFeatureActive()) { + $url = '<a href="index.php?tab=AdminPerformance&token='.Tools::getAdminTokenLite('AdminPerformance').'#featuresDetachables">'. + $this->l('Performance').'</a>'; + $this->displayWarning(sprintf($this->l('This feature has been disabled. You can activate it here: %s.'), $url)); + return; + } + + // toolbar (save, cancel, new, ..) + $this->initTabModuleList(); + $this->initToolbar(); + $this->initPageHeaderToolbar(); + if ($this->display == 'edit' || $this->display == 'add') { + if (!($this->object = $this->loadObject(true))) { + return; + } + $this->content .= $this->renderForm(); + } elseif ($this->display == 'editAttributes') { + if (!$this->object = new Attribute((int)Tools::getValue('id_attribute'))) { + return; + } + + $this->content .= $this->renderFormAttributes(); + } elseif ($this->display != 'view' && !$this->ajax) { + $this->content .= $this->renderList(); + $this->content .= $this->renderOptions(); + } elseif ($this->display == 'view' && !$this->ajax) { + $this->content = $this->renderView(); + } + + $this->context->smarty->assign(array( + 'table' => $this->table, + 'current' => self::$currentIndex, + 'token' => $this->token, + 'content' => $this->content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } + + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_attribute_group'] = array( + 'href' => self::$currentIndex.'&addattribute_group&token='.$this->token, + 'desc' => $this->l('Add new attribute', null, null, false), + 'icon' => 'process-icon-new' + ); + $this->page_header_toolbar_btn['new_value'] = array( + 'href' => self::$currentIndex.'&updateattribute&id_attribute_group='.(int)Tools::getValue('id_attribute_group').'&token='.$this->token, + 'desc' => $this->l('Add new value', null, null, false), + 'icon' => 'process-icon-new' + ); + } + + if ($this->display == 'view') { + $this->page_header_toolbar_btn['new_value'] = array( + 'href' => self::$currentIndex.'&updateattribute&id_attribute_group='.(int)Tools::getValue('id_attribute_group').'&token='.$this->token, + 'desc' => $this->l('Add new value', null, null, false), + 'icon' => 'process-icon-new' + ); + } + + parent::initPageHeaderToolbar(); + } + + public function initToolbar() + { + switch ($this->display) { + // @todo defining default buttons + case 'add': + case 'edit': + case 'editAttributes': + // Default save button - action dynamically handled in javascript + $this->toolbar_btn['save'] = array( + 'href' => '#', + 'desc' => $this->l('Save') + ); + + if ($this->display == 'editAttributes' && !$this->id_attribute) { + $this->toolbar_btn['save-and-stay'] = array( + 'short' => 'SaveAndStay', + 'href' => '#', + 'desc' => $this->l('Save then add another value', null, null, false), + 'force_desc' => true, + ); + } + + $this->toolbar_btn['back'] = array( + 'href' => self::$currentIndex.'&token='.$this->token, + 'desc' => $this->l('Back to list', null, null, false) + ); + break; + case 'view': + $this->toolbar_btn['newAttributes'] = array( + 'href' => self::$currentIndex.'&updateattribute&id_attribute_group='.(int)Tools::getValue('id_attribute_group').'&token='.$this->token, + 'desc' => $this->l('Add New Values', null, null, false), + 'class' => 'toolbar-new' + ); + + $this->toolbar_btn['back'] = array( + 'href' => self::$currentIndex.'&token='.$this->token, + 'desc' => $this->l('Back to list', null, null, false) + ); + break; + default: // list + $this->toolbar_btn['new'] = array( + 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token, + 'desc' => $this->l('Add New Attributes', null, null, false) + ); + if ($this->can_import) { + $this->toolbar_btn['import'] = array( + 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=combinations', + 'desc' => $this->l('Import', null, null, false) + ); + } + } + } + + public function initToolbarTitle() + { + $bread_extended = $this->breadcrumbs; + + switch ($this->display) { + case 'edit': + $bread_extended[] = $this->l('Edit New Attribute'); + break; + + case 'add': + $bread_extended[] = $this->l('Add New Attribute'); + break; + + case 'view': + if (Tools::getIsset('viewattribute_group')) { + if (($id = Tools::getValue('id_attribute_group'))) { + if (Validate::isLoadedObject($obj = new AttributeGroup((int)$id))) { + $bread_extended[] = $obj->name[$this->context->employee->id_lang]; + } + } + } else { + $bread_extended[] = $this->attribute_name[$this->context->employee->id_lang]; + } + break; + + case 'editAttributes': + if ($this->id_attribute) { + if (($id = Tools::getValue('id_attribute_group'))) { + if (Validate::isLoadedObject($obj = new AttributeGroup((int)$id))) { + $bread_extended[] = '<a href="'.Context::getContext()->link->getAdminLink('AdminAttributesGroups').'&id_attribute_group='.$id.'&viewattribute_group">'.$obj->name[$this->context->employee->id_lang].'</a>'; + } + if (Validate::isLoadedObject($obj = new Attribute((int)$this->id_attribute))) { + $bread_extended[] = sprintf($this->l('Edit: %s'), $obj->name[$this->context->employee->id_lang]); + } + } else { + $bread_extended[] = $this->l('Edit Value'); + } + } else { + $bread_extended[] = $this->l('Add New Value'); + } + break; + } + + if (count($bread_extended) > 0) { + $this->addMetaTitle($bread_extended[count($bread_extended) - 1]); + } + + $this->toolbar_title = $bread_extended; + } + + public function initProcess() + { + $this->setTypeAttribute(); + + if (Tools::getIsset('viewattribute_group')) { + $this->list_id = 'attribute_values'; + + if (isset($_POST['submitReset'.$this->list_id])) { + $this->processResetFilters(); + } + } else { + $this->list_id = 'attribute_group'; + } + + parent::initProcess(); + + if ($this->table == 'attribute') { + $this->display = 'editAttributes'; + $this->id_attribute = (int)Tools::getValue('id_attribute'); + } + } + + protected function setTypeAttribute() + { + if (Tools::isSubmit('updateattribute') || Tools::isSubmit('deleteattribute') || Tools::isSubmit('submitAddattribute') || Tools::isSubmit('submitBulkdeleteattribute')) { + $this->table = 'attribute'; + $this->className = 'Attribute'; + $this->identifier = 'id_attribute'; + + if ($this->display == 'edit') { + $this->display = 'editAttributes'; + } + } + } + + public function processPosition() + { + if (Tools::getIsset('viewattribute_group')) { + $object = new Attribute((int)Tools::getValue('id_attribute')); + self::$currentIndex = self::$currentIndex.'&viewattribute_group'; + } else { + $object = new AttributeGroup((int)Tools::getValue('id_attribute_group')); + } + + if (!Validate::isLoadedObject($object)) { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.'). + ' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } elseif (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) { + $this->errors[] = Tools::displayError('Failed to update the position.'); + } else { + $id_identifier_str = ($id_identifier = (int)Tools::getValue($this->identifier)) ? '&'.$this->identifier.'='.$id_identifier : ''; + $redirect = self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=5'.$id_identifier_str.'&token='.$this->token; + $this->redirect_after = $redirect; + } + return $object; + } + + /** + * Call the right method for creating or updating object + * + * @return mixed + */ + public function processSave() + { + if ($this->display == 'add' || $this->display == 'edit') { + $this->identifier = 'id_attribute_group'; + } + + if (!$this->id_object) { + return $this->processAdd(); + } else { + return $this->processUpdate(); + } + } + + public function postProcess() + { + if (!Combination::isFeatureActive()) { + return; + } + + if (!Tools::getValue($this->identifier) && Tools::getValue('id_attribute') && !Tools::getValue('attributeOrderby')) { + // Override var of Controller + $this->table = 'attribute'; + $this->className = 'Attribute'; + $this->identifier = 'id_attribute'; + } + + // If it's an attribute, load object Attribute() + if (Tools::getValue('updateattribute') || Tools::isSubmit('deleteattribute') || Tools::isSubmit('submitAddattribute')) { + if ($this->tabAccess['edit'] !== '1') { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } elseif (!$object = new Attribute((int)Tools::getValue($this->identifier))) { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } + + if (Tools::getValue('position') !== false && Tools::getValue('id_attribute')) { + $_POST['id_attribute_group'] = $object->id_attribute_group; + if (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) { + $this->errors[] = Tools::displayError('Failed to update the position.'); + } else { + Tools::redirectAdmin(self::$currentIndex.'&conf=5&token='.Tools::getAdminTokenLite('AdminAttributesGroups').'#details_details_'.$object->id_attribute_group); + } + } elseif (Tools::isSubmit('deleteattribute') && Tools::getValue('id_attribute')) { + if (!$object->delete()) { + $this->errors[] = Tools::displayError('Failed to delete the attribute.'); + } else { + Tools::redirectAdmin(self::$currentIndex.'&conf=1&token='.Tools::getAdminTokenLite('AdminAttributesGroups')); + } + } elseif (Tools::isSubmit('submitAddattribute')) { + Hook::exec('actionObjectAttributeAddBefore'); + $this->action = 'save'; + $id_attribute = (int)Tools::getValue('id_attribute'); + // Adding last position to the attribute if not exist + if ($id_attribute <= 0) { + $sql = 'SELECT `position`+1 FROM `'._DB_PREFIX_.'attribute` WHERE `id_attribute_group` = '.(int)Tools::getValue('id_attribute_group').' ORDER BY position DESC'; - // set the position of the new group attribute in $_POST for postProcess() method - $_POST['position'] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); - } - $_POST['id_parent'] = 0; - $this->processSave($this->token); - } + // set the position of the new group attribute in $_POST for postProcess() method + $_POST['position'] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); + } + $_POST['id_parent'] = 0; + $this->processSave($this->token); + } - if (Tools::getValue('id_attribute') && Tools::isSubmit('submitAddattribute') && Tools::getValue('color') && !Tools::getValue('filename')) - if (file_exists(_PS_IMG_DIR_.$this->fieldImageSettings['dir'].'/'.(int)Tools::getValue('id_attribute').'.jpg')) - unlink(_PS_IMG_DIR_.$this->fieldImageSettings['dir'].'/'.(int)Tools::getValue('id_attribute').'.jpg'); - } - else - { - if (Tools::getValue('submitDel'.$this->table)) - { - if ($this->tabAccess['delete'] === '1') - { - if (isset($_POST[$this->table.'Box'])) - { - /** @var AttributeGroup $object */ - $object = new $this->className(); - if ($object->deleteSelection($_POST[$this->table.'Box'])) - Tools::redirectAdmin(self::$currentIndex.'&conf=2'.'&token='.$this->token); - $this->errors[] = Tools::displayError('An error occurred while deleting this selection.'); - } - else - $this->errors[] = Tools::displayError('You must select at least one element to delete.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - // clean position after delete - AttributeGroup::cleanPositions(); - } - elseif (Tools::isSubmit('submitAdd'.$this->table)) - { - Hook::exec('actionObjectAttributeGroupAddBefore'); - $id_attribute_group = (int)Tools::getValue('id_attribute_group'); - // Adding last position to the attribute if not exist - if ($id_attribute_group <= 0) - { - $sql = 'SELECT `position`+1 + if (Tools::getValue('id_attribute') && Tools::isSubmit('submitAddattribute') && Tools::getValue('color') && !Tools::getValue('filename')) { + if (file_exists(_PS_IMG_DIR_.$this->fieldImageSettings['dir'].'/'.(int)Tools::getValue('id_attribute').'.jpg')) { + unlink(_PS_IMG_DIR_.$this->fieldImageSettings['dir'].'/'.(int)Tools::getValue('id_attribute').'.jpg'); + } + } + } else { + if (Tools::isSubmit('submitBulkdelete'.$this->table)) { + if ($this->tabAccess['delete'] === '1') { + if (isset($_POST[$this->table.'Box'])) { + /** @var AttributeGroup $object */ + $object = new $this->className(); + if ($object->deleteSelection($_POST[$this->table.'Box'])) { + AttributeGroup::cleanPositions(); + Tools::redirectAdmin(self::$currentIndex.'&conf=2'.'&token='.$this->token); + } + $this->errors[] = Tools::displayError('An error occurred while deleting this selection.'); + } else { + $this->errors[] = Tools::displayError('You must select at least one element to delete.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + // clean position after delete + AttributeGroup::cleanPositions(); + } elseif (Tools::isSubmit('submitAdd'.$this->table)) { + Hook::exec('actionObjectAttributeGroupAddBefore'); + $id_attribute_group = (int)Tools::getValue('id_attribute_group'); + // Adding last position to the attribute if not exist + if ($id_attribute_group <= 0) { + $sql = 'SELECT `position`+1 FROM `'._DB_PREFIX_.'attribute_group` ORDER BY position DESC'; - // set the position of the new group attribute in $_POST for postProcess() method - $_POST['position'] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); - } - // clean \n\r characters - foreach ($_POST as $key => $value) - if (preg_match('/^name_/Ui', $key)) - $_POST[$key] = str_replace ('\n', '', str_replace('\r', '', $value)); - parent::postProcess(); - } - else - parent::postProcess(); - } - } + // set the position of the new group attribute in $_POST for postProcess() method + $_POST['position'] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); + } + // clean \n\r characters + foreach ($_POST as $key => $value) { + if (preg_match('/^name_/Ui', $key)) { + $_POST[$key] = str_replace('\n', '', str_replace('\r', '', $value)); + } + } + parent::postProcess(); + } else { + parent::postProcess(); + if (Tools::isSubmit('delete'.$this->table)) + { + AttributeGroup::cleanPositions(); + } + } + } + } - /** - * AdminController::getList() override - * @see AdminController::getList() - * - * @param int $id_lang - * @param string|null $order_by - * @param string|null $order_way - * @param int $start - * @param int|null $limit - * @param int|bool $id_lang_shop - * - * @throws PrestaShopException - */ - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + /** + * AdminController::getList() override + * @see AdminController::getList() + * + * @param int $id_lang + * @param string|null $order_by + * @param string|null $order_way + * @param int $start + * @param int|null $limit + * @param int|bool $id_lang_shop + * + * @throws PrestaShopException + */ + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - if ($this->display == 'view') - { - foreach ($this->_list as &$list) - if (file_exists(_PS_IMG_DIR_.$this->fieldImageSettings['dir'].'/'.(int)$list['id_attribute'].'.jpg')) - { - if (!isset($list['color']) || !is_array($list['color'])) - $list['color'] = array(); - $list['color']['texture'] = '../img/'.$this->fieldImageSettings['dir'].'/'.(int)$list['id_attribute'].'.jpg'; - } - } - else - { - $nb_items = count($this->_list); - for ($i = 0; $i < $nb_items; ++$i) - { - $item = &$this->_list[$i]; + if ($this->display == 'view') { + foreach ($this->_list as &$list) { + if (file_exists(_PS_IMG_DIR_.$this->fieldImageSettings['dir'].'/'.(int)$list['id_attribute'].'.jpg')) { + if (!isset($list['color']) || !is_array($list['color'])) { + $list['color'] = array(); + } + $list['color']['texture'] = '../img/'.$this->fieldImageSettings['dir'].'/'.(int)$list['id_attribute'].'.jpg'; + } + } + } else { + $nb_items = count($this->_list); + for ($i = 0; $i < $nb_items; ++$i) { + $item = &$this->_list[$i]; - $query = new DbQuery(); - $query->select('COUNT(a.id_attribute) as count_values'); - $query->from('attribute', 'a'); - $query->join(Shop::addSqlAssociation('attribute', 'a')); - $query->where('a.id_attribute_group ='.(int)$item['id_attribute_group']); - $query->groupBy('attribute_shop.id_shop'); - $query->orderBy('count_values DESC'); - $item['count_values'] = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - unset($query); - } - } - } + $query = new DbQuery(); + $query->select('COUNT(a.id_attribute) as count_values'); + $query->from('attribute', 'a'); + $query->join(Shop::addSqlAssociation('attribute', 'a')); + $query->where('a.id_attribute_group ='.(int)$item['id_attribute_group']); + $query->groupBy('attribute_shop.id_shop'); + $query->orderBy('count_values DESC'); + $item['count_values'] = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + unset($query); + } + } + } - /** - * Overrides parent to delete items from sublist - * - * @return mixed - */ - public function processBulkDelete() - { - // If we are deleting attributes instead of attribute_groups - if (Tools::getIsset('attributeBox')) - { - $this->className = 'Attribute'; - $this->table = 'attribute'; - $this->boxes = Tools::getValue($this->table.'Box'); - } + /** + * Overrides parent to delete items from sublist + * + * @return mixed + */ + public function processBulkDelete() + { + // If we are deleting attributes instead of attribute_groups + if (Tools::getIsset('attributeBox')) { + $this->className = 'Attribute'; + $this->table = 'attribute'; + $this->boxes = Tools::getValue($this->table.'Box'); + } - $result = parent::processBulkDelete(); - // Restore vars - $this->className = 'AttributeGroup'; - $this->table = 'attribute_group'; + $result = parent::processBulkDelete(); + // Restore vars + $this->className = 'AttributeGroup'; + $this->table = 'attribute_group'; - return $result; - } + return $result; + } - /* Modify group attribute position */ - public function ajaxProcessUpdateGroupsPositions() - { - $way = (int)Tools::getValue('way'); - $id_attribute_group = (int)Tools::getValue('id_attribute_group'); - $positions = Tools::getValue('attribute_group'); + /* Modify group attribute position */ + public function ajaxProcessUpdateGroupsPositions() + { + $way = (int)Tools::getValue('way'); + $id_attribute_group = (int)Tools::getValue('id_attribute_group'); + $positions = Tools::getValue('attribute_group'); - $new_positions = array(); - foreach ($positions as $k => $v) - if (count(explode('_', $v)) == 4) - $new_positions[] = $v; + $new_positions = array(); + foreach ($positions as $k => $v) { + if (count(explode('_', $v)) == 4) { + $new_positions[] = $v; + } + } - foreach ($new_positions as $position => $value) - { - $pos = explode('_', $value); + foreach ($new_positions as $position => $value) { + $pos = explode('_', $value); - if (isset($pos[2]) && (int)$pos[2] === $id_attribute_group) - { - if ($group_attribute = new AttributeGroup((int)$pos[2])) - if (isset($position) && $group_attribute->updatePosition($way, $position)) - echo 'ok position '.(int)$position.' for attribute group '.(int)$pos[2].'\r\n'; - else - echo '{"hasError" : true, "errors" : "Can not update the '.(int)$id_attribute_group.' attribute group to position '.(int)$position.' "}'; - else - echo '{"hasError" : true, "errors" : "The ('.(int)$id_attribute_group.') attribute group cannot be loaded."}'; + if (isset($pos[2]) && (int)$pos[2] === $id_attribute_group) { + if ($group_attribute = new AttributeGroup((int)$pos[2])) { + if (isset($position) && $group_attribute->updatePosition($way, $position)) { + echo 'ok position '.(int)$position.' for attribute group '.(int)$pos[2].'\r\n'; + } else { + echo '{"hasError" : true, "errors" : "Can not update the '.(int)$id_attribute_group.' attribute group to position '.(int)$position.' "}'; + } + } else { + echo '{"hasError" : true, "errors" : "The ('.(int)$id_attribute_group.') attribute group cannot be loaded."}'; + } - break; - } - } - } + break; + } + } + } - /* Modify attribute position */ - public function ajaxProcessUpdateAttributesPositions() - { - $way = (int)Tools::getValue('way'); - $id_attribute = (int)Tools::getValue('id_attribute'); - $id_attribute_group = (int)Tools::getValue('id_attribute_group'); - $positions = Tools::getValue('attribute'); + /* Modify attribute position */ + public function ajaxProcessUpdateAttributesPositions() + { + $way = (int)Tools::getValue('way'); + $id_attribute = (int)Tools::getValue('id_attribute'); + $id_attribute_group = (int)Tools::getValue('id_attribute_group'); + $positions = Tools::getValue('attribute'); - if (is_array($positions)) - foreach ($positions as $position => $value) - { - $pos = explode('_', $value); + if (is_array($positions)) { + foreach ($positions as $position => $value) { + $pos = explode('_', $value); - if ((isset($pos[1]) && isset($pos[2])) && (int)$pos[2] === $id_attribute) - { - if ($attribute = new Attribute((int)$pos[2])) - if (isset($position) && $attribute->updatePosition($way, $position)) - echo 'ok position '.(int)$position.' for attribute '.(int)$pos[2].'\r\n'; - else - echo '{"hasError" : true, "errors" : "Can not update the '.(int)$id_attribute.' attribute to position '.(int)$position.' "}'; - else - echo '{"hasError" : true, "errors" : "The ('.(int)$id_attribute.') attribute cannot be loaded"}'; + if ((isset($pos[1]) && isset($pos[2])) && (int)$pos[2] === $id_attribute) { + if ($attribute = new Attribute((int)$pos[2])) { + if (isset($position) && $attribute->updatePosition($way, $position)) { + echo 'ok position '.(int)$position.' for attribute '.(int)$pos[2].'\r\n'; + } else { + echo '{"hasError" : true, "errors" : "Can not update the '.(int)$id_attribute.' attribute to position '.(int)$position.' "}'; + } + } else { + echo '{"hasError" : true, "errors" : "The ('.(int)$id_attribute.') attribute cannot be loaded"}'; + } - break; - } - } - - } + break; + } + } + } + } } diff --git a/controllers/admin/AdminBackupController.php b/controllers/admin/AdminBackupController.php index c4a6b238..33483f4b 100644 --- a/controllers/admin/AdminBackupController.php +++ b/controllers/admin/AdminBackupController.php @@ -29,284 +29,284 @@ */ class AdminBackupControllerCore extends AdminController { - /** @var string The field we are sorting on */ - protected $sort_by = 'date'; + /** @var string The field we are sorting on */ + protected $sort_by = 'date'; - public function __construct() - { - $this->bootstrap = true; - $this->table = 'backup'; - $this->className = 'PrestaShopBackup'; - $this->identifier = 'filename'; - parent::__construct(); + public function __construct() + { + $this->bootstrap = true; + $this->table = 'backup'; + $this->className = 'PrestaShopBackup'; + $this->identifier = 'filename'; + parent::__construct(); - $this->fields_list = array ( - 'date' => array('title' => $this->l('Date'), 'type' => 'datetime'), - 'age' => array('title' => $this->l('Age')), - 'filename' => array('title' => $this->l('File name')), - 'filesize' => array('title' => $this->l('File size'), 'class' => 'fixed-width-sm') - ); + $this->fields_list = array( + 'date' => array('title' => $this->l('Date'), 'type' => 'datetime', 'class' => 'fixed-width-lg', 'orderby' => false, 'search' => false), + 'age' => array('title' => $this->l('Age'), 'orderby' => false, 'search' => false), + 'filename' => array('title' => $this->l('File name'), 'orderby' => false, 'search' => false), + 'filesize' => array('title' => $this->l('File size'), 'class' => 'fixed-width-sm', 'orderby' => false, 'search' => false) + ); - $this->bulk_actions = array('delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), 'icon' => 'icon-trash') - ); + $this->bulk_actions = array('delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), 'icon' => 'icon-trash') + ); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Backup options'), - 'fields' => array( - 'PS_BACKUP_ALL' => array( - 'title' => $this->l('Ignore statistics tables'), - 'desc' => $this->l('Drop existing tables during import.').' + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Backup options'), + 'fields' => array( + 'PS_BACKUP_ALL' => array( + 'title' => $this->l('Ignore statistics tables'), + 'desc' => $this->l('Drop existing tables during import.').' <br />'._DB_PREFIX_.'connections, '._DB_PREFIX_.'connections_page, '._DB_PREFIX_ - .'connections_source, '._DB_PREFIX_.'guest, '._DB_PREFIX_.'statssearch', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_BACKUP_DROP_TABLE' => array( - 'title' => $this->l('Drop existing tables during import'), - 'hint' => array( - $this->l('If enabled, the backup script will drop your tables prior to restoring data.'), - $this->l('(ie. "DROP TABLE IF EXISTS")'), - ), - 'cast' => 'intval', - 'type' => 'bool' - ) - ), - 'submit' => array('title' => $this->l('Save')) - ), - ); - } + .'connections_source, '._DB_PREFIX_.'guest, '._DB_PREFIX_.'statssearch', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_BACKUP_DROP_TABLE' => array( + 'title' => $this->l('Drop existing tables during import'), + 'hint' => array( + $this->l('If enabled, the backup script will drop your tables prior to restoring data.'), + $this->l('(ie. "DROP TABLE IF EXISTS")'), + ), + 'cast' => 'intval', + 'type' => 'bool' + ) + ), + 'submit' => array('title' => $this->l('Save')) + ), + ); + } - public function renderList() - { - $this->addRowAction('view'); - $this->addRowAction('delete'); + public function renderList() + { + $this->addRowAction('view'); + $this->addRowAction('delete'); - return parent::renderList(); - } + return parent::renderList(); + } - public function renderView() - { - if (!($object = $this->loadObject())) - $this->errors[] = Tools::displayError('The object could not be loaded.'); + public function renderView() + { + if (!($object = $this->loadObject())) { + $this->errors[] = Tools::displayError('The object could not be loaded.'); + } - if ($object->id) - $this->tpl_view_vars = array('url_backup' => $object->getBackupURL()); - elseif ($object->error) - { - $this->errors[] = $object->error; - $this->tpl_view_vars = array('errors' => $this->errors); - } + if ($object->id) { + $this->tpl_view_vars = array('url_backup' => $object->getBackupURL()); + } elseif ($object->error) { + $this->errors[] = $object->error; + $this->tpl_view_vars = array('errors' => $this->errors); + } - return parent::renderView(); - } + return parent::renderView(); + } - public function initViewDownload() - { - $this->tpl_folder = $this->tpl_folder.'download/'; + public function initViewDownload() + { + $this->tpl_folder = $this->tpl_folder.'download/'; - return parent::renderView(); - } + return parent::renderView(); + } - public function initToolbar() - { - switch ($this->display) - { - case 'add': - case 'edit': - case 'view': - $this->toolbar_btn['cancel'] = array( - 'href' => self::$currentIndex.'&token='.$this->token, - 'desc' => $this->l('Cancel') - ); - break; - case 'options': - $this->toolbar_btn['save'] = array( - 'href' => '#', - 'desc' => $this->l('Save') - ); - break; - } - } + public function initToolbar() + { + switch ($this->display) { + case 'add': + case 'edit': + case 'view': + $this->toolbar_btn['cancel'] = array( + 'href' => self::$currentIndex.'&token='.$this->token, + 'desc' => $this->l('Cancel') + ); + break; + case 'options': + $this->toolbar_btn['save'] = array( + 'href' => '#', + 'desc' => $this->l('Save') + ); + break; + } + } - public function initContent() - { - if ($this->display == 'add') - $this->display = 'list'; + public function initContent() + { + if ($this->display == 'add') { + $this->display = 'list'; + } - return parent::initContent(); - } + return parent::initContent(); + } - /** - * Load class object using identifier in $_GET (if possible) - * otherwise return an empty object - * This method overrides the one in AdminTab because AdminTab assumes the id is a UnsignedInt - * "Backups" Directory in admin directory must be writeable (CHMOD 777) - * @param bool $opt Return an empty object if load fail - * @return object - */ - protected function loadObject($opt = false) - { - if (($id = Tools::getValue($this->identifier)) && PrestaShopBackup::backupExist($id)) - return new $this->className($id); + /** + * Load class object using identifier in $_GET (if possible) + * otherwise return an empty object + * This method overrides the one in AdminTab because AdminTab assumes the id is a UnsignedInt + * "Backups" Directory in admin directory must be writeable (CHMOD 777) + * @param bool $opt Return an empty object if load fail + * @return object + */ + protected function loadObject($opt = false) + { + if (($id = Tools::getValue($this->identifier)) && PrestaShopBackup::backupExist($id)) { + return new $this->className($id); + } - $obj = new $this->className(); - $obj->error = Tools::displayError('The backup file does not exist'); + $obj = new $this->className(); + $obj->error = Tools::displayError('The backup file does not exist'); - return $obj; - } + return $obj; + } - public function postProcess() - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } - /* PrestaShop demo mode*/ + public function postProcess() + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } + /* PrestaShop demo mode*/ - // Test if the backup dir is writable - if (!is_writable(PrestaShopBackup::getBackupPath())) - $this->warnings[] = $this->l('The "Backups" directory located in the admin directory must be writable (CHMOD 755 / 777).'); - elseif ($this->display == 'add') - { - if (($object = $this->loadObject())) - { - if (!$object->add()) - $this->errors[] = $object->error; - else - $this->context->smarty->assign(array( - 'conf' => $this->l('It appears the backup was successful, however you must download and carefully verify the backup file before proceeding.'), - 'backup_url' => $object->getBackupURL(), - 'backup_weight' => number_format((filesize($object->id) * 0.000001), 2, '.', '') - )); - } - } + // Test if the backup dir is writable + if (!is_writable(PrestaShopBackup::getBackupPath())) { + $this->warnings[] = $this->l('The "Backups" directory located in the admin directory must be writable (CHMOD 755 / 777).'); + } elseif ($this->display == 'add') { + if (($object = $this->loadObject())) { + if (!$object->add()) { + $this->errors[] = $object->error; + } else { + $this->context->smarty->assign(array( + 'conf' => $this->l('It appears the backup was successful, however you must download and carefully verify the backup file before proceeding.'), + 'backup_url' => $object->getBackupURL(), + 'backup_weight' => number_format((filesize($object->id) * 0.000001), 2, '.', '') + )); + } + } + } - parent::postProcess(); - } + parent::postProcess(); + } - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, - $id_lang_shop = null) - { - if (!Validate::isTableOrIdentifier($this->table)) - die('filter is corrupted'); - if (empty($order_by)) - $order_by = Tools::getValue($this->table.'Orderby', $this->_defaultOrderBy); - if (empty($order_way)) - $order_way = Tools::getValue($this->table.'Orderway', 'ASC'); + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, + $id_lang_shop = null) + { + if (!Validate::isTableOrIdentifier($this->table)) { + die('filter is corrupted'); + } - // Try and obtain getList arguments from $_GET - $order_by = Tools::getValue($this->table.'Orderby'); - $order_way = Tools::getValue($this->table.'Orderway'); + if (empty($order_by)) { + $order_by = Tools::getValue($this->table.'Orderby', $this->_defaultOrderBy); + } - // Validate the orderBy and orderWay fields - switch ($order_by) - { - case 'filename': - case 'filesize': - case 'date': - case 'age': - break; - default: - $order_by = 'date'; - } - switch ($order_way) - { - case 'asc': - case 'desc': - break; - default: - $order_way = 'desc'; - } - if (empty($limit)) - $limit = ((!isset($this->context->cookie->{$this->table.'_pagination'})) ? $this->_pagination[0] : $limit = - $this->context->cookie->{$this->table.'_pagination'}); - $limit = (int)Tools::getValue('pagination', $limit); - $this->context->cookie->{$this->table.'_pagination'} = $limit; + if (empty($order_way)) { + $order_way = Tools::getValue($this->table.'Orderway', 'ASC'); + } - /* Determine offset from current page */ - if (!empty($_POST['submitFilter'.$this->table]) && is_numeric($_POST['submitFilter'.$this->table])) - $start = (int)$_POST['submitFilter'.$this->table] - 1 * $limit; - $this->_lang = (int)$id_lang; - $this->_orderBy = $order_by; - $this->_orderWay = strtoupper($order_way); - $this->_list = array(); + // Try and obtain getList arguments from $_GET + $order_by = Tools::getValue($this->table.'Orderby'); + $order_way = Tools::getValue($this->table.'Orderway'); - // Find all the backups - $dh = @opendir(PrestaShopBackup::getBackupPath()); + // Validate the orderBy and orderWay fields + switch ($order_by) { + case 'filename': + case 'filesize': + case 'date': + case 'age': + break; + default: + $order_by = 'date'; + } + switch ($order_way) { + case 'asc': + case 'desc': + break; + default: + $order_way = 'desc'; + } + if (empty($limit)) { + $limit = ((!isset($this->context->cookie->{$this->table.'_pagination'})) ? $this->_pagination[0] : $limit = + $this->context->cookie->{$this->table.'_pagination'}); + } + $limit = (int)Tools::getValue('pagination', $limit); + $this->context->cookie->{$this->table.'_pagination'} = $limit; - if ($dh === false) - { - $this->errors[] = Tools::displayError('Unable to open your backup directory'); - return; - } - while (($file = readdir($dh)) !== false) - { - if (preg_match('/^([_a-zA-Z0-9\-]*[\d]+-[a-z\d]+)\.sql(\.gz|\.bz2)?$/', $file, $matches) == 0) - continue; - $timestamp = (int)$matches[1]; - $date = date('Y-m-d H:i:s', $timestamp); - $age = time() - $timestamp; - if ($age < 3600) - $age = '< 1 '.$this->l('Hour', 'AdminTab', false, false); - elseif ($age < 86400) - { - $age = floor($age / 3600); - $age = $age.' '.(($age == 1) ? $this->l('Hour', 'AdminTab', false, false) : - $this->l('Hours', 'AdminTab', false, false)); - } - else - { - $age = floor($age / 86400); - $age = $age.' '.(($age == 1) ? $this->l('Day') : $this->l('Days', 'AdminTab', false, false)); - } - $size = filesize(PrestaShopBackup::getBackupPath($file)); - $this->_list[] = array( - 'filename' => $file, - 'age' => $age, - 'date' => $date, - 'filesize' => number_format($size / 1000, 2).' Kb', - 'timestamp' => $timestamp, - 'filesize_sort' => $size, - ); - } - closedir($dh); - $this->_listTotal = count($this->_list); + /* Determine offset from current page */ + if (!empty($_POST['submitFilter'.$this->list_id]) && is_numeric($_POST['submitFilter'.$this->list_id])) { + $start = (int)$_POST['submitFilter'.$this->list_id] - 1 * $limit; + } - // Sort the _list based on the order requirements - switch ($this->_orderBy) - { - case 'filename': - $this->sort_by = 'filename'; - $sorter = 'strSort'; - break; - case 'filesize': - $this->sort_by = 'filesize_sort'; - $sorter = 'intSort'; - break; - case 'age': - case 'date': - $this->sort_by = 'timestamp'; - $sorter = 'intSort'; - break; - } - usort($this->_list, array($this, $sorter)); - $this->_list = array_slice($this->_list, $start, $limit); - } + $this->_lang = (int)$id_lang; + $this->_orderBy = $order_by; + $this->_orderWay = strtoupper($order_way); + $this->_list = array(); - public function intSort($a, $b) - { - return $this->_orderWay == 'ASC' ? $a[$this->sort_by] - $b[$this->sort_by] : - $b[$this->sort_by] - $a[$this->sort_by]; - } + // Find all the backups + $dh = @opendir(PrestaShopBackup::getBackupPath()); - public function strSort($a, $b) - { - return $this->_orderWay == 'ASC' ? strcmp($a[$this->sort_by], $b[$this->sort_by]) : - strcmp($b[$this->sort_by], $a[$this->sort_by]); - } + if ($dh === false) { + $this->errors[] = Tools::displayError('Unable to open your backup directory'); + return; + } + while (($file = readdir($dh)) !== false) { + if (preg_match('/^([_a-zA-Z0-9\-]*[\d]+-[a-z\d]+)\.sql(\.gz|\.bz2)?$/', $file, $matches) == 0) { + continue; + } + $timestamp = (int)$matches[1]; + $date = date('Y-m-d H:i:s', $timestamp); + $age = time() - $timestamp; + if ($age < 3600) { + $age = '< 1 '.$this->l('Hour', 'AdminTab', false, false); + } elseif ($age < 86400) { + $age = floor($age / 3600); + $age = $age.' '.(($age == 1) ? $this->l('Hour', 'AdminTab', false, false) : + $this->l('Hours', 'AdminTab', false, false)); + } else { + $age = floor($age / 86400); + $age = $age.' '.(($age == 1) ? $this->l('Day') : $this->l('Days', 'AdminTab', false, false)); + } + $size = filesize(PrestaShopBackup::getBackupPath($file)); + $this->_list[] = array( + 'filename' => $file, + 'age' => $age, + 'date' => $date, + 'filesize' => number_format($size / 1000, 2).' Kb', + 'timestamp' => $timestamp, + 'filesize_sort' => $size, + ); + } + closedir($dh); + $this->_listTotal = count($this->_list); + + // Sort the _list based on the order requirements + switch ($this->_orderBy) { + case 'filename': + $this->sort_by = 'filename'; + $sorter = 'strSort'; + break; + case 'filesize': + $this->sort_by = 'filesize_sort'; + $sorter = 'intSort'; + break; + case 'age': + case 'date': + $this->sort_by = 'timestamp'; + $sorter = 'intSort'; + break; + } + usort($this->_list, array($this, $sorter)); + $this->_list = array_slice($this->_list, $start, $limit); + } + + public function intSort($a, $b) + { + return $this->_orderWay == 'ASC' ? $a[$this->sort_by] - $b[$this->sort_by] : + $b[$this->sort_by] - $a[$this->sort_by]; + } + + public function strSort($a, $b) + { + return $this->_orderWay == 'ASC' ? strcmp($a[$this->sort_by], $b[$this->sort_by]) : + strcmp($b[$this->sort_by], $a[$this->sort_by]); + } } diff --git a/controllers/admin/AdminCarrierWizardController.php b/controllers/admin/AdminCarrierWizardController.php index 2253311b..d7eb8f70 100644 --- a/controllers/admin/AdminCarrierWizardController.php +++ b/controllers/admin/AdminCarrierWizardController.php @@ -29,956 +29,944 @@ */ class AdminCarrierWizardControllerCore extends AdminController { - protected $wizard_access; - - public function __construct() - { - $this->bootstrap = true; - $this->display = 'view'; - $this->table = 'carrier'; - $this->identifier = 'id_carrier'; - $this->className = 'Carrier'; - $this->lang = false; - $this->deleted = true; - $this->step_number = 0; - $this->type_context = Shop::getContext(); - $this->old_context = Context::getContext(); - $this->multishop_context = Shop::CONTEXT_ALL; - $this->context = Context::getContext(); - - $this->fieldImageSettings = array( - 'name' => 'logo', - 'dir' => 's' - ); - - parent::__construct(); - - $this->tabAccess = Profile::getProfileAccess($this->context->employee->id_profile, Tab::getIdFromClassName('AdminCarriers')); - } - - public function setMedia() - { - parent::setMedia(); - $this->addJqueryPlugin('smartWizard'); - $this->addJqueryPlugin('typewatch'); - $this->addJs(_PS_JS_DIR_.'admin/carrier_wizard.js'); - } - - public function initWizard() - { - $this->wizard_steps = array( - 'name' => 'carrier_wizard', - 'steps' => array( - array( - 'title' => $this->l('General settings'), - ), - array( - 'title' => $this->l('Shipping locations and costs'), - ), - array( - 'title' => $this->l('Size, weight, and group access'), - ), - array( - 'title' => $this->l('Summary'), - ), - - )); - - if (Shop::isFeatureActive()) - { - $multistore_step = array( - array( - 'title' => $this->l('MultiStore'), - ) - ); - array_splice($this->wizard_steps['steps'], 1, 0, $multistore_step); - } - } - - public function renderView() - { - $this->initWizard(); - - if (Tools::getValue('id_carrier') && $this->tabAccess['edit']) - $carrier = $this->loadObject(); - elseif ($this->tabAccess['add']) - $carrier = new Carrier(); - - if ((!$this->tabAccess['edit'] && Tools::getValue('id_carrier')) || (!$this->tabAccess['add'] && !Tools::getValue('id_carrier'))) - { - $this->errors[] = Tools::displayError('You do not have permission to use this wizard.'); - return ; - } - - $currency = $this->getActualCurrency(); - - $this->tpl_view_vars = array( - 'currency_sign' => $currency->sign, - 'PS_WEIGHT_UNIT' => Configuration::get('PS_WEIGHT_UNIT'), - 'enableAllSteps' => Validate::isLoadedObject($carrier), - 'wizard_steps' => $this->wizard_steps, - 'validate_url' => $this->context->link->getAdminLink('AdminCarrierWizard'), - 'carrierlist_url' => $this->context->link->getAdminLink('AdminCarriers').'&conf='.((int)Validate::isLoadedObject($carrier) ? 4 : 3), - 'multistore_enable' => Shop::isFeatureActive(), - 'wizard_contents' => array( - 'contents' => array( - 0 => $this->renderStepOne($carrier), - 1 => $this->renderStepThree($carrier), - 2 => $this->renderStepFour($carrier), - 3 => $this->renderStepFive($carrier), - )), - 'labels' => array('next' => $this->l('Next'), 'previous' => $this->l('Previous'), 'finish' => $this->l('Finish')) - ); - - - if (Shop::isFeatureActive()) - array_splice($this->tpl_view_vars['wizard_contents']['contents'], 1, 0, array(0 => $this->renderStepTwo($carrier))); - - $this->context->smarty->assign(array( - 'carrier_logo' => (Validate::isLoadedObject($carrier) && file_exists(_PS_SHIP_IMG_DIR_.$carrier->id.'.jpg') ? _THEME_SHIP_DIR_.$carrier->id.'.jpg' : false), - )); - - $this->context->smarty->assign(array( - 'logo_content' => $this->createTemplate('logo.tpl')->fetch() - )); - - $this->addjQueryPlugin(array('ajaxfileupload')); - - return parent::renderView(); - } - - public function initBreadcrumbs($tab_id = null,$tabs = null) - { - if (Tools::getValue('id_carrier')) - $this->display = 'edit'; - else - $this->display = 'add'; - - parent::initBreadcrumbs((int)Tab::getIdFromClassName('AdminCarriers')); - - $this->display = 'view'; - } - - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); - - $this->page_header_toolbar_btn['cancel'] = array( - 'href' => $this->context->link->getAdminLink('AdminCarriers'), - 'desc' => $this->l('Cancel', null, null, false) - ); - } - - public function renderStepOne($carrier) - { - $this->fields_form = array( - 'form' => array( - 'id_form' => 'step_carrier_general', - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Carrier name'), - 'name' => 'name', - 'required' => true, - 'hint' => array( - sprintf($this->l('Allowed characters: letters, spaces and "%s".'), '().-'), - $this->l('The carrier\'s name will be displayed during checkout.'), - $this->l('For in-store pickup, enter 0 to replace the carrier name with your shop name.') - ) - ), - array( - 'type' => 'text', - 'label' => $this->l('Transit time'), - 'name' => 'delay', - 'lang' => true, - 'required' => true, - 'maxlength' => 128, - 'hint' => $this->l('The estimated delivery time will be displayed during checkout.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Speed grade'), - 'name' => 'grade', - 'required' => false, - 'size' => 1, - 'hint' => $this->l('Enter "0" for a longest shipping delay, or "9" for the shortest shipping delay.') - ), - array( - 'type' => 'logo', - 'label' => $this->l('Logo'), - 'name' => 'logo' - ), - array( - 'type' => 'text', - 'label' => $this->l('Tracking URL'), - 'name' => 'url', - 'hint' => $this->l('Delivery tracking URL: Type \'@\' where the tracking number should appear. It will be automatically replaced by the tracking number.'), - 'desc' => $this->l('For example: \'http://exampl.com/track.php?num=@\' with \'@\' where the tracking number should appear.') - ), - )), - ); - - $tpl_vars = array('max_image_size' => (int)Configuration::get('PS_PRODUCT_PICTURE_MAX_SIZE') / 1024 / 1024); - $fields_value = $this->getStepOneFieldsValues($carrier); - return $this->renderGenericForm(array('form' => $this->fields_form), $fields_value, $tpl_vars); - } - - public function renderStepTwo($carrier) - { - $this->fields_form = array( - 'form' => array( - 'id_form' => 'step_carrier_shops', - 'force' => true, - 'input' => array( - array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ), - )) - ); - $fields_value = $this->getStepTwoFieldsValues($carrier); - - return $this->renderGenericForm(array('form' => $this->fields_form), $fields_value); - } - - public function renderStepThree($carrier) - { - $this->fields_form = array( - 'form' => array( - 'id_form' => 'step_carrier_ranges', - 'input' => array( - 'shipping_handling' => array( - 'type' => 'switch', - 'label' => $this->l('Add handling costs'), - 'name' => 'shipping_handling', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'shipping_handling_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'shipping_handling_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Include the handling costs (as set in Shipping > Preferences) in the final carrier price.') - ), - 'is_free' => array( - 'type' => 'switch', - 'label' => $this->l('Free shipping'), - 'name' => 'is_free', - 'required' => false, - 'class' => 't', - 'values' => array( - array( - 'id' => 'is_free_on', - 'value' => 1, - 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('No').'" title="'.$this->l('No').'" />' - ), - array( - 'id' => 'is_free_off', - 'value' => 0, - 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Yes').'" title="'.$this->l('Yes').'" />' - ) - ), - ), - 'shipping_method' => array( - 'type' => 'radio', - 'label' => $this->l('Billing'), - 'name' => 'shipping_method', - 'required' => false, - 'class' => 't', - 'br' => true, - 'values' => array( - array( - 'id' => 'billing_price', - 'value' => Carrier::SHIPPING_METHOD_PRICE, - 'label' => $this->l('According to total price.') - ), - array( - 'id' => 'billing_weight', - 'value' => Carrier::SHIPPING_METHOD_WEIGHT, - 'label' => $this->l('According to total weight.') - ) - ) - ), - 'id_tax_rules_group' => array( - 'type' => 'select', - 'label' => $this->l('Tax'), - 'name' => 'id_tax_rules_group', - 'options' => array( - 'query' => TaxRulesGroup::getTaxRulesGroups(true), - 'id' => 'id_tax_rules_group', - 'name' => 'name', - 'default' => array( - 'label' => $this->l('No tax'), - 'value' => 0 - ) - ) - ), - 'range_behavior' => array( - 'type' => 'select', - 'label' => $this->l('Out-of-range behavior'), - 'name' => 'range_behavior', - 'options' => array( - 'query' => array( - array( - 'id' => 0, - 'name' => $this->l('Apply the cost of the highest defined range') - ), - array( - 'id' => 1, - 'name' => $this->l('Disable carrier') - ) - ), - 'id' => 'id', - 'name' => 'name' - ), - 'hint' => $this->l('Out-of-range behavior occurs when no defined range matches the customer\'s cart (e.g. when the weight of the cart is greater than the highest weight limit defined by the weight ranges).') - ), - 'zones' => array( - 'type' => 'zone', - 'name' => 'zones' - ) - ), - - )); - - if (Configuration::get('PS_ATCP_SHIPWRAP')) - { - unset($this->fields_form['form']['input']['id_tax_rules_group']); - } - - $tpl_vars = array(); - $tpl_vars['PS_WEIGHT_UNIT'] = Configuration::get('PS_WEIGHT_UNIT'); - - $currency = $this->getActualCurrency(); - - $tpl_vars['currency_sign'] = $currency->sign; - - $fields_value = $this->getStepThreeFieldsValues($carrier); - - $this->getTplRangesVarsAndValues($carrier, $tpl_vars, $fields_value); - return $this->renderGenericForm(array('form' => $this->fields_form), $fields_value, $tpl_vars); - } - - /** - * @param Carrier $carrier - * - * @return string - */ - public function renderStepFour($carrier) - { - $this->fields_form = array( - 'form' => array( - 'id_form' => 'step_carrier_conf', - 'input' => array( - array( - 'type' => 'text', - 'label' => sprintf($this->l('Maximum package width (%s)'), Configuration::get('PS_DIMENSION_UNIT')), - 'name' => 'max_width', - 'required' => false, - 'hint' => $this->l('Maximum width managed by this carrier. Set the value to "0", or leave this field blank to ignore.').' '.$this->l('The value must be an integer.') - ), - array( - 'type' => 'text', - 'label' => sprintf($this->l('Maximum package height (%s)'), Configuration::get('PS_DIMENSION_UNIT')), - 'name' => 'max_height', - 'required' => false, - 'hint' => $this->l('Maximum height managed by this carrier. Set the value to "0", or leave this field blank to ignore.').' '.$this->l('The value must be an integer.') - ), - array( - 'type' => 'text', - 'label' => sprintf($this->l('Maximum package depth (%s)'), Configuration::get('PS_DIMENSION_UNIT')), - 'name' => 'max_depth', - 'required' => false, - 'hint' => $this->l('Maximum depth managed by this carrier. Set the value to "0", or leave this field blank to ignore.').' '.$this->l('The value must be an integer.') - ), - array( - 'type' => 'text', - 'label' => sprintf($this->l('Maximum package weight (%s)'), Configuration::get('PS_WEIGHT_UNIT')), - 'name' => 'max_weight', - 'required' => false, - 'hint' => $this->l('Maximum weight managed by this carrier. Set the value to "0", or leave this field blank to ignore.') - ), - array( - 'type' => 'group', - 'label' => $this->l('Group access'), - 'name' => 'groupBox', - 'values' => Group::getGroups(Context::getContext()->language->id), - 'hint' => $this->l('Mark the groups that are allowed access to this carrier.') - ) - ) - )); - - $fields_value = $this->getStepFourFieldsValues($carrier); - - // Added values of object Group - $carrier_groups = $carrier->getGroups(); - $carrier_groups_ids = array(); - if (is_array($carrier_groups)) - foreach ($carrier_groups as $carrier_group) - $carrier_groups_ids[] = $carrier_group['id_group']; - - $groups = Group::getGroups($this->context->language->id); - - foreach ($groups as $group) - $fields_value['groupBox_'.$group['id_group']] = Tools::getValue('groupBox_'.$group['id_group'], (in_array($group['id_group'], $carrier_groups_ids) || empty($carrier_groups_ids) && !$carrier->id)); - - return $this->renderGenericForm(array('form' => $this->fields_form), $fields_value); - } - - public function renderStepFive($carrier) - { - $this->fields_form = array( - 'form' => array( - 'id_form' => 'step_carrier_summary', - 'input' => array( - array( - 'type' => 'switch', - 'label' => $this->l('Enabled'), - 'name' => 'active', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1 - ), - array( - 'id' => 'active_off', - 'value' => 0 - ) - ), - 'hint' => $this->l('Enable the carrier in the front office.') - ) - ) - )); - - $template = $this->createTemplate('controllers/carrier_wizard/summary.tpl'); - - $fields_value = $this->getStepFiveFieldsValues($carrier); - - $active_form = $this->renderGenericForm(array('form' => $this->fields_form), $fields_value); - - $active_form = str_replace(array('<fieldset id="fieldset_form">', '</fieldset>'), '', $active_form); - - $template->assign('active_form', $active_form); - - return $template->fetch('controllers/carrier_wizard/summary.tpl'); - } - - /** - * @param Carrier $carrier - * @param array $tpl_vars - * @param array $fields_value - */ - protected function getTplRangesVarsAndValues($carrier, &$tpl_vars, &$fields_value) - { - $tpl_vars['zones'] = Zone::getZones(false); - $carrier_zones = $carrier->getZones(); - $carrier_zones_ids = array(); - if (is_array($carrier_zones)) - foreach ($carrier_zones as $carrier_zone) - $carrier_zones_ids[] = $carrier_zone['id_zone']; - - $range_table = $carrier->getRangeTable(); - $shipping_method = $carrier->getShippingMethod(); - - $zones = Zone::getZones(false); - foreach ($zones as $zone) - $fields_value['zones'][$zone['id_zone']] = Tools::getValue('zone_'.$zone['id_zone'], (in_array($zone['id_zone'], $carrier_zones_ids))); - - if ($shipping_method == Carrier::SHIPPING_METHOD_FREE) - { - $range_obj = $carrier->getRangeObject($carrier->shipping_method); - $price_by_range = array(); - } - else - { - $range_obj = $carrier->getRangeObject(); - $price_by_range = Carrier::getDeliveryPriceByRanges($range_table, (int)$carrier->id); - } - - foreach ($price_by_range as $price) - $tpl_vars['price_by_range'][$price['id_'.$range_table]][$price['id_zone']] = $price['price']; - - $tmp_range = $range_obj->getRanges((int)$carrier->id); - $tpl_vars['ranges'] = array(); - if ($shipping_method != Carrier::SHIPPING_METHOD_FREE) - foreach ($tmp_range as $id => $range) - { - $tpl_vars['ranges'][$range['id_'.$range_table]] = $range; - $tpl_vars['ranges'][$range['id_'.$range_table]]['id_range'] = $range['id_'.$range_table]; - } - - // init blank range - if (!count($tpl_vars['ranges'])) - $tpl_vars['ranges'][] = array('id_range' => 0, 'delimiter1' => 0, 'delimiter2' => 0); - } - - public function renderGenericForm($fields_form, $fields_value, $tpl_vars = array()) - { - - $helper = new HelperForm(); - $helper->show_toolbar = false; - $helper->table = $this->table; - $lang = new Language((int)Configuration::get('PS_LANG_DEFAULT')); - $helper->default_form_language = $lang->id; - $helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') ? Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') : 0; - $this->fields_form = array(); - $helper->id = (int)Tools::getValue('id_carrier'); - $helper->identifier = $this->identifier; - $helper->tpl_vars = array_merge(array( - 'fields_value' => $fields_value, - 'languages' => $this->getLanguages(), - 'id_language' => $this->context->language->id - ), $tpl_vars); - $helper->override_folder = 'carrier_wizard/'; - - return $helper->generateForm($fields_form); - } - - public function getStepOneFieldsValues($carrier) - { - return array( - 'id_carrier' => $this->getFieldValue($carrier, 'id_carrier'), - 'name' => $this->getFieldValue($carrier, 'name'), - 'delay' => $this->getFieldValue($carrier, 'delay'), - 'grade' => $this->getFieldValue($carrier, 'grade'), - 'url' => $this->getFieldValue($carrier, 'url'), - ); - } - - public function getStepTwoFieldsValues($carrier) - { - return array('shop' => $this->getFieldValue($carrier, 'shop')); - - } - - public function getStepThreeFieldsValues($carrier) - { - $id_tax_rules_group = (is_object($this->object) && !$this->object->id) ? Carrier::getIdTaxRulesGroupMostUsed() : $this->getFieldValue($carrier, 'id_tax_rules_group'); - - $shipping_handling = (is_object($this->object) && !$this->object->id) ? 0 : $this->getFieldValue($carrier, 'shipping_handling'); - - return array( - 'is_free' => $this->getFieldValue($carrier, 'is_free'), - 'id_tax_rules_group' => (int)$id_tax_rules_group, - 'shipping_handling' => $shipping_handling, - 'shipping_method' => $this->getFieldValue($carrier, 'shipping_method'), - 'range_behavior' => $this->getFieldValue($carrier, 'range_behavior'), - 'zones' => $this->getFieldValue($carrier, 'zones'), - ); - } - - public function getStepFourFieldsValues($carrier) - { - return array( - 'range_behavior' => $this->getFieldValue($carrier, 'range_behavior'), - 'max_height' => $this->getFieldValue($carrier, 'max_height'), - 'max_width' => $this->getFieldValue($carrier, 'max_width'), - 'max_depth' => $this->getFieldValue($carrier, 'max_depth'), - 'max_weight' => $this->getFieldValue($carrier, 'max_weight'), - 'group' => $this->getFieldValue($carrier, 'group'), - ); - } - - public function getStepFiveFieldsValues($carrier) - { - return array('active' => $this->getFieldValue($carrier, 'active')); - } - - public function ajaxProcessChangeRanges() - { - if ((Validate::isLoadedObject($this->object) && !$this->tabAccess['edit']) || !$this->tabAccess['add']) - { - $this->errors[] = Tools::displayError('You do not have permission to use this wizard.'); - return; - } - if ((!(int)$shipping_method = Tools::getValue('shipping_method')) || !in_array($shipping_method, array(Carrier::SHIPPING_METHOD_PRICE, Carrier::SHIPPING_METHOD_WEIGHT))) - return ; - - $carrier = $this->loadObject(true); - $carrier->shipping_method = $shipping_method; - - $tpl_vars = array(); - $fields_value = $this->getStepThreeFieldsValues($carrier); - $this->getTplRangesVarsAndValues($carrier, $tpl_vars, $fields_value); - $template = $this->createTemplate('controllers/carrier_wizard/helpers/form/form_ranges.tpl'); - $template->assign($tpl_vars); - $template->assign('change_ranges', 1); - - $template->assign('fields_value', $fields_value); - $template->assign('input', array('type' => 'zone', 'name' => 'zones' )); - - $currency = $this->getActualCurrency(); - - $template->assign('currency_sign', $currency->sign); - $template->assign('PS_WEIGHT_UNIT', Configuration::get('PS_WEIGHT_UNIT')); - - die($template->fetch()); - } - - protected function validateForm($die = true) - { - $step_number = (int)Tools::getValue('step_number'); - $return = array('has_error' => false); - - if (!$this->tabAccess['edit']) - $this->errors[] = Tools::displayError('You do not have permission to use this wizard.'); - else - { - if (Shop::isFeatureActive() && $step_number == 2) - { - if (!Tools::getValue('checkBoxShopAsso_carrier')) - { - $return['has_error'] = true; - $return['errors'][] = $this->l('You must choose at least one shop or group shop.'); - } - } - else - $this->validateRules(); - } - - if (count($this->errors)) - { - $return['has_error'] = true; - $return['errors'] = $this->errors; - } - if (count($this->errors) || $die) - die(Tools::jsonEncode($return)); - - } - - - public function ajaxProcessValidateStep() - { - $this->validateForm(true); - } - - public function processRanges($id_carrier) - { - if (!$this->tabAccess['edit'] || !$this->tabAccess['add']) - { - $this->errors[] = Tools::displayError('You do not have permission to use this wizard.'); - return; - } - - $carrier = new Carrier((int)$id_carrier); - if (!Validate::isLoadedObject($carrier)) - return false; - - $range_inf = Tools::getValue('range_inf'); - $range_sup = Tools::getValue('range_sup'); - $range_type = Tools::getValue('shipping_method'); - - $fees = Tools::getValue('fees'); - - $carrier->deleteDeliveryPrice($carrier->getRangeTable()); - if ($range_type != Carrier::SHIPPING_METHOD_FREE) - { - foreach ($range_inf as $key => $delimiter1) - { - if (!isset($range_sup[$key])) - continue; - $add_range = true; - if ($range_type == Carrier::SHIPPING_METHOD_WEIGHT) - { - if (!RangeWeight::rangeExist((int)$carrier->id, (float)$delimiter1, (float)$range_sup[$key])) - $range = new RangeWeight(); - else - { - $range = new RangeWeight((int)$key); - $add_range = false; - } - } - - if ($range_type == Carrier::SHIPPING_METHOD_PRICE) - { - if (!RangePrice::rangeExist((int)$carrier->id, (float)$delimiter1, (float)$range_sup[$key])) - $range = new RangePrice(); - else - { - $range = new RangePrice((int)$key); - $add_range = false; - } - } - if ($add_range) - { - $range->id_carrier = (int)$carrier->id; - $range->delimiter1 = (float)$delimiter1; - $range->delimiter2 = (float)$range_sup[$key]; - $range->save(); - } - - if (!Validate::isLoadedObject($range)) - return false; - $price_list = array(); - if (is_array($fees) && count($fees)) - { - foreach ($fees as $id_zone => $fee) - { - $price_list[] = array( - 'id_range_price' => ($range_type == Carrier::SHIPPING_METHOD_PRICE ? (int)$range->id : null), - 'id_range_weight' => ($range_type == Carrier::SHIPPING_METHOD_WEIGHT ? (int)$range->id : null), - 'id_carrier' => (int)$carrier->id, - 'id_zone' => (int)$id_zone, - 'price' => isset($fee[$key]) ? (float)$fee[$key] : 0, - ); - } - } - - if (count($price_list) && !$carrier->addDeliveryPrice($price_list, true)) - return false; - } - } - return true; - } - - public function ajaxProcessUploadLogo() - { - if (!$this->tabAccess['edit']) - die('<return result="error" message="'.Tools::displayError('You do not have permission to use this wizard.').'" />'); - - $allowedExtensions = array('jpeg', 'gif', 'png', 'jpg'); - - $logo = (isset($_FILES['carrier_logo_input']) ? $_FILES['carrier_logo_input'] : false); - if ($logo && !empty($logo['tmp_name']) && $logo['tmp_name'] != 'none' - && (!isset($logo['error']) || !$logo['error']) - && preg_match('/\.(jpe?g|gif|png)$/', $logo['name']) - && is_uploaded_file($logo['tmp_name']) - && ImageManager::isRealImage($logo['tmp_name'], $logo['type'])) - { - $file = $logo['tmp_name']; - do $tmp_name = uniqid().'.jpg'; - while (file_exists(_PS_TMP_IMG_DIR_.$tmp_name)); - if (!ImageManager::resize($file, _PS_TMP_IMG_DIR_.$tmp_name)) - die('<return result="error" message="Impossible to resize the image into '.Tools::safeOutput(_PS_TMP_IMG_DIR_).'" />'); - @unlink($file); - die('<return result="success" message="'.Tools::safeOutput(_PS_TMP_IMG_.$tmp_name).'" />'); - } - else - die('<return result="error" message="Cannot upload file" />'); - } - - public function ajaxProcessFinishStep() - { - $return = array('has_error' => false); - if (!$this->tabAccess['edit']) - $return = array( - 'has_error' => true, - $return['errors'][] = Tools::displayError('You do not have permission to use this wizard.') - ); - else - { - $this->validateForm(false); - if ($id_carrier = Tools::getValue('id_carrier')) - { - $current_carrier = new Carrier((int)$id_carrier); - - // if update we duplicate current Carrier - /** @var Carrier $new_carrier */ - $new_carrier = $current_carrier->duplicateObject(); - - if (Validate::isLoadedObject($new_carrier)) - { - // Set flag deteled to true for historization - $current_carrier->deleted = true; - $current_carrier->update(); - - // Fill the new carrier object - $this->copyFromPost($new_carrier, $this->table); - $new_carrier->position = $current_carrier->position; - $new_carrier->update(); - - $this->updateAssoShop((int)$new_carrier->id); - $this->duplicateLogo((int)$new_carrier->id, (int)$current_carrier->id); - $this->changeGroups((int)$new_carrier->id); - - //Copy default carrier - if (Configuration::get('PS_CARRIER_DEFAULT') == $current_carrier->id) - Configuration::updateValue('PS_CARRIER_DEFAULT', (int)$new_carrier->id); - - // Call of hooks - Hook::exec('actionCarrierUpdate', array( - 'id_carrier' => (int)$current_carrier->id, - 'carrier' => $new_carrier - )); - $this->postImage($new_carrier->id); - $this->changeZones($new_carrier->id); - $new_carrier->setTaxRulesGroup((int)Tools::getValue('id_tax_rules_group')); - $carrier = $new_carrier; - } - } - else - { - $carrier = new Carrier(); - $this->copyFromPost($carrier, $this->table); - if (!$carrier->add()) - { - $return['has_error'] = true; - $return['errors'][] = $this->l('An error occurred while saving this carrier.'); - } - } - - if ($carrier->is_free) - { - //if carrier is free delete shipping cost - $carrier->deleteDeliveryPrice('range_weight'); - $carrier->deleteDeliveryPrice('range_price'); - } - - if (Validate::isLoadedObject($carrier)) - { - if (!$this->changeGroups((int)$carrier->id)) - { - $return['has_error'] = true; - $return['errors'][] = $this->l('An error occurred while saving carrier groups.'); - } - - if (!$this->changeZones((int)$carrier->id)) - { - $return['has_error'] = true; - $return['errors'][] = $this->l('An error occurred while saving carrier zones.'); - } - - if (!$carrier->is_free) - if (!$this->processRanges((int)$carrier->id)) - { - $return['has_error'] = true; - $return['errors'][] = $this->l('An error occurred while saving carrier ranges.'); - } - - if (Shop::isFeatureActive() && !$this->updateAssoShop((int)$carrier->id)) - { - $return['has_error'] = true; - $return['errors'][] = $this->l('An error occurred while saving associations of shops.'); - } - - if (!$carrier->setTaxRulesGroup((int)Tools::getValue('id_tax_rules_group'))) - { - $return['has_error'] = true; - $return['errors'][] = $this->l('An error occurred while saving the tax rules group.'); - } - - if (Tools::getValue('logo')) - { - if (Tools::getValue('logo') == 'null' && file_exists(_PS_SHIP_IMG_DIR_.$carrier->id.'.jpg')) - unlink(_PS_SHIP_IMG_DIR_.$carrier->id.'.jpg'); - else - { - $logo = basename(Tools::getValue('logo')); - if (!file_exists(_PS_TMP_IMG_DIR_.$logo) || !copy(_PS_TMP_IMG_DIR_.$logo, _PS_SHIP_IMG_DIR_.$carrier->id.'.jpg')) - { - $return['has_error'] = true; - $return['errors'][] = $this->l('An error occurred while saving carrier logo.'); - } - } - } - $return['id_carrier'] = $carrier->id; - } - } - die(Tools::jsonEncode($return)); - } - - protected function changeGroups($id_carrier, $delete = true) - { - $carrier = new Carrier((int)$id_carrier); - if (!Validate::isLoadedObject($carrier)) - return false; - - return $carrier->setGroups(Tools::getValue('groupBox')); - } - - public function changeZones($id) - { - $return = true; - $carrier = new Carrier($id); - if (!Validate::isLoadedObject($carrier)) - die (Tools::displayError('The object cannot be loaded.')); - $zones = Zone::getZones(false); - foreach ($zones as $zone) - if (count($carrier->getZone($zone['id_zone']))) - { - if (!isset($_POST['zone_'.$zone['id_zone']]) || !$_POST['zone_'.$zone['id_zone']]) - $return &= $carrier->deleteZone((int)$zone['id_zone']); - } - else - if (isset($_POST['zone_'.$zone['id_zone']]) && $_POST['zone_'.$zone['id_zone']]) - $return &= $carrier->addZone((int)$zone['id_zone']); - - return $return; - } - - public function getValidationRules() - { - $step_number = (int)Tools::getValue('step_number'); - if (!$step_number) - return; - - if ($step_number == 4 && !Shop::isFeatureActive() || $step_number == 5 && Shop::isFeatureActive()) - return array('fields' => array()); - - $step_fields = array( - 1 => array('name', 'delay', 'grade', 'url'), - 2 => array('is_free', 'id_tax_rules_group', 'shipping_handling', 'shipping_method', 'range_behavior'), - 3 => array('range_behavior', 'max_height', 'max_width', 'max_depth', 'max_weight'), - 4 => array(), - ); - if (Shop::isFeatureActive()) - { - $tmp = $step_fields; - $step_fields = array_slice($tmp, 0, 1, true) + array(2 => array('shop')); - $step_fields[3] = $tmp[2]; - $step_fields[4] = $tmp[3]; - } - - $definition = ObjectModel::getDefinition('Carrier'); - foreach ($definition['fields'] as $field => $def) - if (is_array($step_fields[$step_number]) && !in_array($field, $step_fields[$step_number])) - unset($definition['fields'][$field]); - return $definition; - } - - public static function displayFieldName($field) - { - return $field; - } - - public function duplicateLogo($new_id, $old_id) - { - $old_logo = _PS_SHIP_IMG_DIR_.'/'.(int)$old_id.'.jpg'; - if (file_exists($old_logo)) - copy($old_logo, _PS_SHIP_IMG_DIR_.'/'.(int)$new_id.'.jpg'); - - $old_tmp_logo = _PS_TMP_IMG_DIR_.'/carrier_mini_'.(int)$old_id.'.jpg'; - if (file_exists($old_tmp_logo)) - { - if (!isset($_FILES['logo'])) - copy($old_tmp_logo, _PS_TMP_IMG_DIR_.'/carrier_mini_'.$new_id.'.jpg'); - unlink($old_tmp_logo); - } - } - - public function getActualCurrency() - { - if ($this->type_context == Shop::CONTEXT_SHOP) - Shop::setContext($this->type_context, $this->old_context->shop->id); - elseif ($this->type_context == Shop::CONTEXT_GROUP) - Shop::setContext($this->type_context, $this->old_context->shop->id_shop_group); - - $currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); - - Shop::setContext(Shop::CONTEXT_ALL); - - return $currency; - } + protected $wizard_access; + + public function __construct() + { + $this->bootstrap = true; + $this->display = 'view'; + $this->table = 'carrier'; + $this->identifier = 'id_carrier'; + $this->className = 'Carrier'; + $this->lang = false; + $this->deleted = true; + $this->step_number = 0; + $this->type_context = Shop::getContext(); + $this->old_context = Context::getContext(); + $this->multishop_context = Shop::CONTEXT_ALL; + $this->context = Context::getContext(); + + $this->fieldImageSettings = array( + 'name' => 'logo', + 'dir' => 's' + ); + + parent::__construct(); + + $this->tabAccess = Profile::getProfileAccess($this->context->employee->id_profile, Tab::getIdFromClassName('AdminCarriers')); + } + + public function setMedia() + { + parent::setMedia(); + $this->addJqueryPlugin('smartWizard'); + $this->addJqueryPlugin('typewatch'); + $this->addJs(_PS_JS_DIR_.'admin/carrier_wizard.js'); + } + + public function initWizard() + { + $this->wizard_steps = array( + 'name' => 'carrier_wizard', + 'steps' => array( + array( + 'title' => $this->l('General settings'), + ), + array( + 'title' => $this->l('Shipping locations and costs'), + ), + array( + 'title' => $this->l('Size, weight, and group access'), + ), + array( + 'title' => $this->l('Summary'), + ), + + )); + + if (Shop::isFeatureActive()) { + $multistore_step = array( + array( + 'title' => $this->l('MultiStore'), + ) + ); + array_splice($this->wizard_steps['steps'], 1, 0, $multistore_step); + } + } + + public function renderView() + { + $this->initWizard(); + + if (Tools::getValue('id_carrier') && $this->tabAccess['edit']) { + $carrier = $this->loadObject(); + } elseif ($this->tabAccess['add']) { + $carrier = new Carrier(); + } + + if ((!$this->tabAccess['edit'] && Tools::getValue('id_carrier')) || (!$this->tabAccess['add'] && !Tools::getValue('id_carrier'))) { + $this->errors[] = Tools::displayError('You do not have permission to use this wizard.'); + return ; + } + + $currency = $this->getActualCurrency(); + + $this->tpl_view_vars = array( + 'currency_sign' => $currency->sign, + 'PS_WEIGHT_UNIT' => Configuration::get('PS_WEIGHT_UNIT'), + 'enableAllSteps' => Validate::isLoadedObject($carrier), + 'wizard_steps' => $this->wizard_steps, + 'validate_url' => $this->context->link->getAdminLink('AdminCarrierWizard'), + 'carrierlist_url' => $this->context->link->getAdminLink('AdminCarriers').'&conf='.((int)Validate::isLoadedObject($carrier) ? 4 : 3), + 'multistore_enable' => Shop::isFeatureActive(), + 'wizard_contents' => array( + 'contents' => array( + 0 => $this->renderStepOne($carrier), + 1 => $this->renderStepThree($carrier), + 2 => $this->renderStepFour($carrier), + 3 => $this->renderStepFive($carrier), + )), + 'labels' => array('next' => $this->l('Next'), 'previous' => $this->l('Previous'), 'finish' => $this->l('Finish')) + ); + + + if (Shop::isFeatureActive()) { + array_splice($this->tpl_view_vars['wizard_contents']['contents'], 1, 0, array(0 => $this->renderStepTwo($carrier))); + } + + $this->context->smarty->assign(array( + 'carrier_logo' => (Validate::isLoadedObject($carrier) && file_exists(_PS_SHIP_IMG_DIR_.$carrier->id.'.jpg') ? _THEME_SHIP_DIR_.$carrier->id.'.jpg' : false), + )); + + $this->context->smarty->assign(array( + 'logo_content' => $this->createTemplate('logo.tpl')->fetch() + )); + + $this->addjQueryPlugin(array('ajaxfileupload')); + + return parent::renderView(); + } + + public function initBreadcrumbs($tab_id = null, $tabs = null) + { + if (Tools::getValue('id_carrier')) { + $this->display = 'edit'; + } else { + $this->display = 'add'; + } + + parent::initBreadcrumbs((int)Tab::getIdFromClassName('AdminCarriers')); + + $this->display = 'view'; + } + + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); + + $this->page_header_toolbar_btn['cancel'] = array( + 'href' => $this->context->link->getAdminLink('AdminCarriers'), + 'desc' => $this->l('Cancel', null, null, false) + ); + } + + public function renderStepOne($carrier) + { + $this->fields_form = array( + 'form' => array( + 'id_form' => 'step_carrier_general', + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Carrier name'), + 'name' => 'name', + 'required' => true, + 'hint' => array( + sprintf($this->l('Allowed characters: letters, spaces and "%s".'), '().-'), + $this->l('The carrier\'s name will be displayed during checkout.'), + $this->l('For in-store pickup, enter 0 to replace the carrier name with your shop name.') + ) + ), + array( + 'type' => 'text', + 'label' => $this->l('Transit time'), + 'name' => 'delay', + 'lang' => true, + 'required' => true, + 'maxlength' => 128, + 'hint' => $this->l('The estimated delivery time will be displayed during checkout.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Speed grade'), + 'name' => 'grade', + 'required' => false, + 'size' => 1, + 'hint' => $this->l('Enter "0" for a longest shipping delay, or "9" for the shortest shipping delay.') + ), + array( + 'type' => 'logo', + 'label' => $this->l('Logo'), + 'name' => 'logo' + ), + array( + 'type' => 'text', + 'label' => $this->l('Tracking URL'), + 'name' => 'url', + 'hint' => $this->l('Delivery tracking URL: Type \'@\' where the tracking number should appear. It will be automatically replaced by the tracking number.'), + 'desc' => $this->l('For example: \'http://exampl.com/track.php?num=@\' with \'@\' where the tracking number should appear.') + ), + )), + ); + + $tpl_vars = array('max_image_size' => (int)Configuration::get('PS_PRODUCT_PICTURE_MAX_SIZE') / 1024 / 1024); + $fields_value = $this->getStepOneFieldsValues($carrier); + return $this->renderGenericForm(array('form' => $this->fields_form), $fields_value, $tpl_vars); + } + + public function renderStepTwo($carrier) + { + $this->fields_form = array( + 'form' => array( + 'id_form' => 'step_carrier_shops', + 'force' => true, + 'input' => array( + array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ), + )) + ); + $fields_value = $this->getStepTwoFieldsValues($carrier); + + return $this->renderGenericForm(array('form' => $this->fields_form), $fields_value); + } + + public function renderStepThree($carrier) + { + $this->fields_form = array( + 'form' => array( + 'id_form' => 'step_carrier_ranges', + 'input' => array( + 'shipping_handling' => array( + 'type' => 'switch', + 'label' => $this->l('Add handling costs'), + 'name' => 'shipping_handling', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'shipping_handling_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'shipping_handling_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Include the handling costs (as set in Shipping > Preferences) in the final carrier price.') + ), + 'is_free' => array( + 'type' => 'switch', + 'label' => $this->l('Free shipping'), + 'name' => 'is_free', + 'required' => false, + 'class' => 't', + 'values' => array( + array( + 'id' => 'is_free_on', + 'value' => 1, + 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('No').'" title="'.$this->l('No').'" />' + ), + array( + 'id' => 'is_free_off', + 'value' => 0, + 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Yes').'" title="'.$this->l('Yes').'" />' + ) + ), + ), + 'shipping_method' => array( + 'type' => 'radio', + 'label' => $this->l('Billing'), + 'name' => 'shipping_method', + 'required' => false, + 'class' => 't', + 'br' => true, + 'values' => array( + array( + 'id' => 'billing_price', + 'value' => Carrier::SHIPPING_METHOD_PRICE, + 'label' => $this->l('According to total price.') + ), + array( + 'id' => 'billing_weight', + 'value' => Carrier::SHIPPING_METHOD_WEIGHT, + 'label' => $this->l('According to total weight.') + ) + ) + ), + 'id_tax_rules_group' => array( + 'type' => 'select', + 'label' => $this->l('Tax'), + 'name' => 'id_tax_rules_group', + 'options' => array( + 'query' => TaxRulesGroup::getTaxRulesGroups(true), + 'id' => 'id_tax_rules_group', + 'name' => 'name', + 'default' => array( + 'label' => $this->l('No tax'), + 'value' => 0 + ) + ) + ), + 'range_behavior' => array( + 'type' => 'select', + 'label' => $this->l('Out-of-range behavior'), + 'name' => 'range_behavior', + 'options' => array( + 'query' => array( + array( + 'id' => 0, + 'name' => $this->l('Apply the cost of the highest defined range') + ), + array( + 'id' => 1, + 'name' => $this->l('Disable carrier') + ) + ), + 'id' => 'id', + 'name' => 'name' + ), + 'hint' => $this->l('Out-of-range behavior occurs when no defined range matches the customer\'s cart (e.g. when the weight of the cart is greater than the highest weight limit defined by the weight ranges).') + ), + 'zones' => array( + 'type' => 'zone', + 'name' => 'zones' + ) + ), + + )); + + if (Configuration::get('PS_ATCP_SHIPWRAP')) { + unset($this->fields_form['form']['input']['id_tax_rules_group']); + } + + $tpl_vars = array(); + $tpl_vars['PS_WEIGHT_UNIT'] = Configuration::get('PS_WEIGHT_UNIT'); + + $currency = $this->getActualCurrency(); + + $tpl_vars['currency_sign'] = $currency->sign; + + $fields_value = $this->getStepThreeFieldsValues($carrier); + + $this->getTplRangesVarsAndValues($carrier, $tpl_vars, $fields_value); + return $this->renderGenericForm(array('form' => $this->fields_form), $fields_value, $tpl_vars); + } + + /** + * @param Carrier $carrier + * + * @return string + */ + public function renderStepFour($carrier) + { + $this->fields_form = array( + 'form' => array( + 'id_form' => 'step_carrier_conf', + 'input' => array( + array( + 'type' => 'text', + 'label' => sprintf($this->l('Maximum package width (%s)'), Configuration::get('PS_DIMENSION_UNIT')), + 'name' => 'max_width', + 'required' => false, + 'hint' => $this->l('Maximum width managed by this carrier. Set the value to "0", or leave this field blank to ignore.').' '.$this->l('The value must be an integer.') + ), + array( + 'type' => 'text', + 'label' => sprintf($this->l('Maximum package height (%s)'), Configuration::get('PS_DIMENSION_UNIT')), + 'name' => 'max_height', + 'required' => false, + 'hint' => $this->l('Maximum height managed by this carrier. Set the value to "0", or leave this field blank to ignore.').' '.$this->l('The value must be an integer.') + ), + array( + 'type' => 'text', + 'label' => sprintf($this->l('Maximum package depth (%s)'), Configuration::get('PS_DIMENSION_UNIT')), + 'name' => 'max_depth', + 'required' => false, + 'hint' => $this->l('Maximum depth managed by this carrier. Set the value to "0", or leave this field blank to ignore.').' '.$this->l('The value must be an integer.') + ), + array( + 'type' => 'text', + 'label' => sprintf($this->l('Maximum package weight (%s)'), Configuration::get('PS_WEIGHT_UNIT')), + 'name' => 'max_weight', + 'required' => false, + 'hint' => $this->l('Maximum weight managed by this carrier. Set the value to "0", or leave this field blank to ignore.') + ), + array( + 'type' => 'group', + 'label' => $this->l('Group access'), + 'name' => 'groupBox', + 'values' => Group::getGroups(Context::getContext()->language->id), + 'hint' => $this->l('Mark the groups that are allowed access to this carrier.') + ) + ) + )); + + $fields_value = $this->getStepFourFieldsValues($carrier); + + // Added values of object Group + $carrier_groups = $carrier->getGroups(); + $carrier_groups_ids = array(); + if (is_array($carrier_groups)) { + foreach ($carrier_groups as $carrier_group) { + $carrier_groups_ids[] = $carrier_group['id_group']; + } + } + + $groups = Group::getGroups($this->context->language->id); + + foreach ($groups as $group) { + $fields_value['groupBox_'.$group['id_group']] = Tools::getValue('groupBox_'.$group['id_group'], (in_array($group['id_group'], $carrier_groups_ids) || empty($carrier_groups_ids) && !$carrier->id)); + } + + return $this->renderGenericForm(array('form' => $this->fields_form), $fields_value); + } + + public function renderStepFive($carrier) + { + $this->fields_form = array( + 'form' => array( + 'id_form' => 'step_carrier_summary', + 'input' => array( + array( + 'type' => 'switch', + 'label' => $this->l('Enabled'), + 'name' => 'active', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1 + ), + array( + 'id' => 'active_off', + 'value' => 0 + ) + ), + 'hint' => $this->l('Enable the carrier in the front office.') + ) + ) + )); + + $template = $this->createTemplate('controllers/carrier_wizard/summary.tpl'); + + $fields_value = $this->getStepFiveFieldsValues($carrier); + + $active_form = $this->renderGenericForm(array('form' => $this->fields_form), $fields_value); + + $active_form = str_replace(array('<fieldset id="fieldset_form">', '</fieldset>'), '', $active_form); + + $template->assign('active_form', $active_form); + + return $template->fetch('controllers/carrier_wizard/summary.tpl'); + } + + /** + * @param Carrier $carrier + * @param array $tpl_vars + * @param array $fields_value + */ + protected function getTplRangesVarsAndValues($carrier, &$tpl_vars, &$fields_value) + { + $tpl_vars['zones'] = Zone::getZones(false); + $carrier_zones = $carrier->getZones(); + $carrier_zones_ids = array(); + if (is_array($carrier_zones)) { + foreach ($carrier_zones as $carrier_zone) { + $carrier_zones_ids[] = $carrier_zone['id_zone']; + } + } + + $range_table = $carrier->getRangeTable(); + $shipping_method = $carrier->getShippingMethod(); + + $zones = Zone::getZones(false); + foreach ($zones as $zone) { + $fields_value['zones'][$zone['id_zone']] = Tools::getValue('zone_'.$zone['id_zone'], (in_array($zone['id_zone'], $carrier_zones_ids))); + } + + if ($shipping_method == Carrier::SHIPPING_METHOD_FREE) { + $range_obj = $carrier->getRangeObject($carrier->shipping_method); + $price_by_range = array(); + } else { + $range_obj = $carrier->getRangeObject(); + $price_by_range = Carrier::getDeliveryPriceByRanges($range_table, (int)$carrier->id); + } + + foreach ($price_by_range as $price) { + $tpl_vars['price_by_range'][$price['id_'.$range_table]][$price['id_zone']] = $price['price']; + } + + $tmp_range = $range_obj->getRanges((int)$carrier->id); + $tpl_vars['ranges'] = array(); + if ($shipping_method != Carrier::SHIPPING_METHOD_FREE) { + foreach ($tmp_range as $id => $range) { + $tpl_vars['ranges'][$range['id_'.$range_table]] = $range; + $tpl_vars['ranges'][$range['id_'.$range_table]]['id_range'] = $range['id_'.$range_table]; + } + } + + // init blank range + if (!count($tpl_vars['ranges'])) { + $tpl_vars['ranges'][] = array('id_range' => 0, 'delimiter1' => 0, 'delimiter2' => 0); + } + } + + public function renderGenericForm($fields_form, $fields_value, $tpl_vars = array()) + { + $helper = new HelperForm(); + $helper->show_toolbar = false; + $helper->table = $this->table; + $lang = new Language((int)Configuration::get('PS_LANG_DEFAULT')); + $helper->default_form_language = $lang->id; + $helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') ? Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') : 0; + $this->fields_form = array(); + $helper->id = (int)Tools::getValue('id_carrier'); + $helper->identifier = $this->identifier; + $helper->tpl_vars = array_merge(array( + 'fields_value' => $fields_value, + 'languages' => $this->getLanguages(), + 'id_language' => $this->context->language->id + ), $tpl_vars); + $helper->override_folder = 'carrier_wizard/'; + + return $helper->generateForm($fields_form); + } + + public function getStepOneFieldsValues($carrier) + { + return array( + 'id_carrier' => $this->getFieldValue($carrier, 'id_carrier'), + 'name' => $this->getFieldValue($carrier, 'name'), + 'delay' => $this->getFieldValue($carrier, 'delay'), + 'grade' => $this->getFieldValue($carrier, 'grade'), + 'url' => $this->getFieldValue($carrier, 'url'), + ); + } + + public function getStepTwoFieldsValues($carrier) + { + return array('shop' => $this->getFieldValue($carrier, 'shop')); + } + + public function getStepThreeFieldsValues($carrier) + { + $id_tax_rules_group = (is_object($this->object) && !$this->object->id) ? Carrier::getIdTaxRulesGroupMostUsed() : $this->getFieldValue($carrier, 'id_tax_rules_group'); + + $shipping_handling = (is_object($this->object) && !$this->object->id) ? 0 : $this->getFieldValue($carrier, 'shipping_handling'); + + return array( + 'is_free' => $this->getFieldValue($carrier, 'is_free'), + 'id_tax_rules_group' => (int)$id_tax_rules_group, + 'shipping_handling' => $shipping_handling, + 'shipping_method' => $this->getFieldValue($carrier, 'shipping_method'), + 'range_behavior' => $this->getFieldValue($carrier, 'range_behavior'), + 'zones' => $this->getFieldValue($carrier, 'zones'), + ); + } + + public function getStepFourFieldsValues($carrier) + { + return array( + 'range_behavior' => $this->getFieldValue($carrier, 'range_behavior'), + 'max_height' => $this->getFieldValue($carrier, 'max_height'), + 'max_width' => $this->getFieldValue($carrier, 'max_width'), + 'max_depth' => $this->getFieldValue($carrier, 'max_depth'), + 'max_weight' => $this->getFieldValue($carrier, 'max_weight'), + 'group' => $this->getFieldValue($carrier, 'group'), + ); + } + + public function getStepFiveFieldsValues($carrier) + { + return array('active' => $this->getFieldValue($carrier, 'active')); + } + + public function ajaxProcessChangeRanges() + { + if ((Validate::isLoadedObject($this->object) && !$this->tabAccess['edit']) || !$this->tabAccess['add']) { + $this->errors[] = Tools::displayError('You do not have permission to use this wizard.'); + return; + } + if ((!(int)$shipping_method = Tools::getValue('shipping_method')) || !in_array($shipping_method, array(Carrier::SHIPPING_METHOD_PRICE, Carrier::SHIPPING_METHOD_WEIGHT))) { + return ; + } + + $carrier = $this->loadObject(true); + $carrier->shipping_method = $shipping_method; + + $tpl_vars = array(); + $fields_value = $this->getStepThreeFieldsValues($carrier); + $this->getTplRangesVarsAndValues($carrier, $tpl_vars, $fields_value); + $template = $this->createTemplate('controllers/carrier_wizard/helpers/form/form_ranges.tpl'); + $template->assign($tpl_vars); + $template->assign('change_ranges', 1); + + $template->assign('fields_value', $fields_value); + $template->assign('input', array('type' => 'zone', 'name' => 'zones' )); + + $currency = $this->getActualCurrency(); + + $template->assign('currency_sign', $currency->sign); + $template->assign('PS_WEIGHT_UNIT', Configuration::get('PS_WEIGHT_UNIT')); + + die($template->fetch()); + } + + protected function validateForm($die = true) + { + $step_number = (int)Tools::getValue('step_number'); + $return = array('has_error' => false); + + if (!$this->tabAccess['edit']) { + $this->errors[] = Tools::displayError('You do not have permission to use this wizard.'); + } else { + if (Shop::isFeatureActive() && $step_number == 2) { + if (!Tools::getValue('checkBoxShopAsso_carrier')) { + $return['has_error'] = true; + $return['errors'][] = $this->l('You must choose at least one shop or group shop.'); + } + } else { + $this->validateRules(); + } + } + + if (count($this->errors)) { + $return['has_error'] = true; + $return['errors'] = $this->errors; + } + if (count($this->errors) || $die) { + die(Tools::jsonEncode($return)); + } + } + + + public function ajaxProcessValidateStep() + { + $this->validateForm(true); + } + + public function processRanges($id_carrier) + { + if (!$this->tabAccess['edit'] || !$this->tabAccess['add']) { + $this->errors[] = Tools::displayError('You do not have permission to use this wizard.'); + return; + } + + $carrier = new Carrier((int)$id_carrier); + if (!Validate::isLoadedObject($carrier)) { + return false; + } + + $range_inf = Tools::getValue('range_inf'); + $range_sup = Tools::getValue('range_sup'); + $range_type = Tools::getValue('shipping_method'); + + $fees = Tools::getValue('fees'); + + $carrier->deleteDeliveryPrice($carrier->getRangeTable()); + if ($range_type != Carrier::SHIPPING_METHOD_FREE) { + foreach ($range_inf as $key => $delimiter1) { + if (!isset($range_sup[$key])) { + continue; + } + $add_range = true; + if ($range_type == Carrier::SHIPPING_METHOD_WEIGHT) { + if (!RangeWeight::rangeExist((int)$carrier->id, (float)$delimiter1, (float)$range_sup[$key])) { + $range = new RangeWeight(); + } else { + $range = new RangeWeight((int)$key); + $add_range = false; + } + } + + if ($range_type == Carrier::SHIPPING_METHOD_PRICE) { + if (!RangePrice::rangeExist((int)$carrier->id, (float)$delimiter1, (float)$range_sup[$key])) { + $range = new RangePrice(); + } else { + $range = new RangePrice((int)$key); + $add_range = false; + } + } + if ($add_range) { + $range->id_carrier = (int)$carrier->id; + $range->delimiter1 = (float)$delimiter1; + $range->delimiter2 = (float)$range_sup[$key]; + $range->save(); + } + + if (!Validate::isLoadedObject($range)) { + return false; + } + $price_list = array(); + if (is_array($fees) && count($fees)) { + foreach ($fees as $id_zone => $fee) { + $price_list[] = array( + 'id_range_price' => ($range_type == Carrier::SHIPPING_METHOD_PRICE ? (int)$range->id : null), + 'id_range_weight' => ($range_type == Carrier::SHIPPING_METHOD_WEIGHT ? (int)$range->id : null), + 'id_carrier' => (int)$carrier->id, + 'id_zone' => (int)$id_zone, + 'price' => isset($fee[$key]) ? (float)$fee[$key] : 0, + ); + } + } + + if (count($price_list) && !$carrier->addDeliveryPrice($price_list, true)) { + return false; + } + } + } + return true; + } + + public function ajaxProcessUploadLogo() + { + if (!$this->tabAccess['edit']) { + die('<return result="error" message="'.Tools::displayError('You do not have permission to use this wizard.').'" />'); + } + + $allowedExtensions = array('jpeg', 'gif', 'png', 'jpg'); + + $logo = (isset($_FILES['carrier_logo_input']) ? $_FILES['carrier_logo_input'] : false); + if ($logo && !empty($logo['tmp_name']) && $logo['tmp_name'] != 'none' + && (!isset($logo['error']) || !$logo['error']) + && preg_match('/\.(jpe?g|gif|png)$/', $logo['name']) + && is_uploaded_file($logo['tmp_name']) + && ImageManager::isRealImage($logo['tmp_name'], $logo['type'])) { + $file = $logo['tmp_name']; + do { + $tmp_name = uniqid().'.jpg'; + } while (file_exists(_PS_TMP_IMG_DIR_.$tmp_name)); + if (!ImageManager::resize($file, _PS_TMP_IMG_DIR_.$tmp_name)) { + die('<return result="error" message="Impossible to resize the image into '.Tools::safeOutput(_PS_TMP_IMG_DIR_).'" />'); + } + @unlink($file); + die('<return result="success" message="'.Tools::safeOutput(_PS_TMP_IMG_.$tmp_name).'" />'); + } else { + die('<return result="error" message="Cannot upload file" />'); + } + } + + public function ajaxProcessFinishStep() + { + $return = array('has_error' => false); + if (!$this->tabAccess['edit']) { + $return = array( + 'has_error' => true, + $return['errors'][] = Tools::displayError('You do not have permission to use this wizard.') + ); + } else { + $this->validateForm(false); + if ($id_carrier = Tools::getValue('id_carrier')) { + $current_carrier = new Carrier((int)$id_carrier); + + // if update we duplicate current Carrier + /** @var Carrier $new_carrier */ + $new_carrier = $current_carrier->duplicateObject(); + + if (Validate::isLoadedObject($new_carrier)) { + // Set flag deteled to true for historization + $current_carrier->deleted = true; + $current_carrier->update(); + + // Fill the new carrier object + $this->copyFromPost($new_carrier, $this->table); + $new_carrier->position = $current_carrier->position; + $new_carrier->update(); + + $this->updateAssoShop((int)$new_carrier->id); + $this->duplicateLogo((int)$new_carrier->id, (int)$current_carrier->id); + $this->changeGroups((int)$new_carrier->id); + + //Copy default carrier + if (Configuration::get('PS_CARRIER_DEFAULT') == $current_carrier->id) { + Configuration::updateValue('PS_CARRIER_DEFAULT', (int)$new_carrier->id); + } + + // Call of hooks + Hook::exec('actionCarrierUpdate', array( + 'id_carrier' => (int)$current_carrier->id, + 'carrier' => $new_carrier + )); + $this->postImage($new_carrier->id); + $this->changeZones($new_carrier->id); + $new_carrier->setTaxRulesGroup((int)Tools::getValue('id_tax_rules_group')); + $carrier = $new_carrier; + } + } else { + $carrier = new Carrier(); + $this->copyFromPost($carrier, $this->table); + if (!$carrier->add()) { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving this carrier.'); + } + } + + if ($carrier->is_free) { + //if carrier is free delete shipping cost + $carrier->deleteDeliveryPrice('range_weight'); + $carrier->deleteDeliveryPrice('range_price'); + } + + if (Validate::isLoadedObject($carrier)) { + if (!$this->changeGroups((int)$carrier->id)) { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving carrier groups.'); + } + + if (!$this->changeZones((int)$carrier->id)) { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving carrier zones.'); + } + + if (!$carrier->is_free) { + if (!$this->processRanges((int)$carrier->id)) { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving carrier ranges.'); + } + } + + if (Shop::isFeatureActive() && !$this->updateAssoShop((int)$carrier->id)) { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving associations of shops.'); + } + + if (!$carrier->setTaxRulesGroup((int)Tools::getValue('id_tax_rules_group'))) { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving the tax rules group.'); + } + + if (Tools::getValue('logo')) { + if (Tools::getValue('logo') == 'null' && file_exists(_PS_SHIP_IMG_DIR_.$carrier->id.'.jpg')) { + unlink(_PS_SHIP_IMG_DIR_.$carrier->id.'.jpg'); + } else { + $logo = basename(Tools::getValue('logo')); + if (!file_exists(_PS_TMP_IMG_DIR_.$logo) || !copy(_PS_TMP_IMG_DIR_.$logo, _PS_SHIP_IMG_DIR_.$carrier->id.'.jpg')) { + $return['has_error'] = true; + $return['errors'][] = $this->l('An error occurred while saving carrier logo.'); + } + } + } + $return['id_carrier'] = $carrier->id; + } + } + die(Tools::jsonEncode($return)); + } + + protected function changeGroups($id_carrier, $delete = true) + { + $carrier = new Carrier((int)$id_carrier); + if (!Validate::isLoadedObject($carrier)) { + return false; + } + + return $carrier->setGroups(Tools::getValue('groupBox')); + } + + public function changeZones($id) + { + $return = true; + $carrier = new Carrier($id); + if (!Validate::isLoadedObject($carrier)) { + die(Tools::displayError('The object cannot be loaded.')); + } + $zones = Zone::getZones(false); + foreach ($zones as $zone) { + if (count($carrier->getZone($zone['id_zone']))) { + if (!isset($_POST['zone_'.$zone['id_zone']]) || !$_POST['zone_'.$zone['id_zone']]) { + $return &= $carrier->deleteZone((int)$zone['id_zone']); + } + } elseif (isset($_POST['zone_'.$zone['id_zone']]) && $_POST['zone_'.$zone['id_zone']]) { + $return &= $carrier->addZone((int)$zone['id_zone']); + } + } + + return $return; + } + + public function getValidationRules() + { + $step_number = (int)Tools::getValue('step_number'); + if (!$step_number) { + return; + } + + if ($step_number == 4 && !Shop::isFeatureActive() || $step_number == 5 && Shop::isFeatureActive()) { + return array('fields' => array()); + } + + $step_fields = array( + 1 => array('name', 'delay', 'grade', 'url'), + 2 => array('is_free', 'id_tax_rules_group', 'shipping_handling', 'shipping_method', 'range_behavior'), + 3 => array('range_behavior', 'max_height', 'max_width', 'max_depth', 'max_weight'), + 4 => array(), + ); + if (Shop::isFeatureActive()) { + $tmp = $step_fields; + $step_fields = array_slice($tmp, 0, 1, true) + array(2 => array('shop')); + $step_fields[3] = $tmp[2]; + $step_fields[4] = $tmp[3]; + } + + $definition = ObjectModel::getDefinition('Carrier'); + foreach ($definition['fields'] as $field => $def) { + if (is_array($step_fields[$step_number]) && !in_array($field, $step_fields[$step_number])) { + unset($definition['fields'][$field]); + } + } + return $definition; + } + + public static function displayFieldName($field) + { + return $field; + } + + public function duplicateLogo($new_id, $old_id) + { + $old_logo = _PS_SHIP_IMG_DIR_.'/'.(int)$old_id.'.jpg'; + if (file_exists($old_logo)) { + copy($old_logo, _PS_SHIP_IMG_DIR_.'/'.(int)$new_id.'.jpg'); + } + + $old_tmp_logo = _PS_TMP_IMG_DIR_.'/carrier_mini_'.(int)$old_id.'.jpg'; + if (file_exists($old_tmp_logo)) { + if (!isset($_FILES['logo'])) { + copy($old_tmp_logo, _PS_TMP_IMG_DIR_.'/carrier_mini_'.$new_id.'.jpg'); + } + unlink($old_tmp_logo); + } + } + + public function getActualCurrency() + { + if ($this->type_context == Shop::CONTEXT_SHOP) { + Shop::setContext($this->type_context, $this->old_context->shop->id); + } elseif ($this->type_context == Shop::CONTEXT_GROUP) { + Shop::setContext($this->type_context, $this->old_context->shop->id_shop_group); + } + + $currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); + + Shop::setContext(Shop::CONTEXT_ALL); + + return $currency; + } } diff --git a/controllers/admin/AdminCarriersController.php b/controllers/admin/AdminCarriersController.php index c16de79b..4ea16f69 100644 --- a/controllers/admin/AdminCarriersController.php +++ b/controllers/admin/AdminCarriersController.php @@ -29,725 +29,732 @@ */ class AdminCarriersControllerCore extends AdminController { - protected $position_identifier = 'id_carrier'; + protected $position_identifier = 'id_carrier'; - public function __construct() - { + public function __construct() + { + if ($id_carrier = Tools::getValue('id_carrier') && !Tools::isSubmit('deletecarrier') && !Tools::isSubmit('statuscarrier') && !Tools::isSubmit('isFreecarrier') && !Tools::isSubmit('onboarding_carrier')) { + Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminCarrierWizard').'&id_carrier='.(int)$id_carrier); + } - if ($id_carrier = Tools::getValue('id_carrier') && !Tools::isSubmit('deletecarrier') && !Tools::isSubmit('statuscarrier') && !Tools::isSubmit('isFreecarrier') && !Tools::isSubmit('onboarding_carrier')) - Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminCarrierWizard').'&id_carrier='.(int)$id_carrier); + $this->bootstrap = true; + $this->table = 'carrier'; + $this->className = 'Carrier'; + $this->lang = false; + $this->deleted = true; - $this->bootstrap = true; - $this->table = 'carrier'; - $this->className = 'Carrier'; - $this->lang = false; - $this->deleted = true; + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->_defaultOrderBy = 'position'; - $this->_defaultOrderBy = 'position'; + $this->context = Context::getContext(); - $this->context = Context::getContext(); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->fieldImageSettings = array( + 'name' => 'logo', + 'dir' => 's' + ); - $this->fieldImageSettings = array( - 'name' => 'logo', - 'dir' => 's' - ); + $this->fields_list = array( + 'id_carrier' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Name') + ), + 'image' => array( + 'title' => $this->l('Logo'), + 'align' => 'center', + 'image' => 's', + 'class' => 'fixed-width-xs', + 'orderby' => false, + 'search' => false + ), + 'delay' => array( + 'title' => $this->l('Delay'), + 'orderby' => false + ), + 'active' => array( + 'title' => $this->l('Status'), + 'align' => 'center', + 'active' => 'status', + 'type' => 'bool', + 'class' => 'fixed-width-sm', + 'orderby' => false, + ), + 'is_free' => array( + 'title' => $this->l('Free Shipping'), + 'align' => 'center', + 'active' => 'isFree', + 'type' => 'bool', + 'class' => 'fixed-width-sm', + 'orderby' => false, + ), + 'position' => array( + 'title' => $this->l('Position'), + 'filter_key' => 'a!position', + 'align' => 'center', + 'class' => 'fixed-width-sm', + 'position' => 'position' + ) + ); + parent::__construct(); - $this->fields_list = array( - 'id_carrier' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Name') - ), - 'image' => array( - 'title' => $this->l('Logo'), - 'align' => 'center', - 'image' => 's', - 'class' => 'fixed-width-xs', - 'orderby' => false, - 'search' => false - ), - 'delay' => array( - 'title' => $this->l('Delay'), - 'orderby' => false - ), - 'active' => array( - 'title' => $this->l('Status'), - 'align' => 'center', - 'active' => 'status', - 'type' => 'bool', - 'class' => 'fixed-width-sm', - 'orderby' => false, - ), - 'is_free' => array( - 'title' => $this->l('Free Shipping'), - 'align' => 'center', - 'active' => 'isFree', - 'type' => 'bool', - 'class' => 'fixed-width-sm', - 'orderby' => false, - ), - 'position' => array( - 'title' => $this->l('Position'), - 'filter_key' => 'a!position', - 'align' => 'center', - 'class' => 'fixed-width-sm', - 'position' => 'position' - ) - ); - parent::__construct(); - - if (Tools::isSubmit('onboarding_carrier')) - $this->display = 'view'; - } + if (Tools::isSubmit('onboarding_carrier')) { + $this->display = 'view'; + } + } - public function initToolbar() - { - parent::initToolbar(); - - if (isset($this->toolbar_btn['new']) && $this->display != 'view') - $this->toolbar_btn['new']['href'] = $this->context->link->getAdminLink('AdminCarriers').'&onboarding_carrier'; - } + public function initToolbar() + { + parent::initToolbar(); - public function initPageHeaderToolbar() - { - $this->page_header_toolbar_title = $this->l('Carriers'); - if ($this->display != 'view') - $this->page_header_toolbar_btn['new_carrier'] = array( - 'href' => $this->context->link->getAdminLink('AdminCarriers').'&onboarding_carrier', - 'desc' => $this->l('Add new carrier', null, null, false), - 'icon' => 'process-icon-new' - ); + if (isset($this->toolbar_btn['new']) && $this->display != 'view') { + $this->toolbar_btn['new']['href'] = $this->context->link->getAdminLink('AdminCarriers').'&onboarding_carrier'; + } + } - parent::initPageHeaderToolbar(); - } - - public function renderView() - { - $this->initTabModuleList(); - $this->filterTabModuleList(); - $this->context->smarty->assign('panel_title', $this->l('Use one of our recommended carrier modules')); - $this->tpl_view_vars = array('modules_list' => $this->renderModulesList()); - unset($this->page_header_toolbar_btn['modules-list']); - return parent::renderView(); - } - - public function renderList() - { - $this->_select = 'b.*'; - $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'carrier_lang` b ON a.id_carrier = b.id_carrier'.Shop::addSqlRestrictionOnLang('b').' AND b.id_lang = '.$this->context->language->id.' LEFT JOIN `'._DB_PREFIX_.'carrier_tax_rules_group_shop` ctrgs ON (a.`id_carrier` = ctrgs.`id_carrier` AND ctrgs.id_shop='.(int)$this->context->shop->id.')'; - $this->_use_found_rows = false; - return parent::renderList(); - } + public function initPageHeaderToolbar() + { + $this->page_header_toolbar_title = $this->l('Carriers'); + if ($this->display != 'view') { + $this->page_header_toolbar_btn['new_carrier'] = array( + 'href' => $this->context->link->getAdminLink('AdminCarriers').'&onboarding_carrier', + 'desc' => $this->l('Add new carrier', null, null, false), + 'icon' => 'process-icon-new' + ); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Carriers'), - 'icon' => 'icon-truck' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Company'), - 'name' => 'name', - 'required' => true, - 'hint' => array( - sprintf($this->l('Allowed characters: letters, spaces and %s'), '().-'), - $this->l('Carrier name displayed during checkout'), - $this->l('For in-store pickup, enter 0 to replace the carrier name with your shop name.') - ) - ), - array( - 'type' => 'file', - 'label' => $this->l('Logo'), - 'name' => 'logo', - 'hint' => $this->l('Upload a logo from your computer.').' (.gif, .jpg, .jpeg '.$this->l('or').' .png)' - ), - array( - 'type' => 'text', - 'label' => $this->l('Transit time'), - 'name' => 'delay', - 'lang' => true, - 'required' => true, - 'maxlength' => 128, - 'hint' => $this->l('Estimated delivery time will be displayed during checkout.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Speed grade'), - 'name' => 'grade', - 'required' => false, - 'hint' => $this->l('Enter "0" for a longest shipping delay, or "9" for the shortest shipping delay.') - ), - array( - 'type' => 'text', - 'label' => $this->l('URL'), - 'name' => 'url', - 'hint' => $this->l('Delivery tracking URL: Type \'@\' where the tracking number should appear. It will then be automatically replaced by the tracking number.') - ), - array( - 'type' => 'checkbox', - 'label' => $this->l('Zone'), - 'name' => 'zone', - 'values' => array( - 'query' => Zone::getZones(false), - 'id' => 'id_zone', - 'name' => 'name' - ), - 'hint' => $this->l('The zones in which this carrier will be used.') - ), - array( - 'type' => 'group', - 'label' => $this->l('Group access'), - 'name' => 'groupBox', - 'values' => Group::getGroups(Context::getContext()->language->id), - 'hint' => $this->l('Mark the groups that are allowed access to this carrier.') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Status'), - 'name' => 'active', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Enable the carrier in the front office.') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Apply shipping cost'), - 'name' => 'is_free', - 'required' => false, - 'class' => 't', - 'values' => array( - array( - 'id' => 'is_free_on', - 'value' => 0, - 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Yes').'" title="'.$this->l('Yes').'" />' - ), - array( - 'id' => 'is_free_off', - 'value' => 1, - 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('No').'" title="'.$this->l('No').'" />' - ) - ), - 'hint' => $this->l('Apply both regular shipping cost and product-specific shipping costs.') - ), - array( - 'type' => 'select', - 'label' => $this->l('Tax'), - 'name' => 'id_tax_rules_group', - 'options' => array( - 'query' => TaxRulesGroup::getTaxRulesGroups(true), - 'id' => 'id_tax_rules_group', - 'name' => 'name', - 'default' => array( - 'label' => $this->l('No Tax'), - 'value' => 0 - ) - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Shipping and handling'), - 'name' => 'shipping_handling', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'shipping_handling_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'shipping_handling_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Include the shipping and handling costs in the carrier price.') - ), - array( - 'type' => 'radio', - 'label' => $this->l('Billing'), - 'name' => 'shipping_method', - 'required' => false, - 'class' => 't', - 'br' => true, - 'values' => array( - array( - 'id' => 'billing_default', - 'value' => Carrier::SHIPPING_METHOD_DEFAULT, - 'label' => $this->l('Default behavior') - ), - array( - 'id' => 'billing_price', - 'value' => Carrier::SHIPPING_METHOD_PRICE, - 'label' => $this->l('According to total price') - ), - array( - 'id' => 'billing_weight', - 'value' => Carrier::SHIPPING_METHOD_WEIGHT, - 'label' => $this->l('According to total weight') - ) - ) - ), - array( - 'type' => 'select', - 'label' => $this->l('Out-of-range behavior'), - 'name' => 'range_behavior', - 'options' => array( - 'query' => array( - array( - 'id' => 0, - 'name' => $this->l('Apply the cost of the highest defined range') - ), - array( - 'id' => 1, - 'name' => $this->l('Disable carrier') - ) - ), - 'id' => 'id', - 'name' => 'name' - ), - 'hint' => $this->l('Out-of-range behavior occurs when none is defined (e.g. when a customer\'s cart weight is greater than the highest range limit).') - ), - array( - 'type' => 'text', - 'label' => $this->l('Maximum package height'), - 'name' => 'max_height', - 'required' => false, - 'hint' => $this->l('Maximum height managed by this carrier. Set the value to "0," or leave this field blank to ignore.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Maximum package width'), - 'name' => 'max_width', - 'required' => false, - 'hint' => $this->l('Maximum width managed by this carrier. Set the value to "0," or leave this field blank to ignore.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Maximum package depth'), - 'name' => 'max_depth', - 'required' => false, - 'hint' => $this->l('Maximum depth managed by this carrier. Set the value to "0," or leave this field blank to ignore.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Maximum package weight'), - 'name' => 'max_weight', - 'required' => false, - 'hint' => $this->l('Maximum weight managed by this carrier. Set the value to "0," or leave this field blank to ignore.') - ), - array( - 'type' => 'hidden', - 'name' => 'is_module' - ), - array( - 'type' => 'hidden', - 'name' => 'external_module_name', - ), - array( - 'type' => 'hidden', - 'name' => 'shipping_external' - ), - array( - 'type' => 'hidden', - 'name' => 'need_range' - ), - ) - ); + parent::initPageHeaderToolbar(); + } - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + public function renderView() + { + $this->initTabModuleList(); + $this->filterTabModuleList(); + $this->context->smarty->assign('panel_title', $this->l('Use one of our recommended carrier modules')); + $this->tpl_view_vars = array('modules_list' => $this->renderModulesList()); + unset($this->page_header_toolbar_btn['modules-list']); + return parent::renderView(); + } - $this->fields_form['submit'] = array( - 'title' => $this->l('Save'), - ); + public function renderList() + { + $this->_select = 'b.*'; + $this->_join = 'INNER JOIN `'._DB_PREFIX_.'carrier_lang` b ON a.id_carrier = b.id_carrier'.Shop::addSqlRestrictionOnLang('b').' AND b.id_lang = '.$this->context->language->id.' LEFT JOIN `'._DB_PREFIX_.'carrier_tax_rules_group_shop` ctrgs ON (a.`id_carrier` = ctrgs.`id_carrier` AND ctrgs.id_shop='.(int)$this->context->shop->id.')'; + $this->_use_found_rows = false; + return parent::renderList(); + } - if (!($obj = $this->loadObject(true))) - return; + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Carriers'), + 'icon' => 'icon-truck' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Company'), + 'name' => 'name', + 'required' => true, + 'hint' => array( + sprintf($this->l('Allowed characters: letters, spaces and %s'), '().-'), + $this->l('Carrier name displayed during checkout'), + $this->l('For in-store pickup, enter 0 to replace the carrier name with your shop name.') + ) + ), + array( + 'type' => 'file', + 'label' => $this->l('Logo'), + 'name' => 'logo', + 'hint' => $this->l('Upload a logo from your computer.').' (.gif, .jpg, .jpeg '.$this->l('or').' .png)' + ), + array( + 'type' => 'text', + 'label' => $this->l('Transit time'), + 'name' => 'delay', + 'lang' => true, + 'required' => true, + 'maxlength' => 128, + 'hint' => $this->l('Estimated delivery time will be displayed during checkout.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Speed grade'), + 'name' => 'grade', + 'required' => false, + 'hint' => $this->l('Enter "0" for a longest shipping delay, or "9" for the shortest shipping delay.') + ), + array( + 'type' => 'text', + 'label' => $this->l('URL'), + 'name' => 'url', + 'hint' => $this->l('Delivery tracking URL: Type \'@\' where the tracking number should appear. It will then be automatically replaced by the tracking number.') + ), + array( + 'type' => 'checkbox', + 'label' => $this->l('Zone'), + 'name' => 'zone', + 'values' => array( + 'query' => Zone::getZones(false), + 'id' => 'id_zone', + 'name' => 'name' + ), + 'hint' => $this->l('The zones in which this carrier will be used.') + ), + array( + 'type' => 'group', + 'label' => $this->l('Group access'), + 'name' => 'groupBox', + 'values' => Group::getGroups(Context::getContext()->language->id), + 'hint' => $this->l('Mark the groups that are allowed access to this carrier.') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Status'), + 'name' => 'active', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Enable the carrier in the front office.') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Apply shipping cost'), + 'name' => 'is_free', + 'required' => false, + 'class' => 't', + 'values' => array( + array( + 'id' => 'is_free_on', + 'value' => 0, + 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Yes').'" title="'.$this->l('Yes').'" />' + ), + array( + 'id' => 'is_free_off', + 'value' => 1, + 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('No').'" title="'.$this->l('No').'" />' + ) + ), + 'hint' => $this->l('Apply both regular shipping cost and product-specific shipping costs.') + ), + array( + 'type' => 'select', + 'label' => $this->l('Tax'), + 'name' => 'id_tax_rules_group', + 'options' => array( + 'query' => TaxRulesGroup::getTaxRulesGroups(true), + 'id' => 'id_tax_rules_group', + 'name' => 'name', + 'default' => array( + 'label' => $this->l('No Tax'), + 'value' => 0 + ) + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Shipping and handling'), + 'name' => 'shipping_handling', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'shipping_handling_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'shipping_handling_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Include the shipping and handling costs in the carrier price.') + ), + array( + 'type' => 'radio', + 'label' => $this->l('Billing'), + 'name' => 'shipping_method', + 'required' => false, + 'class' => 't', + 'br' => true, + 'values' => array( + array( + 'id' => 'billing_default', + 'value' => Carrier::SHIPPING_METHOD_DEFAULT, + 'label' => $this->l('Default behavior') + ), + array( + 'id' => 'billing_price', + 'value' => Carrier::SHIPPING_METHOD_PRICE, + 'label' => $this->l('According to total price') + ), + array( + 'id' => 'billing_weight', + 'value' => Carrier::SHIPPING_METHOD_WEIGHT, + 'label' => $this->l('According to total weight') + ) + ) + ), + array( + 'type' => 'select', + 'label' => $this->l('Out-of-range behavior'), + 'name' => 'range_behavior', + 'options' => array( + 'query' => array( + array( + 'id' => 0, + 'name' => $this->l('Apply the cost of the highest defined range') + ), + array( + 'id' => 1, + 'name' => $this->l('Disable carrier') + ) + ), + 'id' => 'id', + 'name' => 'name' + ), + 'hint' => $this->l('Out-of-range behavior occurs when none is defined (e.g. when a customer\'s cart weight is greater than the highest range limit).') + ), + array( + 'type' => 'text', + 'label' => $this->l('Maximum package height'), + 'name' => 'max_height', + 'required' => false, + 'hint' => $this->l('Maximum height managed by this carrier. Set the value to "0," or leave this field blank to ignore.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Maximum package width'), + 'name' => 'max_width', + 'required' => false, + 'hint' => $this->l('Maximum width managed by this carrier. Set the value to "0," or leave this field blank to ignore.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Maximum package depth'), + 'name' => 'max_depth', + 'required' => false, + 'hint' => $this->l('Maximum depth managed by this carrier. Set the value to "0," or leave this field blank to ignore.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Maximum package weight'), + 'name' => 'max_weight', + 'required' => false, + 'hint' => $this->l('Maximum weight managed by this carrier. Set the value to "0," or leave this field blank to ignore.') + ), + array( + 'type' => 'hidden', + 'name' => 'is_module' + ), + array( + 'type' => 'hidden', + 'name' => 'external_module_name', + ), + array( + 'type' => 'hidden', + 'name' => 'shipping_external' + ), + array( + 'type' => 'hidden', + 'name' => 'need_range' + ), + ) + ); - $this->getFieldsValues($obj); - return parent::renderForm(); - } + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - public function postProcess() - { - if (Tools::getValue('action') == 'GetModuleQuickView' && Tools::getValue('ajax') == '1') - $this->ajaxProcessGetModuleQuickView(); - - if (Tools::getValue('submitAdd'.$this->table)) - { - /* Checking fields validity */ - $this->validateRules(); - if (!count($this->errors)) - { - $id = (int)Tools::getValue('id_'.$this->table); + $this->fields_form['submit'] = array( + 'title' => $this->l('Save'), + ); - /* Object update */ - if (isset($id) && !empty($id)) - { - try { - if ($this->tabAccess['edit'] === '1') - { - $current_carrier = new Carrier($id); - if (!Validate::isLoadedObject($current_carrier)) - throw new PrestaShopException('Cannot load Carrier object'); + if (!($obj = $this->loadObject(true))) { + return; + } - /** @var Carrier $new_carrier */ - // Duplicate current Carrier - $new_carrier = $current_carrier->duplicateObject(); - if (Validate::isLoadedObject($new_carrier)) - { - // Set flag deteled to true for historization - $current_carrier->deleted = true; - $current_carrier->update(); + $this->getFieldsValues($obj); + return parent::renderForm(); + } - // Fill the new carrier object - $this->copyFromPost($new_carrier, $this->table); - $new_carrier->position = $current_carrier->position; - $new_carrier->update(); + public function postProcess() + { + if (Tools::getValue('action') == 'GetModuleQuickView' && Tools::getValue('ajax') == '1') { + $this->ajaxProcessGetModuleQuickView(); + } - $this->updateAssoShop($new_carrier->id); - $new_carrier->copyCarrierData((int)$current_carrier->id); - $this->changeGroups($new_carrier->id); - // Call of hooks - Hook::exec('actionCarrierUpdate', array( - 'id_carrier' => (int)$current_carrier->id, - 'carrier' => $new_carrier - )); - $this->postImage($new_carrier->id); - $this->changeZones($new_carrier->id); - $new_carrier->setTaxRulesGroup((int)Tools::getValue('id_tax_rules_group')); - Tools::redirectAdmin(self::$currentIndex.'&id_'.$this->table.'='.$current_carrier->id.'&conf=4&token='.$this->token); - } - else - $this->errors[] = Tools::displayError('An error occurred while updating an object.').' <b>'.$this->table.'</b>'; - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } catch (PrestaShopException $e) { - $this->errors[] = $e->getMessage(); - } - } + if (Tools::getValue('submitAdd'.$this->table)) { + /* Checking fields validity */ + $this->validateRules(); + if (!count($this->errors)) { + $id = (int)Tools::getValue('id_'.$this->table); - /* Object creation */ - else - { - if ($this->tabAccess['add'] === '1') - { - // Create new Carrier - $carrier = new Carrier(); - $this->copyFromPost($carrier, $this->table); - $carrier->position = Carrier::getHigherPosition() + 1; - if ($carrier->add()) - { - if (($_POST['id_'.$this->table] = $carrier->id /* voluntary */) && $this->postImage($carrier->id) && $this->_redirect) - { - $carrier->setTaxRulesGroup((int)Tools::getValue('id_tax_rules_group'), true); - $this->changeZones($carrier->id); - $this->changeGroups($carrier->id); - $this->updateAssoShop($carrier->id); - Tools::redirectAdmin(self::$currentIndex.'&id_'.$this->table.'='.$carrier->id.'&conf=3&token='.$this->token); - } - } - else - $this->errors[] = Tools::displayError('An error occurred while creating an object.').' <b>'.$this->table.'</b>'; - } - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - } - parent::postProcess(); - } - /* + /* Object update */ + if (isset($id) && !empty($id)) { + try { + if ($this->tabAccess['edit'] === '1') { + $current_carrier = new Carrier($id); + if (!Validate::isLoadedObject($current_carrier)) { + throw new PrestaShopException('Cannot load Carrier object'); + } + + /** @var Carrier $new_carrier */ + // Duplicate current Carrier + $new_carrier = $current_carrier->duplicateObject(); + if (Validate::isLoadedObject($new_carrier)) { + // Set flag deteled to true for historization + $current_carrier->deleted = true; + $current_carrier->update(); + + // Fill the new carrier object + $this->copyFromPost($new_carrier, $this->table); + $new_carrier->position = $current_carrier->position; + $new_carrier->update(); + + $this->updateAssoShop($new_carrier->id); + $new_carrier->copyCarrierData((int)$current_carrier->id); + $this->changeGroups($new_carrier->id); + // Call of hooks + Hook::exec('actionCarrierUpdate', array( + 'id_carrier' => (int)$current_carrier->id, + 'carrier' => $new_carrier + )); + $this->postImage($new_carrier->id); + $this->changeZones($new_carrier->id); + $new_carrier->setTaxRulesGroup((int)Tools::getValue('id_tax_rules_group')); + Tools::redirectAdmin(self::$currentIndex.'&id_'.$this->table.'='.$current_carrier->id.'&conf=4&token='.$this->token); + } else { + $this->errors[] = Tools::displayError('An error occurred while updating an object.').' <b>'.$this->table.'</b>'; + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } catch (PrestaShopException $e) { + $this->errors[] = $e->getMessage(); + } + } + + /* Object creation */ + else { + if ($this->tabAccess['add'] === '1') { + // Create new Carrier + $carrier = new Carrier(); + $this->copyFromPost($carrier, $this->table); + $carrier->position = Carrier::getHigherPosition() + 1; + if ($carrier->add()) { + if (($_POST['id_'.$this->table] = $carrier->id /* voluntary */) && $this->postImage($carrier->id) && $this->_redirect) { + $carrier->setTaxRulesGroup((int)Tools::getValue('id_tax_rules_group'), true); + $this->changeZones($carrier->id); + $this->changeGroups($carrier->id); + $this->updateAssoShop($carrier->id); + Tools::redirectAdmin(self::$currentIndex.'&id_'.$this->table.'='.$carrier->id.'&conf=3&token='.$this->token); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while creating an object.').' <b>'.$this->table.'</b>'; + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } + } + parent::postProcess(); + } + /* elseif ((isset($_GET['status'.$this->table]) || isset($_GET['status'])) && Tools::getValue($this->identifier)) - { - if ($this->tabAccess['edit'] === '1') - { - if (Tools::getValue('id_carrier') == Configuration::get('PS_CARRIER_DEFAULT')) - $this->errors[] = Tools::displayError('You cannot disable the default carrier, however you can change your default carrier. '); - else - parent::postProcess(); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } + { + if ($this->tabAccess['edit'] === '1') + { + if (Tools::getValue('id_carrier') == Configuration::get('PS_CARRIER_DEFAULT')) + $this->errors[] = Tools::displayError('You cannot disable the default carrier, however you can change your default carrier. '); + else + parent::postProcess(); + } + else + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } */ - elseif (isset($_GET['isFree'.$this->table])) - { - $this->processIsFree(); - } - else - { - /* - if ((Tools::isSubmit('submitDel'.$this->table) && in_array(Configuration::get('PS_CARRIER_DEFAULT'), Tools::getValue('carrierBox'))) - || (isset($_GET['delete'.$this->table]) && Tools::getValue('id_carrier') == Configuration::get('PS_CARRIER_DEFAULT'))) - $this->errors[] = $this->l('Please set another carrier as default before deleting this one.'); - else - { + elseif (isset($_GET['isFree'.$this->table])) { + $this->processIsFree(); + } else { + /* + if ((Tools::isSubmit('submitDel'.$this->table) && in_array(Configuration::get('PS_CARRIER_DEFAULT'), Tools::getValue('carrierBox'))) + || (isset($_GET['delete'.$this->table]) && Tools::getValue('id_carrier') == Configuration::get('PS_CARRIER_DEFAULT'))) + $this->errors[] = $this->l('Please set another carrier as default before deleting this one.'); + else + { */ - // if deletion : removes the carrier from the warehouse/carrier association - if (Tools::isSubmit('delete'.$this->table)) - { - $id = (int)Tools::getValue('id_'.$this->table); - // Delete from the reference_id and not from the carrier id - $carrier = new Carrier((int)$id); - Warehouse::removeCarrier($carrier->id_reference); - } - elseif (Tools::isSubmit($this->table.'Box') && count(Tools::isSubmit($this->table.'Box')) > 0) - { - $ids = Tools::getValue($this->table.'Box'); - array_walk($ids, 'intval'); - foreach ($ids as $id) - { - // Delete from the reference_id and not from the carrier id - $carrier = new Carrier((int)$id); - Warehouse::removeCarrier($carrier->id_reference); - } - } - parent::postProcess(); - Carrier::cleanPositions(); - //} - } - } + // if deletion : removes the carrier from the warehouse/carrier association + if (Tools::isSubmit('delete'.$this->table)) { + $id = (int)Tools::getValue('id_'.$this->table); + // Delete from the reference_id and not from the carrier id + $carrier = new Carrier((int)$id); + Warehouse::removeCarrier($carrier->id_reference); + } elseif (Tools::isSubmit($this->table.'Box') && count(Tools::isSubmit($this->table.'Box')) > 0) { + $ids = Tools::getValue($this->table.'Box'); + array_walk($ids, 'intval'); + foreach ($ids as $id) { + // Delete from the reference_id and not from the carrier id + $carrier = new Carrier((int)$id); + Warehouse::removeCarrier($carrier->id_reference); + } + } + parent::postProcess(); + Carrier::cleanPositions(); + //} + } + } - public function processIsFree() - { - $carrier = new Carrier($this->id_object); - if (!Validate::isLoadedObject($carrier)) - $this->errors[] = Tools::displayError('An error occurred while updating carrier information.'); - $carrier->is_free = $carrier->is_free ? 0 : 1; - if (!$carrier->update()) - $this->errors[] = Tools::displayError('An error occurred while updating carrier information.'); - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); - } + public function processIsFree() + { + $carrier = new Carrier($this->id_object); + if (!Validate::isLoadedObject($carrier)) { + $this->errors[] = Tools::displayError('An error occurred while updating carrier information.'); + } + $carrier->is_free = $carrier->is_free ? 0 : 1; + if (!$carrier->update()) { + $this->errors[] = Tools::displayError('An error occurred while updating carrier information.'); + } + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } - /** - * Overload the property $fields_value - * - * @param object $obj - */ - public function getFieldsValues($obj) - { - if ($this->getFieldValue($obj, 'is_module')) - $this->fields_value['is_module'] = 1; + /** + * Overload the property $fields_value + * + * @param object $obj + */ + public function getFieldsValues($obj) + { + if ($this->getFieldValue($obj, 'is_module')) { + $this->fields_value['is_module'] = 1; + } - if ($this->getFieldValue($obj, 'shipping_external')) - $this->fields_value['shipping_external'] = 1; + if ($this->getFieldValue($obj, 'shipping_external')) { + $this->fields_value['shipping_external'] = 1; + } - if ($this->getFieldValue($obj, 'need_range')) - $this->fields_value['need_range'] = 1; - // Added values of object Zone - $carrier_zones = $obj->getZones(); - $carrier_zones_ids = array(); - if (is_array($carrier_zones)) - foreach ($carrier_zones as $carrier_zone) - $carrier_zones_ids[] = $carrier_zone['id_zone']; + if ($this->getFieldValue($obj, 'need_range')) { + $this->fields_value['need_range'] = 1; + } + // Added values of object Zone + $carrier_zones = $obj->getZones(); + $carrier_zones_ids = array(); + if (is_array($carrier_zones)) { + foreach ($carrier_zones as $carrier_zone) { + $carrier_zones_ids[] = $carrier_zone['id_zone']; + } + } - $zones = Zone::getZones(false); - foreach ($zones as $zone) - $this->fields_value['zone_'.$zone['id_zone']] = Tools::getValue('zone_'.$zone['id_zone'], (in_array($zone['id_zone'], $carrier_zones_ids))); + $zones = Zone::getZones(false); + foreach ($zones as $zone) { + $this->fields_value['zone_'.$zone['id_zone']] = Tools::getValue('zone_'.$zone['id_zone'], (in_array($zone['id_zone'], $carrier_zones_ids))); + } - // Added values of object Group - $carrier_groups = $obj->getGroups(); - $carrier_groups_ids = array(); - if (is_array($carrier_groups)) - foreach ($carrier_groups as $carrier_group) - $carrier_groups_ids[] = $carrier_group['id_group']; + // Added values of object Group + $carrier_groups = $obj->getGroups(); + $carrier_groups_ids = array(); + if (is_array($carrier_groups)) { + foreach ($carrier_groups as $carrier_group) { + $carrier_groups_ids[] = $carrier_group['id_group']; + } + } - $groups = Group::getGroups($this->context->language->id); + $groups = Group::getGroups($this->context->language->id); - foreach ($groups as $group) - $this->fields_value['groupBox_'.$group['id_group']] = Tools::getValue('groupBox_'.$group['id_group'], (in_array($group['id_group'], $carrier_groups_ids) || empty($carrier_groups_ids) && !$obj->id)); + foreach ($groups as $group) { + $this->fields_value['groupBox_'.$group['id_group']] = Tools::getValue('groupBox_'.$group['id_group'], (in_array($group['id_group'], $carrier_groups_ids) || empty($carrier_groups_ids) && !$obj->id)); + } - $this->fields_value['id_tax_rules_group'] = $this->object->getIdTaxRulesGroup($this->context); - } + $this->fields_value['id_tax_rules_group'] = $this->object->getIdTaxRulesGroup($this->context); + } - /** - * @param Carrier $object - * @return int - */ - protected function beforeDelete($object) - { - return $object->isUsed(); - } + /** + * @param Carrier $object + * @return int + */ + protected function beforeDelete($object) + { + return $object->isUsed(); + } - protected function changeGroups($id_carrier, $delete = true) - { - if ($delete) - Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'carrier_group WHERE id_carrier = '.(int)$id_carrier); - $groups = Db::getInstance()->executeS('SELECT id_group FROM `'._DB_PREFIX_.'group`'); - foreach ($groups as $group) - if (Tools::getIsset('groupBox') && in_array($group['id_group'], Tools::getValue('groupBox'))) - Db::getInstance()->execute(' + protected function changeGroups($id_carrier, $delete = true) + { + if ($delete) { + Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'carrier_group WHERE id_carrier = '.(int)$id_carrier); + } + $groups = Db::getInstance()->executeS('SELECT id_group FROM `'._DB_PREFIX_.'group`'); + foreach ($groups as $group) { + if (Tools::getIsset('groupBox') && in_array($group['id_group'], Tools::getValue('groupBox'))) { + Db::getInstance()->execute(' INSERT INTO '._DB_PREFIX_.'carrier_group (id_group, id_carrier) VALUES('.(int)$group['id_group'].','.(int)$id_carrier.') '); - } + } + } + } - public function changeZones($id) - { - /** @var Carrier $carrier */ - $carrier = new $this->className($id); - if (!Validate::isLoadedObject($carrier)) - die (Tools::displayError('The object cannot be loaded.')); - $zones = Zone::getZones(false); - foreach ($zones as $zone) - if (count($carrier->getZone($zone['id_zone']))) - { - if (!isset($_POST['zone_'.$zone['id_zone']]) || !$_POST['zone_'.$zone['id_zone']]) - $carrier->deleteZone($zone['id_zone']); - } - else - if (isset($_POST['zone_'.$zone['id_zone']]) && $_POST['zone_'.$zone['id_zone']]) - $carrier->addZone($zone['id_zone']); - } + public function changeZones($id) + { + /** @var Carrier $carrier */ + $carrier = new $this->className($id); + if (!Validate::isLoadedObject($carrier)) { + die(Tools::displayError('The object cannot be loaded.')); + } + $zones = Zone::getZones(false); + foreach ($zones as $zone) { + if (count($carrier->getZone($zone['id_zone']))) { + if (!isset($_POST['zone_'.$zone['id_zone']]) || !$_POST['zone_'.$zone['id_zone']]) { + $carrier->deleteZone($zone['id_zone']); + } + } elseif (isset($_POST['zone_'.$zone['id_zone']]) && $_POST['zone_'.$zone['id_zone']]) { + $carrier->addZone($zone['id_zone']); + } + } + } - /** - * Modifying initial getList method to display position feature (drag and drop) - * - * @param int $id_lang - * @param string|null $order_by - * @param string|null $order_way - * @param int $start - * @param int|null $limit - * @param int|bool $id_lang_shop - * - * @throws PrestaShopException - */ - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + /** + * Modifying initial getList method to display position feature (drag and drop) + * + * @param int $id_lang + * @param string|null $order_by + * @param string|null $order_way + * @param int $start + * @param int|null $limit + * @param int|bool $id_lang_shop + * + * @throws PrestaShopException + */ + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - foreach ($this->_list as $key => $list) - if ($list['name'] == '0') - $this->_list[$key]['name'] = Carrier::getCarrierNameFromShopName(); - } + foreach ($this->_list as $key => $list) { + if ($list['name'] == '0') { + $this->_list[$key]['name'] = Carrier::getCarrierNameFromShopName(); + } + } + } - public function ajaxProcessUpdatePositions() - { - $way = (int)(Tools::getValue('way')); - $id_carrier = (int)(Tools::getValue('id')); - $positions = Tools::getValue($this->table); + public function ajaxProcessUpdatePositions() + { + $way = (int)(Tools::getValue('way')); + $id_carrier = (int)(Tools::getValue('id')); + $positions = Tools::getValue($this->table); - foreach ($positions as $position => $value) - { - $pos = explode('_', $value); + foreach ($positions as $position => $value) { + $pos = explode('_', $value); - if (isset($pos[2]) && (int)$pos[2] === $id_carrier) - { - if ($carrier = new Carrier((int)$pos[2])) - if (isset($position) && $carrier->updatePosition($way, $position)) - echo 'ok position '.(int)$position.' for carrier '.(int)$pos[1].'\r\n'; - else - echo '{"hasError" : true, "errors" : "Can not update carrier '.(int)$id_carrier.' to position '.(int)$position.' "}'; - else - echo '{"hasError" : true, "errors" : "This carrier ('.(int)$id_carrier.') can t be loaded"}'; + if (isset($pos[2]) && (int)$pos[2] === $id_carrier) { + if ($carrier = new Carrier((int)$pos[2])) { + if (isset($position) && $carrier->updatePosition($way, $position)) { + echo 'ok position '.(int)$position.' for carrier '.(int)$pos[1].'\r\n'; + } else { + echo '{"hasError" : true, "errors" : "Can not update carrier '.(int)$id_carrier.' to position '.(int)$position.' "}'; + } + } else { + echo '{"hasError" : true, "errors" : "This carrier ('.(int)$id_carrier.') can t be loaded"}'; + } - break; - } - } - } + break; + } + } + } - public function displayEditLink($token = null, $id, $name = null) - { - if ($this->tabAccess['edit'] == 1) - { - $tpl = $this->createTemplate('helpers/list/list_action_edit.tpl'); - if (!array_key_exists('Edit', self::$cache_lang)) - self::$cache_lang['Edit'] = $this->l('Edit', 'Helper'); + public function displayEditLink($token = null, $id, $name = null) + { + if ($this->tabAccess['edit'] == 1) { + $tpl = $this->createTemplate('helpers/list/list_action_edit.tpl'); + if (!array_key_exists('Edit', self::$cache_lang)) { + self::$cache_lang['Edit'] = $this->l('Edit', 'Helper'); + } - $tpl->assign(array( - 'href' => $this->context->link->getAdminLink('AdminCarrierWizard').'&id_carrier='.(int)$id, - 'action' => self::$cache_lang['Edit'], - 'id' => $id - )); + $tpl->assign(array( + 'href' => $this->context->link->getAdminLink('AdminCarrierWizard').'&id_carrier='.(int)$id, + 'action' => self::$cache_lang['Edit'], + 'id' => $id + )); - return $tpl->fetch(); - } - else - return; - } - - public function displayDeleteLink($token = null, $id, $name = null) - { - if ($this->tabAccess['delete'] == 1) - { - $tpl = $this->createTemplate('helpers/list/list_action_delete.tpl'); + return $tpl->fetch(); + } else { + return; + } + } - if (!array_key_exists('Delete', self::$cache_lang)) - self::$cache_lang['Delete'] = $this->l('Delete', 'Helper'); + public function displayDeleteLink($token = null, $id, $name = null) + { + if ($this->tabAccess['delete'] == 1) { + $tpl = $this->createTemplate('helpers/list/list_action_delete.tpl'); - if (!array_key_exists('DeleteItem', self::$cache_lang)) - self::$cache_lang['DeleteItem'] = $this->l('Delete selected item?', 'Helper'); + if (!array_key_exists('Delete', self::$cache_lang)) { + self::$cache_lang['Delete'] = $this->l('Delete', 'Helper'); + } - if (!array_key_exists('Name', self::$cache_lang)) - self::$cache_lang['Name'] = $this->l('Name:', 'Helper'); + if (!array_key_exists('DeleteItem', self::$cache_lang)) { + self::$cache_lang['DeleteItem'] = $this->l('Delete selected item?', 'Helper'); + } - if (!is_null($name)) - $name = '\n\n'.self::$cache_lang['Name'].' '.$name; + if (!array_key_exists('Name', self::$cache_lang)) { + self::$cache_lang['Name'] = $this->l('Name:', 'Helper'); + } - $data = array( - $this->identifier => $id, - 'href' => $this->context->link->getAdminLink('AdminCarriers').'&id_carrier='.(int)$id.'&deletecarrier=1', - 'action' => self::$cache_lang['Delete'], - ); + if (!is_null($name)) { + $name = '\n\n'.self::$cache_lang['Name'].' '.$name; + } - if ($this->specificConfirmDelete !== false) - $data['confirm'] = !is_null($this->specificConfirmDelete) ? '\r'.$this->specificConfirmDelete : addcslashes(Tools::htmlentitiesDecodeUTF8(self::$cache_lang['DeleteItem'].$name), '\''); + $data = array( + $this->identifier => $id, + 'href' => $this->context->link->getAdminLink('AdminCarriers').'&id_carrier='.(int)$id.'&deletecarrier=1', + 'action' => self::$cache_lang['Delete'], + ); - $tpl->assign(array_merge($this->tpl_delete_link_vars, $data)); + if ($this->specificConfirmDelete !== false) { + $data['confirm'] = !is_null($this->specificConfirmDelete) ? '\r'.$this->specificConfirmDelete : addcslashes(Tools::htmlentitiesDecodeUTF8(self::$cache_lang['DeleteItem'].$name), '\''); + } - return $tpl->fetch(); - } - else - return; - } - - protected function initTabModuleList() - { - if (Tools::isSubmit('onboarding_carrier')) - { - parent::initTabModuleList(); - $this->filter_modules_list = $this->tab_modules_list['default_list'] = $this->tab_modules_list['slider_list']; - } - } + $tpl->assign(array_merge($this->tpl_delete_link_vars, $data)); + + return $tpl->fetch(); + } else { + return; + } + } + + protected function initTabModuleList() + { + if (Tools::isSubmit('onboarding_carrier')) { + parent::initTabModuleList(); + $this->filter_modules_list = $this->tab_modules_list['default_list'] = $this->tab_modules_list['slider_list']; + } + } } - - diff --git a/controllers/admin/AdminCartRulesController.php b/controllers/admin/AdminCartRulesController.php index c198a02f..aa6a8419 100644 --- a/controllers/admin/AdminCartRulesController.php +++ b/controllers/admin/AdminCartRulesController.php @@ -29,287 +29,302 @@ */ class AdminCartRulesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'cart_rule'; - $this->className = 'CartRule'; - $this->lang = true; - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->_orderWay = 'DESC'; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'cart_rule'; + $this->className = 'CartRule'; + $this->lang = true; + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->_orderWay = 'DESC'; - $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'),'icon' => 'icon-trash', 'confirm' => $this->l('Delete selected items?'))); + $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'),'icon' => 'icon-trash', 'confirm' => $this->l('Delete selected items?'))); - $this->fields_list = array( - 'id_cart_rule' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'name' => array('title' => $this->l('Name')), - 'priority' => array('title' => $this->l('Priority'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'code' => array('title' => $this->l('Code'), 'class' => 'fixed-width-sm'), - 'quantity' => array('title' => $this->l('Quantity'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'date_to' => array('title' => $this->l('Expiration date'), 'type' => 'datetime'), - 'active' => array('title' => $this->l('Status'), 'active' => 'status', 'type' => 'bool', 'orderby' => false), - ); + $this->fields_list = array( + 'id_cart_rule' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'name' => array('title' => $this->l('Name')), + 'priority' => array('title' => $this->l('Priority'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'code' => array('title' => $this->l('Code'), 'class' => 'fixed-width-sm'), + 'quantity' => array('title' => $this->l('Quantity'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'date_to' => array('title' => $this->l('Expiration date'), 'type' => 'datetime', 'class' => 'fixed-width-lg'), + 'active' => array('title' => $this->l('Status'), 'active' => 'status', 'type' => 'bool', 'align' => 'center', 'class' => 'fixed-width-xs', 'orderby' => false), + ); - parent::__construct(); - } + parent::__construct(); + } - public function ajaxProcessLoadCartRules() - { - $type = $token = $search = ''; - $limit = $count = $id_cart_rule = 0; - if (Tools::getIsset('limit')) - $limit = Tools::getValue('limit'); + public function ajaxProcessLoadCartRules() + { + $type = $token = $search = ''; + $limit = $count = $id_cart_rule = 0; + if (Tools::getIsset('limit')) { + $limit = Tools::getValue('limit'); + } - if (Tools::getIsset('type')) - $type = Tools::getValue('type'); + if (Tools::getIsset('type')) { + $type = Tools::getValue('type'); + } - if (Tools::getIsset('count')) - $count = Tools::getValue('count'); + if (Tools::getIsset('count')) { + $count = Tools::getValue('count'); + } - if (Tools::getIsset('id_cart_rule')) - $id_cart_rule = Tools::getValue('id_cart_rule'); + if (Tools::getIsset('id_cart_rule')) { + $id_cart_rule = Tools::getValue('id_cart_rule'); + } - if (Tools::getIsset('search')) - $search = Tools::getValue('search'); + if (Tools::getIsset('search')) { + $search = Tools::getValue('search'); + } - $page = floor($count / $limit); + $page = floor($count / $limit); - $html = ''; - $next_link = ''; + $html = ''; + $next_link = ''; - if (($page * $limit) + 1 == $count || $count == 0) - { - if ($count == 0) - $count = 1; + if (($page * $limit) + 1 == $count || $count == 0) { + if ($count == 0) { + $count = 1; + } - /** @var CartRule $current_object */ - $current_object = $this->loadObject(true); - $cart_rules = $current_object->getAssociatedRestrictions('cart_rule', false, true, ($page)*$limit, $limit, $search); + /** @var CartRule $current_object */ + $current_object = $this->loadObject(true); + $cart_rules = $current_object->getAssociatedRestrictions('cart_rule', false, true, ($page)*$limit, $limit, $search); - if ($type == 'selected') - { - $i = 1; - foreach ($cart_rules['selected'] as $cart_rule) - { - $html .= '<option value="'.(int)$cart_rule['id_cart_rule'].'"> '.Tools::safeOutput($cart_rule['name']).'</option>'; - if ($i == $limit) - break; - $i++; - } - if ($i == $limit) - $next_link = Context::getContext()->link->getAdminLink('AdminCartRules').'&ajaxMode=1&ajax=1&id_cart_rule='.(int)$id_cart_rule.'&action=loadCartRules&limit='.(int)$limit.'&type=selected&count='.($count - 1 + count($cart_rules['selected']).'&search='.urlencode($search)); - } - else - { - $i = 1; - foreach ($cart_rules['unselected'] as $cart_rule) - { - $html .= '<option value="'.(int)$cart_rule['id_cart_rule'].'"> '.Tools::safeOutput($cart_rule['name']).'</option>'; - if ($i == $limit) - break; - $i++; - } - if ($i == $limit) - $next_link = Context::getContext()->link->getAdminLink('AdminCartRules').'&ajaxMode=1&ajax=1&id_cart_rule='.(int)$id_cart_rule.'&action=loadCartRules&limit='.(int)$limit.'&type=unselected&count='.($count - 1 + count($cart_rules['unselected']).'&search='.urlencode($search)); - } - } - echo Tools::jsonEncode(array('html' => $html, 'next_link' => $next_link)); - } + if ($type == 'selected') { + $i = 1; + foreach ($cart_rules['selected'] as $cart_rule) { + $html .= '<option value="'.(int)$cart_rule['id_cart_rule'].'"> '.Tools::safeOutput($cart_rule['name']).'</option>'; + if ($i == $limit) { + break; + } + $i++; + } + if ($i == $limit) { + $next_link = Context::getContext()->link->getAdminLink('AdminCartRules').'&ajaxMode=1&ajax=1&id_cart_rule='.(int)$id_cart_rule.'&action=loadCartRules&limit='.(int)$limit.'&type=selected&count='.($count - 1 + count($cart_rules['selected']).'&search='.urlencode($search)); + } + } else { + $i = 1; + foreach ($cart_rules['unselected'] as $cart_rule) { + $html .= '<option value="'.(int)$cart_rule['id_cart_rule'].'"> '.Tools::safeOutput($cart_rule['name']).'</option>'; + if ($i == $limit) { + break; + } + $i++; + } + if ($i == $limit) { + $next_link = Context::getContext()->link->getAdminLink('AdminCartRules').'&ajaxMode=1&ajax=1&id_cart_rule='.(int)$id_cart_rule.'&action=loadCartRules&limit='.(int)$limit.'&type=unselected&count='.($count - 1 + count($cart_rules['unselected']).'&search='.urlencode($search)); + } + } + } + echo Tools::jsonEncode(array('html' => $html, 'next_link' => $next_link)); + } - public function setMedia() - { - parent::setMedia(); - $this->addJqueryPlugin(array('typewatch', 'fancybox', 'autocomplete')); - } + public function setMedia() + { + parent::setMedia(); + $this->addJqueryPlugin(array('typewatch', 'fancybox', 'autocomplete')); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_cart_rule'] = array( - 'href' => self::$currentIndex.'&addcart_rule&token='.$this->token, - 'desc' => $this->l('Add new cart rule', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_cart_rule'] = array( + 'href' => self::$currentIndex.'&addcart_rule&token='.$this->token, + 'desc' => $this->l('Add new cart rule', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function postProcess() - { - if (Tools::isSubmit('submitAddcart_rule') || Tools::isSubmit('submitAddcart_ruleAndStay')) - { - // If the reduction is associated to a specific product, then it must be part of the product restrictions - if ((int)Tools::getValue('reduction_product') && Tools::getValue('apply_discount_to') == 'specific' && Tools::getValue('apply_discount') != 'off') - { - $reduction_product = (int)Tools::getValue('reduction_product'); + public function postProcess() + { + if (Tools::isSubmit('submitAddcart_rule') || Tools::isSubmit('submitAddcart_ruleAndStay')) { + // If the reduction is associated to a specific product, then it must be part of the product restrictions + if ((int)Tools::getValue('reduction_product') && Tools::getValue('apply_discount_to') == 'specific' && Tools::getValue('apply_discount') != 'off') { + $reduction_product = (int)Tools::getValue('reduction_product'); - // First, check if it is not already part of the restrictions - $already_restricted = false; - if (is_array($rule_group_array = Tools::getValue('product_rule_group')) && count($rule_group_array) && Tools::getValue('product_restriction')) - { - foreach ($rule_group_array as $rule_group_id) - if (is_array($rule_array = Tools::getValue('product_rule_'.$rule_group_id)) && count($rule_array)) - foreach ($rule_array as $rule_id) - if (Tools::getValue('product_rule_'.$rule_group_id.'_'.$rule_id.'_type') == 'products' - && in_array($reduction_product, Tools::getValue('product_rule_select_'.$rule_group_id.'_'.$rule_id))) - { - $already_restricted = true; - break 2; - } - } - if ($already_restricted == false) - { - // Check the product restriction - $_POST['product_restriction'] = 1; + // First, check if it is not already part of the restrictions + $already_restricted = false; + if (is_array($rule_group_array = Tools::getValue('product_rule_group')) && count($rule_group_array) && Tools::getValue('product_restriction')) { + foreach ($rule_group_array as $rule_group_id) { + if (is_array($rule_array = Tools::getValue('product_rule_'.$rule_group_id)) && count($rule_array)) { + foreach ($rule_array as $rule_id) { + if (Tools::getValue('product_rule_'.$rule_group_id.'_'.$rule_id.'_type') == 'products' + && in_array($reduction_product, Tools::getValue('product_rule_select_'.$rule_group_id.'_'.$rule_id))) { + $already_restricted = true; + break 2; + } + } + } + } + } + if ($already_restricted == false) { + // Check the product restriction + $_POST['product_restriction'] = 1; - // Add a new rule group - $rule_group_id = 1; - if (is_array($rule_group_array)) - { - // Empty for (with a ; at the end), that just find the first rule_group_id available in rule_group_array - for ($rule_group_id = 1; in_array($rule_group_id, $rule_group_array); ++$rule_group_id) - 42; - $_POST['product_rule_group'][] = $rule_group_id; - } - else - $_POST['product_rule_group'] = array($rule_group_id); + // Add a new rule group + $rule_group_id = 1; + if (is_array($rule_group_array)) { + // Empty for (with a ; at the end), that just find the first rule_group_id available in rule_group_array + for ($rule_group_id = 1; in_array($rule_group_id, $rule_group_array); ++$rule_group_id) { + 42; + } + $_POST['product_rule_group'][] = $rule_group_id; + } else { + $_POST['product_rule_group'] = array($rule_group_id); + } - // Set a quantity of 1 for this new rule group - $_POST['product_rule_group_'.$rule_group_id.'_quantity'] = 1; - // Add one rule to the new rule group - $_POST['product_rule_'.$rule_group_id] = array(1); - // Set a type 'product' for this 1 rule - $_POST['product_rule_'.$rule_group_id.'_1_type'] = 'products'; - // Add the product in the selected products - $_POST['product_rule_select_'.$rule_group_id.'_1'] = array($reduction_product); - } - } + // Set a quantity of 1 for this new rule group + $_POST['product_rule_group_'.$rule_group_id.'_quantity'] = 1; + // Add one rule to the new rule group + $_POST['product_rule_'.$rule_group_id] = array(1); + // Set a type 'product' for this 1 rule + $_POST['product_rule_'.$rule_group_id.'_1_type'] = 'products'; + // Add the product in the selected products + $_POST['product_rule_select_'.$rule_group_id.'_1'] = array($reduction_product); + } + } - // These are checkboxes (which aren't sent through POST when they are not check), so they are forced to 0 - foreach (array('country', 'carrier', 'group', 'cart_rule', 'product', 'shop') as $type) - if (!Tools::getValue($type.'_restriction')) - $_POST[$type.'_restriction'] = 0; + // These are checkboxes (which aren't sent through POST when they are not check), so they are forced to 0 + foreach (array('country', 'carrier', 'group', 'cart_rule', 'product', 'shop') as $type) { + if (!Tools::getValue($type.'_restriction')) { + $_POST[$type.'_restriction'] = 0; + } + } - // Remove the gift if the radio button is set to "no" - if (!(int)Tools::getValue('free_gift')) - $_POST['gift_product'] = 0; + // Remove the gift if the radio button is set to "no" + if (!(int)Tools::getValue('free_gift')) { + $_POST['gift_product'] = 0; + } - // Retrieve the product attribute id of the gift (if available) - if ($id_product = (int)Tools::getValue('gift_product')) - $_POST['gift_product_attribute'] = (int)Tools::getValue('ipa_'.$id_product); + // Retrieve the product attribute id of the gift (if available) + if ($id_product = (int)Tools::getValue('gift_product')) { + $_POST['gift_product_attribute'] = (int)Tools::getValue('ipa_'.$id_product); + } - // Idiot-proof control - if (strtotime(Tools::getValue('date_from')) > strtotime(Tools::getValue('date_to'))) - $this->errors[] = Tools::displayError('The voucher cannot end before it begins.'); - if ((int)Tools::getValue('minimum_amount') < 0) - $this->errors[] = Tools::displayError('The minimum amount cannot be lower than zero.'); - if ((float)Tools::getValue('reduction_percent') < 0 || (float)Tools::getValue('reduction_percent') > 100) - $this->errors[] = Tools::displayError('Reduction percentage must be between 0% and 100%'); - if ((int)Tools::getValue('reduction_amount') < 0) - $this->errors[] = Tools::displayError('Reduction amount cannot be lower than zero.'); - if (Tools::getValue('code') && ($same_code = (int)CartRule::getIdByCode(Tools::getValue('code'))) && $same_code != Tools::getValue('id_cart_rule')) - $this->errors[] = sprintf(Tools::displayError('This cart rule code is already used (conflict with cart rule %d)'), $same_code); - if (Tools::getValue('apply_discount') == 'off' && !Tools::getValue('free_shipping') && !Tools::getValue('free_gift')) - $this->errors[] = Tools::displayError('An action is required for this cart rule.'); - } + // Idiot-proof control + if (strtotime(Tools::getValue('date_from')) > strtotime(Tools::getValue('date_to'))) { + $this->errors[] = Tools::displayError('The voucher cannot end before it begins.'); + } + if ((int)Tools::getValue('minimum_amount') < 0) { + $this->errors[] = Tools::displayError('The minimum amount cannot be lower than zero.'); + } + if ((float)Tools::getValue('reduction_percent') < 0 || (float)Tools::getValue('reduction_percent') > 100) { + $this->errors[] = Tools::displayError('Reduction percentage must be between 0% and 100%'); + } + if ((int)Tools::getValue('reduction_amount') < 0) { + $this->errors[] = Tools::displayError('Reduction amount cannot be lower than zero.'); + } + if (Tools::getValue('code') && ($same_code = (int)CartRule::getIdByCode(Tools::getValue('code'))) && $same_code != Tools::getValue('id_cart_rule')) { + $this->errors[] = sprintf(Tools::displayError('This cart rule code is already used (conflict with cart rule %d)'), $same_code); + } + if (Tools::getValue('apply_discount') == 'off' && !Tools::getValue('free_shipping') && !Tools::getValue('free_gift')) { + $this->errors[] = Tools::displayError('An action is required for this cart rule.'); + } + } - return parent::postProcess(); - } + return parent::postProcess(); + } - protected function afterUpdate($current_object) - { - // All the associations are deleted for an update, then recreated when we call the "afterAdd" method - $id_cart_rule = Tools::getValue('id_cart_rule'); - foreach (array('country', 'carrier', 'group', 'product_rule_group', 'shop') as $type) - Db::getInstance()->delete('cart_rule_'.$type, '`id_cart_rule` = '.(int)$id_cart_rule); + protected function afterUpdate($current_object) + { + // All the associations are deleted for an update, then recreated when we call the "afterAdd" method + $id_cart_rule = Tools::getValue('id_cart_rule'); + foreach (array('country', 'carrier', 'group', 'product_rule_group', 'shop') as $type) { + Db::getInstance()->delete('cart_rule_'.$type, '`id_cart_rule` = '.(int)$id_cart_rule); + } - Db::getInstance()->delete('cart_rule_product_rule', 'NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'cart_rule_product_rule_group` + Db::getInstance()->delete('cart_rule_product_rule', 'NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'cart_rule_product_rule_group` WHERE `'._DB_PREFIX_.'cart_rule_product_rule`.`id_product_rule_group` = `'._DB_PREFIX_.'cart_rule_product_rule_group`.`id_product_rule_group`)'); - Db::getInstance()->delete('cart_rule_product_rule_value', 'NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'cart_rule_product_rule` + Db::getInstance()->delete('cart_rule_product_rule_value', 'NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'cart_rule_product_rule` WHERE `'._DB_PREFIX_.'cart_rule_product_rule_value`.`id_product_rule` = `'._DB_PREFIX_.'cart_rule_product_rule`.`id_product_rule`)'); - Db::getInstance()->delete('cart_rule_combination', '`id_cart_rule_1` = '.(int)$id_cart_rule.' OR `id_cart_rule_2` = '.(int)$id_cart_rule); + Db::getInstance()->delete('cart_rule_combination', '`id_cart_rule_1` = '.(int)$id_cart_rule.' OR `id_cart_rule_2` = '.(int)$id_cart_rule); - $this->afterAdd($current_object); - } + $this->afterAdd($current_object); + } - public function processAdd() - { - if ($cart_rule = parent::processAdd()) - $this->context->smarty->assign('new_cart_rule', $cart_rule); - if (Tools::getValue('submitFormAjax')) - $this->redirect_after = false; + public function processAdd() + { + if ($cart_rule = parent::processAdd()) { + $this->context->smarty->assign('new_cart_rule', $cart_rule); + } + if (Tools::getValue('submitFormAjax')) { + $this->redirect_after = false; + } - return $cart_rule; - } + return $cart_rule; + } - /** - * @TODO Move this function into CartRule - * - * @param ObjectModel $currentObject - * - * @return void - * @throws PrestaShopDatabaseException - */ - protected function afterAdd($currentObject) - { - // Add restrictions for generic entities like country, carrier and group - foreach (array('country', 'carrier', 'group', 'shop') as $type) - if (Tools::getValue($type.'_restriction') && is_array($array = Tools::getValue($type.'_select')) && count($array)) - { - $values = array(); - foreach ($array as $id) - $values[] = '('.(int)$currentObject->id.','.(int)$id.')'; - Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'cart_rule_'.$type.'` (`id_cart_rule`, `id_'.$type.'`) VALUES '.implode(',', $values)); - } - // Add cart rule restrictions - if (Tools::getValue('cart_rule_restriction') && is_array($array = Tools::getValue('cart_rule_select')) && count($array)) - { - $values = array(); - foreach ($array as $id) - $values[] = '('.(int)$currentObject->id.','.(int)$id.')'; - Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'cart_rule_combination` (`id_cart_rule_1`, `id_cart_rule_2`) VALUES '.implode(',', $values)); - } - // Add product rule restrictions - if (Tools::getValue('product_restriction') && is_array($ruleGroupArray = Tools::getValue('product_rule_group')) && count($ruleGroupArray)) - { - foreach ($ruleGroupArray as $ruleGroupId) - { - Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'cart_rule_product_rule_group` (`id_cart_rule`, `quantity`) + /** + * @TODO Move this function into CartRule + * + * @param ObjectModel $currentObject + * + * @return void + * @throws PrestaShopDatabaseException + */ + protected function afterAdd($currentObject) + { + // Add restrictions for generic entities like country, carrier and group + foreach (array('country', 'carrier', 'group', 'shop') as $type) { + if (Tools::getValue($type.'_restriction') && is_array($array = Tools::getValue($type.'_select')) && count($array)) { + $values = array(); + foreach ($array as $id) { + $values[] = '('.(int)$currentObject->id.','.(int)$id.')'; + } + Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'cart_rule_'.$type.'` (`id_cart_rule`, `id_'.$type.'`) VALUES '.implode(',', $values)); + } + } + // Add cart rule restrictions + if (Tools::getValue('cart_rule_restriction') && is_array($array = Tools::getValue('cart_rule_select')) && count($array)) { + $values = array(); + foreach ($array as $id) { + $values[] = '('.(int)$currentObject->id.','.(int)$id.')'; + } + Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'cart_rule_combination` (`id_cart_rule_1`, `id_cart_rule_2`) VALUES '.implode(',', $values)); + } + // Add product rule restrictions + if (Tools::getValue('product_restriction') && is_array($ruleGroupArray = Tools::getValue('product_rule_group')) && count($ruleGroupArray)) { + foreach ($ruleGroupArray as $ruleGroupId) { + Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'cart_rule_product_rule_group` (`id_cart_rule`, `quantity`) VALUES ('.(int)$currentObject->id.', '.(int)Tools::getValue('product_rule_group_'.$ruleGroupId.'_quantity').')'); - $id_product_rule_group = Db::getInstance()->Insert_ID(); + $id_product_rule_group = Db::getInstance()->Insert_ID(); - if (is_array($ruleArray = Tools::getValue('product_rule_'.$ruleGroupId)) && count($ruleArray)) - foreach ($ruleArray as $ruleId) - { - Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'cart_rule_product_rule` (`id_product_rule_group`, `type`) + if (is_array($ruleArray = Tools::getValue('product_rule_'.$ruleGroupId)) && count($ruleArray)) { + foreach ($ruleArray as $ruleId) { + Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'cart_rule_product_rule` (`id_product_rule_group`, `type`) VALUES ('.(int)$id_product_rule_group.', "'.pSQL(Tools::getValue('product_rule_'.$ruleGroupId.'_'.$ruleId.'_type')).'")'); - $id_product_rule = Db::getInstance()->Insert_ID(); + $id_product_rule = Db::getInstance()->Insert_ID(); - $values = array(); - foreach (Tools::getValue('product_rule_select_'.$ruleGroupId.'_'.$ruleId) as $id) - $values[] = '('.(int)$id_product_rule.','.(int)$id.')'; - $values = array_unique($values); - if (count($values)) - Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'cart_rule_product_rule_value` (`id_product_rule`, `id_item`) VALUES '.implode(',', $values)); - } - } - } + $values = array(); + foreach (Tools::getValue('product_rule_select_'.$ruleGroupId.'_'.$ruleId) as $id) { + $values[] = '('.(int)$id_product_rule.','.(int)$id.')'; + } + $values = array_unique($values); + if (count($values)) { + Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'cart_rule_product_rule_value` (`id_product_rule`, `id_item`) VALUES '.implode(',', $values)); + } + } + } + } + } - // If the new rule has no cart rule restriction, then it must be added to the white list of the other cart rules that have restrictions - if (!Tools::getValue('cart_rule_restriction')) - { - Db::getInstance()->execute(' + // If the new rule has no cart rule restriction, then it must be added to the white list of the other cart rules that have restrictions + if (!Tools::getValue('cart_rule_restriction')) { + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'cart_rule_combination` (`id_cart_rule_1`, `id_cart_rule_2`) ( SELECT id_cart_rule, '.(int)$currentObject->id.' FROM `'._DB_PREFIX_.'cart_rule` WHERE cart_rule_restriction = 1 )'); - } - // And if the new cart rule has restrictions, previously unrestricted cart rules may now be restricted (a mug of coffee is strongly advised to understand this sentence) - else - { - $ruleCombinations = Db::getInstance()->executeS(' + } + // And if the new cart rule has restrictions, previously unrestricted cart rules may now be restricted (a mug of coffee is strongly advised to understand this sentence) + else { + $ruleCombinations = Db::getInstance()->executeS(' SELECT cr.id_cart_rule FROM '._DB_PREFIX_.'cart_rule cr WHERE cr.id_cart_rule != '.(int)$currentObject->id.' @@ -325,112 +340,105 @@ class AdminCartRulesControllerCore extends AdminController WHERE cr.id_cart_rule = '._DB_PREFIX_.'cart_rule_combination.id_cart_rule_1 AND '.(int)$currentObject->id.' = id_cart_rule_2 ) '); - foreach ($ruleCombinations as $incompatibleRule) - { - Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'cart_rule` SET cart_rule_restriction = 1 WHERE id_cart_rule = '.(int)$incompatibleRule['id_cart_rule'].' LIMIT 1'); - Db::getInstance()->execute(' + foreach ($ruleCombinations as $incompatibleRule) { + Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'cart_rule` SET cart_rule_restriction = 1 WHERE id_cart_rule = '.(int)$incompatibleRule['id_cart_rule'].' LIMIT 1'); + Db::getInstance()->execute(' INSERT IGNORE INTO `'._DB_PREFIX_.'cart_rule_combination` (`id_cart_rule_1`, `id_cart_rule_2`) ( SELECT id_cart_rule, '.(int)$incompatibleRule['id_cart_rule'].' FROM `'._DB_PREFIX_.'cart_rule` WHERE active = 1 AND id_cart_rule != '.(int)$currentObject->id.' AND id_cart_rule != '.(int)$incompatibleRule['id_cart_rule'].' )'); - } - } - } + } + } + } - /** - * Retrieve the cart rule product rule groups in the POST data - * if available, and in the database if there is none - * - * @param CartRule $cart_rule - * - * @return array - */ - public function getProductRuleGroupsDisplay($cart_rule) - { - $productRuleGroupsArray = array(); - if (Tools::getValue('product_restriction') && is_array($array = Tools::getValue('product_rule_group')) && count($array)) - { - $i = 1; - foreach ($array as $ruleGroupId) - { - $productRulesArray = array(); - if (is_array($array = Tools::getValue('product_rule_'.$ruleGroupId)) && count($array)) - { - foreach ($array as $ruleId) - { - $productRulesArray[] = $this->getProductRuleDisplay( - $ruleGroupId, - $ruleId, - Tools::getValue('product_rule_'.$ruleGroupId.'_'.$ruleId.'_type'), - Tools::getValue('product_rule_select_'.$ruleGroupId.'_'.$ruleId) - ); - } - } + /** + * Retrieve the cart rule product rule groups in the POST data + * if available, and in the database if there is none + * + * @param CartRule $cart_rule + * + * @return array + */ + public function getProductRuleGroupsDisplay($cart_rule) + { + $productRuleGroupsArray = array(); + if (Tools::getValue('product_restriction') && is_array($array = Tools::getValue('product_rule_group')) && count($array)) { + $i = 1; + foreach ($array as $ruleGroupId) { + $productRulesArray = array(); + if (is_array($array = Tools::getValue('product_rule_'.$ruleGroupId)) && count($array)) { + foreach ($array as $ruleId) { + $productRulesArray[] = $this->getProductRuleDisplay( + $ruleGroupId, + $ruleId, + Tools::getValue('product_rule_'.$ruleGroupId.'_'.$ruleId.'_type'), + Tools::getValue('product_rule_select_'.$ruleGroupId.'_'.$ruleId) + ); + } + } - $productRuleGroupsArray[] = $this->getProductRuleGroupDisplay( - $i++, - (int)Tools::getValue('product_rule_group_'.$ruleGroupId.'_quantity'), - $productRulesArray - ); - } - } - else - { - $i = 1; - foreach ($cart_rule->getProductRuleGroups() as $productRuleGroup) - { - $j = 1; - $productRulesDisplay = array(); - foreach ($productRuleGroup['product_rules'] as $id_product_rule => $productRule) - $productRulesDisplay[] = $this->getProductRuleDisplay($i, $j++, $productRule['type'], $productRule['values']); - $productRuleGroupsArray[] = $this->getProductRuleGroupDisplay($i++, $productRuleGroup['quantity'], $productRulesDisplay); - } - } - return $productRuleGroupsArray; - } + $productRuleGroupsArray[] = $this->getProductRuleGroupDisplay( + $i++, + (int)Tools::getValue('product_rule_group_'.$ruleGroupId.'_quantity'), + $productRulesArray + ); + } + } else { + $i = 1; + foreach ($cart_rule->getProductRuleGroups() as $productRuleGroup) { + $j = 1; + $productRulesDisplay = array(); + foreach ($productRuleGroup['product_rules'] as $id_product_rule => $productRule) { + $productRulesDisplay[] = $this->getProductRuleDisplay($i, $j++, $productRule['type'], $productRule['values']); + } + $productRuleGroupsArray[] = $this->getProductRuleGroupDisplay($i++, $productRuleGroup['quantity'], $productRulesDisplay); + } + } + return $productRuleGroupsArray; + } - /* Return the form for a single cart rule group either with or without product_rules set up */ - public function getProductRuleGroupDisplay($product_rule_group_id, $product_rule_group_quantity = 1, $product_rules = null) - { - Context::getContext()->smarty->assign('product_rule_group_id', $product_rule_group_id); - Context::getContext()->smarty->assign('product_rule_group_quantity', $product_rule_group_quantity); - Context::getContext()->smarty->assign('product_rules', $product_rules); + /* Return the form for a single cart rule group either with or without product_rules set up */ + public function getProductRuleGroupDisplay($product_rule_group_id, $product_rule_group_quantity = 1, $product_rules = null) + { + Context::getContext()->smarty->assign('product_rule_group_id', $product_rule_group_id); + Context::getContext()->smarty->assign('product_rule_group_quantity', $product_rule_group_quantity); + Context::getContext()->smarty->assign('product_rules', $product_rules); - return $this->createTemplate('product_rule_group.tpl')->fetch(); - } + return $this->createTemplate('product_rule_group.tpl')->fetch(); + } - public function getProductRuleDisplay($product_rule_group_id, $product_rule_id, $product_rule_type, $selected = array()) - { - Context::getContext()->smarty->assign( - array( - 'product_rule_group_id' => (int)$product_rule_group_id, - 'product_rule_id' => (int)$product_rule_id, - 'product_rule_type' => $product_rule_type, - ) - ); + public function getProductRuleDisplay($product_rule_group_id, $product_rule_id, $product_rule_type, $selected = array()) + { + Context::getContext()->smarty->assign( + array( + 'product_rule_group_id' => (int)$product_rule_group_id, + 'product_rule_id' => (int)$product_rule_id, + 'product_rule_type' => $product_rule_type, + ) + ); - switch ($product_rule_type) - { - case 'attributes': - $attributes = array('selected' => array(), 'unselected' => array()); - $results = Db::getInstance()->executeS(' + switch ($product_rule_type) { + case 'attributes': + $attributes = array('selected' => array(), 'unselected' => array()); + $results = Db::getInstance()->executeS(' SELECT CONCAT(agl.name, " - ", al.name) as name, a.id_attribute as id FROM '._DB_PREFIX_.'attribute_group_lang agl LEFT JOIN '._DB_PREFIX_.'attribute a ON a.id_attribute_group = agl.id_attribute_group LEFT JOIN '._DB_PREFIX_.'attribute_lang al ON (a.id_attribute = al.id_attribute AND al.id_lang = '.(int)Context::getContext()->language->id.') WHERE agl.id_lang = '.(int)Context::getContext()->language->id.' ORDER BY agl.name, al.name'); - foreach ($results as $row) - $attributes[in_array($row['id'], $selected) ? 'selected' : 'unselected'][] = $row; - Context::getContext()->smarty->assign('product_rule_itemlist', $attributes); - $choose_content = $this->createTemplate('controllers/cart_rules/product_rule_itemlist.tpl')->fetch(); - Context::getContext()->smarty->assign('product_rule_choose_content', $choose_content); - break; - case 'products': - $products = array('selected' => array(), 'unselected' => array()); - $results = Db::getInstance()->executeS(' + foreach ($results as $row) { + $attributes[in_array($row['id'], $selected) ? 'selected' : 'unselected'][] = $row; + } + Context::getContext()->smarty->assign('product_rule_itemlist', $attributes); + $choose_content = $this->createTemplate('controllers/cart_rules/product_rule_itemlist.tpl')->fetch(); + Context::getContext()->smarty->assign('product_rule_choose_content', $choose_content); + break; + case 'products': + $products = array('selected' => array(), 'unselected' => array()); + $results = Db::getInstance()->executeS(' SELECT DISTINCT name, p.id_product as id FROM '._DB_PREFIX_.'product p LEFT JOIN `'._DB_PREFIX_.'product_lang` pl @@ -439,39 +447,42 @@ class AdminCartRulesControllerCore extends AdminController '.Shop::addSqlAssociation('product', 'p').' WHERE id_lang = '.(int)Context::getContext()->language->id.' ORDER BY name'); - foreach ($results as $row) - $products[in_array($row['id'], $selected) ? 'selected' : 'unselected'][] = $row; - Context::getContext()->smarty->assign('product_rule_itemlist', $products); - $choose_content = $this->createTemplate('product_rule_itemlist.tpl')->fetch(); - Context::getContext()->smarty->assign('product_rule_choose_content', $choose_content); - break; - case 'manufacturers': - $products = array('selected' => array(), 'unselected' => array()); - $results = Db::getInstance()->executeS(' + foreach ($results as $row) { + $products[in_array($row['id'], $selected) ? 'selected' : 'unselected'][] = $row; + } + Context::getContext()->smarty->assign('product_rule_itemlist', $products); + $choose_content = $this->createTemplate('product_rule_itemlist.tpl')->fetch(); + Context::getContext()->smarty->assign('product_rule_choose_content', $choose_content); + break; + case 'manufacturers': + $products = array('selected' => array(), 'unselected' => array()); + $results = Db::getInstance()->executeS(' SELECT name, id_manufacturer as id FROM '._DB_PREFIX_.'manufacturer ORDER BY name'); - foreach ($results as $row) - $products[in_array($row['id'], $selected) ? 'selected' : 'unselected'][] = $row; - Context::getContext()->smarty->assign('product_rule_itemlist', $products); - $choose_content = $this->createTemplate('product_rule_itemlist.tpl')->fetch(); - Context::getContext()->smarty->assign('product_rule_choose_content', $choose_content); - break; - case 'suppliers': - $products = array('selected' => array(), 'unselected' => array()); - $results = Db::getInstance()->executeS(' + foreach ($results as $row) { + $products[in_array($row['id'], $selected) ? 'selected' : 'unselected'][] = $row; + } + Context::getContext()->smarty->assign('product_rule_itemlist', $products); + $choose_content = $this->createTemplate('product_rule_itemlist.tpl')->fetch(); + Context::getContext()->smarty->assign('product_rule_choose_content', $choose_content); + break; + case 'suppliers': + $products = array('selected' => array(), 'unselected' => array()); + $results = Db::getInstance()->executeS(' SELECT name, id_supplier as id FROM '._DB_PREFIX_.'supplier ORDER BY name'); - foreach ($results as $row) - $products[in_array($row['id'], $selected) ? 'selected' : 'unselected'][] = $row; - Context::getContext()->smarty->assign('product_rule_itemlist', $products); - $choose_content = $this->createTemplate('product_rule_itemlist.tpl')->fetch(); - Context::getContext()->smarty->assign('product_rule_choose_content', $choose_content); - break; - case 'categories': - $categories = array('selected' => array(), 'unselected' => array()); - $results = Db::getInstance()->executeS(' + foreach ($results as $row) { + $products[in_array($row['id'], $selected) ? 'selected' : 'unselected'][] = $row; + } + Context::getContext()->smarty->assign('product_rule_itemlist', $products); + $choose_content = $this->createTemplate('product_rule_itemlist.tpl')->fetch(); + Context::getContext()->smarty->assign('product_rule_choose_content', $choose_content); + break; + case 'categories': + $categories = array('selected' => array(), 'unselected' => array()); + $results = Db::getInstance()->executeS(' SELECT DISTINCT name, c.id_category as id FROM '._DB_PREFIX_.'category c LEFT JOIN `'._DB_PREFIX_.'category_lang` cl @@ -480,31 +491,33 @@ class AdminCartRulesControllerCore extends AdminController '.Shop::addSqlAssociation('category', 'c').' WHERE id_lang = '.(int)Context::getContext()->language->id.' ORDER BY name'); - foreach ($results as $row) - $categories[in_array($row['id'], $selected) ? 'selected' : 'unselected'][] = $row; - Context::getContext()->smarty->assign('product_rule_itemlist', $categories); - $choose_content = $this->createTemplate('product_rule_itemlist.tpl')->fetch(); - Context::getContext()->smarty->assign('product_rule_choose_content', $choose_content); - break; - default : - Context::getContext()->smarty->assign('product_rule_itemlist', array('selected' => array(), 'unselected' => array())); - Context::getContext()->smarty->assign('product_rule_choose_content', ''); - } + foreach ($results as $row) { + $categories[in_array($row['id'], $selected) ? 'selected' : 'unselected'][] = $row; + } + Context::getContext()->smarty->assign('product_rule_itemlist', $categories); + $choose_content = $this->createTemplate('product_rule_itemlist.tpl')->fetch(); + Context::getContext()->smarty->assign('product_rule_choose_content', $choose_content); + break; + default : + Context::getContext()->smarty->assign('product_rule_itemlist', array('selected' => array(), 'unselected' => array())); + Context::getContext()->smarty->assign('product_rule_choose_content', ''); + } - return $this->createTemplate('product_rule.tpl')->fetch(); - } + return $this->createTemplate('product_rule.tpl')->fetch(); + } - public function ajaxProcess() - { - if (Tools::isSubmit('newProductRule')) - die ($this->getProductRuleDisplay(Tools::getValue('product_rule_group_id'), Tools::getValue('product_rule_id'), Tools::getValue('product_rule_type'))); - if (Tools::isSubmit('newProductRuleGroup') && $product_rule_group_id = Tools::getValue('product_rule_group_id')) - die ($this->getProductRuleGroupDisplay($product_rule_group_id, Tools::getValue('product_rule_group_'.$product_rule_group_id.'_quantity', 1))); + public function ajaxProcess() + { + if (Tools::isSubmit('newProductRule')) { + die($this->getProductRuleDisplay(Tools::getValue('product_rule_group_id'), Tools::getValue('product_rule_id'), Tools::getValue('product_rule_type'))); + } + if (Tools::isSubmit('newProductRuleGroup') && $product_rule_group_id = Tools::getValue('product_rule_group_id')) { + die($this->getProductRuleGroupDisplay($product_rule_group_id, Tools::getValue('product_rule_group_'.$product_rule_group_id.'_quantity', 1))); + } - if (Tools::isSubmit('customerFilter')) - { - $search_query = trim(Tools::getValue('q')); - $customers = Db::getInstance()->executeS(' + if (Tools::isSubmit('customerFilter')) { + $search_query = trim(Tools::getValue('q')); + $customers = Db::getInstance()->executeS(' SELECT `id_customer`, `email`, CONCAT(`firstname`, \' \', `lastname`) as cname FROM `'._DB_PREFIX_.'customer` WHERE `deleted` = 0 AND is_guest = 0 AND active = 1 @@ -516,185 +529,188 @@ class AdminCartRulesControllerCore extends AdminController ) ORDER BY `firstname`, `lastname` ASC LIMIT 50'); - die(Tools::jsonEncode($customers)); - } - // Both product filter (free product and product discount) search for products - if (Tools::isSubmit('giftProductFilter') || Tools::isSubmit('reductionProductFilter')) - { - $products = Product::searchByName(Context::getContext()->language->id, trim(Tools::getValue('q'))); - die(Tools::jsonEncode($products)); - } - } + die(Tools::jsonEncode($customers)); + } + // Both product filter (free product and product discount) search for products + if (Tools::isSubmit('giftProductFilter') || Tools::isSubmit('reductionProductFilter')) { + $products = Product::searchByName(Context::getContext()->language->id, trim(Tools::getValue('q'))); + die(Tools::jsonEncode($products)); + } + } - protected function searchProducts($search) - { - if ($products = Product::searchByName((int)$this->context->language->id, $search)) - { - foreach ($products as &$product) - { - $combinations = array(); - $productObj = new Product((int)$product['id_product'], false, (int)$this->context->language->id); - $attributes = $productObj->getAttributesGroups((int)$this->context->language->id); - $product['formatted_price'] = Tools::displayPrice(Tools::convertPrice($product['price_tax_incl'], $this->context->currency), $this->context->currency); + protected function searchProducts($search) + { + if ($products = Product::searchByName((int)$this->context->language->id, $search)) { + foreach ($products as &$product) { + $combinations = array(); + $productObj = new Product((int)$product['id_product'], false, (int)$this->context->language->id); + $attributes = $productObj->getAttributesGroups((int)$this->context->language->id); + $product['formatted_price'] = Tools::displayPrice(Tools::convertPrice($product['price_tax_incl'], $this->context->currency), $this->context->currency); - foreach ($attributes as $attribute) - { - if (!isset($combinations[$attribute['id_product_attribute']]['attributes'])) - $combinations[$attribute['id_product_attribute']]['attributes'] = ''; - $combinations[$attribute['id_product_attribute']]['attributes'] .= $attribute['attribute_name'].' - '; - $combinations[$attribute['id_product_attribute']]['id_product_attribute'] = $attribute['id_product_attribute']; - $combinations[$attribute['id_product_attribute']]['default_on'] = $attribute['default_on']; - if (!isset($combinations[$attribute['id_product_attribute']]['price'])) - { - $price_tax_incl = Product::getPriceStatic((int)$product['id_product'], true, $attribute['id_product_attribute']); - $combinations[$attribute['id_product_attribute']]['formatted_price'] = Tools::displayPrice(Tools::convertPrice($price_tax_incl, $this->context->currency), $this->context->currency); - } - } + foreach ($attributes as $attribute) { + if (!isset($combinations[$attribute['id_product_attribute']]['attributes'])) { + $combinations[$attribute['id_product_attribute']]['attributes'] = ''; + } + $combinations[$attribute['id_product_attribute']]['attributes'] .= $attribute['attribute_name'].' - '; + $combinations[$attribute['id_product_attribute']]['id_product_attribute'] = $attribute['id_product_attribute']; + $combinations[$attribute['id_product_attribute']]['default_on'] = $attribute['default_on']; + if (!isset($combinations[$attribute['id_product_attribute']]['price'])) { + $price_tax_incl = Product::getPriceStatic((int)$product['id_product'], true, $attribute['id_product_attribute']); + $combinations[$attribute['id_product_attribute']]['formatted_price'] = Tools::displayPrice(Tools::convertPrice($price_tax_incl, $this->context->currency), $this->context->currency); + } + } - foreach ($combinations as &$combination) - $combination['attributes'] = rtrim($combination['attributes'], ' - '); - $product['combinations'] = $combinations; - } - return array( - 'products' => $products, - 'found' => true - ); - } - else - return array('found' => false, 'notfound' => Tools::displayError('No product has been found.')); - } + foreach ($combinations as &$combination) { + $combination['attributes'] = rtrim($combination['attributes'], ' - '); + } + $product['combinations'] = $combinations; + } + return array( + 'products' => $products, + 'found' => true + ); + } else { + return array('found' => false, 'notfound' => Tools::displayError('No product has been found.')); + } + } - public function ajaxProcessSearchProducts() - { - $array = $this->searchProducts(Tools::getValue('product_search')); - $this->content = trim(Tools::jsonEncode($array)); - } + public function ajaxProcessSearchProducts() + { + $array = $this->searchProducts(Tools::getValue('product_search')); + $this->content = trim(Tools::jsonEncode($array)); + } - public function renderForm() - { - $limit = 40; - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; + public function renderForm() + { + $limit = 40; + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } - $this->toolbar_btn['save-and-stay'] = array( - 'href' => '#', - 'desc' => $this->l('Save and Stay') - ); + $this->toolbar_btn['save-and-stay'] = array( + 'href' => '#', + 'desc' => $this->l('Save and Stay') + ); - /** @var CartRule $current_object */ - $current_object = $this->loadObject(true); + /** @var CartRule $current_object */ + $current_object = $this->loadObject(true); - // All the filter are prefilled with the correct information - $customer_filter = ''; - if (Validate::isUnsignedId($current_object->id_customer) && - ($customer = new Customer($current_object->id_customer)) && - Validate::isLoadedObject($customer)) - $customer_filter = $customer->firstname.' '.$customer->lastname.' ('.$customer->email.')'; + // All the filter are prefilled with the correct information + $customer_filter = ''; + if (Validate::isUnsignedId($current_object->id_customer) && + ($customer = new Customer($current_object->id_customer)) && + Validate::isLoadedObject($customer)) { + $customer_filter = $customer->firstname.' '.$customer->lastname.' ('.$customer->email.')'; + } - $gift_product_filter = ''; - if (Validate::isUnsignedId($current_object->gift_product) && - ($product = new Product($current_object->gift_product, false, $this->context->language->id)) && - Validate::isLoadedObject($product)) - $gift_product_filter = (!empty($product->reference) ? $product->reference : $product->name); + $gift_product_filter = ''; + if (Validate::isUnsignedId($current_object->gift_product) && + ($product = new Product($current_object->gift_product, false, $this->context->language->id)) && + Validate::isLoadedObject($product)) { + $gift_product_filter = (!empty($product->reference) ? $product->reference : $product->name); + } - $reduction_product_filter = ''; - if (Validate::isUnsignedId($current_object->reduction_product) && - ($product = new Product($current_object->reduction_product, false, $this->context->language->id)) && - Validate::isLoadedObject($product)) - $reduction_product_filter = (!empty($product->reference) ? $product->reference : $product->name); + $reduction_product_filter = ''; + if (Validate::isUnsignedId($current_object->reduction_product) && + ($product = new Product($current_object->reduction_product, false, $this->context->language->id)) && + Validate::isLoadedObject($product)) { + $reduction_product_filter = (!empty($product->reference) ? $product->reference : $product->name); + } - $product_rule_groups = $this->getProductRuleGroupsDisplay($current_object); + $product_rule_groups = $this->getProductRuleGroupsDisplay($current_object); - $attribute_groups = AttributeGroup::getAttributesGroups($this->context->language->id); - $currencies = Currency::getCurrencies(false, true, true); - $languages = Language::getLanguages(); - $countries = $current_object->getAssociatedRestrictions('country', true, true); - $groups = $current_object->getAssociatedRestrictions('group', false, true); - $shops = $current_object->getAssociatedRestrictions('shop', false, false); - $cart_rules = $current_object->getAssociatedRestrictions('cart_rule', false, true, 0, $limit); - $carriers = $current_object->getAssociatedRestrictions('carrier', true, false); - foreach ($carriers as &$carriers2) - foreach ($carriers2 as &$carrier) - foreach ($carrier as $field => &$value) - if ($field == 'name' && $value == '0') - $value = Configuration::get('PS_SHOP_NAME'); + $attribute_groups = AttributeGroup::getAttributesGroups($this->context->language->id); + $currencies = Currency::getCurrencies(false, true, true); + $languages = Language::getLanguages(); + $countries = $current_object->getAssociatedRestrictions('country', true, true); + $groups = $current_object->getAssociatedRestrictions('group', false, true); + $shops = $current_object->getAssociatedRestrictions('shop', false, false); + $cart_rules = $current_object->getAssociatedRestrictions('cart_rule', false, true, 0, $limit); + $carriers = $current_object->getAssociatedRestrictions('carrier', true, false); + foreach ($carriers as &$carriers2) { + foreach ($carriers2 as &$carrier) { + foreach ($carrier as $field => &$value) { + if ($field == 'name' && $value == '0') { + $value = Configuration::get('PS_SHOP_NAME'); + } + } + } + } - $gift_product_select = ''; - $gift_product_attribute_select = ''; - if ((int)$current_object->gift_product) - { - $search_products = $this->searchProducts($gift_product_filter); - if (isset($search_products['products']) && is_array($search_products['products'])) - foreach ($search_products['products'] as $product) - { - $gift_product_select .= ' + $gift_product_select = ''; + $gift_product_attribute_select = ''; + if ((int)$current_object->gift_product) { + $search_products = $this->searchProducts($gift_product_filter); + if (isset($search_products['products']) && is_array($search_products['products'])) { + foreach ($search_products['products'] as $product) { + $gift_product_select .= ' <option value="'.$product['id_product'].'" '.($product['id_product'] == $current_object->gift_product ? 'selected="selected"' : '').'> '.$product['name'].(count($product['combinations']) == 0 ? ' - '.$product['formatted_price'] : '').' </option>'; - if (count($product['combinations'])) - { - $gift_product_attribute_select .= '<select class="control-form id_product_attribute" id="ipa_'.$product['id_product'].'" name="ipa_'.$product['id_product'].'">'; - foreach ($product['combinations'] as $combination) - { - $gift_product_attribute_select .= ' + if (count($product['combinations'])) { + $gift_product_attribute_select .= '<select class="control-form id_product_attribute" id="ipa_'.$product['id_product'].'" name="ipa_'.$product['id_product'].'">'; + foreach ($product['combinations'] as $combination) { + $gift_product_attribute_select .= ' <option '.($combination['id_product_attribute'] == $current_object->gift_product_attribute ? 'selected="selected"' : '').' value="'.$combination['id_product_attribute'].'"> '.$combination['attributes'].' - '.$combination['formatted_price'].' </option>'; - } - $gift_product_attribute_select .= '</select>'; - } - } - } + } + $gift_product_attribute_select .= '</select>'; + } + } + } + } - $product = new Product($current_object->gift_product); - $this->context->smarty->assign( - array( - 'show_toolbar' => true, - 'toolbar_btn' => $this->toolbar_btn, - 'toolbar_scroll' => $this->toolbar_scroll, - 'title' => array($this->l('Payment: '), $this->l('Cart Rules')), - 'defaultDateFrom' => date('Y-m-d H:00:00'), - 'defaultDateTo' => date('Y-m-d H:00:00', strtotime('+1 month')), - 'customerFilter' => $customer_filter, - 'giftProductFilter' => $gift_product_filter, - 'gift_product_select' => $gift_product_select, - 'gift_product_attribute_select' => $gift_product_attribute_select, - 'reductionProductFilter' => $reduction_product_filter, - 'defaultCurrency' => Configuration::get('PS_CURRENCY_DEFAULT'), - 'id_lang_default' => Configuration::get('PS_LANG_DEFAULT'), - 'languages' => $languages, - 'currencies' => $currencies, - 'countries' => $countries, - 'carriers' => $carriers, - 'groups' => $groups, - 'shops' => $shops, - 'cart_rules' => $cart_rules, - 'product_rule_groups' => $product_rule_groups, - 'product_rule_groups_counter' => count($product_rule_groups), - 'attribute_groups' => $attribute_groups, - 'currentIndex' => self::$currentIndex, - 'currentToken' => $this->token, - 'currentObject' => $current_object, - 'currentTab' => $this, - 'hasAttribute' => $product->hasAttributes(), - ) - ); - Media::addJsDef(array('baseHref' => $this->context->link->getAdminLink('AdminCartRules').'&ajaxMode=1&ajax=1&id_cart_rule='. - (int)Tools::getValue('id_cart_rule').'&action=loadCartRules&limit='.(int)$limit.'&count=0')); - $this->content .= $this->createTemplate('form.tpl')->fetch(); + $product = new Product($current_object->gift_product); + $this->context->smarty->assign( + array( + 'show_toolbar' => true, + 'toolbar_btn' => $this->toolbar_btn, + 'toolbar_scroll' => $this->toolbar_scroll, + 'title' => array($this->l('Payment: '), $this->l('Cart Rules')), + 'defaultDateFrom' => date('Y-m-d H:00:00'), + 'defaultDateTo' => date('Y-m-d H:00:00', strtotime('+1 month')), + 'customerFilter' => $customer_filter, + 'giftProductFilter' => $gift_product_filter, + 'gift_product_select' => $gift_product_select, + 'gift_product_attribute_select' => $gift_product_attribute_select, + 'reductionProductFilter' => $reduction_product_filter, + 'defaultCurrency' => Configuration::get('PS_CURRENCY_DEFAULT'), + 'id_lang_default' => Configuration::get('PS_LANG_DEFAULT'), + 'languages' => $languages, + 'currencies' => $currencies, + 'countries' => $countries, + 'carriers' => $carriers, + 'groups' => $groups, + 'shops' => $shops, + 'cart_rules' => $cart_rules, + 'product_rule_groups' => $product_rule_groups, + 'product_rule_groups_counter' => count($product_rule_groups), + 'attribute_groups' => $attribute_groups, + 'currentIndex' => self::$currentIndex, + 'currentToken' => $this->token, + 'currentObject' => $current_object, + 'currentTab' => $this, + 'hasAttribute' => $product->hasAttributes(), + ) + ); + Media::addJsDef(array('baseHref' => $this->context->link->getAdminLink('AdminCartRules').'&ajaxMode=1&ajax=1&id_cart_rule='. + (int)Tools::getValue('id_cart_rule').'&action=loadCartRules&limit='.(int)$limit.'&count=0')); + $this->content .= $this->createTemplate('form.tpl')->fetch(); - $this->addJqueryUI('ui.datepicker'); - $this->addJqueryPlugin(array('jscroll', 'typewatch')); - return parent::renderForm(); - } + $this->addJqueryUI('ui.datepicker'); + $this->addJqueryPlugin(array('jscroll', 'typewatch')); + return parent::renderForm(); + } - public function displayAjaxSearchCartRuleVouchers() - { - $found = false; - if ($vouchers = CartRule::getCartsRuleByCode(Tools::getValue('q'), (int)$this->context->language->id, true)) - $found = true; - echo Tools::jsonEncode(array('found' => $found, 'vouchers' => $vouchers)); - } + public function displayAjaxSearchCartRuleVouchers() + { + $found = false; + if ($vouchers = CartRule::getCartsRuleByCode(Tools::getValue('q'), (int)$this->context->language->id, true)) { + $found = true; + } + echo Tools::jsonEncode(array('found' => $found, 'vouchers' => $vouchers)); + } } diff --git a/controllers/admin/AdminCartsController.php b/controllers/admin/AdminCartsController.php index dfdc0710..c3433452 100644 --- a/controllers/admin/AdminCartsController.php +++ b/controllers/admin/AdminCartsController.php @@ -29,866 +29,889 @@ */ class AdminCartsControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'cart'; - $this->className = 'Cart'; - $this->lang = false; - $this->explicitSelect = true; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'cart'; + $this->className = 'Cart'; + $this->lang = false; + $this->explicitSelect = true; - $this->addRowAction('view'); - $this->addRowAction('delete'); - $this->allow_export = true; - $this->_orderWay = 'DESC'; + $this->addRowAction('view'); + $this->addRowAction('delete'); + $this->allow_export = true; + $this->_orderWay = 'DESC'; - $this->_select = 'CONCAT(LEFT(c.`firstname`, 1), \'. \', c.`lastname`) `customer`, a.id_cart total, ca.name carrier, + $this->_select = 'CONCAT(LEFT(c.`firstname`, 1), \'. \', c.`lastname`) `customer`, a.id_cart total, ca.name carrier, IF (IFNULL(o.id_order, \''.$this->l('Non ordered').'\') = \''.$this->l('Non ordered').'\', IF(TIME_TO_SEC(TIMEDIFF(\''.pSQL(date('Y-m-d H:i:00', time())).'\', a.`date_add`)) > 86400, \''.$this->l('Abandoned cart').'\', \''.$this->l('Non ordered').'\'), o.id_order) AS status, IF(o.id_order, 1, 0) badge_success, IF(o.id_order, 0, 1) badge_danger, IF(co.id_guest, 1, 0) id_guest'; - $this->_join = 'LEFT JOIN '._DB_PREFIX_.'customer c ON (c.id_customer = a.id_customer) + $this->_join = 'LEFT JOIN '._DB_PREFIX_.'customer c ON (c.id_customer = a.id_customer) LEFT JOIN '._DB_PREFIX_.'currency cu ON (cu.id_currency = a.id_currency) LEFT JOIN '._DB_PREFIX_.'carrier ca ON (ca.id_carrier = a.id_carrier) LEFT JOIN '._DB_PREFIX_.'orders o ON (o.id_cart = a.id_cart) LEFT JOIN `'._DB_PREFIX_.'connections` co ON (a.id_guest = co.id_guest AND TIME_TO_SEC(TIMEDIFF(\''.pSQL(date('Y-m-d H:i:00', time())).'\', co.`date_add`)) < 1800)'; - if (Tools::getValue('action') && Tools::getValue('action') == 'filterOnlyAbandonedCarts') - $this->_having = 'status = \''.$this->l('Abandoned cart').'\''; - else - $this->_use_found_rows = false; - - - $this->fields_list = array( - 'id_cart' => array( - 'title' => $this->l('ID'), - 'align' => 'text-center', - 'class' => 'fixed-width-xs' - ), - 'status' => array( - 'title' => $this->l('Order ID'), - 'align' => 'text-center', - 'badge_danger' => true - ), - 'customer' => array( - 'title' => $this->l('Customer'), - 'filter_key' => 'c!lastname' - ), - 'total' => array( - 'title' => $this->l('Total'), - 'callback' => 'getOrderTotalUsingTaxCalculationMethod', - 'orderby' => false, - 'search' => false, - 'align' => 'text-right', - 'badge_success' => true - ), - 'carrier' => array( - 'title' => $this->l('Carrier'), - 'align' => 'text-center', - 'callback' => 'replaceZeroByShopName', - 'filter_key' => 'ca!name' - ), - 'date_add' => array( - 'title' => $this->l('Date'), - 'align' => 'text-right', - 'type' => 'datetime', - 'filter_key' => 'a!date_add' - ), - 'id_guest' => array( - 'title' => $this->l('Online'), - 'align' => 'text-center', - 'type' => 'bool', - 'havingFilter' => true, - 'icon' => array(0 => 'icon-', 1 => 'icon-user') - ) - ); - $this->shopLinkType = 'shop'; - - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); - - parent::__construct(); - } - - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['export_cart'] = array( - 'href' => self::$currentIndex.'&exportcart&token='.$this->token, - 'desc' => $this->l('Export carts', null, null, false), - 'icon' => 'process-icon-export' - ); - - parent::initPageHeaderToolbar(); - } - - public function renderKpis() - { - $time = time(); - $kpis = array(); - - /* The data generation is located in AdminStatsControllerCore */ - $helper = new HelperKpi(); - $helper->id = 'box-conversion-rate'; - $helper->icon = 'icon-sort-by-attributes-alt'; - //$helper->chart = true; - $helper->color = 'color1'; - $helper->title = $this->l('Conversion Rate', null, null, false); - $helper->subtitle = $this->l('30 days', null, null, false); - if (ConfigurationKPI::get('CONVERSION_RATE') !== false) - $helper->value = ConfigurationKPI::get('CONVERSION_RATE'); - if (ConfigurationKPI::get('CONVERSION_RATE_CHART') !== false) - $helper->data = ConfigurationKPI::get('CONVERSION_RATE_CHART'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=conversion_rate'; - $helper->refresh = (bool)(ConfigurationKPI::get('CONVERSION_RATE_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-carts'; - $helper->icon = 'icon-shopping-cart'; - $helper->color = 'color2'; - $helper->title = $this->l('Abandoned Carts', null, null, false); - $date_from = date(Context::getContext()->language->date_format_lite, strtotime('-2 day')); - $date_to = date(Context::getContext()->language->date_format_lite, strtotime('-1 day')); - $helper->subtitle = sprintf($this->l('From %s to %s', null, null, false), $date_from, $date_to); - $helper->href = $this->context->link->getAdminLink('AdminCarts').'&action=filterOnlyAbandonedCarts'; - if (ConfigurationKPI::get('ABANDONED_CARTS') !== false) - $helper->value = ConfigurationKPI::get('ABANDONED_CARTS'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=abandoned_cart'; - $helper->refresh = (bool)(ConfigurationKPI::get('ABANDONED_CARTS_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-average-order'; - $helper->icon = 'icon-money'; - $helper->color = 'color3'; - $helper->title = $this->l('Average Order Value', null, null, false); - $helper->subtitle = $this->l('30 days', null, null, false); - if (ConfigurationKPI::get('AVG_ORDER_VALUE') !== false) - $helper->value = ConfigurationKPI::get('AVG_ORDER_VALUE'); - if (ConfigurationKPI::get('AVG_ORDER_VALUE_EXPIRE') < $time) - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=average_order_value'; - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-net-profit-visitor'; - $helper->icon = 'icon-user'; - $helper->color = 'color4'; - $helper->title = $this->l('Net Profit per Visitor', null, null, false); - $helper->subtitle = $this->l('30 days', null, null, false); - if (ConfigurationKPI::get('NETPROFIT_VISITOR') !== false) - $helper->value = ConfigurationKPI::get('NETPROFIT_VISITOR'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=netprofit_visitor'; - $helper->refresh = (bool)(ConfigurationKPI::get('NETPROFIT_VISITOR_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpiRow(); - $helper->kpis = $kpis; - return $helper->generate(); - } - - - public function renderView() - { - /** @var Cart $cart */ - if (!($cart = $this->loadObject(true))) - return; - $customer = new Customer($cart->id_customer); - $currency = new Currency($cart->id_currency); - $this->context->cart = $cart; - $this->context->currency = $currency; - $this->context->customer = $customer; - $this->toolbar_title = sprintf($this->l('Cart #%06d'), $this->context->cart->id); - $products = $cart->getProducts(); - $customized_datas = Product::getAllCustomizedDatas((int)$cart->id); - Product::addCustomizationPrice($products, $customized_datas); - $summary = $cart->getSummaryDetails(); - - /* Display order information */ - $id_order = (int)Order::getOrderByCartId($cart->id); - $order = new Order($id_order); - if (Validate::isLoadedObject($order)) - { - $tax_calculation_method = $order->getTaxCalculationMethod(); - $id_shop = (int)$order->id_shop; - } - else - { - $id_shop = (int)$cart->id_shop; - $tax_calculation_method = Group::getPriceDisplayMethod(Group::getCurrent()->id); - } - - if ($tax_calculation_method == PS_TAX_EXC) - { - $total_products = $summary['total_products']; - $total_discounts = $summary['total_discounts_tax_exc']; - $total_wrapping = $summary['total_wrapping_tax_exc']; - $total_price = $summary['total_price_without_tax']; - $total_shipping = $summary['total_shipping_tax_exc']; - } - else - { - $total_products = $summary['total_products_wt']; - $total_discounts = $summary['total_discounts']; - $total_wrapping = $summary['total_wrapping']; - $total_price = $summary['total_price']; - $total_shipping = $summary['total_shipping']; - } - foreach ($products as $k => &$product) - { - if ($tax_calculation_method == PS_TAX_EXC) - { - $product['product_price'] = $product['price']; - $product['product_total'] = $product['total']; - } - else - { - $product['product_price'] = $product['price_wt']; - $product['product_total'] = $product['total_wt']; - } - $image = array(); - if (isset($product['id_product_attribute']) && (int)$product['id_product_attribute']) - $image = Db::getInstance()->getRow('SELECT id_image FROM '._DB_PREFIX_.'product_attribute_image WHERE id_product_attribute = '.(int)$product['id_product_attribute']); - if (!isset($image['id_image'])) - $image = Db::getInstance()->getRow('SELECT id_image FROM '._DB_PREFIX_.'image WHERE id_product = '.(int)$product['id_product'].' AND cover = 1'); - - $product['qty_in_stock'] = StockAvailable::getQuantityAvailableByProduct($product['id_product'], isset($product['id_product_attribute']) ? $product['id_product_attribute'] : null, (int)$id_shop); - - $image_product = new Image($image['id_image']); - $product['image'] = (isset($image['id_image']) ? ImageManager::thumbnail(_PS_IMG_DIR_.'p/'.$image_product->getExistingImgPath().'.jpg', 'product_mini_'.(int)$product['id_product'].(isset($product['id_product_attribute']) ? '_'.(int)$product['id_product_attribute'] : '').'.jpg', 45, 'jpg') : '--'); - } - - $helper = new HelperKpi(); - $helper->id = 'box-kpi-cart'; - $helper->icon = 'icon-shopping-cart'; - $helper->color = 'color1'; - $helper->title = $this->l('Total Cart', null, null, false); - $helper->subtitle = sprintf($this->l('Cart #%06d', null, null, false), $cart->id); - $helper->value = Tools::displayPrice($total_price, $currency); - $kpi = $helper->generate(); - - $this->tpl_view_vars = array( - 'kpi' => $kpi, - 'products' => $products, - 'discounts' => $cart->getCartRules(), - 'order' => $order, - 'cart' => $cart, - 'currency' => $currency, - 'customer' => $customer, - 'customer_stats' => $customer->getStats(), - 'total_products' => $total_products, - 'total_discounts' => $total_discounts, - 'total_wrapping' => $total_wrapping, - 'total_price' => $total_price, - 'total_shipping' => $total_shipping, - 'customized_datas' => $customized_datas, - 'tax_calculation_method' => $tax_calculation_method - ); - - return parent::renderView(); - } - - public function ajaxPreProcess() - { - if ($this->tabAccess['edit'] === '1') - { - $id_customer = (int)Tools::getValue('id_customer'); - $customer = new Customer((int)$id_customer); - $this->context->customer = $customer; - $id_cart = (int)Tools::getValue('id_cart'); - if (!$id_cart) - $id_cart = $customer->getLastCart(false); - $this->context->cart = new Cart((int)$id_cart); - - if (!$this->context->cart->id) - { - $this->context->cart->recyclable = 0; - $this->context->cart->gift = 0; - } - - if (!$this->context->cart->id_customer) - $this->context->cart->id_customer = $id_customer; - if (Validate::isLoadedObject($this->context->cart) && $this->context->cart->OrderExists()) - return; - if (!$this->context->cart->secure_key) - $this->context->cart->secure_key = $this->context->customer->secure_key; - if (!$this->context->cart->id_shop) - $this->context->cart->id_shop = (int)$this->context->shop->id; - if (!$this->context->cart->id_lang) - $this->context->cart->id_lang = (($id_lang = (int)Tools::getValue('id_lang')) ? $id_lang : Configuration::get('PS_LANG_DEFAULT')); - if (!$this->context->cart->id_currency) - $this->context->cart->id_currency = (($id_currency = (int)Tools::getValue('id_currency')) ? $id_currency : Configuration::get('PS_CURRENCY_DEFAULT')); - - $addresses = $customer->getAddresses((int)$this->context->cart->id_lang); - $id_address_delivery = (int)Tools::getValue('id_address_delivery'); - $id_address_invoice = (int)Tools::getValue('id_address_delivery'); - - if (!$this->context->cart->id_address_invoice && isset($addresses[0])) - $this->context->cart->id_address_invoice = (int)$addresses[0]['id_address']; - elseif ($id_address_invoice) - $this->context->cart->id_address_invoice = (int)$id_address_invoice; - if (!$this->context->cart->id_address_delivery && isset($addresses[0])) - $this->context->cart->id_address_delivery = $addresses[0]['id_address']; - elseif ($id_address_delivery) - $this->context->cart->id_address_delivery = (int)$id_address_delivery; - $this->context->cart->setNoMultishipping(); - $this->context->cart->save(); - $currency = new Currency((int)$this->context->cart->id_currency); - $this->context->currency = $currency; - } - } - - public function ajaxProcessDeleteProduct() - { - if ($this->tabAccess['edit'] === '1') - { - $errors = array(); - if ((!$id_product = (int)Tools::getValue('id_product')) || !Validate::isInt($id_product)) - $errors[] = Tools::displayError('Invalid product'); - if (($id_product_attribute = (int)Tools::getValue('id_product_attribute')) && !Validate::isInt($id_product_attribute)) - $errors[] = Tools::displayError('Invalid combination'); - if (count($errors)) - die(Tools::jsonEncode($errors)); - if ($this->context->cart->deleteProduct($id_product, $id_product_attribute, (int)Tools::getValue('id_customization'))) - echo Tools::jsonEncode($this->ajaxReturnVars()); - } - } - - public function ajaxProcessUpdateCustomizationFields() - { - $errors = array(); - if ($this->tabAccess['edit'] === '1') - { - $errors = array(); - if (Tools::getValue('only_display') != 1) - { - if (!$this->context->cart->id || (!$id_product = (int)Tools::getValue('id_product'))) - return; - $product = new Product((int)$id_product); - if (!$customization_fields = $product->getCustomizationFieldIds()) - return; - foreach ($customization_fields as $customization_field) - { - $field_id = 'customization_'.$id_product.'_'.$customization_field['id_customization_field']; - if ($customization_field['type'] == Product::CUSTOMIZE_TEXTFIELD) - { - if (!Tools::getValue($field_id)) - { - if ($customization_field['required']) - $errors[] = Tools::displayError('Please fill in all the required fields.'); - continue; - } - if (!Validate::isMessage(Tools::getValue($field_id))) - $errors[] = Tools::displayError('Invalid message'); - $this->context->cart->addTextFieldToProduct((int)$product->id, (int)$customization_field['id_customization_field'], Product::CUSTOMIZE_TEXTFIELD, Tools::getValue($field_id)); - } - elseif ($customization_field['type'] == Product::CUSTOMIZE_FILE) - { - if (!isset($_FILES[$field_id]) || !isset($_FILES[$field_id]['tmp_name']) || empty($_FILES[$field_id]['tmp_name'])) - { - if ($customization_field['required']) - $errors[] = Tools::displayError('Please fill in all the required fields.'); - continue; - } - if ($error = ImageManager::validateUpload($_FILES[$field_id], (int)Configuration::get('PS_PRODUCT_PICTURE_MAX_SIZE'))) - $errors[] = $error; - if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES[$field_id]['tmp_name'], $tmp_name)) - $errors[] = Tools::displayError('An error occurred during the image upload process.'); - $file_name = md5(uniqid(rand(), true)); - if (!ImageManager::resize($tmp_name, _PS_UPLOAD_DIR_.$file_name)) - continue; - elseif (!ImageManager::resize($tmp_name, _PS_UPLOAD_DIR_.$file_name.'_small', (int)Configuration::get('PS_PRODUCT_PICTURE_WIDTH'), (int)Configuration::get('PS_PRODUCT_PICTURE_HEIGHT'))) - $errors[] = Tools::displayError('An error occurred during the image upload process.'); - elseif (!chmod(_PS_UPLOAD_DIR_.$file_name, 0777) || !chmod(_PS_UPLOAD_DIR_.$file_name.'_small', 0777)) - $errors[] = Tools::displayError('An error occurred during the image upload process.'); - else - $this->context->cart->addPictureToProduct((int)$product->id, (int)$customization_field['id_customization_field'], Product::CUSTOMIZE_FILE, $file_name); - unlink($tmp_name); - } - } - } - $this->setMedia(); - $this->initFooter(); - $this->context->smarty->assign(array('customization_errors' => implode('<br />', $errors), - 'css_files' => $this->css_files)); - return $this->smartyOutputContent('controllers/orders/form_customization_feedback.tpl'); - } - } - - public function ajaxProcessUpdateQty() - { - if ($this->tabAccess['edit'] === '1') - { - $errors = array(); - if (!$this->context->cart->id) - return; - if ($this->context->cart->OrderExists()) - $errors[] = Tools::displayError('An order has already been placed with this cart.'); - elseif (!($id_product = (int)Tools::getValue('id_product')) || !($product = new Product((int)$id_product, true, $this->context->language->id))) - $errors[] = Tools::displayError('Invalid product'); - elseif (!($qty = Tools::getValue('qty')) || $qty == 0) - $errors[] = Tools::displayError('Invalid quantity'); - - // Don't try to use a product if not instanciated before due to errors - if (isset($product) && $product->id) - { - if (($id_product_attribute = Tools::getValue('id_product_attribute')) != 0) - { - if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty((int)$id_product_attribute, (int)$qty)) - $errors[] = Tools::displayError('There is not enough product in stock.'); - } - else - if (!$product->checkQty((int)$qty)) - $errors[] = Tools::displayError('There is not enough product in stock.'); - if (!($id_customization = (int)Tools::getValue('id_customization', 0)) && !$product->hasAllRequiredCustomizableFields()) - $errors[] = Tools::displayError('Please fill in all the required fields.'); - $this->context->cart->save(); - } - else - $errors[] = Tools::displayError('This product cannot be added to the cart.'); - - if (!count($errors)) - { - if ((int)$qty < 0) - { - $qty = str_replace('-', '', $qty); - $operator = 'down'; - } - else - $operator = 'up'; - - if (!($qty_upd = $this->context->cart->updateQty($qty, $id_product, (int)$id_product_attribute, (int)$id_customization, $operator))) - $errors[] = Tools::displayError('You already have the maximum quantity available for this product.'); - elseif ($qty_upd < 0) - { - $minimal_qty = $id_product_attribute ? Attribute::getAttributeMinimalQty((int)$id_product_attribute) : $product->minimal_quantity; - $errors[] = sprintf(Tools::displayError('You must add a minimum quantity of %d', false), $minimal_qty); - } - } - - echo Tools::jsonEncode(array_merge($this->ajaxReturnVars(), array('errors' => $errors))); - } - } - - public function ajaxProcessUpdateDeliveryOption() - { - if ($this->tabAccess['edit'] === '1') - { - $delivery_option = Tools::getValue('delivery_option'); - if ($delivery_option !== false) - $this->context->cart->setDeliveryOption(array($this->context->cart->id_address_delivery => $delivery_option)); - if (Validate::isBool(($recyclable = (int)Tools::getValue('recyclable')))) - $this->context->cart->recyclable = $recyclable; - if (Validate::isBool(($gift = (int)Tools::getValue('gift')))) - $this->context->cart->gift = $gift; - if (Validate::isMessage(($gift_message = pSQL(Tools::getValue('gift_message'))))) - $this->context->cart->gift_message = $gift_message; - $this->context->cart->save(); - echo Tools::jsonEncode($this->ajaxReturnVars()); - } - } - - public function ajaxProcessUpdateOrderMessage() - { - if ($this->tabAccess['edit'] === '1') - { - $id_message = false; - if ($old_message = Message::getMessageByCartId((int)$this->context->cart->id)) - $id_message = $old_message['id_message']; - $message = new Message((int)$id_message); - if ($message_content = Tools::getValue('message')) - { - if (Validate::isMessage($message_content)) - { - $message->message = $message_content; - $message->id_cart = (int)$this->context->cart->id; - $message->id_customer = (int)$this->context->cart->id_customer; - $message->save(); - } - } - else - if (Validate::isLoadedObject($message)) - $message->delete(); - echo Tools::jsonEncode($this->ajaxReturnVars()); - } - } - - public function ajaxProcessUpdateCurrency() - { - if ($this->tabAccess['edit'] === '1') - { - $currency = new Currency((int)Tools::getValue('id_currency')); - if (Validate::isLoadedObject($currency) && !$currency->deleted && $currency->active) - { - $this->context->cart->id_currency = (int)$currency->id; - $this->context->currency = $currency; - $this->context->cart->save(); - } - echo Tools::jsonEncode($this->ajaxReturnVars()); - } - } - public function ajaxProcessUpdateLang() - { - if ($this->tabAccess['edit'] === '1') - { - $lang = new Language((int)Tools::getValue('id_lang')); - if (Validate::isLoadedObject($lang) && $lang->active) - { - $this->context->cart->id_lang = (int)$lang->id; - $this->context->cart->save(); - } - echo Tools::jsonEncode($this->ajaxReturnVars()); - } - } - - public function ajaxProcessDuplicateOrder() - { - if ($this->tabAccess['edit'] === '1') - { - $errors = array(); - if (!$id_order = Tools::getValue('id_order')) - $errors[] = Tools::displayError('Invalid order'); - $cart = Cart::getCartByOrderId($id_order); - $new_cart = $cart->duplicate(); - if (!$new_cart || !Validate::isLoadedObject($new_cart['cart'])) - $errors[] = Tools::displayError('The order cannot be renewed.'); - elseif (!$new_cart['success']) - $errors[] = Tools::displayError('The order cannot be renewed.'); - else - { - $this->context->cart = $new_cart['cart']; - echo Tools::jsonEncode($this->ajaxReturnVars()); - } - } - } - - public function ajaxProcessDeleteVoucher() - { - if ($this->tabAccess['edit'] === '1') - { - if ($this->context->cart->removeCartRule((int)Tools::getValue('id_cart_rule'))) - echo Tools::jsonEncode($this->ajaxReturnVars()); - } - } - - public function ajaxProcessupdateFreeShipping() - { - if ($this->tabAccess['edit'] === '1') - { - if (!$id_cart_rule = CartRule::getIdByCode(CartRule::BO_ORDER_CODE_PREFIX.(int)$this->context->cart->id)) - { - $cart_rule = new CartRule(); - $cart_rule->code = CartRule::BO_ORDER_CODE_PREFIX.(int)$this->context->cart->id; - $cart_rule->name = array(Configuration::get('PS_LANG_DEFAULT') => $this->l('Free Shipping', 'AdminTab', false, false)); - $cart_rule->id_customer = (int)$this->context->cart->id_customer; - $cart_rule->free_shipping = true; - $cart_rule->quantity = 1; - $cart_rule->quantity_per_user = 1; - $cart_rule->minimum_amount_currency = (int)$this->context->cart->id_currency; - $cart_rule->reduction_currency = (int)$this->context->cart->id_currency; - $cart_rule->date_from = date('Y-m-d H:i:s', time()); - $cart_rule->date_to = date('Y-m-d H:i:s', time() + 24 * 36000); - $cart_rule->active = 1; - $cart_rule->add(); - } - else - $cart_rule = new CartRule((int)$id_cart_rule); - - $this->context->cart->removeCartRule((int)$cart_rule->id); - if (Tools::getValue('free_shipping')) - $this->context->cart->addCartRule((int)$cart_rule->id); - - echo Tools::jsonEncode($this->ajaxReturnVars()); - } - } - - public function ajaxProcessAddVoucher() - { - if ($this->tabAccess['edit'] === '1') - { - $errors = array(); - if (!($id_cart_rule = Tools::getValue('id_cart_rule')) || !$cart_rule = new CartRule((int)$id_cart_rule)) - $errors[] = Tools::displayError('Invalid voucher.'); - elseif ($err = $cart_rule->checkValidity($this->context)) - $errors[] = $err; - if (!count($errors)) - if (!$this->context->cart->addCartRule((int)$cart_rule->id)) - $errors[] = Tools::displayError('Can\'t add the voucher.'); - echo Tools::jsonEncode(array_merge($this->ajaxReturnVars(), array('errors' => $errors))); - } - } - - public function ajaxProcessUpdateAddress() - { - if ($this->tabAccess['edit'] === '1') - echo Tools::jsonEncode(array('addresses' => $this->context->customer->getAddresses((int)$this->context->cart->id_lang))); - } - - public function ajaxProcessUpdateAddresses() - { - if ($this->tabAccess['edit'] === '1') - { - if (($id_address_delivery = (int)Tools::getValue('id_address_delivery')) && - ($address_delivery = new Address((int)$id_address_delivery)) && - $address_delivery->id_customer == $this->context->cart->id_customer) - $this->context->cart->id_address_delivery = (int)$address_delivery->id; - - if (($id_address_invoice = (int)Tools::getValue('id_address_invoice')) && - ($address_invoice = new Address((int)$id_address_invoice)) && - $address_invoice->id_customer = $this->context->cart->id_customer) - $this->context->cart->id_address_invoice = (int)$address_invoice->id; - $this->context->cart->save(); - - echo Tools::jsonEncode($this->ajaxReturnVars()); - } - } - - protected function getCartSummary() - { - $summary = $this->context->cart->getSummaryDetails(null, true); - $currency = Context::getContext()->currency; - if (count($summary['products'])) - foreach ($summary['products'] as &$product) - { - $product['numeric_price'] = $product['price']; - $product['numeric_total'] = $product['total']; - $product['price'] = str_replace($currency->sign, '', Tools::displayPrice($product['price'], $currency)); - $product['total'] = str_replace($currency->sign, '', Tools::displayPrice($product['total'], $currency)); - $product['image_link'] = $this->context->link->getImageLink($product['link_rewrite'], $product['id_image'], 'small_default'); - if (!isset($product['attributes_small'])) - $product['attributes_small'] = ''; - $product['customized_datas'] = Product::getAllCustomizedDatas((int)$this->context->cart->id, null, true); - } - if (count($summary['discounts'])) - foreach ($summary['discounts'] as &$voucher) - $voucher['value_real'] = Tools::displayPrice($voucher['value_real'], $currency); - - if (isset($summary['gift_products']) && count($summary['gift_products'])) - foreach ($summary['gift_products'] as &$product) - { - $product['image_link'] = $this->context->link->getImageLink($product['link_rewrite'], $product['id_image'], 'small_default'); - if (!isset($product['attributes_small'])) - $product['attributes_small'] = ''; - } - - - return $summary; - } - - protected function getDeliveryOptionList() - { - $delivery_option_list_formated = array(); - $delivery_option_list = $this->context->cart->getDeliveryOptionList(); - - if (!count($delivery_option_list)) - return array(); - - $id_default_carrier = (int)Configuration::get('PS_CARRIER_DEFAULT'); - foreach (current($delivery_option_list) as $key => $delivery_option) - { - $name = ''; - $first = true; - $id_default_carrier_delivery = false; - foreach ($delivery_option['carrier_list'] as $carrier) - { - if (!$first) - $name .= ', '; - else - $first = false; - - $name .= $carrier['instance']->name; - - if ($delivery_option['unique_carrier']) - $name .= ' - '.$carrier['instance']->delay[$this->context->employee->id_lang]; - - if (!$id_default_carrier_delivery) - $id_default_carrier_delivery = (int)$carrier['instance']->id; - if ($carrier['instance']->id == $id_default_carrier) - $id_default_carrier_delivery = $id_default_carrier; - if (!$this->context->cart->id_carrier) - { - $this->context->cart->setDeliveryOption(array($this->context->cart->id_address_delivery => (int)$carrier['instance']->id.',')); - $this->context->cart->save(); - } - } - $delivery_option_list_formated[] = array('name' => $name, 'key' => $key); - } - return $delivery_option_list_formated; - } - - public function displayAjaxSearchCarts() - { - $id_customer = (int)Tools::getValue('id_customer'); - $carts = Cart::getCustomerCarts((int)$id_customer); - $orders = Order::getCustomerOrders((int)$id_customer); - $customer = new Customer((int)$id_customer); - - if (count($carts)) - foreach ($carts as $key => &$cart) - { - $cart_obj = new Cart((int)$cart['id_cart']); - if ($cart['id_cart'] == $this->context->cart->id || !Validate::isLoadedObject($cart_obj) || $cart_obj->OrderExists()) - unset($carts[$key]); - $currency = new Currency((int)$cart['id_currency']); - $cart['total_price'] = Tools::displayPrice($cart_obj->getOrderTotal(), $currency); - } - if (count($orders)) - foreach ($orders as &$order) - $order['total_paid_real'] = Tools::displayPrice($order['total_paid_real'], $currency); - if ($orders || $carts) - $to_return = array_merge($this->ajaxReturnVars(), - array('carts' => $carts, - 'orders' => $orders, - 'found' => true)); - else - $to_return = array_merge($this->ajaxReturnVars(), array('found' => false)); - - echo Tools::jsonEncode($to_return); - } - - public function ajaxReturnVars() - { - $id_cart = (int)$this->context->cart->id; - $message_content = ''; - if ($message = Message::getMessageByCartId((int)$this->context->cart->id)) - $message_content = $message['message']; - $cart_rules = $this->context->cart->getCartRules(CartRule::FILTER_ACTION_SHIPPING); - - $free_shipping = false; - if (count($cart_rules)) - foreach ($cart_rules as $cart_rule) - if ($cart_rule['id_cart_rule'] == CartRule::getIdByCode(CartRule::BO_ORDER_CODE_PREFIX.(int)$this->context->cart->id)) - { - $free_shipping = true; - break; - } - - $addresses = $this->context->customer->getAddresses((int)$this->context->cart->id_lang); - - foreach ($addresses as &$data) - { - $address = new Address((int)$data['id_address']); - $data['formated_address'] = AddressFormat::generateAddress($address, array(), "<br />"); - } - - return array( - 'summary' => $this->getCartSummary(), - 'delivery_option_list' => $this->getDeliveryOptionList(), - 'cart' => $this->context->cart, - 'currency' => new Currency($this->context->cart->id_currency), - 'addresses' => $addresses, - 'id_cart' => $id_cart, - 'order_message' => $message_content, - 'link_order' => $this->context->link->getPageLink( - 'order', false, - (int)$this->context->cart->id_lang, - 'step=3&recover_cart='.$id_cart.'&token_cart='.md5(_COOKIE_KEY_.'recover_cart_'.$id_cart) - ), - 'free_shipping' => (int)$free_shipping - ); - } - - public function initToolbar() - { - parent::initToolbar(); - unset($this->toolbar_btn['new']); - } - - public function displayAjaxGetSummary() - { - echo Tools::jsonEncode($this->ajaxReturnVars()); - } - - public function ajaxProcessUpdateProductPrice() - { - if ($this->tabAccess['edit'] === '1') - { - SpecificPrice::deleteByIdCart((int)$this->context->cart->id, (int)Tools::getValue('id_product'), (int)Tools::getValue('id_product_attribute')); - $specific_price = new SpecificPrice(); - $specific_price->id_cart = (int)$this->context->cart->id; - $specific_price->id_shop = 0; - $specific_price->id_shop_group = 0; - $specific_price->id_currency = 0; - $specific_price->id_country = 0; - $specific_price->id_group = 0; - $specific_price->id_customer = (int)$this->context->customer->id; - $specific_price->id_product = (int)Tools::getValue('id_product'); - $specific_price->id_product_attribute = (int)Tools::getValue('id_product_attribute'); - $specific_price->price = (float)Tools::getValue('price'); - $specific_price->from_quantity = 1; - $specific_price->reduction = 0; - $specific_price->reduction_type = 'amount'; - $specific_price->from = '0000-00-00 00:00:00'; - $specific_price->to = '0000-00-00 00:00:00'; - $specific_price->add(); - echo Tools::jsonEncode($this->ajaxReturnVars()); - } - } - - public static function getOrderTotalUsingTaxCalculationMethod($id_cart) - { - $context = Context::getContext(); - $context->cart = new Cart($id_cart); - $context->currency = new Currency((int)$context->cart->id_currency); - $context->customer = new Customer((int)$context->cart->id_customer); - return Cart::getTotalCart($id_cart, true, Cart::BOTH_WITHOUT_SHIPPING); - } - - public static function replaceZeroByShopName($echo, $tr) - { - return ($echo == '0' ? Carrier::getCarrierNameFromShopName() : $echo); - } - - public function displayDeleteLink($token = null, $id, $name = null) - { - // don't display ordered carts - foreach ($this->_list as $row) - if ($row['id_cart'] == $id && isset($row['id_order']) && is_numeric($row['id_order'])) - return ; - - return $this->helper->displayDeleteLink($token, $id, $name); - } - - public function renderList() - { - if (!($this->fields_list && is_array($this->fields_list))) - return false; - $this->getList($this->context->language->id); - - $helper = new HelperList(); - - // Empty list is ok - if (!is_array($this->_list)) - { - $this->displayWarning($this->l('Bad SQL query', 'Helper').'<br />'.htmlspecialchars($this->_list_error)); - return false; - } - - $this->setHelperDisplay($helper); - $helper->tpl_vars = $this->tpl_list_vars; - $helper->tpl_delete_link_vars = $this->tpl_delete_link_vars; - - // For compatibility reasons, we have to check standard actions in class attributes - foreach ($this->actions_available as $action) - { - if (!in_array($action, $this->actions) && isset($this->$action) && $this->$action) - $this->actions[] = $action; - } - $helper->is_cms = $this->is_cms; - $skip_list = array(); - - foreach ($this->_list as $row) - if (isset($row['id_order']) && is_numeric($row['id_order'])) - $skip_list[] = $row['id_cart']; - - if (array_key_exists('delete', $helper->list_skip_actions)) - $helper->list_skip_actions['delete'] = array_merge($helper->list_skip_actions['delete'], (array)$skip_list); - else - $helper->list_skip_actions['delete'] = (array)$skip_list; - - $list = $helper->generateList($this->_list, $this->fields_list); - return $list; - } + if (Tools::getValue('action') && Tools::getValue('action') == 'filterOnlyAbandonedCarts') { + $this->_having = 'status = \''.$this->l('Abandoned cart').'\''; + } else { + $this->_use_found_rows = false; + } + + $this->fields_list = array( + 'id_cart' => array( + 'title' => $this->l('ID'), + 'align' => 'text-center', + 'class' => 'fixed-width-xs' + ), + 'status' => array( + 'title' => $this->l('Order ID'), + 'align' => 'text-center', + 'badge_danger' => true, + 'havingFilter' => true + ), + 'customer' => array( + 'title' => $this->l('Customer'), + 'filter_key' => 'c!lastname' + ), + 'total' => array( + 'title' => $this->l('Total'), + 'callback' => 'getOrderTotalUsingTaxCalculationMethod', + 'orderby' => false, + 'search' => false, + 'align' => 'text-right', + 'badge_success' => true + ), + 'carrier' => array( + 'title' => $this->l('Carrier'), + 'align' => 'text-left', + 'callback' => 'replaceZeroByShopName', + 'filter_key' => 'ca!name' + ), + 'date_add' => array( + 'title' => $this->l('Date'), + 'align' => 'text-left', + 'type' => 'datetime', + 'class' => 'fixed-width-lg', + 'filter_key' => 'a!date_add' + ), + 'id_guest' => array( + 'title' => $this->l('Online'), + 'align' => 'text-center', + 'type' => 'bool', + 'havingFilter' => true, + 'class' => 'fixed-width-xs', + 'icon' => array(0 => 'icon-', 1 => 'icon-user') + ) + ); + $this->shopLinkType = 'shop'; + + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); + + parent::__construct(); + } + + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['export_cart'] = array( + 'href' => self::$currentIndex.'&exportcart&token='.$this->token, + 'desc' => $this->l('Export carts', null, null, false), + 'icon' => 'process-icon-export' + ); + } + + parent::initPageHeaderToolbar(); + } + + public function renderKpis() + { + $time = time(); + $kpis = array(); + + /* The data generation is located in AdminStatsControllerCore */ + $helper = new HelperKpi(); + $helper->id = 'box-conversion-rate'; + $helper->icon = 'icon-sort-by-attributes-alt'; + //$helper->chart = true; + $helper->color = 'color1'; + $helper->title = $this->l('Conversion Rate', null, null, false); + $helper->subtitle = $this->l('30 days', null, null, false); + if (ConfigurationKPI::get('CONVERSION_RATE') !== false) { + $helper->value = ConfigurationKPI::get('CONVERSION_RATE'); + } + if (ConfigurationKPI::get('CONVERSION_RATE_CHART') !== false) { + $helper->data = ConfigurationKPI::get('CONVERSION_RATE_CHART'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=conversion_rate'; + $helper->refresh = (bool)(ConfigurationKPI::get('CONVERSION_RATE_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-carts'; + $helper->icon = 'icon-shopping-cart'; + $helper->color = 'color2'; + $helper->title = $this->l('Abandoned Carts', null, null, false); + $date_from = date(Context::getContext()->language->date_format_lite, strtotime('-2 day')); + $date_to = date(Context::getContext()->language->date_format_lite, strtotime('-1 day')); + $helper->subtitle = sprintf($this->l('From %s to %s', null, null, false), $date_from, $date_to); + $helper->href = $this->context->link->getAdminLink('AdminCarts').'&action=filterOnlyAbandonedCarts'; + if (ConfigurationKPI::get('ABANDONED_CARTS') !== false) { + $helper->value = ConfigurationKPI::get('ABANDONED_CARTS'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=abandoned_cart'; + $helper->refresh = (bool)(ConfigurationKPI::get('ABANDONED_CARTS_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-average-order'; + $helper->icon = 'icon-money'; + $helper->color = 'color3'; + $helper->title = $this->l('Average Order Value', null, null, false); + $helper->subtitle = $this->l('30 days', null, null, false); + if (ConfigurationKPI::get('AVG_ORDER_VALUE') !== false) { + $helper->value = sprintf($this->l('%s tax excl.'), ConfigurationKPI::get('AVG_ORDER_VALUE')); + } + if (ConfigurationKPI::get('AVG_ORDER_VALUE_EXPIRE') < $time) { + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=average_order_value'; + } + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-net-profit-visitor'; + $helper->icon = 'icon-user'; + $helper->color = 'color4'; + $helper->title = $this->l('Net Profit per Visitor', null, null, false); + $helper->subtitle = $this->l('30 days', null, null, false); + if (ConfigurationKPI::get('NETPROFIT_VISITOR') !== false) { + $helper->value = ConfigurationKPI::get('NETPROFIT_VISITOR'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=netprofit_visitor'; + $helper->refresh = (bool)(ConfigurationKPI::get('NETPROFIT_VISITOR_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpiRow(); + $helper->kpis = $kpis; + return $helper->generate(); + } + + + public function renderView() + { + /** @var Cart $cart */ + if (!($cart = $this->loadObject(true))) { + return; + } + $customer = new Customer($cart->id_customer); + $currency = new Currency($cart->id_currency); + $this->context->cart = $cart; + $this->context->currency = $currency; + $this->context->customer = $customer; + $this->toolbar_title = sprintf($this->l('Cart #%06d'), $this->context->cart->id); + $products = $cart->getProducts(); + $customized_datas = Product::getAllCustomizedDatas((int)$cart->id); + Product::addCustomizationPrice($products, $customized_datas); + $summary = $cart->getSummaryDetails(); + + /* Display order information */ + $id_order = (int)Order::getOrderByCartId($cart->id); + $order = new Order($id_order); + if (Validate::isLoadedObject($order)) { + $tax_calculation_method = $order->getTaxCalculationMethod(); + $id_shop = (int)$order->id_shop; + } else { + $id_shop = (int)$cart->id_shop; + $tax_calculation_method = Group::getPriceDisplayMethod(Group::getCurrent()->id); + } + + if ($tax_calculation_method == PS_TAX_EXC) { + $total_products = $summary['total_products']; + $total_discounts = $summary['total_discounts_tax_exc']; + $total_wrapping = $summary['total_wrapping_tax_exc']; + $total_price = $summary['total_price_without_tax']; + $total_shipping = $summary['total_shipping_tax_exc']; + } else { + $total_products = $summary['total_products_wt']; + $total_discounts = $summary['total_discounts']; + $total_wrapping = $summary['total_wrapping']; + $total_price = $summary['total_price']; + $total_shipping = $summary['total_shipping']; + } + foreach ($products as $k => &$product) { + if ($tax_calculation_method == PS_TAX_EXC) { + $product['product_price'] = $product['price']; + $product['product_total'] = $product['total']; + } else { + $product['product_price'] = $product['price_wt']; + $product['product_total'] = $product['total_wt']; + } + $image = array(); + if (isset($product['id_product_attribute']) && (int)$product['id_product_attribute']) { + $image = Db::getInstance()->getRow('SELECT id_image FROM '._DB_PREFIX_.'product_attribute_image WHERE id_product_attribute = '.(int)$product['id_product_attribute']); + } + if (!isset($image['id_image'])) { + $image = Db::getInstance()->getRow('SELECT id_image FROM '._DB_PREFIX_.'image WHERE id_product = '.(int)$product['id_product'].' AND cover = 1'); + } + + $product['qty_in_stock'] = StockAvailable::getQuantityAvailableByProduct($product['id_product'], isset($product['id_product_attribute']) ? $product['id_product_attribute'] : null, (int)$id_shop); + + $image_product = new Image($image['id_image']); + $product['image'] = (isset($image['id_image']) ? ImageManager::thumbnail(_PS_IMG_DIR_.'p/'.$image_product->getExistingImgPath().'.jpg', 'product_mini_'.(int)$product['id_product'].(isset($product['id_product_attribute']) ? '_'.(int)$product['id_product_attribute'] : '').'.jpg', 45, 'jpg') : '--'); + } + + $helper = new HelperKpi(); + $helper->id = 'box-kpi-cart'; + $helper->icon = 'icon-shopping-cart'; + $helper->color = 'color1'; + $helper->title = $this->l('Total Cart', null, null, false); + $helper->subtitle = sprintf($this->l('Cart #%06d', null, null, false), $cart->id); + $helper->value = Tools::displayPrice($total_price, $currency); + $kpi = $helper->generate(); + + $this->tpl_view_vars = array( + 'kpi' => $kpi, + 'products' => $products, + 'discounts' => $cart->getCartRules(), + 'order' => $order, + 'cart' => $cart, + 'currency' => $currency, + 'customer' => $customer, + 'customer_stats' => $customer->getStats(), + 'total_products' => $total_products, + 'total_discounts' => $total_discounts, + 'total_wrapping' => $total_wrapping, + 'total_price' => $total_price, + 'total_shipping' => $total_shipping, + 'customized_datas' => $customized_datas, + 'tax_calculation_method' => $tax_calculation_method + ); + + return parent::renderView(); + } + + public function ajaxPreProcess() + { + if ($this->tabAccess['edit'] === '1') { + $id_customer = (int)Tools::getValue('id_customer'); + $customer = new Customer((int)$id_customer); + $this->context->customer = $customer; + $id_cart = (int)Tools::getValue('id_cart'); + if (!$id_cart) { + $id_cart = $customer->getLastCart(false); + } + $this->context->cart = new Cart((int)$id_cart); + + if (!$this->context->cart->id) { + $this->context->cart->recyclable = 0; + $this->context->cart->gift = 0; + } + + if (!$this->context->cart->id_customer) { + $this->context->cart->id_customer = $id_customer; + } + if (Validate::isLoadedObject($this->context->cart) && $this->context->cart->OrderExists()) { + return; + } + if (!$this->context->cart->secure_key) { + $this->context->cart->secure_key = $this->context->customer->secure_key; + } + if (!$this->context->cart->id_shop) { + $this->context->cart->id_shop = (int)$this->context->shop->id; + } + if (!$this->context->cart->id_lang) { + $this->context->cart->id_lang = (($id_lang = (int)Tools::getValue('id_lang')) ? $id_lang : Configuration::get('PS_LANG_DEFAULT')); + } + if (!$this->context->cart->id_currency) { + $this->context->cart->id_currency = (($id_currency = (int)Tools::getValue('id_currency')) ? $id_currency : Configuration::get('PS_CURRENCY_DEFAULT')); + } + + $addresses = $customer->getAddresses((int)$this->context->cart->id_lang); + $id_address_delivery = (int)Tools::getValue('id_address_delivery'); + $id_address_invoice = (int)Tools::getValue('id_address_delivery'); + + if (!$this->context->cart->id_address_invoice && isset($addresses[0])) { + $this->context->cart->id_address_invoice = (int)$addresses[0]['id_address']; + } elseif ($id_address_invoice) { + $this->context->cart->id_address_invoice = (int)$id_address_invoice; + } + if (!$this->context->cart->id_address_delivery && isset($addresses[0])) { + $this->context->cart->id_address_delivery = $addresses[0]['id_address']; + } elseif ($id_address_delivery) { + $this->context->cart->id_address_delivery = (int)$id_address_delivery; + } + $this->context->cart->setNoMultishipping(); + $this->context->cart->save(); + $currency = new Currency((int)$this->context->cart->id_currency); + $this->context->currency = $currency; + } + } + + public function ajaxProcessDeleteProduct() + { + if ($this->tabAccess['edit'] === '1') { + $errors = array(); + if ((!$id_product = (int)Tools::getValue('id_product')) || !Validate::isInt($id_product)) { + $errors[] = Tools::displayError('Invalid product'); + } + if (($id_product_attribute = (int)Tools::getValue('id_product_attribute')) && !Validate::isInt($id_product_attribute)) { + $errors[] = Tools::displayError('Invalid combination'); + } + if (count($errors)) { + die(Tools::jsonEncode($errors)); + } + if ($this->context->cart->deleteProduct($id_product, $id_product_attribute, (int)Tools::getValue('id_customization'))) { + echo Tools::jsonEncode($this->ajaxReturnVars()); + } + } + } + + public function ajaxProcessUpdateCustomizationFields() + { + $errors = array(); + if ($this->tabAccess['edit'] === '1') { + $errors = array(); + if (Tools::getValue('only_display') != 1) { + if (!$this->context->cart->id || (!$id_product = (int)Tools::getValue('id_product'))) { + return; + } + $product = new Product((int)$id_product); + if (!$customization_fields = $product->getCustomizationFieldIds()) { + return; + } + foreach ($customization_fields as $customization_field) { + $field_id = 'customization_'.$id_product.'_'.$customization_field['id_customization_field']; + if ($customization_field['type'] == Product::CUSTOMIZE_TEXTFIELD) { + if (!Tools::getValue($field_id)) { + if ($customization_field['required']) { + $errors[] = Tools::displayError('Please fill in all the required fields.'); + } + continue; + } + if (!Validate::isMessage(Tools::getValue($field_id))) { + $errors[] = Tools::displayError('Invalid message'); + } + $this->context->cart->addTextFieldToProduct((int)$product->id, (int)$customization_field['id_customization_field'], Product::CUSTOMIZE_TEXTFIELD, Tools::getValue($field_id)); + } elseif ($customization_field['type'] == Product::CUSTOMIZE_FILE) { + if (!isset($_FILES[$field_id]) || !isset($_FILES[$field_id]['tmp_name']) || empty($_FILES[$field_id]['tmp_name'])) { + if ($customization_field['required']) { + $errors[] = Tools::displayError('Please fill in all the required fields.'); + } + continue; + } + if ($error = ImageManager::validateUpload($_FILES[$field_id], (int)Configuration::get('PS_PRODUCT_PICTURE_MAX_SIZE'))) { + $errors[] = $error; + } + if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES[$field_id]['tmp_name'], $tmp_name)) { + $errors[] = Tools::displayError('An error occurred during the image upload process.'); + } + $file_name = md5(uniqid(rand(), true)); + if (!ImageManager::resize($tmp_name, _PS_UPLOAD_DIR_.$file_name)) { + continue; + } elseif (!ImageManager::resize($tmp_name, _PS_UPLOAD_DIR_.$file_name.'_small', (int)Configuration::get('PS_PRODUCT_PICTURE_WIDTH'), (int)Configuration::get('PS_PRODUCT_PICTURE_HEIGHT'))) { + $errors[] = Tools::displayError('An error occurred during the image upload process.'); + } elseif (!chmod(_PS_UPLOAD_DIR_.$file_name, 0777) || !chmod(_PS_UPLOAD_DIR_.$file_name.'_small', 0777)) { + $errors[] = Tools::displayError('An error occurred during the image upload process.'); + } else { + $this->context->cart->addPictureToProduct((int)$product->id, (int)$customization_field['id_customization_field'], Product::CUSTOMIZE_FILE, $file_name); + } + unlink($tmp_name); + } + } + } + $this->setMedia(); + $this->initFooter(); + $this->context->smarty->assign(array('customization_errors' => implode('<br />', $errors), + 'css_files' => $this->css_files)); + return $this->smartyOutputContent('controllers/orders/form_customization_feedback.tpl'); + } + } + + public function ajaxProcessUpdateQty() + { + if ($this->tabAccess['edit'] === '1') { + $errors = array(); + if (!$this->context->cart->id) { + return; + } + if ($this->context->cart->OrderExists()) { + $errors[] = Tools::displayError('An order has already been placed with this cart.'); + } elseif (!($id_product = (int)Tools::getValue('id_product')) || !($product = new Product((int)$id_product, true, $this->context->language->id))) { + $errors[] = Tools::displayError('Invalid product'); + } elseif (!($qty = Tools::getValue('qty')) || $qty == 0) { + $errors[] = Tools::displayError('Invalid quantity'); + } + + // Don't try to use a product if not instanciated before due to errors + if (isset($product) && $product->id) { + if (($id_product_attribute = Tools::getValue('id_product_attribute')) != 0) { + if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty((int)$id_product_attribute, (int)$qty)) { + $errors[] = Tools::displayError('There is not enough product in stock.'); + } + } elseif (!$product->checkQty((int)$qty)) { + $errors[] = Tools::displayError('There is not enough product in stock.'); + } + if (!($id_customization = (int)Tools::getValue('id_customization', 0)) && !$product->hasAllRequiredCustomizableFields()) { + $errors[] = Tools::displayError('Please fill in all the required fields.'); + } + $this->context->cart->save(); + } else { + $errors[] = Tools::displayError('This product cannot be added to the cart.'); + } + + if (!count($errors)) { + if ((int)$qty < 0) { + $qty = str_replace('-', '', $qty); + $operator = 'down'; + } else { + $operator = 'up'; + } + + if (!($qty_upd = $this->context->cart->updateQty($qty, $id_product, (int)$id_product_attribute, (int)$id_customization, $operator))) { + $errors[] = Tools::displayError('You already have the maximum quantity available for this product.'); + } elseif ($qty_upd < 0) { + $minimal_qty = $id_product_attribute ? Attribute::getAttributeMinimalQty((int)$id_product_attribute) : $product->minimal_quantity; + $errors[] = sprintf(Tools::displayError('You must add a minimum quantity of %d', false), $minimal_qty); + } + } + + echo Tools::jsonEncode(array_merge($this->ajaxReturnVars(), array('errors' => $errors))); + } + } + + public function ajaxProcessUpdateDeliveryOption() + { + if ($this->tabAccess['edit'] === '1') { + $delivery_option = Tools::getValue('delivery_option'); + if ($delivery_option !== false) { + $this->context->cart->setDeliveryOption(array($this->context->cart->id_address_delivery => $delivery_option)); + } + if (Validate::isBool(($recyclable = (int)Tools::getValue('recyclable')))) { + $this->context->cart->recyclable = $recyclable; + } + if (Validate::isBool(($gift = (int)Tools::getValue('gift')))) { + $this->context->cart->gift = $gift; + } + if (Validate::isMessage(($gift_message = pSQL(Tools::getValue('gift_message'))))) { + $this->context->cart->gift_message = $gift_message; + } + $this->context->cart->save(); + echo Tools::jsonEncode($this->ajaxReturnVars()); + } + } + + public function ajaxProcessUpdateOrderMessage() + { + if ($this->tabAccess['edit'] === '1') { + $id_message = false; + if ($old_message = Message::getMessageByCartId((int)$this->context->cart->id)) { + $id_message = $old_message['id_message']; + } + $message = new Message((int)$id_message); + if ($message_content = Tools::getValue('message')) { + if (Validate::isMessage($message_content)) { + $message->message = $message_content; + $message->id_cart = (int)$this->context->cart->id; + $message->id_customer = (int)$this->context->cart->id_customer; + $message->save(); + } + } elseif (Validate::isLoadedObject($message)) { + $message->delete(); + } + echo Tools::jsonEncode($this->ajaxReturnVars()); + } + } + + public function ajaxProcessUpdateCurrency() + { + if ($this->tabAccess['edit'] === '1') { + $currency = new Currency((int)Tools::getValue('id_currency')); + if (Validate::isLoadedObject($currency) && !$currency->deleted && $currency->active) { + $this->context->cart->id_currency = (int)$currency->id; + $this->context->currency = $currency; + $this->context->cart->save(); + } + echo Tools::jsonEncode($this->ajaxReturnVars()); + } + } + public function ajaxProcessUpdateLang() + { + if ($this->tabAccess['edit'] === '1') { + $lang = new Language((int)Tools::getValue('id_lang')); + if (Validate::isLoadedObject($lang) && $lang->active) { + $this->context->cart->id_lang = (int)$lang->id; + $this->context->cart->save(); + } + echo Tools::jsonEncode($this->ajaxReturnVars()); + } + } + + public function ajaxProcessDuplicateOrder() + { + if ($this->tabAccess['edit'] === '1') { + $errors = array(); + if (!$id_order = Tools::getValue('id_order')) { + $errors[] = Tools::displayError('Invalid order'); + } + $cart = Cart::getCartByOrderId($id_order); + $new_cart = $cart->duplicate(); + if (!$new_cart || !Validate::isLoadedObject($new_cart['cart'])) { + $errors[] = Tools::displayError('The order cannot be renewed.'); + } elseif (!$new_cart['success']) { + $errors[] = Tools::displayError('The order cannot be renewed.'); + } else { + $this->context->cart = $new_cart['cart']; + echo Tools::jsonEncode($this->ajaxReturnVars()); + } + } + } + + public function ajaxProcessDeleteVoucher() + { + if ($this->tabAccess['edit'] === '1') { + if ($this->context->cart->removeCartRule((int)Tools::getValue('id_cart_rule'))) { + echo Tools::jsonEncode($this->ajaxReturnVars()); + } + } + } + + public function ajaxProcessupdateFreeShipping() + { + if ($this->tabAccess['edit'] === '1') { + if (!$id_cart_rule = CartRule::getIdByCode(CartRule::BO_ORDER_CODE_PREFIX.(int)$this->context->cart->id)) { + $cart_rule = new CartRule(); + $cart_rule->code = CartRule::BO_ORDER_CODE_PREFIX.(int)$this->context->cart->id; + $cart_rule->name = array(Configuration::get('PS_LANG_DEFAULT') => $this->l('Free Shipping', 'AdminTab', false, false)); + $cart_rule->id_customer = (int)$this->context->cart->id_customer; + $cart_rule->free_shipping = true; + $cart_rule->quantity = 1; + $cart_rule->quantity_per_user = 1; + $cart_rule->minimum_amount_currency = (int)$this->context->cart->id_currency; + $cart_rule->reduction_currency = (int)$this->context->cart->id_currency; + $cart_rule->date_from = date('Y-m-d H:i:s', time()); + $cart_rule->date_to = date('Y-m-d H:i:s', time() + 24 * 36000); + $cart_rule->active = 1; + $cart_rule->add(); + } else { + $cart_rule = new CartRule((int)$id_cart_rule); + } + + $this->context->cart->removeCartRule((int)$cart_rule->id); + if (Tools::getValue('free_shipping')) { + $this->context->cart->addCartRule((int)$cart_rule->id); + } + + echo Tools::jsonEncode($this->ajaxReturnVars()); + } + } + + public function ajaxProcessAddVoucher() + { + if ($this->tabAccess['edit'] === '1') { + $errors = array(); + if (!($id_cart_rule = Tools::getValue('id_cart_rule')) || !$cart_rule = new CartRule((int)$id_cart_rule)) { + $errors[] = Tools::displayError('Invalid voucher.'); + } elseif ($err = $cart_rule->checkValidity($this->context)) { + $errors[] = $err; + } + if (!count($errors)) { + if (!$this->context->cart->addCartRule((int)$cart_rule->id)) { + $errors[] = Tools::displayError('Can\'t add the voucher.'); + } + } + echo Tools::jsonEncode(array_merge($this->ajaxReturnVars(), array('errors' => $errors))); + } + } + + public function ajaxProcessUpdateAddress() + { + if ($this->tabAccess['edit'] === '1') { + echo Tools::jsonEncode(array('addresses' => $this->context->customer->getAddresses((int)$this->context->cart->id_lang))); + } + } + + public function ajaxProcessUpdateAddresses() + { + if ($this->tabAccess['edit'] === '1') { + if (($id_address_delivery = (int)Tools::getValue('id_address_delivery')) && + ($address_delivery = new Address((int)$id_address_delivery)) && + $address_delivery->id_customer == $this->context->cart->id_customer) { + $this->context->cart->id_address_delivery = (int)$address_delivery->id; + } + + if (($id_address_invoice = (int)Tools::getValue('id_address_invoice')) && + ($address_invoice = new Address((int)$id_address_invoice)) && + $address_invoice->id_customer = $this->context->cart->id_customer) { + $this->context->cart->id_address_invoice = (int)$address_invoice->id; + } + $this->context->cart->save(); + + echo Tools::jsonEncode($this->ajaxReturnVars()); + } + } + + protected function getCartSummary() + { + $summary = $this->context->cart->getSummaryDetails(null, true); + $currency = Context::getContext()->currency; + if (count($summary['products'])) { + foreach ($summary['products'] as &$product) { + $product['numeric_price'] = $product['price']; + $product['numeric_total'] = $product['total']; + $product['price'] = str_replace($currency->sign, '', Tools::displayPrice($product['price'], $currency)); + $product['total'] = str_replace($currency->sign, '', Tools::displayPrice($product['total'], $currency)); + $product['image_link'] = $this->context->link->getImageLink($product['link_rewrite'], $product['id_image'], 'small_default'); + if (!isset($product['attributes_small'])) { + $product['attributes_small'] = ''; + } + $product['customized_datas'] = Product::getAllCustomizedDatas((int)$this->context->cart->id, null, true); + } + } + if (count($summary['discounts'])) { + foreach ($summary['discounts'] as &$voucher) { + $voucher['value_real'] = Tools::displayPrice($voucher['value_real'], $currency); + } + } + + if (isset($summary['gift_products']) && count($summary['gift_products'])) { + foreach ($summary['gift_products'] as &$product) { + $product['image_link'] = $this->context->link->getImageLink($product['link_rewrite'], $product['id_image'], 'small_default'); + if (!isset($product['attributes_small'])) { + $product['attributes_small'] = ''; + } + } + } + + + return $summary; + } + + protected function getDeliveryOptionList() + { + $delivery_option_list_formated = array(); + $delivery_option_list = $this->context->cart->getDeliveryOptionList(); + + if (!count($delivery_option_list)) { + return array(); + } + + $id_default_carrier = (int)Configuration::get('PS_CARRIER_DEFAULT'); + foreach (current($delivery_option_list) as $key => $delivery_option) { + $name = ''; + $first = true; + $id_default_carrier_delivery = false; + foreach ($delivery_option['carrier_list'] as $carrier) { + if (!$first) { + $name .= ', '; + } else { + $first = false; + } + + $name .= $carrier['instance']->name; + + if ($delivery_option['unique_carrier']) { + $name .= ' - '.$carrier['instance']->delay[$this->context->employee->id_lang]; + } + + if (!$id_default_carrier_delivery) { + $id_default_carrier_delivery = (int)$carrier['instance']->id; + } + if ($carrier['instance']->id == $id_default_carrier) { + $id_default_carrier_delivery = $id_default_carrier; + } + if (!$this->context->cart->id_carrier) { + $this->context->cart->setDeliveryOption(array($this->context->cart->id_address_delivery => (int)$carrier['instance']->id.',')); + $this->context->cart->save(); + } + } + $delivery_option_list_formated[] = array('name' => $name, 'key' => $key); + } + return $delivery_option_list_formated; + } + + public function displayAjaxSearchCarts() + { + $id_customer = (int)Tools::getValue('id_customer'); + $carts = Cart::getCustomerCarts((int)$id_customer); + $orders = Order::getCustomerOrders((int)$id_customer); + $customer = new Customer((int)$id_customer); + + if (count($carts)) { + foreach ($carts as $key => &$cart) { + $cart_obj = new Cart((int)$cart['id_cart']); + if ($cart['id_cart'] == $this->context->cart->id || !Validate::isLoadedObject($cart_obj) || $cart_obj->OrderExists()) { + unset($carts[$key]); + } + $currency = new Currency((int)$cart['id_currency']); + $cart['total_price'] = Tools::displayPrice($cart_obj->getOrderTotal(), $currency); + } + } + if (count($orders)) { + foreach ($orders as &$order) { + $order['total_paid_real'] = Tools::displayPrice($order['total_paid_real'], $currency); + } + } + if ($orders || $carts) { + $to_return = array_merge($this->ajaxReturnVars(), + array('carts' => $carts, + 'orders' => $orders, + 'found' => true)); + } else { + $to_return = array_merge($this->ajaxReturnVars(), array('found' => false)); + } + + echo Tools::jsonEncode($to_return); + } + + public function ajaxReturnVars() + { + $id_cart = (int)$this->context->cart->id; + $message_content = ''; + if ($message = Message::getMessageByCartId((int)$this->context->cart->id)) { + $message_content = $message['message']; + } + $cart_rules = $this->context->cart->getCartRules(CartRule::FILTER_ACTION_SHIPPING); + + $free_shipping = false; + if (count($cart_rules)) { + foreach ($cart_rules as $cart_rule) { + if ($cart_rule['id_cart_rule'] == CartRule::getIdByCode(CartRule::BO_ORDER_CODE_PREFIX.(int)$this->context->cart->id)) { + $free_shipping = true; + break; + } + } + } + + $addresses = $this->context->customer->getAddresses((int)$this->context->cart->id_lang); + + foreach ($addresses as &$data) { + $address = new Address((int)$data['id_address']); + $data['formated_address'] = AddressFormat::generateAddress($address, array(), "<br />"); + } + + return array( + 'summary' => $this->getCartSummary(), + 'delivery_option_list' => $this->getDeliveryOptionList(), + 'cart' => $this->context->cart, + 'currency' => new Currency($this->context->cart->id_currency), + 'addresses' => $addresses, + 'id_cart' => $id_cart, + 'order_message' => $message_content, + 'link_order' => $this->context->link->getPageLink( + 'order', false, + (int)$this->context->cart->id_lang, + 'step=3&recover_cart='.$id_cart.'&token_cart='.md5(_COOKIE_KEY_.'recover_cart_'.$id_cart) + ), + 'free_shipping' => (int)$free_shipping + ); + } + + public function initToolbar() + { + parent::initToolbar(); + unset($this->toolbar_btn['new']); + } + + public function displayAjaxGetSummary() + { + echo Tools::jsonEncode($this->ajaxReturnVars()); + } + + public function ajaxProcessUpdateProductPrice() + { + if ($this->tabAccess['edit'] === '1') { + SpecificPrice::deleteByIdCart((int)$this->context->cart->id, (int)Tools::getValue('id_product'), (int)Tools::getValue('id_product_attribute')); + $specific_price = new SpecificPrice(); + $specific_price->id_cart = (int)$this->context->cart->id; + $specific_price->id_shop = 0; + $specific_price->id_shop_group = 0; + $specific_price->id_currency = 0; + $specific_price->id_country = 0; + $specific_price->id_group = 0; + $specific_price->id_customer = (int)$this->context->customer->id; + $specific_price->id_product = (int)Tools::getValue('id_product'); + $specific_price->id_product_attribute = (int)Tools::getValue('id_product_attribute'); + $specific_price->price = (float)Tools::getValue('price'); + $specific_price->from_quantity = 1; + $specific_price->reduction = 0; + $specific_price->reduction_type = 'amount'; + $specific_price->from = '0000-00-00 00:00:00'; + $specific_price->to = '0000-00-00 00:00:00'; + $specific_price->add(); + echo Tools::jsonEncode($this->ajaxReturnVars()); + } + } + + public static function getOrderTotalUsingTaxCalculationMethod($id_cart) + { + $context = Context::getContext(); + $context->cart = new Cart($id_cart); + $context->currency = new Currency((int)$context->cart->id_currency); + $context->customer = new Customer((int)$context->cart->id_customer); + return Cart::getTotalCart($id_cart, true, Cart::BOTH_WITHOUT_SHIPPING); + } + + public static function replaceZeroByShopName($echo, $tr) + { + return ($echo == '0' ? Carrier::getCarrierNameFromShopName() : $echo); + } + + public function displayDeleteLink($token = null, $id, $name = null) + { + // don't display ordered carts + foreach ($this->_list as $row) { + if ($row['id_cart'] == $id && isset($row['id_order']) && is_numeric($row['id_order'])) { + return ; + } + } + + return $this->helper->displayDeleteLink($token, $id, $name); + } + + public function renderList() + { + if (!($this->fields_list && is_array($this->fields_list))) { + return false; + } + $this->getList($this->context->language->id); + + $helper = new HelperList(); + + // Empty list is ok + if (!is_array($this->_list)) { + $this->displayWarning($this->l('Bad SQL query', 'Helper').'<br />'.htmlspecialchars($this->_list_error)); + return false; + } + + $this->setHelperDisplay($helper); + $helper->tpl_vars = $this->tpl_list_vars; + $helper->tpl_delete_link_vars = $this->tpl_delete_link_vars; + + // For compatibility reasons, we have to check standard actions in class attributes + foreach ($this->actions_available as $action) { + if (!in_array($action, $this->actions) && isset($this->$action) && $this->$action) { + $this->actions[] = $action; + } + } + $helper->is_cms = $this->is_cms; + $skip_list = array(); + + foreach ($this->_list as $row) { + if (isset($row['id_order']) && is_numeric($row['id_order'])) { + $skip_list[] = $row['id_cart']; + } + } + + if (array_key_exists('delete', $helper->list_skip_actions)) { + $helper->list_skip_actions['delete'] = array_merge($helper->list_skip_actions['delete'], (array)$skip_list); + } else { + $helper->list_skip_actions['delete'] = (array)$skip_list; + } + + $list = $helper->generateList($this->_list, $this->fields_list); + return $list; + } } diff --git a/controllers/admin/AdminCategoriesController.php b/controllers/admin/AdminCategoriesController.php index 702af5b7..e23f988f 100644 --- a/controllers/admin/AdminCategoriesController.php +++ b/controllers/admin/AdminCategoriesController.php @@ -29,837 +29,843 @@ */ class AdminCategoriesControllerCore extends AdminController { - /** - * @var object Category() instance for navigation - */ - protected $_category = null; - protected $position_identifier = 'id_category_to_move'; + /** + * @var object Category() instance for navigation + */ + protected $_category = null; + protected $position_identifier = 'id_category_to_move'; - /** @var bool does the product have to be removed during the delete process */ - public $remove_products = true; + /** @var bool does the product have to be removed during the delete process */ + public $remove_products = true; - /** @var bool does the product have to be disable during the delete process */ - public $disable_products = false; + /** @var bool does the product have to be disable during the delete process */ + public $disable_products = false; - private $original_filter = ''; + private $original_filter = ''; - public function __construct() - { - $this->bootstrap = true; - $this->table = 'category'; - $this->className = 'Category'; - $this->lang = true; - $this->deleted = false; - $this->explicitSelect = true; - $this->_defaultOrderBy = 'position'; - $this->allow_export = true; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'category'; + $this->className = 'Category'; + $this->lang = true; + $this->deleted = false; + $this->explicitSelect = true; + $this->_defaultOrderBy = 'position'; + $this->allow_export = true; - $this->context = Context::getContext(); + $this->context = Context::getContext(); - $this->fieldImageSettings = array( - 'name' => 'image', - 'dir' => 'c' - ); + $this->fieldImageSettings = array( + 'name' => 'image', + 'dir' => 'c' + ); - $this->fields_list = array( - 'id_category' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Name') - ), - 'description' => array( - 'title' => $this->l('Description'), - 'callback' => 'getDescriptionClean', - 'orderby' => false - ), - 'position' => array( - 'title' => $this->l('Position'), - 'filter_key' => 'sa!position', - 'position' => 'position', - 'align' => 'center' - ), - 'active' => array( - 'title' => $this->l('Displayed'), - 'active' => 'status', - 'type' => 'bool', - 'class' => 'fixed-width-xs', - 'align' => 'center', - 'ajax' => true, - 'orderby' => false - ) - ); + $this->fields_list = array( + 'id_category' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Name') + ), + 'description' => array( + 'title' => $this->l('Description'), + 'callback' => 'getDescriptionClean', + 'orderby' => false + ), + 'position' => array( + 'title' => $this->l('Position'), + 'filter_key' => 'sa!position', + 'position' => 'position', + 'align' => 'center' + ), + 'active' => array( + 'title' => $this->l('Displayed'), + 'active' => 'status', + 'type' => 'bool', + 'class' => 'fixed-width-xs', + 'align' => 'center', + 'ajax' => true, + 'orderby' => false + ) + ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'icon' => 'icon-trash', - 'confirm' => $this->l('Delete selected items?') - ) - ); - $this->specificConfirmDelete = false; + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'icon' => 'icon-trash', + 'confirm' => $this->l('Delete selected items?') + ) + ); + $this->specificConfirmDelete = false; - parent::__construct(); - } + parent::__construct(); + } - public function init() - { - parent::init(); + public function init() + { + parent::init(); - // context->shop is set in the init() function, so we move the _category instanciation after that - if (($id_category = Tools::getvalue('id_category')) && $this->action != 'select_delete') - $this->_category = new Category($id_category); - else - { - if (Shop::getContext() == Shop::CONTEXT_SHOP) - $this->_category = new Category($this->context->shop->id_category); - elseif (count(Category::getCategoriesWithoutParent()) > 1 && Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && count(Shop::getShops(true, null, true)) != 1) - $this->_category = Category::getTopCategory(); - else - $this->_category = new Category(Configuration::get('PS_HOME_CATEGORY')); - } + // context->shop is set in the init() function, so we move the _category instanciation after that + if (($id_category = Tools::getvalue('id_category')) && $this->action != 'select_delete') { + $this->_category = new Category($id_category); + } else { + if (Shop::getContext() == Shop::CONTEXT_SHOP) { + $this->_category = new Category($this->context->shop->id_category); + } elseif (count(Category::getCategoriesWithoutParent()) > 1 && Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && count(Shop::getShops(true, null, true)) != 1) { + $this->_category = Category::getTopCategory(); + } else { + $this->_category = new Category(Configuration::get('PS_HOME_CATEGORY')); + } + } - $count_categories_without_parent = count(Category::getCategoriesWithoutParent()); + $count_categories_without_parent = count(Category::getCategoriesWithoutParent()); - if (Tools::isSubmit('id_category')) - $id_parent = $this->_category->id; - elseif (!Shop::isFeatureActive() && $count_categories_without_parent > 1) - $id_parent = (int)Configuration::get('PS_ROOT_CATEGORY'); - elseif (Shop::isFeatureActive() && $count_categories_without_parent == 1) - $id_parent = (int)Configuration::get('PS_HOME_CATEGORY'); - elseif (Shop::isFeatureActive() && $count_categories_without_parent > 1 && Shop::getContext() != Shop::CONTEXT_SHOP) - { - if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && count(Shop::getShops(true, null, true)) == 1) - $id_parent = $this->context->shop->id_category; - else - $id_parent = (int)Configuration::get('PS_ROOT_CATEGORY'); - } - else - $id_parent = $this->context->shop->id_category; - $this->_select = 'sa.position position'; - $this->original_filter = $this->_filter .= ' AND `id_parent` = '.(int)$id_parent.' '; - $this->_use_found_rows = false; + if (Tools::isSubmit('id_category')) { + $id_parent = $this->_category->id; + } elseif (!Shop::isFeatureActive() && $count_categories_without_parent > 1) { + $id_parent = (int)Configuration::get('PS_ROOT_CATEGORY'); + } elseif (Shop::isFeatureActive() && $count_categories_without_parent == 1) { + $id_parent = (int)Configuration::get('PS_HOME_CATEGORY'); + } elseif (Shop::isFeatureActive() && $count_categories_without_parent > 1 && Shop::getContext() != Shop::CONTEXT_SHOP) { + if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && count(Shop::getShops(true, null, true)) == 1) { + $id_parent = $this->context->shop->id_category; + } else { + $id_parent = (int)Configuration::get('PS_ROOT_CATEGORY'); + } + } else { + $id_parent = $this->context->shop->id_category; + } + $this->_select = 'sa.position position'; + $this->original_filter = $this->_filter .= ' AND `id_parent` = '.(int)$id_parent.' '; + $this->_use_found_rows = false; - if (Shop::getContext() == Shop::CONTEXT_SHOP) - $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'category_shop` sa ON (a.`id_category` = sa.`id_category` AND sa.id_shop = '.(int)$this->context->shop->id.') '; - else - $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'category_shop` sa ON (a.`id_category` = sa.`id_category` AND sa.id_shop = a.id_shop_default) '; + if (Shop::getContext() == Shop::CONTEXT_SHOP) { + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'category_shop` sa ON (a.`id_category` = sa.`id_category` AND sa.id_shop = '.(int)$this->context->shop->id.') '; + } else { + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'category_shop` sa ON (a.`id_category` = sa.`id_category` AND sa.id_shop = a.id_shop_default) '; + } - // we add restriction for shop - if (Shop::getContext() == Shop::CONTEXT_SHOP && Shop::isFeatureActive()) - $this->_where = ' AND sa.`id_shop` = '.(int)Context::getContext()->shop->id; + // we add restriction for shop + if (Shop::getContext() == Shop::CONTEXT_SHOP && Shop::isFeatureActive()) { + $this->_where = ' AND sa.`id_shop` = '.(int)Context::getContext()->shop->id; + } - // if we are not in a shop context, we remove the position column - if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) - unset($this->fields_list['position']); - // shop restriction : if category is not available for current shop, we redirect to the list from default category - if (Validate::isLoadedObject($this->_category) && !$this->_category->isAssociatedToShop() && Shop::getContext() == Shop::CONTEXT_SHOP) - { - $this->redirect_after = self::$currentIndex.'&id_category='.(int)$this->context->shop->getCategory().'&token='.$this->token; - $this->redirect(); - } - } + // if we are not in a shop context, we remove the position column + if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) { + unset($this->fields_list['position']); + } + // shop restriction : if category is not available for current shop, we redirect to the list from default category + if (Validate::isLoadedObject($this->_category) && !$this->_category->isAssociatedToShop() && Shop::getContext() == Shop::CONTEXT_SHOP) { + $this->redirect_after = self::$currentIndex.'&id_category='.(int)$this->context->shop->getCategory().'&token='.$this->token; + $this->redirect(); + } + } - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); - if ($this->display != 'edit' && $this->display != 'add') - { - if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE')) - $this->page_header_toolbar_btn['new-url'] = array( - 'href' => self::$currentIndex.'&add'.$this->table.'root&token='.$this->token, - 'desc' => $this->l('Add new root category', null, null, false) - ); + if ($this->display != 'edit' && $this->display != 'add') { + if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE')) { + $this->page_header_toolbar_btn['new-url'] = array( + 'href' => self::$currentIndex.'&add'.$this->table.'root&token='.$this->token, + 'desc' => $this->l('Add new root category', null, null, false) + ); + } - $id_category = (Tools::isSubmit('id_category')) ? '&id_parent='.(int)Tools::getValue('id_category') : ''; - $this->page_header_toolbar_btn['new_category'] = array( - 'href' => self::$currentIndex.'&addcategory&token='.$this->token.$id_category, - 'desc' => $this->l('Add new category', null, null, false), - 'icon' => 'process-icon-new' - ); - } - } + $id_category = (Tools::isSubmit('id_category')) ? '&id_parent='.(int)Tools::getValue('id_category') : ''; + $this->page_header_toolbar_btn['new_category'] = array( + 'href' => self::$currentIndex.'&addcategory&token='.$this->token.$id_category, + 'desc' => $this->l('Add new category', null, null, false), + 'icon' => 'process-icon-new' + ); + } + } - public function initContent() - { - if ($this->action == 'select_delete') - $this->context->smarty->assign(array( - 'delete_form' => true, - 'url_delete' => htmlentities($_SERVER['REQUEST_URI']), - 'boxes' => $this->boxes, - )); + public function initContent() + { + if ($this->action == 'select_delete') { + $this->context->smarty->assign(array( + 'delete_form' => true, + 'url_delete' => htmlentities($_SERVER['REQUEST_URI']), + 'boxes' => $this->boxes, + )); + } - parent::initContent(); - } + parent::initContent(); + } - public function setMedia() - { - parent::setMedia(); - $this->addJqueryUi('ui.widget'); - $this->addJqueryPlugin('tagify'); - } + public function setMedia() + { + parent::setMedia(); + $this->addJqueryUi('ui.widget'); + $this->addJqueryPlugin('tagify'); + } - public function renderList() - { - if (isset($this->_filter) && trim($this->_filter) == '') - $this->_filter = $this->original_filter; + public function renderList() + { + if (isset($this->_filter) && trim($this->_filter) == '') { + $this->_filter = $this->original_filter; + } - $this->addRowAction('view'); - $this->addRowAction('add'); - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('view'); + $this->addRowAction('add'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $count_categories_without_parent = count(Category::getCategoriesWithoutParent()); - $categories_tree = $this->_category->getParentsCategories(); + $count_categories_without_parent = count(Category::getCategoriesWithoutParent()); + $categories_tree = $this->_category->getParentsCategories(); - if (empty($categories_tree) - && ($this->_category->id != (int)Configuration::get('PS_ROOT_CATEGORY') || Tools::isSubmit('id_category')) - && (Shop::getContext() == Shop::CONTEXT_SHOP && !Shop::isFeatureActive() && $count_categories_without_parent > 1)) - $categories_tree = array(array('name' => $this->_category->name[$this->context->language->id])); + if (empty($categories_tree) + && ($this->_category->id != (int)Configuration::get('PS_ROOT_CATEGORY') || Tools::isSubmit('id_category')) + && (Shop::getContext() == Shop::CONTEXT_SHOP && !Shop::isFeatureActive() && $count_categories_without_parent > 1)) { + $categories_tree = array(array('name' => $this->_category->name[$this->context->language->id])); + } - $categories_tree = array_reverse($categories_tree); + $categories_tree = array_reverse($categories_tree); - $this->tpl_list_vars['categories_tree'] = $categories_tree; - $this->tpl_list_vars['categories_tree_current_id'] = $this->_category->id; + $this->tpl_list_vars['categories_tree'] = $categories_tree; + $this->tpl_list_vars['categories_tree_current_id'] = $this->_category->id; - if (Tools::isSubmit('submitBulkdelete'.$this->table) || Tools::isSubmit('delete'.$this->table)) - { - $category = new Category(Tools::getValue('id_category')); - if ($category->is_root_category) - $this->tpl_list_vars['need_delete_mode'] = false; - else - $this->tpl_list_vars['need_delete_mode'] = true; - $this->tpl_list_vars['delete_category'] = true; - $this->tpl_list_vars['REQUEST_URI'] = $_SERVER['REQUEST_URI']; - $this->tpl_list_vars['POST'] = $_POST; - } + if (Tools::isSubmit('submitBulkdelete'.$this->table) || Tools::isSubmit('delete'.$this->table)) { + $category = new Category(Tools::getValue('id_category')); + if ($category->is_root_category) { + $this->tpl_list_vars['need_delete_mode'] = false; + } else { + $this->tpl_list_vars['need_delete_mode'] = true; + } + $this->tpl_list_vars['delete_category'] = true; + $this->tpl_list_vars['REQUEST_URI'] = $_SERVER['REQUEST_URI']; + $this->tpl_list_vars['POST'] = $_POST; + } - return parent::renderList(); - } + return parent::renderList(); + } - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, Context::getContext()->shop->id); - // Check each row to see if there are combinations and get the correct action in consequence + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, Context::getContext()->shop->id); + // Check each row to see if there are combinations and get the correct action in consequence - $nb_items = count($this->_list); - for ($i = 0; $i < $nb_items; $i++) - { - $item = &$this->_list[$i]; - $category_tree = Category::getChildren((int)$item['id_category'], $this->context->language->id); - if (!count($category_tree)) - $this->addRowActionSkipList('view', array($item['id_category'])); - } - } + $nb_items = count($this->_list); + for ($i = 0; $i < $nb_items; $i++) { + $item = &$this->_list[$i]; + $category_tree = Category::getChildren((int)$item['id_category'], $this->context->language->id); + if (!count($category_tree)) { + $this->addRowActionSkipList('view', array($item['id_category'])); + } + } + } - public function renderView() - { - $this->initToolbar(); - return $this->renderList(); - } + public function renderView() + { + $this->initToolbar(); + return $this->renderList(); + } - public function initToolbar() - { - if (empty($this->display)) - { - $this->toolbar_btn['new'] = array( - 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token, - 'desc' => $this->l('Add New') - ); + public function initToolbar() + { + if (empty($this->display)) { + $this->toolbar_btn['new'] = array( + 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token, + 'desc' => $this->l('Add New') + ); - if ($this->can_import) - $this->toolbar_btn['import'] = array( - 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=categories', - 'desc' => $this->l('Import') - ); - } - // be able to edit the Home category - if (count(Category::getCategoriesWithoutParent()) == 1 && !Tools::isSubmit('id_category') - && ($this->display == 'view' || empty($this->display))) - $this->toolbar_btn['edit'] = array( - 'href' => self::$currentIndex.'&update'.$this->table.'&id_category='.(int)$this->_category->id.'&token='.$this->token, - 'desc' => $this->l('Edit') - ); - if (Tools::getValue('id_category') && !Tools::isSubmit('updatecategory')) - { - $this->toolbar_btn['edit'] = array( - 'href' => self::$currentIndex.'&update'.$this->table.'&id_category='.(int)Tools::getValue('id_category').'&token='.$this->token, - 'desc' => $this->l('Edit') - ); - } + if ($this->can_import) { + $this->toolbar_btn['import'] = array( + 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=categories', + 'desc' => $this->l('Import') + ); + } + } + // be able to edit the Home category + if (count(Category::getCategoriesWithoutParent()) == 1 && !Tools::isSubmit('id_category') + && ($this->display == 'view' || empty($this->display))) { + $this->toolbar_btn['edit'] = array( + 'href' => self::$currentIndex.'&update'.$this->table.'&id_category='.(int)$this->_category->id.'&token='.$this->token, + 'desc' => $this->l('Edit') + ); + } + if (Tools::getValue('id_category') && !Tools::isSubmit('updatecategory')) { + $this->toolbar_btn['edit'] = array( + 'href' => self::$currentIndex.'&update'.$this->table.'&id_category='.(int)Tools::getValue('id_category').'&token='.$this->token, + 'desc' => $this->l('Edit') + ); + } - if ($this->display == 'view') - $this->toolbar_btn['new'] = array( - 'href' => self::$currentIndex.'&add'.$this->table.'&id_parent='.(int)Tools::getValue('id_category').'&token='.$this->token, - 'desc' => $this->l('Add New') - ); - parent::initToolbar(); - if ($this->_category->id == (int)Configuration::get('PS_ROOT_CATEGORY') && isset($this->toolbar_btn['new'])) - unset($this->toolbar_btn['new']); - // after adding a category - if (empty($this->display)) - { - $id_category = (Tools::isSubmit('id_category')) ? '&id_parent='.(int)Tools::getValue('id_category') : ''; - $this->toolbar_btn['new'] = array( - 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token.$id_category, - 'desc' => $this->l('Add New') - ); + if ($this->display == 'view') { + $this->toolbar_btn['new'] = array( + 'href' => self::$currentIndex.'&add'.$this->table.'&id_parent='.(int)Tools::getValue('id_category').'&token='.$this->token, + 'desc' => $this->l('Add New') + ); + } + parent::initToolbar(); + if ($this->_category->id == (int)Configuration::get('PS_ROOT_CATEGORY') && isset($this->toolbar_btn['new'])) { + unset($this->toolbar_btn['new']); + } + // after adding a category + if (empty($this->display)) { + $id_category = (Tools::isSubmit('id_category')) ? '&id_parent='.(int)Tools::getValue('id_category') : ''; + $this->toolbar_btn['new'] = array( + 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token.$id_category, + 'desc' => $this->l('Add New') + ); - if (Tools::isSubmit('id_category')) - { - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; - $this->toolbar_btn['back'] = array( - 'href' => $back, - 'desc' => $this->l('Back to list') - ); - } - } - } + if (Tools::isSubmit('id_category')) { + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } + $this->toolbar_btn['back'] = array( + 'href' => $back, + 'desc' => $this->l('Back to list') + ); + } + } + } - public function initProcess() - { - if (Tools::isSubmit('add'.$this->table.'root')) - { - if ($this->tabAccess['add']) - { - $this->action = 'add'.$this->table.'root'; - $obj = $this->loadObject(true); - if (Validate::isLoadedObject($obj)) - $this->display = 'edit'; - else - $this->display = 'add'; - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } + public function initProcess() + { + if (Tools::isSubmit('add'.$this->table.'root')) { + if ($this->tabAccess['add']) { + $this->action = 'add'.$this->table.'root'; + $obj = $this->loadObject(true); + if (Validate::isLoadedObject($obj)) { + $this->display = 'edit'; + } else { + $this->display = 'add'; + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } - parent::initProcess(); + parent::initProcess(); - if ($this->action == 'delete' || $this->action == 'bulkdelete') - if (Tools::getIsset('cancel')) - Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getAdminTokenLite('AdminCategories')); - elseif (Tools::getValue('deleteMode') == 'link' || Tools::getValue('deleteMode') == 'linkanddisable' || Tools::getValue('deleteMode') == 'delete') - $this->delete_mode = Tools::getValue('deleteMode'); - else - $this->action = 'select_delete'; - } + if ($this->action == 'delete' || $this->action == 'bulkdelete') { + if (Tools::getIsset('cancel')) { + Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getAdminTokenLite('AdminCategories')); + } elseif (Tools::getValue('deleteMode') == 'link' || Tools::getValue('deleteMode') == 'linkanddisable' || Tools::getValue('deleteMode') == 'delete') { + $this->delete_mode = Tools::getValue('deleteMode'); + } else { + $this->action = 'select_delete'; + } + } + } - public function renderKpis() - { - $time = time(); - $kpis = array(); + public function renderKpis() + { + $time = time(); + $kpis = array(); - /* The data generation is located in AdminStatsControllerCore */ + /* The data generation is located in AdminStatsControllerCore */ - $helper = new HelperKpi(); - $helper->id = 'box-disabled-categories'; - $helper->icon = 'icon-off'; - $helper->color = 'color1'; - $helper->title = $this->l('Disabled Categories', null, null, false); - if (ConfigurationKPI::get('DISABLED_CATEGORIES') !== false) - $helper->value = ConfigurationKPI::get('DISABLED_CATEGORIES'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=disabled_categories'; - $helper->refresh = (bool)(ConfigurationKPI::get('DISABLED_CATEGORIES_EXPIRE') < $time); - $kpis[] = $helper->generate(); + $helper = new HelperKpi(); + $helper->id = 'box-disabled-categories'; + $helper->icon = 'icon-off'; + $helper->color = 'color1'; + $helper->title = $this->l('Disabled Categories', null, null, false); + if (ConfigurationKPI::get('DISABLED_CATEGORIES') !== false) { + $helper->value = ConfigurationKPI::get('DISABLED_CATEGORIES'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=disabled_categories'; + $helper->refresh = (bool)(ConfigurationKPI::get('DISABLED_CATEGORIES_EXPIRE') < $time); + $kpis[] = $helper->generate(); - $helper = new HelperKpi(); - $helper->id = 'box-empty-categories'; - $helper->icon = 'icon-bookmark-empty'; - $helper->color = 'color2'; - $helper->href = $this->context->link->getAdminLink('AdminTracking'); - $helper->title = $this->l('Empty Categories', null, null, false); - if (ConfigurationKPI::get('EMPTY_CATEGORIES') !== false) - $helper->value = ConfigurationKPI::get('EMPTY_CATEGORIES'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=empty_categories'; - $helper->refresh = (bool)(ConfigurationKPI::get('EMPTY_CATEGORIES_EXPIRE') < $time); - $kpis[] = $helper->generate(); + $helper = new HelperKpi(); + $helper->id = 'box-empty-categories'; + $helper->icon = 'icon-bookmark-empty'; + $helper->color = 'color2'; + $helper->href = $this->context->link->getAdminLink('AdminTracking'); + $helper->title = $this->l('Empty Categories', null, null, false); + if (ConfigurationKPI::get('EMPTY_CATEGORIES') !== false) { + $helper->value = ConfigurationKPI::get('EMPTY_CATEGORIES'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=empty_categories'; + $helper->refresh = (bool)(ConfigurationKPI::get('EMPTY_CATEGORIES_EXPIRE') < $time); + $kpis[] = $helper->generate(); - $helper = new HelperKpi(); - $helper->id = 'box-top-category'; - $helper->icon = 'icon-money'; - $helper->color = 'color3'; - $helper->title = $this->l('Top Category', null, null, false); - $helper->subtitle = $this->l('30 days', null, null, false); - if (ConfigurationKPI::get('TOP_CATEGORY', $this->context->employee->id_lang) !== false) - $helper->value = ConfigurationKPI::get('TOP_CATEGORY', $this->context->employee->id_lang); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=top_category'; - $helper->refresh = (bool)(ConfigurationKPI::get('TOP_CATEGORY_EXPIRE', $this->context->employee->id_lang) < $time); - $kpis[] = $helper->generate(); + $helper = new HelperKpi(); + $helper->id = 'box-top-category'; + $helper->icon = 'icon-money'; + $helper->color = 'color3'; + $helper->title = $this->l('Top Category', null, null, false); + $helper->subtitle = $this->l('30 days', null, null, false); + if (ConfigurationKPI::get('TOP_CATEGORY', $this->context->employee->id_lang) !== false) { + $helper->value = ConfigurationKPI::get('TOP_CATEGORY', $this->context->employee->id_lang); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=top_category'; + $helper->refresh = (bool)(ConfigurationKPI::get('TOP_CATEGORY_EXPIRE', $this->context->employee->id_lang) < $time); + $kpis[] = $helper->generate(); - $helper = new HelperKpi(); - $helper->id = 'box-products-per-category'; - $helper->icon = 'icon-search'; - $helper->color = 'color4'; - $helper->title = $this->l('Average number of products per category', null, null, false); - if (ConfigurationKPI::get('PRODUCTS_PER_CATEGORY') !== false) - $helper->value = ConfigurationKPI::get('PRODUCTS_PER_CATEGORY'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=products_per_category'; - $helper->refresh = (bool)(ConfigurationKPI::get('PRODUCTS_PER_CATEGORY_EXPIRE') < $time); - $kpis[] = $helper->generate(); + $helper = new HelperKpi(); + $helper->id = 'box-products-per-category'; + $helper->icon = 'icon-search'; + $helper->color = 'color4'; + $helper->title = $this->l('Average number of products per category', null, null, false); + if (ConfigurationKPI::get('PRODUCTS_PER_CATEGORY') !== false) { + $helper->value = ConfigurationKPI::get('PRODUCTS_PER_CATEGORY'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=products_per_category'; + $helper->refresh = (bool)(ConfigurationKPI::get('PRODUCTS_PER_CATEGORY_EXPIRE') < $time); + $kpis[] = $helper->generate(); - $helper = new HelperKpiRow(); - $helper->kpis = $kpis; - return $helper->generate(); - } + $helper = new HelperKpiRow(); + $helper->kpis = $kpis; + return $helper->generate(); + } - public function renderForm() - { - $this->initToolbar(); + public function renderForm() + { + $this->initToolbar(); - /** @var Category $obj */ - $obj = $this->loadObject(true); + /** @var Category $obj */ + $obj = $this->loadObject(true); $context = Context::getContext(); - $id_shop = $context->shop->id; - $selected_categories = array((isset($obj->id_parent) && $obj->isParentCategoryAvailable($id_shop))? (int)$obj->id_parent : (int)Tools::getValue('id_parent', Category::getRootCategory()->id)); - $unidentified = new Group(Configuration::get('PS_UNIDENTIFIED_GROUP')); - $guest = new Group(Configuration::get('PS_GUEST_GROUP')); - $default = new Group(Configuration::get('PS_CUSTOMER_GROUP')); + $id_shop = $context->shop->id; + $selected_categories = array((isset($obj->id_parent) && $obj->isParentCategoryAvailable($id_shop))? (int)$obj->id_parent : (int)Tools::getValue('id_parent', Category::getRootCategory()->id)); + $unidentified = new Group(Configuration::get('PS_UNIDENTIFIED_GROUP')); + $guest = new Group(Configuration::get('PS_GUEST_GROUP')); + $default = new Group(Configuration::get('PS_CUSTOMER_GROUP')); - $unidentified_group_information = sprintf($this->l('%s - All people without a valid customer account.'), '<b>'.$unidentified->name[$this->context->language->id].'</b>'); - $guest_group_information = sprintf($this->l('%s - Customer who placed an order with the guest checkout.'), '<b>'.$guest->name[$this->context->language->id].'</b>'); - $default_group_information = sprintf($this->l('%s - All people who have created an account on this site.'), '<b>'.$default->name[$this->context->language->id].'</b>'); + $unidentified_group_information = sprintf($this->l('%s - All people without a valid customer account.'), '<b>'.$unidentified->name[$this->context->language->id].'</b>'); + $guest_group_information = sprintf($this->l('%s - Customer who placed an order with the guest checkout.'), '<b>'.$guest->name[$this->context->language->id].'</b>'); + $default_group_information = sprintf($this->l('%s - All people who have created an account on this site.'), '<b>'.$default->name[$this->context->language->id].'</b>'); - if (!($obj = $this->loadObject(true))) - return; + if (!($obj = $this->loadObject(true))) { + return; + } - $image = _PS_CAT_IMG_DIR_.$obj->id.'.jpg'; - $image_url = ImageManager::thumbnail($image, $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, - $this->imageType, true, true); - $image_size = file_exists($image) ? filesize($image) / 1000 : false; + $image = _PS_CAT_IMG_DIR_.$obj->id.'.jpg'; + $image_url = ImageManager::thumbnail($image, $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, + $this->imageType, true, true); + $image_size = file_exists($image) ? filesize($image) / 1000 : false; - $this->fields_form = array( - 'tinymce' => true, - 'legend' => array( - 'title' => $this->l('Category'), - 'icon' => 'icon-tags' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'lang' => true, - 'required' => true, - 'class' => 'copy2friendlyUrl', - 'hint' => $this->l('Invalid characters:').' <>;=#{}', - ), - array( - 'type' => 'switch', - 'label' => $this->l('Displayed'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ) - ), - array( - 'type' => 'categories', - 'label' => $this->l('Parent category'), - 'name' => 'id_parent', - 'tree' => array( - 'id' => 'categories-tree', - 'selected_categories' => $selected_categories, - 'disabled_categories' => (!Tools::isSubmit('add'.$this->table) && !Tools::isSubmit('submitAdd'.$this->table)) ? array($this->_category->id) : null, + $this->fields_form = array( + 'tinymce' => true, + 'legend' => array( + 'title' => $this->l('Category'), + 'icon' => 'icon-tags' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'lang' => true, + 'required' => true, + 'class' => 'copy2friendlyUrl', + 'hint' => $this->l('Invalid characters:').' <>;=#{}', + ), + array( + 'type' => 'switch', + 'label' => $this->l('Displayed'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ) + ), + array( + 'type' => 'categories', + 'label' => $this->l('Parent category'), + 'name' => 'id_parent', + 'tree' => array( + 'id' => 'categories-tree', + 'selected_categories' => $selected_categories, + 'disabled_categories' => (!Tools::isSubmit('add'.$this->table) && !Tools::isSubmit('submitAdd'.$this->table)) ? array($this->_category->id) : null, 'root_category' => $context->shop->getCategory() - ) - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Description'), - 'name' => 'description', - 'autoload_rte' => true, - 'lang' => true, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'file', - 'label' => $this->l('Image'), - 'name' => 'image', - 'display_image' => true, - 'image' => $image_url ? $image_url : false, - 'size' => $image_size, - 'delete_url' => self::$currentIndex.'&'.$this->identifier.'='.$this->_category->id.'&token='.$this->token.'&deleteImage=1', - 'hint' => $this->l('Upload a category logo from your computer.'), - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Meta title'), - 'name' => 'meta_title', - 'lang' => true, - 'rows' => 5, - 'cols' => 100, - 'hint' => $this->l('Forbidden characters:').' <>;=#{}' - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Meta description'), - 'name' => 'meta_description', - 'lang' => true, - 'rows' => 5, - 'cols' => 100, - 'hint' => $this->l('Forbidden characters:').' <>;=#{}' - ), - array( - 'type' => 'tags', - 'label' => $this->l('Meta keywords'), - 'name' => 'meta_keywords', - 'lang' => true, - 'hint' => $this->l('To add "tags," click in the field, write something, and then press "Enter."').' '.$this->l('Forbidden characters:').' <>;=#{}' - ), - array( - 'type' => 'text', - 'label' => $this->l('Friendly URL'), - 'name' => 'link_rewrite', - 'lang' => true, - 'required' => true, - 'hint' => $this->l('Only letters, numbers, underscore (_) and the minus (-) character are allowed.') - ), - array( - 'type' => 'group', - 'label' => $this->l('Group access'), - 'name' => 'groupBox', - 'values' => Group::getGroups(Context::getContext()->language->id), - 'info_introduction' => $this->l('You now have three default customer groups.'), - 'unidentified' => $unidentified_group_information, - 'guest' => $guest_group_information, - 'customer' => $default_group_information, - 'hint' => $this->l('Mark all of the customer groups which you would like to have access to this category.') - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - 'name' => 'submitAdd'.$this->table.($this->_category->is_root_category && !Tools::isSubmit('add'.$this->table) && !Tools::isSubmit('add'.$this->table.'root') ? '': 'AndBackToParent') - ) - ); + ) + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Description'), + 'name' => 'description', + 'autoload_rte' => true, + 'lang' => true, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'file', + 'label' => $this->l('Image'), + 'name' => 'image', + 'display_image' => true, + 'image' => $image_url ? $image_url : false, + 'size' => $image_size, + 'delete_url' => self::$currentIndex.'&'.$this->identifier.'='.$this->_category->id.'&token='.$this->token.'&deleteImage=1', + 'hint' => $this->l('Upload a category logo from your computer.'), + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Meta title'), + 'name' => 'meta_title', + 'lang' => true, + 'rows' => 5, + 'cols' => 100, + 'hint' => $this->l('Forbidden characters:').' <>;=#{}' + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Meta description'), + 'name' => 'meta_description', + 'lang' => true, + 'rows' => 5, + 'cols' => 100, + 'hint' => $this->l('Forbidden characters:').' <>;=#{}' + ), + array( + 'type' => 'tags', + 'label' => $this->l('Meta keywords'), + 'name' => 'meta_keywords', + 'lang' => true, + 'hint' => $this->l('To add "tags," click in the field, write something, and then press "Enter."').' '.$this->l('Forbidden characters:').' <>;=#{}' + ), + array( + 'type' => 'text', + 'label' => $this->l('Friendly URL'), + 'name' => 'link_rewrite', + 'lang' => true, + 'required' => true, + 'hint' => $this->l('Only letters, numbers, underscore (_) and the minus (-) character are allowed.') + ), + array( + 'type' => 'group', + 'label' => $this->l('Group access'), + 'name' => 'groupBox', + 'values' => Group::getGroups(Context::getContext()->language->id), + 'info_introduction' => $this->l('You now have three default customer groups.'), + 'unidentified' => $unidentified_group_information, + 'guest' => $guest_group_information, + 'customer' => $default_group_information, + 'hint' => $this->l('Mark all of the customer groups which you would like to have access to this category.') + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + 'name' => 'submitAdd'.$this->table.($this->_category->is_root_category && !Tools::isSubmit('add'.$this->table) && !Tools::isSubmit('add'.$this->table.'root') ? '': 'AndBackToParent') + ) + ); - $this->tpl_form_vars['shared_category'] = Validate::isLoadedObject($obj) && $obj->hasMultishopEntries(); - $this->tpl_form_vars['PS_ALLOW_ACCENTED_CHARS_URL'] = (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL'); - $this->tpl_form_vars['displayBackOfficeCategory'] = Hook::exec('displayBackOfficeCategory'); + $this->tpl_form_vars['shared_category'] = Validate::isLoadedObject($obj) && $obj->hasMultishopEntries(); + $this->tpl_form_vars['PS_ALLOW_ACCENTED_CHARS_URL'] = (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL'); + $this->tpl_form_vars['displayBackOfficeCategory'] = Hook::exec('displayBackOfficeCategory'); - // Display this field only if multistore option is enabled - if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && Tools::isSubmit('add'.$this->table.'root')) - { - $this->fields_form['input'][] = array( - 'type' => 'switch', - 'label' => $this->l('Root Category'), - 'name' => 'is_root_category', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'is_root_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'is_root_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ) - ); - unset($this->fields_form['input'][2],$this->fields_form['input'][3]); - } - // Display this field only if multistore option is enabled AND there are several stores configured - if (Shop::isFeatureActive()) - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); + // Display this field only if multistore option is enabled + if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && Tools::isSubmit('add'.$this->table.'root')) { + $this->fields_form['input'][] = array( + 'type' => 'switch', + 'label' => $this->l('Root Category'), + 'name' => 'is_root_category', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'is_root_on', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'is_root_off', + 'value' => 0, + 'label' => $this->l('No') + ) + ) + ); + unset($this->fields_form['input'][2], $this->fields_form['input'][3]); + } + // Display this field only if multistore option is enabled AND there are several stores configured + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - // remove category tree and radio button "is_root_category" if this category has the root category as parent category to avoid any conflict - if ($this->_category->id_parent == (int)Configuration::get('PS_ROOT_CATEGORY') && Tools::isSubmit('updatecategory')) - foreach ($this->fields_form['input'] as $k => $input) - if (in_array($input['name'], array('id_parent', 'is_root_category'))) - unset($this->fields_form['input'][$k]); + // remove category tree and radio button "is_root_category" if this category has the root category as parent category to avoid any conflict + if ($this->_category->id_parent == (int)Configuration::get('PS_ROOT_CATEGORY') && Tools::isSubmit('updatecategory')) { + foreach ($this->fields_form['input'] as $k => $input) { + if (in_array($input['name'], array('id_parent', 'is_root_category'))) { + unset($this->fields_form['input'][$k]); + } + } + } - if (!($obj = $this->loadObject(true))) - return; + if (!($obj = $this->loadObject(true))) { + return; + } - $image = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.'/'.$obj->id.'.jpg', $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, $this->imageType, true); + $image = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.'/'.$obj->id.'.jpg', $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, $this->imageType, true); - $this->fields_value = array( - 'image' => $image ? $image : false, - 'size' => $image ? filesize(_PS_CAT_IMG_DIR_.'/'.$obj->id.'.jpg') / 1000 : false - ); + $this->fields_value = array( + 'image' => $image ? $image : false, + 'size' => $image ? filesize(_PS_CAT_IMG_DIR_.'/'.$obj->id.'.jpg') / 1000 : false + ); - // Added values of object Group - $category_groups_ids = $obj->getGroups(); + // Added values of object Group + $category_groups_ids = $obj->getGroups(); - $groups = Group::getGroups($this->context->language->id); - // if empty $carrier_groups_ids : object creation : we set the default groups - if (empty($category_groups_ids)) - { - $preselected = array(Configuration::get('PS_UNIDENTIFIED_GROUP'), Configuration::get('PS_GUEST_GROUP'), Configuration::get('PS_CUSTOMER_GROUP')); - $category_groups_ids = array_merge($category_groups_ids, $preselected); - } - foreach ($groups as $group) - $this->fields_value['groupBox_'.$group['id_group']] = Tools::getValue('groupBox_'.$group['id_group'], (in_array($group['id_group'], $category_groups_ids))); + $groups = Group::getGroups($this->context->language->id); + // if empty $carrier_groups_ids : object creation : we set the default groups + if (empty($category_groups_ids)) { + $preselected = array(Configuration::get('PS_UNIDENTIFIED_GROUP'), Configuration::get('PS_GUEST_GROUP'), Configuration::get('PS_CUSTOMER_GROUP')); + $category_groups_ids = array_merge($category_groups_ids, $preselected); + } + foreach ($groups as $group) { + $this->fields_value['groupBox_'.$group['id_group']] = Tools::getValue('groupBox_'.$group['id_group'], (in_array($group['id_group'], $category_groups_ids))); + } - $this->fields_value['is_root_category'] = (bool)Tools::isSubmit('add'.$this->table.'root'); + $this->fields_value['is_root_category'] = (bool)Tools::isSubmit('add'.$this->table.'root'); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function postProcess() - { - if (!in_array($this->display, array('edit', 'add'))) - $this->multishop_context_group = false; - if (Tools::isSubmit('forcedeleteImage') || (isset($_FILES['image']) && $_FILES['image']['size'] > 0) || Tools::getValue('deleteImage')) - { - $this->processForceDeleteImage(); - if (Tools::isSubmit('forcedeleteImage')) - Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getAdminTokenLite('AdminCategories').'&conf=7'); - } + public function postProcess() + { + if (!in_array($this->display, array('edit', 'add'))) { + $this->multishop_context_group = false; + } + if (Tools::isSubmit('forcedeleteImage') || (isset($_FILES['image']) && $_FILES['image']['size'] > 0) || Tools::getValue('deleteImage')) { + $this->processForceDeleteImage(); + if (Tools::isSubmit('forcedeleteImage')) { + Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getAdminTokenLite('AdminCategories').'&conf=7'); + } + } - return parent::postProcess(); - } + return parent::postProcess(); + } - public function processForceDeleteImage() - { - $category = $this->loadObject(true); - if (Validate::isLoadedObject($category)) - $category->deleteImage(true); - } + public function processForceDeleteImage() + { + $category = $this->loadObject(true); + if (Validate::isLoadedObject($category)) { + $category->deleteImage(true); + } + } - public function processAdd() - { - $id_category = (int)Tools::getValue('id_category'); - $id_parent = (int)Tools::getValue('id_parent'); + public function processAdd() + { + $id_category = (int)Tools::getValue('id_category'); + $id_parent = (int)Tools::getValue('id_parent'); - // if true, we are in a root category creation - if (!$id_parent) - { - $_POST['is_root_category'] = $_POST['level_depth'] = 1; - $_POST['id_parent'] = $id_parent = (int)Configuration::get('PS_ROOT_CATEGORY'); - } + // if true, we are in a root category creation + if (!$id_parent) { + $_POST['is_root_category'] = $_POST['level_depth'] = 1; + $_POST['id_parent'] = $id_parent = (int)Configuration::get('PS_ROOT_CATEGORY'); + } - if ($id_category) - { - if ($id_category != $id_parent) - { - if (!Category::checkBeforeMove($id_category, $id_parent)) - $this->errors[] = Tools::displayError('The category cannot be moved here.'); - } - else - $this->errors[] = Tools::displayError('The category cannot be a parent of itself.'); - } - $object = parent::processAdd(); + if ($id_category) { + if ($id_category != $id_parent) { + if (!Category::checkBeforeMove($id_category, $id_parent)) { + $this->errors[] = Tools::displayError('The category cannot be moved here.'); + } + } else { + $this->errors[] = Tools::displayError('The category cannot be a parent of itself.'); + } + } + $object = parent::processAdd(); - //if we create a you root category you have to associate to a shop before to add sub categories in. So we redirect to AdminCategories listing - if ($object && Tools::getValue('is_root_category')) - Tools::redirectAdmin(self::$currentIndex.'&id_category='.(int)Configuration::get('PS_ROOT_CATEGORY').'&token='.Tools::getAdminTokenLite('AdminCategories').'&conf=3'); - return $object; - } + //if we create a you root category you have to associate to a shop before to add sub categories in. So we redirect to AdminCategories listing + if ($object && Tools::getValue('is_root_category')) { + Tools::redirectAdmin(self::$currentIndex.'&id_category='.(int)Configuration::get('PS_ROOT_CATEGORY').'&token='.Tools::getAdminTokenLite('AdminCategories').'&conf=3'); + } + return $object; + } - protected function setDeleteMode() - { - if ($this->delete_mode == 'link' || $this->delete_mode == 'linkanddisable') - { - $this->remove_products = false; - if ($this->delete_mode == 'linkanddisable') - $this->disable_products = true; - } - elseif ($this->delete_mode != 'delete') - $this->errors[] = Tools::displayError('Unknown delete mode:'.' '.$this->deleted); + protected function setDeleteMode() + { + if ($this->delete_mode == 'link' || $this->delete_mode == 'linkanddisable') { + $this->remove_products = false; + if ($this->delete_mode == 'linkanddisable') { + $this->disable_products = true; + } + } elseif ($this->delete_mode != 'delete') { + $this->errors[] = Tools::displayError('Unknown delete mode:'.' '.$this->deleted); + } + } - } + protected function processBulkDelete() + { + if ($this->tabAccess['delete'] === '1') { + $cats_ids = array(); + foreach (Tools::getValue($this->table.'Box') as $id_category) { + $category = new Category((int)$id_category); + if (!$category->isRootCategoryForAShop()) { + $cats_ids[$category->id] = $category->id_parent; + } + } - protected function processBulkDelete() - { - if ($this->tabAccess['delete'] === '1') - { - $cats_ids = array(); - foreach (Tools::getValue($this->table.'Box') as $id_category) - { - $category = new Category((int)$id_category); - if (!$category->isRootCategoryForAShop()) - $cats_ids[$category->id] = $category->id_parent; - } + if (parent::processBulkDelete()) { + $this->setDeleteMode(); + foreach ($cats_ids as $id => $id_parent) { + $this->processFatherlessProducts((int)$id_parent); + } + return true; + } else { + return false; + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } - if (parent::processBulkDelete()) - { - $this->setDeleteMode(); - foreach ($cats_ids as $id => $id_parent) - $this->processFatherlessProducts((int)$id_parent); - return true; - } - else - return false; - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } + public function processDelete() + { + if ($this->tabAccess['delete'] === '1') { + /** @var Category $category */ + $category = $this->loadObject(); + if ($category->isRootCategoryForAShop()) { + $this->errors[] = Tools::displayError('You cannot remove this category because one of your shops uses it as a root category.'); + } elseif (parent::processDelete()) { + $this->setDeleteMode(); + $this->processFatherlessProducts((int)$category->id_parent); + return true; + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + return false; + } - public function processDelete() - { - if ($this->tabAccess['delete'] === '1') - { - /** @var Category $category */ - $category = $this->loadObject(); - if ($category->isRootCategoryForAShop()) - $this->errors[] = Tools::displayError('You cannot remove this category because one of your shops uses it as a root category.'); - elseif (parent::processDelete()) - { - $this->setDeleteMode(); - $this->processFatherlessProducts((int)$category->id_parent); - return true; - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - return false; - } - - public function processFatherlessProducts($id_parent) - { - /* Delete or link products which were not in others categories */ - $fatherless_products = Db::getInstance()->executeS(' + public function processFatherlessProducts($id_parent) + { + /* Delete or link products which were not in others categories */ + $fatherless_products = Db::getInstance()->executeS(' SELECT p.`id_product` FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' WHERE NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp WHERE cp.`id_product` = p.`id_product`)'); - foreach ($fatherless_products as $id_poor_product) - { - $poor_product = new Product((int)$id_poor_product['id_product']); - if (Validate::isLoadedObject($poor_product)) - { - if ($this->remove_products || $id_parent == 0) - $poor_product->delete(); - else - { - if ($this->disable_products) - $poor_product->active = 0; - $poor_product->id_category_default = (int)$id_parent; - $poor_product->addToCategories((int)$id_parent); - $poor_product->save(); - } - } - } - } + foreach ($fatherless_products as $id_poor_product) { + $poor_product = new Product((int)$id_poor_product['id_product']); + if (Validate::isLoadedObject($poor_product)) { + if ($this->remove_products || $id_parent == 0) { + $poor_product->delete(); + } else { + if ($this->disable_products) { + $poor_product->active = 0; + } + $poor_product->id_category_default = (int)$id_parent; + $poor_product->addToCategories((int)$id_parent); + $poor_product->save(); + } + } + } + } - public function processPosition() - { - if ($this->tabAccess['edit'] !== '1') - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - elseif (!Validate::isLoadedObject($object = new Category((int)Tools::getValue($this->identifier, Tools::getValue('id_category_to_move', 1))))) - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'. - $this->table.'</b> '.Tools::displayError('(cannot load object)'); - if (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) - $this->errors[] = Tools::displayError('Failed to update the position.'); - else - { - $object->regenerateEntireNtree(); - Tools::redirectAdmin(self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=5'.(($id_category = (int)Tools::getValue($this->identifier, Tools::getValue('id_category_parent', 1))) ? ('&'.$this->identifier.'='.$id_category) : '').'&token='.Tools::getAdminTokenLite('AdminCategories')); - } - } + public function processPosition() + { + if ($this->tabAccess['edit'] !== '1') { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } elseif (!Validate::isLoadedObject($object = new Category((int)Tools::getValue($this->identifier, Tools::getValue('id_category_to_move', 1))))) { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'. + $this->table.'</b> '.Tools::displayError('(cannot load object)'); + } + if (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) { + $this->errors[] = Tools::displayError('Failed to update the position.'); + } else { + $object->regenerateEntireNtree(); + Tools::redirectAdmin(self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=5'.(($id_category = (int)Tools::getValue($this->identifier, Tools::getValue('id_category_parent', 1))) ? ('&'.$this->identifier.'='.$id_category) : '').'&token='.Tools::getAdminTokenLite('AdminCategories')); + } + } - protected function postImage($id) - { - $ret = parent::postImage($id); - $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); + protected function postImage($id) + { + $ret = parent::postImage($id); + $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); - if (($id_category = (int)Tools::getValue('id_category')) && - isset($_FILES) && count($_FILES) && $_FILES['image']['name'] != null && - file_exists(_PS_CAT_IMG_DIR_.$id_category.'.jpg')) - { - $images_types = ImageType::getImagesTypes('categories'); - foreach ($images_types as $k => $image_type) - { - ImageManager::resize( - _PS_CAT_IMG_DIR_.$id_category.'.jpg', - _PS_CAT_IMG_DIR_.$id_category.'-'.stripslashes($image_type['name']).'.jpg', - (int)$image_type['width'], (int)$image_type['height'] - ); + if (($id_category = (int)Tools::getValue('id_category')) && + isset($_FILES) && count($_FILES) && $_FILES['image']['name'] != null && + file_exists(_PS_CAT_IMG_DIR_.$id_category.'.jpg')) { + $images_types = ImageType::getImagesTypes('categories'); + foreach ($images_types as $k => $image_type) { + ImageManager::resize( + _PS_CAT_IMG_DIR_.$id_category.'.jpg', + _PS_CAT_IMG_DIR_.$id_category.'-'.stripslashes($image_type['name']).'.jpg', + (int)$image_type['width'], (int)$image_type['height'] + ); - if ($generate_hight_dpi_images) - ImageManager::resize( - _PS_CAT_IMG_DIR_.$id_category.'.jpg', - _PS_CAT_IMG_DIR_.$id_category.'-'.stripslashes($image_type['name']).'2x.jpg', - (int)$image_type['width']*2, (int)$image_type['height']*2 - ); - } - } + if ($generate_hight_dpi_images) { + ImageManager::resize( + _PS_CAT_IMG_DIR_.$id_category.'.jpg', + _PS_CAT_IMG_DIR_.$id_category.'-'.stripslashes($image_type['name']).'2x.jpg', + (int)$image_type['width']*2, (int)$image_type['height']*2 + ); + } + } + } - return $ret; - } + return $ret; + } - public static function getDescriptionClean($description) - { - return Tools::getDescriptionClean($description); - } + public static function getDescriptionClean($description) + { + return Tools::getDescriptionClean($description); + } - public function ajaxProcessUpdatePositions() - { - $id_category_to_move = (int)Tools::getValue('id_category_to_move'); - $id_category_parent = (int)Tools::getValue('id_category_parent'); - $way = (int)Tools::getValue('way'); - $positions = Tools::getValue('category'); - $found_first = (bool)Tools::getValue('found_first'); - if (is_array($positions)) - foreach ($positions as $key => $value) - { - $pos = explode('_', $value); - if ((isset($pos[1]) && isset($pos[2])) && ($pos[1] == $id_category_parent && $pos[2] == $id_category_to_move)) - { - $position = $key + 1; - break; - } - } + public function ajaxProcessUpdatePositions() + { + $id_category_to_move = (int)Tools::getValue('id_category_to_move'); + $id_category_parent = (int)Tools::getValue('id_category_parent'); + $way = (int)Tools::getValue('way'); + $positions = Tools::getValue('category'); + $found_first = (bool)Tools::getValue('found_first'); + if (is_array($positions)) { + foreach ($positions as $key => $value) { + $pos = explode('_', $value); + if ((isset($pos[1]) && isset($pos[2])) && ($pos[1] == $id_category_parent && $pos[2] == $id_category_to_move)) { + $position = $key; + break; + } + } + } - $category = new Category($id_category_to_move); - if (Validate::isLoadedObject($category)) - { - if (isset($position) && $category->updatePosition($way, $position)) - { - Hook::exec('actionCategoryUpdate'); + $category = new Category($id_category_to_move); + if (Validate::isLoadedObject($category)) { + if (isset($position) && $category->updatePosition($way, $position)) { + Hook::exec('actionCategoryUpdate'); - /* Position '0' was not found in given positions so try to reorder parent category*/ - if (!$found_first) - $category->cleanPositions((int)$category->id_parent); + /* Position '0' was not found in given positions so try to reorder parent category*/ + if (!$found_first) { + $category->cleanPositions((int)$category->id_parent); + } - die(true); - } - else - die('{"hasError" : true, errors : "Cannot update categories position"}'); - } - else - die('{"hasError" : true, "errors" : "This category cannot be loaded"}'); - } + die(true); + } else { + die('{"hasError" : true, errors : "Cannot update categories position"}'); + } + } else { + die('{"hasError" : true, "errors" : "This category cannot be loaded"}'); + } + } - public function ajaxProcessStatusCategory() - { - if (!$id_category = (int)Tools::getValue('id_category')) - die(Tools::jsonEncode(array('success' => false, 'error' => true, 'text' => $this->l('Failed to update the status')))); - else - { - $category = new Category((int)$id_category); - if (Validate::isLoadedObject($category)) - { - $category->active = $category->active == 1 ? 0 : 1; - $category->save() ? - die(Tools::jsonEncode(array('success' => true, 'text' => $this->l('The status has been updated successfully')))) : - die(Tools::jsonEncode(array('success' => false, 'error' => true, 'text' => $this->l('Failed to update the status')))); - } - } - } + public function ajaxProcessStatusCategory() + { + if (!$id_category = (int)Tools::getValue('id_category')) { + die(Tools::jsonEncode(array('success' => false, 'error' => true, 'text' => $this->l('Failed to update the status')))); + } else { + $category = new Category((int)$id_category); + if (Validate::isLoadedObject($category)) { + $category->active = $category->active == 1 ? 0 : 1; + $category->save() ? + die(Tools::jsonEncode(array('success' => true, 'text' => $this->l('The status has been updated successfully')))) : + die(Tools::jsonEncode(array('success' => false, 'error' => true, 'text' => $this->l('Failed to update the status')))); + } + } + } } diff --git a/controllers/admin/AdminCmsCategoriesController.php b/controllers/admin/AdminCmsCategoriesController.php index a90c57f3..9678f5a5 100644 --- a/controllers/admin/AdminCmsCategoriesController.php +++ b/controllers/admin/AdminCmsCategoriesController.php @@ -29,295 +29,277 @@ */ class AdminCmsCategoriesControllerCore extends AdminController { - /** @var object CMSCategory() instance for navigation*/ - protected $cms_category; + /** @var object CMSCategory() instance for navigation*/ + protected $cms_category; - protected $position_identifier = 'id_cms_category_to_move'; + protected $position_identifier = 'id_cms_category_to_move'; - public function __construct() - { - $this->bootstrap = true; - $this->is_cms = true; - $this->table = 'cms_category'; - $this->list_id = 'cms_category'; - $this->className = 'CMSCategory'; - $this->lang = true; - $this->addRowAction('view'); - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->_orderBy = 'position'; + public function __construct() + { + $this->bootstrap = true; + $this->is_cms = true; + $this->table = 'cms_category'; + $this->list_id = 'cms_category'; + $this->className = 'CMSCategory'; + $this->lang = true; + $this->addRowAction('view'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->_orderBy = 'position'; - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); - $this->tpl_list_vars['icon'] = 'icon-folder-close'; - $this->tpl_list_vars['title'] = $this->l('Categories'); - $this->fields_list = array( - 'id_cms_category' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'name' => array('title' => $this->l('Name'), 'width' => 'auto', 'callback' => 'hideCMSCategoryPosition', 'callback_object' => 'CMSCategory'), - 'description' => array('title' => $this->l('Description'), 'maxlength' => 90, 'orderby' => false), - 'position' => array('title' => $this->l('Position'),'filter_key' => 'position', 'align' => 'center', 'class' => 'fixed-width-sm', 'position' => 'position'), - 'active' => array( - 'title' => $this->l('Displayed'), 'class' => 'fixed-width-sm', 'active' => 'status', - 'align' => 'center','type' => 'bool', 'orderby' => false - )); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); + $this->tpl_list_vars['icon'] = 'icon-folder-close'; + $this->tpl_list_vars['title'] = $this->l('Categories'); + $this->fields_list = array( + 'id_cms_category' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'name' => array('title' => $this->l('Name'), 'width' => 'auto', 'callback' => 'hideCMSCategoryPosition', 'callback_object' => 'CMSCategory'), + 'description' => array('title' => $this->l('Description'), 'maxlength' => 90, 'orderby' => false), + 'position' => array('title' => $this->l('Position'),'filter_key' => 'position', 'align' => 'center', 'class' => 'fixed-width-sm', 'position' => 'position'), + 'active' => array( + 'title' => $this->l('Displayed'), 'class' => 'fixed-width-sm', 'active' => 'status', + 'align' => 'center','type' => 'bool', 'orderby' => false + )); - // The controller can't be call directly - // In this case, AdminCmsContentController::getCurrentCMSCategory() is null - if (!AdminCmsContentController::getCurrentCMSCategory()) - { - $this->redirect_after = '?controller=AdminCmsContent&token='.Tools::getAdminTokenLite('AdminCmsContent'); - $this->redirect(); - } + // The controller can't be call directly + // In this case, AdminCmsContentController::getCurrentCMSCategory() is null + if (!AdminCmsContentController::getCurrentCMSCategory()) { + $this->redirect_after = '?controller=AdminCmsContent&token='.Tools::getAdminTokenLite('AdminCmsContent'); + $this->redirect(); + } - $this->cms_category = AdminCmsContentController::getCurrentCMSCategory(); - $this->_where = ' AND `id_parent` = '.(int)$this->cms_category->id; - $this->_select = 'position '; + $this->cms_category = AdminCmsContentController::getCurrentCMSCategory(); + $this->_where = ' AND `id_parent` = '.(int)$this->cms_category->id; + $this->_select = 'position '; - parent::__construct(); - } + parent::__construct(); + } - public function renderList() - { - $this->initToolbar(); - $this->_group = 'GROUP BY a.`id_cms_category`'; - if (isset($this->toolbar_btn['new'])) - $this->toolbar_btn['new']['href'] .= '&id_parent='.(int)Tools::getValue('id_cms_category'); - return parent::renderList(); - } + public function renderList() + { + $this->initToolbar(); + $this->_group = 'GROUP BY a.`id_cms_category`'; + if (isset($this->toolbar_btn['new'])) { + $this->toolbar_btn['new']['href'] .= '&id_parent='.(int)Tools::getValue('id_cms_category'); + } + return parent::renderList(); + } - public function postProcess() - { - $this->tabAccess = Profile::getProfileAccess($this->context->employee->id_profile, $this->id); - if (Tools::isSubmit('submitAdd'.$this->table)) - { - $this->action = 'save'; - if ($id_cms_category = (int)Tools::getValue('id_cms_category')) - { - $this->id_object = $id_cms_category; - if (!CMSCategory::checkBeforeMove($id_cms_category, (int)Tools::getValue('id_parent'))) - { - $this->errors[] = Tools::displayError('The CMS Category cannot be moved here.'); - return false; - } - } + public function postProcess() + { + $this->tabAccess = Profile::getProfileAccess($this->context->employee->id_profile, $this->id); + if (Tools::isSubmit('submitAdd'.$this->table)) { + $this->action = 'save'; + if ($id_cms_category = (int)Tools::getValue('id_cms_category')) { + $this->id_object = $id_cms_category; + if (!CMSCategory::checkBeforeMove($id_cms_category, (int)Tools::getValue('id_parent'))) { + $this->errors[] = Tools::displayError('The CMS Category cannot be moved here.'); + return false; + } + } $object = parent::postProcess(); $this->updateAssoShop((int)Tools::getValue('id_cms_category')); - if ($object !== false) + if ($object !== false) { Tools::redirectAdmin(self::$currentIndex.'&conf=3&id_cms_category='.(int)$object->id.'&token='.Tools::getValue('token')); + } return $object; - } - /* Change object statuts (active, inactive) */ - elseif (Tools::isSubmit('statuscms_category') && Tools::getValue($this->identifier)) - { - if ($this->tabAccess['edit'] === '1') - { - if (Validate::isLoadedObject($object = $this->loadObject())) - { - if ($object->toggleStatus()) - { - $identifier = ((int)$object->id_parent ? '&id_cms_category='.(int)$object->id_parent : ''); - Tools::redirectAdmin(self::$currentIndex.'&conf=5'.$identifier.'&token='.Tools::getValue('token')); - } - else - $this->errors[] = Tools::displayError('An error occurred while updating the status.'); - } - else - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.') - .' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - /* Delete object */ - elseif (Tools::isSubmit('delete'.$this->table)) - { - if ($this->tabAccess['delete'] === '1') - { - if (Validate::isLoadedObject($object = $this->loadObject()) && isset($this->fieldImageSettings)) - { - // check if request at least one object with noZeroObject - if (isset($object->noZeroObject) && count($taxes = call_user_func(array($this->className, $object->noZeroObject))) <= 1) - $this->errors[] = Tools::displayError('You need at least one object.') - .' <b>'.$this->table.'</b><br />'.Tools::displayError('You cannot delete all of the items.'); - else - { + } + /* Change object statuts (active, inactive) */ + elseif (Tools::isSubmit('statuscms_category') && Tools::getValue($this->identifier)) { + if ($this->tabAccess['edit'] === '1') { + if (Validate::isLoadedObject($object = $this->loadObject())) { + if ($object->toggleStatus()) { + $identifier = ((int)$object->id_parent ? '&id_cms_category='.(int)$object->id_parent : ''); + Tools::redirectAdmin(self::$currentIndex.'&conf=5'.$identifier.'&token='.Tools::getValue('token')); + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the status.'); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.') + .' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + /* Delete object */ + elseif (Tools::isSubmit('delete'.$this->table)) { + if ($this->tabAccess['delete'] === '1') { + if (Validate::isLoadedObject($object = $this->loadObject()) && isset($this->fieldImageSettings)) { + // check if request at least one object with noZeroObject + if (isset($object->noZeroObject) && count($taxes = call_user_func(array($this->className, $object->noZeroObject))) <= 1) { + $this->errors[] = Tools::displayError('You need at least one object.') + .' <b>'.$this->table.'</b><br />'.Tools::displayError('You cannot delete all of the items.'); + } else { $identifier = ((int)$object->id_parent ? '&'.$this->identifier.'='.(int)$object->id_parent : ''); - if ($this->deleted) - { - $object->deleted = 1; - if ($object->update()) - Tools::redirectAdmin(self::$currentIndex.'&conf=1&token='.Tools::getValue('token').$identifier); - } - elseif ($object->delete()) - Tools::redirectAdmin(self::$currentIndex.'&conf=1&token='.Tools::getValue('token').$identifier); - $this->errors[] = Tools::displayError('An error occurred during deletion.'); - } - } - else - $this->errors[] = Tools::displayError('An error occurred while deleting the object.') - .' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - elseif (Tools::isSubmit('position')) - { - $object = new CMSCategory((int)Tools::getValue($this->identifier, Tools::getValue('id_cms_category_to_move', 1))); - if ($this->tabAccess['edit'] !== '1') - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - elseif (!Validate::isLoadedObject($object)) - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.') - .' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - elseif (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) - $this->errors[] = Tools::displayError('Failed to update the position.'); - else - { - $identifier = ((int)$object->id_parent ? '&'.$this->identifier.'='.(int)$object->id_parent : ''); - $token = Tools::getAdminTokenLite('AdminCmsContent'); - Tools::redirectAdmin( - self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=5'.$identifier.'&token='.$token - ); - } - } - /* Delete multiple objects */ - elseif (Tools::getValue('submitDel'.$this->table) || Tools::getValue('submitBulkdelete'.$this->table)) - { - if ($this->tabAccess['delete'] === '1') - { - if (Tools::isSubmit($this->table.'Box')) - { - $cms_category = new CMSCategory(); - $result = true; - $result = $cms_category->deleteSelection(Tools::getValue($this->table.'Box')); - if ($result) - { - $cms_category->cleanPositions((int)Tools::getValue('id_cms_category')); - $token = Tools::getAdminTokenLite('AdminCmsContent'); - Tools::redirectAdmin(self::$currentIndex.'&conf=2&token='.$token.'&id_cms_category='.(int)Tools::getValue('id_cms_category')); - } - $this->errors[] = Tools::displayError('An error occurred while deleting this selection.'); + if ($this->deleted) { + $object->deleted = 1; + if ($object->update()) { + Tools::redirectAdmin(self::$currentIndex.'&conf=1&token='.Tools::getValue('token').$identifier); + } + } elseif ($object->delete()) { + Tools::redirectAdmin(self::$currentIndex.'&conf=1&token='.Tools::getValue('token').$identifier); + } + $this->errors[] = Tools::displayError('An error occurred during deletion.'); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while deleting the object.') + .' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } elseif (Tools::isSubmit('position')) { + $object = new CMSCategory((int)Tools::getValue($this->identifier, Tools::getValue('id_cms_category_to_move', 1))); + if ($this->tabAccess['edit'] !== '1') { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } elseif (!Validate::isLoadedObject($object)) { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.') + .' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } elseif (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) { + $this->errors[] = Tools::displayError('Failed to update the position.'); + } else { + $identifier = ((int)$object->id_parent ? '&'.$this->identifier.'='.(int)$object->id_parent : ''); + $token = Tools::getAdminTokenLite('AdminCmsContent'); + Tools::redirectAdmin( + self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=5'.$identifier.'&token='.$token + ); + } + } + /* Delete multiple objects */ + elseif (Tools::getValue('submitDel'.$this->table) || Tools::getValue('submitBulkdelete'.$this->table)) { + if ($this->tabAccess['delete'] === '1') { + if (Tools::isSubmit($this->table.'Box')) { + $cms_category = new CMSCategory(); + $result = true; + $result = $cms_category->deleteSelection(Tools::getValue($this->table.'Box')); + if ($result) { + $cms_category->cleanPositions((int)Tools::getValue('id_cms_category')); + $token = Tools::getAdminTokenLite('AdminCmsContent'); + Tools::redirectAdmin(self::$currentIndex.'&conf=2&token='.$token.'&id_cms_category='.(int)Tools::getValue('id_cms_category')); + } + $this->errors[] = Tools::displayError('An error occurred while deleting this selection.'); + } else { + $this->errors[] = Tools::displayError('You must select at least one element to delete.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } + parent::postProcess(); + } - } - else - $this->errors[] = Tools::displayError('You must select at least one element to delete.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - parent::postProcess(); - } + public function renderForm() + { + $this->display = 'edit'; + $this->initToolbar(); + if (!$this->loadObject(true)) { + return; + } - public function renderForm() - { - $this->display = 'edit'; - $this->initToolbar(); - if (!$this->loadObject(true)) - return; + $categories = CMSCategory::getCategories($this->context->language->id, false); + $html_categories = CMSCategory::recurseCMSCategory($categories, $categories[0][1], 1, $this->getFieldValue($this->object, 'id_parent'), 1); - $categories = CMSCategory::getCategories($this->context->language->id, false); - $html_categories = CMSCategory::recurseCMSCategory($categories, $categories[0][1], 1, $this->getFieldValue($this->object, 'id_parent'), 1); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('CMS Category'), + 'icon' => 'icon-folder-close' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'required' => true, + 'lang' => true, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'switch', + 'label' => $this->l('Displayed'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + ), + // custom template + array( + 'type' => 'select_category', + 'label' => $this->l('Parent CMS Category'), + 'name' => 'id_parent', + 'options' => array( + 'html' => $html_categories, + ), + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Description'), + 'name' => 'description', + 'lang' => true, + 'rows' => 5, + 'cols' => 40, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'text', + 'label' => $this->l('Meta title'), + 'name' => 'meta_title', + 'lang' => true, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'text', + 'label' => $this->l('Meta description'), + 'name' => 'meta_description', + 'lang' => true, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'text', + 'label' => $this->l('Meta keywords'), + 'name' => 'meta_keywords', + 'lang' => true, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'text', + 'label' => $this->l('Friendly URL'), + 'name' => 'link_rewrite', + 'required' => true, + 'lang' => true, + 'hint' => $this->l('Only letters and the minus (-) character are allowed.') + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('CMS Category'), - 'icon' => 'icon-folder-close' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'required' => true, - 'lang' => true, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'switch', - 'label' => $this->l('Displayed'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - ), - // custom template - array( - 'type' => 'select_category', - 'label' => $this->l('Parent CMS Category'), - 'name' => 'id_parent', - 'options' => array( - 'html' => $html_categories, - ), - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Description'), - 'name' => 'description', - 'lang' => true, - 'rows' => 5, - 'cols' => 40, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'text', - 'label' => $this->l('Meta title'), - 'name' => 'meta_title', - 'lang' => true, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'text', - 'label' => $this->l('Meta description'), - 'name' => 'meta_description', - 'lang' => true, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'text', - 'label' => $this->l('Meta keywords'), - 'name' => 'meta_keywords', - 'lang' => true, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'text', - 'label' => $this->l('Friendly URL'), - 'name' => 'link_rewrite', - 'required' => true, - 'lang' => true, - 'hint' => $this->l('Only letters and the minus (-) character are allowed.') - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } - - $this->tpl_form_vars['PS_ALLOW_ACCENTED_CHARS_URL'] = (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL'); - return parent::renderForm(); - } + $this->tpl_form_vars['PS_ALLOW_ACCENTED_CHARS_URL'] = (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL'); + return parent::renderForm(); + } } diff --git a/controllers/admin/AdminCmsContentController.php b/controllers/admin/AdminCmsContentController.php index 19f2a29b..93c357e1 100644 --- a/controllers/admin/AdminCmsContentController.php +++ b/controllers/admin/AdminCmsContentController.php @@ -29,313 +29,288 @@ */ class AdminCmsContentControllerCore extends AdminController { - /** @var object adminCMSCategories() instance */ - protected $admin_cms_categories; + /** @var object adminCMSCategories() instance */ + protected $admin_cms_categories; - /** @var object adminCMS() instance */ - protected $admin_cms; + /** @var object adminCMS() instance */ + protected $admin_cms; - /** @var object Category() instance for navigation*/ - protected static $category = null; + /** @var object Category() instance for navigation*/ + protected static $category = null; - public function __construct() - { - $this->bootstrap = true; - /* Get current category */ - $id_cms_category = (int)Tools::getValue('id_cms_category', Tools::getValue('id_cms_category_parent', 1)); - self::$category = new CMSCategory($id_cms_category); - if (!Validate::isLoadedObject(self::$category)) - die('Category cannot be loaded'); + public function __construct() + { + $this->bootstrap = true; + /* Get current category */ + $id_cms_category = (int)Tools::getValue('id_cms_category', Tools::getValue('id_cms_category_parent', 1)); + self::$category = new CMSCategory($id_cms_category); + if (!Validate::isLoadedObject(self::$category)) { + die('Category cannot be loaded'); + } - $this->table = 'cms'; - $this->className = 'CMS'; - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); - $this->admin_cms_categories = new AdminCmsCategoriesController(); - $this->admin_cms_categories->init(); - $this->admin_cms = new AdminCmsController(); - $this->admin_cms->init(); + $this->table = 'cms'; + $this->className = 'CMS'; + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); + $this->admin_cms_categories = new AdminCmsCategoriesController(); + $this->admin_cms_categories->init(); + $this->admin_cms = new AdminCmsController(); + $this->admin_cms->init(); - parent::__construct(); - } + parent::__construct(); + } - /** - * Return current category - * - * @return object - */ - public static function getCurrentCMSCategory() - { - return self::$category; - } + /** + * Return current category + * + * @return object + */ + public static function getCurrentCMSCategory() + { + return self::$category; + } - public function viewAccess($disable = false) - { - $result = parent::viewAccess($disable); - $this->admin_cms_categories->tabAccess = $this->tabAccess; - $this->admin_cms->tabAccess = $this->tabAccess; - return $result; - } + public function viewAccess($disable = false) + { + $result = parent::viewAccess($disable); + $this->admin_cms_categories->tabAccess = $this->tabAccess; + $this->admin_cms->tabAccess = $this->tabAccess; + return $result; + } - public function initContent() - { - $this->initTabModuleList(); - $this->renderPageHeaderToolbar(); - - $this->admin_cms_categories->token = $this->token; - $this->admin_cms->token = $this->token; + public function initContent() + { + $this->initTabModuleList(); + $this->renderPageHeaderToolbar(); - if ($this->display == 'edit_category') - $this->content .= $this->admin_cms_categories->renderForm(); - elseif ($this->display == 'edit_page') - $this->content .= $this->admin_cms->renderForm(); - elseif ($this->display == 'view_page') - $fixme = 'fixme';// @FIXME - else - { - $id_cms_category = (int)Tools::getValue('id_cms_category'); - if (!$id_cms_category) - $id_cms_category = 1; + $this->admin_cms_categories->token = $this->token; + $this->admin_cms->token = $this->token; - // CMS categories breadcrumb - $cms_tabs = array('cms_category', 'cms'); - // Cleaning links - $cat_bar_index = self::$currentIndex; - foreach ($cms_tabs as $tab) - if (Tools::getValue($tab.'Orderby') && Tools::getValue($tab.'Orderway')) - $cat_bar_index = preg_replace('/&'.$tab.'Orderby=([a-z _]*)&'.$tab.'Orderway=([a-z]*)/i', '', self::$currentIndex); - $this->context->smarty->assign(array( - 'cms_breadcrumb' => getPath($cat_bar_index, $id_cms_category, '', '', 'cms'), - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn, - 'page_header_toolbar_title' => $this->toolbar_title, - )); - - $this->content .= $this->admin_cms_categories->renderList(); - $this->admin_cms->id_cms_category = $id_cms_category; - $this->content .= $this->admin_cms->renderList(); - - } + if ($this->display == 'edit_category') { + $this->content .= $this->admin_cms_categories->renderForm(); + } elseif ($this->display == 'edit_page') { + $this->content .= $this->admin_cms->renderForm(); + } elseif ($this->display == 'view_page') { + $fixme = 'fixme'; + }// @FIXME + else { + $id_cms_category = (int)Tools::getValue('id_cms_category'); + if (!$id_cms_category) { + $id_cms_category = 1; + } - $this->context->smarty->assign(array( - 'content' => $this->content - )); - } + // CMS categories breadcrumb + $cms_tabs = array('cms_category', 'cms'); + // Cleaning links + $cat_bar_index = self::$currentIndex; + foreach ($cms_tabs as $tab) { + if (Tools::getValue($tab.'Orderby') && Tools::getValue($tab.'Orderway')) { + $cat_bar_index = preg_replace('/&'.$tab.'Orderby=([a-z _]*)&'.$tab.'Orderway=([a-z]*)/i', '', self::$currentIndex); + } + } + $this->context->smarty->assign(array( + 'cms_breadcrumb' => getPath($cat_bar_index, $id_cms_category, '', '', 'cms'), + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn, + 'page_header_toolbar_title' => $this->toolbar_title, + )); - public function renderPageHeaderToolbar() - { - $id_cms_category = (int)Tools::getValue('id_cms_category'); - $id_cms_page = Tools::getValue('id_cms'); + $this->content .= $this->admin_cms_categories->renderList(); + $this->admin_cms->id_cms_category = $id_cms_category; + $this->content .= $this->admin_cms->renderList(); + } - if (!$id_cms_category) - $id_cms_category = 1; + $this->context->smarty->assign(array( + 'content' => $this->content + )); + } - $cms_category = new CMSCategory($id_cms_category); + public function renderPageHeaderToolbar() + { + $id_cms_category = (int)Tools::getValue('id_cms_category'); + $id_cms_page = Tools::getValue('id_cms'); - if ($this->display == 'edit_category') - { - if (Tools::getValue('addcms_category') !== false) - $this->toolbar_title[] = $this->l('Add new'); - else - $this->toolbar_title[] = sprintf($this->l('Edit: %s'), $cms_category->name[$this->context->employee->id_lang]); - } - elseif ($this->display == 'edit_page') - { - $this->toolbar_title[] = $cms_category->name[$this->context->employee->id_lang]; + if (!$id_cms_category) { + $id_cms_category = 1; + } - if (Tools::getValue('addcms') !== false) - $this->toolbar_title[] = $this->l('Add new'); - elseif ($id_cms_page) - { - $cms_page = new CMS($id_cms_page); - $this->toolbar_title[] = sprintf($this->l('Edit: %s'), $cms_page->meta_title[$this->context->employee->id_lang]); - } - } - else - $this->toolbar_title[] = $this->l('CMS'); + $cms_category = new CMSCategory($id_cms_category); - if ($this->display == 'list') - { - $this->page_header_toolbar_btn['new_cms_category'] = array( - 'href' => self::$currentIndex.'&addcms_category&token='.$this->token, - 'desc' => $this->l('Add new CMS category', null, null, false), - 'icon' => 'process-icon-new' - ); - $this->page_header_toolbar_btn['new_cms_page'] = array( - 'href' => self::$currentIndex.'&addcms&id_cms_category='.(int)$id_cms_category.'&token='.$this->token, - 'desc' => $this->l('Add new CMS page', null, null, false), - 'icon' => 'process-icon-new' - ); - } + if ($this->display == 'edit_category') { + if (Tools::getValue('addcms_category') !== false) { + $this->toolbar_title[] = $this->l('Add new'); + } else { + $this->toolbar_title[] = sprintf($this->l('Edit: %s'), $cms_category->name[$this->context->employee->id_lang]); + } + } elseif ($this->display == 'edit_page') { + $this->toolbar_title[] = $cms_category->name[$this->context->employee->id_lang]; - $this->page_header_toolbar_title = implode(' '.Configuration::get('PS_NAVIGATION_PIPE').' ', $this->toolbar_title); + if (Tools::getValue('addcms') !== false) { + $this->toolbar_title[] = $this->l('Add new'); + } elseif ($id_cms_page) { + $cms_page = new CMS($id_cms_page); + $this->toolbar_title[] = sprintf($this->l('Edit: %s'), $cms_page->meta_title[$this->context->employee->id_lang]); + } + } else { + $this->toolbar_title[] = $this->l('CMS'); + } - if (is_array($this->page_header_toolbar_btn) - && $this->page_header_toolbar_btn instanceof Traversable - || trim($this->page_header_toolbar_title) != '') - $this->show_page_header_toolbar = true; + if ($this->display == 'list') { + $this->page_header_toolbar_btn['new_cms_category'] = array( + 'href' => self::$currentIndex.'&addcms_category&token='.$this->token, + 'desc' => $this->l('Add new CMS category', null, null, false), + 'icon' => 'process-icon-new' + ); + $this->page_header_toolbar_btn['new_cms_page'] = array( + 'href' => self::$currentIndex.'&addcms&id_cms_category='.(int)$id_cms_category.'&token='.$this->token, + 'desc' => $this->l('Add new CMS page', null, null, false), + 'icon' => 'process-icon-new' + ); + } - $template = $this->context->smarty->createTemplate( - $this->context->smarty->getTemplateDir(0).DIRECTORY_SEPARATOR - .'page_header_toolbar.tpl', $this->context->smarty); + $this->page_header_toolbar_title = implode(' '.Configuration::get('PS_NAVIGATION_PIPE').' ', $this->toolbar_title); - $this->context->smarty->assign(array( - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'title' => $this->page_header_toolbar_title, - 'toolbar_btn' => $this->page_header_toolbar_btn, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn, - 'page_header_toolbar_title' => $this->toolbar_title, - )); - } + if (is_array($this->page_header_toolbar_btn) + && $this->page_header_toolbar_btn instanceof Traversable + || trim($this->page_header_toolbar_title) != '') { + $this->show_page_header_toolbar = true; + } - public function postProcess() - { - /*if (Tools::isSubmit('submitDelcms') - || Tools::isSubmit('previewSubmitAddcmsAndPreview') - || Tools::isSubmit('submitAddcms') - || Tools::isSubmit('submitBulkdeletecms') - || Tools::isSubmit('deletecms') - || Tools::isSubmit('viewcms') - || (Tools::isSubmit('statuscms') && Tools::isSubmit('id_cms')) - || (Tools::isSubmit('way') && Tools::isSubmit('id_cms')) && (Tools::isSubmit('position')) - || Tools::isSubmit('submitFiltercms') - || $this->context->cookie->{'submitFiltercms'} !== false - || Tools::getValue('cmsOrderby') - || Tools::getValue('cmsOrderway'))*/ - $this->admin_cms->postProcess(); - /*elseif (Tools::isSubmit('submitDelcms_category') - || Tools::isSubmit('submitAddcms_categoryAndBackToParent') - || Tools::isSubmit('submitBulkdeletecms_category') - || Tools::isSubmit('submitAddcms_category') - || Tools::isSubmit('deletecms_category') - || (Tools::isSubmit('statuscms_category') && Tools::isSubmit('id_cms_category')) - || (Tools::isSubmit('position') && Tools::isSubmit('id_cms_category_to_move')) - || Tools::isSubmit('submitFiltercms_category') - || $this->context->cookie->{'submitFiltercms_category'} !== false - || Tools::getValue('cms_categoryOrderby') - || Tools::getValue('cms_categoryOrderway'))*/ - $this->admin_cms_categories->postProcess(); - //else - parent::postProcess(); + $template = $this->context->smarty->createTemplate( + $this->context->smarty->getTemplateDir(0).DIRECTORY_SEPARATOR + .'page_header_toolbar.tpl', $this->context->smarty); - if (((Tools::isSubmit('submitAddcms_category') || Tools::isSubmit('submitAddcms_categoryAndStay')) && count($this->admin_cms_categories->errors)) - || Tools::isSubmit('updatecms_category') - || Tools::isSubmit('addcms_category')) - $this->display = 'edit_category'; - elseif (((Tools::isSubmit('submitAddcms') || Tools::isSubmit('submitAddcmsAndStay')) && count($this->admin_cms->errors)) - || Tools::isSubmit('updatecms') - || Tools::isSubmit('addcms')) - $this->display = 'edit_page'; - else - { - $this->display = 'list'; - $this->id_cms_category = (int)Tools::getValue('id_cms_category'); - } + $this->context->smarty->assign(array( + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'title' => $this->page_header_toolbar_title, + 'toolbar_btn' => $this->page_header_toolbar_btn, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn, + 'page_header_toolbar_title' => $this->toolbar_title, + )); + } - if (isset($this->admin_cms->errors)) - $this->errors = array_merge($this->errors, $this->admin_cms->errors); + public function postProcess() + { + $this->admin_cms->postProcess(); + $this->admin_cms_categories->postProcess(); - if (isset($this->admin_cms_categories->errors)) - $this->errors = array_merge($this->errors, $this->admin_cms_categories->errors); - } + parent::postProcess(); - public function setMedia() - { - parent::setMedia(); - $this->addJqueryUi('ui.widget'); - $this->addJqueryPlugin('tagify'); - } + if (((Tools::isSubmit('submitAddcms_category') || Tools::isSubmit('submitAddcms_categoryAndStay')) && count($this->admin_cms_categories->errors)) + || Tools::isSubmit('updatecms_category') + || Tools::isSubmit('addcms_category')) { + $this->display = 'edit_category'; + } elseif (((Tools::isSubmit('submitAddcms') || Tools::isSubmit('submitAddcmsAndStay')) && count($this->admin_cms->errors)) + || Tools::isSubmit('updatecms') + || Tools::isSubmit('addcms')) { + $this->display = 'edit_page'; + } else { + $this->display = 'list'; + $this->id_cms_category = (int)Tools::getValue('id_cms_category'); + } - public function ajaxProcessUpdateCmsPositions() - { - if ($this->tabAccess['edit'] === '1') - { - $id_cms = (int)Tools::getValue('id_cms'); - $id_category = (int)Tools::getValue('id_cms_category'); - $way = (int)Tools::getValue('way'); - $positions = Tools::getValue('cms'); - if (is_array($positions)) - foreach ($positions as $key => $value) - { - $pos = explode('_', $value); - if ((isset($pos[1]) && isset($pos[2])) && ($pos[1] == $id_category && $pos[2] == $id_cms)) - { - $position = $key; - break; - } - } - $cms = new CMS($id_cms); - if (Validate::isLoadedObject($cms)) - { - if (isset($position) && $cms->updatePosition($way, $position)) - die(true); - else - die('{"hasError" : true, "errors" : "Can not update cms position"}'); - } - else - die('{"hasError" : true, "errors" : "This cms can not be loaded"}'); - } - } + if (isset($this->admin_cms->errors)) { + $this->errors = array_merge($this->errors, $this->admin_cms->errors); + } - public function ajaxProcessUpdateCmsCategoriesPositions() - { - if ($this->tabAccess['edit'] === '1') - { - $id_cms_category_to_move = (int)Tools::getValue('id_cms_category_to_move'); - $id_cms_category_parent = (int)Tools::getValue('id_cms_category_parent'); - $way = (int)Tools::getValue('way'); - $positions = Tools::getValue('cms_category'); - if (is_array($positions)) - foreach ($positions as $key => $value) - { - $pos = explode('_', $value); - if ((isset($pos[1]) && isset($pos[2])) && ($pos[1] == $id_cms_category_parent && $pos[2] == $id_cms_category_to_move)) - { - $position = $key; - break; - } - } - $cms_category = new CMSCategory($id_cms_category_to_move); - if (Validate::isLoadedObject($cms_category)) - { - if (isset($position) && $cms_category->updatePosition($way, $position)) - die(true); - else - die('{"hasError" : true, "errors" : "Can not update cms categories position"}'); - } - else - die('{"hasError" : true, "errors" : "This cms category can not be loaded"}'); - } - } + if (isset($this->admin_cms_categories->errors)) { + $this->errors = array_merge($this->errors, $this->admin_cms_categories->errors); + } + } - public function ajaxProcessPublishCMS() - { - if ($this->tabAccess['edit'] === '1') - { - if ($id_cms = (int)Tools::getValue('id_cms')) - { - $bo_cms_url = _PS_BASE_URL_.__PS_BASE_URI__.basename(_PS_ADMIN_DIR_).'/index.php?tab=AdminCmsContent&id_cms='.(int)$id_cms.'&updatecms&token='.$this->token; + public function setMedia() + { + parent::setMedia(); + $this->addJqueryUi('ui.widget'); + $this->addJqueryPlugin('tagify'); + } - if (Tools::getValue('redirect')) - die($bo_cms_url); + public function ajaxProcessUpdateCmsPositions() + { + if ($this->tabAccess['edit'] === '1') { + $id_cms = (int)Tools::getValue('id_cms'); + $id_category = (int)Tools::getValue('id_cms_category'); + $way = (int)Tools::getValue('way'); + $positions = Tools::getValue('cms'); + if (is_array($positions)) { + foreach ($positions as $key => $value) { + $pos = explode('_', $value); + if ((isset($pos[1]) && isset($pos[2])) && ($pos[1] == $id_category && $pos[2] == $id_cms)) { + $position = $key; + break; + } + } + } + $cms = new CMS($id_cms); + if (Validate::isLoadedObject($cms)) { + if (isset($position) && $cms->updatePosition($way, $position)) { + die(true); + } else { + die('{"hasError" : true, "errors" : "Can not update cms position"}'); + } + } else { + die('{"hasError" : true, "errors" : "This cms can not be loaded"}'); + } + } + } - $cms = new CMS((int)(Tools::getValue('id_cms'))); - if (!Validate::isLoadedObject($cms)) - die('error: invalid id'); + public function ajaxProcessUpdateCmsCategoriesPositions() + { + if ($this->tabAccess['edit'] === '1') { + $id_cms_category_to_move = (int)Tools::getValue('id_cms_category_to_move'); + $id_cms_category_parent = (int)Tools::getValue('id_cms_category_parent'); + $way = (int)Tools::getValue('way'); + $positions = Tools::getValue('cms_category'); + if (is_array($positions)) { + foreach ($positions as $key => $value) { + $pos = explode('_', $value); + if ((isset($pos[1]) && isset($pos[2])) && ($pos[1] == $id_cms_category_parent && $pos[2] == $id_cms_category_to_move)) { + $position = $key; + break; + } + } + } + $cms_category = new CMSCategory($id_cms_category_to_move); + if (Validate::isLoadedObject($cms_category)) { + if (isset($position) && $cms_category->updatePosition($way, $position)) { + die(true); + } else { + die('{"hasError" : true, "errors" : "Can not update cms categories position"}'); + } + } else { + die('{"hasError" : true, "errors" : "This cms category can not be loaded"}'); + } + } + } - $cms->active = 1; - if ($cms->save()) - die($bo_cms_url); - else - die('error: saving'); - } - else - die ('error: parameters'); - } - } + public function ajaxProcessPublishCMS() + { + if ($this->tabAccess['edit'] === '1') { + if ($id_cms = (int)Tools::getValue('id_cms')) { + $bo_cms_url = _PS_BASE_URL_.__PS_BASE_URI__.basename(_PS_ADMIN_DIR_).'/index.php?tab=AdminCmsContent&id_cms='.(int)$id_cms.'&updatecms&token='.$this->token; + if (Tools::getValue('redirect')) { + die($bo_cms_url); + } + + $cms = new CMS((int)(Tools::getValue('id_cms'))); + if (!Validate::isLoadedObject($cms)) { + die('error: invalid id'); + } + + $cms->active = 1; + if ($cms->save()) { + die($bo_cms_url); + } else { + die('error: saving'); + } + } else { + die('error: parameters'); + } + } + } } diff --git a/controllers/admin/AdminCmsController.php b/controllers/admin/AdminCmsController.php index 21fa701b..13fe4d9a 100644 --- a/controllers/admin/AdminCmsController.php +++ b/controllers/admin/AdminCmsController.php @@ -29,399 +29,387 @@ */ class AdminCmsControllerCore extends AdminController { - protected $category; + protected $category; - public $id_cms_category; + public $id_cms_category; - protected $position_identifier = 'id_cms'; + protected $position_identifier = 'id_cms'; - public function __construct() - { - $this->bootstrap = true; - $this->table = 'cms'; - $this->list_id = 'cms'; - $this->className = 'CMS'; - $this->lang = true; - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->_orderBy = 'position'; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'cms'; + $this->list_id = 'cms'; + $this->className = 'CMS'; + $this->lang = true; + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->_orderBy = 'position'; - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); - $this->fields_list = array( - 'id_cms' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'link_rewrite' => array('title' => $this->l('URL')), - 'meta_title' => array('title' => $this->l('Title'), 'filter_key' => 'b!meta_title'), - 'position' => array('title' => $this->l('Position'),'filter_key' => 'position', 'align' => 'center', 'class' => 'fixed-width-sm', 'position' => 'position'), - 'active' => array('title' => $this->l('Displayed'), 'align' => 'center', 'active' => 'status', 'class' => 'fixed-width-sm', 'type' => 'bool', 'orderby' => false) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); + $this->fields_list = array( + 'id_cms' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'link_rewrite' => array('title' => $this->l('URL')), + 'meta_title' => array('title' => $this->l('Title'), 'filter_key' => 'b!meta_title'), + 'position' => array('title' => $this->l('Position'),'filter_key' => 'position', 'align' => 'center', 'class' => 'fixed-width-sm', 'position' => 'position'), + 'active' => array('title' => $this->l('Displayed'), 'align' => 'center', 'active' => 'status', 'class' => 'fixed-width-sm', 'type' => 'bool', 'orderby' => false) + ); - // The controller can't be call directly - // In this case, AdminCmsContentController::getCurrentCMSCategory() is null - if (!AdminCmsContentController::getCurrentCMSCategory()) - { - $this->redirect_after = '?controller=AdminCmsContent&token='.Tools::getAdminTokenLite('AdminCmsContent'); - $this->redirect(); - } + // The controller can't be call directly + // In this case, AdminCmsContentController::getCurrentCMSCategory() is null + if (!AdminCmsContentController::getCurrentCMSCategory()) { + $this->redirect_after = '?controller=AdminCmsContent&token='.Tools::getAdminTokenLite('AdminCmsContent'); + $this->redirect(); + } - $this->_category = AdminCmsContentController::getCurrentCMSCategory(); - $this->tpl_list_vars['icon'] = 'icon-folder-close'; - $this->tpl_list_vars['title'] = sprintf($this->l('Pages in category "%s"'), - $this->_category->name[Context::getContext()->employee->id_lang]); - $this->_join = ' + $this->_category = AdminCmsContentController::getCurrentCMSCategory(); + $this->tpl_list_vars['icon'] = 'icon-folder-close'; + $this->tpl_list_vars['title'] = sprintf($this->l('Pages in category "%s"'), + $this->_category->name[Context::getContext()->employee->id_lang]); + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'cms_category` c ON (c.`id_cms_category` = a.`id_cms_category`)'; - $this->_select = 'a.position '; - $this->_where = ' AND c.id_cms_category = '.(int)$this->_category->id; + $this->_select = 'a.position '; + $this->_where = ' AND c.id_cms_category = '.(int)$this->_category->id; - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - $this->page_header_toolbar_btn['save-and-preview'] = array( - 'href' => '#', - 'desc' => $this->l('Save and preview', null, null, false) - ); - $this->page_header_toolbar_btn['save-and-stay'] = array( - 'short' => $this->l('Save and stay', null, null, false), - 'href' => '#', - 'desc' => $this->l('Save and stay', null, null, false), - ); + public function initPageHeaderToolbar() + { + $this->page_header_toolbar_btn['save-and-preview'] = array( + 'href' => '#', + 'desc' => $this->l('Save and preview', null, null, false) + ); + $this->page_header_toolbar_btn['save-and-stay'] = array( + 'short' => $this->l('Save and stay', null, null, false), + 'href' => '#', + 'desc' => $this->l('Save and stay', null, null, false), + ); - return parent::initPageHeaderToolbar(); - } + return parent::initPageHeaderToolbar(); + } - public function renderForm() - { - if (!$this->loadObject(true)) - return; + public function renderForm() + { + if (!$this->loadObject(true)) { + return; + } - if (Validate::isLoadedObject($this->object)) - $this->display = 'edit'; - else - $this->display = 'add'; + if (Validate::isLoadedObject($this->object)) { + $this->display = 'edit'; + } else { + $this->display = 'add'; + } - $this->initToolbar(); - $this->initPageHeaderToolbar(); + $this->initToolbar(); + $this->initPageHeaderToolbar(); - $categories = CMSCategory::getCategories($this->context->language->id, false); - $html_categories = CMSCategory::recurseCMSCategory($categories, $categories[0][1], 1, $this->getFieldValue($this->object, 'id_cms_category'), 1); + $categories = CMSCategory::getCategories($this->context->language->id, false); + $html_categories = CMSCategory::recurseCMSCategory($categories, $categories[0][1], 1, $this->getFieldValue($this->object, 'id_cms_category'), 1); - $this->fields_form = array( - 'tinymce' => true, - 'legend' => array( - 'title' => $this->l('CMS Page'), - 'icon' => 'icon-folder-close' - ), - 'input' => array( - // custom template - array( - 'type' => 'select_category', - 'label' => $this->l('CMS Category'), - 'name' => 'id_cms_category', - 'options' => array( - 'html' => $html_categories, - ), - ), - array( - 'type' => 'text', - 'label' => $this->l('Meta title'), - 'name' => 'meta_title', - 'id' => 'name', // for copyMeta2friendlyURL compatibility - 'lang' => true, - 'required' => true, - 'class' => 'copyMeta2friendlyURL', - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'text', - 'label' => $this->l('Meta description'), - 'name' => 'meta_description', - 'lang' => true, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'tags', - 'label' => $this->l('Meta keywords'), - 'name' => 'meta_keywords', - 'lang' => true, - 'hint' => array( - $this->l('To add "tags" click in the field, write something, and then press "Enter."'), - $this->l('Invalid characters:').' <>;=#{}' - ) - ), - array( - 'type' => 'text', - 'label' => $this->l('Friendly URL'), - 'name' => 'link_rewrite', - 'required' => true, - 'lang' => true, - 'hint' => $this->l('Only letters and the hyphen (-) character are allowed.') - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Page content'), - 'name' => 'content', - 'autoload_rte' => true, - 'lang' => true, - 'rows' => 5, - 'cols' => 40, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'switch', - 'label' => $this->l('Indexation by search engines'), - 'name' => 'indexation', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'indexation_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'indexation_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Displayed'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ), - 'buttons' => array( - 'save_and_preview' => array( - 'name' => 'viewcms', - 'type' => 'submit', - 'title' => $this->l('Save and preview'), - 'class' => 'btn btn-default pull-right', - 'icon' => 'process-icon-preview' - ) - ) - ); + $this->fields_form = array( + 'tinymce' => true, + 'legend' => array( + 'title' => $this->l('CMS Page'), + 'icon' => 'icon-folder-close' + ), + 'input' => array( + // custom template + array( + 'type' => 'select_category', + 'label' => $this->l('CMS Category'), + 'name' => 'id_cms_category', + 'options' => array( + 'html' => $html_categories, + ), + ), + array( + 'type' => 'text', + 'label' => $this->l('Meta title'), + 'name' => 'meta_title', + 'id' => 'name', // for copyMeta2friendlyURL compatibility + 'lang' => true, + 'required' => true, + 'class' => 'copyMeta2friendlyURL', + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'text', + 'label' => $this->l('Meta description'), + 'name' => 'meta_description', + 'lang' => true, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'tags', + 'label' => $this->l('Meta keywords'), + 'name' => 'meta_keywords', + 'lang' => true, + 'hint' => array( + $this->l('To add "tags" click in the field, write something, and then press "Enter."'), + $this->l('Invalid characters:').' <>;=#{}' + ) + ), + array( + 'type' => 'text', + 'label' => $this->l('Friendly URL'), + 'name' => 'link_rewrite', + 'required' => true, + 'lang' => true, + 'hint' => $this->l('Only letters and the hyphen (-) character are allowed.') + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Page content'), + 'name' => 'content', + 'autoload_rte' => true, + 'lang' => true, + 'rows' => 5, + 'cols' => 40, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'switch', + 'label' => $this->l('Indexation by search engines'), + 'name' => 'indexation', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'indexation_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'indexation_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + ), + array( + 'type' => 'switch', + 'label' => $this->l('Displayed'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ), + 'buttons' => array( + 'save_and_preview' => array( + 'name' => 'viewcms', + 'type' => 'submit', + 'title' => $this->l('Save and preview'), + 'class' => 'btn btn-default pull-right', + 'icon' => 'process-icon-preview' + ) + ) + ); - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - if (Validate::isLoadedObject($this->object)) - $this->context->smarty->assign('url_prev', $this->getPreviewUrl($this->object)); + if (Validate::isLoadedObject($this->object)) { + $this->context->smarty->assign('url_prev', $this->getPreviewUrl($this->object)); + } - $this->tpl_form_vars = array( - 'active' => $this->object->active, - 'PS_ALLOW_ACCENTED_CHARS_URL', (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL') - ); - return parent::renderForm(); - } + $this->tpl_form_vars = array( + 'active' => $this->object->active, + 'PS_ALLOW_ACCENTED_CHARS_URL', (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL') + ); + return parent::renderForm(); + } - public function renderList() - { - $this->_group = 'GROUP BY a.`id_cms`'; - //self::$currentIndex = self::$currentIndex.'&cms'; - $this->position_group_identifier = (int)$this->id_cms_category; + public function renderList() + { + $this->_group = 'GROUP BY a.`id_cms`'; + //self::$currentIndex = self::$currentIndex.'&cms'; + $this->position_group_identifier = (int)$this->id_cms_category; - $this->toolbar_title = $this->l('Pages in this category'); - $this->toolbar_btn['new'] = array( - 'href' => self::$currentIndex.'&add'.$this->table.'&id_cms_category='.(int)$this->id_cms_category.'&token='.$this->token, - 'desc' => $this->l('Add new') - ); + $this->toolbar_title = $this->l('Pages in this category'); + $this->toolbar_btn['new'] = array( + 'href' => self::$currentIndex.'&add'.$this->table.'&id_cms_category='.(int)$this->id_cms_category.'&token='.$this->token, + 'desc' => $this->l('Add new') + ); - return parent::renderList(); - } + return parent::renderList(); + } - public function displayList($token = null) - { - /* Display list header (filtering, pagination and column names) */ - $this->displayListHeader($token); - if (!count($this->_list)) - echo '<tr><td class="center" colspan="'.(count($this->fields_list) + 2).'">'.$this->l('No items found').'</td></tr>'; + public function displayList($token = null) + { + /* Display list header (filtering, pagination and column names) */ + $this->displayListHeader($token); + if (!count($this->_list)) { + echo '<tr><td class="center" colspan="'.(count($this->fields_list) + 2).'">'.$this->l('No items found').'</td></tr>'; + } - /* Show the content of the table */ - $this->displayListContent($token); + /* Show the content of the table */ + $this->displayListContent($token); - /* Close list table and submit button */ - $this->displayListFooter($token); - } + /* Close list table and submit button */ + $this->displayListFooter($token); + } - public function postProcess() - { - if (Tools::isSubmit('viewcms') && ($id_cms = (int)Tools::getValue('id_cms'))) - { - parent::postProcess(); - if (($cms = new CMS($id_cms, $this->context->language->id)) && Validate::isLoadedObject($cms)) - Tools::redirectAdmin(self::$currentIndex.'&id_cms='.$id_cms.'&conf=4&updatecms&token='.Tools::getAdminTokenLite('AdminCmsContent').'&url_preview=1'); - } - elseif (Tools::isSubmit('deletecms')) - { - if (Tools::getValue('id_cms') == Configuration::get('PS_CONDITIONS_CMS_ID')) - { - Configuration::updateValue('PS_CONDITIONS', 0); - Configuration::updateValue('PS_CONDITIONS_CMS_ID', 0); - } - $cms = new CMS((int)Tools::getValue('id_cms')); - $cms->cleanPositions($cms->id_cms_category); - if (!$cms->delete()) - $this->errors[] = Tools::displayError('An error occurred while deleting the object.') - .' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>'; - else - Tools::redirectAdmin(self::$currentIndex.'&id_cms_category='.$cms->id_cms_category.'&conf=1&token='.Tools::getAdminTokenLite('AdminCmsContent')); - }/* Delete multiple objects */ - elseif (Tools::getValue('submitDel'.$this->table)) - { - if ($this->tabAccess['delete'] === '1') - { - if (Tools::isSubmit($this->table.'Box')) - { - $cms = new CMS(); - $result = true; - $result = $cms->deleteSelection(Tools::getValue($this->table.'Box')); - if ($result) - { - $cms->cleanPositions((int)Tools::getValue('id_cms_category')); - $token = Tools::getAdminTokenLite('AdminCmsContent'); - Tools::redirectAdmin(self::$currentIndex.'&conf=2&token='.$token.'&id_cms_category='.(int)Tools::getValue('id_cms_category')); - } - $this->errors[] = Tools::displayError('An error occurred while deleting this selection.'); + public function postProcess() + { + if (Tools::isSubmit('viewcms') && ($id_cms = (int)Tools::getValue('id_cms'))) { + parent::postProcess(); + if (($cms = new CMS($id_cms, $this->context->language->id)) && Validate::isLoadedObject($cms)) { + Tools::redirectAdmin(self::$currentIndex.'&id_cms='.$id_cms.'&conf=4&updatecms&token='.Tools::getAdminTokenLite('AdminCmsContent').'&url_preview=1'); + } + } elseif (Tools::isSubmit('deletecms')) { + if (Tools::getValue('id_cms') == Configuration::get('PS_CONDITIONS_CMS_ID')) { + Configuration::updateValue('PS_CONDITIONS', 0); + Configuration::updateValue('PS_CONDITIONS_CMS_ID', 0); + } + $cms = new CMS((int)Tools::getValue('id_cms')); + $cms->cleanPositions($cms->id_cms_category); + if (!$cms->delete()) { + $this->errors[] = Tools::displayError('An error occurred while deleting the object.') + .' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>'; + } else { + Tools::redirectAdmin(self::$currentIndex.'&id_cms_category='.$cms->id_cms_category.'&conf=1&token='.Tools::getAdminTokenLite('AdminCmsContent')); + } + }/* Delete multiple objects */ + elseif (Tools::getValue('submitDel'.$this->table)) { + if ($this->tabAccess['delete'] === '1') { + if (Tools::isSubmit($this->table.'Box')) { + $cms = new CMS(); + $result = true; + $result = $cms->deleteSelection(Tools::getValue($this->table.'Box')); + if ($result) { + $cms->cleanPositions((int)Tools::getValue('id_cms_category')); + $token = Tools::getAdminTokenLite('AdminCmsContent'); + Tools::redirectAdmin(self::$currentIndex.'&conf=2&token='.$token.'&id_cms_category='.(int)Tools::getValue('id_cms_category')); + } + $this->errors[] = Tools::displayError('An error occurred while deleting this selection.'); + } else { + $this->errors[] = Tools::displayError('You must select at least one element to delete.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } elseif (Tools::isSubmit('submitAddcms') || Tools::isSubmit('submitAddcmsAndPreview')) { + parent::validateRules(); + if (count($this->errors)) { + return false; + } + if (!$id_cms = (int)Tools::getValue('id_cms')) { + $cms = new CMS(); + $this->copyFromPost($cms, 'cms'); + if (!$cms->add()) { + $this->errors[] = Tools::displayError('An error occurred while creating an object.').' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>'; + } else { + $this->updateAssoShop($cms->id); + } + } else { + $cms = new CMS($id_cms); + $this->copyFromPost($cms, 'cms'); + if (!$cms->update()) { + $this->errors[] = Tools::displayError('An error occurred while updating an object.').' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>'; + } else { + $this->updateAssoShop($cms->id); + } + } + if (Tools::isSubmit('view'.$this->table)) { + Tools::redirectAdmin(self::$currentIndex.'&id_cms='.$cms->id.'&conf=4&updatecms&token='.Tools::getAdminTokenLite('AdminCmsContent').'&url_preview=1'); + } elseif (Tools::isSubmit('submitAdd'.$this->table.'AndStay')) { + Tools::redirectAdmin(self::$currentIndex.'&'.$this->identifier.'='.$cms->id.'&conf=4&update'.$this->table.'&token='.Tools::getAdminTokenLite('AdminCmsContent')); + } else { + Tools::redirectAdmin(self::$currentIndex.'&id_cms_category='.$cms->id_cms_category.'&conf=4&token='.Tools::getAdminTokenLite('AdminCmsContent')); + } + } elseif (Tools::isSubmit('way') && Tools::isSubmit('id_cms') && (Tools::isSubmit('position'))) { + /** @var CMS $object */ + if ($this->tabAccess['edit'] !== '1') { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } elseif (!Validate::isLoadedObject($object = $this->loadObject())) { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.') + .' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } elseif (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) { + $this->errors[] = Tools::displayError('Failed to update the position.'); + } else { + Tools::redirectAdmin(self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=4&id_cms_category='.(int)$object->id_cms_category.'&token='.Tools::getAdminTokenLite('AdminCmsContent')); + } + } + /* Change object statuts (active, inactive) */ + elseif (Tools::isSubmit('statuscms') && Tools::isSubmit($this->identifier)) { + if ($this->tabAccess['edit'] === '1') { + if (Validate::isLoadedObject($object = $this->loadObject())) { + /** @var CMS $object */ + if ($object->toggleStatus()) { + Tools::redirectAdmin(self::$currentIndex.'&conf=5&id_cms_category='.(int)$object->id_cms_category.'&token='.Tools::getValue('token')); + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the status.'); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.') + .' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + /* Delete multiple CMS content */ + elseif (Tools::isSubmit('submitBulkdeletecms')) { + if ($this->tabAccess['delete'] === '1') { + $this->action = 'bulkdelete'; + $this->boxes = Tools::getValue($this->table.'Box'); + if (is_array($this->boxes) && array_key_exists(0, $this->boxes)) { + $firstCms = new CMS((int)$this->boxes[0]); + $id_cms_category = (int)$firstCms->id_cms_category; + if (!$res = parent::postProcess(true)) { + return $res; + } + Tools::redirectAdmin(self::$currentIndex.'&conf=2&token='.Tools::getAdminTokenLite('AdminCmsContent').'&id_cms_category='.$id_cms_category); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } else { + parent::postProcess(true); + } + } - } - else - $this->errors[] = Tools::displayError('You must select at least one element to delete.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - elseif (Tools::isSubmit('submitAddcms') || Tools::isSubmit('submitAddcmsAndPreview')) - { - parent::validateRules(); - if (count($this->errors)) - return false; - if (!$id_cms = (int)Tools::getValue('id_cms')) - { - $cms = new CMS(); - $this->copyFromPost($cms, 'cms'); - if (!$cms->add()) - $this->errors[] = Tools::displayError('An error occurred while creating an object.').' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>'; - else - $this->updateAssoShop($cms->id); - } - else - { - $cms = new CMS($id_cms); - $this->copyFromPost($cms, 'cms'); - if (!$cms->update()) - $this->errors[] = Tools::displayError('An error occurred while updating an object.').' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>'; - else - $this->updateAssoShop($cms->id); - } - if (Tools::isSubmit('view'.$this->table)) - Tools::redirectAdmin(self::$currentIndex.'&id_cms='.$cms->id.'&conf=4&updatecms&token='.Tools::getAdminTokenLite('AdminCmsContent').'&url_preview=1'); - elseif (Tools::isSubmit('submitAdd'.$this->table.'AndStay')) - Tools::redirectAdmin(self::$currentIndex.'&'.$this->identifier.'='.$cms->id.'&conf=4&update'.$this->table.'&token='.Tools::getAdminTokenLite('AdminCmsContent')); - else - Tools::redirectAdmin(self::$currentIndex.'&id_cms_category='.$cms->id_cms_category.'&conf=4&token='.Tools::getAdminTokenLite('AdminCmsContent')); - } - elseif (Tools::isSubmit('way') && Tools::isSubmit('id_cms') && (Tools::isSubmit('position'))) - { - /** @var CMS $object */ - if ($this->tabAccess['edit'] !== '1') - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - elseif (!Validate::isLoadedObject($object = $this->loadObject())) - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.') - .' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - elseif (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) - $this->errors[] = Tools::displayError('Failed to update the position.'); - else - Tools::redirectAdmin(self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=4&id_cms_category='.(int)$object->id_cms_category.'&token='.Tools::getAdminTokenLite('AdminCmsContent')); - } - /* Change object statuts (active, inactive) */ - elseif (Tools::isSubmit('statuscms') && Tools::isSubmit($this->identifier)) - { - if ($this->tabAccess['edit'] === '1') - { - if (Validate::isLoadedObject($object = $this->loadObject())) - { - /** @var CMS $object */ - if ($object->toggleStatus()) - Tools::redirectAdmin(self::$currentIndex.'&conf=5&id_cms_category='.(int)$object->id_cms_category.'&token='.Tools::getValue('token')); - else - $this->errors[] = Tools::displayError('An error occurred while updating the status.'); - } - else - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.') - .' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - /* Delete multiple CMS content */ - elseif (Tools::isSubmit('submitBulkdeletecms')) - { - if ($this->tabAccess['delete'] === '1') - { - $this->action = 'bulkdelete'; - $this->boxes = Tools::getValue($this->table.'Box'); - if (is_array($this->boxes) && array_key_exists(0, $this->boxes)) - { - $firstCms = new CMS((int)$this->boxes[0]); - $id_cms_category = (int)$firstCms->id_cms_category; - if (!$res = parent::postProcess(true)) - return $res; - Tools::redirectAdmin(self::$currentIndex.'&conf=2&token='.Tools::getAdminTokenLite('AdminCmsContent').'&id_cms_category='.$id_cms_category); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - else - parent::postProcess(true); - } + public function getPreviewUrl(CMS $cms) + { + $preview_url = $this->context->link->getCMSLink($cms, null, null, $this->context->language->id); + if (!$cms->active) { + $params = http_build_query(array( + 'adtoken' => Tools::getAdminTokenLite('AdminCmsContent'), + 'ad' => basename(_PS_ADMIN_DIR_), + 'id_employee' => (int)$this->context->employee->id + ) + ); + $preview_url .= (strpos($preview_url, '?') === false ? '?' : '&').$params; + } - public function getPreviewUrl(CMS $cms) - { - $preview_url = $this->context->link->getCMSLink($cms, null, null, $this->context->language->id); - if (!$cms->active) - { - $params = http_build_query(array( - 'adtoken' => Tools::getAdminTokenLite('AdminCmsContent'), - 'ad' => basename(_PS_ADMIN_DIR_), - 'id_employee' => (int)$this->context->employee->id - ) - ); - $preview_url .= (strpos($preview_url, '?') === false ? '?' : '&').$params; - } - - return $preview_url; - } + return $preview_url; + } } diff --git a/controllers/admin/AdminContactsController.php b/controllers/admin/AdminContactsController.php index 32ef89e6..68dd0994 100644 --- a/controllers/admin/AdminContactsController.php +++ b/controllers/admin/AdminContactsController.php @@ -29,116 +29,115 @@ */ class AdminContactsControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'contact'; - $this->className = 'Contact'; - $this->lang = true; - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + public function __construct() + { + $this->bootstrap = true; + $this->table = 'contact'; + $this->className = 'Contact'; + $this->lang = true; + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->fields_list = array( - 'id_contact' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'name' => array('title' => $this->l('Title')), - 'email' => array('title' => $this->l('Email address')), - 'description' => array('title' => $this->l('Description')), - ); + $this->fields_list = array( + 'id_contact' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'name' => array('title' => $this->l('Title')), + 'email' => array('title' => $this->l('Email address')), + 'description' => array('title' => $this->l('Description')), + ); - parent::__construct(); - } + parent::__construct(); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Contacts'), - 'icon' => 'icon-envelope-alt' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Title'), - 'name' => 'name', - 'required' => true, - 'lang' => true, - 'col' => 4, - 'hint' => $this->l('Contact name (e.g. Customer Support).'), - ), - array( - 'type' => 'text', - 'label' => $this->l('Email address'), - 'name' => 'email', - 'required' => false, - 'col' => 4, - 'hint' => $this->l('Emails will be sent to this address.'), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Save messages?'), - 'name' => 'customer_service', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'hint' => $this->l('If enabled, all messages will be saved in the "Customer Service" page under the "Customer" menu.'), - 'values' => array( - array( - 'id' => 'customer_service_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'customer_service_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Description'), - 'name' => 'description', - 'required' => false, - 'lang' => true, - 'col' => 6, - 'hint' => $this->l('Further information regarding this contact.'), - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); - - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Contacts'), + 'icon' => 'icon-envelope-alt' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Title'), + 'name' => 'name', + 'required' => true, + 'lang' => true, + 'col' => 4, + 'hint' => $this->l('Contact name (e.g. Customer Support).'), + ), + array( + 'type' => 'text', + 'label' => $this->l('Email address'), + 'name' => 'email', + 'required' => false, + 'col' => 4, + 'hint' => $this->l('Emails will be sent to this address.'), + ), + array( + 'type' => 'switch', + 'label' => $this->l('Save messages?'), + 'name' => 'customer_service', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'hint' => $this->l('If enabled, all messages will be saved in the "Customer Service" page under the "Customer" menu.'), + 'values' => array( + array( + 'id' => 'customer_service_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'customer_service_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Description'), + 'name' => 'description', + 'required' => false, + 'lang' => true, + 'col' => 6, + 'hint' => $this->l('Further information regarding this contact.'), + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); + + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - return parent::renderForm(); - } + return parent::renderForm(); + } - public function initPageHeaderToolbar() - { - $this->initToolbar(); - if(empty($this->display)) - $this->page_header_toolbar_btn['new_contact'] = array( - 'href' => self::$currentIndex.'&addcontact&token='.$this->token, - 'desc' => $this->l('Add new contact', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + $this->initToolbar(); + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_contact'] = array( + 'href' => self::$currentIndex.'&addcontact&token='.$this->token, + 'desc' => $this->l('Add new contact', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } - + parent::initPageHeaderToolbar(); + } } diff --git a/controllers/admin/AdminCountriesController.php b/controllers/admin/AdminCountriesController.php index 06cd6513..d6c1a20a 100644 --- a/controllers/admin/AdminCountriesController.php +++ b/controllers/admin/AdminCountriesController.php @@ -29,486 +29,495 @@ */ class AdminCountriesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'country'; - $this->className = 'Country'; - $this->lang = true; - $this->deleted = false; - $this->_defaultOrderBy = 'name'; - $this->_defaultOrderWay = 'ASC'; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'country'; + $this->className = 'Country'; + $this->lang = true; + $this->deleted = false; + $this->_defaultOrderBy = 'name'; + $this->_defaultOrderWay = 'ASC'; - $this->explicitSelect = true; - $this->addRowAction('edit'); + $this->explicitSelect = true; + $this->addRowAction('edit'); - $this->context = Context::getContext(); + $this->context = Context::getContext(); - $this->bulk_actions = array( - 'delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?')), - 'affectzone' => array('text' => $this->l('Assign to a new zone')) - ); + $this->bulk_actions = array( + 'delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?')), + 'affectzone' => array('text' => $this->l('Assign to a new zone')) + ); - $this->fieldImageSettings = array( - 'name' => 'logo', - 'dir' => 'st' - ); + $this->fieldImageSettings = array( + 'name' => 'logo', + 'dir' => 'st' + ); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Country options'), - 'fields' => array( - 'PS_RESTRICT_DELIVERED_COUNTRIES' => array( - 'title' => $this->l('Restrict country selections in front office to those covered by active carriers'), - 'cast' => 'intval', - 'type' => 'bool', - 'default' => '0' - ) - ), - 'submit' => array('title' => $this->l('Save')) - ) - ); + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Country options'), + 'fields' => array( + 'PS_RESTRICT_DELIVERED_COUNTRIES' => array( + 'title' => $this->l('Restrict country selections in front office to those covered by active carriers'), + 'cast' => 'intval', + 'type' => 'bool', + 'default' => '0' + ) + ), + 'submit' => array('title' => $this->l('Save')) + ) + ); - $zones_array = array(); - $this->zones = Zone::getZones(); - foreach ($this->zones as $zone) - $zones_array[$zone['id_zone']] = $zone['name']; + $zones_array = array(); + $this->zones = Zone::getZones(); + foreach ($this->zones as $zone) { + $zones_array[$zone['id_zone']] = $zone['name']; + } - $this->fields_list = array( - 'id_country' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Country'), - 'filter_key' => 'b!name' - ), - 'iso_code' => array( - 'title' => $this->l('ISO code'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'call_prefix' => array( - 'title' => $this->l('Call prefix'), - 'align' => 'center', - 'callback' => 'displayCallPrefix', - 'class' => 'fixed-width-sm' - ), - 'zone' => array( - 'title' => $this->l('Zone'), - 'type' => 'select', - 'list' => $zones_array, - 'filter_key' => 'z!id_zone', - 'filter_type' => 'int', - 'order_key' => 'z!name' - ), - 'active' => array( - 'title' => $this->l('Enabled'), - 'align' => 'center', - 'active' => 'status', - 'type' => 'bool', - 'orderby' => false, - 'filter_key' => 'a!active', - 'class' => 'fixed-width-sm' - ) - ); + $this->fields_list = array( + 'id_country' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Country'), + 'filter_key' => 'b!name' + ), + 'iso_code' => array( + 'title' => $this->l('ISO code'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'call_prefix' => array( + 'title' => $this->l('Call prefix'), + 'align' => 'center', + 'callback' => 'displayCallPrefix', + 'class' => 'fixed-width-sm' + ), + 'zone' => array( + 'title' => $this->l('Zone'), + 'type' => 'select', + 'list' => $zones_array, + 'filter_key' => 'z!id_zone', + 'filter_type' => 'int', + 'order_key' => 'z!name' + ), + 'active' => array( + 'title' => $this->l('Enabled'), + 'align' => 'center', + 'active' => 'status', + 'type' => 'bool', + 'orderby' => false, + 'filter_key' => 'a!active', + 'class' => 'fixed-width-sm' + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_country'] = array( - 'href' => self::$currentIndex.'&addcountry&token='.$this->token, - 'desc' => $this->l('Add new country', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_country'] = array( + 'href' => self::$currentIndex.'&addcountry&token='.$this->token, + 'desc' => $this->l('Add new country', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - /** - * AdminController::setMedia() override - * @see AdminController::setMedia() - */ - public function setMedia() - { - parent::setMedia(); + /** + * AdminController::setMedia() override + * @see AdminController::setMedia() + */ + public function setMedia() + { + parent::setMedia(); - $this->addJqueryPlugin('fieldselection'); - } + $this->addJqueryPlugin('fieldselection'); + } - public function renderList() - { - $this->_select = 'z.`name` AS zone'; - $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'zone` z ON (z.`id_zone` = a.`id_zone`)'; - $this->_use_found_rows = false; + public function renderList() + { + $this->_select = 'z.`name` AS zone'; + $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'zone` z ON (z.`id_zone` = a.`id_zone`)'; + $this->_use_found_rows = false; - $this->tpl_list_vars['zones'] = Zone::getZones(); - return parent::renderList(); - } + $this->tpl_list_vars['zones'] = Zone::getZones(); + return parent::renderList(); + } - public function renderForm() - { - if (!($obj = $this->loadObject(true))) - return; + public function renderForm() + { + if (!($obj = $this->loadObject(true))) { + return; + } - $address_layout = AddressFormat::getAddressCountryFormat($obj->id); - if ($value = Tools::getValue('address_layout')) - $address_layout = $value; + $address_layout = AddressFormat::getAddressCountryFormat($obj->id); + if ($value = Tools::getValue('address_layout')) { + $address_layout = $value; + } - $default_layout = ''; + $default_layout = ''; - $default_layout_tab = array( - array('firstname', 'lastname'), - array('company'), - array('vat_number'), - array('address1'), - array('address2'), - array('postcode', 'city'), - array('Country:name'), - array('phone'), - array('phone_mobile')); + $default_layout_tab = array( + array('firstname', 'lastname'), + array('company'), + array('vat_number'), + array('address1'), + array('address2'), + array('postcode', 'city'), + array('Country:name'), + array('phone'), + array('phone_mobile')); - foreach ($default_layout_tab as $line) - $default_layout .= implode(' ', $line)."\r\n"; + foreach ($default_layout_tab as $line) { + $default_layout .= implode(' ', $line)."\r\n"; + } - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Countries'), - 'icon' => 'icon-globe' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Country'), - 'name' => 'name', - 'lang' => true, - 'required' => true, - 'hint' => $this->l('Country name').' - '.$this->l('Invalid characters:').' <>;=#{} ' - ), - array( - 'type' => 'text', - 'label' => $this->l('ISO code'), - 'name' => 'iso_code', - 'maxlength' => 3, - 'class' => 'uppercase', - 'required' => true, - 'hint' => $this->l('Two -- or three -- letter ISO code (e.g. "us for United States).') - /* @TODO - ajouter les liens dans le hint ? */ - /*'desc' => $this->l('Two -- or three -- letter ISO code (e.g. U.S. for United States)').'. - <a href="http://www.iso.org/iso/country_codes/iso_3166_code_lists/country_names_and_code_elements.htm" target="_blank">'. - $this->l('Official list here').' - </a>.'*/ - ), - array( - 'type' => 'text', - 'label' => $this->l('Call prefix'), - 'name' => 'call_prefix', - 'maxlength' => 3, - 'class' => 'uppercase', - 'required' => true, - 'hint' => $this->l('International call prefix, (e.g. 1 for United States).') - ), - array( - 'type' => 'select', - 'label' => $this->l('Default currency'), - 'name' => 'id_currency', - 'options' => array( - 'query' => Currency::getCurrencies(), - 'id' => 'id_currency', - 'name' => 'name', - 'default' => array( - 'label' => $this->l('Default store currency'), - 'value' => 0 - ) - ) - ), - array( - 'type' => 'select', - 'label' => $this->l('Zone'), - 'name' => 'id_zone', - 'options' => array( - 'query' => Zone::getZones(), - 'id' => 'id_zone', - 'name' => 'name' - ), - 'hint' => $this->l('Geographical region.') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Does it need Zip/postal code?'), - 'name' => 'need_zip_code', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'need_zip_code_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'need_zip_code_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ) - ), - array( - 'type' => 'text', - 'label' => $this->l('Zip/postal code format'), - 'name' => 'zip_code_format', - 'required' => true, - 'desc' => $this->l('Indicate the format of the postal code: use L for a letter, N for a number, and C for the country\'s ISO 3166-1 alpha-2 code. For example, NNNNN for the United States, France, Poland and many other; LNNNNLLL for Argentina, etc. If you do not want PrestaShop to verify the postal code for this country, leave it blank.') - ), - array( - 'type' => 'address_layout', - 'label' => $this->l('Address format'), - 'name' => 'address_layout', - 'address_layout' => $address_layout, - 'encoding_address_layout' => urlencode($address_layout), - 'encoding_default_layout' => urlencode($default_layout), - 'display_valid_fields' => $this->displayValidFields() - ), - array( - 'type' => 'switch', - 'label' => $this->l('Active'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Display this country to your customers (the selected country will always be displayed in the Back Office).') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Contains states'), - 'name' => 'contains_states', - 'required' => false, - 'values' => array( - array( - 'id' => 'contains_states_on', - 'value' => 1, - 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Yes').'" title="'.$this->l('Yes').'" />'.$this->l('Yes') - ), - array( - 'id' => 'contains_states_off', - 'value' => 0, - 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('No').'" title="'.$this->l('No').'" />'.$this->l('No') - ) - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Do you need a tax identification number?'), - 'name' => 'need_identification_number', - 'required' => false, - 'values' => array( - array( - 'id' => 'need_identification_number_on', - 'value' => 1, - 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Yes').'" title="'.$this->l('Yes').'" />'.$this->l('Yes') - ), - array( - 'id' => 'need_identification_number_off', - 'value' => 0, - 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('No').'" title="'.$this->l('No').'" />'.$this->l('No') - ) - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Display tax label (e.g. "Tax incl.")'), - 'name' => 'display_tax_label', - 'required' => false, - 'values' => array( - array( - 'id' => 'display_tax_label_on', - 'value' => 1, - 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Yes').'" title="'.$this->l('Yes').'" />'.$this->l('Yes') - ), - array( - 'id' => 'display_tax_label_off', - 'value' => 0, - 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('No').'" title="'.$this->l('No').'" />'.$this->l('No') - ) - ) - ) - ) + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Countries'), + 'icon' => 'icon-globe' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Country'), + 'name' => 'name', + 'lang' => true, + 'required' => true, + 'hint' => $this->l('Country name').' - '.$this->l('Invalid characters:').' <>;=#{} ' + ), + array( + 'type' => 'text', + 'label' => $this->l('ISO code'), + 'name' => 'iso_code', + 'maxlength' => 3, + 'class' => 'uppercase', + 'required' => true, + 'hint' => $this->l('Two -- or three -- letter ISO code (e.g. "us for United States).') + /* @TODO - ajouter les liens dans le hint ? */ + /*'desc' => $this->l('Two -- or three -- letter ISO code (e.g. U.S. for United States)').'. + <a href="http://www.iso.org/iso/country_codes/iso_3166_code_lists/country_names_and_code_elements.htm" target="_blank">'. + $this->l('Official list here').' + </a>.'*/ + ), + array( + 'type' => 'text', + 'label' => $this->l('Call prefix'), + 'name' => 'call_prefix', + 'maxlength' => 3, + 'class' => 'uppercase', + 'required' => true, + 'hint' => $this->l('International call prefix, (e.g. 1 for United States).') + ), + array( + 'type' => 'select', + 'label' => $this->l('Default currency'), + 'name' => 'id_currency', + 'options' => array( + 'query' => Currency::getCurrencies(), + 'id' => 'id_currency', + 'name' => 'name', + 'default' => array( + 'label' => $this->l('Default store currency'), + 'value' => 0 + ) + ) + ), + array( + 'type' => 'select', + 'label' => $this->l('Zone'), + 'name' => 'id_zone', + 'options' => array( + 'query' => Zone::getZones(), + 'id' => 'id_zone', + 'name' => 'name' + ), + 'hint' => $this->l('Geographical region.') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Does it need Zip/postal code?'), + 'name' => 'need_zip_code', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'need_zip_code_on', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'need_zip_code_off', + 'value' => 0, + 'label' => $this->l('No') + ) + ) + ), + array( + 'type' => 'text', + 'label' => $this->l('Zip/postal code format'), + 'name' => 'zip_code_format', + 'required' => true, + 'desc' => $this->l('Indicate the format of the postal code: use L for a letter, N for a number, and C for the country\'s ISO 3166-1 alpha-2 code. For example, NNNNN for the United States, France, Poland and many other; LNNNNLLL for Argentina, etc. If you do not want PrestaShop to verify the postal code for this country, leave it blank.') + ), + array( + 'type' => 'address_layout', + 'label' => $this->l('Address format'), + 'name' => 'address_layout', + 'address_layout' => $address_layout, + 'encoding_address_layout' => urlencode($address_layout), + 'encoding_default_layout' => urlencode($default_layout), + 'display_valid_fields' => $this->displayValidFields() + ), + array( + 'type' => 'switch', + 'label' => $this->l('Active'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Display this country to your customers (the selected country will always be displayed in the Back Office).') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Contains states'), + 'name' => 'contains_states', + 'required' => false, + 'values' => array( + array( + 'id' => 'contains_states_on', + 'value' => 1, + 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Yes').'" title="'.$this->l('Yes').'" />'.$this->l('Yes') + ), + array( + 'id' => 'contains_states_off', + 'value' => 0, + 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('No').'" title="'.$this->l('No').'" />'.$this->l('No') + ) + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Do you need a tax identification number?'), + 'name' => 'need_identification_number', + 'required' => false, + 'values' => array( + array( + 'id' => 'need_identification_number_on', + 'value' => 1, + 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Yes').'" title="'.$this->l('Yes').'" />'.$this->l('Yes') + ), + array( + 'id' => 'need_identification_number_off', + 'value' => 0, + 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('No').'" title="'.$this->l('No').'" />'.$this->l('No') + ) + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Display tax label (e.g. "Tax incl.")'), + 'name' => 'display_tax_label', + 'required' => false, + 'values' => array( + array( + 'id' => 'display_tax_label_on', + 'value' => 1, + 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Yes').'" title="'.$this->l('Yes').'" />'.$this->l('Yes') + ), + array( + 'id' => 'display_tax_label_off', + 'value' => 0, + 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('No').'" title="'.$this->l('No').'" />'.$this->l('No') + ) + ) + ) + ) - ); + ); - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - $this->fields_form['submit'] = array( - 'title' => $this->l('Save') - ); + $this->fields_form['submit'] = array( + 'title' => $this->l('Save') + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function processUpdate() - { - /** @var Country $country */ - $country = $this->loadObject(); - if (Validate::isLoadedObject($country) && Tools::getValue('id_zone')) - { - $old_id_zone = $country->id_zone; - $results = Db::getInstance()->executeS('SELECT `id_state` FROM `'._DB_PREFIX_.'state` WHERE `id_country` = '.(int)$country->id.' AND `id_zone` = '.(int)$old_id_zone); + public function processUpdate() + { + /** @var Country $country */ + $country = $this->loadObject(); + if (Validate::isLoadedObject($country) && Tools::getValue('id_zone')) { + $old_id_zone = $country->id_zone; + $results = Db::getInstance()->executeS('SELECT `id_state` FROM `'._DB_PREFIX_.'state` WHERE `id_country` = '.(int)$country->id.' AND `id_zone` = '.(int)$old_id_zone); - if ($results && count($results)) - { - $ids = array(); - foreach ($results as $res) - $ids[] = (int)$res['id_state']; + if ($results && count($results)) { + $ids = array(); + foreach ($results as $res) { + $ids[] = (int)$res['id_state']; + } - if (count($ids)) - $res = Db::getInstance()->execute( - 'UPDATE `'._DB_PREFIX_.'state` + if (count($ids)) { + $res = Db::getInstance()->execute( + 'UPDATE `'._DB_PREFIX_.'state` SET `id_zone` = '.(int)Tools::getValue('id_zone').' WHERE `id_state` IN ('.implode(',', $ids).')'); - } - } - return parent::processUpdate(); - } + } + } + } + return parent::processUpdate(); + } - public function postProcess() - { - if (!Tools::getValue('id_'.$this->table)) - { - if (Validate::isLanguageIsoCode(Tools::getValue('iso_code')) && Country::getByIso(Tools::getValue('iso_code'))) - $this->errors[] = Tools::displayError('This ISO code already exists.You cannot create two countries with the same ISO code.'); - } - elseif (Validate::isLanguageIsoCode(Tools::getValue('iso_code'))) - { - $id_country = Country::getByIso(Tools::getValue('iso_code')); - if (!is_null($id_country) && $id_country != Tools::getValue('id_'.$this->table)) - $this->errors[] = Tools::displayError('This ISO code already exists.You cannot create two countries with the same ISO code.'); - } + public function postProcess() + { + if (!Tools::getValue('id_'.$this->table)) { + if (Validate::isLanguageIsoCode(Tools::getValue('iso_code')) && (int)Country::getByIso(Tools::getValue('iso_code'))) { + $this->errors[] = Tools::displayError('This ISO code already exists.You cannot create two countries with the same ISO code.'); + } + } elseif (Validate::isLanguageIsoCode(Tools::getValue('iso_code'))) { + $id_country = (int)Country::getByIso(Tools::getValue('iso_code')); + if (!is_null($id_country) && $id_country != Tools::getValue('id_'.$this->table)) { + $this->errors[] = Tools::displayError('This ISO code already exists.You cannot create two countries with the same ISO code.'); + } + } - return parent::postProcess(); - } + return parent::postProcess(); + } - public function processSave() - { - if (!$this->id_object) - $tmp_addr_format = new AddressFormat(); - else - $tmp_addr_format = new AddressFormat($this->id_object); + public function processSave() + { + if (!$this->id_object) { + $tmp_addr_format = new AddressFormat(); + } else { + $tmp_addr_format = new AddressFormat($this->id_object); + } - $tmp_addr_format->format = Tools::getValue('address_layout'); + $tmp_addr_format->format = Tools::getValue('address_layout'); - if (!$tmp_addr_format->checkFormatFields()) - { - $error_list = $tmp_addr_format->getErrorList(); - foreach ($error_list as $num_error => $error) - $this->errors[] = $error; - } - if (strlen($tmp_addr_format->format) <= 0) - $this->errors[] = $this->l('Address format invalid'); + if (!$tmp_addr_format->checkFormatFields()) { + $error_list = $tmp_addr_format->getErrorList(); + foreach ($error_list as $num_error => $error) { + $this->errors[] = $error; + } + } + if (strlen($tmp_addr_format->format) <= 0) { + $this->errors[] = $this->l('Address format invalid'); + } - $country = parent::processSave(); + $country = parent::processSave(); - if (!count($this->errors)) - { - if (is_null($tmp_addr_format->id_country)) - $tmp_addr_format->id_country = $country->id; + if (!count($this->errors)) { + if (is_null($tmp_addr_format->id_country)) { + $tmp_addr_format->id_country = $country->id; + } - if (!$tmp_addr_format->save()) - $this->errors[] = Tools::displayError('Invalid address layout '.Db::getInstance()->getMsgError()); - } + if (!$tmp_addr_format->save()) { + $this->errors[] = Tools::displayError('Invalid address layout '.Db::getInstance()->getMsgError()); + } + } - return $country; - } + return $country; + } - public function processStatus() - { - parent::processStatus(); + public function processStatus() + { + parent::processStatus(); - /** @var Country $object */ - if (Validate::isLoadedObject($object = $this->loadObject()) && $object->active == 1) - return Country::addModuleRestrictions(array(), array(array('id_country' => $object->id)), array()); + /** @var Country $object */ + if (Validate::isLoadedObject($object = $this->loadObject()) && $object->active == 1) { + return Country::addModuleRestrictions(array(), array(array('id_country' => $object->id)), array()); + } - return false; - } + return false; + } - public function processBulkStatusSelection($way) - { - if (is_array($this->boxes) && !empty($this->boxes)) - { - $countries_ids = array(); - foreach ($this->boxes as $id) - $countries_ids[] = array('id_country' => $id); + public function processBulkStatusSelection($way) + { + if (is_array($this->boxes) && !empty($this->boxes)) { + $countries_ids = array(); + foreach ($this->boxes as $id) { + $countries_ids[] = array('id_country' => $id); + } - if (count($countries_ids)) - Country::addModuleRestrictions(array(), $countries_ids, array()); - } - parent::processBulkStatusSelection($way); - } + if (count($countries_ids)) { + Country::addModuleRestrictions(array(), $countries_ids, array()); + } + } + parent::processBulkStatusSelection($way); + } - protected function displayValidFields() - { - /* The following translations are needed later - don't remove the comments! - $this->l('Customer'); - $this->l('Warehouse'); - $this->l('Country'); - $this->l('State'); - $this->l('Address'); - */ + protected function displayValidFields() + { + /* The following translations are needed later - don't remove the comments! + $this->l('Customer'); + $this->l('Warehouse'); + $this->l('Country'); + $this->l('State'); + $this->l('Address'); + */ - $html_tabnav = '<ul class="nav nav-tabs" id="custom-address-fields">'; - $html_tabcontent = '<div class="tab-content" >'; + $html_tabnav = '<ul class="nav nav-tabs" id="custom-address-fields">'; + $html_tabcontent = '<div class="tab-content" >'; - $object_list = AddressFormat::getLiableClass('Address'); - $object_list['Address'] = null; + $object_list = AddressFormat::getLiableClass('Address'); + $object_list['Address'] = null; - // Get the available properties for each class - $i = 0; - $class_tab_active = 'active'; - foreach ($object_list as $class_name => &$object) - { - if ($i != 0) - $class_tab_active = ''; - $fields = array(); - $html_tabnav .= '<li'.($class_tab_active ? ' class="'.$class_tab_active.'"' : '').'> + // Get the available properties for each class + $i = 0; + $class_tab_active = 'active'; + foreach ($object_list as $class_name => &$object) { + if ($i != 0) { + $class_tab_active = ''; + } + $fields = array(); + $html_tabnav .= '<li'.($class_tab_active ? ' class="'.$class_tab_active.'"' : '').'> <a href="#availableListFieldsFor_'.$class_name.'"><i class="icon-caret-down"></i> '.Translate::getAdminTranslation($class_name, 'AdminCountries').'</a></li>'; - foreach (AddressFormat::getValidateFields($class_name) as $name) - $fields[] = '<a href="javascript:void(0);" class="addPattern btn btn-default btn-xs" id="'.($class_name == 'Address' ? $name : $class_name.':'.$name).'"> + foreach (AddressFormat::getValidateFields($class_name) as $name) { + $fields[] = '<a href="javascript:void(0);" class="addPattern btn btn-default btn-xs" id="'.($class_name == 'Address' ? $name : $class_name.':'.$name).'"> <i class="icon-plus-sign"></i> '.ObjectModel::displayFieldName($name, $class_name).'</a>'; - $html_tabcontent .= ' + } + $html_tabcontent .= ' <div class="tab-pane availableFieldsList panel '.$class_tab_active.'" id="availableListFieldsFor_'.$class_name.'"> '.implode(' ', $fields).'</div>'; - unset($object); - $i ++; - } - $html_tabnav .= '</ul>'; - $html_tabcontent .= '</div>'; - return $html = $html_tabnav.$html_tabcontent; - } + unset($object); + $i ++; + } + $html_tabnav .= '</ul>'; + $html_tabcontent .= '</div>'; + return $html = $html_tabnav.$html_tabcontent; + } - public static function displayCallPrefix($prefix) - { - return ((int)$prefix ? '+'.$prefix : '-'); - } + public static function displayCallPrefix($prefix) + { + return ((int)$prefix ? '+'.$prefix : '-'); + } } diff --git a/controllers/admin/AdminCurrenciesController.php b/controllers/admin/AdminCurrenciesController.php index 4b8b0b75..3a259f89 100644 --- a/controllers/admin/AdminCurrenciesController.php +++ b/controllers/admin/AdminCurrenciesController.php @@ -29,333 +29,336 @@ */ class AdminCurrenciesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'currency'; - $this->className = 'Currency'; - $this->lang = false; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'currency'; + $this->className = 'Currency'; + $this->lang = false; - $this->fields_list = array( - 'id_currency' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'name' => array('title' => $this->l('Currency')), - 'iso_code' => array('title' => $this->l('ISO code'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'iso_code_num' => array('title' => $this->l('ISO code number'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'sign' => array('title' => $this->l('Symbol'), 'width' => 20, 'align' => 'center', 'orderby' => false, 'search' => false, 'class' => 'fixed-width-xs'), - 'conversion_rate' => array('title' => $this->l('Exchange rate'), 'type' => 'float', 'align' => 'center', 'width' => 130, 'search' => false, 'filter_key' => 'currency_shop!conversion_rate'), - 'active' => array('title' => $this->l('Enabled'), 'width' => 25, 'align' => 'center', 'active' => 'status', 'type' => 'bool', 'orderby' => false, 'class' => 'fixed-width-sm'), - ); + $this->fields_list = array( + 'id_currency' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'name' => array('title' => $this->l('Currency')), + 'iso_code' => array('title' => $this->l('ISO code'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'iso_code_num' => array('title' => $this->l('ISO code number'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'sign' => array('title' => $this->l('Symbol'), 'width' => 20, 'align' => 'center', 'orderby' => false, 'search' => false, 'class' => 'fixed-width-xs'), + 'conversion_rate' => array('title' => $this->l('Exchange rate'), 'type' => 'float', 'align' => 'center', 'width' => 130, 'search' => false, 'filter_key' => 'currency_shop!conversion_rate'), + 'active' => array('title' => $this->l('Enabled'), 'width' => 25, 'align' => 'center', 'active' => 'status', 'type' => 'bool', 'orderby' => false, 'class' => 'fixed-width-sm'), + ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->fields_options = array( - 'change' => array( - 'title' => $this->l('Currency rates'), - 'image' => '../img/admin/exchangesrate.gif', - 'description' => $this->l('Use PrestaShop\'s webservice to update your currency\'s exchange rates. However, please use caution: rates are provided as-is.'), - 'submit' => array( - 'title' => $this->l('Update currency rates'), - 'name' => 'SubmitExchangesRates' - ) - ), - 'cron' => array( - 'title' => $this->l('Automatically update currency rates'), - 'image' => '../img/admin/tab-tools.gif', - 'info' => '<div class="alert alert-block"><p>'.$this->l('Use PrestaShop\'s webservice to update your currency exchange rates. However, please use caution: rates are provided as-is.').'<br/>'.$this->l('You can place the following URL in your crontab file, or you can click it yourself regularly:').'</p> + $this->fields_options = array( + 'change' => array( + 'title' => $this->l('Currency rates'), + 'image' => '../img/admin/exchangesrate.gif', + 'description' => $this->l('Use PrestaShop\'s webservice to update your currency\'s exchange rates. However, please use caution: rates are provided as-is.'), + 'submit' => array( + 'title' => $this->l('Update currency rates'), + 'name' => 'SubmitExchangesRates' + ) + ), + 'cron' => array( + 'title' => $this->l('Automatically update currency rates'), + 'image' => '../img/admin/tab-tools.gif', + 'info' => '<div class="alert alert-block"><p>'.$this->l('Use PrestaShop\'s webservice to update your currency exchange rates. However, please use caution: rates are provided as-is.').'<br/>'.$this->l('You can place the following URL in your crontab file, or you can click it yourself regularly:').'</p> <p><strong><a href="'.Tools::getShopDomain(true, true).__PS_BASE_URI__.basename(_PS_ADMIN_DIR_).'/cron_currency_rates.php?secure_key='.md5(_COOKIE_KEY_.Configuration::get('PS_SHOP_NAME')).'" onclick="return !window.open($(this).attr(\'href\'));">'.Tools::getShopDomain(true, true).__PS_BASE_URI__.basename(_PS_ADMIN_DIR_).'/cron_currency_rates.php?secure_key='.md5(_COOKIE_KEY_.Configuration::get('PS_SHOP_NAME')).'</a></strong></p></div>', - ) - ); + ) + ); - parent::__construct(); + parent::__construct(); - $this->_select .= 'currency_shop.conversion_rate conversion_rate'; - $this->_join .= Shop::addSqlAssociation('currency', 'a'); - $this->_group .= 'GROUP BY a.id_currency'; - } + $this->_select .= 'currency_shop.conversion_rate conversion_rate'; + $this->_join .= Shop::addSqlAssociation('currency', 'a'); + $this->_group .= 'GROUP BY a.id_currency'; + } - public function renderList() - { - $this->addRowAction('edit'); - $this->addRowAction('delete'); + public function renderList() + { + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->_where = 'AND a.`deleted` = 0'; + $this->_where = 'AND a.`deleted` = 0'; - return parent::renderList(); - } + return parent::renderList(); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Currencies'), - 'icon' => 'icon-money' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Currency name'), - 'name' => 'name', - 'size' => 30, - 'maxlength' => 32, - 'required' => true, - 'hint' => $this->l('Only letters and the minus character are allowed.') - ), - array( - 'type' => 'text', - 'label' => $this->l('ISO code'), - 'name' => 'iso_code', - 'maxlength' => 32, - 'required' => true, - 'hint' => $this->l('ISO code (e.g. USD for Dollars, EUR for Euros, etc.).') - ), - array( - 'type' => 'text', - 'label' => $this->l('Numeric ISO code'), - 'name' => 'iso_code_num', - 'maxlength' => 32, - 'required' => true, - 'hint' => $this->l('Numeric ISO code (e.g. 840 for Dollars, 978 for Euros, etc.).') - ), - array( - 'type' => 'text', - 'label' => $this->l('Symbol'), - 'name' => 'sign', - 'maxlength' => 8, - 'required' => true, - 'hint' => $this->l('Will appear in front office (e.g. $, €, etc.)') - ), - array( - 'type' => 'text', - 'label' => $this->l('Exchange rate'), - 'name' => 'conversion_rate', - 'maxlength' => 11, - 'required' => true, - 'hint' => $this->l('Exchange rates are calculated from one unit of your shop\'s default currency. For example, if the default currency is euros and your chosen currency is dollars, type "1.20" (1€ = $1.20).') - ), - array( - 'type' => 'select', - 'label' => $this->l('Currency format'), - 'name' => 'format', - 'maxlength' => 11, - 'required' => true, - 'hint' =>$this->l('Applies to all prices (e.g. $1,240.15).'), - 'options' => array( - 'query' => array( - array('key' => 1, 'name' => 'X0,000.00 ('.$this->l('Such as with Dollars').')'), - array('key' => 2, 'name' => '0 000,00X ('.$this->l('Such as with Euros').')'), - array('key' => 3, 'name' => 'X0.000,00'), - array('key' => 4, 'name' => '0,000.00X'), - array('key' => 5, 'name' => '0\'000.00X') // Added for the switzerland currency - ), - 'name' => 'name', - 'id' => 'key' - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Decimals'), - 'name' => 'decimals', - 'required' => false, - 'is_bool' => true, - 'hint' => $this->l('Display decimals in prices.'), - 'values' => array( - array( - 'id' => 'decimals_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'decimals_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Spacing'), - 'name' => 'blank', - 'required' => false, - 'is_bool' => true, - 'hint' => $this->l('Include a space between symbol and price (e.g. $1,240.15 -> $ 1,240.15).'), - 'values' => array( - array( - 'id' => 'blank_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'blank_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Enable'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ) - ) - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Currencies'), + 'icon' => 'icon-money' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Currency name'), + 'name' => 'name', + 'size' => 30, + 'maxlength' => 32, + 'required' => true, + 'hint' => $this->l('Only letters and the minus character are allowed.') + ), + array( + 'type' => 'text', + 'label' => $this->l('ISO code'), + 'name' => 'iso_code', + 'maxlength' => 32, + 'required' => true, + 'hint' => $this->l('ISO code (e.g. USD for Dollars, EUR for Euros, etc.).') + ), + array( + 'type' => 'text', + 'label' => $this->l('Numeric ISO code'), + 'name' => 'iso_code_num', + 'maxlength' => 32, + 'required' => true, + 'hint' => $this->l('Numeric ISO code (e.g. 840 for Dollars, 978 for Euros, etc.).') + ), + array( + 'type' => 'text', + 'label' => $this->l('Symbol'), + 'name' => 'sign', + 'maxlength' => 8, + 'required' => true, + 'hint' => $this->l('Will appear in front office (e.g. $, €, etc.)') + ), + array( + 'type' => 'text', + 'label' => $this->l('Exchange rate'), + 'name' => 'conversion_rate', + 'maxlength' => 11, + 'required' => true, + 'hint' => $this->l('Exchange rates are calculated from one unit of your shop\'s default currency. For example, if the default currency is euros and your chosen currency is dollars, type "1.20" (1€ = $1.20).') + ), + array( + 'type' => 'select', + 'label' => $this->l('Currency format'), + 'name' => 'format', + 'maxlength' => 11, + 'required' => true, + 'hint' =>$this->l('Applies to all prices (e.g. $1,240.15).'), + 'options' => array( + 'query' => array( + array('key' => 1, 'name' => 'X0,000.00 ('.$this->l('Such as with Dollars').')'), + array('key' => 2, 'name' => '0 000,00X ('.$this->l('Such as with Euros').')'), + array('key' => 3, 'name' => 'X0.000,00'), + array('key' => 4, 'name' => '0,000.00X'), + array('key' => 5, 'name' => '0\'000.00X') // Added for the switzerland currency + ), + 'name' => 'name', + 'id' => 'key' + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Decimals'), + 'name' => 'decimals', + 'required' => false, + 'is_bool' => true, + 'hint' => $this->l('Display decimals in prices.'), + 'values' => array( + array( + 'id' => 'decimals_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'decimals_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + ), + array( + 'type' => 'switch', + 'label' => $this->l('Spacing'), + 'name' => 'blank', + 'required' => false, + 'is_bool' => true, + 'hint' => $this->l('Include a space between symbol and price (e.g. $1,240.15 -> $ 1,240.15).'), + 'values' => array( + array( + 'id' => 'blank_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'blank_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + ), + array( + 'type' => 'switch', + 'label' => $this->l('Enable'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ) + ) + ) + ); - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - $this->fields_form['submit'] = array( - 'title' => $this->l('Save'), - ); + $this->fields_form['submit'] = array( + 'title' => $this->l('Save'), + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - protected function checkDeletion($object) - { - if (Validate::isLoadedObject($object)) - { - if ($object->id == Configuration::get('PS_CURRENCY_DEFAULT')) - $this->errors[] = $this->l('You cannot delete the default currency'); - else - return true; - } - else - $this->errors[] = Tools::displayError('An error occurred while deleting the object.').' + protected function checkDeletion($object) + { + if (Validate::isLoadedObject($object)) { + if ($object->id == Configuration::get('PS_CURRENCY_DEFAULT')) { + $this->errors[] = $this->l('You cannot delete the default currency'); + } else { + return true; + } + } else { + $this->errors[] = Tools::displayError('An error occurred while deleting the object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } - return false; - } + return false; + } - protected function checkDisableStatus($object) - { - if (Validate::isLoadedObject($object)) - { - if ($object->active && $object->id == Configuration::get('PS_CURRENCY_DEFAULT')) - $this->errors[] = $this->l('You cannot disable the default currency'); - else - return true; - } - else - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' + protected function checkDisableStatus($object) + { + if (Validate::isLoadedObject($object)) { + if ($object->active && $object->id == Configuration::get('PS_CURRENCY_DEFAULT')) { + $this->errors[] = $this->l('You cannot disable the default currency'); + } else { + return true; + } + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } - return false; - } + return false; + } - /** - * @see AdminController::processDelete() - */ - public function processDelete() - { - $object = $this->loadObject(); - if (!$this->checkDeletion($object)) - return false; - return parent::processDelete(); - } + /** + * @see AdminController::processDelete() + */ + public function processDelete() + { + $object = $this->loadObject(); + if (!$this->checkDeletion($object)) { + return false; + } + return parent::processDelete(); + } - protected function processBulkDelete() - { - if (is_array($this->boxes) && !empty($this->boxes)) - { - foreach ($this->boxes as $id_currency) - { - $object = new Currency((int)$id_currency); - if (!$this->checkDeletion($object)) - return false; - } - } + protected function processBulkDelete() + { + if (is_array($this->boxes) && !empty($this->boxes)) { + foreach ($this->boxes as $id_currency) { + $object = new Currency((int)$id_currency); + if (!$this->checkDeletion($object)) { + return false; + } + } + } - return parent::processBulkDelete(); - } + return parent::processBulkDelete(); + } - /** - * @see AdminController::processStatus() - */ - public function processStatus() - { - $object = $this->loadObject(); - if (!$this->checkDisableStatus($object)) - return false; + /** + * @see AdminController::processStatus() + */ + public function processStatus() + { + $object = $this->loadObject(); + if (!$this->checkDisableStatus($object)) { + return false; + } - return parent::processStatus(); - } + return parent::processStatus(); + } - protected function processBulkDisableSelection() - { - if (is_array($this->boxes) && !empty($this->boxes)) - { - foreach ($this->boxes as $id_currency) - { - $object = new Currency((int)$id_currency); - if (!$this->checkDisableStatus($object)) - return false; - } - } - return parent::processBulkDisableSelection(); - } + protected function processBulkDisableSelection() + { + if (is_array($this->boxes) && !empty($this->boxes)) { + foreach ($this->boxes as $id_currency) { + $object = new Currency((int)$id_currency); + if (!$this->checkDisableStatus($object)) { + return false; + } + } + } + return parent::processBulkDisableSelection(); + } - /** - * Update currency exchange rates - */ - public function processExchangeRates() - { - if (!$this->errors = Currency::refreshCurrencies()) - Tools::redirectAdmin(self::$currentIndex.'&conf=6&token='.$this->token); - } + /** + * Update currency exchange rates + */ + public function processExchangeRates() + { + if (!$this->errors = Currency::refreshCurrencies()) { + Tools::redirectAdmin(self::$currentIndex.'&conf=6&token='.$this->token); + } + } - /** - * @see AdminController::initProcess() - */ - public function initProcess() - { - if (Tools::isSubmit('SubmitExchangesRates')) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'exchangeRates'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - if (Tools::isSubmit('submitAddcurrency') && !Tools::getValue('id_currency') && Currency::exists(Tools::getValue('iso_code'), Tools::getValue('iso_code_num'))) - $this->errors[] = Tools::displayError('This currency already exists.'); - if (Tools::isSubmit('submitAddcurrency') && (float)Tools::getValue('conversion_rate') <= 0) - $this->errors[] = Tools::displayError('The currency conversion rate can not be equal to 0.'); - parent::initProcess(); - } + /** + * @see AdminController::initProcess() + */ + public function initProcess() + { + if (Tools::isSubmit('SubmitExchangesRates')) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'exchangeRates'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + if (Tools::isSubmit('submitAddcurrency') && !Tools::getValue('id_currency') && Currency::exists(Tools::getValue('iso_code'), Tools::getValue('iso_code_num'))) { + $this->errors[] = Tools::displayError('This currency already exists.'); + } + if (Tools::isSubmit('submitAddcurrency') && (float)Tools::getValue('conversion_rate') <= 0) { + $this->errors[] = Tools::displayError('The currency conversion rate can not be equal to 0.'); + } + parent::initProcess(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_currency'] = array( - 'href' => self::$currentIndex.'&addcurrency&token='.$this->token, - 'desc' => $this->l('Add new currency', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_currency'] = array( + 'href' => self::$currentIndex.'&addcurrency&token='.$this->token, + 'desc' => $this->l('Add new currency', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } -} \ No newline at end of file + parent::initPageHeaderToolbar(); + } +} diff --git a/controllers/admin/AdminCustomerPreferencesController.php b/controllers/admin/AdminCustomerPreferencesController.php index 90071adc..d490a647 100644 --- a/controllers/admin/AdminCustomerPreferencesController.php +++ b/controllers/admin/AdminCustomerPreferencesController.php @@ -29,117 +29,114 @@ */ class AdminCustomerPreferencesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->className = 'Configuration'; - $this->table = 'configuration'; + public function __construct() + { + $this->bootstrap = true; + $this->className = 'Configuration'; + $this->table = 'configuration'; - parent::__construct(); + parent::__construct(); - $registration_process_type = array( - array( - 'value' => PS_REGISTRATION_PROCESS_STANDARD, - 'name' => $this->l('Only account creation') - ), - array( - 'value' => PS_REGISTRATION_PROCESS_AIO, - 'name' => $this->l('Standard (account creation and address creation)') - ) - ); + $registration_process_type = array( + array( + 'value' => PS_REGISTRATION_PROCESS_STANDARD, + 'name' => $this->l('Only account creation') + ), + array( + 'value' => PS_REGISTRATION_PROCESS_AIO, + 'name' => $this->l('Standard (account creation and address creation)') + ) + ); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('General'), - 'icon' => 'icon-cogs', - 'fields' => array( - 'PS_REGISTRATION_PROCESS_TYPE' => array( - 'title' => $this->l('Registration process type'), - 'hint' => $this->l('The "Only account creation" registration option allows the customer to register faster, and create his/her address later.'), - 'validation' => 'isInt', - 'cast' => 'intval', - 'type' => 'select', - 'list' => $registration_process_type, - 'identifier' => 'value' - ), - 'PS_ONE_PHONE_AT_LEAST' => array( - 'title' => $this->l('Phone number is mandatory'), - 'hint' => $this->l('If you chose yes, your customer will have to provide at least one phone number to register.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_CART_FOLLOWING' => array( - 'title' => $this->l('Re-display cart at login'), - 'hint' => $this->l('After a customer logs in, you can recall and display the content of his/her last shopping cart.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_CUSTOMER_CREATION_EMAIL' => array( - 'title' => $this->l('Send an email after registration'), - 'hint' => $this->l('Send an email with summary of the account information (email, password) after registration.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_PASSWD_TIME_FRONT' => array( - 'title' => $this->l('Password reset delay'), - 'hint' => $this->l('Minimum time required between two requests for a password reset.'), - 'validation' => 'isUnsignedInt', - 'cast' => 'intval', - 'size' => 5, - 'type' => 'text', - 'suffix' => $this->l('minutes') - ), - 'PS_B2B_ENABLE' => array( - 'title' => $this->l('Enable B2B mode'), - 'hint' => $this->l('Activate or deactivate B2B mode. When this option is enabled, B2B features will be made available.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_CUSTOMER_NWSL' => array( - 'title' => $this->l('Enable newsletter registration'), - 'hint' => $this->l('Display or not the newsletter registration tick box.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_CUSTOMER_OPTIN' => array( - 'title' => $this->l('Enable opt-in'), - 'hint' => $this->l('Display or not the opt-in tick box, to receive offers from the store\'s partners.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - ), - 'submit' => array('title' => $this->l('Save')), - ), - ); - } + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('General'), + 'icon' => 'icon-cogs', + 'fields' => array( + 'PS_REGISTRATION_PROCESS_TYPE' => array( + 'title' => $this->l('Registration process type'), + 'hint' => $this->l('The "Only account creation" registration option allows the customer to register faster, and create his/her address later.'), + 'validation' => 'isInt', + 'cast' => 'intval', + 'type' => 'select', + 'list' => $registration_process_type, + 'identifier' => 'value' + ), + 'PS_ONE_PHONE_AT_LEAST' => array( + 'title' => $this->l('Phone number is mandatory'), + 'hint' => $this->l('If you chose yes, your customer will have to provide at least one phone number to register.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_CART_FOLLOWING' => array( + 'title' => $this->l('Re-display cart at login'), + 'hint' => $this->l('After a customer logs in, you can recall and display the content of his/her last shopping cart.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_CUSTOMER_CREATION_EMAIL' => array( + 'title' => $this->l('Send an email after registration'), + 'hint' => $this->l('Send an email with summary of the account information (email, password) after registration.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_PASSWD_TIME_FRONT' => array( + 'title' => $this->l('Password reset delay'), + 'hint' => $this->l('Minimum time required between two requests for a password reset.'), + 'validation' => 'isUnsignedInt', + 'cast' => 'intval', + 'size' => 5, + 'type' => 'text', + 'suffix' => $this->l('minutes') + ), + 'PS_B2B_ENABLE' => array( + 'title' => $this->l('Enable B2B mode'), + 'hint' => $this->l('Activate or deactivate B2B mode. When this option is enabled, B2B features will be made available.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_CUSTOMER_NWSL' => array( + 'title' => $this->l('Enable newsletter registration'), + 'hint' => $this->l('Display or not the newsletter registration tick box.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_CUSTOMER_OPTIN' => array( + 'title' => $this->l('Enable opt-in'), + 'hint' => $this->l('Display or not the opt-in tick box, to receive offers from the store\'s partners.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + ), + 'submit' => array('title' => $this->l('Save')), + ), + ); + } - /** - * Update PS_B2B_ENABLE and enables / disables the associated tabs - * @param $value integer Value of option - */ - public function updateOptionPsB2bEnable($value) - { - $value = (int)$value; + /** + * Update PS_B2B_ENABLE and enables / disables the associated tabs + * @param $value integer Value of option + */ + public function updateOptionPsB2bEnable($value) + { + $value = (int)$value; - $tabs_class_name = array('AdminOutstanding'); - if (!empty($tabs_class_name)) - { - foreach ($tabs_class_name as $tab_class_name) - { - $tab = Tab::getInstanceFromClassName($tab_class_name); - if (Validate::isLoadedObject($tab)) - { - $tab->active = $value; - $tab->save(); - } - } - } - Configuration::updateValue('PS_B2B_ENABLE', $value); - } + $tabs_class_name = array('AdminOutstanding'); + if (!empty($tabs_class_name)) { + foreach ($tabs_class_name as $tab_class_name) { + $tab = Tab::getInstanceFromClassName($tab_class_name); + if (Validate::isLoadedObject($tab)) { + $tab->active = $value; + $tab->save(); + } + } + } + Configuration::updateValue('PS_B2B_ENABLE', $value); + } } diff --git a/controllers/admin/AdminCustomerThreadsController.php b/controllers/admin/AdminCustomerThreadsController.php index e391db2c..f39f5dc0 100644 --- a/controllers/admin/AdminCustomerThreadsController.php +++ b/controllers/admin/AdminCustomerThreadsController.php @@ -29,201 +29,204 @@ */ class AdminCustomerThreadsControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->context = Context::getContext(); - $this->table = 'customer_thread'; - $this->className = 'CustomerThread'; - $this->lang = false; + public function __construct() + { + $this->bootstrap = true; + $this->context = Context::getContext(); + $this->table = 'customer_thread'; + $this->className = 'CustomerThread'; + $this->lang = false; - $contact_array = array(); - $contacts = Contact::getContacts($this->context->language->id); + $contact_array = array(); + $contacts = Contact::getContacts($this->context->language->id); - foreach ($contacts as $contact) - $contact_array[$contact['id_contact']] = $contact['name']; + foreach ($contacts as $contact) { + $contact_array[$contact['id_contact']] = $contact['name']; + } - $language_array = array(); - $languages = Language::getLanguages(); - foreach ($languages as $language) - $language_array[$language['id_lang']] = $language['name']; + $language_array = array(); + $languages = Language::getLanguages(); + foreach ($languages as $language) { + $language_array[$language['id_lang']] = $language['name']; + } - $icon_array = array( - 'open' => array('class' => 'icon-circle text-success', 'alt' => $this->l('Open')), - 'closed' => array('class' => 'icon-circle text-danger', 'alt' => $this->l('Closed')), - 'pending1' => array('class' => 'icon-circle text-warning', 'alt' => $this->l('Pending 1')), - 'pending2' => array('class' => 'icon-circle text-warning', 'alt' => $this->l('Pending 2')), - ); + $icon_array = array( + 'open' => array('class' => 'icon-circle text-success', 'alt' => $this->l('Open')), + 'closed' => array('class' => 'icon-circle text-danger', 'alt' => $this->l('Closed')), + 'pending1' => array('class' => 'icon-circle text-warning', 'alt' => $this->l('Pending 1')), + 'pending2' => array('class' => 'icon-circle text-warning', 'alt' => $this->l('Pending 2')), + ); - $status_array = array(); - foreach ($icon_array as $k => $v) - $status_array[$k] = $v['alt']; + $status_array = array(); + foreach ($icon_array as $k => $v) { + $status_array[$k] = $v['alt']; + } - $this->fields_list = array( - 'id_customer_thread' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'customer' => array( - 'title' => $this->l('Customer'), - 'filter_key' => 'customer', - 'tmpTableFilter' => true, - ), - 'email' => array( - 'title' => $this->l('Email'), - 'filter_key' => 'a!email', - ), - 'contact' => array( - 'title' => $this->l('Type'), - 'type' => 'select', - 'list' => $contact_array, - 'filter_key' => 'cl!id_contact', - 'filter_type' => 'int', - ), - 'language' => array( - 'title' => $this->l('Language'), - 'type' => 'select', - 'list' => $language_array, - 'filter_key' => 'l!id_lang', - 'filter_type' => 'int', - ), - 'status' => array( - 'title' => $this->l('Status'), - 'type' => 'select', - 'list' => $status_array, - 'icon' => $icon_array, - 'align' => 'center', - 'filter_key' => 'a!status', - 'filter_type' => 'string', - ), - 'employee' => array( - 'title' => $this->l('Employee'), - 'filter_key' => 'employee', - 'tmpTableFilter' => true, - ), - 'messages' => array( - 'title' => $this->l('Messages'), - 'filter_key' => 'messages', - 'tmpTableFilter' => true, - 'maxlength' => 40, - ), - 'date_upd' => array( - 'title' => $this->l('Last message'), - 'havingFilter' => true, - 'type' => 'datetime', - ), - ); + $this->fields_list = array( + 'id_customer_thread' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'customer' => array( + 'title' => $this->l('Customer'), + 'filter_key' => 'customer', + 'tmpTableFilter' => true, + ), + 'email' => array( + 'title' => $this->l('Email'), + 'filter_key' => 'a!email', + ), + 'contact' => array( + 'title' => $this->l('Type'), + 'type' => 'select', + 'list' => $contact_array, + 'filter_key' => 'cl!id_contact', + 'filter_type' => 'int', + ), + 'language' => array( + 'title' => $this->l('Language'), + 'type' => 'select', + 'list' => $language_array, + 'filter_key' => 'l!id_lang', + 'filter_type' => 'int', + ), + 'status' => array( + 'title' => $this->l('Status'), + 'type' => 'select', + 'list' => $status_array, + 'icon' => $icon_array, + 'align' => 'center', + 'filter_key' => 'a!status', + 'filter_type' => 'string', + ), + 'employee' => array( + 'title' => $this->l('Employee'), + 'filter_key' => 'employee', + 'tmpTableFilter' => true, + ), + 'messages' => array( + 'title' => $this->l('Messages'), + 'filter_key' => 'messages', + 'tmpTableFilter' => true, + 'maxlength' => 40, + ), + 'date_upd' => array( + 'title' => $this->l('Last message'), + 'havingFilter' => true, + 'type' => 'datetime', + ), + ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ), - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ), + ); - $this->shopLinkType = 'shop'; + $this->shopLinkType = 'shop'; - $this->fields_options = array( - 'contact' => array( - 'title' => $this->l('Contact options'), - 'fields' => array( - 'PS_CUSTOMER_SERVICE_FILE_UPLOAD' => array( - 'title' => $this->l('Allow file uploading'), - 'hint' => $this->l('Allow customers to upload files using the contact page.'), - 'type' => 'bool' - ), - 'PS_CUSTOMER_SERVICE_SIGNATURE' => array( - 'title' => $this->l('Default message'), - 'hint' => $this->l('Please fill out the message fields that appear by default when you answer a thread on the customer service page.'), - 'type' => 'textareaLang', - 'lang' => true - ) - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'general' => array( - 'title' => $this->l('Customer service options'), - 'fields' => array( - 'PS_SAV_IMAP_URL' => array( - 'title' => $this->l('IMAP URL'), - 'hint' => $this->l('URL for your IMAP server (ie.: mail.server.com).'), - 'type' => 'text' - ), - 'PS_SAV_IMAP_PORT' => array( - 'title' => $this->l('IMAP port'), - 'hint' => $this->l('Port to use to connect to your IMAP server.'), - 'type' => 'text', - 'defaultValue' => 143, - ), - 'PS_SAV_IMAP_USER' => array( - 'title' => $this->l('IMAP user'), - 'hint' => $this->l('User to use to connect to your IMAP server.'), - 'type' => 'text' - ), - 'PS_SAV_IMAP_PWD' => array( - 'title' => $this->l('IMAP password'), - 'hint' => $this->l('Password to use to connect your IMAP server.'), - 'type' => 'text' - ), - 'PS_SAV_IMAP_DELETE_MSG' => array( - 'title' => $this->l('Delete messages'), - 'hint' => $this->l('Delete messages after synchronization. If you do not enable this option, the synchronization will take more time.'), - 'type' => 'bool', - ), - 'PS_SAV_IMAP_CREATE_THREADS' => array( - 'title' => $this->l('Create new threads'), - 'hint' => $this->l('Create new threads for unrecognized emails.'), - 'type' => 'bool', - ), - 'PS_SAV_IMAP_OPT_NORSH' => array( - 'title' => $this->l('IMAP options').' (/norsh)', - 'type' => 'bool', - 'hint' => $this->l('Do not use RSH or SSH to establish a preauthenticated IMAP sessions.'), - ), - 'PS_SAV_IMAP_OPT_SSL' => array( - 'title' => $this->l('IMAP options').' (/ssl)', - 'type' => 'bool', - 'hint' => $this->l('Use the Secure Socket Layer (TLS/SSL) to encrypt the session.'), - ), - 'PS_SAV_IMAP_OPT_VALIDATE-CERT' => array( - 'title' => $this->l('IMAP options').' (/validate-cert)', - 'type' => 'bool', - 'hint' => $this->l('Validate certificates from the TLS/SSL server.'), - ), - 'PS_SAV_IMAP_OPT_NOVALIDATE-CERT' => array( - 'title' => $this->l('IMAP options').' (/novalidate-cert)', - 'type' => 'bool', - 'hint' => $this->l('Do not validate certificates from the TLS/SSL server. This is only needed if a server uses self-signed certificates.'), - ), - 'PS_SAV_IMAP_OPT_TLS' => array( - 'title' => $this->l('IMAP options').' (/tls)', - 'type' => 'bool', - 'hint' => $this->l('Force use of start-TLS to encrypt the session, and reject connection to servers that do not support it.'), - ), - 'PS_SAV_IMAP_OPT_NOTLS' => array( - 'title' => $this->l('IMAP options').' (/notls)', - 'type' => 'bool', - 'hint' => $this->l('Do not use start-TLS to encrypt the session, even with servers that support it.'), - ), - ), - 'submit' => array('title' => $this->l('Save')), - ), - ); + $this->fields_options = array( + 'contact' => array( + 'title' => $this->l('Contact options'), + 'fields' => array( + 'PS_CUSTOMER_SERVICE_FILE_UPLOAD' => array( + 'title' => $this->l('Allow file uploading'), + 'hint' => $this->l('Allow customers to upload files using the contact page.'), + 'type' => 'bool' + ), + 'PS_CUSTOMER_SERVICE_SIGNATURE' => array( + 'title' => $this->l('Default message'), + 'hint' => $this->l('Please fill out the message fields that appear by default when you answer a thread on the customer service page.'), + 'type' => 'textareaLang', + 'lang' => true + ) + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'general' => array( + 'title' => $this->l('Customer service options'), + 'fields' => array( + 'PS_SAV_IMAP_URL' => array( + 'title' => $this->l('IMAP URL'), + 'hint' => $this->l('URL for your IMAP server (ie.: mail.server.com).'), + 'type' => 'text' + ), + 'PS_SAV_IMAP_PORT' => array( + 'title' => $this->l('IMAP port'), + 'hint' => $this->l('Port to use to connect to your IMAP server.'), + 'type' => 'text', + 'defaultValue' => 143, + ), + 'PS_SAV_IMAP_USER' => array( + 'title' => $this->l('IMAP user'), + 'hint' => $this->l('User to use to connect to your IMAP server.'), + 'type' => 'text' + ), + 'PS_SAV_IMAP_PWD' => array( + 'title' => $this->l('IMAP password'), + 'hint' => $this->l('Password to use to connect your IMAP server.'), + 'type' => 'text' + ), + 'PS_SAV_IMAP_DELETE_MSG' => array( + 'title' => $this->l('Delete messages'), + 'hint' => $this->l('Delete messages after synchronization. If you do not enable this option, the synchronization will take more time.'), + 'type' => 'bool', + ), + 'PS_SAV_IMAP_CREATE_THREADS' => array( + 'title' => $this->l('Create new threads'), + 'hint' => $this->l('Create new threads for unrecognized emails.'), + 'type' => 'bool', + ), + 'PS_SAV_IMAP_OPT_NORSH' => array( + 'title' => $this->l('IMAP options').' (/norsh)', + 'type' => 'bool', + 'hint' => $this->l('Do not use RSH or SSH to establish a preauthenticated IMAP sessions.'), + ), + 'PS_SAV_IMAP_OPT_SSL' => array( + 'title' => $this->l('IMAP options').' (/ssl)', + 'type' => 'bool', + 'hint' => $this->l('Use the Secure Socket Layer (TLS/SSL) to encrypt the session.'), + ), + 'PS_SAV_IMAP_OPT_VALIDATE-CERT' => array( + 'title' => $this->l('IMAP options').' (/validate-cert)', + 'type' => 'bool', + 'hint' => $this->l('Validate certificates from the TLS/SSL server.'), + ), + 'PS_SAV_IMAP_OPT_NOVALIDATE-CERT' => array( + 'title' => $this->l('IMAP options').' (/novalidate-cert)', + 'type' => 'bool', + 'hint' => $this->l('Do not validate certificates from the TLS/SSL server. This is only needed if a server uses self-signed certificates.'), + ), + 'PS_SAV_IMAP_OPT_TLS' => array( + 'title' => $this->l('IMAP options').' (/tls)', + 'type' => 'bool', + 'hint' => $this->l('Force use of start-TLS to encrypt the session, and reject connection to servers that do not support it.'), + ), + 'PS_SAV_IMAP_OPT_NOTLS' => array( + 'title' => $this->l('IMAP options').' (/notls)', + 'type' => 'bool', + 'hint' => $this->l('Do not use start-TLS to encrypt the session, even with servers that support it.'), + ), + ), + 'submit' => array('title' => $this->l('Save')), + ), + ); - parent::__construct(); - } + parent::__construct(); + } - public function renderList() - { - // Check the new IMAP messages before rendering the list - $this->renderProcessSyncImap(); + public function renderList() + { + // Check the new IMAP messages before rendering the list + $this->renderProcessSyncImap(); - $this->addRowAction('view'); - $this->addRowAction('delete'); + $this->addRowAction('view'); + $this->addRowAction('delete'); - $this->_select = ' + $this->_select = ' CONCAT(c.`firstname`," ",c.`lastname`) as customer, cl.`name` as contact, l.`name` as language, group_concat(message) as messages, ( SELECT IFNULL(CONCAT(LEFT(e.`firstname`, 1),". ",e.`lastname`), "--") @@ -235,7 +238,7 @@ class AdminCustomerThreadsControllerCore extends AdminController ORDER BY cm2.`date_add` DESC LIMIT 1 ) as employee'; - $this->_join = ' + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'customer` c ON c.`id_customer` = a.`id_customer` LEFT JOIN `'._DB_PREFIX_.'customer_message` cm @@ -245,63 +248,62 @@ class AdminCustomerThreadsControllerCore extends AdminController LEFT JOIN `'._DB_PREFIX_.'contact_lang` cl ON (cl.`id_contact` = a.`id_contact` AND cl.`id_lang` = '.(int)$this->context->language->id.')'; - if ($id_order = Tools::getValue('id_order')) - $this->_where .= ' AND id_order = '.(int)$id_order; + if ($id_order = Tools::getValue('id_order')) { + $this->_where .= ' AND id_order = '.(int)$id_order; + } - $this->_group = 'GROUP BY cm.id_customer_thread'; - $this->_orderBy = 'id_customer_thread'; - $this->_orderWay = 'DESC'; + $this->_group = 'GROUP BY cm.id_customer_thread'; + $this->_orderBy = 'id_customer_thread'; + $this->_orderWay = 'DESC'; - $contacts = CustomerThread::getContacts(); + $contacts = CustomerThread::getContacts(); - $categories = Contact::getCategoriesContacts(); + $categories = Contact::getCategoriesContacts(); - $params = array( - $this->l('Total threads') => $all = CustomerThread::getTotalCustomerThreads(), - $this->l('Threads pending') => $pending = CustomerThread::getTotalCustomerThreads('status LIKE "%pending%"'), - $this->l('Total number of customer messages') => CustomerMessage::getTotalCustomerMessages('id_employee = 0'), - $this->l('Total number of employee messages') => CustomerMessage::getTotalCustomerMessages('id_employee != 0'), - $this->l('Unread threads') => $unread = CustomerThread::getTotalCustomerThreads('status = "open"'), - $this->l('Closed threads') => $all - ($unread + $pending) - ); + $params = array( + $this->l('Total threads') => $all = CustomerThread::getTotalCustomerThreads(), + $this->l('Threads pending') => $pending = CustomerThread::getTotalCustomerThreads('status LIKE "%pending%"'), + $this->l('Total number of customer messages') => CustomerMessage::getTotalCustomerMessages('id_employee = 0'), + $this->l('Total number of employee messages') => CustomerMessage::getTotalCustomerMessages('id_employee != 0'), + $this->l('Unread threads') => $unread = CustomerThread::getTotalCustomerThreads('status = "open"'), + $this->l('Closed threads') => $all - ($unread + $pending) + ); - $this->tpl_list_vars = array( - 'contacts' => $contacts, - 'categories' => $categories, - 'params' => $params - ); + $this->tpl_list_vars = array( + 'contacts' => $contacts, + 'categories' => $categories, + 'params' => $params + ); - return parent::renderList(); - } + return parent::renderList(); + } - public function initToolbar() - { - parent::initToolbar(); - unset($this->toolbar_btn['new']); - } + public function initToolbar() + { + parent::initToolbar(); + unset($this->toolbar_btn['new']); + } - public function postProcess() - { - if ($id_customer_thread = (int)Tools::getValue('id_customer_thread')) - { - if (($id_contact = (int)Tools::getValue('id_contact'))) - Db::getInstance()->execute(' + public function postProcess() + { + if ($id_customer_thread = (int)Tools::getValue('id_customer_thread')) { + if (($id_contact = (int)Tools::getValue('id_contact'))) { + Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'customer_thread SET id_contact = '.(int)$id_contact.' WHERE id_customer_thread = '.(int)$id_customer_thread - ); - if ($id_status = (int)Tools::getValue('setstatus')) - { - $status_array = array(1 => 'open', 2 => 'closed', 3 => 'pending1', 4 => 'pending2'); - Db::getInstance()->execute(' + ); + } + if ($id_status = (int)Tools::getValue('setstatus')) { + $status_array = array(1 => 'open', 2 => 'closed', 3 => 'pending1', 4 => 'pending2'); + Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'customer_thread SET status = "'.$status_array[$id_status].'" WHERE id_customer_thread = '.(int)$id_customer_thread.' LIMIT 1 '); - } - if (isset($_POST['id_employee_forward'])) - { - $messages = Db::getInstance()->getRow(' + } + if (isset($_POST['id_employee_forward'])) { + $messages = Db::getInstance()->getRow(' SELECT ct.*, cm.*, cl.name subject, CONCAT(e.firstname, \' \', e.lastname) employee_name, CONCAT(c.firstname, \' \', c.lastname) customer_name, c.firstname FROM '._DB_PREFIX_.'customer_thread ct @@ -316,732 +318,766 @@ class AdminCustomerThreadsControllerCore extends AdminController WHERE ct.id_customer_thread = '.(int)Tools::getValue('id_customer_thread').' ORDER BY cm.date_add DESC '); - $output = $this->displayMessage($messages, true, (int)Tools::getValue('id_employee_forward')); - $cm = new CustomerMessage(); - $cm->id_employee = (int)$this->context->employee->id; - $cm->id_customer_thread = (int)Tools::getValue('id_customer_thread'); - $cm->ip_address = (int)ip2long(Tools::getRemoteAddr()); - $current_employee = $this->context->employee; - $id_employee = (int)Tools::getValue('id_employee_forward'); - $employee = new Employee($id_employee); - $email = Tools::getValue('email'); - $message = Tools::getValue('message_forward'); - if (($error = $cm->validateField('message', $message, null, array(), true)) !== true) - $this->errors[] = $error; - elseif ($id_employee && $employee && Validate::isLoadedObject($employee)) - { - $params = array( - '{messages}' => stripslashes($output), - '{employee}' => $current_employee->firstname.' '.$current_employee->lastname, - '{comment}' => stripslashes(Tools::nl2br($_POST['message_forward'])), - '{firstname}' => $employee->firstname, - '{lastname}' => $employee->lastname, - ); - - if (Mail::Send( - $this->context->language->id, - 'forward_msg', - Mail::l('Fwd: Customer message', $this->context->language->id), - $params, - $employee->email, - $employee->firstname.' '.$employee->lastname, - $current_employee->email, - $current_employee->firstname.' '.$current_employee->lastname, - null, null, _PS_MAIL_DIR_, true)) - { - $cm->private = 1; - $cm->message = $this->l('Message forwarded to').' '.$employee->firstname.' '.$employee->lastname."\n".$this->l('Comment:').' '.$message; - $cm->add(); - } - } - elseif ($email && Validate::isEmail($email)) - { - $params = array( - '{messages}' => Tools::nl2br(stripslashes($output)), - '{employee}' => $current_employee->firstname.' '.$current_employee->lastname, - '{comment}' => stripslashes($_POST['message_forward']) - ); - - if (Mail::Send( - $this->context->language->id, - 'forward_msg', - Mail::l('Fwd: Customer message', $this->context->language->id), - $params, $email, null, - $current_employee->email, $current_employee->firstname.' '.$current_employee->lastname, - null, null, _PS_MAIL_DIR_, true)) - { - $cm->message = $this->l('Message forwarded to').' '.$email."\n".$this->l('Comment:').' '.$message; - $cm->add(); - } - } - else - $this->errors[] = '<div class="alert error">'.Tools::displayError('The email address is invalid.').'</div>'; - } - if (Tools::isSubmit('submitReply')) - { - $ct = new CustomerThread($id_customer_thread); - - ShopUrl::cacheMainDomainForShop((int)$ct->id_shop); - - $cm = new CustomerMessage(); - $cm->id_employee = (int)$this->context->employee->id; - $cm->id_customer_thread = $ct->id; - $cm->ip_address = (int)ip2long(Tools::getRemoteAddr()); - $cm->message = Tools::getValue('reply_message'); - if (($error = $cm->validateField('message', $cm->message, null, array(), true)) !== true) - $this->errors[] = $error; - elseif (isset($_FILES) && !empty($_FILES['joinFile']['name']) && $_FILES['joinFile']['error'] != 0) - $this->errors[] = Tools::displayError('An error occurred during the file upload process.'); - elseif ($cm->add()) - { - $file_attachment = null; - if (!empty($_FILES['joinFile']['name'])) - { - $file_attachment['content'] = file_get_contents($_FILES['joinFile']['tmp_name']); - $file_attachment['name'] = $_FILES['joinFile']['name']; - $file_attachment['mime'] = $_FILES['joinFile']['type']; - } - $customer = new Customer($ct->id_customer); - $params = array( - '{reply}' => Tools::nl2br(Tools::getValue('reply_message')), - '{link}' => Tools::url( - $this->context->link->getPageLink('contact', true), - 'id_customer_thread='.(int)$ct->id.'&token='.$ct->token - ), - '{firstname}' => $customer->firstname, - '{lastname}' => $customer->lastname - ); - //#ct == id_customer_thread #tc == token of thread <== used in the synchronization imap - $contact = new Contact((int)$ct->id_contact, (int)$ct->id_lang); - - if (Validate::isLoadedObject($contact)) - { - $from_name = $contact->name; - $from_email = $contact->email; - } - else - { - $from_name = null; - $from_email = null; - } - - if (Mail::Send( - (int)$ct->id_lang, - 'reply_msg', - sprintf(Mail::l('An answer to your message is available #ct%1$s #tc%2$s', $ct->id_lang), $ct->id, $ct->token), - $params, Tools::getValue('msg_email'), null, $from_email, $from_name, $file_attachment, null, - _PS_MAIL_DIR_, true)) - { - $ct->status = 'closed'; - $ct->update(); - } - Tools::redirectAdmin( - self::$currentIndex.'&id_customer_thread='.(int)$id_customer_thread.'&viewcustomer_thread&token='.Tools::getValue('token') - ); - } - else - $this->errors[] = Tools::displayError('An error occurred. Your message was not sent. Please contact your system administrator.'); - } - } - - return parent::postProcess(); - } - - public function initContent() - { - if (isset($_GET['filename']) && file_exists(_PS_UPLOAD_DIR_.$_GET['filename']) && Validate::isFileName($_GET['filename'])) - AdminCustomerThreadsController::openUploadedFile(); - - return parent::initContent(); - } - - protected function openUploadedFile() - { - $filename = $_GET['filename']; - - $extensions = array( - '.txt' => 'text/plain', - '.rtf' => 'application/rtf', - '.doc' => 'application/msword', - '.docx'=> 'application/msword', - '.pdf' => 'application/pdf', - '.zip' => 'multipart/x-zip', - '.png' => 'image/png', - '.jpeg' => 'image/jpeg', - '.gif' => 'image/gif', - '.jpg' => 'image/jpeg', - ); - - $extension = false; - foreach ($extensions as $key => $val) - if (substr(Tools::strtolower($filename), -4) == $key || substr(Tools::strtolower($filename), -5) == $key) - { - $extension = $val; - break; - } - - if (!$extension || !Validate::isFileName($filename)) - die(Tools::displayError()); - - if (ob_get_level() && ob_get_length() > 0) - ob_end_clean(); - header('Content-Type: '.$extension); - header('Content-Disposition:attachment;filename="'.$filename.'"'); - readfile(_PS_UPLOAD_DIR_.$filename); - die; - } - - public function renderKpis() - { - $time = time(); - $kpis = array(); - - /* The data generation is located in AdminStatsControllerCore */ - - $helper = new HelperKpi(); - $helper->id = 'box-pending-messages'; - $helper->icon = 'icon-envelope'; - $helper->color = 'color1'; - $helper->href = $this->context->link->getAdminLink('AdminCustomerThreads'); - $helper->title = $this->l('Pending Discussion Threads', null, null, false); - if (ConfigurationKPI::get('PENDING_MESSAGES') !== false) - $helper->value = ConfigurationKPI::get('PENDING_MESSAGES'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=pending_messages'; - $helper->refresh = (bool)(ConfigurationKPI::get('PENDING_MESSAGES_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-age'; - $helper->icon = 'icon-time'; - $helper->color = 'color2'; - $helper->title = $this->l('Average Response Time', null, null, false); - $helper->subtitle = $this->l('30 days', null, null, false); - if (ConfigurationKPI::get('AVG_MSG_RESPONSE_TIME') !== false) - $helper->value = ConfigurationKPI::get('AVG_MSG_RESPONSE_TIME'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=avg_msg_response_time'; - $helper->refresh = (bool)(ConfigurationKPI::get('AVG_MSG_RESPONSE_TIME_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-messages-per-thread'; - $helper->icon = 'icon-copy'; - $helper->color = 'color3'; - $helper->title = $this->l('Messages per Thread', null, null, false); - $helper->subtitle = $this->l('30 day', null, null, false); - if (ConfigurationKPI::get('MESSAGES_PER_THREAD') !== false) - $helper->value = ConfigurationKPI::get('MESSAGES_PER_THREAD'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=messages_per_thread'; - $helper->refresh = (bool)(ConfigurationKPI::get('MESSAGES_PER_THREAD_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpiRow(); - $helper->kpis = $kpis; - return $helper->generate(); - } - - public function renderView() - { - if (!$id_customer_thread = (int)Tools::getValue('id_customer_thread')) - return; - - $this->context = Context::getContext(); - if (!($thread = $this->loadObject())) - return; - $this->context->cookie->{'customer_threadFilter_cl!id_contact'} = $thread->id_contact; - - $employees = Employee::getEmployees(); - - $messages = CustomerThread::getMessageCustomerThreads($id_customer_thread); - - foreach ($messages as $key => $mess) - { - if ($mess['id_employee']) - { - $employee = new Employee($mess['id_employee']); - $messages[$key]['employee_image'] = $employee->getImage(); - } - if (isset($mess['file_name']) && $mess['file_name'] != '') - $messages[$key]['file_name'] = _THEME_PROD_PIC_DIR_.$mess['file_name']; - else - unset($messages[$key]['file_name']); - - if ($mess['id_product']) - { - $product = new Product((int)$mess['id_product'], false, $this->context->language->id); - if (Validate::isLoadedObject($product)) - { - $messages[$key]['product_name'] = $product->name; - $messages[$key]['product_link'] = $this->context->link->getAdminLink('AdminProducts').'&updateproduct&id_product='.(int)$product->id; - } - } - } - - $next_thread = CustomerThread::getNextThread((int)$thread->id); - - $contacts = Contact::getContacts($this->context->language->id); - - $actions = array(); - - if ($next_thread) - $next_thread = array( - 'href' => self::$currentIndex.'&id_customer_thread='.(int)$next_thread.'&viewcustomer_thread&token='.$this->token, - 'name' => $this->l('Reply to the next unanswered message in this thread') - ); - - if ($thread->status != 'closed') - $actions['closed'] = array( - 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=2&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, - 'label' => $this->l('Mark as "handled"'), - 'name' => 'setstatus', - 'value' => 2 - ); - else - $actions['open'] = array( - 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=1&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, - 'label' => $this->l('Re-open'), - 'name' => 'setstatus', - 'value' => 1 - ); - - if ($thread->status != 'pending1') - $actions['pending1'] = array( - 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=3&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, - 'label' => $this->l('Mark as "pending 1" (will be answered later)'), - 'name' => 'setstatus', - 'value' => 3 - ); - else - $actions['pending1'] = array( - 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=1&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, - 'label' => $this->l('Disable pending status'), - 'name' => 'setstatus', - 'value' => 1 - ); - - if ($thread->status != 'pending2') - $actions['pending2'] = array( - 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=4&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, - 'label' => $this->l('Mark as "pending 2" (will be answered later)'), - 'name' => 'setstatus', - 'value' => 4 - ); - else - $actions['pending2'] = array( - 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=1&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, - 'label' => $this->l('Disable pending status'), - 'name' => 'setstatus', - 'value' => 1 - ); - - if ($thread->id_customer) - { - $customer = new Customer($thread->id_customer); - $orders = Order::getCustomerOrders($customer->id); - if ($orders && count($orders)) - { - $total_ok = 0; - $orders_ok = array(); - foreach ($orders as $key => $order) - { - if ($order['valid']) - { - $orders_ok[] = $order; - $total_ok += $order['total_paid_real']; - } - $orders[$key]['date_add'] = Tools::displayDate($order['date_add']); - $orders[$key]['total_paid_real'] = Tools::displayPrice($order['total_paid_real'], new Currency((int)$order['id_currency'])); - } - } - - $products = $customer->getBoughtProducts(); - if ($products && count($products)) - foreach ($products as $key => $product) - $products[$key]['date_add'] = Tools::displayDate($product['date_add'], null, true); - } - $timeline_items = $this->getTimeline($messages, $thread->id_order); - $first_message = $messages[0]; - - if (!$messages[0]['id_employee']) - unset($messages[0]); - - $contact = ''; - foreach ($contacts as $c) - if ($c['id_contact'] == $thread->id_contact) - $contact = $c['name']; - - $this->tpl_view_vars = array( - 'id_customer_thread' => $id_customer_thread, - 'thread' => $thread, - 'actions' => $actions, - 'employees' => $employees, - 'current_employee' => $this->context->employee, - 'messages' => $messages, - 'first_message' => $first_message, - 'contact' => $contact, - 'next_thread' => $next_thread, - 'orders' => isset($orders) ? $orders : false, - 'customer' => isset($customer) ? $customer : false, - 'products' => isset($products) ? $products : false, - 'total_ok' => isset($total_ok) ? Tools::displayPrice($total_ok, $this->context->currency) : false, - 'orders_ok' => isset($orders_ok) ? $orders_ok : false, - 'count_ok' => isset($orders_ok) ? count($orders_ok) : false, - 'PS_CUSTOMER_SERVICE_SIGNATURE' => str_replace('\r\n', "\n", Configuration::get('PS_CUSTOMER_SERVICE_SIGNATURE', (int)$thread->id_lang)), - 'timeline_items' => $timeline_items, - ); - - if ($next_thread) - $this->tpl_view_vars['next_thread'] = $next_thread; - - return parent::renderView(); - } - - public function getTimeline($messages, $id_order) - { - $timeline = array(); - foreach ($messages as $message) - { - $product = new Product((int)$message['id_product'], false, $this->context->language->id); - $link_product = $this->context->link->getAdminLink('AdminOrders').'&vieworder&id_order='.(int)$product->id; - - $content = $this->l('Message to: ').' <span class="badge">'.(!$message['id_employee'] ? $message['subject'] : $message['customer_name']).'</span><br/>'; - if (Validate::isLoadedObject($product)) - $content .= '<br/>'.$this->l('Product: ').'<span class="label label-info">'.$product->name.'</span><br/><br/>'; - $content .= Tools::safeOutput($message['message']); - - $timeline[$message['date_add']][] = array( - 'arrow' => 'left', - 'background_color' => '', - 'icon' => 'icon-envelope', - 'content' => $content, - 'date' => $message['date_add'], - ); - } - - $order = new Order((int)$id_order); - if (Validate::isLoadedObject($order)) - { - $order_history = $order->getHistory($this->context->language->id); - foreach ($order_history as $history) - { - $link_order = $this->context->link->getAdminLink('AdminOrders').'&vieworder&id_order='.(int)$order->id; - - $content = '<a class="badge" target="_blank" href="'.Tools::safeOutput($link_order).'">'.$this->l('Order').' #'.(int)$order->id.'</a><br/><br/>'; - - $content .= '<span>'.$this->l('Status:').' '.$history['ostate_name'].'</span>'; - - $timeline[$history['date_add']][] = array( - 'arrow' => 'right', - 'alt' => true, - 'background_color' => $history['color'], - 'icon' => 'icon-credit-card', - 'content' => $content, - 'date' => $history['date_add'], - 'see_more_link' => $link_order, - ); - } - } - krsort($timeline); - return $timeline; - } - - protected function displayMessage($message, $email = false, $id_employee = null) - { - $tpl = $this->createTemplate('message.tpl'); - - $contacts = Contact::getContacts($this->context->language->id); - foreach ($contacts as $contact) - $contact_array[$contact['id_contact']] = array('id_contact' => $contact['id_contact'], 'name' => $contact['name']); - $contacts = $contact_array; - - if (!$email) - { - if (!empty($message['id_product']) && empty($message['employee_name'])) - $id_order_product = Order::getIdOrderProduct((int)$message['id_customer'], (int)$message['id_product']); - } - $message['date_add'] = Tools::displayDate($message['date_add'], null, true); - $message['user_agent'] = strip_tags($message['user_agent']); - $message['message'] = preg_replace( - '/(https?:\/\/[a-z0-9#%&_=\(\)\.\? \+\-@\/]{6,1000})([\s\n<])/Uui', - '<a href="\1">\1</a>\2', - html_entity_decode($message['message'], - ENT_QUOTES, 'UTF-8') - ); - - $is_valid_order_id = true; - $order = new Order((int)$message['id_order']); - - if (!Validate::isLoadedObject($order)) - $is_valid_order_id = false; - - $tpl->assign(array( - 'thread_url' => Tools::getAdminUrl(basename(_PS_ADMIN_DIR_).'/'. - $this->context->link->getAdminLink('AdminCustomerThreads').'&id_customer_thread=' - .(int)$message['id_customer_thread'].'&viewcustomer_thread=1'), - 'link' => Context::getContext()->link, - 'current' => self::$currentIndex, - 'token' => $this->token, - 'message' => $message, - 'id_order_product' => isset($id_order_product) ? $id_order_product : null, - 'email' => $email, - 'id_employee' => $id_employee, - 'PS_SHOP_NAME' => Configuration::get('PS_SHOP_NAME'), - 'file_name' => file_exists(_PS_UPLOAD_DIR_.$message['file_name']), - 'contacts' => $contacts, - 'is_valid_order_id' => $is_valid_order_id - )); - - return $tpl->fetch(); - } - - protected function displayButton($content) - { - return '<div><p>'.$content.'</p></div>'; - } - - public function renderOptions() - { - if (Configuration::get('PS_SAV_IMAP_URL') - && Configuration::get('PS_SAV_IMAP_PORT') - && Configuration::get('PS_SAV_IMAP_USER') - && Configuration::get('PS_SAV_IMAP_PWD')) - $this->tpl_option_vars['use_sync'] = true; - else - $this->tpl_option_vars['use_sync'] = false; - - return parent::renderOptions(); - } - - /** - * AdminController::getList() override - * @see AdminController::getList() - * - * @param int $id_lang - * @param string|null $order_by - * @param string|null $order_way - * @param int $start - * @param int|null $limit - * @param int|bool $id_lang_shop - * - * @throws PrestaShopException - */ - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - - $nb_items = count($this->_list); - for ($i = 0; $i < $nb_items; ++$i) - { - if (isset($this->_list[$i]['messages'])) - $this->_list[$i]['messages'] = Tools::htmlentitiesDecodeUTF8($this->_list[$i]['messages']); - } - } - - public function updateOptionPsSavImapOpt($value) - { - if ($this->tabAccess['edit'] != '1') - throw new PrestaShopException(Tools::displayError('You do not have permission to edit this.')); - - if (!$this->errors && $value) - Configuration::updateValue('PS_SAV_IMAP_OPT', implode('', $value)); - } - - public function ajaxProcessMarkAsRead() - { - if ($this->tabAccess['edit'] != '1') - throw new PrestaShopException(Tools::displayError('You do not have permission to edit this.')); - - $id_thread = Tools::getValue('id_thread'); - $messages = CustomerThread::getMessageCustomerThreads($id_thread); - if (count($messages)) - Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'customer_message` set `read` = 1 WHERE `id_employee` = '.(int)$this->context->employee->id.' AND `id_customer_thread` = '.(int)$id_thread); - } - - /** - * Call the IMAP synchronization during an AJAX process. - * - * @throws PrestaShopException - */ - public function ajaxProcessSyncImap() - { - if ($this->tabAccess['edit'] != '1') - throw new PrestaShopException(Tools::displayError('You do not have permission to edit this.')); - - if (Tools::isSubmit('syncImapMail')) - die(Tools::jsonEncode($this->syncImap())); - } - - /** - * Call the IMAP synchronization during the render process. - */ - public function renderProcessSyncImap() - { - // To avoid an error if the IMAP isn't configured, we check the configuration here, like during - // the synchronization. All parameters will exists. - if (!(Configuration::get('PS_SAV_IMAP_URL') - || Configuration::get('PS_SAV_IMAP_PORT') - || Configuration::get('PS_SAV_IMAP_USER') - || Configuration::get('PS_SAV_IMAP_PWD'))) - return; - - // Executes the IMAP synchronization. - $sync_errors = $this->syncImap(); - - // Show the errors. - if (isset($sync_errors['hasError']) && $sync_errors['hasError']) - if (isset($sync_errors['errors'])) - foreach ($sync_errors['errors'] as &$error) - $this->displayWarning($error); - } - - /** - * Imap synchronization method. - * - * @return array Errors list. - */ - public function syncImap() - { - if (!($url = Configuration::get('PS_SAV_IMAP_URL')) - || !($port = Configuration::get('PS_SAV_IMAP_PORT')) - || !($user = Configuration::get('PS_SAV_IMAP_USER')) - || !($password = Configuration::get('PS_SAV_IMAP_PWD'))) - return array('hasError' => true, 'errors' => array('IMAP configuration is not correct')); - - $conf = Configuration::getMultiple(array( - 'PS_SAV_IMAP_OPT_NORSH', 'PS_SAV_IMAP_OPT_SSL', - 'PS_SAV_IMAP_OPT_VALIDATE-CERT', 'PS_SAV_IMAP_OPT_NOVALIDATE-CERT', - 'PS_SAV_IMAP_OPT_TLS', 'PS_SAV_IMAP_OPT_NOTLS')); - - $conf_str = ''; - if ($conf['PS_SAV_IMAP_OPT_NORSH']) - $conf_str .= '/norsh'; - if ($conf['PS_SAV_IMAP_OPT_SSL']) - $conf_str .= '/ssl'; - if ($conf['PS_SAV_IMAP_OPT_VALIDATE-CERT']) - $conf_str .= '/validate-cert'; - if ($conf['PS_SAV_IMAP_OPT_NOVALIDATE-CERT']) - $conf_str .= '/novalidate-cert'; - if ($conf['PS_SAV_IMAP_OPT_TLS']) - $conf_str .= '/tls'; - if ($conf['PS_SAV_IMAP_OPT_NOTLS']) - $conf_str .= '/notls'; - - if (!function_exists('imap_open')) - return array('hasError' => true, 'errors' => array('imap is not installed on this server')); - - $mbox = @imap_open('{'.$url.':'.$port.$conf_str.'}', $user, $password); - - //checks if there is no error when connecting imap server - $errors = imap_errors(); - if (is_array($errors)) - $errors = array_unique($errors); - $str_errors = ''; - $str_error_delete = ''; - - if (count($errors) && is_array($errors)) - { - $str_errors = ''; - foreach ($errors as $error) - $str_errors .= $error.', '; - $str_errors = rtrim(trim($str_errors), ','); - } - //checks if imap connexion is active - if (!$mbox) - return array('hasError' => true, 'errors' => array('Cannot connect to the mailbox :<br />'.($str_errors))); - - //Returns information about the current mailbox. Returns FALSE on failure. - $check = imap_check($mbox); - if (!$check) - return array('hasError' => true, 'errors' => array('Fail to get information about the current mailbox')); - - if ($check->Nmsgs == 0) - return array('hasError' => true, 'errors' => array('NO message to sync')); - - $result = imap_fetch_overview($mbox, "1:{$check->Nmsgs}", 0); - foreach ($result as $overview) - { - //check if message exist in database - if (isset($overview->subject)) - $subject = $overview->subject; - else - $subject = ''; - //Creating an md5 to check if message has been allready processed - $md5 = md5($overview->date.$overview->from.$subject.$overview->msgno); - $exist = Db::getInstance()->getValue( - 'SELECT `md5_header` + $output = $this->displayMessage($messages, true, (int)Tools::getValue('id_employee_forward')); + $cm = new CustomerMessage(); + $cm->id_employee = (int)$this->context->employee->id; + $cm->id_customer_thread = (int)Tools::getValue('id_customer_thread'); + $cm->ip_address = (int)ip2long(Tools::getRemoteAddr()); + $current_employee = $this->context->employee; + $id_employee = (int)Tools::getValue('id_employee_forward'); + $employee = new Employee($id_employee); + $email = Tools::getValue('email'); + $message = Tools::getValue('message_forward'); + if (($error = $cm->validateField('message', $message, null, array(), true)) !== true) { + $this->errors[] = $error; + } elseif ($id_employee && $employee && Validate::isLoadedObject($employee)) { + $params = array( + '{messages}' => stripslashes($output), + '{employee}' => $current_employee->firstname.' '.$current_employee->lastname, + '{comment}' => stripslashes(Tools::nl2br($_POST['message_forward'])), + '{firstname}' => $employee->firstname, + '{lastname}' => $employee->lastname, + ); + + if (Mail::Send( + $this->context->language->id, + 'forward_msg', + Mail::l('Fwd: Customer message', $this->context->language->id), + $params, + $employee->email, + $employee->firstname.' '.$employee->lastname, + $current_employee->email, + $current_employee->firstname.' '.$current_employee->lastname, + null, null, _PS_MAIL_DIR_, true)) { + $cm->private = 1; + $cm->message = $this->l('Message forwarded to').' '.$employee->firstname.' '.$employee->lastname."\n".$this->l('Comment:').' '.$message; + $cm->add(); + } + } elseif ($email && Validate::isEmail($email)) { + $params = array( + '{messages}' => Tools::nl2br(stripslashes($output)), + '{employee}' => $current_employee->firstname.' '.$current_employee->lastname, + '{comment}' => stripslashes($_POST['message_forward']) + ); + + if (Mail::Send( + $this->context->language->id, + 'forward_msg', + Mail::l('Fwd: Customer message', $this->context->language->id), + $params, $email, null, + $current_employee->email, $current_employee->firstname.' '.$current_employee->lastname, + null, null, _PS_MAIL_DIR_, true)) { + $cm->message = $this->l('Message forwarded to').' '.$email."\n".$this->l('Comment:').' '.$message; + $cm->add(); + } + } else { + $this->errors[] = '<div class="alert error">'.Tools::displayError('The email address is invalid.').'</div>'; + } + } + if (Tools::isSubmit('submitReply')) { + $ct = new CustomerThread($id_customer_thread); + + ShopUrl::cacheMainDomainForShop((int)$ct->id_shop); + + $cm = new CustomerMessage(); + $cm->id_employee = (int)$this->context->employee->id; + $cm->id_customer_thread = $ct->id; + $cm->ip_address = (int)ip2long(Tools::getRemoteAddr()); + $cm->message = Tools::getValue('reply_message'); + if (($error = $cm->validateField('message', $cm->message, null, array(), true)) !== true) { + $this->errors[] = $error; + } elseif (isset($_FILES) && !empty($_FILES['joinFile']['name']) && $_FILES['joinFile']['error'] != 0) { + $this->errors[] = Tools::displayError('An error occurred during the file upload process.'); + } elseif ($cm->add()) { + $file_attachment = null; + if (!empty($_FILES['joinFile']['name'])) { + $file_attachment['content'] = file_get_contents($_FILES['joinFile']['tmp_name']); + $file_attachment['name'] = $_FILES['joinFile']['name']; + $file_attachment['mime'] = $_FILES['joinFile']['type']; + } + $customer = new Customer($ct->id_customer); + $params = array( + '{reply}' => Tools::nl2br(Tools::getValue('reply_message')), + '{link}' => Tools::url( + $this->context->link->getPageLink('contact', true, null, null, false, $ct->id_shop), + 'id_customer_thread='.(int)$ct->id.'&token='.$ct->token + ), + '{firstname}' => $customer->firstname, + '{lastname}' => $customer->lastname + ); + //#ct == id_customer_thread #tc == token of thread <== used in the synchronization imap + $contact = new Contact((int)$ct->id_contact, (int)$ct->id_lang); + + if (Validate::isLoadedObject($contact)) { + $from_name = $contact->name; + $from_email = $contact->email; + } else { + $from_name = null; + $from_email = null; + } + + if (Mail::Send( + (int)$ct->id_lang, + 'reply_msg', + sprintf(Mail::l('An answer to your message is available #ct%1$s #tc%2$s', $ct->id_lang), $ct->id, $ct->token), + $params, Tools::getValue('msg_email'), null, $from_email, $from_name, $file_attachment, null, + _PS_MAIL_DIR_, true, $ct->id_shop)) { + $ct->status = 'closed'; + $ct->update(); + } + Tools::redirectAdmin( + self::$currentIndex.'&id_customer_thread='.(int)$id_customer_thread.'&viewcustomer_thread&token='.Tools::getValue('token') + ); + } else { + $this->errors[] = Tools::displayError('An error occurred. Your message was not sent. Please contact your system administrator.'); + } + } + } + + return parent::postProcess(); + } + + public function initContent() + { + if (isset($_GET['filename']) && file_exists(_PS_UPLOAD_DIR_.$_GET['filename']) && Validate::isFileName($_GET['filename'])) { + AdminCustomerThreadsController::openUploadedFile(); + } + + return parent::initContent(); + } + + protected function openUploadedFile() + { + $filename = $_GET['filename']; + + $extensions = array( + '.txt' => 'text/plain', + '.rtf' => 'application/rtf', + '.doc' => 'application/msword', + '.docx'=> 'application/msword', + '.pdf' => 'application/pdf', + '.zip' => 'multipart/x-zip', + '.png' => 'image/png', + '.jpeg' => 'image/jpeg', + '.gif' => 'image/gif', + '.jpg' => 'image/jpeg', + ); + + $extension = false; + foreach ($extensions as $key => $val) { + if (substr(Tools::strtolower($filename), -4) == $key || substr(Tools::strtolower($filename), -5) == $key) { + $extension = $val; + break; + } + } + + if (!$extension || !Validate::isFileName($filename)) { + die(Tools::displayError()); + } + + if (ob_get_level() && ob_get_length() > 0) { + ob_end_clean(); + } + header('Content-Type: '.$extension); + header('Content-Disposition:attachment;filename="'.$filename.'"'); + readfile(_PS_UPLOAD_DIR_.$filename); + die; + } + + public function renderKpis() + { + $time = time(); + $kpis = array(); + + /* The data generation is located in AdminStatsControllerCore */ + + $helper = new HelperKpi(); + $helper->id = 'box-pending-messages'; + $helper->icon = 'icon-envelope'; + $helper->color = 'color1'; + $helper->href = $this->context->link->getAdminLink('AdminCustomerThreads'); + $helper->title = $this->l('Pending Discussion Threads', null, null, false); + if (ConfigurationKPI::get('PENDING_MESSAGES') !== false) { + $helper->value = ConfigurationKPI::get('PENDING_MESSAGES'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=pending_messages'; + $helper->refresh = (bool)(ConfigurationKPI::get('PENDING_MESSAGES_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-age'; + $helper->icon = 'icon-time'; + $helper->color = 'color2'; + $helper->title = $this->l('Average Response Time', null, null, false); + $helper->subtitle = $this->l('30 days', null, null, false); + if (ConfigurationKPI::get('AVG_MSG_RESPONSE_TIME') !== false) { + $helper->value = ConfigurationKPI::get('AVG_MSG_RESPONSE_TIME'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=avg_msg_response_time'; + $helper->refresh = (bool)(ConfigurationKPI::get('AVG_MSG_RESPONSE_TIME_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-messages-per-thread'; + $helper->icon = 'icon-copy'; + $helper->color = 'color3'; + $helper->title = $this->l('Messages per Thread', null, null, false); + $helper->subtitle = $this->l('30 day', null, null, false); + if (ConfigurationKPI::get('MESSAGES_PER_THREAD') !== false) { + $helper->value = ConfigurationKPI::get('MESSAGES_PER_THREAD'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=messages_per_thread'; + $helper->refresh = (bool)(ConfigurationKPI::get('MESSAGES_PER_THREAD_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpiRow(); + $helper->kpis = $kpis; + return $helper->generate(); + } + + public function renderView() + { + if (!$id_customer_thread = (int)Tools::getValue('id_customer_thread')) { + return; + } + + $this->context = Context::getContext(); + if (!($thread = $this->loadObject())) { + return; + } + $this->context->cookie->{'customer_threadFilter_cl!id_contact'} = $thread->id_contact; + + $employees = Employee::getEmployees(); + + $messages = CustomerThread::getMessageCustomerThreads($id_customer_thread); + + foreach ($messages as $key => $mess) { + if ($mess['id_employee']) { + $employee = new Employee($mess['id_employee']); + $messages[$key]['employee_image'] = $employee->getImage(); + } + if (isset($mess['file_name']) && $mess['file_name'] != '') { + $messages[$key]['file_name'] = _THEME_PROD_PIC_DIR_.$mess['file_name']; + } else { + unset($messages[$key]['file_name']); + } + + if ($mess['id_product']) { + $product = new Product((int)$mess['id_product'], false, $this->context->language->id); + if (Validate::isLoadedObject($product)) { + $messages[$key]['product_name'] = $product->name; + $messages[$key]['product_link'] = $this->context->link->getAdminLink('AdminProducts').'&updateproduct&id_product='.(int)$product->id; + } + } + } + + $next_thread = CustomerThread::getNextThread((int)$thread->id); + + $contacts = Contact::getContacts($this->context->language->id); + + $actions = array(); + + if ($next_thread) { + $next_thread = array( + 'href' => self::$currentIndex.'&id_customer_thread='.(int)$next_thread.'&viewcustomer_thread&token='.$this->token, + 'name' => $this->l('Reply to the next unanswered message in this thread') + ); + } + + if ($thread->status != 'closed') { + $actions['closed'] = array( + 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=2&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, + 'label' => $this->l('Mark as "handled"'), + 'name' => 'setstatus', + 'value' => 2 + ); + } else { + $actions['open'] = array( + 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=1&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, + 'label' => $this->l('Re-open'), + 'name' => 'setstatus', + 'value' => 1 + ); + } + + if ($thread->status != 'pending1') { + $actions['pending1'] = array( + 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=3&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, + 'label' => $this->l('Mark as "pending 1" (will be answered later)'), + 'name' => 'setstatus', + 'value' => 3 + ); + } else { + $actions['pending1'] = array( + 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=1&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, + 'label' => $this->l('Disable pending status'), + 'name' => 'setstatus', + 'value' => 1 + ); + } + + if ($thread->status != 'pending2') { + $actions['pending2'] = array( + 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=4&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, + 'label' => $this->l('Mark as "pending 2" (will be answered later)'), + 'name' => 'setstatus', + 'value' => 4 + ); + } else { + $actions['pending2'] = array( + 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=1&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, + 'label' => $this->l('Disable pending status'), + 'name' => 'setstatus', + 'value' => 1 + ); + } + + if ($thread->id_customer) { + $customer = new Customer($thread->id_customer); + $orders = Order::getCustomerOrders($customer->id); + if ($orders && count($orders)) { + $total_ok = 0; + $orders_ok = array(); + foreach ($orders as $key => $order) { + if ($order['valid']) { + $orders_ok[] = $order; + $total_ok += $order['total_paid_real']; + } + $orders[$key]['date_add'] = Tools::displayDate($order['date_add']); + $orders[$key]['total_paid_real'] = Tools::displayPrice($order['total_paid_real'], new Currency((int)$order['id_currency'])); + } + } + + $products = $customer->getBoughtProducts(); + if ($products && count($products)) { + foreach ($products as $key => $product) { + $products[$key]['date_add'] = Tools::displayDate($product['date_add'], null, true); + } + } + } + $timeline_items = $this->getTimeline($messages, $thread->id_order); + $first_message = $messages[0]; + + if (!$messages[0]['id_employee']) { + unset($messages[0]); + } + + $contact = ''; + foreach ($contacts as $c) { + if ($c['id_contact'] == $thread->id_contact) { + $contact = $c['name']; + } + } + + $this->tpl_view_vars = array( + 'id_customer_thread' => $id_customer_thread, + 'thread' => $thread, + 'actions' => $actions, + 'employees' => $employees, + 'current_employee' => $this->context->employee, + 'messages' => $messages, + 'first_message' => $first_message, + 'contact' => $contact, + 'next_thread' => $next_thread, + 'orders' => isset($orders) ? $orders : false, + 'customer' => isset($customer) ? $customer : false, + 'products' => isset($products) ? $products : false, + 'total_ok' => isset($total_ok) ? Tools::displayPrice($total_ok, $this->context->currency) : false, + 'orders_ok' => isset($orders_ok) ? $orders_ok : false, + 'count_ok' => isset($orders_ok) ? count($orders_ok) : false, + 'PS_CUSTOMER_SERVICE_SIGNATURE' => str_replace('\r\n', "\n", Configuration::get('PS_CUSTOMER_SERVICE_SIGNATURE', (int)$thread->id_lang)), + 'timeline_items' => $timeline_items, + ); + + if ($next_thread) { + $this->tpl_view_vars['next_thread'] = $next_thread; + } + + return parent::renderView(); + } + + public function getTimeline($messages, $id_order) + { + $timeline = array(); + foreach ($messages as $message) { + $product = new Product((int)$message['id_product'], false, $this->context->language->id); + $link_product = $this->context->link->getAdminLink('AdminOrders').'&vieworder&id_order='.(int)$product->id; + + $content = $this->l('Message to: ').' <span class="badge">'.(!$message['id_employee'] ? $message['subject'] : $message['customer_name']).'</span><br/>'; + if (Validate::isLoadedObject($product)) { + $content .= '<br/>'.$this->l('Product: ').'<span class="label label-info">'.$product->name.'</span><br/><br/>'; + } + $content .= Tools::safeOutput($message['message']); + + $timeline[$message['date_add']][] = array( + 'arrow' => 'left', + 'background_color' => '', + 'icon' => 'icon-envelope', + 'content' => $content, + 'date' => $message['date_add'], + ); + } + + $order = new Order((int)$id_order); + if (Validate::isLoadedObject($order)) { + $order_history = $order->getHistory($this->context->language->id); + foreach ($order_history as $history) { + $link_order = $this->context->link->getAdminLink('AdminOrders').'&vieworder&id_order='.(int)$order->id; + + $content = '<a class="badge" target="_blank" href="'.Tools::safeOutput($link_order).'">'.$this->l('Order').' #'.(int)$order->id.'</a><br/><br/>'; + + $content .= '<span>'.$this->l('Status:').' '.$history['ostate_name'].'</span>'; + + $timeline[$history['date_add']][] = array( + 'arrow' => 'right', + 'alt' => true, + 'background_color' => $history['color'], + 'icon' => 'icon-credit-card', + 'content' => $content, + 'date' => $history['date_add'], + 'see_more_link' => $link_order, + ); + } + } + krsort($timeline); + return $timeline; + } + + protected function displayMessage($message, $email = false, $id_employee = null) + { + $tpl = $this->createTemplate('message.tpl'); + + $contacts = Contact::getContacts($this->context->language->id); + foreach ($contacts as $contact) { + $contact_array[$contact['id_contact']] = array('id_contact' => $contact['id_contact'], 'name' => $contact['name']); + } + $contacts = $contact_array; + + if (!$email) { + if (!empty($message['id_product']) && empty($message['employee_name'])) { + $id_order_product = Order::getIdOrderProduct((int)$message['id_customer'], (int)$message['id_product']); + } + } + $message['date_add'] = Tools::displayDate($message['date_add'], null, true); + $message['user_agent'] = strip_tags($message['user_agent']); + $message['message'] = preg_replace( + '/(https?:\/\/[a-z0-9#%&_=\(\)\.\? \+\-@\/]{6,1000})([\s\n<])/Uui', + '<a href="\1">\1</a>\2', + html_entity_decode($message['message'], + ENT_QUOTES, 'UTF-8') + ); + + $is_valid_order_id = true; + $order = new Order((int)$message['id_order']); + + if (!Validate::isLoadedObject($order)) { + $is_valid_order_id = false; + } + + $tpl->assign(array( + 'thread_url' => Tools::getAdminUrl(basename(_PS_ADMIN_DIR_).'/'. + $this->context->link->getAdminLink('AdminCustomerThreads').'&id_customer_thread=' + .(int)$message['id_customer_thread'].'&viewcustomer_thread=1'), + 'link' => Context::getContext()->link, + 'current' => self::$currentIndex, + 'token' => $this->token, + 'message' => $message, + 'id_order_product' => isset($id_order_product) ? $id_order_product : null, + 'email' => $email, + 'id_employee' => $id_employee, + 'PS_SHOP_NAME' => Configuration::get('PS_SHOP_NAME'), + 'file_name' => file_exists(_PS_UPLOAD_DIR_.$message['file_name']), + 'contacts' => $contacts, + 'is_valid_order_id' => $is_valid_order_id + )); + + return $tpl->fetch(); + } + + protected function displayButton($content) + { + return '<div><p>'.$content.'</p></div>'; + } + + public function renderOptions() + { + if (Configuration::get('PS_SAV_IMAP_URL') + && Configuration::get('PS_SAV_IMAP_PORT') + && Configuration::get('PS_SAV_IMAP_USER') + && Configuration::get('PS_SAV_IMAP_PWD')) { + $this->tpl_option_vars['use_sync'] = true; + } else { + $this->tpl_option_vars['use_sync'] = false; + } + + return parent::renderOptions(); + } + + /** + * AdminController::getList() override + * @see AdminController::getList() + * + * @param int $id_lang + * @param string|null $order_by + * @param string|null $order_way + * @param int $start + * @param int|null $limit + * @param int|bool $id_lang_shop + * + * @throws PrestaShopException + */ + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + + $nb_items = count($this->_list); + for ($i = 0; $i < $nb_items; ++$i) { + if (isset($this->_list[$i]['messages'])) { + $this->_list[$i]['messages'] = Tools::htmlentitiesDecodeUTF8($this->_list[$i]['messages']); + } + } + } + + public function updateOptionPsSavImapOpt($value) + { + if ($this->tabAccess['edit'] != '1') { + throw new PrestaShopException(Tools::displayError('You do not have permission to edit this.')); + } + + if (!$this->errors && $value) { + Configuration::updateValue('PS_SAV_IMAP_OPT', implode('', $value)); + } + } + + public function ajaxProcessMarkAsRead() + { + if ($this->tabAccess['edit'] != '1') { + throw new PrestaShopException(Tools::displayError('You do not have permission to edit this.')); + } + + $id_thread = Tools::getValue('id_thread'); + $messages = CustomerThread::getMessageCustomerThreads($id_thread); + if (count($messages)) { + Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'customer_message` set `read` = 1 WHERE `id_employee` = '.(int)$this->context->employee->id.' AND `id_customer_thread` = '.(int)$id_thread); + } + } + + /** + * Call the IMAP synchronization during an AJAX process. + * + * @throws PrestaShopException + */ + public function ajaxProcessSyncImap() + { + if ($this->tabAccess['edit'] != '1') { + throw new PrestaShopException(Tools::displayError('You do not have permission to edit this.')); + } + + if (Tools::isSubmit('syncImapMail')) { + die(Tools::jsonEncode($this->syncImap())); + } + } + + /** + * Call the IMAP synchronization during the render process. + */ + public function renderProcessSyncImap() + { + // To avoid an error if the IMAP isn't configured, we check the configuration here, like during + // the synchronization. All parameters will exists. + if (!(Configuration::get('PS_SAV_IMAP_URL') + || Configuration::get('PS_SAV_IMAP_PORT') + || Configuration::get('PS_SAV_IMAP_USER') + || Configuration::get('PS_SAV_IMAP_PWD'))) { + return; + } + + // Executes the IMAP synchronization. + $sync_errors = $this->syncImap(); + + // Show the errors. + if (isset($sync_errors['hasError']) && $sync_errors['hasError']) { + if (isset($sync_errors['errors'])) { + foreach ($sync_errors['errors'] as &$error) { + $this->displayWarning($error); + } + } + } + } + + /** + * Imap synchronization method. + * + * @return array Errors list. + */ + public function syncImap() + { + if (!($url = Configuration::get('PS_SAV_IMAP_URL')) + || !($port = Configuration::get('PS_SAV_IMAP_PORT')) + || !($user = Configuration::get('PS_SAV_IMAP_USER')) + || !($password = Configuration::get('PS_SAV_IMAP_PWD'))) { + return array('hasError' => true, 'errors' => array('IMAP configuration is not correct')); + } + + $conf = Configuration::getMultiple(array( + 'PS_SAV_IMAP_OPT_NORSH', 'PS_SAV_IMAP_OPT_SSL', + 'PS_SAV_IMAP_OPT_VALIDATE-CERT', 'PS_SAV_IMAP_OPT_NOVALIDATE-CERT', + 'PS_SAV_IMAP_OPT_TLS', 'PS_SAV_IMAP_OPT_NOTLS')); + + $conf_str = ''; + if ($conf['PS_SAV_IMAP_OPT_NORSH']) { + $conf_str .= '/norsh'; + } + if ($conf['PS_SAV_IMAP_OPT_SSL']) { + $conf_str .= '/ssl'; + } + if ($conf['PS_SAV_IMAP_OPT_VALIDATE-CERT']) { + $conf_str .= '/validate-cert'; + } + if ($conf['PS_SAV_IMAP_OPT_NOVALIDATE-CERT']) { + $conf_str .= '/novalidate-cert'; + } + if ($conf['PS_SAV_IMAP_OPT_TLS']) { + $conf_str .= '/tls'; + } + if ($conf['PS_SAV_IMAP_OPT_NOTLS']) { + $conf_str .= '/notls'; + } + + if (!function_exists('imap_open')) { + return array('hasError' => true, 'errors' => array('imap is not installed on this server')); + } + + $mbox = @imap_open('{'.$url.':'.$port.$conf_str.'}', $user, $password); + + //checks if there is no error when connecting imap server + $errors = imap_errors(); + if (is_array($errors)) { + $errors = array_unique($errors); + } + $str_errors = ''; + $str_error_delete = ''; + + if (count($errors) && is_array($errors)) { + $str_errors = ''; + foreach ($errors as $error) { + $str_errors .= $error.', '; + } + $str_errors = rtrim(trim($str_errors), ','); + } + //checks if imap connexion is active + if (!$mbox) { + return array('hasError' => true, 'errors' => array('Cannot connect to the mailbox :<br />'.($str_errors))); + } + + //Returns information about the current mailbox. Returns FALSE on failure. + $check = imap_check($mbox); + if (!$check) { + return array('hasError' => true, 'errors' => array('Fail to get information about the current mailbox')); + } + + if ($check->Nmsgs == 0) { + return array('hasError' => true, 'errors' => array('NO message to sync')); + } + + $result = imap_fetch_overview($mbox, "1:{$check->Nmsgs}", 0); + foreach ($result as $overview) { + //check if message exist in database + if (isset($overview->subject)) { + $subject = $overview->subject; + } else { + $subject = ''; + } + //Creating an md5 to check if message has been allready processed + $md5 = md5($overview->date.$overview->from.$subject.$overview->msgno); + $exist = Db::getInstance()->getValue( + 'SELECT `md5_header` FROM `'._DB_PREFIX_.'customer_message_sync_imap` WHERE `md5_header` = \''.pSQL($md5).'\''); - if ($exist) - { - if (Configuration::get('PS_SAV_IMAP_DELETE_MSG')) - if (!imap_delete($mbox, $overview->msgno)) - $str_error_delete = ', Fail to delete message'; - } - else - { - //check if subject has id_order - preg_match('/\#ct([0-9]*)/', $subject, $matches1); - preg_match('/\#tc([0-9-a-z-A-Z]*)/', $subject, $matches2); - $match_found = false; - if (isset($matches1[1]) && isset($matches2[1])) - $match_found = true; + if ($exist) { + if (Configuration::get('PS_SAV_IMAP_DELETE_MSG')) { + if (!imap_delete($mbox, $overview->msgno)) { + $str_error_delete = ', Fail to delete message'; + } + } + } else { + //check if subject has id_order + preg_match('/\#ct([0-9]*)/', $subject, $matches1); + preg_match('/\#tc([0-9-a-z-A-Z]*)/', $subject, $matches2); + $match_found = false; + if (isset($matches1[1]) && isset($matches2[1])) { + $match_found = true; + } - $new_ct = ( Configuration::get('PS_SAV_IMAP_CREATE_THREADS') && !$match_found && (strpos($subject, '[no_sync]') == false)); + $new_ct = (Configuration::get('PS_SAV_IMAP_CREATE_THREADS') && !$match_found && (strpos($subject, '[no_sync]') == false)); - if ($match_found || $new_ct) - { - if ($new_ct) - { - if (!preg_match('/<('.Tools::cleanNonUnicodeSupport('[a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]+[.a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]*@[a-z\p{L}0-9]+[._a-z\p{L}0-9-]*\.[a-z0-9]+').')>/', $overview->from, $result) - || !Validate::isEmail($from = $result[1])) - continue; + if ($match_found || $new_ct) { + if ($new_ct) { + if (!preg_match('/<('.Tools::cleanNonUnicodeSupport('[a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]+[.a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]*@[a-z\p{L}0-9]+[._a-z\p{L}0-9-]*\.[a-z0-9]+').')>/', $overview->from, $result) + || !Validate::isEmail($from = $result[1])) { + continue; + } - // we want to assign unrecognized mails to the right contact category - $contacts = Contact::getContacts($this->context->language->id); - if (!$contacts) - continue; + // we want to assign unrecognized mails to the right contact category + $contacts = Contact::getContacts($this->context->language->id); + if (!$contacts) { + continue; + } - foreach ($contacts as $contact) - if (strpos($overview->to, $contact['email']) !== false) - $id_contact = $contact['id_contact']; + foreach ($contacts as $contact) { + if (strpos($overview->to, $contact['email']) !== false) { + $id_contact = $contact['id_contact']; + } + } - if (!isset($id_contact)) // if not use the default contact category - $id_contact = $contacts[0]['id_contact']; + if (!isset($id_contact)) { // if not use the default contact category + $id_contact = $contacts[0]['id_contact']; + } - $customer = new Customer; - $client = $customer->getByEmail($from); //check if we already have a customer with this email + $customer = new Customer; + $client = $customer->getByEmail($from); //check if we already have a customer with this email + $ct = new CustomerThread(); + if (isset($client->id)) { //if mail is owned by a customer assign to him + $ct->id_customer = $client->id; + } + $ct->email = $from; + $ct->id_contact = $id_contact; + $ct->id_lang = (int)Configuration::get('PS_LANG_DEFAULT'); + $ct->id_shop = $this->context->shop->id; //new customer threads for unrecognized mails are not shown without shop id + $ct->status = 'open'; + $ct->token = Tools::passwdGen(12); + $ct->add(); + } else { + $ct = new CustomerThread((int)$matches1[1]); + } //check if order exist in database - $ct = new CustomerThread(); - if (isset($client->id)) //if mail is owned by a customer assign to him - $ct->id_customer = $client->id; - $ct->email = $from; - $ct->id_contact = $id_contact; - $ct->id_lang = (int)Configuration::get('PS_LANG_DEFAULT'); - $ct->id_shop = $this->context->shop->id; //new customer threads for unrecognized mails are not shown without shop id - $ct->status = 'open'; - $ct->token = Tools::passwdGen(12); - $ct->add(); - } - else - $ct = new CustomerThread((int)$matches1[1]); //check if order exist in database + if (Validate::isLoadedObject($ct) && ((isset($matches2[1]) && $ct->token == $matches2[1]) || $new_ct)) { + $message = imap_fetchbody($mbox, $overview->msgno, 1); + $message = quoted_printable_decode($message); + $message = utf8_encode($message); + $message = quoted_printable_decode($message); + $message = nl2br($message); + $cm = new CustomerMessage(); + $cm->id_customer_thread = $ct->id; + $cm->message = $message; - if (Validate::isLoadedObject($ct) && ((isset($matches2[1]) && $ct->token == $matches2[1]) || $new_ct)) - { - $message = imap_fetchbody($mbox, $overview->msgno, 1); - $message = quoted_printable_decode($message); - $message = utf8_encode($message); - $message = quoted_printable_decode($message); - $message = nl2br($message); - $cm = new CustomerMessage(); - $cm->id_customer_thread = $ct->id; - $cm->message = $message; - $cm->add(); - } - } - Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'customer_message_sync_imap` (`md5_header`) VALUES (\''.pSQL($md5).'\')'); - } - } - imap_expunge($mbox); - imap_close($mbox); - return array('hasError' => false, 'errors' => array($str_errors.$str_error_delete)); - } + if (!Validate::isCleanHtml($message)) { + $str_errors.= Tools::displayError(sprintf('Invalid Message Content for subject: %1s', $subject)); + } else { + $cm->add(); + } + } + } + Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'customer_message_sync_imap` (`md5_header`) VALUES (\''.pSQL($md5).'\')'); + } + } + imap_expunge($mbox); + imap_close($mbox); + if ($str_errors.$str_error_delete) { + return array('hasError' => true, 'errors' => array($str_errors.$str_error_delete)); + } + else { + return array('hasError' => false, 'errors' => ''); + } + } } diff --git a/controllers/admin/AdminCustomersController.php b/controllers/admin/AdminCustomersController.php index e00c2dac..26dc269f 100644 --- a/controllers/admin/AdminCustomersController.php +++ b/controllers/admin/AdminCustomersController.php @@ -29,737 +29,753 @@ */ class AdminCustomersControllerCore extends AdminController { - protected $delete_mode; - - protected $_defaultOrderBy = 'date_add'; - protected $_defaultOrderWay = 'DESC'; - protected $can_add_customer = true; - protected static $meaning_status = array(); - - public function __construct() - { - $this->bootstrap = true; - $this->required_database = true; - $this->required_fields = array('newsletter','optin'); - $this->table = 'customer'; - $this->className = 'Customer'; - $this->lang = false; - $this->deleted = true; - $this->explicitSelect = true; - - $this->allow_export = true; - - $this->addRowAction('edit'); - $this->addRowAction('view'); - $this->addRowAction('delete'); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); - - $this->context = Context::getContext(); - - $this->default_form_language = $this->context->language->id; - - $titles_array = array(); - $genders = Gender::getGenders($this->context->language->id); - foreach ($genders as $gender) - { - /** @var Gender $gender */ - $titles_array[$gender->id_gender] = $gender->name; - } - - $this->_select = ' - a.date_add, gl.name as title, ( - SELECT SUM(total_paid_real / conversion_rate) - FROM '._DB_PREFIX_.'orders o - WHERE o.id_customer = a.id_customer - '.Shop::addSqlRestriction(Shop::SHARE_ORDER, 'o').' - AND o.valid = 1 - ) as total_spent, ( - SELECT c.date_add FROM '._DB_PREFIX_.'guest g - LEFT JOIN '._DB_PREFIX_.'connections c ON c.id_guest = g.id_guest - WHERE g.id_customer = a.id_customer - ORDER BY c.date_add DESC - LIMIT 1 - ) as connect'; - $this->_join = 'LEFT JOIN '._DB_PREFIX_.'gender_lang gl ON (a.id_gender = gl.id_gender AND gl.id_lang = '.(int)$this->context->language->id.')'; - $this->_use_found_rows = false; - $this->fields_list = array( - 'id_customer' => array( - 'title' => $this->l('ID'), - 'align' => 'text-center', - 'class' => 'fixed-width-xs' - ), - 'title' => array( - 'title' => $this->l('Social title'), - 'filter_key' => 'a!id_gender', - 'type' => 'select', - 'list' => $titles_array, - 'filter_type' => 'int', - 'order_key' => 'gl!name' - ), - 'firstname' => array( - 'title' => $this->l('First name') - ), - 'lastname' => array( - 'title' => $this->l('Last name') - ), - 'email' => array( - 'title' => $this->l('Email address') - ), - ); - - if (Configuration::get('PS_B2B_ENABLE')) - { - $this->fields_list = array_merge($this->fields_list, array( - 'company' => array( - 'title' => $this->l('Company') - ), - )); - } - - $this->fields_list = array_merge($this->fields_list, array( - 'total_spent' => array( - 'title' => $this->l('Sales'), - 'type' => 'price', - 'search' => false, - 'havingFilter' => true, - 'align' => 'text-right', - 'badge_success' => true - ), - 'active' => array( - 'title' => $this->l('Enabled'), - 'align' => 'text-center', - 'active' => 'status', - 'type' => 'bool', - 'orderby' => false, - 'filter_key' => 'a!active' - ), - 'newsletter' => array( - 'title' => $this->l('Newsletter'), - 'align' => 'text-center', - 'type' => 'bool', - 'callback' => 'printNewsIcon', - 'orderby' => false - ), - 'optin' => array( - 'title' => $this->l('Opt-in'), - 'align' => 'text-center', - 'type' => 'bool', - 'callback' => 'printOptinIcon', - 'orderby' => false - ), - 'date_add' => array( - 'title' => $this->l('Registration'), - 'type' => 'date', - 'align' => 'text-right' - ), - 'connect' => array( - 'title' => $this->l('Last visit'), - 'type' => 'datetime', - 'search' => false, - 'havingFilter' => true - ) - )); - - $this->shopLinkType = 'shop'; - $this->shopShareDatas = Shop::SHARE_CUSTOMER; - - parent::__construct(); - - // Check if we can add a customer - if (Shop::isFeatureActive() && (Shop::getContext() == Shop::CONTEXT_ALL || Shop::getContext() == Shop::CONTEXT_GROUP)) - $this->can_add_customer = false; - - self::$meaning_status = array( - 'open' => $this->l('Open'), - 'closed' => $this->l('Closed'), - 'pending1' => $this->l('Pending 1'), - 'pending2' => $this->l('Pending 2') - ); - } - - public function postProcess() - { - if (!$this->can_add_customer && $this->display == 'add') - $this->redirect_after = $this->context->link->getAdminLink('AdminCustomers'); - - parent::postProcess(); - } - - public function initContent() - { - if ($this->action == 'select_delete') - $this->context->smarty->assign(array( - 'delete_form' => true, - 'url_delete' => htmlentities($_SERVER['REQUEST_URI']), - 'boxes' => $this->boxes, - )); - - if (!$this->can_add_customer && !$this->display) - $this->informations[] = $this->l('You have to select a shop if you want to create a customer.'); - - parent::initContent(); - } - - public function initToolbar() - { - parent::initToolbar(); - - if (!$this->can_add_customer) - unset($this->toolbar_btn['new']); - elseif (!$this->display && $this->can_import) - $this->toolbar_btn['import'] = array( - 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=customers', - 'desc' => $this->l('Import') - ); - } - - public function getList($id_lang, $orderBy = null, $orderWay = null, $start = 0, $limit = null, $id_lang_shop = null) - { - parent::getList($id_lang, $orderBy, $orderWay, $start, $limit, $id_lang_shop); - - if ($this->_list) - foreach ($this->_list as &$row) - $row['badge_success'] = $row['total_spent'] > 0; - } - - - public function initToolbarTitle() - { - parent::initToolbarTitle(); - - switch ($this->display) - { - case '': - case 'list': - array_pop($this->toolbar_title); - $this->toolbar_title[] = $this->l('Manage your Customers'); - break; - case 'view': - /** @var Customer $customer */ - if (($customer = $this->loadObject(true)) && Validate::isLoadedObject($customer)) - array_pop($this->toolbar_title); - $this->toolbar_title[] = sprintf('Information about Customer: %s', Tools::substr($customer->firstname, 0, 1).'. '.$customer->lastname); - break; - case 'add': - case 'edit': - array_pop($this->toolbar_title); - /** @var Customer $customer */ - if (($customer = $this->loadObject(true)) && Validate::isLoadedObject($customer)) - $this->toolbar_title[] = sprintf($this->l('Editing Customer: %s'), Tools::substr($customer->firstname, 0, 1).'. '.$customer->lastname); - else - $this->toolbar_title[] = $this->l('Creating a new Customer'); - break; - } - - array_pop($this->meta_title); - if (count($this->toolbar_title) > 0) - $this->addMetaTitle($this->toolbar_title[count($this->toolbar_title) - 1]); - } - - public function initPageHeaderToolbar() - { - if (empty($this->display) && $this->can_add_customer) - $this->page_header_toolbar_btn['new_customer'] = array( - 'href' => self::$currentIndex.'&addcustomer&token='.$this->token, - 'desc' => $this->l('Add new customer', null, null, false), - 'icon' => 'process-icon-new' - ); - - parent::initPageHeaderToolbar(); - } - - public function initProcess() - { - parent::initProcess(); - - if (Tools::isSubmit('submitGuestToCustomer') && $this->id_object) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'guest_to_customer'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('changeNewsletterVal') && $this->id_object) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'change_newsletter_val'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('changeOptinVal') && $this->id_object) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'change_optin_val'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - - // When deleting, first display a form to select the type of deletion - if ($this->action == 'delete' || $this->action == 'bulkdelete') - if (Tools::getValue('deleteMode') == 'real' || Tools::getValue('deleteMode') == 'deleted') - $this->delete_mode = Tools::getValue('deleteMode'); - else - $this->action = 'select_delete'; - } - - public function renderList() - { - if ((Tools::isSubmit('submitBulkdelete'.$this->table) || Tools::isSubmit('delete'.$this->table)) && $this->tabAccess['delete'] === '1') - $this->tpl_list_vars = array( - 'delete_customer' => true, - 'REQUEST_URI' => $_SERVER['REQUEST_URI'], - 'POST' => $_POST - ); - - return parent::renderList(); - } - - public function renderForm() - { - /** @var Customer $obj */ - if (!($obj = $this->loadObject(true))) - return; - - $genders = Gender::getGenders(); - $list_genders = array(); - foreach ($genders as $key => $gender) - { - /** @var Gender $gender */ - $list_genders[$key]['id'] = 'gender_'.$gender->id; - $list_genders[$key]['value'] = $gender->id; - $list_genders[$key]['label'] = $gender->name; - } - - $years = Tools::dateYears(); - $months = Tools::dateMonths(); - $days = Tools::dateDays(); - - $groups = Group::getGroups($this->default_form_language, true); - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Customer'), - 'icon' => 'icon-user' - ), - 'input' => array( - array( - 'type' => 'radio', - 'label' => $this->l('Social title'), - 'name' => 'id_gender', - 'required' => false, - 'class' => 't', - 'values' => $list_genders - ), - array( - 'type' => 'text', - 'label' => $this->l('First name'), - 'name' => 'firstname', - 'required' => true, - 'col' => '4', - 'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()@#"°{}_$%:' - ), - array( - 'type' => 'text', - 'label' => $this->l('Last name'), - 'name' => 'lastname', - 'required' => true, - 'col' => '4', - 'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()@#"°{}_$%:' - ), - array( - 'type' => 'text', - 'prefix' => '<i class="icon-envelope-o"></i>', - 'label' => $this->l('Email address'), - 'name' => 'email', - 'col' => '4', - 'required' => true, - 'autocomplete' => false - ), - array( - 'type' => 'password', - 'label' => $this->l('Password'), - 'name' => 'passwd', - 'required' => ($obj->id ? false : true), - 'col' => '4', - 'hint' => ($obj->id ? $this->l('Leave this field blank if there\'s no change.') : - sprintf($this->l('Password should be at least %s characters long.'), Validate::PASSWORD_LENGTH)) - ), - array( - 'type' => 'birthday', - 'label' => $this->l('Birthday'), - 'name' => 'birthday', - 'options' => array( - 'days' => $days, - 'months' => $months, - 'years' => $years - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Enabled'), - 'name' => 'active', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Enable or disable customer login.') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Newsletter'), - 'name' => 'newsletter', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'newsletter_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'newsletter_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'disabled' => (bool)!Configuration::get('PS_CUSTOMER_NWSL'), - 'hint' => $this->l('This customer will receive your newsletter via email.') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Opt-in'), - 'name' => 'optin', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'optin_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'optin_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'disabled' => (bool)!Configuration::get('PS_CUSTOMER_OPTIN'), - 'hint' => $this->l('This customer will receive your ads via email.') - ), - ) - ); - - // if we add a customer via fancybox (ajax), it's a customer and he doesn't need to be added to the visitor and guest groups - if (Tools::isSubmit('addcustomer') && Tools::isSubmit('submitFormAjax')) - { - $visitor_group = Configuration::get('PS_UNIDENTIFIED_GROUP'); - $guest_group = Configuration::get('PS_GUEST_GROUP'); - foreach ($groups as $key => $g) - if (in_array($g['id_group'], array($visitor_group, $guest_group))) - unset($groups[$key]); - } - - $this->fields_form['input'] = array_merge( - $this->fields_form['input'], - array( - array( - 'type' => 'group', - 'label' => $this->l('Group access'), - 'name' => 'groupBox', - 'values' => $groups, - 'required' => true, - 'col' => '6', - 'hint' => $this->l('Select all the groups that you would like to apply to this customer.') - ), - array( - 'type' => 'select', - 'label' => $this->l('Default customer group'), - 'name' => 'id_default_group', - 'options' => array( - 'query' => $groups, - 'id' => 'id_group', - 'name' => 'name' - ), - 'col' => '4', - 'hint' => array( - $this->l('This group will be the user\'s default group.'), - $this->l('Only the discount for the selected group will be applied to this customer.') - ) - ) - ) - ); - - // if customer is a guest customer, password hasn't to be there - if ($obj->id && ($obj->is_guest && $obj->id_default_group == Configuration::get('PS_GUEST_GROUP'))) - { - foreach ($this->fields_form['input'] as $k => $field) - if ($field['type'] == 'password') - array_splice($this->fields_form['input'], $k, 1); - } - - if (Configuration::get('PS_B2B_ENABLE')) - { - $risks = Risk::getRisks(); - - $list_risks = array(); - foreach ($risks as $key => $risk) - { - /** @var Risk $risk */ - $list_risks[$key]['id_risk'] = (int)$risk->id; - $list_risks[$key]['name'] = $risk->name; - } - - $this->fields_form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('Company'), - 'name' => 'company' - ); - $this->fields_form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('SIRET'), - 'name' => 'siret' - ); - $this->fields_form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('APE'), - 'name' => 'ape' - ); - $this->fields_form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('Website'), - 'name' => 'website' - ); - $this->fields_form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('Allowed outstanding amount'), - 'name' => 'outstanding_allow_amount', - 'hint' => $this->l('Valid characters:').' 0-9', - 'suffix' => $this->context->currency->sign - ); - $this->fields_form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('Maximum number of payment days'), - 'name' => 'max_payment_days', - 'hint' => $this->l('Valid characters:').' 0-9' - ); - $this->fields_form['input'][] = array( - 'type' => 'select', - 'label' => $this->l('Risk rating'), - 'name' => 'id_risk', - 'required' => false, - 'class' => 't', - 'options' => array( - 'query' => $list_risks, - 'id' => 'id_risk', - 'name' => 'name' - ), - ); - } - - $this->fields_form['submit'] = array( - 'title' => $this->l('Save'), - ); - - $birthday = explode('-', $this->getFieldValue($obj, 'birthday')); - - $this->fields_value = array( - 'years' => $this->getFieldValue($obj, 'birthday') ? $birthday[0] : 0, - 'months' => $this->getFieldValue($obj, 'birthday') ? $birthday[1] : 0, - 'days' => $this->getFieldValue($obj, 'birthday') ? $birthday[2] : 0, - ); - - // Added values of object Group - if (!Validate::isUnsignedId($obj->id)) - $customer_groups = array(); - else - $customer_groups = $obj->getGroups(); - $customer_groups_ids = array(); - if (is_array($customer_groups)) - foreach ($customer_groups as $customer_group) - $customer_groups_ids[] = $customer_group; - - // if empty $carrier_groups_ids : object creation : we set the default groups - if (empty($customer_groups_ids)) - { - $preselected = array(Configuration::get('PS_UNIDENTIFIED_GROUP'), Configuration::get('PS_GUEST_GROUP'), Configuration::get('PS_CUSTOMER_GROUP')); - $customer_groups_ids = array_merge($customer_groups_ids, $preselected); - } - - foreach ($groups as $group) - $this->fields_value['groupBox_'.$group['id_group']] = - Tools::getValue('groupBox_'.$group['id_group'], in_array($group['id_group'], $customer_groups_ids)); - - return parent::renderForm(); - } - - public function beforeAdd($customer) - { - $customer->id_shop = $this->context->shop->id; - } - - public function renderKpis() - { - $time = time(); - $kpis = array(); - - /* The data generation is located in AdminStatsControllerCore */ - - $helper = new HelperKpi(); - $helper->id = 'box-gender'; - $helper->icon = 'icon-male'; - $helper->color = 'color1'; - $helper->title = $this->l('Customers', null, null, false); - $helper->subtitle = $this->l('All Time', null, null, false); - if (ConfigurationKPI::get('CUSTOMER_MAIN_GENDER', $this->context->language->id) !== false) - $helper->value = ConfigurationKPI::get('CUSTOMER_MAIN_GENDER', $this->context->language->id); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=customer_main_gender'; - $helper->refresh = (bool)(ConfigurationKPI::get('CUSTOMER_MAIN_GENDER_EXPIRE', $this->context->language->id) < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-age'; - $helper->icon = 'icon-calendar'; - $helper->color = 'color2'; - $helper->title = $this->l('Average Age', 'AdminTab', null, false); - $helper->subtitle = $this->l('All Time', null, null, false); - if (ConfigurationKPI::get('AVG_CUSTOMER_AGE', $this->context->language->id) !== false) - $helper->value = ConfigurationKPI::get('AVG_CUSTOMER_AGE', $this->context->language->id); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=avg_customer_age'; - $helper->refresh = (bool)(ConfigurationKPI::get('AVG_CUSTOMER_AGE_EXPIRE', $this->context->language->id) < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-orders'; - $helper->icon = 'icon-retweet'; - $helper->color = 'color3'; - $helper->title = $this->l('Orders per Customer', null, null, false); - $helper->subtitle = $this->l('All Time', null, null, false); - if (ConfigurationKPI::get('ORDERS_PER_CUSTOMER') !== false) - $helper->value = ConfigurationKPI::get('ORDERS_PER_CUSTOMER'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=orders_per_customer'; - $helper->refresh = (bool)(ConfigurationKPI::get('ORDERS_PER_CUSTOMER_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-newsletter'; - $helper->icon = 'icon-envelope'; - $helper->color = 'color4'; - $helper->title = $this->l('Newsletter Registrations', null, null, false); - $helper->subtitle = $this->l('All Time', null, null, false); - if (ConfigurationKPI::get('NEWSLETTER_REGISTRATIONS') !== false) - $helper->value = ConfigurationKPI::get('NEWSLETTER_REGISTRATIONS'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=newsletter_registrations'; - $helper->refresh = (bool)(ConfigurationKPI::get('NEWSLETTER_REGISTRATIONS_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpiRow(); - $helper->kpis = $kpis; - return $helper->generate(); - } - - public function renderView() - { - /** @var Customer $customer */ - if (!($customer = $this->loadObject())) - return; - - $this->context->customer = $customer; - $gender = new Gender($customer->id_gender, $this->context->language->id); - $gender_image = $gender->getImage(); - - $customer_stats = $customer->getStats(); - $sql = 'SELECT SUM(total_paid_real) FROM '._DB_PREFIX_.'orders WHERE id_customer = %d AND valid = 1'; - if ($total_customer = Db::getInstance()->getValue(sprintf($sql, $customer->id))) - { - $sql = 'SELECT SQL_CALC_FOUND_ROWS COUNT(*) FROM '._DB_PREFIX_.'orders WHERE valid = 1 AND id_customer != '.(int)$customer->id.' GROUP BY id_customer HAVING SUM(total_paid_real) > %d'; - Db::getInstance()->getValue(sprintf($sql, (int)$total_customer)); - $count_better_customers = (int)Db::getInstance()->getValue('SELECT FOUND_ROWS()') + 1; - } - else - $count_better_customers = '-'; - - $orders = Order::getCustomerOrders($customer->id, true); - $total_orders = count($orders); - for ($i = 0; $i < $total_orders; $i++) - { - $orders[$i]['total_paid_real_not_formated'] = $orders[$i]['total_paid_real']; - $orders[$i]['total_paid_real'] = Tools::displayPrice($orders[$i]['total_paid_real'], new Currency((int)$orders[$i]['id_currency'])); - } - - $messages = CustomerThread::getCustomerMessages((int)$customer->id); - - $total_messages = count($messages); - for ($i = 0; $i < $total_messages; $i++) - { - $messages[$i]['message'] = substr(strip_tags(html_entity_decode($messages[$i]['message'], ENT_NOQUOTES, 'UTF-8')), 0, 75); - $messages[$i]['date_add'] = Tools::displayDate($messages[$i]['date_add'], null, true); - if (isset(self::$meaning_status[$messages[$i]['status']])) - $messages[$i]['status'] = self::$meaning_status[$messages[$i]['status']]; - } - - $groups = $customer->getGroups(); - $total_groups = count($groups); - for ($i = 0; $i < $total_groups; $i++) - { - $group = new Group($groups[$i]); - $groups[$i] = array(); - $groups[$i]['id_group'] = $group->id; - $groups[$i]['name'] = $group->name[$this->default_form_language]; - } - - $total_ok = 0; - $orders_ok = array(); - $orders_ko = array(); - foreach ($orders as $order) - { - if (!isset($order['order_state'])) - $order['order_state'] = $this->l('There is no status defined for this order.'); - - if ($order['valid']) - { - $orders_ok[] = $order; - $total_ok += $order['total_paid_real_not_formated']; - } - else - $orders_ko[] = $order; - } - - $products = $customer->getBoughtProducts(); - - $carts = Cart::getCustomerCarts($customer->id); - $total_carts = count($carts); - for ($i = 0; $i < $total_carts; $i++) - { - $cart = new Cart((int)$carts[$i]['id_cart']); - $this->context->cart = $cart; - $summary = $cart->getSummaryDetails(); - $currency = new Currency((int)$carts[$i]['id_currency']); - $carrier = new Carrier((int)$carts[$i]['id_carrier']); - $carts[$i]['id_cart'] = sprintf('%06d', $carts[$i]['id_cart']); - $carts[$i]['date_add'] = Tools::displayDate($carts[$i]['date_add'], null, true); - $carts[$i]['total_price'] = Tools::displayPrice($summary['total_price'], $currency); - $carts[$i]['name'] = $carrier->name; - } - - $sql = 'SELECT DISTINCT cp.id_product, c.id_cart, c.id_shop, cp.id_shop AS cp_id_shop + protected $delete_mode; + + protected $_defaultOrderBy = 'date_add'; + protected $_defaultOrderWay = 'DESC'; + protected $can_add_customer = true; + protected static $meaning_status = array(); + + public function __construct() + { + $this->bootstrap = true; + $this->required_database = true; + $this->required_fields = array('newsletter','optin'); + $this->table = 'customer'; + $this->className = 'Customer'; + $this->lang = false; + $this->deleted = true; + $this->explicitSelect = true; + + $this->allow_export = true; + + $this->addRowAction('edit'); + $this->addRowAction('view'); + $this->addRowAction('delete'); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); + + $this->context = Context::getContext(); + + $this->default_form_language = $this->context->language->id; + + $titles_array = array(); + $genders = Gender::getGenders($this->context->language->id); + foreach ($genders as $gender) { + /** @var Gender $gender */ + $titles_array[$gender->id_gender] = $gender->name; + } + + $this->_join = 'LEFT JOIN '._DB_PREFIX_.'gender_lang gl ON (a.id_gender = gl.id_gender AND gl.id_lang = '.(int)$this->context->language->id.')'; + $this->_use_found_rows = false; + $this->fields_list = array( + 'id_customer' => array( + 'title' => $this->l('ID'), + 'align' => 'text-center', + 'class' => 'fixed-width-xs' + ), + 'title' => array( + 'title' => $this->l('Social title'), + 'filter_key' => 'a!id_gender', + 'type' => 'select', + 'list' => $titles_array, + 'filter_type' => 'int', + 'order_key' => 'gl!name' + ), + 'firstname' => array( + 'title' => $this->l('First name') + ), + 'lastname' => array( + 'title' => $this->l('Last name') + ), + 'email' => array( + 'title' => $this->l('Email address') + ), + ); + + if (Configuration::get('PS_B2B_ENABLE')) { + $this->fields_list = array_merge($this->fields_list, array( + 'company' => array( + 'title' => $this->l('Company') + ), + )); + } + + $this->fields_list = array_merge($this->fields_list, array( + 'total_spent' => array( + 'title' => $this->l('Sales'), + 'type' => 'price', + 'search' => false, + 'havingFilter' => true, + 'align' => 'text-right', + 'badge_success' => true + ), + 'active' => array( + 'title' => $this->l('Enabled'), + 'align' => 'text-center', + 'active' => 'status', + 'type' => 'bool', + 'orderby' => false, + 'filter_key' => 'a!active' + ), + 'newsletter' => array( + 'title' => $this->l('Newsletter'), + 'align' => 'text-center', + 'type' => 'bool', + 'callback' => 'printNewsIcon', + 'orderby' => false + ), + 'optin' => array( + 'title' => $this->l('Opt-in'), + 'align' => 'text-center', + 'type' => 'bool', + 'callback' => 'printOptinIcon', + 'orderby' => false + ), + 'date_add' => array( + 'title' => $this->l('Registration'), + 'type' => 'date', + 'align' => 'text-right' + ), + 'connect' => array( + 'title' => $this->l('Last visit'), + 'type' => 'datetime', + 'search' => false, + 'havingFilter' => true + ) + )); + + $this->shopLinkType = 'shop'; + $this->shopShareDatas = Shop::SHARE_CUSTOMER; + + parent::__construct(); + + $this->_select = ' + a.date_add, gl.name as title, ( + SELECT SUM(total_paid_real / conversion_rate) + FROM '._DB_PREFIX_.'orders o + WHERE o.id_customer = a.id_customer + '.Shop::addSqlRestriction(Shop::SHARE_ORDER, 'o').' + AND o.valid = 1 + ) as total_spent, ( + SELECT c.date_add FROM '._DB_PREFIX_.'guest g + LEFT JOIN '._DB_PREFIX_.'connections c ON c.id_guest = g.id_guest + WHERE g.id_customer = a.id_customer + ORDER BY c.date_add DESC + LIMIT 1 + ) as connect'; + + // Check if we can add a customer + if (Shop::isFeatureActive() && (Shop::getContext() == Shop::CONTEXT_ALL || Shop::getContext() == Shop::CONTEXT_GROUP)) { + $this->can_add_customer = false; + } + + self::$meaning_status = array( + 'open' => $this->l('Open'), + 'closed' => $this->l('Closed'), + 'pending1' => $this->l('Pending 1'), + 'pending2' => $this->l('Pending 2') + ); + } + + public function postProcess() + { + if (!$this->can_add_customer && $this->display == 'add') { + $this->redirect_after = $this->context->link->getAdminLink('AdminCustomers'); + } + + parent::postProcess(); + } + + public function initContent() + { + if ($this->action == 'select_delete') { + $this->context->smarty->assign(array( + 'delete_form' => true, + 'url_delete' => htmlentities($_SERVER['REQUEST_URI']), + 'boxes' => $this->boxes, + )); + } + + if (!$this->can_add_customer && !$this->display) { + $this->informations[] = $this->l('You have to select a shop if you want to create a customer.'); + } + + parent::initContent(); + } + + public function initToolbar() + { + parent::initToolbar(); + + if (!$this->can_add_customer) { + unset($this->toolbar_btn['new']); + } elseif (!$this->display && $this->can_import) { + $this->toolbar_btn['import'] = array( + 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=customers', + 'desc' => $this->l('Import') + ); + } + } + + public function getList($id_lang, $orderBy = null, $orderWay = null, $start = 0, $limit = null, $id_lang_shop = null) + { + parent::getList($id_lang, $orderBy, $orderWay, $start, $limit, $id_lang_shop); + + if ($this->_list) { + foreach ($this->_list as &$row) { + $row['badge_success'] = $row['total_spent'] > 0; + } + } + } + + + public function initToolbarTitle() + { + parent::initToolbarTitle(); + + switch ($this->display) { + case '': + case 'list': + array_pop($this->toolbar_title); + $this->toolbar_title[] = $this->l('Manage your Customers'); + break; + case 'view': + /** @var Customer $customer */ + if (($customer = $this->loadObject(true)) && Validate::isLoadedObject($customer)) { + array_pop($this->toolbar_title); + } + $this->toolbar_title[] = sprintf('Information about Customer: %s', Tools::substr($customer->firstname, 0, 1).'. '.$customer->lastname); + break; + case 'add': + case 'edit': + array_pop($this->toolbar_title); + /** @var Customer $customer */ + if (($customer = $this->loadObject(true)) && Validate::isLoadedObject($customer)) { + $this->toolbar_title[] = sprintf($this->l('Editing Customer: %s'), Tools::substr($customer->firstname, 0, 1).'. '.$customer->lastname); + } else { + $this->toolbar_title[] = $this->l('Creating a new Customer'); + } + break; + } + + array_pop($this->meta_title); + if (count($this->toolbar_title) > 0) { + $this->addMetaTitle($this->toolbar_title[count($this->toolbar_title) - 1]); + } + } + + public function initPageHeaderToolbar() + { + if (empty($this->display) && $this->can_add_customer) { + $this->page_header_toolbar_btn['new_customer'] = array( + 'href' => self::$currentIndex.'&addcustomer&token='.$this->token, + 'desc' => $this->l('Add new customer', null, null, false), + 'icon' => 'process-icon-new' + ); + } + + parent::initPageHeaderToolbar(); + } + + public function initProcess() + { + parent::initProcess(); + + if (Tools::isSubmit('submitGuestToCustomer') && $this->id_object) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'guest_to_customer'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('changeNewsletterVal') && $this->id_object) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'change_newsletter_val'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('changeOptinVal') && $this->id_object) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'change_optin_val'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + + // When deleting, first display a form to select the type of deletion + if ($this->action == 'delete' || $this->action == 'bulkdelete') { + if (Tools::getValue('deleteMode') == 'real' || Tools::getValue('deleteMode') == 'deleted') { + $this->delete_mode = Tools::getValue('deleteMode'); + } else { + $this->action = 'select_delete'; + } + } + } + + public function renderList() + { + if ((Tools::isSubmit('submitBulkdelete'.$this->table) || Tools::isSubmit('delete'.$this->table)) && $this->tabAccess['delete'] === '1') { + $this->tpl_list_vars = array( + 'delete_customer' => true, + 'REQUEST_URI' => $_SERVER['REQUEST_URI'], + 'POST' => $_POST + ); + } + + return parent::renderList(); + } + + public function renderForm() + { + /** @var Customer $obj */ + if (!($obj = $this->loadObject(true))) { + return; + } + + $genders = Gender::getGenders(); + $list_genders = array(); + foreach ($genders as $key => $gender) { + /** @var Gender $gender */ + $list_genders[$key]['id'] = 'gender_'.$gender->id; + $list_genders[$key]['value'] = $gender->id; + $list_genders[$key]['label'] = $gender->name; + } + + $years = Tools::dateYears(); + $months = Tools::dateMonths(); + $days = Tools::dateDays(); + + $groups = Group::getGroups($this->default_form_language, true); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Customer'), + 'icon' => 'icon-user' + ), + 'input' => array( + array( + 'type' => 'radio', + 'label' => $this->l('Social title'), + 'name' => 'id_gender', + 'required' => false, + 'class' => 't', + 'values' => $list_genders + ), + array( + 'type' => 'text', + 'label' => $this->l('First name'), + 'name' => 'firstname', + 'required' => true, + 'col' => '4', + 'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()@#"°{}_$%:' + ), + array( + 'type' => 'text', + 'label' => $this->l('Last name'), + 'name' => 'lastname', + 'required' => true, + 'col' => '4', + 'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()@#"°{}_$%:' + ), + array( + 'type' => 'text', + 'prefix' => '<i class="icon-envelope-o"></i>', + 'label' => $this->l('Email address'), + 'name' => 'email', + 'col' => '4', + 'required' => true, + 'autocomplete' => false + ), + array( + 'type' => 'password', + 'label' => $this->l('Password'), + 'name' => 'passwd', + 'required' => ($obj->id ? false : true), + 'col' => '4', + 'hint' => ($obj->id ? $this->l('Leave this field blank if there\'s no change.') : + sprintf($this->l('Password should be at least %s characters long.'), Validate::PASSWORD_LENGTH)) + ), + array( + 'type' => 'birthday', + 'label' => $this->l('Birthday'), + 'name' => 'birthday', + 'options' => array( + 'days' => $days, + 'months' => $months, + 'years' => $years + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Enabled'), + 'name' => 'active', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Enable or disable customer login.') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Newsletter'), + 'name' => 'newsletter', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'newsletter_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'newsletter_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'disabled' => (bool)!Configuration::get('PS_CUSTOMER_NWSL'), + 'hint' => $this->l('This customer will receive your newsletter via email.') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Opt-in'), + 'name' => 'optin', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'optin_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'optin_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'disabled' => (bool)!Configuration::get('PS_CUSTOMER_OPTIN'), + 'hint' => $this->l('This customer will receive your ads via email.') + ), + ) + ); + + // if we add a customer via fancybox (ajax), it's a customer and he doesn't need to be added to the visitor and guest groups + if (Tools::isSubmit('addcustomer') && Tools::isSubmit('submitFormAjax')) { + $visitor_group = Configuration::get('PS_UNIDENTIFIED_GROUP'); + $guest_group = Configuration::get('PS_GUEST_GROUP'); + foreach ($groups as $key => $g) { + if (in_array($g['id_group'], array($visitor_group, $guest_group))) { + unset($groups[$key]); + } + } + } + + $this->fields_form['input'] = array_merge( + $this->fields_form['input'], + array( + array( + 'type' => 'group', + 'label' => $this->l('Group access'), + 'name' => 'groupBox', + 'values' => $groups, + 'required' => true, + 'col' => '6', + 'hint' => $this->l('Select all the groups that you would like to apply to this customer.') + ), + array( + 'type' => 'select', + 'label' => $this->l('Default customer group'), + 'name' => 'id_default_group', + 'options' => array( + 'query' => $groups, + 'id' => 'id_group', + 'name' => 'name' + ), + 'col' => '4', + 'hint' => array( + $this->l('This group will be the user\'s default group.'), + $this->l('Only the discount for the selected group will be applied to this customer.') + ) + ) + ) + ); + + // if customer is a guest customer, password hasn't to be there + if ($obj->id && ($obj->is_guest && $obj->id_default_group == Configuration::get('PS_GUEST_GROUP'))) { + foreach ($this->fields_form['input'] as $k => $field) { + if ($field['type'] == 'password') { + array_splice($this->fields_form['input'], $k, 1); + } + } + } + + if (Configuration::get('PS_B2B_ENABLE')) { + $risks = Risk::getRisks(); + + $list_risks = array(); + foreach ($risks as $key => $risk) { + /** @var Risk $risk */ + $list_risks[$key]['id_risk'] = (int)$risk->id; + $list_risks[$key]['name'] = $risk->name; + } + + $this->fields_form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('Company'), + 'name' => 'company' + ); + $this->fields_form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('SIRET'), + 'name' => 'siret' + ); + $this->fields_form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('APE'), + 'name' => 'ape' + ); + $this->fields_form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('Website'), + 'name' => 'website' + ); + $this->fields_form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('Allowed outstanding amount'), + 'name' => 'outstanding_allow_amount', + 'hint' => $this->l('Valid characters:').' 0-9', + 'suffix' => $this->context->currency->sign + ); + $this->fields_form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('Maximum number of payment days'), + 'name' => 'max_payment_days', + 'hint' => $this->l('Valid characters:').' 0-9' + ); + $this->fields_form['input'][] = array( + 'type' => 'select', + 'label' => $this->l('Risk rating'), + 'name' => 'id_risk', + 'required' => false, + 'class' => 't', + 'options' => array( + 'query' => $list_risks, + 'id' => 'id_risk', + 'name' => 'name' + ), + ); + } + + $this->fields_form['submit'] = array( + 'title' => $this->l('Save'), + ); + + $birthday = explode('-', $this->getFieldValue($obj, 'birthday')); + + $this->fields_value = array( + 'years' => $this->getFieldValue($obj, 'birthday') ? $birthday[0] : 0, + 'months' => $this->getFieldValue($obj, 'birthday') ? $birthday[1] : 0, + 'days' => $this->getFieldValue($obj, 'birthday') ? $birthday[2] : 0, + ); + + // Added values of object Group + if (!Validate::isUnsignedId($obj->id)) { + $customer_groups = array(); + } else { + $customer_groups = $obj->getGroups(); + } + $customer_groups_ids = array(); + if (is_array($customer_groups)) { + foreach ($customer_groups as $customer_group) { + $customer_groups_ids[] = $customer_group; + } + } + + // if empty $carrier_groups_ids : object creation : we set the default groups + if (empty($customer_groups_ids)) { + $preselected = array(Configuration::get('PS_UNIDENTIFIED_GROUP'), Configuration::get('PS_GUEST_GROUP'), Configuration::get('PS_CUSTOMER_GROUP')); + $customer_groups_ids = array_merge($customer_groups_ids, $preselected); + } + + foreach ($groups as $group) { + $this->fields_value['groupBox_'.$group['id_group']] = + Tools::getValue('groupBox_'.$group['id_group'], in_array($group['id_group'], $customer_groups_ids)); + } + + return parent::renderForm(); + } + + public function beforeAdd($customer) + { + $customer->id_shop = $this->context->shop->id; + } + + public function renderKpis() + { + $time = time(); + $kpis = array(); + + /* The data generation is located in AdminStatsControllerCore */ + + $helper = new HelperKpi(); + $helper->id = 'box-gender'; + $helper->icon = 'icon-male'; + $helper->color = 'color1'; + $helper->title = $this->l('Customers', null, null, false); + $helper->subtitle = $this->l('All Time', null, null, false); + if (ConfigurationKPI::get('CUSTOMER_MAIN_GENDER', $this->context->language->id) !== false) { + $helper->value = ConfigurationKPI::get('CUSTOMER_MAIN_GENDER', $this->context->language->id); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=customer_main_gender'; + $helper->refresh = (bool)(ConfigurationKPI::get('CUSTOMER_MAIN_GENDER_EXPIRE', $this->context->language->id) < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-age'; + $helper->icon = 'icon-calendar'; + $helper->color = 'color2'; + $helper->title = $this->l('Average Age', 'AdminTab', null, false); + $helper->subtitle = $this->l('All Time', null, null, false); + if (ConfigurationKPI::get('AVG_CUSTOMER_AGE', $this->context->language->id) !== false) { + $helper->value = ConfigurationKPI::get('AVG_CUSTOMER_AGE', $this->context->language->id); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=avg_customer_age'; + $helper->refresh = (bool)(ConfigurationKPI::get('AVG_CUSTOMER_AGE_EXPIRE', $this->context->language->id) < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-orders'; + $helper->icon = 'icon-retweet'; + $helper->color = 'color3'; + $helper->title = $this->l('Orders per Customer', null, null, false); + $helper->subtitle = $this->l('All Time', null, null, false); + if (ConfigurationKPI::get('ORDERS_PER_CUSTOMER') !== false) { + $helper->value = ConfigurationKPI::get('ORDERS_PER_CUSTOMER'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=orders_per_customer'; + $helper->refresh = (bool)(ConfigurationKPI::get('ORDERS_PER_CUSTOMER_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-newsletter'; + $helper->icon = 'icon-envelope'; + $helper->color = 'color4'; + $helper->title = $this->l('Newsletter Registrations', null, null, false); + $helper->subtitle = $this->l('All Time', null, null, false); + if (ConfigurationKPI::get('NEWSLETTER_REGISTRATIONS') !== false) { + $helper->value = ConfigurationKPI::get('NEWSLETTER_REGISTRATIONS'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=newsletter_registrations'; + $helper->refresh = (bool)(ConfigurationKPI::get('NEWSLETTER_REGISTRATIONS_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpiRow(); + $helper->kpis = $kpis; + return $helper->generate(); + } + + public function renderView() + { + /** @var Customer $customer */ + if (!($customer = $this->loadObject())) { + return; + } + + $this->context->customer = $customer; + $gender = new Gender($customer->id_gender, $this->context->language->id); + $gender_image = $gender->getImage(); + + $customer_stats = $customer->getStats(); + $sql = 'SELECT SUM(total_paid_real) FROM '._DB_PREFIX_.'orders WHERE id_customer = %d AND valid = 1'; + if ($total_customer = Db::getInstance()->getValue(sprintf($sql, $customer->id))) { + $sql = 'SELECT SQL_CALC_FOUND_ROWS COUNT(*) FROM '._DB_PREFIX_.'orders WHERE valid = 1 AND id_customer != '.(int)$customer->id.' GROUP BY id_customer HAVING SUM(total_paid_real) > %d'; + Db::getInstance()->getValue(sprintf($sql, (int)$total_customer)); + $count_better_customers = (int)Db::getInstance()->getValue('SELECT FOUND_ROWS()') + 1; + } else { + $count_better_customers = '-'; + } + + $orders = Order::getCustomerOrders($customer->id, true); + $total_orders = count($orders); + for ($i = 0; $i < $total_orders; $i++) { + $orders[$i]['total_paid_real_not_formated'] = $orders[$i]['total_paid_real']; + $orders[$i]['total_paid_real'] = Tools::displayPrice($orders[$i]['total_paid_real'], new Currency((int)$orders[$i]['id_currency'])); + } + + $messages = CustomerThread::getCustomerMessages((int)$customer->id); + + $total_messages = count($messages); + for ($i = 0; $i < $total_messages; $i++) { + $messages[$i]['message'] = substr(strip_tags(html_entity_decode($messages[$i]['message'], ENT_NOQUOTES, 'UTF-8')), 0, 75); + $messages[$i]['date_add'] = Tools::displayDate($messages[$i]['date_add'], null, true); + if (isset(self::$meaning_status[$messages[$i]['status']])) { + $messages[$i]['status'] = self::$meaning_status[$messages[$i]['status']]; + } + } + + $groups = $customer->getGroups(); + $total_groups = count($groups); + for ($i = 0; $i < $total_groups; $i++) { + $group = new Group($groups[$i]); + $groups[$i] = array(); + $groups[$i]['id_group'] = $group->id; + $groups[$i]['name'] = $group->name[$this->default_form_language]; + } + + $total_ok = 0; + $orders_ok = array(); + $orders_ko = array(); + foreach ($orders as $order) { + if (!isset($order['order_state'])) { + $order['order_state'] = $this->l('There is no status defined for this order.'); + } + + if ($order['valid']) { + $orders_ok[] = $order; + $total_ok += $order['total_paid_real_not_formated']; + } else { + $orders_ko[] = $order; + } + } + + $products = $customer->getBoughtProducts(); + + $carts = Cart::getCustomerCarts($customer->id); + $total_carts = count($carts); + for ($i = 0; $i < $total_carts; $i++) { + $cart = new Cart((int)$carts[$i]['id_cart']); + $this->context->cart = $cart; + $currency = new Currency((int)$carts[$i]['id_currency']); + $this->context->currency = $currency; + $summary = $cart->getSummaryDetails(); + $carrier = new Carrier((int)$carts[$i]['id_carrier']); + $carts[$i]['id_cart'] = sprintf('%06d', $carts[$i]['id_cart']); + $carts[$i]['date_add'] = Tools::displayDate($carts[$i]['date_add'], null, true); + $carts[$i]['total_price'] = Tools::displayPrice($summary['total_price'], $currency); + $carts[$i]['name'] = $carrier->name; + } + + $this->context->currency = Currency::getDefaultCurrency(); + + $sql = 'SELECT DISTINCT cp.id_product, c.id_cart, c.id_shop, cp.id_shop AS cp_id_shop FROM '._DB_PREFIX_.'cart_product cp JOIN '._DB_PREFIX_.'cart c ON (c.id_cart = cp.id_cart) JOIN '._DB_PREFIX_.'product p ON (cp.id_product = p.id_product) @@ -770,323 +786,339 @@ class AdminCustomersControllerCore extends AdminController JOIN '._DB_PREFIX_.'order_detail od ON (o.id_order = od.id_order) WHERE product_id = cp.id_product AND o.valid = 1 AND o.id_customer = '.(int)$customer->id.' )'; - $interested = Db::getInstance()->executeS($sql); - $total_interested = count($interested); - for ($i = 0; $i < $total_interested; $i++) - { - $product = new Product($interested[$i]['id_product'], false, $this->default_form_language, $interested[$i]['id_shop']); - if (!Validate::isLoadedObject($product)) - continue; - $interested[$i]['url'] = $this->context->link->getProductLink( - $product->id, - $product->link_rewrite, - Category::getLinkRewrite($product->id_category_default, $this->default_form_language), - null, - null, - $interested[$i]['cp_id_shop'] - ); - $interested[$i]['id'] = (int)$product->id; - $interested[$i]['name'] = Tools::htmlentitiesUTF8($product->name); - } + $interested = Db::getInstance()->executeS($sql); + $total_interested = count($interested); + for ($i = 0; $i < $total_interested; $i++) { + $product = new Product($interested[$i]['id_product'], false, $this->default_form_language, $interested[$i]['id_shop']); + if (!Validate::isLoadedObject($product)) { + continue; + } + $interested[$i]['url'] = $this->context->link->getProductLink( + $product->id, + $product->link_rewrite, + Category::getLinkRewrite($product->id_category_default, $this->default_form_language), + null, + null, + $interested[$i]['cp_id_shop'] + ); + $interested[$i]['id'] = (int)$product->id; + $interested[$i]['name'] = Tools::htmlentitiesUTF8($product->name); + } - $emails = $customer->getLastEmails(); + $emails = $customer->getLastEmails(); - $connections = $customer->getLastConnections(); - if (!is_array($connections)) - $connections = array(); - $total_connections = count($connections); - for ($i = 0; $i < $total_connections; $i++) - $connections[$i]['http_referer'] = $connections[$i]['http_referer'] ? preg_replace('/^www./', '', parse_url($connections[$i]['http_referer'], PHP_URL_HOST)) : $this->l('Direct link'); + $connections = $customer->getLastConnections(); + if (!is_array($connections)) { + $connections = array(); + } + $total_connections = count($connections); + for ($i = 0; $i < $total_connections; $i++) { + $connections[$i]['http_referer'] = $connections[$i]['http_referer'] ? preg_replace('/^www./', '', parse_url($connections[$i]['http_referer'], PHP_URL_HOST)) : $this->l('Direct link'); + } - $referrers = Referrer::getReferrers($customer->id); - $total_referrers = count($referrers); - for ($i = 0; $i < $total_referrers; $i++) - $referrers[$i]['date_add'] = Tools::displayDate($referrers[$i]['date_add'],null , true); + $referrers = Referrer::getReferrers($customer->id); + $total_referrers = count($referrers); + for ($i = 0; $i < $total_referrers; $i++) { + $referrers[$i]['date_add'] = Tools::displayDate($referrers[$i]['date_add'], null, true); + } - $customerLanguage = new Language($customer->id_lang); - $shop = new Shop($customer->id_shop); - $this->tpl_view_vars = array( - 'customer' => $customer, - 'gender' => $gender, - 'gender_image' => $gender_image, - // General information of the customer - 'registration_date' => Tools::displayDate($customer->date_add,null , true), - 'customer_stats' => $customer_stats, - 'last_visit' => Tools::displayDate($customer_stats['last_visit'],null , true), - 'count_better_customers' => $count_better_customers, - 'shop_is_feature_active' => Shop::isFeatureActive(), - 'name_shop' => $shop->name, - 'customer_birthday' => Tools::displayDate($customer->birthday), - 'last_update' => Tools::displayDate($customer->date_upd,null , true), - 'customer_exists' => Customer::customerExists($customer->email), - 'id_lang' => $customer->id_lang, - 'customerLanguage' => $customerLanguage, - // Add a Private note - 'customer_note' => Tools::htmlentitiesUTF8($customer->note), - // Messages - 'messages' => $messages, - // Groups - 'groups' => $groups, - // Orders - 'orders' => $orders, - 'orders_ok' => $orders_ok, - 'orders_ko' => $orders_ko, - 'total_ok' => Tools::displayPrice($total_ok, $this->context->currency->id), - // Products - 'products' => $products, - // Addresses - 'addresses' => $customer->getAddresses($this->default_form_language), - // Discounts - 'discounts' => CartRule::getCustomerCartRules($this->default_form_language, $customer->id, false, false), - // Carts - 'carts' => $carts, - // Interested - 'interested' => $interested, - // Emails - 'emails' => $emails, - // Connections - 'connections' => $connections, - // Referrers - 'referrers' => $referrers, - 'show_toolbar' => true - ); + $customerLanguage = new Language($customer->id_lang); + $shop = new Shop($customer->id_shop); + $this->tpl_view_vars = array( + 'customer' => $customer, + 'gender' => $gender, + 'gender_image' => $gender_image, + // General information of the customer + 'registration_date' => Tools::displayDate($customer->date_add, null, true), + 'customer_stats' => $customer_stats, + 'last_visit' => Tools::displayDate($customer_stats['last_visit'], null, true), + 'count_better_customers' => $count_better_customers, + 'shop_is_feature_active' => Shop::isFeatureActive(), + 'name_shop' => $shop->name, + 'customer_birthday' => Tools::displayDate($customer->birthday), + 'last_update' => Tools::displayDate($customer->date_upd, null, true), + 'customer_exists' => Customer::customerExists($customer->email), + 'id_lang' => $customer->id_lang, + 'customerLanguage' => $customerLanguage, + // Add a Private note + 'customer_note' => Tools::htmlentitiesUTF8($customer->note), + // Messages + 'messages' => $messages, + // Groups + 'groups' => $groups, + // Orders + 'orders' => $orders, + 'orders_ok' => $orders_ok, + 'orders_ko' => $orders_ko, + 'total_ok' => Tools::displayPrice($total_ok, $this->context->currency->id), + // Products + 'products' => $products, + // Addresses + 'addresses' => $customer->getAddresses($this->default_form_language), + // Discounts + 'discounts' => CartRule::getCustomerCartRules($this->default_form_language, $customer->id, false, false), + // Carts + 'carts' => $carts, + // Interested + 'interested' => $interested, + // Emails + 'emails' => $emails, + // Connections + 'connections' => $connections, + // Referrers + 'referrers' => $referrers, + 'show_toolbar' => true + ); - return parent::renderView(); - } + return parent::renderView(); + } - public function processDelete() - { - $this->_setDeletedMode(); - parent::processDelete(); - } + public function processDelete() + { + $this->_setDeletedMode(); + parent::processDelete(); + } - protected function _setDeletedMode() - { - if ($this->delete_mode == 'real') - $this->deleted = false; - elseif ($this->delete_mode == 'deleted') - $this->deleted = true; - else - { - $this->errors[] = Tools::displayError('Unknown delete mode:').' '.$this->deleted; - return; - } - } + protected function _setDeletedMode() + { + if ($this->delete_mode == 'real') { + $this->deleted = false; + } elseif ($this->delete_mode == 'deleted') { + $this->deleted = true; + } else { + $this->errors[] = Tools::displayError('Unknown delete mode:').' '.$this->deleted; + return; + } + } - protected function processBulkDelete() - { - $this->_setDeletedMode(); - parent::processBulkDelete(); - } + protected function processBulkDelete() + { + $this->_setDeletedMode(); + parent::processBulkDelete(); + } - public function processAdd() - { - if (Tools::getValue('submitFormAjax')) - $this->redirect_after = false; - // Check that the new email is not already in use - $customer_email = strval(Tools::getValue('email')); - $customer = new Customer(); - if (Validate::isEmail($customer_email)) - $customer->getByEmail($customer_email); - if ($customer->id) - { - $this->errors[] = Tools::displayError('An account already exists for this email address:').' '.$customer_email; - $this->display = 'edit'; - return $customer; - } - elseif (trim(Tools::getValue('passwd')) == '') - { - $this->validateRules(); - $this->errors[] = Tools::displayError('Password can not be empty.'); - $this->display = 'edit'; - } - elseif ($customer = parent::processAdd()) - { - $this->context->smarty->assign('new_customer', $customer); - return $customer; - } - return false; - } + public function processAdd() + { + if (Tools::getValue('submitFormAjax')) { + $this->redirect_after = false; + } + // Check that the new email is not already in use + $customer_email = strval(Tools::getValue('email')); + $customer = new Customer(); + if (Validate::isEmail($customer_email)) { + $customer->getByEmail($customer_email); + } + if ($customer->id) { + $this->errors[] = Tools::displayError('An account already exists for this email address:').' '.$customer_email; + $this->display = 'edit'; + return $customer; + } elseif (trim(Tools::getValue('passwd')) == '') { + $this->validateRules(); + $this->errors[] = Tools::displayError('Password can not be empty.'); + $this->display = 'edit'; + } elseif ($customer = parent::processAdd()) { + $this->context->smarty->assign('new_customer', $customer); + return $customer; + } + return false; + } - public function processUpdate() - { - if (Validate::isLoadedObject($this->object)) - { - $customer_email = strval(Tools::getValue('email')); + public function processUpdate() + { + if (Validate::isLoadedObject($this->object)) { + $customer_email = strval(Tools::getValue('email')); - // check if e-mail already used - if ($customer_email != $this->object->email) - { - $customer = new Customer(); - if (Validate::isEmail($customer_email)) - $customer->getByEmail($customer_email); - if (($customer->id) && ($customer->id != (int)$this->object->id)) - $this->errors[] = Tools::displayError('An account already exists for this email address:').' '.$customer_email; - } + // check if e-mail already used + if ($customer_email != $this->object->email) { + $customer = new Customer(); + if (Validate::isEmail($customer_email)) { + $customer->getByEmail($customer_email); + } + if (($customer->id) && ($customer->id != (int)$this->object->id)) { + $this->errors[] = Tools::displayError('An account already exists for this email address:').' '.$customer_email; + } + } - return parent::processUpdate(); - } - else - $this->errors[] = Tools::displayError('An error occurred while loading the object.').' + return parent::processUpdate(); + } else { + $this->errors[] = Tools::displayError('An error occurred while loading the object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - } + } + } - public function processSave() - { - // Check that default group is selected - if (!is_array(Tools::getValue('groupBox')) || !in_array(Tools::getValue('id_default_group'), Tools::getValue('groupBox'))) - $this->errors[] = Tools::displayError('A default customer group must be selected in group box.'); + public function processSave() + { + // Check that default group is selected + if (!is_array(Tools::getValue('groupBox')) || !in_array(Tools::getValue('id_default_group'), Tools::getValue('groupBox'))) { + $this->errors[] = Tools::displayError('A default customer group must be selected in group box.'); + } - // Check the requires fields which are settings in the BO - $customer = new Customer(); - $this->errors = array_merge($this->errors, $customer->validateFieldsRequiredDatabase()); + // Check the requires fields which are settings in the BO + $customer = new Customer(); + $this->errors = array_merge($this->errors, $customer->validateFieldsRequiredDatabase()); - return parent::processSave(); - } + return parent::processSave(); + } - protected function afterDelete($object, $old_id) - { - $customer = new Customer($old_id); - $addresses = $customer->getAddresses($this->default_form_language); - foreach ($addresses as $k => $v) - { - $address = new Address($v['id_address']); - $address->id_customer = $object->id; - $address->save(); - } - return true; - } - /** - * Transform a guest account into a registered customer account - */ - public function processGuestToCustomer() - { - $customer = new Customer((int)Tools::getValue('id_customer')); - if (!Validate::isLoadedObject($customer)) - $this->errors[] = Tools::displayError('This customer does not exist.'); - if (Customer::customerExists($customer->email)) - $this->errors[] = Tools::displayError('This customer already exists as a non-guest.'); - elseif ($customer->transformToCustomer(Tools::getValue('id_lang', $this->context->language->id))) - Tools::redirectAdmin(self::$currentIndex.'&'.$this->identifier.'='.$customer->id.'&conf=3&token='.$this->token); - else - $this->errors[] = Tools::displayError('An error occurred while updating customer information.'); - } + protected function afterDelete($object, $old_id) + { + $customer = new Customer($old_id); + $addresses = $customer->getAddresses($this->default_form_language); + foreach ($addresses as $k => $v) { + $address = new Address($v['id_address']); + $address->id_customer = $object->id; + $address->save(); + } + return true; + } + /** + * Transform a guest account into a registered customer account + */ + public function processGuestToCustomer() + { + $customer = new Customer((int)Tools::getValue('id_customer')); + if (!Validate::isLoadedObject($customer)) { + $this->errors[] = Tools::displayError('This customer does not exist.'); + } + if (Customer::customerExists($customer->email)) { + $this->errors[] = Tools::displayError('This customer already exists as a non-guest.'); + } elseif ($customer->transformToCustomer(Tools::getValue('id_lang', $this->context->language->id))) { + if ($id_order = (int)Tools::getValue('id_order')) { + Tools::redirectAdmin($this->context->link->getAdminLink('AdminOrders').'&id_order='.$id_order.'&vieworder&conf=3'); + } else { + Tools::redirectAdmin(self::$currentIndex.'&'.$this->identifier.'='.$customer->id.'&viewcustomer&conf=3&token='.$this->token); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while updating customer information.'); + } + } - /** - * Toggle the newsletter flag - */ - public function processChangeNewsletterVal() - { - $customer = new Customer($this->id_object); - if (!Validate::isLoadedObject($customer)) - $this->errors[] = Tools::displayError('An error occurred while updating customer information.'); - $customer->newsletter = $customer->newsletter ? 0 : 1; - if (!$customer->update()) - $this->errors[] = Tools::displayError('An error occurred while updating customer information.'); - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); - } + /** + * Toggle the newsletter flag + */ + public function processChangeNewsletterVal() + { + $customer = new Customer($this->id_object); + if (!Validate::isLoadedObject($customer)) { + $this->errors[] = Tools::displayError('An error occurred while updating customer information.'); + } + $customer->newsletter = $customer->newsletter ? 0 : 1; + if (!$customer->update()) { + $this->errors[] = Tools::displayError('An error occurred while updating customer information.'); + } + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } - /** - * Toggle newsletter optin flag - */ - public function processChangeOptinVal() - { - $customer = new Customer($this->id_object); - if (!Validate::isLoadedObject($customer)) - $this->errors[] = Tools::displayError('An error occurred while updating customer information.'); - $customer->optin = $customer->optin ? 0 : 1; - if (!$customer->update()) - $this->errors[] = Tools::displayError('An error occurred while updating customer information.'); - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); - } + /** + * Toggle newsletter optin flag + */ + public function processChangeOptinVal() + { + $customer = new Customer($this->id_object); + if (!Validate::isLoadedObject($customer)) { + $this->errors[] = Tools::displayError('An error occurred while updating customer information.'); + } + $customer->optin = $customer->optin ? 0 : 1; + if (!$customer->update()) { + $this->errors[] = Tools::displayError('An error occurred while updating customer information.'); + } + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } - public function printNewsIcon($value, $customer) - { - return '<a class="list-action-enable '.($value ? 'action-enabled' : 'action-disabled').'" href="index.php?'.htmlspecialchars('tab=AdminCustomers&id_customer=' - .(int)$customer['id_customer'].'&changeNewsletterVal&token='.Tools::getAdminTokenLite('AdminCustomers')).'"> + public function printNewsIcon($value, $customer) + { + return '<a class="list-action-enable '.($value ? 'action-enabled' : 'action-disabled').'" href="index.php?'.htmlspecialchars('tab=AdminCustomers&id_customer=' + .(int)$customer['id_customer'].'&changeNewsletterVal&token='.Tools::getAdminTokenLite('AdminCustomers')).'"> '.($value ? '<i class="icon-check"></i>' : '<i class="icon-remove"></i>'). - '</a>'; - } + '</a>'; + } - public function printOptinIcon($value, $customer) - { - return '<a class="list-action-enable '.($value ? 'action-enabled' : 'action-disabled').'" href="index.php?'.htmlspecialchars('tab=AdminCustomers&id_customer=' - .(int)$customer['id_customer'].'&changeOptinVal&token='.Tools::getAdminTokenLite('AdminCustomers')).'"> + public function printOptinIcon($value, $customer) + { + return '<a class="list-action-enable '.($value ? 'action-enabled' : 'action-disabled').'" href="index.php?'.htmlspecialchars('tab=AdminCustomers&id_customer=' + .(int)$customer['id_customer'].'&changeOptinVal&token='.Tools::getAdminTokenLite('AdminCustomers')).'"> '.($value ? '<i class="icon-check"></i>' : '<i class="icon-remove"></i>'). - '</a>'; - } + '</a>'; + } - /** - * @param string $token - * @param int $id - * @param string $name - * @return mixed - */ - public function displayDeleteLink($token = null, $id, $name = null) - { - $tpl = $this->createTemplate('helpers/list/list_action_delete.tpl'); + /** + * @param string $token + * @param int $id + * @param string $name + * @return mixed + */ + public function displayDeleteLink($token = null, $id, $name = null) + { + $tpl = $this->createTemplate('helpers/list/list_action_delete.tpl'); - $customer = new Customer($id); - $name = $customer->lastname.' '.$customer->firstname; - $name = '\n\n'.$this->l('Name:', 'helper').' '.$name; + $customer = new Customer($id); + $name = $customer->lastname.' '.$customer->firstname; + $name = '\n\n'.$this->l('Name:', 'helper').' '.$name; - $tpl->assign(array( - 'href' => self::$currentIndex.'&'.$this->identifier.'='.$id.'&delete'.$this->table.'&token='.($token != null ? $token : $this->token), - 'confirm' => $this->l('Delete the selected item?').$name, - 'action' => $this->l('Delete'), - 'id' => $id, - )); + $tpl->assign(array( + 'href' => self::$currentIndex.'&'.$this->identifier.'='.$id.'&delete'.$this->table.'&token='.($token != null ? $token : $this->token), + 'confirm' => $this->l('Delete the selected item?').$name, + 'action' => $this->l('Delete'), + 'id' => $id, + )); - return $tpl->fetch(); - } + return $tpl->fetch(); + } - /** - * add to $this->content the result of Customer::SearchByName - * (encoded in json) - * - * @return void - */ - public function ajaxProcessSearchCustomers() - { - $searches = explode(' ', Tools::getValue('customer_search')); - $customers = array(); - $searches = array_unique($searches); - foreach ($searches as $search) - if (!empty($search) && $results = Customer::searchByName($search, 50)) - foreach ($results as $result) - if ($result['active']) - $customers[$result['id_customer']] = $result; + /** + * add to $this->content the result of Customer::SearchByName + * (encoded in json) + * + * @return void + */ + public function ajaxProcessSearchCustomers() + { + $searches = explode(' ', Tools::getValue('customer_search')); + $customers = array(); + $searches = array_unique($searches); + foreach ($searches as $search) { + if (!empty($search) && $results = Customer::searchByName($search, 50)) { + foreach ($results as $result) { + if ($result['active']) { + $customers[$result['id_customer']] = $result; + } + } + } + } - if (count($customers)) - $to_return = array( - 'customers' => $customers, - 'found' => true - ); - else - $to_return = array('found' => false); + if (count($customers)) { + $to_return = array( + 'customers' => $customers, + 'found' => true + ); + } else { + $to_return = array('found' => false); + } - $this->content = Tools::jsonEncode($to_return); - } + $this->content = Tools::jsonEncode($to_return); + } - /** - * Uodate the customer note - * - * @return void - */ - public function ajaxProcessUpdateCustomerNote() - { - if ($this->tabAccess['edit'] === '1') - { - $note = Tools::htmlentitiesDecodeUTF8(Tools::getValue('note')); - $customer = new Customer((int)Tools::getValue('id_customer')); - if (!Validate::isLoadedObject($customer)) - die ('error:update'); - if (!empty($note) && !Validate::isCleanHtml($note)) - die ('error:validation'); - $customer->note = $note; - if (!$customer->update()) - die ('error:update'); - die('ok'); - } - } + /** + * Uodate the customer note + * + * @return void + */ + public function ajaxProcessUpdateCustomerNote() + { + if ($this->tabAccess['edit'] === '1') { + $note = Tools::htmlentitiesDecodeUTF8(Tools::getValue('note')); + $customer = new Customer((int)Tools::getValue('id_customer')); + if (!Validate::isLoadedObject($customer)) { + die('error:update'); + } + if (!empty($note) && !Validate::isCleanHtml($note)) { + die('error:validation'); + } + $customer->note = $note; + if (!$customer->update()) { + die('error:update'); + } + die('ok'); + } + } } diff --git a/controllers/admin/AdminDashboardController.php b/controllers/admin/AdminDashboardController.php index 6b174a2f..e407dee4 100644 --- a/controllers/admin/AdminDashboardController.php +++ b/controllers/admin/AdminDashboardController.php @@ -26,449 +26,453 @@ class AdminDashboardControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->display = 'view'; + public function __construct() + { + $this->bootstrap = true; + $this->display = 'view'; - parent::__construct(); + parent::__construct(); - if (Tools::isSubmit('profitability_conf') || Tools::isSubmit('submitOptionsconfiguration')) - $this->fields_options = $this->getOptionFields(); - } + if (Tools::isSubmit('profitability_conf') || Tools::isSubmit('submitOptionsconfiguration')) { + $this->fields_options = $this->getOptionFields(); + } + } - public function setMedia() - { - parent::setMedia(); + public function setMedia() + { + parent::setMedia(); - $this->addJqueryUI('ui.datepicker'); - $this->addJS(array( - _PS_JS_DIR_.'vendor/d3.v3.min.js', - __PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/vendor/nv.d3.min.js', - _PS_JS_DIR_.'/admin/dashboard.js', - )); - $this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/vendor/nv.d3.css'); - } + $this->addJqueryUI('ui.datepicker'); + $this->addJS(array( + _PS_JS_DIR_.'vendor/d3.v3.min.js', + __PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/vendor/nv.d3.min.js', + _PS_JS_DIR_.'/admin/dashboard.js', + )); + $this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/vendor/nv.d3.css'); + } - public function initPageHeaderToolbar() - { - $this->page_header_toolbar_title = $this->l('Dashboard'); - $this->page_header_toolbar_btn['switch_demo'] = array( - 'desc' => $this->l('Demo mode', null, null, false), - 'icon' => 'process-icon-toggle-'.(Configuration::get('PS_DASHBOARD_SIMULATION') ? 'on' : 'off'), - 'help' => $this->l('This mode displays sample data so you can try your dashboard without real numbers.', null, null, false) - ); + public function initPageHeaderToolbar() + { + $this->page_header_toolbar_title = $this->l('Dashboard'); + $this->page_header_toolbar_btn['switch_demo'] = array( + 'desc' => $this->l('Demo mode', null, null, false), + 'icon' => 'process-icon-toggle-'.(Configuration::get('PS_DASHBOARD_SIMULATION') ? 'on' : 'off'), + 'help' => $this->l('This mode displays sample data so you can try your dashboard without real numbers.', null, null, false) + ); - parent::initPageHeaderToolbar(); + parent::initPageHeaderToolbar(); - // Remove the last element on this controller to match the title with the rule of the others - array_pop($this->meta_title); - } + // Remove the last element on this controller to match the title with the rule of the others + array_pop($this->meta_title); + } - protected function getOptionFields() - { - $forms = array(); - $currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); - $carriers = Carrier::getCarriers($this->context->language->id, true); - $modules = Module::getModulesOnDisk(true); + protected function getOptionFields() + { + $forms = array(); + $currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); + $carriers = Carrier::getCarriers($this->context->language->id, true); + $modules = Module::getModulesOnDisk(true); - $forms = array( - 'payment' => array('title' => $this->l('Average bank fees per payment method'), 'id' => 'payment'), - 'carriers' => array('title' => $this->l('Average shipping fees per shipping method'), 'id' => 'carriers'), - 'other' => array('title' => $this->l('Other settings'), 'id' => 'other') - ); - foreach ($forms as &$form) - { - $form['icon'] = 'tab-preferences'; - $form['fields'] = array(); - $form['submit'] = array('title' => $this->l('Save')); - } + $forms = array( + 'payment' => array('title' => $this->l('Average bank fees per payment method'), 'id' => 'payment'), + 'carriers' => array('title' => $this->l('Average shipping fees per shipping method'), 'id' => 'carriers'), + 'other' => array('title' => $this->l('Other settings'), 'id' => 'other') + ); + foreach ($forms as &$form) { + $form['icon'] = 'tab-preferences'; + $form['fields'] = array(); + $form['submit'] = array('title' => $this->l('Save')); + } - foreach ($modules as $module) - if (isset($module->tab) && $module->tab == 'payments_gateways' && $module->id) - { - $moduleClass = Module::getInstanceByName($module->name); - if (!$moduleClass->isEnabledForShopContext()) - continue; + foreach ($modules as $module) { + if (isset($module->tab) && $module->tab == 'payments_gateways' && $module->id) { + $moduleClass = Module::getInstanceByName($module->name); + if (!$moduleClass->isEnabledForShopContext()) { + continue; + } - $forms['payment']['fields']['CONF_'.strtoupper($module->name).'_FIXED'] = array( - 'title' => $module->displayName, - 'desc' => sprintf($this->l('Choose a fixed fee for each order placed in %1$s with %2$s.'), $currency->iso_code, $module->displayName), - 'validation' => 'isPrice', - 'cast' => 'floatval', - 'type' => 'text', - 'defaultValue' => '0', - 'suffix' => $currency->iso_code - ); - $forms['payment']['fields']['CONF_'.strtoupper($module->name).'_VAR'] = array( - 'title' => $module->displayName, - 'desc' => sprintf($this->l('Choose a variable fee for each order placed in %1$s with %2$s. It will be applied on the total paid with taxes.'), $currency->iso_code, $module->displayName), - 'validation' => 'isPercentage', - 'cast' => 'floatval', - 'type' => 'text', - 'defaultValue' => '0', - 'suffix' => '%' - ); + $forms['payment']['fields']['CONF_'.strtoupper($module->name).'_FIXED'] = array( + 'title' => $module->displayName, + 'desc' => sprintf($this->l('Choose a fixed fee for each order placed in %1$s with %2$s.'), $currency->iso_code, $module->displayName), + 'validation' => 'isPrice', + 'cast' => 'floatval', + 'type' => 'text', + 'defaultValue' => '0', + 'suffix' => $currency->iso_code + ); + $forms['payment']['fields']['CONF_'.strtoupper($module->name).'_VAR'] = array( + 'title' => $module->displayName, + 'desc' => sprintf($this->l('Choose a variable fee for each order placed in %1$s with %2$s. It will be applied on the total paid with taxes.'), $currency->iso_code, $module->displayName), + 'validation' => 'isPercentage', + 'cast' => 'floatval', + 'type' => 'text', + 'defaultValue' => '0', + 'suffix' => '%' + ); - if (Currency::isMultiCurrencyActivated()) - { - $forms['payment']['fields']['CONF_'.strtoupper($module->name).'_FIXED_FOREIGN'] = array( - 'title' => $module->displayName, - 'desc' => sprintf($this->l('Choose a fixed fee for each order placed with a foreign currency with %s.'), $module->displayName), - 'validation' => 'isPrice', - 'cast' => 'floatval', - 'type' => 'text', - 'defaultValue' => '0', - 'suffix' => $currency->iso_code - ); - $forms['payment']['fields']['CONF_'.strtoupper($module->name).'_VAR_FOREIGN'] = array( - 'title' => $module->displayName, - 'desc' => sprintf($this->l('Choose a variable fee for each order placed with a foreign currency with %s. It will be applied on the total paid with taxes.'), $module->displayName), - 'validation' => 'isPercentage', - 'cast' => 'floatval', - 'type' => 'text', - 'defaultValue' => '0', - 'suffix' => '%' - ); - } - } + if (Currency::isMultiCurrencyActivated()) { + $forms['payment']['fields']['CONF_'.strtoupper($module->name).'_FIXED_FOREIGN'] = array( + 'title' => $module->displayName, + 'desc' => sprintf($this->l('Choose a fixed fee for each order placed with a foreign currency with %s.'), $module->displayName), + 'validation' => 'isPrice', + 'cast' => 'floatval', + 'type' => 'text', + 'defaultValue' => '0', + 'suffix' => $currency->iso_code + ); + $forms['payment']['fields']['CONF_'.strtoupper($module->name).'_VAR_FOREIGN'] = array( + 'title' => $module->displayName, + 'desc' => sprintf($this->l('Choose a variable fee for each order placed with a foreign currency with %s. It will be applied on the total paid with taxes.'), $module->displayName), + 'validation' => 'isPercentage', + 'cast' => 'floatval', + 'type' => 'text', + 'defaultValue' => '0', + 'suffix' => '%' + ); + } + } + } - foreach ($carriers as $carrier) - { - $forms['carriers']['fields']['CONF_'.strtoupper($carrier['id_reference']).'_SHIP'] = array( - 'title' => $carrier['name'], - 'desc' => sprintf($this->l('For the carrier named %s, indicate the domestic delivery costs in percentage of the price charged to customers.'), $carrier['name']), - 'validation' => 'isPercentage', - 'cast' => 'floatval', - 'type' => 'text', - 'defaultValue' => '0', - 'suffix' => '%' - ); - $forms['carriers']['fields']['CONF_'.strtoupper($carrier['id_reference']).'_SHIP_OVERSEAS'] = array( - 'title' => $carrier['name'], - 'desc' => sprintf($this->l('For the carrier named %s, indicate the overseas delivery costs in percentage of the price charged to customers.'), $carrier['name']), - 'validation' => 'isPercentage', - 'cast' => 'floatval', - 'type' => 'text', - 'defaultValue' => '0', - 'suffix' => '%' - ); - } + foreach ($carriers as $carrier) { + $forms['carriers']['fields']['CONF_'.strtoupper($carrier['id_reference']).'_SHIP'] = array( + 'title' => $carrier['name'], + 'desc' => sprintf($this->l('For the carrier named %s, indicate the domestic delivery costs in percentage of the price charged to customers.'), $carrier['name']), + 'validation' => 'isPercentage', + 'cast' => 'floatval', + 'type' => 'text', + 'defaultValue' => '0', + 'suffix' => '%' + ); + $forms['carriers']['fields']['CONF_'.strtoupper($carrier['id_reference']).'_SHIP_OVERSEAS'] = array( + 'title' => $carrier['name'], + 'desc' => sprintf($this->l('For the carrier named %s, indicate the overseas delivery costs in percentage of the price charged to customers.'), $carrier['name']), + 'validation' => 'isPercentage', + 'cast' => 'floatval', + 'type' => 'text', + 'defaultValue' => '0', + 'suffix' => '%' + ); + } - $forms['carriers']['description'] = $this->l('Method: Indicate the percentage of your carrier margin. For example, if you charge $10 of shipping fees to your customer for each shipment, but you really pay $4 to this carrier, then you should indicate "40" in the percentage field.'); + $forms['carriers']['description'] = $this->l('Method: Indicate the percentage of your carrier margin. For example, if you charge $10 of shipping fees to your customer for each shipment, but you really pay $4 to this carrier, then you should indicate "40" in the percentage field.'); - $forms['other']['fields']['CONF_AVERAGE_PRODUCT_MARGIN'] = array( - 'title' => $this->l('Average gross margin'), - 'desc' => $this->l('You should calculate this percentage as follows: ((total sales revenue) - (cost of goods sold)) / (total sales revenue) * 100. This value is only used to calculate the Dashboard approximate gross margin, if you do not specify the wholesale price for each product.'), - 'validation' => 'isPercentage', - 'cast' => 'intval', - 'type' => 'text', - 'defaultValue' => '0', - 'suffix' => '%' - ); + $forms['other']['fields']['CONF_AVERAGE_PRODUCT_MARGIN'] = array( + 'title' => $this->l('Average gross margin percentage'), + 'desc' => $this->l('You should calculate this percentage as follows: ((total sales revenue) - (cost of goods sold)) / (total sales revenue) * 100. This value is only used to calculate the Dashboard approximate gross margin, if you do not specify the wholesale price for each product.'), + 'validation' => 'isPercentage', + 'cast' => 'intval', + 'type' => 'text', + 'defaultValue' => '0', + 'suffix' => '%' + ); - $forms['other']['fields']['CONF_ORDER_FIXED'] = array( - 'title' => $this->l('Other fees per order'), - 'desc' => $this->l('You should calculate this value by making the sum of all of your additional costs per order.'), - 'validation' => 'isPrice', - 'cast' => 'floatval', - 'type' => 'text', - 'defaultValue' => '0', - 'suffix' => $currency->iso_code - ); + $forms['other']['fields']['CONF_ORDER_FIXED'] = array( + 'title' => $this->l('Other fees per order'), + 'desc' => $this->l('You should calculate this value by making the sum of all of your additional costs per order.'), + 'validation' => 'isPrice', + 'cast' => 'floatval', + 'type' => 'text', + 'defaultValue' => '0', + 'suffix' => $currency->iso_code + ); - Media::addJsDef(array( - 'dashboard_ajax_url' => $this->context->link->getAdminLink('AdminDashboard'), - 'read_more' => '', - )); + Media::addJsDef(array( + 'dashboard_ajax_url' => $this->context->link->getAdminLink('AdminDashboard'), + 'read_more' => '', + )); - return $forms; - } + return $forms; + } - public function renderView() - { - if (Tools::isSubmit('profitability_conf')) - return parent::renderOptions(); + public function renderView() + { + if (Tools::isSubmit('profitability_conf')) { + return parent::renderOptions(); + } - // $translations = array( - // 'Calendar' => $this->l('Calendar', 'AdminStatsTab'), - // 'Day' => $this->l('Day', 'AdminStatsTab'), - // 'Month' => $this->l('Month', 'AdminStatsTab'), - // 'Year' => $this->l('Year', 'AdminStatsTab'), - // 'From' => $this->l('From:', 'AdminStatsTab'), - // 'To' => $this->l('To:', 'AdminStatsTab'), - // 'Save' => $this->l('Save', 'AdminStatsTab') - // ); + // $translations = array( + // 'Calendar' => $this->l('Calendar', 'AdminStatsTab'), + // 'Day' => $this->l('Day', 'AdminStatsTab'), + // 'Month' => $this->l('Month', 'AdminStatsTab'), + // 'Year' => $this->l('Year', 'AdminStatsTab'), + // 'From' => $this->l('From:', 'AdminStatsTab'), + // 'To' => $this->l('To:', 'AdminStatsTab'), + // 'Save' => $this->l('Save', 'AdminStatsTab') + // ); - if ($this->context->cookie->__get('stats_date_update') < strtotime(date('Y-m-d'))) - { - switch ($this->context->employee->preselect_date_range) - { - case 'day': - $date_from = date('Y-m-d'); - $date_to = date('Y-m-d'); - break; - case 'prev-day': - $date_from = date('Y-m-d', strtotime('-1 day')); - $date_to = date('Y-m-d', strtotime('-1 day')); - break; - case 'month': - default: - $date_from = date('Y-m-01'); - $date_to = date('Y-m-d'); - break; - case 'prev-month': - $date_from = date('Y-m-01', strtotime('-1 month')); - $date_to = date('Y-m-t', strtotime('-1 month')); - break; - case 'year': - $date_from = date('Y-01-01'); - $date_to = date('Y-m-d'); - break; - case 'prev-year': - $date_from = date('Y-m-01', strtotime('-1 year')); - $date_to = date('Y-12-t', strtotime('-1 year')); - break; - } - $this->context->employee->stats_date_from = $date_from; - $this->context->employee->stats_date_to = $date_to; - $this->context->employee->update(); - $this->context->cookie->__set('stats_date_update', strtotime(date('Y-m-d'))); - $this->context->cookie->write(); - } + if ($this->context->cookie->__get('stats_date_update') < strtotime(date('Y-m-d'))) { + switch ($this->context->employee->preselect_date_range) { + case 'day': + $date_from = date('Y-m-d'); + $date_to = date('Y-m-d'); + break; + case 'prev-day': + $date_from = date('Y-m-d', strtotime('-1 day')); + $date_to = date('Y-m-d', strtotime('-1 day')); + break; + case 'month': + default: + $date_from = date('Y-m-01'); + $date_to = date('Y-m-d'); + break; + case 'prev-month': + $date_from = date('Y-m-01', strtotime('-1 month')); + $date_to = date('Y-m-t', strtotime('-1 month')); + break; + case 'year': + $date_from = date('Y-01-01'); + $date_to = date('Y-m-d'); + break; + case 'prev-year': + $date_from = date('Y-m-01', strtotime('-1 year')); + $date_to = date('Y-12-t', strtotime('-1 year')); + break; + } + $this->context->employee->stats_date_from = $date_from; + $this->context->employee->stats_date_to = $date_to; + $this->context->employee->update(); + $this->context->cookie->__set('stats_date_update', strtotime(date('Y-m-d'))); + $this->context->cookie->write(); + } - $calendar_helper = new HelperCalendar(); + $calendar_helper = new HelperCalendar(); - $calendar_helper->setDateFrom(Tools::getValue('date_from', $this->context->employee->stats_date_from)); - $calendar_helper->setDateTo(Tools::getValue('date_to', $this->context->employee->stats_date_to)); + $calendar_helper->setDateFrom(Tools::getValue('date_from', $this->context->employee->stats_date_from)); + $calendar_helper->setDateTo(Tools::getValue('date_to', $this->context->employee->stats_date_to)); - $stats_compare_from = $this->context->employee->stats_compare_from; - $stats_compare_to = $this->context->employee->stats_compare_to; + $stats_compare_from = $this->context->employee->stats_compare_from; + $stats_compare_to = $this->context->employee->stats_compare_to; - if (is_null($stats_compare_from) || $stats_compare_from == '0000-00-00') - $stats_compare_from = null; + if (is_null($stats_compare_from) || $stats_compare_from == '0000-00-00') { + $stats_compare_from = null; + } - if (is_null($stats_compare_to) || $stats_compare_to == '0000-00-00') - $stats_compare_to = null; + if (is_null($stats_compare_to) || $stats_compare_to == '0000-00-00') { + $stats_compare_to = null; + } - $calendar_helper->setCompareDateFrom($stats_compare_from); - $calendar_helper->setCompareDateTo($stats_compare_to); - $calendar_helper->setCompareOption(Tools::getValue('compare_date_option', $this->context->employee->stats_compare_option)); + $calendar_helper->setCompareDateFrom($stats_compare_from); + $calendar_helper->setCompareDateTo($stats_compare_to); + $calendar_helper->setCompareOption(Tools::getValue('compare_date_option', $this->context->employee->stats_compare_option)); - $params = array( - 'date_from' => $this->context->employee->stats_date_from, - 'date_to' => $this->context->employee->stats_date_to - ); + $params = array( + 'date_from' => $this->context->employee->stats_date_from, + 'date_to' => $this->context->employee->stats_date_to + ); - $this->tpl_view_vars = array( - 'date_from' => $this->context->employee->stats_date_from, - 'date_to' => $this->context->employee->stats_date_to, - 'hookDashboardZoneOne' => Hook::exec('dashboardZoneOne', $params), - 'hookDashboardZoneTwo' => Hook::exec('dashboardZoneTwo', $params), - //'translations' => $translations, - 'action' => '#', - 'warning' => $this->getWarningDomainName(), - 'new_version_url' => Tools::getCurrentUrlProtocolPrefix()._PS_API_DOMAIN_.'/version/check_version.php?v='._PS_VERSION_.'&lang='.$this->context->language->iso_code.'&autoupgrade='.(int)(Module::isInstalled('autoupgrade') && Module::isEnabled('autoupgrade')).'&hosted_mode='.(int)defined('_PS_HOST_MODE_'), - 'dashboard_use_push' => Configuration::get('PS_DASHBOARD_USE_PUSH'), - 'calendar' => $calendar_helper->generate(), - 'PS_DASHBOARD_SIMULATION' => Configuration::get('PS_DASHBOARD_SIMULATION'), - 'datepickerFrom' => Tools::getValue('datepickerFrom', $this->context->employee->stats_date_from), - 'datepickerTo' => Tools::getValue('datepickerTo', $this->context->employee->stats_date_to), - 'preselect_date_range' => Tools::getValue('preselectDateRange', $this->context->employee->preselect_date_range) - ); - return parent::renderView(); - } + $this->tpl_view_vars = array( + 'date_from' => $this->context->employee->stats_date_from, + 'date_to' => $this->context->employee->stats_date_to, + 'hookDashboardZoneOne' => Hook::exec('dashboardZoneOne', $params), + 'hookDashboardZoneTwo' => Hook::exec('dashboardZoneTwo', $params), + //'translations' => $translations, + 'action' => '#', + 'warning' => $this->getWarningDomainName(), + 'new_version_url' => Tools::getCurrentUrlProtocolPrefix()._PS_API_DOMAIN_.'/version/check_version.php?v='._PS_VERSION_.'&lang='.$this->context->language->iso_code.'&autoupgrade='.(int)(Module::isInstalled('autoupgrade') && Module::isEnabled('autoupgrade')).'&hosted_mode='.(int)defined('_PS_HOST_MODE_'), + 'dashboard_use_push' => Configuration::get('PS_DASHBOARD_USE_PUSH'), + 'calendar' => $calendar_helper->generate(), + 'PS_DASHBOARD_SIMULATION' => Configuration::get('PS_DASHBOARD_SIMULATION'), + 'datepickerFrom' => Tools::getValue('datepickerFrom', $this->context->employee->stats_date_from), + 'datepickerTo' => Tools::getValue('datepickerTo', $this->context->employee->stats_date_to), + 'preselect_date_range' => Tools::getValue('preselectDateRange', $this->context->employee->preselect_date_range) + ); + return parent::renderView(); + } - public function postProcess() - { - if (Tools::isSubmit('submitDateRealTime')) - { - if ($use_realtime = (int)Tools::getValue('submitDateRealTime')) - { - $this->context->employee->stats_date_from = date('Y-m-d'); - $this->context->employee->stats_date_to = date('Y-m-d'); - $this->context->employee->stats_compare_option = HelperCalendar::DEFAULT_COMPARE_OPTION; - $this->context->employee->stats_compare_from = null; - $this->context->employee->stats_compare_to = null; - $this->context->employee->update(); - } - Configuration::updateValue('PS_DASHBOARD_USE_PUSH', $use_realtime); - } + public function postProcess() + { + if (Tools::isSubmit('submitDateRealTime')) { + if ($use_realtime = (int)Tools::getValue('submitDateRealTime')) { + $this->context->employee->stats_date_from = date('Y-m-d'); + $this->context->employee->stats_date_to = date('Y-m-d'); + $this->context->employee->stats_compare_option = HelperCalendar::DEFAULT_COMPARE_OPTION; + $this->context->employee->stats_compare_from = null; + $this->context->employee->stats_compare_to = null; + $this->context->employee->update(); + } + Configuration::updateValue('PS_DASHBOARD_USE_PUSH', $use_realtime); + } - if (Tools::isSubmit('submitDateRange')) - { - if (!Validate::isDate(Tools::getValue('date_from')) - || !Validate::isDate(Tools::getValue('date_to'))) - $this->errors[] = Tools::displayError('The selected date range is not valid.'); + if (Tools::isSubmit('submitDateRange')) { + if (!Validate::isDate(Tools::getValue('date_from')) + || !Validate::isDate(Tools::getValue('date_to'))) { + $this->errors[] = Tools::displayError('The selected date range is not valid.'); + } - if (Tools::getValue('datepicker_compare')) - if (!Validate::isDate(Tools::getValue('compare_date_from')) - || !Validate::isDate(Tools::getValue('compare_date_to'))) - $this->errors[] = Tools::displayError('The selected date range is not valid.'); + if (Tools::getValue('datepicker_compare')) { + if (!Validate::isDate(Tools::getValue('compare_date_from')) + || !Validate::isDate(Tools::getValue('compare_date_to'))) { + $this->errors[] = Tools::displayError('The selected date range is not valid.'); + } + } - if (!count($this->errors)) - { - $this->context->employee->stats_date_from = Tools::getValue('date_from'); - $this->context->employee->stats_date_to = Tools::getValue('date_to'); - $this->context->employee->preselect_date_range = Tools::getValue('preselectDateRange'); + if (!count($this->errors)) { + $this->context->employee->stats_date_from = Tools::getValue('date_from'); + $this->context->employee->stats_date_to = Tools::getValue('date_to'); + $this->context->employee->preselect_date_range = Tools::getValue('preselectDateRange'); - if (Tools::getValue('datepicker_compare')) - { - $this->context->employee->stats_compare_from = Tools::getValue('compare_date_from'); - $this->context->employee->stats_compare_to = Tools::getValue('compare_date_to'); - $this->context->employee->stats_compare_option = Tools::getValue('compare_date_option'); - } - else - { - $this->context->employee->stats_compare_from = null; - $this->context->employee->stats_compare_to = null; - $this->context->employee->stats_compare_option = HelperCalendar::DEFAULT_COMPARE_OPTION; - } + if (Tools::getValue('datepicker_compare')) { + $this->context->employee->stats_compare_from = Tools::getValue('compare_date_from'); + $this->context->employee->stats_compare_to = Tools::getValue('compare_date_to'); + $this->context->employee->stats_compare_option = Tools::getValue('compare_date_option'); + } else { + $this->context->employee->stats_compare_from = null; + $this->context->employee->stats_compare_to = null; + $this->context->employee->stats_compare_option = HelperCalendar::DEFAULT_COMPARE_OPTION; + } - $this->context->employee->update(); - } - } + $this->context->employee->update(); + } + } - parent::postProcess(); - } + parent::postProcess(); + } - protected function getWarningDomainName() - { - $warning = false; - if (Shop::isFeatureActive()) - return; + protected function getWarningDomainName() + { + $warning = false; + if (Shop::isFeatureActive()) { + return; + } - $shop = Context::getContext()->shop; - if ($_SERVER['HTTP_HOST'] != $shop->domain && $_SERVER['HTTP_HOST'] != $shop->domain_ssl && Tools::getValue('ajax') == false && !defined('_PS_HOST_MODE_')) - { - $warning = $this->l('You are currently connected under the following domain name:').' <span style="color: #CC0000;">'.$_SERVER['HTTP_HOST'].'</span><br />'; - if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE')) - $warning .= sprintf($this->l('This is different from the shop domain name set in the Multistore settings: "%s".'), $shop->domain).' + $shop = Context::getContext()->shop; + if ($_SERVER['HTTP_HOST'] != $shop->domain && $_SERVER['HTTP_HOST'] != $shop->domain_ssl && Tools::getValue('ajax') == false && !defined('_PS_HOST_MODE_')) { + $warning = $this->l('You are currently connected under the following domain name:').' <span style="color: #CC0000;">'.$_SERVER['HTTP_HOST'].'</span><br />'; + if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE')) { + $warning .= sprintf($this->l('This is different from the shop domain name set in the Multistore settings: "%s".'), $shop->domain).' '.preg_replace('@{link}(.*){/link}@', '<a href="index.php?controller=AdminShopUrl&id_shop_url='.(int)$shop->id.'&updateshop_url&token='.Tools::getAdminTokenLite('AdminShopUrl').'">$1</a>', $this->l('If this is your main domain, please {link}change it now{/link}.')); - else - $warning .= $this->l('This is different from the domain name set in the "SEO & URLs" tab.').' + } else { + $warning .= $this->l('This is different from the domain name set in the "SEO & URLs" tab.').' '.preg_replace('@{link}(.*){/link}@', '<a href="index.php?controller=AdminMeta&token='.Tools::getAdminTokenLite('AdminMeta').'#meta_fieldset_shop_url">$1</a>', $this->l('If this is your main domain, please {link}change it now{/link}.')); - } - return $warning; - } + } + } + return $warning; + } - public function ajaxProcessRefreshDashboard() - { - $id_module = null; - if ($module = Tools::getValue('module')) - { - $module_obj = Module::getInstanceByName($module); - if (Validate::isLoadedObject($module_obj)) - $id_module = $module_obj->id; - } + public function ajaxProcessRefreshDashboard() + { + $id_module = null; + if ($module = Tools::getValue('module')) { + $module_obj = Module::getInstanceByName($module); + if (Validate::isLoadedObject($module_obj)) { + $id_module = $module_obj->id; + } + } - $params = array( - 'date_from' => $this->context->employee->stats_date_from, - 'date_to' => $this->context->employee->stats_date_to, - 'compare_from' => $this->context->employee->stats_compare_from, - 'compare_to' => $this->context->employee->stats_compare_to, - 'dashboard_use_push' => (int)Tools::getValue('dashboard_use_push'), - 'extra' => (int)Tools::getValue('extra') - ); + $params = array( + 'date_from' => $this->context->employee->stats_date_from, + 'date_to' => $this->context->employee->stats_date_to, + 'compare_from' => $this->context->employee->stats_compare_from, + 'compare_to' => $this->context->employee->stats_compare_to, + 'dashboard_use_push' => (int)Tools::getValue('dashboard_use_push'), + 'extra' => (int)Tools::getValue('extra') + ); - die(Tools::jsonEncode(Hook::exec('dashboardData', $params, $id_module, true, true, (int)Tools::getValue('dashboard_use_push')))); - } + die(Tools::jsonEncode(Hook::exec('dashboardData', $params, $id_module, true, true, (int)Tools::getValue('dashboard_use_push')))); + } - public function ajaxProcessSetSimulationMode() - { - Configuration::updateValue('PS_DASHBOARD_SIMULATION', (int)Tools::getValue('PS_DASHBOARD_SIMULATION')); - die ('k'.Configuration::get('PS_DASHBOARD_SIMULATION').'k'); - } + public function ajaxProcessSetSimulationMode() + { + Configuration::updateValue('PS_DASHBOARD_SIMULATION', (int)Tools::getValue('PS_DASHBOARD_SIMULATION')); + die('k'.Configuration::get('PS_DASHBOARD_SIMULATION').'k'); + } - public function ajaxProcessGetBlogRss() - { - $return = array('has_errors' => false, 'rss' => array()); - if (!$this->isFresh('/config/xml/blog-'.$this->context->language->iso_code.'.xml', 86400)) - if (!$this->refresh('/config/xml/blog-'.$this->context->language->iso_code.'.xml', _PS_API_URL_.'/rss/blog/blog-'.$this->context->language->iso_code.'.xml')) - $return['has_errors'] = true; + public function ajaxProcessGetBlogRss() + { + $return = array('has_errors' => false, 'rss' => array()); + if (!$this->isFresh('/config/xml/blog-'.$this->context->language->iso_code.'.xml', 86400)) { + if (!$this->refresh('/config/xml/blog-'.$this->context->language->iso_code.'.xml', _PS_API_URL_.'/rss/blog/blog-'.$this->context->language->iso_code.'.xml')) { + $return['has_errors'] = true; + } + } - if (!$return['has_errors']) - { - $rss = simpleXML_load_file(_PS_ROOT_DIR_.'/config/xml/blog-'.$this->context->language->iso_code.'.xml'); - $articles_limit = 2; - foreach ($rss->channel->item as $item) - { - if ($articles_limit > 0 && Validate::isCleanHtml((string)$item->title) && Validate::isCleanHtml((string)$item->description) - && isset($item->link) && isset($item->title)) - { - if (in_array($this->context->mode, array(Context::MODE_HOST, Context::MODE_HOST_CONTRIB))) - $utm_content = 'cloud'; - else - $utm_content = 'download'; + if (!$return['has_errors']) { + $rss = @simplexml_load_file(_PS_ROOT_DIR_.'/config/xml/blog-'.$this->context->language->iso_code.'.xml'); + if (!$rss) { + $return['has_errors'] = true; + } + $articles_limit = 2; + if ($rss) { + foreach ($rss->channel->item as $item) { + if ($articles_limit > 0 && Validate::isCleanHtml((string)$item->title) && Validate::isCleanHtml((string)$item->description) + && isset($item->link) && isset($item->title)) { + if (in_array($this->context->mode, array(Context::MODE_HOST, Context::MODE_HOST_CONTRIB))) { + $utm_content = 'cloud'; + } else { + $utm_content = 'download'; + } - $shop_default_country_id = (int)Configuration::get('PS_COUNTRY_DEFAULT'); - $shop_default_iso_country = (string)Tools::strtoupper(Country::getIsoById($shop_default_country_id)); - $analytics_params = array('utm_source' => 'back-office', - 'utm_medium' => 'rss', - 'utm_campaign' => 'back-office-'.$shop_default_iso_country, - 'utm_content' => $utm_content + $shop_default_country_id = (int)Configuration::get('PS_COUNTRY_DEFAULT'); + $shop_default_iso_country = (string)Tools::strtoupper(Country::getIsoById($shop_default_country_id)); + $analytics_params = array('utm_source' => 'back-office', + 'utm_medium' => 'rss', + 'utm_campaign' => 'back-office-'.$shop_default_iso_country, + 'utm_content' => $utm_content - ); - $url_query = parse_url($item->link, PHP_URL_QUERY); - parse_str($url_query, $link_query_params); + ); + $url_query = parse_url($item->link, PHP_URL_QUERY); + parse_str($url_query, $link_query_params); - if ($link_query_params) - { - $full_url_params = array_merge($link_query_params, $analytics_params); - $base_url = explode('?', (string)$item->link); - $base_url = (string)$base_url[0]; - $article_link = $base_url.'?'.http_build_query($full_url_params); - } - else - $article_link = (string)$item->link.'?'.http_build_query($analytics_params); + if ($link_query_params) { + $full_url_params = array_merge($link_query_params, $analytics_params); + $base_url = explode('?', (string)$item->link); + $base_url = (string)$base_url[0]; + $article_link = $base_url.'?'.http_build_query($full_url_params); + } else { + $article_link = (string)$item->link.'?'.http_build_query($analytics_params); + } - $return['rss'][] = array( - 'date' => Tools::displayDate(date('Y-m-d', strtotime((string)$item->pubDate))), - 'title' => (string)Tools::htmlentitiesUTF8($item->title), - 'short_desc' => Tools::truncateString(strip_tags((string)$item->description), 150), - 'link' => (string)$article_link, - ); - } - else - break; - $articles_limit --; - } - } - die(Tools::jsonEncode($return)); - } + $return['rss'][] = array( + 'date' => Tools::displayDate(date('Y-m-d', strtotime((string)$item->pubDate))), + 'title' => (string)Tools::htmlentitiesUTF8($item->title), + 'short_desc' => Tools::truncateString(strip_tags((string)$item->description), 150), + 'link' => (string)$article_link, + ); + } else { + break; + } + $articles_limit --; + } + } + } + die(Tools::jsonEncode($return)); + } - public function ajaxProcessSaveDashConfig() - { - $return = array('has_errors' => false, 'errors' => array()); - $module = Tools::getValue('module'); - $hook = Tools::getValue('hook'); - $configs = Tools::getValue('configs'); + public function ajaxProcessSaveDashConfig() + { + $return = array('has_errors' => false, 'errors' => array()); + $module = Tools::getValue('module'); + $hook = Tools::getValue('hook'); + $configs = Tools::getValue('configs'); - $params = array( - 'date_from' => $this->context->employee->stats_date_from, - 'date_to' => $this->context->employee->stats_date_to - ); + $params = array( + 'date_from' => $this->context->employee->stats_date_from, + 'date_to' => $this->context->employee->stats_date_to + ); - if (Validate::isModuleName($module) && $module_obj = Module::getInstanceByName($module)) - { - if (Validate::isLoadedObject($module_obj) && method_exists($module_obj, 'validateDashConfig')) - $return['errors'] = $module_obj->validateDashConfig($configs); - if (!count($return['errors'])) - { - if (Validate::isLoadedObject($module_obj) && method_exists($module_obj, 'saveDashConfig')) - $return['has_errors'] = $module_obj->saveDashConfig($configs); - elseif (is_array($configs) && count($configs)) - foreach ($configs as $name => $value) - if (Validate::isConfigName($name)) - Configuration::updateValue($name, $value); - } - else - $return['has_errors'] = true; - } + if (Validate::isModuleName($module) && $module_obj = Module::getInstanceByName($module)) { + if (Validate::isLoadedObject($module_obj) && method_exists($module_obj, 'validateDashConfig')) { + $return['errors'] = $module_obj->validateDashConfig($configs); + } + if (!count($return['errors'])) { + if (Validate::isLoadedObject($module_obj) && method_exists($module_obj, 'saveDashConfig')) { + $return['has_errors'] = $module_obj->saveDashConfig($configs); + } elseif (is_array($configs) && count($configs)) { + foreach ($configs as $name => $value) { + if (Validate::isConfigName($name)) { + Configuration::updateValue($name, $value); + } + } + } + } else { + $return['has_errors'] = true; + } + } - if (Validate::isHookName($hook) && method_exists($module_obj, $hook)) - $return['widget_html'] = $module_obj->$hook($params); + if (Validate::isHookName($hook) && method_exists($module_obj, $hook)) { + $return['widget_html'] = $module_obj->$hook($params); + } - die(Tools::jsonEncode($return)); - } + die(Tools::jsonEncode($return)); + } } diff --git a/controllers/admin/AdminDeliverySlipController.php b/controllers/admin/AdminDeliverySlipController.php index 27002ad3..78c22506 100644 --- a/controllers/admin/AdminDeliverySlipController.php +++ b/controllers/admin/AdminDeliverySlipController.php @@ -26,117 +26,116 @@ class AdminDeliverySlipControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'delivery'; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'delivery'; - $this->context = Context::getContext(); + $this->context = Context::getContext(); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Delivery slip options'), - 'fields' => array( - 'PS_DELIVERY_PREFIX' => array( - 'title' => $this->l('Delivery prefix'), - 'desc' => $this->l('Prefix used for delivery slips.'), - 'type' => 'textLang' - ), - 'PS_DELIVERY_NUMBER' => array( - 'title' => $this->l('Delivery number'), - 'desc' => $this->l('The next delivery slip will begin with this number and then increase with each additional slip.'), - 'cast' => 'intval', - 'type' => 'text' - ), - 'PS_PDF_IMG_DELIVERY' => array( - 'title' => $this->l('Enable product image on Delivery-slip'), - 'hint' => $this->l('Adds an image before product name on Delivery-slip'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - ), - 'submit' => array('title' => $this->l('Save')) - ) - ); + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Delivery slip options'), + 'fields' => array( + 'PS_DELIVERY_PREFIX' => array( + 'title' => $this->l('Delivery prefix'), + 'desc' => $this->l('Prefix used for delivery slips.'), + 'type' => 'textLang' + ), + 'PS_DELIVERY_NUMBER' => array( + 'title' => $this->l('Delivery number'), + 'desc' => $this->l('The next delivery slip will begin with this number and then increase with each additional slip.'), + 'cast' => 'intval', + 'type' => 'text' + ), + 'PS_PDF_IMG_DELIVERY' => array( + 'title' => $this->l('Enable product image'), + 'hint' => $this->l('Adds an image before product name on Delivery-slip'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + ), + 'submit' => array('title' => $this->l('Save')) + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Print PDF delivery slips'), - 'icon' => 'icon-print' - ), - 'input' => array( - array( - 'type' => 'date', - 'label' => $this->l('From'), - 'name' => 'date_from', - 'maxlength' => 10, - 'required' => true, - 'hint' => $this->l('Format: 2011-12-31 (inclusive).') - ), - array( - 'type' => 'date', - 'label' => $this->l('To'), - 'name' => 'date_to', - 'maxlength' => 10, - 'required' => true, - 'hint' => $this->l('Format: 2012-12-31 (inclusive).') - ) - ), - 'submit' => array( - 'title' => $this->l('Generate PDF file'), - 'icon' => 'process-icon-download-alt' - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Print PDF delivery slips'), + 'icon' => 'icon-print' + ), + 'input' => array( + array( + 'type' => 'date', + 'label' => $this->l('From'), + 'name' => 'date_from', + 'maxlength' => 10, + 'required' => true, + 'hint' => $this->l('Format: 2011-12-31 (inclusive).') + ), + array( + 'type' => 'date', + 'label' => $this->l('To'), + 'name' => 'date_to', + 'maxlength' => 10, + 'required' => true, + 'hint' => $this->l('Format: 2012-12-31 (inclusive).') + ) + ), + 'submit' => array( + 'title' => $this->l('Generate PDF file'), + 'icon' => 'process-icon-download-alt' + ) + ); - $this->fields_value = array( - 'date_from' => date('Y-m-d'), - 'date_to' => date('Y-m-d') - ); + $this->fields_value = array( + 'date_from' => date('Y-m-d'), + 'date_to' => date('Y-m-d') + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function postProcess() - { - if (Tools::isSubmit('submitAdddelivery')) - { - if (!Validate::isDate(Tools::getValue('date_from'))) - $this->errors[] = Tools::displayError('Invalid \'from\' date'); - if (!Validate::isDate(Tools::getValue('date_to'))) - $this->errors[] = Tools::displayError('Invalid \'to\' date'); - if (!count($this->errors)) - { - if (count(OrderInvoice::getByDeliveryDateInterval(Tools::getValue('date_from'), Tools::getValue('date_to')))) - Tools::redirectAdmin($this->context->link->getAdminLink('AdminPdf').'&submitAction=generateDeliverySlipsPDF&date_from='.urlencode(Tools::getValue('date_from')).'&date_to='.urlencode(Tools::getValue('date_to'))); - else - $this->errors[] = Tools::displayError('No delivery slip was found for this period.'); - } - } - else - parent::postProcess(); - } + public function postProcess() + { + if (Tools::isSubmit('submitAdddelivery')) { + if (!Validate::isDate(Tools::getValue('date_from'))) { + $this->errors[] = Tools::displayError('Invalid \'from\' date'); + } + if (!Validate::isDate(Tools::getValue('date_to'))) { + $this->errors[] = Tools::displayError('Invalid \'to\' date'); + } + if (!count($this->errors)) { + if (count(OrderInvoice::getByDeliveryDateInterval(Tools::getValue('date_from'), Tools::getValue('date_to')))) { + Tools::redirectAdmin($this->context->link->getAdminLink('AdminPdf').'&submitAction=generateDeliverySlipsPDF&date_from='.urlencode(Tools::getValue('date_from')).'&date_to='.urlencode(Tools::getValue('date_to'))); + } else { + $this->errors[] = Tools::displayError('No delivery slip was found for this period.'); + } + } + } else { + parent::postProcess(); + } + } - public function initContent() - { - $this->initTabModuleList(); - $this->initPageHeaderToolbar(); - $this->show_toolbar = false; - $this->content .= $this->renderForm(); - $this->content .= $this->renderOptions(); - $this->context->smarty->assign(array( - 'content' => $this->content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } + public function initContent() + { + $this->initTabModuleList(); + $this->initPageHeaderToolbar(); + $this->show_toolbar = false; + $this->content .= $this->renderForm(); + $this->content .= $this->renderOptions(); + $this->context->smarty->assign(array( + 'content' => $this->content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } } - - diff --git a/controllers/admin/AdminEmailsController.php b/controllers/admin/AdminEmailsController.php index da2c60b6..bb7eeaf1 100644 --- a/controllers/admin/AdminEmailsController.php +++ b/controllers/admin/AdminEmailsController.php @@ -29,322 +29,327 @@ */ class AdminEmailsControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; + public function __construct() + { + $this->bootstrap = true; - if (Configuration::get('PS_LOG_EMAILS')) - { - $this->table = 'mail'; - $this->className = 'Mail'; + if (Configuration::get('PS_LOG_EMAILS')) { + $this->table = 'mail'; + $this->className = 'Mail'; - $this->lang = false; - $this->noLink = true; - $this->list_no_link = true; - $this->explicitSelect = true; - $this->addRowAction('delete'); + $this->lang = false; + $this->noLink = true; + $this->list_no_link = true; + $this->explicitSelect = true; + $this->addRowAction('delete'); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - foreach (Language::getLanguages() as $language) - $languages[$language['id_lang']] = $language['name']; + foreach (Language::getLanguages() as $language) { + $languages[$language['id_lang']] = $language['name']; + } - $this->fields_list = array( - 'id_mail' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'recipient' => array('title' => $this->l('Recipient')), - 'template' => array('title' => $this->l('Template')), - 'language' => array( - 'title' => $this->l('Language'), - 'type' => 'select', - 'color' => 'color', - 'list' => $languages, - 'filter_key' => 'a!id_lang', - 'filter_type' => 'int', - 'order_key' => 'language' - ), - 'subject' => array('title' => $this->l('Subject')), - 'date_add' => array( - 'title' => $this->l('Sent'), - 'type' => 'datetime', - ) - ); - $this->_select .= 'l.name as language'; - $this->_join .= ' LEFT JOIN '._DB_PREFIX_.'lang l ON (a.id_lang = l.id_lang)'; - $this->_use_found_rows = false; - } + $this->fields_list = array( + 'id_mail' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'recipient' => array('title' => $this->l('Recipient')), + 'template' => array('title' => $this->l('Template')), + 'language' => array( + 'title' => $this->l('Language'), + 'type' => 'select', + 'color' => 'color', + 'list' => $languages, + 'filter_key' => 'a!id_lang', + 'filter_type' => 'int', + 'order_key' => 'language' + ), + 'subject' => array('title' => $this->l('Subject')), + 'date_add' => array( + 'title' => $this->l('Sent'), + 'type' => 'datetime', + ) + ); + $this->_select .= 'l.name as language'; + $this->_join .= ' LEFT JOIN '._DB_PREFIX_.'lang l ON (a.id_lang = l.id_lang)'; + $this->_use_found_rows = false; + } - parent::__construct(); + parent::__construct(); - foreach (Contact::getContacts($this->context->language->id) as $contact) - $arr[] = array('email_message' => $contact['id_contact'], 'name' => $contact['name']); + foreach (Contact::getContacts($this->context->language->id) as $contact) { + $arr[] = array('email_message' => $contact['id_contact'], 'name' => $contact['name']); + } - $this->fields_options = array( - 'email' => array( - 'title' => $this->l('Email'), - 'icon' => 'icon-envelope', - 'fields' => array( - 'PS_MAIL_EMAIL_MESSAGE' => array( - 'title' => $this->l('Send email to'), - 'desc' => $this->l('Where customers send messages from the order page.'), - 'validation' => 'isUnsignedId', - 'type' => 'select', - 'cast' => 'intval', - 'identifier' => 'email_message', - 'list' => $arr - ), - 'PS_MAIL_METHOD' => array( - 'title' => '', - 'validation' => 'isGenericName', - 'type' => 'radio', - 'required' => true, - 'choices' => array( - 3 => $this->l('Never send emails (may be useful for testing purposes)'), - 2 => $this->l('Set my own SMTP parameters (for advanced users ONLY)') - ) - ), - 'PS_MAIL_TYPE' => array( - 'title' => '', - 'validation' => 'isGenericName', - 'type' => 'radio', - 'required' => true, - 'choices' => array( - Mail::TYPE_HTML => $this->l('Send email in HTML format'), - Mail::TYPE_TEXT => $this->l('Send email in text format'), - Mail::TYPE_BOTH => $this->l('Both') - ) - ), - 'PS_LOG_EMAILS' => array( - 'title' => $this->l('Log Emails'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'smtp' => array( - 'title' => $this->l('Email'), - 'fields' => array( - 'PS_MAIL_DOMAIN' => array( - 'title' => $this->l('Mail domain name'), - 'hint' => $this->l('Fully qualified domain name (keep this field empty if you don\'t know).'), - 'empty' => true, 'validation' => - 'isUrl', - 'type' => 'text', - ), - 'PS_MAIL_SERVER' => array( - 'title' => $this->l('SMTP server'), - 'hint' => $this->l('IP address or server name (e.g. smtp.mydomain.com).'), - 'validation' => 'isGenericName', - 'type' => 'text', - ), - 'PS_MAIL_USER' => array( - 'title' => $this->l('SMTP username'), - 'hint' => $this->l('Leave blank if not applicable.'), - 'validation' => 'isGenericName', - 'type' => 'text', - ), - 'PS_MAIL_PASSWD' => array( - 'title' => $this->l('SMTP password'), - 'hint' => $this->l('Leave blank if not applicable.'), - 'validation' => 'isAnything', - 'type' => 'password', - 'autocomplete' => false - ), - 'PS_MAIL_SMTP_ENCRYPTION' => array( - 'title' => $this->l('Encryption'), - 'hint' => $this->l('Use an encrypt protocol'), - 'desc' => extension_loaded('openssl') ? '' : '/!\\ '.$this->l('SSL does not seem to be available on your server.'), - 'type' => 'select', - 'cast' => 'strval', - 'identifier' => 'mode', - 'list' => array( - array( - 'mode' => 'off', - 'name' => $this->l('None') - ), - array( - 'mode' => 'tls', - 'name' => $this->l('TLS') - ), - array( - 'mode' => 'ssl', - 'name' => $this->l('SSL') - ) - ), - ), - 'PS_MAIL_SMTP_PORT' => array( - 'title' => $this->l('Port'), - 'hint' => $this->l('Port number to use.'), - 'validation' => 'isInt', - 'type' => 'text', - 'cast' => 'intval', - 'class' => 'fixed-width-sm' - ), - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'test' => array( - 'title' => $this->l('Test your email configuration'), - 'hide_multishop_checkbox' => true, - 'fields' => array( - 'PS_SHOP_EMAIL' => array( - 'title' => $this->l('Send a test email to'), - 'type' => 'text', - 'id' => 'testEmail', - 'no_multishop_checkbox' => true - ), - ), - 'bottom' => '<div class="row"><div class="col-lg-9 col-lg-offset-3"> + $this->fields_options = array( + 'email' => array( + 'title' => $this->l('Email'), + 'icon' => 'icon-envelope', + 'fields' => array( + 'PS_MAIL_EMAIL_MESSAGE' => array( + 'title' => $this->l('Send email to'), + 'desc' => $this->l('Where customers send messages from the order page.'), + 'validation' => 'isUnsignedId', + 'type' => 'select', + 'cast' => 'intval', + 'identifier' => 'email_message', + 'list' => $arr + ), + 'PS_MAIL_METHOD' => array( + 'title' => '', + 'validation' => 'isGenericName', + 'type' => 'radio', + 'required' => true, + 'choices' => array( + 3 => $this->l('Never send emails (may be useful for testing purposes)'), + 2 => $this->l('Set my own SMTP parameters (for advanced users ONLY)') + ) + ), + 'PS_MAIL_TYPE' => array( + 'title' => '', + 'validation' => 'isGenericName', + 'type' => 'radio', + 'required' => true, + 'choices' => array( + Mail::TYPE_HTML => $this->l('Send email in HTML format'), + Mail::TYPE_TEXT => $this->l('Send email in text format'), + Mail::TYPE_BOTH => $this->l('Both') + ) + ), + 'PS_LOG_EMAILS' => array( + 'title' => $this->l('Log Emails'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'smtp' => array( + 'title' => $this->l('Email'), + 'fields' => array( + 'PS_MAIL_DOMAIN' => array( + 'title' => $this->l('Mail domain name'), + 'hint' => $this->l('Fully qualified domain name (keep this field empty if you don\'t know).'), + 'empty' => true, 'validation' => + 'isUrl', + 'type' => 'text', + ), + 'PS_MAIL_SERVER' => array( + 'title' => $this->l('SMTP server'), + 'hint' => $this->l('IP address or server name (e.g. smtp.mydomain.com).'), + 'validation' => 'isGenericName', + 'type' => 'text', + ), + 'PS_MAIL_USER' => array( + 'title' => $this->l('SMTP username'), + 'hint' => $this->l('Leave blank if not applicable.'), + 'validation' => 'isGenericName', + 'type' => 'text', + ), + 'PS_MAIL_PASSWD' => array( + 'title' => $this->l('SMTP password'), + 'hint' => $this->l('Leave blank if not applicable.'), + 'validation' => 'isAnything', + 'type' => 'password', + 'autocomplete' => false + ), + 'PS_MAIL_SMTP_ENCRYPTION' => array( + 'title' => $this->l('Encryption'), + 'hint' => $this->l('Use an encrypt protocol'), + 'desc' => extension_loaded('openssl') ? '' : '/!\\ '.$this->l('SSL does not seem to be available on your server.'), + 'type' => 'select', + 'cast' => 'strval', + 'identifier' => 'mode', + 'list' => array( + array( + 'mode' => 'off', + 'name' => $this->l('None') + ), + array( + 'mode' => 'tls', + 'name' => $this->l('TLS') + ), + array( + 'mode' => 'ssl', + 'name' => $this->l('SSL') + ) + ), + ), + 'PS_MAIL_SMTP_PORT' => array( + 'title' => $this->l('Port'), + 'hint' => $this->l('Port number to use.'), + 'validation' => 'isInt', + 'type' => 'text', + 'cast' => 'intval', + 'class' => 'fixed-width-sm' + ), + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'test' => array( + 'title' => $this->l('Test your email configuration'), + 'hide_multishop_checkbox' => true, + 'fields' => array( + 'PS_SHOP_EMAIL' => array( + 'title' => $this->l('Send a test email to'), + 'type' => 'text', + 'id' => 'testEmail', + 'no_multishop_checkbox' => true + ), + ), + 'bottom' => '<div class="row"><div class="col-lg-9 col-lg-offset-3"> <div class="alert" id="mailResultCheck" style="display:none;"></div> </div></div>', - 'buttons' => array( - array('title' => $this->l('Send a test email'), - 'icon' => 'process-icon-envelope', - 'name' => 'btEmailTest', - 'js' => 'verifyMail()', - 'class' => 'btn btn-default pull-right' - ) - ) - ) - ); + 'buttons' => array( + array('title' => $this->l('Send a test email'), + 'icon' => 'process-icon-envelope', + 'name' => 'btEmailTest', + 'js' => 'verifyMail()', + 'class' => 'btn btn-default pull-right' + ) + ) + ) + ); - if (!defined('_PS_HOST_MODE_')) - $this->fields_options['email']['fields']['PS_MAIL_METHOD']['choices'][1] = - $this->l('Use PHP\'s mail() function (recommended; works in most cases)'); + if (!defined('_PS_HOST_MODE_')) { + $this->fields_options['email']['fields']['PS_MAIL_METHOD']['choices'][1] = + $this->l('Use PHP\'s mail() function (recommended; works in most cases)'); + } - ksort($this->fields_options['email']['fields']['PS_MAIL_METHOD']['choices']); - } + ksort($this->fields_options['email']['fields']['PS_MAIL_METHOD']['choices']); + } - public function setMedia() - { - parent::setMedia(); + public function setMedia() + { + parent::setMedia(); - $this->addJs(_PS_JS_DIR_.'/admin/email.js'); + $this->addJs(_PS_JS_DIR_.'/admin/email.js'); - Media::addJsDefL('textMsg', $this->l('This is a test message. Your server is now configured to send email.')); - Media::addJsDefL('textSubject', $this->l('Test message -- Prestashop')); - Media::addJsDefL('textSendOk', $this->l('A test email has been sent to the email address you provided.')); - Media::addJsDefL('textSendError', $this->l('Error: Please check your configuration')); - Media::addJsDefL('token_mail', $this->token); - Media::addJsDefL('errorMail', $this->l('This email address is not valid')); - } - - public function processDelete() - { - if ((int)$id_mail = Tools::getValue('id_mail', 0)) - $return = Mail::eraseLog((int)$id_mail); - else - $return = Mail::eraseAllLogs(); + Media::addJsDefL('textMsg', $this->l('This is a test message. Your server is now configured to send email.', null, true, false)); + Media::addJsDefL('textSubject', $this->l('Test message -- Prestashop', null, true, false)); + Media::addJsDefL('textSendOk', $this->l('A test email has been sent to the email address you provided.', null, true, false)); + Media::addJsDefL('textSendError', $this->l('Error: Please check your configuration', null, true, false)); + Media::addJsDefL('token_mail', $this->token); + Media::addJsDefL('errorMail', $this->l('This email address is not valid', null, true, false)); + } - return $return; - } + public function processDelete() + { + if ((int)$id_mail = Tools::getValue('id_mail', 0)) { + $return = Mail::eraseLog((int)$id_mail); + } else { + $return = Mail::eraseAllLogs(); + } - public function initToolbar() - { - parent::initToolbar(); - $this->toolbar_btn['delete'] = array( - 'short' => 'Erase', - 'desc' => $this->l('Erase all'), - 'js' => 'if (confirm(\''.$this->l('Are you sure?').'\')) document.location = \''.Tools::safeOutput($this->context->link->getAdminLink('AdminEmails')).'&token='.$this->token.'&deletemail=1\';' - ); - unset($this->toolbar_btn['new']); - } - - public function updateOptionPsMailPasswd($value) - { - if (Tools::getValue('PS_MAIL_PASSWD') == '' && Configuration::get('PS_MAIL_PASSWD')) - return true; - else - Configuration::updateValue('PS_MAIL_PASSWD', Tools::getValue('PS_MAIL_PASSWD')); - } + return $return; + } - /** - * AdminController::initContent() override - * @see AdminController::initContent() - */ - public function initContent() - { - $this->initTabModuleList(); - $this->initToolbar(); - $this->initPageHeaderToolbar(); - $this->addToolBarModulesListButton(); - unset($this->toolbar_btn['save']); - $back = $this->context->link->getAdminLink('AdminDashboard'); - - $this->toolbar_btn['back'] = array( - 'href' => $back, - 'desc' => $this->l('Back to the dashboard') - ); - - // $this->content .= $this->renderOptions(); + public function initToolbar() + { + parent::initToolbar(); + $this->toolbar_btn['delete'] = array( + 'short' => 'Erase', + 'desc' => $this->l('Erase all'), + 'js' => 'if (confirm(\''.$this->l('Are you sure?').'\')) document.location = \''.Tools::safeOutput($this->context->link->getAdminLink('AdminEmails')).'&token='.$this->token.'&deletemail=1\';' + ); + unset($this->toolbar_btn['new']); + } - $this->context->smarty->assign(array( - 'content' => $this->content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - - return parent::initContent(); - } + public function updateOptionPsMailPasswd($value) + { + if (Tools::getValue('PS_MAIL_PASSWD') == '' && Configuration::get('PS_MAIL_PASSWD')) { + return true; + } else { + Configuration::updateValue('PS_MAIL_PASSWD', Tools::getValue('PS_MAIL_PASSWD')); + } + } - public function beforeUpdateOptions() - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } - /* PrestaShop demo mode*/ + /** + * AdminController::initContent() override + * @see AdminController::initContent() + */ + public function initContent() + { + $this->initTabModuleList(); + $this->initToolbar(); + $this->initPageHeaderToolbar(); + $this->addToolBarModulesListButton(); + unset($this->toolbar_btn['save']); + $back = $this->context->link->getAdminLink('AdminDashboard'); - // We don't want to update the shop e-mail when sending test e-mails - if (isset($_POST['PS_SHOP_EMAIL'])) - $_POST['PS_SHOP_EMAIL'] = Configuration::get('PS_SHOP_EMAIL'); + $this->toolbar_btn['back'] = array( + 'href' => $back, + 'desc' => $this->l('Back to the dashboard') + ); - if (isset($_POST['PS_MAIL_METHOD']) && $_POST['PS_MAIL_METHOD'] == 2 - && (empty($_POST['PS_MAIL_SERVER']) || empty($_POST['PS_MAIL_SMTP_PORT']))) - $this->errors[] = Tools::displayError('You must define an SMTP server and an SMTP port. If you do not know it, use the PHP mail() function instead.'); - } + // $this->content .= $this->renderOptions(); - public function ajaxProcessSendMailTest() - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - die(Tools::displayError('This functionality has been disabled.')); - /* PrestaShop demo mode */ - if ($this->tabAccess['view'] === '1') - { - $smtpChecked = (trim(Tools::getValue('mailMethod')) == 'smtp'); - $smtpServer = Tools::getValue('smtpSrv'); - $content = urldecode(Tools::getValue('testMsg')); - $content = html_entity_decode($content); - $subject = urldecode(Tools::getValue('testSubject')); - $type = 'text/html'; - $to = Tools::getValue('testEmail'); - $from = Configuration::get('PS_SHOP_EMAIL'); - $smtpLogin = Tools::getValue('smtpLogin'); - $smtpPassword = Tools::getValue('smtpPassword'); - $smtpPassword = (!empty($smtpPassword)) ? urldecode($smtpPassword) : Configuration::get('PS_MAIL_PASSWD'); - $smtpPassword = str_replace( - array('<', '>', '"', '&'), - array('<', '>', '"', '&'), - Tools::htmlentitiesUTF8($smtpPassword) - ); - - $smtpPort = Tools::getValue('smtpPort'); - $smtpEncryption = Tools::getValue('smtpEnc'); - - $result = Mail::sendMailTest(Tools::htmlentitiesUTF8($smtpChecked), Tools::htmlentitiesUTF8($smtpServer), Tools::htmlentitiesUTF8($content), Tools::htmlentitiesUTF8($subject), Tools::htmlentitiesUTF8($type), Tools::htmlentitiesUTF8($to), Tools::htmlentitiesUTF8($from), Tools::htmlentitiesUTF8($smtpLogin), $smtpPassword, Tools::htmlentitiesUTF8($smtpPort), Tools::htmlentitiesUTF8($smtpEncryption)); - die($result === true ? 'ok' : $result); - } - } + $this->context->smarty->assign(array( + 'content' => $this->content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + + return parent::initContent(); + } + + public function beforeUpdateOptions() + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } + /* PrestaShop demo mode*/ + + // We don't want to update the shop e-mail when sending test e-mails + if (isset($_POST['PS_SHOP_EMAIL'])) { + $_POST['PS_SHOP_EMAIL'] = Configuration::get('PS_SHOP_EMAIL'); + } + + if (isset($_POST['PS_MAIL_METHOD']) && $_POST['PS_MAIL_METHOD'] == 2 + && (empty($_POST['PS_MAIL_SERVER']) || empty($_POST['PS_MAIL_SMTP_PORT']))) { + $this->errors[] = Tools::displayError('You must define an SMTP server and an SMTP port. If you do not know it, use the PHP mail() function instead.'); + } + } + + public function ajaxProcessSendMailTest() + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + die(Tools::displayError('This functionality has been disabled.')); + } + /* PrestaShop demo mode */ + if ($this->tabAccess['view'] === '1') { + $smtpChecked = (trim(Tools::getValue('mailMethod')) == 'smtp'); + $smtpServer = Tools::getValue('smtpSrv'); + $content = urldecode(Tools::getValue('testMsg')); + $content = html_entity_decode($content); + $subject = urldecode(Tools::getValue('testSubject')); + $type = 'text/html'; + $to = Tools::getValue('testEmail'); + $from = Configuration::get('PS_SHOP_EMAIL'); + $smtpLogin = Tools::getValue('smtpLogin'); + $smtpPassword = Tools::getValue('smtpPassword'); + $smtpPassword = (!empty($smtpPassword)) ? urldecode($smtpPassword) : Configuration::get('PS_MAIL_PASSWD'); + $smtpPassword = str_replace( + array('<', '>', '"', '&'), + array('<', '>', '"', '&'), + Tools::htmlentitiesUTF8($smtpPassword) + ); + + $smtpPort = Tools::getValue('smtpPort'); + $smtpEncryption = Tools::getValue('smtpEnc'); + + $result = Mail::sendMailTest(Tools::htmlentitiesUTF8($smtpChecked), Tools::htmlentitiesUTF8($smtpServer), Tools::htmlentitiesUTF8($content), Tools::htmlentitiesUTF8($subject), Tools::htmlentitiesUTF8($type), Tools::htmlentitiesUTF8($to), Tools::htmlentitiesUTF8($from), Tools::htmlentitiesUTF8($smtpLogin), $smtpPassword, Tools::htmlentitiesUTF8($smtpPort), Tools::htmlentitiesUTF8($smtpEncryption)); + die($result === true ? 'ok' : $result); + } + } } diff --git a/controllers/admin/AdminEmployeesController.php b/controllers/admin/AdminEmployeesController.php index e46c889e..b55aee8f 100644 --- a/controllers/admin/AdminEmployeesController.php +++ b/controllers/admin/AdminEmployeesController.php @@ -29,658 +29,664 @@ */ class AdminEmployeesControllerCore extends AdminController { - /** @var array profiles list */ - protected $profiles_array = array(); + /** @var array profiles list */ + protected $profiles_array = array(); - /** @var array themes list*/ - protected $themes = array(); + /** @var array themes list*/ + protected $themes = array(); - /** @var array tabs list*/ - protected $tabs_list = array(); + /** @var array tabs list*/ + protected $tabs_list = array(); - protected $restrict_edition = false; + protected $restrict_edition = false; - public function __construct() - { - $this->bootstrap = true; - $this->table = 'employee'; - $this->className = 'Employee'; - $this->lang = false; - $this->context = Context::getContext(); + public function __construct() + { + $this->bootstrap = true; + $this->table = 'employee'; + $this->className = 'Employee'; + $this->lang = false; + $this->context = Context::getContext(); - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->addRowActionSkipList('delete', array((int)$this->context->employee->id)); + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->addRowActionSkipList('delete', array((int)$this->context->employee->id)); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); - /* - check if there are more than one superAdmin - if it's the case then we can delete a superAdmin - */ - $super_admin = Employee::countProfile(_PS_ADMIN_PROFILE_, true); - if ($super_admin == 1) - { - $super_admin_array = Employee::getEmployeesByProfile(_PS_ADMIN_PROFILE_, true); - $super_admin_id = array(); - foreach ($super_admin_array as $key => $val) - $super_admin_id[] = $val['id_employee']; - $this->addRowActionSkipList('delete', $super_admin_id); - } + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); + /* + check if there are more than one superAdmin + if it's the case then we can delete a superAdmin + */ + $super_admin = Employee::countProfile(_PS_ADMIN_PROFILE_, true); + if ($super_admin == 1) { + $super_admin_array = Employee::getEmployeesByProfile(_PS_ADMIN_PROFILE_, true); + $super_admin_id = array(); + foreach ($super_admin_array as $key => $val) { + $super_admin_id[] = $val['id_employee']; + } + $this->addRowActionSkipList('delete', $super_admin_id); + } - $profiles = Profile::getProfiles($this->context->language->id); - if (!$profiles) - $this->errors[] = Tools::displayError('No profile.'); - else - foreach ($profiles as $profile) - $this->profiles_array[$profile['name']] = $profile['name']; + $profiles = Profile::getProfiles($this->context->language->id); + if (!$profiles) { + $this->errors[] = Tools::displayError('No profile.'); + } else { + foreach ($profiles as $profile) { + $this->profiles_array[$profile['name']] = $profile['name']; + } + } - $this->fields_list = array( - 'id_employee' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'firstname' => array('title' => $this->l('First Name')), - 'lastname' => array('title' => $this->l('Last Name')), - 'email' => array('title' => $this->l('Email address')), - 'profile' => array('title' => $this->l('Profile'), 'type' => 'select', 'list' => $this->profiles_array, - 'filter_key' => 'pl!name', 'class' => 'fixed-width-lg'), - 'active' => array('title' => $this->l('Active'), 'align' => 'center', 'active' => 'status', - 'type' => 'bool', 'class' => 'fixed-width-sm'), - ); + $this->fields_list = array( + 'id_employee' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'firstname' => array('title' => $this->l('First Name')), + 'lastname' => array('title' => $this->l('Last Name')), + 'email' => array('title' => $this->l('Email address')), + 'profile' => array('title' => $this->l('Profile'), 'type' => 'select', 'list' => $this->profiles_array, + 'filter_key' => 'pl!name', 'class' => 'fixed-width-lg'), + 'active' => array('title' => $this->l('Active'), 'align' => 'center', 'active' => 'status', + 'type' => 'bool', 'class' => 'fixed-width-sm'), + ); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Employee options'), - 'fields' => array( - 'PS_PASSWD_TIME_BACK' => array( - 'title' => $this->l('Password regeneration'), - 'hint' => $this->l('Security: Minimum time to wait between two password changes.'), - 'cast' => 'intval', - 'type' => 'text', - 'suffix' => ' '.$this->l('minutes'), - 'visibility' => Shop::CONTEXT_ALL - ), - 'PS_BO_ALLOW_EMPLOYEE_FORM_LANG' => array( - 'title' => $this->l('Memorize the language used in Admin panel forms'), - 'hint' => $this->l('Allow employees to select a specific language for the Admin panel form.'), - 'cast' => 'intval', - 'type' => 'select', - 'identifier' => 'value', - 'list' => array( - '0' => array('value' => 0, 'name' => $this->l('No')), - '1' => array('value' => 1, 'name' => $this->l('Yes') - ) - ), 'visibility' => Shop::CONTEXT_ALL) - ), - 'submit' => array('title' => $this->l('Save')) - ) - ); - $rtl = $this->context->language->is_rtl ? '_rtl' : ''; - $path = _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes'.DIRECTORY_SEPARATOR; - foreach (scandir($path) as $theme) - if ($theme[0] != '.' && is_dir($path.$theme) && (@filemtime($path.$theme.DIRECTORY_SEPARATOR.'css'.DIRECTORY_SEPARATOR.'admin-theme.css'))) - { - $this->themes[] = array('id' => $theme.'|admin-theme'.$rtl.'.css', 'name' => $this->l('Default')); - if (file_exists($path.$theme.DIRECTORY_SEPARATOR.'css'.DIRECTORY_SEPARATOR.'schemes'.$rtl)) - foreach (scandir($path.$theme.DIRECTORY_SEPARATOR.'css'.DIRECTORY_SEPARATOR.'schemes'.$rtl) as $css) - if ($css[0] != '.' && preg_match('/\.css$/', $css)) - { - $name = strpos($css, 'admin-theme-') !== false ? Tools::ucfirst(preg_replace('/^admin-theme-(.*)\.css$/', '$1', $css)) : $css; - $this->themes[] = array('id' => $theme.'|schemes'.$rtl.'/'.$css, 'name' => $name); - } - } + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Employee options'), + 'fields' => array( + 'PS_PASSWD_TIME_BACK' => array( + 'title' => $this->l('Password regeneration'), + 'hint' => $this->l('Security: Minimum time to wait between two password changes.'), + 'cast' => 'intval', + 'type' => 'text', + 'suffix' => ' '.$this->l('minutes'), + 'visibility' => Shop::CONTEXT_ALL + ), + 'PS_BO_ALLOW_EMPLOYEE_FORM_LANG' => array( + 'title' => $this->l('Memorize the language used in Admin panel forms'), + 'hint' => $this->l('Allow employees to select a specific language for the Admin panel form.'), + 'cast' => 'intval', + 'type' => 'select', + 'identifier' => 'value', + 'list' => array( + '0' => array('value' => 0, 'name' => $this->l('No')), + '1' => array('value' => 1, 'name' => $this->l('Yes') + ) + ), 'visibility' => Shop::CONTEXT_ALL) + ), + 'submit' => array('title' => $this->l('Save')) + ) + ); + $rtl = $this->context->language->is_rtl ? '_rtl' : ''; + $path = _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes'.DIRECTORY_SEPARATOR; + foreach (scandir($path) as $theme) { + if ($theme[0] != '.' && is_dir($path.$theme) && (@filemtime($path.$theme.DIRECTORY_SEPARATOR.'css'.DIRECTORY_SEPARATOR.'admin-theme.css'))) { + $this->themes[] = array('id' => $theme.'|admin-theme'.$rtl.'.css', 'name' => $theme == 'default' ? $this->l('Default') : ucfirst($theme)); + if (file_exists($path.$theme.DIRECTORY_SEPARATOR.'css'.DIRECTORY_SEPARATOR.'schemes'.$rtl)) { + foreach (scandir($path.$theme.DIRECTORY_SEPARATOR.'css'.DIRECTORY_SEPARATOR.'schemes'.$rtl) as $css) { + if ($css[0] != '.' && preg_match('/\.css$/', $css)) { + $name = strpos($css, 'admin-theme-') !== false ? Tools::ucfirst(preg_replace('/^admin-theme-(.*)\.css$/', '$1', $css)) : $css; + $this->themes[] = array('id' => $theme.'|schemes'.$rtl.'/'.$css, 'name' => $name); + } + } + } + } + } - $home_tab = Tab::getInstanceFromClassName('AdminDashboard', $this->context->language->id); - $this->tabs_list[$home_tab->id] = array( - 'name' => $home_tab->name, - 'id_tab' => $home_tab->id, - 'children' => array(array( - 'id_tab' => $home_tab->id, - 'name' => $home_tab->name - )) - ); - foreach (Tab::getTabs($this->context->language->id, 0) as $tab) - { - if (Tab::checkTabRights($tab['id_tab'])) - { - $this->tabs_list[$tab['id_tab']] = $tab; - foreach (Tab::getTabs($this->context->language->id, $tab['id_tab']) as $children) - if (Tab::checkTabRights($children['id_tab'])) - $this->tabs_list[$tab['id_tab']]['children'][] = $children; - } - } - parent::__construct(); + $home_tab = Tab::getInstanceFromClassName('AdminDashboard', $this->context->language->id); + $this->tabs_list[$home_tab->id] = array( + 'name' => $home_tab->name, + 'id_tab' => $home_tab->id, + 'children' => array(array( + 'id_tab' => $home_tab->id, + 'name' => $home_tab->name + )) + ); + foreach (Tab::getTabs($this->context->language->id, 0) as $tab) { + if (Tab::checkTabRights($tab['id_tab'])) { + $this->tabs_list[$tab['id_tab']] = $tab; + foreach (Tab::getTabs($this->context->language->id, $tab['id_tab']) as $children) { + if (Tab::checkTabRights($children['id_tab'])) { + $this->tabs_list[$tab['id_tab']]['children'][] = $children; + } + } + } + } + parent::__construct(); - // An employee can edit its own profile - if ($this->context->employee->id == Tools::getValue('id_employee')) - { - $this->tabAccess['view'] = '1'; - $this->restrict_edition = true; - $this->tabAccess['edit'] = '1'; - } - } + // An employee can edit its own profile + if ($this->context->employee->id == Tools::getValue('id_employee')) { + $this->tabAccess['view'] = '1'; + $this->restrict_edition = true; + $this->tabAccess['edit'] = '1'; + } + } - public function setMedia() - { - parent::setMedia(); - $this->addJS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/vendor/jquery-passy.js'); - $this->addjQueryPlugin('validate'); - $this->addJS(_PS_JS_DIR_.'jquery/plugins/validate/localization/messages_'.$this->context->language->iso_code.'.js'); - } + public function setMedia() + { + parent::setMedia(); + $this->addJS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/js/vendor/jquery-passy.js'); + $this->addjQueryPlugin('validate'); + $this->addJS(_PS_JS_DIR_.'jquery/plugins/validate/localization/messages_'.$this->context->language->iso_code.'.js'); + } - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); - if (empty($this->display)) - $this->page_header_toolbar_btn['new_employee'] = array( - 'href' => self::$currentIndex.'&addemployee&token='.$this->token, - 'desc' => $this->l('Add new employee', null, null, false), - 'icon' => 'process-icon-new' - ); + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_employee'] = array( + 'href' => self::$currentIndex.'&addemployee&token='.$this->token, + 'desc' => $this->l('Add new employee', null, null, false), + 'icon' => 'process-icon-new' + ); + } - if ($this->display == 'edit') - { - $obj = $this->loadObject(true); - if (Validate::isLoadedObject($obj)) - { - /** @var Employee $obj */ - array_pop($this->toolbar_title); - $this->toolbar_title[] = sprintf($this->l('Edit: %1$s %2$s'), $obj->lastname, $obj->firstname); - $this->page_header_toolbar_title = implode(' '.Configuration::get('PS_NAVIGATION_PIPE').' ', - $this->toolbar_title); - } - } - } + if ($this->display == 'edit') { + $obj = $this->loadObject(true); + if (Validate::isLoadedObject($obj)) { + /** @var Employee $obj */ + array_pop($this->toolbar_title); + $this->toolbar_title[] = sprintf($this->l('Edit: %1$s %2$s'), $obj->lastname, $obj->firstname); + $this->page_header_toolbar_title = implode(' '.Configuration::get('PS_NAVIGATION_PIPE').' ', + $this->toolbar_title); + } + } + } - public function renderList() - { - $this->_select = 'pl.`name` AS profile'; - $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'profile` p ON a.`id_profile` = p.`id_profile` + public function renderList() + { + $this->_select = 'pl.`name` AS profile'; + $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'profile` p ON a.`id_profile` = p.`id_profile` LEFT JOIN `'._DB_PREFIX_.'profile_lang` pl ON (pl.`id_profile` = p.`id_profile` AND pl.`id_lang` = ' - .(int)$this->context->language->id.')'; - $this->_use_found_rows = false; + .(int)$this->context->language->id.')'; + $this->_use_found_rows = false; - return parent::renderList(); - } + return parent::renderList(); + } - public function renderForm() - { - /** @var Employee $obj */ - if (!($obj = $this->loadObject(true))) - return; + public function renderForm() + { + /** @var Employee $obj */ + if (!($obj = $this->loadObject(true))) { + return; + } - $available_profiles = Profile::getProfiles($this->context->language->id); + $available_profiles = Profile::getProfiles($this->context->language->id); - if ($obj->id_profile == _PS_ADMIN_PROFILE_ && $this->context->employee->id_profile != _PS_ADMIN_PROFILE_) - { - $this->errors[] = Tools::displayError('You cannot edit the SuperAdmin profile.'); - return parent::renderForm(); - } + if ($obj->id_profile == _PS_ADMIN_PROFILE_ && $this->context->employee->id_profile != _PS_ADMIN_PROFILE_) { + $this->errors[] = Tools::displayError('You cannot edit the SuperAdmin profile.'); + return parent::renderForm(); + } - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Employees'), - 'icon' => 'icon-user' - ), - 'input' => array( - array( - 'type' => 'text', - 'class' => 'fixed-width-xl', - 'label' => $this->l('First Name'), - 'name' => 'firstname', - 'required' => true - ), - array( - 'type' => 'text', - 'class' => 'fixed-width-xl', - 'label' => $this->l('Last Name'), - 'name' => 'lastname', - 'required' => true - ), - array( - 'type' => 'html', - 'name' => 'employee_avatar', - 'html_content' => '<div id="employee-thumbnail"><a href="http://www.prestashop.com/forums/index.php?app=core&module=usercp" target="_blank" style="background-image:url('.$obj->getImage().')"></a></div> + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Employees'), + 'icon' => 'icon-user' + ), + 'input' => array( + array( + 'type' => 'text', + 'class' => 'fixed-width-xl', + 'label' => $this->l('First Name'), + 'name' => 'firstname', + 'required' => true + ), + array( + 'type' => 'text', + 'class' => 'fixed-width-xl', + 'label' => $this->l('Last Name'), + 'name' => 'lastname', + 'required' => true + ), + array( + 'type' => 'html', + 'name' => 'employee_avatar', + 'html_content' => '<div id="employee-thumbnail"><a href="http://www.prestashop.com/forums/index.php?app=core&module=usercp" target="_blank" style="background-image:url('.$obj->getImage().')"></a></div> <div class="alert alert-info">'.sprintf($this->l('Your avatar in PrestaShop 1.6.x is your profile picture on %1$s. To change your avatar, log in to PrestaShop.com with your email %2$s and follow the on-screen instructions.'), '<a href="http://www.prestashop.com/forums/index.php?app=core&module=usercp" class="alert-link" target="_blank">PrestaShop.com</a>', $obj->email).'</div>', - ), - array( - 'type' => 'text', - 'class'=> 'fixed-width-xxl', - 'prefix' => '<i class="icon-envelope-o"></i>', - 'label' => $this->l('Email address'), - 'name' => 'email', - 'required' => true, - 'autocomplete' => false - ), - ), - ); + ), + array( + 'type' => 'text', + 'class'=> 'fixed-width-xxl', + 'prefix' => '<i class="icon-envelope-o"></i>', + 'label' => $this->l('Email address'), + 'name' => 'email', + 'required' => true, + 'autocomplete' => false + ), + ), + ); - if ($this->restrict_edition) - { - $this->fields_form['input'][] = array( - 'type' => 'change-password', - 'label' => $this->l('Password'), - 'name' => 'passwd' - ); + if ($this->restrict_edition) { + $this->fields_form['input'][] = array( + 'type' => 'change-password', + 'label' => $this->l('Password'), + 'name' => 'passwd' + ); - if (Tab::checkTabRights(Tab::getIdFromClassName('AdminModulesController'))) - $this->fields_form['input'][] = array( - 'type' => 'prestashop_addons', - 'label' => 'PrestaShop Addons', - 'name' => 'prestashop_addons', - ); - } - else - $this->fields_form['input'][] = array( - 'type' => 'password', - 'label' => $this->l('Password'), - 'hint' => sprintf($this->l('Password should be at least %s characters long.'), Validate::ADMIN_PASSWORD_LENGTH), - 'name' => 'passwd' - ); + if (Tab::checkTabRights(Tab::getIdFromClassName('AdminModulesController'))) { + $this->fields_form['input'][] = array( + 'type' => 'prestashop_addons', + 'label' => 'PrestaShop Addons', + 'name' => 'prestashop_addons', + ); + } + } else { + $this->fields_form['input'][] = array( + 'type' => 'password', + 'label' => $this->l('Password'), + 'hint' => sprintf($this->l('Password should be at least %s characters long.'), Validate::ADMIN_PASSWORD_LENGTH), + 'name' => 'passwd' + ); + } - $this->fields_form['input'] = array_merge($this->fields_form['input'], array( - array( - 'type' => 'switch', - 'label' => $this->l('Connect to PrestaShop'), - 'name' => 'optin', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'optin_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'optin_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - 'hint' => $this->l('PrestaShop can provide you with guidance on a regular basis by sending you tips on how to optimize the management of your store which will help you grow your business. If you do not wish to receive these tips, please uncheck this box.') - ), - array( - 'type' => 'default_tab', - 'label' => $this->l('Default page'), - 'name' => 'default_tab', - 'hint' => $this->l('This page will be displayed just after login.'), - 'options' => $this->tabs_list - ), - array( - 'type' => 'select', - 'label' => $this->l('Language'), - 'name' => 'id_lang', - //'required' => true, - 'options' => array( - 'query' => Language::getLanguages(false), - 'id' => 'id_lang', - 'name' => 'name' - ) - ), - array( - 'type' => 'select', - 'label' => $this->l('Theme'), - 'name' => 'bo_theme_css', - 'options' => array( - 'query' => $this->themes, - 'id' => 'id', - 'name' => 'name' - ), - 'onchange' => 'var value_array = $(this).val().split("|"); $("link").first().attr("href", "themes/" + value_array[0] + "/css/" + value_array[1]);', - 'hint' => $this->l('Back office theme.') - ), - array( - 'type' => 'radio', - 'label' => $this->l('Admin menu orientation'), - 'name' => 'bo_menu', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'bo_menu_on', - 'value' => 0, - 'label' => $this->l('Top') - ), - array( - 'id' => 'bo_menu_off', - 'value' => 1, - 'label' => $this->l('Left') - ) - ) - ) - )); + $this->fields_form['input'] = array_merge($this->fields_form['input'], array( + array( + 'type' => 'switch', + 'label' => $this->l('Subscribe to PrestaShop newsletter'), + 'name' => 'optin', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'optin_on', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'optin_off', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + 'hint' => $this->l('PrestaShop can provide you with guidance on a regular basis by sending you tips on how to optimize the management of your store which will help you grow your business. If you do not wish to receive these tips, you can disable this option.') + ), + array( + 'type' => 'default_tab', + 'label' => $this->l('Default page'), + 'name' => 'default_tab', + 'hint' => $this->l('This page will be displayed just after login.'), + 'options' => $this->tabs_list + ), + array( + 'type' => 'select', + 'label' => $this->l('Language'), + 'name' => 'id_lang', + //'required' => true, + 'options' => array( + 'query' => Language::getLanguages(false), + 'id' => 'id_lang', + 'name' => 'name' + ) + ), + array( + 'type' => 'select', + 'label' => $this->l('Theme'), + 'name' => 'bo_theme_css', + 'options' => array( + 'query' => $this->themes, + 'id' => 'id', + 'name' => 'name' + ), + 'onchange' => 'var value_array = $(this).val().split("|"); $("link").first().attr("href", "themes/" + value_array[0] + "/css/" + value_array[1]);', + 'hint' => $this->l('Back office theme.') + ), + array( + 'type' => 'radio', + 'label' => $this->l('Admin menu orientation'), + 'name' => 'bo_menu', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'bo_menu_on', + 'value' => 0, + 'label' => $this->l('Top') + ), + array( + 'id' => 'bo_menu_off', + 'value' => 1, + 'label' => $this->l('Left') + ) + ) + ) + )); - if ((int)$this->tabAccess['edit'] && !$this->restrict_edition) - { - $this->fields_form['input'][] = array( - 'type' => 'switch', - 'label' => $this->l('Active'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Allow or disallow this employee to log into the Admin panel.') - ); + if ((int)$this->tabAccess['edit'] && !$this->restrict_edition) { + $this->fields_form['input'][] = array( + 'type' => 'switch', + 'label' => $this->l('Active'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Allow or disallow this employee to log into the Admin panel.') + ); - // if employee is not SuperAdmin (id_profile = 1), don't make it possible to select the admin profile - if ($this->context->employee->id_profile != _PS_ADMIN_PROFILE_) - foreach ($available_profiles as $i => $profile) - if ($available_profiles[$i]['id_profile'] == _PS_ADMIN_PROFILE_) - { - unset($available_profiles[$i]); - break; - } - $this->fields_form['input'][] = array( - 'type' => 'select', - 'label' => $this->l('Permission profile'), - 'name' => 'id_profile', - 'required' => true, - 'options' => array( - 'query' => $available_profiles, - 'id' => 'id_profile', - 'name' => 'name', - 'default' => array( - 'value' => '', - 'label' => $this->l('-- Choose --') - ) - ) - ); + // if employee is not SuperAdmin (id_profile = 1), don't make it possible to select the admin profile + if ($this->context->employee->id_profile != _PS_ADMIN_PROFILE_) { + foreach ($available_profiles as $i => $profile) { + if ($available_profiles[$i]['id_profile'] == _PS_ADMIN_PROFILE_) { + unset($available_profiles[$i]); + break; + } + } + } + $this->fields_form['input'][] = array( + 'type' => 'select', + 'label' => $this->l('Permission profile'), + 'name' => 'id_profile', + 'required' => true, + 'options' => array( + 'query' => $available_profiles, + 'id' => 'id_profile', + 'name' => 'name', + 'default' => array( + 'value' => '', + 'label' => $this->l('-- Choose --') + ) + ) + ); - if (Shop::isFeatureActive()) - { - $this->context->smarty->assign('_PS_ADMIN_PROFILE_', (int)_PS_ADMIN_PROFILE_); - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'hint' => $this->l('Select the shops the employee is allowed to access.'), - 'name' => 'checkBoxShopAsso', - ); - } - } + if (Shop::isFeatureActive()) { + $this->context->smarty->assign('_PS_ADMIN_PROFILE_', (int)_PS_ADMIN_PROFILE_); + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'hint' => $this->l('Select the shops the employee is allowed to access.'), + 'name' => 'checkBoxShopAsso', + ); + } + } - $this->fields_form['submit'] = array( - 'title' => $this->l('Save'), - ); + $this->fields_form['submit'] = array( + 'title' => $this->l('Save'), + ); - $this->fields_value['passwd'] = false; - $this->fields_value['bo_theme_css'] = $obj->bo_theme.'|'.$obj->bo_css; + $this->fields_value['passwd'] = false; + $this->fields_value['bo_theme_css'] = $obj->bo_theme.'|'.$obj->bo_css; - if (empty($obj->id)) - $this->fields_value['id_lang'] = $this->context->language->id; + if (empty($obj->id)) { + $this->fields_value['id_lang'] = $this->context->language->id; + } - return parent::renderForm(); - } + return parent::renderForm(); + } - protected function _childValidation() - { - if (!($obj = $this->loadObject(true))) - return false; + protected function _childValidation() + { + if (!($obj = $this->loadObject(true))) { + return false; + } - if (Tools::getValue('id_profile') == _PS_ADMIN_PROFILE_ && $this->context->employee->id_profile != _PS_ADMIN_PROFILE_) - $this->errors[] = Tools::displayError('The provided profile is invalid'); + if (Tools::getValue('id_profile') == _PS_ADMIN_PROFILE_ && $this->context->employee->id_profile != _PS_ADMIN_PROFILE_) { + $this->errors[] = Tools::displayError('The provided profile is invalid'); + } - $email = $this->getFieldValue($obj, 'email'); - if (Validate::isEmail($email) && Employee::employeeExists($email) && (!Tools::getValue('id_employee') - || ($employee = new Employee((int)Tools::getValue('id_employee'))) && $employee->email != $email)) - $this->errors[] = Tools::displayError('An account already exists for this email address:').' '.$email; - } + $email = $this->getFieldValue($obj, 'email'); + if (Validate::isEmail($email) && Employee::employeeExists($email) && (!Tools::getValue('id_employee') + || ($employee = new Employee((int)Tools::getValue('id_employee'))) && $employee->email != $email)) { + $this->errors[] = Tools::displayError('An account already exists for this email address:').' '.$email; + } + } - public function processDelete() - { - if (!$this->canModifyEmployee()) - return false; + public function processDelete() + { + if (!$this->canModifyEmployee()) { + return false; + } - return parent::processDelete(); - } + return parent::processDelete(); + } - public function processStatus() - { - if (!$this->canModifyEmployee()) - return false; + public function processStatus() + { + if (!$this->canModifyEmployee()) { + return false; + } - parent::processStatus(); - } + parent::processStatus(); + } - protected function processBulkDelete() - { - if (is_array($this->boxes) && !empty($this->boxes)) - foreach ($this->boxes as $id_employee) - if ((int)$this->context->employee->id == (int)$id_employee) - { - $this->restrict_edition = true; - return $this->canModifyEmployee(); - } + protected function processBulkDelete() + { + if (is_array($this->boxes) && !empty($this->boxes)) { + foreach ($this->boxes as $id_employee) { + if ((int)$this->context->employee->id == (int)$id_employee) { + $this->restrict_edition = true; + return $this->canModifyEmployee(); + } + } + } - return parent::processBulkDelete(); - } + return parent::processBulkDelete(); + } - protected function canModifyEmployee() - { - if ($this->restrict_edition) - { - $this->errors[] = Tools::displayError('You cannot disable or delete your own account.'); - return false; - } + protected function canModifyEmployee() + { + if ($this->restrict_edition) { + $this->errors[] = Tools::displayError('You cannot disable or delete your own account.'); + return false; + } - $employee = new Employee(Tools::getValue('id_employee')); - if ($employee->isLastAdmin()) - { - $this->errors[] = Tools::displayError('You cannot disable or delete the administrator account.'); - return false; - } + $employee = new Employee(Tools::getValue('id_employee')); + if ($employee->isLastAdmin()) { + $this->errors[] = Tools::displayError('You cannot disable or delete the administrator account.'); + return false; + } - // It is not possible to delete an employee if he manages warehouses - $warehouses = Warehouse::getWarehousesByEmployee((int)Tools::getValue('id_employee')); - if (Tools::isSubmit('deleteemployee') && count($warehouses) > 0) - { - $this->errors[] = Tools::displayError('You cannot delete this account because it manages warehouses. Check your warehouses first.'); - return false; - } + // It is not possible to delete an employee if he manages warehouses + $warehouses = Warehouse::getWarehousesByEmployee((int)Tools::getValue('id_employee')); + if (Tools::isSubmit('deleteemployee') && count($warehouses) > 0) { + $this->errors[] = Tools::displayError('You cannot delete this account because it manages warehouses. Check your warehouses first.'); + return false; + } - return true; - } + return true; + } - public function processSave() - { - $employee = new Employee((int)Tools::getValue('id_employee')); + public function processSave() + { + $employee = new Employee((int)Tools::getValue('id_employee')); - // If the employee is editing its own account - if ($this->restrict_edition) - { - $current_password = trim(Tools::getValue('old_passwd')); - if (Tools::getValue('passwd') && (empty($current_password) || !Validate::isPasswdAdmin($current_password) || !$employee->getByEmail($employee->email, $current_password))) - $this->errors[] = Tools::displayError('Your current password is invalid.'); - elseif (Tools::getValue('passwd') && (!Tools::getValue('passwd2') || Tools::getValue('passwd') !== Tools::getValue('passwd2'))) - $this->errors[] = Tools::displayError('The confirmation password does not match.'); + // If the employee is editing its own account + if ($this->restrict_edition) { + $current_password = trim(Tools::getValue('old_passwd')); + if (Tools::getValue('passwd') && (empty($current_password) || !Validate::isPasswdAdmin($current_password) || !$employee->getByEmail($employee->email, $current_password))) { + $this->errors[] = Tools::displayError('Your current password is invalid.'); + } elseif (Tools::getValue('passwd') && (!Tools::getValue('passwd2') || Tools::getValue('passwd') !== Tools::getValue('passwd2'))) { + $this->errors[] = Tools::displayError('The confirmation password does not match.'); + } - $_POST['id_profile'] = $_GET['id_profile'] = $employee->id_profile; - $_POST['active'] = $_GET['active'] = $employee->active; + $_POST['id_profile'] = $_GET['id_profile'] = $employee->id_profile; + $_POST['active'] = $_GET['active'] = $employee->active; - // Unset set shops - foreach ($_POST as $postkey => $postvalue) - if (strstr($postkey, 'checkBoxShopAsso_'.$this->table) !== false) - unset($_POST[$postkey]); - foreach ($_GET as $postkey => $postvalue) - if (strstr($postkey, 'checkBoxShopAsso_'.$this->table) !== false) - unset($_GET[$postkey]); + // Unset set shops + foreach ($_POST as $postkey => $postvalue) { + if (strstr($postkey, 'checkBoxShopAsso_'.$this->table) !== false) { + unset($_POST[$postkey]); + } + } + foreach ($_GET as $postkey => $postvalue) { + if (strstr($postkey, 'checkBoxShopAsso_'.$this->table) !== false) { + unset($_GET[$postkey]); + } + } - // Add current shops associated to the employee - $result = Shop::getShopById((int)$employee->id, $this->identifier, $this->table); - foreach ($result as $row) - { - $key = 'checkBoxShopAsso_'.$this->table; - if (!isset($_POST[$key])) - $_POST[$key] = array(); - if (!isset($_GET[$key])) - $_GET[$key] = array(); - $_POST[$key][$row['id_shop']] = 1; - $_GET[$key][$row['id_shop']] = 1; - } - } - else - { - $_POST['id_last_order'] = $employee->getLastElementsForNotify('order'); - $_POST['id_last_customer_message'] = $employee->getLastElementsForNotify('customer_message'); - $_POST['id_last_customer'] = $employee->getLastElementsForNotify('customer'); - } + // Add current shops associated to the employee + $result = Shop::getShopById((int)$employee->id, $this->identifier, $this->table); + foreach ($result as $row) { + $key = 'checkBoxShopAsso_'.$this->table; + if (!isset($_POST[$key])) { + $_POST[$key] = array(); + } + if (!isset($_GET[$key])) { + $_GET[$key] = array(); + } + $_POST[$key][$row['id_shop']] = 1; + $_GET[$key][$row['id_shop']] = 1; + } + } else { + $_POST['id_last_order'] = $employee->getLastElementsForNotify('order'); + $_POST['id_last_customer_message'] = $employee->getLastElementsForNotify('customer_message'); + $_POST['id_last_customer'] = $employee->getLastElementsForNotify('customer'); + } - //if profile is super admin, manually fill checkBoxShopAsso_employee because in the form they are disabled. - if ($_POST['id_profile'] == _PS_ADMIN_PROFILE_) - { - $result = Db::getInstance()->executeS('SELECT id_shop FROM '._DB_PREFIX_.'shop'); - foreach ($result as $row) - { - $key = 'checkBoxShopAsso_'.$this->table; - if (!isset($_POST[$key])) - $_POST[$key] = array(); - if (!isset($_GET[$key])) - $_GET[$key] = array(); - $_POST[$key][$row['id_shop']] = 1; - $_GET[$key][$row['id_shop']] = 1; - } - } + //if profile is super admin, manually fill checkBoxShopAsso_employee because in the form they are disabled. + if ($_POST['id_profile'] == _PS_ADMIN_PROFILE_) { + $result = Db::getInstance()->executeS('SELECT id_shop FROM '._DB_PREFIX_.'shop'); + foreach ($result as $row) { + $key = 'checkBoxShopAsso_'.$this->table; + if (!isset($_POST[$key])) { + $_POST[$key] = array(); + } + if (!isset($_GET[$key])) { + $_GET[$key] = array(); + } + $_POST[$key][$row['id_shop']] = 1; + $_GET[$key][$row['id_shop']] = 1; + } + } - if ($employee->isLastAdmin()) - { - if (Tools::getValue('id_profile') != (int)_PS_ADMIN_PROFILE_) - { - $this->errors[] = Tools::displayError('You should have at least one employee in the administrator group.'); - return false; - } + if ($employee->isLastAdmin()) { + if (Tools::getValue('id_profile') != (int)_PS_ADMIN_PROFILE_) { + $this->errors[] = Tools::displayError('You should have at least one employee in the administrator group.'); + return false; + } - if (Tools::getvalue('active') == 0) - { - $this->errors[] = Tools::displayError('You cannot disable or delete the administrator account.'); - return false; - } - } + if (Tools::getvalue('active') == 0) { + $this->errors[] = Tools::displayError('You cannot disable or delete the administrator account.'); + return false; + } + } - if (Tools::getValue('bo_theme_css')) - { - $bo_theme = explode('|', Tools::getValue('bo_theme_css')); - $_POST['bo_theme'] = $bo_theme[0]; - if (!in_array($bo_theme[0], scandir(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes'))) - { - $this->errors[] = Tools::displayError('Invalid theme'); - return false; - } - if (isset($bo_theme[1])) - $_POST['bo_css'] = $bo_theme[1]; - } + if (Tools::getValue('bo_theme_css')) { + $bo_theme = explode('|', Tools::getValue('bo_theme_css')); + $_POST['bo_theme'] = $bo_theme[0]; + if (!in_array($bo_theme[0], scandir(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes'))) { + $this->errors[] = Tools::displayError('Invalid theme'); + return false; + } + if (isset($bo_theme[1])) { + $_POST['bo_css'] = $bo_theme[1]; + } + } - $assos = $this->getSelectedAssoShop($this->table); - if (!$assos && $this->table = 'employee') - if (Shop::isFeatureActive() && _PS_ADMIN_PROFILE_ != $_POST['id_profile']) - $this->errors[] = Tools::displayError('The employee must be associated with at least one shop.'); + $assos = $this->getSelectedAssoShop($this->table); + if (!$assos && $this->table = 'employee') { + if (Shop::isFeatureActive() && _PS_ADMIN_PROFILE_ != $_POST['id_profile']) { + $this->errors[] = Tools::displayError('The employee must be associated with at least one shop.'); + } + } - if (count($this->errors)) - return false; + if (count($this->errors)) { + return false; + } - return parent::processSave(); - } + return parent::processSave(); + } - public function validateRules($class_name = false) - { - $employee = new Employee((int)Tools::getValue('id_employee')); + public function validateRules($class_name = false) + { + $employee = new Employee((int)Tools::getValue('id_employee')); - if (!Validate::isLoadedObject($employee) && !Validate::isPasswd(Tools::getvalue('passwd'), Validate::ADMIN_PASSWORD_LENGTH)) - return !($this->errors[] = sprintf(Tools::displayError('The password must be at least %s characters long.'), - Validate::ADMIN_PASSWORD_LENGTH)); + if (!Validate::isLoadedObject($employee) && !Validate::isPasswd(Tools::getvalue('passwd'), Validate::ADMIN_PASSWORD_LENGTH)) { + return !($this->errors[] = sprintf(Tools::displayError('The password must be at least %s characters long.'), + Validate::ADMIN_PASSWORD_LENGTH)); + } - return parent::validateRules($class_name); - } + return parent::validateRules($class_name); + } - public function postProcess() - { - /* PrestaShop demo mode */ - if ((Tools::isSubmit('submitBulkdeleteemployee') || Tools::isSubmit('submitBulkdisableSelectionemployee') || Tools::isSubmit('deleteemployee') || Tools::isSubmit('status') || Tools::isSubmit('statusemployee') || Tools::isSubmit('submitAddemployee')) && _PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } + public function postProcess() + { + /* PrestaShop demo mode */ + if ((Tools::isSubmit('submitBulkdeleteemployee') || Tools::isSubmit('submitBulkdisableSelectionemployee') || Tools::isSubmit('deleteemployee') || Tools::isSubmit('status') || Tools::isSubmit('statusemployee') || Tools::isSubmit('submitAddemployee')) && _PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } - return parent::postProcess(); - } + return parent::postProcess(); + } - public function initContent() - { - if ($this->context->employee->id == Tools::getValue('id_employee')) - $this->display = 'edit'; + public function initContent() + { + if ($this->context->employee->id == Tools::getValue('id_employee')) { + $this->display = 'edit'; + } - return parent::initContent(); - } + return parent::initContent(); + } - /** - * @param Employee $object - * - * @return bool - */ - protected function afterUpdate($object) - { - $res = parent::afterUpdate($object); - // Update cookie if needed - if (Tools::getValue('id_employee') == $this->context->employee->id && ($passwd = Tools::getValue('passwd')) - && $object->passwd != $this->context->employee->passwd) - { - $this->context->cookie->passwd = $this->context->employee->passwd = $object->passwd; - if (Tools::getValue('passwd_send_email')) - { - $params = array( - '{email}' => $object->email, - '{lastname}' => $object->lastname, - '{firstname}' => $object->firstname, - '{passwd}' => $passwd - ); - Mail::Send($object->id_lang, 'password', Mail::l('Your new password', $object->id_lang), $params, $object->email, $object->firstname.' '.$object->lastname); - } - } + /** + * @param Employee $object + * + * @return bool + */ + protected function afterUpdate($object) + { + $res = parent::afterUpdate($object); + // Update cookie if needed + if (Tools::getValue('id_employee') == $this->context->employee->id && ($passwd = Tools::getValue('passwd')) + && $object->passwd != $this->context->employee->passwd) { + $this->context->cookie->passwd = $this->context->employee->passwd = $object->passwd; + if (Tools::getValue('passwd_send_email')) { + $params = array( + '{email}' => $object->email, + '{lastname}' => $object->lastname, + '{firstname}' => $object->firstname, + '{passwd}' => $passwd + ); + Mail::Send($object->id_lang, 'password', Mail::l('Your new password', $object->id_lang), $params, $object->email, $object->firstname.' '.$object->lastname); + } + } - return $res; - } + return $res; + } - protected function ajaxProcessFormLanguage() - { - $this->context->cookie->employee_form_lang = (int)Tools::getValue('form_language_id'); - if (!$this->context->cookie->write()) - die ('Error while updating cookie.'); - die ('Form language updated.'); - } + protected function ajaxProcessFormLanguage() + { + $this->context->cookie->employee_form_lang = (int)Tools::getValue('form_language_id'); + if (!$this->context->cookie->write()) { + die('Error while updating cookie.'); + } + die('Form language updated.'); + } - protected function ajaxProcessToggleMenu() - { - $this->context->cookie->collapse_menu = (int)Tools::getValue('collapse'); - $this->context->cookie->write(); - } - public function ajaxProcessGetTabByIdProfile() - { - $id_profile = Tools::getValue('id_profile'); - $tabs = Tab::getTabByIdProfile(0, $id_profile); - $this->tabs_list = array(); - foreach ($tabs as $tab) - { - if (Tab::checkTabRights($tab['id_tab'])) - { - $this->tabs_list[$tab['id_tab']] = $tab; - foreach (Tab::getTabByIdProfile($tab['id_tab'], $id_profile) as $children) - if (Tab::checkTabRights($children['id_tab'])) - $this->tabs_list[$tab['id_tab']]['children'][] = $children; - } - } - die(Tools::jsonEncode($this->tabs_list)); - } + protected function ajaxProcessToggleMenu() + { + $this->context->cookie->collapse_menu = (int)Tools::getValue('collapse'); + $this->context->cookie->write(); + } + public function ajaxProcessGetTabByIdProfile() + { + $id_profile = Tools::getValue('id_profile'); + $tabs = Tab::getTabByIdProfile(0, $id_profile); + $this->tabs_list = array(); + foreach ($tabs as $tab) { + if (Tab::checkTabRights($tab['id_tab'])) { + $this->tabs_list[$tab['id_tab']] = $tab; + foreach (Tab::getTabByIdProfile($tab['id_tab'], $id_profile) as $children) { + if (Tab::checkTabRights($children['id_tab'])) { + $this->tabs_list[$tab['id_tab']]['children'][] = $children; + } + } + } + } + die(Tools::jsonEncode($this->tabs_list)); + } } diff --git a/controllers/admin/AdminFeaturesController.php b/controllers/admin/AdminFeaturesController.php index ef69eb8a..cca06973 100644 --- a/controllers/admin/AdminFeaturesController.php +++ b/controllers/admin/AdminFeaturesController.php @@ -29,607 +29,603 @@ */ class AdminFeaturesControllerCore extends AdminController { - public $bootstrap = true; - protected $position_identifier = 'id_feature'; - protected $feature_name; + public $bootstrap = true; + protected $position_identifier = 'id_feature'; + protected $feature_name; - public function __construct() - { - $this->table = 'feature'; - $this->className = 'Feature'; - $this->list_id = 'feature'; - $this->identifier = 'id_feature'; - $this->lang = true; + public function __construct() + { + $this->table = 'feature'; + $this->className = 'Feature'; + $this->list_id = 'feature'; + $this->identifier = 'id_feature'; + $this->lang = true; - $this->fields_list = array( - 'id_feature' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Name'), - 'width' => 'auto', - 'filter_key' => 'b!name' - ), - 'value' => array( - 'title' => $this->l('Values'), - 'orderby' => false, - 'search' => false, - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'position' => array( - 'title' => $this->l('Position'), - 'filter_key' => 'a!position', - 'align' => 'center', - 'class' => 'fixed-width-xs', - 'position' => 'position' - ) - ); + $this->fields_list = array( + 'id_feature' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Name'), + 'width' => 'auto', + 'filter_key' => 'b!name' + ), + 'value' => array( + 'title' => $this->l('Values'), + 'orderby' => false, + 'search' => false, + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'position' => array( + 'title' => $this->l('Position'), + 'filter_key' => 'a!position', + 'align' => 'center', + 'class' => 'fixed-width-xs', + 'position' => 'position' + ) + ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'icon' => 'icon-trash', - 'confirm' => $this->l('Delete selected items?') - ) - ); - parent::__construct(); - } + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'icon' => 'icon-trash', + 'confirm' => $this->l('Delete selected items?') + ) + ); + parent::__construct(); + } - /** - * AdminController::renderList() override - * @see AdminController::renderList() - */ - public function renderList() - { - $this->addRowAction('view'); - $this->addRowAction('edit'); - $this->addRowAction('delete'); + /** + * AdminController::renderList() override + * @see AdminController::renderList() + */ + public function renderList() + { + $this->addRowAction('view'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - return parent::renderList(); - } + return parent::renderList(); + } - /** - * Change object type to feature value (use when processing a feature value) - */ - protected function setTypeValue() - { - $this->table = 'feature_value'; - $this->className = 'FeatureValue'; - $this->identifier = 'id_feature_value'; - } + /** + * Change object type to feature value (use when processing a feature value) + */ + protected function setTypeValue() + { + $this->table = 'feature_value'; + $this->className = 'FeatureValue'; + $this->identifier = 'id_feature_value'; + } - /** - * Change object type to feature (use when processing a feature) - */ - protected function setTypeFeature() - { - $this->table = 'feature'; - $this->className = 'Feature'; - $this->identifier = 'id_feature'; - } + /** + * Change object type to feature (use when processing a feature) + */ + protected function setTypeFeature() + { + $this->table = 'feature'; + $this->className = 'Feature'; + $this->identifier = 'id_feature'; + } - public function renderView() - { - if (($id = Tools::getValue('id_feature'))) - { - $this->setTypeValue(); - $this->list_id = 'feature_value'; - $this->lang = true; + public function renderView() + { + if (($id = Tools::getValue('id_feature'))) { + $this->setTypeValue(); + $this->list_id = 'feature_value'; + $this->lang = true; - // Action for list - $this->addRowAction('edit'); - $this->addRowAction('delete'); + // Action for list + $this->addRowAction('edit'); + $this->addRowAction('delete'); - if (!Validate::isLoadedObject($obj = new Feature((int)$id))) - { - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - return; - } + if (!Validate::isLoadedObject($obj = new Feature((int)$id))) { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + return; + } - $this->feature_name = $obj->name; - $this->toolbar_title = $this->feature_name[$this->context->employee->id_lang]; - $this->fields_list = array( - 'id_feature_value' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'value' => array( - 'title' => $this->l('Value') - ) - ); + $this->feature_name = $obj->name; + $this->toolbar_title = $this->feature_name[$this->context->employee->id_lang]; + $this->fields_list = array( + 'id_feature_value' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'value' => array( + 'title' => $this->l('Value') + ) + ); - $this->_where = sprintf('AND `id_feature` = %d', (int)$id); - self::$currentIndex = self::$currentIndex.'&id_feature='.(int)$id.'&viewfeature'; - $this->processFilter(); - return parent::renderList(); - } - } + $this->_where = sprintf('AND `id_feature` = %d', (int)$id); + self::$currentIndex = self::$currentIndex.'&id_feature='.(int)$id.'&viewfeature'; + $this->processFilter(); + return parent::renderList(); + } + } - /** - * AdminController::renderForm() override - * @see AdminController::renderForm() - */ - public function renderForm() - { - $this->toolbar_title = $this->l('Add a new feature'); - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Feature'), - 'icon' => 'icon-info-sign' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'lang' => true, - 'size' => 33, - 'hint' => $this->l('Invalid characters:').' <>;=#{}', - 'required' => true - ) - ) - ); + /** + * AdminController::renderForm() override + * @see AdminController::renderForm() + */ + public function renderForm() + { + $this->toolbar_title = $this->l('Add a new feature'); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Feature'), + 'icon' => 'icon-info-sign' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'lang' => true, + 'size' => 33, + 'hint' => $this->l('Invalid characters:').' <>;=#{}', + 'required' => true + ) + ) + ); - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - $this->fields_form['submit'] = array( - 'title' => $this->l('Save'), - ); + $this->fields_form['submit'] = array( + 'title' => $this->l('Save'), + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - { - $this->page_header_toolbar_btn['new_feature'] = array( - 'href' => self::$currentIndex.'&addfeature&token='.$this->token, - 'desc' => $this->l('Add new feature', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_feature'] = array( + 'href' => self::$currentIndex.'&addfeature&token='.$this->token, + 'desc' => $this->l('Add new feature', null, null, false), + 'icon' => 'process-icon-new' + ); - $this->page_header_toolbar_btn['new_feature_value'] = array( - 'href' => self::$currentIndex.'&addfeature_value&id_feature='.(int)Tools::getValue('id_feature').'&token='.$this->token, - 'desc' => $this->l('Add new feature value', null, null, false), - 'icon' => 'process-icon-new' - ); - } + $this->page_header_toolbar_btn['new_feature_value'] = array( + 'href' => self::$currentIndex.'&addfeature_value&id_feature='.(int)Tools::getValue('id_feature').'&token='.$this->token, + 'desc' => $this->l('Add new feature value', null, null, false), + 'icon' => 'process-icon-new' + ); + } - if ($this->display == 'view') - $this->page_header_toolbar_btn['new_feature_value'] = array( - 'href' => self::$currentIndex.'&addfeature_value&id_feature='.(int)Tools::getValue('id_feature').'&token='.$this->token, - 'desc' => $this->l('Add new feature value', null, null, false), - 'icon' => 'process-icon-new' - ); + if ($this->display == 'view') { + $this->page_header_toolbar_btn['new_feature_value'] = array( + 'href' => self::$currentIndex.'&addfeature_value&id_feature='.(int)Tools::getValue('id_feature').'&token='.$this->token, + 'desc' => $this->l('Add new feature value', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - /** - * AdminController::initToolbar() override - * @see AdminController::initToolbar() - */ - public function initToolbar() - { - switch ($this->display) - { - case 'editFeatureValue': - case 'add': - case 'edit': - $this->toolbar_btn['save'] = array( - 'href' => '#', - 'desc' => $this->l('Save') - ); + /** + * AdminController::initToolbar() override + * @see AdminController::initToolbar() + */ + public function initToolbar() + { + switch ($this->display) { + case 'editFeatureValue': + case 'add': + case 'edit': + $this->toolbar_btn['save'] = array( + 'href' => '#', + 'desc' => $this->l('Save') + ); - if ($this->display == 'editFeatureValue') - $this->toolbar_btn['save-and-stay'] = array( - 'short' => 'SaveAndStay', - 'href' => '#', - 'desc' => $this->l('Save and add another value'), - 'force_desc' => true, - ); + if ($this->display == 'editFeatureValue') { + $this->toolbar_btn['save-and-stay'] = array( + 'short' => 'SaveAndStay', + 'href' => '#', + 'desc' => $this->l('Save and add another value'), + 'force_desc' => true, + ); + } - // Default cancel button - like old back link - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; + // Default cancel button - like old back link + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } - $this->toolbar_btn['back'] = array( - 'href' => $back, - 'desc' => $this->l('Back to the list') - ); - break; - case 'view': - $this->toolbar_btn['newAttributes'] = array( - 'href' => self::$currentIndex.'&addfeature_value&id_feature='.(int)Tools::getValue('id_feature').'&token='.$this->token, - 'desc' => $this->l('Add new feature values') - ); - $this->toolbar_btn['back'] = array( - 'href' => self::$currentIndex.'&token='.$this->token, - 'desc' => $this->l('Back to the list') - ); - break; - default: - parent::initToolbar(); - } - } + $this->toolbar_btn['back'] = array( + 'href' => $back, + 'desc' => $this->l('Back to the list') + ); + break; + case 'view': + $this->toolbar_btn['newAttributes'] = array( + 'href' => self::$currentIndex.'&addfeature_value&id_feature='.(int)Tools::getValue('id_feature').'&token='.$this->token, + 'desc' => $this->l('Add new feature values') + ); + $this->toolbar_btn['back'] = array( + 'href' => self::$currentIndex.'&token='.$this->token, + 'desc' => $this->l('Back to the list') + ); + break; + default: + parent::initToolbar(); + } + } - public function initToolbarTitle() - { - $bread_extended = $this->breadcrumbs; + public function initToolbarTitle() + { + $bread_extended = $this->breadcrumbs; - switch ($this->display) - { - case 'edit': - $bread_extended[] = $this->l('Edit New Feature'); - $this->addMetaTitle($bread_extended[count($bread_extended) - 1]); - break; + switch ($this->display) { + case 'edit': + $bread_extended[] = $this->l('Edit New Feature'); + $this->addMetaTitle($bread_extended[count($bread_extended) - 1]); + break; - case 'add': - $bread_extended[] = $this->l('Add New Feature'); - $this->addMetaTitle($bread_extended[count($bread_extended) - 1]); - break; + case 'add': + $bread_extended[] = $this->l('Add New Feature'); + $this->addMetaTitle($bread_extended[count($bread_extended) - 1]); + break; - case 'view': - $bread_extended[] = $this->feature_name[$this->context->employee->id_lang]; - $this->addMetaTitle($bread_extended[count($bread_extended) - 1]); - break; + case 'view': + $bread_extended[] = $this->feature_name[$this->context->employee->id_lang]; + $this->addMetaTitle($bread_extended[count($bread_extended) - 1]); + break; - case 'editFeatureValue': - if (($id_feature_value = Tools::getValue('id_feature_value'))) - { - if (($id = Tools::getValue('id_feature'))) - { - if (Validate::isLoadedObject($obj = new Feature((int)$id))) - $bread_extended[] = '<a href="'.Context::getContext()->link->getAdminLink('AdminFeatures').'&id_feature='.$id.'&viewfeature">'.$obj->name[$this->context->employee->id_lang].'</a>'; + case 'editFeatureValue': + if (($id_feature_value = Tools::getValue('id_feature_value'))) { + if (($id = Tools::getValue('id_feature'))) { + if (Validate::isLoadedObject($obj = new Feature((int)$id))) { + $bread_extended[] = '<a href="'.Context::getContext()->link->getAdminLink('AdminFeatures').'&id_feature='.$id.'&viewfeature">'.$obj->name[$this->context->employee->id_lang].'</a>'; + } - if (Validate::isLoadedObject($obj = new FeatureValue((int)Tools::getValue('id_feature_value')))) - $bread_extended[] = sprintf($this->l('Edit: %s'), $obj->value[$this->context->employee->id_lang]); - } - else - $bread_extended[] = $this->l('Edit Value'); - } - else - $bread_extended[] = $this->l('Add New Value'); + if (Validate::isLoadedObject($obj = new FeatureValue((int)Tools::getValue('id_feature_value')))) { + $bread_extended[] = sprintf($this->l('Edit: %s'), $obj->value[$this->context->employee->id_lang]); + } + } else { + $bread_extended[] = $this->l('Edit Value'); + } + } else { + $bread_extended[] = $this->l('Add New Value'); + } - if (count($bread_extended) > 0) - $this->addMetaTitle($bread_extended[count($bread_extended) - 1]); - break; - } + if (count($bread_extended) > 0) { + $this->addMetaTitle($bread_extended[count($bread_extended) - 1]); + } + break; + } - $this->toolbar_title = $bread_extended; - } + $this->toolbar_title = $bread_extended; + } - /** - * AdminController::renderForm() override - * @see AdminController::renderForm() - */ - public function initFormFeatureValue() - { - $this->setTypeValue(); + /** + * AdminController::renderForm() override + * @see AdminController::renderForm() + */ + public function initFormFeatureValue() + { + $this->setTypeValue(); - $this->fields_form[0]['form'] = array( - 'legend' => array( - 'title' => $this->l('Feature value'), - 'icon' => 'icon-info-sign' - ), - 'input' => array( - array( - 'type' => 'select', - 'label' => $this->l('Feature'), - 'name' => 'id_feature', - 'options' => array( - 'query' => Feature::getFeatures($this->context->language->id), - 'id' => 'id_feature', - 'name' => 'name' - ), - 'required' => true - ), - array( - 'type' => 'text', - 'label' => $this->l('Value'), - 'name' => 'value', - 'lang' => true, - 'size' => 33, - 'hint' => $this->l('Invalid characters:').' <>;=#{}', - 'required' => true - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ), - 'buttons' => array( - 'save-and-stay' => array( - 'title' => $this->l('Save then add another value'), - 'name' => 'submitAdd'.$this->table.'AndStay', - 'type' => 'submit', - 'class' => 'btn btn-default pull-right', - 'icon' => 'process-icon-save' - ) - ) - ); + $this->fields_form[0]['form'] = array( + 'legend' => array( + 'title' => $this->l('Feature value'), + 'icon' => 'icon-info-sign' + ), + 'input' => array( + array( + 'type' => 'select', + 'label' => $this->l('Feature'), + 'name' => 'id_feature', + 'options' => array( + 'query' => Feature::getFeatures($this->context->language->id), + 'id' => 'id_feature', + 'name' => 'name' + ), + 'required' => true + ), + array( + 'type' => 'text', + 'label' => $this->l('Value'), + 'name' => 'value', + 'lang' => true, + 'size' => 33, + 'hint' => $this->l('Invalid characters:').' <>;=#{}', + 'required' => true + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ), + 'buttons' => array( + 'save-and-stay' => array( + 'title' => $this->l('Save then add another value'), + 'name' => 'submitAdd'.$this->table.'AndStay', + 'type' => 'submit', + 'class' => 'btn btn-default pull-right', + 'icon' => 'process-icon-save' + ) + ) + ); - $this->fields_value['id_feature'] = (int)Tools::getValue('id_feature'); + $this->fields_value['id_feature'] = (int)Tools::getValue('id_feature'); - // Create Object FeatureValue - $feature_value = new FeatureValue(Tools::getValue('id_feature_value')); + // Create Object FeatureValue + $feature_value = new FeatureValue(Tools::getValue('id_feature_value')); - $this->tpl_vars = array( - 'feature_value' => $feature_value, - ); + $this->tpl_vars = array( + 'feature_value' => $feature_value, + ); - $this->getlanguages(); - $helper = new HelperForm(); - $helper->show_cancel_button = true; + $this->getlanguages(); + $helper = new HelperForm(); + $helper->show_cancel_button = true; - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; - if (!Validate::isCleanHtml($back)) - die(Tools::displayError()); + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } + if (!Validate::isCleanHtml($back)) { + die(Tools::displayError()); + } - $helper->back_url = $back; - $helper->currentIndex = self::$currentIndex; - $helper->token = $this->token; - $helper->table = $this->table; - $helper->identifier = $this->identifier; - $helper->override_folder = 'feature_value/'; - $helper->id = $feature_value->id; - $helper->toolbar_scroll = false; - $helper->tpl_vars = $this->tpl_vars; - $helper->languages = $this->_languages; - $helper->default_form_language = $this->default_form_language; - $helper->allow_employee_form_lang = $this->allow_employee_form_lang; - $helper->fields_value = $this->getFieldsValue($feature_value); - $helper->toolbar_btn = $this->toolbar_btn; - $helper->title = $this->l('Add a new feature value'); - $this->content .= $helper->generateForm($this->fields_form); - } + $helper->back_url = $back; + $helper->currentIndex = self::$currentIndex; + $helper->token = $this->token; + $helper->table = $this->table; + $helper->identifier = $this->identifier; + $helper->override_folder = 'feature_value/'; + $helper->id = $feature_value->id; + $helper->toolbar_scroll = false; + $helper->tpl_vars = $this->tpl_vars; + $helper->languages = $this->_languages; + $helper->default_form_language = $this->default_form_language; + $helper->allow_employee_form_lang = $this->allow_employee_form_lang; + $helper->fields_value = $this->getFieldsValue($feature_value); + $helper->toolbar_btn = $this->toolbar_btn; + $helper->title = $this->l('Add a new feature value'); + $this->content .= $helper->generateForm($this->fields_form); + } - /** - * AdminController::initContent() override - * @see AdminController::initContent() - */ - public function initContent() - { - if (Feature::isFeatureActive()) - { - // toolbar (save, cancel, new, ..) - $this->initTabModuleList(); - $this->initToolbar(); - $this->initPageHeaderToolbar(); - if ($this->display == 'edit' || $this->display == 'add') - { - if (!$this->loadObject(true)) - return; - $this->content .= $this->renderForm(); - } - elseif ($this->display == 'view') - { - // Some controllers use the view action without an object - if ($this->className) - $this->loadObject(true); - $this->content .= $this->renderView(); - } - elseif ($this->display == 'editFeatureValue') - { - if (!$this->object = new FeatureValue((int)Tools::getValue('id_feature_value'))) - return; + /** + * AdminController::initContent() override + * @see AdminController::initContent() + */ + public function initContent() + { + if (Feature::isFeatureActive()) { + // toolbar (save, cancel, new, ..) + $this->initTabModuleList(); + $this->initToolbar(); + $this->initPageHeaderToolbar(); + if ($this->display == 'edit' || $this->display == 'add') { + if (!$this->loadObject(true)) { + return; + } + $this->content .= $this->renderForm(); + } elseif ($this->display == 'view') { + // Some controllers use the view action without an object + if ($this->className) { + $this->loadObject(true); + } + $this->content .= $this->renderView(); + } elseif ($this->display == 'editFeatureValue') { + if (!$this->object = new FeatureValue((int)Tools::getValue('id_feature_value'))) { + return; + } - $this->content .= $this->initFormFeatureValue(); - } - elseif (!$this->ajax) - { - // If a feature value was saved, we need to reset the values to display the list - $this->setTypeFeature(); - $this->content .= $this->renderList(); - } - } - else - { - $url = '<a href="index.php?tab=AdminPerformance&token='.Tools::getAdminTokenLite('AdminPerformance').'#featuresDetachables">'.$this->l('Performance').'</a>'; - $this->displayWarning(sprintf($this->l('This feature has been disabled. You can activate it here: %s.'), $url)); - } + $this->content .= $this->initFormFeatureValue(); + } elseif (!$this->ajax) { + // If a feature value was saved, we need to reset the values to display the list + $this->setTypeFeature(); + $this->content .= $this->renderList(); + } + } else { + $url = '<a href="index.php?tab=AdminPerformance&token='.Tools::getAdminTokenLite('AdminPerformance').'#featuresDetachables">'.$this->l('Performance').'</a>'; + $this->displayWarning(sprintf($this->l('This feature has been disabled. You can activate it here: %s.'), $url)); + } - $this->context->smarty->assign(array( - 'content' => $this->content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } + $this->context->smarty->assign(array( + 'content' => $this->content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } - public function initProcess() - { - // Are we working on feature values? - if (Tools::getValue('id_feature_value') - || Tools::isSubmit('deletefeature_value') - || Tools::isSubmit('submitAddfeature_value') - || Tools::isSubmit('addfeature_value') - || Tools::isSubmit('updatefeature_value') - || Tools::isSubmit('submitBulkdeletefeature_value')) - $this->setTypeValue(); + public function initProcess() + { + // Are we working on feature values? + if (Tools::getValue('id_feature_value') + || Tools::isSubmit('deletefeature_value') + || Tools::isSubmit('submitAddfeature_value') + || Tools::isSubmit('addfeature_value') + || Tools::isSubmit('updatefeature_value') + || Tools::isSubmit('submitBulkdeletefeature_value')) { + $this->setTypeValue(); + } - if (Tools::getIsset('viewfeature')) - { - $this->list_id = 'feature_value'; + if (Tools::getIsset('viewfeature')) { + $this->list_id = 'feature_value'; - if (isset($_POST['submitReset'.$this->list_id])) - $this->processResetFilters(); - } - else - { - $this->list_id = 'feature'; - $this->_defaultOrderBy = 'position'; - $this->_defaultOrderWay = 'ASC'; - } + if (isset($_POST['submitReset'.$this->list_id])) { + $this->processResetFilters(); + } + } else { + $this->list_id = 'feature'; + $this->_defaultOrderBy = 'position'; + $this->_defaultOrderWay = 'ASC'; + } - parent::initProcess(); + parent::initProcess(); + } - } + public function postProcess() + { + if (!Feature::isFeatureActive()) { + return; + } - public function postProcess() - { - if (!Feature::isFeatureActive()) - return; + if ($this->table == 'feature_value' && ($this->action == 'save' || $this->action == 'delete' || $this->action == 'bulkDelete')) { + Hook::exec('displayFeatureValuePostProcess', + array('errors' => &$this->errors)); + } // send errors as reference to allow displayFeatureValuePostProcess to stop saving process + else { + Hook::exec('displayFeaturePostProcess', + array('errors' => &$this->errors)); + } // send errors as reference to allow displayFeaturePostProcess to stop saving process - if ($this->table == 'feature_value' && ($this->action == 'save' || $this->action == 'delete' || $this->action == 'bulkDelete')) - Hook::exec('displayFeatureValuePostProcess', - array('errors' => &$this->errors)); // send errors as reference to allow displayFeatureValuePostProcess to stop saving process - else - Hook::exec('displayFeaturePostProcess', - array('errors' => &$this->errors)); // send errors as reference to allow displayFeaturePostProcess to stop saving process + parent::postProcess(); - parent::postProcess(); + if ($this->table == 'feature_value' && ($this->display == 'edit' || $this->display == 'add')) { + $this->display = 'editFeatureValue'; + } + } - if ($this->table == 'feature_value' && ($this->display == 'edit' || $this->display == 'add')) - $this->display = 'editFeatureValue'; - } + /** + * Override processAdd to change SaveAndStay button action + * @see classes/AdminControllerCore::processAdd() + */ + public function processAdd() + { + $object = parent::processAdd(); - /** - * Override processAdd to change SaveAndStay button action - * @see classes/AdminControllerCore::processAdd() - */ - public function processAdd() - { - $object = parent::processAdd(); + if (Tools::isSubmit('submitAdd'.$this->table.'AndStay') && !count($this->errors)) { + if ($this->table == 'feature_value' && ($this->display == 'edit' || $this->display == 'add')) { + $this->redirect_after = self::$currentIndex.'&addfeature_value&id_feature='.(int)Tools::getValue('id_feature').'&token='.$this->token; + } else { + $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'=&conf=3&update'.$this->table.'&token='.$this->token; + } + } elseif (Tools::isSubmit('submitAdd'.$this->table.'AndStay') && count($this->errors)) { + $this->display = 'editFeatureValue'; + } - if (Tools::isSubmit('submitAdd'.$this->table.'AndStay') && !count($this->errors)) - { - if( $this->table == 'feature_value' && ($this->display == 'edit' || $this->display == 'add') ) - $this->redirect_after = self::$currentIndex.'&addfeature_value&id_feature='.(int)Tools::getValue('id_feature').'&token='.$this->token; - else - $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'=&conf=3&update'.$this->table.'&token='.$this->token; - } - elseif (Tools::isSubmit('submitAdd'.$this->table.'AndStay') && count($this->errors)) - $this->display = 'editFeatureValue'; + return $object; + } - return $object; - } + /** + * Override processUpdate to change SaveAndStay button action + * @see classes/AdminControllerCore::processUpdate() + */ + public function processUpdate() + { + $object = parent::processUpdate(); - /** - * Override processUpdate to change SaveAndStay button action - * @see classes/AdminControllerCore::processUpdate() - */ - public function processUpdate() - { - $object = parent::processUpdate(); + if (Tools::isSubmit('submitAdd'.$this->table.'AndStay') && !count($this->errors)) { + $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'=&conf=3&update'.$this->table.'&token='.$this->token; + } - if (Tools::isSubmit('submitAdd'.$this->table.'AndStay') && !count($this->errors)) - $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'=&conf=3&update'.$this->table.'&token='.$this->token; + return $object; + } - return $object; - } - - /** - * Call the right method for creating or updating object - * - * @return mixed - */ - public function processSave() - { - if ($this->table == 'feature') - { - $id_feature = (int)Tools::getValue('id_feature'); - // Adding last position to the feature if not exist - if ($id_feature <= 0) - { - $sql = 'SELECT `position`+1 + /** + * Call the right method for creating or updating object + * + * @return mixed + */ + public function processSave() + { + if ($this->table == 'feature') { + $id_feature = (int)Tools::getValue('id_feature'); + // Adding last position to the feature if not exist + if ($id_feature <= 0) { + $sql = 'SELECT `position`+1 FROM `'._DB_PREFIX_.'feature` ORDER BY position DESC'; - // set the position of the new feature in $_POST for postProcess() method - $_POST['position'] = DB::getInstance()->getValue($sql); - } - // clean \n\r characters - foreach ($_POST as $key => $value) - if (preg_match('/^name_/Ui', $key)) - $_POST[$key] = str_replace ('\n', '', str_replace('\r', '', $value)); - } - return parent::processSave(); - } + // set the position of the new feature in $_POST for postProcess() method + $_POST['position'] = DB::getInstance()->getValue($sql); + } + // clean \n\r characters + foreach ($_POST as $key => $value) { + if (preg_match('/^name_/Ui', $key)) { + $_POST[$key] = str_replace('\n', '', str_replace('\r', '', $value)); + } + } + } + return parent::processSave(); + } - /** - * AdminController::getList() override - * @see AdminController::getList() - * - * @param int $id_lang - * @param string|null $order_by - * @param string|null $order_way - * @param int $start - * @param int|null $limit - * @param int|bool $id_lang_shop - * - * @throws PrestaShopException - */ - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - if ($this->table == 'feature_value') - $this->_where .= ' AND (a.custom = 0 OR a.custom IS NULL)'; + /** + * AdminController::getList() override + * @see AdminController::getList() + * + * @param int $id_lang + * @param string|null $order_by + * @param string|null $order_way + * @param int $start + * @param int|null $limit + * @param int|bool $id_lang_shop + * + * @throws PrestaShopException + */ + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + if ($this->table == 'feature_value') { + $this->_where .= ' AND (a.custom = 0 OR a.custom IS NULL)'; + } - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - if ($this->table == 'feature') - { - $nb_items = count($this->_list); - for ($i = 0; $i < $nb_items; ++$i) - { - $item = &$this->_list[$i]; + if ($this->table == 'feature') { + $nb_items = count($this->_list); + for ($i = 0; $i < $nb_items; ++$i) { + $item = &$this->_list[$i]; - $query = new DbQuery(); - $query->select('COUNT(fv.id_feature_value) as count_values'); - $query->from('feature_value', 'fv'); - $query->where('fv.id_feature ='.(int)$item['id_feature']); - $query->where('(fv.custom=0 OR fv.custom IS NULL)'); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - $item['value'] = (int)$res; - unset($query); - } - } - } + $query = new DbQuery(); + $query->select('COUNT(fv.id_feature_value) as count_values'); + $query->from('feature_value', 'fv'); + $query->where('fv.id_feature ='.(int)$item['id_feature']); + $query->where('(fv.custom=0 OR fv.custom IS NULL)'); + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + $item['value'] = (int)$res; + unset($query); + } + } + } - public function ajaxProcessUpdatePositions() - { - if ($this->tabAccess['edit'] === '1') - { - $way = (int)Tools::getValue('way'); - $id_feature = (int)Tools::getValue('id'); - $positions = Tools::getValue('feature'); + public function ajaxProcessUpdatePositions() + { + if ($this->tabAccess['edit'] === '1') { + $way = (int)Tools::getValue('way'); + $id_feature = (int)Tools::getValue('id'); + $positions = Tools::getValue('feature'); - $new_positions = array(); - foreach ($positions as $k => $v) - if (!empty($v)) - $new_positions[] = $v; + $new_positions = array(); + foreach ($positions as $k => $v) { + if (!empty($v)) { + $new_positions[] = $v; + } + } - foreach ($new_positions as $position => $value) - { - $pos = explode('_', $value); + foreach ($new_positions as $position => $value) { + $pos = explode('_', $value); - if (isset($pos[2]) && (int)$pos[2] === $id_feature) - { - if ($feature = new Feature((int)$pos[2])) - if (isset($position) && $feature->updatePosition($way, $position, $id_feature)) - echo 'ok position '.(int)$position.' for feature '.(int)$pos[1].'\r\n'; - else - echo '{"hasError" : true, "errors" : "Can not update feature '.(int)$id_feature.' to position '.(int)$position.' "}'; - else - echo '{"hasError" : true, "errors" : "This feature ('.(int)$id_feature.') can t be loaded"}'; + if (isset($pos[2]) && (int)$pos[2] === $id_feature) { + if ($feature = new Feature((int)$pos[2])) { + if (isset($position) && $feature->updatePosition($way, $position, $id_feature)) { + echo 'ok position '.(int)$position.' for feature '.(int)$pos[1].'\r\n'; + } else { + echo '{"hasError" : true, "errors" : "Can not update feature '.(int)$id_feature.' to position '.(int)$position.' "}'; + } + } else { + echo '{"hasError" : true, "errors" : "This feature ('.(int)$id_feature.') can t be loaded"}'; + } - break; - } - } - } - } + break; + } + } + } + } } diff --git a/controllers/admin/AdminGendersController.php b/controllers/admin/AdminGendersController.php index 21e9b6b4..99b6a47a 100644 --- a/controllers/admin/AdminGendersController.php +++ b/controllers/admin/AdminGendersController.php @@ -29,208 +29,204 @@ */ class AdminGendersControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'gender'; - $this->className = 'Gender'; - $this->lang = true; - $this->addRowAction('edit'); - $this->addRowAction('delete'); + public function __construct() + { + $this->bootstrap = true; + $this->table = 'gender'; + $this->className = 'Gender'; + $this->lang = true; + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->context = Context::getContext(); + $this->context = Context::getContext(); - if (!Tools::getValue('realedit')) - $this->deleted = false; + if (!Tools::getValue('realedit')) { + $this->deleted = false; + } - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->default_image_height = 16; - $this->default_image_width = 16; + $this->default_image_height = 16; + $this->default_image_width = 16; - $this->fieldImageSettings = array( - 'name' => 'image', - 'dir' => 'genders' - ); + $this->fieldImageSettings = array( + 'name' => 'image', + 'dir' => 'genders' + ); - $this->fields_list = array( - 'id_gender' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Social title'), - 'filter_key' => 'b!name' - ), - 'type' => array( - 'title' => $this->l('Gender'), - 'orderby' => false, - 'type' => 'select', - 'list' => array( - 0 => $this->l('Male'), - 1 => $this->l('Female'), - 2 => $this->l('Neutral') - ), - 'filter_key' => 'a!type', - 'callback' => 'displayGenderType', - 'callback_object' => $this - ), - 'image' => array( - 'title' => $this->l('Image'), - 'align' => 'center', - 'image' => 'genders', - 'orderby' => false, - 'search' => false - ) - ); + $this->fields_list = array( + 'id_gender' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Social title'), + 'filter_key' => 'b!name' + ), + 'type' => array( + 'title' => $this->l('Gender'), + 'orderby' => false, + 'type' => 'select', + 'list' => array( + 0 => $this->l('Male'), + 1 => $this->l('Female'), + 2 => $this->l('Neutral') + ), + 'filter_key' => 'a!type', + 'callback' => 'displayGenderType', + 'callback_object' => $this + ), + 'image' => array( + 'title' => $this->l('Image'), + 'align' => 'center', + 'image' => 'genders', + 'orderby' => false, + 'search' => false + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - if(empty($this->display)) - $this->page_header_toolbar_btn['new_gender'] = array( - 'href' => self::$currentIndex.'&addgender&token='.$this->token, - 'desc' => $this->l('Add new title', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_gender'] = array( + 'href' => self::$currentIndex.'&addgender&token='.$this->token, + 'desc' => $this->l('Add new title', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Social titles'), - 'icon' => 'icon-male' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Social title'), - 'name' => 'name', - 'lang' => true, - 'col' => 4, - 'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()@#"�{}_$%:', - 'required' => true - ), - array( - 'type' => 'radio', - 'label' => $this->l('Gender'), - 'name' => 'type', - 'required' => false, - 'class' => 't', - 'values' => array( - array( - 'id' => 'type_male', - 'value' => 0, - 'label' => $this->l('Male') - ), - array( - 'id' => 'type_female', - 'value' => 1, - 'label' => $this->l('Female') - ), - array( - 'id' => 'type_neutral', - 'value' => 2, - 'label' => $this->l('Neutral') - ) - ) - ), - array( - 'type' => 'file', - 'label' => $this->l('Image'), - 'name' => 'image', - 'col' => 6, - 'value' => true - ), - array( - 'type' => 'text', - 'label' => $this->l('Image width'), - 'name' => 'img_width', - 'col' => 2, - 'hint' => $this->l('Image width in pixels. Enter "0" to use the original size.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Image height'), - 'name' => 'img_height', - 'col' => 2, - 'hint' => $this->l('Image height in pixels. Enter "0" to use the original size.') - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Social titles'), + 'icon' => 'icon-male' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Social title'), + 'name' => 'name', + 'lang' => true, + 'col' => 4, + 'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()@#"�{}_$%:', + 'required' => true + ), + array( + 'type' => 'radio', + 'label' => $this->l('Gender'), + 'name' => 'type', + 'required' => false, + 'class' => 't', + 'values' => array( + array( + 'id' => 'type_male', + 'value' => 0, + 'label' => $this->l('Male') + ), + array( + 'id' => 'type_female', + 'value' => 1, + 'label' => $this->l('Female') + ), + array( + 'id' => 'type_neutral', + 'value' => 2, + 'label' => $this->l('Neutral') + ) + ) + ), + array( + 'type' => 'file', + 'label' => $this->l('Image'), + 'name' => 'image', + 'col' => 6, + 'value' => true + ), + array( + 'type' => 'text', + 'label' => $this->l('Image width'), + 'name' => 'img_width', + 'col' => 2, + 'hint' => $this->l('Image width in pixels. Enter "0" to use the original size.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Image height'), + 'name' => 'img_height', + 'col' => 2, + 'hint' => $this->l('Image height in pixels. Enter "0" to use the original size.') + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - /** @var Gender $obj */ - if (!($obj = $this->loadObject(true))) - return; + /** @var Gender $obj */ + if (!($obj = $this->loadObject(true))) { + return; + } - $this->fields_value = array( - 'img_width' => $this->default_image_width, - 'img_height' => $this->default_image_height, - 'image' => $obj->getImage() - ); + $this->fields_value = array( + 'img_width' => $this->default_image_width, + 'img_height' => $this->default_image_height, + 'image' => $obj->getImage() + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function displayGenderType($value, $tr) - { - return $this->fields_list['type']['list'][$value]; - } + public function displayGenderType($value, $tr) + { + return $this->fields_list['type']['list'][$value]; + } - protected function postImage($id) - { - if (isset($this->fieldImageSettings['name']) && isset($this->fieldImageSettings['dir'])) - { - if (!Validate::isInt(Tools::getValue('img_width')) || !Validate::isInt(Tools::getValue('img_height'))) - $this->errors[] = Tools::displayError('Width and height must be numeric values.'); - else - { - if ((int)Tools::getValue('img_width') > 0 && (int)Tools::getValue('img_height') > 0) - { - $width = (int)Tools::getValue('img_width'); - $height = (int)Tools::getValue('img_height'); - } - else - { - $width = null; - $height = null; - } - return $this->uploadImage($id, $this->fieldImageSettings['name'], $this->fieldImageSettings['dir'].'/', false, $width, $height); - } - } - return !count($this->errors) ? true : false; - } + protected function postImage($id) + { + if (isset($this->fieldImageSettings['name']) && isset($this->fieldImageSettings['dir'])) { + if (!Validate::isInt(Tools::getValue('img_width')) || !Validate::isInt(Tools::getValue('img_height'))) { + $this->errors[] = Tools::displayError('Width and height must be numeric values.'); + } else { + if ((int)Tools::getValue('img_width') > 0 && (int)Tools::getValue('img_height') > 0) { + $width = (int)Tools::getValue('img_width'); + $height = (int)Tools::getValue('img_height'); + } else { + $width = null; + $height = null; + } + return $this->uploadImage($id, $this->fieldImageSettings['name'], $this->fieldImageSettings['dir'].'/', false, $width, $height); + } + } + return !count($this->errors) ? true : false; + } - protected function afterImageUpload() - { - parent::afterImageUpload(); + protected function afterImageUpload() + { + parent::afterImageUpload(); - if (($id_gender = (int)Tools::getValue('id_gender')) && - isset($_FILES) && count($_FILES) && file_exists(_PS_GENDERS_DIR_.$id_gender.'.jpg')) - { - $current_file = _PS_TMP_IMG_DIR_.'gender_mini_'.$id_gender.'_'.$this->context->shop->id.'.jpg'; + if (($id_gender = (int)Tools::getValue('id_gender')) && + isset($_FILES) && count($_FILES) && file_exists(_PS_GENDERS_DIR_.$id_gender.'.jpg')) { + $current_file = _PS_TMP_IMG_DIR_.'gender_mini_'.$id_gender.'_'.$this->context->shop->id.'.jpg'; - if (file_exists($current_file)) - unlink($current_file); - } + if (file_exists($current_file)) { + unlink($current_file); + } + } - return true; - } + return true; + } } - - diff --git a/controllers/admin/AdminGeolocationController.php b/controllers/admin/AdminGeolocationController.php index b91da011..a5f30f0b 100644 --- a/controllers/admin/AdminGeolocationController.php +++ b/controllers/admin/AdminGeolocationController.php @@ -26,135 +26,134 @@ class AdminGeolocationControllerCore extends AdminController { - public function __construct() - { - parent::__construct(); + public function __construct() + { + parent::__construct(); - $this->bootstrap = true; - $this->fields_options = array( - 'geolocationConfiguration' => array( - 'title' => $this->l('Geolocation by IP address'), - 'icon' => 'icon-map-marker', - 'fields' => array( - 'PS_GEOLOCATION_ENABLED' => array( - 'title' => $this->l('Geolocation by IP address'), - 'hint' => $this->l('This option allows you, among other things, to restrict access to your shop for certain countries. See below.'), - 'validation' => 'isUnsignedId', - 'cast' => 'intval', - 'type' => 'bool' - ), - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'geolocationCountries' => array( - 'title' => $this->l('Options'), - 'icon' => 'icon-map-marker', - 'description' => $this->l('The following features are only available if you enable the Geolocation by IP address feature.'), - 'fields' => array( - 'PS_GEOLOCATION_BEHAVIOR' => array( - 'title' => $this->l('Geolocation behavior for restricted countries'), - 'type' => 'select', - 'identifier' => 'key', - 'list' => array(array('key' => _PS_GEOLOCATION_NO_CATALOG_, 'name' => $this->l('Visitors cannot see your catalog.')), - array('key' => _PS_GEOLOCATION_NO_ORDER_, 'name' => $this->l('Visitors can see your catalog but cannot place an order.'))), - ), - 'PS_GEOLOCATION_NA_BEHAVIOR' => array( - 'title' => $this->l('Geolocation behavior for other countries'), - 'type' => 'select', - 'identifier' => 'key', - 'list' => array(array('key' => '-1', 'name' => $this->l('All features are available')), - array('key' => _PS_GEOLOCATION_NO_CATALOG_, 'name' => $this->l('Visitors cannot see your catalog.')), - array('key' => _PS_GEOLOCATION_NO_ORDER_, 'name' => $this->l('Visitors can see your catalog but cannot place an order.'))) - ), - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'geolocationWhitelist' => array( - 'title' => $this->l('IP address whitelist'), - 'icon' => 'icon-sitemap', - 'description' => $this->l('You can add IP addresses that will always be allowed to access your shop (e.g. Google bots\' IP).'), - 'fields' => array( - 'PS_GEOLOCATION_WHITELIST' => array('title' => $this->l('Whitelisted IP addresses'), 'type' => 'textarea_newlines', 'cols' => 15, 'rows' => 30), - ), - 'submit' => array('title' => $this->l('Save')) - ), - ); - } + $this->bootstrap = true; + $this->fields_options = array( + 'geolocationConfiguration' => array( + 'title' => $this->l('Geolocation by IP address'), + 'icon' => 'icon-map-marker', + 'fields' => array( + 'PS_GEOLOCATION_ENABLED' => array( + 'title' => $this->l('Geolocation by IP address'), + 'hint' => $this->l('This option allows you, among other things, to restrict access to your shop for certain countries. See below.'), + 'validation' => 'isUnsignedId', + 'cast' => 'intval', + 'type' => 'bool' + ), + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'geolocationCountries' => array( + 'title' => $this->l('Options'), + 'icon' => 'icon-map-marker', + 'description' => $this->l('The following features are only available if you enable the Geolocation by IP address feature.'), + 'fields' => array( + 'PS_GEOLOCATION_BEHAVIOR' => array( + 'title' => $this->l('Geolocation behavior for restricted countries'), + 'type' => 'select', + 'identifier' => 'key', + 'list' => array(array('key' => _PS_GEOLOCATION_NO_CATALOG_, 'name' => $this->l('Visitors cannot see your catalog.')), + array('key' => _PS_GEOLOCATION_NO_ORDER_, 'name' => $this->l('Visitors can see your catalog but cannot place an order.'))), + ), + 'PS_GEOLOCATION_NA_BEHAVIOR' => array( + 'title' => $this->l('Geolocation behavior for other countries'), + 'type' => 'select', + 'identifier' => 'key', + 'list' => array(array('key' => '-1', 'name' => $this->l('All features are available')), + array('key' => _PS_GEOLOCATION_NO_CATALOG_, 'name' => $this->l('Visitors cannot see your catalog.')), + array('key' => _PS_GEOLOCATION_NO_ORDER_, 'name' => $this->l('Visitors can see your catalog but cannot place an order.'))) + ), + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'geolocationWhitelist' => array( + 'title' => $this->l('IP address whitelist'), + 'icon' => 'icon-sitemap', + 'description' => $this->l('You can add IP addresses that will always be allowed to access your shop (e.g. Google bots\' IP).'), + 'fields' => array( + 'PS_GEOLOCATION_WHITELIST' => array('title' => $this->l('Whitelisted IP addresses'), 'type' => 'textarea_newlines', 'cols' => 15, 'rows' => 30), + ), + 'submit' => array('title' => $this->l('Save')) + ), + ); + } - /** - * @see AdminController::processUpdateOptions() - */ - public function processUpdateOptions() - { - if ($this->isGeoLiteCityAvailable()) - Configuration::updateValue('PS_GEOLOCATION_ENABLED', (int)Tools::getValue('PS_GEOLOCATION_ENABLED')); - // stop processing if geolocation is set to yes but geolite pack is not available - elseif (Tools::getValue('PS_GEOLOCATION_ENABLED')) - $this->errors[] = Tools::displayError('The geolocation database is unavailable.'); + /** + * @see AdminController::processUpdateOptions() + */ + public function processUpdateOptions() + { + if ($this->isGeoLiteCityAvailable()) { + Configuration::updateValue('PS_GEOLOCATION_ENABLED', (int)Tools::getValue('PS_GEOLOCATION_ENABLED')); + } + // stop processing if geolocation is set to yes but geolite pack is not available + elseif (Tools::getValue('PS_GEOLOCATION_ENABLED')) { + $this->errors[] = Tools::displayError('The geolocation database is unavailable.'); + } - if (empty($this->errors)) - { - if (!is_array(Tools::getValue('countries')) || !count(Tools::getValue('countries'))) - $this->errors[] = Tools::displayError('Country selection is invalid.'); - else - { - Configuration::updateValue( - 'PS_GEOLOCATION_BEHAVIOR', - (!(int)Tools::getValue('PS_GEOLOCATION_BEHAVIOR') ? _PS_GEOLOCATION_NO_CATALOG_ : _PS_GEOLOCATION_NO_ORDER_) - ); - Configuration::updateValue('PS_GEOLOCATION_NA_BEHAVIOR', (int)Tools::getValue('PS_GEOLOCATION_NA_BEHAVIOR')); - Configuration::updateValue('PS_ALLOWED_COUNTRIES', implode(';', Tools::getValue('countries'))); - } + if (empty($this->errors)) { + if (!is_array(Tools::getValue('countries')) || !count(Tools::getValue('countries'))) { + $this->errors[] = Tools::displayError('Country selection is invalid.'); + } else { + Configuration::updateValue( + 'PS_GEOLOCATION_BEHAVIOR', + (!(int)Tools::getValue('PS_GEOLOCATION_BEHAVIOR') ? _PS_GEOLOCATION_NO_CATALOG_ : _PS_GEOLOCATION_NO_ORDER_) + ); + Configuration::updateValue('PS_GEOLOCATION_NA_BEHAVIOR', (int)Tools::getValue('PS_GEOLOCATION_NA_BEHAVIOR')); + Configuration::updateValue('PS_ALLOWED_COUNTRIES', implode(';', Tools::getValue('countries'))); + } - if (!Validate::isCleanHtml(Tools::getValue('PS_GEOLOCATION_WHITELIST'))) - $this->errors[] = Tools::displayError('Invalid whitelist'); - else - { - Configuration::updateValue( - 'PS_GEOLOCATION_WHITELIST', - str_replace("\n", ';', str_replace("\r", '', Tools::getValue('PS_GEOLOCATION_WHITELIST'))) - ); - } - } + if (!Validate::isCleanHtml(Tools::getValue('PS_GEOLOCATION_WHITELIST'))) { + $this->errors[] = Tools::displayError('Invalid whitelist'); + } else { + Configuration::updateValue( + 'PS_GEOLOCATION_WHITELIST', + str_replace("\n", ';', str_replace("\r", '', Tools::getValue('PS_GEOLOCATION_WHITELIST'))) + ); + } + } - return parent::processUpdateOptions(); - } + return parent::processUpdateOptions(); + } - public function renderOptions() - { - // This field is not declared in class constructor because we want it to be manually post processed - $this->fields_options['geolocationCountries']['fields']['countries'] = array( - 'title' => $this->l('Select the countries from which your store is accessible'), - 'type' => 'checkbox_table', - 'identifier' => 'iso_code', - 'list' => Country::getCountries($this->context->language->id), - 'auto_value' => false - ); + public function renderOptions() + { + // This field is not declared in class constructor because we want it to be manually post processed + $this->fields_options['geolocationCountries']['fields']['countries'] = array( + 'title' => $this->l('Select the countries from which your store is accessible'), + 'type' => 'checkbox_table', + 'identifier' => 'iso_code', + 'list' => Country::getCountries($this->context->language->id), + 'auto_value' => false + ); - $this->tpl_option_vars = array('allowed_countries' => explode(';', Configuration::get('PS_ALLOWED_COUNTRIES'))); + $this->tpl_option_vars = array('allowed_countries' => explode(';', Configuration::get('PS_ALLOWED_COUNTRIES'))); - return parent::renderOptions(); - } + return parent::renderOptions(); + } - public function initContent() - { - $this->display = 'options'; - if (!$this->isGeoLiteCityAvailable()) - { - $this->displayWarning($this->l('In order to use Geolocation, please download').' + public function initContent() + { + $this->display = 'options'; + if (!$this->isGeoLiteCityAvailable()) { + $this->displayWarning($this->l('In order to use Geolocation, please download').' <a href="http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz">'.$this->l('this file').'</a> '. - $this->l('and extract it (using Winrar or Gzip) into the /tools/geoip/ directory.')); - Configuration::updateValue('PS_GEOLOCATION_ENABLED', 0); - } + $this->l('and extract it (using Winrar or Gzip) into the /tools/geoip/ directory.')); + Configuration::updateValue('PS_GEOLOCATION_ENABLED', 0); + } - parent::initContent(); - } + parent::initContent(); + } - protected function isGeoLiteCityAvailable() - { - if (@filemtime(_PS_GEOIP_DIR_._PS_GEOIP_CITY_FILE_)) - return true; + protected function isGeoLiteCityAvailable() + { + if (@filemtime(_PS_GEOIP_DIR_._PS_GEOIP_CITY_FILE_)) { + return true; + } - return false; - } + return false; + } } diff --git a/controllers/admin/AdminGroupsController.php b/controllers/admin/AdminGroupsController.php index 5fed2c0f..a61b7b77 100644 --- a/controllers/admin/AdminGroupsController.php +++ b/controllers/admin/AdminGroupsController.php @@ -29,576 +29,591 @@ */ class AdminGroupsControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'group'; - $this->className = 'Group'; - $this->list_id = 'group'; - $this->lang = true; - $this->addRowAction('edit'); - $this->addRowAction('view'); - $this->addRowAction('delete'); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + public function __construct() + { + $this->bootstrap = true; + $this->table = 'group'; + $this->className = 'Group'; + $this->list_id = 'group'; + $this->lang = true; + $this->addRowAction('edit'); + $this->addRowAction('view'); + $this->addRowAction('delete'); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $groups_to_keep = array( - Configuration::get('PS_UNIDENTIFIED_GROUP'), - Configuration::get('PS_GUEST_GROUP'), - Configuration::get('PS_CUSTOMER_GROUP') - ); + $groups_to_keep = array( + Configuration::get('PS_UNIDENTIFIED_GROUP'), + Configuration::get('PS_GUEST_GROUP'), + Configuration::get('PS_CUSTOMER_GROUP') + ); - $this->fields_list = array( - 'id_group' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Group name'), - 'filter_key' => 'b!name' - ), - 'reduction' => array( - 'title' => $this->l('Discount (%)'), - 'align' => 'right', - 'type' => 'percent' - ), - 'nb' => array( - 'title' => $this->l('Members'), - 'align' => 'center', - 'havingFilter' => true, - ), - 'show_prices' => array( - 'title' => $this->l('Show prices'), - 'align' => 'center', - 'type' => 'bool', - 'callback' => 'printShowPricesIcon', - 'orderby' => false - ), - 'date_add' => array( - 'title' => $this->l('Creation date'), - 'type' => 'date', - 'align' => 'right' - ) - ); + $this->fields_list = array( + 'id_group' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Group name'), + 'filter_key' => 'b!name' + ), + 'reduction' => array( + 'title' => $this->l('Discount (%)'), + 'align' => 'right', + 'type' => 'percent' + ), + 'nb' => array( + 'title' => $this->l('Members'), + 'align' => 'center', + 'havingFilter' => true, + ), + 'show_prices' => array( + 'title' => $this->l('Show prices'), + 'align' => 'center', + 'type' => 'bool', + 'callback' => 'printShowPricesIcon', + 'orderby' => false + ), + 'date_add' => array( + 'title' => $this->l('Creation date'), + 'type' => 'date', + 'align' => 'right' + ) + ); - $this->addRowActionSkipList('delete', $groups_to_keep); + $this->addRowActionSkipList('delete', $groups_to_keep); - parent::__construct(); + parent::__construct(); - $this->_select .= '(SELECT COUNT(jcg.`id_customer`) + $this->_select .= '(SELECT COUNT(jcg.`id_customer`) FROM `'._DB_PREFIX_.'customer_group` jcg LEFT JOIN `'._DB_PREFIX_.'customer` jc ON (jc.`id_customer` = jcg.`id_customer`) WHERE jc.`deleted` != 1 '.Shop::addSqlRestriction(Shop::SHARE_CUSTOMER).' AND jcg.`id_group` = a.`id_group`) AS nb'; - $this->_use_found_rows = false; + $this->_use_found_rows = false; - $groups = Group::getGroups(Context::getContext()->language->id, true); - if (Shop::isFeatureActive()) - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Default groups options'), - 'fields' => array( - 'PS_UNIDENTIFIED_GROUP' => array( - 'title' => $this->l('Visitors group'), - 'desc' => $this->l('The group defined for your un-identified visitors.'), - 'cast' => 'intval', - 'type' => 'select', - 'list' => $groups, - 'identifier' => 'id_group' - ), - 'PS_GUEST_GROUP' => array( - 'title' => $this->l('Guests group'), - 'desc' => $this->l('The group defined for your identified guest customers (used in guest checkout).'), - 'cast' => 'intval', - 'type' => 'select', - 'list' => $groups, - 'identifier' => 'id_group' - ), - 'PS_CUSTOMER_GROUP' => array( - 'title' => $this->l('Customers group'), - 'desc' => $this->l('The group defined for your identified registered customers.'), - 'cast' => 'intval', - 'type' => 'select', - 'list' => $groups, - 'identifier' => 'id_group' - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ), - ); - } + $groups = Group::getGroups(Context::getContext()->language->id, true); + if (Shop::isFeatureActive()) { + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Default groups options'), + 'fields' => array( + 'PS_UNIDENTIFIED_GROUP' => array( + 'title' => $this->l('Visitors group'), + 'desc' => $this->l('The group defined for your un-identified visitors.'), + 'cast' => 'intval', + 'type' => 'select', + 'list' => $groups, + 'identifier' => 'id_group' + ), + 'PS_GUEST_GROUP' => array( + 'title' => $this->l('Guests group'), + 'desc' => $this->l('The group defined for your identified guest customers (used in guest checkout).'), + 'cast' => 'intval', + 'type' => 'select', + 'list' => $groups, + 'identifier' => 'id_group' + ), + 'PS_CUSTOMER_GROUP' => array( + 'title' => $this->l('Customers group'), + 'desc' => $this->l('The group defined for your identified registered customers.'), + 'cast' => 'intval', + 'type' => 'select', + 'list' => $groups, + 'identifier' => 'id_group' + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ), + ); + } + } - public function setMedia() - { - parent::setMedia(); - $this->addJqueryPlugin('fancybox'); - $this->addJqueryUi('ui.sortable'); - } + public function setMedia() + { + parent::setMedia(); + $this->addJqueryPlugin('fancybox'); + $this->addJqueryUi('ui.sortable'); + } - public function initToolbar() - { - if ($this->display == 'add' || $this->display == 'edit') - $this->toolbar_btn['save-and-stay'] = array( - 'short' => 'SaveAndStay', - 'href' => '#', - 'desc' => $this->l('Save, then add a category reduction.'), - 'force_desc' => true, - ); - parent::initToolbar(); - } + public function initToolbar() + { + if ($this->display == 'add' || $this->display == 'edit') { + $this->toolbar_btn['save-and-stay'] = array( + 'short' => 'SaveAndStay', + 'href' => '#', + 'desc' => $this->l('Save, then add a category reduction.'), + 'force_desc' => true, + ); + } + parent::initToolbar(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_group'] = array( - 'href' => self::$currentIndex.'&addgroup&token='.$this->token, - 'desc' => $this->l('Add new group', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_group'] = array( + 'href' => self::$currentIndex.'&addgroup&token='.$this->token, + 'desc' => $this->l('Add new group', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function initProcess() - { - $this->id_object = Tools::getValue('id_'.$this->table); + public function initProcess() + { + $this->id_object = Tools::getValue('id_'.$this->table); - if (Tools::isSubmit('changeShowPricesVal') && $this->id_object) - $this->action = 'change_show_prices_val'; + if (Tools::isSubmit('changeShowPricesVal') && $this->id_object) { + $this->action = 'change_show_prices_val'; + } - if (Tools::getIsset('viewgroup')) - { - $this->list_id = 'customer_group'; + if (Tools::getIsset('viewgroup')) { + $this->list_id = 'customer_group'; - if (isset($_POST['submitReset'.$this->list_id])) - $this->processResetFilters(); - } - else - $this->list_id = 'group'; + if (isset($_POST['submitReset'.$this->list_id])) { + $this->processResetFilters(); + } + } else { + $this->list_id = 'group'; + } - parent::initProcess(); - } + parent::initProcess(); + } - public function renderView() - { - $this->context = Context::getContext(); - if (!($group = $this->loadObject(true))) - return; + public function renderView() + { + $this->context = Context::getContext(); + if (!($group = $this->loadObject(true))) { + return; + } - $this->tpl_view_vars = array( - 'group' => $group, - 'language' => $this->context->language, - 'customerList' => $this->renderCustomersList($group), - 'categorieReductions' => $this->formatCategoryDiscountList($group->id) - ); + $this->tpl_view_vars = array( + 'group' => $group, + 'language' => $this->context->language, + 'customerList' => $this->renderCustomersList($group), + 'categorieReductions' => $this->formatCategoryDiscountList($group->id) + ); - return parent::renderView(); - } + return parent::renderView(); + } - protected function renderCustomersList($group) - { - $genders = array(0 => '?'); - $genders_icon = array('default' => 'unknown.gif'); - foreach (Gender::getGenders() as $gender) - { - /** @var Gender $gender */ - $genders_icon[$gender->id] = '../genders/'.(int)$gender->id.'.jpg'; - $genders[$gender->id] = $gender->name; - } - $this->table = 'customer_group'; - $this->lang = false; - $this->list_id = 'customer_group'; - $this->actions = array(); - $this->addRowAction('edit'); - $this->identifier = 'id_customer'; - $this->bulk_actions = false; - $this->list_no_link = true; - $this->explicitSelect = true; + protected function renderCustomersList($group) + { + $genders = array(0 => '?'); + $genders_icon = array('default' => 'unknown.gif'); + foreach (Gender::getGenders() as $gender) { + /** @var Gender $gender */ + $genders_icon[$gender->id] = '../genders/'.(int)$gender->id.'.jpg'; + $genders[$gender->id] = $gender->name; + } + $this->table = 'customer_group'; + $this->lang = false; + $this->list_id = 'customer_group'; + $this->actions = array(); + $this->addRowAction('edit'); + $this->identifier = 'id_customer'; + $this->bulk_actions = false; + $this->list_no_link = true; + $this->explicitSelect = true; - $this->fields_list = (array( - 'id_customer' => array('title' => $this->l('ID'), 'align' => 'center', 'filter_key' => 'c!id_customer', 'class' => 'fixed-width-xs'), - 'id_gender' => array('title' => $this->l('Social title'), 'icon' => $genders_icon, 'list' => $genders), - 'firstname' => array('title' => $this->l('First name')), - 'lastname' => array('title' => $this->l('Last name')), - 'email' => array('title' => $this->l('Email address'), 'filter_key' => 'c!email', 'orderby' => true), - 'birthday' => array('title' => $this->l('Birth date'), 'type' => 'date', 'class' => 'fixed-width-md', 'align' => 'center'), - 'date_add' => array('title' => $this->l('Registration date'), 'type' => 'date', 'class' => 'fixed-width-md', 'align' => 'center'), - 'active' => array('title' => $this->l('Enabled'),'align' => 'center', 'class' => 'fixed-width-sm', 'active' => 'status','type' => 'bool', 'search' => false, 'orderby' => false, 'filter_key' => 'c!active') - )); - $this->_select = 'c.*, a.id_group'; - $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'customer` c ON (a.`id_customer` = c.`id_customer`)'; - $this->_where = 'AND a.`id_group` = '.(int)$group->id.' AND c.`deleted` != 1'; - $this->_where .= Shop::addSqlRestriction(Shop::SHARE_CUSTOMER, 'c'); - self::$currentIndex = self::$currentIndex.'&id_group='.(int)$group->id.'&viewgroup'; + $this->fields_list = (array( + 'id_customer' => array('title' => $this->l('ID'), 'align' => 'center', 'filter_key' => 'c!id_customer', 'class' => 'fixed-width-xs'), + 'id_gender' => array('title' => $this->l('Social title'), 'icon' => $genders_icon, 'list' => $genders), + 'firstname' => array('title' => $this->l('First name')), + 'lastname' => array('title' => $this->l('Last name')), + 'email' => array('title' => $this->l('Email address'), 'filter_key' => 'c!email', 'orderby' => true), + 'birthday' => array('title' => $this->l('Birth date'), 'type' => 'date', 'class' => 'fixed-width-md', 'align' => 'center'), + 'date_add' => array('title' => $this->l('Registration date'), 'type' => 'date', 'class' => 'fixed-width-md', 'align' => 'center'), + 'active' => array('title' => $this->l('Enabled'), 'align' => 'center', 'class' => 'fixed-width-sm', 'active' => 'status', 'type' => 'bool', 'search' => false, 'orderby' => false, 'filter_key' => 'c!active') + )); + $this->_select = 'c.*, a.id_group'; + $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'customer` c ON (a.`id_customer` = c.`id_customer`)'; + $this->_where = 'AND a.`id_group` = '.(int)$group->id.' AND c.`deleted` != 1'; + $this->_where .= Shop::addSqlRestriction(Shop::SHARE_CUSTOMER, 'c'); + self::$currentIndex = self::$currentIndex.'&id_group='.(int)$group->id.'&viewgroup'; - $this->processFilter(); - return parent::renderList(); - } + $this->processFilter(); + return parent::renderList(); + } - public function renderForm() - { - if (!($group = $this->loadObject(true))) - return; + public function renderForm() + { + if (!($group = $this->loadObject(true))) { + return; + } - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Customer group'), - 'icon' => 'icon-group' - ), - 'submit' => array( - 'title' => $this->l('Save'), - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'required' => true, - 'lang' => true, - 'col' => 4, - 'hint' => $this->l('Forbidden characters:').' 0-9!&lt;&gt;,;?=+()@#"�{}_$%:' - ), - array( - 'type' => 'text', - 'label' => $this->l('Discount'), - 'name' => 'reduction', - 'suffix' => '%', - 'col' => 1, - 'hint' => $this->l('Automatically apply this value as a discount on all products for members of this customer group.') - ), - array( - 'type' => 'select', - 'label' => $this->l('Price display method'), - 'name' => 'price_display_method', - 'col' => 2, - 'hint' => $this->l('How prices are displayed in the order summary for this customer group.'), - 'options' => array( - 'query' => array( - array( - 'id_method' => PS_TAX_EXC, - 'name' => $this->l('Tax excluded') - ), - array( - 'id_method' => PS_TAX_INC, - 'name' => $this->l('Tax included') - ) - ), - 'id' => 'id_method', - 'name' => 'name' - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Show prices'), - 'name' => 'show_prices', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'show_prices_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'show_prices_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Customers in this group can view prices.') - ), - array( - 'type' => 'group_discount_category', - 'label' => $this->l('Category discount'), - 'name' => 'reduction', - 'values' => ($group->id ? $this->formatCategoryDiscountList((int)$group->id) : array()) - ), - array( - 'type' => 'modules', - 'label' => $this->l('Modules Authorization'), - 'name' => 'auth_modules', - 'values' => $this->formatModuleListAuth($group->id) - ) - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Customer group'), + 'icon' => 'icon-group' + ), + 'submit' => array( + 'title' => $this->l('Save'), + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'required' => true, + 'lang' => true, + 'col' => 4, + 'hint' => $this->l('Forbidden characters:').' 0-9!&lt;&gt;,;?=+()@#"�{}_$%:' + ), + array( + 'type' => 'text', + 'label' => $this->l('Discount'), + 'name' => 'reduction', + 'suffix' => '%', + 'col' => 1, + 'hint' => $this->l('Automatically apply this value as a discount on all products for members of this customer group.') + ), + array( + 'type' => 'select', + 'label' => $this->l('Price display method'), + 'name' => 'price_display_method', + 'col' => 2, + 'hint' => $this->l('How prices are displayed in the order summary for this customer group.'), + 'options' => array( + 'query' => array( + array( + 'id_method' => PS_TAX_EXC, + 'name' => $this->l('Tax excluded') + ), + array( + 'id_method' => PS_TAX_INC, + 'name' => $this->l('Tax included') + ) + ), + 'id' => 'id_method', + 'name' => 'name' + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Show prices'), + 'name' => 'show_prices', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'show_prices_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'show_prices_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Customers in this group can view prices.') + ), + array( + 'type' => 'group_discount_category', + 'label' => $this->l('Category discount'), + 'name' => 'reduction', + 'values' => ($group->id ? $this->formatCategoryDiscountList((int)$group->id) : array()) + ), + array( + 'type' => 'modules', + 'label' => $this->l('Modules Authorization'), + 'name' => 'auth_modules', + 'values' => $this->formatModuleListAuth($group->id) + ) + ) + ); - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - if (Tools::getIsset('addgroup')) - $this->fields_value['price_display_method'] = Configuration::get('PRICE_DISPLAY_METHOD'); + if (Tools::getIsset('addgroup')) { + $this->fields_value['price_display_method'] = Configuration::get('PRICE_DISPLAY_METHOD'); + } - $this->fields_value['reduction'] = isset($group->reduction) ? $group->reduction : 0; + $this->fields_value['reduction'] = isset($group->reduction) ? $group->reduction : 0; - $tree = new HelperTreeCategories('categories-tree'); - $this->tpl_form_vars['categoryTreeView'] = $tree->setRootCategory((int)Category::getRootCategory()->id)->render(); + $tree = new HelperTreeCategories('categories-tree'); + $this->tpl_form_vars['categoryTreeView'] = $tree->setRootCategory((int)Category::getRootCategory()->id)->render(); - return parent::renderForm(); - } + return parent::renderForm(); + } - protected function formatCategoryDiscountList($id_group) - { - $group_reductions = GroupReduction::getGroupReductions((int)$id_group, $this->context->language->id); - $category_reductions = array(); - $category_reduction = Tools::getValue('category_reduction'); + protected function formatCategoryDiscountList($id_group) + { + $group_reductions = GroupReduction::getGroupReductions((int)$id_group, $this->context->language->id); + $category_reductions = array(); + $category_reduction = Tools::getValue('category_reduction'); - foreach ($group_reductions as $category) - { - if (is_array($category_reduction) && array_key_exists($category['id_category'], $category_reduction)) - $category['reduction'] = $category_reduction[$category['id_category']]; + foreach ($group_reductions as $category) { + if (is_array($category_reduction) && array_key_exists($category['id_category'], $category_reduction)) { + $category['reduction'] = $category_reduction[$category['id_category']]; + } - $category_reductions[(int)$category['id_category']] = array( - 'path' => getPath(Context::getContext()->link->getAdminLink('AdminCategories'), (int)$category['id_category']), - 'reduction' => (float)$category['reduction'] * 100, - 'id_category' => (int)$category['id_category'] - ); - } + $category_reductions[(int)$category['id_category']] = array( + 'path' => getPath(Context::getContext()->link->getAdminLink('AdminCategories'), (int)$category['id_category']), + 'reduction' => (float)$category['reduction'] * 100, + 'id_category' => (int)$category['id_category'] + ); + } - if (is_array($category_reduction)) - foreach ($category_reduction as $key => $val) - if (!array_key_exists($key, $category_reductions)) - $category_reductions[(int)$key] = array( - 'path' => getPath(Context::getContext()->link->getAdminLink('AdminCategories'), $key), - 'reduction' => (float)$val * 100, - 'id_category' => (int)$key - ); + if (is_array($category_reduction)) { + foreach ($category_reduction as $key => $val) { + if (!array_key_exists($key, $category_reductions)) { + $category_reductions[(int)$key] = array( + 'path' => getPath(Context::getContext()->link->getAdminLink('AdminCategories'), $key), + 'reduction' => (float)$val * 100, + 'id_category' => (int)$key + ); + } + } + } - return $category_reductions; - } + return $category_reductions; + } - public function formatModuleListAuth($id_group) - { - $modules = Module::getModulesInstalled(); - $authorized_modules = ''; + public function formatModuleListAuth($id_group) + { + $modules = Module::getModulesInstalled(); + $authorized_modules = ''; - $auth_modules = array(); - $unauth_modules = array(); + $auth_modules = array(); + $unauth_modules = array(); - if ($id_group) - $authorized_modules = Module::getAuthorizedModules($id_group); + if ($id_group) { + $authorized_modules = Module::getAuthorizedModules($id_group); + } - if (is_array($authorized_modules)) - { - foreach ($modules as $module) - { - $authorized = false; - foreach ($authorized_modules as $auth_module) - if ($module['id_module'] == $auth_module['id_module']) - $authorized = true; + if (is_array($authorized_modules)) { + foreach ($modules as $module) { + $authorized = false; + foreach ($authorized_modules as $auth_module) { + if ($module['id_module'] == $auth_module['id_module']) { + $authorized = true; + } + } - if ($authorized) - $auth_modules[] = $module; - else - $unauth_modules[] = $module; - } - } - else - $auth_modules = $modules; - $auth_modules_tmp = array(); - foreach ($auth_modules as $key => $val) - if ($module = Module::getInstanceById($val['id_module'])) - $auth_modules_tmp[] = $module; + if ($authorized) { + $auth_modules[] = $module; + } else { + $unauth_modules[] = $module; + } + } + } else { + $auth_modules = $modules; + } + $auth_modules_tmp = array(); + foreach ($auth_modules as $key => $val) { + if ($module = Module::getInstanceById($val['id_module'])) { + $auth_modules_tmp[] = $module; + } + } - $auth_modules = $auth_modules_tmp; + $auth_modules = $auth_modules_tmp; - $unauth_modules_tmp = array(); - foreach ($unauth_modules as $key => $val) - if (($tmp_obj = Module::getInstanceById($val['id_module']))) - $unauth_modules_tmp[] = $tmp_obj; + $unauth_modules_tmp = array(); + foreach ($unauth_modules as $key => $val) { + if (($tmp_obj = Module::getInstanceById($val['id_module']))) { + $unauth_modules_tmp[] = $tmp_obj; + } + } - $unauth_modules = $unauth_modules_tmp; + $unauth_modules = $unauth_modules_tmp; - return array('unauth_modules' => $unauth_modules, 'auth_modules' => $auth_modules); - } + return array('unauth_modules' => $unauth_modules, 'auth_modules' => $auth_modules); + } - public function processSave() - { - if (!$this->validateDiscount(Tools::getValue('reduction'))) - $this->errors[] = Tools::displayError('The discount value is incorrect (must be a percentage).'); - else - { - $this->updateCategoryReduction(); - $object = parent::processSave(); - $this->updateRestrictions(); - return $object; - } - } + public function processSave() + { + if (!$this->validateDiscount(Tools::getValue('reduction'))) { + $this->errors[] = Tools::displayError('The discount value is incorrect (must be a percentage).'); + } else { + $this->updateCategoryReduction(); + $object = parent::processSave(); + $this->updateRestrictions(); + return $object; + } + } - protected function validateDiscount($reduction) - { - if (!Validate::isPrice($reduction) || $reduction > 100 || $reduction < 0) - return false; - else - return true; - } + protected function validateDiscount($reduction) + { + if (!Validate::isPrice($reduction) || $reduction > 100 || $reduction < 0) { + return false; + } else { + return true; + } + } - public function ajaxProcessAddCategoryReduction() - { - $category_reduction = Tools::getValue('category_reduction'); - $id_category = Tools::getValue('id_category'); //no cast validation is done with Validate::isUnsignedId($id_category) + public function ajaxProcessAddCategoryReduction() + { + $category_reduction = Tools::getValue('category_reduction'); + $id_category = Tools::getValue('id_category'); //no cast validation is done with Validate::isUnsignedId($id_category) - $result = array(); - if (!Validate::isUnsignedId($id_category)) - { - $result['errors'][] = Tools::displayError('Wrong category ID.'); - $result['hasError'] = true; - } - elseif (!$this->validateDiscount($category_reduction)) - { - $result['errors'][] = Tools::displayError('The discount value is incorrect (must be a percentage).'); - $result['hasError'] = true; - } - else - { - $result['id_category'] = (int)$id_category; - $result['catPath'] = getPath(self::$currentIndex.'?tab=AdminCategories', (int)$id_category); - $result['discount'] = $category_reduction; - $result['hasError'] = false; - } - die(Tools::jsonEncode($result)); - } + $result = array(); + if (!Validate::isUnsignedId($id_category)) { + $result['errors'][] = Tools::displayError('Wrong category ID.'); + $result['hasError'] = true; + } elseif (!$this->validateDiscount($category_reduction)) { + $result['errors'][] = Tools::displayError('The discount value is incorrect (must be a percentage).'); + $result['hasError'] = true; + } else { + $result['id_category'] = (int)$id_category; + $result['catPath'] = getPath(self::$currentIndex.'?tab=AdminCategories', (int)$id_category); + $result['discount'] = $category_reduction; + $result['hasError'] = false; + } + die(Tools::jsonEncode($result)); + } - /** - * Update (or create) restrictions for modules by group - */ - protected function updateRestrictions() - { - $id_group = Tools::getValue('id_group'); - $auth_modules = Tools::getValue('modulesBoxAuth'); - $return = true; - if ($id_group) - Group::truncateModulesRestrictions((int)$id_group); - $shops = Shop::getShops(true, null, true); - if (is_array($auth_modules)) - $return &= Group::addModulesRestrictions($id_group, $auth_modules, $shops); - return $return; - } + /** + * Update (or create) restrictions for modules by group + */ + protected function updateRestrictions() + { + $id_group = Tools::getValue('id_group'); + $auth_modules = Tools::getValue('modulesBoxAuth'); + $return = true; + if ($id_group) { + Group::truncateModulesRestrictions((int)$id_group); + } + $shops = Shop::getShops(true, null, true); + if (is_array($auth_modules)) { + $return &= Group::addModulesRestrictions($id_group, $auth_modules, $shops); + } + return $return; + } - protected function updateCategoryReduction() - { - $category_reduction = Tools::getValue('category_reduction'); - Db::getInstance()->execute(' + protected function updateCategoryReduction() + { + $category_reduction = Tools::getValue('category_reduction'); + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'group_reduction` WHERE `id_group` = '.(int)Tools::getValue('id_group') - ); - Db::getInstance()->execute(' + ); + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'product_group_reduction_cache` WHERE `id_group` = '.(int)Tools::getValue('id_group') - ); - if (is_array($category_reduction) && count($category_reduction)) - { - if (!Configuration::getGlobalValue('PS_GROUP_FEATURE_ACTIVE')) - Configuration::updateGlobalValue('PS_GROUP_FEATURE_ACTIVE', 1); - foreach ($category_reduction as $cat => $reduction) - { - if (!Validate::isUnsignedId($cat) || !$this->validateDiscount($reduction)) - $this->errors[] = Tools::displayError('The discount value is incorrect.'); - else - { - $category = new Category((int)$cat); - $category->addGroupsIfNoExist((int)Tools::getValue('id_group')); - $group_reduction = new GroupReduction(); - $group_reduction->id_group = (int)Tools::getValue('id_group'); - $group_reduction->reduction = (float)($reduction / 100); - $group_reduction->id_category = (int)$cat; - if (!$group_reduction->save()) - $this->errors[] = Tools::displayError('You cannot save group reductions.'); - } - } - } - } + ); + if (is_array($category_reduction) && count($category_reduction)) { + if (!Configuration::getGlobalValue('PS_GROUP_FEATURE_ACTIVE')) { + Configuration::updateGlobalValue('PS_GROUP_FEATURE_ACTIVE', 1); + } + foreach ($category_reduction as $cat => $reduction) { + if (!Validate::isUnsignedId($cat) || !$this->validateDiscount($reduction)) { + $this->errors[] = Tools::displayError('The discount value is incorrect.'); + } else { + $category = new Category((int)$cat); + $category->addGroupsIfNoExist((int)Tools::getValue('id_group')); + $group_reduction = new GroupReduction(); + $group_reduction->id_group = (int)Tools::getValue('id_group'); + $group_reduction->reduction = (float)($reduction / 100); + $group_reduction->id_category = (int)$cat; + if (!$group_reduction->save()) { + $this->errors[] = Tools::displayError('You cannot save group reductions.'); + } + } + } + } + } - /** - * Toggle show prices flag - */ - public function processChangeShowPricesVal() - { - $group = new Group($this->id_object); - if (!Validate::isLoadedObject($group)) - $this->errors[] = Tools::displayError('An error occurred while updating this group.'); - $update = Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'group` SET show_prices = '.($group->show_prices ? 0 : 1).' WHERE `id_group` = '.(int)$group->id); - if (!$update) - $this->errors[] = Tools::displayError('An error occurred while updating this group.'); - Tools::clearSmartyCache(); - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); - } + /** + * Toggle show prices flag + */ + public function processChangeShowPricesVal() + { + $group = new Group($this->id_object); + if (!Validate::isLoadedObject($group)) { + $this->errors[] = Tools::displayError('An error occurred while updating this group.'); + } + $update = Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'group` SET show_prices = '.($group->show_prices ? 0 : 1).' WHERE `id_group` = '.(int)$group->id); + if (!$update) { + $this->errors[] = Tools::displayError('An error occurred while updating this group.'); + } + Tools::clearSmartyCache(); + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } - /** - * Print enable / disable icon for show prices option - * - * @param $id_group integer Group ID - * @param $tr array Row data - * @return string HTML link and icon - */ - public function printShowPricesIcon($id_group, $tr) - { - $group = new Group($tr['id_group']); - if (!Validate::isLoadedObject($group)) - return; - return '<a class="list-action-enable'.($group->show_prices ? ' action-enabled' : ' action-disabled').'" href="index.php?tab=AdminGroups&id_group='.(int)$group->id.'&changeShowPricesVal&token='.Tools::getAdminTokenLite('AdminGroups').'"> + /** + * Print enable / disable icon for show prices option + * + * @param $id_group integer Group ID + * @param $tr array Row data + * @return string HTML link and icon + */ + public function printShowPricesIcon($id_group, $tr) + { + $group = new Group($tr['id_group']); + if (!Validate::isLoadedObject($group)) { + return; + } + return '<a class="list-action-enable'.($group->show_prices ? ' action-enabled' : ' action-disabled').'" href="index.php?tab=AdminGroups&id_group='.(int)$group->id.'&changeShowPricesVal&token='.Tools::getAdminTokenLite('AdminGroups').'"> '.($group->show_prices ? '<i class="icon-check"></i>' : '<i class="icon-remove"></i>'). - '</a>'; - } + '</a>'; + } - public function renderList() - { - $unidentified = new Group(Configuration::get('PS_UNIDENTIFIED_GROUP')); - $guest = new Group(Configuration::get('PS_GUEST_GROUP')); - $default = new Group(Configuration::get('PS_CUSTOMER_GROUP')); + public function renderList() + { + $unidentified = new Group(Configuration::get('PS_UNIDENTIFIED_GROUP')); + $guest = new Group(Configuration::get('PS_GUEST_GROUP')); + $default = new Group(Configuration::get('PS_CUSTOMER_GROUP')); - $unidentified_group_information = sprintf( - $this->l('%s - All persons without a customer account or customers that are not logged in.'), - '<b>'.$unidentified->name[$this->context->language->id].'</b>' - ); - $guest_group_information = sprintf( - $this->l('%s - All persons who placed an order through Guest Checkout.'), - '<b>'.$guest->name[$this->context->language->id].'</b>' - ); - $default_group_information = sprintf( - $this->l('%s - All persons who created an account on this site.'), - '<b>'.$default->name[$this->context->language->id].'</b>' - ); + $unidentified_group_information = sprintf( + $this->l('%s - All persons without a customer account or customers that are not logged in.'), + '<b>'.$unidentified->name[$this->context->language->id].'</b>' + ); + $guest_group_information = sprintf( + $this->l('%s - All persons who placed an order through Guest Checkout.'), + '<b>'.$guest->name[$this->context->language->id].'</b>' + ); + $default_group_information = sprintf( + $this->l('%s - All persons who created an account on this site.'), + '<b>'.$default->name[$this->context->language->id].'</b>' + ); - $this->displayInformation($this->l('PrestaShop has three default customer groups:')); - $this->displayInformation($unidentified_group_information); - $this->displayInformation($guest_group_information); - $this->displayInformation($default_group_information); - return parent::renderList(); - } + $this->displayInformation($this->l('PrestaShop has three default customer groups:')); + $this->displayInformation($unidentified_group_information); + $this->displayInformation($guest_group_information); + $this->displayInformation($default_group_information); + return parent::renderList(); + } - public function displayEditLink($token = null, $id, $name = null) - { - $tpl = $this->createTemplate('helpers/list/list_action_edit.tpl'); - if (!array_key_exists('Edit', self::$cache_lang)) - self::$cache_lang['Edit'] = $this->l('Edit', 'Helper'); + public function displayEditLink($token = null, $id, $name = null) + { + $tpl = $this->createTemplate('helpers/list/list_action_edit.tpl'); + if (!array_key_exists('Edit', self::$cache_lang)) { + self::$cache_lang['Edit'] = $this->l('Edit', 'Helper'); + } - $href = self::$currentIndex.'&'.$this->identifier.'='.$id.'&update'.$this->table.'&token='.($token != null ? $token : $this->token); + $href = self::$currentIndex.'&'.$this->identifier.'='.$id.'&update'.$this->table.'&token='.($token != null ? $token : $this->token); - if ($this->display == 'view') - $href = Context::getContext()->link->getAdminLink('AdminCustomers').'&id_customer='.(int)$id.'&updatecustomer'; + if ($this->display == 'view') { + $href = Context::getContext()->link->getAdminLink('AdminCustomers').'&id_customer='.(int)$id.'&updatecustomer'; + } - $tpl->assign(array( - 'href' => $href, - 'action' => self::$cache_lang['Edit'], - 'id' => $id - )); + $tpl->assign(array( + 'href' => $href, + 'action' => self::$cache_lang['Edit'], + 'id' => $id + )); - return $tpl->fetch(); - } + return $tpl->fetch(); + } } diff --git a/controllers/admin/AdminImagesController.php b/controllers/admin/AdminImagesController.php index 0c3421a6..8bbc9493 100644 --- a/controllers/admin/AdminImagesController.php +++ b/controllers/admin/AdminImagesController.php @@ -29,713 +29,731 @@ */ class AdminImagesControllerCore extends AdminController { - protected $start_time = 0; - protected $max_execution_time = 7200; - protected $display_move; + protected $start_time = 0; + protected $max_execution_time = 7200; + protected $display_move; - public function __construct() - { - $this->bootstrap = true; - $this->table = 'image_type'; - $this->className = 'ImageType'; - $this->lang = false; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'image_type'; + $this->className = 'ImageType'; + $this->lang = false; - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->fields_list = array( - 'id_image_type' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'name' => array('title' => $this->l('Name')), - 'width' => array('title' => $this->l('Width'), 'suffix' => ' px'), - 'height' => array('title' => $this->l('Height'), 'suffix' => ' px'), - 'products' => array('title' => $this->l('Products'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false), - 'categories' => array('title' => $this->l('Categories'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false), - 'manufacturers' => array('title' => $this->l('Manufacturers'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false), - 'suppliers' => array('title' => $this->l('Suppliers'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false), - 'stores' => array('title' => $this->l('Stores'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false) - ); + $this->fields_list = array( + 'id_image_type' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'name' => array('title' => $this->l('Name')), + 'width' => array('title' => $this->l('Width'), 'suffix' => ' px'), + 'height' => array('title' => $this->l('Height'), 'suffix' => ' px'), + 'products' => array('title' => $this->l('Products'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false), + 'categories' => array('title' => $this->l('Categories'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false), + 'manufacturers' => array('title' => $this->l('Manufacturers'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false), + 'suppliers' => array('title' => $this->l('Suppliers'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false), + 'stores' => array('title' => $this->l('Stores'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false) + ); - // Scenes tab has been removed by default from the installation, but may still exists in updates - if (Tab::getIdFromClassName('AdminScenes')) - $this->fields_list['scenes'] = array('title' => $this->l('Scenes'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false); + // Scenes tab has been removed by default from the installation, but may still exists in updates + if (Tab::getIdFromClassName('AdminScenes')) { + $this->fields_list['scenes'] = array('title' => $this->l('Scenes'), 'align' => 'center', 'type' => 'bool', 'callback' => 'printEntityActiveIcon', 'orderby' => false); + } - // No need to display the old image system migration tool except if product images are in _PS_PROD_IMG_DIR_ - $this->display_move = false; - $dir = _PS_PROD_IMG_DIR_; - if (is_dir($dir)) - if ($dh = opendir($dir)) - { - while (($file = readdir($dh)) !== false && $this->display_move == false) - if (!is_dir($dir.DIRECTORY_SEPARATOR.$file) && $file[0] != '.' && is_numeric($file[0])) - $this->display_move = true; - closedir($dh); - } + // No need to display the old image system migration tool except if product images are in _PS_PROD_IMG_DIR_ + $this->display_move = false; + $dir = _PS_PROD_IMG_DIR_; + if (is_dir($dir)) { + if ($dh = opendir($dir)) { + while (($file = readdir($dh)) !== false && $this->display_move == false) { + if (!is_dir($dir.DIRECTORY_SEPARATOR.$file) && $file[0] != '.' && is_numeric($file[0])) { + $this->display_move = true; + } + } + closedir($dh); + } + } - $this->fields_options = array( - 'images' => array( - 'title' => $this->l('Images generation options'), - 'icon' => 'icon-picture', - 'top' => '', - 'bottom' => '', - 'description' => $this->l('JPEG images have a small file size and standard quality. PNG images have a larger file size, a higher quality and support transparency. Note that in all cases the image files will have the .jpg extension.').' + $this->fields_options = array( + 'images' => array( + 'title' => $this->l('Images generation options'), + 'icon' => 'icon-picture', + 'top' => '', + 'bottom' => '', + 'description' => $this->l('JPEG images have a small file size and standard quality. PNG images have a larger file size, a higher quality and support transparency. Note that in all cases the image files will have the .jpg extension.').' <br /><br />'.$this->l('WARNING: This feature may not be compatible with your theme, or with some of your modules. In particular, PNG mode is not compatible with the Watermark module. If you encounter any issues, turn it off by selecting "Use JPEG".'), - 'fields' => array( - 'PS_IMAGE_QUALITY' => array( - 'title' => $this->l('Image format'), - 'show' => true, - 'required' => true, - 'type' => 'radio', - 'choices' => array('jpg' => $this->l('Use JPEG.'), 'png' => $this->l('Use PNG only if the base image is in PNG format.'), 'png_all' => $this->l('Use PNG for all images.')) - ), - 'PS_JPEG_QUALITY' => array( - 'title' => $this->l('JPEG compression'), - 'hint' => $this->l('Ranges from 0 (worst quality, smallest file) to 100 (best quality, biggest file).').' '.$this->l('Recommended: 90.'), - 'validation' => 'isUnsignedId', - 'required' => true, - 'cast' => 'intval', - 'type' => 'text' - ), - 'PS_PNG_QUALITY' => array( - 'title' => $this->l('PNG compression'), - 'hint' => $this->l('PNG compression is lossless: unlike JPG, you do not lose image quality with a high compression ratio. However, photographs will compress very badly.').' '.$this->l('Ranges from 0 (biggest file) to 9 (smallest file, slowest decompression).').' '.$this->l('Recommended: 7.'), - 'validation' => 'isUnsignedId', - 'required' => true, - 'cast' => 'intval', - 'type' => 'text' - ), - 'PS_IMAGE_GENERATION_METHOD' => array( - 'title' => $this->l('Generate images based on one side of the source image'), - 'validation' => 'isUnsignedId', - 'required' => false, - 'cast' => 'intval', - 'type' => 'select', - 'list' => array( - array( - 'id' => '0', - 'name' => $this->l('Automatic (longest side)') - ), - array( - 'id' => '1', - 'name' => $this->l('Width') - ), - array( - 'id' => '2', - 'name' => $this->l('Height') - ) - ), - 'identifier' => 'id', - 'visibility' => Shop::CONTEXT_ALL - ), - 'PS_PRODUCT_PICTURE_MAX_SIZE' => array( - 'title' => $this->l('Maximum file size of product customization pictures'), - 'hint' => $this->l('The maximum file size of pictures that customers can upload to customize a product (in bytes).'), - 'validation' => 'isUnsignedInt', - 'required' => true, - 'cast' => 'intval', - 'type' => 'text', - 'suffix' => $this->l('bytes'), - 'visibility' => Shop::CONTEXT_ALL - ), - 'PS_PRODUCT_PICTURE_WIDTH' => array( - 'title' => $this->l('Product picture width'), - 'hint' => $this->l('Width of product customization pictures that customers can upload (in pixels).'), - 'validation' => 'isUnsignedInt', - 'required' => true, - 'cast' => 'intval', - 'type' => 'text', - 'width' => 'px', - 'suffix' => $this->l('pixels'), - 'visibility' => Shop::CONTEXT_ALL - ), - 'PS_PRODUCT_PICTURE_HEIGHT' => array( - 'title' => $this->l('Product picture height'), - 'hint' => $this->l('Height of product customization pictures that customers can upload (in pixels).'), - 'validation' => 'isUnsignedInt', - 'required' => true, - 'cast' => 'intval', - 'type' => 'text', - 'height' => 'px', - 'suffix' => $this->l('pixels'), - 'visibility' => Shop::CONTEXT_ALL - ), - 'PS_HIGHT_DPI' => array( - 'type' => 'bool', - 'title' => $this->l('Generate high resolution images'), - 'required' => false, - 'is_bool' => true, - 'hint' => $this->l('This will generate an additional file for each image (thus doubling your total amount of images). Resolution of these images will be twice higher.'), - 'desc' => $this->l('Enable to optimize the display of your images on high pixel density screens.'), - 'visibility' => Shop::CONTEXT_ALL, - ), - ), - 'submit' => array('title' => $this->l('Save')), - ), - ); + 'fields' => array( + 'PS_IMAGE_QUALITY' => array( + 'title' => $this->l('Image format'), + 'show' => true, + 'required' => true, + 'type' => 'radio', + 'choices' => array('jpg' => $this->l('Use JPEG.'), 'png' => $this->l('Use PNG only if the base image is in PNG format.'), 'png_all' => $this->l('Use PNG for all images.')) + ), + 'PS_JPEG_QUALITY' => array( + 'title' => $this->l('JPEG compression'), + 'hint' => $this->l('Ranges from 0 (worst quality, smallest file) to 100 (best quality, biggest file).').' '.$this->l('Recommended: 90.'), + 'validation' => 'isUnsignedId', + 'required' => true, + 'cast' => 'intval', + 'type' => 'text' + ), + 'PS_PNG_QUALITY' => array( + 'title' => $this->l('PNG compression'), + 'hint' => $this->l('PNG compression is lossless: unlike JPG, you do not lose image quality with a high compression ratio. However, photographs will compress very badly.').' '.$this->l('Ranges from 0 (biggest file) to 9 (smallest file, slowest decompression).').' '.$this->l('Recommended: 7.'), + 'validation' => 'isUnsignedId', + 'required' => true, + 'cast' => 'intval', + 'type' => 'text' + ), + 'PS_IMAGE_GENERATION_METHOD' => array( + 'title' => $this->l('Generate images based on one side of the source image'), + 'validation' => 'isUnsignedId', + 'required' => false, + 'cast' => 'intval', + 'type' => 'select', + 'list' => array( + array( + 'id' => '0', + 'name' => $this->l('Automatic (longest side)') + ), + array( + 'id' => '1', + 'name' => $this->l('Width') + ), + array( + 'id' => '2', + 'name' => $this->l('Height') + ) + ), + 'identifier' => 'id', + 'visibility' => Shop::CONTEXT_ALL + ), + 'PS_PRODUCT_PICTURE_MAX_SIZE' => array( + 'title' => $this->l('Maximum file size of product customization pictures'), + 'hint' => $this->l('The maximum file size of pictures that customers can upload to customize a product (in bytes).'), + 'validation' => 'isUnsignedInt', + 'required' => true, + 'cast' => 'intval', + 'type' => 'text', + 'suffix' => $this->l('bytes'), + 'visibility' => Shop::CONTEXT_ALL + ), + 'PS_PRODUCT_PICTURE_WIDTH' => array( + 'title' => $this->l('Product picture width'), + 'hint' => $this->l('Width of product customization pictures that customers can upload (in pixels).'), + 'validation' => 'isUnsignedInt', + 'required' => true, + 'cast' => 'intval', + 'type' => 'text', + 'width' => 'px', + 'suffix' => $this->l('pixels'), + 'visibility' => Shop::CONTEXT_ALL + ), + 'PS_PRODUCT_PICTURE_HEIGHT' => array( + 'title' => $this->l('Product picture height'), + 'hint' => $this->l('Height of product customization pictures that customers can upload (in pixels).'), + 'validation' => 'isUnsignedInt', + 'required' => true, + 'cast' => 'intval', + 'type' => 'text', + 'height' => 'px', + 'suffix' => $this->l('pixels'), + 'visibility' => Shop::CONTEXT_ALL + ), + 'PS_HIGHT_DPI' => array( + 'type' => 'bool', + 'title' => $this->l('Generate high resolution images'), + 'required' => false, + 'is_bool' => true, + 'hint' => $this->l('This will generate an additional file for each image (thus doubling your total amount of images). Resolution of these images will be twice higher.'), + 'desc' => $this->l('Enable to optimize the display of your images on high pixel density screens.'), + 'visibility' => Shop::CONTEXT_ALL, + ), + ), + 'submit' => array('title' => $this->l('Save')), + ), + ); - if ($this->display_move) - $this->fields_options['product_images']['fields']['PS_LEGACY_IMAGES'] = array( - 'title' => $this->l('Use the legacy image filesystem'), - 'hint' => $this->l('This should be set to yes unless you successfully moved images in "Images" page under the "Preferences" menu.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'required' => false, - 'type' => 'bool', - 'visibility' => Shop::CONTEXT_ALL - ); + if ($this->display_move) { + $this->fields_options['product_images']['fields']['PS_LEGACY_IMAGES'] = array( + 'title' => $this->l('Use the legacy image filesystem'), + 'hint' => $this->l('This should be set to yes unless you successfully moved images in "Images" page under the "Preferences" menu.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'required' => false, + 'type' => 'bool', + 'visibility' => Shop::CONTEXT_ALL + ); + } - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Image type'), - 'icon' => 'icon-picture' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name for the image type'), - 'name' => 'name', - 'required' => true, - 'hint' => $this->l('Letters, underscores and hyphens only (e.g. "small_custom", "cart_medium", "large", "thickbox_extra-large").') - ), - array( - 'type' => 'text', - 'label' => $this->l('Width'), - 'name' => 'width', - 'required' => true, - 'maxlength' => 5, - 'suffix' => $this->l('pixels'), - 'hint' => $this->l('Maximum image width in pixels.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Height'), - 'name' => 'height', - 'required' => true, - 'maxlength' => 5, - 'suffix' => $this->l('pixels'), - 'hint' => $this->l('Maximum image height in pixels.') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Products'), - 'name' => 'products', - 'required' => false, - 'is_bool' => true, - 'hint' => $this->l('This type will be used for Product images.'), - 'values' => array( - array( - 'id' => 'products_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'products_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ), - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Categories'), - 'name' => 'categories', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'hint' => $this->l('This type will be used for Category images.'), - 'values' => array( - array( - 'id' => 'categories_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'categories_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ), - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Manufacturers'), - 'name' => 'manufacturers', - 'required' => false, - 'is_bool' => true, - 'hint' => $this->l('This type will be used for Manufacturer images.'), - 'values' => array( - array( - 'id' => 'manufacturers_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'manufacturers_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ), - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Suppliers'), - 'name' => 'suppliers', - 'required' => false, - 'is_bool' => true, - 'hint' => $this->l('This type will be used for Supplier images.'), - 'values' => array( - array( - 'id' => 'suppliers_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'suppliers_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ), - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Scenes'), - 'name' => 'scenes', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'hint' => $this->l('This type will be used for Scene images.'), - 'values' => array( - array( - 'id' => 'scenes_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'scenes_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ), - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Stores'), - 'name' => 'stores', - 'required' => false, - 'is_bool' => true, - 'hint' => $this->l('This type will be used for Store images.'), - 'values' => array( - array( - 'id' => 'stores_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'stores_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ), - ) - ), - ), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Image type'), + 'icon' => 'icon-picture' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name for the image type'), + 'name' => 'name', + 'required' => true, + 'hint' => $this->l('Letters, underscores and hyphens only (e.g. "small_custom", "cart_medium", "large", "thickbox_extra-large").') + ), + array( + 'type' => 'text', + 'label' => $this->l('Width'), + 'name' => 'width', + 'required' => true, + 'maxlength' => 5, + 'suffix' => $this->l('pixels'), + 'hint' => $this->l('Maximum image width in pixels.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Height'), + 'name' => 'height', + 'required' => true, + 'maxlength' => 5, + 'suffix' => $this->l('pixels'), + 'hint' => $this->l('Maximum image height in pixels.') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Products'), + 'name' => 'products', + 'required' => false, + 'is_bool' => true, + 'hint' => $this->l('This type will be used for Product images.'), + 'values' => array( + array( + 'id' => 'products_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'products_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ), + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Categories'), + 'name' => 'categories', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'hint' => $this->l('This type will be used for Category images.'), + 'values' => array( + array( + 'id' => 'categories_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'categories_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ), + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Manufacturers'), + 'name' => 'manufacturers', + 'required' => false, + 'is_bool' => true, + 'hint' => $this->l('This type will be used for Manufacturer images.'), + 'values' => array( + array( + 'id' => 'manufacturers_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'manufacturers_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ), + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Suppliers'), + 'name' => 'suppliers', + 'required' => false, + 'is_bool' => true, + 'hint' => $this->l('This type will be used for Supplier images.'), + 'values' => array( + array( + 'id' => 'suppliers_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'suppliers_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ), + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Scenes'), + 'name' => 'scenes', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'hint' => $this->l('This type will be used for Scene images.'), + 'values' => array( + array( + 'id' => 'scenes_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'scenes_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ), + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Stores'), + 'name' => 'stores', + 'required' => false, + 'is_bool' => true, + 'hint' => $this->l('This type will be used for Store images.'), + 'values' => array( + array( + 'id' => 'stores_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'stores_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ), + ) + ), + ), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function postProcess() - { - // When moving images, if duplicate images were found they are moved to a folder named duplicates/ - if (file_exists(_PS_PROD_IMG_DIR_.'duplicates/')) - $this->warnings[] = sprintf($this->l('Duplicate images were found when moving the product images. This is likely caused by unused demonstration images. Please make sure that the folder %s only contains demonstration images, and then delete it.'), _PS_PROD_IMG_DIR_.'duplicates/'); + public function postProcess() + { + // When moving images, if duplicate images were found they are moved to a folder named duplicates/ + if (file_exists(_PS_PROD_IMG_DIR_.'duplicates/')) { + $this->warnings[] = sprintf($this->l('Duplicate images were found when moving the product images. This is likely caused by unused demonstration images. Please make sure that the folder %s only contains demonstration images, and then delete it.'), _PS_PROD_IMG_DIR_.'duplicates/'); + } - if (Tools::isSubmit('submitRegenerate'.$this->table)) - { - if ($this->tabAccess['edit'] === '1') - { - if ($this->_regenerateThumbnails(Tools::getValue('type'), Tools::getValue('erase'))) - Tools::redirectAdmin(self::$currentIndex.'&conf=9'.'&token='.$this->token); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('submitMoveImages'.$this->table)) - { - if ($this->tabAccess['edit'] === '1') - { - if ($this->_moveImagesToNewFileSystem()) - Tools::redirectAdmin(self::$currentIndex.'&conf=25'.'&token='.$this->token); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('submitOptions'.$this->table)) - { - if ($this->tabAccess['edit'] === '1') - { - if ((int)Tools::getValue('PS_JPEG_QUALITY') < 0 - || (int)Tools::getValue('PS_JPEG_QUALITY') > 100) - $this->errors[] = Tools::displayError('Incorrect value for the selected JPEG image compression.'); - elseif ((int)Tools::getValue('PS_PNG_QUALITY') < 0 - || (int)Tools::getValue('PS_PNG_QUALITY') > 9) - $this->errors[] = Tools::displayError('Incorrect value for the selected PNG image compression.'); - elseif (!Configuration::updateValue('PS_IMAGE_QUALITY', Tools::getValue('PS_IMAGE_QUALITY')) - || !Configuration::updateValue('PS_JPEG_QUALITY', Tools::getValue('PS_JPEG_QUALITY')) - || !Configuration::updateValue('PS_PNG_QUALITY', Tools::getValue('PS_PNG_QUALITY'))) - $this->errors[] = Tools::displayError('Unknown error.'); - else - $this->confirmations[] = $this->_conf[6]; - return parent::postProcess(); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - else - return parent::postProcess(); - } + if (Tools::isSubmit('submitRegenerate'.$this->table)) { + if ($this->tabAccess['edit'] === '1') { + if ($this->_regenerateThumbnails(Tools::getValue('type'), Tools::getValue('erase'))) { + Tools::redirectAdmin(self::$currentIndex.'&conf=9'.'&token='.$this->token); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('submitMoveImages'.$this->table)) { + if ($this->tabAccess['edit'] === '1') { + if ($this->_moveImagesToNewFileSystem()) { + Tools::redirectAdmin(self::$currentIndex.'&conf=25'.'&token='.$this->token); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('submitOptions'.$this->table)) { + if ($this->tabAccess['edit'] === '1') { + if ((int)Tools::getValue('PS_JPEG_QUALITY') < 0 + || (int)Tools::getValue('PS_JPEG_QUALITY') > 100) { + $this->errors[] = Tools::displayError('Incorrect value for the selected JPEG image compression.'); + } elseif ((int)Tools::getValue('PS_PNG_QUALITY') < 0 + || (int)Tools::getValue('PS_PNG_QUALITY') > 9) { + $this->errors[] = Tools::displayError('Incorrect value for the selected PNG image compression.'); + } elseif (!Configuration::updateValue('PS_IMAGE_QUALITY', Tools::getValue('PS_IMAGE_QUALITY')) + || !Configuration::updateValue('PS_JPEG_QUALITY', Tools::getValue('PS_JPEG_QUALITY')) + || !Configuration::updateValue('PS_PNG_QUALITY', Tools::getValue('PS_PNG_QUALITY'))) { + $this->errors[] = Tools::displayError('Unknown error.'); + } else { + $this->confirmations[] = $this->_conf[6]; + } + return parent::postProcess(); + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } else { + return parent::postProcess(); + } + } - public static function printEntityActiveIcon($value, $object) - { - return ($value ? '<span class="list-action-enable action-enabled"><i class="icon-check"></i></span>' : '<span class="list-action-enable action-disabled"><i class="icon-remove"></i></span>'); - } + public static function printEntityActiveIcon($value, $object) + { + return ($value ? '<span class="list-action-enable action-enabled"><i class="icon-check"></i></span>' : '<span class="list-action-enable action-disabled"><i class="icon-remove"></i></span>'); + } - protected function _childValidation() - { - if (!Tools::getValue('id_image_type') && Validate::isImageTypeName($typeName = Tools::getValue('name')) && ImageType::typeAlreadyExists($typeName)) - $this->errors[] = Tools::displayError('This name already exists.'); - } + protected function _childValidation() + { + if (!Tools::getValue('id_image_type') && Validate::isImageTypeName($typeName = Tools::getValue('name')) && ImageType::typeAlreadyExists($typeName)) { + $this->errors[] = Tools::displayError('This name already exists.'); + } + } - /** - * Init display for the thumbnails regeneration block - */ - public function initRegenerate() - { - $types = array( - 'categories' => $this->l('Categories'), - 'manufacturers' => $this->l('Manufacturers'), - 'suppliers' => $this->l('Suppliers'), - 'scenes' => $this->l('Scenes'), - 'products' => $this->l('Products'), - 'stores' => $this->l('Stores') - ); + /** + * Init display for the thumbnails regeneration block + */ + public function initRegenerate() + { + $types = array( + 'categories' => $this->l('Categories'), + 'manufacturers' => $this->l('Manufacturers'), + 'suppliers' => $this->l('Suppliers'), + 'scenes' => $this->l('Scenes'), + 'products' => $this->l('Products'), + 'stores' => $this->l('Stores') + ); - $formats = array(); - foreach ($types as $i => $type) - $formats[$i] = ImageType::getImagesTypes($i); + $formats = array(); + foreach ($types as $i => $type) { + $formats[$i] = ImageType::getImagesTypes($i); + } - $this->context->smarty->assign(array( - 'types' => $types, - 'formats' => $formats, - )); - } + $this->context->smarty->assign(array( + 'types' => $types, + 'formats' => $formats, + )); + } - /** - * Delete resized image then regenerate new one with updated settings - * - * @param string $dir - * @param array $type - * @param bool $product - * - * @return bool - */ - protected function _deleteOldImages($dir, $type, $product = false) - { - if (!is_dir($dir)) - return false; - $toDel = scandir($dir); + /** + * Delete resized image then regenerate new one with updated settings + * + * @param string $dir + * @param array $type + * @param bool $product + * + * @return bool + */ + protected function _deleteOldImages($dir, $type, $product = false) + { + if (!is_dir($dir)) { + return false; + } + $toDel = scandir($dir); - foreach ($toDel as $d) - foreach ($type as $imageType) - if (preg_match('/^[0-9]+\-'.($product ? '[0-9]+\-' : '').$imageType['name'].'\.jpg$/', $d) - || (count($type) > 1 && preg_match('/^[0-9]+\-[_a-zA-Z0-9-]*\.jpg$/', $d)) - || preg_match('/^([[:lower:]]{2})\-default\-'.$imageType['name'].'\.jpg$/', $d)) - if (file_exists($dir.$d)) - unlink($dir.$d); + foreach ($toDel as $d) { + foreach ($type as $imageType) { + if (preg_match('/^[0-9]+\-'.($product ? '[0-9]+\-' : '').$imageType['name'].'\.jpg$/', $d) + || (count($type) > 1 && preg_match('/^[0-9]+\-[_a-zA-Z0-9-]*\.jpg$/', $d)) + || preg_match('/^([[:lower:]]{2})\-default\-'.$imageType['name'].'\.jpg$/', $d)) { + if (file_exists($dir.$d)) { + unlink($dir.$d); + } + } + } + } - // delete product images using new filesystem. - if ($product) - { - $productsImages = Image::getAllImages(); - foreach ($productsImages as $image) - { - $imageObj = new Image($image['id_image']); - $imageObj->id_product = $image['id_product']; - if (file_exists($dir.$imageObj->getImgFolder())) - { - $toDel = scandir($dir.$imageObj->getImgFolder()); - foreach ($toDel as $d) - foreach ($type as $imageType) - if (preg_match('/^[0-9]+\-'.$imageType['name'].'\.jpg$/', $d) || (count($type) > 1 && preg_match('/^[0-9]+\-[_a-zA-Z0-9-]*\.jpg$/', $d))) - if (file_exists($dir.$imageObj->getImgFolder().$d)) - unlink($dir.$imageObj->getImgFolder().$d); - } - } - } - } + // delete product images using new filesystem. + if ($product) { + $productsImages = Image::getAllImages(); + foreach ($productsImages as $image) { + $imageObj = new Image($image['id_image']); + $imageObj->id_product = $image['id_product']; + if (file_exists($dir.$imageObj->getImgFolder())) { + $toDel = scandir($dir.$imageObj->getImgFolder()); + foreach ($toDel as $d) { + foreach ($type as $imageType) { + if (preg_match('/^[0-9]+\-'.$imageType['name'].'\.jpg$/', $d) || (count($type) > 1 && preg_match('/^[0-9]+\-[_a-zA-Z0-9-]*\.jpg$/', $d))) { + if (file_exists($dir.$imageObj->getImgFolder().$d)) { + unlink($dir.$imageObj->getImgFolder().$d); + } + } + } + } + } + } + } + } - /** - * Regenerate images - * - * @param $dir - * @param $type - * @param bool $productsImages - * @return bool|string - */ - protected function _regenerateNewImages($dir, $type, $productsImages = false) - { - if (!is_dir($dir)) - return false; + /** + * Regenerate images + * + * @param $dir + * @param $type + * @param bool $productsImages + * @return bool|string + */ + protected function _regenerateNewImages($dir, $type, $productsImages = false) + { + if (!is_dir($dir)) { + return false; + } - $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); + $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); - if (!$productsImages) - { - foreach (scandir($dir) as $image) - if (preg_match('/^[0-9]*\.jpg$/', $image)) - foreach ($type as $k => $imageType) - { - // Customizable writing dir - $newDir = $dir; - if ($imageType['name'] == 'thumb_scene') - $newDir .= 'thumbs/'; - if (!file_exists($newDir)) - continue; - if (!file_exists($newDir.substr($image, 0, -4).'-'.stripslashes($imageType['name']).'.jpg')) - { - if (!file_exists($dir.$image) || !filesize($dir.$image)) - $this->errors[] = sprintf(Tools::displayError('Source file does not exist or is empty (%s)'), $dir.$image); - else - { - if (!ImageManager::resize($dir.$image, $newDir.substr($image, 0, -4).'-'.stripslashes($imageType['name']).'.jpg', (int)$imageType['width'], (int)$imageType['height'])) - $this->errors[] = sprintf(Tools::displayError('Failed to resize image file (%s)'), $dir.$image); + if (!$productsImages) { + foreach (scandir($dir) as $image) { + if (preg_match('/^[0-9]*\.jpg$/', $image)) { + foreach ($type as $k => $imageType) { + // Customizable writing dir + $newDir = $dir; + if ($imageType['name'] == 'thumb_scene') { + $newDir .= 'thumbs/'; + } + if (!file_exists($newDir)) { + continue; + } + if (!file_exists($newDir.substr($image, 0, -4).'-'.stripslashes($imageType['name']).'.jpg')) { + if (!file_exists($dir.$image) || !filesize($dir.$image)) { + $this->errors[] = sprintf(Tools::displayError('Source file does not exist or is empty (%s)'), $dir.$image); + } else { + if (!ImageManager::resize($dir.$image, $newDir.substr($image, 0, -4).'-'.stripslashes($imageType['name']).'.jpg', (int)$imageType['width'], (int)$imageType['height'])) { + $this->errors[] = sprintf(Tools::displayError('Failed to resize image file (%s)'), $dir.$image); + } - if ($generate_hight_dpi_images) - { - if (!ImageManager::resize($dir.$image, $newDir.substr($image, 0, -4).'-'.stripslashes($imageType['name']).'2x.jpg', (int)$imageType['width']*2, (int)$imageType['height']*2)) - $this->errors[] = sprintf(Tools::displayError('Failed to resize image file to high resolution (%s)'), $dir.$image); - } - } - } - if (time() - $this->start_time > $this->max_execution_time - 4) // stop 4 seconds before the timeout, just enough time to process the end of the page on a slow server - return 'timeout'; - } - } - else - { - foreach (Image::getAllImages() as $image) - { - $imageObj = new Image($image['id_image']); - $existing_img = $dir.$imageObj->getExistingImgPath().'.jpg'; - if (file_exists($existing_img) && filesize($existing_img)) - { - foreach ($type as $imageType) - if (!file_exists($dir.$imageObj->getExistingImgPath().'-'.stripslashes($imageType['name']).'.jpg')) - { - if (!ImageManager::resize($existing_img, $dir.$imageObj->getExistingImgPath().'-'.stripslashes($imageType['name']).'.jpg', (int)$imageType['width'], (int)$imageType['height'])) - $this->errors[] = sprintf(Tools::displayError('Original image is corrupt (%s) for product ID %2$d or bad permission on folder'), $existing_img, (int)$imageObj->id_product); + if ($generate_hight_dpi_images) { + if (!ImageManager::resize($dir.$image, $newDir.substr($image, 0, -4).'-'.stripslashes($imageType['name']).'2x.jpg', (int)$imageType['width']*2, (int)$imageType['height']*2)) { + $this->errors[] = sprintf(Tools::displayError('Failed to resize image file to high resolution (%s)'), $dir.$image); + } + } + } + } + if (time() - $this->start_time > $this->max_execution_time - 4) { // stop 4 seconds before the timeout, just enough time to process the end of the page on a slow server + return 'timeout'; + } + } + } + } + } else { + foreach (Image::getAllImages() as $image) { + $imageObj = new Image($image['id_image']); + $existing_img = $dir.$imageObj->getExistingImgPath().'.jpg'; + if (file_exists($existing_img) && filesize($existing_img)) { + foreach ($type as $imageType) { + if (!file_exists($dir.$imageObj->getExistingImgPath().'-'.stripslashes($imageType['name']).'.jpg')) { + if (!ImageManager::resize($existing_img, $dir.$imageObj->getExistingImgPath().'-'.stripslashes($imageType['name']).'.jpg', (int)$imageType['width'], (int)$imageType['height'])) { + $this->errors[] = sprintf(Tools::displayError('Original image is corrupt (%s) for product ID %2$d or bad permission on folder'), $existing_img, (int)$imageObj->id_product); + } - if ($generate_hight_dpi_images) - { - if (!ImageManager::resize($existing_img, $dir.$imageObj->getExistingImgPath().'-'.stripslashes($imageType['name']).'2x.jpg', (int)$imageType['width']*2, (int)$imageType['height']*2)) - $this->errors[] = sprintf(Tools::displayError('Original image is corrupt (%s) for product ID %2$d or bad permission on folder'), $existing_img, (int)$imageObj->id_product); - } - } - } - else - $this->errors[] = sprintf(Tools::displayError('Original image is missing or empty (%1$s) for product ID %2$d'), $existing_img, (int)$imageObj->id_product); - if (time() - $this->start_time > $this->max_execution_time - 4) // stop 4 seconds before the tiemout, just enough time to process the end of the page on a slow server - return 'timeout'; - } - } + if ($generate_hight_dpi_images) { + if (!ImageManager::resize($existing_img, $dir.$imageObj->getExistingImgPath().'-'.stripslashes($imageType['name']).'2x.jpg', (int)$imageType['width']*2, (int)$imageType['height']*2)) { + $this->errors[] = sprintf(Tools::displayError('Original image is corrupt (%s) for product ID %2$d or bad permission on folder'), $existing_img, (int)$imageObj->id_product); + } + } + } + } + } else { + $this->errors[] = sprintf(Tools::displayError('Original image is missing or empty (%1$s) for product ID %2$d'), $existing_img, (int)$imageObj->id_product); + } + if (time() - $this->start_time > $this->max_execution_time - 4) { // stop 4 seconds before the tiemout, just enough time to process the end of the page on a slow server + return 'timeout'; + } + } + } - return (bool)count($this->errors); - } + return (bool)count($this->errors); + } - /** - * Regenerate no-pictures images - * - * @param $dir - * @param $type - * @param $languages - * @return bool - */ - protected function _regenerateNoPictureImages($dir, $type, $languages) - { - $errors = false; - $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); + /** + * Regenerate no-pictures images + * + * @param $dir + * @param $type + * @param $languages + * @return bool + */ + protected function _regenerateNoPictureImages($dir, $type, $languages) + { + $errors = false; + $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); - foreach ($type as $image_type) - foreach ($languages as $language) - { - $file = $dir.$language['iso_code'].'.jpg'; - if (!file_exists($file)) - $file = _PS_PROD_IMG_DIR_.Language::getIsoById((int)Configuration::get('PS_LANG_DEFAULT')).'.jpg'; - if (!file_exists($dir.$language['iso_code'].'-default-'.stripslashes($image_type['name']).'.jpg')) - { - if (!ImageManager::resize($file, $dir.$language['iso_code'].'-default-'.stripslashes($image_type['name']).'.jpg', (int)$image_type['width'], (int)$image_type['height'])) - $errors = true; + foreach ($type as $image_type) { + foreach ($languages as $language) { + $file = $dir.$language['iso_code'].'.jpg'; + if (!file_exists($file)) { + $file = _PS_PROD_IMG_DIR_.Language::getIsoById((int)Configuration::get('PS_LANG_DEFAULT')).'.jpg'; + } + if (!file_exists($dir.$language['iso_code'].'-default-'.stripslashes($image_type['name']).'.jpg')) { + if (!ImageManager::resize($file, $dir.$language['iso_code'].'-default-'.stripslashes($image_type['name']).'.jpg', (int)$image_type['width'], (int)$image_type['height'])) { + $errors = true; + } - if ($generate_hight_dpi_images) - if (!ImageManager::resize($file, $dir.$language['iso_code'].'-default-'.stripslashes($image_type['name']).'2x.jpg', (int)$image_type['width']*2, (int)$image_type['height']*2)) - $errors = true; - } - } - return $errors; - } + if ($generate_hight_dpi_images) { + if (!ImageManager::resize($file, $dir.$language['iso_code'].'-default-'.stripslashes($image_type['name']).'2x.jpg', (int)$image_type['width']*2, (int)$image_type['height']*2)) { + $errors = true; + } + } + } + } + } + return $errors; + } - /* Hook watermark optimization */ - protected function _regenerateWatermark($dir, $type = null) - { - $result = Db::getInstance()->executeS(' + /* Hook watermark optimization */ + protected function _regenerateWatermark($dir, $type = null) + { + $result = Db::getInstance()->executeS(' SELECT m.`name` FROM `'._DB_PREFIX_.'module` m LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_module` = m.`id_module` LEFT JOIN `'._DB_PREFIX_.'hook` h ON hm.`id_hook` = h.`id_hook` WHERE h.`name` = \'actionWatermark\' AND m.`active` = 1'); - if ($result && count($result)) - { - $productsImages = Image::getAllImages(); - foreach ($productsImages as $image) - { - $imageObj = new Image($image['id_image']); - if (file_exists($dir.$imageObj->getExistingImgPath().'.jpg')) - foreach ($result as $module) - { - $moduleInstance = Module::getInstanceByName($module['name']); - if ($moduleInstance && is_callable(array($moduleInstance, 'hookActionWatermark'))) - call_user_func(array($moduleInstance, 'hookActionWatermark'), array('id_image' => $imageObj->id, 'id_product' => $imageObj->id_product, 'image_type' => $type)); + if ($result && count($result)) { + $productsImages = Image::getAllImages(); + foreach ($productsImages as $image) { + $imageObj = new Image($image['id_image']); + if (file_exists($dir.$imageObj->getExistingImgPath().'.jpg')) { + foreach ($result as $module) { + $moduleInstance = Module::getInstanceByName($module['name']); + if ($moduleInstance && is_callable(array($moduleInstance, 'hookActionWatermark'))) { + call_user_func(array($moduleInstance, 'hookActionWatermark'), array('id_image' => $imageObj->id, 'id_product' => $imageObj->id_product, 'image_type' => $type)); + } - if (time() - $this->start_time > $this->max_execution_time - 4) // stop 4 seconds before the tiemout, just enough time to process the end of the page on a slow server - return 'timeout'; - } - } - } - } + if (time() - $this->start_time > $this->max_execution_time - 4) { // stop 4 seconds before the tiemout, just enough time to process the end of the page on a slow server + return 'timeout'; + } + } + } + } + } + } - protected function _regenerateThumbnails($type = 'all', $deleteOldImages = false) - { - $this->start_time = time(); - ini_set('max_execution_time', $this->max_execution_time); // ini_set may be disabled, we need the real value - $this->max_execution_time = (int)ini_get('max_execution_time'); - $languages = Language::getLanguages(false); + protected function _regenerateThumbnails($type = 'all', $deleteOldImages = false) + { + $this->start_time = time(); + ini_set('max_execution_time', $this->max_execution_time); // ini_set may be disabled, we need the real value + $this->max_execution_time = (int)ini_get('max_execution_time'); + $languages = Language::getLanguages(false); - $process = array( - array('type' => 'categories', 'dir' => _PS_CAT_IMG_DIR_), - array('type' => 'manufacturers', 'dir' => _PS_MANU_IMG_DIR_), - array('type' => 'suppliers', 'dir' => _PS_SUPP_IMG_DIR_), - array('type' => 'scenes', 'dir' => _PS_SCENE_IMG_DIR_), - array('type' => 'products', 'dir' => _PS_PROD_IMG_DIR_), - array('type' => 'stores', 'dir' => _PS_STORE_IMG_DIR_) - ); + $process = array( + array('type' => 'categories', 'dir' => _PS_CAT_IMG_DIR_), + array('type' => 'manufacturers', 'dir' => _PS_MANU_IMG_DIR_), + array('type' => 'suppliers', 'dir' => _PS_SUPP_IMG_DIR_), + array('type' => 'scenes', 'dir' => _PS_SCENE_IMG_DIR_), + array('type' => 'products', 'dir' => _PS_PROD_IMG_DIR_), + array('type' => 'stores', 'dir' => _PS_STORE_IMG_DIR_) + ); - // Launching generation process - foreach ($process as $proc) - { - if ($type != 'all' && $type != $proc['type']) - continue; + // Launching generation process + foreach ($process as $proc) { + if ($type != 'all' && $type != $proc['type']) { + continue; + } - // Getting format generation - $formats = ImageType::getImagesTypes($proc['type']); - if ($type != 'all') - { - $format = strval(Tools::getValue('format_'.$type)); - if ($format != 'all') - foreach ($formats as $k => $form) - if ($form['id_image_type'] != $format) - unset($formats[$k]); - } + // Getting format generation + $formats = ImageType::getImagesTypes($proc['type']); + if ($type != 'all') { + $format = strval(Tools::getValue('format_'.$type)); + if ($format != 'all') { + foreach ($formats as $k => $form) { + if ($form['id_image_type'] != $format) { + unset($formats[$k]); + } + } + } + } - if ($deleteOldImages) - $this->_deleteOldImages($proc['dir'], $formats, ($proc['type'] == 'products' ? true : false)); - if (($return = $this->_regenerateNewImages($proc['dir'], $formats, ($proc['type'] == 'products' ? true : false))) === true) - { - if (!count($this->errors)) - $this->errors[] = sprintf(Tools::displayError('Cannot write images for this type: %s. Please check the %s folder\'s writing permissions.'), $proc['type'], $proc['dir']); - } - elseif ($return == 'timeout') - $this->errors[] = Tools::displayError('Only part of the images have been regenerated. The server timed out before finishing.'); - else - { - if ($proc['type'] == 'products') - if ($this->_regenerateWatermark($proc['dir'], $formats) == 'timeout') - $this->errors[] = Tools::displayError('Server timed out. The watermark may not have been applied to all images.'); - if (!count($this->errors)) - if ($this->_regenerateNoPictureImages($proc['dir'], $formats, $languages)) - $this->errors[] = sprintf(Tools::displayError('Cannot write "No picture" image to (%s) images folder. Please check the folder\'s writing permissions.'), $proc['type']); - } - } - return (count($this->errors) > 0 ? false : true); - } + if ($deleteOldImages) { + $this->_deleteOldImages($proc['dir'], $formats, ($proc['type'] == 'products' ? true : false)); + } + if (($return = $this->_regenerateNewImages($proc['dir'], $formats, ($proc['type'] == 'products' ? true : false))) === true) { + if (!count($this->errors)) { + $this->errors[] = sprintf(Tools::displayError('Cannot write images for this type: %s. Please check the %s folder\'s writing permissions.'), $proc['type'], $proc['dir']); + } + } elseif ($return == 'timeout') { + $this->errors[] = Tools::displayError('Only part of the images have been regenerated. The server timed out before finishing.'); + } else { + if ($proc['type'] == 'products') { + if ($this->_regenerateWatermark($proc['dir'], $formats) == 'timeout') { + $this->errors[] = Tools::displayError('Server timed out. The watermark may not have been applied to all images.'); + } + } + if (!count($this->errors)) { + if ($this->_regenerateNoPictureImages($proc['dir'], $formats, $languages)) { + $this->errors[] = sprintf(Tools::displayError('Cannot write "No picture" image to (%s) images folder. Please check the folder\'s writing permissions.'), $proc['type']); + } + } + } + } + return (count($this->errors) > 0 ? false : true); + } - /** - * Init display for move images block - */ - public function initMoveImages() - { - $this->context->smarty->assign(array( - 'safe_mode' => Tools::getSafeModeStatus(), - 'link_ppreferences' => 'index.php?tab=AdminPPreferences&token='.Tools::getAdminTokenLite('AdminPPreferences').'#PS_LEGACY_IMAGES_on', - )); - } + /** + * Init display for move images block + */ + public function initMoveImages() + { + $this->context->smarty->assign(array( + 'safe_mode' => Tools::getSafeModeStatus(), + 'link_ppreferences' => 'index.php?tab=AdminPPreferences&token='.Tools::getAdminTokenLite('AdminPPreferences').'#PS_LEGACY_IMAGES_on', + )); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_image_type'] = array( - 'href' => self::$currentIndex.'&addimage_type&token='.$this->token, - 'desc' => $this->l('Add new image type', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_image_type'] = array( + 'href' => self::$currentIndex.'&addimage_type&token='.$this->token, + 'desc' => $this->l('Add new image type', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - /** - * Move product images to the new filesystem - */ - protected function _moveImagesToNewFileSystem() - { - if (!Image::testFileSystem()) - $this->errors[] = Tools::displayError('Error: Your server configuration is not compatible with the new image system. No images were moved.'); - else - { - ini_set('max_execution_time', $this->max_execution_time); // ini_set may be disabled, we need the real value - $this->max_execution_time = (int)ini_get('max_execution_time'); - $result = Image::moveToNewFileSystem($this->max_execution_time); - if ($result === 'timeout') - $this->errors[] = Tools::displayError('Not all images have been moved. The server timed out before finishing. Click on "Move images" again to resume the moving process.'); - elseif ($result === false) - $this->errors[] = Tools::displayError('Error: Some -- or all -- images cannot be moved.'); - } - return (count($this->errors) > 0 ? false : true); - } + /** + * Move product images to the new filesystem + */ + protected function _moveImagesToNewFileSystem() + { + if (!Image::testFileSystem()) { + $this->errors[] = Tools::displayError('Error: Your server configuration is not compatible with the new image system. No images were moved.'); + } else { + ini_set('max_execution_time', $this->max_execution_time); // ini_set may be disabled, we need the real value + $this->max_execution_time = (int)ini_get('max_execution_time'); + $result = Image::moveToNewFileSystem($this->max_execution_time); + if ($result === 'timeout') { + $this->errors[] = Tools::displayError('Not all images have been moved. The server timed out before finishing. Click on "Move images" again to resume the moving process.'); + } elseif ($result === false) { + $this->errors[] = Tools::displayError('Error: Some -- or all -- images cannot be moved.'); + } + } + return (count($this->errors) > 0 ? false : true); + } - public function initContent() - { - if ($this->display != 'edit' && $this->display != 'add') - { - $this->initRegenerate(); - $this->initMoveImages(); + public function initContent() + { + if ($this->display != 'edit' && $this->display != 'add') { + $this->initRegenerate(); + $this->initMoveImages(); - $this->context->smarty->assign(array( - 'display_regenerate' => true, - 'display_move' => $this->display_move - )); - } + $this->context->smarty->assign(array( + 'display_regenerate' => true, + 'display_move' => $this->display_move + )); + } - if ($this->display == 'edit') - $this->warnings[] = $this->l('After modification, do not forget to regenerate thumbnails'); + if ($this->display == 'edit') { + $this->warnings[] = $this->l('After modification, do not forget to regenerate thumbnails'); + } - parent::initContent(); - } + parent::initContent(); + } } diff --git a/controllers/admin/AdminImportController.php b/controllers/admin/AdminImportController.php index 4aaa5fd1..923745ed 100644 --- a/controllers/admin/AdminImportController.php +++ b/controllers/admin/AdminImportController.php @@ -39,3535 +39,3568 @@ define('MAX_COLUMNS', 6); class AdminImportControllerCore extends AdminController { - public static $column_mask; + public static $column_mask; - public $entities = array(); + public $entities = array(); - public $available_fields = array(); + public $available_fields = array(); - public $required_fields = array(); + public $required_fields = array(); - public $cache_image_deleted = array(); + public $cache_image_deleted = array(); - public static $default_values = array(); + public static $default_values = array(); - public static $validators = array( - 'active' => array('AdminImportController', 'getBoolean'), - 'tax_rate' => array('AdminImportController', 'getPrice'), - /** Tax excluded */ - 'price_tex' => array('AdminImportController', 'getPrice'), - /** Tax included */ - 'price_tin' => array('AdminImportController', 'getPrice'), - 'reduction_price' => array('AdminImportController', 'getPrice'), - 'reduction_percent' => array('AdminImportController', 'getPrice'), - 'wholesale_price' => array('AdminImportController', 'getPrice'), - 'ecotax' => array('AdminImportController', 'getPrice'), - 'name' => array('AdminImportController', 'createMultiLangField'), - 'description' => array('AdminImportController', 'createMultiLangField'), - 'description_short' => array('AdminImportController', 'createMultiLangField'), - 'meta_title' => array('AdminImportController', 'createMultiLangField'), - 'meta_keywords' => array('AdminImportController', 'createMultiLangField'), - 'meta_description' => array('AdminImportController', 'createMultiLangField'), - 'link_rewrite' => array('AdminImportController', 'createMultiLangField'), - 'available_now' => array('AdminImportController', 'createMultiLangField'), - 'available_later' => array('AdminImportController', 'createMultiLangField'), - 'category' => array('AdminImportController', 'split'), - 'online_only' => array('AdminImportController', 'getBoolean'), - ); + public static $validators = array( + 'active' => array('AdminImportController', 'getBoolean'), + 'tax_rate' => array('AdminImportController', 'getPrice'), + /** Tax excluded */ + 'price_tex' => array('AdminImportController', 'getPrice'), + /** Tax included */ + 'price_tin' => array('AdminImportController', 'getPrice'), + 'reduction_price' => array('AdminImportController', 'getPrice'), + 'reduction_percent' => array('AdminImportController', 'getPrice'), + 'wholesale_price' => array('AdminImportController', 'getPrice'), + 'ecotax' => array('AdminImportController', 'getPrice'), + 'name' => array('AdminImportController', 'createMultiLangField'), + 'description' => array('AdminImportController', 'createMultiLangField'), + 'description_short' => array('AdminImportController', 'createMultiLangField'), + 'meta_title' => array('AdminImportController', 'createMultiLangField'), + 'meta_keywords' => array('AdminImportController', 'createMultiLangField'), + 'meta_description' => array('AdminImportController', 'createMultiLangField'), + 'link_rewrite' => array('AdminImportController', 'createMultiLangField'), + 'available_now' => array('AdminImportController', 'createMultiLangField'), + 'available_later' => array('AdminImportController', 'createMultiLangField'), + 'category' => array('AdminImportController', 'split'), + 'online_only' => array('AdminImportController', 'getBoolean'), + ); - public $separator; - public $multiple_value_separator; + public $separator; + public $multiple_value_separator; - public function __construct() - { - $this->bootstrap = true; - $this->entities = array( - $this->l('Categories'), - $this->l('Products'), - $this->l('Combinations'), - $this->l('Customers'), - $this->l('Addresses'), - $this->l('Manufacturers'), - $this->l('Suppliers'), - $this->l('Alias'), - ); + public function __construct() + { + $this->bootstrap = true; + $this->entities = array( + $this->l('Categories'), + $this->l('Products'), + $this->l('Combinations'), + $this->l('Customers'), + $this->l('Addresses'), + $this->l('Manufacturers'), + $this->l('Suppliers'), + $this->l('Alias'), + ); - // @since 1.5.0 - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->entities = array_merge( - $this->entities, - array( - $this->l('Supply Orders'), - $this->l('Supply Order Details'), - ) - ); - } + // @since 1.5.0 + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->entities = array_merge( + $this->entities, + array( + $this->l('Supply Orders'), + $this->l('Supply Order Details'), + ) + ); + } - $this->entities = array_flip($this->entities); + $this->entities = array_flip($this->entities); - switch ((int)Tools::getValue('entity')) - { - case $this->entities[$this->l('Combinations')]: - $this->required_fields = array( - 'group', - 'attribute' - ); + switch ((int)Tools::getValue('entity')) { + case $this->entities[$this->l('Combinations')]: + $this->required_fields = array( + 'group', + 'attribute' + ); - $this->available_fields = array( - 'no' => array('label' => $this->l('Ignore this column')), - 'id_product' => array('label' => $this->l('Product ID')), - 'product_reference' => array('label' => $this->l('Product Reference')), - 'group' => array( - 'label' => $this->l('Attribute (Name:Type:Position)').'*' - ), - 'attribute' => array( - 'label' => $this->l('Value (Value:Position)').'*' - ), - 'supplier_reference' => array('label' => $this->l('Supplier reference')), - 'reference' => array('label' => $this->l('Reference')), - 'ean13' => array('label' => $this->l('EAN13')), - 'upc' => array('label' => $this->l('UPC')), - 'wholesale_price' => array('label' => $this->l('Wholesale price')), - 'price' => array('label' => $this->l('Impact on price')), - 'ecotax' => array('label' => $this->l('Ecotax')), - 'quantity' => array('label' => $this->l('Quantity')), - 'minimal_quantity' => array('label' => $this->l('Minimal quantity')), - 'weight' => array('label' => $this->l('Impact on weight')), - 'default_on' => array('label' => $this->l('Default (0 = No, 1 = Yes)')), - 'available_date' => array('label' => $this->l('Combination availability date')), - 'image_position' => array( - 'label' => $this->l('Choose among product images by position (1,2,3...)') - ), - 'image_url' => array('label' => $this->l('Image URLs (x,y,z...)')), - 'delete_existing_images' => array( - 'label' => $this->l('Delete existing images (0 = No, 1 = Yes).') - ), - 'shop' => array( - 'label' => $this->l('ID / Name of shop'), - 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'), - ), - 'advanced_stock_management' => array( - 'label' => $this->l('Advanced Stock Management'), - 'help' => $this->l('Enable Advanced Stock Management on product (0 = No, 1 = Yes)') - ), - 'depends_on_stock' => array( - 'label' => $this->l('Depends on stock'), - 'help' => $this->l('0 = Use quantity set in product, 1 = Use quantity from warehouse.') - ), - 'warehouse' => array( - 'label' => $this->l('Warehouse'), - 'help' => $this->l('ID of the warehouse to set as storage.') - ), - ); + $this->available_fields = array( + 'no' => array('label' => $this->l('Ignore this column')), + 'id_product' => array('label' => $this->l('Product ID')), + 'product_reference' => array('label' => $this->l('Product Reference')), + 'group' => array( + 'label' => $this->l('Attribute (Name:Type:Position)').'*' + ), + 'attribute' => array( + 'label' => $this->l('Value (Value:Position)').'*' + ), + 'supplier_reference' => array('label' => $this->l('Supplier reference')), + 'reference' => array('label' => $this->l('Reference')), + 'ean13' => array('label' => $this->l('EAN13')), + 'upc' => array('label' => $this->l('UPC')), + 'wholesale_price' => array('label' => $this->l('Wholesale price')), + 'price' => array('label' => $this->l('Impact on price')), + 'ecotax' => array('label' => $this->l('Ecotax')), + 'quantity' => array('label' => $this->l('Quantity')), + 'minimal_quantity' => array('label' => $this->l('Minimal quantity')), + 'weight' => array('label' => $this->l('Impact on weight')), + 'default_on' => array('label' => $this->l('Default (0 = No, 1 = Yes)')), + 'available_date' => array('label' => $this->l('Combination availability date')), + 'image_position' => array( + 'label' => $this->l('Choose among product images by position (1,2,3...)') + ), + 'image_url' => array('label' => $this->l('Image URLs (x,y,z...)')), + 'delete_existing_images' => array( + 'label' => $this->l('Delete existing images (0 = No, 1 = Yes).') + ), + 'shop' => array( + 'label' => $this->l('ID / Name of shop'), + 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'), + ), + 'advanced_stock_management' => array( + 'label' => $this->l('Advanced Stock Management'), + 'help' => $this->l('Enable Advanced Stock Management on product (0 = No, 1 = Yes)') + ), + 'depends_on_stock' => array( + 'label' => $this->l('Depends on stock'), + 'help' => $this->l('0 = Use quantity set in product, 1 = Use quantity from warehouse.') + ), + 'warehouse' => array( + 'label' => $this->l('Warehouse'), + 'help' => $this->l('ID of the warehouse to set as storage.') + ), + ); - self::$default_values = array( - 'reference' => '', - 'supplier_reference' => '', - 'ean13' => '', - 'upc' => '', - 'wholesale_price' => 0, - 'price' => 0, - 'ecotax' => 0, - 'quantity' => 0, - 'minimal_quantity' => 1, - 'weight' => 0, - 'default_on' => 0, - 'advanced_stock_management' => 0, - 'depends_on_stock' => 0, - 'available_date' => date('Y-m-d') - ); - break; + self::$default_values = array( + 'reference' => '', + 'supplier_reference' => '', + 'ean13' => '', + 'upc' => '', + 'wholesale_price' => 0, + 'price' => 0, + 'ecotax' => 0, + 'quantity' => 0, + 'minimal_quantity' => 1, + 'weight' => 0, + 'default_on' => 0, + 'advanced_stock_management' => 0, + 'depends_on_stock' => 0, + 'available_date' => date('Y-m-d') + ); + break; - case $this->entities[$this->l('Categories')]: - $this->available_fields = array( - 'no' => array('label' => $this->l('Ignore this column')), - 'id' => array('label' => $this->l('ID')), - 'active' => array('label' => $this->l('Active (0/1)')), - 'name' => array('label' => $this->l('Name')), - 'parent' => array('label' => $this->l('Parent category')), - 'is_root_category' => array( - 'label' => $this->l('Root category (0/1)'), - 'help' => $this->l('A category root is where a category tree can begin. This is used with multistore.') - ), - 'description' => array('label' => $this->l('Description')), - 'meta_title' => array('label' => $this->l('Meta title')), - 'meta_keywords' => array('label' => $this->l('Meta keywords')), - 'meta_description' => array('label' => $this->l('Meta description')), - 'link_rewrite' => array('label' => $this->l('URL rewritten')), - 'image' => array('label' => $this->l('Image URL')), - 'shop' => array( - 'label' => $this->l('ID / Name of shop'), - 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'), - ), - ); + case $this->entities[$this->l('Categories')]: + $this->available_fields = array( + 'no' => array('label' => $this->l('Ignore this column')), + 'id' => array('label' => $this->l('ID')), + 'active' => array('label' => $this->l('Active (0/1)')), + 'name' => array('label' => $this->l('Name')), + 'parent' => array('label' => $this->l('Parent category')), + 'is_root_category' => array( + 'label' => $this->l('Root category (0/1)'), + 'help' => $this->l('A category root is where a category tree can begin. This is used with multistore.') + ), + 'description' => array('label' => $this->l('Description')), + 'meta_title' => array('label' => $this->l('Meta title')), + 'meta_keywords' => array('label' => $this->l('Meta keywords')), + 'meta_description' => array('label' => $this->l('Meta description')), + 'link_rewrite' => array('label' => $this->l('URL rewritten')), + 'image' => array('label' => $this->l('Image URL')), + 'shop' => array( + 'label' => $this->l('ID / Name of shop'), + 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'), + ), + ); - self::$default_values = array( - 'active' => '1', - 'parent' => Configuration::get('PS_HOME_CATEGORY'), - 'link_rewrite' => '' - ); - break; + self::$default_values = array( + 'active' => '1', + 'parent' => Configuration::get('PS_HOME_CATEGORY'), + 'link_rewrite' => '' + ); + break; - case $this->entities[$this->l('Products')]: - self::$validators['image'] = array( - 'AdminImportController', - 'split' - ); + case $this->entities[$this->l('Products')]: + self::$validators['image'] = array( + 'AdminImportController', + 'split' + ); - $this->available_fields = array( - 'no' => array('label' => $this->l('Ignore this column')), - 'id' => array('label' => $this->l('ID')), - 'active' => array('label' => $this->l('Active (0/1)')), - 'name' => array('label' => $this->l('Name')), - 'category' => array('label' => $this->l('Categories (x,y,z...)')), - 'price_tex' => array('label' => $this->l('Price tax excluded')), - 'price_tin' => array('label' => $this->l('Price tax included')), - 'id_tax_rules_group' => array('label' => $this->l('Tax rules ID')), - 'wholesale_price' => array('label' => $this->l('Wholesale price')), - 'on_sale' => array('label' => $this->l('On sale (0/1)')), - 'reduction_price' => array('label' => $this->l('Discount amount')), - 'reduction_percent' => array('label' => $this->l('Discount percent')), - 'reduction_from' => array('label' => $this->l('Discount from (yyyy-mm-dd)')), - 'reduction_to' => array('label' => $this->l('Discount to (yyyy-mm-dd)')), - 'reference' => array('label' => $this->l('Reference #')), - 'supplier_reference' => array('label' => $this->l('Supplier reference #')), - 'supplier' => array('label' => $this->l('Supplier')), - 'manufacturer' => array('label' => $this->l('Manufacturer')), - 'ean13' => array('label' => $this->l('EAN13')), - 'upc' => array('label' => $this->l('UPC')), - 'ecotax' => array('label' => $this->l('Ecotax')), - 'width' => array('label' => $this->l('Width')), - 'height' => array('label' => $this->l('Height')), - 'depth' => array('label' => $this->l('Depth')), - 'weight' => array('label' => $this->l('Weight')), - 'quantity' => array('label' => $this->l('Quantity')), - 'minimal_quantity' => array('label' => $this->l('Minimal quantity')), - 'visibility' => array('label' => $this->l('Visibility')), - 'additional_shipping_cost' => array('label' => $this->l('Additional shipping cost')), - 'unity' => array('label' => $this->l('Unit for the unit price')), - 'unit_price' => array('label' => $this->l('Unit price')), - 'description_short' => array('label' => $this->l('Short description')), - 'description' => array('label' => $this->l('Description')), - 'tags' => array('label' => $this->l('Tags (x,y,z...)')), - 'meta_title' => array('label' => $this->l('Meta title')), - 'meta_keywords' => array('label' => $this->l('Meta keywords')), - 'meta_description' => array('label' => $this->l('Meta description')), - 'link_rewrite' => array('label' => $this->l('URL rewritten')), - 'available_now' => array('label' => $this->l('Text when in stock')), - 'available_later' => array('label' => $this->l('Text when backorder allowed')), - 'available_for_order' => array('label' => $this->l('Available for order (0 = No, 1 = Yes)')), - 'available_date' => array('label' => $this->l('Product availability date')), - 'date_add' => array('label' => $this->l('Product creation date')), - 'show_price' => array('label' => $this->l('Show price (0 = No, 1 = Yes)')), - 'image' => array('label' => $this->l('Image URLs (x,y,z...)')), - 'delete_existing_images' => array( - 'label' => $this->l('Delete existing images (0 = No, 1 = Yes)') - ), - 'features' => array('label' => $this->l('Feature (Name:Value:Position:Customized)')), - 'online_only' => array('label' => $this->l('Available online only (0 = No, 1 = Yes)')), - 'condition' => array('label' => $this->l('Condition')), - 'customizable' => array('label' => $this->l('Customizable (0 = No, 1 = Yes)')), - 'uploadable_files' => array('label' => $this->l('Uploadable files (0 = No, 1 = Yes)')), - 'text_fields' => array('label' => $this->l('Text fields (0 = No, 1 = Yes)')), - 'out_of_stock' => array('label' => $this->l('Action when out of stock')), - 'shop' => array( - 'label' => $this->l('ID / Name of shop'), - 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'), - ), - 'advanced_stock_management' => array( - 'label' => $this->l('Advanced Stock Management'), - 'help' => $this->l('Enable Advanced Stock Management on product (0 = No, 1 = Yes).') - ), - 'depends_on_stock' => array( - 'label' => $this->l('Depends on stock'), - 'help' => $this->l('0 = Use quantity set in product, 1 = Use quantity from warehouse.') - ), - 'warehouse' => array( - 'label' => $this->l('Warehouse'), - 'help' => $this->l('ID of the warehouse to set as storage.') - ), - ); + $this->available_fields = array( + 'no' => array('label' => $this->l('Ignore this column')), + 'id' => array('label' => $this->l('ID')), + 'active' => array('label' => $this->l('Active (0/1)')), + 'name' => array('label' => $this->l('Name')), + 'category' => array('label' => $this->l('Categories (x,y,z...)')), + 'price_tex' => array('label' => $this->l('Price tax excluded')), + 'price_tin' => array('label' => $this->l('Price tax included')), + 'id_tax_rules_group' => array('label' => $this->l('Tax rules ID')), + 'wholesale_price' => array('label' => $this->l('Wholesale price')), + 'on_sale' => array('label' => $this->l('On sale (0/1)')), + 'reduction_price' => array('label' => $this->l('Discount amount')), + 'reduction_percent' => array('label' => $this->l('Discount percent')), + 'reduction_from' => array('label' => $this->l('Discount from (yyyy-mm-dd)')), + 'reduction_to' => array('label' => $this->l('Discount to (yyyy-mm-dd)')), + 'reference' => array('label' => $this->l('Reference #')), + 'supplier_reference' => array('label' => $this->l('Supplier reference #')), + 'supplier' => array('label' => $this->l('Supplier')), + 'manufacturer' => array('label' => $this->l('Manufacturer')), + 'ean13' => array('label' => $this->l('EAN13')), + 'upc' => array('label' => $this->l('UPC')), + 'ecotax' => array('label' => $this->l('Ecotax')), + 'width' => array('label' => $this->l('Width')), + 'height' => array('label' => $this->l('Height')), + 'depth' => array('label' => $this->l('Depth')), + 'weight' => array('label' => $this->l('Weight')), + 'quantity' => array('label' => $this->l('Quantity')), + 'minimal_quantity' => array('label' => $this->l('Minimal quantity')), + 'visibility' => array('label' => $this->l('Visibility')), + 'additional_shipping_cost' => array('label' => $this->l('Additional shipping cost')), + 'unity' => array('label' => $this->l('Unit for the unit price')), + 'unit_price' => array('label' => $this->l('Unit price')), + 'description_short' => array('label' => $this->l('Short description')), + 'description' => array('label' => $this->l('Description')), + 'tags' => array('label' => $this->l('Tags (x,y,z...)')), + 'meta_title' => array('label' => $this->l('Meta title')), + 'meta_keywords' => array('label' => $this->l('Meta keywords')), + 'meta_description' => array('label' => $this->l('Meta description')), + 'link_rewrite' => array('label' => $this->l('URL rewritten')), + 'available_now' => array('label' => $this->l('Text when in stock')), + 'available_later' => array('label' => $this->l('Text when backorder allowed')), + 'available_for_order' => array('label' => $this->l('Available for order (0 = No, 1 = Yes)')), + 'available_date' => array('label' => $this->l('Product availability date')), + 'date_add' => array('label' => $this->l('Product creation date')), + 'show_price' => array('label' => $this->l('Show price (0 = No, 1 = Yes)')), + 'image' => array('label' => $this->l('Image URLs (x,y,z...)')), + 'delete_existing_images' => array( + 'label' => $this->l('Delete existing images (0 = No, 1 = Yes)') + ), + 'features' => array('label' => $this->l('Feature (Name:Value:Position:Customized)')), + 'online_only' => array('label' => $this->l('Available online only (0 = No, 1 = Yes)')), + 'condition' => array('label' => $this->l('Condition')), + 'customizable' => array('label' => $this->l('Customizable (0 = No, 1 = Yes)')), + 'uploadable_files' => array('label' => $this->l('Uploadable files (0 = No, 1 = Yes)')), + 'text_fields' => array('label' => $this->l('Text fields (0 = No, 1 = Yes)')), + 'out_of_stock' => array('label' => $this->l('Action when out of stock')), + 'shop' => array( + 'label' => $this->l('ID / Name of shop'), + 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'), + ), + 'advanced_stock_management' => array( + 'label' => $this->l('Advanced Stock Management'), + 'help' => $this->l('Enable Advanced Stock Management on product (0 = No, 1 = Yes).') + ), + 'depends_on_stock' => array( + 'label' => $this->l('Depends on stock'), + 'help' => $this->l('0 = Use quantity set in product, 1 = Use quantity from warehouse.') + ), + 'warehouse' => array( + 'label' => $this->l('Warehouse'), + 'help' => $this->l('ID of the warehouse to set as storage.') + ), + ); - self::$default_values = array( - 'id_category' => array((int)Configuration::get('PS_HOME_CATEGORY')), - 'id_category_default' => null, - 'active' => '1', - 'width' => 0.000000, - 'height' => 0.000000, - 'depth' => 0.000000, - 'weight' => 0.000000, - 'visibility' => 'both', - 'additional_shipping_cost' => 0.00, - 'unit_price' => 0, - 'quantity' => 0, - 'minimal_quantity' => 1, - 'price' => 0, - 'id_tax_rules_group' => 0, - 'description_short' => array((int)Configuration::get('PS_LANG_DEFAULT') => ''), - 'link_rewrite' => array((int)Configuration::get('PS_LANG_DEFAULT') => ''), - 'online_only' => 0, - 'condition' => 'new', - 'available_date' => date('Y-m-d'), - 'date_add' => date('Y-m-d H:i:s'), - 'customizable' => 0, - 'uploadable_files' => 0, - 'text_fields' => 0, - 'advanced_stock_management' => 0, - 'depends_on_stock' => 0, - ); - break; + self::$default_values = array( + 'id_category' => array((int)Configuration::get('PS_HOME_CATEGORY')), + 'id_category_default' => null, + 'active' => '1', + 'width' => 0.000000, + 'height' => 0.000000, + 'depth' => 0.000000, + 'weight' => 0.000000, + 'visibility' => 'both', + 'additional_shipping_cost' => 0.00, + 'unit_price' => 0, + 'quantity' => 0, + 'minimal_quantity' => 1, + 'price' => 0, + 'id_tax_rules_group' => 0, + 'description_short' => array((int)Configuration::get('PS_LANG_DEFAULT') => ''), + 'link_rewrite' => array((int)Configuration::get('PS_LANG_DEFAULT') => ''), + 'online_only' => 0, + 'condition' => 'new', + 'available_date' => date('Y-m-d'), + 'date_add' => date('Y-m-d H:i:s'), + 'customizable' => 0, + 'uploadable_files' => 0, + 'text_fields' => 0, + 'advanced_stock_management' => 0, + 'depends_on_stock' => 0, + ); + break; - case $this->entities[$this->l('Customers')]: - //Overwrite required_fields AS only email is required whereas other entities - $this->required_fields = array('email', 'passwd', 'lastname', 'firstname'); + case $this->entities[$this->l('Customers')]: + //Overwrite required_fields AS only email is required whereas other entities + $this->required_fields = array('email', 'passwd', 'lastname', 'firstname'); - $this->available_fields = array( - 'no' => array('label' => $this->l('Ignore this column')), - 'id' => array('label' => $this->l('ID')), - 'active' => array('label' => $this->l('Active (0/1)')), - 'id_gender' => array('label' => $this->l('Titles ID (Mr = 1, Ms = 2, else 0)')), - 'email' => array('label' => $this->l('Email *')), - 'passwd' => array('label' => $this->l('Password *')), - 'birthday' => array('label' => $this->l('Birthday (yyyy-mm-dd)')), - 'lastname' => array('label' => $this->l('Last Name *')), - 'firstname' => array('label' => $this->l('First Name *')), - 'newsletter' => array('label' => $this->l('Newsletter (0/1)')), - 'optin' => array('label' => $this->l('Opt-in (0/1)')), - 'group' => array('label' => $this->l('Groups (x,y,z...)')), - 'id_default_group' => array('label' => $this->l('Default group ID')), - 'id_shop' => array( - 'label' => $this->l('ID / Name of shop'), - 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'), - ), - ); + $this->available_fields = array( + 'no' => array('label' => $this->l('Ignore this column')), + 'id' => array('label' => $this->l('ID')), + 'active' => array('label' => $this->l('Active (0/1)')), + 'id_gender' => array('label' => $this->l('Titles ID (Mr = 1, Ms = 2, else 0)')), + 'email' => array('label' => $this->l('Email *')), + 'passwd' => array('label' => $this->l('Password *')), + 'birthday' => array('label' => $this->l('Birthday (yyyy-mm-dd)')), + 'lastname' => array('label' => $this->l('Last Name *')), + 'firstname' => array('label' => $this->l('First Name *')), + 'newsletter' => array('label' => $this->l('Newsletter (0/1)')), + 'optin' => array('label' => $this->l('Opt-in (0/1)')), + 'group' => array('label' => $this->l('Groups (x,y,z...)')), + 'id_default_group' => array('label' => $this->l('Default group ID')), + 'id_shop' => array( + 'label' => $this->l('ID / Name of shop'), + 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'), + ), + ); - self::$default_values = array( - 'active' => '1', - 'id_shop' => Configuration::get('PS_SHOP_DEFAULT'), - ); - break; + self::$default_values = array( + 'active' => '1', + 'id_shop' => Configuration::get('PS_SHOP_DEFAULT'), + ); + break; - case $this->entities[$this->l('Addresses')]: - //Overwrite required_fields - $this->required_fields = array( - 'alias', - 'lastname', - 'firstname', - 'address1', - 'postcode', - 'country', - 'customer_email', - 'city' - ); + case $this->entities[$this->l('Addresses')]: + //Overwrite required_fields + $this->required_fields = array( + 'alias', + 'lastname', + 'firstname', + 'address1', + 'postcode', + 'country', + 'customer_email', + 'city' + ); - $this->available_fields = array( - 'no' => array('label' => $this->l('Ignore this column')), - 'id' => array('label' => $this->l('ID')), - 'alias' => array('label' => $this->l('Alias *')), - 'active' => array('label' => $this->l('Active (0/1)')), - 'customer_email' => array('label' => $this->l('Customer email *')), - 'id_customer' => array('label' => $this->l('Customer ID')), - 'manufacturer' => array('label' => $this->l('Manufacturer')), - 'supplier' => array('label' => $this->l('Supplier')), - 'company' => array('label' => $this->l('Company')), - 'lastname' => array('label' => $this->l('Last Name *')), - 'firstname' => array('label' => $this->l('First Name *')), - 'address1' => array('label' => $this->l('Address 1 *')), - 'address2' => array('label' => $this->l('Address 2')), - 'postcode' => array('label' => $this->l('Zip/postal code *')), - 'city' => array('label' => $this->l('City *')), - 'country' => array('label' => $this->l('Country *')), - 'state' => array('label' => $this->l('State')), - 'other' => array('label' => $this->l('Other')), - 'phone' => array('label' => $this->l('Phone')), - 'phone_mobile' => array('label' => $this->l('Mobile Phone')), - 'vat_number' => array('label' => $this->l('VAT number')), - 'dni' => array('label' => $this->l('DNI/NIF/NIE')), - ); + $this->available_fields = array( + 'no' => array('label' => $this->l('Ignore this column')), + 'id' => array('label' => $this->l('ID')), + 'alias' => array('label' => $this->l('Alias *')), + 'active' => array('label' => $this->l('Active (0/1)')), + 'customer_email' => array('label' => $this->l('Customer email *')), + 'id_customer' => array('label' => $this->l('Customer ID')), + 'manufacturer' => array('label' => $this->l('Manufacturer')), + 'supplier' => array('label' => $this->l('Supplier')), + 'company' => array('label' => $this->l('Company')), + 'lastname' => array('label' => $this->l('Last Name *')), + 'firstname' => array('label' => $this->l('First Name *')), + 'address1' => array('label' => $this->l('Address 1 *')), + 'address2' => array('label' => $this->l('Address 2')), + 'postcode' => array('label' => $this->l('Zip/postal code *')), + 'city' => array('label' => $this->l('City *')), + 'country' => array('label' => $this->l('Country *')), + 'state' => array('label' => $this->l('State')), + 'other' => array('label' => $this->l('Other')), + 'phone' => array('label' => $this->l('Phone')), + 'phone_mobile' => array('label' => $this->l('Mobile Phone')), + 'vat_number' => array('label' => $this->l('VAT number')), + 'dni' => array('label' => $this->l('DNI/NIF/NIE')), + ); - self::$default_values = array( - 'alias' => 'Alias', - 'postcode' => 'X' - ); - break; - case $this->entities[$this->l('Manufacturers')]: - case $this->entities[$this->l('Suppliers')]: - //Overwrite validators AS name is not MultiLangField - self::$validators = array( - 'description' => array('AdminImportController', 'createMultiLangField'), - 'short_description' => array('AdminImportController', 'createMultiLangField'), - 'meta_title' => array('AdminImportController', 'createMultiLangField'), - 'meta_keywords' => array('AdminImportController', 'createMultiLangField'), - 'meta_description' => array('AdminImportController', 'createMultiLangField'), - ); + self::$default_values = array( + 'alias' => 'Alias', + 'postcode' => 'X' + ); + break; + case $this->entities[$this->l('Manufacturers')]: + case $this->entities[$this->l('Suppliers')]: + //Overwrite validators AS name is not MultiLangField + self::$validators = array( + 'description' => array('AdminImportController', 'createMultiLangField'), + 'short_description' => array('AdminImportController', 'createMultiLangField'), + 'meta_title' => array('AdminImportController', 'createMultiLangField'), + 'meta_keywords' => array('AdminImportController', 'createMultiLangField'), + 'meta_description' => array('AdminImportController', 'createMultiLangField'), + ); - $this->available_fields = array( - 'no' => array('label' => $this->l('Ignore this column')), - 'id' => array('label' => $this->l('ID')), - 'active' => array('label' => $this->l('Active (0/1)')), - 'name' => array('label' => $this->l('Name')), - 'description' => array('label' => $this->l('Description')), - 'short_description' => array('label' => $this->l('Short description')), - 'meta_title' => array('label' => $this->l('Meta title')), - 'meta_keywords' => array('label' => $this->l('Meta keywords')), - 'meta_description' => array('label' => $this->l('Meta description')), - 'image' => array('label' => $this->l('Image URL')), - 'shop' => array( - 'label' => $this->l('ID / Name of group shop'), - 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'), - ), - ); + $this->available_fields = array( + 'no' => array('label' => $this->l('Ignore this column')), + 'id' => array('label' => $this->l('ID')), + 'active' => array('label' => $this->l('Active (0/1)')), + 'name' => array('label' => $this->l('Name')), + 'description' => array('label' => $this->l('Description')), + 'short_description' => array('label' => $this->l('Short description')), + 'meta_title' => array('label' => $this->l('Meta title')), + 'meta_keywords' => array('label' => $this->l('Meta keywords')), + 'meta_description' => array('label' => $this->l('Meta description')), + 'image' => array('label' => $this->l('Image URL')), + 'shop' => array( + 'label' => $this->l('ID / Name of group shop'), + 'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'), + ), + ); - self::$default_values = array( - 'shop' => Shop::getGroupFromShop(Configuration::get('PS_SHOP_DEFAULT')), - ); - break; - case $this->entities[$this->l('Alias')]: - //Overwrite required_fields - $this->required_fields = array( - 'alias', - 'search', - ); - $this->available_fields = array( - 'no' => array('label' => $this->l('Ignore this column')), - 'id' => array('label' => $this->l('ID')), - 'alias' => array('label' => $this->l('Alias *')), - 'search' => array('label' => $this->l('Search *')), - 'active' => array('label' => $this->l('Active')), - ); - self::$default_values = array( - 'active' => '1', - ); - break; - } + self::$default_values = array( + 'shop' => Shop::getGroupFromShop(Configuration::get('PS_SHOP_DEFAULT')), + ); + break; + case $this->entities[$this->l('Alias')]: + //Overwrite required_fields + $this->required_fields = array( + 'alias', + 'search', + ); + $this->available_fields = array( + 'no' => array('label' => $this->l('Ignore this column')), + 'id' => array('label' => $this->l('ID')), + 'alias' => array('label' => $this->l('Alias *')), + 'search' => array('label' => $this->l('Search *')), + 'active' => array('label' => $this->l('Active')), + ); + self::$default_values = array( + 'active' => '1', + ); + break; + } - // @since 1.5.0 - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - switch ((int)Tools::getValue('entity')) - { - case $this->entities[$this->l('Supply Orders')]: - // required fields - $this->required_fields = array( - 'id_supplier', - 'id_warehouse', - 'reference', - 'date_delivery_expected', - ); - // available fields - $this->available_fields = array( - 'no' => array('label' => $this->l('Ignore this column')), - 'id' => array('label' => $this->l('ID')), - 'id_supplier' => array('label' => $this->l('Supplier ID *')), - 'id_lang' => array('label' => $this->l('Lang ID')), - 'id_warehouse' => array('label' => $this->l('Warehouse ID *')), - 'id_currency' => array('label' => $this->l('Currency ID *')), - 'reference' => array('label' => $this->l('Supply Order Reference *')), - 'date_delivery_expected' => array('label' => $this->l('Delivery Date (Y-M-D)*')), - 'discount_rate' => array('label' => $this->l('Discount Rate')), - 'is_template' => array('label' => $this->l('Template')), - ); - // default values - self::$default_values = array( - 'id_lang' => (int)Configuration::get('PS_LANG_DEFAULT'), - 'id_currency' => Currency::getDefaultCurrency()->id, - 'discount_rate' => '0', - 'is_template' => '0', - ); - break; - case $this->entities[$this->l('Supply Order Details')]: - // required fields - $this->required_fields = array( - 'supply_order_reference', - 'id_product', - 'unit_price_te', - 'quantity_expected', - ); - // available fields - $this->available_fields = array( - 'no' => array('label' => $this->l('Ignore this column')), - 'supply_order_reference' => array('label' => $this->l('Supply Order Reference *')), - 'id_product' => array('label' => $this->l('Product ID *')), - 'id_product_attribute' => array('label' => $this->l('Product Attribute ID')), - 'unit_price_te' => array('label' => $this->l('Unit Price (tax excl.)*')), - 'quantity_expected' => array('label' => $this->l('Quantity Expected *')), - 'discount_rate' => array('label' => $this->l('Discount Rate')), - 'tax_rate' => array('label' => $this->l('Tax Rate')), - ); - // default values - self::$default_values = array( - 'discount_rate' => '0', - 'tax_rate' => '0', - ); - break; + // @since 1.5.0 + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + switch ((int)Tools::getValue('entity')) { + case $this->entities[$this->l('Supply Orders')]: + // required fields + $this->required_fields = array( + 'id_supplier', + 'id_warehouse', + 'reference', + 'date_delivery_expected', + ); + // available fields + $this->available_fields = array( + 'no' => array('label' => $this->l('Ignore this column')), + 'id' => array('label' => $this->l('ID')), + 'id_supplier' => array('label' => $this->l('Supplier ID *')), + 'id_lang' => array('label' => $this->l('Lang ID')), + 'id_warehouse' => array('label' => $this->l('Warehouse ID *')), + 'id_currency' => array('label' => $this->l('Currency ID *')), + 'reference' => array('label' => $this->l('Supply Order Reference *')), + 'date_delivery_expected' => array('label' => $this->l('Delivery Date (Y-M-D)*')), + 'discount_rate' => array('label' => $this->l('Discount Rate')), + 'is_template' => array('label' => $this->l('Template')), + ); + // default values + self::$default_values = array( + 'id_lang' => (int)Configuration::get('PS_LANG_DEFAULT'), + 'id_currency' => Currency::getDefaultCurrency()->id, + 'discount_rate' => '0', + 'is_template' => '0', + ); + break; + case $this->entities[$this->l('Supply Order Details')]: + // required fields + $this->required_fields = array( + 'supply_order_reference', + 'id_product', + 'unit_price_te', + 'quantity_expected', + ); + // available fields + $this->available_fields = array( + 'no' => array('label' => $this->l('Ignore this column')), + 'supply_order_reference' => array('label' => $this->l('Supply Order Reference *')), + 'id_product' => array('label' => $this->l('Product ID *')), + 'id_product_attribute' => array('label' => $this->l('Product Attribute ID')), + 'unit_price_te' => array('label' => $this->l('Unit Price (tax excl.)*')), + 'quantity_expected' => array('label' => $this->l('Quantity Expected *')), + 'discount_rate' => array('label' => $this->l('Discount Rate')), + 'tax_rate' => array('label' => $this->l('Tax Rate')), + ); + // default values + self::$default_values = array( + 'discount_rate' => '0', + 'tax_rate' => '0', + ); + break; - } + } + } - $this->separator = ($separator = Tools::substr(strval(trim(Tools::getValue('separator'))), 0, 1)) ? $separator : ';'; - $this->multiple_value_separator = ($separator = Tools::substr(strval(trim(Tools::getValue('multiple_value_separator'))), 0, 1)) ? $separator : ','; - parent::__construct(); - } + $this->separator = ($separator = Tools::substr(strval(trim(Tools::getValue('separator'))), 0, 1)) ? $separator : ';'; + $this->multiple_value_separator = ($separator = Tools::substr(strval(trim(Tools::getValue('multiple_value_separator'))), 0, 1)) ? $separator : ','; + parent::__construct(); + } - public function setMedia() - { - $bo_theme = ((Validate::isLoadedObject($this->context->employee) - && $this->context->employee->bo_theme) ? $this->context->employee->bo_theme : 'default'); + public function setMedia() + { + $bo_theme = ((Validate::isLoadedObject($this->context->employee) + && $this->context->employee->bo_theme) ? $this->context->employee->bo_theme : 'default'); - if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR - .'template')) - $bo_theme = 'default'; + if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR + .'template')) { + $bo_theme = 'default'; + } - // We need to set parent media first, so that jQuery is loaded before the dependant plugins - parent::setMedia(); + // We need to set parent media first, so that jQuery is loaded before the dependant plugins + parent::setMedia(); - $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.iframe-transport.js'); - $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload.js'); - $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload-process.js'); - $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload-validate.js'); - $this->addJs(__PS_BASE_URI__.'js/vendor/spin.js'); - $this->addJs(__PS_BASE_URI__.'js/vendor/ladda.js'); - } + $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.iframe-transport.js'); + $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload.js'); + $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload-process.js'); + $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload-validate.js'); + $this->addJs(__PS_BASE_URI__.'js/vendor/spin.js'); + $this->addJs(__PS_BASE_URI__.'js/vendor/ladda.js'); + } - public function renderForm() - { - if (!is_dir(AdminImportController::getPath())) - return !($this->errors[] = Tools::displayError('The import directory does not exist.')); + public function renderForm() + { + if (!is_dir(AdminImportController::getPath())) { + return !($this->errors[] = Tools::displayError('The import directory does not exist.')); + } - if (!is_writable(AdminImportController::getPath())) - $this->displayWarning($this->l('The import directory must be writable (CHMOD 755 / 777).')); + if (!is_writable(AdminImportController::getPath())) { + $this->displayWarning($this->l('The import directory must be writable (CHMOD 755 / 777).')); + } - if (isset($this->warnings) && count($this->warnings)) - { - $warnings = array(); - foreach ($this->warnings as $warning) - $warnings[] = $warning; - } + if (isset($this->warnings) && count($this->warnings)) { + $warnings = array(); + foreach ($this->warnings as $warning) { + $warnings[] = $warning; + } + } - $files_to_import = scandir(AdminImportController::getPath()); - uasort($files_to_import, array('AdminImportController', 'usortFiles')); - foreach ($files_to_import as $k => &$filename) - //exclude . .. .svn and index.php and all hidden files - if (preg_match('/^\..*|index\.php/i', $filename)) - unset($files_to_import[$k]); - unset($filename); + $files_to_import = scandir(AdminImportController::getPath()); + uasort($files_to_import, array('AdminImportController', 'usortFiles')); + foreach ($files_to_import as $k => &$filename) { + //exclude . .. .svn and index.php and all hidden files + if (preg_match('/^\..*|index\.php/i', $filename)) { + unset($files_to_import[$k]); + } + } + unset($filename); - $this->fields_form = array(''); + $this->fields_form = array(''); - $this->toolbar_scroll = false; - $this->toolbar_btn = array(); + $this->toolbar_scroll = false; + $this->toolbar_btn = array(); - // adds fancybox - $this->addJqueryPlugin(array('fancybox')); + // adds fancybox + $this->addJqueryPlugin(array('fancybox')); - $entity_selected = 0; - if (isset($this->entities[$this->l(Tools::ucfirst(Tools::getValue('import_type')))])) - { - $entity_selected = $this->entities[$this->l(Tools::ucfirst(Tools::getValue('import_type')))]; - $this->context->cookie->entity_selected = (int)$entity_selected; - } - elseif (isset($this->context->cookie->entity_selected)) - $entity_selected = (int)$this->context->cookie->entity_selected; + $entity_selected = 0; + if (isset($this->entities[$this->l(Tools::ucfirst(Tools::getValue('import_type')))])) { + $entity_selected = $this->entities[$this->l(Tools::ucfirst(Tools::getValue('import_type')))]; + $this->context->cookie->entity_selected = (int)$entity_selected; + } elseif (isset($this->context->cookie->entity_selected)) { + $entity_selected = (int)$this->context->cookie->entity_selected; + } - $csv_selected = ''; - if (isset($this->context->cookie->csv_selected) && @filemtime(AdminImportController::getPath( - urldecode($this->context->cookie->csv_selected)))) - $csv_selected = urldecode($this->context->cookie->csv_selected); - else - $this->context->cookie->csv_selected = $csv_selected; + $csv_selected = ''; + if (isset($this->context->cookie->csv_selected) && @filemtime(AdminImportController::getPath( + urldecode($this->context->cookie->csv_selected)))) { + $csv_selected = urldecode($this->context->cookie->csv_selected); + } else { + $this->context->cookie->csv_selected = $csv_selected; + } - $id_lang_selected = ''; - if (isset($this->context->cookie->iso_lang_selected) && $this->context->cookie->iso_lang_selected) - $id_lang_selected = (int)Language::getIdByIso(urldecode($this->context->cookie->iso_lang_selected)); + $id_lang_selected = ''; + if (isset($this->context->cookie->iso_lang_selected) && $this->context->cookie->iso_lang_selected) { + $id_lang_selected = (int)Language::getIdByIso(urldecode($this->context->cookie->iso_lang_selected)); + } - $separator_selected = $this->separator; - if (isset($this->context->cookie->separator_selected) && $this->context->cookie->separator_selected) - $separator_selected = urldecode($this->context->cookie->separator_selected); + $separator_selected = $this->separator; + if (isset($this->context->cookie->separator_selected) && $this->context->cookie->separator_selected) { + $separator_selected = urldecode($this->context->cookie->separator_selected); + } - $multiple_value_separator_selected = $this->multiple_value_separator; - if (isset($this->context->cookie->multiple_value_separator_selected) && $this->context->cookie->multiple_value_separator_selected) - $multiple_value_separator_selected = urldecode($this->context->cookie->multiple_value_separator_selected); + $multiple_value_separator_selected = $this->multiple_value_separator; + if (isset($this->context->cookie->multiple_value_separator_selected) && $this->context->cookie->multiple_value_separator_selected) { + $multiple_value_separator_selected = urldecode($this->context->cookie->multiple_value_separator_selected); + } - //get post max size - $post_max_size = ini_get('post_max_size'); - $bytes = trim($post_max_size); - $last = strtolower($post_max_size[strlen($post_max_size) - 1]); + //get post max size + $post_max_size = ini_get('post_max_size'); + $bytes = trim($post_max_size); + $last = strtolower($post_max_size[strlen($post_max_size) - 1]); - switch ($last) - { - case 'g': $bytes *= 1024; - case 'm': $bytes *= 1024; - case 'k': $bytes *= 1024; - } + switch ($last) { + case 'g': $bytes *= 1024; + case 'm': $bytes *= 1024; + case 'k': $bytes *= 1024; + } - if (!isset($bytes) || $bytes == '') - $bytes = 20971520; // 20Mb + if (!isset($bytes) || $bytes == '') { + $bytes = 20971520; + } // 20Mb - $this->tpl_form_vars = array( - 'post_max_size' => (int)$bytes, - 'module_confirmation' => Tools::isSubmit('import') && (isset($this->warnings) && !count($this->warnings)), - 'path_import' => AdminImportController::getPath(), - 'entities' => $this->entities, - 'entity_selected' => $entity_selected, - 'csv_selected' => $csv_selected, - 'separator_selected' => $separator_selected, - 'multiple_value_separator_selected' => $multiple_value_separator_selected, - 'files_to_import' => $files_to_import, - 'languages' => Language::getLanguages(false), - 'id_language' => ($id_lang_selected) ? $id_lang_selected : $this->context->language->id, - 'available_fields' => $this->getAvailableFields(), - 'truncateAuthorized' => (Shop::isFeatureActive() && $this->context->employee->isSuperAdmin()) || !Shop::isFeatureActive(), - 'PS_ADVANCED_STOCK_MANAGEMENT' => Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'), - ); + $this->tpl_form_vars = array( + 'post_max_size' => (int)$bytes, + 'module_confirmation' => Tools::isSubmit('import') && (isset($this->warnings) && !count($this->warnings)), + 'path_import' => AdminImportController::getPath(), + 'entities' => $this->entities, + 'entity_selected' => $entity_selected, + 'csv_selected' => $csv_selected, + 'separator_selected' => $separator_selected, + 'multiple_value_separator_selected' => $multiple_value_separator_selected, + 'files_to_import' => $files_to_import, + 'languages' => Language::getLanguages(false), + 'id_language' => ($id_lang_selected) ? $id_lang_selected : $this->context->language->id, + 'available_fields' => $this->getAvailableFields(), + 'truncateAuthorized' => (Shop::isFeatureActive() && $this->context->employee->isSuperAdmin()) || !Shop::isFeatureActive(), + 'PS_ADVANCED_STOCK_MANAGEMENT' => Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'), + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function ajaxProcessuploadCsv() - { - $filename_prefix = date('YmdHis').'-'; + public function ajaxProcessuploadCsv() + { + $filename_prefix = date('YmdHis').'-'; - if (isset($_FILES['file']) && !empty($_FILES['file']['error'])) - { - switch ($_FILES['file']['error']) - { - case UPLOAD_ERR_INI_SIZE: - $_FILES['file']['error'] = Tools::displayError('The uploaded file exceeds the upload_max_filesize directive in php.ini. If your server configuration allows it, you may add a directive in your .htaccess.'); - break; - case UPLOAD_ERR_FORM_SIZE: - $_FILES['file']['error'] = Tools::displayError('The uploaded file exceeds the post_max_size directive in php.ini. + if (isset($_FILES['file']) && !empty($_FILES['file']['error'])) { + switch ($_FILES['file']['error']) { + case UPLOAD_ERR_INI_SIZE: + $_FILES['file']['error'] = Tools::displayError('The uploaded file exceeds the upload_max_filesize directive in php.ini. If your server configuration allows it, you may add a directive in your .htaccess.'); + break; + case UPLOAD_ERR_FORM_SIZE: + $_FILES['file']['error'] = Tools::displayError('The uploaded file exceeds the post_max_size directive in php.ini. If your server configuration allows it, you may add a directive in your .htaccess, for example:') - .'<br/><a href="'.$this->context->link->getAdminLink('AdminMeta').'" > + .'<br/><a href="'.$this->context->link->getAdminLink('AdminMeta').'" > <code>php_value post_max_size 20M</code> '. - Tools::displayError('(click to open "Generators" page)').'</a>'; - break; - break; - case UPLOAD_ERR_PARTIAL: - $_FILES['file']['error'] = Tools::displayError('The uploaded file was only partially uploaded.'); - break; - break; - case UPLOAD_ERR_NO_FILE: - $_FILES['file']['error'] = Tools::displayError('No file was uploaded.'); - break; - break; - } - } - elseif (!preg_match('/.*\.csv$/i', $_FILES['file']['name'])) - $_FILES['file']['error'] = Tools::displayError('The extension of your file should be .csv.'); - elseif (!@filemtime($_FILES['file']['tmp_name']) || - !@move_uploaded_file($_FILES['file']['tmp_name'], AdminImportController::getPath().$filename_prefix.str_replace("\0", '', $_FILES['file']['name']))) - $_FILES['file']['error'] = $this->l('An error occurred while uploading / copying the file.'); - else - { - @chmod(AdminImportController::getPath().$filename_prefix.$_FILES['file']['name'], 0664); - $_FILES['file']['filename'] = $filename_prefix.str_replace('\0', '', $_FILES['file']['name']); - } + Tools::displayError('(click to open "Generators" page)').'</a>'; + break; + break; + case UPLOAD_ERR_PARTIAL: + $_FILES['file']['error'] = Tools::displayError('The uploaded file was only partially uploaded.'); + break; + break; + case UPLOAD_ERR_NO_FILE: + $_FILES['file']['error'] = Tools::displayError('No file was uploaded.'); + break; + break; + } + } elseif (!preg_match('/.*\.csv$/i', $_FILES['file']['name'])) { + $_FILES['file']['error'] = Tools::displayError('The extension of your file should be .csv.'); + } elseif (!@filemtime($_FILES['file']['tmp_name']) || + !@move_uploaded_file($_FILES['file']['tmp_name'], AdminImportController::getPath().$filename_prefix.str_replace("\0", '', $_FILES['file']['name']))) { + $_FILES['file']['error'] = $this->l('An error occurred while uploading / copying the file.'); + } else { + @chmod(AdminImportController::getPath().$filename_prefix.$_FILES['file']['name'], 0664); + $_FILES['file']['filename'] = $filename_prefix.str_replace('\0', '', $_FILES['file']['name']); + } - die(Tools::jsonEncode($_FILES)); - } + die(Tools::jsonEncode($_FILES)); + } - public function renderView() - { - $this->addJS(_PS_JS_DIR_.'admin/import.js'); + public function renderView() + { + $this->addJS(_PS_JS_DIR_.'admin/import.js'); - $handle = $this->openCsvFile(); - $nb_column = $this->getNbrColumn($handle, $this->separator); - $nb_table = ceil($nb_column / MAX_COLUMNS); + $handle = $this->openCsvFile(); + $nb_column = $this->getNbrColumn($handle, $this->separator); + $nb_table = ceil($nb_column / MAX_COLUMNS); - $res = array(); - foreach ($this->required_fields as $elem) - $res[] = '\''.$elem.'\''; + $res = array(); + foreach ($this->required_fields as $elem) { + $res[] = '\''.$elem.'\''; + } - $data = array(); - for ($i = 0; $i < $nb_table; $i++) - $data[$i] = $this->generateContentTable($i, $nb_column, $handle, $this->separator); + $data = array(); + for ($i = 0; $i < $nb_table; $i++) { + $data[$i] = $this->generateContentTable($i, $nb_column, $handle, $this->separator); + } - $this->context->cookie->entity_selected = (int)Tools::getValue('entity'); - $this->context->cookie->iso_lang_selected = urlencode(Tools::getValue('iso_lang')); - $this->context->cookie->separator_selected = urlencode($this->separator); - $this->context->cookie->multiple_value_separator_selected = urlencode($this->multiple_value_separator); - $this->context->cookie->csv_selected = urlencode(Tools::getValue('csv')); + $this->context->cookie->entity_selected = (int)Tools::getValue('entity'); + $this->context->cookie->iso_lang_selected = urlencode(Tools::getValue('iso_lang')); + $this->context->cookie->separator_selected = urlencode($this->separator); + $this->context->cookie->multiple_value_separator_selected = urlencode($this->multiple_value_separator); + $this->context->cookie->csv_selected = urlencode(Tools::getValue('csv')); - $this->tpl_view_vars = array( - 'import_matchs' => Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'import_match', true, false), - 'fields_value' => array( - 'csv' => Tools::getValue('csv'), - 'convert' => Tools::getValue('convert'), - 'entity' => (int)Tools::getValue('entity'), - 'iso_lang' => Tools::getValue('iso_lang'), - 'truncate' => Tools::getValue('truncate'), - 'forceIDs' => Tools::getValue('forceIDs'), - 'regenerate' => Tools::getValue('regenerate'), - 'match_ref' => Tools::getValue('match_ref'), - 'separator' => $this->separator, - 'multiple_value_separator' => $this->multiple_value_separator - ), - 'nb_table' => $nb_table, - 'nb_column' => $nb_column, - 'res' => implode(',', $res), - 'max_columns' => MAX_COLUMNS, - 'no_pre_select' => array('price_tin', 'feature'), - 'available_fields' => $this->available_fields, - 'data' => $data - ); + $this->tpl_view_vars = array( + 'import_matchs' => Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'import_match', true, false), + 'fields_value' => array( + 'csv' => Tools::getValue('csv'), + 'convert' => Tools::getValue('convert'), + 'entity' => (int)Tools::getValue('entity'), + 'iso_lang' => Tools::getValue('iso_lang'), + 'truncate' => Tools::getValue('truncate'), + 'forceIDs' => Tools::getValue('forceIDs'), + 'regenerate' => Tools::getValue('regenerate'), + 'match_ref' => Tools::getValue('match_ref'), + 'separator' => $this->separator, + 'multiple_value_separator' => $this->multiple_value_separator + ), + 'nb_table' => $nb_table, + 'nb_column' => $nb_column, + 'res' => implode(',', $res), + 'max_columns' => MAX_COLUMNS, + 'no_pre_select' => array('price_tin', 'feature'), + 'available_fields' => $this->available_fields, + 'data' => $data + ); - return parent::renderView(); - } + return parent::renderView(); + } - public function initToolbar() - { - switch ($this->display) - { - case 'import': - // Default cancel button - like old back link - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; + public function initToolbar() + { + switch ($this->display) { + case 'import': + // Default cancel button - like old back link + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } - $this->toolbar_btn['cancel'] = array( - 'href' => $back, - 'desc' => $this->l('Cancel') - ); - // Default save button - action dynamically handled in javascript - $this->toolbar_btn['save-import'] = array( - 'href' => '#', - 'desc' => $this->l('Import .CSV data') - ); - break; - } - } + $this->toolbar_btn['cancel'] = array( + 'href' => $back, + 'desc' => $this->l('Cancel') + ); + // Default save button - action dynamically handled in javascript + $this->toolbar_btn['save-import'] = array( + 'href' => '#', + 'desc' => $this->l('Import .CSV data') + ); + break; + } + } - protected function generateContentTable($current_table, $nb_column, $handle, $glue) - { - $html = '<table id="table'.$current_table.'" style="display: none;" class="table table-bordered"><thead><tr>'; - // Header - for ($i = 0; $i < $nb_column; $i++) - if (MAX_COLUMNS * (int)$current_table <= $i && (int)$i < MAX_COLUMNS * ((int)$current_table + 1)) - $html .= '<th> + protected function generateContentTable($current_table, $nb_column, $handle, $glue) + { + $html = '<table id="table'.$current_table.'" style="display: none;" class="table table-bordered"><thead><tr>'; + // Header + for ($i = 0; $i < $nb_column; $i++) { + if (MAX_COLUMNS * (int)$current_table <= $i && (int)$i < MAX_COLUMNS * ((int)$current_table + 1)) { + $html .= '<th> <select id="type_value['.$i.']" name="type_value['.$i.']" class="type_value"> '.$this->getTypeValuesOptions($i).' </select> </th>'; - $html .= '</tr></thead><tbody>'; + } + } + $html .= '</tr></thead><tbody>'; - AdminImportController::setLocale(); - for ($current_line = 0; $current_line < 10 && $line = fgetcsv($handle, MAX_LINE_SIZE, $glue); $current_line++) - { - /* UTF-8 conversion */ - if (Tools::getValue('convert')) - $line = $this->utf8EncodeArray($line); - $html .= '<tr id="table_'.$current_table.'_line_'.$current_line.'">'; - foreach ($line as $nb_c => $column) - if ((MAX_COLUMNS * (int)$current_table <= $nb_c) && ((int)$nb_c < MAX_COLUMNS * ((int)$current_table + 1))) - $html .= '<td>'.htmlentities(Tools::substr($column, 0, 200), ENT_QUOTES, 'UTF-8').'</td>'; - $html .= '</tr>'; - } - $html .= '</tbody></table>'; - AdminImportController::rewindBomAware($handle); - return $html; - } + AdminImportController::setLocale(); + for ($current_line = 0; $current_line < 10 && $line = fgetcsv($handle, MAX_LINE_SIZE, $glue); $current_line++) { + /* UTF-8 conversion */ + if (Tools::getValue('convert')) { + $line = $this->utf8EncodeArray($line); + } + $html .= '<tr id="table_'.$current_table.'_line_'.$current_line.'">'; + foreach ($line as $nb_c => $column) { + if ((MAX_COLUMNS * (int)$current_table <= $nb_c) && ((int)$nb_c < MAX_COLUMNS * ((int)$current_table + 1))) { + $html .= '<td>'.htmlentities(Tools::substr($column, 0, 200), ENT_QUOTES, 'UTF-8').'</td>'; + } + } + $html .= '</tr>'; + } + $html .= '</tbody></table>'; + AdminImportController::rewindBomAware($handle); + return $html; + } - public function init() - { - parent::init(); - if (Tools::isSubmit('submitImportFile')) - $this->display = 'import'; - } + public function init() + { + parent::init(); + if (Tools::isSubmit('submitImportFile')) { + $this->display = 'import'; + } + } - public function initContent() - { - $this->initTabModuleList(); - // toolbar (save, cancel, new, ..) - $this->initToolbar(); - $this->initPageHeaderToolbar(); - if ($this->display == 'import') - { - if (Tools::getValue('csv')) - $this->content .= $this->renderView(); - else - { - $this->errors[] = $this->l('You must upload a file in order to proceed to the next step'); - $this->content .= $this->renderForm(); - } - } - else - $this->content .= $this->renderForm(); + public function initContent() + { + $this->initTabModuleList(); + // toolbar (save, cancel, new, ..) + $this->initToolbar(); + $this->initPageHeaderToolbar(); + if ($this->display == 'import') { + if (Tools::getValue('csv')) { + $this->content .= $this->renderView(); + } else { + $this->errors[] = $this->l('You must upload a file in order to proceed to the next step'); + $this->content .= $this->renderForm(); + } + } else { + $this->content .= $this->renderForm(); + } - $this->context->smarty->assign(array( - 'content' => $this->content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } + $this->context->smarty->assign(array( + 'content' => $this->content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } - protected static function rewindBomAware($handle) - { - // A rewind wrapper that skips BOM signature wrongly - if (!is_resource($handle)) - return false; - rewind($handle); - if (($bom = fread($handle, 3)) != "\xEF\xBB\xBF") - rewind($handle); - } + protected static function rewindBomAware($handle) + { + // A rewind wrapper that skips BOM signature wrongly + if (!is_resource($handle)) { + return false; + } + rewind($handle); + if (($bom = fread($handle, 3)) != "\xEF\xBB\xBF") { + rewind($handle); + } + } - protected static function getBoolean($field) - { - return (bool)$field; - } + protected static function getBoolean($field) + { + return (bool)$field; + } - protected static function getPrice($field) - { - $field = ((float)str_replace(',', '.', $field)); - $field = ((float)str_replace('%', '', $field)); - return $field; - } + protected static function getPrice($field) + { + $field = ((float)str_replace(',', '.', $field)); + $field = ((float)str_replace('%', '', $field)); + return $field; + } - protected static function split($field) - { - if (empty($field)) - return array(); + protected static function split($field) + { + if (empty($field)) { + return array(); + } - $separator = Tools::getValue('multiple_value_separator'); - if (is_null($separator) || trim($separator) == '') - $separator = ','; + $separator = Tools::getValue('multiple_value_separator'); + if (is_null($separator) || trim($separator) == '') { + $separator = ','; + } - do - $uniqid_path = _PS_UPLOAD_DIR_.uniqid(); - while (file_exists($uniqid_path)); - file_put_contents($uniqid_path, $field); - $tab = ''; - if (!empty($uniqid_path)) - { - $fd = fopen($uniqid_path, 'r'); - $tab = fgetcsv($fd, MAX_LINE_SIZE, $separator); - fclose($fd); - if (file_exists($uniqid_path)) - @unlink($uniqid_path); - } + do { + $uniqid_path = _PS_UPLOAD_DIR_.uniqid(); + } while (file_exists($uniqid_path)); + file_put_contents($uniqid_path, $field); + $tab = ''; + if (!empty($uniqid_path)) { + $fd = fopen($uniqid_path, 'r'); + $tab = fgetcsv($fd, MAX_LINE_SIZE, $separator); + fclose($fd); + if (file_exists($uniqid_path)) { + @unlink($uniqid_path); + } + } - if (empty($tab) || (!is_array($tab))) - return array(); - return $tab; - } + if (empty($tab) || (!is_array($tab))) { + return array(); + } + return $tab; + } - protected static function createMultiLangField($field) - { - $res = array(); - foreach (Language::getIDs(false) as $id_lang) - $res[$id_lang] = $field; + protected static function createMultiLangField($field) + { + $res = array(); + foreach (Language::getIDs(false) as $id_lang) { + $res[$id_lang] = $field; + } - return $res; - } + return $res; + } - protected function getTypeValuesOptions($nb_c) - { - $i = 0; - $no_pre_select = array('price_tin', 'feature'); + protected function getTypeValuesOptions($nb_c) + { + $i = 0; + $no_pre_select = array('price_tin', 'feature'); - $options = ''; - foreach ($this->available_fields as $k => $field) - { - $options .= '<option value="'.$k.'"'; - if ($k === 'price_tin') - ++$nb_c; - if ($i === ($nb_c + 1) && (!in_array($k, $no_pre_select))) - $options .= ' selected="selected"'; - $options .= '>'.$field['label'].'</option>'; - ++$i; - } - return $options; - } + $options = ''; + foreach ($this->available_fields as $k => $field) { + $options .= '<option value="'.$k.'"'; + if ($k === 'price_tin') { + ++$nb_c; + } + if ($i === ($nb_c + 1) && (!in_array($k, $no_pre_select))) { + $options .= ' selected="selected"'; + } + $options .= '>'.$field['label'].'</option>'; + ++$i; + } + return $options; + } - /* - * Return fields to be display AS piece of advise - * - * @param $in_array boolean - * @return string or return array - */ - public function getAvailableFields($in_array = false) - { - $i = 0; - $fields = array(); - $keys = array_keys($this->available_fields); - array_shift($keys); - foreach ($this->available_fields as $k => $field) - { - if ($k === 'no') - continue; - if ($k === 'price_tin') - $fields[$i - 1] = '<div>'.$this->available_fields[$keys[$i - 1]]['label'].' '.$this->l('or').' '.$field['label'].'</div>'; - else - { - if (isset($field['help'])) + /* + * Return fields to be display AS piece of advise + * + * @param $in_array boolean + * @return string or return array + */ + public function getAvailableFields($in_array = false) + { + $i = 0; + $fields = array(); + $keys = array_keys($this->available_fields); + array_shift($keys); + foreach ($this->available_fields as $k => $field) { + if ($k === 'no') { + continue; + } + if ($k === 'price_tin') { + $fields[$i - 1] = '<div>'.$this->available_fields[$keys[$i - 1]]['label'].' '.$this->l('or').' '.$field['label'].'</div>'; + } else { + if (isset($field['help'])) { + $html = ' <a href="#" class="help-tooltip" data-toggle="tooltip" title="'.$field['help'].'"><i class="icon-info-sign"></i></a>'; + } else { + $html = ''; + } + $fields[] = '<div>'.$field['label'].$html.'</div>'; + } + ++$i; + } + if ($in_array) { + return $fields; + } else { + return implode("\n\r", $fields); + } + } - $html = ' <a href="#" class="help-tooltip" data-toggle="tooltip" title="'.$field['help'].'"><i class="icon-info-sign"></i></a>'; - else - $html = ''; - $fields[] = '<div>'.$field['label'].$html.'</div>'; - } - ++$i; - } - if ($in_array) - return $fields; - else - return implode("\n\r", $fields); - } + protected function receiveTab() + { + $type_value = Tools::getValue('type_value') ? Tools::getValue('type_value') : array(); + foreach ($type_value as $nb => $type) { + if ($type != 'no') { + self::$column_mask[$type] = $nb; + } + } + } - protected function receiveTab() - { - $type_value = Tools::getValue('type_value') ? Tools::getValue('type_value') : array(); - foreach ($type_value as $nb => $type) - if ($type != 'no') - self::$column_mask[$type] = $nb; - } + public static function getMaskedRow($row) + { + $res = array(); + if (is_array(self::$column_mask)) { + foreach (self::$column_mask as $type => $nb) { + $res[$type] = isset($row[$nb]) ? $row[$nb] : null; + } + } - public static function getMaskedRow($row) - { - $res = array(); - if (is_array(self::$column_mask)) - foreach (self::$column_mask as $type => $nb) - $res[$type] = isset($row[$nb]) ? $row[$nb] : null; + return $res; + } - return $res; - } + protected static function setDefaultValues(&$info) + { + foreach (self::$default_values as $k => $v) { + if (!isset($info[$k]) || $info[$k] == '') { + $info[$k] = $v; + } + } + } - protected static function setDefaultValues(&$info) - { - foreach (self::$default_values as $k => $v) - if (!isset($info[$k]) || $info[$k] == '') - $info[$k] = $v; - } + protected static function setEntityDefaultValues(&$entity) + { + $members = get_object_vars($entity); + foreach (self::$default_values as $k => $v) { + if ((array_key_exists($k, $members) && $entity->$k === null) || !array_key_exists($k, $members)) { + $entity->$k = $v; + } + } + } - protected static function setEntityDefaultValues(&$entity) - { - $members = get_object_vars($entity); - foreach (self::$default_values as $k => $v) - if ((array_key_exists($k, $members) && $entity->$k === null) || !array_key_exists($k, $members)) - $entity->$k = $v; - } + protected static function fillInfo($infos, $key, &$entity) + { + $infos = trim($infos); + if (isset(self::$validators[$key][1]) && self::$validators[$key][1] == 'createMultiLangField' && Tools::getValue('iso_lang')) { + $id_lang = Language::getIdByIso(Tools::getValue('iso_lang')); + $tmp = call_user_func(self::$validators[$key], $infos); + foreach ($tmp as $id_lang_tmp => $value) { + if (empty($entity->{$key}[$id_lang_tmp]) || $id_lang_tmp == $id_lang) { + $entity->{$key}[$id_lang_tmp] = $value; + } + } + } elseif (!empty($infos) || $infos == '0') { // ($infos == '0') => if you want to disable a product by using "0" in active because empty('0') return true + $entity->{$key} = isset(self::$validators[$key]) ? call_user_func(self::$validators[$key], $infos) : $infos; + } - protected static function fillInfo($infos, $key, &$entity) - { - $infos = trim($infos); - if (isset(self::$validators[$key][1]) && self::$validators[$key][1] == 'createMultiLangField' && Tools::getValue('iso_lang')) - { - $id_lang = Language::getIdByIso(Tools::getValue('iso_lang')); - $tmp = call_user_func(self::$validators[$key], $infos); - foreach ($tmp as $id_lang_tmp => $value) - if (empty($entity->{$key}[$id_lang_tmp]) || $id_lang_tmp == $id_lang) - $entity->{$key}[$id_lang_tmp] = $value; - } - else - if (!empty($infos) || $infos == '0') // ($infos == '0') => if you want to disable a product by using "0" in active because empty('0') return true - $entity->{$key} = isset(self::$validators[$key]) ? call_user_func(self::$validators[$key], $infos) : $infos; + return true; + } - return true; - } + /** + * @param $array + * @param $funcname + * @param mixed $user_data + * @return bool + */ + public static function arrayWalk(&$array, $funcname, &$user_data = false) + { + if (!is_callable($funcname)) { + return false; + } - /** - * @param $array - * @param $funcname - * @param mixed $user_data - * @return bool - */ - public static function arrayWalk(&$array, $funcname, &$user_data = false) - { - if (!is_callable($funcname)) return false; + foreach ($array as $k => $row) { + if (!call_user_func_array($funcname, array($row, $k, $user_data))) { + return false; + } + } + return true; + } - foreach ($array as $k => $row) - if (!call_user_func_array($funcname, array($row, $k, $user_data))) - return false; - return true; - } + /** + * copyImg copy an image located in $url and save it in a path + * according to $entity->$id_entity . + * $id_image is used if we need to add a watermark + * + * @param int $id_entity id of product or category (set in entity) + * @param int $id_image (default null) id of the image if watermark enabled. + * @param string $url path or url to use + * @param string $entity 'products' or 'categories' + * @param bool $regenerate + * @return bool + */ + protected static function copyImg($id_entity, $id_image = null, $url, $entity = 'products', $regenerate = true) + { + $tmpfile = tempnam(_PS_TMP_IMG_DIR_, 'ps_import'); + $watermark_types = explode(',', Configuration::get('WATERMARK_TYPES')); - /** - * copyImg copy an image located in $url and save it in a path - * according to $entity->$id_entity . - * $id_image is used if we need to add a watermark - * - * @param int $id_entity id of product or category (set in entity) - * @param int $id_image (default null) id of the image if watermark enabled. - * @param string $url path or url to use - * @param string $entity 'products' or 'categories' - * @param bool $regenerate - * @return bool - */ - protected static function copyImg($id_entity, $id_image = null, $url, $entity = 'products', $regenerate = true) - { - $tmpfile = tempnam(_PS_TMP_IMG_DIR_, 'ps_import'); - $watermark_types = explode(',', Configuration::get('WATERMARK_TYPES')); + switch ($entity) { + default: + case 'products': + $image_obj = new Image($id_image); + $path = $image_obj->getPathForCreation(); + break; + case 'categories': + $path = _PS_CAT_IMG_DIR_.(int)$id_entity; + break; + case 'manufacturers': + $path = _PS_MANU_IMG_DIR_.(int)$id_entity; + break; + case 'suppliers': + $path = _PS_SUPP_IMG_DIR_.(int)$id_entity; + break; + } - switch ($entity) - { - default: - case 'products': - $image_obj = new Image($id_image); - $path = $image_obj->getPathForCreation(); - break; - case 'categories': - $path = _PS_CAT_IMG_DIR_.(int)$id_entity; - break; - case 'manufacturers': - $path = _PS_MANU_IMG_DIR_.(int)$id_entity; - break; - case 'suppliers': - $path = _PS_SUPP_IMG_DIR_.(int)$id_entity; - break; - } + $url = urldecode(trim($url)); + $parced_url = parse_url($url); - $url = str_replace(' ', '%20', trim($url)); - $url = urldecode($url); - $parced_url = parse_url($url); + if (isset($parced_url['path'])) { + $uri = ltrim($parced_url['path'], '/'); + $parts = explode('/', $uri); + foreach ($parts as &$part) { + $part = rawurlencode($part); + } + unset($part); + $parced_url['path'] = '/'.implode('/', $parts); + } - if (isset($parced_url['path'])) - { - $uri = ltrim($parced_url['path'], '/'); - $parts = explode('/', $uri); - foreach ($parts as &$part) - $part = urlencode ($part); - unset($part); - $parced_url['path'] = '/'.implode('/', $parts); - } + if (isset($parced_url['query'])) { + $query_parts = array(); + parse_str($parced_url['query'], $query_parts); + $parced_url['query'] = http_build_query($query_parts); + } - if (isset($parced_url['query'])) - { - $query_parts = array(); - parse_str($parced_url['query'], $query_parts); - $parced_url['query'] = http_build_query($query_parts); - } + if (!function_exists('http_build_url')) { + require_once(_PS_TOOL_DIR_.'http_build_url/http_build_url.php'); + } - if (!function_exists('http_build_url')) - require_once(_PS_TOOL_DIR_.'http_build_url/http_build_url.php'); + $url = http_build_url('', $parced_url); - $url = http_build_url('', $parced_url); + $orig_tmpfile = $tmpfile; - // Evaluate the memory required to resize the image: if it's too much, you can't resize it. - if (!ImageManager::checkImageMemoryLimit($url)) - return false; + if (Tools::copy($url, $tmpfile)) { + // Evaluate the memory required to resize the image: if it's too much, you can't resize it. + if (!ImageManager::checkImageMemoryLimit($tmpfile)) { + @unlink($tmpfile); + return false; + } - $orig_tmpfile = $tmpfile; + $tgt_width = $tgt_height = 0; + $src_width = $src_height = 0; + $error = 0; + ImageManager::resize($tmpfile, $path.'.jpg', null, null, 'jpg', false, $error, $tgt_width, $tgt_height, 5, + $src_width, $src_height); + $images_types = ImageType::getImagesTypes($entity, true); - // 'file_exists' doesn't work on distant file, and getimagesize makes the import slower. - // Just hide the warning, the processing will be the same. - if (Tools::copy($url, $tmpfile)) - { - $tgt_width = $tgt_height = 0; - $src_width = $src_height = 0; - $error = 0; - ImageManager::resize($tmpfile, $path.'.jpg', null, null, 'jpg', false, $error, $tgt_width, $tgt_height, 5, - $src_width, $src_height); - $images_types = ImageType::getImagesTypes($entity, true); + if ($regenerate) { + $previous_path = null; + $path_infos = array(); + $path_infos[] = array($tgt_width, $tgt_height, $path.'.jpg'); + foreach ($images_types as $image_type) { + $tmpfile = self::get_best_path($image_type['width'], $image_type['height'], $path_infos); - if ($regenerate) - { - $previous_path = null; - $path_infos = array(); - $path_infos[] = array($tgt_width, $tgt_height, $path.'.jpg'); - foreach ($images_types as $image_type) - { - $tmpfile = self::get_best_path($image_type['width'], $image_type['height'], $path_infos); + if (ImageManager::resize($tmpfile, $path.'-'.stripslashes($image_type['name']).'.jpg', $image_type['width'], + $image_type['height'], 'jpg', false, $error, $tgt_width, $tgt_height, 5, + $src_width, $src_height)) { + // the last image should not be added in the candidate list if it's bigger than the original image + if ($tgt_width <= $src_width && $tgt_height <= $src_height) { + $path_infos[] = array($tgt_width, $tgt_height, $path.'-'.stripslashes($image_type['name']).'.jpg'); + } + } + if (in_array($image_type['id_image_type'], $watermark_types)) { + Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_entity)); + } + } + } + } else { + @unlink($orig_tmpfile); + return false; + } + unlink($orig_tmpfile); + return true; + } - if (ImageManager::resize($tmpfile, $path.'-'.stripslashes($image_type['name']).'.jpg', $image_type['width'], - $image_type['height'], 'jpg', false, $error, $tgt_width, $tgt_height, 5, - $src_width, $src_height)) - { - // the last image should not be added in the candidate list if it's bigger than the original image - if ($tgt_width <= $src_width && $tgt_height <= $src_height) - $path_infos[] = array($tgt_width, $tgt_height, $path.'-'.stripslashes($image_type['name']).'.jpg'); - } - if (in_array($image_type['id_image_type'], $watermark_types)) - Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_entity)); - } - } - } - else - { - @unlink($orig_tmpfile); - return false; - } - unlink($orig_tmpfile); - return true; - } + private static function get_best_path($tgt_width, $tgt_height, $path_infos) + { + $path_infos = array_reverse($path_infos); + $path = ''; + foreach ($path_infos as $path_info) { + list($width, $height, $path) = $path_info; + if ($width >= $tgt_width && $height >= $tgt_height) { + return $path; + } + } + return $path; + } - private static function get_best_path($tgt_width, $tgt_height, $path_infos) - { - $path_infos = array_reverse($path_infos); - $path = ''; - foreach($path_infos as $path_info) - { - list($width, $height, $path) = $path_info; - if ($width >= $tgt_width && $height >= $tgt_height) - return $path; - } - return $path; - } + public function categoryImport() + { + $cat_moved = array(); - public function categoryImport() - { - $cat_moved = array(); + $this->receiveTab(); + $handle = $this->openCsvFile(); + $default_language_id = (int)Configuration::get('PS_LANG_DEFAULT'); + $id_lang = Language::getIdByIso(Tools::getValue('iso_lang')); + if (!Validate::isUnsignedId($id_lang)) { + $id_lang = $default_language_id; + } + AdminImportController::setLocale(); - $this->receiveTab(); - $handle = $this->openCsvFile(); - $default_language_id = (int)Configuration::get('PS_LANG_DEFAULT'); - $id_lang = Language::getIdByIso(Tools::getValue('iso_lang')); - if (!Validate::isUnsignedId($id_lang)) - $id_lang = $default_language_id; - AdminImportController::setLocale(); + $convert = Tools::getValue('convert'); + $force_ids = Tools::getValue('forceIDs'); + $regenerate = Tools::getValue('regenerate'); + $shop_is_feature_active = Shop::isFeatureActive(); - $convert = Tools::getValue('convert'); - $force_ids = Tools::getValue('forceIDs'); - $regenerate = Tools::getValue('regenerate'); - $shop_is_feature_active = Shop::isFeatureActive(); + for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) { + if ($convert) { + $line = $this->utf8EncodeArray($line); + } + $info = AdminImportController::getMaskedRow($line); - for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) - { - if ($convert) - $line = $this->utf8EncodeArray($line); - $info = AdminImportController::getMaskedRow($line); + $tab_categ = array(Configuration::get('PS_HOME_CATEGORY'), Configuration::get('PS_ROOT_CATEGORY')); + if (isset($info['id']) && in_array((int)$info['id'], $tab_categ)) { + $this->errors[] = Tools::displayError('The category ID cannot be the same as the Root category ID or the Home category ID.'); + continue; + } + AdminImportController::setDefaultValues($info); - $tab_categ = array(Configuration::get('PS_HOME_CATEGORY'), Configuration::get('PS_ROOT_CATEGORY')); - if (isset($info['id']) && in_array((int)$info['id'], $tab_categ)) - { - $this->errors[] = Tools::displayError('The category ID cannot be the same as the Root category ID or the Home category ID.'); - continue; - } - AdminImportController::setDefaultValues($info); + if ($force_ids && isset($info['id']) && (int)$info['id']) { + $category = new Category((int)$info['id']); + } else { + if (isset($info['id']) && (int)$info['id'] && Category::existsInDatabase((int)$info['id'], 'category')) { + $category = new Category((int)$info['id']); + } else { + $category = new Category(); + } + } - if ($force_ids && isset($info['id']) && (int)$info['id']) - $category = new Category((int)$info['id']); - else - { - if (isset($info['id']) && (int)$info['id'] && Category::existsInDatabase((int)$info['id'], 'category')) - $category = new Category((int)$info['id']); - else - $category = new Category(); - } + AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $category); - AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $category); + if (isset($category->parent) && is_numeric($category->parent)) { + if (isset($cat_moved[$category->parent])) { + $category->parent = $cat_moved[$category->parent]; + } + $category->id_parent = $category->parent; + } elseif (isset($category->parent) && is_string($category->parent)) { + $category_parent = Category::searchByName($id_lang, $category->parent, true); + if ($category_parent['id_category']) { + $category->id_parent = (int)$category_parent['id_category']; + $category->level_depth = (int)$category_parent['level_depth'] + 1; + } else { + $category_to_create = new Category(); + $category_to_create->name = AdminImportController::createMultiLangField($category->parent); + $category_to_create->active = 1; + $category_link_rewrite = Tools::link_rewrite($category_to_create->name[$id_lang]); + $category_to_create->link_rewrite = AdminImportController::createMultiLangField($category_link_rewrite); + $category_to_create->id_parent = Configuration::get('PS_HOME_CATEGORY'); // Default parent is home for unknown category to create + if (($field_error = $category_to_create->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $category_to_create->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $category_to_create->add()) { + $category->id_parent = $category_to_create->id; + Cache::clean('Category::searchByName_'.$category->parent); + } else { + $this->errors[] = sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + $category_to_create->name[$id_lang], + (isset($category_to_create->id) && !empty($category_to_create->id))? $category_to_create->id : 'null' + ); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). + Db::getInstance()->getMsgError(); + } + } + } + if (isset($category->link_rewrite) && !empty($category->link_rewrite[$default_language_id])) { + $valid_link = Validate::isLinkRewrite($category->link_rewrite[$default_language_id]); + } else { + $valid_link = false; + } - if (isset($category->parent) && is_numeric($category->parent)) - { - if (isset($cat_moved[$category->parent])) - $category->parent = $cat_moved[$category->parent]; - $category->id_parent = $category->parent; - } - elseif (isset($category->parent) && is_string($category->parent)) - { - $category_parent = Category::searchByName($id_lang, $category->parent, true); - if ($category_parent['id_category']) - { - $category->id_parent = (int)$category_parent['id_category']; - $category->level_depth = (int)$category_parent['level_depth'] + 1; - } - else - { - $category_to_create = new Category(); - $category_to_create->name = AdminImportController::createMultiLangField($category->parent); - $category_to_create->active = 1; - $category_link_rewrite = Tools::link_rewrite($category_to_create->name[$id_lang]); - $category_to_create->link_rewrite = AdminImportController::createMultiLangField($category_link_rewrite); - $category_to_create->id_parent = Configuration::get('PS_HOME_CATEGORY'); // Default parent is home for unknown category to create - if (($field_error = $category_to_create->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $category_to_create->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $category_to_create->add()) - $category->id_parent = $category_to_create->id; - else - { - $this->errors[] = sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - $category_to_create->name[$id_lang], - (isset($category_to_create->id) && !empty($category_to_create->id))? $category_to_create->id : 'null' - ); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). - Db::getInstance()->getMsgError(); - } - } - } - if (isset($category->link_rewrite) && !empty($category->link_rewrite[$default_language_id])) - $valid_link = Validate::isLinkRewrite($category->link_rewrite[$default_language_id]); - else - $valid_link = false; + if (!$shop_is_feature_active) { + $category->id_shop_default = 1; + } else { + $category->id_shop_default = (int)Context::getContext()->shop->id; + } - if (!$shop_is_feature_active) - $category->id_shop_default = 1; - else - $category->id_shop_default = (int)Context::getContext()->shop->id; + $bak = $category->link_rewrite[$default_language_id]; + if ((isset($category->link_rewrite) && empty($category->link_rewrite[$default_language_id])) || !$valid_link) { + $category->link_rewrite = Tools::link_rewrite($category->name[$default_language_id]); + if ($category->link_rewrite == '') { + $category->link_rewrite = 'friendly-url-autogeneration-failed'; + $this->warnings[] = sprintf(Tools::displayError('URL rewriting failed to auto-generate a friendly URL for: %s'), $category->name[$default_language_id]); + } + $category->link_rewrite = AdminImportController::createMultiLangField($category->link_rewrite); + } - $bak = $category->link_rewrite[$default_language_id]; - if ((isset($category->link_rewrite) && empty($category->link_rewrite[$default_language_id])) || !$valid_link) - { - $category->link_rewrite = Tools::link_rewrite($category->name[$default_language_id]); - if ($category->link_rewrite == '') - { - $category->link_rewrite = 'friendly-url-autogeneration-failed'; - $this->warnings[] = sprintf(Tools::displayError('URL rewriting failed to auto-generate a friendly URL for: %s'), $category->name[$default_language_id]); - } - $category->link_rewrite = AdminImportController::createMultiLangField($category->link_rewrite); - } + if (!$valid_link) { + $this->warnings[] = sprintf( + Tools::displayError('Rewrite link for %1$s (ID: %2$s) was re-written as %3$s.'), + $bak, + (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null', + $category->link_rewrite[$default_language_id] + ); + } + $res = false; + if (($field_error = $category->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $category->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && empty($this->errors)) { + $category_already_created = Category::searchByNameAndParentCategoryId( + $id_lang, + $category->name[$id_lang], + $category->id_parent + ); - if (!$valid_link) - $this->warnings[] = sprintf( - Tools::displayError('Rewrite link for %1$s (ID: %2$s) was re-written as %3$s.'), - $bak, - (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null', - $category->link_rewrite[$default_language_id] - ); - $res = false; - if (($field_error = $category->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $category->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && empty($this->errors)) - { - $category_already_created = Category::searchByNameAndParentCategoryId( - $id_lang, - $category->name[$id_lang], - $category->id_parent - ); + // If category already in base, get id category back + if ($category_already_created['id_category']) { + $cat_moved[$category->id] = (int)$category_already_created['id_category']; + $category->id = (int)$category_already_created['id_category']; + if (Validate::isDate($category_already_created['date_add'])) { + $category->date_add = $category_already_created['date_add']; + } + } - // If category already in base, get id category back - if ($category_already_created['id_category']) - { - $cat_moved[$category->id] = (int)$category_already_created['id_category']; - $category->id = (int)$category_already_created['id_category']; - if (Validate::isDate($category_already_created['date_add'])) - $category->date_add = $category_already_created['date_add']; - } + if ($category->id && $category->id == $category->id_parent) { + $this->errors[] = Tools::displayError('A category cannot be its own parent'); + continue; + } - if ($category->id && $category->id == $category->id_parent) - { - $this->errors[] = Tools::displayError('A category cannot be its own parent'); - continue; - } + /* No automatic nTree regeneration for import */ + $category->doNotRegenerateNTree = true; - /* No automatic nTree regeneration for import */ - $category->doNotRegenerateNTree = true; - - // If id category AND id category already in base, trying to update - $categories_home_root = array(Configuration::get('PS_ROOT_CATEGORY'), Configuration::get('PS_HOME_CATEGORY')); - if ($category->id && $category->categoryExists($category->id) && !in_array($category->id, $categories_home_root)) - $res = $category->update(); - if ($category->id == Configuration::get('PS_ROOT_CATEGORY')) - $this->errors[] = Tools::displayError('The root category cannot be modified.'); - // If no id_category or update failed - $category->force_id = (bool)$force_ids; - if (!$res) - $res = $category->add(); - } - //copying images of categories - if (isset($category->image) && !empty($category->image)) - if (!(AdminImportController::copyImg($category->id, null, $category->image, 'categories', !$regenerate))) - $this->warnings[] = $category->image.' '.Tools::displayError('cannot be copied.'); - // If both failed, mysql error - if (!$res) - { - $this->errors[] = sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - (isset($info['name']) && !empty($info['name']))? Tools::safeOutput($info['name']) : 'No Name', - (isset($info['id']) && !empty($info['id']))? Tools::safeOutput($info['id']) : 'No ID' - ); - $error_tmp = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').Db::getInstance()->getMsgError(); - if ($error_tmp != '') - $this->errors[] = $error_tmp; - } - else - { - // Associate category to shop - if ($shop_is_feature_active) - { - Db::getInstance()->execute(' + // If id category AND id category already in base, trying to update + $categories_home_root = array(Configuration::get('PS_ROOT_CATEGORY'), Configuration::get('PS_HOME_CATEGORY')); + if ($category->id && $category->categoryExists($category->id) && !in_array($category->id, $categories_home_root)) { + $res = $category->update(); + } + if ($category->id == Configuration::get('PS_ROOT_CATEGORY')) { + $this->errors[] = Tools::displayError('The root category cannot be modified.'); + } + // If no id_category or update failed + $category->force_id = (bool)$force_ids; + if (!$res) { + $res = $category->add(); + } + } + //copying images of categories + if (isset($category->image) && !empty($category->image)) { + if (!(AdminImportController::copyImg($category->id, null, $category->image, 'categories', !$regenerate))) { + $this->warnings[] = $category->image.' '.Tools::displayError('cannot be copied.'); + } + } + // If both failed, mysql error + if (!$res) { + $this->errors[] = sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + (isset($info['name']) && !empty($info['name']))? Tools::safeOutput($info['name']) : 'No Name', + (isset($info['id']) && !empty($info['id']))? Tools::safeOutput($info['id']) : 'No ID' + ); + $error_tmp = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').Db::getInstance()->getMsgError(); + if ($error_tmp != '') { + $this->errors[] = $error_tmp; + } + } else { + // Associate category to shop + if ($shop_is_feature_active) { + Db::getInstance()->execute(' DELETE FROM '._DB_PREFIX_.'category_shop WHERE id_category = '.(int)$category->id - ); + ); - if (!$shop_is_feature_active) - $info['shop'] = 1; - elseif (!isset($info['shop']) || empty($info['shop'])) - $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID()); + if (!$shop_is_feature_active) { + $info['shop'] = 1; + } elseif (!isset($info['shop']) || empty($info['shop'])) { + $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID()); + } - // Get shops for each attributes - $info['shop'] = explode($this->multiple_value_separator, $info['shop']); + // Get shops for each attributes + $info['shop'] = explode($this->multiple_value_separator, $info['shop']); - foreach ($info['shop'] as $shop) - if (!empty($shop) && !is_numeric($shop)) - $category->addShop(Shop::getIdByName($shop)); - elseif (!empty($shop)) - $category->addShop($shop); - } - } - } + foreach ($info['shop'] as $shop) { + if (!empty($shop) && !is_numeric($shop)) { + $category->addShop(Shop::getIdByName($shop)); + } elseif (!empty($shop)) { + $category->addShop($shop); + } + } + } + } + } - /* Import has finished, we can regenerate the categories nested tree */ - Category::regenerateEntireNtree(); + /* Import has finished, we can regenerate the categories nested tree */ + Category::regenerateEntireNtree(); - $this->closeCsvFile($handle); - } + $this->closeCsvFile($handle); + } - public function productImport() - { - if (!defined('PS_MASS_PRODUCT_CREATION')) - define('PS_MASS_PRODUCT_CREATION', true); + public function productImport() + { + if (!defined('PS_MASS_PRODUCT_CREATION')) { + define('PS_MASS_PRODUCT_CREATION', true); + } - $this->receiveTab(); - $handle = $this->openCsvFile(); - $default_language_id = (int)Configuration::get('PS_LANG_DEFAULT'); - $id_lang = Language::getIdByIso(Tools::getValue('iso_lang')); - if (!Validate::isUnsignedId($id_lang)) - $id_lang = $default_language_id; - AdminImportController::setLocale(); - $shop_ids = Shop::getCompleteListOfShopsID(); + $this->receiveTab(); + $handle = $this->openCsvFile(); + $default_language_id = (int)Configuration::get('PS_LANG_DEFAULT'); + $id_lang = Language::getIdByIso(Tools::getValue('iso_lang')); + if (!Validate::isUnsignedId($id_lang)) { + $id_lang = $default_language_id; + } + AdminImportController::setLocale(); + $shop_ids = Shop::getCompleteListOfShopsID(); - $convert = Tools::getValue('convert'); - $force_ids = Tools::getValue('forceIDs'); - $match_ref = Tools::getValue('match_ref'); - $regenerate = Tools::getValue('regenerate'); - $shop_is_feature_active = Shop::isFeatureActive(); - Module::setBatchMode(true); + $convert = Tools::getValue('convert'); + $force_ids = Tools::getValue('forceIDs'); + $match_ref = Tools::getValue('match_ref'); + $regenerate = Tools::getValue('regenerate'); + $shop_is_feature_active = Shop::isFeatureActive(); + Module::setBatchMode(true); - for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) - { - if ($convert) - $line = $this->utf8EncodeArray($line); - $info = AdminImportController::getMaskedRow($line); + for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) { + if ($convert) { + $line = $this->utf8EncodeArray($line); + } + $info = AdminImportController::getMaskedRow($line); - if ($force_ids && isset($info['id']) && (int)$info['id']) - $product = new Product((int)$info['id']); - elseif ($match_ref && array_key_exists('reference', $info)) - { - $datas = Db::getInstance()->getRow(' + if ($force_ids && isset($info['id']) && (int)$info['id']) { + $product = new Product((int)$info['id']); + } elseif ($match_ref && array_key_exists('reference', $info)) { + $datas = Db::getInstance()->getRow(' SELECT p.`id_product` FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' WHERE p.`reference` = "'.pSQL($info['reference']).'" ', false); - if (isset($datas['id_product']) && $datas['id_product']) - $product = new Product((int)$datas['id_product']); - else - $product = new Product(); - } - elseif (array_key_exists('id', $info) && (int)$info['id'] && Product::existsInDatabase((int)$info['id'], 'product')) - $product = new Product((int)$info['id']); - else - $product = new Product(); + if (isset($datas['id_product']) && $datas['id_product']) { + $product = new Product((int)$datas['id_product']); + } else { + $product = new Product(); + } + } elseif (array_key_exists('id', $info) && (int)$info['id'] && Product::existsInDatabase((int)$info['id'], 'product')) { + $product = new Product((int)$info['id']); + } else { + $product = new Product(); + } - $update_advanced_stock_management_value = false; - if (isset($product->id) && $product->id && Product::existsInDatabase((int)$product->id, 'product')) - { - $product->loadStockData(); - $update_advanced_stock_management_value = true; - $category_data = Product::getProductCategories((int)$product->id); + $update_advanced_stock_management_value = false; + if (isset($product->id) && $product->id && Product::existsInDatabase((int)$product->id, 'product')) { + $product->loadStockData(); + $update_advanced_stock_management_value = true; + $category_data = Product::getProductCategories((int)$product->id); - if (is_array($category_data)) - foreach ($category_data as $tmp) - if (!isset($product->category) || !$product->category || is_array($product->category)) - $product->category[] = $tmp; - } + if (is_array($category_data)) { + foreach ($category_data as $tmp) { + if (!isset($product->category) || !$product->category || is_array($product->category)) { + $product->category[] = $tmp; + } + } + } + } - AdminImportController::setEntityDefaultValues($product); - AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $product); + AdminImportController::setEntityDefaultValues($product); + AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $product); - if (!$shop_is_feature_active) - $product->shop = (int)Configuration::get('PS_SHOP_DEFAULT'); - elseif (!isset($product->shop) || empty($product->shop)) - $product->shop = implode($this->multiple_value_separator, Shop::getContextListShopID()); + if (!$shop_is_feature_active) { + $product->shop = (int)Configuration::get('PS_SHOP_DEFAULT'); + } elseif (!isset($product->shop) || empty($product->shop)) { + $product->shop = implode($this->multiple_value_separator, Shop::getContextListShopID()); + } - if (!$shop_is_feature_active) - $product->id_shop_default = (int)Configuration::get('PS_SHOP_DEFAULT'); - else - $product->id_shop_default = (int)Context::getContext()->shop->id; + if (!$shop_is_feature_active) { + $product->id_shop_default = (int)Configuration::get('PS_SHOP_DEFAULT'); + } else { + $product->id_shop_default = (int)Context::getContext()->shop->id; + } - // link product to shops - $product->id_shop_list = array(); - foreach (explode($this->multiple_value_separator, $product->shop) as $shop) - if (!empty($shop) && !is_numeric($shop)) - $product->id_shop_list[] = Shop::getIdByName($shop); - elseif (!empty($shop)) - $product->id_shop_list[] = $shop; + // link product to shops + $product->id_shop_list = array(); + foreach (explode($this->multiple_value_separator, $product->shop) as $shop) { + if (!empty($shop) && !is_numeric($shop)) { + $product->id_shop_list[] = Shop::getIdByName($shop); + } elseif (!empty($shop)) { + $product->id_shop_list[] = $shop; + } + } - if ((int)$product->id_tax_rules_group != 0) - { - if (Validate::isLoadedObject(new TaxRulesGroup($product->id_tax_rules_group))) - { - $address = $this->context->shop->getAddress(); - $tax_manager = TaxManagerFactory::getManager($address, $product->id_tax_rules_group); - $product_tax_calculator = $tax_manager->getTaxCalculator(); - $product->tax_rate = $product_tax_calculator->getTotalRate(); - } - else - $this->addProductWarning( - 'id_tax_rules_group', - $product->id_tax_rules_group, - Tools::displayError('Invalid tax rule group ID. You first need to create a group with this ID.') - ); - } - if (isset($product->manufacturer) && is_numeric($product->manufacturer) && Manufacturer::manufacturerExists((int)$product->manufacturer)) - $product->id_manufacturer = (int)$product->manufacturer; - elseif (isset($product->manufacturer) && is_string($product->manufacturer) && !empty($product->manufacturer)) - { - if ($manufacturer = Manufacturer::getIdByName($product->manufacturer)) - $product->id_manufacturer = (int)$manufacturer; - else - { - $manufacturer = new Manufacturer(); - $manufacturer->name = $product->manufacturer; - $manufacturer->active = true; + if ((int)$product->id_tax_rules_group != 0) { + if (Validate::isLoadedObject(new TaxRulesGroup($product->id_tax_rules_group))) { + $address = $this->context->shop->getAddress(); + $tax_manager = TaxManagerFactory::getManager($address, $product->id_tax_rules_group); + $product_tax_calculator = $tax_manager->getTaxCalculator(); + $product->tax_rate = $product_tax_calculator->getTotalRate(); + } else { + $this->addProductWarning( + 'id_tax_rules_group', + $product->id_tax_rules_group, + Tools::displayError('Invalid tax rule group ID. You first need to create a group with this ID.') + ); + } + } + if (isset($product->manufacturer) && is_numeric($product->manufacturer) && Manufacturer::manufacturerExists((int)$product->manufacturer)) { + $product->id_manufacturer = (int)$product->manufacturer; + } elseif (isset($product->manufacturer) && is_string($product->manufacturer) && !empty($product->manufacturer)) { + if ($manufacturer = Manufacturer::getIdByName($product->manufacturer)) { + $product->id_manufacturer = (int)$manufacturer; + } else { + $manufacturer = new Manufacturer(); + $manufacturer->name = $product->manufacturer; + $manufacturer->active = true; - if (($field_error = $manufacturer->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $manufacturer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $manufacturer->add()) - { - $product->id_manufacturer = (int)$manufacturer->id; - $manufacturer->associateTo($product->id_shop_list); - } - else - { - $this->errors[] = sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - $manufacturer->name, - (isset($manufacturer->id) && !empty($manufacturer->id))? $manufacturer->id : 'null' - ); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). - Db::getInstance()->getMsgError(); - } - } - } + if (($field_error = $manufacturer->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $manufacturer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $manufacturer->add()) { + $product->id_manufacturer = (int)$manufacturer->id; + $manufacturer->associateTo($product->id_shop_list); + } else { + $this->errors[] = sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + $manufacturer->name, + (isset($manufacturer->id) && !empty($manufacturer->id))? $manufacturer->id : 'null' + ); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). + Db::getInstance()->getMsgError(); + } + } + } - if (isset($product->supplier) && is_numeric($product->supplier) && Supplier::supplierExists((int)$product->supplier)) - $product->id_supplier = (int)$product->supplier; - elseif (isset($product->supplier) && is_string($product->supplier) && !empty($product->supplier)) - { - if ($supplier = Supplier::getIdByName($product->supplier)) - $product->id_supplier = (int)$supplier; - else - { - $supplier = new Supplier(); - $supplier->name = $product->supplier; - $supplier->active = true; + if (isset($product->supplier) && is_numeric($product->supplier) && Supplier::supplierExists((int)$product->supplier)) { + $product->id_supplier = (int)$product->supplier; + } elseif (isset($product->supplier) && is_string($product->supplier) && !empty($product->supplier)) { + if ($supplier = Supplier::getIdByName($product->supplier)) { + $product->id_supplier = (int)$supplier; + } else { + $supplier = new Supplier(); + $supplier->name = $product->supplier; + $supplier->active = true; - if (($field_error = $supplier->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $supplier->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $supplier->add()) - { - $product->id_supplier = (int)$supplier->id; - $supplier->associateTo($product->id_shop_list); - } - else - { - $this->errors[] = sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - $supplier->name, - (isset($supplier->id) && !empty($supplier->id))? $supplier->id : 'null' - ); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). - Db::getInstance()->getMsgError(); - } - } - } + if (($field_error = $supplier->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $supplier->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $supplier->add()) { + $product->id_supplier = (int)$supplier->id; + $supplier->associateTo($product->id_shop_list); + } else { + $this->errors[] = sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + $supplier->name, + (isset($supplier->id) && !empty($supplier->id))? $supplier->id : 'null' + ); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). + Db::getInstance()->getMsgError(); + } + } + } - if (isset($product->price_tex) && !isset($product->price_tin)) - $product->price = $product->price_tex; - elseif (isset($product->price_tin) && !isset($product->price_tex)) - { - $product->price = $product->price_tin; - // If a tax is already included in price, withdraw it from price - if ($product->tax_rate) - $product->price = (float)number_format($product->price / (1 + $product->tax_rate / 100), 6, '.', ''); - } - elseif (isset($product->price_tin) && isset($product->price_tex)) - $product->price = $product->price_tex; + if (isset($product->price_tex) && !isset($product->price_tin)) { + $product->price = $product->price_tex; + } elseif (isset($product->price_tin) && !isset($product->price_tex)) { + $product->price = $product->price_tin; + // If a tax is already included in price, withdraw it from price + if ($product->tax_rate) { + $product->price = (float)number_format($product->price / (1 + $product->tax_rate / 100), 6, '.', ''); + } + } elseif (isset($product->price_tin) && isset($product->price_tex)) { + $product->price = $product->price_tex; + } - if (!Configuration::get('PS_USE_ECOTAX')) - $product->ecotax = 0; + if (!Configuration::get('PS_USE_ECOTAX')) { + $product->ecotax = 0; + } - if (isset($product->category) && is_array($product->category) && count($product->category)) - { - $product->id_category = array(); // Reset default values array - foreach ($product->category as $value) - { - if (is_numeric($value)) - { - if (Category::categoryExists((int)$value)) - $product->id_category[] = (int)$value; - else - { - $category_to_create = new Category(); - $category_to_create->id = (int)$value; - $category_to_create->name = AdminImportController::createMultiLangField($value); - $category_to_create->active = 1; - $category_to_create->id_parent = Configuration::get('PS_HOME_CATEGORY'); // Default parent is home for unknown category to create - $category_link_rewrite = Tools::link_rewrite($category_to_create->name[$default_language_id]); - $category_to_create->link_rewrite = AdminImportController::createMultiLangField($category_link_rewrite); - if (($field_error = $category_to_create->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $category_to_create->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $category_to_create->add()) - $product->id_category[] = (int)$category_to_create->id; - else - { - $this->errors[] = sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - $category_to_create->name[$default_language_id], - (isset($category_to_create->id) && !empty($category_to_create->id))? $category_to_create->id : 'null' - ); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). - Db::getInstance()->getMsgError(); - } - } - } - elseif (is_string($value) && !empty($value)) - { - $category = Category::searchByPath($default_language_id, trim($value), $this, 'productImportCreateCat'); - if ($category['id_category']) - $product->id_category[] = (int)$category['id_category']; - else - $this->errors[] = sprintf(Tools::displayError('%1$s cannot be saved'), trim($value)); - } - } - $product->id_category = array_values(array_unique($product->id_category)); - } + if (isset($product->category) && is_array($product->category) && count($product->category)) { + $product->id_category = array(); // Reset default values array + foreach ($product->category as $value) { + if (is_numeric($value)) { + if (Category::categoryExists((int)$value)) { + $product->id_category[] = (int)$value; + } else { + $category_to_create = new Category(); + $category_to_create->id = (int)$value; + $category_to_create->name = AdminImportController::createMultiLangField($value); + $category_to_create->active = 1; + $category_to_create->id_parent = Configuration::get('PS_HOME_CATEGORY'); // Default parent is home for unknown category to create + $category_link_rewrite = Tools::link_rewrite($category_to_create->name[$default_language_id]); + $category_to_create->link_rewrite = AdminImportController::createMultiLangField($category_link_rewrite); + if (($field_error = $category_to_create->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $category_to_create->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $category_to_create->add()) { + $product->id_category[] = (int)$category_to_create->id; + } else { + $this->errors[] = sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + $category_to_create->name[$default_language_id], + (isset($category_to_create->id) && !empty($category_to_create->id))? $category_to_create->id : 'null' + ); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). + Db::getInstance()->getMsgError(); + } + } + } elseif (is_string($value) && !empty($value)) { + $category = Category::searchByPath($default_language_id, trim($value), $this, 'productImportCreateCat'); + if ($category['id_category']) { + $product->id_category[] = (int)$category['id_category']; + } else { + $this->errors[] = sprintf(Tools::displayError('%1$s cannot be saved'), trim($value)); + } + } + } + $product->id_category = array_values(array_unique($product->id_category)); + + // Will update default category if category column is not ignored AND if there is categories that are set in the import file row. + if (isset($product->id_category[0])) { + $product->id_category_default = (int)$product->id_category[0]; + } else { + $defaultProductShop = new Shop($product->id_shop_default); + $product->id_category_default = Category::getRootCategory(null, Validate::isLoadedObject($defaultProductShop)?$defaultProductShop:null)->id; + } + } - if (!isset($product->id_category_default) || !$product->id_category_default) - $product->id_category_default = isset($product->id_category[0]) ? (int)$product->id_category[0] : (int)Configuration::get('PS_HOME_CATEGORY'); + // Will update default category if there is none set here. Home if no category at all. + if (!isset($product->id_category_default) || !$product->id_category_default) { + // this if will avoid ereasing default category if category column is not present in the CSV file (or ignored) + if (isset($product->id_category[0])) { + $product->id_category_default = (int)$product->id_category[0]; + } else { + $defaultProductShop = new Shop($product->id_shop_default); + $product->id_category_default = Category::getRootCategory(null, Validate::isLoadedObject($defaultProductShop)?$defaultProductShop:null)->id; + } + } - $link_rewrite = (is_array($product->link_rewrite) && isset($product->link_rewrite[$id_lang])) ? trim($product->link_rewrite[$id_lang]) : ''; - $valid_link = Validate::isLinkRewrite($link_rewrite); + $link_rewrite = (is_array($product->link_rewrite) && isset($product->link_rewrite[$id_lang])) ? trim($product->link_rewrite[$id_lang]) : ''; + $valid_link = Validate::isLinkRewrite($link_rewrite); - if ((isset($product->link_rewrite[$id_lang]) && empty($product->link_rewrite[$id_lang])) || !$valid_link) - { - $link_rewrite = Tools::link_rewrite($product->name[$id_lang]); - if ($link_rewrite == '') - $link_rewrite = 'friendly-url-autogeneration-failed'; - } + if ((isset($product->link_rewrite[$id_lang]) && empty($product->link_rewrite[$id_lang])) || !$valid_link) { + $link_rewrite = Tools::link_rewrite($product->name[$id_lang]); + if ($link_rewrite == '') { + $link_rewrite = 'friendly-url-autogeneration-failed'; + } + } - if (!$valid_link) - $this->warnings[] = sprintf( - Tools::displayError('Rewrite link for %1$s (ID: %2$s) was re-written as %3$s.'), - $product->name[$id_lang], - (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null', - $link_rewrite - ); + if (!$valid_link) { + $this->warnings[] = sprintf( + Tools::displayError('Rewrite link for %1$s (ID: %2$s) was re-written as %3$s.'), + $product->name[$id_lang], + (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null', + $link_rewrite + ); + } - if (!($match_ref || $force_ids) || !(is_array($product->link_rewrite) && count($product->link_rewrite) && !empty($product->link_rewrite[$id_lang]))) - $product->link_rewrite = AdminImportController::createMultiLangField($link_rewrite); + if (!($match_ref || $force_ids) || !(is_array($product->link_rewrite) && count($product->link_rewrite) && !empty($product->link_rewrite[$id_lang]))) { + $product->link_rewrite = AdminImportController::createMultiLangField($link_rewrite); + } - // replace the value of separator by coma - if ($this->multiple_value_separator != ',') - if (is_array($product->meta_keywords)) - foreach ($product->meta_keywords as &$meta_keyword) - if (!empty($meta_keyword)) - $meta_keyword = str_replace($this->multiple_value_separator, ',', $meta_keyword); + // replace the value of separator by coma + if ($this->multiple_value_separator != ',') { + if (is_array($product->meta_keywords)) { + foreach ($product->meta_keywords as &$meta_keyword) { + if (!empty($meta_keyword)) { + $meta_keyword = str_replace($this->multiple_value_separator, ',', $meta_keyword); + } + } + } + } - // Convert comma into dot for all floating values - foreach (Product::$definition['fields'] as $key => $array) - if ($array['type'] == Product::TYPE_FLOAT) - $product->{$key} = str_replace(',', '.', $product->{$key}); + // Convert comma into dot for all floating values + foreach (Product::$definition['fields'] as $key => $array) { + if ($array['type'] == Product::TYPE_FLOAT) { + $product->{$key} = str_replace(',', '.', $product->{$key}); + } + } - // Indexation is already 0 if it's a new product, but not if it's an update - $product->indexed = 0; + // Indexation is already 0 if it's a new product, but not if it's an update + $product->indexed = 0; + $productExistsInDatabase = false; - $res = false; - $field_error = $product->validateFields(UNFRIENDLY_ERROR, true); - $lang_field_error = $product->validateFieldsLang(UNFRIENDLY_ERROR, true); - if ($field_error === true && $lang_field_error === true) - { - // check quantity - if ($product->quantity == null) - $product->quantity = 0; + if ($product->id && Product::existsInDatabase((int)$product->id, 'product')) { + $productExistsInDatabase = true; + } - // If match ref is specified && ref product && ref product already in base, trying to update - if ($match_ref && $product->reference && $product->existsRefInDatabase($product->reference)) - { - $datas = Db::getInstance()->getRow(' + if (($match_ref && $product->reference && $product->existsRefInDatabase($product->reference)) || $productExistsInDatabase) { + $product->date_upd = date('Y-m-d H:i:s'); + } + + $res = false; + $field_error = $product->validateFields(UNFRIENDLY_ERROR, true); + $lang_field_error = $product->validateFieldsLang(UNFRIENDLY_ERROR, true); + if ($field_error === true && $lang_field_error === true) { + // check quantity + if ($product->quantity == null) { + $product->quantity = 0; + } + + // If match ref is specified && ref product && ref product already in base, trying to update + if ($match_ref && $product->reference && $product->existsRefInDatabase($product->reference)) { + $datas = Db::getInstance()->getRow(' SELECT product_shop.`date_add`, p.`id_product` FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' WHERE p.`reference` = "'.pSQL($product->reference).'" ', false); - $product->id = (int)$datas['id_product']; - $product->date_add = pSQL($datas['date_add']); - $res = $product->update(); - } // Else If id product && id product already in base, trying to update - elseif ($product->id && Product::existsInDatabase((int)$product->id, 'product')) - { - $datas = Db::getInstance()->getRow(' + $product->id = (int)$datas['id_product']; + $product->date_add = pSQL($datas['date_add']); + $res = $product->update(); + } // Else If id product && id product already in base, trying to update + elseif ($productExistsInDatabase) { + $datas = Db::getInstance()->getRow(' SELECT product_shop.`date_add` FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' WHERE p.`id_product` = '.(int)$product->id, false); - $product->date_add = pSQL($datas['date_add']); - $res = $product->update(); - } - // If no id_product or update failed - $product->force_id = (bool)$force_ids; + $product->date_add = pSQL($datas['date_add']); + $res = $product->update(); + } + // If no id_product or update failed + $product->force_id = (bool)$force_ids; - if (!$res) - { - if (isset($product->date_add) && $product->date_add != '') - $res = $product->add(false); - else - $res = $product->add(); - } + if (!$res) { + if (isset($product->date_add) && $product->date_add != '') { + $res = $product->add(false); + } else { + $res = $product->add(); + } + } - if ($product->getType() == Product::PTYPE_VIRTUAL) - StockAvailable::setProductOutOfStock((int)$product->id, 1); - else - StockAvailable::setProductOutOfStock((int)$product->id, (int)$product->out_of_stock); + if ($product->getType() == Product::PTYPE_VIRTUAL) { + StockAvailable::setProductOutOfStock((int)$product->id, 1); + } else { + StockAvailable::setProductOutOfStock((int)$product->id, (int)$product->out_of_stock); + } + } - } + $shops = array(); + $product_shop = explode($this->multiple_value_separator, $product->shop); + foreach ($product_shop as $shop) { + if (empty($shop)) { + continue; + } + $shop = trim($shop); + if (!empty($shop) && !is_numeric($shop)) { + $shop = Shop::getIdByName($shop); + } - $shops = array(); - $product_shop = explode($this->multiple_value_separator, $product->shop); - foreach ($product_shop as $shop) - { - if (empty($shop)) - continue; - $shop = trim($shop); - if (!empty($shop) && !is_numeric($shop)) - $shop = Shop::getIdByName($shop); + if (in_array($shop, $shop_ids)) { + $shops[] = $shop; + } else { + $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->l('Shop is not valid')); + } + } + if (empty($shops)) { + $shops = Shop::getContextListShopID(); + } + // If both failed, mysql error + if (!$res) { + $this->errors[] = sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + (isset($info['name']) && !empty($info['name']))? Tools::safeOutput($info['name']) : 'No Name', + (isset($info['id']) && !empty($info['id']))? Tools::safeOutput($info['id']) : 'No ID' + ); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). + Db::getInstance()->getMsgError(); + } else { + // Product supplier + if (isset($product->id) && $product->id && isset($product->id_supplier) && property_exists($product, 'supplier_reference')) { + $id_product_supplier = (int)ProductSupplier::getIdByProductAndSupplier((int)$product->id, 0, (int)$product->id_supplier); + if ($id_product_supplier) { + $product_supplier = new ProductSupplier($id_product_supplier); + } else { + $product_supplier = new ProductSupplier(); + } - if (in_array($shop, $shop_ids)) - $shops[] = $shop; - else - $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->l('Shop is not valid')); - } - if (empty($shops)) - $shops = Shop::getContextListShopID(); - // If both failed, mysql error - if (!$res) - { - $this->errors[] = sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - (isset($info['name']) && !empty($info['name']))? Tools::safeOutput($info['name']) : 'No Name', - (isset($info['id']) && !empty($info['id']))? Tools::safeOutput($info['id']) : 'No ID' - ); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). - Db::getInstance()->getMsgError(); + $product_supplier->id_product = (int)$product->id; + $product_supplier->id_product_attribute = 0; + $product_supplier->id_supplier = (int)$product->id_supplier; + $product_supplier->product_supplier_price_te = $product->wholesale_price; + $product_supplier->product_supplier_reference = $product->supplier_reference; + $product_supplier->save(); + } - } - else - { - // Product supplier - if (isset($product->id) && $product->id && isset($product->id_supplier) && property_exists($product, 'supplier_reference')) - { - $id_product_supplier = (int)ProductSupplier::getIdByProductAndSupplier((int)$product->id, 0, (int)$product->id_supplier); - if ($id_product_supplier) - $product_supplier = new ProductSupplier($id_product_supplier); - else - $product_supplier = new ProductSupplier(); + // SpecificPrice (only the basic reduction feature is supported by the import) + if (!$shop_is_feature_active) { + $info['shop'] = 1; + } elseif (!isset($info['shop']) || empty($info['shop'])) { + $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID()); + } - $product_supplier->id_product = (int)$product->id; - $product_supplier->id_product_attribute = 0; - $product_supplier->id_supplier = (int)$product->id_supplier; - $product_supplier->product_supplier_price_te = $product->wholesale_price; - $product_supplier->product_supplier_reference = $product->supplier_reference; - $product_supplier->save(); - } + // Get shops for each attributes + $info['shop'] = explode($this->multiple_value_separator, $info['shop']); - // SpecificPrice (only the basic reduction feature is supported by the import) - if (!$shop_is_feature_active) - $info['shop'] = 1; - elseif (!isset($info['shop']) || empty($info['shop'])) - $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID()); + $id_shop_list = array(); + foreach ($info['shop'] as $shop) { + if (!empty($shop) && !is_numeric($shop)) { + $id_shop_list[] = (int)Shop::getIdByName($shop); + } elseif (!empty($shop)) { + $id_shop_list[] = $shop; + } + } - // Get shops for each attributes - $info['shop'] = explode($this->multiple_value_separator, $info['shop']); + if ((isset($info['reduction_price']) && $info['reduction_price'] > 0) || (isset($info['reduction_percent']) && $info['reduction_percent'] > 0)) { + foreach ($id_shop_list as $id_shop) { + $specific_price = SpecificPrice::getSpecificPrice($product->id, $id_shop, 0, 0, 0, 1, 0, 0, 0, 0); - $id_shop_list = array(); - foreach ($info['shop'] as $shop) - if (!empty($shop) && !is_numeric($shop)) - $id_shop_list[] = (int)Shop::getIdByName($shop); - elseif (!empty($shop)) - $id_shop_list[] = $shop; + if (is_array($specific_price) && isset($specific_price['id_specific_price'])) { + $specific_price = new SpecificPrice((int)$specific_price['id_specific_price']); + } else { + $specific_price = new SpecificPrice(); + } + $specific_price->id_product = (int)$product->id; + $specific_price->id_specific_price_rule = 0; + $specific_price->id_shop = $id_shop; + $specific_price->id_currency = 0; + $specific_price->id_country = 0; + $specific_price->id_group = 0; + $specific_price->price = -1; + $specific_price->id_customer = 0; + $specific_price->from_quantity = 1; + $specific_price->reduction = (isset($info['reduction_price']) && $info['reduction_price']) ? $info['reduction_price'] : $info['reduction_percent'] / 100; + $specific_price->reduction_type = (isset($info['reduction_price']) && $info['reduction_price']) ? 'amount' : 'percentage'; + $specific_price->from = (isset($info['reduction_from']) && Validate::isDate($info['reduction_from'])) ? $info['reduction_from'] : '0000-00-00 00:00:00'; + $specific_price->to = (isset($info['reduction_to']) && Validate::isDate($info['reduction_to'])) ? $info['reduction_to'] : '0000-00-00 00:00:00'; + if (!$specific_price->save()) { + $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->l('Discount is invalid')); + } + } + } - if ((isset($info['reduction_price']) && $info['reduction_price'] > 0) || (isset($info['reduction_percent']) && $info['reduction_percent'] > 0)) - foreach ($id_shop_list as $id_shop) - { - $specific_price = SpecificPrice::getSpecificPrice($product->id, $id_shop, 0, 0, 0, 1, 0, 0, 0, 0); + if (isset($product->tags) && !empty($product->tags)) { + if (isset($product->id) && $product->id) { + $tags = Tag::getProductTags($product->id); + if (is_array($tags) && count($tags)) { + if (!empty($product->tags)) { + $product->tags = explode($this->multiple_value_separator, $product->tags); + } + if (is_array($product->tags) && count($product->tags)) { + foreach ($product->tags as $key => $tag) { + if (!empty($tag)) { + $product->tags[$key] = trim($tag); + } + } + $tags[$id_lang] = $product->tags; + $product->tags = $tags; + } + } + } + // Delete tags for this id product, for no duplicating error + Tag::deleteTagsForProduct($product->id); + if (!is_array($product->tags) && !empty($product->tags)) { + $product->tags = AdminImportController::createMultiLangField($product->tags); + foreach ($product->tags as $key => $tags) { + $is_tag_added = Tag::addTags($key, $product->id, $tags, $this->multiple_value_separator); + if (!$is_tag_added) { + $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->l('Tags list is invalid')); + break; + } + } + } else { + foreach ($product->tags as $key => $tags) { + $str = ''; + foreach ($tags as $one_tag) { + $str .= $one_tag.$this->multiple_value_separator; + } + $str = rtrim($str, $this->multiple_value_separator); - if (is_array($specific_price) && isset($specific_price['id_specific_price'])) - $specific_price = new SpecificPrice((int)$specific_price['id_specific_price']); - else - $specific_price = new SpecificPrice(); - $specific_price->id_product = (int)$product->id; - $specific_price->id_specific_price_rule = 0; - $specific_price->id_shop = $id_shop; - $specific_price->id_currency = 0; - $specific_price->id_country = 0; - $specific_price->id_group = 0; - $specific_price->price = -1; - $specific_price->id_customer = 0; - $specific_price->from_quantity = 1; - $specific_price->reduction = (isset($info['reduction_price']) && $info['reduction_price']) ? $info['reduction_price'] : $info['reduction_percent'] / 100; - $specific_price->reduction_type = (isset($info['reduction_price']) && $info['reduction_price']) ? 'amount' : 'percentage'; - $specific_price->from = (isset($info['reduction_from']) && Validate::isDate($info['reduction_from'])) ? $info['reduction_from'] : '0000-00-00 00:00:00'; - $specific_price->to = (isset($info['reduction_to']) && Validate::isDate($info['reduction_to'])) ? $info['reduction_to'] : '0000-00-00 00:00:00'; - if (!$specific_price->save()) - $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->l('Discount is invalid')); - } + $is_tag_added = Tag::addTags($key, $product->id, $str, $this->multiple_value_separator); + if (!$is_tag_added) { + $this->addProductWarning(Tools::safeOutput($info['name']), (int)$product->id, 'Invalid tag(s) ('.$str.')'); + break; + } + } + } + } - if (isset($product->tags) && !empty($product->tags)) - { - if (isset($product->id) && $product->id) - { - $tags = Tag::getProductTags($product->id); - if (is_array($tags) && count($tags)) - { - if (!empty($product->tags)) - $product->tags = explode($this->multiple_value_separator, $product->tags); - if (is_array($product->tags) && count($product->tags)) - { - foreach ($product->tags as $key => $tag) - if (!empty($tag)) - $product->tags[$key] = trim($tag); - $tags[$id_lang] = $product->tags; - $product->tags = $tags; - } - } - } - // Delete tags for this id product, for no duplicating error - Tag::deleteTagsForProduct($product->id); - if (!is_array($product->tags) && !empty($product->tags)) - { - $product->tags = AdminImportController::createMultiLangField($product->tags); - foreach ($product->tags as $key => $tags) - { - $is_tag_added = Tag::addTags($key, $product->id, $tags, $this->multiple_value_separator); - if (!$is_tag_added) - { - $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->l('Tags list is invalid')); - break; - } - } - } - else - { - foreach ($product->tags as $key => $tags) - { - $str = ''; - foreach ($tags as $one_tag) - $str .= $one_tag.$this->multiple_value_separator; - $str = rtrim($str, $this->multiple_value_separator); + //delete existing images if "delete_existing_images" is set to 1 + if (isset($product->delete_existing_images)) { + if ((bool)$product->delete_existing_images) { + $product->deleteImages(); + } + } - $is_tag_added = Tag::addTags($key, $product->id, $str, $this->multiple_value_separator); - if (!$is_tag_added) - { - $this->addProductWarning(Tools::safeOutput($info['name']), (int)$product->id, 'Invalid tag(s) ('.$str.')'); - break; - } - } - } - } + if (isset($product->image) && is_array($product->image) && count($product->image)) { + $product_has_images = (bool)Image::getImages($this->context->language->id, (int)$product->id); + foreach ($product->image as $key => $url) { + $url = trim($url); + $error = false; + if (!empty($url)) { + $url = str_replace(' ', '%20', $url); - //delete existing images if "delete_existing_images" is set to 1 - if (isset($product->delete_existing_images)) - if ((bool)$product->delete_existing_images) - $product->deleteImages(); + $image = new Image(); + $image->id_product = (int)$product->id; + $image->position = Image::getHighestPosition($product->id) + 1; + $image->cover = (!$key && !$product_has_images) ? true : false; + // file_exists doesn't work with HTTP protocol + if (($field_error = $image->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $image->add()) { + // associate image to selected shops + $image->associateTo($shops); + if (!AdminImportController::copyImg($product->id, $image->id, $url, 'products', !$regenerate)) { + $image->delete(); + $this->warnings[] = sprintf(Tools::displayError('Error copying image: %s'), $url); + } + } else { + $error = true; + } + } else { + $error = true; + } - if (isset($product->image) && is_array($product->image) && count($product->image)) - { - $product_has_images = (bool)Image::getImages($this->context->language->id, (int)$product->id); - foreach ($product->image as $key => $url) - { - $url = trim($url); - $error = false; - if (!empty($url)) - { - $url = str_replace(' ', '%20', $url); + if ($error) { + $this->warnings[] = sprintf(Tools::displayError('Product #%1$d: the picture (%2$s) cannot be saved.'), $image->id_product, $url); + } + } + } - $image = new Image(); - $image->id_product = (int)$product->id; - $image->position = Image::getHighestPosition($product->id) + 1; - $image->cover = (!$key && !$product_has_images) ? true : false; - // file_exists doesn't work with HTTP protocol - if (($field_error = $image->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $image->add()) - { - // associate image to selected shops - $image->associateTo($shops); - if (!AdminImportController::copyImg($product->id, $image->id, $url, 'products', !$regenerate)) - { - $image->delete(); - $this->warnings[] = sprintf(Tools::displayError('Error copying image: %s'), $url); - } - } - else - $error = true; - } - else - $error = true; + if (isset($product->id_category) && is_array($product->id_category)) { + $product->updateCategories(array_map('intval', $product->id_category)); + } - if ($error) - $this->warnings[] = sprintf(Tools::displayError('Product #%1$d: the picture (%2$s) cannot be saved.'), $image->id_product, $url); - } - } + $product->checkDefaultAttributes(); + if (!$product->cache_default_attribute) { + Product::updateDefaultAttribute($product->id); + } - if (isset($product->id_category) && is_array($product->id_category)) - $product->updateCategories(array_map('intval', $product->id_category)); + // Features import + $features = get_object_vars($product); - $product->checkDefaultAttributes(); - if (!$product->cache_default_attribute) - Product::updateDefaultAttribute($product->id); + if (isset($features['features']) && !empty($features['features'])) { + foreach (explode($this->multiple_value_separator, $features['features']) as $single_feature) { + if (empty($single_feature)) { + continue; + } + $tab_feature = explode(':', $single_feature); + $feature_name = isset($tab_feature[0]) ? trim($tab_feature[0]) : ''; + $feature_value = isset($tab_feature[1]) ? trim($tab_feature[1]) : ''; + $position = isset($tab_feature[2]) ? (int)$tab_feature[2] - 1 : false; + $custom = isset($tab_feature[3]) ? (int)$tab_feature[3] : false; + if (!empty($feature_name) && !empty($feature_value)) { + $id_feature = (int)Feature::addFeatureImport($feature_name, $position); + $id_product = null; + if ($force_ids || $match_ref) { + $id_product = (int)$product->id; + } + $id_feature_value = (int)FeatureValue::addFeatureValueImport($id_feature, $feature_value, $id_product, $id_lang, $custom); + Product::addFeatureProductImport($product->id, $id_feature, $id_feature_value); + } + } + } + // clean feature positions to avoid conflict + Feature::cleanPositions(); - // Features import - $features = get_object_vars($product); + // set advanced stock managment + if (isset($product->advanced_stock_management)) { + if ($product->advanced_stock_management != 1 && $product->advanced_stock_management != 0) { + $this->warnings[] = sprintf(Tools::displayError('Advanced stock management has incorrect value. Not set for product %1$s '), $product->name[$default_language_id]); + } elseif (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management == 1) { + $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, cannot enable on product %1$s '), $product->name[$default_language_id]); + } elseif ($update_advanced_stock_management_value) { + $product->setAdvancedStockManagement($product->advanced_stock_management); + } + // automaticly disable depends on stock, if a_s_m set to disabled + if (StockAvailable::dependsOnStock($product->id) == 1 && $product->advanced_stock_management == 0) { + StockAvailable::setProductDependsOnStock($product->id, 0); + } + } - if (isset($features['features']) && !empty($features['features'])) - foreach (explode($this->multiple_value_separator, $features['features']) as $single_feature) - { - if (empty($single_feature)) - continue; - $tab_feature = explode(':', $single_feature); - $feature_name = isset($tab_feature[0]) ? trim($tab_feature[0]) : ''; - $feature_value = isset($tab_feature[1]) ? trim($tab_feature[1]) : ''; - $position = isset($tab_feature[2]) ? (int)$tab_feature[2] - 1 : false; - $custom = isset($tab_feature[3]) ? (int)$tab_feature[3] : false; - if (!empty($feature_name) && !empty($feature_value)) - { - $id_feature = (int)Feature::addFeatureImport($feature_name, $position); - $id_product = null; - if ($force_ids || $match_ref) - $id_product = (int)$product->id; - $id_feature_value = (int)FeatureValue::addFeatureValueImport($id_feature, $feature_value, $id_product, $id_lang, $custom); - Product::addFeatureProductImport($product->id, $id_feature, $id_feature_value); - } - } - // clean feature positions to avoid conflict - Feature::cleanPositions(); + // Check if warehouse exists + if (isset($product->warehouse) && $product->warehouse) { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, warehouse not set on product %1$s '), $product->name[$default_language_id]); + } else { + if (Warehouse::exists($product->warehouse)) { + // Get already associated warehouses + $associated_warehouses_collection = WarehouseProductLocation::getCollection($product->id); + // Delete any entry in warehouse for this product + foreach ($associated_warehouses_collection as $awc) { + $awc->delete(); + } + $warehouse_location_entity = new WarehouseProductLocation(); + $warehouse_location_entity->id_product = $product->id; + $warehouse_location_entity->id_product_attribute = 0; + $warehouse_location_entity->id_warehouse = $product->warehouse; + if (WarehouseProductLocation::getProductLocation($product->id, 0, $product->warehouse) !== false) { + $warehouse_location_entity->update(); + } else { + $warehouse_location_entity->save(); + } + StockAvailable::synchronize($product->id); + } else { + $this->warnings[] = sprintf(Tools::displayError('Warehouse did not exist, cannot set on product %1$s.'), $product->name[$default_language_id]); + } + } + } - // set advanced stock managment - if (isset($product->advanced_stock_management)) - { - if ($product->advanced_stock_management != 1 && $product->advanced_stock_management != 0) - $this->warnings[] = sprintf(Tools::displayError('Advanced stock management has incorrect value. Not set for product %1$s '), $product->name[$default_language_id]); - elseif (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management == 1) - $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, cannot enable on product %1$s '), $product->name[$default_language_id]); - elseif ($update_advanced_stock_management_value) - $product->setAdvancedStockManagement($product->advanced_stock_management); - // automaticly disable depends on stock, if a_s_m set to disabled - if (StockAvailable::dependsOnStock($product->id) == 1 && $product->advanced_stock_management == 0) - StockAvailable::setProductDependsOnStock($product->id, 0); - } + // stock available + if (isset($product->depends_on_stock)) { + if ($product->depends_on_stock != 0 && $product->depends_on_stock != 1) { + $this->warnings[] = sprintf(Tools::displayError('Incorrect value for "depends on stock" for product %1$s '), $product->name[$default_language_id]); + } elseif ((!$product->advanced_stock_management || $product->advanced_stock_management == 0) && $product->depends_on_stock == 1) { + $this->warnings[] = sprintf(Tools::displayError('Advanced stock management not enabled, cannot set "depends on stock" for product %1$s '), $product->name[$default_language_id]); + } else { + StockAvailable::setProductDependsOnStock($product->id, $product->depends_on_stock); + } - // Check if warehouse exists - if (isset($product->warehouse) && $product->warehouse) - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, warehouse not set on product %1$s '), $product->name[$default_language_id]); - else - { - if (Warehouse::exists($product->warehouse)) - { - // Get already associated warehouses - $associated_warehouses_collection = WarehouseProductLocation::getCollection($product->id); - // Delete any entry in warehouse for this product - foreach ($associated_warehouses_collection as $awc) - $awc->delete(); - $warehouse_location_entity = new WarehouseProductLocation(); - $warehouse_location_entity->id_product = $product->id; - $warehouse_location_entity->id_product_attribute = 0; - $warehouse_location_entity->id_warehouse = $product->warehouse; - if (WarehouseProductLocation::getProductLocation($product->id, 0, $product->warehouse) !== false) - $warehouse_location_entity->update(); - else - $warehouse_location_entity->save(); - StockAvailable::synchronize($product->id); - } - else - $this->warnings[] = sprintf(Tools::displayError('Warehouse did not exist, cannot set on product %1$s.'), $product->name[$default_language_id]); - } - } + // This code allows us to set qty and disable depends on stock + if (isset($product->quantity) && (int)$product->quantity) { + // if depends on stock and quantity, add quantity to stock + if ($product->depends_on_stock == 1) { + $stock_manager = StockManagerFactory::getManager(); + $price = str_replace(',', '.', $product->wholesale_price); + if ($price == 0) { + $price = 0.000001; + } + $price = round(floatval($price), 6); + $warehouse = new Warehouse($product->warehouse); + if ($stock_manager->addProduct((int)$product->id, 0, $warehouse, (int)$product->quantity, 1, $price, true)) { + StockAvailable::synchronize((int)$product->id); + } + } else { + if ($shop_is_feature_active) { + foreach ($shops as $shop) { + StockAvailable::setQuantity((int)$product->id, 0, (int)$product->quantity, (int)$shop); + } + } else { + StockAvailable::setQuantity((int)$product->id, 0, (int)$product->quantity, (int)$this->context->shop->id); + } + } + } + } else { + // if not depends_on_stock set, use normal qty - // stock available - if (isset($product->depends_on_stock)) - { - if ($product->depends_on_stock != 0 && $product->depends_on_stock != 1) - $this->warnings[] = sprintf(Tools::displayError('Incorrect value for "depends on stock" for product %1$s '), $product->name[$default_language_id]); - elseif ((!$product->advanced_stock_management || $product->advanced_stock_management == 0) && $product->depends_on_stock == 1) - $this->warnings[] = sprintf(Tools::displayError('Advanced stock management not enabled, cannot set "depends on stock" for product %1$s '), $product->name[$default_language_id]); - else - StockAvailable::setProductDependsOnStock($product->id, $product->depends_on_stock); + if ($shop_is_feature_active) { + foreach ($shops as $shop) { + StockAvailable::setQuantity((int)$product->id, 0, (int)$product->quantity, (int)$shop); + } + } else { + StockAvailable::setQuantity((int)$product->id, 0, (int)$product->quantity, (int)$this->context->shop->id); + } + } + } + } + $this->closeCsvFile($handle); + Module::processDeferedFuncCall(); + Module::processDeferedClearCache(); + Tag::updateTagCount(); + } - // This code allows us to set qty and disable depends on stock - if (isset($product->quantity) && (int)$product->quantity) - { - // if depends on stock and quantity, add quantity to stock - if ($product->depends_on_stock == 1) - { - $stock_manager = StockManagerFactory::getManager(); - $price = str_replace(',', '.', $product->wholesale_price); - if ($price == 0) - $price = 0.000001; - $price = round(floatval($price), 6); - $warehouse = new Warehouse($product->warehouse); - if ($stock_manager->addProduct((int)$product->id, 0, $warehouse, (int)$product->quantity, 1, $price, true)) - StockAvailable::synchronize((int)$product->id); - } - else - { - if ($shop_is_feature_active) - foreach ($shops as $shop) - StockAvailable::setQuantity((int)$product->id, 0, (int)$product->quantity, (int)$shop); - else - StockAvailable::setQuantity((int)$product->id, 0, (int)$product->quantity, (int)$this->context->shop->id); - } - } - } - else // if not depends_on_stock set, use normal qty - { - if ($shop_is_feature_active) - foreach ($shops as $shop) - StockAvailable::setQuantity((int)$product->id, 0, (int)$product->quantity, (int)$shop); - else - StockAvailable::setQuantity((int)$product->id, 0, (int)$product->quantity, (int)$this->context->shop->id); - } - } - } - $this->closeCsvFile($handle); - Module::processDeferedFuncCall(); - Module::processDeferedClearCache(); - Tag::updateTagCount(); - } + public function productImportCreateCat($default_language_id, $category_name, $id_parent_category = null) + { + $category_to_create = new Category(); + $shop_is_feature_active = Shop::isFeatureActive(); + if (!$shop_is_feature_active) { + $category_to_create->id_shop_default = 1; + } else { + $category_to_create->id_shop_default = (int)Context::getContext()->shop->id; + } + $category_to_create->name = AdminImportController::createMultiLangField(trim($category_name)); + $category_to_create->active = 1; + $category_to_create->id_parent = (int)$id_parent_category ? (int)$id_parent_category : (int)Configuration::get('PS_HOME_CATEGORY'); // Default parent is home for unknown category to create + $category_link_rewrite = Tools::link_rewrite($category_to_create->name[$default_language_id]); + $category_to_create->link_rewrite = AdminImportController::createMultiLangField($category_link_rewrite); - public function productImportCreateCat($default_language_id, $category_name, $id_parent_category = null) - { - $category_to_create = new Category(); - $shop_is_feature_active = Shop::isFeatureActive(); - if (!$shop_is_feature_active) - $category_to_create->id_shop_default = 1; - else - $category_to_create->id_shop_default = (int)Context::getContext()->shop->id; - $category_to_create->name = AdminImportController::createMultiLangField(trim($category_name)); - $category_to_create->active = 1; - $category_to_create->id_parent = (int)$id_parent_category ? (int)$id_parent_category : (int)Configuration::get('PS_HOME_CATEGORY'); // Default parent is home for unknown category to create - $category_link_rewrite = Tools::link_rewrite($category_to_create->name[$default_language_id]); - $category_to_create->link_rewrite = AdminImportController::createMultiLangField($category_link_rewrite); + if (($field_error = $category_to_create->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $category_to_create->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $category_to_create->add()) { + /** + * @see AdminImportController::productImport() @ Line 1480 + * @TODO Refactor if statement + */ + // $product->id_category[] = (int)$category_to_create->id; + } else { + $this->errors[] = sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + $category_to_create->name[$default_language_id], + (isset($category_to_create->id) && !empty($category_to_create->id))? $category_to_create->id : 'null' + ); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). + Db::getInstance()->getMsgError(); + } + } - if (($field_error = $category_to_create->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $category_to_create->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $category_to_create->add()) - { - /** - * @see AdminImportController::productImport() @ Line 1480 - * @TODO Refactor if statement - */ - // $product->id_category[] = (int)$category_to_create->id; - } - else - { - $this->errors[] = sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - $category_to_create->name[$default_language_id], - (isset($category_to_create->id) && !empty($category_to_create->id))? $category_to_create->id : 'null' - ); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). - Db::getInstance()->getMsgError(); - } - } + public function attributeImport() + { + $default_language = Configuration::get('PS_LANG_DEFAULT'); - public function attributeImport() - { - $default_language = Configuration::get('PS_LANG_DEFAULT'); + $groups = array(); + foreach (AttributeGroup::getAttributesGroups($default_language) as $group) { + $groups[$group['name']] = (int)$group['id_attribute_group']; + } - $groups = array(); - foreach (AttributeGroup::getAttributesGroups($default_language) as $group) - $groups[$group['name']] = (int)$group['id_attribute_group']; + $attributes = array(); + foreach (Attribute::getAttributes($default_language) as $attribute) { + $attributes[$attribute['attribute_group'].'_'.$attribute['name']] = (int)$attribute['id_attribute']; + } - $attributes = array(); - foreach (Attribute::getAttributes($default_language) as $attribute) - $attributes[$attribute['attribute_group'].'_'.$attribute['name']] = (int)$attribute['id_attribute']; + $this->receiveTab(); + $handle = $this->openCsvFile(); + AdminImportController::setLocale(); - $this->receiveTab(); - $handle = $this->openCsvFile(); - AdminImportController::setLocale(); + $convert = Tools::getValue('convert'); + $regenerate = Tools::getValue('regenerate'); + $shop_is_feature_active = Shop::isFeatureActive(); - $convert = Tools::getValue('convert'); - $regenerate = Tools::getValue('regenerate'); - $shop_is_feature_active = Shop::isFeatureActive(); + for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) { + if (count($line) == 1 && empty($line[0])) { + continue; + } - for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) - { - if (count($line) == 1 && empty($line[0])) - continue; + if ($convert) { + $line = $this->utf8EncodeArray($line); + } + $info = AdminImportController::getMaskedRow($line); + $info = array_map('trim', $info); - if ($convert) - $line = $this->utf8EncodeArray($line); - $info = AdminImportController::getMaskedRow($line); - $info = array_map('trim', $info); + AdminImportController::setDefaultValues($info); - AdminImportController::setDefaultValues($info); + if (!$shop_is_feature_active) { + $info['shop'] = 1; + } elseif (!isset($info['shop']) || empty($info['shop'])) { + $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID()); + } - if (!$shop_is_feature_active) - $info['shop'] = 1; - elseif (!isset($info['shop']) || empty($info['shop'])) - $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID()); + // Get shops for each attributes + $info['shop'] = explode($this->multiple_value_separator, $info['shop']); - // Get shops for each attributes - $info['shop'] = explode($this->multiple_value_separator, $info['shop']); + $id_shop_list = array(); + if (is_array($info['shop']) && count($info['shop'])) { + foreach ($info['shop'] as $shop) { + if (!empty($shop) && !is_numeric($shop)) { + $id_shop_list[] = Shop::getIdByName($shop); + } elseif (!empty($shop)) { + $id_shop_list[] = $shop; + } + } + } - $id_shop_list = array(); - if (is_array($info['shop']) && count($info['shop'])) - foreach ($info['shop'] as $shop) - if (!empty($shop) && !is_numeric($shop)) - $id_shop_list[] = Shop::getIdByName($shop); - elseif (!empty($shop)) - $id_shop_list[] = $shop; - - if (isset($info['id_product']) && $info['id_product']) - $product = new Product((int)$info['id_product'], false, $default_language); - elseif (Tools::getValue('match_ref') && isset($info['product_reference']) && $info['product_reference']) - { - $datas = Db::getInstance()->getRow(' + if (isset($info['id_product']) && $info['id_product']) { + $product = new Product((int)$info['id_product'], false, $default_language); + } elseif (Tools::getValue('match_ref') && isset($info['product_reference']) && $info['product_reference']) { + $datas = Db::getInstance()->getRow(' SELECT p.`id_product` FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' WHERE p.`reference` = "'.pSQL($info['product_reference']).'" ', false); - if (isset($datas['id_product']) && $datas['id_product']) - $product = new Product((int)$datas['id_product'], false, $default_language); - } - else - continue; + if (isset($datas['id_product']) && $datas['id_product']) { + $product = new Product((int)$datas['id_product'], false, $default_language); + } + } else { + continue; + } - $id_image = array(); + $id_image = array(); - //delete existing images if "delete_existing_images" is set to 1 - if (array_key_exists('delete_existing_images', $info) && $info['delete_existing_images'] && !isset($this->cache_image_deleted[(int)$product->id])) - { - $product->deleteImages(); - $this->cache_image_deleted[(int)$product->id] = true; - } + //delete existing images if "delete_existing_images" is set to 1 + if (array_key_exists('delete_existing_images', $info) && $info['delete_existing_images'] && !isset($this->cache_image_deleted[(int)$product->id])) { + $product->deleteImages(); + $this->cache_image_deleted[(int)$product->id] = true; + } - if (isset($info['image_url']) && $info['image_url']) - { - $info['image_url'] = explode($this->multiple_value_separator, $info['image_url']); + if (isset($info['image_url']) && $info['image_url']) { + $info['image_url'] = explode($this->multiple_value_separator, $info['image_url']); - if (is_array($info['image_url'] ) && count($info['image_url'] )) - foreach ($info['image_url'] as $url) - { - $url = trim($url); - $product_has_images = (bool)Image::getImages($this->context->language->id, $product->id); + if (is_array($info['image_url']) && count($info['image_url'])) { + foreach ($info['image_url'] as $url) { + $url = trim($url); + $product_has_images = (bool)Image::getImages($this->context->language->id, $product->id); - $image = new Image(); - $image->id_product = (int)$product->id; - $image->position = Image::getHighestPosition($product->id) + 1; - $image->cover = (!$product_has_images) ? true : false; + $image = new Image(); + $image->id_product = (int)$product->id; + $image->position = Image::getHighestPosition($product->id) + 1; + $image->cover = (!$product_has_images) ? true : false; - $field_error = $image->validateFields(UNFRIENDLY_ERROR, true); - $lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true); + $field_error = $image->validateFields(UNFRIENDLY_ERROR, true); + $lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true); - if ($field_error === true && $lang_field_error === true && $image->add()) - { - $image->associateTo($id_shop_list); - if (!AdminImportController::copyImg($product->id, $image->id, $url, 'products', !$regenerate)) - { - $this->warnings[] = sprintf(Tools::displayError('Error copying image: %s'), $url); - $image->delete(); - } - else - $id_image[] = (int)$image->id; - } - else - { - $this->warnings[] = sprintf( - Tools::displayError('%s cannot be saved'), - (isset($image->id_product) ? ' ('.$image->id_product.')' : '') - ); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').mysql_error(); - } - } - } - elseif (isset($info['image_position']) && $info['image_position']) - { - $info['image_position'] = explode($this->multiple_value_separator, $info['image_position']); + if ($field_error === true && $lang_field_error === true && $image->add()) { + $image->associateTo($id_shop_list); + if (!AdminImportController::copyImg($product->id, $image->id, $url, 'products', !$regenerate)) { + $this->warnings[] = sprintf(Tools::displayError('Error copying image: %s'), $url); + $image->delete(); + } else { + $id_image[] = (int)$image->id; + } + } else { + $this->warnings[] = sprintf( + Tools::displayError('%s cannot be saved'), + (isset($image->id_product) ? ' ('.$image->id_product.')' : '') + ); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '').mysql_error(); + } + } + } + } elseif (isset($info['image_position']) && $info['image_position']) { + $info['image_position'] = explode($this->multiple_value_separator, $info['image_position']); - if (is_array($info['image_position']) && count($info['image_position'])) - foreach ($info['image_position'] as $position) - { - // choose images from product by position - $images = $product->getImages($default_language); + if (is_array($info['image_position']) && count($info['image_position'])) { + foreach ($info['image_position'] as $position) { + // choose images from product by position + $images = $product->getImages($default_language); - if ($images) - foreach ($images as $row) - if ($row['position'] == (int)$position) - { - $id_image[] = (int)$row['id_image']; - break; - } - if (empty($id_image)) - $this->warnings[] = sprintf( - Tools::displayError('No image was found for combination with id_product = %s and image position = %s.'), - $product->id, - (int)$position - ); - } - } + if ($images) { + foreach ($images as $row) { + if ($row['position'] == (int)$position) { + $id_image[] = (int)$row['id_image']; + break; + } + } + } + if (empty($id_image)) { + $this->warnings[] = sprintf( + Tools::displayError('No image was found for combination with id_product = %s and image position = %s.'), + $product->id, + (int)$position + ); + } + } + } + } - $id_attribute_group = 0; - // groups - $groups_attributes = array(); - if (isset($info['group'])) - foreach (explode($this->multiple_value_separator, $info['group']) as $key => $group) - { - if (empty($group)) - continue; - $tab_group = explode(':', $group); - $group = trim($tab_group[0]); - if (!isset($tab_group[1])) - $type = 'select'; - else - $type = trim($tab_group[1]); + $id_attribute_group = 0; + // groups + $groups_attributes = array(); + if (isset($info['group'])) { + foreach (explode($this->multiple_value_separator, $info['group']) as $key => $group) { + if (empty($group)) { + continue; + } + $tab_group = explode(':', $group); + $group = trim($tab_group[0]); + if (!isset($tab_group[1])) { + $type = 'select'; + } else { + $type = trim($tab_group[1]); + } - // sets group - $groups_attributes[$key]['group'] = $group; + // sets group + $groups_attributes[$key]['group'] = $group; - // if position is filled - if (isset($tab_group[2])) - $position = trim($tab_group[2]); - else - $position = false; + // if position is filled + if (isset($tab_group[2])) { + $position = trim($tab_group[2]); + } else { + $position = false; + } - if (!isset($groups[$group])) - { - $obj = new AttributeGroup(); - $obj->is_color_group = false; - $obj->group_type = pSQL($type); - $obj->name[$default_language] = $group; - $obj->public_name[$default_language] = $group; - $obj->position = (!$position) ? AttributeGroup::getHigherPosition() + 1 : $position; + if (!isset($groups[$group])) { + $obj = new AttributeGroup(); + $obj->is_color_group = false; + $obj->group_type = pSQL($type); + $obj->name[$default_language] = $group; + $obj->public_name[$default_language] = $group; + $obj->position = (!$position) ? AttributeGroup::getHigherPosition() + 1 : $position; - if (($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) - { - $obj->add(); - $obj->associateTo($id_shop_list); - $groups[$group] = $obj->id; - } - else - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); + if (($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) { + $obj->add(); + $obj->associateTo($id_shop_list); + $groups[$group] = $obj->id; + } else { + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); + } - // fills groups attributes - $id_attribute_group = $obj->id; - $groups_attributes[$key]['id'] = $id_attribute_group; - } - else // already exists - { - $id_attribute_group = $groups[$group]; - $groups_attributes[$key]['id'] = $id_attribute_group; - } - } + // fills groups attributes + $id_attribute_group = $obj->id; + $groups_attributes[$key]['id'] = $id_attribute_group; + } else { + // already exists - // inits attribute - $id_product_attribute = 0; - $id_product_attribute_update = false; - $attributes_to_add = array(); + $id_attribute_group = $groups[$group]; + $groups_attributes[$key]['id'] = $id_attribute_group; + } + } + } - // for each attribute - if (isset($info['attribute'])) - foreach (explode($this->multiple_value_separator, $info['attribute']) as $key => $attribute) - { - if (empty($attribute)) - continue; - $tab_attribute = explode(':', $attribute); - $attribute = trim($tab_attribute[0]); - // if position is filled - if (isset($tab_attribute[1])) - $position = trim($tab_attribute[1]); - else - $position = false; + // inits attribute + $id_product_attribute = 0; + $id_product_attribute_update = false; + $attributes_to_add = array(); - if (isset($groups_attributes[$key])) - { - $group = $groups_attributes[$key]['group']; - if (!isset($attributes[$group.'_'.$attribute]) && count($groups_attributes[$key]) == 2) - { - $id_attribute_group = $groups_attributes[$key]['id']; - $obj = new Attribute(); - // sets the proper id (corresponding to the right key) - $obj->id_attribute_group = $groups_attributes[$key]['id']; - $obj->name[$default_language] = str_replace('\n', '', str_replace('\r', '', $attribute)); - $obj->position = (!$position && isset($groups[$group])) ? Attribute::getHigherPosition($groups[$group]) + 1 : $position; + // for each attribute + if (isset($info['attribute'])) { + foreach (explode($this->multiple_value_separator, $info['attribute']) as $key => $attribute) { + if (empty($attribute)) { + continue; + } + $tab_attribute = explode(':', $attribute); + $attribute = trim($tab_attribute[0]); + // if position is filled + if (isset($tab_attribute[1])) { + $position = trim($tab_attribute[1]); + } else { + $position = false; + } - if (($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) - { - $obj->add(); - $obj->associateTo($id_shop_list); - $attributes[$group.'_'.$attribute] = $obj->id; - } - else - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); - } + if (isset($groups_attributes[$key])) { + $group = $groups_attributes[$key]['group']; + if (!isset($attributes[$group.'_'.$attribute]) && count($groups_attributes[$key]) == 2) { + $id_attribute_group = $groups_attributes[$key]['id']; + $obj = new Attribute(); + // sets the proper id (corresponding to the right key) + $obj->id_attribute_group = $groups_attributes[$key]['id']; + $obj->name[$default_language] = str_replace('\n', '', str_replace('\r', '', $attribute)); + $obj->position = (!$position && isset($groups[$group])) ? Attribute::getHigherPosition($groups[$group]) + 1 : $position; - $info['minimal_quantity'] = isset($info['minimal_quantity']) && $info['minimal_quantity'] ? (int)$info['minimal_quantity'] : 1; + if (($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) { + $obj->add(); + $obj->associateTo($id_shop_list); + $attributes[$group.'_'.$attribute] = $obj->id; + } else { + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); + } + } - $info['wholesale_price'] = str_replace(',', '.', $info['wholesale_price']); - $info['price'] = str_replace(',', '.', $info['price']); - $info['ecotax'] = str_replace(',', '.', $info['ecotax']); - $info['weight'] = str_replace(',', '.', $info['weight']); - $info['available_date'] = Validate::isDate($info['available_date']) ? $info['available_date'] : null; + $info['minimal_quantity'] = isset($info['minimal_quantity']) && $info['minimal_quantity'] ? (int)$info['minimal_quantity'] : 1; - if (!Validate::isEan13($info['ean13'])) - { - $this->warnings[] = sprintf(Tools::displayError('EAN13 "%1s" has incorrect value for product with id %2d.'), $info['ean13'], $product->id); - $info['ean13'] = ''; - } + $info['wholesale_price'] = str_replace(',', '.', $info['wholesale_price']); + $info['price'] = str_replace(',', '.', $info['price']); + $info['ecotax'] = str_replace(',', '.', $info['ecotax']); + $info['weight'] = str_replace(',', '.', $info['weight']); + $info['available_date'] = Validate::isDate($info['available_date']) ? $info['available_date'] : null; - if ($info['default_on']) - $product->deleteDefaultAttributes(); + if (!Validate::isEan13($info['ean13'])) { + $this->warnings[] = sprintf(Tools::displayError('EAN13 "%1s" has incorrect value for product with id %2d.'), $info['ean13'], $product->id); + $info['ean13'] = ''; + } - // if a reference is specified for this product, get the associate id_product_attribute to UPDATE - if (isset($info['reference']) && !empty($info['reference'])) - { - $id_product_attribute = Combination::getIdByReference($product->id, strval($info['reference'])); + if ($info['default_on']) { + $product->deleteDefaultAttributes(); + } - // updates the attribute - if ($id_product_attribute) - { - // gets all the combinations of this product - $attribute_combinations = $product->getAttributeCombinations($default_language); - foreach ($attribute_combinations as $attribute_combination) - { - if ($id_product_attribute && in_array($id_product_attribute, $attribute_combination)) - { - $product->updateAttribute( - $id_product_attribute, - (float)$info['wholesale_price'], - (float)$info['price'], - (float)$info['weight'], - 0, - (Configuration::get('PS_USE_ECOTAX') ? (float)$info['ecotax'] : 0), - $id_image, - strval($info['reference']), - strval($info['ean13']), - (int)$info['default_on'], - 0, - strval($info['upc']), - (int)$info['minimal_quantity'], - $info['available_date'], - null, - $id_shop_list - ); - $id_product_attribute_update = true; - if (isset($info['supplier_reference']) && !empty($info['supplier_reference'])) - $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']); - } - } - } - } + // if a reference is specified for this product, get the associate id_product_attribute to UPDATE + if (isset($info['reference']) && !empty($info['reference'])) { + $id_product_attribute = Combination::getIdByReference($product->id, strval($info['reference'])); - // if no attribute reference is specified, creates a new one - if (!$id_product_attribute) - { - $id_product_attribute = $product->addCombinationEntity( - (float)$info['wholesale_price'], - (float)$info['price'], - (float)$info['weight'], - 0, - (Configuration::get('PS_USE_ECOTAX') ? (float)$info['ecotax'] : 0), - (int)$info['quantity'], - $id_image, - strval($info['reference']), - 0, - strval($info['ean13']), - (int)$info['default_on'], - 0, - strval($info['upc']), - (int)$info['minimal_quantity'], - $id_shop_list, - $info['available_date'] - ); + // updates the attribute + if ($id_product_attribute) { + // gets all the combinations of this product + $attribute_combinations = $product->getAttributeCombinations($default_language); + foreach ($attribute_combinations as $attribute_combination) { + if ($id_product_attribute && in_array($id_product_attribute, $attribute_combination)) { + $product->updateAttribute( + $id_product_attribute, + (float)$info['wholesale_price'], + (float)$info['price'], + (float)$info['weight'], + 0, + (Configuration::get('PS_USE_ECOTAX') ? (float)$info['ecotax'] : 0), + $id_image, + strval($info['reference']), + strval($info['ean13']), + (int)$info['default_on'], + 0, + strval($info['upc']), + (int)$info['minimal_quantity'], + $info['available_date'], + null, + $id_shop_list + ); + $id_product_attribute_update = true; + if (isset($info['supplier_reference']) && !empty($info['supplier_reference'])) { + $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']); + } + } + } + } + } - if (isset($info['supplier_reference']) && !empty($info['supplier_reference'])) - $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']); - } + // if no attribute reference is specified, creates a new one + if (!$id_product_attribute) { + $id_product_attribute = $product->addCombinationEntity( + (float)$info['wholesale_price'], + (float)$info['price'], + (float)$info['weight'], + 0, + (Configuration::get('PS_USE_ECOTAX') ? (float)$info['ecotax'] : 0), + (int)$info['quantity'], + $id_image, + strval($info['reference']), + 0, + strval($info['ean13']), + (int)$info['default_on'], + 0, + strval($info['upc']), + (int)$info['minimal_quantity'], + $id_shop_list, + $info['available_date'] + ); - // fills our attributes array, in order to add the attributes to the product_attribute afterwards - if (isset($attributes[$group.'_'.$attribute])) - $attributes_to_add[] = (int)$attributes[$group.'_'.$attribute]; + if (isset($info['supplier_reference']) && !empty($info['supplier_reference'])) { + $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']); + } + } - // after insertion, we clean attribute position and group attribute position - $obj = new Attribute(); - $obj->cleanPositions((int)$id_attribute_group, false); - AttributeGroup::cleanPositions(); - } - } + // fills our attributes array, in order to add the attributes to the product_attribute afterwards + if (isset($attributes[$group.'_'.$attribute])) { + $attributes_to_add[] = (int)$attributes[$group.'_'.$attribute]; + } - $product->checkDefaultAttributes(); - if (!$product->cache_default_attribute) - Product::updateDefaultAttribute($product->id); - if ($id_product_attribute) - { - // now adds the attributes in the attribute_combination table - if ($id_product_attribute_update) - { - Db::getInstance()->execute(' + // after insertion, we clean attribute position and group attribute position + $obj = new Attribute(); + $obj->cleanPositions((int)$id_attribute_group, false); + AttributeGroup::cleanPositions(); + } + } + } + + $product->checkDefaultAttributes(); + if (!$product->cache_default_attribute) { + Product::updateDefaultAttribute($product->id); + } + if ($id_product_attribute) { + // now adds the attributes in the attribute_combination table + if ($id_product_attribute_update) { + Db::getInstance()->execute(' DELETE FROM '._DB_PREFIX_.'product_attribute_combination WHERE id_product_attribute = '.(int)$id_product_attribute); - } + } - foreach ($attributes_to_add as $attribute_to_add) - { - Db::getInstance()->execute(' + foreach ($attributes_to_add as $attribute_to_add) { + Db::getInstance()->execute(' INSERT IGNORE INTO '._DB_PREFIX_.'product_attribute_combination (id_attribute, id_product_attribute) VALUES ('.(int)$attribute_to_add.','.(int)$id_product_attribute.')', false); - } + } - // set advanced stock managment - if (isset($info['advanced_stock_management'])) - { - if ($info['advanced_stock_management'] != 1 && $info['advanced_stock_management'] != 0) - $this->warnings[] = sprintf(Tools::displayError('Advanced stock management has incorrect value. Not set for product with id %d.'), $product->id); - elseif (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $info['advanced_stock_management'] == 1) - $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, cannot enable on product with id %d.'), $product->id); - else - $product->setAdvancedStockManagement($info['advanced_stock_management']); - // automaticly disable depends on stock, if a_s_m set to disabled - if (StockAvailable::dependsOnStock($product->id) == 1 && $info['advanced_stock_management'] == 0) - StockAvailable::setProductDependsOnStock($product->id, 0, null, $id_product_attribute); - } + // set advanced stock managment + if (isset($info['advanced_stock_management'])) { + if ($info['advanced_stock_management'] != 1 && $info['advanced_stock_management'] != 0) { + $this->warnings[] = sprintf(Tools::displayError('Advanced stock management has incorrect value. Not set for product with id %d.'), $product->id); + } elseif (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $info['advanced_stock_management'] == 1) { + $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, cannot enable on product with id %d.'), $product->id); + } else { + $product->setAdvancedStockManagement($info['advanced_stock_management']); + } + // automaticly disable depends on stock, if a_s_m set to disabled + if (StockAvailable::dependsOnStock($product->id) == 1 && $info['advanced_stock_management'] == 0) { + StockAvailable::setProductDependsOnStock($product->id, 0, null, $id_product_attribute); + } + } - // Check if warehouse exists - if (isset($info['warehouse']) && $info['warehouse']) - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, warehouse is not set on product with id %d.'), $product->id); - else - { - if (Warehouse::exists($info['warehouse'])) - { - $warehouse_location_entity = new WarehouseProductLocation(); - $warehouse_location_entity->id_product = $product->id; - $warehouse_location_entity->id_product_attribute = $id_product_attribute; - $warehouse_location_entity->id_warehouse = $info['warehouse']; - if (WarehouseProductLocation::getProductLocation($product->id, $id_product_attribute, $info['warehouse']) !== false) - $warehouse_location_entity->update(); - else - $warehouse_location_entity->save(); - StockAvailable::synchronize($product->id); - } - else - $this->warnings[] = sprintf(Tools::displayError('Warehouse did not exist, cannot set on product %1$s.'), $product->name[$default_language]); - } - } + // Check if warehouse exists + if (isset($info['warehouse']) && $info['warehouse']) { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, warehouse is not set on product with id %d.'), $product->id); + } else { + if (Warehouse::exists($info['warehouse'])) { + $warehouse_location_entity = new WarehouseProductLocation(); + $warehouse_location_entity->id_product = $product->id; + $warehouse_location_entity->id_product_attribute = $id_product_attribute; + $warehouse_location_entity->id_warehouse = $info['warehouse']; + if (WarehouseProductLocation::getProductLocation($product->id, $id_product_attribute, $info['warehouse']) !== false) { + $warehouse_location_entity->update(); + } else { + $warehouse_location_entity->save(); + } + StockAvailable::synchronize($product->id); + } else { + $this->warnings[] = sprintf(Tools::displayError('Warehouse did not exist, cannot set on product %1$s.'), $product->name[$default_language]); + } + } + } - // stock available - if (isset($info['depends_on_stock'])) - { - if ($info['depends_on_stock'] != 0 && $info['depends_on_stock'] != 1) - $this->warnings[] = sprintf(Tools::displayError('Incorrect value for depends on stock for product %1$s '), $product->name[$default_language]); - elseif ((!$info['advanced_stock_management'] || $info['advanced_stock_management'] == 0) && $info['depends_on_stock'] == 1) - $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, cannot set depends on stock %1$s '), $product->name[$default_language]); - else - StockAvailable::setProductDependsOnStock($product->id, $info['depends_on_stock'], null, $id_product_attribute); + // stock available + if (isset($info['depends_on_stock'])) { + if ($info['depends_on_stock'] != 0 && $info['depends_on_stock'] != 1) { + $this->warnings[] = sprintf(Tools::displayError('Incorrect value for depends on stock for product %1$s '), $product->name[$default_language]); + } elseif ((!$info['advanced_stock_management'] || $info['advanced_stock_management'] == 0) && $info['depends_on_stock'] == 1) { + $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, cannot set depends on stock %1$s '), $product->name[$default_language]); + } else { + StockAvailable::setProductDependsOnStock($product->id, $info['depends_on_stock'], null, $id_product_attribute); + } - // This code allows us to set qty and disable depends on stock - if (isset($info['quantity']) && (int)$info['quantity']) - { - // if depends on stock and quantity, add quantity to stock - if ($info['depends_on_stock'] == 1) - { - $stock_manager = StockManagerFactory::getManager(); - $price = str_replace(',', '.', $info['wholesale_price']); - if ($price == 0) - $price = 0.000001; - $price = round(floatval($price), 6); - $warehouse = new Warehouse($info['warehouse']); - if ($stock_manager->addProduct((int)$product->id, $id_product_attribute, $warehouse, (int)$info['quantity'], 1, $price, true)) - StockAvailable::synchronize((int)$product->id); - } - else - { - if ($shop_is_feature_active) - foreach ($id_shop_list as $shop) - StockAvailable::setQuantity((int)$product->id, $id_product_attribute, (int)$info['quantity'], (int)$shop); - else - StockAvailable::setQuantity((int)$product->id, $id_product_attribute, (int)$info['quantity'], $this->context->shop->id); - } + // This code allows us to set qty and disable depends on stock + if (isset($info['quantity']) && (int)$info['quantity']) { + // if depends on stock and quantity, add quantity to stock + if ($info['depends_on_stock'] == 1) { + $stock_manager = StockManagerFactory::getManager(); + $price = str_replace(',', '.', $info['wholesale_price']); + if ($price == 0) { + $price = 0.000001; + } + $price = round(floatval($price), 6); + $warehouse = new Warehouse($info['warehouse']); + if ($stock_manager->addProduct((int)$product->id, $id_product_attribute, $warehouse, (int)$info['quantity'], 1, $price, true)) { + StockAvailable::synchronize((int)$product->id); + } + } else { + if ($shop_is_feature_active) { + foreach ($id_shop_list as $shop) { + StockAvailable::setQuantity((int)$product->id, $id_product_attribute, (int)$info['quantity'], (int)$shop); + } + } else { + StockAvailable::setQuantity((int)$product->id, $id_product_attribute, (int)$info['quantity'], $this->context->shop->id); + } + } + } + } + // if not depends_on_stock set, use normal qty + else { + if ($shop_is_feature_active) { + foreach ($id_shop_list as $shop) { + StockAvailable::setQuantity((int)$product->id, $id_product_attribute, (int)$info['quantity'], (int)$shop); + } + } else { + StockAvailable::setQuantity((int)$product->id, $id_product_attribute, (int)$info['quantity'], $this->context->shop->id); + } + } + } + } + $this->closeCsvFile($handle); + } - } - } - // if not depends_on_stock set, use normal qty - else - { - if ($shop_is_feature_active) - foreach ($id_shop_list as $shop) - StockAvailable::setQuantity((int)$product->id, $id_product_attribute, (int)$info['quantity'], (int)$shop); - else - StockAvailable::setQuantity((int)$product->id, $id_product_attribute, (int)$info['quantity'], $this->context->shop->id); - } + public function customerImport() + { + $this->receiveTab(); + $handle = $this->openCsvFile(); + $default_language_id = (int)Configuration::get('PS_LANG_DEFAULT'); + $id_lang = Language::getIdByIso(Tools::getValue('iso_lang')); + if (!Validate::isUnsignedId($id_lang)) { + $id_lang = $default_language_id; + } + AdminImportController::setLocale(); - } - } - $this->closeCsvFile($handle); - } + $shop_is_feature_active = Shop::isFeatureActive(); + $convert = Tools::getValue('convert'); + $force_ids = Tools::getValue('forceIDs'); - public function customerImport() - { - $this->receiveTab(); - $handle = $this->openCsvFile(); - $default_language_id = (int)Configuration::get('PS_LANG_DEFAULT'); - $id_lang = Language::getIdByIso(Tools::getValue('iso_lang')); - if (!Validate::isUnsignedId($id_lang)) - $id_lang = $default_language_id; - AdminImportController::setLocale(); + for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) { + if ($convert) { + $line = $this->utf8EncodeArray($line); + } + $info = AdminImportController::getMaskedRow($line); - $shop_is_feature_active = Shop::isFeatureActive(); - $convert = Tools::getValue('convert'); - $force_ids = Tools::getValue('forceIDs'); + AdminImportController::setDefaultValues($info); - for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) - { - if ($convert) - $line = $this->utf8EncodeArray($line); - $info = AdminImportController::getMaskedRow($line); + if ($force_ids && isset($info['id']) && (int)$info['id']) { + $customer = new Customer((int)$info['id']); + } else { + if (array_key_exists('id', $info) && (int)$info['id'] && Customer::customerIdExistsStatic((int)$info['id'])) { + $customer = new Customer((int)$info['id']); + } else { + $customer = new Customer(); + } + } - AdminImportController::setDefaultValues($info); + $customer_exist = false; - if ($force_ids && isset($info['id']) && (int)$info['id']) - $customer = new Customer((int)$info['id']); - else - { - if (array_key_exists('id', $info) && (int)$info['id'] && Customer::customerIdExistsStatic((int)$info['id'])) - $customer = new Customer((int)$info['id']); - else - $customer = new Customer(); - } + if (array_key_exists('id', $info) && (int)$info['id'] && Customer::customerIdExistsStatic((int)$info['id']) && Validate::isLoadedObject($customer)) { + $current_id_customer = (int)$customer->id; + $current_id_shop = (int)$customer->id_shop; + $current_id_shop_group = (int)$customer->id_shop_group; + $customer_exist = true; + $customer_groups = $customer->getGroups(); + $addresses = $customer->getAddresses((int)Configuration::get('PS_LANG_DEFAULT')); + } - $customer_exist = false; + // Group Importation + if (isset($info['group']) && !empty($info['group'])) { + foreach (explode($this->multiple_value_separator, $info['group']) as $key => $group) { + $group = trim($group); + if (empty($group)) { + continue; + } + $id_group = false; + if (is_numeric($group) && $group) { + $my_group = new Group((int)$group); + if (Validate::isLoadedObject($my_group)) { + $customer_groups[] = (int)$group; + } + continue; + } + $my_group = Group::searchByName($group); + if (isset($my_group['id_group']) && $my_group['id_group']) { + $id_group = (int)$my_group['id_group']; + } + if (!$id_group) { + $my_group = new Group(); + $my_group->name = array($id_lang => $group); + if ($id_lang != $default_language_id) { + $my_group->name = $my_group->name + array($default_language_id => $group); + } + $my_group->price_display_method = 1; + $my_group->add(); + if (Validate::isLoadedObject($my_group)) { + $id_group = (int)$my_group->id; + } + } + if ($id_group) { + $customer_groups[] = (int)$id_group; + } + } + } elseif (empty($info['group']) && isset($customer->id) && $customer->id) { + $customer_groups = array(0 => Configuration::get('PS_CUSTOMER_GROUP')); + } - if (array_key_exists('id', $info) && (int)$info['id'] && Customer::customerIdExistsStatic((int)$info['id']) && Validate::isLoadedObject($customer)) - { - $current_id_customer = (int)$customer->id; - $current_id_shop = (int)$customer->id_shop; - $current_id_shop_group = (int)$customer->id_shop_group; - $customer_exist = true; - $customer_groups = $customer->getGroups(); - $addresses = $customer->getAddresses((int)Configuration::get('PS_LANG_DEFAULT')); - } + AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $customer); - // Group Importation - if (isset($info['group']) && !empty($info['group'])) - { - foreach (explode($this->multiple_value_separator, $info['group']) as $key => $group) - { - $group = trim($group); - if (empty($group)) - continue; - $id_group = false; - if (is_numeric($group) && $group) - { - $my_group = new Group((int)$group); - if (Validate::isLoadedObject($my_group)) - $customer_groups[] = (int)$group; - continue; - } - $my_group = Group::searchByName($group); - if (isset($my_group['id_group']) && $my_group['id_group']) - $id_group = (int)$my_group['id_group']; - if (!$id_group) - { - $my_group = new Group(); - $my_group->name = Array($id_lang => $group); - if ($id_lang != $default_language_id) - $my_group->name = $my_group->name + array($default_language_id => $group); - $my_group->price_display_method = 1; - $my_group->add(); - if (Validate::isLoadedObject($my_group)) - $id_group = (int)$my_group->id; - } - if ($id_group) - $customer_groups[] = (int)$id_group; - } - } - elseif (empty($info['group']) && isset($customer->id) && $customer->id) - $customer_groups = array(0 => Configuration::get('PS_CUSTOMER_GROUP')); + if ($customer->passwd) { + $customer->passwd = Tools::encrypt($customer->passwd); + } - AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $customer); + $id_shop_list = explode($this->multiple_value_separator, $customer->id_shop); + $customers_shop = array(); + $customers_shop['shared'] = array(); + $default_shop = new Shop((int)Configuration::get('PS_SHOP_DEFAULT')); + if ($shop_is_feature_active && $id_shop_list) { + foreach ($id_shop_list as $id_shop) { + if (empty($id_shop)) { + continue; + } + $shop = new Shop((int)$id_shop); + $group_shop = $shop->getGroup(); + if ($group_shop->share_customer) { + if (!in_array($group_shop->id, $customers_shop['shared'])) { + $customers_shop['shared'][(int)$id_shop] = $group_shop->id; + } + } else { + $customers_shop[(int)$id_shop] = $group_shop->id; + } + } + } else { + $default_shop = new Shop((int)Configuration::get('PS_SHOP_DEFAULT')); + $default_shop->getGroup(); + $customers_shop[$default_shop->id] = $default_shop->getGroup()->id; + } - if ($customer->passwd) - $customer->passwd = Tools::encrypt($customer->passwd); + //set temporally for validate field + $customer->id_shop = $default_shop->id; + $customer->id_shop_group = $default_shop->getGroup()->id; + if (isset($info['id_default_group']) && !empty($info['id_default_group']) && !is_numeric($info['id_default_group'])) { + $info['id_default_group'] = trim($info['id_default_group']); + $my_group = Group::searchByName($info['id_default_group']); + if (isset($my_group['id_group']) && $my_group['id_group']) { + $info['id_default_group'] = (int)$my_group['id_group']; + } + } + $my_group = new Group($customer->id_default_group); + if (!Validate::isLoadedObject($my_group)) { + $customer->id_default_group = (int)Configuration::get('PS_CUSTOMER_GROUP'); + } + $customer_groups[] = (int)$customer->id_default_group; + $customer_groups = array_flip(array_flip($customer_groups)); + $res = false; + if (($field_error = $customer->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $customer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) { + $res = true; + foreach ($customers_shop as $id_shop => $id_group) { + $customer->force_id = (bool)$force_ids; + if ($id_shop == 'shared') { + foreach ($id_group as $key => $id) { + $customer->id_shop = (int)$key; + $customer->id_shop_group = (int)$id; + if ($customer_exist && ((int)$current_id_shop_group == (int)$id || in_array($current_id_shop, ShopGroup::getShopsFromGroup($id)))) { + $customer->id = (int)$current_id_customer; + $res &= $customer->update(); + } else { + $res &= $customer->add(); + if (isset($addresses)) { + foreach ($addresses as $address) { + $address['id_customer'] = $customer->id; + unset($address['country'], $address['state'], $address['state_iso'], $address['id_address']); + Db::getInstance()->insert('address', $address, false, false); + } + } + } + if ($res && isset($customer_groups)) { + $customer->updateGroup($customer_groups); + } + } + } else { + $customer->id_shop = $id_shop; + $customer->id_shop_group = $id_group; + if ($customer_exist && (int)$id_shop == (int)$current_id_shop) { + $customer->id = (int)$current_id_customer; + $res &= $customer->update(); + } else { + $res &= $customer->add(); + if (isset($addresses)) { + foreach ($addresses as $address) { + $address['id_customer'] = $customer->id; + unset($address['country'], $address['state'], $address['state_iso'], $address['id_address']); + Db::getInstance()->insert('address', $address, false, false); + } + } + } + if ($res && isset($customer_groups)) { + $customer->updateGroup($customer_groups); + } + } + } + } - $id_shop_list = explode($this->multiple_value_separator, $customer->id_shop); - $customers_shop = array(); - $customers_shop['shared'] = array(); - $default_shop = new Shop((int)Configuration::get('PS_SHOP_DEFAULT')); - if ($shop_is_feature_active && $id_shop_list) - { - foreach ($id_shop_list as $id_shop) - { - if (empty($id_shop)) - continue; - $shop = new Shop((int)$id_shop); - $group_shop = $shop->getGroup(); - if ($group_shop->share_customer) - { - if (!in_array($group_shop->id, $customers_shop['shared'])) - $customers_shop['shared'][(int)$id_shop] = $group_shop->id; - } - else - $customers_shop[(int)$id_shop] = $group_shop->id; - } - } - else - { - $default_shop = new Shop((int)Configuration::get('PS_SHOP_DEFAULT')); - $default_shop->getGroup(); - $customers_shop[$default_shop->id] = $default_shop->getGroup()->id; - } + if (isset($customer_groups)) { + unset($customer_groups); + } + if (isset($current_id_customer)) { + unset($current_id_customer); + } + if (isset($current_id_shop)) { + unset($current_id_shop); + } + if (isset($current_id_shop_group)) { + unset($current_id_shop_group); + } + if (isset($addresses)) { + unset($addresses); + } - //set temporally for validate field - $customer->id_shop = $default_shop->id; - $customer->id_shop_group = $default_shop->getGroup()->id; - if (isset($info['id_default_group']) && !empty($info['id_default_group']) && !is_numeric($info['id_default_group'])) - { - $info['id_default_group'] = trim($info['id_default_group']); - $my_group = Group::searchByName($info['id_default_group']); - if (isset($my_group['id_group']) && $my_group['id_group']) - $info['id_default_group'] = (int)$my_group['id_group']; - } - $my_group = new Group($customer->id_default_group); - if (!Validate::isLoadedObject($my_group)) - $customer->id_default_group = (int)Configuration::get('PS_CUSTOMER_GROUP'); - $customer_groups[] = (int)$customer->id_default_group; - $customer_groups = array_flip(array_flip($customer_groups)); - $res = false; - if (($field_error = $customer->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $customer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) - { - $res = true; - foreach ($customers_shop as $id_shop => $id_group) - { - $customer->force_id = (bool)$force_ids; - if ($id_shop == 'shared') - { - foreach ($id_group as $key => $id) - { - $customer->id_shop = (int)$key; - $customer->id_shop_group = (int)$id; - if ($customer_exist && ((int)$current_id_shop_group == (int)$id || in_array($current_id_shop, ShopGroup::getShopsFromGroup($id)))) - { - $customer->id = (int)$current_id_customer; - $res &= $customer->update(); - } - else - { - $res &= $customer->add(); - if (isset($addresses)) - foreach ($addresses as $address) - { - $address['id_customer'] = $customer->id; - unset($address['country'], $address['state'], $address['state_iso'], $address['id_address']); - Db::getInstance()->insert('address', $address, false, false); - } - } - if ($res && isset($customer_groups)) - $customer->updateGroup($customer_groups); - } - } - else - { - $customer->id_shop = $id_shop; - $customer->id_shop_group = $id_group; - if ($customer_exist && (int)$id_shop == (int)$current_id_shop) - { - $customer->id = (int)$current_id_customer; - $res &= $customer->update(); - } - else - { - $res &= $customer->add(); - if (isset($addresses)) - foreach ($addresses as $address) - { - $address['id_customer'] = $customer->id; - unset($address['country'], $address['state'], $address['state_iso'], $address['id_address']); - Db::getInstance()->insert('address', $address, false, false); - } - } - if ($res && isset($customer_groups)) - $customer->updateGroup($customer_groups); - } - } - } + if (!$res) { + $this->errors[] = sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + $info['email'], + (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null' + ); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). + Db::getInstance()->getMsgError(); + } + } + $this->closeCsvFile($handle); + } - if (isset($customer_groups)) - unset($customer_groups); - if (isset($current_id_customer)) - unset($current_id_customer); - if (isset($current_id_shop)) - unset($current_id_shop); - if (isset($current_id_shop_group)) - unset($current_id_shop_group); - if (isset($addresses)) - unset($addresses); + public function addressImport() + { + $this->receiveTab(); + $default_language_id = (int)Configuration::get('PS_LANG_DEFAULT'); + $handle = $this->openCsvFile(); + AdminImportController::setLocale(); - if (!$res) - { - $this->errors[] = sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - $info['email'], - (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null' - ); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). - Db::getInstance()->getMsgError(); - } - } - $this->closeCsvFile($handle); - } + $convert = Tools::getValue('convert'); + $force_ids = Tools::getValue('forceIDs'); - public function addressImport() - { - $this->receiveTab(); - $default_language_id = (int)Configuration::get('PS_LANG_DEFAULT'); - $handle = $this->openCsvFile(); - AdminImportController::setLocale(); + for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) { + if ($convert) { + $line = $this->utf8EncodeArray($line); + } + $info = AdminImportController::getMaskedRow($line); - $convert = Tools::getValue('convert'); - $force_ids = Tools::getValue('forceIDs'); + AdminImportController::setDefaultValues($info); - for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) - { - if ($convert) - $line = $this->utf8EncodeArray($line); - $info = AdminImportController::getMaskedRow($line); + if ($force_ids && isset($info['id']) && (int)$info['id']) { + $address = new Address((int)$info['id']); + } else { + if (array_key_exists('id', $info) && (int)$info['id'] && Address::addressExists((int)$info['id'])) { + $address = new Address((int)$info['id']); + } else { + $address = new Address(); + } + } - AdminImportController::setDefaultValues($info); + AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $address); - if ($force_ids && isset($info['id']) && (int)$info['id']) - $address = new Address((int)$info['id']); - else - { - if (array_key_exists('id', $info) && (int)$info['id'] && Address::addressExists((int)$info['id'])) - $address = new Address((int)$info['id']); - else - $address = new Address(); - } + if (isset($address->country) && is_numeric($address->country)) { + if (Country::getNameById(Configuration::get('PS_LANG_DEFAULT'), (int)$address->country)) { + $address->id_country = (int)$address->country; + } + } elseif (isset($address->country) && is_string($address->country) && !empty($address->country)) { + if ($id_country = (int)Country::getIdByName(null, $address->country)) { + $address->id_country = $id_country; + } else { + $country = new Country(); + $country->active = 1; + $country->name = AdminImportController::createMultiLangField($address->country); + $country->id_zone = 0; // Default zone for country to create + $country->iso_code = Tools::strtoupper(Tools::substr($address->country, 0, 2)); // Default iso for country to create + $country->contains_states = 0; // Default value for country to create + $lang_field_error = $country->validateFieldsLang(UNFRIENDLY_ERROR, true); + if (($field_error = $country->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $country->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $country->add()) { + $address->id_country = (int)$country->id; + } else { + $this->errors[] = sprintf(Tools::displayError('%s cannot be saved'), $country->name[$default_language_id]); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). + Db::getInstance()->getMsgError(); + } + } + } - AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $address); + if (isset($address->state) && is_numeric($address->state)) { + if (State::getNameById((int)$address->state)) { + $address->id_state = (int)$address->state; + } + } elseif (isset($address->state) && is_string($address->state) && !empty($address->state)) { + if ($id_state = State::getIdByName($address->state)) { + $address->id_state = (int)$id_state; + } else { + $state = new State(); + $state->active = 1; + $state->name = $address->state; + $state->id_country = isset($country->id) ? (int)$country->id : 0; + $state->id_zone = 0; // Default zone for state to create + $state->iso_code = Tools::strtoupper(Tools::substr($address->state, 0, 2)); // Default iso for state to create + $state->tax_behavior = 0; + if (($field_error = $state->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $state->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $state->add()) { + $address->id_state = (int)$state->id; + } else { + $this->errors[] = sprintf(Tools::displayError('%s cannot be saved'), $state->name); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). + Db::getInstance()->getMsgError(); + } + } + } - if (isset($address->country) && is_numeric($address->country)) - { - if (Country::getNameById(Configuration::get('PS_LANG_DEFAULT'), (int)$address->country)) - $address->id_country = (int)$address->country; - } - elseif (isset($address->country) && is_string($address->country) && !empty($address->country)) - { - if ($id_country = Country::getIdByName(null, $address->country)) - $address->id_country = (int)$id_country; - else - { - $country = new Country(); - $country->active = 1; - $country->name = AdminImportController::createMultiLangField($address->country); - $country->id_zone = 0; // Default zone for country to create - $country->iso_code = Tools::strtoupper(Tools::substr($address->country, 0, 2)); // Default iso for country to create - $country->contains_states = 0; // Default value for country to create - $lang_field_error = $country->validateFieldsLang(UNFRIENDLY_ERROR, true); - if (($field_error = $country->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $country->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $country->add()) - $address->id_country = (int)$country->id; - else - { - $this->errors[] = sprintf(Tools::displayError('%s cannot be saved'), $country->name[$default_language_id]); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). - Db::getInstance()->getMsgError(); - } - } - } + if (isset($address->customer_email) && !empty($address->customer_email)) { + if (Validate::isEmail($address->customer_email)) { + // a customer could exists in different shop + $customer_list = Customer::getCustomersByEmail($address->customer_email); - if (isset($address->state) && is_numeric($address->state)) - { - if (State::getNameById((int)$address->state)) - $address->id_state = (int)$address->state; - } - elseif (isset($address->state) && is_string($address->state) && !empty($address->state)) - { - if ($id_state = State::getIdByName($address->state)) - $address->id_state = (int)$id_state; - else - { - $state = new State(); - $state->active = 1; - $state->name = $address->state; - $state->id_country = isset($country->id) ? (int)$country->id : 0; - $state->id_zone = 0; // Default zone for state to create - $state->iso_code = Tools::strtoupper(Tools::substr($address->state, 0, 2)); // Default iso for state to create - $state->tax_behavior = 0; - if (($field_error = $state->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $state->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $state->add()) - $address->id_state = (int)$state->id; - else - { - $this->errors[] = sprintf(Tools::displayError('%s cannot be saved'), $state->name); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). - Db::getInstance()->getMsgError(); - } - } - } + if (count($customer_list) == 0) { + $this->errors[] = sprintf( + Tools::displayError('%1$s does not exist in database %2$s (ID: %3$s), and therefore cannot be saved.'), + Db::getInstance()->getMsgError(), + $address->customer_email, + (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null' + ); + } + } else { + $this->errors[] = sprintf(Tools::displayError('"%s" is not a valid email address.'), $address->customer_email); + continue; + } + } elseif (isset($address->id_customer) && !empty($address->id_customer)) { + if (Customer::customerIdExistsStatic((int)$address->id_customer)) { + $customer = new Customer((int)$address->id_customer); - if (isset($address->customer_email) && !empty($address->customer_email)) - { - if (Validate::isEmail($address->customer_email)) - { - // a customer could exists in different shop - $customer_list = Customer::getCustomersByEmail($address->customer_email); + // a customer could exists in different shop + $customer_list = Customer::getCustomersByEmail($customer->email); - if (count($customer_list) == 0) - $this->errors[] = sprintf( - Tools::displayError('%1$s does not exist in database %2$s (ID: %3$s), and therefore cannot be saved.'), - Db::getInstance()->getMsgError(), - $address->customer_email, - (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null' - ); - } - else - { - $this->errors[] = sprintf(Tools::displayError('"%s" is not a valid email address.'), $address->customer_email); - continue; - } - } - elseif (isset($address->id_customer) && !empty($address->id_customer)) - { - if (Customer::customerIdExistsStatic((int)$address->id_customer)) - { - $customer = new Customer((int)$address->id_customer); + if (count($customer_list) == 0) { + $this->errors[] = sprintf( + Tools::displayError('%1$s does not exist in database %2$s (ID: %3$s), and therefore cannot be saved.'), + Db::getInstance()->getMsgError(), + $customer->email, + (int)$address->id_customer + ); + } + } else { + $this->errors[] = sprintf(Tools::displayError('The customer ID #%d does not exist in the database, and therefore cannot be saved.'), $address->id_customer); + } + } else { + $customer_list = array(); + $address->id_customer = 0; + } - // a customer could exists in different shop - $customer_list = Customer::getCustomersByEmail($customer->email); + if (isset($address->manufacturer) && is_numeric($address->manufacturer) && Manufacturer::manufacturerExists((int)$address->manufacturer)) { + $address->id_manufacturer = (int)$address->manufacturer; + } elseif (isset($address->manufacturer) && is_string($address->manufacturer) && !empty($address->manufacturer)) { + $manufacturer = new Manufacturer(); + $manufacturer->name = $address->manufacturer; + if (($field_error = $manufacturer->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $manufacturer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $manufacturer->add()) { + $address->id_manufacturer = (int)$manufacturer->id; + } else { + $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + $manufacturer->name, + (isset($manufacturer->id) && !empty($manufacturer->id))? $manufacturer->id : 'null' + ); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). + Db::getInstance()->getMsgError(); + } + } - if (count($customer_list) == 0) - $this->errors[] = sprintf( - Tools::displayError('%1$s does not exist in database %2$s (ID: %3$s), and therefore cannot be saved.'), - Db::getInstance()->getMsgError(), - $customer->email, - (int)$address->id_customer - ); - } - else - $this->errors[] = sprintf(Tools::displayError('The customer ID #%d does not exist in the database, and therefore cannot be saved.'), $address->id_customer); - } - else - { - $customer_list = array(); - $address->id_customer = 0; - } + if (isset($address->supplier) && is_numeric($address->supplier) && Supplier::supplierExists((int)$address->supplier)) { + $address->id_supplier = (int)$address->supplier; + } elseif (isset($address->supplier) && is_string($address->supplier) && !empty($address->supplier)) { + $supplier = new Supplier(); + $supplier->name = $address->supplier; + if (($field_error = $supplier->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $supplier->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $supplier->add()) { + $address->id_supplier = (int)$supplier->id; + } else { + $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + $supplier->name, + (isset($supplier->id) && !empty($supplier->id))? $supplier->id : 'null' + ); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). + Db::getInstance()->getMsgError(); + } + } - if (isset($address->manufacturer) && is_numeric($address->manufacturer) && Manufacturer::manufacturerExists((int)$address->manufacturer)) - $address->id_manufacturer = (int)$address->manufacturer; - elseif (isset($address->manufacturer) && is_string($address->manufacturer) && !empty($address->manufacturer)) - { - $manufacturer = new Manufacturer(); - $manufacturer->name = $address->manufacturer; - if (($field_error = $manufacturer->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $manufacturer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $manufacturer->add()) - $address->id_manufacturer = (int)$manufacturer->id; - else - { - $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - $manufacturer->name, - (isset($manufacturer->id) && !empty($manufacturer->id))? $manufacturer->id : 'null' - ); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). - Db::getInstance()->getMsgError(); - } - } + $res = false; + if (($field_error = $address->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $address->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) { + $address->force_id = (bool)$force_ids; - if (isset($address->supplier) && is_numeric($address->supplier) && Supplier::supplierExists((int)$address->supplier)) - $address->id_supplier = (int)$address->supplier; - elseif (isset($address->supplier) && is_string($address->supplier) && !empty($address->supplier)) - { - $supplier = new Supplier(); - $supplier->name = $address->supplier; - if (($field_error = $supplier->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $supplier->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $supplier->add()) - $address->id_supplier = (int)$supplier->id; - else - { - $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - $supplier->name, - (isset($supplier->id) && !empty($supplier->id))? $supplier->id : 'null' - ); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). - Db::getInstance()->getMsgError(); - } - } + if (isset($customer_list) && count($customer_list) > 0) { + $filter_list = array(); + foreach ($customer_list as $customer) { + if (in_array($customer['id_customer'], $filter_list)) { + continue; + } - $res = false; - if (($field_error = $address->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $address->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) - { - $address->force_id = (bool)$force_ids; + $filter_list[] = $customer['id_customer']; + $address->id_customer = $customer['id_customer']; + } + } - if (isset($customer_list) && count($customer_list) > 0) - { - $filter_list = array(); - foreach ($customer_list as $customer) - { - if (in_array($customer['id_customer'], $filter_list)) - continue; + if ($address->id && $address->addressExists($address->id)) { + $res = $address->update(); + } + if (!$res) { + $res = $address->add(); + } + } + if (!$res) { + $this->errors[] = sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + $info['alias'], + (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null' + ); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). + Db::getInstance()->getMsgError(); + } + } + $this->closeCsvFile($handle); + } - $filter_list[] = $customer['id_customer']; - $address->id_customer = $customer['id_customer']; - } - } + public function manufacturerImport() + { + $this->receiveTab(); + $handle = $this->openCsvFile(); + AdminImportController::setLocale(); - if ($address->id && $address->addressExists($address->id)) - $res = $address->update(); - if (!$res) - $res = $address->add(); - } - if (!$res) - { - $this->errors[] = sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - $info['alias'], - (isset($info['id']) && !empty($info['id']))? $info['id'] : 'null' - ); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). - Db::getInstance()->getMsgError(); - } - } - $this->closeCsvFile($handle); - } + $shop_is_feature_active = Shop::isFeatureActive(); + $convert = Tools::getValue('convert'); + $regenerate = Tools::getValue('regenerate'); + $force_ids = Tools::getValue('forceIDs'); - public function manufacturerImport() - { - $this->receiveTab(); - $handle = $this->openCsvFile(); - AdminImportController::setLocale(); + for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) { + if ($convert) { + $line = $this->utf8EncodeArray($line); + } + $info = AdminImportController::getMaskedRow($line); - $shop_is_feature_active = Shop::isFeatureActive(); - $convert = Tools::getValue('convert'); - $regenerate = Tools::getValue('regenerate'); - $force_ids = Tools::getValue('forceIDs'); + AdminImportController::setDefaultValues($info); - for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) - { - if ($convert) - $line = $this->utf8EncodeArray($line); - $info = AdminImportController::getMaskedRow($line); + if ($force_ids && isset($info['id']) && (int)$info['id']) { + $manufacturer = new Manufacturer((int)$info['id']); + } else { + if (array_key_exists('id', $info) && (int)$info['id'] && Manufacturer::existsInDatabase((int)$info['id'], 'manufacturer')) { + $manufacturer = new Manufacturer((int)$info['id']); + } else { + $manufacturer = new Manufacturer(); + } + } - AdminImportController::setDefaultValues($info); + AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $manufacturer); - if ($force_ids && isset($info['id']) && (int)$info['id']) - $manufacturer = new Manufacturer((int)$info['id']); - else - { - if (array_key_exists('id', $info) && (int)$info['id'] && Manufacturer::existsInDatabase((int)$info['id'], 'manufacturer')) - $manufacturer = new Manufacturer((int)$info['id']); - else - $manufacturer = new Manufacturer(); - } + $res = false; + if (($field_error = $manufacturer->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $manufacturer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) { + if ($manufacturer->id && $manufacturer->manufacturerExists($manufacturer->id)) { + $res = $manufacturer->update(); + } + $manufacturer->force_id = (bool)$force_ids; + if (!$res) { + $res = $manufacturer->add(); + } - AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $manufacturer); + //copying images of manufacturer + if (isset($manufacturer->image) && !empty($manufacturer->image)) { + if (!AdminImportController::copyImg($manufacturer->id, null, $manufacturer->image, 'manufacturers', !$regenerate)) { + $this->warnings[] = $manufacturer->image.' '.Tools::displayError('cannot be copied.'); + } + } - $res = false; - if (($field_error = $manufacturer->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $manufacturer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) - { - if ($manufacturer->id && $manufacturer->manufacturerExists($manufacturer->id)) - $res = $manufacturer->update(); - $manufacturer->force_id = (bool)$force_ids; - if (!$res) - $res = $manufacturer->add(); - - //copying images of manufacturer - if (isset($manufacturer->image) && !empty($manufacturer->image)) - if (!AdminImportController::copyImg($manufacturer->id, null, $manufacturer->image, 'manufacturers', !$regenerate)) - $this->warnings[] = $manufacturer->image.' '.Tools::displayError('cannot be copied.'); - - if ($res) - { - // Associate supplier to group shop - if ($shop_is_feature_active && $manufacturer->shop) - { - Db::getInstance()->execute(' + if ($res) { + // Associate supplier to group shop + if ($shop_is_feature_active && $manufacturer->shop) { + Db::getInstance()->execute(' DELETE FROM '._DB_PREFIX_.'manufacturer_shop WHERE id_manufacturer = '.(int)$manufacturer->id - ); - $manufacturer->shop = explode($this->multiple_value_separator, $manufacturer->shop); - $shops = array(); - foreach ($manufacturer->shop as $shop) - { - if (empty($shop)) - continue; - $shop = trim($shop); - if (!is_numeric($shop)) - $shop = ShopGroup::getIdByName($shop); - $shops[] = $shop; - } - $manufacturer->associateTo($shops); - } - } - } + ); + $manufacturer->shop = explode($this->multiple_value_separator, $manufacturer->shop); + $shops = array(); + foreach ($manufacturer->shop as $shop) { + if (empty($shop)) { + continue; + } + $shop = trim($shop); + if (!is_numeric($shop)) { + $shop = ShopGroup::getIdByName($shop); + } + $shops[] = $shop; + } + $manufacturer->associateTo($shops); + } + } + } - if (!$res) - { - $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - (isset($info['name']) && !empty($info['name']))? Tools::safeOutput($info['name']) : 'No Name', - (isset($info['id']) && !empty($info['id']))? Tools::safeOutput($info['id']) : 'No ID' - ); - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). - Db::getInstance()->getMsgError(); - } - } - $this->closeCsvFile($handle); - } + if (!$res) { + $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + (isset($info['name']) && !empty($info['name']))? Tools::safeOutput($info['name']) : 'No Name', + (isset($info['id']) && !empty($info['id']))? Tools::safeOutput($info['id']) : 'No ID' + ); + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''). + Db::getInstance()->getMsgError(); + } + } + $this->closeCsvFile($handle); + } - public function supplierImport() - { - $this->receiveTab(); - $handle = $this->openCsvFile(); - AdminImportController::setLocale(); + public function supplierImport() + { + $this->receiveTab(); + $handle = $this->openCsvFile(); + AdminImportController::setLocale(); - $shop_is_feature_active = Shop::isFeatureActive(); - $convert = Tools::getValue('convert'); - $regenerate = Tools::getValue('regenerate'); - $force_ids = Tools::getValue('forceIDs'); + $shop_is_feature_active = Shop::isFeatureActive(); + $convert = Tools::getValue('convert'); + $regenerate = Tools::getValue('regenerate'); + $force_ids = Tools::getValue('forceIDs'); - for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) - { - if ($convert) - $line = $this->utf8EncodeArray($line); - $info = AdminImportController::getMaskedRow($line); + for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) { + if ($convert) { + $line = $this->utf8EncodeArray($line); + } + $info = AdminImportController::getMaskedRow($line); - AdminImportController::setDefaultValues($info); + AdminImportController::setDefaultValues($info); - if ($force_ids && isset($info['id']) && (int)$info['id']) - $supplier = new Supplier((int)$info['id']); - else - { - if (array_key_exists('id', $info) && (int)$info['id'] && Supplier::existsInDatabase((int)$info['id'], 'supplier')) - $supplier = new Supplier((int)$info['id']); - else - $supplier = new Supplier(); - } + if ($force_ids && isset($info['id']) && (int)$info['id']) { + $supplier = new Supplier((int)$info['id']); + } else { + if (array_key_exists('id', $info) && (int)$info['id'] && Supplier::existsInDatabase((int)$info['id'], 'supplier')) { + $supplier = new Supplier((int)$info['id']); + } else { + $supplier = new Supplier(); + } + } - AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $supplier); - if (($field_error = $supplier->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $supplier->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) - { - $res = false; - if ($supplier->id && $supplier->supplierExists($supplier->id)) - $res = $supplier->update(); - $supplier->force_id = (bool)$force_ids; - if (!$res) - $res = $supplier->add(); + AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $supplier); + if (($field_error = $supplier->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $supplier->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) { + $res = false; + if ($supplier->id && $supplier->supplierExists($supplier->id)) { + $res = $supplier->update(); + } + $supplier->force_id = (bool)$force_ids; + if (!$res) { + $res = $supplier->add(); + } - //copying images of suppliers - if (isset($supplier->image) && !empty($supplier->image)) - if (!AdminImportController::copyImg($supplier->id, null, $supplier->image, 'suppliers', !$regenerate)) - $this->warnings[] = $supplier->image.' '.Tools::displayError('cannot be copied.'); + //copying images of suppliers + if (isset($supplier->image) && !empty($supplier->image)) { + if (!AdminImportController::copyImg($supplier->id, null, $supplier->image, 'suppliers', !$regenerate)) { + $this->warnings[] = $supplier->image.' '.Tools::displayError('cannot be copied.'); + } + } - if (!$res) - $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - (isset($info['name']) && !empty($info['name']))? Tools::safeOutput($info['name']) : 'No Name', - (isset($info['id']) && !empty($info['id']))? Tools::safeOutput($info['id']) : 'No ID' - ); - else - { - // Associate supplier to group shop - if ($shop_is_feature_active && $supplier->shop) - { - Db::getInstance()->execute(' + if (!$res) { + $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + (isset($info['name']) && !empty($info['name']))? Tools::safeOutput($info['name']) : 'No Name', + (isset($info['id']) && !empty($info['id']))? Tools::safeOutput($info['id']) : 'No ID' + ); + } else { + // Associate supplier to group shop + if ($shop_is_feature_active && $supplier->shop) { + Db::getInstance()->execute(' DELETE FROM '._DB_PREFIX_.'supplier_shop WHERE id_supplier = '.(int)$supplier->id - ); - $supplier->shop = explode($this->multiple_value_separator, $supplier->shop); - $shops = array(); - foreach ($supplier->shop as $shop) - { - if (empty($shop)) - continue; - $shop = trim($shop); - if (!is_numeric($shop)) - $shop = ShopGroup::getIdByName($shop); - $shops[] = $shop; - } - $supplier->associateTo($shops); - } - } - } - else - { - $this->errors[] = $this->l('Supplier is invalid').' ('.$supplier->name.')'; - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); - } - } - $this->closeCsvFile($handle); - } + ); + $supplier->shop = explode($this->multiple_value_separator, $supplier->shop); + $shops = array(); + foreach ($supplier->shop as $shop) { + if (empty($shop)) { + continue; + } + $shop = trim($shop); + if (!is_numeric($shop)) { + $shop = ShopGroup::getIdByName($shop); + } + $shops[] = $shop; + } + $supplier->associateTo($shops); + } + } + } else { + $this->errors[] = $this->l('Supplier is invalid').' ('.$supplier->name.')'; + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); + } + } + $this->closeCsvFile($handle); + } - public function aliasImport() - { - $this->receiveTab(); - $handle = $this->openCsvFile(); - AdminImportController::setLocale(); + public function aliasImport() + { + $this->receiveTab(); + $handle = $this->openCsvFile(); + AdminImportController::setLocale(); - $convert = Tools::getValue('convert'); - $force_ids = Tools::getValue('forceIDs'); + $convert = Tools::getValue('convert'); + $force_ids = Tools::getValue('forceIDs'); - for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) - { - if ($convert) - $line = $this->utf8EncodeArray($line); - $info = AdminImportController::getMaskedRow($line); + for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) { + if ($convert) { + $line = $this->utf8EncodeArray($line); + } + $info = AdminImportController::getMaskedRow($line); - AdminImportController::setDefaultValues($info); + AdminImportController::setDefaultValues($info); - if ($force_ids && isset($info['id']) && (int)$info['id']) - $alias = new Alias((int)$info['id']); - else - { - if (array_key_exists('id', $info) && (int)$info['id'] && Alias::existsInDatabase((int)$info['id'], 'alias')) - $alias = new Alias((int)$info['id']); - else - $alias = new Alias(); - } + if ($force_ids && isset($info['id']) && (int)$info['id']) { + $alias = new Alias((int)$info['id']); + } else { + if (array_key_exists('id', $info) && (int)$info['id'] && Alias::existsInDatabase((int)$info['id'], 'alias')) { + $alias = new Alias((int)$info['id']); + } else { + $alias = new Alias(); + } + } - AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $alias); + AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $alias); - $res = false; - if (($field_error = $alias->validateFields(UNFRIENDLY_ERROR, true)) === true && - ($lang_field_error = $alias->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) - { - if ($alias->id && $alias->aliasExists($alias->id)) - $res = $alias->update(); - $alias->force_id = (bool)$force_ids; - if (!$res) - $res = $alias->add(); + $res = false; + if (($field_error = $alias->validateFields(UNFRIENDLY_ERROR, true)) === true && + ($lang_field_error = $alias->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) { + if ($alias->id && $alias->aliasExists($alias->id)) { + $res = $alias->update(); + } + $alias->force_id = (bool)$force_ids; + if (!$res) { + $res = $alias->add(); + } - if (!$res) - $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf( - Tools::displayError('%1$s (ID: %2$s) cannot be saved'), - $info['name'], - (isset($info['id']) ? $info['id'] : 'null') - ); - } - else - { - $this->errors[] = $this->l('Alias is invalid').' ('.$alias->name.')'; - $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); - } - } - $this->closeCsvFile($handle); - } + if (!$res) { + $this->errors[] = Db::getInstance()->getMsgError().' '.sprintf( + Tools::displayError('%1$s (ID: %2$s) cannot be saved'), + $info['name'], + (isset($info['id']) ? $info['id'] : 'null') + ); + } + } else { + $this->errors[] = $this->l('Alias is invalid').' ('.$alias->name.')'; + $this->errors[] = ($field_error !== true ? $field_error : '').(isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); + } + } + $this->closeCsvFile($handle); + } - /** - * @since 1.5.0 - */ - public function supplyOrdersImport() - { - // opens CSV & sets locale - $this->receiveTab(); - $handle = $this->openCsvFile(); - AdminImportController::setLocale(); + /** + * @since 1.5.0 + */ + public function supplyOrdersImport() + { + // opens CSV & sets locale + $this->receiveTab(); + $handle = $this->openCsvFile(); + AdminImportController::setLocale(); - $convert = Tools::getValue('convert'); - $force_ids = Tools::getValue('forceIDs'); + $convert = Tools::getValue('convert'); + $force_ids = Tools::getValue('forceIDs'); - // main loop, for each supply orders to import - for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); ++$current_line) - { - // if convert requested - if ($convert) - $line = $this->utf8EncodeArray($line); - $info = AdminImportController::getMaskedRow($line); + // main loop, for each supply orders to import + for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); ++$current_line) { + // if convert requested + if ($convert) { + $line = $this->utf8EncodeArray($line); + } + $info = AdminImportController::getMaskedRow($line); - // sets default values if needed - AdminImportController::setDefaultValues($info); + // sets default values if needed + AdminImportController::setDefaultValues($info); - // if an id is set, instanciates a supply order with this id if possible - if (array_key_exists('id', $info) && (int)$info['id'] && SupplyOrder::exists((int)$info['id'])) - $supply_order = new SupplyOrder((int)$info['id']); - // if a reference is set, instanciates a supply order with this reference if possible - elseif (array_key_exists('reference', $info) && $info['reference'] && SupplyOrder::exists(pSQL($info['reference']))) - $supply_order = SupplyOrder::getSupplyOrderByReference(pSQL($info['reference'])); - else // new supply order - $supply_order = new SupplyOrder(); + // if an id is set, instanciates a supply order with this id if possible + if (array_key_exists('id', $info) && (int)$info['id'] && SupplyOrder::exists((int)$info['id'])) { + $supply_order = new SupplyOrder((int)$info['id']); + } + // if a reference is set, instanciates a supply order with this reference if possible + elseif (array_key_exists('reference', $info) && $info['reference'] && SupplyOrder::exists(pSQL($info['reference']))) { + $supply_order = SupplyOrder::getSupplyOrderByReference(pSQL($info['reference'])); + } else { // new supply order + $supply_order = new SupplyOrder(); + } - // gets parameters - $id_supplier = (int)$info['id_supplier']; - $id_lang = (int)$info['id_lang']; - $id_warehouse = (int)$info['id_warehouse']; - $id_currency = (int)$info['id_currency']; - $reference = pSQL($info['reference']); - $date_delivery_expected = pSQL($info['date_delivery_expected']); - $discount_rate = (float)$info['discount_rate']; - $is_template = (bool)$info['is_template']; + // gets parameters + $id_supplier = (int)$info['id_supplier']; + $id_lang = (int)$info['id_lang']; + $id_warehouse = (int)$info['id_warehouse']; + $id_currency = (int)$info['id_currency']; + $reference = pSQL($info['reference']); + $date_delivery_expected = pSQL($info['date_delivery_expected']); + $discount_rate = (float)$info['discount_rate']; + $is_template = (bool)$info['is_template']; - $error = ''; - // checks parameters - if (!Supplier::supplierExists($id_supplier)) - $error = sprintf($this->l('Supplier ID (%d) is not valid (at line %d).'), $id_supplier, $current_line + 1); - if (!Language::getLanguage($id_lang)) - $error = sprintf($this->l('Lang ID (%d) is not valid (at line %d).'), $id_lang, $current_line + 1); - if (!Warehouse::exists($id_warehouse)) - $error = sprintf($this->l('Warehouse ID (%d) is not valid (at line %d).'), $id_warehouse, $current_line + 1); - if (!Currency::getCurrency($id_currency)) - $error = sprintf($this->l('Currency ID (%d) is not valid (at line %d).'), $id_currency, $current_line + 1); - if (empty($supply_order->reference) && SupplyOrder::exists($reference)) - $error = sprintf($this->l('Reference (%s) already exists (at line %d).'), $reference, $current_line + 1); - if (!empty($supply_order->reference) && ($supply_order->reference != $reference && SupplyOrder::exists($reference))) - $error = sprintf($this->l('Reference (%s) already exists (at line %d).'), $reference, $current_line + 1); - if (!Validate::isDateFormat($date_delivery_expected)) - $error = sprintf($this->l('Date (%s) is not valid (at line %d). Format: %s.'), $date_delivery_expected, $current_line + 1, $this->l('YYYY-MM-DD')); - elseif (new DateTime($date_delivery_expected) <= new DateTime('yesterday')) - $error = sprintf($this->l('Date (%s) cannot be in the past (at line %d). Format: %s.'), $date_delivery_expected, $current_line + 1, $this->l('YYYY-MM-DD')); - if ($discount_rate < 0 || $discount_rate > 100) - $error = sprintf($this->l('Discount rate (%d) is not valid (at line %d). %s.'), $discount_rate, $current_line + 1, $this->l('Format: Between 0 and 100')); - if ($supply_order->id > 0 && !$supply_order->isEditable()) - $error = sprintf($this->l('Supply Order (%d) is not editable (at line %d).'), $supply_order->id, $current_line + 1); + $error = ''; + // checks parameters + if (!Supplier::supplierExists($id_supplier)) { + $error = sprintf($this->l('Supplier ID (%d) is not valid (at line %d).'), $id_supplier, $current_line + 1); + } + if (!Language::getLanguage($id_lang)) { + $error = sprintf($this->l('Lang ID (%d) is not valid (at line %d).'), $id_lang, $current_line + 1); + } + if (!Warehouse::exists($id_warehouse)) { + $error = sprintf($this->l('Warehouse ID (%d) is not valid (at line %d).'), $id_warehouse, $current_line + 1); + } + if (!Currency::getCurrency($id_currency)) { + $error = sprintf($this->l('Currency ID (%d) is not valid (at line %d).'), $id_currency, $current_line + 1); + } + if (empty($supply_order->reference) && SupplyOrder::exists($reference)) { + $error = sprintf($this->l('Reference (%s) already exists (at line %d).'), $reference, $current_line + 1); + } + if (!empty($supply_order->reference) && ($supply_order->reference != $reference && SupplyOrder::exists($reference))) { + $error = sprintf($this->l('Reference (%s) already exists (at line %d).'), $reference, $current_line + 1); + } + if (!Validate::isDateFormat($date_delivery_expected)) { + $error = sprintf($this->l('Date (%s) is not valid (at line %d). Format: %s.'), $date_delivery_expected, $current_line + 1, $this->l('YYYY-MM-DD')); + } elseif (new DateTime($date_delivery_expected) <= new DateTime('yesterday')) { + $error = sprintf($this->l('Date (%s) cannot be in the past (at line %d). Format: %s.'), $date_delivery_expected, $current_line + 1, $this->l('YYYY-MM-DD')); + } + if ($discount_rate < 0 || $discount_rate > 100) { + $error = sprintf($this->l('Discount rate (%d) is not valid (at line %d). %s.'), $discount_rate, $current_line + 1, $this->l('Format: Between 0 and 100')); + } + if ($supply_order->id > 0 && !$supply_order->isEditable()) { + $error = sprintf($this->l('Supply Order (%d) is not editable (at line %d).'), $supply_order->id, $current_line + 1); + } - // if no errors, sets supply order - if (empty($error)) - { - // adds parameters - $info['id_ref_currency'] = (int)Currency::getDefaultCurrency()->id; - $info['supplier_name'] = pSQL(Supplier::getNameById($id_supplier)); - if ($supply_order->id > 0) - { - $info['id_supply_order_state'] = (int)$supply_order->id_supply_order_state; - $info['id'] = (int)$supply_order->id; - } - else - $info['id_supply_order_state'] = 1; + // if no errors, sets supply order + if (empty($error)) { + // adds parameters + $info['id_ref_currency'] = (int)Currency::getDefaultCurrency()->id; + $info['supplier_name'] = pSQL(Supplier::getNameById($id_supplier)); + if ($supply_order->id > 0) { + $info['id_supply_order_state'] = (int)$supply_order->id_supply_order_state; + $info['id'] = (int)$supply_order->id; + } else { + $info['id_supply_order_state'] = 1; + } - // sets parameters - AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $supply_order); + // sets parameters + AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $supply_order); - // updatesd($supply_order); + // updatesd($supply_order); - $res = false; + $res = false; - if ((int)$supply_order->id && ($supply_order->exists((int)$supply_order->id) || $supply_order->exists($supply_order->reference))) - $res = $supply_order->update(); - else - { - $supply_order->force_id = (bool)$force_ids; - $res = $supply_order->add(); - } + if ((int)$supply_order->id && ($supply_order->exists((int)$supply_order->id) || $supply_order->exists($supply_order->reference))) { + $res = $supply_order->update(); + } else { + $supply_order->force_id = (bool)$force_ids; + $res = $supply_order->add(); + } - // errors - if (!$res) - $this->errors[] = sprintf($this->l('Supply Order could not be saved (at line %d).'), $current_line + 1); - } - else - $this->errors[] = $error; - } + // errors + if (!$res) { + $this->errors[] = sprintf($this->l('Supply Order could not be saved (at line %d).'), $current_line + 1); + } + } else { + $this->errors[] = $error; + } + } - // closes - $this->closeCsvFile($handle); - } + // closes + $this->closeCsvFile($handle); + } - public function supplyOrdersDetailsImport() - { - // opens CSV & sets locale - $this->receiveTab(); - $handle = $this->openCsvFile(); - AdminImportController::setLocale(); + public function supplyOrdersDetailsImport() + { + // opens CSV & sets locale + $this->receiveTab(); + $handle = $this->openCsvFile(); + AdminImportController::setLocale(); - $products = array(); - $reset = true; + $products = array(); + $reset = true; - $convert = Tools::getValue('convert'); - $force_ids = Tools::getValue('forceIDs'); + $convert = Tools::getValue('convert'); + $force_ids = Tools::getValue('forceIDs'); - // main loop, for each supply orders details to import - for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); ++$current_line) - { - // if convert requested - if ($convert) - $line = $this->utf8EncodeArray($line); - $info = AdminImportController::getMaskedRow($line); + // main loop, for each supply orders details to import + for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); ++$current_line) { + // if convert requested + if ($convert) { + $line = $this->utf8EncodeArray($line); + } + $info = AdminImportController::getMaskedRow($line); - // sets default values if needed - AdminImportController::setDefaultValues($info); + // sets default values if needed + AdminImportController::setDefaultValues($info); - // gets the supply order - if (array_key_exists('supply_order_reference', $info) && pSQL($info['supply_order_reference']) && SupplyOrder::exists(pSQL($info['supply_order_reference']))) - $supply_order = SupplyOrder::getSupplyOrderByReference(pSQL($info['supply_order_reference'])); - else - $this->errors[] = sprintf($this->l('Supply Order (%s) could not be loaded (at line %d).'), (int)$info['supply_order_reference'], $current_line + 1); + // gets the supply order + if (array_key_exists('supply_order_reference', $info) && pSQL($info['supply_order_reference']) && SupplyOrder::exists(pSQL($info['supply_order_reference']))) { + $supply_order = SupplyOrder::getSupplyOrderByReference(pSQL($info['supply_order_reference'])); + } else { + $this->errors[] = sprintf($this->l('Supply Order (%s) could not be loaded (at line %d).'), (int)$info['supply_order_reference'], $current_line + 1); + } - if (empty($this->errors)) - { - // sets parameters - $id_product = (int)$info['id_product']; - if (!$info['id_product_attribute']) - $info['id_product_attribute'] = 0; - $id_product_attribute = (int)$info['id_product_attribute']; - $unit_price_te = (float)$info['unit_price_te']; - $quantity_expected = (int)$info['quantity_expected']; - $discount_rate = (float)$info['discount_rate']; - $tax_rate = (float)$info['tax_rate']; + if (empty($this->errors)) { + // sets parameters + $id_product = (int)$info['id_product']; + if (!$info['id_product_attribute']) { + $info['id_product_attribute'] = 0; + } + $id_product_attribute = (int)$info['id_product_attribute']; + $unit_price_te = (float)$info['unit_price_te']; + $quantity_expected = (int)$info['quantity_expected']; + $discount_rate = (float)$info['discount_rate']; + $tax_rate = (float)$info['tax_rate']; - // checks if one product/attribute is there only once - if (isset($products[$id_product][$id_product_attribute])) - $this->errors[] = sprintf($this->l('Product/Attribute (%d/%d) cannot be added twice (at line %d).'), $id_product, - $id_product_attribute, $current_line + 1); - else - $products[$id_product][$id_product_attribute] = $quantity_expected; + // checks if one product/attribute is there only once + if (isset($products[$id_product][$id_product_attribute])) { + $this->errors[] = sprintf($this->l('Product/Attribute (%d/%d) cannot be added twice (at line %d).'), $id_product, + $id_product_attribute, $current_line + 1); + } else { + $products[$id_product][$id_product_attribute] = $quantity_expected; + } - // checks parameters - if (false === ($supplier_reference = ProductSupplier::getProductSupplierReference($id_product, $id_product_attribute, $supply_order->id_supplier))) - $this->errors[] = sprintf($this->l('Product (%d/%d) is not available for this order (at line %d).'), $id_product, - $id_product_attribute, $current_line + 1); - if ($unit_price_te < 0) - $this->errors[] = sprintf($this->l('Unit Price (tax excl.) (%d) is not valid (at line %d).'), $unit_price_te, $current_line + 1); - if ($quantity_expected < 0) - $this->errors[] = sprintf($this->l('Quantity Expected (%d) is not valid (at line %d).'), $quantity_expected, $current_line + 1); - if ($discount_rate < 0 || $discount_rate > 100) - $this->errors[] = sprintf($this->l('Discount rate (%d) is not valid (at line %d). %s.'), $discount_rate, - $current_line + 1, $this->l('Format: Between 0 and 100')); - if ($tax_rate < 0 || $tax_rate > 100) - $this->errors[] = sprintf($this->l('Quantity Expected (%d) is not valid (at line %d).'), $tax_rate, - $current_line + 1, $this->l('Format: Between 0 and 100')); + // checks parameters + if (false === ($supplier_reference = ProductSupplier::getProductSupplierReference($id_product, $id_product_attribute, $supply_order->id_supplier))) { + $this->errors[] = sprintf($this->l('Product (%d/%d) is not available for this order (at line %d).'), $id_product, + $id_product_attribute, $current_line + 1); + } + if ($unit_price_te < 0) { + $this->errors[] = sprintf($this->l('Unit Price (tax excl.) (%d) is not valid (at line %d).'), $unit_price_te, $current_line + 1); + } + if ($quantity_expected < 0) { + $this->errors[] = sprintf($this->l('Quantity Expected (%d) is not valid (at line %d).'), $quantity_expected, $current_line + 1); + } + if ($discount_rate < 0 || $discount_rate > 100) { + $this->errors[] = sprintf($this->l('Discount rate (%d) is not valid (at line %d). %s.'), $discount_rate, + $current_line + 1, $this->l('Format: Between 0 and 100')); + } + if ($tax_rate < 0 || $tax_rate > 100) { + $this->errors[] = sprintf($this->l('Quantity Expected (%d) is not valid (at line %d).'), $tax_rate, + $current_line + 1, $this->l('Format: Between 0 and 100')); + } - // if no errors, sets supply order details - if (empty($this->errors)) - { - // resets order if needed - if ($reset) - { - $supply_order->resetProducts(); - $reset = false; - } + // if no errors, sets supply order details + if (empty($this->errors)) { + // resets order if needed + if ($reset) { + $supply_order->resetProducts(); + $reset = false; + } - // creates new product - $supply_order_detail = new SupplyOrderDetail(); - AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $supply_order_detail); + // creates new product + $supply_order_detail = new SupplyOrderDetail(); + AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $supply_order_detail); - // sets parameters - $supply_order_detail->id_supply_order = $supply_order->id; - $currency = new Currency($supply_order->id_ref_currency); - $supply_order_detail->id_currency = $currency->id; - $supply_order_detail->exchange_rate = $currency->conversion_rate; - $supply_order_detail->supplier_reference = $supplier_reference; - $supply_order_detail->name = Product::getProductName($id_product, $id_product_attribute, $supply_order->id_lang); + // sets parameters + $supply_order_detail->id_supply_order = $supply_order->id; + $currency = new Currency($supply_order->id_ref_currency); + $supply_order_detail->id_currency = $currency->id; + $supply_order_detail->exchange_rate = $currency->conversion_rate; + $supply_order_detail->supplier_reference = $supplier_reference; + $supply_order_detail->name = Product::getProductName($id_product, $id_product_attribute, $supply_order->id_lang); - // gets ean13 / ref / upc - $query = new DbQuery(); - $query->select(' + // gets ean13 / ref / upc + $query = new DbQuery(); + $query->select(' IFNULL(pa.reference, IFNULL(p.reference, \'\')) as reference, IFNULL(pa.ean13, IFNULL(p.ean13, \'\')) as ean13, IFNULL(pa.upc, IFNULL(p.upc, \'\')) as upc '); - $query->from('product', 'p'); - $query->leftJoin('product_attribute', 'pa', 'pa.id_product = p.id_product AND id_product_attribute = '.(int)$id_product_attribute); - $query->where('p.id_product = '.(int)$id_product); - $query->where('p.is_virtual = 0 AND p.cache_is_pack = 0'); - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - $product_infos = $res['0']; + $query->from('product', 'p'); + $query->leftJoin('product_attribute', 'pa', 'pa.id_product = p.id_product AND id_product_attribute = '.(int)$id_product_attribute); + $query->where('p.id_product = '.(int)$id_product); + $query->where('p.is_virtual = 0 AND p.cache_is_pack = 0'); + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + $product_infos = $res['0']; - $supply_order_detail->reference = $product_infos['reference']; - $supply_order_detail->ean13 = $product_infos['ean13']; - $supply_order_detail->upc = $product_infos['upc']; - $supply_order_detail->force_id = (bool)$force_ids; - $supply_order_detail->add(); - $supply_order->update(); - unset($supply_order_detail); + $supply_order_detail->reference = $product_infos['reference']; + $supply_order_detail->ean13 = $product_infos['ean13']; + $supply_order_detail->upc = $product_infos['upc']; + $supply_order_detail->force_id = (bool)$force_ids; + $supply_order_detail->add(); + $supply_order->update(); + unset($supply_order_detail); + } + } + } - } - } - } + // closes + $this->closeCsvFile($handle); + } - // closes - $this->closeCsvFile($handle); - } + public function utf8EncodeArray($array) + { + return (is_array($array) ? array_map('utf8_encode', $array) : utf8_encode($array)); + } - public function utf8EncodeArray($array) - { - return (is_array($array) ? array_map('utf8_encode', $array) : utf8_encode($array)); - } + protected function getNbrColumn($handle, $glue) + { + if (!is_resource($handle)) { + return false; + } + $tmp = fgetcsv($handle, MAX_LINE_SIZE, $glue); + AdminImportController::rewindBomAware($handle); + return count($tmp); + } - protected function getNbrColumn($handle, $glue) - { - if (!is_resource($handle)) - return false; - $tmp = fgetcsv($handle, MAX_LINE_SIZE, $glue); - AdminImportController::rewindBomAware($handle); - return count($tmp); - } + protected static function usortFiles($a, $b) + { + if ($a == $b) { + return 0; + } + return ($b < $a) ? 1 : - 1; + } - protected static function usortFiles($a, $b) - { - if ($a == $b) - return 0; - return ($b < $a) ? 1 : - 1; - } + protected function openCsvFile() + { + $file = AdminImportController::getPath(strval(preg_replace('/\.{2,}/', '.', Tools::getValue('csv')))); + $handle = false; + if (is_file($file) && is_readable($file)) { + $handle = fopen($file, 'r'); + } - protected function openCsvFile() - { - $file = AdminImportController::getPath(strval(preg_replace('/\.{2,}/', '.', Tools::getValue('csv')))); - $handle = false; - if (is_file($file) && is_readable($file)) - $handle = fopen($file, 'r'); + if (!$handle) { + $this->errors[] = Tools::displayError('Cannot read the .CSV file'); + } - if (!$handle) - $this->errors[] = Tools::displayError('Cannot read the .CSV file'); + AdminImportController::rewindBomAware($handle); - AdminImportController::rewindBomAware($handle); + for ($i = 0; $i < (int)Tools::getValue('skip'); ++$i) { + $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); + } + return $handle; + } - for ($i = 0; $i < (int)Tools::getValue('skip'); ++$i) - $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); - return $handle; - } + protected function closeCsvFile($handle) + { + fclose($handle); + } - protected function closeCsvFile($handle) - { - fclose($handle); - } - - protected function truncateTables($case) - { - switch ((int)$case) - { - case $this->entities[$this->l('Categories')]: - Db::getInstance()->execute(' + protected function truncateTables($case) + { + switch ((int)$case) { + case $this->entities[$this->l('Categories')]: + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'category` WHERE id_category NOT IN ('.(int)Configuration::get('PS_HOME_CATEGORY'). - ', '.(int)Configuration::get('PS_ROOT_CATEGORY').')'); - Db::getInstance()->execute(' + ', '.(int)Configuration::get('PS_ROOT_CATEGORY').')'); + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'category_lang` WHERE id_category NOT IN ('.(int)Configuration::get('PS_HOME_CATEGORY'). - ', '.(int)Configuration::get('PS_ROOT_CATEGORY').')'); - Db::getInstance()->execute(' + ', '.(int)Configuration::get('PS_ROOT_CATEGORY').')'); + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'category_shop` WHERE `id_category` NOT IN ('.(int)Configuration::get('PS_HOME_CATEGORY'). - ', '.(int)Configuration::get('PS_ROOT_CATEGORY').')'); - Db::getInstance()->execute('ALTER TABLE `'._DB_PREFIX_.'category` AUTO_INCREMENT = 3'); - foreach (scandir(_PS_CAT_IMG_DIR_) as $d) - if (preg_match('/^[0-9]+(\-(.*))?\.jpg$/', $d)) - unlink(_PS_CAT_IMG_DIR_.$d); - break; - case $this->entities[$this->l('Products')]: - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_shop`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'feature_product`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_lang`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'category_product`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_tag`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'image`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'image_lang`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'image_shop`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'specific_price`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'specific_price_priority`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_carrier`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'cart_product`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'compare_product`'); - if (count(Db::getInstance()->executeS('SHOW TABLES LIKE \''._DB_PREFIX_.'favorite_product\' '))) //check if table exist - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'favorite_product`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attachment`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_country_tax`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_download`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_group_reduction_cache`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_sale`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_supplier`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'scene_products`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'warehouse_product_location`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'stock`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'stock_available`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'stock_mvt`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'customization`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'customization_field`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supply_order_detail`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_impact`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_shop`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_combination`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_image`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'pack`'); - Image::deleteAllImages(_PS_PROD_IMG_DIR_); - if (!file_exists(_PS_PROD_IMG_DIR_)) - mkdir(_PS_PROD_IMG_DIR_); - break; - case $this->entities[$this->l('Combinations')]: - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_impact`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_lang`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_group`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_group_lang`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_group_shop`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_shop`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_shop`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_combination`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_image`'); - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'stock_available` WHERE id_product_attribute != 0'); - break; - case $this->entities[$this->l('Customers')]: - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'customer`'); - break; - case $this->entities[$this->l('Addresses')]: - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'address`'); - break; - case $this->entities[$this->l('Manufacturers')]: - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'manufacturer`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'manufacturer_lang`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'manufacturer_shop`'); - foreach (scandir(_PS_MANU_IMG_DIR_) as $d) - if (preg_match('/^[0-9]+(\-(.*))?\.jpg$/', $d)) - unlink(_PS_MANU_IMG_DIR_.$d); - break; - case $this->entities[$this->l('Suppliers')]: - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supplier`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supplier_lang`'); - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supplier_shop`'); - foreach (scandir(_PS_SUPP_IMG_DIR_) as $d) - if (preg_match('/^[0-9]+(\-(.*))?\.jpg$/', $d)) - unlink(_PS_SUPP_IMG_DIR_.$d); - break; - case $this->entities[$this->l('Alias')]: - Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'alias`'); - break; - } - Image::clearTmpDir(); - return true; - } + ', '.(int)Configuration::get('PS_ROOT_CATEGORY').')'); + Db::getInstance()->execute('ALTER TABLE `'._DB_PREFIX_.'category` AUTO_INCREMENT = 3'); + foreach (scandir(_PS_CAT_IMG_DIR_) as $d) { + if (preg_match('/^[0-9]+(\-(.*))?\.jpg$/', $d)) { + unlink(_PS_CAT_IMG_DIR_.$d); + } + } + break; + case $this->entities[$this->l('Products')]: + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_shop`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'feature_product`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_lang`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'category_product`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_tag`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'image`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'image_lang`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'image_shop`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'specific_price`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'specific_price_priority`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_carrier`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'cart_product`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'compare_product`'); + if (count(Db::getInstance()->executeS('SHOW TABLES LIKE \''._DB_PREFIX_.'favorite_product\' '))) { //check if table exist + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'favorite_product`'); + } + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attachment`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_country_tax`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_download`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_group_reduction_cache`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_sale`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_supplier`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'scene_products`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'warehouse_product_location`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'stock`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'stock_available`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'stock_mvt`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'customization`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'customization_field`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supply_order_detail`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_impact`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_shop`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_combination`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_image`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'pack`'); + Image::deleteAllImages(_PS_PROD_IMG_DIR_); + if (!file_exists(_PS_PROD_IMG_DIR_)) { + mkdir(_PS_PROD_IMG_DIR_); + } + break; + case $this->entities[$this->l('Combinations')]: + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_impact`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_lang`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_group`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_group_lang`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_group_shop`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'attribute_shop`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_shop`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_combination`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'product_attribute_image`'); + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'stock_available` WHERE id_product_attribute != 0'); + break; + case $this->entities[$this->l('Customers')]: + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'customer`'); + break; + case $this->entities[$this->l('Addresses')]: + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'address`'); + break; + case $this->entities[$this->l('Manufacturers')]: + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'manufacturer`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'manufacturer_lang`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'manufacturer_shop`'); + foreach (scandir(_PS_MANU_IMG_DIR_) as $d) { + if (preg_match('/^[0-9]+(\-(.*))?\.jpg$/', $d)) { + unlink(_PS_MANU_IMG_DIR_.$d); + } + } + break; + case $this->entities[$this->l('Suppliers')]: + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supplier`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supplier_lang`'); + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'supplier_shop`'); + foreach (scandir(_PS_SUPP_IMG_DIR_) as $d) { + if (preg_match('/^[0-9]+(\-(.*))?\.jpg$/', $d)) { + unlink(_PS_SUPP_IMG_DIR_.$d); + } + } + break; + case $this->entities[$this->l('Alias')]: + Db::getInstance()->execute('TRUNCATE TABLE `'._DB_PREFIX_.'alias`'); + break; + } + Image::clearTmpDir(); + return true; + } - public function clearSmartyCache() - { - Tools::enableCache(); - Tools::clearCache($this->context->smarty); - Tools::restoreCacheSettings(); - } + public function clearSmartyCache() + { + Tools::enableCache(); + Tools::clearCache($this->context->smarty); + Tools::restoreCacheSettings(); + } - public function postProcess() - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } + public function postProcess() + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } - if (Tools::isSubmit('import')) - { - // Check if the CSV file exist - if (Tools::getValue('csv')) - { - $shop_is_feature_active = Shop::isFeatureActive(); - // If i am a superadmin, i can truncate table - if ((($shop_is_feature_active && $this->context->employee->isSuperAdmin()) || !$shop_is_feature_active) && Tools::getValue('truncate')) - $this->truncateTables((int)Tools::getValue('entity')); - $import_type = false; - Db::getInstance()->disableCache(); - switch ((int)Tools::getValue('entity')) - { - case $this->entities[$import_type = $this->l('Categories')]: - $this->categoryImport(); - $this->clearSmartyCache(); - break; - case $this->entities[$import_type = $this->l('Products')]: - $this->productImport(); - $this->clearSmartyCache(); - break; - case $this->entities[$import_type = $this->l('Customers')]: - $this->customerImport(); - break; - case $this->entities[$import_type = $this->l('Addresses')]: - $this->addressImport(); - break; - case $this->entities[$import_type = $this->l('Combinations')]: - $this->attributeImport(); - $this->clearSmartyCache(); - break; - case $this->entities[$import_type = $this->l('Manufacturers')]: - $this->manufacturerImport(); - $this->clearSmartyCache(); - break; - case $this->entities[$import_type = $this->l('Suppliers')]: - $this->supplierImport(); - $this->clearSmartyCache(); - break; - case $this->entities[$import_type = $this->l('Alias')]: - $this->aliasImport(); - break; - } + if (Tools::isSubmit('import')) { + // Check if the CSV file exist + if (Tools::getValue('csv')) { + $shop_is_feature_active = Shop::isFeatureActive(); + // If i am a superadmin, i can truncate table + if ((($shop_is_feature_active && $this->context->employee->isSuperAdmin()) || !$shop_is_feature_active) && Tools::getValue('truncate')) { + $this->truncateTables((int)Tools::getValue('entity')); + } + $import_type = false; + Db::getInstance()->disableCache(); + switch ((int)Tools::getValue('entity')) { + case $this->entities[$import_type = $this->l('Categories')]: + $this->categoryImport(); + $this->clearSmartyCache(); + break; + case $this->entities[$import_type = $this->l('Products')]: + $this->productImport(); + $this->clearSmartyCache(); + break; + case $this->entities[$import_type = $this->l('Customers')]: + $this->customerImport(); + break; + case $this->entities[$import_type = $this->l('Addresses')]: + $this->addressImport(); + break; + case $this->entities[$import_type = $this->l('Combinations')]: + $this->attributeImport(); + $this->clearSmartyCache(); + break; + case $this->entities[$import_type = $this->l('Manufacturers')]: + $this->manufacturerImport(); + $this->clearSmartyCache(); + break; + case $this->entities[$import_type = $this->l('Suppliers')]: + $this->supplierImport(); + $this->clearSmartyCache(); + break; + case $this->entities[$import_type = $this->l('Alias')]: + $this->aliasImport(); + break; + } - // @since 1.5.0 - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - switch ((int)Tools::getValue('entity')) - { - case $this->entities[$import_type = $this->l('Supply Orders')]: - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - $this->supplyOrdersImport(); - break; - case $this->entities[$import_type = $this->l('Supply Order Details')]: - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - $this->supplyOrdersDetailsImport(); - break; - } + // @since 1.5.0 + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + switch ((int)Tools::getValue('entity')) { + case $this->entities[$import_type = $this->l('Supply Orders')]: + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->supplyOrdersImport(); + } + break; + case $this->entities[$import_type = $this->l('Supply Order Details')]: + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->supplyOrdersDetailsImport(); + } + break; + } + } - if ($import_type !== false) - { - $log_message = sprintf($this->l('%s import', 'AdminTab', false, false), $import_type); - if (Tools::getValue('truncate')) - $log_message .= ' '.$this->l('with truncate', 'AdminTab', false, false); - PrestaShopLogger::addLog($log_message, 1, null, $import_type, null, true, (int)$this->context->employee->id); - } - } - else - $this->errors[] = $this->l('You must upload a file in order to proceed to the next step'); - } - elseif ($filename = Tools::getValue('csvfilename')) - { - $filename = urldecode($filename); - $file = AdminImportController::getPath(basename($filename)); - if (realpath(dirname($file)) != realpath(AdminImportController::getPath())) - exit(); - if (!empty($filename)) - { - $b_name = basename($filename); - if (Tools::getValue('delete') && file_exists($file)) - @unlink($file); - elseif (file_exists($file)) - { - $b_name = explode('.', $b_name); - $b_name = strtolower($b_name[count($b_name) - 1]); - $mime_types = array('csv' => 'text/csv'); + if ($import_type !== false) { + $log_message = sprintf($this->l('%s import', 'AdminTab', false, false), $import_type); + if (Tools::getValue('truncate')) { + $log_message .= ' '.$this->l('with truncate', 'AdminTab', false, false); + } + PrestaShopLogger::addLog($log_message, 1, null, $import_type, null, true, (int)$this->context->employee->id); + } + } else { + $this->errors[] = $this->l('You must upload a file in order to proceed to the next step'); + } + } elseif ($filename = Tools::getValue('csvfilename')) { + $filename = urldecode($filename); + $file = AdminImportController::getPath(basename($filename)); + if (realpath(dirname($file)) != realpath(AdminImportController::getPath())) { + exit(); + } + if (!empty($filename)) { + $b_name = basename($filename); + if (Tools::getValue('delete') && file_exists($file)) { + @unlink($file); + } elseif (file_exists($file)) { + $b_name = explode('.', $b_name); + $b_name = strtolower($b_name[count($b_name) - 1]); + $mime_types = array('csv' => 'text/csv'); - if (isset($mime_types[$b_name])) - $mime_type = $mime_types[$b_name]; - else - $mime_type = 'application/octet-stream'; + if (isset($mime_types[$b_name])) { + $mime_type = $mime_types[$b_name]; + } else { + $mime_type = 'application/octet-stream'; + } - if (ob_get_level() && ob_get_length() > 0) - ob_end_clean(); + if (ob_get_level() && ob_get_length() > 0) { + ob_end_clean(); + } - header('Content-Transfer-Encoding: binary'); - header('Content-Type: '.$mime_type); - header('Content-Length: '.filesize($file)); - header('Content-Disposition: attachment; filename="'.$filename.'"'); - $fp = fopen($file, 'rb'); - while (is_resource($fp) && !feof($fp)) - echo fgets($fp, 16384); - exit; - } - } - } - Db::getInstance()->enableCache(); - return parent::postProcess(); - } + header('Content-Transfer-Encoding: binary'); + header('Content-Type: '.$mime_type); + header('Content-Length: '.filesize($file)); + header('Content-Disposition: attachment; filename="'.$filename.'"'); + $fp = fopen($file, 'rb'); + while (is_resource($fp) && !feof($fp)) { + echo fgets($fp, 16384); + } + exit; + } + } + } + Db::getInstance()->enableCache(); + return parent::postProcess(); + } - public static function setLocale() - { - $iso_lang = trim(Tools::getValue('iso_lang')); - setlocale(LC_COLLATE, strtolower($iso_lang).'_'.strtoupper($iso_lang).'.UTF-8'); - setlocale(LC_CTYPE, strtolower($iso_lang).'_'.strtoupper($iso_lang).'.UTF-8'); - } + public static function setLocale() + { + $iso_lang = trim(Tools::getValue('iso_lang')); + setlocale(LC_COLLATE, strtolower($iso_lang).'_'.strtoupper($iso_lang).'.UTF-8'); + setlocale(LC_CTYPE, strtolower($iso_lang).'_'.strtoupper($iso_lang).'.UTF-8'); + } - protected function addProductWarning($product_name, $product_id = null, $message = '') - { - $this->warnings[] = $product_name.(isset($product_id) ? ' (ID '.$product_id.')' : '').' ' - .Tools::displayError($message); - } + protected function addProductWarning($product_name, $product_id = null, $message = '') + { + $this->warnings[] = $product_name.(isset($product_id) ? ' (ID '.$product_id.')' : '').' ' + .Tools::displayError($message); + } - public function ajaxProcessSaveImportMatchs() - { - if ($this->tabAccess['edit'] === '1') - { - $match = implode('|', Tools::getValue('type_value')); - Db::getInstance()->execute('INSERT IGNORE INTO `'._DB_PREFIX_.'import_match` ( + public function ajaxProcessSaveImportMatchs() + { + if ($this->tabAccess['edit'] === '1') { + $match = implode('|', Tools::getValue('type_value')); + Db::getInstance()->execute('INSERT IGNORE INTO `'._DB_PREFIX_.'import_match` ( `id_import_match` , `name` , `match`, @@ -3580,34 +3613,32 @@ class AdminImportControllerCore extends AdminController \''.pSQL(Tools::getValue('skip')).'\' )', false); - die('{"id" : "'.Db::getInstance()->Insert_ID().'"}'); - } - } + die('{"id" : "'.Db::getInstance()->Insert_ID().'"}'); + } + } - public function ajaxProcessLoadImportMatchs() - { - if ($this->tabAccess['edit'] === '1') - { - $return = Db::getInstance()->executeS('SELECT * FROM `'._DB_PREFIX_.'import_match` WHERE `id_import_match` = ' - .(int)Tools::getValue('idImportMatchs'), true, false); - die('{"id" : "'.$return[0]['id_import_match'].'", "matchs" : "'.$return[0]['match'].'", "skip" : "' - .$return[0]['skip'].'"}'); - } - } + public function ajaxProcessLoadImportMatchs() + { + if ($this->tabAccess['edit'] === '1') { + $return = Db::getInstance()->executeS('SELECT * FROM `'._DB_PREFIX_.'import_match` WHERE `id_import_match` = ' + .(int)Tools::getValue('idImportMatchs'), true, false); + die('{"id" : "'.$return[0]['id_import_match'].'", "matchs" : "'.$return[0]['match'].'", "skip" : "' + .$return[0]['skip'].'"}'); + } + } - public function ajaxProcessDeleteImportMatchs() - { - if ($this->tabAccess['edit'] === '1') - { - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'import_match` WHERE `id_import_match` = ' - .(int)Tools::getValue('idImportMatchs'), false); - die; - } - } + public function ajaxProcessDeleteImportMatchs() + { + if ($this->tabAccess['edit'] === '1') { + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'import_match` WHERE `id_import_match` = ' + .(int)Tools::getValue('idImportMatchs'), false); + die; + } + } - public static function getPath($file = '') - { - return (defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_ : _PS_ADMIN_DIR_).DIRECTORY_SEPARATOR.'import' - .DIRECTORY_SEPARATOR.$file; - } + public static function getPath($file = '') + { + return (defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_ : _PS_ADMIN_DIR_).DIRECTORY_SEPARATOR.'import' + .DIRECTORY_SEPARATOR.$file; + } } diff --git a/controllers/admin/AdminInformationController.php b/controllers/admin/AdminInformationController.php index 217ccbd7..8b88e693 100644 --- a/controllers/admin/AdminInformationController.php +++ b/controllers/admin/AdminInformationController.php @@ -26,173 +26,177 @@ class AdminInformationControllerCore extends AdminController { + public function __construct() + { + $this->bootstrap = true; + parent::__construct(); + } - public function __construct() - { - $this->bootstrap = true; - parent::__construct(); - } + public function initContent() + { + $this->show_toolbar = false; + $this->display = 'view'; + parent::initContent(); + } - public function initContent() - { - $this->show_toolbar = false; - $this->display = 'view'; - parent::initContent(); - } + public function initToolbarTitle() + { + $this->toolbar_title = array_unique($this->breadcrumbs); + } - public function initToolbarTitle() - { - $this->toolbar_title = array_unique($this->breadcrumbs); - } + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); + unset($this->page_header_toolbar_btn['back']); + } - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); - unset($this->page_header_toolbar_btn['back']); - } + public function renderView() + { + $this->initPageHeaderToolbar(); - public function renderView() - { - $this->initPageHeaderToolbar(); + $hosting_vars = array(); + if (!defined('_PS_HOST_MODE_')) { + $hosting_vars = array( + 'version' => array( + 'php' => phpversion(), + 'server' => $_SERVER['SERVER_SOFTWARE'], + 'memory_limit' => ini_get('memory_limit'), + 'max_execution_time' => ini_get('max_execution_time') + ), + 'database' => array( + 'version' => Db::getInstance()->getVersion(), + 'server' => _DB_SERVER_, + 'name' => _DB_NAME_, + 'user' => _DB_USER_, + 'prefix' => _DB_PREFIX_, + 'engine' => _MYSQL_ENGINE_, + ), + 'uname' => function_exists('php_uname') ? php_uname('s').' '.php_uname('v').' '.php_uname('m') : '', + 'apache_instaweb' => Tools::apacheModExists('mod_instaweb') + ); + } - $hosting_vars = array(); - if (!defined('_PS_HOST_MODE_')) - $hosting_vars = array( - 'version' => array( - 'php' => phpversion(), - 'server' => $_SERVER['SERVER_SOFTWARE'], - 'memory_limit' => ini_get('memory_limit'), - 'max_execution_time' => ini_get('max_execution_time') - ), - 'database' => array( - 'version' => Db::getInstance()->getVersion(), - 'server' => _DB_SERVER_, - 'name' => _DB_NAME_, - 'user' => _DB_USER_, - 'prefix' => _DB_PREFIX_, - 'engine' => _MYSQL_ENGINE_, - ), - 'uname' => function_exists('php_uname') ? php_uname('s').' '.php_uname('v').' '.php_uname('m') : '', - 'apache_instaweb' => Tools::apacheModExists('mod_instaweb') - ); + $shop_vars = array( + 'shop' => array( + 'ps' => _PS_VERSION_, + 'url' => $this->context->shop->getBaseURL(), + 'theme' => $this->context->shop->theme_name, + ), + 'mail' => Configuration::get('PS_MAIL_METHOD') == 1, + 'smtp' => array( + 'server' => Configuration::get('PS_MAIL_SERVER'), + 'user' => Configuration::get('PS_MAIL_USER'), + 'password' => Configuration::get('PS_MAIL_PASSWD'), + 'encryption' => Configuration::get('PS_MAIL_SMTP_ENCRYPTION'), + 'port' => Configuration::get('PS_MAIL_SMTP_PORT'), + ), + 'user_agent' => $_SERVER['HTTP_USER_AGENT'], + ); - $shop_vars = array( - 'shop' => array( - 'ps' => _PS_VERSION_, - 'url' => $this->context->shop->getBaseURL(), - 'theme' => $this->context->shop->theme_name, - ), - 'mail' => Configuration::get('PS_MAIL_METHOD') == 1, - 'smtp' => array( - 'server' => Configuration::get('PS_MAIL_SERVER'), - 'user' => Configuration::get('PS_MAIL_USER'), - 'password' => Configuration::get('PS_MAIL_PASSWD'), - 'encryption' => Configuration::get('PS_MAIL_SMTP_ENCRYPTION'), - 'port' => Configuration::get('PS_MAIL_SMTP_PORT'), - ), - 'user_agent' => $_SERVER['HTTP_USER_AGENT'], - ); + $this->tpl_view_vars = array_merge($this->getTestResult(), array_merge($hosting_vars, $shop_vars)); - $this->tpl_view_vars = array_merge($this->getTestResult(), array_merge($hosting_vars, $shop_vars)); + return parent::renderView(); + } - return parent::renderView(); - } + /** + * get all tests + * + * @return array of test results + */ + public function getTestResult() + { + $tests_errors = array( + 'phpversion' => $this->l('Update your PHP version.'), + 'upload' => $this->l('Configure your server to allow file uploads.'), + 'system' => $this->l('Configure your server to allow the creation of directories and files with write permissions.'), + 'gd' => $this->l('Enable the GD library on your server.'), + 'mysql_support' => $this->l('Enable the MySQL support on your server.'), + 'config_dir' => $this->l('Set write permissions for the "config" folder.'), + 'cache_dir' => $this->l('Set write permissions for the "cache" folder.'), + 'sitemap' => $this->l('Set write permissions for the "sitemap.xml" file.'), + 'img_dir' => $this->l('Set write permissions for the "img" folder and subfolders.'), + 'log_dir' => $this->l('Set write permissions for the "log" folder and subfolders.'), + 'mails_dir' => $this->l('Set write permissions for the "mails" folder and subfolders.'), + 'module_dir' => $this->l('Set write permissions for the "modules" folder and subfolders.'), + 'theme_lang_dir' => sprintf($this->l('Set the write permissions for the "themes%s/lang/" folder and subfolders, recursively.'), _THEME_NAME_), + 'translations_dir' => $this->l('Set write permissions for the "translations" folder and subfolders.'), + 'customizable_products_dir' => $this->l('Set write permissions for the "upload" folder and subfolders.'), + 'virtual_products_dir' => $this->l('Set write permissions for the "download" folder and subfolders.'), + 'fopen' => $this->l('Allow the PHP fopen() function on your server.'), + 'register_globals' => $this->l('Set PHP "register_globals" option to "Off".'), + 'gz' => $this->l('Enable GZIP compression on your server.'), + 'files' => $this->l('Some PrestaShop files are missing from your server.'), + 'new_phpversion' => sprintf($this->l('You are using PHP %s version. Soon, the latest PHP version supported by PrestaShop will be PHP 5.4. To make sure you’re ready for the future, we recommend you to upgrade to PHP 5.4 now!'), phpversion()) + ); - /** - * get all tests - * - * @return array of test results - */ - public function getTestResult() - { - $tests_errors = array( - 'phpversion' => $this->l('Update your PHP version.'), - 'upload' => $this->l('Configure your server to allow file uploads.'), - 'system' => $this->l('Configure your server to allow the creation of directories and files with write permissions.'), - 'gd' => $this->l('Enable the GD library on your server.'), - 'mysql_support' => $this->l('Enable the MySQL support on your server.'), - 'config_dir' => $this->l('Set write permissions for the "config" folder.'), - 'cache_dir' => $this->l('Set write permissions for the "cache" folder.'), - 'sitemap' => $this->l('Set write permissions for the "sitemap.xml" file.'), - 'img_dir' => $this->l('Set write permissions for the "img" folder and subfolders.'), - 'log_dir' => $this->l('Set write permissions for the "log" folder and subfolders.'), - 'mails_dir' => $this->l('Set write permissions for the "mails" folder and subfolders.'), - 'module_dir' => $this->l('Set write permissions for the "modules" folder and subfolders.'), - 'theme_lang_dir' => sprintf($this->l('Set the write permissions for the "themes%s/lang/" folder and subfolders, recursively.'), _THEME_NAME_), - 'translations_dir' => $this->l('Set write permissions for the "translations" folder and subfolders.'), - 'customizable_products_dir' => $this->l('Set write permissions for the "upload" folder and subfolders.'), - 'virtual_products_dir' => $this->l('Set write permissions for the "download" folder and subfolders.'), - 'fopen' => $this->l('Allow the PHP fopen() function on your server.'), - 'register_globals' => $this->l('Set PHP "register_globals" option to "Off".'), - 'gz' => $this->l('Enable GZIP compression on your server.'), - 'files' => $this->l('Some PrestaShop files are missing from your server.'), - 'new_phpversion' => sprintf($this->l('You are using PHP %s version. Soon, the latest PHP version supported by PrestaShop will be PHP 5.4. To make sure you’re ready for the future, we recommend you to upgrade to PHP 5.4 now!'), phpversion()) - ); + // Functions list to test with 'test_system' + // Test to execute (function/args): lets uses the default test + $params_required_results = ConfigurationTest::check(ConfigurationTest::getDefaultTests()); - // Functions list to test with 'test_system' - // Test to execute (function/args): lets uses the default test - $params_required_results = ConfigurationTest::check(ConfigurationTest::getDefaultTests()); + if (!defined('_PS_HOST_MODE_')) { + $params_optional_results = ConfigurationTest::check(ConfigurationTest::getDefaultTestsOp()); + } - if (!defined('_PS_HOST_MODE_')) - $params_optional_results = ConfigurationTest::check(ConfigurationTest::getDefaultTestsOp()); + $fail_required = in_array('fail', $params_required_results); - $fail_required = in_array('fail', $params_required_results); + if ($fail_required && $params_required_results['files'] != 'ok') { + $tmp = ConfigurationTest::test_files(true); + if (is_array($tmp) && count($tmp)) { + $tests_errors['files'] = $tests_errors['files'].'<br/>('.implode(', ', $tmp).')'; + } + } - if ($fail_required && $params_required_results['files'] != 'ok') - { - $tmp = ConfigurationTest::test_files(true); - if (is_array($tmp) && count($tmp)) - $tests_errors['files'] = $tests_errors['files'].'<br/>('.implode(', ', $tmp).')'; - } + $results = array( + 'failRequired' => $fail_required, + 'testsErrors' => $tests_errors, + 'testsRequired' => $params_required_results, + ); - $results = array( - 'failRequired' => $fail_required, - 'testsErrors' => $tests_errors, - 'testsRequired' => $params_required_results, - ); + if (!defined('_PS_HOST_MODE_')) { + $results = array_merge($results, array( + 'failOptional' => in_array('fail', $params_optional_results), + 'testsOptional' => $params_optional_results, + )); + } - if (!defined('_PS_HOST_MODE_')) - $results = array_merge($results, array( - 'failOptional' => in_array('fail', $params_optional_results), - 'testsOptional' => $params_optional_results, - )); + return $results; + } - return $results; - } + public function displayAjaxCheckFiles() + { + $this->file_list = array('missing' => array(), 'updated' => array()); + $xml = @simplexml_load_file(_PS_API_URL_.'/xml/md5/'._PS_VERSION_.'.xml'); + if (!$xml) { + die(Tools::jsonEncode($this->file_list)); + } - public function displayAjaxCheckFiles() - { - $this->file_list = array('missing' => array(), 'updated' => array()); - $xml = @simplexml_load_file(_PS_API_URL_.'/xml/md5/'._PS_VERSION_.'.xml'); - if (!$xml) - die(Tools::jsonEncode($this->file_list)); + $this->getListOfUpdatedFiles($xml->ps_root_dir[0]); + die(Tools::jsonEncode($this->file_list)); + } - $this->getListOfUpdatedFiles($xml->ps_root_dir[0]); - die(Tools::jsonEncode($this->file_list)); - } + public function getListOfUpdatedFiles(SimpleXMLElement $dir, $path = '') + { + $exclude_regexp = '(install(-dev|-new)?|themes|tools|cache|docs|download|img|localization|log|mails|translations|upload|modules|override/(:?.*)index.php$)'; + $admin_dir = basename(_PS_ADMIN_DIR_); - public function getListOfUpdatedFiles(SimpleXMLElement $dir, $path = '') - { - $exclude_regexp = '(install(-dev|-new)?|themes|tools|cache|docs|download|img|localization|log|mails|translations|upload|modules|override/(:?.*)index.php$)'; - $admin_dir = basename(_PS_ADMIN_DIR_); + foreach ($dir->md5file as $file) { + $filename = preg_replace('#^admin/#', $admin_dir.'/', $path.$file['name']); + if (preg_match('#^'.$exclude_regexp.'#', $filename)) { + continue; + } - foreach ($dir->md5file as $file) - { - $filename = preg_replace('#^admin/#', $admin_dir.'/', $path.$file['name']); - if (preg_match('#^'.$exclude_regexp.'#', $filename)) - continue; + if (!file_exists(_PS_ROOT_DIR_.'/'.$filename)) { + $this->file_list['missing'][] = $filename; + } else { + $md5_local = md5_file(_PS_ROOT_DIR_.'/'.$filename); + if ($md5_local != (string)$file) { + $this->file_list['updated'][] = $filename; + } + } + } - if (!file_exists(_PS_ROOT_DIR_.'/'.$filename)) - $this->file_list['missing'][] = $filename; - else - { - $md5_local = md5_file(_PS_ROOT_DIR_.'/'.$filename); - if ($md5_local != (string)$file) - $this->file_list['updated'][] = $filename; - } - } - - foreach ($dir->dir as $subdir) - $this->getListOfUpdatedFiles($subdir, $path.$subdir['name'].'/'); - } + foreach ($dir->dir as $subdir) { + $this->getListOfUpdatedFiles($subdir, $path.$subdir['name'].'/'); + } + } } diff --git a/controllers/admin/AdminInvoicesController.php b/controllers/admin/AdminInvoicesController.php index c63db375..6eebf5cb 100644 --- a/controllers/admin/AdminInvoicesController.php +++ b/controllers/admin/AdminInvoicesController.php @@ -26,277 +26,280 @@ class AdminInvoicesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'invoice'; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'invoice'; - parent::__construct(); + parent::__construct(); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Invoice options'), - 'fields' => array( - 'PS_INVOICE' => array( - 'title' => $this->l('Enable invoices'), - 'desc' => $this->l('If enabled, your customers will receive an invoice for their purchase(s).'), - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_INVOICE_TAXES_BREAKDOWN' => array( - 'title' => $this->l('Enable tax breakdown'), - 'desc' => $this->l('Show a summary of tax rates when there are several taxes.'), - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_PDF_IMG_INVOICE' => array( - 'title' => $this->l('Enable product image'), - 'hint' => $this->l('Adds an image before product name on the invoice'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_INVOICE_PREFIX' => array( - 'title' => $this->l('Invoice prefix'), - 'desc' => $this->l('Prefix used for invoice name (e.g. #IN00001).'), - 'size' => 6, - 'type' => 'textLang' - ), - 'PS_INVOICE_START_NUMBER' => array( - 'title' => $this->l('Invoice number'), - 'desc' => sprintf($this->l('The next invoice will begin with this number, and then increase with each additional invoice. Set to 0 if you want to keep the current number (which is #%s).'), Order::getLastInvoiceNumber() + 1), - 'size' => 6, - 'type' => 'text', - 'cast' => 'intval' - ), - 'PS_INVOICE_LEGAL_FREE_TEXT' => array( - 'title' => $this->l('Legal free text'), - 'desc' => $this->l('Use this field to display additional text on your invoice, like specific legal information. It will appear below the payment methods summary.'), - 'size' => 50, - 'type' => 'textareaLang', - ), - 'PS_INVOICE_FREE_TEXT' => array( - 'title' => $this->l('Footer text'), - 'desc' => $this->l('This text will appear at the bottom of the invoice, below your company details.'), - 'size' => 50, - 'type' => 'textLang', - ), - 'PS_INVOICE_MODEL' => array( - 'title' => $this->l('Invoice model'), - 'desc' => $this->l('Choose an invoice model.'), - 'type' => 'select', - 'identifier' => 'value', - 'list' => $this->getInvoicesModels() - ), - 'PS_PDF_USE_CACHE' => array( - 'title' => $this->l('Use the disk as cache for PDF invoices'), - 'desc' => $this->l('Saves memory but slows down the PDF generation.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ) - ), - 'submit' => array('title' => $this->l('Save')) - ) - ); - } + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Invoice options'), + 'fields' => array( + 'PS_INVOICE' => array( + 'title' => $this->l('Enable invoices'), + 'desc' => $this->l('If enabled, your customers will receive an invoice for their purchase(s).'), + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_INVOICE_TAXES_BREAKDOWN' => array( + 'title' => $this->l('Enable tax breakdown'), + 'desc' => $this->l('Show a summary of tax rates when there are several taxes.'), + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_PDF_IMG_INVOICE' => array( + 'title' => $this->l('Enable product image'), + 'hint' => $this->l('Adds an image before product name on the invoice'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_INVOICE_PREFIX' => array( + 'title' => $this->l('Invoice prefix'), + 'desc' => $this->l('Prefix used for invoice name (e.g. #IN00001).'), + 'size' => 6, + 'type' => 'textLang' + ), + 'PS_INVOICE_START_NUMBER' => array( + 'title' => $this->l('Invoice number'), + 'desc' => sprintf($this->l('The next invoice will begin with this number, and then increase with each additional invoice. Set to 0 if you want to keep the current number (which is #%s).'), Order::getLastInvoiceNumber() + 1), + 'size' => 6, + 'type' => 'text', + 'cast' => 'intval' + ), + 'PS_INVOICE_LEGAL_FREE_TEXT' => array( + 'title' => $this->l('Legal free text'), + 'desc' => $this->l('Use this field to display additional text on your invoice, like specific legal information. It will appear below the payment methods summary.'), + 'size' => 50, + 'type' => 'textareaLang', + ), + 'PS_INVOICE_FREE_TEXT' => array( + 'title' => $this->l('Footer text'), + 'desc' => $this->l('This text will appear at the bottom of the invoice, below your company details.'), + 'size' => 50, + 'type' => 'textLang', + ), + 'PS_INVOICE_MODEL' => array( + 'title' => $this->l('Invoice model'), + 'desc' => $this->l('Choose an invoice model.'), + 'type' => 'select', + 'identifier' => 'value', + 'list' => $this->getInvoicesModels() + ), + 'PS_PDF_USE_CACHE' => array( + 'title' => $this->l('Use the disk as cache for PDF invoices'), + 'desc' => $this->l('Saves memory but slows down the PDF generation.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ) + ), + 'submit' => array('title' => $this->l('Save')) + ) + ); + } - public function initFormByDate() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('By date'), - 'icon' => 'icon-calendar' - ), - 'input' => array( - array( - 'type' => 'date', - 'label' => $this->l('From'), - 'name' => 'date_from', - 'maxlength' => 10, - 'required' => true, - 'hint' => $this->l('Format: 2011-12-31 (inclusive).') - ), - array( - 'type' => 'date', - 'label' => $this->l('To'), - 'name' => 'date_to', - 'maxlength' => 10, - 'required' => true, - 'hint' => $this->l('Format: 2012-12-31 (inclusive).') - ) - ), - 'submit' => array( - 'title' => $this->l('Generate PDF file by date'), - 'id' => 'submitPrint', - 'icon' => 'process-icon-download-alt' - ) - ); + public function initFormByDate() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('By date'), + 'icon' => 'icon-calendar' + ), + 'input' => array( + array( + 'type' => 'date', + 'label' => $this->l('From'), + 'name' => 'date_from', + 'maxlength' => 10, + 'required' => true, + 'hint' => $this->l('Format: 2011-12-31 (inclusive).') + ), + array( + 'type' => 'date', + 'label' => $this->l('To'), + 'name' => 'date_to', + 'maxlength' => 10, + 'required' => true, + 'hint' => $this->l('Format: 2012-12-31 (inclusive).') + ) + ), + 'submit' => array( + 'title' => $this->l('Generate PDF file by date'), + 'id' => 'submitPrint', + 'icon' => 'process-icon-download-alt' + ) + ); - $this->fields_value = array( - 'date_from' => date('Y-m-d'), - 'date_to' => date('Y-m-d') - ); + $this->fields_value = array( + 'date_from' => date('Y-m-d'), + 'date_to' => date('Y-m-d') + ); - $this->table = 'invoice_date'; - $this->show_toolbar = false; - $this->show_form_cancel_button = false; - $this->toolbar_title = $this->l('Print PDF invoices'); - return parent::renderForm(); - } + $this->table = 'invoice_date'; + $this->show_toolbar = false; + $this->show_form_cancel_button = false; + $this->toolbar_title = $this->l('Print PDF invoices'); + return parent::renderForm(); + } - public function initFormByStatus() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('By order status'), - 'icon' => 'icon-time' - ), - 'input' => array( - array( - 'type' => 'checkboxStatuses', - 'label' => $this->l('Order statuses'), - 'name' => 'id_order_state', - 'values' => array( - 'query' => OrderState::getOrderStates($this->context->language->id), - 'id' => 'id_order_state', - 'name' => 'name' - ), - 'hint' => $this->l('You can also export orders which have not been charged yet.') - ) - ), - 'submit' => array( - 'title' => $this->l('Generate PDF file by status'), - 'id' => 'submitPrint2', - 'icon' => 'process-icon-download-alt' - ) - ); + public function initFormByStatus() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('By order status'), + 'icon' => 'icon-time' + ), + 'input' => array( + array( + 'type' => 'checkboxStatuses', + 'label' => $this->l('Order statuses'), + 'name' => 'id_order_state', + 'values' => array( + 'query' => OrderState::getOrderStates($this->context->language->id), + 'id' => 'id_order_state', + 'name' => 'name' + ), + 'hint' => $this->l('You can also export orders which have not been charged yet.') + ) + ), + 'submit' => array( + 'title' => $this->l('Generate PDF file by status'), + 'id' => 'submitPrint2', + 'icon' => 'process-icon-download-alt' + ) + ); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT COUNT( o.id_order ) AS nbOrders, o.current_state as id_order_state FROM `'._DB_PREFIX_.'order_invoice` oi - LEFT JOIN `'._DB_PREFIX_.'orders` o ON oi.id_order = o.id_order + LEFT JOIN `'._DB_PREFIX_.'orders` o ON oi.id_order = o.id_order WHERE o.id_shop IN('.implode(', ', Shop::getContextListShopID()).') AND oi.number > 0 GROUP BY o.current_state '); - $status_stats = array(); - foreach ($result as $row) - $status_stats[$row['id_order_state']] = $row['nbOrders']; + $status_stats = array(); + foreach ($result as $row) { + $status_stats[$row['id_order_state']] = $row['nbOrders']; + } - $this->tpl_form_vars = array( - 'statusStats' => $status_stats, - 'style' => '' - ); + $this->tpl_form_vars = array( + 'statusStats' => $status_stats, + 'style' => '' + ); - $this->table = 'invoice_status'; - $this->show_toolbar = false; - return parent::renderForm(); - } + $this->table = 'invoice_status'; + $this->show_toolbar = false; + return parent::renderForm(); + } - public function initContent() - { - $this->display = 'edit'; - $this->initTabModuleList(); - $this->initToolbar(); - $this->initPageHeaderToolbar(); - $this->content .= $this->initFormByDate(); - $this->content .= $this->initFormByStatus(); - $this->table = 'invoice'; - $this->content .= $this->renderOptions(); + public function initContent() + { + $this->display = 'edit'; + $this->initTabModuleList(); + $this->initToolbar(); + $this->initPageHeaderToolbar(); + $this->content .= $this->initFormByDate(); + $this->content .= $this->initFormByStatus(); + $this->table = 'invoice'; + $this->content .= $this->renderOptions(); - $this->context->smarty->assign(array( - 'content' => $this->content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } + $this->context->smarty->assign(array( + 'content' => $this->content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } - public function initToolbarTitle() - { - $this->toolbar_title = array_unique($this->breadcrumbs); - } + public function initToolbarTitle() + { + $this->toolbar_title = array_unique($this->breadcrumbs); + } - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); - unset($this->page_header_toolbar_btn['cancel']); - } + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); + unset($this->page_header_toolbar_btn['cancel']); + } - public function postProcess() - { - if (Tools::isSubmit('submitAddinvoice_date')) - { - if (!Validate::isDate(Tools::getValue('date_from'))) - $this->errors[] = $this->l('Invalid "From" date'); + public function postProcess() + { + if (Tools::isSubmit('submitAddinvoice_date')) { + if (!Validate::isDate(Tools::getValue('date_from'))) { + $this->errors[] = $this->l('Invalid "From" date'); + } - if (!Validate::isDate(Tools::getValue('date_to'))) - $this->errors[] = $this->l('Invalid "To" date'); + if (!Validate::isDate(Tools::getValue('date_to'))) { + $this->errors[] = $this->l('Invalid "To" date'); + } - if (!count($this->errors)) - { - if (count(OrderInvoice::getByDateInterval(Tools::getValue('date_from'), Tools::getValue('date_to')))) - Tools::redirectAdmin($this->context->link->getAdminLink('AdminPdf').'&submitAction=generateInvoicesPDF&date_from='.urlencode(Tools::getValue('date_from')).'&date_to='.urlencode(Tools::getValue('date_to'))); + if (!count($this->errors)) { + if (count(OrderInvoice::getByDateInterval(Tools::getValue('date_from'), Tools::getValue('date_to')))) { + Tools::redirectAdmin($this->context->link->getAdminLink('AdminPdf').'&submitAction=generateInvoicesPDF&date_from='.urlencode(Tools::getValue('date_from')).'&date_to='.urlencode(Tools::getValue('date_to'))); + } - $this->errors[] = $this->l('No invoice has been found for this period.'); - } - } - elseif (Tools::isSubmit('submitAddinvoice_status')) - { - if (!is_array($status_array = Tools::getValue('id_order_state')) || !count($status_array)) - $this->errors[] = $this->l('You must select at least one order status.'); - else - { - foreach ($status_array as $id_order_state) - if (count(OrderInvoice::getByStatus((int)$id_order_state))) - Tools::redirectAdmin($this->context->link->getAdminLink('AdminPdf').'&submitAction=generateInvoicesPDF2&id_order_state='.implode('-', $status_array)); + $this->errors[] = $this->l('No invoice has been found for this period.'); + } + } elseif (Tools::isSubmit('submitAddinvoice_status')) { + if (!is_array($status_array = Tools::getValue('id_order_state')) || !count($status_array)) { + $this->errors[] = $this->l('You must select at least one order status.'); + } else { + foreach ($status_array as $id_order_state) { + if (count(OrderInvoice::getByStatus((int)$id_order_state))) { + Tools::redirectAdmin($this->context->link->getAdminLink('AdminPdf').'&submitAction=generateInvoicesPDF2&id_order_state='.implode('-', $status_array)); + } + } - $this->errors[] = $this->l('No invoice has been found for this status.'); - } - } - else - parent::postProcess(); - } + $this->errors[] = $this->l('No invoice has been found for this status.'); + } + } else { + parent::postProcess(); + } + } - public function beforeUpdateOptions() - { - if ((int)Tools::getValue('PS_INVOICE_START_NUMBER') != 0 && (int)Tools::getValue('PS_INVOICE_START_NUMBER') <= Order::getLastInvoiceNumber()) - $this->errors[] = $this->l('Invalid invoice number.').Order::getLastInvoiceNumber().')'; - } + public function beforeUpdateOptions() + { + if ((int)Tools::getValue('PS_INVOICE_START_NUMBER') != 0 && (int)Tools::getValue('PS_INVOICE_START_NUMBER') <= Order::getLastInvoiceNumber()) { + $this->errors[] = $this->l('Invalid invoice number.').Order::getLastInvoiceNumber().')'; + } + } - protected function getInvoicesModels() - { - $models = array( - array( - 'value' => 'invoice', - 'name' => 'invoice' - ) - ); + protected function getInvoicesModels() + { + $models = array( + array( + 'value' => 'invoice', + 'name' => 'invoice' + ) + ); - $templates_override = $this->getInvoicesModelsFromDir(_PS_THEME_DIR_.'pdf/'); - $templates_default = $this->getInvoicesModelsFromDir(_PS_PDF_DIR_); + $templates_override = $this->getInvoicesModelsFromDir(_PS_THEME_DIR_.'pdf/'); + $templates_default = $this->getInvoicesModelsFromDir(_PS_PDF_DIR_); - foreach (array_merge($templates_default, $templates_override) as $template) - { - $template_name = basename($template, '.tpl'); - $models[] = array('value' => $template_name, 'name' => $template_name); - } - return $models; - } + foreach (array_merge($templates_default, $templates_override) as $template) { + $template_name = basename($template, '.tpl'); + $models[] = array('value' => $template_name, 'name' => $template_name); + } + return $models; + } - protected function getInvoicesModelsFromDir($directory) - { - $templates = false; + protected function getInvoicesModelsFromDir($directory) + { + $templates = false; - if (is_dir($directory)) - $templates = glob($directory.'invoice-*.tpl'); + if (is_dir($directory)) { + $templates = glob($directory.'invoice-*.tpl'); + } - if (!$templates) - $templates = array(); + if (!$templates) { + $templates = array(); + } - return $templates; - } + return $templates; + } } diff --git a/controllers/admin/AdminLanguagesController.php b/controllers/admin/AdminLanguagesController.php index 1b0f203b..dff3f69c 100644 --- a/controllers/admin/AdminLanguagesController.php +++ b/controllers/admin/AdminLanguagesController.php @@ -29,553 +29,553 @@ */ class AdminLanguagesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'lang'; - $this->className = 'Language'; - $this->lang = false; - $this->deleted = false; - $this->multishop_context = Shop::CONTEXT_ALL; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'lang'; + $this->className = 'Language'; + $this->lang = false; + $this->deleted = false; + $this->multishop_context = Shop::CONTEXT_ALL; - $this->context = Context::getContext(); + $this->context = Context::getContext(); - $this->fieldImageSettings = array( - array( - 'name' => 'flag', - 'dir' => 'l' - ), - array( - 'name' => 'no_picture', - 'dir' => 'p' - ) - ); + $this->fieldImageSettings = array( + array( + 'name' => 'flag', + 'dir' => 'l' + ), + array( + 'name' => 'no_picture', + 'dir' => 'p' + ) + ); - $this->fields_list = array( - 'id_lang' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'flag' => array( - 'title' => $this->l('Flag'), - 'align' => 'center', - 'image' => 'l', - 'orderby' => false, - 'search' => false, - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Name') - ), - 'iso_code' => array( - 'title' => $this->l('ISO code'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'language_code' => array( - 'title' => $this->l('Language code'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'date_format_lite' => array( - 'title' => $this->l('Date format') - ), - 'date_format_full' => array( - 'title' => $this->l('Date format (full)') - ), - 'active' => array( - 'title' => $this->l('Enabled'), - 'align' => 'center', - 'active' => 'status', - 'type' => 'bool', - 'class' => 'fixed-width-sm' - ) - ); + $this->fields_list = array( + 'id_lang' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'flag' => array( + 'title' => $this->l('Flag'), + 'align' => 'center', + 'image' => 'l', + 'orderby' => false, + 'search' => false, + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Name') + ), + 'iso_code' => array( + 'title' => $this->l('ISO code'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'language_code' => array( + 'title' => $this->l('Language code'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'date_format_lite' => array( + 'title' => $this->l('Date format') + ), + 'date_format_full' => array( + 'title' => $this->l('Date format (full)') + ), + 'active' => array( + 'title' => $this->l('Enabled'), + 'align' => 'center', + 'active' => 'status', + 'type' => 'bool', + 'class' => 'fixed-width-sm' + ) + ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); - $this->specificConfirmDelete = $this->l('When you delete a language, all related translations in the database will be deleted. Are you sure you want to proceed?'); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); + $this->specificConfirmDelete = $this->l('When you delete a language, all related translations in the database will be deleted. Are you sure you want to proceed?'); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_language'] = array( - 'href' => self::$currentIndex.'&addlang&token='.$this->token, - 'desc' => $this->l('Add new language', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_language'] = array( + 'href' => self::$currentIndex.'&addlang&token='.$this->token, + 'desc' => $this->l('Add new language', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderList() - { - $this->addRowAction('edit'); - $this->addRowAction('delete'); + public function renderList() + { + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->displayWarning($this->l('When you delete a language, all related translations in the database will be deleted.')); - if (!is_writable(_PS_ROOT_DIR_.'/.htaccess') && Configuration::get('PS_REWRITING_SETTINGS')) - $this->displayInformation($this->l('Your .htaccess file must be writable.')); - return parent::renderList(); - } + $this->displayWarning($this->l('When you delete a language, all related translations in the database will be deleted.')); + if (!is_writable(_PS_ROOT_DIR_.'/.htaccess') && Configuration::get('PS_REWRITING_SETTINGS')) { + $this->displayInformation($this->l('Your .htaccess file must be writable.')); + } + return parent::renderList(); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Languages'), - 'icon' => 'icon-globe' - ), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'ps_version' - ), - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'maxlength' => 32, - 'required' => true - ), - array( - 'type' => 'text', - 'label' => $this->l('ISO code'), - 'name' => 'iso_code', - 'required' => true, - 'maxlength' => 2, - 'hint' => $this->l('Two-letter ISO code (e.g. FR, EN, DE).') - ), - array( - 'type' => 'text', - 'label' => $this->l('Language code'), - 'name' => 'language_code', - 'required' => true, - 'maxlength' => 5, - 'hint' => $this->l('IETF language tag (e.g. en-US, pt-BR).') - /* TO DO - ajouter les liens dans le hint ? */ - /*'desc' => $this->l('IETF language tag (e.g. en-US, pt-BR).').' '.sprintf('<a href="http://en.wikipedia.org/wiki/IETF_language_tag" target="_blank">%s <img src="../img/admin/external_link.png" class="icon-top" /></a>', $this->l('IETF on Wikipedia'))*/ - ), - array( - 'type' => 'text', - 'label' => $this->l('Date format'), - 'name' => 'date_format_lite', - 'required' => true, - 'hint' => sprintf($this->l('Short date format (e.g., %s).'), 'Y-m-d') - /* TO DO - ajouter les liens dans le hint ? */ - /*'desc' => sprintf($this->l('Short date format (e.g., %s)'), '<a href="http://php.net/date" target="_blank">Y-m-d</a>')*/ - ), - array( - 'type' => 'text', - 'label' => $this->l('Date format (full)'), - 'name' => 'date_format_full', - 'required' => true, - 'hint' => sprintf($this->l('Full date format (e.g., %s).'), 'Y-m-d H:i:s') - /* TO DO - ajouter les liens dans le hint ? */ - /*'desc' => sprintf($this->l('Full date format (e.g., %s)'), '<a href="http://php.net/date" target="_blank">Y-m-d H:i:s</a>')*/ - ), - array( - 'type' => 'file', - 'label' => $this->l('Flag'), - 'name' => 'flag', - 'required' => true, - 'hint' => $this->l('Upload the country flag from your computer.') - ), - array( - 'type' => 'file', - 'label' => $this->l('"No-picture" image'), - 'name' => 'no_picture', - 'hint' => $this->l('Image is displayed when "no picture is found".') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Is RTL language'), - 'name' => 'is_rtl', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'is_rtl_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => array( - $this->l('Enable if this language is read from right to left.').' '. - $this->l('(Experimental: your theme must be compliant with RTL languages).') - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Status'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Activate this language.') - ), - array( - 'type' => 'special', - 'name' => 'resultCheckLangPack', - 'text' => $this->l('Check to see if a language pack is available for this ISO code.'), - 'img' => 'ajax-loader.gif' - ) - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Languages'), + 'icon' => 'icon-globe' + ), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'ps_version' + ), + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'maxlength' => 32, + 'required' => true + ), + array( + 'type' => 'text', + 'label' => $this->l('ISO code'), + 'name' => 'iso_code', + 'required' => true, + 'maxlength' => 2, + 'hint' => $this->l('Two-letter ISO code (e.g. FR, EN, DE).') + ), + array( + 'type' => 'text', + 'label' => $this->l('Language code'), + 'name' => 'language_code', + 'required' => true, + 'maxlength' => 5, + 'hint' => $this->l('IETF language tag (e.g. en-US, pt-BR).') + /* TO DO - ajouter les liens dans le hint ? */ + /*'desc' => $this->l('IETF language tag (e.g. en-US, pt-BR).').' '.sprintf('<a href="http://en.wikipedia.org/wiki/IETF_language_tag" target="_blank">%s <img src="../img/admin/external_link.png" class="icon-top" /></a>', $this->l('IETF on Wikipedia'))*/ + ), + array( + 'type' => 'text', + 'label' => $this->l('Date format'), + 'name' => 'date_format_lite', + 'required' => true, + 'hint' => sprintf($this->l('Short date format (e.g., %s).'), 'Y-m-d') + /* TO DO - ajouter les liens dans le hint ? */ + /*'desc' => sprintf($this->l('Short date format (e.g., %s)'), '<a href="http://php.net/date" target="_blank">Y-m-d</a>')*/ + ), + array( + 'type' => 'text', + 'label' => $this->l('Date format (full)'), + 'name' => 'date_format_full', + 'required' => true, + 'hint' => sprintf($this->l('Full date format (e.g., %s).'), 'Y-m-d H:i:s') + /* TO DO - ajouter les liens dans le hint ? */ + /*'desc' => sprintf($this->l('Full date format (e.g., %s)'), '<a href="http://php.net/date" target="_blank">Y-m-d H:i:s</a>')*/ + ), + array( + 'type' => 'file', + 'label' => $this->l('Flag'), + 'name' => 'flag', + 'required' => true, + 'hint' => $this->l('Upload the country flag from your computer.') + ), + array( + 'type' => 'file', + 'label' => $this->l('"No-picture" image'), + 'name' => 'no_picture', + 'hint' => $this->l('Image is displayed when "no picture is found".') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Is RTL language'), + 'name' => 'is_rtl', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'is_rtl_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => array( + $this->l('Enable if this language is read from right to left.').' '. + $this->l('(Experimental: your theme must be compliant with RTL languages).') + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Status'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Activate this language.') + ), + array( + 'type' => 'special', + 'name' => 'resultCheckLangPack', + 'text' => $this->l('Check to see if a language pack is available for this ISO code.'), + 'img' => 'ajax-loader.gif' + ) + ) + ); - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - $this->fields_form['submit'] = array( - 'title' => $this->l('Save'), - ); + $this->fields_form['submit'] = array( + 'title' => $this->l('Save'), + ); - /** @var Language $obj */ - if (!($obj = $this->loadObject(true))) - return; + /** @var Language $obj */ + if (!($obj = $this->loadObject(true))) { + return; + } - if ($obj->id && !$obj->checkFiles()) - { - $this->fields_form['new'] = array( - 'legend' => array( - 'title' => $this->l('Warning'), - 'image' => '../img/admin/warning.gif' - ), - 'list_files' => array( - array( - 'label' => $this->l('Translation files'), - 'files' => Language::getFilesList($obj->iso_code, _THEME_NAME_, false, false, 'tr', true) - ), - array( - 'label' => $this->l('Theme files'), - 'files' => Language::getFilesList($obj->iso_code, _THEME_NAME_, false, false, 'theme', true) - ), - array( - 'label' => $this->l('Mail files'), - 'files' => Language::getFilesList($obj->iso_code, _THEME_NAME_, false, false, 'mail', true) - ) - ) - ); - } + if ($obj->id && !$obj->checkFiles()) { + $this->fields_form['new'] = array( + 'legend' => array( + 'title' => $this->l('Warning'), + 'image' => '../img/admin/warning.gif' + ), + 'list_files' => array( + array( + 'label' => $this->l('Translation files'), + 'files' => Language::getFilesList($obj->iso_code, _THEME_NAME_, false, false, 'tr', true) + ), + array( + 'label' => $this->l('Theme files'), + 'files' => Language::getFilesList($obj->iso_code, _THEME_NAME_, false, false, 'theme', true) + ), + array( + 'label' => $this->l('Mail files'), + 'files' => Language::getFilesList($obj->iso_code, _THEME_NAME_, false, false, 'mail', true) + ) + ) + ); + } - $this->fields_value = array('ps_version' => _PS_VERSION_); + $this->fields_value = array('ps_version' => _PS_VERSION_); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function processDelete() - { - $object = $this->loadObject(); - if (!$this->checkDeletion($object)) - return false; - if (!$this->deleteNoPictureImages((int)$object->id)) - $this->errors[] = Tools::displayError('An error occurred while deleting the object.').' <b>'.$this->table.'</b> '; + public function processDelete() + { + $object = $this->loadObject(); + if (!$this->checkDeletion($object)) { + return false; + } + if (!$this->deleteNoPictureImages((int)$object->id)) { + $this->errors[] = Tools::displayError('An error occurred while deleting the object.').' <b>'.$this->table.'</b> '; + } - return parent::processDelete(); - } + return parent::processDelete(); + } - protected function processBulkDelete() - { - $can_bulk = true; - if (is_array($this->boxes) && !empty($this->boxes)) - { - foreach ($this->boxes as $id_lang) - { - $object = new Language((int)$id_lang); - if (!$this->checkDeletion($object)) - return false; - if (!$this->deleteNoPictureImages((int)$object->id)) - { - $this->errors[] = Tools::displayError('An error occurred while deleting the object.').' <b>'.$this->table.'</b> '; - return false; - } - } - } - return parent::processBulkDelete(); - } + protected function processBulkDelete() + { + $can_bulk = true; + if (is_array($this->boxes) && !empty($this->boxes)) { + foreach ($this->boxes as $id_lang) { + $object = new Language((int)$id_lang); + if (!$this->checkDeletion($object)) { + return false; + } + if (!$this->deleteNoPictureImages((int)$object->id)) { + $this->errors[] = Tools::displayError('An error occurred while deleting the object.').' <b>'.$this->table.'</b> '; + return false; + } + } + } + return parent::processBulkDelete(); + } - protected function checkDeletion($object) - { - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } + protected function checkDeletion($object) + { + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } - if (Validate::isLoadedObject($object)) - { - if ($object->id == Configuration::get('PS_LANG_DEFAULT')) - $this->errors[] = $this->l('You cannot delete the default language.'); - elseif ($object->id == $this->context->language->id) - $this->errors[] = $this->l('You cannot delete the language currently in use. Please select a different language.'); - else - return true; - } - else - $this->errors[] = Tools::displayError('(cannot load object)'); + if (Validate::isLoadedObject($object)) { + if ($object->id == Configuration::get('PS_LANG_DEFAULT')) { + $this->errors[] = $this->l('You cannot delete the default language.'); + } elseif ($object->id == $this->context->language->id) { + $this->errors[] = $this->l('You cannot delete the language currently in use. Please select a different language.'); + } else { + return true; + } + } else { + $this->errors[] = Tools::displayError('(cannot load object)'); + } - return false; - } + return false; + } - protected function checkDisableStatus($object) - { - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } - if (!Validate::isLoadedObject($object)) - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - else - { - if ($object->id == (int)Configuration::get('PS_LANG_DEFAULT')) - $this->errors[] = Tools::displayError('You cannot change the status of the default language.'); - else - return true; - } - return false; - } + protected function checkDisableStatus($object) + { + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } + if (!Validate::isLoadedObject($object)) { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } else { + if ($object->id == (int)Configuration::get('PS_LANG_DEFAULT')) { + $this->errors[] = Tools::displayError('You cannot change the status of the default language.'); + } else { + return true; + } + } + return false; + } - public function processStatus() - { - $object = $this->loadObject(); - if ($this->checkDisableStatus($object)) - { - $this->checkEmployeeIdLang($object->id); - return parent::processStatus(); - } - return false; - } + public function processStatus() + { + $object = $this->loadObject(); + if ($this->checkDisableStatus($object)) { + $this->checkEmployeeIdLang($object->id); + return parent::processStatus(); + } + return false; + } - protected function processBulkDisableSelection() - { - if (is_array($this->boxes) && !empty($this->boxes)) - { - foreach ($this->boxes as $id_lang) - { - $object = new Language((int)$id_lang); - if (!$this->checkDisableStatus($object)) - return false; - $this->checkEmployeeIdLang($object->id); - } - } - return parent::processBulkDisableSelection(); - } + protected function processBulkDisableSelection() + { + if (is_array($this->boxes) && !empty($this->boxes)) { + foreach ($this->boxes as $id_lang) { + $object = new Language((int)$id_lang); + if (!$this->checkDisableStatus($object)) { + return false; + } + $this->checkEmployeeIdLang($object->id); + } + } + return parent::processBulkDisableSelection(); + } - public function processAdd() - { - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } + public function processAdd() + { + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } - if (isset($_POST['iso_code']) && !empty($_POST['iso_code']) && Validate::isLanguageIsoCode(Tools::getValue('iso_code')) && Language::getIdByIso($_POST['iso_code'])) - $this->errors[] = Tools::displayError('This ISO code is already linked to another language.'); - if ((!empty($_FILES['no_picture']['tmp_name']) || !empty($_FILES['flag']['tmp_name'])) && Validate::isLanguageIsoCode(Tools::getValue('iso_code'))) - { - if ($_FILES['no_picture']['error'] == UPLOAD_ERR_OK) - $this->copyNoPictureImage(strtolower(Tools::getValue('iso_code'))); - unset($_FILES['no_picture']); - } - else - $this->errors[] = Tools::displayError('Flag and "No picture" image fields are required.'); + if (isset($_POST['iso_code']) && !empty($_POST['iso_code']) && Validate::isLanguageIsoCode(Tools::getValue('iso_code')) && Language::getIdByIso($_POST['iso_code'])) { + $this->errors[] = Tools::displayError('This ISO code is already linked to another language.'); + } + if ((!empty($_FILES['no_picture']['tmp_name']) || !empty($_FILES['flag']['tmp_name'])) && Validate::isLanguageIsoCode(Tools::getValue('iso_code'))) { + if ($_FILES['no_picture']['error'] == UPLOAD_ERR_OK) { + $this->copyNoPictureImage(strtolower(Tools::getValue('iso_code'))); + } + unset($_FILES['no_picture']); + } else { + $this->errors[] = Tools::displayError('Flag and "No picture" image fields are required.'); + } - return parent::processAdd(); - } + return parent::processAdd(); + } - public function processUpdate() - { - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } + public function processUpdate() + { + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } - if (( isset($_FILES['no_picture']) && !$_FILES['no_picture']['error'] || isset($_FILES['flag']) && !$_FILES['flag']['error']) - && Validate::isLanguageIsoCode(Tools::getValue('iso_code'))) - { - if ($_FILES['no_picture']['error'] == UPLOAD_ERR_OK) - $this->copyNoPictureImage(strtolower(Tools::getValue('iso_code'))); - // class AdminTab deal with every $_FILES content, don't do that for no_picture - unset($_FILES['no_picture']); - } + if ((isset($_FILES['no_picture']) && !$_FILES['no_picture']['error'] || isset($_FILES['flag']) && !$_FILES['flag']['error']) + && Validate::isLanguageIsoCode(Tools::getValue('iso_code'))) { + if ($_FILES['no_picture']['error'] == UPLOAD_ERR_OK) { + $this->copyNoPictureImage(strtolower(Tools::getValue('iso_code'))); + } + // class AdminTab deal with every $_FILES content, don't do that for no_picture + unset($_FILES['no_picture']); + } - /** @var Language $object */ - $object = $this->loadObject(); - if (Tools::getValue('active') != (int)$object->active) - if (!$this->checkDisableStatus($object)) - return false; + /** @var Language $object */ + $object = $this->loadObject(); + if (Tools::getValue('active') != (int)$object->active) { + if (!$this->checkDisableStatus($object)) { + return false; + } + } - $this->checkEmployeeIdLang($object->id); - return parent::processUpdate(); - } + $this->checkEmployeeIdLang($object->id); + return parent::processUpdate(); + } - /** - * Copy a no-product image - * - * @param string $language Language iso_code for no_picture image filename - * - * @return void|false - */ - public function copyNoPictureImage($language) - { - if (isset($_FILES['no_picture']) && $_FILES['no_picture']['error'] === 0) - if ($error = ImageManager::validateUpload($_FILES['no_picture'], Tools::getMaxUploadSize())) - $this->errors[] = $error; - else - { - if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES['no_picture']['tmp_name'], $tmp_name)) - return false; - if (!ImageManager::resize($tmp_name, _PS_IMG_DIR_.'p/'.$language.'.jpg')) - $this->errors[] = Tools::displayError('An error occurred while copying "No Picture" image to your product folder.'); - if (!ImageManager::resize($tmp_name, _PS_IMG_DIR_.'c/'.$language.'.jpg')) - $this->errors[] = Tools::displayError('An error occurred while copying "No picture" image to your category folder.'); - if (!ImageManager::resize($tmp_name, _PS_IMG_DIR_.'m/'.$language.'.jpg')) - $this->errors[] = Tools::displayError('An error occurred while copying "No picture" image to your manufacturer folder.'); - else - { - $images_types = ImageType::getImagesTypes('products'); - foreach ($images_types as $k => $image_type) - { - if (!ImageManager::resize($tmp_name, _PS_IMG_DIR_.'p/'.$language.'-default-'.stripslashes($image_type['name']).'.jpg', $image_type['width'], $image_type['height'])) - $this->errors[] = Tools::displayError('An error occurred while resizing "No picture" image to your product directory.'); - if (!ImageManager::resize($tmp_name, _PS_IMG_DIR_.'c/'.$language.'-default-'.stripslashes($image_type['name']).'.jpg', $image_type['width'], $image_type['height'])) - $this->errors[] = Tools::displayError('An error occurred while resizing "No picture" image to your category directory.'); - if (!ImageManager::resize($tmp_name, _PS_IMG_DIR_.'m/'.$language.'-default-'.stripslashes($image_type['name']).'.jpg', $image_type['width'], $image_type['height'])) - $this->errors[] = Tools::displayError('An error occurred while resizing "No picture" image to your manufacturer directory.'); - } - } - unlink($tmp_name); - } - } + /** + * Copy a no-product image + * + * @param string $language Language iso_code for no_picture image filename + * + * @return void|false + */ + public function copyNoPictureImage($language) + { + if (isset($_FILES['no_picture']) && $_FILES['no_picture']['error'] === 0) { + if ($error = ImageManager::validateUpload($_FILES['no_picture'], Tools::getMaxUploadSize())) { + $this->errors[] = $error; + } else { + if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES['no_picture']['tmp_name'], $tmp_name)) { + return false; + } + if (!ImageManager::resize($tmp_name, _PS_IMG_DIR_.'p/'.$language.'.jpg')) { + $this->errors[] = Tools::displayError('An error occurred while copying "No Picture" image to your product folder.'); + } + if (!ImageManager::resize($tmp_name, _PS_IMG_DIR_.'c/'.$language.'.jpg')) { + $this->errors[] = Tools::displayError('An error occurred while copying "No picture" image to your category folder.'); + } + if (!ImageManager::resize($tmp_name, _PS_IMG_DIR_.'m/'.$language.'.jpg')) { + $this->errors[] = Tools::displayError('An error occurred while copying "No picture" image to your manufacturer folder.'); + } else { + $images_types = ImageType::getImagesTypes('products'); + foreach ($images_types as $k => $image_type) { + if (!ImageManager::resize($tmp_name, _PS_IMG_DIR_.'p/'.$language.'-default-'.stripslashes($image_type['name']).'.jpg', $image_type['width'], $image_type['height'])) { + $this->errors[] = Tools::displayError('An error occurred while resizing "No picture" image to your product directory.'); + } + if (!ImageManager::resize($tmp_name, _PS_IMG_DIR_.'c/'.$language.'-default-'.stripslashes($image_type['name']).'.jpg', $image_type['width'], $image_type['height'])) { + $this->errors[] = Tools::displayError('An error occurred while resizing "No picture" image to your category directory.'); + } + if (!ImageManager::resize($tmp_name, _PS_IMG_DIR_.'m/'.$language.'-default-'.stripslashes($image_type['name']).'.jpg', $image_type['width'], $image_type['height'])) { + $this->errors[] = Tools::displayError('An error occurred while resizing "No picture" image to your manufacturer directory.'); + } + } + } + unlink($tmp_name); + } + } + } - /** - * deleteNoPictureImages will delete all default image created for the language id_language - * - * @param string $id_language - * @return bool true if no error - */ - protected function deleteNoPictureImages($id_language) - { - $language = Language::getIsoById($id_language); - $images_types = ImageType::getImagesTypes('products'); - $dirs = array(_PS_PROD_IMG_DIR_, _PS_CAT_IMG_DIR_, _PS_MANU_IMG_DIR_, _PS_SUPP_IMG_DIR_, _PS_MANU_IMG_DIR_); - foreach ($dirs as $dir) - { - foreach ($images_types as $k => $image_type) - if (file_exists($dir.$language.'-default-'.stripslashes($image_type['name']).'.jpg')) - if (!unlink($dir.$language.'-default-'.stripslashes($image_type['name']).'.jpg')) - $this->errors[] = Tools::displayError('An error occurred during image deletion process.'); + /** + * deleteNoPictureImages will delete all default image created for the language id_language + * + * @param string $id_language + * @return bool true if no error + */ + protected function deleteNoPictureImages($id_language) + { + $language = Language::getIsoById($id_language); + $images_types = ImageType::getImagesTypes('products'); + $dirs = array(_PS_PROD_IMG_DIR_, _PS_CAT_IMG_DIR_, _PS_MANU_IMG_DIR_, _PS_SUPP_IMG_DIR_, _PS_MANU_IMG_DIR_); + foreach ($dirs as $dir) { + foreach ($images_types as $k => $image_type) { + if (file_exists($dir.$language.'-default-'.stripslashes($image_type['name']).'.jpg')) { + if (!unlink($dir.$language.'-default-'.stripslashes($image_type['name']).'.jpg')) { + $this->errors[] = Tools::displayError('An error occurred during image deletion process.'); + } + } + } - if (file_exists($dir.$language.'.jpg')) - if (!unlink($dir.$language.'.jpg')) - $this->errors[] = Tools::displayError('An error occurred during image deletion process.'); - } + if (file_exists($dir.$language.'.jpg')) { + if (!unlink($dir.$language.'.jpg')) { + $this->errors[] = Tools::displayError('An error occurred during image deletion process.'); + } + } + } - return !count($this->errors) ? true : false; - } + return !count($this->errors) ? true : false; + } - /** - * @param Language $object - * @param string $table - */ - protected function copyFromPost(&$object, $table) - { - if ($object->id && ($object->iso_code != $_POST['iso_code'])) - if (Validate::isLanguageIsoCode($_POST['iso_code'])) - $object->moveToIso($_POST['iso_code']); - parent::copyFromPost($object, $table); - } + /** + * @param Language $object + * @param string $table + */ + protected function copyFromPost(&$object, $table) + { + if ($object->id && ($object->iso_code != $_POST['iso_code'])) { + if (Validate::isLanguageIsoCode($_POST['iso_code'])) { + $object->moveToIso($_POST['iso_code']); + } + } + parent::copyFromPost($object, $table); + } - public function ajaxProcessCheckLangPack() - { - $this->json = true; - if (!Tools::getValue('iso_lang') || !Validate::isLanguageIsoCode(Tools::getValue('iso_lang'))) - { - $this->status = 'error'; - $this->errors[] = $this->l('Iso code is not valid'); - return; - } - if (!Tools::getValue('ps_version') || !Validate::isPrestaShopVersion(Tools::getValue('ps_version'))) - { - $this->status = 'error'; - $this->errors[] = $this->l('Technical Error: ps_version is not valid'); - return; - } + public function ajaxProcessCheckLangPack() + { + $this->json = true; + if (!Tools::getValue('iso_lang') || !Validate::isLanguageIsoCode(Tools::getValue('iso_lang'))) { + $this->status = 'error'; + $this->errors[] = $this->l('Iso code is not valid'); + return; + } + if (!Tools::getValue('ps_version') || !Validate::isPrestaShopVersion(Tools::getValue('ps_version'))) { + $this->status = 'error'; + $this->errors[] = $this->l('Technical Error: ps_version is not valid'); + return; + } - // Get all iso code available - if ($lang_packs = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/get_language_pack.php?version='.Tools::getValue('ps_version').'&iso_lang='.Tools::strtolower(Tools::getValue('iso_lang')))) - { - $result = Tools::jsonDecode($lang_packs); - if ($lang_packs !== '' && $result && !isset($result->error)) - { - $this->status = 'ok'; - $this->content = $lang_packs; - } - else - { - $this->status = 'error'; - $this->errors[] = $this->l('Wrong ISO code, or the selected language pack is unavailable.'); - } - } - else - { - $this->status = 'error'; - $this->errors[] = $this->l('Technical Error: translation server unreachable.'); - } - } + // Get all iso code available + if ($lang_packs = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/get_language_pack.php?version='.Tools::getValue('ps_version').'&iso_lang='.Tools::strtolower(Tools::getValue('iso_lang')))) { + $result = Tools::jsonDecode($lang_packs); + if ($lang_packs !== '' && $result && !isset($result->error)) { + $this->status = 'ok'; + $this->content = $lang_packs; + } else { + $this->status = 'error'; + $this->errors[] = $this->l('Wrong ISO code, or the selected language pack is unavailable.'); + } + } else { + $this->status = 'error'; + $this->errors[] = $this->l('Technical Error: translation server unreachable.'); + } + } - protected function checkEmployeeIdLang($current_id_lang) - { - //update employee lang if current id lang is disabled - Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'employee` set `id_lang`='.(int)Configuration::get('PS_LANG_DEFAULT').' WHERE `id_lang`='.(int)$current_id_lang); - } + protected function checkEmployeeIdLang($current_id_lang) + { + //update employee lang if current id lang is disabled + Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'employee` set `id_lang`='.(int)Configuration::get('PS_LANG_DEFAULT').' WHERE `id_lang`='.(int)$current_id_lang); + } - protected function afterImageUpload() - { - parent::afterImageUpload(); + protected function afterImageUpload() + { + parent::afterImageUpload(); - if (($id_lang = (int)Tools::getValue('id_lang')) && - isset($_FILES) && count($_FILES) && file_exists(_PS_LANG_IMG_DIR_.$id_lang.'.jpg')) - { - $current_file = _PS_TMP_IMG_DIR_.'lang_mini_'.$id_lang.'_'.$this->context->shop->id.'.jpg'; + if (($id_lang = (int)Tools::getValue('id_lang')) && + isset($_FILES) && count($_FILES) && file_exists(_PS_LANG_IMG_DIR_.$id_lang.'.jpg')) { + $current_file = _PS_TMP_IMG_DIR_.'lang_mini_'.$id_lang.'_'.$this->context->shop->id.'.jpg'; - if (file_exists($current_file)) - unlink($current_file); - } + if (file_exists($current_file)) { + unlink($current_file); + } + } - return true; - } -} \ No newline at end of file + return true; + } +} diff --git a/controllers/admin/AdminLocalizationController.php b/controllers/admin/AdminLocalizationController.php index 26d00a79..f93d7612 100644 --- a/controllers/admin/AdminLocalizationController.php +++ b/controllers/admin/AdminLocalizationController.php @@ -26,403 +26,410 @@ class AdminLocalizationControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - parent::__construct(); + public function __construct() + { + $this->bootstrap = true; + parent::__construct(); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Configuration'), - 'fields' => array( - 'PS_LANG_DEFAULT' => array( - 'title' => $this->l('Default language'), - 'hint' => $this->l('The default language used in your shop.'), - 'cast' => 'intval', - 'type' => 'select', - 'identifier' => 'id_lang', - 'list' => Language::getLanguages(false) - ), - 'PS_DETECT_LANG' => array( - 'title' => $this->l('Set language from browser'), - 'desc' => $this->l('Set browser language as default language'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'default' => '1' - ), - 'PS_COUNTRY_DEFAULT' => array( - 'title' => $this->l('Default country'), - 'hint' => $this->l('The default country used in your shop.'), - 'cast' => 'intval', - 'type' => 'select', - 'class' => 'chosen', - 'identifier' => 'id_country', - 'list' => Country::getCountries($this->context->language->id) - ), - 'PS_DETECT_COUNTRY' => array( - 'title' => $this->l('Set default country from browser language'), - 'desc' => $this->l('Set country corresponding to browser language'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'default' => '1' - ), - 'PS_CURRENCY_DEFAULT' => array( - 'title' => $this->l('Default currency'), - 'hint' => - $this->l('The default currency used in your shop.').' - '.$this->l('If you change the default currency, you will have to manually edit every product price.'), - 'cast' => 'intval', - 'type' => 'select', - 'identifier' => 'id_currency', - 'list' => Currency::getCurrencies(false, true, true) - ), - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'localization' => array( - 'title' => $this->l('Local units'), - 'icon' => 'icon-globe', - 'fields' => array( - 'PS_WEIGHT_UNIT' => array( - 'title' => $this->l('Weight unit'), - 'hint' => $this->l('The default weight unit for your shop (e.g. "kg" for kilograms, "lbs" for pound-mass, etc.).'), - 'validation' => 'isWeightUnit', - 'required' => true, - 'type' => 'text', - 'class' => 'fixed-width-sm' - ), - 'PS_DISTANCE_UNIT' => array( - 'title' => $this->l('Distance unit'), - 'hint' => $this->l('The default distance unit for your shop (e.g. "km" for kilometer, "mi" for mile, etc.).'), - 'validation' => 'isDistanceUnit', - 'required' => true, - 'type' => 'text', - 'class' => 'fixed-width-sm' - ), - 'PS_VOLUME_UNIT' => array( - 'title' => $this->l('Volume unit'), - 'hint' => $this->l('The default volume unit for your shop (e.g. "L" for liter, "gal" for gallon, etc.).'), - 'validation' => 'isWeightUnit', - 'required' => true, - 'type' => 'text', - 'class' => 'fixed-width-sm' - ), - 'PS_DIMENSION_UNIT' => array( - 'title' => $this->l('Dimension unit'), - 'hint' => $this->l('The default dimension unit for your shop (e.g. "cm" for centimeter, "in" for inch, etc.).'), - 'validation' => 'isDistanceUnit', - 'required' => true, - 'type' => 'text', - 'class' => 'fixed-width-sm' - ) - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'options' => array( - 'title' => $this->l('Advanced'), - 'fields' => array( - 'PS_LOCALE_LANGUAGE' => array( - 'title' => $this->l('Language identifier'), - 'hint' => $this->l('The ISO 639-1 identifier for the language of the country where your web server is located (en, fr, sp, ru, pl, nl, etc.).'), - 'validation' => 'isLanguageIsoCode', - 'type' => 'text', - 'visibility' => Shop::CONTEXT_ALL, - 'class' => 'fixed-width-sm' - ), - 'PS_LOCALE_COUNTRY' => array( - 'title' => $this->l('Country identifier'), - 'hint' => $this->l('The ISO 3166-1 alpha-2 identifier for the country/region where your web server is located, in lowercase (us, gb, fr, sp, ru, pl, nl, etc.).'), - 'validation' => 'isLanguageIsoCode', - 'type' => 'text', - 'visibility' => Shop::CONTEXT_ALL, - 'class' => 'fixed-width-sm' - ) - ), - 'submit' => array('title' => $this->l('Save')) - ) - ); + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Configuration'), + 'fields' => array( + 'PS_LANG_DEFAULT' => array( + 'title' => $this->l('Default language'), + 'hint' => $this->l('The default language used in your shop.'), + 'cast' => 'intval', + 'type' => 'select', + 'identifier' => 'id_lang', + 'list' => Language::getLanguages(false) + ), + 'PS_DETECT_LANG' => array( + 'title' => $this->l('Set language from browser'), + 'desc' => $this->l('Set browser language as default language'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'default' => '1' + ), + 'PS_COUNTRY_DEFAULT' => array( + 'title' => $this->l('Default country'), + 'hint' => $this->l('The default country used in your shop.'), + 'cast' => 'intval', + 'type' => 'select', + 'class' => 'chosen', + 'identifier' => 'id_country', + 'list' => Country::getCountries($this->context->language->id) + ), + 'PS_DETECT_COUNTRY' => array( + 'title' => $this->l('Set default country from browser language'), + 'desc' => $this->l('Set country corresponding to browser language'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'default' => '1' + ), + 'PS_CURRENCY_DEFAULT' => array( + 'title' => $this->l('Default currency'), + 'hint' => + $this->l('The default currency used in your shop.').' - '.$this->l('If you change the default currency, you will have to manually edit every product price.'), + 'cast' => 'intval', + 'type' => 'select', + 'identifier' => 'id_currency', + 'list' => Currency::getCurrencies(false, true, true) + ), + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'localization' => array( + 'title' => $this->l('Local units'), + 'icon' => 'icon-globe', + 'fields' => array( + 'PS_WEIGHT_UNIT' => array( + 'title' => $this->l('Weight unit'), + 'hint' => $this->l('The default weight unit for your shop (e.g. "kg" for kilograms, "lbs" for pound-mass, etc.).'), + 'validation' => 'isWeightUnit', + 'required' => true, + 'type' => 'text', + 'class' => 'fixed-width-sm' + ), + 'PS_DISTANCE_UNIT' => array( + 'title' => $this->l('Distance unit'), + 'hint' => $this->l('The default distance unit for your shop (e.g. "km" for kilometer, "mi" for mile, etc.).'), + 'validation' => 'isDistanceUnit', + 'required' => true, + 'type' => 'text', + 'class' => 'fixed-width-sm' + ), + 'PS_VOLUME_UNIT' => array( + 'title' => $this->l('Volume unit'), + 'hint' => $this->l('The default volume unit for your shop (e.g. "L" for liter, "gal" for gallon, etc.).'), + 'validation' => 'isWeightUnit', + 'required' => true, + 'type' => 'text', + 'class' => 'fixed-width-sm' + ), + 'PS_DIMENSION_UNIT' => array( + 'title' => $this->l('Dimension unit'), + 'hint' => $this->l('The default dimension unit for your shop (e.g. "cm" for centimeter, "in" for inch, etc.).'), + 'validation' => 'isDistanceUnit', + 'required' => true, + 'type' => 'text', + 'class' => 'fixed-width-sm' + ) + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'options' => array( + 'title' => $this->l('Advanced'), + 'fields' => array( + 'PS_LOCALE_LANGUAGE' => array( + 'title' => $this->l('Language identifier'), + 'hint' => $this->l('The ISO 639-1 identifier for the language of the country where your web server is located (en, fr, sp, ru, pl, nl, etc.).'), + 'validation' => 'isLanguageIsoCode', + 'type' => 'text', + 'visibility' => Shop::CONTEXT_ALL, + 'class' => 'fixed-width-sm' + ), + 'PS_LOCALE_COUNTRY' => array( + 'title' => $this->l('Country identifier'), + 'hint' => $this->l('The ISO 3166-1 alpha-2 identifier for the country/region where your web server is located, in lowercase (us, gb, fr, sp, ru, pl, nl, etc.).'), + 'validation' => 'isLanguageIsoCode', + 'type' => 'text', + 'visibility' => Shop::CONTEXT_ALL, + 'class' => 'fixed-width-sm' + ) + ), + 'submit' => array('title' => $this->l('Save')) + ) + ); - if (function_exists('date_default_timezone_set')) - $this->fields_options['general']['fields']['PS_TIMEZONE'] = array( - 'title' => $this->l('Time zone'), - 'validation' => 'isAnything', - 'type' => 'select', - 'class' => 'chosen', - 'list' => Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT name FROM '._DB_PREFIX_.'timezone'), - 'identifier' => 'name', - 'visibility' => Shop::CONTEXT_ALL - ); - } + if (function_exists('date_default_timezone_set')) { + $this->fields_options['general']['fields']['PS_TIMEZONE'] = array( + 'title' => $this->l('Time zone'), + 'validation' => 'isAnything', + 'type' => 'select', + 'class' => 'chosen', + 'list' => Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT name FROM '._DB_PREFIX_.'timezone'), + 'identifier' => 'name', + 'visibility' => Shop::CONTEXT_ALL + ); + } + } - public function postProcess() - { - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } + public function postProcess() + { + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } - if (!extension_loaded('openssl')) - $this->displayWarning($this->l('Importing a new language may fail without the OpenSSL module. Please enable "openssl.so" on your server configuration.')); + if (!extension_loaded('openssl')) { + $this->displayWarning($this->l('Importing a new language may fail without the OpenSSL module. Please enable "openssl.so" on your server configuration.')); + } - if (Tools::isSubmit('submitLocalizationPack')) - { - $version = str_replace('.', '', _PS_VERSION_); - $version = substr($version, 0, 2); + if (Tools::isSubmit('submitLocalizationPack')) { + $version = str_replace('.', '', _PS_VERSION_); + $version = substr($version, 0, 2); - if (($iso_localization_pack = Tools::getValue('iso_localization_pack')) && Validate::isFileName($iso_localization_pack)) - { - if (Tools::getValue('download_updated_pack') == '1' || defined('_PS_HOST_MODE_')) - $pack = @Tools::file_get_contents(_PS_API_URL_.'/localization/'.$version.'/'.$iso_localization_pack.'.xml'); - else - $pack = false; - - if (defined('_PS_HOST_MODE_')) - $path = _PS_CORE_DIR_.'/localization/'.$iso_localization_pack.'.xml'; - else - $path = _PS_ROOT_DIR_.'/localization/'.$iso_localization_pack.'.xml'; + if (($iso_localization_pack = Tools::getValue('iso_localization_pack')) && Validate::isFileName($iso_localization_pack)) { + if (Tools::getValue('download_updated_pack') == '1' || defined('_PS_HOST_MODE_')) { + $pack = @Tools::file_get_contents(_PS_API_URL_.'/localization/'.$version.'/'.$iso_localization_pack.'.xml'); + } else { + $pack = false; + } - if (!$pack && !($pack = @Tools::file_get_contents($path))) - $this->errors[] = Tools::displayError('Cannot load the localization pack.'); + if (defined('_PS_HOST_MODE_')) { + $path = _PS_CORE_DIR_.'/localization/'.$iso_localization_pack.'.xml'; + } else { + $path = _PS_ROOT_DIR_.'/localization/'.$iso_localization_pack.'.xml'; + } - if (!$selection = Tools::getValue('selection')) - $this->errors[] = Tools::displayError('Please select at least one item to import.'); - else - { - foreach ($selection as $selected) - if (!Validate::isLocalizationPackSelection($selected)) - { - $this->errors[] = Tools::displayError('Invalid selection'); - return; - } - $localization_pack = new LocalizationPack(); - if (!$localization_pack->loadLocalisationPack($pack, $selection, false, $iso_localization_pack)) - $this->errors = array_merge($this->errors, $localization_pack->getErrors()); - else - Tools::redirectAdmin(self::$currentIndex.'&conf=23&token='.$this->token); - } - } - } + if (!$pack && !($pack = @Tools::file_get_contents($path))) { + $this->errors[] = Tools::displayError('Cannot load the localization pack.'); + } - // Remove the module list cache if the default country changed - if (Tools::isSubmit('submitOptionsconfiguration') && file_exists(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST)) - @unlink(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST); - parent::postProcess(); - } + if (!$selection = Tools::getValue('selection')) { + $this->errors[] = Tools::displayError('Please select at least one item to import.'); + } else { + foreach ($selection as $selected) { + if (!Validate::isLocalizationPackSelection($selected)) { + $this->errors[] = Tools::displayError('Invalid selection'); + return; + } + } + $localization_pack = new LocalizationPack(); + if (!$localization_pack->loadLocalisationPack($pack, $selection, false, $iso_localization_pack)) { + $this->errors = array_merge($this->errors, $localization_pack->getErrors()); + } else { + Tools::redirectAdmin(self::$currentIndex.'&conf=23&token='.$this->token); + } + } + } + } - public function sortLocalizationsPack($a, $b) - { - return $a['name'] > $b['name']; - } + // Remove the module list cache if the default country changed + if (Tools::isSubmit('submitOptionsconfiguration') && file_exists(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST)) { + @unlink(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST); + } + parent::postProcess(); + } - public function renderForm() - { - $localizations_pack = false; - $this->tpl_option_vars['options_content'] = $this->renderOptions(); + public function sortLocalizationsPack($a, $b) + { + return $a['name'] > $b['name']; + } - $xml_localization = Tools::simplexml_load_file(_PS_API_URL_.'/rss/localization.xml'); - if (!$xml_localization) - { - $localization_file = _PS_ROOT_DIR_.'/localization/localization.xml'; - if (file_exists($localization_file)) - $xml_localization = simplexml_load_file($localization_file); - } + public function renderForm() + { + $localizations_pack = false; + $this->tpl_option_vars['options_content'] = $this->renderOptions(); - // Array to hold the list of country ISOs that have a localization pack hosted on prestashop.com - $remote_isos = array(); + $xml_localization = Tools::simplexml_load_file(_PS_API_URL_.'/rss/localization.xml'); + if (!$xml_localization) { + $localization_file = _PS_ROOT_DIR_.'/localization/localization.xml'; + if (file_exists($localization_file)) { + $xml_localization = @simplexml_load_file($localization_file); + } + } - $i = 0; - if ($xml_localization) - foreach ($xml_localization->pack as $key => $pack) - { - $remote_isos[(string)$pack->iso] = true; - $localizations_pack[$i]['iso_localization_pack'] = (string)$pack->iso; - $localizations_pack[$i]['name'] = (string)$pack->name; - $i++; - } + // Array to hold the list of country ISOs that have a localization pack hosted on prestashop.com + $remote_isos = array(); - if (!$localizations_pack) - return $this->displayWarning($this->l('Cannot connect to '._PS_API_URL_)); + $i = 0; + if ($xml_localization) { + foreach ($xml_localization->pack as $key => $pack) { + $remote_isos[(string)$pack->iso] = true; + $localizations_pack[$i]['iso_localization_pack'] = (string)$pack->iso; + $localizations_pack[$i]['name'] = (string)$pack->name; + $i++; + } + } - // Add local localization .xml files to the list if they are not already there - foreach (scandir(_PS_ROOT_DIR_.'/localization/') as $entry) - { - $m = array(); - if (preg_match('/^([a-z]{2})\.xml$/', $entry, $m)) - { - $iso = $m[1]; - if (empty($remote_isos[$iso])) // if the pack is only there locally and not on prestashop.com - { - $xml_pack = simplexml_load_file(_PS_ROOT_DIR_.'/localization/'.$entry); - $localizations_pack[$i]['iso_localization_pack'] = $iso; - $localizations_pack[$i]['name'] = sprintf($this->l('%s (local)'), (string)$xml_pack['name']); - $i++; - } - } - } + if (!$localizations_pack) { + return $this->displayWarning($this->l('Cannot connect to '._PS_API_URL_)); + } - usort($localizations_pack, array($this, 'sortLocalizationsPack')); + // Add local localization .xml files to the list if they are not already there + foreach (scandir(_PS_ROOT_DIR_.'/localization/') as $entry) { + $m = array(); + if (preg_match('/^([a-z]{2})\.xml$/', $entry, $m)) { + $iso = $m[1]; + if (empty($remote_isos[$iso])) { + // if the pack is only there locally and not on prestashop.com - $selection_import = array( - array( - 'id' => 'states', - 'val' => 'states', - 'name' => $this->l('States') - ), - array( - 'id' => 'taxes', - 'val' => 'taxes', - 'name' => $this->l('Taxes') - ), - array( - 'id' => 'currencies', - 'val' => 'currencies', - 'name' => $this->l('Currencies') - ), - array( - 'id' => 'languages', - 'val' => 'languages', - 'name' => $this->l('Languages') - ), - array( - 'id' => 'units', - 'val' => 'units', - 'name' => $this->l('Units (e.g. weight, volume, distance)') - ), - array( - 'id' => 'groups', - 'val' => 'groups', - 'name' => $this->l('Change the behavior of the taxes displayed to the groups') - ) - ); + $xml_pack = @simplexml_load_file(_PS_ROOT_DIR_.'/localization/'.$entry); + if (!$xml_pack) { + return $this->displayWarning($this->l(sprintf('%1s could not be loaded', $entry))); + } + $localizations_pack[$i]['iso_localization_pack'] = $iso; + $localizations_pack[$i]['name'] = sprintf($this->l('%s (local)'), (string)$xml_pack['name']); + $i++; + } + } + } - $this->fields_form = array( - 'tinymce' => true, - 'legend' => array( - 'title' => $this->l('Import a localization pack'), - 'icon' => 'icon-globe' - ), - 'input' => array( - array( - 'type' => 'select', - 'class' => 'chosen', - 'label' => $this->l('Localization pack you want to import'), - 'name' => 'iso_localization_pack', - 'options' => array( - 'query' => $localizations_pack, - 'id' => 'iso_localization_pack', - 'name' => 'name' - ) - ), - array( - 'type' => 'checkbox', - 'label' => $this->l('Content to import'), - 'name' => 'selection[]', - 'lang' => true, - 'values' => array( - 'query' => $selection_import, - 'id' => 'id', - 'name' => 'name' - ) - ), - array( - 'type' => 'radio', - 'label' => $this->l('Download pack data'), - 'desc' => $this->l('If set to yes then the localization pack will be downloaded from prestashop.com. Otherwise the local xml file found in the localization folder of your PrestaShop installation will be used.'), - 'name' => 'download_updated_pack', - 'is_bool'=> true, - 'values' => array( - array( - 'id' => 'download_updated_pack_yes', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'download_updated_pack_no', - 'value' => 0, - 'label' => $this->l('No') - ) - ) - ) - ), - 'submit' => array( - 'title' => $this->l('Import'), - 'icon' => 'process-icon-import', - 'name' => 'submitLocalizationPack' - ), - ); + usort($localizations_pack, array($this, 'sortLocalizationsPack')); - $this->fields_value = array( - 'selection[]_states' => true, - 'selection[]_taxes' => true, - 'selection[]_currencies' => true, - 'selection[]_languages' => true, - 'selection[]_units' => true, - 'download_updated_pack' => 1 - ); + $selection_import = array( + array( + 'id' => 'states', + 'val' => 'states', + 'name' => $this->l('States') + ), + array( + 'id' => 'taxes', + 'val' => 'taxes', + 'name' => $this->l('Taxes') + ), + array( + 'id' => 'currencies', + 'val' => 'currencies', + 'name' => $this->l('Currencies') + ), + array( + 'id' => 'languages', + 'val' => 'languages', + 'name' => $this->l('Languages') + ), + array( + 'id' => 'units', + 'val' => 'units', + 'name' => $this->l('Units (e.g. weight, volume, distance)') + ), + array( + 'id' => 'groups', + 'val' => 'groups', + 'name' => $this->l('Change the behavior of the taxes displayed to the groups') + ) + ); - $this->show_toolbar = true; - return parent::renderForm(); - } + $this->fields_form = array( + 'tinymce' => true, + 'legend' => array( + 'title' => $this->l('Import a localization pack'), + 'icon' => 'icon-globe' + ), + 'input' => array( + array( + 'type' => 'select', + 'class' => 'chosen', + 'label' => $this->l('Localization pack you want to import'), + 'name' => 'iso_localization_pack', + 'options' => array( + 'query' => $localizations_pack, + 'id' => 'iso_localization_pack', + 'name' => 'name' + ) + ), + array( + 'type' => 'checkbox', + 'label' => $this->l('Content to import'), + 'name' => 'selection[]', + 'lang' => true, + 'values' => array( + 'query' => $selection_import, + 'id' => 'id', + 'name' => 'name' + ) + ), + array( + 'type' => 'radio', + 'label' => $this->l('Download pack data'), + 'desc' => $this->l('If set to yes then the localization pack will be downloaded from prestashop.com. Otherwise the local xml file found in the localization folder of your PrestaShop installation will be used.'), + 'name' => 'download_updated_pack', + 'is_bool'=> true, + 'values' => array( + array( + 'id' => 'download_updated_pack_yes', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'download_updated_pack_no', + 'value' => 0, + 'label' => $this->l('No') + ) + ) + ) + ), + 'submit' => array( + 'title' => $this->l('Import'), + 'icon' => 'process-icon-import', + 'name' => 'submitLocalizationPack' + ), + ); - public function initContent() - { - $this->initTabModuleList(); - if (!$this->loadObject(true)) - return; + $this->fields_value = array( + 'selection[]_states' => true, + 'selection[]_taxes' => true, + 'selection[]_currencies' => true, + 'selection[]_languages' => true, + 'selection[]_units' => true, + 'download_updated_pack' => 1 + ); - $this->initToolbar(); - $this->initPageHeaderToolbar(); - $this->context->smarty->assign(array( - 'localization_form' => $this->renderForm(), - 'localization_options' => $this->renderOptions(), - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } - - public function display() - { - $this->initContent(); - parent::display(); - } + $this->show_toolbar = true; + return parent::renderForm(); + } - public function beforeUpdateOptions() - { - $lang = new Language((int)Tools::getValue('PS_LANG_DEFAULT')); + public function initContent() + { + $this->initTabModuleList(); + if (!$this->loadObject(true)) { + return; + } - if (!$lang->active) - { - $lang->active = 1; - $lang->save(); - } - } + $this->initToolbar(); + $this->initPageHeaderToolbar(); + $this->context->smarty->assign(array( + 'localization_form' => $this->renderForm(), + 'localization_options' => $this->renderOptions(), + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } - public function updateOptionPsCurrencyDefault($value) - { - if ($value == Configuration::get('PS_CURRENCY_DEFAULT')) - return; - Configuration::updateValue('PS_CURRENCY_DEFAULT', $value); + public function display() + { + $this->initContent(); + parent::display(); + } - /* Set conversion rate of default currency to 1 */ - ObjectModel::updateMultishopTable('Currency', array('conversion_rate' => 1), 'a.id_currency'); - - $tmp_context = Shop::getContext(); - if ($tmp_context == Shop::CONTEXT_GROUP) - $tmp_shop = Shop::getContextShopGroupID(); - else - $tmp_shop = (int)Shop::getContextShopID(); + public function beforeUpdateOptions() + { + $lang = new Language((int)Tools::getValue('PS_LANG_DEFAULT')); - foreach (Shop::getContextListShopID() as $id_shop) - { - Shop::setContext(Shop::CONTEXT_SHOP, (int)$id_shop); - Currency::refreshCurrencies(); - } - Shop::setContext($tmp_context , $tmp_shop); - } + if (!$lang->active) { + $lang->active = 1; + $lang->save(); + } + } + + public function updateOptionPsCurrencyDefault($value) + { + if ($value == Configuration::get('PS_CURRENCY_DEFAULT')) { + return; + } + Configuration::updateValue('PS_CURRENCY_DEFAULT', $value); + + /* Set conversion rate of default currency to 1 */ + ObjectModel::updateMultishopTable('Currency', array('conversion_rate' => 1), 'a.id_currency'); + + $tmp_context = Shop::getContext(); + if ($tmp_context == Shop::CONTEXT_GROUP) { + $tmp_shop = Shop::getContextShopGroupID(); + } else { + $tmp_shop = (int)Shop::getContextShopID(); + } + + foreach (Shop::getContextListShopID() as $id_shop) { + Shop::setContext(Shop::CONTEXT_SHOP, (int)$id_shop); + Currency::refreshCurrencies(); + } + Shop::setContext($tmp_context, $tmp_shop); + } } diff --git a/controllers/admin/AdminLoginController.php b/controllers/admin/AdminLoginController.php index 80140828..1284f628 100644 --- a/controllers/admin/AdminLoginController.php +++ b/controllers/admin/AdminLoginController.php @@ -26,265 +26,264 @@ class AdminLoginControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->errors = array(); - $this->context = Context::getContext(); - $this->display_header = false; - $this->display_footer = false; - $this->meta_title = $this->l('Administration panel'); - parent::__construct(); - $this->layout = _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes'.DIRECTORY_SEPARATOR.$this->bo_theme - .DIRECTORY_SEPARATOR.'template'.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.'login' - .DIRECTORY_SEPARATOR.'layout.tpl'; + public function __construct() + { + $this->bootstrap = true; + $this->errors = array(); + $this->context = Context::getContext(); + $this->display_header = false; + $this->display_footer = false; + $this->meta_title = $this->l('Administration panel'); + parent::__construct(); + $this->layout = _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes'.DIRECTORY_SEPARATOR.$this->bo_theme + .DIRECTORY_SEPARATOR.'template'.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.'login' + .DIRECTORY_SEPARATOR.'layout.tpl'; - if (!headers_sent()) - header('Login: true'); - } + if (!headers_sent()) { + header('Login: true'); + } + } - public function setMedia() - { - $this->addJquery(); - $this->addjqueryPlugin('validate'); - $this->addJS(_PS_JS_DIR_.'jquery/plugins/validate/localization/messages_'.$this->context->language->iso_code.'.js'); - $this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/admin-theme.css', 'all', 0); - $this->addJS(_PS_JS_DIR_.'vendor/spin.js'); - $this->addJS(_PS_JS_DIR_.'vendor/ladda.js'); - Media::addJsDef(array('img_dir' => _PS_IMG_)); - Media::addJsDefL('one_error', $this->l('There is one error.')); - Media::addJsDefL('more_errors', $this->l('There are several errors.')); + public function setMedia() + { + $this->addJquery(); + $this->addjqueryPlugin('validate'); + $this->addJS(_PS_JS_DIR_.'jquery/plugins/validate/localization/messages_'.$this->context->language->iso_code.'.js'); + $this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/admin-theme.css', 'all', 0); + $this->addJS(_PS_JS_DIR_.'vendor/spin.js'); + $this->addJS(_PS_JS_DIR_.'vendor/ladda.js'); + Media::addJsDef(array('img_dir' => _PS_IMG_)); + Media::addJsDefL('one_error', $this->l('There is one error.', null, true, false)); + Media::addJsDefL('more_errors', $this->l('There are several errors.', null, true, false)); - Hook::exec('actionAdminLoginControllerSetMedia'); + Hook::exec('actionAdminLoginControllerSetMedia'); - // Specific Admin Theme - $this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/overrides.css', 'all', PHP_INT_MAX); - } + // Specific Admin Theme + $this->addCSS(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$this->bo_theme.'/css/overrides.css', 'all', PHP_INT_MAX); + } - public function initContent() - { - if (!Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) - { - // You can uncomment these lines if you want to force https even from localhost and automatically redirect - // header('HTTP/1.1 301 Moved Permanently'); - // header('Location: '.Tools::getShopDomainSsl(true).$_SERVER['REQUEST_URI']); - // exit(); - $clientIsMaintenanceOrLocal = in_array(Tools::getRemoteAddr(), array_merge(array('127.0.0.1'), explode(',', Configuration::get('PS_MAINTENANCE_IP')))); - // If ssl is enabled, https protocol is required. Exception for maintenance and local (127.0.0.1) IP - if ($clientIsMaintenanceOrLocal) - $warningSslMessage = Tools::displayError('SSL is activated. However, your IP is allowed to enter unsecure mode for maintenance or local IP issues.'); - else - { - $url = 'https://'.Tools::safeOutput(Tools::getServerName()).Tools::safeOutput($_SERVER['REQUEST_URI']); - $warningSslMessage = sprintf( - Translate::ppTags( - Tools::displayError('SSL is activated. Please connect using the following link to [1]log into secure mode (https://)[/1]', false), - array('<a href="%s">') - ), - $url - ); - } - $this->context->smarty->assign('warningSslMessage', $warningSslMessage); - } + public function initContent() + { + if (!Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) { + // You can uncomment these lines if you want to force https even from localhost and automatically redirect + // header('HTTP/1.1 301 Moved Permanently'); + // header('Location: '.Tools::getShopDomainSsl(true).$_SERVER['REQUEST_URI']); + // exit(); + $clientIsMaintenanceOrLocal = in_array(Tools::getRemoteAddr(), array_merge(array('127.0.0.1'), explode(',', Configuration::get('PS_MAINTENANCE_IP')))); + // If ssl is enabled, https protocol is required. Exception for maintenance and local (127.0.0.1) IP + if ($clientIsMaintenanceOrLocal) { + $warningSslMessage = Tools::displayError('SSL is activated. However, your IP is allowed to enter unsecure mode for maintenance or local IP issues.'); + } else { + $url = 'https://'.Tools::safeOutput(Tools::getServerName()).Tools::safeOutput($_SERVER['REQUEST_URI']); + $warningSslMessage = sprintf( + Translate::ppTags( + Tools::displayError('SSL is activated. Please connect using the following link to [1]log into secure mode (https://)[/1]', false), + array('<a href="%s">') + ), + $url + ); + } + $this->context->smarty->assign('warningSslMessage', $warningSslMessage); + } - if (file_exists(_PS_ADMIN_DIR_.'/../install')) - $this->context->smarty->assign('wrong_install_name', true); + if (file_exists(_PS_ADMIN_DIR_.'/../install')) { + $this->context->smarty->assign('wrong_install_name', true); + } - if (basename(_PS_ADMIN_DIR_) == 'admin' && file_exists(_PS_ADMIN_DIR_.'/../admin/')) - { - $rand = 'admin'.sprintf('%03d', rand(0, 999)).Tools::strtolower(Tools::passwdGen(6)).'/'; - if (@rename(_PS_ADMIN_DIR_.'/../admin/', _PS_ADMIN_DIR_.'/../'.$rand)) - Tools::redirectAdmin('../'.$rand); - else - $this->context->smarty->assign(array( - 'wrong_folder_name' => true - )); - } - else - $rand = basename(_PS_ADMIN_DIR_).'/'; + if (basename(_PS_ADMIN_DIR_) == 'admin' && file_exists(_PS_ADMIN_DIR_.'/../admin/')) { + $rand = 'admin'.sprintf('%03d', rand(0, 999)).Tools::strtolower(Tools::passwdGen(6)).'/'; + if (@rename(_PS_ADMIN_DIR_.'/../admin/', _PS_ADMIN_DIR_.'/../'.$rand)) { + Tools::redirectAdmin('../'.$rand); + } else { + $this->context->smarty->assign(array( + 'wrong_folder_name' => true + )); + } + } else { + $rand = basename(_PS_ADMIN_DIR_).'/'; + } - $this->context->smarty->assign(array( - 'randomNb' => $rand, - 'adminUrl' => Tools::getCurrentUrlProtocolPrefix().Tools::getShopDomain().__PS_BASE_URI__.$rand - )); + $this->context->smarty->assign(array( + 'randomNb' => $rand, + 'adminUrl' => Tools::getCurrentUrlProtocolPrefix().Tools::getShopDomain().__PS_BASE_URI__.$rand + )); - // Redirect to admin panel - if (Tools::isSubmit('redirect') && Validate::isControllerName(Tools::getValue('redirect'))) - $this->context->smarty->assign('redirect', Tools::getValue('redirect')); - else - { - $tab = new Tab((int)$this->context->employee->default_tab); - $this->context->smarty->assign('redirect', $this->context->link->getAdminLink($tab->class_name)); - } + // Redirect to admin panel + if (Tools::isSubmit('redirect') && Validate::isControllerName(Tools::getValue('redirect'))) { + $this->context->smarty->assign('redirect', Tools::getValue('redirect')); + } else { + $tab = new Tab((int)$this->context->employee->default_tab); + $this->context->smarty->assign('redirect', $this->context->link->getAdminLink($tab->class_name)); + } - if ($nb_errors = count($this->errors)) - $this->context->smarty->assign(array( - 'errors' => $this->errors, - 'nbErrors' => $nb_errors, - 'shop_name' => Tools::safeOutput(Configuration::get('PS_SHOP_NAME')), - 'disableDefaultErrorOutPut' => true, - )); + if ($nb_errors = count($this->errors)) { + $this->context->smarty->assign(array( + 'errors' => $this->errors, + 'nbErrors' => $nb_errors, + 'shop_name' => Tools::safeOutput(Configuration::get('PS_SHOP_NAME')), + 'disableDefaultErrorOutPut' => true, + )); + } - if ($email = Tools::getValue('email')) - $this->context->smarty->assign('email', $email); - if ($password = Tools::getValue('password')) - $this->context->smarty->assign('password', $password); + if ($email = Tools::getValue('email')) { + $this->context->smarty->assign('email', $email); + } + if ($password = Tools::getValue('password')) { + $this->context->smarty->assign('password', $password); + } - $this->setMedia(); - $this->initHeader(); - parent::initContent(); - $this->initFooter(); + $this->setMedia(); + $this->initHeader(); + parent::initContent(); + $this->initFooter(); - //force to disable modals - $this->context->smarty->assign('modals', null); - } + //force to disable modals + $this->context->smarty->assign('modals', null); + } - public function checkToken() - { - return true; - } + public function checkToken() + { + return true; + } - /** - * All BO users can access the login page - * - * @return bool - */ - public function viewAccess() - { - return true; - } + /** + * All BO users can access the login page + * + * @return bool + */ + public function viewAccess() + { + return true; + } - public function postProcess() - { - if (Tools::isSubmit('submitLogin')) - $this->processLogin(); - elseif (Tools::isSubmit('submitForgot')) - $this->processForgot(); - } + public function postProcess() + { + if (Tools::isSubmit('submitLogin')) { + $this->processLogin(); + } elseif (Tools::isSubmit('submitForgot')) { + $this->processForgot(); + } + } - public function processLogin() - { - /* Check fields validity */ - $passwd = trim(Tools::getValue('passwd')); - $email = trim(Tools::getValue('email')); - if (empty($email)) - $this->errors[] = Tools::displayError('Email is empty.'); - elseif (!Validate::isEmail($email)) - $this->errors[] = Tools::displayError('Invalid email address.'); + public function processLogin() + { + /* Check fields validity */ + $passwd = trim(Tools::getValue('passwd')); + $email = trim(Tools::getValue('email')); + if (empty($email)) { + $this->errors[] = Tools::displayError('Email is empty.'); + } elseif (!Validate::isEmail($email)) { + $this->errors[] = Tools::displayError('Invalid email address.'); + } - if (empty($passwd)) - $this->errors[] = Tools::displayError('The password field is blank.'); - elseif (!Validate::isPasswd($passwd)) - $this->errors[] = Tools::displayError('Invalid password.'); + if (empty($passwd)) { + $this->errors[] = Tools::displayError('The password field is blank.'); + } elseif (!Validate::isPasswd($passwd)) { + $this->errors[] = Tools::displayError('Invalid password.'); + } - if (!count($this->errors)) - { - // Find employee - $this->context->employee = new Employee(); - $is_employee_loaded = $this->context->employee->getByEmail($email, $passwd); - $employee_associated_shop = $this->context->employee->getAssociatedShops(); - if (!$is_employee_loaded) - { - $this->errors[] = Tools::displayError('The Employee does not exist, or the password provided is incorrect.'); - $this->context->employee->logout(); - } - elseif (empty($employee_associated_shop) && !$this->context->employee->isSuperAdmin()) - { - $this->errors[] = Tools::displayError('This employee does not manage the shop anymore (Either the shop has been deleted or permissions have been revoked).'); - $this->context->employee->logout(); - } - else - { - PrestaShopLogger::addLog(sprintf($this->l('Back Office connection from %s', 'AdminTab', false, false), Tools::getRemoteAddr()), 1, null, '', 0, true, (int)$this->context->employee->id); + if (!count($this->errors)) { + // Find employee + $this->context->employee = new Employee(); + $is_employee_loaded = $this->context->employee->getByEmail($email, $passwd); + $employee_associated_shop = $this->context->employee->getAssociatedShops(); + if (!$is_employee_loaded) { + $this->errors[] = Tools::displayError('The Employee does not exist, or the password provided is incorrect.'); + $this->context->employee->logout(); + } elseif (empty($employee_associated_shop) && !$this->context->employee->isSuperAdmin()) { + $this->errors[] = Tools::displayError('This employee does not manage the shop anymore (Either the shop has been deleted or permissions have been revoked).'); + $this->context->employee->logout(); + } else { + PrestaShopLogger::addLog(sprintf($this->l('Back Office connection from %s', 'AdminTab', false, false), Tools::getRemoteAddr()), 1, null, '', 0, true, (int)$this->context->employee->id); - $this->context->employee->remote_addr = (int)ip2long(Tools::getRemoteAddr()); - // Update cookie - $cookie = Context::getContext()->cookie; - $cookie->id_employee = $this->context->employee->id; - $cookie->email = $this->context->employee->email; - $cookie->profile = $this->context->employee->id_profile; - $cookie->passwd = $this->context->employee->passwd; - $cookie->remote_addr = $this->context->employee->remote_addr; + $this->context->employee->remote_addr = (int)ip2long(Tools::getRemoteAddr()); + // Update cookie + $cookie = Context::getContext()->cookie; + $cookie->id_employee = $this->context->employee->id; + $cookie->email = $this->context->employee->email; + $cookie->profile = $this->context->employee->id_profile; + $cookie->passwd = $this->context->employee->passwd; + $cookie->remote_addr = $this->context->employee->remote_addr; - if (!Tools::getValue('stay_logged_in')) - $cookie->last_activity = time(); + if (!Tools::getValue('stay_logged_in')) { + $cookie->last_activity = time(); + } - $cookie->write(); + $cookie->write(); - // If there is a valid controller name submitted, redirect to it - if (isset($_POST['redirect']) && Validate::isControllerName($_POST['redirect'])) - $url = $this->context->link->getAdminLink($_POST['redirect']); - else - { - $tab = new Tab((int)$this->context->employee->default_tab); - $url = $this->context->link->getAdminLink($tab->class_name); - } + // If there is a valid controller name submitted, redirect to it + if (isset($_POST['redirect']) && Validate::isControllerName($_POST['redirect'])) { + $url = $this->context->link->getAdminLink($_POST['redirect']); + } else { + $tab = new Tab((int)$this->context->employee->default_tab); + $url = $this->context->link->getAdminLink($tab->class_name); + } - if (Tools::isSubmit('ajax')) - die(Tools::jsonEncode(array('hasErrors' => false, 'redirect' => $url))); - else - $this->redirect_after = $url; - } - } - if (Tools::isSubmit('ajax')) - die(Tools::jsonEncode(array('hasErrors' => true, 'errors' => $this->errors))); - } + if (Tools::isSubmit('ajax')) { + die(Tools::jsonEncode(array('hasErrors' => false, 'redirect' => $url))); + } else { + $this->redirect_after = $url; + } + } + } + if (Tools::isSubmit('ajax')) { + die(Tools::jsonEncode(array('hasErrors' => true, 'errors' => $this->errors))); + } + } - public function processForgot() - { - if (_PS_MODE_DEMO_) - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - elseif (!($email = trim(Tools::getValue('email_forgot')))) - $this->errors[] = Tools::displayError('Email is empty.'); - elseif (!Validate::isEmail($email)) - $this->errors[] = Tools::displayError('Invalid email address.'); - else - { - $employee = new Employee(); - if (!$employee->getByEmail($email) || !$employee) - $this->errors[] = Tools::displayError('This account does not exist.'); - elseif ((strtotime($employee->last_passwd_gen.'+'.Configuration::get('PS_PASSWD_TIME_BACK').' minutes') - time()) > 0) - $this->errors[] = sprintf( - Tools::displayError('You can regenerate your password only every %d minute(s)'), - Configuration::get('PS_PASSWD_TIME_BACK') - ); - } + public function processForgot() + { + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + } elseif (!($email = trim(Tools::getValue('email_forgot')))) { + $this->errors[] = Tools::displayError('Email is empty.'); + } elseif (!Validate::isEmail($email)) { + $this->errors[] = Tools::displayError('Invalid email address.'); + } else { + $employee = new Employee(); + if (!$employee->getByEmail($email) || !$employee) { + $this->errors[] = Tools::displayError('This account does not exist.'); + } elseif ((strtotime($employee->last_passwd_gen.'+'.Configuration::get('PS_PASSWD_TIME_BACK').' minutes') - time()) > 0) { + $this->errors[] = sprintf( + Tools::displayError('You can regenerate your password only every %d minute(s)'), + Configuration::get('PS_PASSWD_TIME_BACK') + ); + } + } - if (!count($this->errors)) - { - $pwd = Tools::passwdGen(10, 'RANDOM'); - $employee->passwd = Tools::encrypt($pwd); - $employee->last_passwd_gen = date('Y-m-d H:i:s', time()); + if (!count($this->errors)) { + $pwd = Tools::passwdGen(10, 'RANDOM'); + $employee->passwd = Tools::encrypt($pwd); + $employee->last_passwd_gen = date('Y-m-d H:i:s', time()); - $params = array( - '{email}' => $employee->email, - '{lastname}' => $employee->lastname, - '{firstname}' => $employee->firstname, - '{passwd}' => $pwd - ); + $params = array( + '{email}' => $employee->email, + '{lastname}' => $employee->lastname, + '{firstname}' => $employee->firstname, + '{passwd}' => $pwd + ); - if (Mail::Send($employee->id_lang, 'employee_password', Mail::l('Your new password', $employee->id_lang), $params, $employee->email, $employee->firstname.' '.$employee->lastname)) - { - // Update employee only if the mail can be sent - Shop::setContext(Shop::CONTEXT_SHOP, (int)min($employee->getAssociatedShops())); + if (Mail::Send($employee->id_lang, 'employee_password', Mail::l('Your new password', $employee->id_lang), $params, $employee->email, $employee->firstname.' '.$employee->lastname)) { + // Update employee only if the mail can be sent + Shop::setContext(Shop::CONTEXT_SHOP, (int)min($employee->getAssociatedShops())); - $result = $employee->update(); - if (!$result) - $this->errors[] = Tools::displayError('An error occurred while attempting to change your password.'); - else - die(Tools::jsonEncode(array( - 'hasErrors' => false, - 'confirm' => $this->l('Your password has been emailed to you.', 'AdminTab', false, false) - ))); - } - else - die(Tools::jsonEncode(array( - 'hasErrors' => true, - 'errors' => array(Tools::displayError('An error occurred while attempting to change your password.')) - ))); - - } - elseif (Tools::isSubmit('ajax')) - die(Tools::jsonEncode(array('hasErrors' => true, 'errors' => $this->errors))); - } + $result = $employee->update(); + if (!$result) { + $this->errors[] = Tools::displayError('An error occurred while attempting to change your password.'); + } else { + die(Tools::jsonEncode(array( + 'hasErrors' => false, + 'confirm' => $this->l('Your password has been emailed to you.', 'AdminTab', false, false) + ))); + } + } else { + die(Tools::jsonEncode(array( + 'hasErrors' => true, + 'errors' => array(Tools::displayError('An error occurred while attempting to change your password.')) + ))); + } + } elseif (Tools::isSubmit('ajax')) { + die(Tools::jsonEncode(array('hasErrors' => true, 'errors' => $this->errors))); + } + } } diff --git a/controllers/admin/AdminLogsController.php b/controllers/admin/AdminLogsController.php index 77c6c7ce..fb7c04a7 100644 --- a/controllers/admin/AdminLogsController.php +++ b/controllers/admin/AdminLogsController.php @@ -29,103 +29,104 @@ */ class AdminLogsControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'log'; - $this->className = 'PrestaShopLogger'; - $this->lang = false; - $this->noLink = true; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'log'; + $this->className = 'PrestaShopLogger'; + $this->lang = false; + $this->noLink = true; - $this->fields_list = array( - 'id_log' => array( - 'title' => $this->l('ID'), - 'align' => 'text-center', - 'class' => 'fixed-width-xs' - ), - 'employee' => array( - 'title' => $this->l('Employee'), - 'havingFilter' => true, - 'callback' => 'displayEmployee', - 'callback_object' => $this - ), - 'severity' => array( - 'title' => $this->l('Severity (1-4)'), - 'align' => 'text-center', - 'class' => 'fixed-width-xs' - ), - 'message' => array( - 'title' => $this->l('Message') - ), - 'object_type' => array( - 'title' => $this->l('Object type'), - 'class' => 'fixed-width-sm' - ), - 'object_id' => array( - 'title' => $this->l('Object ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'error_code' => array( - 'title' => $this->l('Error code'), - 'align' => 'center', - 'prefix' => '0x', - 'class' => 'fixed-width-xs' - ), - 'date_add' => array( - 'title' => $this->l('Date'), - 'align' => 'right', - 'type' => 'datetime' - ) - ); + $this->fields_list = array( + 'id_log' => array( + 'title' => $this->l('ID'), + 'align' => 'text-center', + 'class' => 'fixed-width-xs' + ), + 'employee' => array( + 'title' => $this->l('Employee'), + 'havingFilter' => true, + 'callback' => 'displayEmployee', + 'callback_object' => $this + ), + 'severity' => array( + 'title' => $this->l('Severity (1-4)'), + 'align' => 'text-center', + 'class' => 'fixed-width-xs' + ), + 'message' => array( + 'title' => $this->l('Message') + ), + 'object_type' => array( + 'title' => $this->l('Object type'), + 'class' => 'fixed-width-sm' + ), + 'object_id' => array( + 'title' => $this->l('Object ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'error_code' => array( + 'title' => $this->l('Error code'), + 'align' => 'center', + 'prefix' => '0x', + 'class' => 'fixed-width-xs' + ), + 'date_add' => array( + 'title' => $this->l('Date'), + 'align' => 'right', + 'type' => 'datetime' + ) + ); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Logs by email'), - 'icon' => 'icon-envelope', - 'fields' => array( - 'PS_LOGS_BY_EMAIL' => array( - 'title' => $this->l('Minimum severity level'), - 'hint' => $this->l('Enter "5" if you do not want to receive any emails.').'<br />'.$this->l('Emails will be sent to the shop owner.'), - 'cast' => 'intval', - 'type' => 'text' - ) - ), - 'submit' => array('title' => $this->l('Save')) - ) - ); - $this->list_no_link = true; - $this->_select .= 'CONCAT(LEFT(e.firstname, 1), \'. \', e.lastname) employee'; - $this->_join .= ' LEFT JOIN '._DB_PREFIX_.'employee e ON (a.id_employee = e.id_employee)'; - $this->_use_found_rows = false; - parent::__construct(); - } + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Logs by email'), + 'icon' => 'icon-envelope', + 'fields' => array( + 'PS_LOGS_BY_EMAIL' => array( + 'title' => $this->l('Minimum severity level'), + 'hint' => $this->l('Enter "5" if you do not want to receive any emails.').'<br />'.$this->l('Emails will be sent to the shop owner.'), + 'cast' => 'intval', + 'type' => 'text' + ) + ), + 'submit' => array('title' => $this->l('Save')) + ) + ); + $this->list_no_link = true; + $this->_select .= 'CONCAT(LEFT(e.firstname, 1), \'. \', e.lastname) employee'; + $this->_join .= ' LEFT JOIN '._DB_PREFIX_.'employee e ON (a.id_employee = e.id_employee)'; + $this->_use_found_rows = false; + parent::__construct(); + } - public function processDelete() - { - if (PrestaShopLogger::eraseAllLogs()) - Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminLogs')); - } + public function processDelete() + { + if (PrestaShopLogger::eraseAllLogs()) { + Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminLogs')); + } + } - public function initToolbar() - { - parent::initToolbar(); - $this->toolbar_btn['delete'] = array( - 'short' => 'Erase', - 'desc' => $this->l('Erase all'), - 'js' => 'if (confirm(\''.$this->l('Are you sure?').'\')) document.location = \''.Tools::safeOutput($this->context->link->getAdminLink('AdminLogs')).'&token='.$this->token.'&deletelog=1\';' - ); - unset($this->toolbar_btn['new']); - } + public function initToolbar() + { + parent::initToolbar(); + $this->toolbar_btn['delete'] = array( + 'short' => 'Erase', + 'desc' => $this->l('Erase all'), + 'js' => 'if (confirm(\''.$this->l('Are you sure?').'\')) document.location = \''.Tools::safeOutput($this->context->link->getAdminLink('AdminLogs')).'&token='.$this->token.'&deletelog=1\';' + ); + unset($this->toolbar_btn['new']); + } - public function displayEmployee($value, $tr) - { - $template = $this->context->smarty->createTemplate('controllers/logs/employee_field.tpl', $this->context->smarty); - $employee = new Employee((int)$tr['id_employee']); - $template->assign(array( - 'employee_image' => $employee->getImage(), - 'employee_name' => $value - )); - return $template->fetch(); - } + public function displayEmployee($value, $tr) + { + $template = $this->context->smarty->createTemplate('controllers/logs/employee_field.tpl', $this->context->smarty); + $employee = new Employee((int)$tr['id_employee']); + $template->assign(array( + 'employee_image' => $employee->getImage(), + 'employee_name' => $value + )); + return $template->fetch(); + } } diff --git a/controllers/admin/AdminMaintenanceController.php b/controllers/admin/AdminMaintenanceController.php index 0a9c1f9e..f0700e9a 100644 --- a/controllers/admin/AdminMaintenanceController.php +++ b/controllers/admin/AdminMaintenanceController.php @@ -29,35 +29,35 @@ */ class AdminMaintenanceControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->className = 'Configuration'; - $this->table = 'configuration'; + public function __construct() + { + $this->bootstrap = true; + $this->className = 'Configuration'; + $this->table = 'configuration'; - parent::__construct(); + parent::__construct(); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('General'), - 'fields' => array( - 'PS_SHOP_ENABLE' => array( - 'title' => $this->l('Enable Shop'), - 'desc' => $this->l('Activate or deactivate your shop (It is a good idea to deactivate your shop while you perform maintenance. Please note that the webservice will not be disabled).'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_MAINTENANCE_IP' => array( - 'title' => $this->l('Maintenance IP'), - 'hint' => $this->l('IP addresses allowed to access the front office even if the shop is disabled. Please use a comma to separate them (e.g. 42.24.4.2,127.0.0.1,99.98.97.96)'), - 'validation' => 'isGenericName', - 'type' => 'maintenance_ip', - 'default' => '' - ), - ), - 'submit' => array('title' => $this->l('Save')) - ), - ); - } + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('General'), + 'fields' => array( + 'PS_SHOP_ENABLE' => array( + 'title' => $this->l('Enable Shop'), + 'desc' => $this->l('Activate or deactivate your shop (It is a good idea to deactivate your shop while you perform maintenance. Please note that the webservice will not be disabled).'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_MAINTENANCE_IP' => array( + 'title' => $this->l('Maintenance IP'), + 'hint' => $this->l('IP addresses allowed to access the front office even if the shop is disabled. Please use a comma to separate them (e.g. 42.24.4.2,127.0.0.1,99.98.97.96)'), + 'validation' => 'isGenericName', + 'type' => 'maintenance_ip', + 'default' => '' + ), + ), + 'submit' => array('title' => $this->l('Save')) + ), + ); + } } diff --git a/controllers/admin/AdminManufacturersController.php b/controllers/admin/AdminManufacturersController.php index 377093ca..523dcac0 100644 --- a/controllers/admin/AdminManufacturersController.php +++ b/controllers/admin/AdminManufacturersController.php @@ -29,841 +29,840 @@ */ class AdminManufacturersControllerCore extends AdminController { - public $bootstrap = true ; - /** @var array countries list */ - protected $countries_array = array(); + public $bootstrap = true ; + /** @var array countries list */ + protected $countries_array = array(); - public function __construct() - { - $this->table = 'manufacturer'; - $this->className = 'Manufacturer'; - $this->lang = false; - $this->deleted = false; - $this->allow_export = true; - $this->list_id = 'manufacturer'; - $this->identifier = 'id_manufacturer'; - $this->_defaultOrderBy = 'name'; - $this->_defaultOrderWay = 'ASC'; + public function __construct() + { + $this->table = 'manufacturer'; + $this->className = 'Manufacturer'; + $this->lang = false; + $this->deleted = false; + $this->allow_export = true; + $this->list_id = 'manufacturer'; + $this->identifier = 'id_manufacturer'; + $this->_defaultOrderBy = 'name'; + $this->_defaultOrderWay = 'ASC'; - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'icon' => 'icon-trash', - 'confirm' => $this->l('Delete selected items?') - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'icon' => 'icon-trash', + 'confirm' => $this->l('Delete selected items?') + ) + ); - $this->context = Context::getContext(); + $this->context = Context::getContext(); - $this->fieldImageSettings = array( - 'name' => 'logo', - 'dir' => 'm' - ); + $this->fieldImageSettings = array( + 'name' => 'logo', + 'dir' => 'm' + ); - $this->fields_list = array( - 'id_manufacturer' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'logo' => array( - 'title' => $this->l('Logo'), - 'image' => 'm', - 'orderby' => false, - 'search' => false, - 'align' => 'center', - ), - 'name' => array( - 'title' => $this->l('Name'), - 'width' => 'auto' - ), - 'addresses' => array( - 'title' => $this->l('Addresses'), - 'search' => false, - 'align' => 'center' - ), - 'products' => array( - 'title' => $this->l('Products'), - 'search' => false, - 'align' => 'center', - ), - 'active' => array( - 'title' => $this->l('Enabled'), - 'active' => 'status', - 'type' => 'bool', - 'align' => 'center', - 'class' => 'fixed-width-xs', - 'orderby' => false - ) - ); + $this->fields_list = array( + 'id_manufacturer' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'logo' => array( + 'title' => $this->l('Logo'), + 'image' => 'm', + 'orderby' => false, + 'search' => false, + 'align' => 'center', + ), + 'name' => array( + 'title' => $this->l('Name'), + 'width' => 'auto' + ), + 'addresses' => array( + 'title' => $this->l('Addresses'), + 'search' => false, + 'align' => 'center' + ), + 'products' => array( + 'title' => $this->l('Products'), + 'search' => false, + 'align' => 'center', + ), + 'active' => array( + 'title' => $this->l('Enabled'), + 'active' => 'status', + 'type' => 'bool', + 'align' => 'center', + 'class' => 'fixed-width-xs', + 'orderby' => false + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function setMedia() - { - parent::setMedia(); - $this->addJqueryUi('ui.widget'); - $this->addJqueryPlugin('tagify'); - } + public function setMedia() + { + parent::setMedia(); + $this->addJqueryUi('ui.widget'); + $this->addJqueryPlugin('tagify'); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - { - $this->page_header_toolbar_btn['new_manufacturer'] = array( - 'href' => self::$currentIndex.'&addmanufacturer&token='.$this->token, - 'desc' => $this->l('Add new manufacturer', null, null, false), - 'icon' => 'process-icon-new' - ); - $this->page_header_toolbar_btn['new_manufacturer_address'] = array( - 'href' => self::$currentIndex.'&addaddress&token='.$this->token, - 'desc' => $this->l('Add new manufacturer address', null, null, false), - 'icon' => 'process-icon-new' - ); - } - elseif ($this->display == 'editaddresses' || $this->display == 'addaddress') { - // Default cancel button - like old back link - if (!isset($this->no_back) || $this->no_back == false) - { - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_manufacturer'] = array( + 'href' => self::$currentIndex.'&addmanufacturer&token='.$this->token, + 'desc' => $this->l('Add new manufacturer', null, null, false), + 'icon' => 'process-icon-new' + ); + $this->page_header_toolbar_btn['new_manufacturer_address'] = array( + 'href' => self::$currentIndex.'&addaddress&token='.$this->token, + 'desc' => $this->l('Add new manufacturer address', null, null, false), + 'icon' => 'process-icon-new' + ); + } elseif ($this->display == 'editaddresses' || $this->display == 'addaddress') { + // Default cancel button - like old back link + if (!isset($this->no_back) || $this->no_back == false) { + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } - $this->page_header_toolbar_btn['cancel'] = array( - 'href' => $back, - 'desc' => $this->l('Cancel', null, null, false) - ); - } - } + $this->page_header_toolbar_btn['cancel'] = array( + 'href' => $back, + 'desc' => $this->l('Cancel', null, null, false) + ); + } + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function initListManufacturer() - { - $this->addRowAction('view'); - $this->addRowAction('edit'); - $this->addRowAction('delete'); + public function initListManufacturer() + { + $this->addRowAction('view'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->_select = ' + $this->_select = ' COUNT(`id_product`) AS `products`, ( SELECT COUNT(ad.`id_manufacturer`) as `addresses` FROM `'._DB_PREFIX_.'address` ad WHERE ad.`id_manufacturer` = a.`id_manufacturer` AND ad.`deleted` = 0 GROUP BY ad.`id_manufacturer`) as `addresses`'; - $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'product` p ON (a.`id_manufacturer` = p.`id_manufacturer`)'; - $this->_group = 'GROUP BY a.`id_manufacturer`'; + $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'product` p ON (a.`id_manufacturer` = p.`id_manufacturer`)'; + $this->_group = 'GROUP BY a.`id_manufacturer`'; - $this->context->smarty->assign('title_list', $this->l('List of manufacturers')); + $this->context->smarty->assign('title_list', $this->l('List of manufacturers')); - $this->content .= parent::renderList(); - } + $this->content .= parent::renderList(); + } - protected function getAddressFieldsList() - { - // Sub tab addresses - $countries = Country::getCountries($this->context->language->id); - foreach ($countries as $country) - $this->countries_array[$country['id_country']] = $country['name']; + protected function getAddressFieldsList() + { + // Sub tab addresses + $countries = Country::getCountries($this->context->language->id); + foreach ($countries as $country) { + $this->countries_array[$country['id_country']] = $country['name']; + } - return array( - 'id_address' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'manufacturer_name' => array( - 'title' => $this->l('Manufacturer'), - 'width' => 'auto', - 'filter_key' => 'manufacturer_name' - ), - 'firstname' => array( - 'title' => $this->l('First name') - ), - 'lastname' => array( - 'title' => $this->l('Last name'), - 'filter_key' => 'a!lastname' - ), - 'postcode' => array( - 'title' => $this->l('Zip/Postal code'), - 'align' => 'right' - ), - 'city' => array( - 'title' => $this->l('City') - ), - 'country' => array( - 'title' => $this->l('Country'), - 'type' => 'select', - 'list' => $this->countries_array, - 'filter_key' => 'cl!id_country' - ) - ); - } + return array( + 'id_address' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'manufacturer_name' => array( + 'title' => $this->l('Manufacturer'), + 'width' => 'auto', + 'filter_key' => 'manufacturer_name' + ), + 'firstname' => array( + 'title' => $this->l('First name') + ), + 'lastname' => array( + 'title' => $this->l('Last name'), + 'filter_key' => 'a!lastname' + ), + 'postcode' => array( + 'title' => $this->l('Zip/Postal code'), + 'align' => 'right' + ), + 'city' => array( + 'title' => $this->l('City') + ), + 'country' => array( + 'title' => $this->l('Country'), + 'type' => 'select', + 'list' => $this->countries_array, + 'filter_key' => 'cl!id_country' + ) + ); + } - public function processExport($text_delimiter = '"') - { - if (strtolower($this->table) == 'address') - { - $this->_defaultOrderBy = 'id_manufacturer'; - $this->_where = 'AND a.`id_customer` = 0 AND a.`id_supplier` = 0 AND a.`id_warehouse` = 0 AND a.`deleted`= 0'; - } + public function processExport($text_delimiter = '"') + { + if (strtolower($this->table) == 'address') { + $this->_defaultOrderBy = 'id_manufacturer'; + $this->_where = 'AND a.`id_customer` = 0 AND a.`id_supplier` = 0 AND a.`id_warehouse` = 0 AND a.`deleted`= 0'; + } - return parent::processExport($text_delimiter); - } + return parent::processExport($text_delimiter); + } - public function initListManufacturerAddresses() - { - $this->toolbar_title = $this->l('Addresses'); - // reset actions and query vars - $this->actions = array(); - unset($this->fields_list, $this->_select, $this->_join, $this->_group, $this->_filterHaving, $this->_filter); + public function initListManufacturerAddresses() + { + $this->toolbar_title = $this->l('Addresses'); + // reset actions and query vars + $this->actions = array(); + unset($this->fields_list, $this->_select, $this->_join, $this->_group, $this->_filterHaving, $this->_filter); - $this->table = 'address'; - $this->list_id = 'address'; - $this->identifier = 'id_address'; - $this->deleted = true; + $this->table = 'address'; + $this->list_id = 'address'; + $this->identifier = 'id_address'; + $this->deleted = true; - $this->_defaultOrderBy = 'id_address'; - $this->_defaultOrderWay = 'ASC'; + $this->_defaultOrderBy = 'id_address'; + $this->_defaultOrderWay = 'ASC'; - $this->_orderBy = null; + $this->_orderBy = null; - $this->addRowAction('editaddresses'); - $this->addRowAction('delete'); + $this->addRowAction('editaddresses'); + $this->addRowAction('delete'); - // test if a filter is applied for this list - if (Tools::isSubmit('submitFilter'.$this->table) || $this->context->cookie->{'submitFilter'.$this->table} !== false) - $this->filter = true; + // test if a filter is applied for this list + if (Tools::isSubmit('submitFilter'.$this->table) || $this->context->cookie->{'submitFilter'.$this->table} !== false) { + $this->filter = true; + } - // test if a filter reset request is required for this list - $this->action = (isset($_POST['submitReset'.$this->table]) ? 'reset_filters' : ''); + // test if a filter reset request is required for this list + $this->action = (isset($_POST['submitReset'.$this->table]) ? 'reset_filters' : ''); - $this->fields_list = $this->getAddressFieldsList(); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'icon' => 'icon-trash', - 'confirm' => $this->l('Delete selected items?') - ) - ); + $this->fields_list = $this->getAddressFieldsList(); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'icon' => 'icon-trash', + 'confirm' => $this->l('Delete selected items?') + ) + ); - $this->_select = 'cl.`name` as country, m.`name` AS manufacturer_name'; - $this->_join = ' + $this->_select = 'cl.`name` as country, m.`name` AS manufacturer_name'; + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'country_lang` cl ON (cl.`id_country` = a.`id_country` AND cl.`id_lang` = '.(int)$this->context->language->id.') '; - $this->_join .= ' + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (a.`id_manufacturer` = m.`id_manufacturer`)'; - $this->_where = 'AND a.`id_customer` = 0 AND a.`id_supplier` = 0 AND a.`id_warehouse` = 0 AND a.`deleted`= 0'; + $this->_where = 'AND a.`id_customer` = 0 AND a.`id_supplier` = 0 AND a.`id_warehouse` = 0 AND a.`deleted`= 0'; - $this->context->smarty->assign('title_list', $this->l('Manufacturers addresses')); + $this->context->smarty->assign('title_list', $this->l('Manufacturers addresses')); - // call postProcess() for take care about actions and filters - $this->postProcess(); + // call postProcess() for take care about actions and filters + $this->postProcess(); - $this->initToolbar(); + $this->initToolbar(); - $this->content .= parent::renderList(); + $this->content .= parent::renderList(); + } - } + public function renderList() + { + $this->initListManufacturer(); + $this->initListManufacturerAddresses(); + } - public function renderList() - { - $this->initListManufacturer(); - $this->initListManufacturerAddresses(); - } + /** + * Display editaddresses action link + * @param string $token the token to add to the link + * @param int $id the identifier to add to the link + * @return string + */ + public function displayEditaddressesLink($token = null, $id) + { + if (!array_key_exists('editaddresses', self::$cache_lang)) { + self::$cache_lang['editaddresses'] = $this->l('Edit'); + } - /** - * Display editaddresses action link - * @param string $token the token to add to the link - * @param int $id the identifier to add to the link - * @return string - */ - public function displayEditaddressesLink($token = null, $id) - { - if (!array_key_exists('editaddresses', self::$cache_lang)) - self::$cache_lang['editaddresses'] = $this->l('Edit'); + $this->context->smarty->assign(array( + 'href' => self::$currentIndex. + '&'.$this->identifier.'='.$id. + '&editaddresses&token='.($token != null ? $token : $this->token), + 'action' => self::$cache_lang['editaddresses'], + )); - $this->context->smarty->assign(array( - 'href' => self::$currentIndex. - '&'.$this->identifier.'='.$id. - '&editaddresses&token='.($token != null ? $token : $this->token), - 'action' => self::$cache_lang['editaddresses'], - )); + return $this->context->smarty->fetch('helpers/list/list_action_edit.tpl'); + } - return $this->context->smarty->fetch('helpers/list/list_action_edit.tpl'); - } + public function renderForm() + { + if (!($manufacturer = $this->loadObject(true))) { + return; + } - public function renderForm() - { - if (!($manufacturer = $this->loadObject(true))) - return; + $image = _PS_MANU_IMG_DIR_.$manufacturer->id.'.jpg'; + $image_url = ImageManager::thumbnail($image, $this->table.'_'.(int)$manufacturer->id.'.'.$this->imageType, 350, + $this->imageType, true, true); + $image_size = file_exists($image) ? filesize($image) / 1000 : false; - $image = _PS_MANU_IMG_DIR_.$manufacturer->id.'.jpg'; - $image_url = ImageManager::thumbnail($image, $this->table.'_'.(int)$manufacturer->id.'.'.$this->imageType, 350, - $this->imageType, true, true); - $image_size = file_exists($image) ? filesize($image) / 1000 : false; + $this->fields_form = array( + 'tinymce' => true, + 'legend' => array( + 'title' => $this->l('Manufacturers'), + 'icon' => 'icon-certificate' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'col' => 4, + 'required' => true, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Short description'), + 'name' => 'short_description', + 'lang' => true, + 'cols' => 60, + 'rows' => 10, + 'autoload_rte' => 'rte', //Enable TinyMCE editor for short description + 'col' => 6, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Description'), + 'name' => 'description', + 'lang' => true, + 'cols' => 60, + 'rows' => 10, + 'col' => 6, + 'autoload_rte' => 'rte', //Enable TinyMCE editor for description + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'file', + 'label' => $this->l('Logo'), + 'name' => 'logo', + 'image' => $image_url ? $image_url : false, + 'size' => $image_size, + 'display_image' => true, + 'col' => 6, + 'hint' => $this->l('Upload a manufacturer logo from your computer.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Meta title'), + 'name' => 'meta_title', + 'lang' => true, + 'col' => 4, + 'hint' => $this->l('Forbidden characters:').' <>;=#{}' + ), + array( + 'type' => 'text', + 'label' => $this->l('Meta description'), + 'name' => 'meta_description', + 'lang' => true, + 'col' => 6, + 'hint' => $this->l('Forbidden characters:').' <>;=#{}' + ), + array( + 'type' => 'tags', + 'label' => $this->l('Meta keywords'), + 'name' => 'meta_keywords', + 'lang' => true, + 'col' => 6, + 'hint' => array( + $this->l('Forbidden characters:').' <>;=#{}', + $this->l('To add "tags," click inside the field, write something, and then press "Enter."') + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Enable'), + 'name' => 'active', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ) + ) + ) + ); - $this->fields_form = array( - 'tinymce' => true, - 'legend' => array( - 'title' => $this->l('Manufacturers'), - 'icon' => 'icon-certificate' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'col' => 4, - 'required' => true, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Short description'), - 'name' => 'short_description', - 'lang' => true, - 'cols' => 60, - 'rows' => 10, - 'autoload_rte' => 'rte', //Enable TinyMCE editor for short description - 'col' => 6, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Description'), - 'name' => 'description', - 'lang' => true, - 'cols' => 60, - 'rows' => 10, - 'col' => 6, - 'autoload_rte' => 'rte', //Enable TinyMCE editor for description - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'file', - 'label' => $this->l('Logo'), - 'name' => 'logo', - 'image' => $image_url ? $image_url : false, - 'size' => $image_size, - 'display_image' => true, - 'col' => 6, - 'hint' => $this->l('Upload a manufacturer logo from your computer.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Meta title'), - 'name' => 'meta_title', - 'lang' => true, - 'col' => 4, - 'hint' => $this->l('Forbidden characters:').' <>;=#{}' - ), - array( - 'type' => 'text', - 'label' => $this->l('Meta description'), - 'name' => 'meta_description', - 'lang' => true, - 'col' => 6, - 'hint' => $this->l('Forbidden characters:').' <>;=#{}' - ), - array( - 'type' => 'tags', - 'label' => $this->l('Meta keywords'), - 'name' => 'meta_keywords', - 'lang' => true, - 'col' => 6, - 'hint' => array( - $this->l('Forbidden characters:').' <>;=#{}', - $this->l('To add "tags," click inside the field, write something, and then press "Enter."') - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Enable'), - 'name' => 'active', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ) - ) - ) - ); + if (!($manufacturer = $this->loadObject(true))) { + return; + } - if (!($manufacturer = $this->loadObject(true))) - return; + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + $this->fields_form['submit'] = array( + 'title' => $this->l('Save') + ); - $this->fields_form['submit'] = array( - 'title' => $this->l('Save') - ); + foreach ($this->_languages as $language) { + $this->fields_value['short_description_'.$language['id_lang']] = htmlentities(stripslashes($this->getFieldValue( + $manufacturer, + 'short_description', + $language['id_lang'] + )), ENT_COMPAT, 'UTF-8'); - foreach ($this->_languages as $language) - { - $this->fields_value['short_description_'.$language['id_lang']] = htmlentities(stripslashes($this->getFieldValue( - $manufacturer, - 'short_description', - $language['id_lang'] - )), ENT_COMPAT, 'UTF-8'); + $this->fields_value['description_'.$language['id_lang']] = htmlentities(stripslashes($this->getFieldValue( + $manufacturer, + 'description', + $language['id_lang'] + )), ENT_COMPAT, 'UTF-8'); + } - $this->fields_value['description_'.$language['id_lang']] = htmlentities(stripslashes($this->getFieldValue( - $manufacturer, - 'description', - $language['id_lang'] - )), ENT_COMPAT, 'UTF-8'); - } + return parent::renderForm(); + } - return parent::renderForm(); - } + public function renderFormAddress() + { + // Change table and className for addresses + $this->table = 'address'; + $this->className = 'Address'; + $id_address = Tools::getValue('id_address'); - public function renderFormAddress() - { - // Change table and className for addresses - $this->table = 'address'; - $this->className = 'Address'; - $id_address = Tools::getValue('id_address'); + // Create Object Address + $address = new Address($id_address); - // Create Object Address - $address = new Address($id_address); + $res = $address->getFieldsRequiredDatabase(); + $required_fields = array(); + foreach ($res as $row) { + $required_fields[(int)$row['id_required_field']] = $row['field_name']; + } - $res = $address->getFieldsRequiredDatabase(); - $required_fields = array(); - foreach ($res as $row) - $required_fields[(int)$row['id_required_field']] = $row['field_name']; + $form = array( + 'legend' => array( + 'title' => $this->l('Addresses'), + 'icon' => 'icon-building' + ) + ); - $form = array( - 'legend' => array( - 'title' => $this->l('Addresses'), - 'icon' => 'icon-building' - ) - ); + if (!$address->id_manufacturer || !Manufacturer::manufacturerExists($address->id_manufacturer)) { + $form['input'][] = array( + 'type' => 'select', + 'label' => $this->l('Choose the manufacturer'), + 'name' => 'id_manufacturer', + 'options' => array( + 'query' => Manufacturer::getManufacturers(), + 'id' => 'id_manufacturer', + 'name' => 'name' + ) + ); + } else { + $form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('Manufacturer'), + 'name' => 'name', + 'col' => 4, + 'disabled' => true, + ); - if (!$address->id_manufacturer || !Manufacturer::manufacturerExists($address->id_manufacturer)) - $form['input'][] = array( - 'type' => 'select', - 'label' => $this->l('Choose the manufacturer'), - 'name' => 'id_manufacturer', - 'options' => array( - 'query' => Manufacturer::getManufacturers(), - 'id' => 'id_manufacturer', - 'name' => 'name' - ) - ); - else - { - $form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('Manufacturer'), - 'name' => 'name', - 'col' => 4, - 'disabled' => true, - ); + $form['input'][] = array( + 'type' => 'hidden', + 'name' => 'id_manufacturer' + ); + } - $form['input'][] = array( - 'type' => 'hidden', - 'name' => 'id_manufacturer' - ); - } + $form['input'][] = array( + 'type' => 'hidden', + 'name' => 'alias', + ); - $form['input'][] = array( - 'type' => 'hidden', - 'name' => 'alias', - ); + $form['input'][] = array( + 'type' => 'hidden', + 'name' => 'id_address', + ); - $form['input'][] = array( - 'type' => 'hidden', - 'name' => 'id_address', - ); + if (in_array('company', $required_fields)) { + $form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('Company'), + 'name' => 'company', + 'display' => in_array('company', $required_fields), + 'required' => in_array('company', $required_fields), + 'maxlength' => 16, + 'col' => 4, + 'hint' => $this->l('Company name for this supplier') + ); + } - if (in_array('company', $required_fields)) - $form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('Company'), - 'name' => 'company', - 'display' => in_array('company', $required_fields), - 'required' => in_array('company', $required_fields), - 'maxlength' => 16, - 'col' => 4, - 'hint' => $this->l('Company name for this supplier') - ); + $form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('Last name'), + 'name' => 'lastname', + 'required' => true, + 'col' => 4, + 'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()@#"�{}_$%:' + ); + $form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('First name'), + 'name' => 'firstname', + 'required' => true, + 'col' => 4, + 'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()@#"�{}_$%:' + ); + $form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('Address'), + 'name' => 'address1', + 'col' => 6, + 'required' => true, + ); + $form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('Address (2)'), + 'name' => 'address2', + 'col' => 6, + 'required' => in_array('address2', $required_fields) + ); + $form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('Zip/postal code'), + 'name' => 'postcode', + 'col' => 2, + 'required' => in_array('postcode', $required_fields) + ); + $form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('City'), + 'name' => 'city', + 'col' => 4, + 'required' => true, + ); + $form['input'][] = array( + 'type' => 'select', + 'label' => $this->l('Country'), + 'name' => 'id_country', + 'required' => false, + 'default_value' => (int)$this->context->country->id, + 'col' => 4, + 'options' => array( + 'query' => Country::getCountries($this->context->language->id), + 'id' => 'id_country', + 'name' => 'name', + ) + ); + $form['input'][] = array( + 'type' => 'select', + 'label' => $this->l('State'), + 'name' => 'id_state', + 'required' => false, + 'col' => 4, + 'options' => array( + 'query' => array(), + 'id' => 'id_state', + 'name' => 'name' + ) + ); + $form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('Home phone'), + 'name' => 'phone', + 'col' => 4, + 'required' => in_array('phone', $required_fields) + ); + $form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('Mobile phone'), + 'name' => 'phone_mobile', + 'col' => 4, + 'required' => in_array('phone_mobile', $required_fields) + ); + $form['input'][] = array( + 'type' => 'textarea', + 'label' => $this->l('Other'), + 'name' => 'other', + 'required' => false, + 'hint' => $this->l('Forbidden characters:').' <>;=#{}', + 'rows' => 2, + 'cols' => 10, + 'col' => 6, + ); + $form['submit'] = array( + 'title' => $this->l('Save'), + ); - $form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('Last name'), - 'name' => 'lastname', - 'required' => true, - 'col' => 4, - 'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()@#"�{}_$%:' - ); - $form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('First name'), - 'name' => 'firstname', - 'required' => true, - 'col' => 4, - 'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()@#"�{}_$%:' - ); - $form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('Address'), - 'name' => 'address1', - 'col' => 6, - 'required' => true, - ); - $form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('Address (2)'), - 'name' => 'address2', - 'col' => 6, - 'required' => in_array('address2', $required_fields) - ); - $form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('Zip/postal code'), - 'name' => 'postcode', - 'col' => 2, - 'required' => in_array('postcode', $required_fields) - ); - $form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('City'), - 'name' => 'city', - 'col' => 4, - 'required' => true, - ); - $form['input'][] = array( - 'type' => 'select', - 'label' => $this->l('Country'), - 'name' => 'id_country', - 'required' => false, - 'default_value' => (int)$this->context->country->id, - 'col' => 4, - 'options' => array( - 'query' => Country::getCountries($this->context->language->id), - 'id' => 'id_country', - 'name' => 'name', - ) - ); - $form['input'][] = array( - 'type' => 'select', - 'label' => $this->l('State'), - 'name' => 'id_state', - 'required' => false, - 'col' => 4, - 'options' => array( - 'query' => array(), - 'id' => 'id_state', - 'name' => 'name' - ) - ); - $form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('Home phone'), - 'name' => 'phone', - 'col' => 4, - 'required' => in_array('phone', $required_fields) - ); - $form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('Mobile phone'), - 'name' => 'phone_mobile', - 'col' => 4, - 'required' => in_array('phone_mobile', $required_fields) - ); - $form['input'][] = array( - 'type' => 'textarea', - 'label' => $this->l('Other'), - 'name' => 'other', - 'required' => false, - 'hint' => $this->l('Forbidden characters:').' <>;=#{}', - 'rows' => 2, - 'cols' => 10, - 'col' => 6, - ); - $form['submit'] = array( - 'title' => $this->l('Save'), - ); + $this->fields_value = array( + 'name' => Manufacturer::getNameById($address->id_manufacturer), + 'alias' => 'manufacturer', + 'id_country' => $address->id_country + ); - $this->fields_value = array( - 'name' => Manufacturer::getNameById($address->id_manufacturer), - 'alias' => 'manufacturer', - 'id_country' => $address->id_country - ); + $this->initToolbar(); + $this->fields_form[0]['form'] = $form; + $this->getlanguages(); + $helper = new HelperForm(); + $helper->show_cancel_button = true; - $this->initToolbar(); - $this->fields_form[0]['form'] = $form; - $this->getlanguages(); - $helper = new HelperForm(); - $helper->show_cancel_button = true; + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } + if (!Validate::isCleanHtml($back)) { + die(Tools::displayError()); + } - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; - if (!Validate::isCleanHtml($back)) - die(Tools::displayError()); + $helper->back_url = $back; + $helper->currentIndex = self::$currentIndex; + $helper->token = $this->token; + $helper->table = $this->table; + $helper->identifier = $this->identifier; + $helper->title = $this->l('Edit Addresses'); + $helper->id = $address->id; + $helper->toolbar_scroll = true; + $helper->languages = $this->_languages; + $helper->default_form_language = $this->default_form_language; + $helper->allow_employee_form_lang = $this->allow_employee_form_lang; + $helper->fields_value = $this->getFieldsValue($address); + $helper->toolbar_btn = $this->toolbar_btn; + $this->content .= $helper->generateForm($this->fields_form); + } - $helper->back_url = $back; - $helper->currentIndex = self::$currentIndex; - $helper->token = $this->token; - $helper->table = $this->table; - $helper->identifier = $this->identifier; - $helper->title = $this->l('Edit Addresses'); - $helper->id = $address->id; - $helper->toolbar_scroll = true; - $helper->languages = $this->_languages; - $helper->default_form_language = $this->default_form_language; - $helper->allow_employee_form_lang = $this->allow_employee_form_lang; - $helper->fields_value = $this->getFieldsValue($address); - $helper->toolbar_btn = $this->toolbar_btn; - $this->content .= $helper->generateForm($this->fields_form); - } + /** + * AdminController::initToolbar() override + * @see AdminController::initToolbar() + * + */ + public function initToolbar() + { + switch ($this->display) { + case 'editaddresses': + case 'addaddress': + $this->toolbar_btn['save'] = array( + 'href' => '#', + 'desc' => $this->l('Save') + ); - /** - * AdminController::initToolbar() override - * @see AdminController::initToolbar() - * - */ - public function initToolbar() - { - switch ($this->display) - { - case 'editaddresses': - case 'addaddress': - $this->toolbar_btn['save'] = array( - 'href' => '#', - 'desc' => $this->l('Save') - ); + // Default cancel button - like old back link + if (!isset($this->no_back) || $this->no_back == false) { + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } - // Default cancel button - like old back link - if (!isset($this->no_back) || $this->no_back == false) - { - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; + $this->toolbar_btn['cancel'] = array( + 'href' => $back, + 'desc' => $this->l('Cancel') + ); + } + break; - $this->toolbar_btn['cancel'] = array( - 'href' => $back, - 'desc' => $this->l('Cancel') - ); - } - break; + default: + parent::initToolbar(); - default: - parent::initToolbar(); + if ($this->can_import) { + $this->toolbar_btn['import'] = array( + 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=manufacturers', + 'desc' => $this->l('Import') + ); + } + } + } - if ($this->can_import) - $this->toolbar_btn['import'] = array( - 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=manufacturers', - 'desc' => $this->l('Import') - ); - } - } + public function renderView() + { + if (!($manufacturer = $this->loadObject())) { + return; + } - public function renderView() - { - if (!($manufacturer = $this->loadObject())) - return; + /** @var Manufacturer $manufacturer */ - /** @var Manufacturer $manufacturer */ + $this->toolbar_btn['new'] = array( + 'href' => $this->context->link->getAdminLink('AdminManufacturers').'&addaddress=1&id_manufacturer='.(int)$manufacturer->id, + 'desc' => $this->l('Add address') + ); - $this->toolbar_btn['new'] = array( - 'href' => $this->context->link->getAdminLink('AdminManufacturers').'&addaddress=1&id_manufacturer='.(int)$manufacturer->id, - 'desc' => $this->l('Add address') - ); + $this->toolbar_title = is_array($this->breadcrumbs) ? array_unique($this->breadcrumbs) : array($this->breadcrumbs); + $this->toolbar_title[] = $manufacturer->name; - $this->toolbar_title = is_array($this->breadcrumbs) ? array_unique($this->breadcrumbs) : array($this->breadcrumbs); - $this->toolbar_title[] = $manufacturer->name; + $addresses = $manufacturer->getAddresses($this->context->language->id); - $addresses = $manufacturer->getAddresses($this->context->language->id); + $products = $manufacturer->getProductsLite($this->context->language->id); + $total_product = count($products); + for ($i = 0; $i < $total_product; $i++) { + $products[$i] = new Product($products[$i]['id_product'], false, $this->context->language->id); + $products[$i]->loadStockData(); + /* Build attributes combinations */ + $combinations = $products[$i]->getAttributeCombinations($this->context->language->id); + foreach ($combinations as $k => $combination) { + $comb_array[$combination['id_product_attribute']]['reference'] = $combination['reference']; + $comb_array[$combination['id_product_attribute']]['ean13'] = $combination['ean13']; + $comb_array[$combination['id_product_attribute']]['upc'] = $combination['upc']; + $comb_array[$combination['id_product_attribute']]['quantity'] = $combination['quantity']; + $comb_array[$combination['id_product_attribute']]['attributes'][] = array( + $combination['group_name'], + $combination['attribute_name'], + $combination['id_attribute'] + ); + } - $products = $manufacturer->getProductsLite($this->context->language->id); - $total_product = count($products); - for ($i = 0; $i < $total_product; $i++) - { - $products[$i] = new Product($products[$i]['id_product'], false, $this->context->language->id); - $products[$i]->loadStockData(); - /* Build attributes combinations */ - $combinations = $products[$i]->getAttributeCombinations($this->context->language->id); - foreach ($combinations as $k => $combination) - { - $comb_array[$combination['id_product_attribute']]['reference'] = $combination['reference']; - $comb_array[$combination['id_product_attribute']]['ean13'] = $combination['ean13']; - $comb_array[$combination['id_product_attribute']]['upc'] = $combination['upc']; - $comb_array[$combination['id_product_attribute']]['quantity'] = $combination['quantity']; - $comb_array[$combination['id_product_attribute']]['attributes'][] = array( - $combination['group_name'], - $combination['attribute_name'], - $combination['id_attribute'] - ); - } + if (isset($comb_array)) { + foreach ($comb_array as $key => $product_attribute) { + $list = ''; + foreach ($product_attribute['attributes'] as $attribute) { + $list .= $attribute[0].' - '.$attribute[1].', '; + } + $comb_array[$key]['attributes'] = rtrim($list, ', '); + } + isset($comb_array) ? $products[$i]->combination = $comb_array : ''; + unset($comb_array); + } + } - if (isset($comb_array)) - { - foreach ($comb_array as $key => $product_attribute) - { - $list = ''; - foreach ($product_attribute['attributes'] as $attribute) - $list .= $attribute[0].' - '.$attribute[1].', '; - $comb_array[$key]['attributes'] = rtrim($list, ', '); - } - isset($comb_array) ? $products[$i]->combination = $comb_array : ''; - unset($comb_array); - } - } + $this->tpl_view_vars = array( + 'manufacturer' => $manufacturer, + 'addresses' => $addresses, + 'products' => $products, + 'stock_management' => Configuration::get('PS_STOCK_MANAGEMENT'), + 'shopContext' => Shop::getContext(), + ); - $this->tpl_view_vars = array( - 'manufacturer' => $manufacturer, - 'addresses' => $addresses, - 'products' => $products, - 'stock_management' => Configuration::get('PS_STOCK_MANAGEMENT'), - 'shopContext' => Shop::getContext(), - ); + return parent::renderView(); + } - return parent::renderView(); - } + public function initContent() + { + $this->initTabModuleList(); + // toolbar (save, cancel, new, ..) + $this->initToolbar(); + $this->initPageHeaderToolbar(); + if ($this->display == 'editaddresses' || $this->display == 'addaddress') { + $this->content .= $this->renderFormAddress(); + } elseif ($this->display == 'edit' || $this->display == 'add') { + if (!$this->loadObject(true)) { + return; + } + $this->content .= $this->renderForm(); + } elseif ($this->display == 'view') { + // Some controllers use the view action without an object + if ($this->className) { + $this->loadObject(true); + } + $this->content .= $this->renderView(); + } elseif (!$this->ajax) { + $this->content .= $this->renderList(); + $this->content .= $this->renderOptions(); + } - public function initContent() - { - $this->initTabModuleList(); - // toolbar (save, cancel, new, ..) - $this->initToolbar(); - $this->initPageHeaderToolbar(); - if ($this->display == 'editaddresses' || $this->display == 'addaddress') - $this->content .= $this->renderFormAddress(); - elseif ($this->display == 'edit' || $this->display == 'add') - { - if (!$this->loadObject(true)) - return; - $this->content .= $this->renderForm(); - } - elseif ($this->display == 'view') - { - // Some controllers use the view action without an object - if ($this->className) - $this->loadObject(true); - $this->content .= $this->renderView(); - } - elseif (!$this->ajax) - { - $this->content .= $this->renderList(); - $this->content .= $this->renderOptions(); - } + $this->context->smarty->assign(array( + 'content' => $this->content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } - $this->context->smarty->assign(array( - 'content' => $this->content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } + /** + * AdminController::init() override + * @see AdminController::init() + */ + public function init() + { + parent::init(); - /** - * AdminController::init() override - * @see AdminController::init() - */ - public function init() - { - parent::init(); + if (Tools::isSubmit('editaddresses')) { + $this->display = 'editaddresses'; + } elseif (Tools::isSubmit('updateaddress')) { + $this->display = 'editaddresses'; + } elseif (Tools::isSubmit('addaddress')) { + $this->display = 'addaddress'; + } elseif (Tools::isSubmit('submitAddaddress')) { + $this->action = 'save'; + } elseif (Tools::isSubmit('deleteaddress')) { + $this->action = 'delete'; + } + } - if (Tools::isSubmit('editaddresses')) - $this->display = 'editaddresses'; - elseif (Tools::isSubmit('updateaddress')) - $this->display = 'editaddresses'; - elseif (Tools::isSubmit('addaddress')) - $this->display = 'addaddress'; - elseif (Tools::isSubmit('submitAddaddress')) - $this->action = 'save'; - elseif (Tools::isSubmit('deleteaddress')) - $this->action = 'delete'; - } + public function initProcess() + { + if (Tools::isSubmit('submitAddaddress') || Tools::isSubmit('deleteaddress') || Tools::isSubmit('submitBulkdeleteaddress') || Tools::isSubmit('exportaddress')) { + $this->table = 'address'; + $this->className = 'Address'; + $this->identifier = 'id_address'; + $this->deleted = true; + $this->fields_list = $this->getAddressFieldsList(); + } + parent::initProcess(); + } - public function initProcess() - { - if (Tools::isSubmit('submitAddaddress') || Tools::isSubmit('deleteaddress') || Tools::isSubmit('submitBulkdeleteaddress') || Tools::isSubmit('exportaddress')) - { - $this->table = 'address'; - $this->className = 'Address'; - $this->identifier = 'id_address'; - $this->deleted = true; - $this->fields_list = $this->getAddressFieldsList(); - } - parent::initProcess(); - } + protected function afterImageUpload() + { + $res = true; + $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); - protected function afterImageUpload() - { - $res = true; - $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); + /* Generate image with differents size */ + if (($id_manufacturer = (int)Tools::getValue('id_manufacturer')) && + isset($_FILES) && + count($_FILES) && + file_exists(_PS_MANU_IMG_DIR_.$id_manufacturer.'.jpg')) { + $images_types = ImageType::getImagesTypes('manufacturers'); + foreach ($images_types as $k => $image_type) { + $res &= ImageManager::resize( + _PS_MANU_IMG_DIR_.$id_manufacturer.'.jpg', + _PS_MANU_IMG_DIR_.$id_manufacturer.'-'.stripslashes($image_type['name']).'.jpg', + (int)$image_type['width'], + (int)$image_type['height'] + ); - /* Generate image with differents size */ - if (($id_manufacturer = (int)Tools::getValue('id_manufacturer')) && - isset($_FILES) && - count($_FILES) && - file_exists(_PS_MANU_IMG_DIR_.$id_manufacturer.'.jpg')) - { - $images_types = ImageType::getImagesTypes('manufacturers'); - foreach ($images_types as $k => $image_type) - { - $res &= ImageManager::resize( - _PS_MANU_IMG_DIR_.$id_manufacturer.'.jpg', - _PS_MANU_IMG_DIR_.$id_manufacturer.'-'.stripslashes($image_type['name']).'.jpg', - (int)$image_type['width'], - (int)$image_type['height'] - ); + if ($generate_hight_dpi_images) { + $res &= ImageManager::resize( + _PS_MANU_IMG_DIR_.$id_manufacturer.'.jpg', + _PS_MANU_IMG_DIR_.$id_manufacturer.'-'.stripslashes($image_type['name']).'2x.jpg', + (int)$image_type['width']*2, + (int)$image_type['height']*2 + ); + } + } - if ($generate_hight_dpi_images) - $res &= ImageManager::resize( - _PS_MANU_IMG_DIR_.$id_manufacturer.'.jpg', - _PS_MANU_IMG_DIR_.$id_manufacturer.'-'.stripslashes($image_type['name']).'2x.jpg', - (int)$image_type['width']*2, - (int)$image_type['height']*2 - ); - } + $current_logo_file = _PS_TMP_IMG_DIR_.'manufacturer_mini_'.$id_manufacturer.'_'.$this->context->shop->id.'.jpg'; - $current_logo_file = _PS_TMP_IMG_DIR_.'manufacturer_mini_'.$id_manufacturer.'_'.$this->context->shop->id.'.jpg'; + if ($res && file_exists($current_logo_file)) { + unlink($current_logo_file); + } + } - if ($res && file_exists($current_logo_file)) - unlink($current_logo_file); - } + if (!$res) { + $this->errors[] = Tools::displayError('Unable to resize one or more of your pictures.'); + } - if (!$res) - $this->errors[] = Tools::displayError('Unable to resize one or more of your pictures.'); + return $res; + } - return $res; - } + protected function beforeDelete($object) + { + return true; + } - protected function beforeDelete($object) - { - return true; - } + public function processSave() + { + if (Tools::isSubmit('submitAddaddress')) { + $this->display = 'editaddresses'; + } - public function processSave() - { - if (Tools::isSubmit('submitAddaddress')) - $this->display = 'editaddresses'; - - return parent::processSave(); - } + return parent::processSave(); + } } diff --git a/controllers/admin/AdminMarketingController.php b/controllers/admin/AdminMarketingController.php index 7d906ee8..539c5913 100644 --- a/controllers/admin/AdminMarketingController.php +++ b/controllers/admin/AdminMarketingController.php @@ -26,40 +26,39 @@ class AdminMarketingControllerCore extends AdminController { + public function __construct() + { + $this->bootstrap = true; + parent::__construct(); + } - public function __construct() - { - $this->bootstrap = true; - parent::__construct(); - } + public function initContent() + { + $this->display = 'view'; + return parent::initContent(); + } + + public function initToolbarTitle() + { + $this->toolbar_title = array_unique($this->breadcrumbs); + } - public function initContent() - { - $this->display = 'view'; - return parent::initContent(); - } - - public function initToolbarTitle() - { - $this->toolbar_title = array_unique($this->breadcrumbs); - } - - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); - $this->page_header_toolbar_btn = array(); - } - - public function initToolbar() - { - return false; - } - - public function renderView() - { - $this->tpl_view_vars = array( - 'modules_list' => $this->renderModulesList(), - ); - return parent::renderView(); - } + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); + $this->page_header_toolbar_btn = array(); + } + + public function initToolbar() + { + return false; + } + + public function renderView() + { + $this->tpl_view_vars = array( + 'modules_list' => $this->renderModulesList(), + ); + return parent::renderView(); + } } diff --git a/controllers/admin/AdminMetaController.php b/controllers/admin/AdminMetaController.php index c8853932..dc80c35b 100644 --- a/controllers/admin/AdminMetaController.php +++ b/controllers/admin/AdminMetaController.php @@ -29,778 +29,777 @@ */ class AdminMetaControllerCore extends AdminController { - public $table = 'meta'; - public $className = 'Meta'; - public $lang = true; - - /** @var ShopUrl */ - protected $url = false; - protected $toolbar_scroll = false; - - public function __construct() - { - $this->table = 'meta'; - $this->className = 'Meta'; - - $this->bootstrap = true; - $this->identifier_name = 'page'; - $this->ht_file = _PS_ROOT_DIR_.'/.htaccess'; - $this->rb_file = _PS_ROOT_DIR_.'/robots.txt'; - $this->rb_data = $this->getRobotsContent(); - - $this->explicitSelect = true; - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); - - $this->fields_list = array( - 'id_meta' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'page' => array('title' => $this->l('Page')), - 'title' => array('title' => $this->l('Page title')), - 'url_rewrite' => array('title' => $this->l('Friendly URL')) - ); - $this->_where = ' AND a.configurable = 1'; - $this->_group = 'GROUP BY a.id_meta'; - - parent::__construct(); - - $this->sm_file = _PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$this->context->shop->id.'_index_sitemap.xml'; - // Options to generate friendly urls - $mod_rewrite = Tools::modRewriteActive(); - $general_fields = array( - 'PS_REWRITING_SETTINGS' => array( - 'title' => $this->l('Friendly URL'), - 'hint' => ($mod_rewrite ? $this->l('Enable this option only if your server allows URL rewriting (recommended).') : ''), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'desc' => (!$mod_rewrite ? $this->l('URL rewriting (mod_rewrite) is not active on your server, or it is not possible to check your server configuration. If you want to use Friendly URLs, you must activate this mod.') : '') - ), - 'PS_ALLOW_ACCENTED_CHARS_URL' => array( - 'title' => $this->l('Accented URL'), - 'hint' => $this->l('Enable this option if you want to allow accented characters in your friendly URLs.').' '.$this->l('You should only activate this option if you are using non-latin characters ; for all the latin charsets, your SEO will be better without this option.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_CANONICAL_REDIRECT' => array( - 'title' => $this->l('Redirect to the canonical URL'), - 'validation' => 'isUnsignedInt', - 'cast' => 'intval', - 'type' => 'select', - 'list' => array( - array('value' => 0, 'name' => $this->l('No redirection (you may have duplicate content issues)')), - array('value' => 1, 'name' => $this->l('302 Moved Temporarily (recommended while setting up your store)')), - array('value' => 2, 'name' => $this->l('301 Moved Permanently (recommended once you have gone live)')) - ), - 'identifier' => 'value', - ), - ); - - $url_description = ''; - if (!defined('_PS_HOST_MODE_')) - { - if ($this->checkConfiguration($this->ht_file)) - { - $general_fields['PS_HTACCESS_DISABLE_MULTIVIEWS'] = array( - 'title' => $this->l('Disable Apache\'s MultiViews option'), - 'hint' => $this->l('Enable this option only if you have problems with URL rewriting.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - ); - - $general_fields['PS_HTACCESS_DISABLE_MODSEC'] = array( - 'title' => $this->l('Disable Apache\'s mod_security module'), - 'hint' => $this->l('Some of PrestaShop\'s features might not work correctly with a specific configuration of Apache\'s mod_security module. We recommend to turn it off.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - ); - } - else - { - $url_description = $this->l('Before you can use this tool, you need to:'); - $url_description .= $this->l('1) Create a blank .htaccess file in your root directory.'); - $url_description .= $this->l('2) Give it write permissions (CHMOD 666 on Unix system).'); - } - } - - // Options to generate robot.txt - $robots_description = $this->l('Your robots.txt file MUST be in your website\'s root directory and nowhere else (e.g. http://www.example.com/robots.txt).'); - if ($this->checkConfiguration($this->rb_file)) - { - $robots_description .= $this->l('Generate your "robots.txt" file by clicking on the following button (this will erase the old robots.txt file)'); - $robots_submit = array('name' => 'submitRobots', 'title' => $this->l('Generate robots.txt file')); - } - else - { - $robots_description .= $this->l('Before you can use this tool, you need to:'); - $robots_description .= $this->l('1) Create a blank robots.txt file in your root directory.'); - $robots_description .= $this->l('2) Give it write permissions (CHMOD 666 on Unix system).'); - } - - $robots_options = array( - 'title' => $this->l('Robots file generation'), - 'description' => $robots_description, - ); - - if (isset($robots_submit)) - $robots_options['submit'] = $robots_submit; - - if (!defined('_PS_HOST_MODE_')) - { - // Options for shop URL if multishop is disabled - $shop_url_options = array( - 'title' => $this->l('Set shop URL'), - 'fields' => array(), - ); - - if (!Shop::isFeatureActive()) - { - $this->url = ShopUrl::getShopUrls($this->context->shop->id)->where('main', '=', 1)->getFirst(); - if ($this->url) - { - $shop_url_options['description'] = $this->l('Here you can set the URL for your shop. If you migrate your shop to a new URL, remember to change the values below.'); - $shop_url_options['fields'] = array( - 'domain' => array( - 'title' => $this->l('Shop domain'), - 'validation' => 'isString', - 'type' => 'text', - 'defaultValue' => $this->url->domain, - ), - 'domain_ssl' => array( - 'title' => $this->l('SSL domain'), - 'validation' => 'isString', - 'type' => 'text', - 'defaultValue' => $this->url->domain_ssl, - ), - 'uri' => array( - 'title' => $this->l('Base URI'), - 'validation' => 'isString', - 'type' => 'text', - 'defaultValue' => $this->url->physical_uri, - ) - ); - $shop_url_options['submit'] = array('title' => $this->l('Save')); - } - } - else - $shop_url_options['description'] = $this->l('The multistore option is enabled. If you want to change the URL of your shop, you must go to the "Multistore" page under the "Advanced Parameters" menu.'); - } - - // List of options - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Set up URLs'), - 'description' => $url_description, - 'fields' => $general_fields, - 'submit' => array('title' => $this->l('Save')) - ) - ); - - if (!defined('_PS_HOST_MODE_')) - $this->fields_options['shop_url'] = $shop_url_options; - else - $this->fields_options['manage_domain_name'] = array( - 'title' => $this->l('Manage domain name'), - 'description' => $this->l('You can search for a new domain name or add a domain name that you already own. You will be redirected to your PrestaShop account.'), - 'buttons' => array( - array( - 'title' => $this->l('Add a domain name'), - 'href' => 'https://www.prestashop.com/cloud/', - 'class' => 'pull-right', 'icon' => 'process-icon-new', - 'js' => 'return !window.open(this.href);' - ) - ) - ); - - // Add display route options to options form - if (Configuration::get('PS_REWRITING_SETTINGS') || Tools::getValue('PS_REWRITING_SETTINGS')) - { - if (Configuration::get('PS_REWRITING_SETTINGS')) - $this->addAllRouteFields(); - $this->fields_options['routes']['title'] = $this->l('Schema of URLs'); - $this->fields_options['routes']['description'] = $this->l('This section enables you to change the default pattern of your links. In order to use this functionality, PrestaShop\'s "Friendly URL" option must be enabled, and Apache\'s URL rewriting module (mod_rewrite) must be activated on your web server.').'<br />'.$this->l('There are several available keywords for each route listed below; note that keywords with * are required!').'<br />'.$this->l('To add a keyword in your URL, use the {keyword} syntax. If the keyword is not empty, you can add text before or after the keyword with syntax {prepend:keyword:append}. For example {-hey-:meta_title} will add "-hey-my-title" in the URL if the meta title is set.'); - $this->fields_options['routes']['submit'] = array('title' => $this->l('Save')); - } - - $this->fields_options['robots'] = $robots_options; - } - - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_meta'] = array( - 'href' => self::$currentIndex.'&addmeta&token='.$this->token, - 'desc' => $this->l('Add a new page', null, null, false), - 'icon' => 'process-icon-new' - ); - - parent::initPageHeaderToolbar(); - } - - public function initProcess() - { - parent::initProcess(); - // This is a composite page, we don't want the "options" display mode - if ($this->display == 'options') - $this->display = ''; - } - - public function setMedia() - { - parent::setMedia(); - $this->addJqueryUi('ui.widget'); - $this->addJqueryPlugin('tagify'); - } - - public function addFieldRoute($route_id, $title) - { - $keywords = array(); - foreach (Dispatcher::getInstance()->default_routes[$route_id]['keywords'] as $keyword => $data) - $keywords[] = ((isset($data['param'])) ? '<span class="red">'.$keyword.'*</span>' : $keyword); - - $this->fields_options['routes']['fields']['PS_ROUTE_'.$route_id] = array( - 'title' => $title, - 'desc' => sprintf($this->l('Keywords: %s'), implode(', ', $keywords)), - 'validation' => 'isString', - 'type' => 'text', - 'size' => 70, - 'defaultValue' => Dispatcher::getInstance()->default_routes[$route_id]['rule'], - ); - } - - public function renderForm() - { - $files = Meta::getPages(true, ($this->object->page ? $this->object->page : false)); - - $is_index = false; - if (is_object($this->object) && is_array($this->object->url_rewrite) && count($this->object->url_rewrite)) - foreach ($this->object->url_rewrite as $rewrite) - if ($is_index != true) - $is_index = ($this->object->page == 'index' && empty($rewrite)) ? true : false; - - $pages = array( - 'common' => array( - 'name' => $this->l('Default pages'), - 'query' => array(), - ), - 'module' => array( - 'name' => $this->l('Modules pages'), - 'query' => array(), - ), - ); - - foreach ($files as $name => $file) - { - $k = (preg_match('#^module-#', $file)) ? 'module' : 'common'; - $pages[$k]['query'][] = array( - 'id' => $file, - 'page' => $name, - ); - } - - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Meta tags'), - 'icon' => 'icon-tags' - ), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'id_meta', - ), - array( - 'type' => 'select', - 'label' => $this->l('Page'), - 'name' => 'page', - - 'options' => array( - 'optiongroup' => array( - 'label' => 'name', - 'query' => $pages, - ), - 'options' => array( - 'id' => 'id', - 'name' => 'page', - 'query' => 'query', - ), - ), - 'hint' => $this->l('Name of the related page.'), - 'required' => true, - 'empty_message' => '<p>'.$this->l('There is no page available!').'</p>', - ), - array( - 'type' => 'text', - 'label' => $this->l('Page title'), - 'name' => 'title', - 'lang' => true, - 'hint' => array( - $this->l('Title of this page.'), - $this->l('Invalid characters:').' <>;=#{}' - ) - ), - array( - 'type' => 'text', - 'label' => $this->l('Meta description'), - 'name' => 'description', - 'lang' => true, - 'hint' => array( - $this->l('A short description of your shop.'), - $this->l('Invalid characters:').' <>;=#{}' - ) - ), - array( - 'type' => 'tags', - 'label' => $this->l('Meta keywords'), - 'name' => 'keywords', - 'lang' => true, - 'hint' => array( - $this->l('List of keywords for search engines.'), - $this->l('To add tags, click in the field, write something, and then press the "Enter" key.'), - $this->l('Invalid characters:').' <>;=#{}' - ) - ), - array( - 'type' => 'text', - 'label' => $this->l('Rewritten URL'), - 'name' => 'url_rewrite', - 'lang' => true, - 'required' => true, - 'disabled' => (bool)$is_index, - 'hint' => array( - $this->l('For instance, "contacts" for http://example.com/shop/contacts to redirect to http://example.com/shop/contact-form.php'), - $this->l('Only letters and hyphens are allowed.'), - ) - ), - ), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); - return parent::renderForm(); - } - - public function postProcess() - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_ && Tools::isSubmit('submitOptionsmeta') - && (Tools::getValue('domain') != Configuration::get('PS_SHOP_DOMAIN') || Tools::getValue('domain_ssl') != Configuration::get('PS_SHOP_DOMAIN_SSL'))) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } - - if (Tools::isSubmit('submitAddmeta')) - { - $default_language = Configuration::get('PS_LANG_DEFAULT'); - if (Tools::getValue('page') != 'index') - { - $defaultLangIsValidated = Validate::isLinkRewrite(Tools::getValue('url_rewrite_'.$default_language)); - $englishLangIsValidated = Validate::isLinkRewrite(Tools::getValue('url_rewrite_1')); - } - else - { // index.php can have empty rewrite rule - $defaultLangIsValidated = !Tools::getValue('url_rewrite_'.$default_language) || Validate::isLinkRewrite(Tools::getValue('url_rewrite_'.$default_language)); - $englishLangIsValidated = !Tools::getValue('url_rewrite_1') || Validate::isLinkRewrite(Tools::getValue('url_rewrite_1')); - } - - if (!$defaultLangIsValidated && !$englishLangIsValidated) - { - $this->errors[] = Tools::displayError('The URL rewrite field must be filled in either the default or English language.'); - return false; - } - - foreach (Language::getIDs(false) as $id_lang) - { - $current = Tools::getValue('url_rewrite_'.$id_lang); - if (strlen($current) == 0) - // Prioritize default language first - if ($defaultLangIsValidated) - $_POST['url_rewrite_'.$id_lang] = Tools::getValue('url_rewrite_'.$default_language); - else - $_POST['url_rewrite_'.$id_lang] = Tools::getValue('url_rewrite_1'); - } - - Hook::exec('actionAdminMetaSave'); - } - elseif (Tools::isSubmit('submitRobots')) - $this->generateRobotsFile(); - - if (Tools::isSubmit('PS_ROUTE_product_rule')) - Tools::clearCache($this->context->smarty); - - if (Tools::isSubmit('deletemeta') && (int)Tools::getValue('id_meta') > 0) - Db::getInstance()->delete('theme_meta', 'id_meta='.(int)Tools::getValue('id_meta')); - - $ret = parent::postProcess(); - - if (Tools::isSubmit('submitAddmeta') && Validate::isLoadedObject($ret)) - { - /** @var Theme $ret */ - $themes = Theme::getThemes(); - $theme_meta_value = array(); - foreach ($themes as $theme) - { - /** @var Theme $theme */ - $theme_meta_value[] = array( - 'id_theme' => (int)$theme->id, - 'id_meta' => (int)$ret->id, - 'left_column' => (int)$theme->default_left_column, - 'right_column' => (int)$theme->default_right_column - ); - - } - if (count($theme_meta_value) > 0) - Db::getInstance()->insert('theme_meta', $theme_meta_value, false, true, DB::INSERT_IGNORE); - } - - return $ret; - } - - public function generateRobotsFile() - { - if (!$write_fd = @fopen($this->rb_file, 'w')) - $this->errors[] = sprintf(Tools::displayError('Cannot write into file: %s. Please check write permissions.'), $this->rb_file); - else - { - Hook::exec('actionAdminMetaBeforeWriteRobotsFile', array( - 'rb_data' => &$this->rb_data - )); - - // PS Comments - fwrite($write_fd, "# robots.txt automaticaly generated by PrestaShop e-commerce open-source solution\n"); - fwrite($write_fd, "# http://www.prestashop.com - http://www.prestashop.com/forums\n"); - fwrite($write_fd, "# This file is to prevent the crawling and indexing of certain parts\n"); - fwrite($write_fd, "# of your site by web crawlers and spiders run by sites like Yahoo!\n"); - fwrite($write_fd, "# and Google. By telling these \"robots\" where not to go on your site,\n"); - fwrite($write_fd, "# you save bandwidth and server resources.\n"); - fwrite($write_fd, "# For more information about the robots.txt standard, see:\n"); - fwrite($write_fd, "# http://www.robotstxt.org/robotstxt.html\n"); - - // User-Agent - fwrite($write_fd, "User-agent: *\n"); - - // Private pages - if (count($this->rb_data['GB'])) - { - fwrite($write_fd, "# Private pages\n"); - foreach ($this->rb_data['GB'] as $gb) - fwrite($write_fd, 'Disallow: /*'.$gb."\n"); - } - - // Directories - if (count($this->rb_data['Directories'])) - { - fwrite($write_fd, "# Directories\n"); - foreach ($this->rb_data['Directories'] as $dir) - fwrite($write_fd, 'Disallow: */'.$dir."\n"); - } - - // Files - if (count($this->rb_data['Files'])) - { - $language_ids = Language::getIDs(); - fwrite($write_fd, "# Files\n"); - foreach ($this->rb_data['Files'] as $iso_code => $files) - foreach ($files as $file) - if (!empty($language_ids)) - fwrite($write_fd, 'Disallow: /*'.$iso_code.'/'.$file."\n"); - else - fwrite($write_fd, 'Disallow: /'.$file."\n"); - } - - // Sitemap - if (file_exists($this->sm_file) && filesize($this->sm_file)) - { - fwrite($write_fd, "# Sitemap\n"); - $sitemap_filename = basename($this->sm_file); - fwrite($write_fd, 'Sitemap: '.(Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://').$_SERVER['SERVER_NAME'] - .__PS_BASE_URI__.$sitemap_filename."\n"); - } - - Hook::exec('actionAdminMetaAfterWriteRobotsFile', array( - 'rb_data' => $this->rb_data, - 'write_fd' => &$write_fd - )); - - fclose($write_fd); - - $this->redirect_after = self::$currentIndex.'&conf=4&token='.$this->token; - } - } - - public function getList($id_lang, $orderBy = null, $orderWay = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $orderBy, $orderWay, $start, $limit, Context::getContext()->shop->id); - } - - public function renderList() - { - if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) - $this->displayInformation($this->l('You can only display the page list in a shop context.')); - else - return parent::renderList(); - } - - /** - * Validate route syntax and save it in configuration - * - * @param string $route_id - */ - public function checkAndUpdateRoute($route_id) - { - $default_routes = Dispatcher::getInstance()->default_routes; - if (!isset($default_routes[$route_id])) - return; - - $rule = Tools::getValue('PS_ROUTE_'.$route_id); - if (!Validate::isRoutePattern($rule)) - $this->errors[] = sprintf('The route %s is not valid', htmlspecialchars($rule)); - else - { - if (!$rule || $rule == $default_routes[$route_id]['rule']) - { - Configuration::updateValue('PS_ROUTE_'.$route_id, ''); - return; - } - - $errors = array(); - if (!Dispatcher::getInstance()->validateRoute($route_id, $rule, $errors)) - { - foreach ($errors as $error) - $this->errors[] = sprintf('Keyword "{%1$s}" required for route "%2$s" (rule: "%3$s")', $error, $route_id, htmlspecialchars($rule)); - } - else - Configuration::updateValue('PS_ROUTE_'.$route_id, $rule); - } - } - - /** - * Called when PS_REWRITING_SETTINGS option is saved - */ - public function updateOptionPsRewritingSettings() - { - Configuration::updateValue('PS_REWRITING_SETTINGS', (int)Tools::getValue('PS_REWRITING_SETTINGS')); - - $this->updateOptionDomain(Tools::getValue('domain')); - $this->updateOptionDomainSsl(Tools::getValue('domain_ssl')); - - if (Tools::getIsset('uri')) - $this->updateOptionUri(Tools::getValue('uri')); - - if (Tools::generateHtaccess($this->ht_file, null, null, '', Tools::getValue('PS_HTACCESS_DISABLE_MULTIVIEWS'), false, Tools::getValue('PS_HTACCESS_DISABLE_MODSEC'))) - { - Tools::enableCache(); - Tools::clearCache($this->context->smarty); - Tools::restoreCacheSettings(); - } - else - { - Configuration::updateValue('PS_REWRITING_SETTINGS', 0); - // Message copied/pasted from the information tip - $message = $this->l('Before being able to use this tool, you need to:'); - $message .= '<br />- '.$this->l('Create a blank .htaccess in your root directory.'); - $message .= '<br />- '.$this->l('Give it write permissions (CHMOD 666 on Unix system).'); - $this->errors[] = $message; - } - } - - public function updateOptionPsRouteProductRule() - { - $this->checkAndUpdateRoute('product_rule'); - } - - public function updateOptionPsRouteCategoryRule() - { - $this->checkAndUpdateRoute('category_rule'); - } - - public function updateOptionPsRouteLayeredRule() - { - $this->checkAndUpdateRoute('layered_rule'); - } - - public function updateOptionPsRouteSupplierRule() - { - $this->checkAndUpdateRoute('supplier_rule'); - } - - public function updateOptionPsRouteManufacturerRule() - { - $this->checkAndUpdateRoute('manufacturer_rule'); - } - - public function updateOptionPsRouteCmsRule() - { - $this->checkAndUpdateRoute('cms_rule'); - } - - public function updateOptionPsRouteCmsCategoryRule() - { - $this->checkAndUpdateRoute('cms_category_rule'); - } - - /** - * Update shop domain (for mono shop) - * - * @param string $value - * - * @throws PrestaShopException - */ - public function updateOptionDomain($value) - { - if (!Shop::isFeatureActive() && $this->url && $this->url->domain != $value) - { - if (Validate::isCleanHtml($value)) - { - $this->url->domain = $value; - $this->url->update(); - Configuration::updateGlobalValue('PS_SHOP_DOMAIN', $value); - } - else - $this->errors[] = Tools::displayError('This domain is not valid.'); - } - } - - /** - * Update shop SSL domain (for mono shop) - * - * @param string $value - * - * @throws PrestaShopException - */ - public function updateOptionDomainSsl($value) - { - if (!Shop::isFeatureActive() && $this->url && $this->url->domain_ssl != $value) - { - if (Validate::isCleanHtml($value)) - { - $this->url->domain_ssl = $value; - $this->url->update(); - Configuration::updateGlobalValue('PS_SHOP_DOMAIN_SSL', $value); - } - else - $this->errors[] = Tools::displayError('The SSL domain is not valid.'); - } - } - - /** - * Update shop physical uri for mono shop) - * - * @param string $value - * - * @throws PrestaShopException - */ - public function updateOptionUri($value) - { - if (!Shop::isFeatureActive() && $this->url && $this->url->physical_uri != $value) - { - $this->url->physical_uri = $value; - $this->url->update(); - } - } - - /** - * Function used to render the options for this controller - */ - public function renderOptions() - { - // If friendly url is not active, do not display custom routes form - if (Configuration::get('PS_REWRITING_SETTINGS')) - $this->addAllRouteFields(); - - if ($this->fields_options && is_array($this->fields_options)) - { - $helper = new HelperOptions($this); - $this->setHelperDisplay($helper); - $helper->toolbar_scroll = true; - $helper->toolbar_btn = array( - 'save' => array( - 'href' => '#', - 'desc' => $this->l('Save') - ) - ); - $helper->id = $this->id; - $helper->tpl_vars = $this->tpl_option_vars; - $options = $helper->generateOptions($this->fields_options); - - return $options; - } - } - - /** - * Add all custom route fields to the options form - */ - public function addAllRouteFields() - { - $this->addFieldRoute('product_rule', $this->l('Route to products')); - $this->addFieldRoute('category_rule', $this->l('Route to category')); - $this->addFieldRoute('layered_rule', $this->l('Route to category which has the "selected_filter" attribute for the "Layered Navigation" (blocklayered) module')); - $this->addFieldRoute('supplier_rule', $this->l('Route to supplier')); - $this->addFieldRoute('manufacturer_rule', $this->l('Route to manufacturer')); - $this->addFieldRoute('cms_rule', $this->l('Route to CMS page')); - $this->addFieldRoute('cms_category_rule', $this->l('Route to CMS category')); - $this->addFieldRoute('module', $this->l('Route to modules')); - } - - /** - * Check if a file is writable - * - * @param string $file - * @return bool - */ - public function checkConfiguration($file) - { - if (file_exists($file)) - return is_writable($file); - return is_writable(dirname($file)); - } - - public function getRobotsContent() - { - $tab = array(); - - // Directories - $tab['Directories'] = array('classes/', 'config/', 'download/', 'mails/', 'modules/', 'translations/', 'tools/'); - - // Files - $disallow_controllers = array( - 'addresses', 'address', 'authentication', 'cart', 'discount', 'footer', - 'get-file', 'header', 'history', 'identity', 'images.inc', 'init', 'my-account', 'order', 'order-opc', - 'order-slip', 'order-detail', 'order-follow', 'order-return', 'order-confirmation', 'pagination', 'password', - 'pdf-invoice', 'pdf-order-return', 'pdf-order-slip', 'product-sort', 'search', 'statistics','attachment', 'guest-tracking' - ); - - // Rewrite files - $tab['Files'] = array(); - if (Configuration::get('PS_REWRITING_SETTINGS')) - { - $sql = 'SELECT ml.url_rewrite, l.iso_code + public $table = 'meta'; + public $className = 'Meta'; + public $lang = true; + + /** @var ShopUrl */ + protected $url = false; + protected $toolbar_scroll = false; + + public function __construct() + { + $this->table = 'meta'; + $this->className = 'Meta'; + + $this->bootstrap = true; + $this->identifier_name = 'page'; + $this->ht_file = _PS_ROOT_DIR_.'/.htaccess'; + $this->rb_file = _PS_ROOT_DIR_.'/robots.txt'; + $this->rb_data = $this->getRobotsContent(); + + $this->explicitSelect = true; + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); + + $this->fields_list = array( + 'id_meta' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'page' => array('title' => $this->l('Page')), + 'title' => array('title' => $this->l('Page title')), + 'url_rewrite' => array('title' => $this->l('Friendly URL')) + ); + $this->_where = ' AND a.configurable = 1'; + $this->_group = 'GROUP BY a.id_meta'; + + parent::__construct(); + + $this->sm_file = _PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$this->context->shop->id.'_index_sitemap.xml'; + // Options to generate friendly urls + $mod_rewrite = Tools::modRewriteActive(); + $general_fields = array( + 'PS_REWRITING_SETTINGS' => array( + 'title' => $this->l('Friendly URL'), + 'hint' => ($mod_rewrite ? $this->l('Enable this option only if your server allows URL rewriting (recommended).') : ''), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'desc' => (!$mod_rewrite ? $this->l('URL rewriting (mod_rewrite) is not active on your server, or it is not possible to check your server configuration. If you want to use Friendly URLs, you must activate this mod.') : '') + ), + 'PS_ALLOW_ACCENTED_CHARS_URL' => array( + 'title' => $this->l('Accented URL'), + 'hint' => $this->l('Enable this option if you want to allow accented characters in your friendly URLs.').' '.$this->l('You should only activate this option if you are using non-latin characters ; for all the latin charsets, your SEO will be better without this option.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_CANONICAL_REDIRECT' => array( + 'title' => $this->l('Redirect to the canonical URL'), + 'validation' => 'isUnsignedInt', + 'cast' => 'intval', + 'type' => 'select', + 'list' => array( + array('value' => 0, 'name' => $this->l('No redirection (you may have duplicate content issues)')), + array('value' => 1, 'name' => $this->l('302 Moved Temporarily (recommended while setting up your store)')), + array('value' => 2, 'name' => $this->l('301 Moved Permanently (recommended once you have gone live)')) + ), + 'identifier' => 'value', + ), + ); + + $url_description = ''; + if (!defined('_PS_HOST_MODE_')) { + if ($this->checkConfiguration($this->ht_file)) { + $general_fields['PS_HTACCESS_DISABLE_MULTIVIEWS'] = array( + 'title' => $this->l('Disable Apache\'s MultiViews option'), + 'hint' => $this->l('Enable this option only if you have problems with URL rewriting.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + ); + + $general_fields['PS_HTACCESS_DISABLE_MODSEC'] = array( + 'title' => $this->l('Disable Apache\'s mod_security module'), + 'hint' => $this->l('Some of PrestaShop\'s features might not work correctly with a specific configuration of Apache\'s mod_security module. We recommend to turn it off.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + ); + } else { + $url_description = $this->l('Before you can use this tool, you need to:'); + $url_description .= $this->l('1) Create a blank .htaccess file in your root directory.'); + $url_description .= $this->l('2) Give it write permissions (CHMOD 666 on Unix system).'); + } + } + + // Options to generate robot.txt + $robots_description = $this->l('Your robots.txt file MUST be in your website\'s root directory and nowhere else (e.g. http://www.example.com/robots.txt).'); + if ($this->checkConfiguration($this->rb_file)) { + $robots_description .= $this->l('Generate your "robots.txt" file by clicking on the following button (this will erase the old robots.txt file)'); + $robots_submit = array('name' => 'submitRobots', 'title' => $this->l('Generate robots.txt file')); + } else { + $robots_description .= $this->l('Before you can use this tool, you need to:'); + $robots_description .= $this->l('1) Create a blank robots.txt file in your root directory.'); + $robots_description .= $this->l('2) Give it write permissions (CHMOD 666 on Unix system).'); + } + + $robots_options = array( + 'title' => $this->l('Robots file generation'), + 'description' => $robots_description, + ); + + if (isset($robots_submit)) { + $robots_options['submit'] = $robots_submit; + } + + if (!defined('_PS_HOST_MODE_')) { + // Options for shop URL if multishop is disabled + $shop_url_options = array( + 'title' => $this->l('Set shop URL'), + 'fields' => array(), + ); + + if (!Shop::isFeatureActive()) { + $this->url = ShopUrl::getShopUrls($this->context->shop->id)->where('main', '=', 1)->getFirst(); + if ($this->url) { + $shop_url_options['description'] = $this->l('Here you can set the URL for your shop. If you migrate your shop to a new URL, remember to change the values below.'); + $shop_url_options['fields'] = array( + 'domain' => array( + 'title' => $this->l('Shop domain'), + 'validation' => 'isString', + 'type' => 'text', + 'defaultValue' => $this->url->domain, + ), + 'domain_ssl' => array( + 'title' => $this->l('SSL domain'), + 'validation' => 'isString', + 'type' => 'text', + 'defaultValue' => $this->url->domain_ssl, + ), + 'uri' => array( + 'title' => $this->l('Base URI'), + 'validation' => 'isString', + 'type' => 'text', + 'defaultValue' => $this->url->physical_uri, + ) + ); + $shop_url_options['submit'] = array('title' => $this->l('Save')); + } + } else { + $shop_url_options['description'] = $this->l('The multistore option is enabled. If you want to change the URL of your shop, you must go to the "Multistore" page under the "Advanced Parameters" menu.'); + } + } + + // List of options + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Set up URLs'), + 'description' => $url_description, + 'fields' => $general_fields, + 'submit' => array('title' => $this->l('Save')) + ) + ); + + if (!defined('_PS_HOST_MODE_')) { + $this->fields_options['shop_url'] = $shop_url_options; + } else { + $this->fields_options['manage_domain_name'] = array( + 'title' => $this->l('Manage domain name'), + 'description' => $this->l('You can search for a new domain name or add a domain name that you already own. You will be redirected to your PrestaShop account.'), + 'buttons' => array( + array( + 'title' => $this->l('Add a domain name'), + 'href' => 'https://www.prestashop.com/cloud/', + 'class' => 'pull-right', 'icon' => 'process-icon-new', + 'js' => 'return !window.open(this.href);' + ) + ) + ); + } + + // Add display route options to options form + if (Configuration::get('PS_REWRITING_SETTINGS') || Tools::getValue('PS_REWRITING_SETTINGS')) { + if (Configuration::get('PS_REWRITING_SETTINGS')) { + $this->addAllRouteFields(); + } + $this->fields_options['routes']['title'] = $this->l('Schema of URLs'); + $this->fields_options['routes']['description'] = $this->l('This section enables you to change the default pattern of your links. In order to use this functionality, PrestaShop\'s "Friendly URL" option must be enabled, and Apache\'s URL rewriting module (mod_rewrite) must be activated on your web server.').'<br />'.$this->l('There are several available keywords for each route listed below; note that keywords with * are required!').'<br />'.$this->l('To add a keyword in your URL, use the {keyword} syntax. If the keyword is not empty, you can add text before or after the keyword with syntax {prepend:keyword:append}. For example {-hey-:meta_title} will add "-hey-my-title" in the URL if the meta title is set.'); + $this->fields_options['routes']['submit'] = array('title' => $this->l('Save')); + } + + $this->fields_options['robots'] = $robots_options; + } + + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_meta'] = array( + 'href' => self::$currentIndex.'&addmeta&token='.$this->token, + 'desc' => $this->l('Add a new page', null, null, false), + 'icon' => 'process-icon-new' + ); + } + + parent::initPageHeaderToolbar(); + } + + public function initProcess() + { + parent::initProcess(); + // This is a composite page, we don't want the "options" display mode + if ($this->display == 'options') { + $this->display = ''; + } + } + + public function setMedia() + { + parent::setMedia(); + $this->addJqueryUi('ui.widget'); + $this->addJqueryPlugin('tagify'); + } + + public function addFieldRoute($route_id, $title) + { + $keywords = array(); + foreach (Dispatcher::getInstance()->default_routes[$route_id]['keywords'] as $keyword => $data) { + $keywords[] = ((isset($data['param'])) ? '<span class="red">'.$keyword.'*</span>' : $keyword); + } + + $this->fields_options['routes']['fields']['PS_ROUTE_'.$route_id] = array( + 'title' => $title, + 'desc' => sprintf($this->l('Keywords: %s'), implode(', ', $keywords)), + 'validation' => 'isString', + 'type' => 'text', + 'size' => 70, + 'defaultValue' => Dispatcher::getInstance()->default_routes[$route_id]['rule'], + ); + } + + public function renderForm() + { + $files = Meta::getPages(true, ($this->object->page ? $this->object->page : false)); + + $is_index = false; + if (is_object($this->object) && is_array($this->object->url_rewrite) && count($this->object->url_rewrite)) { + foreach ($this->object->url_rewrite as $rewrite) { + if ($is_index != true) { + $is_index = ($this->object->page == 'index' && empty($rewrite)) ? true : false; + } + } + } + + $pages = array( + 'common' => array( + 'name' => $this->l('Default pages'), + 'query' => array(), + ), + 'module' => array( + 'name' => $this->l('Modules pages'), + 'query' => array(), + ), + ); + + foreach ($files as $name => $file) { + $k = (preg_match('#^module-#', $file)) ? 'module' : 'common'; + $pages[$k]['query'][] = array( + 'id' => $file, + 'page' => $name, + ); + } + + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Meta tags'), + 'icon' => 'icon-tags' + ), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'id_meta', + ), + array( + 'type' => 'select', + 'label' => $this->l('Page'), + 'name' => 'page', + + 'options' => array( + 'optiongroup' => array( + 'label' => 'name', + 'query' => $pages, + ), + 'options' => array( + 'id' => 'id', + 'name' => 'page', + 'query' => 'query', + ), + ), + 'hint' => $this->l('Name of the related page.'), + 'required' => true, + 'empty_message' => '<p>'.$this->l('There is no page available!').'</p>', + ), + array( + 'type' => 'text', + 'label' => $this->l('Page title'), + 'name' => 'title', + 'lang' => true, + 'hint' => array( + $this->l('Title of this page.'), + $this->l('Invalid characters:').' <>;=#{}' + ) + ), + array( + 'type' => 'text', + 'label' => $this->l('Meta description'), + 'name' => 'description', + 'lang' => true, + 'hint' => array( + $this->l('A short description of your shop.'), + $this->l('Invalid characters:').' <>;=#{}' + ) + ), + array( + 'type' => 'tags', + 'label' => $this->l('Meta keywords'), + 'name' => 'keywords', + 'lang' => true, + 'hint' => array( + $this->l('List of keywords for search engines.'), + $this->l('To add tags, click in the field, write something, and then press the "Enter" key.'), + $this->l('Invalid characters:').' <>;=#{}' + ) + ), + array( + 'type' => 'text', + 'label' => $this->l('Rewritten URL'), + 'name' => 'url_rewrite', + 'lang' => true, + 'required' => true, + 'disabled' => (bool)$is_index, + 'hint' => array( + $this->l('For instance, "contacts" for http://example.com/shop/contacts to redirect to http://example.com/shop/contact-form.php'), + $this->l('Only letters and hyphens are allowed.'), + ) + ), + ), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); + return parent::renderForm(); + } + + public function postProcess() + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_ && Tools::isSubmit('submitOptionsmeta') + && (Tools::getValue('domain') != Configuration::get('PS_SHOP_DOMAIN') || Tools::getValue('domain_ssl') != Configuration::get('PS_SHOP_DOMAIN_SSL'))) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } + + if (Tools::isSubmit('submitAddmeta')) { + $default_language = Configuration::get('PS_LANG_DEFAULT'); + if (Tools::getValue('page') != 'index') { + $defaultLangIsValidated = Validate::isLinkRewrite(Tools::getValue('url_rewrite_'.$default_language)); + $englishLangIsValidated = Validate::isLinkRewrite(Tools::getValue('url_rewrite_1')); + } else { // index.php can have empty rewrite rule + $defaultLangIsValidated = !Tools::getValue('url_rewrite_'.$default_language) || Validate::isLinkRewrite(Tools::getValue('url_rewrite_'.$default_language)); + $englishLangIsValidated = !Tools::getValue('url_rewrite_1') || Validate::isLinkRewrite(Tools::getValue('url_rewrite_1')); + } + + if (!$defaultLangIsValidated && !$englishLangIsValidated) { + $this->errors[] = Tools::displayError('The URL rewrite field must be filled in either the default or English language.'); + return false; + } + + foreach (Language::getIDs(false) as $id_lang) { + $current = Tools::getValue('url_rewrite_'.$id_lang); + if (strlen($current) == 0) { + // Prioritize default language first + if ($defaultLangIsValidated) { + $_POST['url_rewrite_'.$id_lang] = Tools::getValue('url_rewrite_'.$default_language); + } else { + $_POST['url_rewrite_'.$id_lang] = Tools::getValue('url_rewrite_1'); + } + } + } + + Hook::exec('actionAdminMetaSave'); + } elseif (Tools::isSubmit('submitRobots')) { + $this->generateRobotsFile(); + } + + if (Tools::isSubmit('PS_ROUTE_product_rule')) { + Tools::clearCache($this->context->smarty); + } + + if (Tools::isSubmit('deletemeta') && (int)Tools::getValue('id_meta') > 0) { + Db::getInstance()->delete('theme_meta', 'id_meta='.(int)Tools::getValue('id_meta')); + } + + $ret = parent::postProcess(); + + if (Tools::isSubmit('submitAddmeta') && Validate::isLoadedObject($ret)) { + /** @var Theme $ret */ + $themes = Theme::getThemes(); + $theme_meta_value = array(); + foreach ($themes as $theme) { + /** @var Theme $theme */ + $theme_meta_value[] = array( + 'id_theme' => (int)$theme->id, + 'id_meta' => (int)$ret->id, + 'left_column' => (int)$theme->default_left_column, + 'right_column' => (int)$theme->default_right_column + ); + } + if (count($theme_meta_value) > 0) { + Db::getInstance()->insert('theme_meta', $theme_meta_value, false, true, DB::INSERT_IGNORE); + } + } + + return $ret; + } + + public function generateRobotsFile() + { + if (!$write_fd = @fopen($this->rb_file, 'w')) { + $this->errors[] = sprintf(Tools::displayError('Cannot write into file: %s. Please check write permissions.'), $this->rb_file); + } else { + Hook::exec('actionAdminMetaBeforeWriteRobotsFile', array( + 'rb_data' => &$this->rb_data + )); + + // PS Comments + fwrite($write_fd, "# robots.txt automaticaly generated by PrestaShop e-commerce open-source solution\n"); + fwrite($write_fd, "# http://www.prestashop.com - http://www.prestashop.com/forums\n"); + fwrite($write_fd, "# This file is to prevent the crawling and indexing of certain parts\n"); + fwrite($write_fd, "# of your site by web crawlers and spiders run by sites like Yahoo!\n"); + fwrite($write_fd, "# and Google. By telling these \"robots\" where not to go on your site,\n"); + fwrite($write_fd, "# you save bandwidth and server resources.\n"); + fwrite($write_fd, "# For more information about the robots.txt standard, see:\n"); + fwrite($write_fd, "# http://www.robotstxt.org/robotstxt.html\n"); + + // User-Agent + fwrite($write_fd, "User-agent: *\n"); + + // Allow Directives + if (count($this->rb_data['Allow'])) { + fwrite($write_fd, "# Allow Directives\n"); + foreach ($this->rb_data['Allow'] as $allow) { + fwrite($write_fd, 'Allow: '.$allow."\n"); + } + } + + // Private pages + if (count($this->rb_data['GB'])) { + fwrite($write_fd, "# Private pages\n"); + foreach ($this->rb_data['GB'] as $gb) { + fwrite($write_fd, 'Disallow: /*'.$gb."\n"); + } + } + + // Directories + if (count($this->rb_data['Directories'])) { + fwrite($write_fd, "# Directories\n"); + foreach ($this->rb_data['Directories'] as $dir) { + fwrite($write_fd, 'Disallow: */'.$dir."\n"); + } + } + + // Files + if (count($this->rb_data['Files'])) { + $language_ids = Language::getIDs(); + fwrite($write_fd, "# Files\n"); + foreach ($this->rb_data['Files'] as $iso_code => $files) { + foreach ($files as $file) { + if (!empty($language_ids)) { + fwrite($write_fd, 'Disallow: /*'.$iso_code.'/'.$file."\n"); + } else { + fwrite($write_fd, 'Disallow: /'.$file."\n"); + } + } + } + } + + // Sitemap + if (file_exists($this->sm_file) && filesize($this->sm_file)) { + fwrite($write_fd, "# Sitemap\n"); + $sitemap_filename = basename($this->sm_file); + fwrite($write_fd, 'Sitemap: '.(Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://').$_SERVER['SERVER_NAME'] + .__PS_BASE_URI__.$sitemap_filename."\n"); + } + + Hook::exec('actionAdminMetaAfterWriteRobotsFile', array( + 'rb_data' => $this->rb_data, + 'write_fd' => &$write_fd + )); + + fclose($write_fd); + + $this->redirect_after = self::$currentIndex.'&conf=4&token='.$this->token; + } + } + + public function getList($id_lang, $orderBy = null, $orderWay = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $orderBy, $orderWay, $start, $limit, Context::getContext()->shop->id); + } + + public function renderList() + { + if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) { + $this->displayInformation($this->l('You can only display the page list in a shop context.')); + } else { + return parent::renderList(); + } + } + + /** + * Validate route syntax and save it in configuration + * + * @param string $route_id + */ + public function checkAndUpdateRoute($route_id) + { + $default_routes = Dispatcher::getInstance()->default_routes; + if (!isset($default_routes[$route_id])) { + return; + } + + $rule = Tools::getValue('PS_ROUTE_'.$route_id); + if (!Validate::isRoutePattern($rule)) { + $this->errors[] = sprintf('The route %s is not valid', htmlspecialchars($rule)); + } else { + if (!$rule || $rule == $default_routes[$route_id]['rule']) { + Configuration::updateValue('PS_ROUTE_'.$route_id, ''); + return; + } + + $errors = array(); + if (!Dispatcher::getInstance()->validateRoute($route_id, $rule, $errors)) { + foreach ($errors as $error) { + $this->errors[] = sprintf('Keyword "{%1$s}" required for route "%2$s" (rule: "%3$s")', $error, $route_id, htmlspecialchars($rule)); + } + } else { + Configuration::updateValue('PS_ROUTE_'.$route_id, $rule); + } + } + } + + /** + * Called when PS_REWRITING_SETTINGS option is saved + */ + public function updateOptionPsRewritingSettings() + { + Configuration::updateValue('PS_REWRITING_SETTINGS', (int)Tools::getValue('PS_REWRITING_SETTINGS')); + + $this->updateOptionDomain(Tools::getValue('domain')); + $this->updateOptionDomainSsl(Tools::getValue('domain_ssl')); + + if (Tools::getIsset('uri')) { + $this->updateOptionUri(Tools::getValue('uri')); + } + + if (Tools::generateHtaccess($this->ht_file, null, null, '', Tools::getValue('PS_HTACCESS_DISABLE_MULTIVIEWS'), false, Tools::getValue('PS_HTACCESS_DISABLE_MODSEC'))) { + Tools::enableCache(); + Tools::clearCache($this->context->smarty); + Tools::restoreCacheSettings(); + } else { + Configuration::updateValue('PS_REWRITING_SETTINGS', 0); + // Message copied/pasted from the information tip + $message = $this->l('Before being able to use this tool, you need to:'); + $message .= '<br />- '.$this->l('Create a blank .htaccess in your root directory.'); + $message .= '<br />- '.$this->l('Give it write permissions (CHMOD 666 on Unix system).'); + $this->errors[] = $message; + } + } + + public function updateOptionPsRouteProductRule() + { + $this->checkAndUpdateRoute('product_rule'); + } + + public function updateOptionPsRouteCategoryRule() + { + $this->checkAndUpdateRoute('category_rule'); + } + + public function updateOptionPsRouteLayeredRule() + { + $this->checkAndUpdateRoute('layered_rule'); + } + + public function updateOptionPsRouteSupplierRule() + { + $this->checkAndUpdateRoute('supplier_rule'); + } + + public function updateOptionPsRouteManufacturerRule() + { + $this->checkAndUpdateRoute('manufacturer_rule'); + } + + public function updateOptionPsRouteCmsRule() + { + $this->checkAndUpdateRoute('cms_rule'); + } + + public function updateOptionPsRouteCmsCategoryRule() + { + $this->checkAndUpdateRoute('cms_category_rule'); + } + + /** + * Update shop domain (for mono shop) + * + * @param string $value + * + * @throws PrestaShopException + */ + public function updateOptionDomain($value) + { + if (!Shop::isFeatureActive() && $this->url && $this->url->domain != $value) { + if (Validate::isCleanHtml($value)) { + $this->url->domain = $value; + $this->url->update(); + Configuration::updateGlobalValue('PS_SHOP_DOMAIN', $value); + } else { + $this->errors[] = Tools::displayError('This domain is not valid.'); + } + } + } + + /** + * Update shop SSL domain (for mono shop) + * + * @param string $value + * + * @throws PrestaShopException + */ + public function updateOptionDomainSsl($value) + { + if (!Shop::isFeatureActive() && $this->url && $this->url->domain_ssl != $value) { + if (Validate::isCleanHtml($value)) { + $this->url->domain_ssl = $value; + $this->url->update(); + Configuration::updateGlobalValue('PS_SHOP_DOMAIN_SSL', $value); + } else { + $this->errors[] = Tools::displayError('The SSL domain is not valid.'); + } + } + } + + /** + * Update shop physical uri for mono shop) + * + * @param string $value + * + * @throws PrestaShopException + */ + public function updateOptionUri($value) + { + if (!Shop::isFeatureActive() && $this->url && $this->url->physical_uri != $value) { + $this->url->physical_uri = $value; + $this->url->update(); + } + } + + /** + * Function used to render the options for this controller + */ + public function renderOptions() + { + // If friendly url is not active, do not display custom routes form + if (Configuration::get('PS_REWRITING_SETTINGS')) { + $this->addAllRouteFields(); + } + + if ($this->fields_options && is_array($this->fields_options)) { + $helper = new HelperOptions($this); + $this->setHelperDisplay($helper); + $helper->toolbar_scroll = true; + $helper->toolbar_btn = array( + 'save' => array( + 'href' => '#', + 'desc' => $this->l('Save') + ) + ); + $helper->id = $this->id; + $helper->tpl_vars = $this->tpl_option_vars; + $options = $helper->generateOptions($this->fields_options); + + return $options; + } + } + + /** + * Add all custom route fields to the options form + */ + public function addAllRouteFields() + { + $this->addFieldRoute('product_rule', $this->l('Route to products')); + $this->addFieldRoute('category_rule', $this->l('Route to category')); + $this->addFieldRoute('layered_rule', $this->l('Route to category which has the "selected_filter" attribute for the "Layered Navigation" (blocklayered) module')); + $this->addFieldRoute('supplier_rule', $this->l('Route to supplier')); + $this->addFieldRoute('manufacturer_rule', $this->l('Route to manufacturer')); + $this->addFieldRoute('cms_rule', $this->l('Route to CMS page')); + $this->addFieldRoute('cms_category_rule', $this->l('Route to CMS category')); + $this->addFieldRoute('module', $this->l('Route to modules')); + } + + /** + * Check if a file is writable + * + * @param string $file + * @return bool + */ + public function checkConfiguration($file) + { + if (file_exists($file)) { + return is_writable($file); + } + return is_writable(dirname($file)); + } + + public function getRobotsContent() + { + $tab = array(); + + // Special allow directives + $tab['Allow'] = array('*/modules/*.css', '*/modules/*.js'); + + // Directories + $tab['Directories'] = array('classes/', 'config/', 'download/', 'mails/', 'modules/', 'translations/', 'tools/'); + + // Files + $disallow_controllers = array( + 'addresses', 'address', 'authentication', 'cart', 'discount', 'footer', + 'get-file', 'header', 'history', 'identity', 'images.inc', 'init', 'my-account', 'order', 'order-opc', + 'order-slip', 'order-detail', 'order-follow', 'order-return', 'order-confirmation', 'pagination', 'password', + 'pdf-invoice', 'pdf-order-return', 'pdf-order-slip', 'product-sort', 'search', 'statistics','attachment', 'guest-tracking' + ); + + // Rewrite files + $tab['Files'] = array(); + if (Configuration::get('PS_REWRITING_SETTINGS')) { + $sql = 'SELECT ml.url_rewrite, l.iso_code FROM '._DB_PREFIX_.'meta m INNER JOIN '._DB_PREFIX_.'meta_lang ml ON ml.id_meta = m.id_meta INNER JOIN '._DB_PREFIX_.'lang l ON l.id_lang = ml.id_lang WHERE l.active = 1 AND m.page IN (\''.implode('\', \'', $disallow_controllers).'\')'; - if ($results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql)) - foreach ($results as $row) - $tab['Files'][$row['iso_code']][] = $row['url_rewrite']; - } + if ($results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql)) { + foreach ($results as $row) { + $tab['Files'][$row['iso_code']][] = $row['url_rewrite']; + } + } + } - $tab['GB'] = array( - '?orderby=','?orderway=','?tag=','?id_currency=','?search_query=','?back=','?n=', - '&orderby=','&orderway=','&tag=','&id_currency=','&search_query=','&back=','&n=' - ); + $tab['GB'] = array( + '?orderby=','?orderway=','?tag=','?id_currency=','?search_query=','?back=','?n=', + '&orderby=','&orderway=','&tag=','&id_currency=','&search_query=','&back=','&n=' + ); - foreach ($disallow_controllers as $controller) - $tab['GB'][] = 'controller='.$controller; + foreach ($disallow_controllers as $controller) { + $tab['GB'][] = 'controller='.$controller; + } - return $tab; - } + return $tab; + } } diff --git a/controllers/admin/AdminModulesController.php b/controllers/admin/AdminModulesController.php index d5775fa1..acced032 100644 --- a/controllers/admin/AdminModulesController.php +++ b/controllers/admin/AdminModulesController.php @@ -26,1591 +26,1640 @@ class AdminModulesControllerCore extends AdminController { - private $_modules_ad = array( - 'blockcart' => array('cartabandonmentpro'), - /* 'bloctopmenu' => array('advancedtopmenu'), */ - 'blocklayered' => array('pm_advancedsearch4') - ); - /* - ** @var array map with $_GET keywords and their callback - */ - protected $map = array( - 'check' => 'check', - 'install' => 'install', - 'uninstall' => 'uninstall', - 'configure' => 'getContent', - 'update' => 'update', - 'delete' => 'delete', - 'checkAndUpdate' => 'checkAndUpdate' - ); + private $_modules_ad = array( + 'blockcart' => array('cartabandonmentpro'), + /* 'bloctopmenu' => array('advancedtopmenu'), */ + 'blocklayered' => array('pm_advancedsearch4') + ); + /* + ** @var array map with $_GET keywords and their callback + */ + protected $map = array( + 'check' => 'check', + 'install' => 'install', + 'uninstall' => 'uninstall', + 'configure' => 'getContent', + 'update' => 'update', + 'delete' => 'delete', + 'checkAndUpdate' => 'checkAndUpdate', + 'updateAll' => 'updateAll' + ); - protected $list_modules_categories = array(); - protected $list_partners_modules = array(); - protected $list_natives_modules = array(); + protected $list_modules_categories = array(); + protected $list_partners_modules = array(); + protected $list_natives_modules = array(); - protected $nb_modules_total = 0; - protected $nb_modules_installed = 0; - protected $nb_modules_activated = 0; + protected $nb_modules_total = 0; + protected $nb_modules_installed = 0; + protected $nb_modules_activated = 0; - protected $serial_modules = ''; - protected $modules_authors = array(); + protected $serial_modules = ''; + protected $modules_authors = array(); - protected $id_employee; - protected $iso_default_country; - protected $filter_configuration = array(); + protected $id_employee; + protected $iso_default_country; + protected $filter_configuration = array(); - protected $xml_modules_list = _PS_API_MODULES_LIST_16_; + protected $xml_modules_list = _PS_API_MODULES_LIST_16_; - /** - * Admin Modules Controller Constructor - * Init list modules categories - * Load id employee - * Load filter configuration - * Load cache file - */ + /** + * Admin Modules Controller Constructor + * Init list modules categories + * Load id employee + * Load filter configuration + * Load cache file + */ - public function __construct() - { - $this->bootstrap = true; - parent::__construct(); + public function __construct() + { + $this->bootstrap = true; + parent::__construct(); - register_shutdown_function('displayFatalError'); + register_shutdown_function('displayFatalError'); - // Set the modules categories - $this->list_modules_categories['administration']['name'] = $this->l('Administration'); - $this->list_modules_categories['advertising_marketing']['name'] = $this->l('Advertising and Marketing'); - $this->list_modules_categories['analytics_stats']['name'] = $this->l('Analytics and Stats'); - $this->list_modules_categories['billing_invoicing']['name'] = $this->l('Taxes & Invoicing'); - $this->list_modules_categories['checkout']['name'] = $this->l('Checkout'); - $this->list_modules_categories['content_management']['name'] = $this->l('Content Management'); - $this->list_modules_categories['export']['name'] = $this->l('Export'); - $this->list_modules_categories['emailing']['name'] = $this->l('Emailing'); - $this->list_modules_categories['front_office_features']['name'] = $this->l('Front office Features'); - $this->list_modules_categories['i18n_localization']['name'] = $this->l('Internationalization and Localization'); - $this->list_modules_categories['merchandizing']['name'] = $this->l('Merchandising'); - $this->list_modules_categories['migration_tools']['name'] = $this->l('Migration Tools'); - $this->list_modules_categories['payments_gateways']['name'] = $this->l('Payments and Gateways'); - $this->list_modules_categories['payment_security']['name'] = $this->l('Site certification & Fraud prevention'); - $this->list_modules_categories['pricing_promotion']['name'] = $this->l('Pricing and Promotion'); - $this->list_modules_categories['quick_bulk_update']['name'] = $this->l('Quick / Bulk update'); + // Set the modules categories + $this->list_modules_categories['administration']['name'] = $this->l('Administration'); + $this->list_modules_categories['advertising_marketing']['name'] = $this->l('Advertising and Marketing'); + $this->list_modules_categories['analytics_stats']['name'] = $this->l('Analytics and Stats'); + $this->list_modules_categories['billing_invoicing']['name'] = $this->l('Taxes & Invoicing'); + $this->list_modules_categories['checkout']['name'] = $this->l('Checkout'); + $this->list_modules_categories['content_management']['name'] = $this->l('Content Management'); + $this->list_modules_categories['customer_reviews']['name'] = $this->l('Customer Reviews'); + $this->list_modules_categories['export']['name'] = $this->l('Export'); + $this->list_modules_categories['emailing']['name'] = $this->l('Emailing'); + $this->list_modules_categories['front_office_features']['name'] = $this->l('Front office Features'); + $this->list_modules_categories['i18n_localization']['name'] = $this->l('Internationalization and Localization'); + $this->list_modules_categories['merchandizing']['name'] = $this->l('Merchandising'); + $this->list_modules_categories['migration_tools']['name'] = $this->l('Migration Tools'); + $this->list_modules_categories['payments_gateways']['name'] = $this->l('Payments and Gateways'); + $this->list_modules_categories['payment_security']['name'] = $this->l('Site certification & Fraud prevention'); + $this->list_modules_categories['pricing_promotion']['name'] = $this->l('Pricing and Promotion'); + $this->list_modules_categories['quick_bulk_update']['name'] = $this->l('Quick / Bulk update'); /* $this->list_modules_categories['search_filter']['name'] = $this->l('Search and Filter'); */ - $this->list_modules_categories['seo']['name'] = $this->l('SEO'); - $this->list_modules_categories['shipping_logistics']['name'] = $this->l('Shipping and Logistics'); - $this->list_modules_categories['slideshows']['name'] = $this->l('Slideshows'); - $this->list_modules_categories['smart_shopping']['name'] = $this->l('Comparison site & Feed management'); - $this->list_modules_categories['market_place']['name'] = $this->l('Marketplace'); - $this->list_modules_categories['others']['name'] = $this->l('Other Modules'); - $this->list_modules_categories['mobile']['name'] = $this->l('Mobile'); - $this->list_modules_categories['dashboard']['name'] = $this->l('Dashboard'); - $this->list_modules_categories['i18n_localization']['name'] = $this->l('Internationalization & Localization'); - $this->list_modules_categories['emailing']['name'] = $this->l('Emailing & SMS'); - $this->list_modules_categories['social_networks']['name'] = $this->l('Social Networks'); - - uasort($this->list_modules_categories, array($this, 'checkCategoriesNames')); - - // Set Id Employee, Iso Default Country and Filter Configuration - $this->id_employee = (int)$this->context->employee->id; - $this->iso_default_country = $this->context->country->iso_code; - $this->filter_configuration = Configuration::getMultiple(array( - 'PS_SHOW_TYPE_MODULES_'.(int)$this->id_employee, - 'PS_SHOW_COUNTRY_MODULES_'.(int)$this->id_employee, - 'PS_SHOW_INSTALLED_MODULES_'.(int)$this->id_employee, - 'PS_SHOW_ENABLED_MODULES_'.(int)$this->id_employee, - 'PS_SHOW_CAT_MODULES_'.(int)$this->id_employee, - )); - - // Load cache file modules list (natives and partners modules) - $xml_modules = false; - if (file_exists(_PS_ROOT_DIR_.Module::CACHE_FILE_MODULES_LIST)) - $xml_modules = @simplexml_load_file(_PS_ROOT_DIR_.Module::CACHE_FILE_MODULES_LIST); - if ($xml_modules) - foreach ($xml_modules->children() as $xml_module) - { - /** @var SimpleXMLElement $xml_module */ - foreach ($xml_module->children() as $module) - { - /** @var SimpleXMLElement $module */ - foreach ($module->attributes() as $key => $value) - { - if ($xml_module->attributes() == 'native' && $key == 'name') - $this->list_natives_modules[] = (string)$value; - if ($xml_module->attributes() == 'partner' && $key == 'name') - $this->list_partners_modules[] = (string)$value; - } - } - } - } - - public function checkCategoriesNames($a, $b) - { - if ($a['name'] === $this->l('Other Modules')) - return true; - - return (bool)($a['name'] > $b['name']); - } - - public function setMedia() - { - parent::setMedia(); - $this->addJqueryPlugin(array('autocomplete', 'fancybox', 'tablefilter')); - - if ($this->context->mode == Context::MODE_HOST && Tools::isSubmit('addnewmodule')) - $this->addJS(_PS_JS_DIR_.'admin/addons.js'); - } - - public function ajaxProcessRefreshModuleList($force_reload_cache = false) - { - // Refresh modules_list.xml every week - if (!$this->isFresh(Module::CACHE_FILE_MODULES_LIST, 86400) || $force_reload_cache) - { - if ($this->refresh(Module::CACHE_FILE_MODULES_LIST, 'https://'.$this->xml_modules_list)) - $this->status = 'refresh'; - elseif ($this->refresh(Module::CACHE_FILE_MODULES_LIST, 'http://'.$this->xml_modules_list)) - $this->status = 'refresh'; - else - $this->status = 'error'; - } - else - $this->status = 'cache'; - - // If logged to Addons Webservices, refresh default country native modules list every day - if ($this->status != 'error') - { - if (!$this->isFresh(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 86400) || $force_reload_cache) - { - if (file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, Tools::addonsRequest('native'))) - $this->status = 'refresh'; - else - $this->status = 'error'; - } - else - $this->status = 'cache'; - - if (!$this->isFresh(Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, 86400) || $force_reload_cache) - { - if (file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, Tools::addonsRequest('must-have'))) - $this->status = 'refresh'; - else - $this->status = 'error'; - } - else - $this->status = 'cache'; - } - - // If logged to Addons Webservices, refresh customer modules list every day - if ($this->logged_on_addons && $this->status != 'error') - { - if (!$this->isFresh(Module::CACHE_FILE_CUSTOMER_MODULES_LIST, 60) || $force_reload_cache) - { - if (file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_CUSTOMER_MODULES_LIST, Tools::addonsRequest('customer'))) - $this->status = 'refresh'; - else - $this->status = 'error'; - } - else - $this->status = 'cache'; - } - } - - public function displayAjaxRefreshModuleList() - { - echo Tools::jsonEncode(array('status' => $this->status)); - } - - - public function ajaxProcessLogOnAddonsWebservices() - { - $content = Tools::addonsRequest('check_customer', array('username_addons' => pSQL(trim(Tools::getValue('username_addons'))), 'password_addons' => pSQL(trim(Tools::getValue('password_addons'))))); - $xml = @simplexml_load_string($content, null, LIBXML_NOCDATA); - if (!$xml) - die('KO'); - $result = strtoupper((string)$xml->success); - if (!in_array($result, array('OK', 'KO'))) - die ('KO'); - if ($result == 'OK') - { - Tools::clearXMLCache(); - Configuration::updateValue('PS_LOGGED_ON_ADDONS', 1); - $this->context->cookie->username_addons = pSQL(trim(Tools::getValue('username_addons'))); - $this->context->cookie->password_addons = pSQL(trim(Tools::getValue('password_addons'))); - $this->context->cookie->is_contributor = (int)$xml->is_contributor; - $this->context->cookie->write(); - } - die($result); - } - - public function ajaxProcessLogOutAddonsWebservices() - { - $this->context->cookie->username_addons = ''; - $this->context->cookie->password_addons = ''; - $this->context->cookie->is_contributor = 0; - $this->context->cookie->write(); - die('OK'); - } - - public function ajaxProcessReloadModulesList() - { - if (Tools::getValue('filterCategory')) - Configuration::updateValue('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee, Tools::getValue('filterCategory')); - if (Tools::getValue('unfilterCategory')) - Configuration::updateValue('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee, ''); - - $this->initContent(); - $this->smartyOutputContent('controllers/modules/list.tpl'); - exit; - } - - public function ajaxProcessGetTabModulesList() - { - $tab_modules_list = Tools::getValue('tab_modules_list'); - $back = Tools::getValue('back_tab_modules_list'); - if ($back) - $back .= '&tab_modules_open=1'; - $modules_list = array('installed' =>array(), 'not_installed' => array()); - if ($tab_modules_list) - { - $tab_modules_list = explode(',', $tab_modules_list); - $modules_list_unsort = $this->getModulesByInstallation($tab_modules_list); - } - - $installed = $uninstalled = array(); - foreach ($tab_modules_list as $key => $value) - { - $continue = 0; - foreach ($modules_list_unsort['installed'] as $mod_in) - if ($mod_in->name == $value) - { - $continue = 1; - $installed[] = $mod_in; - } - if ($continue) - continue; - foreach ($modules_list_unsort['not_installed'] as $mod_in) - if ($mod_in->name == $value) - $uninstalled[] = $mod_in; - } - - $modules_list_sort = array( - 'installed' => $installed, - 'not_installed' => $uninstalled - ); - - $this->context->smarty->assign(array( - 'tab_modules_list' => $modules_list_sort, - 'admin_module_favorites_view' => $this->context->link->getAdminLink('AdminModules').'&select=favorites', - )); - - $this->smartyOutputContent('controllers/modules/tab_modules_list.tpl'); - exit; - } - - public function ajaxProcessSetFilter() - { - $this->setFilterModules(Tools::getValue('module_type'), Tools::getValue('country_module_value'), Tools::getValue('module_install'), Tools::getValue('module_status')); - die('OK'); - } - - public function ajaxProcessSaveFavoritePreferences() - { - $action = Tools::getValue('action_pref'); - $value = Tools::getValue('value_pref'); - $module = Tools::getValue('module_pref'); - $id_module_preference = (int)Db::getInstance()->getValue('SELECT `id_module_preference` FROM `'._DB_PREFIX_.'module_preference` WHERE `id_employee` = '.(int)$this->id_employee.' AND `module` = \''.pSQL($module).'\''); - if ($id_module_preference > 0) - { - if ($action == 'i') - $update = array('interest' => ($value == '' ? null : (int)$value)); - if ($action == 'f') - $update = array('favorite' => ($value == '' ? null : (int)$value)); - Db::getInstance()->update('module_preference', $update, '`id_employee` = '.(int)$this->id_employee.' AND `module` = \''.pSQL($module).'\'', 0, true); - } - else - { - $insert = array('id_employee' => (int)$this->id_employee, 'module' => pSQL($module), 'interest' => null, 'favorite' => null); - if ($action == 'i') - $insert['interest'] = ($value == '' ? null : (int)$value); - if ($action == 'f') - $insert['favorite'] = ($value == '' ? null : (int)$value); - Db::getInstance()->insert('module_preference', $insert, true); - } - die('OK'); - } - - public function ajaxProcessSaveTabModulePreferences() - { - $values = Tools::getValue('value_pref'); - $module = Tools::getValue('module_pref'); - if (Validate::isModuleName($module)) - { - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'tab_module_preference` WHERE `id_employee` = '.(int)$this->id_employee.' AND `module` = \''.pSQL($module).'\''); - if (is_array($values) && count($values)) - foreach ($values as $value) - Db::getInstance()->execute(' - INSERT INTO `'._DB_PREFIX_.'tab_module_preference` (`id_tab_module_preference`, `id_employee`, `id_tab`, `module`) - VALUES (NULL, '.(int)$this->id_employee.', '.(int)$value.', \''.pSQL($module).'\');'); - } - die('OK'); - } - - /* - ** Get current URL - ** - ** @param array $remove List of keys to remove from URL - ** @return string - */ - protected function getCurrentUrl($remove = array()) - { - $url = $_SERVER['REQUEST_URI']; - if (!$remove) - return $url; - - if (!is_array($remove)) - $remove = array($remove); - - $url = preg_replace('#(?<=&|\?)('.implode('|', $remove).')=.*?(&|$)#i', '', $url); - $len = strlen($url); - if ($url[$len - 1] == '&') - $url = substr($url, 0, $len - 1); - return $url; - } - - protected function extractArchive($file, $redirect = true) - { - $zip_folders = array(); - $tmp_folder = _PS_MODULE_DIR_.md5(time()); - - $success = false; - if (substr($file, -4) == '.zip') - { - if (Tools::ZipExtract($file, $tmp_folder)) - { - $zip_folders = scandir($tmp_folder); - if (Tools::ZipExtract($file, _PS_MODULE_DIR_)) - $success = true; - } - } - else - { - require_once(_PS_TOOL_DIR_.'tar/Archive_Tar.php'); - $archive = new Archive_Tar($file); - if ($archive->extract($tmp_folder)) - { - $zip_folders = scandir($tmp_folder); - if ($archive->extract(_PS_MODULE_DIR_)) - $success = true; - } - } - - if (!$success) - $this->errors[] = Tools::displayError('There was an error while extracting the module (file may be corrupted).'); - else - { - //check if it's a real module - foreach ($zip_folders as $folder) - if (!in_array($folder, array('.', '..', '.svn', '.git', '__MACOSX')) && !Module::getInstanceByName($folder)) - { - $this->errors[] = sprintf(Tools::displayError('The module %1$s that you uploaded is not a valid module.'), $folder); - $this->recursiveDeleteOnDisk(_PS_MODULE_DIR_.$folder); - } - } - - @unlink($file); - $this->recursiveDeleteOnDisk($tmp_folder); - - if ($success && $redirect) - Tools::redirectAdmin(self::$currentIndex.'&conf=8&anchor='.ucfirst($folder).'&token='.$this->token); - - return $success; - } - - protected function recursiveDeleteOnDisk($dir) - { - if (strpos(realpath($dir), realpath(_PS_MODULE_DIR_)) === false) - return; - if (is_dir($dir)) - { - $objects = scandir($dir); - foreach ($objects as $object) - if ($object != '.' && $object != '..') - { - if (filetype($dir.'/'.$object) == 'dir') - $this->recursiveDeleteOnDisk($dir.'/'.$object); - else - unlink($dir.'/'.$object); - } - reset($objects); - rmdir($dir); - } - } - - /* - ** Filter Configuration Methods - ** Set and reset filter configuration - */ - - protected function setFilterModules($module_type, $country_module_value, $module_install, $module_status) - { - Configuration::updateValue('PS_SHOW_TYPE_MODULES_'.(int)$this->id_employee, $module_type); - Configuration::updateValue('PS_SHOW_COUNTRY_MODULES_'.(int)$this->id_employee, $country_module_value); - Configuration::updateValue('PS_SHOW_INSTALLED_MODULES_'.(int)$this->id_employee, $module_install); - Configuration::updateValue('PS_SHOW_ENABLED_MODULES_'.(int)$this->id_employee, $module_status); - } - - protected function resetFilterModules() - { - Configuration::updateValue('PS_SHOW_TYPE_MODULES_'.(int)$this->id_employee, 'allModules'); - Configuration::updateValue('PS_SHOW_COUNTRY_MODULES_'.(int)$this->id_employee, 0); - Configuration::updateValue('PS_SHOW_INSTALLED_MODULES_'.(int)$this->id_employee, 'installedUninstalled'); - Configuration::updateValue('PS_SHOW_ENABLED_MODULES_'.(int)$this->id_employee, 'enabledDisabled'); - Configuration::updateValue('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee, ''); - } - - /* - ** Post Process Filter - ** - */ - - public function postProcessFilterModules() - { - $this->setFilterModules(Tools::getValue('module_type'), Tools::getValue('country_module_value'), Tools::getValue('module_install'), Tools::getValue('module_status')); - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); - } - - public function postProcessResetFilterModules() - { - $this->resetFilterModules(); - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); - } - - public function postProcessFilterCategory() - { - // Save configuration and redirect employee - Configuration::updateValue('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee, Tools::getValue('filterCategory')); - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); - } - - public function postProcessUnfilterCategory() - { - // Save configuration and redirect employee - Configuration::updateValue('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee, ''); - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); - } - - /* - ** Post Process Module CallBack - ** - */ - - public function postProcessReset() - { - if ($this->tabAccess['edit'] === '1') - { - $module = Module::getInstanceByName(Tools::getValue('module_name')); - if (Validate::isLoadedObject($module)) - { - if (!$module->getPermission('configure')) - $this->errors[] = Tools::displayError('You do not have the permission to use this module.'); - else - { - if (Tools::getValue('keep_data') == '1' && method_exists($module, 'reset')) - { - if ($module->reset()) - Tools::redirectAdmin(self::$currentIndex.'&conf=21&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name)); - else - $this->errors[] = Tools::displayError('Cannot reset this module.'); - } - else - { - if ($module->uninstall()) - if ($module->install()) - Tools::redirectAdmin(self::$currentIndex.'&conf=21&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name)); - else - $this->errors[] = Tools::displayError('Cannot install this module.'); - else - $this->errors[] = Tools::displayError('Cannot uninstall this module.'); - } - } - } - else - $this->errors[] = Tools::displayError('Cannot load the module\'s object.'); - - if (($errors = $module->getErrors()) && is_array($errors)) - $this->errors = array_merge($this->errors, $errors); - } - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - - public function postProcessDownload() - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_ || ($this->context->mode == Context::MODE_HOST)) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } - - // Try to upload and unarchive the module - if ($this->tabAccess['add'] === '1') - { - // UPLOAD_ERR_OK: 0 - // UPLOAD_ERR_INI_SIZE: 1 - // UPLOAD_ERR_FORM_SIZE: 2 - // UPLOAD_ERR_NO_TMP_DIR: 6 - // UPLOAD_ERR_CANT_WRITE: 7 - // UPLOAD_ERR_EXTENSION: 8 - // UPLOAD_ERR_PARTIAL: 3 - - if (isset($_FILES['file']['error']) && $_FILES['file']['error'] != UPLOAD_ERR_OK) - switch ($_FILES['file']['error']) - { - case UPLOAD_ERR_INI_SIZE: - case UPLOAD_ERR_FORM_SIZE: - $this->errors[] = sprintf($this->l('File too large (limit of %s bytes).'), Tools::getMaxUploadSize()); - break; - case UPLOAD_ERR_PARTIAL: - $this->errors[] = $this->l('File upload was not completed.'); - break; - case UPLOAD_ERR_NO_FILE: - $this->errors[] = $this->l('No file was uploaded.'); - break; - default: - $this->errors[] = sprintf($this->l('Internal error #%s'), $_FILES['newfile']['error']); - break; - } - elseif (!isset($_FILES['file']['tmp_name']) || empty($_FILES['file']['tmp_name'])) - $this->errors[] = $this->l('No file has been selected'); - elseif (substr($_FILES['file']['name'], -4) != '.tar' && substr($_FILES['file']['name'], -4) != '.zip' - && substr($_FILES['file']['name'], -4) != '.tgz' && substr($_FILES['file']['name'], -7) != '.tar.gz') - $this->errors[] = Tools::displayError('Unknown archive type.'); - elseif (!move_uploaded_file($_FILES['file']['tmp_name'], _PS_MODULE_DIR_.$_FILES['file']['name'])) - $this->errors[] = Tools::displayError('An error occurred while copying the archive to the module directory.'); - else - $this->extractArchive(_PS_MODULE_DIR_.$_FILES['file']['name']); - } - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - - public function postProcessEnable() - { - if ($this->tabAccess['edit'] === '1') - { - $module = Module::getInstanceByName(Tools::getValue('module_name')); - if (Validate::isLoadedObject($module)) - { - if (!$module->getPermission('configure')) - $this->errors[] = Tools::displayError('You do not have the permission to use this module.'); - else - { - if (Tools::getValue('enable')) - $module->enable(); - else - $module->disable(); - Tools::redirectAdmin($this->getCurrentUrl('enable')); - } - } - else - $this->errors[] = Tools::displayError('Cannot load the module\'s object.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - - public function postProcessEnable_Device() - { - if ($this->tabAccess['edit'] === '1') - { - $module = Module::getInstanceByName(Tools::getValue('module_name')); - if (Validate::isLoadedObject($module)) - { - if (!$module->getPermission('configure')) - $this->errors[] = Tools::displayError('You do not have the permission to use this module.'); - else - { - $module->enableDevice((int)Tools::getValue('enable_device')); - Tools::redirectAdmin($this->getCurrentUrl('enable_device')); - } - } - else - $this->errors[] = Tools::displayError('Cannot load the module\'s object.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - - public function postProcessDisable_Device() - { - if ($this->tabAccess['edit'] === '1') - { - $module = Module::getInstanceByName(Tools::getValue('module_name')); - if (Validate::isLoadedObject($module)) - { - if (!$module->getPermission('configure')) - $this->errors[] = Tools::displayError('You do not have the permission to use this module.'); - else - { - $module->disableDevice((int)Tools::getValue('disable_device')); - Tools::redirectAdmin($this->getCurrentUrl('disable_device')); - } - } - else - $this->errors[] = Tools::displayError('Cannot load the module\'s object.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - - public function postProcessDelete() - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } - - if ($this->tabAccess['delete'] === '1') - { - if (Tools::getValue('module_name') != '') - { - $module = Module::getInstanceByName(Tools::getValue('module_name')); - if (Validate::isLoadedObject($module) && !$module->getPermission('configure')) - $this->errors[] = Tools::displayError('You do not have the permission to use this module.'); - else - { - // Uninstall the module before deleting the files, but do not block the process if uninstall returns false - if (Module::isInstalled($module->name)) - $module->uninstall(); - $moduleDir = _PS_MODULE_DIR_.str_replace(array('.', '/', '\\'), array('', '', ''), Tools::getValue('module_name')); - $this->recursiveDeleteOnDisk($moduleDir); - if (!file_exists($moduleDir)) - Tools::redirectAdmin(self::$currentIndex.'&conf=22&token='.$this->token.'&tab_module='.Tools::getValue('tab_module').'&module_name='.Tools::getValue('module_name')); - else - $this->errors[] = Tools::displayError('Sorry, the module cannot be deleted. Please check if you have the right permissions on this folder.'); - } - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - - public function postProcessCallback() - { - $return = false; - $installed_modules = array(); - - foreach ($this->map as $key => $method) - { - if (!Tools::getValue($key)) - continue; - - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } - - if ($key == 'check') - $this->ajaxProcessRefreshModuleList(true); - elseif ($key == 'checkAndUpdate') - { - $modules = array(); - $this->ajaxProcessRefreshModuleList(true); - $modules_on_disk = Module::getModulesOnDisk(true, $this->logged_on_addons, $this->id_employee); - - // Browse modules list - foreach ($modules_on_disk as $km => $module_on_disk) - { - if (!Tools::getValue('module_name') && isset($module_on_disk->version_addons) && $module_on_disk->version_addons) - $modules[] = $module_on_disk->name; - } - - if (!Tools::getValue('module_name')) - $modules_list_save = implode('|', $modules); - - } - elseif (($modules = Tools::getValue($key)) && $key != 'checkAndUpdate') - { - if (strpos($modules, '|')) - { - $modules_list_save = $modules; - $modules = explode('|', $modules); - } - - if (!is_array($modules)) - $modules = (array)$modules; - } - - $module_upgraded = array(); - $module_errors = array(); - if (isset($modules)) - foreach ($modules as $name) - { - $module_to_update = array(); - $module_to_update[$name] = null; - $full_report = null; - // If Addons module, download and unzip it before installing it - if (!file_exists(_PS_MODULE_DIR_.$name.'/'.$name.'.php') || $key == 'update') - { - $files_list = array( - array('type' => 'addonsNative', 'file' => Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 'loggedOnAddons' => 0), - array('type' => 'addonsBought', 'file' => Module::CACHE_FILE_CUSTOMER_MODULES_LIST, 'loggedOnAddons' => 1), - ); - - foreach ($files_list as $f) - if (file_exists(_PS_ROOT_DIR_.$f['file'])) - { - $file = $f['file']; - $content = Tools::file_get_contents(_PS_ROOT_DIR_.$file); - if ($xml = @simplexml_load_string($content, null, LIBXML_NOCDATA)) - foreach ($xml->module as $modaddons) - if (Tools::strtolower($name) == Tools::strtolower($modaddons->name)) - { - $module_to_update[$name]['id'] = $modaddons->id; - $module_to_update[$name]['displayName'] = $modaddons->displayName; - $module_to_update[$name]['need_loggedOnAddons'] = $f['loggedOnAddons']; - } - } - - foreach ($module_to_update as $name => $attr) - { - // if ((is_null($attr) && $this->logged_on_addons == 0) || ($attr['need_loggedOnAddons'] == 1 && $this->logged_on_addons == 0)) - // $this->errors[] = sprintf(Tools::displayError('You need to be logged in to your PrestaShop Addons account in order to update the %s module. %s'), '<strong>'.$name.'</strong>', '<a href="#" class="addons_connect" data-toggle="modal" data-target="#modal_addons_connect" title="Addons">'.$this->l('Click here to log in.').'</a>'); - // elseif (!is_null($attr['id'])) - // { - // $download_ok = false; - - // if ($attr['need_loggedOnAddons'] == 0 && file_put_contents(_PS_MODULE_DIR_.$name.'.zip', Tools::addonsRequest('module', array('id_module' => pSQL($attr['id']))))) - // $download_ok = true; - // elseif ($attr['need_loggedOnAddons'] == 1 && $this->logged_on_addons && file_put_contents(_PS_MODULE_DIR_.$name.'.zip', Tools::addonsRequest('module', array('id_module' => pSQL($attr['id']), 'username_addons' => pSQL(trim($this->context->cookie->username_addons)), 'password_addons' => pSQL(trim($this->context->cookie->password_addons)))))) - // $download_ok = true; - - // if (!$download_ok) - // $this->errors[] = sprintf(Tools::displayError('Module %s cannot be upgraded: Error while downloading the latest version.'), '<strong>'.$attr['displayName'].'</strong>'); - // elseif (!$this->extractArchive(_PS_MODULE_DIR_.$name.'.zip', false)) - // $this->errors[] = sprintf(Tools::displayError('Module %s cannot be upgraded: Error while extracting the latest version.'), '<strong>'.$attr['displayName'].'</strong>'); - // else - // $module_upgraded[] = $name; - // } - // else - // $this->errors[] = sprintf(Tools::displayError('You do not have the rights to update the %s module. Please make sure you are logged in to the PrestaShop Addons account that purchased the module.'), '<strong>'.$name.'</strong>'); - } - } - - if (count($this->errors)) - continue; - - // Check potential error - if (!($module = Module::getInstanceByName(urldecode($name)))) - $this->errors[] = $this->l('Module not found'); - elseif (($this->context->mode >= Context::MODE_HOST_CONTRIB) && in_array($module->name, Module::$hosted_modules_blacklist)) - $this->errors[] = Tools::displayError('You do not have permission to access this module.'); - elseif ($key == 'install' && $this->tabAccess['add'] !== '1') - $this->errors[] = Tools::displayError('You do not have permission to install this module.'); - elseif ($key == 'install' && ($this->context->mode == Context::MODE_HOST) && !Module::isModuleTrusted($module->name)) - $this->errors[] = Tools::displayError('You do not have permission to install this module.'); - elseif ($key == 'delete' && ($this->tabAccess['delete'] !== '1' || !$module->getPermission('configure'))) - $this->errors[] = Tools::displayError('You do not have permission to delete this module.'); - elseif ($key == 'configure' && ($this->tabAccess['edit'] !== '1' || !$module->getPermission('configure') || !Module::isInstalled(urldecode($name)))) - $this->errors[] = Tools::displayError('You do not have permission to configure this module.'); - elseif ($key == 'install' && Module::isInstalled($module->name)) - $this->errors[] = sprintf(Tools::displayError('This module is already installed: %s.'), $module->name); - elseif ($key == 'uninstall' && !Module::isInstalled($module->name)) - $this->errors[] = sprintf(Tools::displayError('This module has already been uninstalled: %s.'), $module->name); - elseif ($key == 'update' && !Module::isInstalled($module->name)) - $this->errors[] = sprintf(Tools::displayError('This module needs to be installed in order to be updated: %s.'), $module->name); - else - { - // If we install a module, force temporary global context for multishop - if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL && $method != 'getContent') - { - $shop_id = (int)Context::getContext()->shop->id; - Context::getContext()->tmpOldShop = clone(Context::getContext()->shop); - if ($shop_id) - Context::getContext()->shop = new Shop($shop_id); - } - - //retrocompatibility - if (Tools::getValue('controller') != '') - $_POST['tab'] = Tools::safeOutput(Tools::getValue('controller')); - - $echo = ''; - if ($key != 'update' && $key != 'checkAndUpdate') - { - // We check if method of module exists - if (!method_exists($module, $method)) - throw new PrestaShopException('Method of module cannot be found'); - - if ($key == 'uninstall' && !Module::getPermissionStatic($module->id, 'uninstall')) - $this->errors[] = Tools::displayError('You do not have permission to uninstall this module.'); - - if (count($this->errors)) - continue; - // Get the return value of current method - $echo = $module->{$method}(); - - // After a successful install of a single module that has a configuration method, to the configuration page - if ($key == 'install' && $echo === true && strpos(Tools::getValue('install'), '|') === false && method_exists($module, 'getContent')) - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&configure='.$module->name.'&conf=12'); - } - - // If the method called is "configure" (getContent method), we show the html code of configure page - if ($key == 'configure' && Module::isInstalled($module->name)) - { - $this->bootstrap = (isset($module->bootstrap) && $module->bootstrap); - if (isset($module->multishop_context)) - $this->multishop_context = $module->multishop_context; - - $back_link = self::$currentIndex.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name; - $hook_link = 'index.php?tab=AdminModulesPositions&token='.Tools::getAdminTokenLite('AdminModulesPositions').'&show_modules='.(int)$module->id; - $trad_link = 'index.php?tab=AdminTranslations&token='.Tools::getAdminTokenLite('AdminTranslations').'&type=modules&lang='; - $disable_link = $this->context->link->getAdminLink('AdminModules').'&module_name='.$module->name.'&enable=0&tab_module='.$module->tab; - $uninstall_link = $this->context->link->getAdminLink('AdminModules').'&module_name='.$module->name.'&uninstall='.$module->name.'&tab_module='.$module->tab; - $reset_link = $this->context->link->getAdminLink('AdminModules').'&module_name='.$module->name.'&reset&tab_module='.$module->tab; - $update_link = $this->context->link->getAdminLink('AdminModules').'&checkAndUpdate=1&module_name='.$module->name; - - $is_reset_ready = false; - if (method_exists($module, 'reset')) - $is_reset_ready = true; - - $this->context->smarty->assign( - array( - 'module_name' => $module->name, - 'module_display_name' => $module->displayName, - 'back_link' => $back_link, - 'module_hook_link' => $hook_link, - 'module_disable_link' => $disable_link, - 'module_uninstall_link' => $uninstall_link, - 'module_reset_link' => $reset_link, - 'module_update_link' => $update_link, - 'trad_link' => $trad_link, - 'module_languages' => Language::getLanguages(false), - 'theme_language_dir' => _THEME_LANG_DIR_, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn, - 'add_permission' => $this->tabAccess['add'], - 'is_reset_ready' => $is_reset_ready, - ) - ); - - // Display checkbox in toolbar if multishop - if (Shop::isFeatureActive()) - { - if (Shop::getContext() == Shop::CONTEXT_SHOP) - $shop_context = 'shop <strong>'.$this->context->shop->name.'</strong>'; - elseif (Shop::getContext() == Shop::CONTEXT_GROUP) - { - $shop_group = new ShopGroup((int)Shop::getContextShopGroupID()); - $shop_context = 'all shops of group shop <strong>'.$shop_group->name.'</strong>'; - } - else - $shop_context = 'all shops'; - - $this->context->smarty->assign(array( - 'module' => $module, - 'display_multishop_checkbox' => true, - 'current_url' => $this->getCurrentUrl('enable'), - 'shop_context' => $shop_context, - )); - } - - $this->context->smarty->assign(array( - 'is_multishop' => Shop::isFeatureActive(), - 'multishop_context' => Shop::CONTEXT_ALL | Shop::CONTEXT_GROUP | Shop::CONTEXT_SHOP - )); - - if (Shop::isFeatureActive() && isset(Context::getContext()->tmpOldShop)) - { - Context::getContext()->shop = clone(Context::getContext()->tmpOldShop); - unset(Context::getContext()->tmpOldShop); - } - - // Display module configuration - $header = $this->context->smarty->fetch('controllers/modules/configure.tpl'); - $configuration_bar = $this->context->smarty->fetch('controllers/modules/configuration_bar.tpl'); - - $output = $header.$echo; - - if (isset($this->_modules_ad[$module->name])) - { - $ad_modules = $this->getModulesByInstallation($this->_modules_ad[$module->name]); - - foreach ($ad_modules['not_installed'] as $key => &$module) - { - if (isset($module->addons_buy_url)) - $module->addons_buy_url = str_replace('utm_source=v1trunk_api', 'utm_source=back-office', $module->addons_buy_url) - .'&utm_medium=related-modules&utm_campaign=back-office-'.strtoupper($this->context->language->iso_code) - .'&utm_content='.(($this->context->mode >= Context::MODE_HOST_CONTRIB) ? 'cloud' : 'download'); - if (isset($module->description_full) && trim($module->description_full) != '') - $module->show_quick_view = true; - } - $this->context->smarty->assign(array( - 'ad_modules' => $ad_modules, - 'currentIndex' => self::$currentIndex - )); - $ad_bar = $this->context->smarty->fetch('controllers/modules/ad_bar.tpl'); - $output .= $ad_bar; - } - - $this->context->smarty->assign('module_content', $output.$configuration_bar); - } - elseif ($echo === true) - { - $return = 13; - if ($method == 'install') - { - $return = 12; - $installed_modules[] = $module->id; - } - } - elseif ($echo === false) - $module_errors[] = array('name' => $name, 'message' => $module->getErrors()); - - if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL && isset(Context::getContext()->tmpOldShop)) - { - Context::getContext()->shop = clone(Context::getContext()->tmpOldShop); - unset(Context::getContext()->tmpOldShop); - } - } - if ($key != 'configure' && Tools::getIsset('bpay')) - Tools::redirectAdmin('index.php?tab=AdminPayment&token='.Tools::getAdminToken('AdminPayment'.(int)Tab::getIdFromClassName('AdminPayment').(int)$this->id_employee)); - } - - if (count($module_errors)) - { - // If error during module installation, no redirection - $html_error = $this->generateHtmlMessage($module_errors); - if ($key == 'uninstall') - $this->errors[] = sprintf(Tools::displayError('The following module(s) could not be uninstalled properly: %s.'), $html_error); - else - $this->errors[] = sprintf(Tools::displayError('The following module(s) could not be installed properly: %s.'), $html_error); - $this->context->smarty->assign('error_module', 'true'); - } - } - - if ($return) - { - $params = (count($installed_modules)) ? '&installed_modules='.implode('|', $installed_modules) : ''; - - // If redirect parameter is present and module installed with success, we redirect on configuration module page - if (Tools::getValue('redirect') == 'config' && Tools::getValue('module_name') != '' && $return == '12' && Module::isInstalled(pSQL(Tools::getValue('module_name')))) - Tools::redirectAdmin('index.php?controller=adminmodules&configure='.Tools::getValue('module_name').'&token='.Tools::getValue('token').'&module_name='.Tools::getValue('module_name').$params); - Tools::redirectAdmin(self::$currentIndex.'&conf='.$return.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name).(isset($modules_list_save) ? '&modules_list='.$modules_list_save : '').$params); - } - - if (Tools::getValue('update') || Tools::getValue('checkAndUpdate')) - { - $updated = '&updated=1'; - if (Tools::getValue('checkAndUpdate')) - { - $updated = '&check=1'; - if (Tools::getValue('module_name')) - { - $module = Module::getInstanceByName(Tools::getValue('module_name')); - if (!Validate::isLoadedObject($module)) - unset($module); - } - } - - $module_upgraded = implode('|', $module_upgraded); - - if (isset($module_upgraded) && $module_upgraded != '') - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&updated=1&module_name='.$module_upgraded); - elseif (isset($modules_list_save)) - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&updated=1&module_name='.$modules_list_save); - elseif (isset($module)) - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.$updated.'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name).(isset($modules_list_save) ? '&modules_list='.$modules_list_save : '')); - } - } - - protected function getModulesByInstallation($tab_modules_list = null) - { - $all_modules = Module::getModulesOnDisk(true, $this->logged_on_addons, $this->id_employee); - $all_unik_modules = array(); - $modules_list = array('installed' =>array(), 'not_installed' => array()); - - foreach ($all_modules as $mod) - if (!isset($all_unik_modules[$mod->name])) - $all_unik_modules[$mod->name] = $mod; - - $all_modules = $all_unik_modules; - - foreach ($all_modules as $module) - { - if (!isset($tab_modules_list) || in_array($module->name, $tab_modules_list)) - { - $perm = true; - if ($module->id) - $perm &= Module::getPermissionStatic($module->id, 'configure'); - else - { - $id_admin_module = Tab::getIdFromClassName('AdminModules'); - $access = Profile::getProfileAccess($this->context->employee->id_profile, $id_admin_module); - if (!$access['edit']) - $perm &= false; - } - - if (in_array($module->name, $this->list_partners_modules)) - $module->type = 'addonsPartner'; - - if ($perm) - { - $this->fillModuleData($module, 'array'); - if ($module->id) - $modules_list['installed'][] = $module; - else - $modules_list['not_installed'][] = $module; - } - } - } - - return $modules_list; - } - - public function postProcess() - { - // Parent Post Process - parent::postProcess(); - - // Get the list of installed module ans prepare it for ajax call. - if (($list = Tools::getValue('installed_modules'))) - Context::getContext()->smarty->assign('installed_modules', Tools::jsonEncode(explode('|', $list))); - - // If redirect parameter is present and module already installed, we redirect on configuration module page - if (Tools::getValue('redirect') == 'config' && Tools::getValue('module_name') != '' && Module::isInstalled(pSQL(Tools::getValue('module_name')))) - Tools::redirectAdmin('index.php?controller=adminmodules&configure='.Tools::getValue('module_name').'&token='.Tools::getValue('token').'&module_name='.Tools::getValue('module_name')); - - // Execute filter or callback methods - $filter_methods = array('filterModules', 'resetFilterModules', 'filterCategory', 'unfilterCategory'); - $callback_methods = array('reset', 'download', 'enable', 'delete', 'enable_device', 'disable_device'); - $post_process_methods_list = array_merge((array)$filter_methods, (array)$callback_methods); - foreach ($post_process_methods_list as $ppm) - if (Tools::isSubmit($ppm)) - { - $ppm = 'postProcess'.ucfirst($ppm); - if (method_exists($this, $ppm)) - $ppm_return = $this->$ppm(); - } - - // Call appropriate module callback - if (!isset($ppm_return)) - $this->postProcessCallback(); - - if ($back = Tools::getValue('back')) - Tools::redirectAdmin($back); - } - - /** - * Generate html errors for a module process - * - * @param $module_errors - * @return string - */ - protected function generateHtmlMessage($module_errors) - { - $html_error = ''; - - if (count($module_errors)) - { - $html_error = '<ul>'; - foreach ($module_errors as $module_error) - { - $html_error_description = ''; - if (count($module_error['message']) > 0) - foreach ($module_error['message'] as $e) - $html_error_description .= '<br />    '.$e; - $html_error .= '<li><b>'.$module_error['name'].'</b> : '.$html_error_description.'</li>'; - } - $html_error .= '</ul>'; - } - return $html_error; - } - - public function initModulesList(&$modules) - { - foreach ($modules as $k => $module) - { - // Check add permissions, if add permissions not set, addons modules and uninstalled modules will not be displayed - if ($this->tabAccess['add'] !== '1' && isset($module->type) && ($module->type != 'addonsNative' || $module->type != 'addonsBought')) - unset($modules[$k]); - elseif ($this->tabAccess['add'] !== '1' && (!isset($module->id) || $module->id < 1)) - unset($modules[$k]); - elseif ($module->id && !Module::getPermissionStatic($module->id, 'view') && !Module::getPermissionStatic($module->id, 'configure')) - unset($modules[$k]); - else - { - // Init serial and modules author list - if (!in_array($module->name, $this->list_natives_modules)) - $this->serial_modules .= $module->name.' '.$module->version.'-'.($module->active ? 'a' : 'i')."\n"; - $module_author = $module->author; - if (!empty($module_author) && ($module_author != '')) - $this->modules_authors[strtolower($module_author)] = 'notselected'; - } - } - $this->serial_modules = urlencode($this->serial_modules); - } - - public function makeModulesStats($module) - { - // Count Installed Modules - if (isset($module->id) && $module->id > 0) - $this->nb_modules_installed++; - - // Count Activated Modules - if (isset($module->id) && $module->id > 0 && $module->active > 0) - $this->nb_modules_activated++; - - // Count Modules By Category - if (isset($this->list_modules_categories[$module->tab]['nb'])) - $this->list_modules_categories[$module->tab]['nb']++; - else - $this->list_modules_categories['others']['nb']++; - } - - public function isModuleFiltered($module) - { - // If action on module, we display it - if (Tools::getValue('module_name') != '' && Tools::getValue('module_name') == $module->name) - return false; - - // Filter on module name - $filter_name = Tools::getValue('filtername'); - if (!empty($filter_name)) - { - if (stristr($module->name, $filter_name) === false && stristr($module->displayName, $filter_name) === false && stristr($module->description, $filter_name) === false) - return true; - return false; - } - - // Filter on interest - if ($module->interest !== '') - { - if ($module->interest === '0') - return true; - } - elseif ((int)Db::getInstance()->getValue('SELECT `id_module_preference` FROM `'._DB_PREFIX_.'module_preference` WHERE `module` = \''.pSQL($module->name).'\' AND `id_employee` = '.(int)$this->id_employee.' AND `interest` = 0') > 0) - return true; - - // Filter on favorites - if (Configuration::get('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee) == 'favorites') - { - if ((int)Db::getInstance()->getValue('SELECT `id_module_preference` FROM `'._DB_PREFIX_.'module_preference` WHERE `module` = \''.pSQL($module->name).'\' AND `id_employee` = '.(int)$this->id_employee.' AND `favorite` = 1 AND (`interest` = 1 OR `interest` IS NULL)') < 1) - return true; - } - else - { - // Handle "others" category - if (!isset($this->list_modules_categories[$module->tab])) - $module->tab = 'others'; - - // Filter on module category - $category_filtered = array(); - $filter_categories = explode('|', Configuration::get('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee)); - if (count($filter_categories) > 0) - foreach ($filter_categories as $fc) - if (!empty($fc)) - $category_filtered[$fc] = 1; - if (count($category_filtered) > 0 && !isset($category_filtered[$module->tab])) - return true; - } - - // Filter on module type and author - $show_type_modules = $this->filter_configuration['PS_SHOW_TYPE_MODULES_'.(int)$this->id_employee]; - if ($show_type_modules == 'nativeModules' && !in_array($module->name, $this->list_natives_modules)) - return true; - elseif ($show_type_modules == 'partnerModules' && !in_array($module->name, $this->list_partners_modules)) - return true; - elseif ($show_type_modules == 'addonsModules' && (!isset($module->type) || $module->type != 'addonsBought')) - return true; - elseif ($show_type_modules == 'mustHaveModules' && (!isset($module->type) || $module->type != 'addonsMustHave')) - return true; - elseif ($show_type_modules == 'otherModules' && (in_array($module->name, $this->list_partners_modules) || in_array($module->name, $this->list_natives_modules))) - return true; - elseif (strpos($show_type_modules, 'authorModules[') !== false) - { - // setting selected author in authors set - $author_selected = substr(str_replace(array('authorModules[', "\'"), array('', "'"), $show_type_modules), 0, -1); - $this->modules_authors[$author_selected] = 'selected'; - if (empty($module->author) || strtolower($module->author) != $author_selected) - return true; - } - - // Filter on install status - $show_installed_modules = $this->filter_configuration['PS_SHOW_INSTALLED_MODULES_'.(int)$this->id_employee]; - if ($show_installed_modules == 'installed' && !$module->id) - return true; - if ($show_installed_modules == 'uninstalled' && $module->id) - return true; - - // Filter on active status - $show_enabled_modules = $this->filter_configuration['PS_SHOW_ENABLED_MODULES_'.(int)$this->id_employee]; - if ($show_enabled_modules == 'enabled' && !$module->active) - return true; - if ($show_enabled_modules == 'disabled' && $module->active) - return true; - - // Filter on country - $show_country_modules = $this->filter_configuration['PS_SHOW_COUNTRY_MODULES_'.(int)$this->id_employee]; - if ($show_country_modules && (isset($module->limited_countries) && !empty($module->limited_countries) - && ((is_array($module->limited_countries) && count($module->limited_countries) - && !in_array(strtolower($this->iso_default_country), $module->limited_countries)) - || (!is_array($module->limited_countries) && strtolower($this->iso_default_country) != strval($module->limited_countries))))) - return true; - - // Module has not been filtered - return false; - } - - public function renderKpis() - { - $time = time(); - $kpis = array(); - - /* The data generation is located in AdminStatsControllerCore */ - - $helper = new HelperKpi(); - $helper->id = 'box-installed-modules'; - $helper->icon = 'icon-puzzle-piece'; - $helper->color = 'color1'; - $helper->title = $this->l('Installed Modules', null, null, false); - if (ConfigurationKPI::get('INSTALLED_MODULES') !== false && ConfigurationKPI::get('INSTALLED_MODULES') != '') - $helper->value = ConfigurationKPI::get('INSTALLED_MODULES'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=installed_modules'; - $helper->refresh = (bool)(ConfigurationKPI::get('INSTALLED_MODULES_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-disabled-modules'; - $helper->icon = 'icon-off'; - $helper->color = 'color2'; - $helper->title = $this->l('Disabled Modules', null, null, false); - if (ConfigurationKPI::get('DISABLED_MODULES') !== false && ConfigurationKPI::get('DISABLED_MODULES') != '') - $helper->value = ConfigurationKPI::get('DISABLED_MODULES'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=disabled_modules'; - $helper->refresh = (bool)(ConfigurationKPI::get('DISABLED_MODULES_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-update-modules'; - $helper->icon = 'icon-refresh'; - $helper->color = 'color3'; - $helper->title = $this->l('Modules to update', null, null, false); - if (ConfigurationKPI::get('UPDATE_MODULES') !== false && ConfigurationKPI::get('UPDATE_MODULES') != '') - $helper->value = ConfigurationKPI::get('UPDATE_MODULES'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=update_modules'; - $helper->refresh = (bool)(ConfigurationKPI::get('UPDATE_MODULES_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpiRow(); - $helper->kpis = $kpis; - return $helper->generate(); - } - - public function initModal() - { - parent::initModal(); - - $this->context->smarty->assign(array( - 'trad_link' => 'index.php?tab=AdminTranslations&token='.Tools::getAdminTokenLite('AdminTranslations').'&type=modules&lang=', - 'module_languages' => Language::getLanguages(false), - 'module_name' => Tools::getValue('module_name'), - )); - - $modal_content = $this->context->smarty->fetch('controllers/modules/modal_translation.tpl'); - $this->modals[] = array( - 'modal_id' => 'moduleTradLangSelect', - 'modal_class' => 'modal-sm', - 'modal_title' => $this->l('Translate this module'), - 'modal_content' => $modal_content - ); - - $modal_content = $this->context->smarty->fetch('controllers/modules/'.(($this->context->mode == Context::MODE_HOST) ? 'modal_not_trusted_blocked.tpl' : 'modal_not_trusted.tpl')); - $this->modals[] = array( - 'modal_id' => 'moduleNotTrusted', - 'modal_class' => 'modal-lg', - 'modal_title' => ($this->context->mode == Context::MODE_HOST) ? $this->l('This module cannot be installed') : $this->l('Important Notice'), - 'modal_content' => $modal_content - ); - - $modal_content = $this->context->smarty->fetch('controllers/modules/modal_not_trusted_country.tpl'); - $this->modals[] = array( - 'modal_id' => 'moduleNotTrustedCountry', - 'modal_class' => 'modal-lg', - 'modal_title' => $this->l('This module is Untrusted for your country'), - 'modal_content' => $modal_content - ); - } - - public function initContent() - { - if (Tools::isSubmit('addnewmodule') && $this->context->mode == Context::MODE_HOST) - { - $this->display = 'add'; - $this->context->smarty->assign(array('iso_code' => $this->context->language->iso_code)); - return parent::initContent(); - } - - $this->meta_title = 'Modules'; - - // If we are on a module configuration, no need to load all modules - if (Tools::getValue('configure') != '') - return true; - - $this->initToolbar(); - $this->initPageHeaderToolbar(); - - // Init - $smarty = $this->context->smarty; - $autocomplete_list = 'var moduleList = ['; - $category_filtered = array(); - $filter_categories = explode('|', Configuration::get('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee)); - if (count($filter_categories) > 0) - foreach ($filter_categories as $fc) - if (!empty($fc)) - $category_filtered[$fc] = 1; - - if (empty($category_filtered) && Tools::getValue('tab_module')) - $category_filtered[Tools::getValue('tab_module')] = 1; - - foreach ($this->list_modules_categories as $k => $v) - $this->list_modules_categories[$k]['nb'] = 0; - - // Retrieve Modules Preferences - $modules_preferences = ''; - $tab_modules_preferences = array(); - $modules_preferences_tmp = Db::getInstance()->executeS('SELECT * FROM `'._DB_PREFIX_.'module_preference` WHERE `id_employee` = '.(int)$this->id_employee); - $tab_modules_preferences_tmp = Db::getInstance()->executeS('SELECT * FROM `'._DB_PREFIX_.'tab_module_preference` WHERE `id_employee` = '.(int)$this->id_employee); - - foreach ($tab_modules_preferences_tmp as $i => $j) - $tab_modules_preferences[$j['module']][] = $j['id_tab']; - - foreach ($modules_preferences_tmp as $k => $v) - { - if ($v['interest'] == null) - unset($v['interest']); - if ($v['favorite'] == null) - unset($v['favorite']); - $modules_preferences[$v['module']] = $v; - } - - // Retrieve Modules List - $modules = Module::getModulesOnDisk(true, $this->logged_on_addons, $this->id_employee); - $this->initModulesList($modules); - $this->nb_modules_total = count($modules); - $module_errors = array(); - $module_success = array(); - $upgrade_available = array(); - $dont_filter = false; - - //Add succes message for one module update - if (Tools::getValue('updated') && Tools::getValue('module_name')) - { - $module_names = (string)Tools::getValue('module_name'); - if (strpos($module_names, '|')) - { - $module_names = explode('|', $module_names); - $dont_filter = true; - } - - if (!is_array($module_names)) - $module_names = (array)$module_names; - - foreach ($modules as $km => $module) - if (in_array($module->name, $module_names)) - $module_success[] = array('name' => $module->displayName, 'message' => array( - 0 => sprintf($this->l('Current version: %s'), $module->version))); - } - - // Browse modules list - foreach ($modules as $km => $module) - { - //if we are in favorites view we only display installed modules - if (Tools::getValue('select') == 'favorites' && !$module->id) - { - unset($modules[$km]); - continue; - } - - // Upgrade Module process, init check if a module could be upgraded - if (Module::initUpgradeModule($module)) - { - // When the XML cache file is up-to-date, the module may not be loaded yet - if (!class_exists($module->name)) - { - if (!file_exists(_PS_MODULE_DIR_.$module->name.'/'.$module->name.'.php')) - continue; - require_once(_PS_MODULE_DIR_.$module->name.'/'.$module->name.'.php'); - } - - if ($object = new $module->name()) - { - /** @var Module $object */ - $object->runUpgradeModule(); - if ((count($errors_module_list = $object->getErrors()))) - $module_errors[] = array('name' => $module->displayName, 'message' => $errors_module_list); - elseif ((count($conf_module_list = $object->getConfirmations()))) - $module_success[] = array('name' => $module->displayName, 'message' => $conf_module_list); - unset($object); - } - } - // Module can't be upgraded if not file exist but can change the database version... - // User has to be prevented - elseif (Module::getUpgradeStatus($module->name)) - { - // When the XML cache file is up-to-date, the module may not be loaded yet - if (!class_exists($module->name)) - if (file_exists(_PS_MODULE_DIR_.$module->name.'/'.$module->name.'.php')) - { - require_once(_PS_MODULE_DIR_.$module->name.'/'.$module->name.'.php'); - $object = new $module->name(); - $module_success[] = array('name' => $module->name, 'message' => array( - 0 => sprintf($this->l('Current version: %s'), $object->version), - 1 => $this->l('No file upgrades applied (none exist).')) - ); - } - else - continue; - unset($object); - } - - // Make modules stats - $this->makeModulesStats($module); - - // Assign warnings - if ($module->active && isset($module->warning) && !empty($module->warning) && !$this->ajax) - { - $href = Context::getContext()->link->getAdminLink('AdminModules', true).'&module_name='.$module->name.'&tab_module='.$module->tab.'&configure='.$module->name; - $this->context->smarty->assign('text', sprintf($this->l('%1$s: %2$s'), $module->displayName, $module->warning)); - $this->context->smarty->assign('module_link', $href); - $this->displayWarning($this->context->smarty->fetch('controllers/modules/warning_module.tpl')); - } - - // AutoComplete array - $autocomplete_list .= Tools::jsonEncode(array( - 'displayName' => (string)$module->displayName, - 'desc' => (string)$module->description, - 'name' => (string)$module->name, - 'author' => (string)$module->author, - 'image' => (isset($module->image) ? (string)$module->image : ''), - 'option' => '', - )).', '; - - // Apply filter - if ($this->isModuleFiltered($module) && Tools::getValue('select') != 'favorites') - unset($modules[$km]); - else - { - if (isset($modules_preferences[$modules[$km]->name])) - $modules[$km]->preferences = $modules_preferences[$modules[$km]->name]; - - $this->fillModuleData($module, 'array'); - $module->categoryName = (isset($this->list_modules_categories[$module->tab]['name']) ? $this->list_modules_categories[$module->tab]['name'] : $this->list_modules_categories['others']['name']); - } - unset($object); - if ($module->installed && isset($module->version_addons) && $module->version_addons) - $upgrade_available[] = array('anchor' => ucfirst($module->name), 'name' => $module->name, 'displayName' => $module->displayName); - - if (in_array($module->name, $this->list_partners_modules)) - $module->type = 'addonsPartner'; - - if (isset($module->description_full) && trim($module->description_full) != '') - $module->show_quick_view = true; - } - - // Don't display categories without modules - $cleaned_list = array(); - foreach ($this->list_modules_categories as $k => $list) - if ($list['nb'] > 0) - $cleaned_list[$k] = $list; - - // Actually used for the report of the upgraded errors - if (count($module_errors)) - { - $html = $this->generateHtmlMessage($module_errors); - $this->errors[] = sprintf(Tools::displayError('The following module(s) were not upgraded successfully: %s.'), $html); - } - if (count($module_success)) - { - $html = $this->generateHtmlMessage($module_success); - $this->confirmations[] = sprintf($this->l('The following module(s) were upgraded successfully: %s.'), $html); - } - - ConfigurationKPI::updateValue('UPDATE_MODULES', count($upgrade_available)); - - if (count($upgrade_available) == 0 && (int)Tools::getValue('check') == 1) - $this->confirmations[] = $this->l('Everything is up-to-date'); - - // Init tpl vars for smarty - $tpl_vars = array( - 'token' => $this->token, - 'upgrade_available' => $upgrade_available, - 'currentIndex' => self::$currentIndex, - 'dirNameCurrentIndex' => dirname(self::$currentIndex), - 'ajaxCurrentIndex' => str_replace('index', 'ajax-tab', self::$currentIndex), - 'autocompleteList' => rtrim($autocomplete_list, ' ,').'];', - 'showTypeModules' => $this->filter_configuration['PS_SHOW_TYPE_MODULES_'.(int)$this->id_employee], - 'showCountryModules' => $this->filter_configuration['PS_SHOW_COUNTRY_MODULES_'.(int)$this->id_employee], - 'showInstalledModules' => $this->filter_configuration['PS_SHOW_INSTALLED_MODULES_'.(int)$this->id_employee], - 'showEnabledModules' => $this->filter_configuration['PS_SHOW_ENABLED_MODULES_'.(int)$this->id_employee], - 'nameCountryDefault' => Country::getNameById($this->context->language->id, Configuration::get('PS_COUNTRY_DEFAULT')), - 'isoCountryDefault' => $this->iso_default_country, - 'categoryFiltered' => $category_filtered, - 'modules' => $modules, - 'nb_modules' => $this->nb_modules_total, - 'nb_modules_favorites' => count($this->context->employee->favoriteModulesList()), - 'nb_modules_installed' => $this->nb_modules_installed, - 'nb_modules_uninstalled' => $this->nb_modules_total - $this->nb_modules_installed, - 'nb_modules_activated' => $this->nb_modules_activated, - 'nb_modules_unactivated' => $this->nb_modules_installed - $this->nb_modules_activated, - 'list_modules_categories' => $cleaned_list, - 'list_modules_authors' => $this->modules_authors, - 'add_permission' => $this->tabAccess['add'], - 'tab_modules_preferences' => $tab_modules_preferences, - 'kpis' => $this->renderKpis(), - 'module_name' => Tools::getValue('module_name'), - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn, - 'modules_uri' => __PS_BASE_URI__.basename(_PS_MODULE_DIR_), - 'dont_filter' => $dont_filter, - 'is_contributor' => (int)$this->context->cookie->is_contributor - ); - - if ($this->logged_on_addons) - { - $tpl_vars['logged_on_addons'] = 1; - $tpl_vars['username_addons'] = $this->context->cookie->username_addons; - } - $smarty->assign($tpl_vars); - } - - public function ajaxProcessGetModuleQuickView() - { - $modules = Module::getModulesOnDisk(); - - foreach ($modules as $module) - if ($module->name == Tools::getValue('module')) - break; - - $url = $module->url; - - if (isset($module->type) && ($module->type == 'addonsPartner' || $module->type == 'addonsNative')) - $url = $this->context->link->getAdminLink('AdminModules').'&install='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name); - - $this->context->smarty->assign(array( - 'displayName' => $module->displayName, - 'image' => $module->image, - 'nb_rates' => (int)$module->nb_rates[0], - 'avg_rate' => (int)$module->avg_rate[0], - 'badges' => $module->badges, - 'compatibility' => $module->compatibility, - 'description_full' => $module->description_full, - 'additional_description' => $module->additional_description, - 'is_addons_partner' => (isset($module->type) && ($module->type == 'addonsPartner' || $module->type == 'addonsNative')), - 'url' => $url, - 'price' => $module->price - )); - $this->smartyOutputContent('controllers/modules/quickview.tpl'); - } + $this->list_modules_categories['seo']['name'] = $this->l('SEO'); + $this->list_modules_categories['shipping_logistics']['name'] = $this->l('Shipping and Logistics'); + $this->list_modules_categories['slideshows']['name'] = $this->l('Slideshows'); + $this->list_modules_categories['smart_shopping']['name'] = $this->l('Comparison site & Feed management'); + $this->list_modules_categories['market_place']['name'] = $this->l('Marketplace'); + $this->list_modules_categories['others']['name'] = $this->l('Other Modules'); + $this->list_modules_categories['mobile']['name'] = $this->l('Mobile'); + $this->list_modules_categories['dashboard']['name'] = $this->l('Dashboard'); + $this->list_modules_categories['i18n_localization']['name'] = $this->l('Internationalization & Localization'); + $this->list_modules_categories['emailing']['name'] = $this->l('Emailing & SMS'); + $this->list_modules_categories['social_networks']['name'] = $this->l('Social Networks'); + $this->list_modules_categories['social_community']['name'] = $this->l('Social & Community'); + + uasort($this->list_modules_categories, array($this, 'checkCategoriesNames')); + + // Set Id Employee, Iso Default Country and Filter Configuration + $this->id_employee = (int)$this->context->employee->id; + $this->iso_default_country = $this->context->country->iso_code; + $this->filter_configuration = Configuration::getMultiple(array( + 'PS_SHOW_TYPE_MODULES_'.(int)$this->id_employee, + 'PS_SHOW_COUNTRY_MODULES_'.(int)$this->id_employee, + 'PS_SHOW_INSTALLED_MODULES_'.(int)$this->id_employee, + 'PS_SHOW_ENABLED_MODULES_'.(int)$this->id_employee, + 'PS_SHOW_CAT_MODULES_'.(int)$this->id_employee, + )); + + // Load cache file modules list (natives and partners modules) + $xml_modules = false; + if (file_exists(_PS_ROOT_DIR_.Module::CACHE_FILE_MODULES_LIST)) { + $xml_modules = @simplexml_load_file(_PS_ROOT_DIR_.Module::CACHE_FILE_MODULES_LIST); + } + if ($xml_modules) { + foreach ($xml_modules->children() as $xml_module) { + /** @var SimpleXMLElement $xml_module */ + foreach ($xml_module->children() as $module) { + /** @var SimpleXMLElement $module */ + foreach ($module->attributes() as $key => $value) { + if ($xml_module->attributes() == 'native' && $key == 'name') { + $this->list_natives_modules[] = (string)$value; + } + if ($xml_module->attributes() == 'partner' && $key == 'name') { + $this->list_partners_modules[] = (string)$value; + } + } + } + } + } + } + + public function checkCategoriesNames($a, $b) + { + if ($a['name'] === $this->l('Other Modules')) { + return true; + } + + return (bool)($a['name'] > $b['name']); + } + + public function setMedia() + { + parent::setMedia(); + $this->addJqueryPlugin(array('autocomplete', 'fancybox', 'tablefilter')); + + if ($this->context->mode == Context::MODE_HOST && Tools::isSubmit('addnewmodule')) { + $this->addJS(_PS_JS_DIR_.'admin/addons.js'); + } + } + + public function ajaxProcessRefreshModuleList($force_reload_cache = false) + { + // Refresh modules_list.xml every week + if (!$this->isFresh(Module::CACHE_FILE_MODULES_LIST, 86400) || $force_reload_cache) { + if ($this->refresh(Module::CACHE_FILE_MODULES_LIST, 'https://'.$this->xml_modules_list)) { + $this->status = 'refresh'; + } elseif ($this->refresh(Module::CACHE_FILE_MODULES_LIST, 'http://'.$this->xml_modules_list)) { + $this->status = 'refresh'; + } else { + $this->status = 'error'; + } + } else { + $this->status = 'cache'; + } + + // If logged to Addons Webservices, refresh default country native modules list every day + if ($this->status != 'error') { + if (!$this->isFresh(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 86400) || $force_reload_cache) { + if (file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, Tools::addonsRequest('native'))) { + $this->status = 'refresh'; + } else { + $this->status = 'error'; + } + } else { + $this->status = 'cache'; + } + + if (!$this->isFresh(Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, 86400) || $force_reload_cache) { + if (file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, Tools::addonsRequest('must-have'))) { + $this->status = 'refresh'; + } else { + $this->status = 'error'; + } + } else { + $this->status = 'cache'; + } + } + + // If logged to Addons Webservices, refresh customer modules list every 5 minutes + if ($this->logged_on_addons && $this->status != 'error') { + if (!$this->isFresh(Module::CACHE_FILE_CUSTOMER_MODULES_LIST, 300) || $force_reload_cache) { + if (file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_CUSTOMER_MODULES_LIST, Tools::addonsRequest('customer'))) { + $this->status = 'refresh'; + } else { + $this->status = 'error'; + } + } else { + $this->status = 'cache'; + } + } + } + + public function displayAjaxRefreshModuleList() + { + echo Tools::jsonEncode(array('status' => $this->status)); + } + + + public function ajaxProcessLogOnAddonsWebservices() + { + $content = Tools::addonsRequest('check_customer', array('username_addons' => pSQL(trim(Tools::getValue('username_addons'))), 'password_addons' => pSQL(trim(Tools::getValue('password_addons'))))); + $xml = @simplexml_load_string($content, null, LIBXML_NOCDATA); + if (!$xml) { + die('KO'); + } + $result = strtoupper((string)$xml->success); + if (!in_array($result, array('OK', 'KO'))) { + die('KO'); + } + if ($result == 'OK') { + Tools::clearXMLCache(); + Configuration::updateValue('PS_LOGGED_ON_ADDONS', 1); + $this->context->cookie->username_addons = pSQL(trim(Tools::getValue('username_addons'))); + $this->context->cookie->password_addons = pSQL(trim(Tools::getValue('password_addons'))); + $this->context->cookie->is_contributor = (int)$xml->is_contributor; + $this->context->cookie->write(); + } + die($result); + } + + public function ajaxProcessLogOutAddonsWebservices() + { + $this->context->cookie->username_addons = ''; + $this->context->cookie->password_addons = ''; + $this->context->cookie->is_contributor = 0; + $this->context->cookie->write(); + die('OK'); + } + + public function ajaxProcessReloadModulesList() + { + if (Tools::getValue('filterCategory')) { + Configuration::updateValue('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee, Tools::getValue('filterCategory')); + } + if (Tools::getValue('unfilterCategory')) { + Configuration::updateValue('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee, ''); + } + + $this->initContent(); + $this->smartyOutputContent('controllers/modules/list.tpl'); + exit; + } + + public function ajaxProcessGetTabModulesList() + { + $tab_modules_list = Tools::getValue('tab_modules_list'); + $back = Tools::getValue('back_tab_modules_list'); + if ($back) { + $back .= '&tab_modules_open=1'; + } + $modules_list = array('installed' =>array(), 'not_installed' => array()); + if ($tab_modules_list) { + $tab_modules_list = explode(',', $tab_modules_list); + $modules_list_unsort = $this->getModulesByInstallation($tab_modules_list); + } + + $installed = $uninstalled = array(); + foreach ($tab_modules_list as $key => $value) { + $continue = 0; + foreach ($modules_list_unsort['installed'] as $mod_in) { + if ($mod_in->name == $value) { + $continue = 1; + $installed[] = $mod_in; + } + } + if ($continue) { + continue; + } + foreach ($modules_list_unsort['not_installed'] as $mod_in) { + if ($mod_in->name == $value) { + $uninstalled[] = $mod_in; + } + } + } + + $modules_list_sort = array( + 'installed' => $installed, + 'not_installed' => $uninstalled + ); + + $this->context->smarty->assign(array( + 'tab_modules_list' => $modules_list_sort, + 'admin_module_favorites_view' => $this->context->link->getAdminLink('AdminModules').'&select=favorites', + )); + + $this->smartyOutputContent('controllers/modules/tab_modules_list.tpl'); + exit; + } + + public function ajaxProcessSetFilter() + { + $this->setFilterModules(Tools::getValue('module_type'), Tools::getValue('country_module_value'), Tools::getValue('module_install'), Tools::getValue('module_status')); + die('OK'); + } + + public function ajaxProcessSaveFavoritePreferences() + { + $action = Tools::getValue('action_pref'); + $value = Tools::getValue('value_pref'); + $module = Tools::getValue('module_pref'); + $id_module_preference = (int)Db::getInstance()->getValue('SELECT `id_module_preference` FROM `'._DB_PREFIX_.'module_preference` WHERE `id_employee` = '.(int)$this->id_employee.' AND `module` = \''.pSQL($module).'\''); + if ($id_module_preference > 0) { + if ($action == 'i') { + $update = array('interest' => ($value == '' ? null : (int)$value)); + } + if ($action == 'f') { + $update = array('favorite' => ($value == '' ? null : (int)$value)); + } + Db::getInstance()->update('module_preference', $update, '`id_employee` = '.(int)$this->id_employee.' AND `module` = \''.pSQL($module).'\'', 0, true); + } else { + $insert = array('id_employee' => (int)$this->id_employee, 'module' => pSQL($module), 'interest' => null, 'favorite' => null); + if ($action == 'i') { + $insert['interest'] = ($value == '' ? null : (int)$value); + } + if ($action == 'f') { + $insert['favorite'] = ($value == '' ? null : (int)$value); + } + Db::getInstance()->insert('module_preference', $insert, true); + } + die('OK'); + } + + public function ajaxProcessSaveTabModulePreferences() + { + $values = Tools::getValue('value_pref'); + $module = Tools::getValue('module_pref'); + if (Validate::isModuleName($module)) { + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'tab_module_preference` WHERE `id_employee` = '.(int)$this->id_employee.' AND `module` = \''.pSQL($module).'\''); + if (is_array($values) && count($values)) { + foreach ($values as $value) { + Db::getInstance()->execute(' + INSERT INTO `'._DB_PREFIX_.'tab_module_preference` (`id_tab_module_preference`, `id_employee`, `id_tab`, `module`) + VALUES (NULL, '.(int)$this->id_employee.', '.(int)$value.', \''.pSQL($module).'\');'); + } + } + } + die('OK'); + } + + /* + ** Get current URL + ** + ** @param array $remove List of keys to remove from URL + ** @return string + */ + protected function getCurrentUrl($remove = array()) + { + $url = $_SERVER['REQUEST_URI']; + if (!$remove) { + return $url; + } + + if (!is_array($remove)) { + $remove = array($remove); + } + + $url = preg_replace('#(?<=&|\?)('.implode('|', $remove).')=.*?(&|$)#i', '', $url); + $len = strlen($url); + if ($url[$len - 1] == '&') { + $url = substr($url, 0, $len - 1); + } + return $url; + } + + protected function extractArchive($file, $redirect = true) + { + $zip_folders = array(); + $tmp_folder = _PS_MODULE_DIR_.md5(time()); + + $success = false; + if (substr($file, -4) == '.zip') { + if (Tools::ZipExtract($file, $tmp_folder)) { + $zip_folders = scandir($tmp_folder); + if (Tools::ZipExtract($file, _PS_MODULE_DIR_)) { + $success = true; + } + } + } else { + require_once(_PS_TOOL_DIR_.'tar/Archive_Tar.php'); + $archive = new Archive_Tar($file); + if ($archive->extract($tmp_folder)) { + $zip_folders = scandir($tmp_folder); + if ($archive->extract(_PS_MODULE_DIR_)) { + $success = true; + } + } + } + + if (!$success) { + $this->errors[] = Tools::displayError('There was an error while extracting the module (file may be corrupted).'); + } else { + //check if it's a real module + foreach ($zip_folders as $folder) { + if (!in_array($folder, array('.', '..', '.svn', '.git', '__MACOSX')) && !Module::getInstanceByName($folder)) { + $this->errors[] = sprintf(Tools::displayError('The module %1$s that you uploaded is not a valid module.'), $folder); + $this->recursiveDeleteOnDisk(_PS_MODULE_DIR_.$folder); + } + } + } + + @unlink($file); + $this->recursiveDeleteOnDisk($tmp_folder); + + if ($success && $redirect) { + Tools::redirectAdmin(self::$currentIndex.'&conf=8&anchor='.ucfirst($folder).'&token='.$this->token); + } + + return $success; + } + + protected function recursiveDeleteOnDisk($dir) + { + if (strpos(realpath($dir), realpath(_PS_MODULE_DIR_)) === false) { + return; + } + if (is_dir($dir)) { + $objects = scandir($dir); + foreach ($objects as $object) { + if ($object != '.' && $object != '..') { + if (filetype($dir.'/'.$object) == 'dir') { + $this->recursiveDeleteOnDisk($dir.'/'.$object); + } else { + unlink($dir.'/'.$object); + } + } + } + reset($objects); + rmdir($dir); + } + } + + /* + ** Filter Configuration Methods + ** Set and reset filter configuration + */ + + protected function setFilterModules($module_type, $country_module_value, $module_install, $module_status) + { + Configuration::updateValue('PS_SHOW_TYPE_MODULES_'.(int)$this->id_employee, $module_type); + Configuration::updateValue('PS_SHOW_COUNTRY_MODULES_'.(int)$this->id_employee, $country_module_value); + Configuration::updateValue('PS_SHOW_INSTALLED_MODULES_'.(int)$this->id_employee, $module_install); + Configuration::updateValue('PS_SHOW_ENABLED_MODULES_'.(int)$this->id_employee, $module_status); + } + + protected function resetFilterModules() + { + Configuration::updateValue('PS_SHOW_TYPE_MODULES_'.(int)$this->id_employee, 'allModules'); + Configuration::updateValue('PS_SHOW_COUNTRY_MODULES_'.(int)$this->id_employee, 0); + Configuration::updateValue('PS_SHOW_INSTALLED_MODULES_'.(int)$this->id_employee, 'installedUninstalled'); + Configuration::updateValue('PS_SHOW_ENABLED_MODULES_'.(int)$this->id_employee, 'enabledDisabled'); + Configuration::updateValue('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee, ''); + } + + /* + ** Post Process Filter + ** + */ + + public function postProcessFilterModules() + { + $this->setFilterModules(Tools::getValue('module_type'), Tools::getValue('country_module_value'), Tools::getValue('module_install'), Tools::getValue('module_status')); + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } + + public function postProcessResetFilterModules() + { + $this->resetFilterModules(); + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } + + public function postProcessFilterCategory() + { + // Save configuration and redirect employee + Configuration::updateValue('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee, Tools::getValue('filterCategory')); + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } + + public function postProcessUnfilterCategory() + { + // Save configuration and redirect employee + Configuration::updateValue('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee, ''); + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } + + /* + ** Post Process Module CallBack + ** + */ + + public function postProcessReset() + { + if ($this->tabAccess['edit'] === '1') { + $module = Module::getInstanceByName(Tools::getValue('module_name')); + if (Validate::isLoadedObject($module)) { + if (!$module->getPermission('configure')) { + $this->errors[] = Tools::displayError('You do not have the permission to use this module.'); + } else { + if (Tools::getValue('keep_data') == '1' && method_exists($module, 'reset')) { + if ($module->reset()) { + Tools::redirectAdmin(self::$currentIndex.'&conf=21&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name)); + } else { + $this->errors[] = Tools::displayError('Cannot reset this module.'); + } + } else { + if ($module->uninstall()) { + if ($module->install()) { + Tools::redirectAdmin(self::$currentIndex.'&conf=21&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name)); + } else { + $this->errors[] = Tools::displayError('Cannot install this module.'); + } + } else { + $this->errors[] = Tools::displayError('Cannot uninstall this module.'); + } + } + } + } else { + $this->errors[] = Tools::displayError('Cannot load the module\'s object.'); + } + + if (($errors = $module->getErrors()) && is_array($errors)) { + $this->errors = array_merge($this->errors, $errors); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } + + public function postProcessDownload() + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_ || ($this->context->mode == Context::MODE_HOST)) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } + + // Try to upload and unarchive the module + if ($this->tabAccess['add'] === '1') { + // UPLOAD_ERR_OK: 0 + // UPLOAD_ERR_INI_SIZE: 1 + // UPLOAD_ERR_FORM_SIZE: 2 + // UPLOAD_ERR_NO_TMP_DIR: 6 + // UPLOAD_ERR_CANT_WRITE: 7 + // UPLOAD_ERR_EXTENSION: 8 + // UPLOAD_ERR_PARTIAL: 3 + + if (isset($_FILES['file']['error']) && $_FILES['file']['error'] != UPLOAD_ERR_OK) { + switch ($_FILES['file']['error']) { + case UPLOAD_ERR_INI_SIZE: + case UPLOAD_ERR_FORM_SIZE: + $this->errors[] = sprintf($this->l('File too large (limit of %s bytes).'), Tools::getMaxUploadSize()); + break; + case UPLOAD_ERR_PARTIAL: + $this->errors[] = $this->l('File upload was not completed.'); + break; + case UPLOAD_ERR_NO_FILE: + $this->errors[] = $this->l('No file was uploaded.'); + break; + default: + $this->errors[] = sprintf($this->l('Internal error #%s'), $_FILES['newfile']['error']); + break; + } + } elseif (!isset($_FILES['file']['tmp_name']) || empty($_FILES['file']['tmp_name'])) { + $this->errors[] = $this->l('No file has been selected'); + } elseif (substr($_FILES['file']['name'], -4) != '.tar' && substr($_FILES['file']['name'], -4) != '.zip' + && substr($_FILES['file']['name'], -4) != '.tgz' && substr($_FILES['file']['name'], -7) != '.tar.gz') { + $this->errors[] = Tools::displayError('Unknown archive type.'); + } elseif (!move_uploaded_file($_FILES['file']['tmp_name'], _PS_MODULE_DIR_.$_FILES['file']['name'])) { + $this->errors[] = Tools::displayError('An error occurred while copying the archive to the module directory.'); + } else { + $this->extractArchive(_PS_MODULE_DIR_.$_FILES['file']['name']); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } + + public function postProcessEnable() + { + if ($this->tabAccess['edit'] === '1') { + $module = Module::getInstanceByName(Tools::getValue('module_name')); + if (Validate::isLoadedObject($module)) { + if (!$module->getPermission('configure')) { + $this->errors[] = Tools::displayError('You do not have the permission to use this module.'); + } else { + if (Tools::getValue('enable')) { + $module->enable(); + } else { + $module->disable(); + } + Tools::redirectAdmin($this->getCurrentUrl('enable')); + } + } else { + $this->errors[] = Tools::displayError('Cannot load the module\'s object.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } + + public function postProcessEnable_Device() + { + if ($this->tabAccess['edit'] === '1') { + $module = Module::getInstanceByName(Tools::getValue('module_name')); + if (Validate::isLoadedObject($module)) { + if (!$module->getPermission('configure')) { + $this->errors[] = Tools::displayError('You do not have the permission to use this module.'); + } else { + $module->enableDevice((int)Tools::getValue('enable_device')); + Tools::redirectAdmin($this->getCurrentUrl('enable_device')); + } + } else { + $this->errors[] = Tools::displayError('Cannot load the module\'s object.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } + + public function postProcessDisable_Device() + { + if ($this->tabAccess['edit'] === '1') { + $module = Module::getInstanceByName(Tools::getValue('module_name')); + if (Validate::isLoadedObject($module)) { + if (!$module->getPermission('configure')) { + $this->errors[] = Tools::displayError('You do not have the permission to use this module.'); + } else { + $module->disableDevice((int)Tools::getValue('disable_device')); + Tools::redirectAdmin($this->getCurrentUrl('disable_device')); + } + } else { + $this->errors[] = Tools::displayError('Cannot load the module\'s object.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } + + public function postProcessDelete() + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } + + if ($this->tabAccess['delete'] === '1') { + if (Tools::getValue('module_name') != '') { + $module = Module::getInstanceByName(Tools::getValue('module_name')); + if (Validate::isLoadedObject($module) && !$module->getPermission('configure')) { + $this->errors[] = Tools::displayError('You do not have the permission to use this module.'); + } else { + // Uninstall the module before deleting the files, but do not block the process if uninstall returns false + if (Module::isInstalled($module->name)) { + $module->uninstall(); + } + $moduleDir = _PS_MODULE_DIR_.str_replace(array('.', '/', '\\'), array('', '', ''), Tools::getValue('module_name')); + $this->recursiveDeleteOnDisk($moduleDir); + if (!file_exists($moduleDir)) { + Tools::redirectAdmin(self::$currentIndex.'&conf=22&token='.$this->token.'&tab_module='.Tools::getValue('tab_module').'&module_name='.Tools::getValue('module_name')); + } else { + $this->errors[] = Tools::displayError('Sorry, the module cannot be deleted. Please check if you have the right permissions on this folder.'); + } + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } + + public function postProcessCallback() + { + $return = false; + $installed_modules = array(); + + foreach ($this->map as $key => $method) { + if (!Tools::getValue($key)) { + continue; + } + + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } + + if ($key == 'check') { + $this->ajaxProcessRefreshModuleList(true); + } elseif ($key == 'checkAndUpdate') { + $modules = array(); + $this->ajaxProcessRefreshModuleList(true); + $modules_on_disk = Module::getModulesOnDisk(true, $this->logged_on_addons, $this->id_employee); + + // Browse modules list + foreach ($modules_on_disk as $km => $module_on_disk) { + if (!Tools::getValue('module_name') && isset($module_on_disk->version_addons) && $module_on_disk->version_addons) { + $modules[] = $module_on_disk->name; + } + } + + if (!Tools::getValue('module_name')) { + $modules_list_save = implode('|', $modules); + } + } elseif (($modules = Tools::getValue($key)) && $key != 'checkAndUpdate' && $key != 'updateAll') { + if (strpos($modules, '|')) { + $modules_list_save = $modules; + $modules = explode('|', $modules); + } + + if (!is_array($modules)) { + $modules = (array)$modules; + } + } elseif ($key == 'updateAll') { + $loggedOnAddons = false; + + if (isset($this->context->cookie->username_addons) + && isset($this->context->cookie->password_addons) + && !empty($this->context->cookie->username_addons) + && !empty($this->context->cookie->password_addons)) { + $loggedOnAddons = true; + } + + $allModules = Module::getModulesOnDisk(true, $loggedOnAddons, $this->context->employee->id); + $upgradeAvailable = 0; + $modules = array(); + + foreach ($allModules as $km => $moduleToUpdate) { + if ($moduleToUpdate->installed && isset($moduleToUpdate->version_addons) && $moduleToUpdate->version_addons) { + $modules[] = (string)$moduleToUpdate->name; + } + } + } + + $module_upgraded = array(); + $module_errors = array(); + if (isset($modules)) { + foreach ($modules as $name) { + $module_to_update = array(); + $module_to_update[$name] = null; + $full_report = null; + // If Addons module, download and unzip it before installing it + if (!file_exists(_PS_MODULE_DIR_.$name.'/'.$name.'.php') || $key == 'update' || $key == 'updateAll') { + $files_list = array( + array('type' => 'addonsNative', 'file' => Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 'loggedOnAddons' => 0), + array('type' => 'addonsBought', 'file' => Module::CACHE_FILE_CUSTOMER_MODULES_LIST, 'loggedOnAddons' => 1), + ); + + foreach ($files_list as $f) { + if (file_exists(_PS_ROOT_DIR_.$f['file'])) { + $file = $f['file']; + $content = Tools::file_get_contents(_PS_ROOT_DIR_.$file); + if ($xml = @simplexml_load_string($content, null, LIBXML_NOCDATA)) { + foreach ($xml->module as $modaddons) { + if (Tools::strtolower($name) == Tools::strtolower($modaddons->name)) { + $module_to_update[$name]['id'] = $modaddons->id; + $module_to_update[$name]['displayName'] = $modaddons->displayName; + $module_to_update[$name]['need_loggedOnAddons'] = $f['loggedOnAddons']; + } + } + } + } + } + + foreach ($module_to_update as $name => $attr) { + if ((is_null($attr) && $this->logged_on_addons == 0) || ($attr['need_loggedOnAddons'] == 1 && $this->logged_on_addons == 0)) { + $this->errors[] = sprintf(Tools::displayError('You need to be logged in to your PrestaShop Addons account in order to update the %s module. %s'), '<strong>'.$name.'</strong>', '<a href="#" class="addons_connect" data-toggle="modal" data-target="#modal_addons_connect" title="Addons">'.$this->l('Click here to log in.').'</a>'); + } elseif (!is_null($attr['id'])) { + $download_ok = false; + if ($attr['need_loggedOnAddons'] == 0 && file_put_contents(_PS_MODULE_DIR_.$name.'.zip', Tools::addonsRequest('module', array('id_module' => pSQL($attr['id']))))) { + $download_ok = true; + } elseif ($attr['need_loggedOnAddons'] == 1 && $this->logged_on_addons && file_put_contents(_PS_MODULE_DIR_.$name.'.zip', Tools::addonsRequest('module', array('id_module' => pSQL($attr['id']), 'username_addons' => pSQL(trim($this->context->cookie->username_addons)), 'password_addons' => pSQL(trim($this->context->cookie->password_addons)))))) { + $download_ok = true; + } + + if (!$download_ok) { + $this->errors[] = sprintf(Tools::displayError('Module %s cannot be upgraded: Error while downloading the latest version.'), '<strong>'.$attr['displayName'].'</strong>'); + } elseif (!$this->extractArchive(_PS_MODULE_DIR_.$name.'.zip', false)) { + $this->errors[] = sprintf(Tools::displayError('Module %s cannot be upgraded: Error while extracting the latest version.'), '<strong>'.$attr['displayName'].'</strong>'); + } else { + $module_upgraded[] = $name; + } + } else { + $this->errors[] = sprintf(Tools::displayError('You do not have the rights to update the %s module. Please make sure you are logged in to the PrestaShop Addons account that purchased the module.'), '<strong>'.$name.'</strong>'); + } + } + } + + if (count($this->errors)) { + continue; + } + + // Check potential error + if (!($module = Module::getInstanceByName(urldecode($name)))) { + $this->errors[] = $this->l('Module not found'); + } elseif (($this->context->mode >= Context::MODE_HOST_CONTRIB) && in_array($module->name, Module::$hosted_modules_blacklist)) { + $this->errors[] = Tools::displayError('You do not have permission to access this module.'); + } elseif ($key == 'install' && $this->tabAccess['add'] !== '1') { + $this->errors[] = Tools::displayError('You do not have permission to install this module.'); + } elseif ($key == 'install' && ($this->context->mode == Context::MODE_HOST) && !Module::isModuleTrusted($module->name)) { + $this->errors[] = Tools::displayError('You do not have permission to install this module.'); + } elseif ($key == 'delete' && ($this->tabAccess['delete'] !== '1' || !$module->getPermission('configure'))) { + $this->errors[] = Tools::displayError('You do not have permission to delete this module.'); + } elseif ($key == 'configure' && ($this->tabAccess['edit'] !== '1' || !$module->getPermission('configure') || !Module::isInstalled(urldecode($name)))) { + $this->errors[] = Tools::displayError('You do not have permission to configure this module.'); + } elseif ($key == 'install' && Module::isInstalled($module->name)) { + $this->errors[] = sprintf(Tools::displayError('This module is already installed: %s.'), $module->name); + } elseif ($key == 'uninstall' && !Module::isInstalled($module->name)) { + $this->errors[] = sprintf(Tools::displayError('This module has already been uninstalled: %s.'), $module->name); + } elseif ($key == 'update' && !Module::isInstalled($module->name)) { + $this->errors[] = sprintf(Tools::displayError('This module needs to be installed in order to be updated: %s.'), $module->name); + } else { + // If we install a module, force temporary global context for multishop + if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL && $method != 'getContent') { + $shop_id = (int)Context::getContext()->shop->id; + Context::getContext()->tmpOldShop = clone(Context::getContext()->shop); + if ($shop_id) { + Context::getContext()->shop = new Shop($shop_id); + } + } + + //retrocompatibility + if (Tools::getValue('controller') != '') { + $_POST['tab'] = Tools::safeOutput(Tools::getValue('controller')); + } + + $echo = ''; + if ($key != 'update' && $key != 'updateAll' && $key != 'checkAndUpdate') { + // We check if method of module exists + if (!method_exists($module, $method)) { + throw new PrestaShopException('Method of module cannot be found'); + } + + if ($key == 'uninstall' && !Module::getPermissionStatic($module->id, 'uninstall')) { + $this->errors[] = Tools::displayError('You do not have permission to uninstall this module.'); + } + + if (count($this->errors)) { + continue; + } + // Get the return value of current method + $echo = $module->{$method}(); + + // After a successful install of a single module that has a configuration method, to the configuration page + if ($key == 'install' && $echo === true && strpos(Tools::getValue('install'), '|') === false && method_exists($module, 'getContent')) { + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&configure='.$module->name.'&conf=12'); + } + } + + // If the method called is "configure" (getContent method), we show the html code of configure page + if ($key == 'configure' && Module::isInstalled($module->name)) { + $this->bootstrap = (isset($module->bootstrap) && $module->bootstrap); + if (isset($module->multishop_context)) { + $this->multishop_context = $module->multishop_context; + } + + $back_link = self::$currentIndex.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name; + $hook_link = 'index.php?tab=AdminModulesPositions&token='.Tools::getAdminTokenLite('AdminModulesPositions').'&show_modules='.(int)$module->id; + $trad_link = 'index.php?tab=AdminTranslations&token='.Tools::getAdminTokenLite('AdminTranslations').'&type=modules&lang='; + $disable_link = $this->context->link->getAdminLink('AdminModules').'&module_name='.$module->name.'&enable=0&tab_module='.$module->tab; + $uninstall_link = $this->context->link->getAdminLink('AdminModules').'&module_name='.$module->name.'&uninstall='.$module->name.'&tab_module='.$module->tab; + $reset_link = $this->context->link->getAdminLink('AdminModules').'&module_name='.$module->name.'&reset&tab_module='.$module->tab; + $update_link = $this->context->link->getAdminLink('AdminModules').'&checkAndUpdate=1&module_name='.$module->name; + + $is_reset_ready = false; + if (method_exists($module, 'reset')) { + $is_reset_ready = true; + } + + $this->context->smarty->assign( + array( + 'module_name' => $module->name, + 'module_display_name' => $module->displayName, + 'back_link' => $back_link, + 'module_hook_link' => $hook_link, + 'module_disable_link' => $disable_link, + 'module_uninstall_link' => $uninstall_link, + 'module_reset_link' => $reset_link, + 'module_update_link' => $update_link, + 'trad_link' => $trad_link, + 'module_languages' => Language::getLanguages(false), + 'theme_language_dir' => _THEME_LANG_DIR_, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn, + 'add_permission' => $this->tabAccess['add'], + 'is_reset_ready' => $is_reset_ready, + ) + ); + + // Display checkbox in toolbar if multishop + if (Shop::isFeatureActive()) { + if (Shop::getContext() == Shop::CONTEXT_SHOP) { + $shop_context = 'shop <strong>'.$this->context->shop->name.'</strong>'; + } elseif (Shop::getContext() == Shop::CONTEXT_GROUP) { + $shop_group = new ShopGroup((int)Shop::getContextShopGroupID()); + $shop_context = 'all shops of group shop <strong>'.$shop_group->name.'</strong>'; + } else { + $shop_context = 'all shops'; + } + + $this->context->smarty->assign(array( + 'module' => $module, + 'display_multishop_checkbox' => true, + 'current_url' => $this->getCurrentUrl('enable'), + 'shop_context' => $shop_context, + )); + } + + $this->context->smarty->assign(array( + 'is_multishop' => Shop::isFeatureActive(), + 'multishop_context' => Shop::CONTEXT_ALL | Shop::CONTEXT_GROUP | Shop::CONTEXT_SHOP + )); + + if (Shop::isFeatureActive() && isset(Context::getContext()->tmpOldShop)) { + Context::getContext()->shop = clone(Context::getContext()->tmpOldShop); + unset(Context::getContext()->tmpOldShop); + } + + // Display module configuration + $header = $this->context->smarty->fetch('controllers/modules/configure.tpl'); + $configuration_bar = $this->context->smarty->fetch('controllers/modules/configuration_bar.tpl'); + + $output = $header.$echo; + + if (isset($this->_modules_ad[$module->name])) { + $ad_modules = $this->getModulesByInstallation($this->_modules_ad[$module->name]); + + foreach ($ad_modules['not_installed'] as $key => &$module) { + if (isset($module->addons_buy_url)) { + $module->addons_buy_url = str_replace('utm_source=v1trunk_api', 'utm_source=back-office', $module->addons_buy_url) + .'&utm_medium=related-modules&utm_campaign=back-office-'.strtoupper($this->context->language->iso_code) + .'&utm_content='.(($this->context->mode >= Context::MODE_HOST_CONTRIB) ? 'cloud' : 'download'); + } + if (isset($module->description_full) && trim($module->description_full) != '') { + $module->show_quick_view = true; + } + } + $this->context->smarty->assign(array( + 'ad_modules' => $ad_modules, + 'currentIndex' => self::$currentIndex + )); + $ad_bar = $this->context->smarty->fetch('controllers/modules/ad_bar.tpl'); + $output .= $ad_bar; + } + + $this->context->smarty->assign('module_content', $output.$configuration_bar); + } elseif ($echo === true) { + $return = 13; + if ($method == 'install') { + $return = 12; + $installed_modules[] = $module->id; + } + } elseif ($echo === false) { + $module_errors[] = array('name' => $name, 'message' => $module->getErrors()); + } + + if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL && isset(Context::getContext()->tmpOldShop)) { + Context::getContext()->shop = clone(Context::getContext()->tmpOldShop); + unset(Context::getContext()->tmpOldShop); + } + } + if ($key != 'configure' && Tools::getIsset('bpay')) { + Tools::redirectAdmin('index.php?tab=AdminPayment&token='.Tools::getAdminToken('AdminPayment'.(int)Tab::getIdFromClassName('AdminPayment').(int)$this->id_employee)); + } + } + } + + if (count($module_errors)) { + // If error during module installation, no redirection + $html_error = $this->generateHtmlMessage($module_errors); + if ($key == 'uninstall') { + $this->errors[] = sprintf(Tools::displayError('The following module(s) could not be uninstalled properly: %s.'), $html_error); + } else { + $this->errors[] = sprintf(Tools::displayError('The following module(s) could not be installed properly: %s.'), $html_error); + } + $this->context->smarty->assign('error_module', 'true'); + } + } + + if ($return) { + $params = (count($installed_modules)) ? '&installed_modules='.implode('|', $installed_modules) : ''; + + // If redirect parameter is present and module installed with success, we redirect on configuration module page + if (Tools::getValue('redirect') == 'config' && Tools::getValue('module_name') != '' && $return == '12' && Module::isInstalled(pSQL(Tools::getValue('module_name')))) { + Tools::redirectAdmin('index.php?controller=adminmodules&configure='.Tools::getValue('module_name').'&token='.Tools::getValue('token').'&module_name='.Tools::getValue('module_name').$params); + } + Tools::redirectAdmin(self::$currentIndex.'&conf='.$return.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name).(isset($modules_list_save) ? '&modules_list='.$modules_list_save : '').$params); + } + + if (Tools::getValue('update') || Tools::getValue('updateAll') || Tools::getValue('checkAndUpdate')) { + $updated = '&updated=1'; + if (Tools::getValue('checkAndUpdate')) { + $updated = '&check=1'; + if (Tools::getValue('module_name')) { + $module = Module::getInstanceByName(Tools::getValue('module_name')); + if (!Validate::isLoadedObject($module)) { + unset($module); + } + } + } + + $module_upgraded = implode('|', $module_upgraded); + + if ($key == 'updateAll') { + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&allUpdated=1'); + } elseif (isset($module_upgraded) && $module_upgraded != '') { + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&updated=1&module_name='.$module_upgraded); + } elseif (isset($modules_list_save)) { + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&updated=1&module_name='.$modules_list_save); + } elseif (isset($module)) { + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.$updated.'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name).(isset($modules_list_save) ? '&modules_list='.$modules_list_save : '')); + } + } + } + + protected function getModulesByInstallation($tab_modules_list = null) + { + $all_modules = Module::getModulesOnDisk(true, $this->logged_on_addons, $this->id_employee); + $all_unik_modules = array(); + $modules_list = array('installed' =>array(), 'not_installed' => array()); + + foreach ($all_modules as $mod) { + if (!isset($all_unik_modules[$mod->name])) { + $all_unik_modules[$mod->name] = $mod; + } + } + + $all_modules = $all_unik_modules; + + foreach ($all_modules as $module) { + if (!isset($tab_modules_list) || in_array($module->name, $tab_modules_list)) { + $perm = true; + if ($module->id) { + $perm &= Module::getPermissionStatic($module->id, 'configure'); + } else { + $id_admin_module = Tab::getIdFromClassName('AdminModules'); + $access = Profile::getProfileAccess($this->context->employee->id_profile, $id_admin_module); + if (!$access['edit']) { + $perm &= false; + } + } + + if (in_array($module->name, $this->list_partners_modules)) { + $module->type = 'addonsPartner'; + } + + if ($perm) { + $this->fillModuleData($module, 'array'); + if ($module->id) { + $modules_list['installed'][] = $module; + } else { + $modules_list['not_installed'][] = $module; + } + } + } + } + + return $modules_list; + } + + public function postProcess() + { + // Parent Post Process + parent::postProcess(); + + // Get the list of installed module ans prepare it for ajax call. + if (($list = Tools::getValue('installed_modules'))) { + Context::getContext()->smarty->assign('installed_modules', Tools::jsonEncode(explode('|', $list))); + } + + // If redirect parameter is present and module already installed, we redirect on configuration module page + if (Tools::getValue('redirect') == 'config' && Tools::getValue('module_name') != '' && Module::isInstalled(pSQL(Tools::getValue('module_name')))) { + Tools::redirectAdmin('index.php?controller=adminmodules&configure='.Tools::getValue('module_name').'&token='.Tools::getValue('token').'&module_name='.Tools::getValue('module_name')); + } + + // Execute filter or callback methods + $filter_methods = array('filterModules', 'resetFilterModules', 'filterCategory', 'unfilterCategory'); + $callback_methods = array('reset', 'download', 'enable', 'delete', 'enable_device', 'disable_device'); + $post_process_methods_list = array_merge((array)$filter_methods, (array)$callback_methods); + foreach ($post_process_methods_list as $ppm) { + if (Tools::isSubmit($ppm)) { + $ppm = 'postProcess'.ucfirst($ppm); + if (method_exists($this, $ppm)) { + $ppm_return = $this->$ppm(); + } + } + } + + // Call appropriate module callback + if (!isset($ppm_return)) { + $this->postProcessCallback(); + } + + if ($back = Tools::getValue('back')) { + Tools::redirectAdmin($back); + } + } + + /** + * Generate html errors for a module process + * + * @param $module_errors + * @return string + */ + protected function generateHtmlMessage($module_errors) + { + $html_error = ''; + + if (count($module_errors)) { + $html_error = '<ul>'; + foreach ($module_errors as $module_error) { + $html_error_description = ''; + if (count($module_error['message']) > 0) { + foreach ($module_error['message'] as $e) { + $html_error_description .= '<br />    '.$e; + } + } + $html_error .= '<li><b>'.$module_error['name'].'</b> : '.$html_error_description.'</li>'; + } + $html_error .= '</ul>'; + } + return $html_error; + } + + public function initModulesList(&$modules) + { + foreach ($modules as $k => $module) { + // Check add permissions, if add permissions not set, addons modules and uninstalled modules will not be displayed + if ($this->tabAccess['add'] !== '1' && isset($module->type) && ($module->type != 'addonsNative' || $module->type != 'addonsBought')) { + unset($modules[$k]); + } elseif ($this->tabAccess['add'] !== '1' && (!isset($module->id) || $module->id < 1)) { + unset($modules[$k]); + } elseif ($module->id && !Module::getPermissionStatic($module->id, 'view') && !Module::getPermissionStatic($module->id, 'configure')) { + unset($modules[$k]); + } else { + // Init serial and modules author list + if (!in_array($module->name, $this->list_natives_modules)) { + $this->serial_modules .= $module->name.' '.$module->version.'-'.($module->active ? 'a' : 'i')."\n"; + } + $module_author = $module->author; + if (!empty($module_author) && ($module_author != '')) { + $this->modules_authors[strtolower($module_author)] = 'notselected'; + } + } + } + $this->serial_modules = urlencode($this->serial_modules); + } + + public function makeModulesStats($module) + { + // Count Installed Modules + if (isset($module->id) && $module->id > 0) { + $this->nb_modules_installed++; + } + + // Count Activated Modules + if (isset($module->id) && $module->id > 0 && $module->active > 0) { + $this->nb_modules_activated++; + } + + // Count Modules By Category + if (isset($this->list_modules_categories[$module->tab]['nb'])) { + $this->list_modules_categories[$module->tab]['nb']++; + } else { + $this->list_modules_categories['others']['nb']++; + } + } + + public function isModuleFiltered($module) + { + // If action on module, we display it + if (Tools::getValue('module_name') != '' && Tools::getValue('module_name') == $module->name) { + return false; + } + + // Filter on module name + $filter_name = Tools::getValue('filtername'); + if (!empty($filter_name)) { + if (stristr($module->name, $filter_name) === false && stristr($module->displayName, $filter_name) === false && stristr($module->description, $filter_name) === false) { + return true; + } + return false; + } + + // Filter on interest + if ($module->interest !== '') { + if ($module->interest === '0') { + return true; + } + } elseif ((int)Db::getInstance()->getValue('SELECT `id_module_preference` FROM `'._DB_PREFIX_.'module_preference` WHERE `module` = \''.pSQL($module->name).'\' AND `id_employee` = '.(int)$this->id_employee.' AND `interest` = 0') > 0) { + return true; + } + + // Filter on favorites + if (Configuration::get('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee) == 'favorites') { + if ((int)Db::getInstance()->getValue('SELECT `id_module_preference` FROM `'._DB_PREFIX_.'module_preference` WHERE `module` = \''.pSQL($module->name).'\' AND `id_employee` = '.(int)$this->id_employee.' AND `favorite` = 1 AND (`interest` = 1 OR `interest` IS NULL)') < 1) { + return true; + } + } else { + // Handle "others" category + if (!isset($this->list_modules_categories[$module->tab])) { + $module->tab = 'others'; + } + + // Filter on module category + $category_filtered = array(); + $filter_categories = explode('|', Configuration::get('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee)); + if (count($filter_categories) > 0) { + foreach ($filter_categories as $fc) { + if (!empty($fc)) { + $category_filtered[$fc] = 1; + } + } + } + if (count($category_filtered) > 0 && !isset($category_filtered[$module->tab])) { + return true; + } + } + + // Filter on module type and author + $show_type_modules = $this->filter_configuration['PS_SHOW_TYPE_MODULES_'.(int)$this->id_employee]; + if ($show_type_modules == 'nativeModules' && !in_array($module->name, $this->list_natives_modules)) { + return true; + } elseif ($show_type_modules == 'partnerModules' && !in_array($module->name, $this->list_partners_modules)) { + return true; + } elseif ($show_type_modules == 'addonsModules' && (!isset($module->type) || $module->type != 'addonsBought')) { + return true; + } elseif ($show_type_modules == 'mustHaveModules' && (!isset($module->type) || $module->type != 'addonsMustHave')) { + return true; + } elseif ($show_type_modules == 'otherModules' && (in_array($module->name, $this->list_partners_modules) || in_array($module->name, $this->list_natives_modules))) { + return true; + } elseif (strpos($show_type_modules, 'authorModules[') !== false) { + // setting selected author in authors set + $author_selected = substr(str_replace(array('authorModules[', "\'"), array('', "'"), $show_type_modules), 0, -1); + $this->modules_authors[$author_selected] = 'selected'; + if (empty($module->author) || strtolower($module->author) != $author_selected) { + return true; + } + } + + // Filter on install status + $show_installed_modules = $this->filter_configuration['PS_SHOW_INSTALLED_MODULES_'.(int)$this->id_employee]; + if ($show_installed_modules == 'installed' && !$module->id) { + return true; + } + if ($show_installed_modules == 'uninstalled' && $module->id) { + return true; + } + + // Filter on active status + $show_enabled_modules = $this->filter_configuration['PS_SHOW_ENABLED_MODULES_'.(int)$this->id_employee]; + if ($show_enabled_modules == 'enabled' && !$module->active) { + return true; + } + if ($show_enabled_modules == 'disabled' && $module->active) { + return true; + } + + // Filter on country + $show_country_modules = $this->filter_configuration['PS_SHOW_COUNTRY_MODULES_'.(int)$this->id_employee]; + if ($show_country_modules && (isset($module->limited_countries) && !empty($module->limited_countries) + && ((is_array($module->limited_countries) && count($module->limited_countries) + && !in_array(strtolower($this->iso_default_country), $module->limited_countries)) + || (!is_array($module->limited_countries) && strtolower($this->iso_default_country) != strval($module->limited_countries))))) { + return true; + } + + // Module has not been filtered + return false; + } + + public function renderKpis() + { + $time = time(); + $kpis = array(); + + /* The data generation is located in AdminStatsControllerCore */ + + $helper = new HelperKpi(); + $helper->id = 'box-installed-modules'; + $helper->icon = 'icon-puzzle-piece'; + $helper->color = 'color1'; + $helper->title = $this->l('Installed Modules', null, null, false); + if (ConfigurationKPI::get('INSTALLED_MODULES') !== false && ConfigurationKPI::get('INSTALLED_MODULES') != '') { + $helper->value = ConfigurationKPI::get('INSTALLED_MODULES'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=installed_modules'; + $helper->refresh = (bool)(ConfigurationKPI::get('INSTALLED_MODULES_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-disabled-modules'; + $helper->icon = 'icon-off'; + $helper->color = 'color2'; + $helper->title = $this->l('Disabled Modules', null, null, false); + if (ConfigurationKPI::get('DISABLED_MODULES') !== false && ConfigurationKPI::get('DISABLED_MODULES') != '') { + $helper->value = ConfigurationKPI::get('DISABLED_MODULES'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=disabled_modules'; + $helper->refresh = (bool)(ConfigurationKPI::get('DISABLED_MODULES_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-update-modules'; + $helper->icon = 'icon-refresh'; + $helper->color = 'color3'; + $helper->title = $this->l('Modules to update', null, null, false); + if (ConfigurationKPI::get('UPDATE_MODULES') !== false && ConfigurationKPI::get('UPDATE_MODULES') != '') { + $helper->value = ConfigurationKPI::get('UPDATE_MODULES'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=update_modules'; + $helper->refresh = (bool)(ConfigurationKPI::get('UPDATE_MODULES_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpiRow(); + $helper->kpis = $kpis; + return $helper->generate(); + } + + public function initModal() + { + parent::initModal(); + + $this->context->smarty->assign(array( + 'trad_link' => 'index.php?tab=AdminTranslations&token='.Tools::getAdminTokenLite('AdminTranslations').'&type=modules&lang=', + 'module_languages' => Language::getLanguages(false), + 'module_name' => Tools::getValue('module_name'), + )); + + $modal_content = $this->context->smarty->fetch('controllers/modules/modal_translation.tpl'); + $this->modals[] = array( + 'modal_id' => 'moduleTradLangSelect', + 'modal_class' => 'modal-sm', + 'modal_title' => $this->l('Translate this module'), + 'modal_content' => $modal_content + ); + + $modal_content = $this->context->smarty->fetch('controllers/modules/'.(($this->context->mode == Context::MODE_HOST) ? 'modal_not_trusted_blocked.tpl' : 'modal_not_trusted.tpl')); + $this->modals[] = array( + 'modal_id' => 'moduleNotTrusted', + 'modal_class' => 'modal-lg', + 'modal_title' => ($this->context->mode == Context::MODE_HOST) ? $this->l('This module cannot be installed') : $this->l('Important Notice'), + 'modal_content' => $modal_content + ); + + $modal_content = $this->context->smarty->fetch('controllers/modules/modal_not_trusted_country.tpl'); + $this->modals[] = array( + 'modal_id' => 'moduleNotTrustedCountry', + 'modal_class' => 'modal-lg', + 'modal_title' => $this->l('This module is Untrusted for your country'), + 'modal_content' => $modal_content + ); + } + + public function initContent() + { + if (Tools::isSubmit('addnewmodule') && $this->context->mode == Context::MODE_HOST) { + $this->display = 'add'; + $this->context->smarty->assign(array('iso_code' => $this->context->language->iso_code)); + return parent::initContent(); + } + + $this->meta_title = 'Modules'; + + // If we are on a module configuration, no need to load all modules + if (Tools::getValue('configure') != '') { + $this->context->smarty->assign(array('maintenance_mode' => !(bool)Configuration::Get('PS_SHOP_ENABLE'))); + + return true; + } + + $this->initToolbar(); + $this->initPageHeaderToolbar(); + + // Init + $smarty = $this->context->smarty; + $autocomplete_list = 'var moduleList = ['; + $category_filtered = array(); + $filter_categories = explode('|', Configuration::get('PS_SHOW_CAT_MODULES_'.(int)$this->id_employee)); + if (count($filter_categories) > 0) { + foreach ($filter_categories as $fc) { + if (!empty($fc)) { + $category_filtered[$fc] = 1; + } + } + } + + if (empty($category_filtered) && Tools::getValue('tab_module')) { + $category_filtered[Tools::getValue('tab_module')] = 1; + } + + foreach ($this->list_modules_categories as $k => $v) { + $this->list_modules_categories[$k]['nb'] = 0; + } + + // Retrieve Modules Preferences + $modules_preferences = ''; + $tab_modules_preferences = array(); + $modules_preferences_tmp = Db::getInstance()->executeS('SELECT * FROM `'._DB_PREFIX_.'module_preference` WHERE `id_employee` = '.(int)$this->id_employee); + $tab_modules_preferences_tmp = Db::getInstance()->executeS('SELECT * FROM `'._DB_PREFIX_.'tab_module_preference` WHERE `id_employee` = '.(int)$this->id_employee); + + foreach ($tab_modules_preferences_tmp as $i => $j) { + $tab_modules_preferences[$j['module']][] = $j['id_tab']; + } + + foreach ($modules_preferences_tmp as $k => $v) { + if ($v['interest'] == null) { + unset($v['interest']); + } + if ($v['favorite'] == null) { + unset($v['favorite']); + } + $modules_preferences[$v['module']] = $v; + } + + // Retrieve Modules List + $modules = Module::getModulesOnDisk(true, $this->logged_on_addons, $this->id_employee); + $this->initModulesList($modules); + $this->nb_modules_total = count($modules); + $module_errors = array(); + $module_success = array(); + $upgrade_available = array(); + $dont_filter = false; + + //Add succes message for one module update + if (Tools::getValue('updated') && Tools::getValue('module_name')) { + $module_names = (string)Tools::getValue('module_name'); + if (strpos($module_names, '|')) { + $module_names = explode('|', $module_names); + $dont_filter = true; + } + + if (!is_array($module_names)) { + $module_names = (array)$module_names; + } + + foreach ($modules as $km => $module) { + if (in_array($module->name, $module_names)) { + $module_success[] = array('name' => $module->displayName, 'message' => array( + 0 => sprintf($this->l('Current version: %s'), $module->version))); + } + } + } + + if (Tools::getValue('allUpdated')) { + $this->confirmations[] = $this->l('All modules updated successfully.'); + } + + // Browse modules list + foreach ($modules as $km => $module) { + //if we are in favorites view we only display installed modules + if (Tools::getValue('select') == 'favorites' && !$module->id) { + unset($modules[$km]); + continue; + } + + // Upgrade Module process, init check if a module could be upgraded + if (Module::initUpgradeModule($module)) { + // When the XML cache file is up-to-date, the module may not be loaded yet + if (!class_exists($module->name)) { + if (!file_exists(_PS_MODULE_DIR_.$module->name.'/'.$module->name.'.php')) { + continue; + } + require_once(_PS_MODULE_DIR_.$module->name.'/'.$module->name.'.php'); + } + + if ($object = new $module->name()) { + /** @var Module $object */ + $object->runUpgradeModule(); + if ((count($errors_module_list = $object->getErrors()))) { + $module_errors[] = array('name' => $module->displayName, 'message' => $errors_module_list); + } elseif ((count($conf_module_list = $object->getConfirmations()))) { + $module_success[] = array('name' => $module->displayName, 'message' => $conf_module_list); + } + unset($object); + } + } + // Module can't be upgraded if not file exist but can change the database version... + // User has to be prevented + elseif (Module::getUpgradeStatus($module->name)) { + // When the XML cache file is up-to-date, the module may not be loaded yet + if (!class_exists($module->name)) { + if (file_exists(_PS_MODULE_DIR_.$module->name.'/'.$module->name.'.php')) { + require_once(_PS_MODULE_DIR_.$module->name.'/'.$module->name.'.php'); + $object = new $module->name(); + $module_success[] = array('name' => $module->name, 'message' => array( + 0 => sprintf($this->l('Current version: %s'), $object->version), + 1 => $this->l('No file upgrades applied (none exist).')) + ); + } else { + continue; + } + } + unset($object); + } + + // Make modules stats + $this->makeModulesStats($module); + + // Assign warnings + if ($module->active && isset($module->warning) && !empty($module->warning) && !$this->ajax) { + $href = Context::getContext()->link->getAdminLink('AdminModules', true).'&module_name='.$module->name.'&tab_module='.$module->tab.'&configure='.$module->name; + $this->context->smarty->assign('text', sprintf($this->l('%1$s: %2$s'), $module->displayName, $module->warning)); + $this->context->smarty->assign('module_link', $href); + $this->displayWarning($this->context->smarty->fetch('controllers/modules/warning_module.tpl')); + } + + // AutoComplete array + $autocomplete_list .= Tools::jsonEncode(array( + 'displayName' => (string)$module->displayName, + 'desc' => (string)$module->description, + 'name' => (string)$module->name, + 'author' => (string)$module->author, + 'image' => (isset($module->image) ? (string)$module->image : ''), + 'option' => '', + )).', '; + + // Apply filter + if ($this->isModuleFiltered($module) && Tools::getValue('select') != 'favorites') { + unset($modules[$km]); + } else { + if (isset($modules_preferences[$modules[$km]->name])) { + $modules[$km]->preferences = $modules_preferences[$modules[$km]->name]; + } + + $this->fillModuleData($module, 'array'); + $module->categoryName = (isset($this->list_modules_categories[$module->tab]['name']) ? $this->list_modules_categories[$module->tab]['name'] : $this->list_modules_categories['others']['name']); + } + unset($object); + if ($module->installed && isset($module->version_addons) && $module->version_addons) { + $upgrade_available[] = array('anchor' => ucfirst($module->name), 'name' => $module->name, 'displayName' => $module->displayName); + } + + if (in_array($module->name, $this->list_partners_modules)) { + $module->type = 'addonsPartner'; + } + + if (isset($module->description_full) && trim($module->description_full) != '') { + $module->show_quick_view = true; + } + } + + // Don't display categories without modules + $cleaned_list = array(); + foreach ($this->list_modules_categories as $k => $list) { + if ($list['nb'] > 0) { + $cleaned_list[$k] = $list; + } + } + + // Actually used for the report of the upgraded errors + if (count($module_errors)) { + $html = $this->generateHtmlMessage($module_errors); + $this->errors[] = sprintf(Tools::displayError('The following module(s) were not upgraded successfully: %s.'), $html); + } + if (count($module_success)) { + $html = $this->generateHtmlMessage($module_success); + $this->confirmations[] = sprintf($this->l('The following module(s) were upgraded successfully: %s.'), $html); + } + + ConfigurationKPI::updateValue('UPDATE_MODULES', count($upgrade_available)); + + if (count($upgrade_available) == 0 && (int)Tools::getValue('check') == 1) { + $this->confirmations[] = $this->l('Everything is up-to-date'); + } + + // Init tpl vars for smarty + $tpl_vars = array( + 'token' => $this->token, + 'upgrade_available' => $upgrade_available, + 'currentIndex' => self::$currentIndex, + 'dirNameCurrentIndex' => dirname(self::$currentIndex), + 'ajaxCurrentIndex' => str_replace('index', 'ajax-tab', self::$currentIndex), + 'autocompleteList' => rtrim($autocomplete_list, ' ,').'];', + 'showTypeModules' => $this->filter_configuration['PS_SHOW_TYPE_MODULES_'.(int)$this->id_employee], + 'showCountryModules' => $this->filter_configuration['PS_SHOW_COUNTRY_MODULES_'.(int)$this->id_employee], + 'showInstalledModules' => $this->filter_configuration['PS_SHOW_INSTALLED_MODULES_'.(int)$this->id_employee], + 'showEnabledModules' => $this->filter_configuration['PS_SHOW_ENABLED_MODULES_'.(int)$this->id_employee], + 'nameCountryDefault' => Country::getNameById($this->context->language->id, Configuration::get('PS_COUNTRY_DEFAULT')), + 'isoCountryDefault' => $this->iso_default_country, + 'categoryFiltered' => $category_filtered, + 'modules' => $modules, + 'nb_modules' => $this->nb_modules_total, + 'nb_modules_favorites' => count($this->context->employee->favoriteModulesList()), + 'nb_modules_installed' => $this->nb_modules_installed, + 'nb_modules_uninstalled' => $this->nb_modules_total - $this->nb_modules_installed, + 'nb_modules_activated' => $this->nb_modules_activated, + 'nb_modules_unactivated' => $this->nb_modules_installed - $this->nb_modules_activated, + 'list_modules_categories' => $cleaned_list, + 'list_modules_authors' => $this->modules_authors, + 'add_permission' => $this->tabAccess['add'], + 'tab_modules_preferences' => $tab_modules_preferences, + 'kpis' => $this->renderKpis(), + 'module_name' => Tools::getValue('module_name'), + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn, + 'modules_uri' => __PS_BASE_URI__.basename(_PS_MODULE_DIR_), + 'dont_filter' => $dont_filter, + 'is_contributor' => (int)$this->context->cookie->is_contributor, + 'maintenance_mode' => !(bool)Configuration::Get('PS_SHOP_ENABLE') + ); + + if ($this->logged_on_addons) { + $tpl_vars['logged_on_addons'] = 1; + $tpl_vars['username_addons'] = $this->context->cookie->username_addons; + } + $smarty->assign($tpl_vars); + } + + public function ajaxProcessGetModuleQuickView() + { + $modules = Module::getModulesOnDisk(); + + foreach ($modules as $module) { + if ($module->name == Tools::getValue('module')) { + break; + } + } + + $url = $module->url; + + if (isset($module->type) && ($module->type == 'addonsPartner' || $module->type == 'addonsNative')) { + $url = $this->context->link->getAdminLink('AdminModules').'&install='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name); + } + + $this->context->smarty->assign(array( + 'displayName' => $module->displayName, + 'image' => $module->image, + 'nb_rates' => (int)$module->nb_rates[0], + 'avg_rate' => (int)$module->avg_rate[0], + 'badges' => $module->badges, + 'compatibility' => $module->compatibility, + 'description_full' => $module->description_full, + 'additional_description' => $module->additional_description, + 'is_addons_partner' => (isset($module->type) && ($module->type == 'addonsPartner' || $module->type == 'addonsNative')), + 'url' => $url, + 'price' => $module->price + )); + $this->smartyOutputContent('controllers/modules/quickview.tpl'); + } } diff --git a/controllers/admin/AdminModulesPositionsController.php b/controllers/admin/AdminModulesPositionsController.php index 89500ec4..95957694 100644 --- a/controllers/admin/AdminModulesPositionsController.php +++ b/controllers/admin/AdminModulesPositionsController.php @@ -26,624 +26,631 @@ class AdminModulesPositionsControllerCore extends AdminController { - protected $display_key = 0; + protected $display_key = 0; - public function __construct() - { - $this->bootstrap = true; - parent::__construct(); - } + public function __construct() + { + $this->bootstrap = true; + parent::__construct(); + } - public function postProcess() - { - // Getting key value for display - if (Tools::getValue('show_modules') && strval(Tools::getValue('show_modules')) != 'all') - $this->display_key = (int)Tools::getValue('show_modules'); + public function postProcess() + { + // Getting key value for display + if (Tools::getValue('show_modules') && strval(Tools::getValue('show_modules')) != 'all') { + $this->display_key = (int)Tools::getValue('show_modules'); + } - $this->addjQueryPlugin(array( - 'select2', - )); + $this->addjQueryPlugin(array( + 'select2', + )); - $this->addJS(array( - _PS_JS_DIR_.'admin/modules-position.js', - _PS_JS_DIR_.'jquery/plugins/select2/select2_locale_'.$this->context->language->iso_code.'.js', - )); + $this->addJS(array( + _PS_JS_DIR_.'admin/modules-position.js', + _PS_JS_DIR_.'jquery/plugins/select2/select2_locale_'.$this->context->language->iso_code.'.js', + )); - // Change position in hook - if (array_key_exists('changePosition', $_GET)) - { - if ($this->tabAccess['edit'] === '1') - { - $id_module = (int)Tools::getValue('id_module'); - $id_hook = (int)Tools::getValue('id_hook'); - $module = Module::getInstanceById($id_module); - if (Validate::isLoadedObject($module)) - { - $module->updatePosition($id_hook, (int)Tools::getValue('direction')); - Tools::redirectAdmin(self::$currentIndex.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token); - } - else - $this->errors[] = Tools::displayError('This module cannot be loaded.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } + // Change position in hook + if (array_key_exists('changePosition', $_GET)) { + if ($this->tabAccess['edit'] === '1') { + $id_module = (int)Tools::getValue('id_module'); + $id_hook = (int)Tools::getValue('id_hook'); + $module = Module::getInstanceById($id_module); + if (Validate::isLoadedObject($module)) { + $module->updatePosition($id_hook, (int)Tools::getValue('direction')); + Tools::redirectAdmin(self::$currentIndex.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token); + } else { + $this->errors[] = Tools::displayError('This module cannot be loaded.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } - // Add new module in hook - elseif (Tools::isSubmit('submitAddToHook')) - { - if ($this->tabAccess['add'] === '1') - { - // Getting vars... - $id_module = (int)Tools::getValue('id_module'); - $module = Module::getInstanceById($id_module); - $id_hook = (int)Tools::getValue('id_hook'); - $hook = new Hook($id_hook); + // Add new module in hook + elseif (Tools::isSubmit('submitAddToHook')) { + if ($this->tabAccess['add'] === '1') { + // Getting vars... + $id_module = (int)Tools::getValue('id_module'); + $module = Module::getInstanceById($id_module); + $id_hook = (int)Tools::getValue('id_hook'); + $hook = new Hook($id_hook); - if (!$id_module || !Validate::isLoadedObject($module)) - $this->errors[] = Tools::displayError('This module cannot be loaded.'); - elseif (!$id_hook || !Validate::isLoadedObject($hook)) - $this->errors[] = Tools::displayError('Hook cannot be loaded.'); - elseif (Hook::getModulesFromHook($id_hook, $id_module)) - $this->errors[] = Tools::displayError('This module has already been transplanted to this hook.'); - elseif (!$module->isHookableOn($hook->name)) - $this->errors[] = Tools::displayError('This module cannot be transplanted to this hook.'); - // Adding vars... - else - { - if (!$module->registerHook($hook->name, Shop::getContextListShopID())) - $this->errors[] = Tools::displayError('An error occurred while transplanting the module to its hook.'); - else - { - $exceptions = Tools::getValue('exceptions'); - $exceptions = (isset($exceptions[0])) ? $exceptions[0] : array(); - $exceptions = explode(',', str_replace(' ', '', $exceptions)); + if (!$id_module || !Validate::isLoadedObject($module)) { + $this->errors[] = Tools::displayError('This module cannot be loaded.'); + } elseif (!$id_hook || !Validate::isLoadedObject($hook)) { + $this->errors[] = Tools::displayError('Hook cannot be loaded.'); + } elseif (Hook::getModulesFromHook($id_hook, $id_module)) { + $this->errors[] = Tools::displayError('This module has already been transplanted to this hook.'); + } elseif (!$module->isHookableOn($hook->name)) { + $this->errors[] = Tools::displayError('This module cannot be transplanted to this hook.'); + } + // Adding vars... + else { + if (!$module->registerHook($hook->name, Shop::getContextListShopID())) { + $this->errors[] = Tools::displayError('An error occurred while transplanting the module to its hook.'); + } else { + $exceptions = Tools::getValue('exceptions'); + $exceptions = (isset($exceptions[0])) ? $exceptions[0] : array(); + $exceptions = explode(',', str_replace(' ', '', $exceptions)); + $exceptions = array_unique($exceptions); - foreach ($exceptions as $key => $except) - { - if (empty($except)) - unset($exceptions[$key]); - elseif (!empty($except) && !Validate::isFileName($except)) - $this->errors[] = Tools::displayError('No valid value for field exceptions has been defined.'); - } - if (!$this->errors && !$module->registerExceptions($id_hook, $exceptions, Shop::getContextListShopID())) - $this->errors[] = Tools::displayError('An error occurred while transplanting the module to its hook.'); - } - if (!$this->errors) - Tools::redirectAdmin(self::$currentIndex.'&conf=16'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } + foreach ($exceptions as $key => $except) { + if (empty($except)) { + unset($exceptions[$key]); + } elseif (!empty($except) && !Validate::isFileName($except)) { + $this->errors[] = Tools::displayError('No valid value for field exceptions has been defined.'); + } + } + if (!$this->errors && !$module->registerExceptions($id_hook, $exceptions, Shop::getContextListShopID())) { + $this->errors[] = Tools::displayError('An error occurred while transplanting the module to its hook.'); + } + } + if (!$this->errors) { + Tools::redirectAdmin(self::$currentIndex.'&conf=16'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } - // Edit module from hook - elseif (Tools::isSubmit('submitEditGraft')) - { - if ($this->tabAccess['add'] === '1') - { - // Getting vars... - $id_module = (int)Tools::getValue('id_module'); - $module = Module::getInstanceById($id_module); - $id_hook = (int)Tools::getValue('id_hook'); - $hook = new Hook($id_hook); + // Edit module from hook + elseif (Tools::isSubmit('submitEditGraft')) { + if ($this->tabAccess['add'] === '1') { + // Getting vars... + $id_module = (int)Tools::getValue('id_module'); + $module = Module::getInstanceById($id_module); + $id_hook = (int)Tools::getValue('id_hook'); + $hook = new Hook($id_hook); - if (!$id_module || !Validate::isLoadedObject($module)) - $this->errors[] = Tools::displayError('This module cannot be loaded.'); - elseif (!$id_hook || !Validate::isLoadedObject($hook)) - $this->errors[] = Tools::displayError('Hook cannot be loaded.'); - else - { - $exceptions = Tools::getValue('exceptions'); - if (is_array($exceptions)) - { - foreach ($exceptions as $id => $exception) - { - $exception = explode(',', str_replace(' ', '', $exception)); - // Check files name - foreach ($exception as $except) - if (!empty($except) && !Validate::isFileName($except)) - $this->errors[] = Tools::displayError('No valid value for field exceptions has been defined.'); + if (!$id_module || !Validate::isLoadedObject($module)) { + $this->errors[] = Tools::displayError('This module cannot be loaded.'); + } elseif (!$id_hook || !Validate::isLoadedObject($hook)) { + $this->errors[] = Tools::displayError('Hook cannot be loaded.'); + } else { + $exceptions = Tools::getValue('exceptions'); + if (is_array($exceptions)) { + foreach ($exceptions as $id => $exception) { + $exception = explode(',', str_replace(' ', '', $exception)); + $exception = array_unique($exception); + // Check files name + foreach ($exception as $except) { + if (!empty($except) && !Validate::isFileName($except)) { + $this->errors[] = Tools::displayError('No valid value for field exceptions has been defined.'); + } + } - $exceptions[$id] = $exception; - } + $exceptions[$id] = $exception; + } - // Add files exceptions - if (!$module->editExceptions($id_hook, $exceptions)) - $this->errors[] = Tools::displayError('An error occurred while transplanting the module to its hook.'); + // Add files exceptions + if (!$module->editExceptions($id_hook, $exceptions)) { + $this->errors[] = Tools::displayError('An error occurred while transplanting the module to its hook.'); + } - if (!$this->errors) - Tools::redirectAdmin(self::$currentIndex.'&conf=16'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token); - } - else - { - $exceptions = explode(',', str_replace(' ', '', $exceptions)); + if (!$this->errors) { + Tools::redirectAdmin(self::$currentIndex.'&conf=16'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token); + } + } else { + $exceptions = explode(',', str_replace(' ', '', $exceptions)); + $exceptions = array_unique($exceptions); - // Check files name - foreach ($exceptions as $except) - if (!empty($except) && !Validate::isFileName($except)) - $this->errors[] = Tools::displayError('No valid value for field exceptions has been defined.'); + // Check files name + foreach ($exceptions as $except) { + if (!empty($except) && !Validate::isFileName($except)) { + $this->errors[] = Tools::displayError('No valid value for field exceptions has been defined.'); + } + } - // Add files exceptions - if (!$module->editExceptions($id_hook, $exceptions, Shop::getContextListShopID())) - $this->errors[] = Tools::displayError('An error occurred while transplanting the module to its hook.'); - else - Tools::redirectAdmin(self::$currentIndex.'&conf=16'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token); - } - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } + // Add files exceptions + if (!$module->editExceptions($id_hook, $exceptions, Shop::getContextListShopID())) { + $this->errors[] = Tools::displayError('An error occurred while transplanting the module to its hook.'); + } else { + Tools::redirectAdmin(self::$currentIndex.'&conf=16'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token); + } + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } - // Delete module from hook - elseif (array_key_exists('deleteGraft', $_GET)) - { - if ($this->tabAccess['delete'] === '1') - { - $id_module = (int)Tools::getValue('id_module'); - $module = Module::getInstanceById($id_module); - $id_hook = (int)Tools::getValue('id_hook'); - $hook = new Hook($id_hook); - if (!Validate::isLoadedObject($module)) - $this->errors[] = Tools::displayError('This module cannot be loaded.'); - elseif (!$id_hook || !Validate::isLoadedObject($hook)) - $this->errors[] = Tools::displayError('Hook cannot be loaded.'); - else - { - if (!$module->unregisterHook($id_hook, Shop::getContextListShopID()) - || !$module->unregisterExceptions($id_hook, Shop::getContextListShopID())) - $this->errors[] = Tools::displayError('An error occurred while deleting the module from its hook.'); - else - Tools::redirectAdmin(self::$currentIndex.'&conf=17'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - elseif (Tools::isSubmit('unhookform')) - { - if (!($unhooks = Tools::getValue('unhooks')) || !is_array($unhooks)) - $this->errors[] = Tools::displayError('Please select a module to unhook.'); - else - { - foreach ($unhooks as $unhook) - { - $explode = explode('_', $unhook); - $id_hook = $explode[0]; - $id_module = $explode[1]; - $module = Module::getInstanceById((int)$id_module); - $hook = new Hook((int)$id_hook); - if (!Validate::isLoadedObject($module)) - $this->errors[] = Tools::displayError('This module cannot be loaded.'); - elseif (!$id_hook || !Validate::isLoadedObject($hook)) - $this->errors[] = Tools::displayError('Hook cannot be loaded.'); - else - { - if (!$module->unregisterHook((int)$id_hook) || !$module->unregisterExceptions((int)$id_hook)) - $this->errors[] = Tools::displayError('An error occurred while deleting the module from its hook.'); - } - } - if (!count($this->errors)) - Tools::redirectAdmin(self::$currentIndex.'&conf=17'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token); - } - } - else - parent::postProcess(); - } + // Delete module from hook + elseif (array_key_exists('deleteGraft', $_GET)) { + if ($this->tabAccess['delete'] === '1') { + $id_module = (int)Tools::getValue('id_module'); + $module = Module::getInstanceById($id_module); + $id_hook = (int)Tools::getValue('id_hook'); + $hook = new Hook($id_hook); + if (!Validate::isLoadedObject($module)) { + $this->errors[] = Tools::displayError('This module cannot be loaded.'); + } elseif (!$id_hook || !Validate::isLoadedObject($hook)) { + $this->errors[] = Tools::displayError('Hook cannot be loaded.'); + } else { + if (!$module->unregisterHook($id_hook, Shop::getContextListShopID()) + || !$module->unregisterExceptions($id_hook, Shop::getContextListShopID())) { + $this->errors[] = Tools::displayError('An error occurred while deleting the module from its hook.'); + } else { + Tools::redirectAdmin(self::$currentIndex.'&conf=17'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } elseif (Tools::isSubmit('unhookform')) { + if (!($unhooks = Tools::getValue('unhooks')) || !is_array($unhooks)) { + $this->errors[] = Tools::displayError('Please select a module to unhook.'); + } else { + foreach ($unhooks as $unhook) { + $explode = explode('_', $unhook); + $id_hook = $explode[0]; + $id_module = $explode[1]; + $module = Module::getInstanceById((int)$id_module); + $hook = new Hook((int)$id_hook); + if (!Validate::isLoadedObject($module)) { + $this->errors[] = Tools::displayError('This module cannot be loaded.'); + } elseif (!$id_hook || !Validate::isLoadedObject($hook)) { + $this->errors[] = Tools::displayError('Hook cannot be loaded.'); + } else { + if (!$module->unregisterHook((int)$id_hook) || !$module->unregisterExceptions((int)$id_hook)) { + $this->errors[] = Tools::displayError('An error occurred while deleting the module from its hook.'); + } + } + } + if (!count($this->errors)) { + Tools::redirectAdmin(self::$currentIndex.'&conf=17'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token); + } + } + } else { + parent::postProcess(); + } + } - public function initContent() - { - $this->initTabModuleList(); - $this->addjqueryPlugin('sortable'); - $this->initPageHeaderToolbar(); + public function initContent() + { + $this->initTabModuleList(); + $this->addjqueryPlugin('sortable'); + $this->initPageHeaderToolbar(); - if (array_key_exists('addToHook', $_GET) || array_key_exists('editGraft', $_GET) || (Tools::isSubmit('submitAddToHook') && $this->errors)) - { - $this->display = 'edit'; + if (array_key_exists('addToHook', $_GET) || array_key_exists('editGraft', $_GET) || (Tools::isSubmit('submitAddToHook') && $this->errors)) { + $this->display = 'edit'; - $this->content .= $this->renderForm(); - } - else - $this->content .= $this->initMain(); + $this->content .= $this->renderForm(); + } else { + $this->content .= $this->initMain(); + } - $this->context->smarty->assign(array( - 'content' => $this->content, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } + $this->context->smarty->assign(array( + 'content' => $this->content, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } - public function initPageHeaderToolbar() - { - $this->page_header_toolbar_btn['save'] = array( - 'href' => self::$currentIndex.'&addToHook'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token, - 'desc' => $this->l('Transplant a module', null, null, false), - 'icon' => 'process-icon-anchor' - ); + public function initPageHeaderToolbar() + { + $this->page_header_toolbar_btn['save'] = array( + 'href' => self::$currentIndex.'&addToHook'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token, + 'desc' => $this->l('Transplant a module', null, null, false), + 'icon' => 'process-icon-anchor' + ); - return parent::initPageHeaderToolbar(); - } + return parent::initPageHeaderToolbar(); + } - public function initMain() - { - // Init toolbar - $this->initToolbarTitle(); + public function initMain() + { + // Init toolbar + $this->initToolbarTitle(); - $admin_dir = basename(_PS_ADMIN_DIR_); - $modules = Module::getModulesInstalled(); + $admin_dir = basename(_PS_ADMIN_DIR_); + $modules = Module::getModulesInstalled(); - $assoc_modules_id = array(); - foreach ($modules as $module) - if ($tmp_instance = Module::getInstanceById((int)$module['id_module'])) - { - // We want to be able to sort modules by display name - $module_instances[$tmp_instance->displayName] = $tmp_instance; - // But we also want to associate hooks to modules using the modules IDs - $assoc_modules_id[(int)$module['id_module']] = $tmp_instance->displayName; - } - ksort($module_instances); - $hooks = Hook::getHooks(); - foreach ($hooks as $key => $hook) - { - // Get all modules for this hook or only the filtered module - $hooks[$key]['modules'] = Hook::getModulesFromHook($hook['id_hook'], $this->display_key); - $hooks[$key]['module_count'] = count($hooks[$key]['modules']); - if($hooks[$key]['module_count']) - { - // If modules were found, link to the previously created Module instances - if (is_array($hooks[$key]['modules']) && !empty($hooks[$key]['modules'])) - foreach ($hooks[$key]['modules'] as $module_key => $module) - if (isset($assoc_modules_id[$module['id_module']])) - $hooks[$key]['modules'][$module_key]['instance'] = $module_instances[$assoc_modules_id[$module['id_module']]]; - } - else - unset($hooks[$key]); - } + $assoc_modules_id = array(); + foreach ($modules as $module) { + if ($tmp_instance = Module::getInstanceById((int)$module['id_module'])) { + // We want to be able to sort modules by display name + $module_instances[$tmp_instance->displayName] = $tmp_instance; + // But we also want to associate hooks to modules using the modules IDs + $assoc_modules_id[(int)$module['id_module']] = $tmp_instance->displayName; + } + } + ksort($module_instances); + $hooks = Hook::getHooks(); + foreach ($hooks as $key => $hook) { + // Get all modules for this hook or only the filtered module + $hooks[$key]['modules'] = Hook::getModulesFromHook($hook['id_hook'], $this->display_key); + $hooks[$key]['module_count'] = count($hooks[$key]['modules']); + if ($hooks[$key]['module_count']) { + // If modules were found, link to the previously created Module instances + if (is_array($hooks[$key]['modules']) && !empty($hooks[$key]['modules'])) { + foreach ($hooks[$key]['modules'] as $module_key => $module) { + if (isset($assoc_modules_id[$module['id_module']])) { + $hooks[$key]['modules'][$module_key]['instance'] = $module_instances[$assoc_modules_id[$module['id_module']]]; + } + } + } + } else { + unset($hooks[$key]); + } + } - $this->addJqueryPlugin('tablednd'); + $this->addJqueryPlugin('tablednd'); - $this->toolbar_btn['save'] = array( - 'href' => self::$currentIndex.'&addToHook'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token, - 'desc' => $this->l('Transplant a module') - ); + $this->toolbar_btn['save'] = array( + 'href' => self::$currentIndex.'&addToHook'.($this->display_key ? '&show_modules='.$this->display_key : '').'&token='.$this->token, + 'desc' => $this->l('Transplant a module') + ); - $live_edit_params = array( - 'live_edit' => true, - 'ad' => $admin_dir, - 'liveToken' => $this->token, - 'id_employee' => (int)$this->context->employee->id, - 'id_shop' => (int)$this->context->shop->id - ); + $live_edit_params = array( + 'live_edit' => true, + 'ad' => $admin_dir, + 'liveToken' => $this->token, + 'id_employee' => (int)$this->context->employee->id, + 'id_shop' => (int)$this->context->shop->id + ); - $this->context->smarty->assign(array( - 'show_toolbar' => true, - 'toolbar_btn' => $this->toolbar_btn, - 'title' => $this->toolbar_title, - 'toolbar_scroll' => 'false', - 'token' => $this->token, - 'url_show_modules' => self::$currentIndex.'&token='.$this->token.'&show_modules=', - 'modules' => $module_instances, - 'url_show_invisible' => self::$currentIndex.'&token='.$this->token.'&show_modules='.(int)Tools::getValue('show_modules').'&hook_position=', - 'live_edit' => Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP, - 'url_live_edit' => $this->getLiveEditUrl($live_edit_params), - 'display_key' => $this->display_key, - 'hooks' => $hooks, - 'url_submit' => self::$currentIndex.'&token='.$this->token, - 'can_move' => (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) ? false : true, - )); + $this->context->smarty->assign(array( + 'show_toolbar' => true, + 'toolbar_btn' => $this->toolbar_btn, + 'title' => $this->toolbar_title, + 'toolbar_scroll' => 'false', + 'token' => $this->token, + 'url_show_modules' => self::$currentIndex.'&token='.$this->token.'&show_modules=', + 'modules' => $module_instances, + 'url_show_invisible' => self::$currentIndex.'&token='.$this->token.'&show_modules='.(int)Tools::getValue('show_modules').'&hook_position=', + 'live_edit' => Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP, + 'url_live_edit' => $this->getLiveEditUrl($live_edit_params), + 'display_key' => $this->display_key, + 'hooks' => $hooks, + 'url_submit' => self::$currentIndex.'&token='.$this->token, + 'can_move' => (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) ? false : true, + )); - return $this->createTemplate('list_modules.tpl')->fetch(); - } + return $this->createTemplate('list_modules.tpl')->fetch(); + } - public function getLiveEditUrl($live_edit_params) - { - $lang = ''; + public function getLiveEditUrl($live_edit_params) + { + $lang = ''; - $language_ids = Language::getIDs(true); - if (Configuration::get('PS_REWRITING_SETTINGS') && !empty($language_ids) && count($language_ids) > 1) - $lang = Language::getIsoById($this->context->employee->id_lang).'/'; - unset($language_ids); + $language_ids = Language::getIDs(true); + if (Configuration::get('PS_REWRITING_SETTINGS') && !empty($language_ids) && count($language_ids) > 1) { + $lang = Language::getIsoById($this->context->employee->id_lang).'/'; + } + unset($language_ids); - // Shop::initialize() in config.php may empty $this->context->shop->virtual_uri so using a new shop instance for getBaseUrl() - $this->context->shop = new Shop((int)$this->context->shop->id); - $url = $this->context->shop->getBaseURL().$lang.Dispatcher::getInstance()->createUrl('index', (int)$this->context->language->id, $live_edit_params); + // Shop::initialize() in config.php may empty $this->context->shop->virtual_uri so using a new shop instance for getBaseUrl() + $this->context->shop = new Shop((int)$this->context->shop->id); + $url = $this->context->shop->getBaseURL().$lang.Dispatcher::getInstance()->createUrl('index', (int)$this->context->language->id, $live_edit_params); - return $url; - } + return $url; + } - public function renderForm() - { - // Init toolbar - $this->initToolbarTitle(); - // toolbar (save, cancel, new, ..) - $this->initToolbar(); - $id_module = (int)Tools::getValue('id_module'); - $id_hook = (int)Tools::getValue('id_hook'); - if (Tools::isSubmit('editGraft')) - { - // Check auth for this page - if (!$id_module || !$id_hook) - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + public function renderForm() + { + // Init toolbar + $this->initToolbarTitle(); + // toolbar (save, cancel, new, ..) + $this->initToolbar(); + $id_module = (int)Tools::getValue('id_module'); + $id_hook = (int)Tools::getValue('id_hook'); + $show_modules = (int)Tools::getValue('show_modules'); - $sql = 'SELECT id_module + if (Tools::isSubmit('editGraft')) { + // Check auth for this page + if (!$id_module || !$id_hook) { + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } + + $sql = 'SELECT id_module FROM '._DB_PREFIX_.'hook_module WHERE id_module = '.$id_module.' AND id_hook = '.$id_hook.' AND id_shop IN('.implode(', ', Shop::getContextListShopID()).')'; - if (!Db::getInstance()->getValue($sql)) - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + if (!Db::getInstance()->getValue($sql)) { + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } - $sl_module = Module::getInstanceById($id_module); - $excepts_list = $sl_module->getExceptions($id_hook, true); - $excepts_diff = false; - $excepts = ''; - if ($excepts_list) - { - $first = current($excepts_list); - foreach ($excepts_list as $k => $v) - if (array_diff($v, $first) || array_diff($first, $v)) - $excepts_diff = true; + $sl_module = Module::getInstanceById($id_module); + $excepts_list = $sl_module->getExceptions($id_hook, true); + $excepts_diff = false; + $excepts = ''; + if ($excepts_list) { + $first = current($excepts_list); + foreach ($excepts_list as $k => $v) { + if (array_diff($v, $first) || array_diff($first, $v)) { + $excepts_diff = true; + } + } - if (!$excepts_diff) - $excepts = implode(', ', $first); - } - } - else - { - $excepts_diff = false; - $excepts_list = Tools::getValue('exceptions', array(array())); - } - $modules = Module::getModulesInstalled(0); + if (!$excepts_diff) { + $excepts = implode(', ', $first); + } + } + } else { + $excepts_diff = false; + $excepts_list = Tools::getValue('exceptions', array(array())); + } + $modules = Module::getModulesInstalled(0); - $instances = array(); - foreach ($modules as $module) - if ($tmp_instance = Module::getInstanceById($module['id_module'])) - $instances[$tmp_instance->displayName] = $tmp_instance; - ksort($instances); - $modules = $instances; + $instances = array(); + foreach ($modules as $module) { + if ($tmp_instance = Module::getInstanceById($module['id_module'])) { + $instances[$tmp_instance->displayName] = $tmp_instance; + } + } + ksort($instances); + $modules = $instances; - $hooks = array(); - if ((int)Tools::getValue('id_hook') > 0) - { - $module_instance = Module::getInstanceById((int)Tools::getValue('id_module')); - $hooks = $module_instance->getPossibleHooksList(); - } + $hooks = array(); + if ($show_modules || (Tools::getValue('id_hook') > 0)) { + $module_instance = Module::getInstanceById((int)Tools::getValue('id_module', $show_modules)); + $hooks = $module_instance->getPossibleHooksList(); + } - $exception_list_diff = array(); - foreach ($excepts_list as $shop_id => $file_list) - $exception_list_diff[] = $this->displayModuleExceptionList($file_list, $shop_id); + $exception_list_diff = array(); + foreach ($excepts_list as $shop_id => $file_list) { + $exception_list_diff[] = $this->displayModuleExceptionList($file_list, $shop_id); + } - $tpl = $this->createTemplate('form.tpl'); - $tpl->assign(array( - 'url_submit' => self::$currentIndex.'&token='.$this->token, - 'edit_graft' => Tools::isSubmit('editGraft'), - 'id_module' => (int)Tools::getValue('id_module'), - 'id_hook' => (int)Tools::getValue('id_hook'), - 'show_modules' => Tools::getValue('show_modules'), - 'hooks' => $hooks, - 'exception_list' => $this->displayModuleExceptionList(array_shift($excepts_list), 0), - 'exception_list_diff' => $exception_list_diff, - 'except_diff' => isset($excepts_diff) ? $excepts_diff : null, - 'display_key' => $this->display_key, - 'modules' => $modules, - 'show_toolbar' => true, - 'toolbar_btn' => $this->toolbar_btn, - 'toolbar_scroll' => $this->toolbar_scroll, - 'title' => $this->toolbar_title, - 'table' => 'hook_module', - )); + $tpl = $this->createTemplate('form.tpl'); + $tpl->assign(array( + 'url_submit' => self::$currentIndex.'&token='.$this->token, + 'edit_graft' => Tools::isSubmit('editGraft'), + 'id_module' => (int)Tools::getValue('id_module'), + 'id_hook' => (int)Tools::getValue('id_hook'), + 'show_modules' => $show_modules, + 'hooks' => $hooks, + 'exception_list' => $this->displayModuleExceptionList(array_shift($excepts_list), 0), + 'exception_list_diff' => $exception_list_diff, + 'except_diff' => isset($excepts_diff) ? $excepts_diff : null, + 'display_key' => $this->display_key, + 'modules' => $modules, + 'show_toolbar' => true, + 'toolbar_btn' => $this->toolbar_btn, + 'toolbar_scroll' => $this->toolbar_scroll, + 'title' => $this->toolbar_title, + 'table' => 'hook_module', + )); - return $tpl->fetch(); - } + return $tpl->fetch(); + } - public function displayModuleExceptionList($file_list, $shop_id) - { - if (!is_array($file_list)) - $file_list = ($file_list) ? array($file_list) : array(); + public function displayModuleExceptionList($file_list, $shop_id) + { + if (!is_array($file_list)) { + $file_list = ($file_list) ? array($file_list) : array(); + } - $content = '<p><input type="text" name="exceptions['.$shop_id.']" value="'.implode(', ', $file_list).'" id="em_text_'.$shop_id.'" placeholder="'.$this->l('E.g. address, addresses, attachment').'"/></p>'; + $content = '<p><input type="text" name="exceptions['.$shop_id.']" value="'.implode(', ', $file_list).'" id="em_text_'.$shop_id.'" placeholder="'.$this->l('E.g. address, addresses, attachment').'"/></p>'; - if ($shop_id) - { - $shop = new Shop($shop_id); - $content .= ' ('.$shop->name.')'; - } + if ($shop_id) { + $shop = new Shop($shop_id); + $content .= ' ('.$shop->name.')'; + } - $content .= '<p> + $content .= '<p> <select size="25" id="em_list_'.$shop_id.'" multiple="multiple"> <option disabled="disabled">'.$this->l('___________ CUSTOM ___________').'</option>'; - // @todo do something better with controllers - $controllers = Dispatcher::getControllers(_PS_FRONT_CONTROLLER_DIR_); - ksort($controllers); + // @todo do something better with controllers + $controllers = Dispatcher::getControllers(_PS_FRONT_CONTROLLER_DIR_); + ksort($controllers); - foreach ($file_list as $k => $v) - if ( ! array_key_exists ($v, $controllers)) - $content .= '<option value="'.$v.'">'.$v.'</option>'; + foreach ($file_list as $k => $v) { + if (! array_key_exists($v, $controllers)) { + $content .= '<option value="'.$v.'">'.$v.'</option>'; + } + } - $content .= '<option disabled="disabled">'.$this->l('____________ CORE ____________').'</option>'; + $content .= '<option disabled="disabled">'.$this->l('____________ CORE ____________').'</option>'; - foreach ($controllers as $k => $v) - $content .= '<option value="'.$k.'">'.$k.'</option>'; + foreach ($controllers as $k => $v) { + $content .= '<option value="'.$k.'">'.$k.'</option>'; + } - $modules_controllers_type = array('admin' => $this->l('Admin modules controller'), 'front' => $this->l('Front modules controller')); - foreach ($modules_controllers_type as $type => $label) - { - $content .= '<option disabled="disabled">____________ '.$label.' ____________</option>'; - $all_modules_controllers = Dispatcher::getModuleControllers($type); - foreach ($all_modules_controllers as $module => $modules_controllers) - foreach ($modules_controllers as $cont) - $content .= '<option value="module-'.$module.'-'.$cont.'">module-'.$module.'-'.$cont.'</option>'; - } + $modules_controllers_type = array('admin' => $this->l('Admin modules controller'), 'front' => $this->l('Front modules controller')); + foreach ($modules_controllers_type as $type => $label) { + $content .= '<option disabled="disabled">____________ '.$label.' ____________</option>'; + $all_modules_controllers = Dispatcher::getModuleControllers($type); + foreach ($all_modules_controllers as $module => $modules_controllers) { + foreach ($modules_controllers as $cont) { + $content .= '<option value="module-'.$module.'-'.$cont.'">module-'.$module.'-'.$cont.'</option>'; + } + } + } - $content .= '</select> + $content .= '</select> </p>'; - return $content; - } + return $content; + } - public function ajaxProcessUpdatePositions() - { - if ($this->tabAccess['edit'] === '1') - { - $id_module = (int)(Tools::getValue('id_module')); - $id_hook = (int)(Tools::getValue('id_hook')); - $way = (int)(Tools::getValue('way')); - $positions = Tools::getValue(strval($id_hook)); - $position = (is_array($positions)) ? array_search($id_hook.'_'.$id_module, $positions) : null; - $module = Module::getInstanceById($id_module); - if (Validate::isLoadedObject($module)) - if ($module->updatePosition($id_hook, $way, $position)) - die(true); - else - die('{"hasError" : true, "errors" : "Cannot update module position."}'); - else - die('{"hasError" : true, "errors" : "This module cannot be loaded."}'); - } - } + public function ajaxProcessUpdatePositions() + { + if ($this->tabAccess['edit'] === '1') { + $id_module = (int)(Tools::getValue('id_module')); + $id_hook = (int)(Tools::getValue('id_hook')); + $way = (int)(Tools::getValue('way')); + $positions = Tools::getValue(strval($id_hook)); + $position = (is_array($positions)) ? array_search($id_hook.'_'.$id_module, $positions) : null; + $module = Module::getInstanceById($id_module); + if (Validate::isLoadedObject($module)) { + if ($module->updatePosition($id_hook, $way, $position)) { + die(true); + } else { + die('{"hasError" : true, "errors" : "Cannot update module position."}'); + } + } else { + die('{"hasError" : true, "errors" : "This module cannot be loaded."}'); + } + } + } - public function ajaxProcessGetHookableList() - { - if ($this->tabAccess['view'] === '1') - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - die('{"hasError" : true, "errors" : ["Live Edit: This functionality has been disabled."]}'); + public function ajaxProcessGetHookableList() + { + if ($this->tabAccess['view'] === '1') { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + die('{"hasError" : true, "errors" : ["Live Edit: This functionality has been disabled."]}'); + } - if (!count(Tools::getValue('hooks_list'))) - die('{"hasError" : true, "errors" : ["Live Edit: no module on this page."]}'); + if (!count(Tools::getValue('hooks_list'))) { + die('{"hasError" : true, "errors" : ["Live Edit: no module on this page."]}'); + } - $modules_list = Tools::getValue('modules_list'); - $hooks_list = Tools::getValue('hooks_list'); - $hookableList = array(); + $modules_list = Tools::getValue('modules_list'); + $hooks_list = Tools::getValue('hooks_list'); + $hookableList = array(); - foreach ($modules_list as $module) - { - $module = trim($module); - if (!$module) - continue; + foreach ($modules_list as $module) { + $module = trim($module); + if (!$module) { + continue; + } - if (!Validate::isModuleName($module)) - die('{"hasError" : true, "errors" : ["Live Edit: module is invalid."]}'); + if (!Validate::isModuleName($module)) { + die('{"hasError" : true, "errors" : ["Live Edit: module is invalid."]}'); + } - $moduleInstance = Module::getInstanceByName($module); - foreach ($hooks_list as $hook_name) - { - $hook_name = trim($hook_name); - if (!$hook_name) - continue; - if (!array_key_exists($hook_name, $hookableList)) - $hookableList[$hook_name] = array(); - if ($moduleInstance->isHookableOn($hook_name)) - array_push($hookableList[$hook_name], str_replace('_', '-', $module)); - } + $moduleInstance = Module::getInstanceByName($module); + foreach ($hooks_list as $hook_name) { + $hook_name = trim($hook_name); + if (!$hook_name) { + continue; + } + if (!array_key_exists($hook_name, $hookableList)) { + $hookableList[$hook_name] = array(); + } + if ($moduleInstance->isHookableOn($hook_name)) { + array_push($hookableList[$hook_name], str_replace('_', '-', $module)); + } + } + } + $hookableList['hasError'] = false; + die(Tools::jsonEncode($hookableList)); + } + } - } - $hookableList['hasError'] = false; - die(Tools::jsonEncode($hookableList)); - } - } + public function ajaxProcessGetHookableModuleList() + { + if ($this->tabAccess['view'] === '1') { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + die('{"hasError" : true, "errors" : ["Live Edit: This functionality has been disabled."]}'); + } + /* PrestaShop demo mode*/ - public function ajaxProcessGetHookableModuleList() - { - if ($this->tabAccess['view'] === '1') - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - die('{"hasError" : true, "errors" : ["Live Edit: This functionality has been disabled."]}'); - /* PrestaShop demo mode*/ + $hook_name = Tools::getValue('hook'); + $hookableModulesList = array(); + $modules = Db::getInstance()->executeS('SELECT id_module, name FROM `'._DB_PREFIX_.'module` '); + foreach ($modules as $module) { + if (!Validate::isModuleName($module['name'])) { + continue; + } + if (file_exists(_PS_MODULE_DIR_.$module['name'].'/'.$module['name'].'.php')) { + include_once(_PS_MODULE_DIR_.$module['name'].'/'.$module['name'].'.php'); - $hook_name = Tools::getValue('hook'); - $hookableModulesList = array(); - $modules = Db::getInstance()->executeS('SELECT id_module, name FROM `'._DB_PREFIX_.'module` '); - foreach ($modules as $module) - { - if (!Validate::isModuleName($module['name'])) - continue; - if (file_exists(_PS_MODULE_DIR_.$module['name'].'/'.$module['name'].'.php')) - { - include_once(_PS_MODULE_DIR_.$module['name'].'/'.$module['name'].'.php'); + /** @var Module $mod */ + $mod = new $module['name'](); + if ($mod->isHookableOn($hook_name)) { + $hookableModulesList[] = array('id' => (int)$mod->id, 'name' => $mod->displayName, 'display' => Hook::exec($hook_name, array(), (int)$mod->id)); + } + } + } + die(Tools::jsonEncode($hookableModulesList)); + } + } + public function ajaxProcessSaveHook() + { + if ($this->tabAccess['edit'] === '1') { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + die('{"hasError" : true, "errors" : ["Live Edit: This functionality has been disabled."]}'); + } - /** @var Module $mod */ - $mod = new $module['name'](); - if ($mod->isHookableOn($hook_name)) - $hookableModulesList[] = array('id' => (int)$mod->id, 'name' => $mod->displayName, 'display' => Hook::exec($hook_name, array(), (int)$mod->id)); - } - } - die(Tools::jsonEncode($hookableModulesList)); - } - } - public function ajaxProcessSaveHook() - { - if ($this->tabAccess['edit'] === '1') - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - die('{"hasError" : true, "errors" : ["Live Edit: This functionality has been disabled."]}'); + $hooks_list = explode(',', Tools::getValue('hooks_list')); + $id_shop = (int)Tools::getValue('id_shop'); + if (!$id_shop) { + $id_shop = Context::getContext()->shop->id; + } - $hooks_list = explode(',', Tools::getValue('hooks_list')); - $id_shop = (int)Tools::getValue('id_shop'); - if (!$id_shop) - $id_shop = Context::getContext()->shop->id; + $res = true; + $hookableList = array(); + // $_POST['hook'] is an array of id_module + $hooks_list = Tools::getValue('hook'); - $res = true; - $hookableList = array(); - // $_POST['hook'] is an array of id_module - $hooks_list = Tools::getValue('hook'); + foreach ($hooks_list as $id_hook => $modules) { + // 1st, drop all previous hooked modules + $sql = 'DELETE FROM `'._DB_PREFIX_.'hook_module` WHERE `id_hook` = '.(int)$id_hook.' AND id_shop = '.(int)$id_shop; + $res &= Db::getInstance()->execute($sql); - foreach ($hooks_list as $id_hook => $modules) - { - // 1st, drop all previous hooked modules - $sql = 'DELETE FROM `'._DB_PREFIX_.'hook_module` WHERE `id_hook` = '.(int)$id_hook.' AND id_shop = '.(int)$id_shop; - $res &= Db::getInstance()->execute($sql); + $i = 1; + $value = ''; + $ids = array(); + // then prepare sql query to rehook all chosen modules(id_module, id_shop, id_hook, position) + // position is i (autoincremented) + if (is_array($modules) && count($modules)) { + foreach ($modules as $id_module) { + if ($id_module && !in_array($id_module, $ids)) { + $ids[] = (int)$id_module; + $value .= '('.(int)$id_module.', '.(int)$id_shop.', '.(int)$id_hook.', '.(int)$i.'),'; + } + $i++; + } - $i = 1; - $value = ''; - $ids = array(); - // then prepare sql query to rehook all chosen modules(id_module, id_shop, id_hook, position) - // position is i (autoincremented) - if (is_array($modules) && count($modules)) - { - foreach ($modules as $id_module) - { - if ($id_module && !in_array($id_module, $ids)) - { - $ids[] = (int)$id_module; - $value .= '('.(int)$id_module.', '.(int)$id_shop.', '.(int)$id_hook.', '.(int)$i.'),'; - } - $i++; - } + if ($value) { + $value = rtrim($value, ','); + $res &= Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'hook_module` (id_module, id_shop, id_hook, position) VALUES '.$value); + } + } + } + if ($res) { + $hasError = true; + } else { + $hasError = false; + } + die('{"hasError" : false, "errors" : ""}'); + } + } - if ($value) - { - $value = rtrim($value, ','); - $res &= Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_.'hook_module` (id_module, id_shop, id_hook, position) VALUES '.$value); - } - } - } - if ($res) - $hasError = true; - else - $hasError = false; - die('{"hasError" : false, "errors" : ""}'); - } - } + /** + * Return a json array containing the possible hooks for a module. + * + * @return null + */ + public function ajaxProcessGetPossibleHookingListForModule() + { + $module_id = (int)Tools::getValue('module_id'); + if ($module_id == 0) { + die('{"hasError" : true, "errors" : ["Wrong module ID."]}'); + } - /** - * Return a json array containing the possible hooks for a module. - * - * @return null - */ - public function ajaxProcessGetPossibleHookingListForModule() - { - $module_id = (int)Tools::getValue('module_id'); - if ($module_id == 0) - die('{"hasError" : true, "errors" : ["Wrong module ID."]}'); - - $module_instance = Module::getInstanceById($module_id); - die(json_encode($module_instance->getPossibleHooksList())); - } + $module_instance = Module::getInstanceById($module_id); + die(json_encode($module_instance->getPossibleHooksList())); + } } diff --git a/controllers/admin/AdminNotFoundController.php b/controllers/admin/AdminNotFoundController.php index 52a9e371..fbc3dc02 100644 --- a/controllers/admin/AdminNotFoundController.php +++ b/controllers/admin/AdminNotFoundController.php @@ -26,28 +26,27 @@ class AdminNotFoundControllerCore extends AdminController { + public function __construct() + { + $this->bootstrap = true; + parent::__construct(); + } - public function __construct() - { - $this->bootstrap = true; - parent::__construct(); - } + public function checkAccess() + { + return true; + } - public function checkAccess() - { - return true; - } + public function viewAccess() + { + return true; + } - public function viewAccess() - { - return true; - } - - public function initContent() - { - $this->errors[] = Tools::displayError('Controller not found'); - $tpl_vars['controller'] = Tools::getvalue('controllerUri', Tools::getvalue('controller')); - $this->context->smarty->assign($tpl_vars); - parent::initContent(); - } + public function initContent() + { + $this->errors[] = Tools::displayError('Controller not found'); + $tpl_vars['controller'] = Tools::getvalue('controllerUri', Tools::getvalue('controller')); + $this->context->smarty->assign($tpl_vars); + parent::initContent(); + } } diff --git a/controllers/admin/AdminOrderMessageController.php b/controllers/admin/AdminOrderMessageController.php index cf1c078d..7c81dec0 100644 --- a/controllers/admin/AdminOrderMessageController.php +++ b/controllers/admin/AdminOrderMessageController.php @@ -29,84 +29,84 @@ */ class AdminOrderMessageControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'order_message'; - $this->className = 'OrderMessage'; - $this->lang = true; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'order_message'; + $this->className = 'OrderMessage'; + $this->lang = true; - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->context = Context::getContext(); + $this->context = Context::getContext(); - if (!Tools::getValue('realedit')) - $this->deleted = false; + if (!Tools::getValue('realedit')) { + $this->deleted = false; + } - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->fields_list = array( - 'id_order_message' => array( - 'title' => $this->l('ID'), - 'align' => 'center' - ), - 'name' => array( - 'title' => $this->l('Name') - ), - 'message' => array( - 'title' => $this->l('Message'), - 'maxlength' => 300 - ) - ); + $this->fields_list = array( + 'id_order_message' => array( + 'title' => $this->l('ID'), + 'align' => 'center' + ), + 'name' => array( + 'title' => $this->l('Name') + ), + 'message' => array( + 'title' => $this->l('Message'), + 'maxlength' => 300 + ) + ); - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Order messages'), - 'icon' => 'icon-mail' - ), - 'input' => array( - array( - 'type' => 'text', - 'lang' => true, - 'label' => $this->l('Name'), - 'name' => 'name', - 'size' => 53, - 'required' => true - ), - array( - 'type' => 'textarea', - 'lang' => true, - 'label' => $this->l('Message'), - 'name' => 'message', - 'required' => true - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Order messages'), + 'icon' => 'icon-mail' + ), + 'input' => array( + array( + 'type' => 'text', + 'lang' => true, + 'label' => $this->l('Name'), + 'name' => 'name', + 'size' => 53, + 'required' => true + ), + array( + 'type' => 'textarea', + 'lang' => true, + 'label' => $this->l('Message'), + 'name' => 'message', + 'required' => true + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_order_message'] = array( - 'href' => self::$currentIndex.'&addorder_message&token='.$this->token, - 'desc' => $this->l('Add new order message'), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_order_message'] = array( + 'href' => self::$currentIndex.'&addorder_message&token='.$this->token, + 'desc' => $this->l('Add new order message'), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } } - - diff --git a/controllers/admin/AdminOrderPreferencesController.php b/controllers/admin/AdminOrderPreferencesController.php index 27905ecf..540f5b5e 100644 --- a/controllers/admin/AdminOrderPreferencesController.php +++ b/controllers/admin/AdminOrderPreferencesController.php @@ -29,160 +29,164 @@ */ class AdminOrderPreferencesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->className = 'Configuration'; - $this->table = 'configuration'; + public function __construct() + { + $this->bootstrap = true; + $this->className = 'Configuration'; + $this->table = 'configuration'; - parent::__construct(); + parent::__construct(); - // List of CMS tabs - $cms_tab = array(0 => array( - 'id' => 0, - 'name' => $this->l('None') - )); - foreach (CMS::listCms($this->context->language->id) as $cms_file) - $cms_tab[] = array('id' => $cms_file['id_cms'], 'name' => $cms_file['meta_title']); + // List of CMS tabs + $cms_tab = array(0 => array( + 'id' => 0, + 'name' => $this->l('None') + )); + foreach (CMS::listCms($this->context->language->id) as $cms_file) { + $cms_tab[] = array('id' => $cms_file['id_cms'], 'name' => $cms_file['meta_title']); + } - // List of order process types - $order_process_type = array( - array( - 'value' => PS_ORDER_PROCESS_STANDARD, - 'name' => $this->l('Standard (Five steps)') - ), - array( - 'value' => PS_ORDER_PROCESS_OPC, - 'name' => $this->l('One-page checkout') - ) - ); + // List of order process types + $order_process_type = array( + array( + 'value' => PS_ORDER_PROCESS_STANDARD, + 'name' => $this->l('Standard (Five steps)') + ), + array( + 'value' => PS_ORDER_PROCESS_OPC, + 'name' => $this->l('One-page checkout') + ) + ); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('General'), - 'icon' => 'icon-cogs', - 'fields' => array( - 'PS_ORDER_PROCESS_TYPE' => array( - 'title' => $this->l('Order process type'), - 'hint' => $this->l('Please choose either the five-step or one-page checkout process.'), - 'validation' => 'isInt', - 'cast' => 'intval', - 'type' => 'select', - 'list' => $order_process_type, - 'identifier' => 'value' - ), - 'PS_GUEST_CHECKOUT_ENABLED' => array( - 'title' => $this->l('Enable guest checkout'), - 'hint' => $this->l('Allow guest visitors to place an order without registering.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_DISALLOW_HISTORY_REORDERING' => array( - 'title' => $this->l('Disable Reordering Option'), - 'hint' => $this->l('Disable the option to allow customers to reorder in one click from the order history page (required in some European countries).'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_PURCHASE_MINIMUM' => array( - 'title' => $this->l('Minimum purchase total required in order to validate the order'), - 'hint' => $this->l('Set to 0 to disable this feature.'), - 'validation' => 'isFloat', - 'cast' => 'floatval', - 'type' => 'price' - ), - 'PS_ALLOW_MULTISHIPPING' => array( - 'title' => $this->l('Allow multishipping'), - 'hint' => $this->l('Allow the customer to ship orders to multiple addresses. This option will convert the customer\'s cart into one or more orders.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_SHIP_WHEN_AVAILABLE' => array( - 'title' => $this->l('Delayed shipping'), - 'hint' => $this->l('Allows you to delay shipping at your customers\' request. '), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_CONDITIONS' => array( - 'title' => $this->l('Terms of service'), - 'hint' => $this->l('Require customers to accept or decline terms of service before processing an order.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'js' => array( - 'on' => 'onchange="changeCMSActivationAuthorization()"', - 'off' => 'onchange="changeCMSActivationAuthorization()"' - ) - ), - 'PS_CONDITIONS_CMS_ID' => array( - 'title' => $this->l('CMS page for the Conditions of use'), - 'hint' => $this->l('Choose the CMS page which contains your store\'s conditions of use.'), - 'validation' => 'isInt', - 'type' => 'select', - 'list' => $cms_tab, - 'identifier' => 'id', - 'cast' => 'intval' - ) - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'gift' => array( - 'title' => $this->l('Gift options'), - 'icon' => 'icon-gift', - 'fields' => array( - 'PS_GIFT_WRAPPING' => array( - 'title' => $this->l('Offer gift wrapping'), - 'hint' => $this->l('Suggest gift-wrapping to customers.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_GIFT_WRAPPING_PRICE' => array( - 'title' => $this->l('Gift-wrapping price'), - 'hint' => $this->l('Set a price for gift wrapping.'), - 'validation' => 'isPrice', - 'cast' => 'floatval', - 'type' => 'price' - ), - 'PS_GIFT_WRAPPING_TAX_RULES_GROUP' => array( - 'title' => $this->l('Gift-wrapping tax'), - 'hint' => $this->l('Set a tax for gift wrapping.'), - 'validation' => 'isInt', - 'cast' => 'intval', - 'type' => 'select', - 'list' => array_merge(array(array('id_tax_rules_group' => 0, 'name' => $this->l('None'))), TaxRulesGroup::getTaxRulesGroups(true)), - 'identifier' => 'id_tax_rules_group' - ), - 'PS_RECYCLABLE_PACK' => array( - 'title' => $this->l('Offer recycled packaging'), - 'hint' => $this->l('Suggest recycled packaging to customer.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - ), - 'submit' => array('title' => $this->l('Save')), - ), - ); + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('General'), + 'icon' => 'icon-cogs', + 'fields' => array( + 'PS_ORDER_PROCESS_TYPE' => array( + 'title' => $this->l('Order process type'), + 'hint' => $this->l('Please choose either the five-step or one-page checkout process.'), + 'validation' => 'isInt', + 'cast' => 'intval', + 'type' => 'select', + 'list' => $order_process_type, + 'identifier' => 'value' + ), + 'PS_GUEST_CHECKOUT_ENABLED' => array( + 'title' => $this->l('Enable guest checkout'), + 'hint' => $this->l('Allow guest visitors to place an order without registering.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_DISALLOW_HISTORY_REORDERING' => array( + 'title' => $this->l('Disable Reordering Option'), + 'hint' => $this->l('Disable the option to allow customers to reorder in one click from the order history page (required in some European countries).'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_PURCHASE_MINIMUM' => array( + 'title' => $this->l('Minimum purchase total required in order to validate the order'), + 'hint' => $this->l('Set to 0 to disable this feature.'), + 'validation' => 'isFloat', + 'cast' => 'floatval', + 'type' => 'price' + ), + 'PS_ALLOW_MULTISHIPPING' => array( + 'title' => $this->l('Allow multishipping'), + 'hint' => $this->l('Allow the customer to ship orders to multiple addresses. This option will convert the customer\'s cart into one or more orders.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_SHIP_WHEN_AVAILABLE' => array( + 'title' => $this->l('Delayed shipping'), + 'hint' => $this->l('Allows you to delay shipping at your customers\' request. '), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_CONDITIONS' => array( + 'title' => $this->l('Terms of service'), + 'hint' => $this->l('Require customers to accept or decline terms of service before processing an order.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'js' => array( + 'on' => 'onchange="changeCMSActivationAuthorization()"', + 'off' => 'onchange="changeCMSActivationAuthorization()"' + ) + ), + 'PS_CONDITIONS_CMS_ID' => array( + 'title' => $this->l('CMS page for the Conditions of use'), + 'hint' => $this->l('Choose the CMS page which contains your store\'s conditions of use.'), + 'validation' => 'isInt', + 'type' => 'select', + 'list' => $cms_tab, + 'identifier' => 'id', + 'cast' => 'intval' + ) + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'gift' => array( + 'title' => $this->l('Gift options'), + 'icon' => 'icon-gift', + 'fields' => array( + 'PS_GIFT_WRAPPING' => array( + 'title' => $this->l('Offer gift wrapping'), + 'hint' => $this->l('Suggest gift-wrapping to customers.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_GIFT_WRAPPING_PRICE' => array( + 'title' => $this->l('Gift-wrapping price'), + 'hint' => $this->l('Set a price for gift wrapping.'), + 'validation' => 'isPrice', + 'cast' => 'floatval', + 'type' => 'price' + ), + 'PS_GIFT_WRAPPING_TAX_RULES_GROUP' => array( + 'title' => $this->l('Gift-wrapping tax'), + 'hint' => $this->l('Set a tax for gift wrapping.'), + 'validation' => 'isInt', + 'cast' => 'intval', + 'type' => 'select', + 'list' => array_merge(array(array('id_tax_rules_group' => 0, 'name' => $this->l('None'))), TaxRulesGroup::getTaxRulesGroups(true)), + 'identifier' => 'id_tax_rules_group' + ), + 'PS_RECYCLABLE_PACK' => array( + 'title' => $this->l('Offer recycled packaging'), + 'hint' => $this->l('Suggest recycled packaging to customer.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + ), + 'submit' => array('title' => $this->l('Save')), + ), + ); - if (!Configuration::get('PS_ALLOW_MULTISHIPPING')) - unset($this->fields_options['general']['fields']['PS_ALLOW_MULTISHIPPING']); + if (!Configuration::get('PS_ALLOW_MULTISHIPPING')) { + unset($this->fields_options['general']['fields']['PS_ALLOW_MULTISHIPPING']); + } - if (Configuration::get('PS_ATCP_SHIPWRAP')) - unset($this->fields_options['gift']['fields']['PS_GIFT_WRAPPING_TAX_RULES_GROUP']); - } + if (Configuration::get('PS_ATCP_SHIPWRAP')) { + unset($this->fields_options['gift']['fields']['PS_GIFT_WRAPPING_TAX_RULES_GROUP']); + } + } - /** - * This method is called before we start to update options configuration - */ - public function beforeUpdateOptions() - { - $sql = 'SELECT `id_cms` FROM `'._DB_PREFIX_.'cms` + /** + * This method is called before we start to update options configuration + */ + public function beforeUpdateOptions() + { + $sql = 'SELECT `id_cms` FROM `'._DB_PREFIX_.'cms` WHERE id_cms = '.(int)Tools::getValue('PS_CONDITIONS_CMS_ID'); - if (Tools::getValue('PS_CONDITIONS') && (Tools::getValue('PS_CONDITIONS_CMS_ID') == 0 || !Db::getInstance()->getValue($sql))) - $this->errors[] = Tools::displayError('Assign a valid CMS page if you want it to be read.'); - } + if (Tools::getValue('PS_CONDITIONS') && (Tools::getValue('PS_CONDITIONS_CMS_ID') == 0 || !Db::getInstance()->getValue($sql))) { + $this->errors[] = Tools::displayError('Assign a valid CMS page if you want it to be read.'); + } + } } diff --git a/controllers/admin/AdminOrdersController.php b/controllers/admin/AdminOrdersController.php index 9dd889e8..91bef18b 100644 --- a/controllers/admin/AdminOrdersController.php +++ b/controllers/admin/AdminOrdersController.php @@ -26,13 +26,13 @@ class BoOrder extends PaymentModule { - public $active = 1; - public $name = 'bo_order'; + public $active = 1; + public $name = 'bo_order'; - public function __construct() - { - $this->displayName = $this->l('Back office order'); - } + public function __construct() + { + $this->displayName = $this->l('Back office order'); + } } /** @@ -40,23 +40,23 @@ class BoOrder extends PaymentModule */ class AdminOrdersControllerCore extends AdminController { - public $toolbar_title; + public $toolbar_title; - protected $statuses_array = array(); + protected $statuses_array = array(); - public function __construct() - { - $this->bootstrap = true; - $this->table = 'order'; - $this->className = 'Order'; - $this->lang = false; - $this->addRowAction('view'); - $this->explicitSelect = true; - $this->allow_export = true; - $this->deleted = false; - $this->context = Context::getContext(); + public function __construct() + { + $this->bootstrap = true; + $this->table = 'order'; + $this->className = 'Order'; + $this->lang = false; + $this->addRowAction('view'); + $this->explicitSelect = true; + $this->allow_export = true; + $this->deleted = false; + $this->context = Context::getContext(); - $this->_select = ' + $this->_select = ' a.id_currency, a.id_order AS id_pdf, CONCAT(LEFT(c.`firstname`, 1), \'. \', c.`lastname`) AS `customer`, @@ -66,94 +66,93 @@ class AdminOrdersControllerCore extends AdminController country_lang.name as cname, IF(a.valid, 1, 0) badge_success'; - $this->_join = ' + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'customer` c ON (c.`id_customer` = a.`id_customer`) INNER JOIN `'._DB_PREFIX_.'address` address ON address.id_address = a.id_address_delivery INNER JOIN `'._DB_PREFIX_.'country` country ON address.id_country = country.id_country INNER JOIN `'._DB_PREFIX_.'country_lang` country_lang ON (country.`id_country` = country_lang.`id_country` AND country_lang.`id_lang` = '.(int)$this->context->language->id.') LEFT JOIN `'._DB_PREFIX_.'order_state` os ON (os.`id_order_state` = a.`current_state`) LEFT JOIN `'._DB_PREFIX_.'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = '.(int)$this->context->language->id.')'; - $this->_orderBy = 'id_order'; - $this->_orderWay = 'DESC'; - $this->_use_found_rows = false; + $this->_orderBy = 'id_order'; + $this->_orderWay = 'DESC'; + $this->_use_found_rows = true; - $statuses = OrderState::getOrderStates((int)$this->context->language->id); - foreach ($statuses as $status) - $this->statuses_array[$status['id_order_state']] = $status['name']; + $statuses = OrderState::getOrderStates((int)$this->context->language->id); + foreach ($statuses as $status) { + $this->statuses_array[$status['id_order_state']] = $status['name']; + } - $this->fields_list = array( - 'id_order' => array( - 'title' => $this->l('ID'), - 'align' => 'text-center', - 'class' => 'fixed-width-xs' - ), - 'reference' => array( - 'title' => $this->l('Reference') - ), - 'new' => array( - 'title' => $this->l('New client'), - 'align' => 'text-center', - 'type' => 'bool', - 'tmpTableFilter' => true, - 'orderby' => false, - 'callback' => 'printNewCustomer' - ), - 'customer' => array( - 'title' => $this->l('Customer'), - 'havingFilter' => true, - ), - ); + $this->fields_list = array( + 'id_order' => array( + 'title' => $this->l('ID'), + 'align' => 'text-center', + 'class' => 'fixed-width-xs' + ), + 'reference' => array( + 'title' => $this->l('Reference') + ), + 'new' => array( + 'title' => $this->l('New client'), + 'align' => 'text-center', + 'type' => 'bool', + 'tmpTableFilter' => true, + 'orderby' => false, + 'callback' => 'printNewCustomer' + ), + 'customer' => array( + 'title' => $this->l('Customer'), + 'havingFilter' => true, + ), + ); - if (Configuration::get('PS_B2B_ENABLE')) - { - $this->fields_list = array_merge($this->fields_list, array( - 'company' => array( - 'title' => $this->l('Company'), - 'filter_key' => 'c!company' - ), - )); - } + if (Configuration::get('PS_B2B_ENABLE')) { + $this->fields_list = array_merge($this->fields_list, array( + 'company' => array( + 'title' => $this->l('Company'), + 'filter_key' => 'c!company' + ), + )); + } - $this->fields_list = array_merge($this->fields_list, array( - 'total_paid_tax_incl' => array( - 'title' => $this->l('Total'), - 'align' => 'text-right', - 'type' => 'price', - 'currency' => true, - 'callback' => 'setOrderCurrency', - 'badge_success' => true - ), - 'payment' => array( - 'title' => $this->l('Payment') - ), - 'osname' => array( - 'title' => $this->l('Status'), - 'type' => 'select', - 'color' => 'color', - 'list' => $this->statuses_array, - 'filter_key' => 'os!id_order_state', - 'filter_type' => 'int', - 'order_key' => 'osname' - ), - 'date_add' => array( - 'title' => $this->l('Date'), - 'align' => 'text-right', - 'type' => 'datetime', - 'filter_key' => 'a!date_add' - ), - 'id_pdf' => array( - 'title' => $this->l('PDF'), - 'align' => 'text-center', - 'callback' => 'printPDFIcons', - 'orderby' => false, - 'search' => false, - 'remove_onclick' => true - ) - )); + $this->fields_list = array_merge($this->fields_list, array( + 'total_paid_tax_incl' => array( + 'title' => $this->l('Total'), + 'align' => 'text-right', + 'type' => 'price', + 'currency' => true, + 'callback' => 'setOrderCurrency', + 'badge_success' => true + ), + 'payment' => array( + 'title' => $this->l('Payment') + ), + 'osname' => array( + 'title' => $this->l('Status'), + 'type' => 'select', + 'color' => 'color', + 'list' => $this->statuses_array, + 'filter_key' => 'os!id_order_state', + 'filter_type' => 'int', + 'order_key' => 'osname' + ), + 'date_add' => array( + 'title' => $this->l('Date'), + 'align' => 'text-right', + 'type' => 'datetime', + 'filter_key' => 'a!date_add' + ), + 'id_pdf' => array( + 'title' => $this->l('PDF'), + 'align' => 'text-center', + 'callback' => 'printPDFIcons', + 'orderby' => false, + 'search' => false, + 'remove_onclick' => true + ) + )); - if (Country::isCurrentlyUsed('country', true)) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' + if (Country::isCurrentlyUsed('country', true)) { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT DISTINCT c.id_country, cl.`name` FROM `'._DB_PREFIX_.'orders` o '.Shop::addSqlAssociation('orders', 'o').' @@ -162,2660 +161,2654 @@ class AdminOrdersControllerCore extends AdminController INNER JOIN `'._DB_PREFIX_.'country_lang` cl ON (c.`id_country` = cl.`id_country` AND cl.`id_lang` = '.(int)$this->context->language->id.') ORDER BY cl.name ASC'); - $country_array = array(); - foreach ($result as $row) - $country_array[$row['id_country']] = $row['name']; + $country_array = array(); + foreach ($result as $row) { + $country_array[$row['id_country']] = $row['name']; + } - $part1 = array_slice($this->fields_list, 0, 3); - $part2 = array_slice($this->fields_list, 3); - $part1['cname'] = array( - 'title' => $this->l('Delivery'), - 'type' => 'select', - 'list' => $country_array, - 'filter_key' => 'country!id_country', - 'filter_type' => 'int', - 'order_key' => 'cname' - ); - $this->fields_list = array_merge($part1, $part2); - } + $part1 = array_slice($this->fields_list, 0, 3); + $part2 = array_slice($this->fields_list, 3); + $part1['cname'] = array( + 'title' => $this->l('Delivery'), + 'type' => 'select', + 'list' => $country_array, + 'filter_key' => 'country!id_country', + 'filter_type' => 'int', + 'order_key' => 'cname' + ); + $this->fields_list = array_merge($part1, $part2); + } - $this->shopLinkType = 'shop'; - $this->shopShareDatas = Shop::SHARE_ORDER; + $this->shopLinkType = 'shop'; + $this->shopShareDatas = Shop::SHARE_ORDER; - if (Tools::isSubmit('id_order')) - { - // Save context (in order to apply cart rule) - $order = new Order((int)Tools::getValue('id_order')); - $this->context->cart = new Cart($order->id_cart); - $this->context->customer = new Customer($order->id_customer); - } + if (Tools::isSubmit('id_order')) { + // Save context (in order to apply cart rule) + $order = new Order((int)Tools::getValue('id_order')); + $this->context->cart = new Cart($order->id_cart); + $this->context->customer = new Customer($order->id_customer); + } - $this->bulk_actions = array( - 'updateOrderStatus' => array('text' => $this->l('Change Order Status'), 'icon' => 'icon-refresh') - ); + $this->bulk_actions = array( + 'updateOrderStatus' => array('text' => $this->l('Change Order Status'), 'icon' => 'icon-refresh') + ); - parent::__construct(); - } + parent::__construct(); + } - public static function setOrderCurrency($echo, $tr) - { - $order = new Order($tr['id_order']); - return Tools::displayPrice($echo, (int)$order->id_currency); - } + public static function setOrderCurrency($echo, $tr) + { + $order = new Order($tr['id_order']); + return Tools::displayPrice($echo, (int)$order->id_currency); + } - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); - if (empty($this->display)) - $this->page_header_toolbar_btn['new_order'] = array( - 'href' => self::$currentIndex.'&addorder&token='.$this->token, - 'desc' => $this->l('Add new order', null, null, false), - 'icon' => 'process-icon-new' - ); + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_order'] = array( + 'href' => self::$currentIndex.'&addorder&token='.$this->token, + 'desc' => $this->l('Add new order', null, null, false), + 'icon' => 'process-icon-new' + ); + } - if ($this->display == 'add') - unset($this->page_header_toolbar_btn['save']); + if ($this->display == 'add') { + unset($this->page_header_toolbar_btn['save']); + } - if (Context::getContext()->shop->getContext() != Shop::CONTEXT_SHOP && isset($this->page_header_toolbar_btn['new_order']) - && Shop::isFeatureActive()) - unset($this->page_header_toolbar_btn['new_order']); - } + if (Context::getContext()->shop->getContext() != Shop::CONTEXT_SHOP && isset($this->page_header_toolbar_btn['new_order']) + && Shop::isFeatureActive()) { + unset($this->page_header_toolbar_btn['new_order']); + } + } - public function renderForm() - { - if (Context::getContext()->shop->getContext() != Shop::CONTEXT_SHOP && Shop::isFeatureActive()) - $this->errors[] = $this->l('You have to select a shop before creating new orders.'); + public function renderForm() + { + if (Context::getContext()->shop->getContext() != Shop::CONTEXT_SHOP && Shop::isFeatureActive()) { + $this->errors[] = $this->l('You have to select a shop before creating new orders.'); + } - $id_cart = (int)Tools::getValue('id_cart'); - $cart = new Cart((int)$id_cart); - if ($id_cart && !Validate::isLoadedObject($cart)) - $this->errors[] = $this->l('This cart does not exists'); - if ($id_cart && Validate::isLoadedObject($cart) && !$cart->id_customer) - $this->errors[] = $this->l('The cart must have a customer'); - if (count($this->errors)) - return false; + $id_cart = (int)Tools::getValue('id_cart'); + $cart = new Cart((int)$id_cart); + if ($id_cart && !Validate::isLoadedObject($cart)) { + $this->errors[] = $this->l('This cart does not exists'); + } + if ($id_cart && Validate::isLoadedObject($cart) && !$cart->id_customer) { + $this->errors[] = $this->l('The cart must have a customer'); + } + if (count($this->errors)) { + return false; + } - parent::renderForm(); - unset($this->toolbar_btn['save']); - $this->addJqueryPlugin(array('autocomplete', 'fancybox', 'typewatch')); + parent::renderForm(); + unset($this->toolbar_btn['save']); + $this->addJqueryPlugin(array('autocomplete', 'fancybox', 'typewatch')); - $defaults_order_state = array('cheque' => (int)Configuration::get('PS_OS_CHEQUE'), - 'bankwire' => (int)Configuration::get('PS_OS_BANKWIRE'), - 'cashondelivery' => Configuration::get('PS_OS_COD_VALIDATION') ? (int)Configuration::get('PS_OS_COD_VALIDATION') : (int)Configuration::get('PS_OS_PREPARATION'), - 'other' => (int)Configuration::get('PS_OS_PAYMENT')); - $payment_modules = array(); - foreach (PaymentModule::getInstalledPaymentModules() as $p_module) - $payment_modules[] = Module::getInstanceById((int)$p_module['id_module']); + $defaults_order_state = array('cheque' => (int)Configuration::get('PS_OS_CHEQUE'), + 'bankwire' => (int)Configuration::get('PS_OS_BANKWIRE'), + 'cashondelivery' => Configuration::get('PS_OS_COD_VALIDATION') ? (int)Configuration::get('PS_OS_COD_VALIDATION') : (int)Configuration::get('PS_OS_PREPARATION'), + 'other' => (int)Configuration::get('PS_OS_PAYMENT')); + $payment_modules = array(); + foreach (PaymentModule::getInstalledPaymentModules() as $p_module) { + $payment_modules[] = Module::getInstanceById((int)$p_module['id_module']); + } - $this->context->smarty->assign(array( - 'recyclable_pack' => (int)Configuration::get('PS_RECYCLABLE_PACK'), - 'gift_wrapping' => (int)Configuration::get('PS_GIFT_WRAPPING'), - 'cart' => $cart, - 'currencies' => Currency::getCurrenciesByIdShop(Context::getContext()->shop->id), - 'langs' => Language::getLanguages(true, Context::getContext()->shop->id), - 'payment_modules' => $payment_modules, - 'order_states' => OrderState::getOrderStates((int)Context::getContext()->language->id), - 'defaults_order_state' => $defaults_order_state, - 'show_toolbar' => $this->show_toolbar, - 'toolbar_btn' => $this->toolbar_btn, - 'toolbar_scroll' => $this->toolbar_scroll, - 'PS_CATALOG_MODE' => Configuration::get('PS_CATALOG_MODE'), - 'title' => array($this->l('Orders'), $this->l('Create order')) + $this->context->smarty->assign(array( + 'recyclable_pack' => (int)Configuration::get('PS_RECYCLABLE_PACK'), + 'gift_wrapping' => (int)Configuration::get('PS_GIFT_WRAPPING'), + 'cart' => $cart, + 'currencies' => Currency::getCurrenciesByIdShop(Context::getContext()->shop->id), + 'langs' => Language::getLanguages(true, Context::getContext()->shop->id), + 'payment_modules' => $payment_modules, + 'order_states' => OrderState::getOrderStates((int)Context::getContext()->language->id), + 'defaults_order_state' => $defaults_order_state, + 'show_toolbar' => $this->show_toolbar, + 'toolbar_btn' => $this->toolbar_btn, + 'toolbar_scroll' => $this->toolbar_scroll, + 'PS_CATALOG_MODE' => Configuration::get('PS_CATALOG_MODE'), + 'title' => array($this->l('Orders'), $this->l('Create order')) - )); - $this->content .= $this->createTemplate('form.tpl')->fetch(); - } + )); + $this->content .= $this->createTemplate('form.tpl')->fetch(); + } - public function initToolbar() - { - if ($this->display == 'view') - { - /** @var Order $order */ - $order = $this->loadObject(); - $customer = $this->context->customer; + public function initToolbar() + { + if ($this->display == 'view') { + /** @var Order $order */ + $order = $this->loadObject(); + $customer = $this->context->customer; - if (!Validate::isLoadedObject($order)) - Tools::redirectAdmin($this->context->link->getAdminLink('AdminOrders')); + if (!Validate::isLoadedObject($order)) { + Tools::redirectAdmin($this->context->link->getAdminLink('AdminOrders')); + } - $this->toolbar_title[] = sprintf($this->l('Order %1$s from %2$s %3$s'), $order->reference, $customer->firstname, $customer->lastname); - $this->addMetaTitle($this->toolbar_title[count($this->toolbar_title) - 1]); + $this->toolbar_title[] = sprintf($this->l('Order %1$s from %2$s %3$s'), $order->reference, $customer->firstname, $customer->lastname); + $this->addMetaTitle($this->toolbar_title[count($this->toolbar_title) - 1]); - if ($order->hasBeenShipped()) - $type = $this->l('Return products'); - elseif ($order->hasBeenPaid()) - $type = $this->l('Standard refund'); - else - $type = $this->l('Cancel products'); + if ($order->hasBeenShipped()) { + $type = $this->l('Return products'); + } elseif ($order->hasBeenPaid()) { + $type = $this->l('Standard refund'); + } else { + $type = $this->l('Cancel products'); + } - if (!$order->hasBeenShipped() && !$this->lite_display) - $this->toolbar_btn['new'] = array( - 'short' => 'Create', - 'href' => '#', - 'desc' => $this->l('Add a product'), - 'class' => 'add_product' - ); + if (!$order->hasBeenShipped() && !$this->lite_display) { + $this->toolbar_btn['new'] = array( + 'short' => 'Create', + 'href' => '#', + 'desc' => $this->l('Add a product'), + 'class' => 'add_product' + ); + } - if (Configuration::get('PS_ORDER_RETURN') && !$this->lite_display) - $this->toolbar_btn['standard_refund'] = array( - 'short' => 'Create', - 'href' => '', - 'desc' => $type, - 'class' => 'process-icon-standardRefund' - ); + if (Configuration::get('PS_ORDER_RETURN') && !$this->lite_display) { + $this->toolbar_btn['standard_refund'] = array( + 'short' => 'Create', + 'href' => '', + 'desc' => $type, + 'class' => 'process-icon-standardRefund' + ); + } - if ($order->hasInvoice() && !$this->lite_display) - $this->toolbar_btn['partial_refund'] = array( - 'short' => 'Create', - 'href' => '', - 'desc' => $this->l('Partial refund'), - 'class' => 'process-icon-partialRefund' - ); - } - $res = parent::initToolbar(); - if (Context::getContext()->shop->getContext() != Shop::CONTEXT_SHOP && isset($this->toolbar_btn['new']) && Shop::isFeatureActive()) - unset($this->toolbar_btn['new']); - return $res; - } + if ($order->hasInvoice() && !$this->lite_display) { + $this->toolbar_btn['partial_refund'] = array( + 'short' => 'Create', + 'href' => '', + 'desc' => $this->l('Partial refund'), + 'class' => 'process-icon-partialRefund' + ); + } + } + $res = parent::initToolbar(); + if (Context::getContext()->shop->getContext() != Shop::CONTEXT_SHOP && isset($this->toolbar_btn['new']) && Shop::isFeatureActive()) { + unset($this->toolbar_btn['new']); + } + return $res; + } - public function setMedia() - { - parent::setMedia(); + public function setMedia() + { + parent::setMedia(); - $this->addJqueryUI('ui.datepicker'); - $this->addJS(_PS_JS_DIR_.'vendor/d3.v3.min.js'); - $this->addJS('https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false'); + $this->addJqueryUI('ui.datepicker'); + $this->addJS(_PS_JS_DIR_.'vendor/d3.v3.min.js'); + $this->addJS('https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false'); - if ($this->tabAccess['edit'] == 1 && $this->display == 'view') - { - $this->addJS(_PS_JS_DIR_.'admin/orders.js'); - $this->addJS(_PS_JS_DIR_.'tools.js'); - $this->addJqueryPlugin('autocomplete'); - } - } + if ($this->tabAccess['edit'] == 1 && $this->display == 'view') { + $this->addJS(_PS_JS_DIR_.'admin/orders.js'); + $this->addJS(_PS_JS_DIR_.'tools.js'); + $this->addJqueryPlugin('autocomplete'); + } + } - public function printPDFIcons($id_order, $tr) - { - static $valid_order_state = array(); + public function printPDFIcons($id_order, $tr) + { + static $valid_order_state = array(); - $order = new Order($id_order); - if (!Validate::isLoadedObject($order)) - return ''; + $order = new Order($id_order); + if (!Validate::isLoadedObject($order)) { + return ''; + } - if (!isset($valid_order_state[$order->current_state])) - $valid_order_state[$order->current_state] = Validate::isLoadedObject($order->getCurrentOrderState()); + if (!isset($valid_order_state[$order->current_state])) { + $valid_order_state[$order->current_state] = Validate::isLoadedObject($order->getCurrentOrderState()); + } - if (!$valid_order_state[$order->current_state]) - return ''; + if (!$valid_order_state[$order->current_state]) { + return ''; + } - $this->context->smarty->assign(array( - 'order' => $order, - 'tr' => $tr - )); + $this->context->smarty->assign(array( + 'order' => $order, + 'tr' => $tr + )); - return $this->createTemplate('_print_pdf_icon.tpl')->fetch(); - } + return $this->createTemplate('_print_pdf_icon.tpl')->fetch(); + } - public function printNewCustomer($id_order, $tr) - { - return ($tr['new'] ? $this->l('Yes') : $this->l('No')); - } + public function printNewCustomer($id_order, $tr) + { + return ($tr['new'] ? $this->l('Yes') : $this->l('No')); + } - public function processBulkUpdateOrderStatus() - { - if (Tools::isSubmit('submitUpdateOrderStatus') - && ($id_order_state = (int)Tools::getValue('id_order_state'))) - { - if ($this->tabAccess['edit'] !== '1') - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - else - { - $order_state = new OrderState($id_order_state); + public function processBulkUpdateOrderStatus() + { + if (Tools::isSubmit('submitUpdateOrderStatus') + && ($id_order_state = (int)Tools::getValue('id_order_state'))) { + if ($this->tabAccess['edit'] !== '1') { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } else { + $order_state = new OrderState($id_order_state); - if (!Validate::isLoadedObject($order_state)) - $this->errors[] = sprintf(Tools::displayError('Order status #%d cannot be loaded'), $id_order_state); - else - { - foreach (Tools::getValue('orderBox') as $id_order) - { - $order = new Order((int)$id_order); - if (!Validate::isLoadedObject($order)) - $this->errors[] = sprintf(Tools::displayError('Order #%d cannot be loaded'), $id_order); - else - { - $current_order_state = $order->getCurrentOrderState(); - if ($current_order_state->id == $order_state->id) - $this->errors[] = $this->displayWarning(sprintf('Order #%d has already been assigned this status.', $id_order)); - else - { - $history = new OrderHistory(); - $history->id_order = $order->id; - $history->id_employee = (int)$this->context->employee->id; + if (!Validate::isLoadedObject($order_state)) { + $this->errors[] = sprintf(Tools::displayError('Order status #%d cannot be loaded'), $id_order_state); + } else { + foreach (Tools::getValue('orderBox') as $id_order) { + $order = new Order((int)$id_order); + if (!Validate::isLoadedObject($order)) { + $this->errors[] = sprintf(Tools::displayError('Order #%d cannot be loaded'), $id_order); + } else { + $current_order_state = $order->getCurrentOrderState(); + if ($current_order_state->id == $order_state->id) { + $this->errors[] = $this->displayWarning(sprintf('Order #%d has already been assigned this status.', $id_order)); + } else { + $history = new OrderHistory(); + $history->id_order = $order->id; + $history->id_employee = (int)$this->context->employee->id; - $use_existings_payment = !$order->hasInvoice(); - $history->changeIdOrderState((int)$order_state->id, $order, $use_existings_payment); + $use_existings_payment = !$order->hasInvoice(); + $history->changeIdOrderState((int)$order_state->id, $order, $use_existings_payment); - $carrier = new Carrier($order->id_carrier, $order->id_lang); - $templateVars = array(); - if ($history->id_order_state == Configuration::get('PS_OS_SHIPPING') && $order->shipping_number) - $templateVars = array('{followup}' => str_replace('@', $order->shipping_number, $carrier->url)); + $carrier = new Carrier($order->id_carrier, $order->id_lang); + $templateVars = array(); + if ($history->id_order_state == Configuration::get('PS_OS_SHIPPING') && $order->shipping_number) { + $templateVars = array('{followup}' => str_replace('@', $order->shipping_number, $carrier->url)); + } - if ($history->addWithemail(true, $templateVars)) - { - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - foreach ($order->getProducts() as $product) - if (StockAvailable::dependsOnStock($product['product_id'])) - StockAvailable::synchronize($product['product_id'], (int)$product['id_shop']); - } - else - $this->errors[] = sprintf(Tools::displayError('Cannot change status for order #%d.'), $id_order); - } - } - } - } - } - if (!count($this->errors)) - Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$this->token); - } - } + if ($history->addWithemail(true, $templateVars)) { + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + foreach ($order->getProducts() as $product) { + if (StockAvailable::dependsOnStock($product['product_id'])) { + StockAvailable::synchronize($product['product_id'], (int)$product['id_shop']); + } + } + } + } else { + $this->errors[] = sprintf(Tools::displayError('Cannot change status for order #%d.'), $id_order); + } + } + } + } + } + } + if (!count($this->errors)) { + Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$this->token); + } + } + } - public function renderList() - { - if (Tools::isSubmit('submitBulkupdateOrderStatus'.$this->table)) - { - if (Tools::getIsset('cancel')) - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + public function renderList() + { + if (Tools::isSubmit('submitBulkupdateOrderStatus'.$this->table)) { + if (Tools::getIsset('cancel')) { + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } - $this->tpl_list_vars['updateOrderStatus_mode'] = true; - $this->tpl_list_vars['order_statuses'] = $this->statuses_array; - $this->tpl_list_vars['REQUEST_URI'] = $_SERVER['REQUEST_URI']; - $this->tpl_list_vars['POST'] = $_POST; - } + $this->tpl_list_vars['updateOrderStatus_mode'] = true; + $this->tpl_list_vars['order_statuses'] = $this->statuses_array; + $this->tpl_list_vars['REQUEST_URI'] = $_SERVER['REQUEST_URI']; + $this->tpl_list_vars['POST'] = $_POST; + } - return parent::renderList(); - } + return parent::renderList(); + } - public function postProcess() - { - // If id_order is sent, we instanciate a new Order object - if (Tools::isSubmit('id_order') && Tools::getValue('id_order') > 0) - { - $order = new Order(Tools::getValue('id_order')); - if (!Validate::isLoadedObject($order)) - $this->errors[] = Tools::displayError('The order cannot be found within your database.'); - ShopUrl::cacheMainDomainForShop((int)$order->id_shop); - } + public function postProcess() + { + // If id_order is sent, we instanciate a new Order object + if (Tools::isSubmit('id_order') && Tools::getValue('id_order') > 0) { + $order = new Order(Tools::getValue('id_order')); + if (!Validate::isLoadedObject($order)) { + $this->errors[] = Tools::displayError('The order cannot be found within your database.'); + } + ShopUrl::cacheMainDomainForShop((int)$order->id_shop); + } - /* Update shipping number */ - if (Tools::isSubmit('submitShippingNumber') && isset($order)) - { - if ($this->tabAccess['edit'] === '1') - { - $order_carrier = new OrderCarrier(Tools::getValue('id_order_carrier')); - if (!Validate::isLoadedObject($order_carrier)) - $this->errors[] = Tools::displayError('The order carrier ID is invalid.'); - elseif (!Validate::isTrackingNumber(Tools::getValue('tracking_number'))) - $this->errors[] = Tools::displayError('The tracking number is incorrect.'); - else - { - // update shipping number - // Keep these two following lines for backward compatibility, remove on 1.6 version - $order->shipping_number = Tools::getValue('tracking_number'); - $order->update(); + /* Update shipping number */ + if (Tools::isSubmit('submitShippingNumber') && isset($order)) { + if ($this->tabAccess['edit'] === '1') { + $order_carrier = new OrderCarrier(Tools::getValue('id_order_carrier')); + if (!Validate::isLoadedObject($order_carrier)) { + $this->errors[] = Tools::displayError('The order carrier ID is invalid.'); + } elseif (!Validate::isTrackingNumber(Tools::getValue('tracking_number'))) { + $this->errors[] = Tools::displayError('The tracking number is incorrect.'); + } else { + // update shipping number + // Keep these two following lines for backward compatibility, remove on 1.6 version + $order->shipping_number = Tools::getValue('tracking_number'); + $order->update(); - // Update order_carrier - $order_carrier->tracking_number = pSQL(Tools::getValue('tracking_number')); - if ($order_carrier->update()) - { - // Send mail to customer - $customer = new Customer((int)$order->id_customer); - $carrier = new Carrier((int)$order->id_carrier, $order->id_lang); - if (!Validate::isLoadedObject($customer)) - throw new PrestaShopException('Can\'t load Customer object'); - if (!Validate::isLoadedObject($carrier)) - throw new PrestaShopException('Can\'t load Carrier object'); - $templateVars = array( - '{followup}' => str_replace('@', $order->shipping_number, $carrier->url), - '{firstname}' => $customer->firstname, - '{lastname}' => $customer->lastname, - '{id_order}' => $order->id, - '{shipping_number}' => $order->shipping_number, - '{order_name}' => $order->getUniqReference() - ); - if (@Mail::Send((int)$order->id_lang, 'in_transit', Mail::l('Package in transit', (int)$order->id_lang), $templateVars, - $customer->email, $customer->firstname.' '.$customer->lastname, null, null, null, null, - _PS_MAIL_DIR_, true, (int)$order->id_shop)) - { - Hook::exec('actionAdminOrdersTrackingNumberUpdate', array('order' => $order, 'customer' => $customer, 'carrier' => $carrier), null, false, true, false, $order->id_shop); - Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); - } - else - $this->errors[] = Tools::displayError('An error occurred while sending an email to the customer.'); - } - else - $this->errors[] = Tools::displayError('The order carrier cannot be updated.'); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } + // Update order_carrier + $order_carrier->tracking_number = pSQL(Tools::getValue('tracking_number')); + if ($order_carrier->update()) { + // Send mail to customer + $customer = new Customer((int)$order->id_customer); + $carrier = new Carrier((int)$order->id_carrier, $order->id_lang); + if (!Validate::isLoadedObject($customer)) { + throw new PrestaShopException('Can\'t load Customer object'); + } + if (!Validate::isLoadedObject($carrier)) { + throw new PrestaShopException('Can\'t load Carrier object'); + } + $templateVars = array( + '{followup}' => str_replace('@', $order->shipping_number, $carrier->url), + '{firstname}' => $customer->firstname, + '{lastname}' => $customer->lastname, + '{id_order}' => $order->id, + '{shipping_number}' => $order->shipping_number, + '{order_name}' => $order->getUniqReference() + ); + if (@Mail::Send((int)$order->id_lang, 'in_transit', Mail::l('Package in transit', (int)$order->id_lang), $templateVars, + $customer->email, $customer->firstname.' '.$customer->lastname, null, null, null, null, + _PS_MAIL_DIR_, true, (int)$order->id_shop)) { + Hook::exec('actionAdminOrdersTrackingNumberUpdate', array('order' => $order, 'customer' => $customer, 'carrier' => $carrier), null, false, true, false, $order->id_shop); + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); + } else { + $this->errors[] = Tools::displayError('An error occurred while sending an email to the customer.'); + } + } else { + $this->errors[] = Tools::displayError('The order carrier cannot be updated.'); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } - /* Change order status, add a new entry in order history and send an e-mail to the customer if needed */ - elseif (Tools::isSubmit('submitState') && isset($order)) - { - if ($this->tabAccess['edit'] === '1') - { - $order_state = new OrderState(Tools::getValue('id_order_state')); + /* Change order status, add a new entry in order history and send an e-mail to the customer if needed */ + elseif (Tools::isSubmit('submitState') && isset($order)) { + if ($this->tabAccess['edit'] === '1') { + $order_state = new OrderState(Tools::getValue('id_order_state')); - if (!Validate::isLoadedObject($order_state)) - $this->errors[] = Tools::displayError('The new order status is invalid.'); - else - { - $current_order_state = $order->getCurrentOrderState(); - if ($current_order_state->id != $order_state->id) - { - // Create new OrderHistory - $history = new OrderHistory(); - $history->id_order = $order->id; - $history->id_employee = (int)$this->context->employee->id; + if (!Validate::isLoadedObject($order_state)) { + $this->errors[] = Tools::displayError('The new order status is invalid.'); + } else { + $current_order_state = $order->getCurrentOrderState(); + if ($current_order_state->id != $order_state->id) { + // Create new OrderHistory + $history = new OrderHistory(); + $history->id_order = $order->id; + $history->id_employee = (int)$this->context->employee->id; - $use_existings_payment = false; - if (!$order->hasInvoice()) - $use_existings_payment = true; - $history->changeIdOrderState((int)$order_state->id, $order, $use_existings_payment); + $use_existings_payment = false; + if (!$order->hasInvoice()) { + $use_existings_payment = true; + } + $history->changeIdOrderState((int)$order_state->id, $order, $use_existings_payment); - $carrier = new Carrier($order->id_carrier, $order->id_lang); - $templateVars = array(); - if ($history->id_order_state == Configuration::get('PS_OS_SHIPPING') && $order->shipping_number) - $templateVars = array('{followup}' => str_replace('@', $order->shipping_number, $carrier->url)); + $carrier = new Carrier($order->id_carrier, $order->id_lang); + $templateVars = array(); + if ($history->id_order_state == Configuration::get('PS_OS_SHIPPING') && $order->shipping_number) { + $templateVars = array('{followup}' => str_replace('@', $order->shipping_number, $carrier->url)); + } - // Save all changes - if ($history->addWithemail(true, $templateVars)) - { - // synchronizes quantities if needed.. - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - foreach ($order->getProducts() as $product) - { - if (StockAvailable::dependsOnStock($product['product_id'])) - StockAvailable::synchronize($product['product_id'], (int)$product['id_shop']); - } - } + // Save all changes + if ($history->addWithemail(true, $templateVars)) { + // synchronizes quantities if needed.. + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + foreach ($order->getProducts() as $product) { + if (StockAvailable::dependsOnStock($product['product_id'])) { + StockAvailable::synchronize($product['product_id'], (int)$product['id_shop']); + } + } + } - Tools::redirectAdmin(self::$currentIndex.'&id_order='.(int)$order->id.'&vieworder&token='.$this->token); - } - $this->errors[] = Tools::displayError('An error occurred while changing order status, or we were unable to send an email to the customer.'); - } - else - $this->errors[] = Tools::displayError('The order has already been assigned this status.'); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } + Tools::redirectAdmin(self::$currentIndex.'&id_order='.(int)$order->id.'&vieworder&token='.$this->token); + } + $this->errors[] = Tools::displayError('An error occurred while changing order status, or we were unable to send an email to the customer.'); + } else { + $this->errors[] = Tools::displayError('The order has already been assigned this status.'); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } - /* Add a new message for the current order and send an e-mail to the customer if needed */ - elseif (Tools::isSubmit('submitMessage') && isset($order)) - { - if ($this->tabAccess['edit'] === '1') - { - $customer = new Customer(Tools::getValue('id_customer')); - if (!Validate::isLoadedObject($customer)) - $this->errors[] = Tools::displayError('The customer is invalid.'); - elseif (!Tools::getValue('message')) - $this->errors[] = Tools::displayError('The message cannot be blank.'); - else - { - /* Get message rules and and check fields validity */ - $rules = call_user_func(array('Message', 'getValidationRules'), 'Message'); - foreach ($rules['required'] as $field) - if (($value = Tools::getValue($field)) == false && (string)$value != '0') - if (!Tools::getValue('id_'.$this->table) || $field != 'passwd') - $this->errors[] = sprintf(Tools::displayError('field %s is required.'), $field); - foreach ($rules['size'] as $field => $maxLength) - if (Tools::getValue($field) && Tools::strlen(Tools::getValue($field)) > $maxLength) - $this->errors[] = sprintf(Tools::displayError('field %1$s is too long (%2$d chars max).'), $field, $maxLength); - foreach ($rules['validate'] as $field => $function) - if (Tools::getValue($field)) - if (!Validate::$function(htmlentities(Tools::getValue($field), ENT_COMPAT, 'UTF-8'))) - $this->errors[] = sprintf(Tools::displayError('field %s is invalid.'), $field); + /* Add a new message for the current order and send an e-mail to the customer if needed */ + elseif (Tools::isSubmit('submitMessage') && isset($order)) { + if ($this->tabAccess['edit'] === '1') { + $customer = new Customer(Tools::getValue('id_customer')); + if (!Validate::isLoadedObject($customer)) { + $this->errors[] = Tools::displayError('The customer is invalid.'); + } elseif (!Tools::getValue('message')) { + $this->errors[] = Tools::displayError('The message cannot be blank.'); + } else { + /* Get message rules and and check fields validity */ + $rules = call_user_func(array('Message', 'getValidationRules'), 'Message'); + foreach ($rules['required'] as $field) { + if (($value = Tools::getValue($field)) == false && (string)$value != '0') { + if (!Tools::getValue('id_'.$this->table) || $field != 'passwd') { + $this->errors[] = sprintf(Tools::displayError('field %s is required.'), $field); + } + } + } + foreach ($rules['size'] as $field => $maxLength) { + if (Tools::getValue($field) && Tools::strlen(Tools::getValue($field)) > $maxLength) { + $this->errors[] = sprintf(Tools::displayError('field %1$s is too long (%2$d chars max).'), $field, $maxLength); + } + } + foreach ($rules['validate'] as $field => $function) { + if (Tools::getValue($field)) { + if (!Validate::$function(htmlentities(Tools::getValue($field), ENT_COMPAT, 'UTF-8'))) { + $this->errors[] = sprintf(Tools::displayError('field %s is invalid.'), $field); + } + } + } - if (!count($this->errors)) - { - //check if a thread already exist - $id_customer_thread = CustomerThread::getIdCustomerThreadByEmailAndIdOrder($customer->email, $order->id); - if (!$id_customer_thread) - { - $customer_thread = new CustomerThread(); - $customer_thread->id_contact = 0; - $customer_thread->id_customer = (int)$order->id_customer; - $customer_thread->id_shop = (int)$this->context->shop->id; - $customer_thread->id_order = (int)$order->id; - $customer_thread->id_lang = (int)$this->context->language->id; - $customer_thread->email = $customer->email; - $customer_thread->status = 'open'; - $customer_thread->token = Tools::passwdGen(12); - $customer_thread->add(); - } - else - $customer_thread = new CustomerThread((int)$id_customer_thread); + if (!count($this->errors)) { + //check if a thread already exist + $id_customer_thread = CustomerThread::getIdCustomerThreadByEmailAndIdOrder($customer->email, $order->id); + if (!$id_customer_thread) { + $customer_thread = new CustomerThread(); + $customer_thread->id_contact = 0; + $customer_thread->id_customer = (int)$order->id_customer; + $customer_thread->id_shop = (int)$this->context->shop->id; + $customer_thread->id_order = (int)$order->id; + $customer_thread->id_lang = (int)$this->context->language->id; + $customer_thread->email = $customer->email; + $customer_thread->status = 'open'; + $customer_thread->token = Tools::passwdGen(12); + $customer_thread->add(); + } else { + $customer_thread = new CustomerThread((int)$id_customer_thread); + } - $customer_message = new CustomerMessage(); - $customer_message->id_customer_thread = $customer_thread->id; - $customer_message->id_employee = (int)$this->context->employee->id; - $customer_message->message = Tools::getValue('message'); - $customer_message->private = Tools::getValue('visibility'); + $customer_message = new CustomerMessage(); + $customer_message->id_customer_thread = $customer_thread->id; + $customer_message->id_employee = (int)$this->context->employee->id; + $customer_message->message = Tools::getValue('message'); + $customer_message->private = Tools::getValue('visibility'); - if (!$customer_message->add()) - $this->errors[] = Tools::displayError('An error occurred while saving the message.'); - elseif ($customer_message->private) - Tools::redirectAdmin(self::$currentIndex.'&id_order='.(int)$order->id.'&vieworder&conf=11&token='.$this->token); - else - { - $message = $customer_message->message; - if (Configuration::get('PS_MAIL_TYPE', null, null, $order->id_shop) != Mail::TYPE_TEXT) - $message = Tools::nl2br($customer_message->message); + if (!$customer_message->add()) { + $this->errors[] = Tools::displayError('An error occurred while saving the message.'); + } elseif ($customer_message->private) { + Tools::redirectAdmin(self::$currentIndex.'&id_order='.(int)$order->id.'&vieworder&conf=11&token='.$this->token); + } else { + $message = $customer_message->message; + if (Configuration::get('PS_MAIL_TYPE', null, null, $order->id_shop) != Mail::TYPE_TEXT) { + $message = Tools::nl2br($customer_message->message); + } - $varsTpl = array( - '{lastname}' => $customer->lastname, - '{firstname}' => $customer->firstname, - '{id_order}' => $order->id, - '{order_name}' => $order->getUniqReference(), - '{message}' => $message - ); - if (@Mail::Send((int)$order->id_lang, 'order_merchant_comment', - Mail::l('New message regarding your order', (int)$order->id_lang), $varsTpl, $customer->email, - $customer->firstname.' '.$customer->lastname, null, null, null, null, _PS_MAIL_DIR_, true, (int)$order->id_shop)) - Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=11'.'&token='.$this->token); - } - $this->errors[] = Tools::displayError('An error occurred while sending an email to the customer.'); - } - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } + $varsTpl = array( + '{lastname}' => $customer->lastname, + '{firstname}' => $customer->firstname, + '{id_order}' => $order->id, + '{order_name}' => $order->getUniqReference(), + '{message}' => $message + ); + if (@Mail::Send((int)$order->id_lang, 'order_merchant_comment', + Mail::l('New message regarding your order', (int)$order->id_lang), $varsTpl, $customer->email, + $customer->firstname.' '.$customer->lastname, null, null, null, null, _PS_MAIL_DIR_, true, (int)$order->id_shop)) { + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=11'.'&token='.$this->token); + } + } + $this->errors[] = Tools::displayError('An error occurred while sending an email to the customer.'); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } - /* Partial refund from order */ - elseif (Tools::isSubmit('partialRefund') && isset($order)) - { - if ($this->tabAccess['edit'] == '1') - { - if (Tools::isSubmit('partialRefundProduct') && ($refunds = Tools::getValue('partialRefundProduct')) && is_array($refunds)) - { - $amount = 0; - $order_detail_list = array(); - foreach ($refunds as $id_order_detail => $amount_detail) - { - $quantity = Tools::getValue('partialRefundProductQuantity'); - if (!$quantity[$id_order_detail]) - continue; + /* Partial refund from order */ + elseif (Tools::isSubmit('partialRefund') && isset($order)) { + if ($this->tabAccess['edit'] == '1') { + if (Tools::isSubmit('partialRefundProduct') && ($refunds = Tools::getValue('partialRefundProduct')) && is_array($refunds)) { + $amount = 0; + $order_detail_list = array(); + $full_quantity_list = array(); + foreach ($refunds as $id_order_detail => $amount_detail) { + $quantity = Tools::getValue('partialRefundProductQuantity'); + if (!$quantity[$id_order_detail]) { + continue; + } - $order_detail_list[$id_order_detail] = array( - 'quantity' => (int)$quantity[$id_order_detail], - 'id_order_detail' => (int)$id_order_detail - ); + $full_quantity_list[$id_order_detail] = (int)$quantity[$id_order_detail]; - $order_detail = new OrderDetail((int)$id_order_detail); - if (empty($amount_detail)) - { - $order_detail_list[$id_order_detail]['unit_price'] = (!Tools::getValue('TaxMethod') ? $order_detail->unit_price_tax_excl : $order_detail->unit_price_tax_incl); - $order_detail_list[$id_order_detail]['amount'] = $order_detail->unit_price_tax_incl * $order_detail_list[$id_order_detail]['quantity']; - } - else - { - $order_detail_list[$id_order_detail]['unit_price'] = (float)str_replace(',', '.', $amount_detail / $order_detail_list[$id_order_detail]['quantity']); - $order_detail_list[$id_order_detail]['amount'] = (float)str_replace(',', '.', $amount_detail); - } - $amount += $order_detail_list[$id_order_detail]['amount']; - if (!$order->hasBeenDelivered() || ($order->hasBeenDelivered() && Tools::isSubmit('reinjectQuantities')) && $order_detail_list[$id_order_detail]['quantity'] > 0) - $this->reinjectQuantity($order_detail, $order_detail_list[$id_order_detail]['quantity']); - } + $order_detail_list[$id_order_detail] = array( + 'quantity' => (int)$quantity[$id_order_detail], + 'id_order_detail' => (int)$id_order_detail + ); - $shipping_cost_amount = (float)str_replace(',', '.', Tools::getValue('partialRefundShippingCost')) ? (float)str_replace(',', '.', Tools::getValue('partialRefundShippingCost')) : false; + $order_detail = new OrderDetail((int)$id_order_detail); + if (empty($amount_detail)) { + $order_detail_list[$id_order_detail]['unit_price'] = (!Tools::getValue('TaxMethod') ? $order_detail->unit_price_tax_excl : $order_detail->unit_price_tax_incl); + $order_detail_list[$id_order_detail]['amount'] = $order_detail->unit_price_tax_incl * $order_detail_list[$id_order_detail]['quantity']; + } else { + $order_detail_list[$id_order_detail]['amount'] = (float)str_replace(',', '.', $amount_detail); + $order_detail_list[$id_order_detail]['unit_price'] = $order_detail_list[$id_order_detail]['amount'] / $order_detail_list[$id_order_detail]['quantity']; + } + $amount += $order_detail_list[$id_order_detail]['amount']; + if (!$order->hasBeenDelivered() || ($order->hasBeenDelivered() && Tools::isSubmit('reinjectQuantities')) && $order_detail_list[$id_order_detail]['quantity'] > 0) { + $this->reinjectQuantity($order_detail, $order_detail_list[$id_order_detail]['quantity']); + } + } - if ($amount == 0 && $shipping_cost_amount == 0) - { - if (!empty($refunds)) - $this->errors[] = Tools::displayError('Please enter a quantity to proceed with your refund.'); - else - $this->errors[] = Tools::displayError('Please enter an amount to proceed with your refund.'); + $shipping_cost_amount = (float)str_replace(',', '.', Tools::getValue('partialRefundShippingCost')) ? (float)str_replace(',', '.', Tools::getValue('partialRefundShippingCost')) : false; + + if ($amount == 0 && $shipping_cost_amount == 0) { + if (!empty($refunds)) { + $this->errors[] = Tools::displayError('Please enter a quantity to proceed with your refund.'); + } else { + $this->errors[] = Tools::displayError('Please enter an amount to proceed with your refund.'); + } return false; } $choosen = false; - $voucher = 0; - - if ((int)Tools::getValue('refund_voucher_off') == 1) - $amount -= $voucher = (float)Tools::getValue('order_discount_price'); - elseif ((int)Tools::getValue('refund_voucher_off') == 2) - { - $choosen = true; - $amount = $voucher = (float)Tools::getValue('refund_voucher_choose'); - } - - if ($shipping_cost_amount > 0) - { - if (!Tools::getValue('TaxMethod')) - { - $tax = new Tax(); - $tax->rate = $order->carrier_tax_rate; - $tax_calculator = new TaxCalculator(array($tax)); - $amount += $tax_calculator->addTaxes($shipping_cost_amount); - } - else - $amount += $shipping_cost_amount; - } - - $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); - if (Validate::isLoadedObject($order_carrier)) - { - $order_carrier->weight = (float)$order->getTotalWeight(); - if ($order_carrier->update()) - $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); - } - - if ($amount >= 0) - { - if (!OrderSlip::create($order, $order_detail_list, $shipping_cost_amount, $voucher, $choosen, - (Tools::getValue('TaxMethod') ? false : true))) - $this->errors[] = Tools::displayError('You cannot generate a partial credit slip.'); - - foreach ($order_detail_list as &$product) - { - $order_detail = new OrderDetail((int)$product['id_order_detail']); - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - StockAvailable::synchronize($order_detail->product_id); - } - - // Generate voucher - if (Tools::isSubmit('generateDiscountRefund') && !count($this->errors) && $amount > 0) - { - $cart_rule = new CartRule(); - $cart_rule->description = sprintf($this->l('Credit slip for order #%d'), $order->id); - $language_ids = Language::getIDs(false); - foreach ($language_ids as $id_lang) - // Define a temporary name - $cart_rule->name[$id_lang] = sprintf('V0C%1$dO%2$d', $order->id_customer, $order->id); - - // Define a temporary code - $cart_rule->code = sprintf('V0C%1$dO%2$d', $order->id_customer, $order->id); - $cart_rule->quantity = 1; - $cart_rule->quantity_per_user = 1; - - // Specific to the customer - $cart_rule->id_customer = $order->id_customer; - $now = time(); - $cart_rule->date_from = date('Y-m-d H:i:s', $now); - $cart_rule->date_to = date('Y-m-d H:i:s', strtotime('+1 year')); - $cart_rule->partial_use = 1; - $cart_rule->active = 1; - - $cart_rule->reduction_amount = $amount; - $cart_rule->reduction_tax = true; - $cart_rule->minimum_amount_currency = $order->id_currency; - $cart_rule->reduction_currency = $order->id_currency; - - if (!$cart_rule->add()) - $this->errors[] = Tools::displayError('You cannot generate a voucher.'); - else - { - // Update the voucher code and name - foreach ($language_ids as $id_lang) - $cart_rule->name[$id_lang] = sprintf('V%1$dC%2$dO%3$d', $cart_rule->id, $order->id_customer, $order->id); - $cart_rule->code = sprintf('V%1$dC%2$dO%3$d', $cart_rule->id, $order->id_customer, $order->id); - - if (!$cart_rule->update()) - $this->errors[] = Tools::displayError('You cannot generate a voucher.'); - else - { - $currency = $this->context->currency; - $customer = new Customer((int)($order->id_customer)); - $params['{lastname}'] = $customer->lastname; - $params['{firstname}'] = $customer->firstname; - $params['{id_order}'] = $order->id; - $params['{order_name}'] = $order->getUniqReference(); - $params['{voucher_amount}'] = Tools::displayPrice($cart_rule->reduction_amount, $currency, false); - $params['{voucher_num}'] = $cart_rule->code; - @Mail::Send((int)$order->id_lang, 'voucher', sprintf(Mail::l('New voucher for your order #%s', (int)$order->id_lang), $order->reference), - $params, $customer->email, $customer->firstname.' '.$customer->lastname, null, null, null, - null, _PS_MAIL_DIR_, true, (int)$order->id_shop); - } - } - } - } - else - { - if (!empty($refunds)) - $this->errors[] = Tools::displayError('Please enter a quantity to proceed with your refund.'); - else - $this->errors[] = Tools::displayError('Please enter an amount to proceed with your refund.'); - } - - // Redirect if no errors - if (!count($this->errors)) - Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=30&token='.$this->token); - } - else - $this->errors[] = Tools::displayError('The partial refund data is incorrect.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - - /* Cancel product from order */ - elseif (Tools::isSubmit('cancelProduct') && isset($order)) - { - if ($this->tabAccess['delete'] === '1') - { - if (!Tools::isSubmit('id_order_detail') && !Tools::isSubmit('id_customization')) - $this->errors[] = Tools::displayError('You must select a product.'); - elseif (!Tools::isSubmit('cancelQuantity') && !Tools::isSubmit('cancelCustomizationQuantity')) - $this->errors[] = Tools::displayError('You must enter a quantity.'); - else - { - $productList = Tools::getValue('id_order_detail'); - if ($productList) - $productList = array_map('intval', $productList); - - $customizationList = Tools::getValue('id_customization'); - if ($customizationList) - $customizationList = array_map('intval', $customizationList); - - $qtyList = Tools::getValue('cancelQuantity'); - if ($qtyList) - $qtyList = array_map('intval', $qtyList); - - $customizationQtyList = Tools::getValue('cancelCustomizationQuantity'); - if ($customizationQtyList) - $customizationQtyList = array_map('intval', $customizationQtyList); - - $full_product_list = $productList; - $full_quantity_list = $qtyList; - - if ($customizationList) - foreach ($customizationList as $key => $id_order_detail) - { - $full_product_list[(int)$id_order_detail] = $id_order_detail; - if (isset($customizationQtyList[$key])) - $full_quantity_list[(int)$id_order_detail] += $customizationQtyList[$key]; - } - - if ($productList || $customizationList) - { - if ($productList) - { - $id_cart = Cart::getCartIdByOrderId($order->id); - $customization_quantities = Customization::countQuantityByCart($id_cart); - - foreach ($productList as $key => $id_order_detail) - { - $qtyCancelProduct = abs($qtyList[$key]); - if (!$qtyCancelProduct) - $this->errors[] = Tools::displayError('No quantity has been selected for this product.'); - - $order_detail = new OrderDetail($id_order_detail); - $customization_quantity = 0; - if (array_key_exists($order_detail->product_id, $customization_quantities) && array_key_exists($order_detail->product_attribute_id, $customization_quantities[$order_detail->product_id])) - $customization_quantity = (int)$customization_quantities[$order_detail->product_id][$order_detail->product_attribute_id]; - - if (($order_detail->product_quantity - $customization_quantity - $order_detail->product_quantity_refunded - $order_detail->product_quantity_return) < $qtyCancelProduct) - $this->errors[] = Tools::displayError('An invalid quantity was selected for this product.'); - - } - } - if ($customizationList) - { - $customization_quantities = Customization::retrieveQuantitiesFromIds(array_keys($customizationList)); - - foreach ($customizationList as $id_customization => $id_order_detail) - { - $qtyCancelProduct = abs($customizationQtyList[$id_customization]); - $customization_quantity = $customization_quantities[$id_customization]; - - if (!$qtyCancelProduct) - $this->errors[] = Tools::displayError('No quantity has been selected for this product.'); - - if ($qtyCancelProduct > ($customization_quantity['quantity'] - ($customization_quantity['quantity_refunded'] + $customization_quantity['quantity_returned']))) - $this->errors[] = Tools::displayError('An invalid quantity was selected for this product.'); - } - } - - if (!count($this->errors) && $productList) - foreach ($productList as $key => $id_order_detail) - { - $qty_cancel_product = abs($qtyList[$key]); - $order_detail = new OrderDetail((int)($id_order_detail)); - - if (!$order->hasBeenDelivered() || ($order->hasBeenDelivered() && Tools::isSubmit('reinjectQuantities')) && $qty_cancel_product > 0) - $this->reinjectQuantity($order_detail, $qty_cancel_product); - - // Delete product - $order_detail = new OrderDetail((int)$id_order_detail); - if (!$order->deleteProduct($order, $order_detail, $qty_cancel_product)) - $this->errors[] = Tools::displayError('An error occurred while attempting to delete the product.').' <span class="bold">'.$order_detail->product_name.'</span>'; - // Update weight SUM - $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); - if (Validate::isLoadedObject($order_carrier)) - { - $order_carrier->weight = (float)$order->getTotalWeight(); - if ($order_carrier->update()) - $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); - } - - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && StockAvailable::dependsOnStock($order_detail->product_id)) - StockAvailable::synchronize($order_detail->product_id); - Hook::exec('actionProductCancel', array('order' => $order, 'id_order_detail' => (int)$id_order_detail), null, false, true, false, $order->id_shop); - } - if (!count($this->errors) && $customizationList) - foreach ($customizationList as $id_customization => $id_order_detail) - { - $order_detail = new OrderDetail((int)($id_order_detail)); - $qtyCancelProduct = abs($customizationQtyList[$id_customization]); - if (!$order->deleteCustomization($id_customization, $qtyCancelProduct, $order_detail)) - $this->errors[] = Tools::displayError('An error occurred while attempting to delete product customization.').' '.$id_customization; - } - // E-mail params - if ((Tools::isSubmit('generateCreditSlip') || Tools::isSubmit('generateDiscount')) && !count($this->errors)) - { - $customer = new Customer((int)($order->id_customer)); - $params['{lastname}'] = $customer->lastname; - $params['{firstname}'] = $customer->firstname; - $params['{id_order}'] = $order->id; - $params['{order_name}'] = $order->getUniqReference(); - } - - // Generate credit slip - if (Tools::isSubmit('generateCreditSlip') && !count($this->errors)) - { - $product_list = array(); - $amount = $order_detail->unit_price_tax_incl * $full_quantity_list[$id_order_detail]; - - $choosen = false; - if ((int)Tools::getValue('refund_total_voucher_off') == 1) - $amount -= $voucher = (float)Tools::getValue('order_discount_price'); - elseif ((int)Tools::getValue('refund_total_voucher_off') == 2) - { - $choosen = true; - $amount = $voucher = (float)Tools::getValue('refund_total_voucher_choose'); - } - foreach ($full_product_list as $id_order_detail) - { - $order_detail = new OrderDetail((int)$id_order_detail); - $product_list[$id_order_detail] = array( - 'id_order_detail' => $id_order_detail, - 'quantity' => $full_quantity_list[$id_order_detail], - 'unit_price' => $order_detail->unit_price_tax_excl, - 'amount' => isset($amount) ? $amount : $order_detail->unit_price_tax_incl * $full_quantity_list[$id_order_detail], - ); - } - - $shipping = Tools::isSubmit('shippingBack') ? null : false; - - if (!OrderSlip::create($order, $product_list, $shipping, $voucher, $choosen)) - $this->errors[] = Tools::displayError('A credit slip cannot be generated. '); - else - { - Hook::exec('actionOrderSlipAdd', array('order' => $order, 'productList' => $full_product_list, 'qtyList' => $full_quantity_list), null, false, true, false, $order->id_shop); - @Mail::Send( - (int)$order->id_lang, - 'credit_slip', - Mail::l('New credit slip regarding your order', (int)$order->id_lang), - $params, - $customer->email, - $customer->firstname.' '.$customer->lastname, - null, - null, - null, - null, - _PS_MAIL_DIR_, - true, - (int)$order->id_shop - ); - } - } - - // Generate voucher - if (Tools::isSubmit('generateDiscount') && !count($this->errors)) - { - $cartrule = new CartRule(); - $language_ids = Language::getIDs((bool)$order); - $cartrule->description = sprintf($this->l('Credit card slip for order #%d'), $order->id); - foreach ($language_ids as $id_lang) - { - // Define a temporary name - $cartrule->name[$id_lang] = 'V0C'.(int)($order->id_customer).'O'.(int)($order->id); - } - // Define a temporary code - $cartrule->code = 'V0C'.(int)($order->id_customer).'O'.(int)($order->id); - - $cartrule->quantity = 1; - $cartrule->quantity_per_user = 1; - // Specific to the customer - $cartrule->id_customer = $order->id_customer; - $now = time(); - $cartrule->date_from = date('Y-m-d H:i:s', $now); - $cartrule->date_to = date('Y-m-d H:i:s', $now + (3600 * 24 * 365.25)); /* 1 year */ - $cartrule->active = 1; - - $products = $order->getProducts(false, $full_product_list, $full_quantity_list); - - $total = 0; - foreach ($products as $product) - $total += $product['unit_price_tax_incl'] * $product['product_quantity']; - - if (Tools::isSubmit('shippingBack')) - $total += $order->total_shipping; - - if ((int)Tools::getValue('refund_total_voucher_off') == 1) - $total -= (float)Tools::getValue('order_discount_price'); - elseif ((int)Tools::getValue('refund_total_voucher_off') == 2) - $total = (float)Tools::getValue('refund_total_voucher_choose'); - - $cartrule->reduction_amount = $total; - $cartrule->reduction_tax = true; - $cartrule->minimum_amount_currency = $order->id_currency; - $cartrule->reduction_currency = $order->id_currency; - - if (!$cartrule->add()) - $this->errors[] = Tools::displayError('You cannot generate a voucher.'); - else - { - // Update the voucher code and name - foreach ($language_ids as $id_lang) - $cartrule->name[$id_lang] = 'V'.(int)($cartrule->id).'C'.(int)($order->id_customer).'O'.$order->id; - $cartrule->code = 'V'.(int)($cartrule->id).'C'.(int)($order->id_customer).'O'.$order->id; - if (!$cartrule->update()) - $this->errors[] = Tools::displayError('You cannot generate a voucher.'); - else - { - $currency = $this->context->currency; - $params['{voucher_amount}'] = Tools::displayPrice($cartrule->reduction_amount, $currency, false); - $params['{voucher_num}'] = $cartrule->code; - @Mail::Send((int)$order->id_lang, 'voucher', sprintf(Mail::l('New voucher for your order #%s', (int)$order->id_lang), $order->reference), - $params, $customer->email, $customer->firstname.' '.$customer->lastname, null, null, null, - null, _PS_MAIL_DIR_, true, (int)$order->id_shop); - } - } - } - } - else - $this->errors[] = Tools::displayError('No product or quantity has been selected.'); - - // Redirect if no errors - if (!count($this->errors)) - Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=31&token='.$this->token); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - elseif (Tools::isSubmit('messageReaded')) - Message::markAsReaded(Tools::getValue('messageReaded'), $this->context->employee->id); - elseif (Tools::isSubmit('submitAddPayment') && isset($order)) - { - if ($this->tabAccess['edit'] === '1') - { - $amount = str_replace(',', '.', Tools::getValue('payment_amount')); - $currency = new Currency(Tools::getValue('payment_currency')); - $order_has_invoice = $order->hasInvoice(); - if ($order_has_invoice) - $order_invoice = new OrderInvoice(Tools::getValue('payment_invoice')); - else - $order_invoice = null; - - if (!Validate::isLoadedObject($order)) - $this->errors[] = Tools::displayError('The order cannot be found'); - elseif (!Validate::isNegativePrice($amount) || !(float)$amount) - $this->errors[] = Tools::displayError('The amount is invalid.'); - elseif (!Validate::isGenericName(Tools::getValue('payment_method'))) - $this->errors[] = Tools::displayError('The selected payment method is invalid.'); - elseif (!Validate::isString(Tools::getValue('payment_transaction_id'))) - $this->errors[] = Tools::displayError('The transaction ID is invalid.'); - elseif (!Validate::isLoadedObject($currency)) - $this->errors[] = Tools::displayError('The selected currency is invalid.'); - elseif ($order_has_invoice && !Validate::isLoadedObject($order_invoice)) - $this->errors[] = Tools::displayError('The invoice is invalid.'); - elseif (!Validate::isDate(Tools::getValue('payment_date'))) - $this->errors[] = Tools::displayError('The date is invalid'); - else - { - if (!$order->addOrderPayment($amount, Tools::getValue('payment_method'), Tools::getValue('payment_transaction_id'), $currency, Tools::getValue('payment_date'), $order_invoice)) - $this->errors[] = Tools::displayError('An error occurred during payment.'); - else - Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('submitEditNote')) - { - $note = Tools::getValue('note'); - $order_invoice = new OrderInvoice((int)Tools::getValue('id_order_invoice')); - if (Validate::isLoadedObject($order_invoice) && Validate::isCleanHtml($note)) - { - if ($this->tabAccess['edit'] === '1') - { - $order_invoice->note = $note; - if ($order_invoice->save()) - Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order_invoice->id_order.'&vieworder&conf=4&token='.$this->token); - else - $this->errors[] = Tools::displayError('The invoice note was not saved.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - else - $this->errors[] = Tools::displayError('The invoice for edit note was unable to load. '); - } - elseif (Tools::isSubmit('submitAddOrder') && ($id_cart = Tools::getValue('id_cart')) && - ($module_name = Tools::getValue('payment_module_name')) && - ($id_order_state = Tools::getValue('id_order_state')) && Validate::isModuleName($module_name)) - { - if ($this->tabAccess['edit'] === '1') - { - if (!Configuration::get('PS_CATALOG_MODE')) - $payment_module = Module::getInstanceByName($module_name); - else - $payment_module = new BoOrder(); - - $cart = new Cart((int)$id_cart); - Context::getContext()->currency = new Currency((int)$cart->id_currency); - Context::getContext()->customer = new Customer((int)$cart->id_customer); - - $bad_delivery = false; - if (($bad_delivery = (bool)!Address::isCountryActiveById((int)$cart->id_address_delivery)) - || !Address::isCountryActiveById((int)$cart->id_address_invoice)) - { - if ($bad_delivery) - $this->errors[] = Tools::displayError('This delivery address country is not active.'); - else - $this->errors[] = Tools::displayError('This invoice address country is not active.'); - } - else - { - $employee = new Employee((int)Context::getContext()->cookie->id_employee); - $payment_module->validateOrder( - (int)$cart->id, (int)$id_order_state, - $cart->getOrderTotal(true, Cart::BOTH), $payment_module->displayName, $this->l('Manual order -- Employee:').' '. - substr($employee->firstname, 0, 1).'. '.$employee->lastname, array(), null, false, $cart->secure_key - ); - if ($payment_module->currentOrder) - Tools::redirectAdmin(self::$currentIndex.'&id_order='.$payment_module->currentOrder.'&vieworder'.'&token='.$this->token); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - elseif ((Tools::isSubmit('submitAddressShipping') || Tools::isSubmit('submitAddressInvoice')) && isset($order)) - { - if ($this->tabAccess['edit'] === '1') - { - $address = new Address(Tools::getValue('id_address')); - if (Validate::isLoadedObject($address)) - { - // Update the address on order - if (Tools::isSubmit('submitAddressShipping')) - $order->id_address_delivery = $address->id; - elseif (Tools::isSubmit('submitAddressInvoice')) - $order->id_address_invoice = $address->id; - $order->update(); - Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); - } - else - $this->errors[] = Tools::displayError('This address can\'t be loaded'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('submitChangeCurrency') && isset($order)) - { - if ($this->tabAccess['edit'] === '1') - { - if (Tools::getValue('new_currency') != $order->id_currency && !$order->valid) - { - $old_currency = new Currency($order->id_currency); - $currency = new Currency(Tools::getValue('new_currency')); - if (!Validate::isLoadedObject($currency)) - throw new PrestaShopException('Can\'t load Currency object'); - - // Update order detail amount - foreach ($order->getOrderDetailList() as $row) - { - $order_detail = new OrderDetail($row['id_order_detail']); - $fields = array( - 'ecotax', - 'product_price', - 'reduction_amount', - 'total_shipping_price_tax_excl', - 'total_shipping_price_tax_incl', - 'total_price_tax_incl', - 'total_price_tax_excl', - 'product_quantity_discount', - 'purchase_supplier_price', - 'reduction_amount', - 'reduction_amount_tax_incl', - 'reduction_amount_tax_excl', - 'unit_price_tax_incl', - 'unit_price_tax_excl', - 'original_product_price' - - ); - foreach ($fields as $field) - $order_detail->{$field} = Tools::convertPriceFull($order_detail->{$field}, $old_currency, $currency); - - $order_detail->update(); - $order_detail->updateTaxAmount($order); - } - - $id_order_carrier = (int)$order->getIdOrderCarrier(); - if ($id_order_carrier) - { - $order_carrier = $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); - $order_carrier->shipping_cost_tax_excl = (float)Tools::convertPriceFull($order_carrier->shipping_cost_tax_excl, $old_currency, $currency); - $order_carrier->shipping_cost_tax_incl = (float)Tools::convertPriceFull($order_carrier->shipping_cost_tax_incl, $old_currency, $currency); - $order_carrier->update(); - } - - // Update order && order_invoice amount - $fields = array( - 'total_discounts', - 'total_discounts_tax_incl', - 'total_discounts_tax_excl', - 'total_discount_tax_excl', - 'total_discount_tax_incl', - 'total_paid', - 'total_paid_tax_incl', - 'total_paid_tax_excl', - 'total_paid_real', - 'total_products', - 'total_products_wt', - 'total_shipping', - 'total_shipping_tax_incl', - 'total_shipping_tax_excl', - 'total_wrapping', - 'total_wrapping_tax_incl', - 'total_wrapping_tax_excl', - ); - - $invoices = $order->getInvoicesCollection(); - if ($invoices) - foreach ($invoices as $invoice) - { - foreach ($fields as $field) - if (isset($invoice->$field)) - $invoice->{$field} = Tools::convertPriceFull($invoice->{$field}, $old_currency, $currency); - $invoice->save(); - } - - foreach ($fields as $field) - if (isset($order->$field)) - $order->{$field} = Tools::convertPriceFull($order->{$field}, $old_currency, $currency); - - // Update currency in order - $order->id_currency = $currency->id; - // Update exchange rate - $order->conversion_rate = (float)$currency->conversion_rate; - $order->update(); - } - else - $this->errors[] = Tools::displayError('You cannot change the currency.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('submitGenerateInvoice') && isset($order)) - { - if (!Configuration::get('PS_INVOICE', null, null, $order->id_shop)) - $this->errors[] = Tools::displayError('Invoice management has been disabled.'); - elseif ($order->hasInvoice()) - $this->errors[] = Tools::displayError('This order already has an invoice.'); - else - { - $order->setInvoice(true); - Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); - } - } - elseif (Tools::isSubmit('submitDeleteVoucher') && isset($order)) - { - if ($this->tabAccess['edit'] === '1') - { - $order_cart_rule = new OrderCartRule(Tools::getValue('id_order_cart_rule')); - if (Validate::isLoadedObject($order_cart_rule) && $order_cart_rule->id_order == $order->id) - { - if ($order_cart_rule->id_order_invoice) - { - $order_invoice = new OrderInvoice($order_cart_rule->id_order_invoice); - if (!Validate::isLoadedObject($order_invoice)) - throw new PrestaShopException('Can\'t load Order Invoice object'); - - // Update amounts of Order Invoice - $order_invoice->total_discount_tax_excl -= $order_cart_rule->value_tax_excl; - $order_invoice->total_discount_tax_incl -= $order_cart_rule->value; - - $order_invoice->total_paid_tax_excl += $order_cart_rule->value_tax_excl; - $order_invoice->total_paid_tax_incl += $order_cart_rule->value; - - // Update Order Invoice - $order_invoice->update(); - } - - // Update amounts of order - $order->total_discounts -= $order_cart_rule->value; - $order->total_discounts_tax_incl -= $order_cart_rule->value; - $order->total_discounts_tax_excl -= $order_cart_rule->value_tax_excl; - - $order->total_paid += $order_cart_rule->value; - $order->total_paid_tax_incl += $order_cart_rule->value; - $order->total_paid_tax_excl += $order_cart_rule->value_tax_excl; - - // Delete Order Cart Rule and update Order - $order_cart_rule->delete(); - $order->update(); - Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); - } - else - $this->errors[] = Tools::displayError('You cannot edit this cart rule.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('submitNewVoucher') && isset($order)) - { - if ($this->tabAccess['edit'] === '1') - { - if (!Tools::getValue('discount_name')) - $this->errors[] = Tools::displayError('You must specify a name in order to create a new discount.'); - else - { - if ($order->hasInvoice()) - { - // If the discount is for only one invoice - if (!Tools::isSubmit('discount_all_invoices')) - { - $order_invoice = new OrderInvoice(Tools::getValue('discount_invoice')); - if (!Validate::isLoadedObject($order_invoice)) - throw new PrestaShopException('Can\'t load Order Invoice object'); - } - } - - $cart_rules = array(); - $discount_value = (float)str_replace(',', '.', Tools::getValue('discount_value')); - switch (Tools::getValue('discount_type')) - { - // Percent type - case 1: - if ($discount_value < 100) - { - if (isset($order_invoice)) - { - $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($order_invoice->total_paid_tax_incl * $discount_value / 100, 2); - $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($order_invoice->total_paid_tax_excl * $discount_value / 100, 2); - - // Update OrderInvoice - $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); - } - elseif ($order->hasInvoice()) - { - $order_invoices_collection = $order->getInvoicesCollection(); - foreach ($order_invoices_collection as $order_invoice) - { - /** @var OrderInvoice $order_invoice */ - $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($order_invoice->total_paid_tax_incl * $discount_value / 100, 2); - $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($order_invoice->total_paid_tax_excl * $discount_value / 100, 2); - - // Update OrderInvoice - $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); - } - } - else - { - $cart_rules[0]['value_tax_incl'] = Tools::ps_round($order->total_paid_tax_incl * $discount_value / 100, 2); - $cart_rules[0]['value_tax_excl'] = Tools::ps_round($order->total_paid_tax_excl * $discount_value / 100, 2); - } - } - else - $this->errors[] = Tools::displayError('The discount value is invalid.'); - break; - // Amount type - case 2: - if (isset($order_invoice)) - { - if ($discount_value > $order_invoice->total_paid_tax_incl) - $this->errors[] = Tools::displayError('The discount value is greater than the order invoice total.'); - else - { - $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($discount_value, 2); - $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($discount_value / (1 + ($order->getTaxesAverageUsed() / 100)), 2); - - // Update OrderInvoice - $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); - } - } - elseif ($order->hasInvoice()) - { - $order_invoices_collection = $order->getInvoicesCollection(); - foreach ($order_invoices_collection as $order_invoice) - { - /** @var OrderInvoice $order_invoice */ - if ($discount_value > $order_invoice->total_paid_tax_incl) - $this->errors[] = Tools::displayError('The discount value is greater than the order invoice total.').$order_invoice->getInvoiceNumberFormatted(Context::getContext()->language->id, (int)$order->id_shop).')'; - else - { - $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($discount_value, 2); - $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($discount_value / (1 + ($order->getTaxesAverageUsed() / 100)), 2); - - // Update OrderInvoice - $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); - } - } - } - else - { - if ($discount_value > $order->total_paid_tax_incl) - $this->errors[] = Tools::displayError('The discount value is greater than the order total.'); - else - { - $cart_rules[0]['value_tax_incl'] = Tools::ps_round($discount_value, 2); - $cart_rules[0]['value_tax_excl'] = Tools::ps_round($discount_value / (1 + ($order->getTaxesAverageUsed() / 100)), 2); - } - } - break; - // Free shipping type - case 3: - if (isset($order_invoice)) - { - if ($order_invoice->total_shipping_tax_incl > 0) - { - $cart_rules[$order_invoice->id]['value_tax_incl'] = $order_invoice->total_shipping_tax_incl; - $cart_rules[$order_invoice->id]['value_tax_excl'] = $order_invoice->total_shipping_tax_excl; - - // Update OrderInvoice - $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); - } - } - elseif ($order->hasInvoice()) - { - $order_invoices_collection = $order->getInvoicesCollection(); - foreach ($order_invoices_collection as $order_invoice) - { - /** @var OrderInvoice $order_invoice */ - if ($order_invoice->total_shipping_tax_incl <= 0) - continue; - $cart_rules[$order_invoice->id]['value_tax_incl'] = $order_invoice->total_shipping_tax_incl; - $cart_rules[$order_invoice->id]['value_tax_excl'] = $order_invoice->total_shipping_tax_excl; - - // Update OrderInvoice - $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); - } - } - else - { - $cart_rules[0]['value_tax_incl'] = $order->total_shipping_tax_incl; - $cart_rules[0]['value_tax_excl'] = $order->total_shipping_tax_excl; - } - break; - default: - $this->errors[] = Tools::displayError('The discount type is invalid.'); - } - - $res = true; - foreach ($cart_rules as &$cart_rule) - { - $cartRuleObj = new CartRule(); - $cartRuleObj->date_from = date('Y-m-d H:i:s', strtotime('-1 hour', strtotime($order->date_add))); - $cartRuleObj->date_to = date('Y-m-d H:i:s', strtotime('+1 hour')); - $cartRuleObj->name[Configuration::get('PS_LANG_DEFAULT')] = Tools::getValue('discount_name'); - $cartRuleObj->quantity = 0; - $cartRuleObj->quantity_per_user = 1; - if (Tools::getValue('discount_type') == 1) - $cartRuleObj->reduction_percent = $discount_value; - elseif (Tools::getValue('discount_type') == 2) - $cartRuleObj->reduction_amount = $cart_rule['value_tax_excl']; - elseif (Tools::getValue('discount_type') == 3) - $cartRuleObj->free_shipping = 1; - $cartRuleObj->active = 0; - if ($res = $cartRuleObj->add()) - $cart_rule['id'] = $cartRuleObj->id; - else - break; - } - - if ($res) - { - foreach ($cart_rules as $id_order_invoice => $cart_rule) - { - // Create OrderCartRule - $order_cart_rule = new OrderCartRule(); - $order_cart_rule->id_order = $order->id; - $order_cart_rule->id_cart_rule = $cart_rule['id']; - $order_cart_rule->id_order_invoice = $id_order_invoice; - $order_cart_rule->name = Tools::getValue('discount_name'); - $order_cart_rule->value = $cart_rule['value_tax_incl']; - $order_cart_rule->value_tax_excl = $cart_rule['value_tax_excl']; - $res &= $order_cart_rule->add(); - - $order->total_discounts += $order_cart_rule->value; - $order->total_discounts_tax_incl += $order_cart_rule->value; - $order->total_discounts_tax_excl += $order_cart_rule->value_tax_excl; - $order->total_paid -= $order_cart_rule->value; - $order->total_paid_tax_incl -= $order_cart_rule->value; - $order->total_paid_tax_excl -= $order_cart_rule->value_tax_excl; - } - - // Update Order - $res &= $order->update(); - } - - if ($res) - Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); - else - $this->errors[] = Tools::displayError('An error occurred during the OrderCartRule creation'); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('sendStateEmail') && Tools::getValue('sendStateEmail') > 0 && Tools::getValue('id_order') > 0) - { - if ($this->tabAccess['edit'] === '1') - { - $order_state = new OrderState((int)Tools::getValue('sendStateEmail')); - - if (!Validate::isLoadedObject($order_state)) - $this->errors[] = Tools::displayError('An error occurred while loading order status.'); - else - { - $history = new OrderHistory((int)Tools::getValue('id_order_history')); - - $carrier = new Carrier($order->id_carrier, $order->id_lang); - $templateVars = array(); - if ($order_state->id == Configuration::get('PS_OS_SHIPPING') && $order->shipping_number) - $templateVars = array('{followup}' => str_replace('@', $order->shipping_number, $carrier->url)); - - if ($history->sendEmail($order, $templateVars)) - Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=10&token='.$this->token); - else - $this->errors[] = Tools::displayError('An error occurred while sending the e-mail to the customer.'); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - - parent::postProcess(); - } - - public function renderKpis() - { - $time = time(); - $kpis = array(); - - /* The data generation is located in AdminStatsControllerCore */ - - $helper = new HelperKpi(); - $helper->id = 'box-conversion-rate'; - $helper->icon = 'icon-sort-by-attributes-alt'; - //$helper->chart = true; - $helper->color = 'color1'; - $helper->title = $this->l('Conversion Rate', null, null, false); - $helper->subtitle = $this->l('30 days', null, null, false); - if (ConfigurationKPI::get('CONVERSION_RATE') !== false) - $helper->value = ConfigurationKPI::get('CONVERSION_RATE'); - if (ConfigurationKPI::get('CONVERSION_RATE_CHART') !== false) - $helper->data = ConfigurationKPI::get('CONVERSION_RATE_CHART'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=conversion_rate'; - $helper->refresh = (bool)(ConfigurationKPI::get('CONVERSION_RATE_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-carts'; - $helper->icon = 'icon-shopping-cart'; - $helper->color = 'color2'; - $helper->title = $this->l('Abandoned Carts', null, null, false); - $helper->subtitle = $this->l('Today', null, null, false); - $helper->href = $this->context->link->getAdminLink('AdminCarts').'&action=filterOnlyAbandonedCarts'; - if (ConfigurationKPI::get('ABANDONED_CARTS') !== false) - $helper->value = ConfigurationKPI::get('ABANDONED_CARTS'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=abandoned_cart'; - $helper->refresh = (bool)(ConfigurationKPI::get('ABANDONED_CARTS_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-average-order'; - $helper->icon = 'icon-money'; - $helper->color = 'color3'; - $helper->title = $this->l('Average Order Value', null, null, false); - $helper->subtitle = $this->l('30 days', null, null, false); - if (ConfigurationKPI::get('AVG_ORDER_VALUE') !== false) - $helper->value = ConfigurationKPI::get('AVG_ORDER_VALUE'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=average_order_value'; - $helper->refresh = (bool)(ConfigurationKPI::get('AVG_ORDER_VALUE_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-net-profit-visit'; - $helper->icon = 'icon-user'; - $helper->color = 'color4'; - $helper->title = $this->l('Net Profit per Visit', null, null, false); - $helper->subtitle = $this->l('30 days', null, null, false); - if (ConfigurationKPI::get('NETPROFIT_VISIT') !== false) - $helper->value = ConfigurationKPI::get('NETPROFIT_VISIT'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=netprofit_visit'; - $helper->refresh = (bool)(ConfigurationKPI::get('NETPROFIT_VISIT_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpiRow(); - $helper->kpis = $kpis; - return $helper->generate(); - } - - public function renderView() - { - $order = new Order(Tools::getValue('id_order')); - if (!Validate::isLoadedObject($order)) - $this->errors[] = Tools::displayError('The order cannot be found within your database.'); - - $customer = new Customer($order->id_customer); - $carrier = new Carrier($order->id_carrier); - $products = $this->getProducts($order); - $currency = new Currency((int)$order->id_currency); - // Carrier module call - $carrier_module_call = null; - if ($carrier->is_module) - { - $module = Module::getInstanceByName($carrier->external_module_name); - if (method_exists($module, 'displayInfoByCart')) - $carrier_module_call = call_user_func(array($module, 'displayInfoByCart'), $order->id_cart); - } - - // Retrieve addresses information - $addressInvoice = new Address($order->id_address_invoice, $this->context->language->id); - if (Validate::isLoadedObject($addressInvoice) && $addressInvoice->id_state) - $invoiceState = new State((int)$addressInvoice->id_state); - - if ($order->id_address_invoice == $order->id_address_delivery) - { - $addressDelivery = $addressInvoice; - if (isset($invoiceState)) - $deliveryState = $invoiceState; - } - else - { - $addressDelivery = new Address($order->id_address_delivery, $this->context->language->id); - if (Validate::isLoadedObject($addressDelivery) && $addressDelivery->id_state) - $deliveryState = new State((int)($addressDelivery->id_state)); - } - - $this->toolbar_title = sprintf($this->l('Order #%1$d (%2$s) - %3$s %4$s'), $order->id, $order->reference, $customer->firstname, $customer->lastname); - if (Shop::isFeatureActive()) - { - $shop = new Shop((int)$order->id_shop); - $this->toolbar_title .= ' - '.sprintf($this->l('Shop: %s'), $shop->name); - } - - // gets warehouses to ship products, if and only if advanced stock management is activated - $warehouse_list = null; - - $order_details = $order->getOrderDetailList(); - foreach ($order_details as $order_detail) - { - $product = new Product($order_detail['product_id']); - - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') - && $product->advanced_stock_management) - { - $warehouses = Warehouse::getWarehousesByProductId($order_detail['product_id'], $order_detail['product_attribute_id']); - foreach ($warehouses as $warehouse) - { - if (!isset($warehouse_list[$warehouse['id_warehouse']])) - $warehouse_list[$warehouse['id_warehouse']] = $warehouse; - } - } - } - - $payment_methods = array(); - foreach (PaymentModule::getInstalledPaymentModules() as $payment) - { - $module = Module::getInstanceByName($payment['name']); - if (Validate::isLoadedObject($module) && $module->active) - $payment_methods[] = $module->displayName; - } - - // display warning if there are products out of stock - $display_out_of_stock_warning = false; - $current_order_state = $order->getCurrentOrderState(); - if (Configuration::get('PS_STOCK_MANAGEMENT') && (!Validate::isLoadedObject($current_order_state) || ($current_order_state->delivery != 1 && $current_order_state->shipped != 1))) - $display_out_of_stock_warning = true; - - // products current stock (from stock_available) - foreach ($products as &$product) - { - // Get total customized quantity for current product - $customized_product_quantity = 0; - - if (is_array($product['customizedDatas'])) - foreach ($product['customizedDatas'] as $customizationPerAddress) - foreach ($customizationPerAddress as $customizationId => $customization) - $customized_product_quantity += (int)$customization['quantity']; - - $product['customized_product_quantity'] = $customized_product_quantity; - $product['current_stock'] = StockAvailable::getQuantityAvailableByProduct($product['product_id'], $product['product_attribute_id'], $product['id_shop']); - $resume = OrderSlip::getProductSlipResume($product['id_order_detail']); - $product['quantity_refundable'] = $product['product_quantity'] - $resume['product_quantity']; - $product['amount_refundable'] = $product['total_price_tax_excl'] - $resume['amount_tax_excl']; - $product['amount_refundable_tax_incl'] = $product['total_price_tax_incl'] - $resume['amount_tax_incl']; - $product['amount_refund'] = Tools::displayPrice($resume['amount_tax_incl'], $currency); - $product['refund_history'] = OrderSlip::getProductSlipDetail($product['id_order_detail']); - $product['return_history'] = OrderReturn::getProductReturnDetail($product['id_order_detail']); - - // if the current stock requires a warning - if ($product['current_stock'] == 0 && $display_out_of_stock_warning) - $this->displayWarning($this->l('This product is out of stock: ').' '.$product['product_name']); - if ($product['id_warehouse'] != 0) - { - $warehouse = new Warehouse((int)$product['id_warehouse']); - $product['warehouse_name'] = $warehouse->name; - $warehouse_location = WarehouseProductLocation::getProductLocation($product['product_id'], $product['product_attribute_id'], $product['id_warehouse']); - if (!empty($warehouse_location)) - $product['warehouse_location'] = $warehouse_location; - else - $product['warehouse_location'] = false; - } - else - { - $product['warehouse_name'] = '--'; - $product['warehouse_location'] = false; - } - } - - $gender = new Gender((int)$customer->id_gender, $this->context->language->id); - - $history = $order->getHistory($this->context->language->id); - - foreach ($history as &$order_state) - $order_state['text-color'] = Tools::getBrightness($order_state['color']) < 128 ? 'white' : 'black'; - - // Smarty assign - $this->tpl_view_vars = array( - 'order' => $order, - 'cart' => new Cart($order->id_cart), - 'customer' => $customer, - 'gender' => $gender, - 'customer_addresses' => $customer->getAddresses($this->context->language->id), - 'addresses' => array( - 'delivery' => $addressDelivery, - 'deliveryState' => isset($deliveryState) ? $deliveryState : null, - 'invoice' => $addressInvoice, - 'invoiceState' => isset($invoiceState) ? $invoiceState : null - ), - 'customerStats' => $customer->getStats(), - 'products' => $products, - 'discounts' => $order->getCartRules(), - 'orders_total_paid_tax_incl' => $order->getOrdersTotalPaid(), // Get the sum of total_paid_tax_incl of the order with similar reference - 'total_paid' => $order->getTotalPaid(), - 'returns' => OrderReturn::getOrdersReturn($order->id_customer, $order->id), - 'customer_thread_message' => CustomerThread::getCustomerMessages($order->id_customer, null, $order->id), - 'orderMessages' => OrderMessage::getOrderMessages($order->id_lang), - 'messages' => Message::getMessagesByOrderId($order->id, true), - 'carrier' => new Carrier($order->id_carrier), - 'history' => $history, - 'states' => OrderState::getOrderStates($this->context->language->id), - 'warehouse_list' => $warehouse_list, - 'sources' => ConnectionsSource::getOrderSources($order->id), - 'currentState' => $order->getCurrentOrderState(), - 'currency' => new Currency($order->id_currency), - 'currencies' => Currency::getCurrenciesByIdShop($order->id_shop), - 'previousOrder' => $order->getPreviousOrderId(), - 'nextOrder' => $order->getNextOrderId(), - 'current_index' => self::$currentIndex, - 'carrierModuleCall' => $carrier_module_call, - 'iso_code_lang' => $this->context->language->iso_code, - 'id_lang' => $this->context->language->id, - 'can_edit' => ($this->tabAccess['edit'] == 1), - 'current_id_lang' => $this->context->language->id, - 'invoices_collection' => $order->getInvoicesCollection(), - 'not_paid_invoices_collection' => $order->getNotPaidInvoicesCollection(), - 'payment_methods' => $payment_methods, - 'invoice_management_active' => Configuration::get('PS_INVOICE', null, null, $order->id_shop), - 'display_warehouse' => (int)Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'), - 'HOOK_CONTENT_ORDER' => Hook::exec('displayAdminOrderContentOrder', array( - 'order' => $order, - 'products' => $products, - 'customer' => $customer) - ), - 'HOOK_CONTENT_SHIP' => Hook::exec('displayAdminOrderContentShip', array( - 'order' => $order, - 'products' => $products, - 'customer' => $customer) - ), - 'HOOK_TAB_ORDER' => Hook::exec('displayAdminOrderTabOrder', array( - 'order' => $order, - 'products' => $products, - 'customer' => $customer) - ), - 'HOOK_TAB_SHIP' => Hook::exec('displayAdminOrderTabShip', array( - 'order' => $order, - 'products' => $products, - 'customer' => $customer) - ), - ); - - return parent::renderView(); - } - - public function ajaxProcessSearchProducts() - { - Context::getContext()->customer = new Customer((int)Tools::getValue('id_customer')); - $currency = new Currency((int)Tools::getValue('id_currency')); - if ($products = Product::searchByName((int)$this->context->language->id, pSQL(Tools::getValue('product_search')))) - { - foreach ($products as &$product) - { - // Formatted price - $product['formatted_price'] = Tools::displayPrice(Tools::convertPrice($product['price_tax_incl'], $currency), $currency); - // Concret price - $product['price_tax_incl'] = Tools::ps_round(Tools::convertPrice($product['price_tax_incl'], $currency), 2); - $product['price_tax_excl'] = Tools::ps_round(Tools::convertPrice($product['price_tax_excl'], $currency), 2); - $productObj = new Product((int)$product['id_product'], false, (int)$this->context->language->id); - $combinations = array(); - $attributes = $productObj->getAttributesGroups((int)$this->context->language->id); - - // Tax rate for this customer - if (Tools::isSubmit('id_address')) - $product['tax_rate'] = $productObj->getTaxesRate(new Address(Tools::getValue('id_address'))); - - $product['warehouse_list'] = array(); - - foreach ($attributes as $attribute) - { - if (!isset($combinations[$attribute['id_product_attribute']]['attributes'])) - $combinations[$attribute['id_product_attribute']]['attributes'] = ''; - $combinations[$attribute['id_product_attribute']]['attributes'] .= $attribute['attribute_name'].' - '; - $combinations[$attribute['id_product_attribute']]['id_product_attribute'] = $attribute['id_product_attribute']; - $combinations[$attribute['id_product_attribute']]['default_on'] = $attribute['default_on']; - if (!isset($combinations[$attribute['id_product_attribute']]['price'])) - { - $price_tax_incl = Product::getPriceStatic((int)$product['id_product'], true, $attribute['id_product_attribute']); - $price_tax_excl = Product::getPriceStatic((int)$product['id_product'], false, $attribute['id_product_attribute']); - $combinations[$attribute['id_product_attribute']]['price_tax_incl'] = Tools::ps_round(Tools::convertPrice($price_tax_incl, $currency), 2); - $combinations[$attribute['id_product_attribute']]['price_tax_excl'] = Tools::ps_round(Tools::convertPrice($price_tax_excl, $currency), 2); - $combinations[$attribute['id_product_attribute']]['formatted_price'] = Tools::displayPrice(Tools::convertPrice($price_tax_excl, $currency), $currency); - } - if (!isset($combinations[$attribute['id_product_attribute']]['qty_in_stock'])) - $combinations[$attribute['id_product_attribute']]['qty_in_stock'] = StockAvailable::getQuantityAvailableByProduct((int)$product['id_product'], $attribute['id_product_attribute'], (int)$this->context->shop->id); - - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && (int)$product['advanced_stock_management'] == 1) - $product['warehouse_list'][$attribute['id_product_attribute']] = Warehouse::getProductWarehouseList($product['id_product'], $attribute['id_product_attribute']); - else - $product['warehouse_list'][$attribute['id_product_attribute']] = array(); - - $product['stock'][$attribute['id_product_attribute']] = Product::getRealQuantity($product['id_product'], $attribute['id_product_attribute']); - - } - - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && (int)$product['advanced_stock_management'] == 1) - $product['warehouse_list'][0] = Warehouse::getProductWarehouseList($product['id_product']); - else - $product['warehouse_list'][0] = array(); - - $product['stock'][0] = StockAvailable::getQuantityAvailableByProduct((int)$product['id_product'], 0, (int)$this->context->shop->id); - - foreach ($combinations as &$combination) - $combination['attributes'] = rtrim($combination['attributes'], ' - '); - $product['combinations'] = $combinations; - - if ($product['customizable']) - { - $product_instance = new Product((int)$product['id_product']); - $product['customization_fields'] = $product_instance->getCustomizationFields($this->context->language->id); - } - } - - $to_return = array( - 'products' => $products, - 'found' => true - ); - } - else - $to_return = array('found' => false); - - $this->content = Tools::jsonEncode($to_return); - } - - public function ajaxProcessSendMailValidateOrder() - { - if ($this->tabAccess['edit'] === '1') - { - $cart = new Cart((int)Tools::getValue('id_cart')); - if (Validate::isLoadedObject($cart)) - { - $customer = new Customer((int)$cart->id_customer); - if (Validate::isLoadedObject($customer)) - { - $mailVars = array( - '{order_link}' => Context::getContext()->link->getPageLink('order', false, (int)$cart->id_lang, 'step=3&recover_cart='.(int)$cart->id.'&token_cart='.md5(_COOKIE_KEY_.'recover_cart_'.(int)$cart->id)), - '{firstname}' => $customer->firstname, - '{lastname}' => $customer->lastname - ); - if (Mail::Send((int)$cart->id_lang, 'backoffice_order', Mail::l('Process the payment of your order', (int)$cart->id_lang), $mailVars, $customer->email, - $customer->firstname.' '.$customer->lastname, null, null, null, null, _PS_MAIL_DIR_, true, $cart->id_shop)) - die(Tools::jsonEncode(array('errors' => false, 'result' => $this->l('The email was sent to your customer.')))); - } - } - $this->content = Tools::jsonEncode(array('errors' => true, 'result' => $this->l('Error in sending the email to your customer.'))); - } - } - - public function ajaxProcessAddProductOnOrder() - { - // Load object - $order = new Order((int)Tools::getValue('id_order')); - if (!Validate::isLoadedObject($order)) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('The order object cannot be loaded.') - ))); - - $old_cart_rules = Context::getContext()->cart->getCartRules(); - - if ($order->hasBeenShipped()) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('You cannot add products to delivered orders. ') - ))); - - $product_informations = $_POST['add_product']; - if (isset($_POST['add_invoice'])) - $invoice_informations = $_POST['add_invoice']; - else - $invoice_informations = array(); - $product = new Product($product_informations['product_id'], false, $order->id_lang); - if (!Validate::isLoadedObject($product)) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('The product object cannot be loaded.') - ))); - - if (isset($product_informations['product_attribute_id']) && $product_informations['product_attribute_id']) - { - $combination = new Combination($product_informations['product_attribute_id']); - if (!Validate::isLoadedObject($combination)) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('The combination object cannot be loaded.') - ))); - } - - // Total method - $total_method = Cart::BOTH_WITHOUT_SHIPPING; - - // Create new cart - $cart = new Cart(); - $cart->id_shop_group = $order->id_shop_group; - $cart->id_shop = $order->id_shop; - $cart->id_customer = $order->id_customer; - $cart->id_carrier = $order->id_carrier; - $cart->id_address_delivery = $order->id_address_delivery; - $cart->id_address_invoice = $order->id_address_invoice; - $cart->id_currency = $order->id_currency; - $cart->id_lang = $order->id_lang; - $cart->secure_key = $order->secure_key; - - // Save new cart - $cart->add(); - - // Save context (in order to apply cart rule) - $this->context->cart = $cart; - $this->context->customer = new Customer($order->id_customer); - - // always add taxes even if there are not displayed to the customer - $use_taxes = true; - - $initial_product_price_tax_incl = Product::getPriceStatic($product->id, $use_taxes, isset($combination) ? $combination->id : null, 2, null, false, true, 1, - false, $order->id_customer, $cart->id, $order->{Configuration::get('PS_TAX_ADDRESS_TYPE', null, null, $order->id_shop)}); - - // Creating specific price if needed - if ($product_informations['product_price_tax_incl'] != $initial_product_price_tax_incl) - { - $specific_price = new SpecificPrice(); - $specific_price->id_shop = 0; - $specific_price->id_shop_group = 0; - $specific_price->id_currency = 0; - $specific_price->id_country = 0; - $specific_price->id_group = 0; - $specific_price->id_customer = $order->id_customer; - $specific_price->id_product = $product->id; - if (isset($combination)) - $specific_price->id_product_attribute = $combination->id; - else - $specific_price->id_product_attribute = 0; - $specific_price->price = $product_informations['product_price_tax_excl']; - $specific_price->from_quantity = 1; - $specific_price->reduction = 0; - $specific_price->reduction_type = 'amount'; - $specific_price->reduction_tax = 0; - $specific_price->from = '0000-00-00 00:00:00'; - $specific_price->to = '0000-00-00 00:00:00'; - $specific_price->add(); - } - - // Add product to cart - $update_quantity = $cart->updateQty($product_informations['product_quantity'], $product->id, isset($product_informations['product_attribute_id']) ? $product_informations['product_attribute_id'] : null, - isset($combination) ? $combination->id : null, 'up', 0, new Shop($cart->id_shop)); - - if ($update_quantity < 0) - { - // If product has attribute, minimal quantity is set with minimal quantity of attribute - $minimal_quantity = ($product_informations['product_attribute_id']) ? Attribute::getAttributeMinimalQty($product_informations['product_attribute_id']) : $product->minimal_quantity; - die(Tools::jsonEncode(array('error' => sprintf(Tools::displayError('You must add %d minimum quantity', false), $minimal_quantity)))); - } - elseif (!$update_quantity) - die(Tools::jsonEncode(array('error' => Tools::displayError('You already have the maximum quantity available for this product.', false)))); - - // If order is valid, we can create a new invoice or edit an existing invoice - if ($order->hasInvoice()) - { - $order_invoice = new OrderInvoice($product_informations['invoice']); - // Create new invoice - if ($order_invoice->id == 0) - { - // If we create a new invoice, we calculate shipping cost - $total_method = Cart::BOTH; - // Create Cart rule in order to make free shipping - if (isset($invoice_informations['free_shipping']) && $invoice_informations['free_shipping']) - { - $cart_rule = new CartRule(); - $cart_rule->id_customer = $order->id_customer; - $cart_rule->name = array( - Configuration::get('PS_LANG_DEFAULT') => $this->l('[Generated] CartRule for Free Shipping') - ); - $cart_rule->date_from = date('Y-m-d H:i:s', time()); - $cart_rule->date_to = date('Y-m-d H:i:s', time() + 24 * 3600); - $cart_rule->quantity = 1; - $cart_rule->quantity_per_user = 1; - $cart_rule->minimum_amount_currency = $order->id_currency; - $cart_rule->reduction_currency = $order->id_currency; - $cart_rule->free_shipping = true; - $cart_rule->active = 1; - $cart_rule->add(); - - // Add cart rule to cart and in order - $cart->addCartRule($cart_rule->id); - $values = array( - 'tax_incl' => $cart_rule->getContextualValue(true), - 'tax_excl' => $cart_rule->getContextualValue(false) - ); - $order->addCartRule($cart_rule->id, $cart_rule->name[Configuration::get('PS_LANG_DEFAULT')], $values); - } - - $order_invoice->id_order = $order->id; - if ($order_invoice->number) - Configuration::updateValue('PS_INVOICE_START_NUMBER', false, false, null, $order->id_shop); - else - $order_invoice->number = Order::getLastInvoiceNumber() + 1; - - $invoice_address = new Address((int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE', null, null, $order->id_shop)}); - $carrier = new Carrier((int)$order->id_carrier); - $tax_calculator = $carrier->getTaxCalculator($invoice_address); - - $order_invoice->total_paid_tax_excl = Tools::ps_round((float)$cart->getOrderTotal(false, $total_method), 2); - $order_invoice->total_paid_tax_incl = Tools::ps_round((float)$cart->getOrderTotal($use_taxes, $total_method), 2); - $order_invoice->total_products = (float)$cart->getOrderTotal(false, Cart::ONLY_PRODUCTS); - $order_invoice->total_products_wt = (float)$cart->getOrderTotal($use_taxes, Cart::ONLY_PRODUCTS); - $order_invoice->total_shipping_tax_excl = (float)$cart->getTotalShippingCost(null, false); - $order_invoice->total_shipping_tax_incl = (float)$cart->getTotalShippingCost(); - - $order_invoice->total_wrapping_tax_excl = abs($cart->getOrderTotal(false, Cart::ONLY_WRAPPING)); - $order_invoice->total_wrapping_tax_incl = abs($cart->getOrderTotal($use_taxes, Cart::ONLY_WRAPPING)); - $order_invoice->shipping_tax_computation_method = (int)$tax_calculator->computation_method; - - // Update current order field, only shipping because other field is updated later - $order->total_shipping += $order_invoice->total_shipping_tax_incl; - $order->total_shipping_tax_excl += $order_invoice->total_shipping_tax_excl; - $order->total_shipping_tax_incl += ($use_taxes) ? $order_invoice->total_shipping_tax_incl : $order_invoice->total_shipping_tax_excl; - - $order->total_wrapping += abs($cart->getOrderTotal($use_taxes, Cart::ONLY_WRAPPING)); - $order->total_wrapping_tax_excl += abs($cart->getOrderTotal(false, Cart::ONLY_WRAPPING)); - $order->total_wrapping_tax_incl += abs($cart->getOrderTotal($use_taxes, Cart::ONLY_WRAPPING)); - $order_invoice->add(); - - $order_invoice->saveCarrierTaxCalculator($tax_calculator->getTaxesAmount($order_invoice->total_shipping_tax_excl)); - - $order_carrier = new OrderCarrier(); - $order_carrier->id_order = (int)$order->id; - $order_carrier->id_carrier = (int)$order->id_carrier; - $order_carrier->id_order_invoice = (int)$order_invoice->id; - $order_carrier->weight = (float)$cart->getTotalWeight(); - $order_carrier->shipping_cost_tax_excl = (float)$order_invoice->total_shipping_tax_excl; - $order_carrier->shipping_cost_tax_incl = ($use_taxes) ? (float)$order_invoice->total_shipping_tax_incl : (float)$order_invoice->total_shipping_tax_excl; - $order_carrier->add(); - } - // Update current invoice - else - { - $order_invoice->total_paid_tax_excl += Tools::ps_round((float)($cart->getOrderTotal(false, $total_method)), 2); - $order_invoice->total_paid_tax_incl += Tools::ps_round((float)($cart->getOrderTotal($use_taxes, $total_method)), 2); - $order_invoice->total_products += (float)$cart->getOrderTotal(false, Cart::ONLY_PRODUCTS); - $order_invoice->total_products_wt += (float)$cart->getOrderTotal($use_taxes, Cart::ONLY_PRODUCTS); - $order_invoice->update(); - } - } - - // Create Order detail information - $order_detail = new OrderDetail(); - $order_detail->createList($order, $cart, $order->getCurrentOrderState(), $cart->getProducts(), (isset($order_invoice) ? $order_invoice->id : 0), $use_taxes, (int)Tools::getValue('add_product_warehouse')); - - // update totals amount of order - $order->total_products += (float)$cart->getOrderTotal(false, Cart::ONLY_PRODUCTS); - $order->total_products_wt += (float)$cart->getOrderTotal($use_taxes, Cart::ONLY_PRODUCTS); - - $order->total_paid += Tools::ps_round((float)($cart->getOrderTotal(true, $total_method)), 2); - $order->total_paid_tax_excl += Tools::ps_round((float)($cart->getOrderTotal(false, $total_method)), 2); - $order->total_paid_tax_incl += Tools::ps_round((float)($cart->getOrderTotal($use_taxes, $total_method)), 2); - - if (isset($order_invoice) && Validate::isLoadedObject($order_invoice)) - { - $order->total_shipping = $order_invoice->total_shipping_tax_incl; - $order->total_shipping_tax_incl = $order_invoice->total_shipping_tax_incl; - $order->total_shipping_tax_excl = $order_invoice->total_shipping_tax_excl; - } - // discount - $order->total_discounts += (float)abs($cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS)); - $order->total_discounts_tax_excl += (float)abs($cart->getOrderTotal(false, Cart::ONLY_DISCOUNTS)); - $order->total_discounts_tax_incl += (float)abs($cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS)); - - // Save changes of order - $order->update(); - - // Update weight SUM - $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); - if (Validate::isLoadedObject($order_carrier)) - { - $order_carrier->weight = (float)$order->getTotalWeight(); - if ($order_carrier->update()) - $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); - } - - // Update Tax lines - $order_detail->updateTaxAmount($order); - - // Delete specific price if exists - if (isset($specific_price)) - $specific_price->delete(); - - $products = $this->getProducts($order); - - // Get the last product - $product = end($products); - $resume = OrderSlip::getProductSlipResume((int)$product['id_order_detail']); - $product['quantity_refundable'] = $product['product_quantity'] - $resume['product_quantity']; - $product['amount_refundable'] = $product['total_price_tax_excl'] - $resume['amount_tax_excl']; - $product['amount_refund'] = Tools::displayPrice($resume['amount_tax_incl']); - $product['return_history'] = OrderReturn::getProductReturnDetail((int)$product['id_order_detail']); - $product['refund_history'] = OrderSlip::getProductSlipDetail((int)$product['id_order_detail']); - if ($product['id_warehouse'] != 0) - { - $warehouse = new Warehouse((int)$product['id_warehouse']); - $product['warehouse_name'] = $warehouse->name; - $warehouse_location = WarehouseProductLocation::getProductLocation($product['product_id'], $product['product_attribute_id'], $product['id_warehouse']); - if (!empty($warehouse_location)) - $product['warehouse_location'] = $warehouse_location; - else - $product['warehouse_location'] = false; - } - else - { - $product['warehouse_name'] = '--'; - $product['warehouse_location'] = false; - } - - // Get invoices collection - $invoice_collection = $order->getInvoicesCollection(); - - $invoice_array = array(); - foreach ($invoice_collection as $invoice) - { - /** @var OrderInvoice $invoice */ - $invoice->name = $invoice->getInvoiceNumberFormatted(Context::getContext()->language->id, (int)$order->id_shop); - $invoice_array[] = $invoice; - } - - // Assign to smarty informations in order to show the new product line - $this->context->smarty->assign(array( - 'product' => $product, - 'order' => $order, - 'currency' => new Currency($order->id_currency), - 'can_edit' => $this->tabAccess['edit'], - 'invoices_collection' => $invoice_collection, - 'current_id_lang' => Context::getContext()->language->id, - 'link' => Context::getContext()->link, - 'current_index' => self::$currentIndex, - 'display_warehouse' => (int)Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') - )); - - $this->sendChangedNotification($order); - $new_cart_rules = Context::getContext()->cart->getCartRules(); - sort($old_cart_rules); - sort($new_cart_rules); - $result = array_diff($new_cart_rules, $old_cart_rules); - $refresh = false; - - $res = true; - foreach ($result as $cart_rule) - { - $refresh = true; - // Create OrderCartRule - $rule = new CartRule($cart_rule['id_cart_rule']); - $values = array( - 'tax_incl' => $rule->getContextualValue(true), - 'tax_excl' => $rule->getContextualValue(false) - ); - $order_cart_rule = new OrderCartRule(); - $order_cart_rule->id_order = $order->id; - $order_cart_rule->id_cart_rule = $cart_rule['id_cart_rule']; - $order_cart_rule->id_order_invoice = $order_invoice->id; - $order_cart_rule->name = $cart_rule['name']; - $order_cart_rule->value = $values['tax_incl']; - $order_cart_rule->value_tax_excl = $values['tax_excl']; - $res &= $order_cart_rule->add(); - - $order->total_discounts += $order_cart_rule->value; - $order->total_discounts_tax_incl += $order_cart_rule->value; - $order->total_discounts_tax_excl += $order_cart_rule->value_tax_excl; - $order->total_paid -= $order_cart_rule->value; - $order->total_paid_tax_incl -= $order_cart_rule->value; - $order->total_paid_tax_excl -= $order_cart_rule->value_tax_excl; - } - - // Update Order - $res &= $order->update(); - - - die(Tools::jsonEncode(array( - 'result' => true, - 'view' => $this->createTemplate('_product_line.tpl')->fetch(), - 'can_edit' => $this->tabAccess['add'], - 'order' => $order, - 'invoices' => $invoice_array, - 'documents_html' => $this->createTemplate('_documents.tpl')->fetch(), - 'shipping_html' => $this->createTemplate('_shipping.tpl')->fetch(), - 'discount_form_html' => $this->createTemplate('_discount_form.tpl')->fetch(), - 'refresh' => $refresh - ))); - } - - public function sendChangedNotification(Order $order = null) - { - if (is_null($order)) - $order = new Order(Tools::getValue('id_order')); - - Hook::exec('actionOrderEdited', array('order' => $order)); - } - - public function ajaxProcessLoadProductInformation() - { - $order_detail = new OrderDetail(Tools::getValue('id_order_detail')); - if (!Validate::isLoadedObject($order_detail)) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('The OrderDetail object cannot be loaded.') - ))); - - $product = new Product($order_detail->product_id); - if (!Validate::isLoadedObject($product)) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('The product object cannot be loaded.') - ))); - - $address = new Address(Tools::getValue('id_address')); - if (!Validate::isLoadedObject($address)) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('The address object cannot be loaded.') - ))); - - die(Tools::jsonEncode(array( - 'result' => true, - 'product' => $product, - 'tax_rate' => $product->getTaxesRate($address), - 'price_tax_incl' => Product::getPriceStatic($product->id, true, $order_detail->product_attribute_id, 2), - 'price_tax_excl' => Product::getPriceStatic($product->id, false, $order_detail->product_attribute_id, 2), - 'reduction_percent' => $order_detail->reduction_percent - ))); - } - - public function ajaxProcessEditProductOnOrder() - { - // Return value - $res = true; - - $order = new Order((int)Tools::getValue('id_order')); - $order_detail = new OrderDetail((int)Tools::getValue('product_id_order_detail')); - if (Tools::isSubmit('product_invoice')) - $order_invoice = new OrderInvoice((int)Tools::getValue('product_invoice')); - - // Check fields validity - $this->doEditProductValidation($order_detail, $order, isset($order_invoice) ? $order_invoice : null); - - // If multiple product_quantity, the order details concern a product customized - $product_quantity = 0; - if (is_array(Tools::getValue('product_quantity'))) - foreach (Tools::getValue('product_quantity') as $id_customization => $qty) - { - // Update quantity of each customization - Db::getInstance()->update('customization', array('quantity' => (int)$qty), 'id_customization = '.(int)$id_customization); - // Calculate the real quantity of the product - $product_quantity += $qty; - } - else - $product_quantity = Tools::getValue('product_quantity'); - - $product_price_tax_incl = Tools::ps_round(Tools::getValue('product_price_tax_incl'), 2); - $product_price_tax_excl = Tools::ps_round(Tools::getValue('product_price_tax_excl'), 2); - $total_products_tax_incl = $product_price_tax_incl * $product_quantity; - $total_products_tax_excl = $product_price_tax_excl * $product_quantity; - - // Calculate differences of price (Before / After) - $diff_price_tax_incl = $total_products_tax_incl - $order_detail->total_price_tax_incl; - $diff_price_tax_excl = $total_products_tax_excl - $order_detail->total_price_tax_excl; - - // Apply change on OrderInvoice - if (isset($order_invoice)) - // If OrderInvoice to use is different, we update the old invoice and new invoice - if ($order_detail->id_order_invoice != $order_invoice->id) - { - $old_order_invoice = new OrderInvoice($order_detail->id_order_invoice); - // We remove cost of products - $old_order_invoice->total_products -= $order_detail->total_price_tax_excl; - $old_order_invoice->total_products_wt -= $order_detail->total_price_tax_incl; - - $old_order_invoice->total_paid_tax_excl -= $order_detail->total_price_tax_excl; - $old_order_invoice->total_paid_tax_incl -= $order_detail->total_price_tax_incl; - - $res &= $old_order_invoice->update(); - - $order_invoice->total_products += $order_detail->total_price_tax_excl; - $order_invoice->total_products_wt += $order_detail->total_price_tax_incl; - - $order_invoice->total_paid_tax_excl += $order_detail->total_price_tax_excl; - $order_invoice->total_paid_tax_incl += $order_detail->total_price_tax_incl; - - $order_detail->id_order_invoice = $order_invoice->id; - } - - if ($diff_price_tax_incl != 0 && $diff_price_tax_excl != 0) - { - $order_detail->unit_price_tax_excl = $product_price_tax_excl; - $order_detail->unit_price_tax_incl = $product_price_tax_incl; - - $order_detail->total_price_tax_incl += $diff_price_tax_incl; - $order_detail->total_price_tax_excl += $diff_price_tax_excl; - - if (isset($order_invoice)) - { - // Apply changes on OrderInvoice - $order_invoice->total_products += $diff_price_tax_excl; - $order_invoice->total_products_wt += $diff_price_tax_incl; - - $order_invoice->total_paid_tax_excl += $diff_price_tax_excl; - $order_invoice->total_paid_tax_incl += $diff_price_tax_incl; - } - - // Apply changes on Order - $order = new Order($order_detail->id_order); - $order->total_products += $diff_price_tax_excl; - $order->total_products_wt += $diff_price_tax_incl; - - $order->total_paid += $diff_price_tax_incl; - $order->total_paid_tax_excl += $diff_price_tax_excl; - $order->total_paid_tax_incl += $diff_price_tax_incl; - - $res &= $order->update(); - } - - $old_quantity = $order_detail->product_quantity; - - $order_detail->product_quantity = $product_quantity; - $order_detail->reduction_percent = 0; - - // update taxes - $res &= $order_detail->updateTaxAmount($order); - - // Save order detail - $res &= $order_detail->update(); - - // Update weight SUM - $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); - if (Validate::isLoadedObject($order_carrier)) - { - $order_carrier->weight = (float)$order->getTotalWeight(); - $res &= $order_carrier->update(); - if ($res) - $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); - } - - // Save order invoice - if (isset($order_invoice)) - $res &= $order_invoice->update(); - - // Update product available quantity - StockAvailable::updateQuantity($order_detail->product_id, $order_detail->product_attribute_id, ($old_quantity - $order_detail->product_quantity), $order->id_shop); - - $products = $this->getProducts($order); - // Get the last product - $product = $products[$order_detail->id]; - $resume = OrderSlip::getProductSlipResume($order_detail->id); - $product['quantity_refundable'] = $product['product_quantity'] - $resume['product_quantity']; - $product['amount_refundable'] = $product['total_price_tax_excl'] - $resume['amount_tax_excl']; - $product['amount_refund'] = Tools::displayPrice($resume['amount_tax_incl']); - $product['refund_history'] = OrderSlip::getProductSlipDetail($order_detail->id); - if ($product['id_warehouse'] != 0) - { - $warehouse = new Warehouse((int)$product['id_warehouse']); - $product['warehouse_name'] = $warehouse->name; - $warehouse_location = WarehouseProductLocation::getProductLocation($product['product_id'], $product['product_attribute_id'], $product['id_warehouse']); - if (!empty($warehouse_location)) - $product['warehouse_location'] = $warehouse_location; - else - $product['warehouse_location'] = false; - } - else - { - $product['warehouse_name'] = '--'; - $product['warehouse_location'] = false; - } - - // Get invoices collection - $invoice_collection = $order->getInvoicesCollection(); - - $invoice_array = array(); - foreach ($invoice_collection as $invoice) - { - /** @var OrderInvoice $invoice */ - $invoice->name = $invoice->getInvoiceNumberFormatted(Context::getContext()->language->id, (int)$order->id_shop); - $invoice_array[] = $invoice; - } - - // Assign to smarty informations in order to show the new product line - $this->context->smarty->assign(array( - 'product' => $product, - 'order' => $order, - 'currency' => new Currency($order->id_currency), - 'can_edit' => $this->tabAccess['edit'], - 'invoices_collection' => $invoice_collection, - 'current_id_lang' => Context::getContext()->language->id, - 'link' => Context::getContext()->link, - 'current_index' => self::$currentIndex, - 'display_warehouse' => (int)Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') - )); - - if (!$res) - die(Tools::jsonEncode(array( - 'result' => $res, - 'error' => Tools::displayError('An error occurred while editing the product line.') - ))); - - - if (is_array(Tools::getValue('product_quantity'))) - $view = $this->createTemplate('_customized_data.tpl')->fetch(); - else - $view = $this->createTemplate('_product_line.tpl')->fetch(); - - $this->sendChangedNotification($order); - - die(Tools::jsonEncode(array( - 'result' => $res, - 'view' => $view, - 'can_edit' => $this->tabAccess['add'], - 'invoices_collection' => $invoice_collection, - 'order' => $order, - 'invoices' => $invoice_array, - 'documents_html' => $this->createTemplate('_documents.tpl')->fetch(), - 'shipping_html' => $this->createTemplate('_shipping.tpl')->fetch(), - 'customized_product' => is_array(Tools::getValue('product_quantity')) - ))); - } - - public function ajaxProcessDeleteProductLine() - { - $res = true; - - $order_detail = new OrderDetail((int)Tools::getValue('id_order_detail')); - $order = new Order((int)Tools::getValue('id_order')); - - $this->doDeleteProductLineValidation($order_detail, $order); - - // Update OrderInvoice of this OrderDetail - if ($order_detail->id_order_invoice != 0) - { - $order_invoice = new OrderInvoice($order_detail->id_order_invoice); - $order_invoice->total_paid_tax_excl -= $order_detail->total_price_tax_excl; - $order_invoice->total_paid_tax_incl -= $order_detail->total_price_tax_incl; - $order_invoice->total_products -= $order_detail->total_price_tax_excl; - $order_invoice->total_products_wt -= $order_detail->total_price_tax_incl; - $res &= $order_invoice->update(); - } - - // Update Order - $order->total_paid -= $order_detail->total_price_tax_incl; - $order->total_paid_tax_incl -= $order_detail->total_price_tax_incl; - $order->total_paid_tax_excl -= $order_detail->total_price_tax_excl; - $order->total_products -= $order_detail->total_price_tax_excl; - $order->total_products_wt -= $order_detail->total_price_tax_incl; - - $res &= $order->update(); - - // Reinject quantity in stock - $this->reinjectQuantity($order_detail, $order_detail->product_quantity, true); - - // Update weight SUM - $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); - if (Validate::isLoadedObject($order_carrier)) - { - $order_carrier->weight = (float)$order->getTotalWeight(); - $res &= $order_carrier->update(); - if ($res) - $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); - } - - if (!$res) - die(Tools::jsonEncode(array( - 'result' => $res, - 'error' => Tools::displayError('An error occurred while attempting to delete the product line.') - ))); - - // Get invoices collection - $invoice_collection = $order->getInvoicesCollection(); - - $invoice_array = array(); - foreach ($invoice_collection as $invoice) - { - /** @var OrderInvoice $invoice */ - $invoice->name = $invoice->getInvoiceNumberFormatted(Context::getContext()->language->id, (int)$order->id_shop); - $invoice_array[] = $invoice; - } - - // Assign to smarty informations in order to show the new product line - $this->context->smarty->assign(array( - 'order' => $order, - 'currency' => new Currency($order->id_currency), - 'invoices_collection' => $invoice_collection, - 'current_id_lang' => Context::getContext()->language->id, - 'link' => Context::getContext()->link, - 'current_index' => self::$currentIndex - )); - - $this->sendChangedNotification($order); - - die(Tools::jsonEncode(array( - 'result' => $res, - 'order' => $order, - 'invoices' => $invoice_array, - 'documents_html' => $this->createTemplate('_documents.tpl')->fetch(), - 'shipping_html' => $this->createTemplate('_shipping.tpl')->fetch() - ))); - } - - protected function doEditProductValidation(OrderDetail $order_detail, Order $order, OrderInvoice $order_invoice = null) - { - if (!Validate::isLoadedObject($order_detail)) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('The Order Detail object could not be loaded.') - ))); - - if (!empty($order_invoice) && !Validate::isLoadedObject($order_invoice)) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('The invoice object cannot be loaded.') - ))); - - if (!Validate::isLoadedObject($order)) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('The order object cannot be loaded.') - ))); - - if ($order_detail->id_order != $order->id) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('You cannot edit the order detail for this order.') - ))); - - // We can't edit a delivered order - if ($order->hasBeenDelivered()) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('You cannot edit a delivered order.') - ))); - - if (!empty($order_invoice) && $order_invoice->id_order != Tools::getValue('id_order')) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('You cannot use this invoice for the order') - ))); - - // Clean price - $product_price_tax_incl = str_replace(',', '.', Tools::getValue('product_price_tax_incl')); - $product_price_tax_excl = str_replace(',', '.', Tools::getValue('product_price_tax_excl')); - - if (!Validate::isPrice($product_price_tax_incl) || !Validate::isPrice($product_price_tax_excl)) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('Invalid price') - ))); - - if (!is_array(Tools::getValue('product_quantity')) && !Validate::isUnsignedInt(Tools::getValue('product_quantity'))) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('Invalid quantity') - ))); - elseif (is_array(Tools::getValue('product_quantity'))) - foreach (Tools::getValue('product_quantity') as $qty) - if (!Validate::isUnsignedInt($qty)) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('Invalid quantity') - ))); - } - - protected function doDeleteProductLineValidation(OrderDetail $order_detail, Order $order) - { - if (!Validate::isLoadedObject($order_detail)) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('The Order Detail object could not be loaded.') - ))); - - if (!Validate::isLoadedObject($order)) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('The order object cannot be loaded.') - ))); - - if ($order_detail->id_order != $order->id) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('You cannot delete the order detail.') - ))); - - // We can't edit a delivered order - if ($order->hasBeenDelivered()) - die(Tools::jsonEncode(array( - 'result' => false, - 'error' => Tools::displayError('You cannot edit a delivered order.') - ))); - } - - /** - * @param Order $order - * @return array - */ - protected function getProducts($order) - { - $products = $order->getProducts(); - - foreach ($products as &$product) - { - if ($product['image'] != null) - { - $name = 'product_mini_'.(int)$product['product_id'].(isset($product['product_attribute_id']) ? '_'.(int)$product['product_attribute_id'] : '').'.jpg'; - // generate image cache, only for back office - $product['image_tag'] = ImageManager::thumbnail(_PS_IMG_DIR_.'p/'.$product['image']->getExistingImgPath().'.jpg', $name, 45, 'jpg'); - if (file_exists(_PS_TMP_IMG_DIR_.$name)) - $product['image_size'] = getimagesize(_PS_TMP_IMG_DIR_.$name); - else - $product['image_size'] = false; - } - } - - ksort($products); - - return $products; - } - - /** - * @param OrderDetail $order_detail - * @param int $qty_cancel_product - * @param bool $delete - */ - protected function reinjectQuantity($order_detail, $qty_cancel_product, $delete = false) - { - // Reinject product - $reinjectable_quantity = (int)$order_detail->product_quantity - (int)$order_detail->product_quantity_reinjected; - $quantity_to_reinject = $qty_cancel_product > $reinjectable_quantity ? $reinjectable_quantity : $qty_cancel_product; - // @since 1.5.0 : Advanced Stock Management - $product_to_inject = new Product($order_detail->product_id, false, (int)$this->context->language->id, (int)$order_detail->id_shop); - - $product = new Product($order_detail->product_id, false, (int)$this->context->language->id, (int)$order_detail->id_shop); - - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management && $order_detail->id_warehouse != 0) - { - $manager = StockManagerFactory::getManager(); - $movements = StockMvt::getNegativeStockMvts( - $order_detail->id_order, - $order_detail->product_id, - $order_detail->product_attribute_id, - $quantity_to_reinject - ); - $left_to_reinject = $quantity_to_reinject; - foreach ($movements as $movement) - { - if ($left_to_reinject > $movement['physical_quantity']) - $quantity_to_reinject = $movement['physical_quantity']; - - $left_to_reinject -= $quantity_to_reinject; - if (Pack::isPack((int)$product->id)) - { - // Gets items - if ($product->pack_stock_type == 1 || $product->pack_stock_type == 2 || ($product->pack_stock_type == 3 && Configuration::get('PS_PACK_STOCK_TYPE') > 0)) - { - $products_pack = Pack::getItems((int)$product->id, (int)Configuration::get('PS_LANG_DEFAULT')); - // Foreach item - foreach ($products_pack as $product_pack) - if ($product_pack->advanced_stock_management == 1) - { - $manager->addProduct( - $product_pack->id, - $product_pack->id_pack_product_attribute, - new Warehouse($movement['id_warehouse']), - $product_pack->pack_quantity * $quantity_to_reinject, - null, - $movement['price_te'], - true - ); - } - } - if ($product->pack_stock_type == 0 || $product->pack_stock_type == 2 || - ($product->pack_stock_type == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 0 || Configuration::get('PS_PACK_STOCK_TYPE') == 2))) - $manager->addProduct( - $order_detail->product_id, - $order_detail->product_attribute_id, - new Warehouse($movement['id_warehouse']), - $quantity_to_reinject, - null, - $movement['price_te'], - true - ); - } - else - { - $manager->addProduct( - $order_detail->product_id, - $order_detail->product_attribute_id, - new Warehouse($movement['id_warehouse']), - $quantity_to_reinject, - null, - $movement['price_te'], - true - ); - } - } - - $id_product = $order_detail->product_id; - if ($delete) - $order_detail->delete(); - StockAvailable::synchronize($id_product); - } - elseif ($order_detail->id_warehouse == 0) - { - StockAvailable::updateQuantity( - $order_detail->product_id, - $order_detail->product_attribute_id, - $quantity_to_reinject, - $order_detail->id_shop - ); - - if ($delete) - $order_detail->delete(); - } - else - $this->errors[] = Tools::displayError('This product cannot be re-stocked.'); - } - - /** - * @param OrderInvoice $order_invoice - * @param float $value_tax_incl - * @param float $value_tax_excl - */ - protected function applyDiscountOnInvoice($order_invoice, $value_tax_incl, $value_tax_excl) - { - // Update OrderInvoice - $order_invoice->total_discount_tax_incl += $value_tax_incl; - $order_invoice->total_discount_tax_excl += $value_tax_excl; - $order_invoice->total_paid_tax_incl -= $value_tax_incl; - $order_invoice->total_paid_tax_excl -= $value_tax_excl; - $order_invoice->update(); - } - - public function ajaxProcessChangePaymentMethod() - { - $customer = new Customer(Tools::getValue('id_customer')); - $modules = Module::getAuthorizedModules($customer->id_default_group); - $authorized_modules = array(); - - if (!Validate::isLoadedObject($customer) || !is_array($modules)) - die(Tools::jsonEncode(array('result' => false))); - - foreach ($modules as $module) - $authorized_modules[] = (int)$module['id_module']; - - $payment_modules = array(); - - foreach (PaymentModule::getInstalledPaymentModules() as $p_module) - if (in_array((int)$p_module['id_module'], $authorized_modules)) - $payment_modules[] = Module::getInstanceById((int)$p_module['id_module']); - - $this->context->smarty->assign(array( - 'payment_modules' => $payment_modules, - )); - - die(Tools::jsonEncode(array( - 'result' => true, - 'view' => $this->createTemplate('_select_payment.tpl')->fetch(), - ))); - } + $voucher = 0; + + if ((int)Tools::getValue('refund_voucher_off') == 1) { + $amount -= $voucher = (float)Tools::getValue('order_discount_price'); + } elseif ((int)Tools::getValue('refund_voucher_off') == 2) { + $choosen = true; + $amount = $voucher = (float)Tools::getValue('refund_voucher_choose'); + } + + if ($shipping_cost_amount > 0) { + if (!Tools::getValue('TaxMethod')) { + $tax = new Tax(); + $tax->rate = $order->carrier_tax_rate; + $tax_calculator = new TaxCalculator(array($tax)); + $amount += $tax_calculator->addTaxes($shipping_cost_amount); + } else { + $amount += $shipping_cost_amount; + } + } + + $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); + if (Validate::isLoadedObject($order_carrier)) { + $order_carrier->weight = (float)$order->getTotalWeight(); + if ($order_carrier->update()) { + $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); + } + } + + if ($amount >= 0) { + if (!OrderSlip::create($order, $order_detail_list, $shipping_cost_amount, $voucher, $choosen, + (Tools::getValue('TaxMethod') ? false : true))) { + $this->errors[] = Tools::displayError('You cannot generate a partial credit slip.'); + } else { + Hook::exec('actionOrderSlipAdd', array('order' => $order, 'productList' => $order_detail_list, 'qtyList' => $full_quantity_list), null, false, true, false, $order->id_shop); + $customer = new Customer((int)($order->id_customer)); + $params['{lastname}'] = $customer->lastname; + $params['{firstname}'] = $customer->firstname; + $params['{id_order}'] = $order->id; + $params['{order_name}'] = $order->getUniqReference(); + @Mail::Send( + (int)$order->id_lang, + 'credit_slip', + Mail::l('New credit slip regarding your order', (int)$order->id_lang), + $params, + $customer->email, + $customer->firstname.' '.$customer->lastname, + null, + null, + null, + null, + _PS_MAIL_DIR_, + true, + (int)$order->id_shop + ); + } + + foreach ($order_detail_list as &$product) { + $order_detail = new OrderDetail((int)$product['id_order_detail']); + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + StockAvailable::synchronize($order_detail->product_id); + } + } + + // Generate voucher + if (Tools::isSubmit('generateDiscountRefund') && !count($this->errors) && $amount > 0) { + $cart_rule = new CartRule(); + $cart_rule->description = sprintf($this->l('Credit slip for order #%d'), $order->id); + $language_ids = Language::getIDs(false); + foreach ($language_ids as $id_lang) { + // Define a temporary name + $cart_rule->name[$id_lang] = sprintf('V0C%1$dO%2$d', $order->id_customer, $order->id); + } + + // Define a temporary code + $cart_rule->code = sprintf('V0C%1$dO%2$d', $order->id_customer, $order->id); + $cart_rule->quantity = 1; + $cart_rule->quantity_per_user = 1; + + // Specific to the customer + $cart_rule->id_customer = $order->id_customer; + $now = time(); + $cart_rule->date_from = date('Y-m-d H:i:s', $now); + $cart_rule->date_to = date('Y-m-d H:i:s', strtotime('+1 year')); + $cart_rule->partial_use = 1; + $cart_rule->active = 1; + + $cart_rule->reduction_amount = $amount; + $cart_rule->reduction_tax = true; + $cart_rule->minimum_amount_currency = $order->id_currency; + $cart_rule->reduction_currency = $order->id_currency; + + if (!$cart_rule->add()) { + $this->errors[] = Tools::displayError('You cannot generate a voucher.'); + } else { + // Update the voucher code and name + foreach ($language_ids as $id_lang) { + $cart_rule->name[$id_lang] = sprintf('V%1$dC%2$dO%3$d', $cart_rule->id, $order->id_customer, $order->id); + } + $cart_rule->code = sprintf('V%1$dC%2$dO%3$d', $cart_rule->id, $order->id_customer, $order->id); + + if (!$cart_rule->update()) { + $this->errors[] = Tools::displayError('You cannot generate a voucher.'); + } else { + $currency = $this->context->currency; + $customer = new Customer((int)($order->id_customer)); + $params['{lastname}'] = $customer->lastname; + $params['{firstname}'] = $customer->firstname; + $params['{id_order}'] = $order->id; + $params['{order_name}'] = $order->getUniqReference(); + $params['{voucher_amount}'] = Tools::displayPrice($cart_rule->reduction_amount, $currency, false); + $params['{voucher_num}'] = $cart_rule->code; + @Mail::Send((int)$order->id_lang, 'voucher', sprintf(Mail::l('New voucher for your order #%s', (int)$order->id_lang), $order->reference), + $params, $customer->email, $customer->firstname.' '.$customer->lastname, null, null, null, + null, _PS_MAIL_DIR_, true, (int)$order->id_shop); + } + } + } + } else { + if (!empty($refunds)) { + $this->errors[] = Tools::displayError('Please enter a quantity to proceed with your refund.'); + } else { + $this->errors[] = Tools::displayError('Please enter an amount to proceed with your refund.'); + } + } + + // Redirect if no errors + if (!count($this->errors)) { + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=30&token='.$this->token); + } + } else { + $this->errors[] = Tools::displayError('The partial refund data is incorrect.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } + + /* Cancel product from order */ + elseif (Tools::isSubmit('cancelProduct') && isset($order)) { + if ($this->tabAccess['delete'] === '1') { + if (!Tools::isSubmit('id_order_detail') && !Tools::isSubmit('id_customization')) { + $this->errors[] = Tools::displayError('You must select a product.'); + } elseif (!Tools::isSubmit('cancelQuantity') && !Tools::isSubmit('cancelCustomizationQuantity')) { + $this->errors[] = Tools::displayError('You must enter a quantity.'); + } else { + $productList = Tools::getValue('id_order_detail'); + if ($productList) { + $productList = array_map('intval', $productList); + } + + $customizationList = Tools::getValue('id_customization'); + if ($customizationList) { + $customizationList = array_map('intval', $customizationList); + } + + $qtyList = Tools::getValue('cancelQuantity'); + if ($qtyList) { + $qtyList = array_map('intval', $qtyList); + } + + $customizationQtyList = Tools::getValue('cancelCustomizationQuantity'); + if ($customizationQtyList) { + $customizationQtyList = array_map('intval', $customizationQtyList); + } + + $full_product_list = $productList; + $full_quantity_list = $qtyList; + + if ($customizationList) { + foreach ($customizationList as $key => $id_order_detail) { + $full_product_list[(int)$id_order_detail] = $id_order_detail; + if (isset($customizationQtyList[$key])) { + $full_quantity_list[(int)$id_order_detail] += $customizationQtyList[$key]; + } + } + } + + if ($productList || $customizationList) { + if ($productList) { + $id_cart = Cart::getCartIdByOrderId($order->id); + $customization_quantities = Customization::countQuantityByCart($id_cart); + + foreach ($productList as $key => $id_order_detail) { + $qtyCancelProduct = abs($qtyList[$key]); + if (!$qtyCancelProduct) { + $this->errors[] = Tools::displayError('No quantity has been selected for this product.'); + } + + $order_detail = new OrderDetail($id_order_detail); + $customization_quantity = 0; + if (array_key_exists($order_detail->product_id, $customization_quantities) && array_key_exists($order_detail->product_attribute_id, $customization_quantities[$order_detail->product_id])) { + $customization_quantity = (int)$customization_quantities[$order_detail->product_id][$order_detail->product_attribute_id]; + } + + if (($order_detail->product_quantity - $customization_quantity - $order_detail->product_quantity_refunded - $order_detail->product_quantity_return) < $qtyCancelProduct) { + $this->errors[] = Tools::displayError('An invalid quantity was selected for this product.'); + } + } + } + if ($customizationList) { + $customization_quantities = Customization::retrieveQuantitiesFromIds(array_keys($customizationList)); + + foreach ($customizationList as $id_customization => $id_order_detail) { + $qtyCancelProduct = abs($customizationQtyList[$id_customization]); + $customization_quantity = $customization_quantities[$id_customization]; + + if (!$qtyCancelProduct) { + $this->errors[] = Tools::displayError('No quantity has been selected for this product.'); + } + + if ($qtyCancelProduct > ($customization_quantity['quantity'] - ($customization_quantity['quantity_refunded'] + $customization_quantity['quantity_returned']))) { + $this->errors[] = Tools::displayError('An invalid quantity was selected for this product.'); + } + } + } + + if (!count($this->errors) && $productList) { + foreach ($productList as $key => $id_order_detail) { + $qty_cancel_product = abs($qtyList[$key]); + $order_detail = new OrderDetail((int)($id_order_detail)); + + if (!$order->hasBeenDelivered() || ($order->hasBeenDelivered() && Tools::isSubmit('reinjectQuantities')) && $qty_cancel_product > 0) { + $this->reinjectQuantity($order_detail, $qty_cancel_product); + } + + // Delete product + $order_detail = new OrderDetail((int)$id_order_detail); + if (!$order->deleteProduct($order, $order_detail, $qty_cancel_product)) { + $this->errors[] = Tools::displayError('An error occurred while attempting to delete the product.').' <span class="bold">'.$order_detail->product_name.'</span>'; + } + // Update weight SUM + $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); + if (Validate::isLoadedObject($order_carrier)) { + $order_carrier->weight = (float)$order->getTotalWeight(); + if ($order_carrier->update()) { + $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); + } + } + + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && StockAvailable::dependsOnStock($order_detail->product_id)) { + StockAvailable::synchronize($order_detail->product_id); + } + Hook::exec('actionProductCancel', array('order' => $order, 'id_order_detail' => (int)$id_order_detail), null, false, true, false, $order->id_shop); + } + } + if (!count($this->errors) && $customizationList) { + foreach ($customizationList as $id_customization => $id_order_detail) { + $order_detail = new OrderDetail((int)($id_order_detail)); + $qtyCancelProduct = abs($customizationQtyList[$id_customization]); + if (!$order->deleteCustomization($id_customization, $qtyCancelProduct, $order_detail)) { + $this->errors[] = Tools::displayError('An error occurred while attempting to delete product customization.').' '.$id_customization; + } + } + } + // E-mail params + if ((Tools::isSubmit('generateCreditSlip') || Tools::isSubmit('generateDiscount')) && !count($this->errors)) { + $customer = new Customer((int)($order->id_customer)); + $params['{lastname}'] = $customer->lastname; + $params['{firstname}'] = $customer->firstname; + $params['{id_order}'] = $order->id; + $params['{order_name}'] = $order->getUniqReference(); + } + + // Generate credit slip + if (Tools::isSubmit('generateCreditSlip') && !count($this->errors)) { + $product_list = array(); + $amount = $order_detail->unit_price_tax_incl * $full_quantity_list[$id_order_detail]; + + $choosen = false; + if ((int)Tools::getValue('refund_total_voucher_off') == 1) { + $amount -= $voucher = (float)Tools::getValue('order_discount_price'); + } elseif ((int)Tools::getValue('refund_total_voucher_off') == 2) { + $choosen = true; + $amount = $voucher = (float)Tools::getValue('refund_total_voucher_choose'); + } + foreach ($full_product_list as $id_order_detail) { + $order_detail = new OrderDetail((int)$id_order_detail); + $product_list[$id_order_detail] = array( + 'id_order_detail' => $id_order_detail, + 'quantity' => $full_quantity_list[$id_order_detail], + 'unit_price' => $order_detail->unit_price_tax_excl, + 'amount' => isset($amount) ? $amount : $order_detail->unit_price_tax_incl * $full_quantity_list[$id_order_detail], + ); + } + + $shipping = Tools::isSubmit('shippingBack') ? null : false; + + if (!OrderSlip::create($order, $product_list, $shipping, $voucher, $choosen)) { + $this->errors[] = Tools::displayError('A credit slip cannot be generated. '); + } else { + Hook::exec('actionOrderSlipAdd', array('order' => $order, 'productList' => $full_product_list, 'qtyList' => $full_quantity_list), null, false, true, false, $order->id_shop); + @Mail::Send( + (int)$order->id_lang, + 'credit_slip', + Mail::l('New credit slip regarding your order', (int)$order->id_lang), + $params, + $customer->email, + $customer->firstname.' '.$customer->lastname, + null, + null, + null, + null, + _PS_MAIL_DIR_, + true, + (int)$order->id_shop + ); + } + } + + // Generate voucher + if (Tools::isSubmit('generateDiscount') && !count($this->errors)) { + $cartrule = new CartRule(); + $language_ids = Language::getIDs((bool)$order); + $cartrule->description = sprintf($this->l('Credit card slip for order #%d'), $order->id); + foreach ($language_ids as $id_lang) { + // Define a temporary name + $cartrule->name[$id_lang] = 'V0C'.(int)($order->id_customer).'O'.(int)($order->id); + } + // Define a temporary code + $cartrule->code = 'V0C'.(int)($order->id_customer).'O'.(int)($order->id); + + $cartrule->quantity = 1; + $cartrule->quantity_per_user = 1; + // Specific to the customer + $cartrule->id_customer = $order->id_customer; + $now = time(); + $cartrule->date_from = date('Y-m-d H:i:s', $now); + $cartrule->date_to = date('Y-m-d H:i:s', $now + (3600 * 24 * 365.25)); /* 1 year */ + $cartrule->active = 1; + + $products = $order->getProducts(false, $full_product_list, $full_quantity_list); + + $total = 0; + foreach ($products as $product) { + $total += $product['unit_price_tax_incl'] * $product['product_quantity']; + } + + if (Tools::isSubmit('shippingBack')) { + $total += $order->total_shipping; + } + + if ((int)Tools::getValue('refund_total_voucher_off') == 1) { + $total -= (float)Tools::getValue('order_discount_price'); + } elseif ((int)Tools::getValue('refund_total_voucher_off') == 2) { + $total = (float)Tools::getValue('refund_total_voucher_choose'); + } + + $cartrule->reduction_amount = $total; + $cartrule->reduction_tax = true; + $cartrule->minimum_amount_currency = $order->id_currency; + $cartrule->reduction_currency = $order->id_currency; + + if (!$cartrule->add()) { + $this->errors[] = Tools::displayError('You cannot generate a voucher.'); + } else { + // Update the voucher code and name + foreach ($language_ids as $id_lang) { + $cartrule->name[$id_lang] = 'V'.(int)($cartrule->id).'C'.(int)($order->id_customer).'O'.$order->id; + } + $cartrule->code = 'V'.(int)($cartrule->id).'C'.(int)($order->id_customer).'O'.$order->id; + if (!$cartrule->update()) { + $this->errors[] = Tools::displayError('You cannot generate a voucher.'); + } else { + $currency = $this->context->currency; + $params['{voucher_amount}'] = Tools::displayPrice($cartrule->reduction_amount, $currency, false); + $params['{voucher_num}'] = $cartrule->code; + @Mail::Send((int)$order->id_lang, 'voucher', sprintf(Mail::l('New voucher for your order #%s', (int)$order->id_lang), $order->reference), + $params, $customer->email, $customer->firstname.' '.$customer->lastname, null, null, null, + null, _PS_MAIL_DIR_, true, (int)$order->id_shop); + } + } + } + } else { + $this->errors[] = Tools::displayError('No product or quantity has been selected.'); + } + + // Redirect if no errors + if (!count($this->errors)) { + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=31&token='.$this->token); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } elseif (Tools::isSubmit('messageReaded')) { + Message::markAsReaded(Tools::getValue('messageReaded'), $this->context->employee->id); + } elseif (Tools::isSubmit('submitAddPayment') && isset($order)) { + if ($this->tabAccess['edit'] === '1') { + $amount = str_replace(',', '.', Tools::getValue('payment_amount')); + $currency = new Currency(Tools::getValue('payment_currency')); + $order_has_invoice = $order->hasInvoice(); + if ($order_has_invoice) { + $order_invoice = new OrderInvoice(Tools::getValue('payment_invoice')); + } else { + $order_invoice = null; + } + + if (!Validate::isLoadedObject($order)) { + $this->errors[] = Tools::displayError('The order cannot be found'); + } elseif (!Validate::isNegativePrice($amount) || !(float)$amount) { + $this->errors[] = Tools::displayError('The amount is invalid.'); + } elseif (!Validate::isGenericName(Tools::getValue('payment_method'))) { + $this->errors[] = Tools::displayError('The selected payment method is invalid.'); + } elseif (!Validate::isString(Tools::getValue('payment_transaction_id'))) { + $this->errors[] = Tools::displayError('The transaction ID is invalid.'); + } elseif (!Validate::isLoadedObject($currency)) { + $this->errors[] = Tools::displayError('The selected currency is invalid.'); + } elseif ($order_has_invoice && !Validate::isLoadedObject($order_invoice)) { + $this->errors[] = Tools::displayError('The invoice is invalid.'); + } elseif (!Validate::isDate(Tools::getValue('payment_date'))) { + $this->errors[] = Tools::displayError('The date is invalid'); + } else { + if (!$order->addOrderPayment($amount, Tools::getValue('payment_method'), Tools::getValue('payment_transaction_id'), $currency, Tools::getValue('payment_date'), $order_invoice)) { + $this->errors[] = Tools::displayError('An error occurred during payment.'); + } else { + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('submitEditNote')) { + $note = Tools::getValue('note'); + $order_invoice = new OrderInvoice((int)Tools::getValue('id_order_invoice')); + if (Validate::isLoadedObject($order_invoice) && Validate::isCleanHtml($note)) { + if ($this->tabAccess['edit'] === '1') { + $order_invoice->note = $note; + if ($order_invoice->save()) { + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order_invoice->id_order.'&vieworder&conf=4&token='.$this->token); + } else { + $this->errors[] = Tools::displayError('The invoice note was not saved.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } else { + $this->errors[] = Tools::displayError('The invoice for edit note was unable to load. '); + } + } elseif (Tools::isSubmit('submitAddOrder') && ($id_cart = Tools::getValue('id_cart')) && + ($module_name = Tools::getValue('payment_module_name')) && + ($id_order_state = Tools::getValue('id_order_state')) && Validate::isModuleName($module_name)) { + if ($this->tabAccess['edit'] === '1') { + if (!Configuration::get('PS_CATALOG_MODE')) { + $payment_module = Module::getInstanceByName($module_name); + } else { + $payment_module = new BoOrder(); + } + + $cart = new Cart((int)$id_cart); + Context::getContext()->currency = new Currency((int)$cart->id_currency); + Context::getContext()->customer = new Customer((int)$cart->id_customer); + + $bad_delivery = false; + if (($bad_delivery = (bool)!Address::isCountryActiveById((int)$cart->id_address_delivery)) + || !Address::isCountryActiveById((int)$cart->id_address_invoice)) { + if ($bad_delivery) { + $this->errors[] = Tools::displayError('This delivery address country is not active.'); + } else { + $this->errors[] = Tools::displayError('This invoice address country is not active.'); + } + } else { + $employee = new Employee((int)Context::getContext()->cookie->id_employee); + $payment_module->validateOrder( + (int)$cart->id, (int)$id_order_state, + $cart->getOrderTotal(true, Cart::BOTH), $payment_module->displayName, $this->l('Manual order -- Employee:').' '. + substr($employee->firstname, 0, 1).'. '.$employee->lastname, array(), null, false, $cart->secure_key + ); + if ($payment_module->currentOrder) { + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$payment_module->currentOrder.'&vieworder'.'&token='.$this->token); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } elseif ((Tools::isSubmit('submitAddressShipping') || Tools::isSubmit('submitAddressInvoice')) && isset($order)) { + if ($this->tabAccess['edit'] === '1') { + $address = new Address(Tools::getValue('id_address')); + if (Validate::isLoadedObject($address)) { + // Update the address on order + if (Tools::isSubmit('submitAddressShipping')) { + $order->id_address_delivery = $address->id; + } elseif (Tools::isSubmit('submitAddressInvoice')) { + $order->id_address_invoice = $address->id; + } + $order->update(); + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); + } else { + $this->errors[] = Tools::displayError('This address can\'t be loaded'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('submitChangeCurrency') && isset($order)) { + if ($this->tabAccess['edit'] === '1') { + if (Tools::getValue('new_currency') != $order->id_currency && !$order->valid) { + $old_currency = new Currency($order->id_currency); + $currency = new Currency(Tools::getValue('new_currency')); + if (!Validate::isLoadedObject($currency)) { + throw new PrestaShopException('Can\'t load Currency object'); + } + + // Update order detail amount + foreach ($order->getOrderDetailList() as $row) { + $order_detail = new OrderDetail($row['id_order_detail']); + $fields = array( + 'ecotax', + 'product_price', + 'reduction_amount', + 'total_shipping_price_tax_excl', + 'total_shipping_price_tax_incl', + 'total_price_tax_incl', + 'total_price_tax_excl', + 'product_quantity_discount', + 'purchase_supplier_price', + 'reduction_amount', + 'reduction_amount_tax_incl', + 'reduction_amount_tax_excl', + 'unit_price_tax_incl', + 'unit_price_tax_excl', + 'original_product_price' + + ); + foreach ($fields as $field) { + $order_detail->{$field} = Tools::convertPriceFull($order_detail->{$field}, $old_currency, $currency); + } + + $order_detail->update(); + $order_detail->updateTaxAmount($order); + } + + $id_order_carrier = (int)$order->getIdOrderCarrier(); + if ($id_order_carrier) { + $order_carrier = $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); + $order_carrier->shipping_cost_tax_excl = (float)Tools::convertPriceFull($order_carrier->shipping_cost_tax_excl, $old_currency, $currency); + $order_carrier->shipping_cost_tax_incl = (float)Tools::convertPriceFull($order_carrier->shipping_cost_tax_incl, $old_currency, $currency); + $order_carrier->update(); + } + + // Update order && order_invoice amount + $fields = array( + 'total_discounts', + 'total_discounts_tax_incl', + 'total_discounts_tax_excl', + 'total_discount_tax_excl', + 'total_discount_tax_incl', + 'total_paid', + 'total_paid_tax_incl', + 'total_paid_tax_excl', + 'total_paid_real', + 'total_products', + 'total_products_wt', + 'total_shipping', + 'total_shipping_tax_incl', + 'total_shipping_tax_excl', + 'total_wrapping', + 'total_wrapping_tax_incl', + 'total_wrapping_tax_excl', + ); + + $invoices = $order->getInvoicesCollection(); + if ($invoices) { + foreach ($invoices as $invoice) { + foreach ($fields as $field) { + if (isset($invoice->$field)) { + $invoice->{$field} = Tools::convertPriceFull($invoice->{$field}, $old_currency, $currency); + } + } + $invoice->save(); + } + } + + foreach ($fields as $field) { + if (isset($order->$field)) { + $order->{$field} = Tools::convertPriceFull($order->{$field}, $old_currency, $currency); + } + } + + // Update currency in order + $order->id_currency = $currency->id; + // Update exchange rate + $order->conversion_rate = (float)$currency->conversion_rate; + $order->update(); + } else { + $this->errors[] = Tools::displayError('You cannot change the currency.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('submitGenerateInvoice') && isset($order)) { + if (!Configuration::get('PS_INVOICE', null, null, $order->id_shop)) { + $this->errors[] = Tools::displayError('Invoice management has been disabled.'); + } elseif ($order->hasInvoice()) { + $this->errors[] = Tools::displayError('This order already has an invoice.'); + } else { + $order->setInvoice(true); + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); + } + } elseif (Tools::isSubmit('submitDeleteVoucher') && isset($order)) { + if ($this->tabAccess['edit'] === '1') { + $order_cart_rule = new OrderCartRule(Tools::getValue('id_order_cart_rule')); + if (Validate::isLoadedObject($order_cart_rule) && $order_cart_rule->id_order == $order->id) { + if ($order_cart_rule->id_order_invoice) { + $order_invoice = new OrderInvoice($order_cart_rule->id_order_invoice); + if (!Validate::isLoadedObject($order_invoice)) { + throw new PrestaShopException('Can\'t load Order Invoice object'); + } + + // Update amounts of Order Invoice + $order_invoice->total_discount_tax_excl -= $order_cart_rule->value_tax_excl; + $order_invoice->total_discount_tax_incl -= $order_cart_rule->value; + + $order_invoice->total_paid_tax_excl += $order_cart_rule->value_tax_excl; + $order_invoice->total_paid_tax_incl += $order_cart_rule->value; + + // Update Order Invoice + $order_invoice->update(); + } + + // Update amounts of order + $order->total_discounts -= $order_cart_rule->value; + $order->total_discounts_tax_incl -= $order_cart_rule->value; + $order->total_discounts_tax_excl -= $order_cart_rule->value_tax_excl; + + $order->total_paid += $order_cart_rule->value; + $order->total_paid_tax_incl += $order_cart_rule->value; + $order->total_paid_tax_excl += $order_cart_rule->value_tax_excl; + + // Delete Order Cart Rule and update Order + $order_cart_rule->delete(); + $order->update(); + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); + } else { + $this->errors[] = Tools::displayError('You cannot edit this cart rule.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('submitNewVoucher') && isset($order)) { + if ($this->tabAccess['edit'] === '1') { + if (!Tools::getValue('discount_name')) { + $this->errors[] = Tools::displayError('You must specify a name in order to create a new discount.'); + } else { + if ($order->hasInvoice()) { + // If the discount is for only one invoice + if (!Tools::isSubmit('discount_all_invoices')) { + $order_invoice = new OrderInvoice(Tools::getValue('discount_invoice')); + if (!Validate::isLoadedObject($order_invoice)) { + throw new PrestaShopException('Can\'t load Order Invoice object'); + } + } + } + + $cart_rules = array(); + $discount_value = (float)str_replace(',', '.', Tools::getValue('discount_value')); + switch (Tools::getValue('discount_type')) { + // Percent type + case 1: + if ($discount_value < 100) { + if (isset($order_invoice)) { + $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($order_invoice->total_paid_tax_incl * $discount_value / 100, 2); + $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($order_invoice->total_paid_tax_excl * $discount_value / 100, 2); + + // Update OrderInvoice + $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); + } elseif ($order->hasInvoice()) { + $order_invoices_collection = $order->getInvoicesCollection(); + foreach ($order_invoices_collection as $order_invoice) { + /** @var OrderInvoice $order_invoice */ + $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($order_invoice->total_paid_tax_incl * $discount_value / 100, 2); + $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($order_invoice->total_paid_tax_excl * $discount_value / 100, 2); + + // Update OrderInvoice + $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); + } + } else { + $cart_rules[0]['value_tax_incl'] = Tools::ps_round($order->total_paid_tax_incl * $discount_value / 100, 2); + $cart_rules[0]['value_tax_excl'] = Tools::ps_round($order->total_paid_tax_excl * $discount_value / 100, 2); + } + } else { + $this->errors[] = Tools::displayError('The discount value is invalid.'); + } + break; + // Amount type + case 2: + if (isset($order_invoice)) { + if ($discount_value > $order_invoice->total_paid_tax_incl) { + $this->errors[] = Tools::displayError('The discount value is greater than the order invoice total.'); + } else { + $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($discount_value, 2); + $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($discount_value / (1 + ($order->getTaxesAverageUsed() / 100)), 2); + + // Update OrderInvoice + $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); + } + } elseif ($order->hasInvoice()) { + $order_invoices_collection = $order->getInvoicesCollection(); + foreach ($order_invoices_collection as $order_invoice) { + /** @var OrderInvoice $order_invoice */ + if ($discount_value > $order_invoice->total_paid_tax_incl) { + $this->errors[] = Tools::displayError('The discount value is greater than the order invoice total.').$order_invoice->getInvoiceNumberFormatted(Context::getContext()->language->id, (int)$order->id_shop).')'; + } else { + $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($discount_value, 2); + $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($discount_value / (1 + ($order->getTaxesAverageUsed() / 100)), 2); + + // Update OrderInvoice + $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); + } + } + } else { + if ($discount_value > $order->total_paid_tax_incl) { + $this->errors[] = Tools::displayError('The discount value is greater than the order total.'); + } else { + $cart_rules[0]['value_tax_incl'] = Tools::ps_round($discount_value, 2); + $cart_rules[0]['value_tax_excl'] = Tools::ps_round($discount_value / (1 + ($order->getTaxesAverageUsed() / 100)), 2); + } + } + break; + // Free shipping type + case 3: + if (isset($order_invoice)) { + if ($order_invoice->total_shipping_tax_incl > 0) { + $cart_rules[$order_invoice->id]['value_tax_incl'] = $order_invoice->total_shipping_tax_incl; + $cart_rules[$order_invoice->id]['value_tax_excl'] = $order_invoice->total_shipping_tax_excl; + + // Update OrderInvoice + $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); + } + } elseif ($order->hasInvoice()) { + $order_invoices_collection = $order->getInvoicesCollection(); + foreach ($order_invoices_collection as $order_invoice) { + /** @var OrderInvoice $order_invoice */ + if ($order_invoice->total_shipping_tax_incl <= 0) { + continue; + } + $cart_rules[$order_invoice->id]['value_tax_incl'] = $order_invoice->total_shipping_tax_incl; + $cart_rules[$order_invoice->id]['value_tax_excl'] = $order_invoice->total_shipping_tax_excl; + + // Update OrderInvoice + $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); + } + } else { + $cart_rules[0]['value_tax_incl'] = $order->total_shipping_tax_incl; + $cart_rules[0]['value_tax_excl'] = $order->total_shipping_tax_excl; + } + break; + default: + $this->errors[] = Tools::displayError('The discount type is invalid.'); + } + + $res = true; + foreach ($cart_rules as &$cart_rule) { + $cartRuleObj = new CartRule(); + $cartRuleObj->date_from = date('Y-m-d H:i:s', strtotime('-1 hour', strtotime($order->date_add))); + $cartRuleObj->date_to = date('Y-m-d H:i:s', strtotime('+1 hour')); + $cartRuleObj->name[Configuration::get('PS_LANG_DEFAULT')] = Tools::getValue('discount_name'); + $cartRuleObj->quantity = 0; + $cartRuleObj->quantity_per_user = 1; + if (Tools::getValue('discount_type') == 1) { + $cartRuleObj->reduction_percent = $discount_value; + } elseif (Tools::getValue('discount_type') == 2) { + $cartRuleObj->reduction_amount = $cart_rule['value_tax_excl']; + } elseif (Tools::getValue('discount_type') == 3) { + $cartRuleObj->free_shipping = 1; + } + $cartRuleObj->active = 0; + if ($res = $cartRuleObj->add()) { + $cart_rule['id'] = $cartRuleObj->id; + } else { + break; + } + } + + if ($res) { + foreach ($cart_rules as $id_order_invoice => $cart_rule) { + // Create OrderCartRule + $order_cart_rule = new OrderCartRule(); + $order_cart_rule->id_order = $order->id; + $order_cart_rule->id_cart_rule = $cart_rule['id']; + $order_cart_rule->id_order_invoice = $id_order_invoice; + $order_cart_rule->name = Tools::getValue('discount_name'); + $order_cart_rule->value = $cart_rule['value_tax_incl']; + $order_cart_rule->value_tax_excl = $cart_rule['value_tax_excl']; + $res &= $order_cart_rule->add(); + + $order->total_discounts += $order_cart_rule->value; + $order->total_discounts_tax_incl += $order_cart_rule->value; + $order->total_discounts_tax_excl += $order_cart_rule->value_tax_excl; + $order->total_paid -= $order_cart_rule->value; + $order->total_paid_tax_incl -= $order_cart_rule->value; + $order->total_paid_tax_excl -= $order_cart_rule->value_tax_excl; + } + + // Update Order + $res &= $order->update(); + } + + if ($res) { + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); + } else { + $this->errors[] = Tools::displayError('An error occurred during the OrderCartRule creation'); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('sendStateEmail') && Tools::getValue('sendStateEmail') > 0 && Tools::getValue('id_order') > 0) { + if ($this->tabAccess['edit'] === '1') { + $order_state = new OrderState((int)Tools::getValue('sendStateEmail')); + + if (!Validate::isLoadedObject($order_state)) { + $this->errors[] = Tools::displayError('An error occurred while loading order status.'); + } else { + $history = new OrderHistory((int)Tools::getValue('id_order_history')); + + $carrier = new Carrier($order->id_carrier, $order->id_lang); + $templateVars = array(); + if ($order_state->id == Configuration::get('PS_OS_SHIPPING') && $order->shipping_number) { + $templateVars = array('{followup}' => str_replace('@', $order->shipping_number, $carrier->url)); + } + + if ($history->sendEmail($order, $templateVars)) { + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=10&token='.$this->token); + } else { + $this->errors[] = Tools::displayError('An error occurred while sending the e-mail to the customer.'); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + + parent::postProcess(); + } + + public function renderKpis() + { + $time = time(); + $kpis = array(); + + /* The data generation is located in AdminStatsControllerCore */ + + $helper = new HelperKpi(); + $helper->id = 'box-conversion-rate'; + $helper->icon = 'icon-sort-by-attributes-alt'; + //$helper->chart = true; + $helper->color = 'color1'; + $helper->title = $this->l('Conversion Rate', null, null, false); + $helper->subtitle = $this->l('30 days', null, null, false); + if (ConfigurationKPI::get('CONVERSION_RATE') !== false) { + $helper->value = ConfigurationKPI::get('CONVERSION_RATE'); + } + if (ConfigurationKPI::get('CONVERSION_RATE_CHART') !== false) { + $helper->data = ConfigurationKPI::get('CONVERSION_RATE_CHART'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=conversion_rate'; + $helper->refresh = (bool)(ConfigurationKPI::get('CONVERSION_RATE_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-carts'; + $helper->icon = 'icon-shopping-cart'; + $helper->color = 'color2'; + $helper->title = $this->l('Abandoned Carts', null, null, false); + $helper->subtitle = $this->l('Today', null, null, false); + $helper->href = $this->context->link->getAdminLink('AdminCarts').'&action=filterOnlyAbandonedCarts'; + if (ConfigurationKPI::get('ABANDONED_CARTS') !== false) { + $helper->value = ConfigurationKPI::get('ABANDONED_CARTS'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=abandoned_cart'; + $helper->refresh = (bool)(ConfigurationKPI::get('ABANDONED_CARTS_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-average-order'; + $helper->icon = 'icon-money'; + $helper->color = 'color3'; + $helper->title = $this->l('Average Order Value', null, null, false); + $helper->subtitle = $this->l('30 days', null, null, false); + if (ConfigurationKPI::get('AVG_ORDER_VALUE') !== false) { + $helper->value = sprintf($this->l('%s tax excl.'), ConfigurationKPI::get('AVG_ORDER_VALUE')); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=average_order_value'; + $helper->refresh = (bool)(ConfigurationKPI::get('AVG_ORDER_VALUE_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-net-profit-visit'; + $helper->icon = 'icon-user'; + $helper->color = 'color4'; + $helper->title = $this->l('Net Profit per Visit', null, null, false); + $helper->subtitle = $this->l('30 days', null, null, false); + if (ConfigurationKPI::get('NETPROFIT_VISIT') !== false) { + $helper->value = ConfigurationKPI::get('NETPROFIT_VISIT'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=netprofit_visit'; + $helper->refresh = (bool)(ConfigurationKPI::get('NETPROFIT_VISIT_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpiRow(); + $helper->kpis = $kpis; + return $helper->generate(); + } + + public function renderView() + { + $order = new Order(Tools::getValue('id_order')); + if (!Validate::isLoadedObject($order)) { + $this->errors[] = Tools::displayError('The order cannot be found within your database.'); + } + + $customer = new Customer($order->id_customer); + $carrier = new Carrier($order->id_carrier); + $products = $this->getProducts($order); + $currency = new Currency((int)$order->id_currency); + // Carrier module call + $carrier_module_call = null; + if ($carrier->is_module) { + $module = Module::getInstanceByName($carrier->external_module_name); + if (method_exists($module, 'displayInfoByCart')) { + $carrier_module_call = call_user_func(array($module, 'displayInfoByCart'), $order->id_cart); + } + } + + // Retrieve addresses information + $addressInvoice = new Address($order->id_address_invoice, $this->context->language->id); + if (Validate::isLoadedObject($addressInvoice) && $addressInvoice->id_state) { + $invoiceState = new State((int)$addressInvoice->id_state); + } + + if ($order->id_address_invoice == $order->id_address_delivery) { + $addressDelivery = $addressInvoice; + if (isset($invoiceState)) { + $deliveryState = $invoiceState; + } + } else { + $addressDelivery = new Address($order->id_address_delivery, $this->context->language->id); + if (Validate::isLoadedObject($addressDelivery) && $addressDelivery->id_state) { + $deliveryState = new State((int)($addressDelivery->id_state)); + } + } + + $this->toolbar_title = sprintf($this->l('Order #%1$d (%2$s) - %3$s %4$s'), $order->id, $order->reference, $customer->firstname, $customer->lastname); + if (Shop::isFeatureActive()) { + $shop = new Shop((int)$order->id_shop); + $this->toolbar_title .= ' - '.sprintf($this->l('Shop: %s'), $shop->name); + } + + // gets warehouses to ship products, if and only if advanced stock management is activated + $warehouse_list = null; + + $order_details = $order->getOrderDetailList(); + foreach ($order_details as $order_detail) { + $product = new Product($order_detail['product_id']); + + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') + && $product->advanced_stock_management) { + $warehouses = Warehouse::getWarehousesByProductId($order_detail['product_id'], $order_detail['product_attribute_id']); + foreach ($warehouses as $warehouse) { + if (!isset($warehouse_list[$warehouse['id_warehouse']])) { + $warehouse_list[$warehouse['id_warehouse']] = $warehouse; + } + } + } + } + + $payment_methods = array(); + foreach (PaymentModule::getInstalledPaymentModules() as $payment) { + $module = Module::getInstanceByName($payment['name']); + if (Validate::isLoadedObject($module) && $module->active) { + $payment_methods[] = $module->displayName; + } + } + + // display warning if there are products out of stock + $display_out_of_stock_warning = false; + $current_order_state = $order->getCurrentOrderState(); + if (Configuration::get('PS_STOCK_MANAGEMENT') && (!Validate::isLoadedObject($current_order_state) || ($current_order_state->delivery != 1 && $current_order_state->shipped != 1))) { + $display_out_of_stock_warning = true; + } + + // products current stock (from stock_available) + foreach ($products as &$product) { + // Get total customized quantity for current product + $customized_product_quantity = 0; + + if (is_array($product['customizedDatas'])) { + foreach ($product['customizedDatas'] as $customizationPerAddress) { + foreach ($customizationPerAddress as $customizationId => $customization) { + $customized_product_quantity += (int)$customization['quantity']; + } + } + } + + $product['customized_product_quantity'] = $customized_product_quantity; + $product['current_stock'] = StockAvailable::getQuantityAvailableByProduct($product['product_id'], $product['product_attribute_id'], $product['id_shop']); + $resume = OrderSlip::getProductSlipResume($product['id_order_detail']); + $product['quantity_refundable'] = $product['product_quantity'] - $resume['product_quantity']; + $product['amount_refundable'] = $product['total_price_tax_excl'] - $resume['amount_tax_excl']; + $product['amount_refundable_tax_incl'] = $product['total_price_tax_incl'] - $resume['amount_tax_incl']; + $product['amount_refund'] = Tools::displayPrice($resume['amount_tax_incl'], $currency); + $product['refund_history'] = OrderSlip::getProductSlipDetail($product['id_order_detail']); + $product['return_history'] = OrderReturn::getProductReturnDetail($product['id_order_detail']); + + // if the current stock requires a warning + if ($product['current_stock'] == 0 && $display_out_of_stock_warning) { + $this->displayWarning($this->l('This product is out of stock: ').' '.$product['product_name']); + } + if ($product['id_warehouse'] != 0) { + $warehouse = new Warehouse((int)$product['id_warehouse']); + $product['warehouse_name'] = $warehouse->name; + $warehouse_location = WarehouseProductLocation::getProductLocation($product['product_id'], $product['product_attribute_id'], $product['id_warehouse']); + if (!empty($warehouse_location)) { + $product['warehouse_location'] = $warehouse_location; + } else { + $product['warehouse_location'] = false; + } + } else { + $product['warehouse_name'] = '--'; + $product['warehouse_location'] = false; + } + } + + $gender = new Gender((int)$customer->id_gender, $this->context->language->id); + + $history = $order->getHistory($this->context->language->id); + + foreach ($history as &$order_state) { + $order_state['text-color'] = Tools::getBrightness($order_state['color']) < 128 ? 'white' : 'black'; + } + + // Smarty assign + $this->tpl_view_vars = array( + 'order' => $order, + 'cart' => new Cart($order->id_cart), + 'customer' => $customer, + 'gender' => $gender, + 'customer_addresses' => $customer->getAddresses($this->context->language->id), + 'addresses' => array( + 'delivery' => $addressDelivery, + 'deliveryState' => isset($deliveryState) ? $deliveryState : null, + 'invoice' => $addressInvoice, + 'invoiceState' => isset($invoiceState) ? $invoiceState : null + ), + 'customerStats' => $customer->getStats(), + 'products' => $products, + 'discounts' => $order->getCartRules(), + 'orders_total_paid_tax_incl' => $order->getOrdersTotalPaid(), // Get the sum of total_paid_tax_incl of the order with similar reference + 'total_paid' => $order->getTotalPaid(), + 'returns' => OrderReturn::getOrdersReturn($order->id_customer, $order->id), + 'customer_thread_message' => CustomerThread::getCustomerMessages($order->id_customer, null, $order->id), + 'orderMessages' => OrderMessage::getOrderMessages($order->id_lang), + 'messages' => Message::getMessagesByOrderId($order->id, true), + 'carrier' => new Carrier($order->id_carrier), + 'history' => $history, + 'states' => OrderState::getOrderStates($this->context->language->id), + 'warehouse_list' => $warehouse_list, + 'sources' => ConnectionsSource::getOrderSources($order->id), + 'currentState' => $order->getCurrentOrderState(), + 'currency' => new Currency($order->id_currency), + 'currencies' => Currency::getCurrenciesByIdShop($order->id_shop), + 'previousOrder' => $order->getPreviousOrderId(), + 'nextOrder' => $order->getNextOrderId(), + 'current_index' => self::$currentIndex, + 'carrierModuleCall' => $carrier_module_call, + 'iso_code_lang' => $this->context->language->iso_code, + 'id_lang' => $this->context->language->id, + 'can_edit' => ($this->tabAccess['edit'] == 1), + 'current_id_lang' => $this->context->language->id, + 'invoices_collection' => $order->getInvoicesCollection(), + 'not_paid_invoices_collection' => $order->getNotPaidInvoicesCollection(), + 'payment_methods' => $payment_methods, + 'invoice_management_active' => Configuration::get('PS_INVOICE', null, null, $order->id_shop), + 'display_warehouse' => (int)Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'), + 'HOOK_CONTENT_ORDER' => Hook::exec('displayAdminOrderContentOrder', array( + 'order' => $order, + 'products' => $products, + 'customer' => $customer) + ), + 'HOOK_CONTENT_SHIP' => Hook::exec('displayAdminOrderContentShip', array( + 'order' => $order, + 'products' => $products, + 'customer' => $customer) + ), + 'HOOK_TAB_ORDER' => Hook::exec('displayAdminOrderTabOrder', array( + 'order' => $order, + 'products' => $products, + 'customer' => $customer) + ), + 'HOOK_TAB_SHIP' => Hook::exec('displayAdminOrderTabShip', array( + 'order' => $order, + 'products' => $products, + 'customer' => $customer) + ), + ); + + return parent::renderView(); + } + + public function ajaxProcessSearchProducts() + { + Context::getContext()->customer = new Customer((int)Tools::getValue('id_customer')); + $currency = new Currency((int)Tools::getValue('id_currency')); + if ($products = Product::searchByName((int)$this->context->language->id, pSQL(Tools::getValue('product_search')))) { + foreach ($products as &$product) { + // Formatted price + $product['formatted_price'] = Tools::displayPrice(Tools::convertPrice($product['price_tax_incl'], $currency), $currency); + // Concret price + $product['price_tax_incl'] = Tools::ps_round(Tools::convertPrice($product['price_tax_incl'], $currency), 2); + $product['price_tax_excl'] = Tools::ps_round(Tools::convertPrice($product['price_tax_excl'], $currency), 2); + $productObj = new Product((int)$product['id_product'], false, (int)$this->context->language->id); + $combinations = array(); + $attributes = $productObj->getAttributesGroups((int)$this->context->language->id); + + // Tax rate for this customer + if (Tools::isSubmit('id_address')) { + $product['tax_rate'] = $productObj->getTaxesRate(new Address(Tools::getValue('id_address'))); + } + + $product['warehouse_list'] = array(); + + foreach ($attributes as $attribute) { + if (!isset($combinations[$attribute['id_product_attribute']]['attributes'])) { + $combinations[$attribute['id_product_attribute']]['attributes'] = ''; + } + $combinations[$attribute['id_product_attribute']]['attributes'] .= $attribute['attribute_name'].' - '; + $combinations[$attribute['id_product_attribute']]['id_product_attribute'] = $attribute['id_product_attribute']; + $combinations[$attribute['id_product_attribute']]['default_on'] = $attribute['default_on']; + if (!isset($combinations[$attribute['id_product_attribute']]['price'])) { + $price_tax_incl = Product::getPriceStatic((int)$product['id_product'], true, $attribute['id_product_attribute']); + $price_tax_excl = Product::getPriceStatic((int)$product['id_product'], false, $attribute['id_product_attribute']); + $combinations[$attribute['id_product_attribute']]['price_tax_incl'] = Tools::ps_round(Tools::convertPrice($price_tax_incl, $currency), 2); + $combinations[$attribute['id_product_attribute']]['price_tax_excl'] = Tools::ps_round(Tools::convertPrice($price_tax_excl, $currency), 2); + $combinations[$attribute['id_product_attribute']]['formatted_price'] = Tools::displayPrice(Tools::convertPrice($price_tax_excl, $currency), $currency); + } + if (!isset($combinations[$attribute['id_product_attribute']]['qty_in_stock'])) { + $combinations[$attribute['id_product_attribute']]['qty_in_stock'] = StockAvailable::getQuantityAvailableByProduct((int)$product['id_product'], $attribute['id_product_attribute'], (int)$this->context->shop->id); + } + + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && (int)$product['advanced_stock_management'] == 1) { + $product['warehouse_list'][$attribute['id_product_attribute']] = Warehouse::getProductWarehouseList($product['id_product'], $attribute['id_product_attribute']); + } else { + $product['warehouse_list'][$attribute['id_product_attribute']] = array(); + } + + $product['stock'][$attribute['id_product_attribute']] = Product::getRealQuantity($product['id_product'], $attribute['id_product_attribute']); + } + + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && (int)$product['advanced_stock_management'] == 1) { + $product['warehouse_list'][0] = Warehouse::getProductWarehouseList($product['id_product']); + } else { + $product['warehouse_list'][0] = array(); + } + + $product['stock'][0] = StockAvailable::getQuantityAvailableByProduct((int)$product['id_product'], 0, (int)$this->context->shop->id); + + foreach ($combinations as &$combination) { + $combination['attributes'] = rtrim($combination['attributes'], ' - '); + } + $product['combinations'] = $combinations; + + if ($product['customizable']) { + $product_instance = new Product((int)$product['id_product']); + $product['customization_fields'] = $product_instance->getCustomizationFields($this->context->language->id); + } + } + + $to_return = array( + 'products' => $products, + 'found' => true + ); + } else { + $to_return = array('found' => false); + } + + $this->content = Tools::jsonEncode($to_return); + } + + public function ajaxProcessSendMailValidateOrder() + { + if ($this->tabAccess['edit'] === '1') { + $cart = new Cart((int)Tools::getValue('id_cart')); + if (Validate::isLoadedObject($cart)) { + $customer = new Customer((int)$cart->id_customer); + if (Validate::isLoadedObject($customer)) { + $mailVars = array( + '{order_link}' => Context::getContext()->link->getPageLink('order', false, (int)$cart->id_lang, 'step=3&recover_cart='.(int)$cart->id.'&token_cart='.md5(_COOKIE_KEY_.'recover_cart_'.(int)$cart->id)), + '{firstname}' => $customer->firstname, + '{lastname}' => $customer->lastname + ); + if (Mail::Send((int)$cart->id_lang, 'backoffice_order', Mail::l('Process the payment of your order', (int)$cart->id_lang), $mailVars, $customer->email, + $customer->firstname.' '.$customer->lastname, null, null, null, null, _PS_MAIL_DIR_, true, $cart->id_shop)) { + die(Tools::jsonEncode(array('errors' => false, 'result' => $this->l('The email was sent to your customer.')))); + } + } + } + $this->content = Tools::jsonEncode(array('errors' => true, 'result' => $this->l('Error in sending the email to your customer.'))); + } + } + + public function ajaxProcessAddProductOnOrder() + { + // Load object + $order = new Order((int)Tools::getValue('id_order')); + if (!Validate::isLoadedObject($order)) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('The order object cannot be loaded.') + ))); + } + + $old_cart_rules = Context::getContext()->cart->getCartRules(); + + if ($order->hasBeenShipped()) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('You cannot add products to delivered orders. ') + ))); + } + + $product_informations = $_POST['add_product']; + if (isset($_POST['add_invoice'])) { + $invoice_informations = $_POST['add_invoice']; + } else { + $invoice_informations = array(); + } + $product = new Product($product_informations['product_id'], false, $order->id_lang); + if (!Validate::isLoadedObject($product)) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('The product object cannot be loaded.') + ))); + } + + if (isset($product_informations['product_attribute_id']) && $product_informations['product_attribute_id']) { + $combination = new Combination($product_informations['product_attribute_id']); + if (!Validate::isLoadedObject($combination)) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('The combination object cannot be loaded.') + ))); + } + } + + // Total method + $total_method = Cart::BOTH_WITHOUT_SHIPPING; + + // Create new cart + $cart = new Cart(); + $cart->id_shop_group = $order->id_shop_group; + $cart->id_shop = $order->id_shop; + $cart->id_customer = $order->id_customer; + $cart->id_carrier = $order->id_carrier; + $cart->id_address_delivery = $order->id_address_delivery; + $cart->id_address_invoice = $order->id_address_invoice; + $cart->id_currency = $order->id_currency; + $cart->id_lang = $order->id_lang; + $cart->secure_key = $order->secure_key; + + // Save new cart + $cart->add(); + + // Save context (in order to apply cart rule) + $this->context->cart = $cart; + $this->context->customer = new Customer($order->id_customer); + + // always add taxes even if there are not displayed to the customer + $use_taxes = true; + + $initial_product_price_tax_incl = Product::getPriceStatic($product->id, $use_taxes, isset($combination) ? $combination->id : null, 2, null, false, true, 1, + false, $order->id_customer, $cart->id, $order->{Configuration::get('PS_TAX_ADDRESS_TYPE', null, null, $order->id_shop)}); + + // Creating specific price if needed + if ($product_informations['product_price_tax_incl'] != $initial_product_price_tax_incl) { + $specific_price = new SpecificPrice(); + $specific_price->id_shop = 0; + $specific_price->id_shop_group = 0; + $specific_price->id_currency = 0; + $specific_price->id_country = 0; + $specific_price->id_group = 0; + $specific_price->id_customer = $order->id_customer; + $specific_price->id_product = $product->id; + if (isset($combination)) { + $specific_price->id_product_attribute = $combination->id; + } else { + $specific_price->id_product_attribute = 0; + } + $specific_price->price = $product_informations['product_price_tax_excl']; + $specific_price->from_quantity = 1; + $specific_price->reduction = 0; + $specific_price->reduction_type = 'amount'; + $specific_price->reduction_tax = 0; + $specific_price->from = '0000-00-00 00:00:00'; + $specific_price->to = '0000-00-00 00:00:00'; + $specific_price->add(); + } + + // Add product to cart + $update_quantity = $cart->updateQty($product_informations['product_quantity'], $product->id, isset($product_informations['product_attribute_id']) ? $product_informations['product_attribute_id'] : null, + isset($combination) ? $combination->id : null, 'up', 0, new Shop($cart->id_shop)); + + if ($update_quantity < 0) { + // If product has attribute, minimal quantity is set with minimal quantity of attribute + $minimal_quantity = ($product_informations['product_attribute_id']) ? Attribute::getAttributeMinimalQty($product_informations['product_attribute_id']) : $product->minimal_quantity; + die(Tools::jsonEncode(array('error' => sprintf(Tools::displayError('You must add %d minimum quantity', false), $minimal_quantity)))); + } elseif (!$update_quantity) { + die(Tools::jsonEncode(array('error' => Tools::displayError('You already have the maximum quantity available for this product.', false)))); + } + + // If order is valid, we can create a new invoice or edit an existing invoice + if ($order->hasInvoice()) { + $order_invoice = new OrderInvoice($product_informations['invoice']); + // Create new invoice + if ($order_invoice->id == 0) { + // If we create a new invoice, we calculate shipping cost + $total_method = Cart::BOTH; + // Create Cart rule in order to make free shipping + if (isset($invoice_informations['free_shipping']) && $invoice_informations['free_shipping']) { + $cart_rule = new CartRule(); + $cart_rule->id_customer = $order->id_customer; + $cart_rule->name = array( + Configuration::get('PS_LANG_DEFAULT') => $this->l('[Generated] CartRule for Free Shipping') + ); + $cart_rule->date_from = date('Y-m-d H:i:s', time()); + $cart_rule->date_to = date('Y-m-d H:i:s', time() + 24 * 3600); + $cart_rule->quantity = 1; + $cart_rule->quantity_per_user = 1; + $cart_rule->minimum_amount_currency = $order->id_currency; + $cart_rule->reduction_currency = $order->id_currency; + $cart_rule->free_shipping = true; + $cart_rule->active = 1; + $cart_rule->add(); + + // Add cart rule to cart and in order + $cart->addCartRule($cart_rule->id); + $values = array( + 'tax_incl' => $cart_rule->getContextualValue(true), + 'tax_excl' => $cart_rule->getContextualValue(false) + ); + $order->addCartRule($cart_rule->id, $cart_rule->name[Configuration::get('PS_LANG_DEFAULT')], $values); + } + + $order_invoice->id_order = $order->id; + if ($order_invoice->number) { + Configuration::updateValue('PS_INVOICE_START_NUMBER', false, false, null, $order->id_shop); + } else { + $order_invoice->number = Order::getLastInvoiceNumber() + 1; + } + + $invoice_address = new Address((int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE', null, null, $order->id_shop)}); + $carrier = new Carrier((int)$order->id_carrier); + $tax_calculator = $carrier->getTaxCalculator($invoice_address); + + $order_invoice->total_paid_tax_excl = Tools::ps_round((float)$cart->getOrderTotal(false, $total_method), 2); + $order_invoice->total_paid_tax_incl = Tools::ps_round((float)$cart->getOrderTotal($use_taxes, $total_method), 2); + $order_invoice->total_products = (float)$cart->getOrderTotal(false, Cart::ONLY_PRODUCTS); + $order_invoice->total_products_wt = (float)$cart->getOrderTotal($use_taxes, Cart::ONLY_PRODUCTS); + $order_invoice->total_shipping_tax_excl = (float)$cart->getTotalShippingCost(null, false); + $order_invoice->total_shipping_tax_incl = (float)$cart->getTotalShippingCost(); + + $order_invoice->total_wrapping_tax_excl = abs($cart->getOrderTotal(false, Cart::ONLY_WRAPPING)); + $order_invoice->total_wrapping_tax_incl = abs($cart->getOrderTotal($use_taxes, Cart::ONLY_WRAPPING)); + $order_invoice->shipping_tax_computation_method = (int)$tax_calculator->computation_method; + + // Update current order field, only shipping because other field is updated later + $order->total_shipping += $order_invoice->total_shipping_tax_incl; + $order->total_shipping_tax_excl += $order_invoice->total_shipping_tax_excl; + $order->total_shipping_tax_incl += ($use_taxes) ? $order_invoice->total_shipping_tax_incl : $order_invoice->total_shipping_tax_excl; + + $order->total_wrapping += abs($cart->getOrderTotal($use_taxes, Cart::ONLY_WRAPPING)); + $order->total_wrapping_tax_excl += abs($cart->getOrderTotal(false, Cart::ONLY_WRAPPING)); + $order->total_wrapping_tax_incl += abs($cart->getOrderTotal($use_taxes, Cart::ONLY_WRAPPING)); + $order_invoice->add(); + + $order_invoice->saveCarrierTaxCalculator($tax_calculator->getTaxesAmount($order_invoice->total_shipping_tax_excl)); + + $order_carrier = new OrderCarrier(); + $order_carrier->id_order = (int)$order->id; + $order_carrier->id_carrier = (int)$order->id_carrier; + $order_carrier->id_order_invoice = (int)$order_invoice->id; + $order_carrier->weight = (float)$cart->getTotalWeight(); + $order_carrier->shipping_cost_tax_excl = (float)$order_invoice->total_shipping_tax_excl; + $order_carrier->shipping_cost_tax_incl = ($use_taxes) ? (float)$order_invoice->total_shipping_tax_incl : (float)$order_invoice->total_shipping_tax_excl; + $order_carrier->add(); + } + // Update current invoice + else { + $order_invoice->total_paid_tax_excl += Tools::ps_round((float)($cart->getOrderTotal(false, $total_method)), 2); + $order_invoice->total_paid_tax_incl += Tools::ps_round((float)($cart->getOrderTotal($use_taxes, $total_method)), 2); + $order_invoice->total_products += (float)$cart->getOrderTotal(false, Cart::ONLY_PRODUCTS); + $order_invoice->total_products_wt += (float)$cart->getOrderTotal($use_taxes, Cart::ONLY_PRODUCTS); + $order_invoice->update(); + } + } + + // Create Order detail information + $order_detail = new OrderDetail(); + $order_detail->createList($order, $cart, $order->getCurrentOrderState(), $cart->getProducts(), (isset($order_invoice) ? $order_invoice->id : 0), $use_taxes, (int)Tools::getValue('add_product_warehouse')); + + // update totals amount of order + $order->total_products += (float)$cart->getOrderTotal(false, Cart::ONLY_PRODUCTS); + $order->total_products_wt += (float)$cart->getOrderTotal($use_taxes, Cart::ONLY_PRODUCTS); + + $order->total_paid += Tools::ps_round((float)($cart->getOrderTotal(true, $total_method)), 2); + $order->total_paid_tax_excl += Tools::ps_round((float)($cart->getOrderTotal(false, $total_method)), 2); + $order->total_paid_tax_incl += Tools::ps_round((float)($cart->getOrderTotal($use_taxes, $total_method)), 2); + + if (isset($order_invoice) && Validate::isLoadedObject($order_invoice)) { + $order->total_shipping = $order_invoice->total_shipping_tax_incl; + $order->total_shipping_tax_incl = $order_invoice->total_shipping_tax_incl; + $order->total_shipping_tax_excl = $order_invoice->total_shipping_tax_excl; + } + // discount + $order->total_discounts += (float)abs($cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS)); + $order->total_discounts_tax_excl += (float)abs($cart->getOrderTotal(false, Cart::ONLY_DISCOUNTS)); + $order->total_discounts_tax_incl += (float)abs($cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS)); + + // Save changes of order + $order->update(); + + // Update weight SUM + $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); + if (Validate::isLoadedObject($order_carrier)) { + $order_carrier->weight = (float)$order->getTotalWeight(); + if ($order_carrier->update()) { + $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); + } + } + + // Update Tax lines + $order_detail->updateTaxAmount($order); + + // Delete specific price if exists + if (isset($specific_price)) { + $specific_price->delete(); + } + + $products = $this->getProducts($order); + + // Get the last product + $product = end($products); + $resume = OrderSlip::getProductSlipResume((int)$product['id_order_detail']); + $product['quantity_refundable'] = $product['product_quantity'] - $resume['product_quantity']; + $product['amount_refundable'] = $product['total_price_tax_excl'] - $resume['amount_tax_excl']; + $product['amount_refund'] = Tools::displayPrice($resume['amount_tax_incl']); + $product['return_history'] = OrderReturn::getProductReturnDetail((int)$product['id_order_detail']); + $product['refund_history'] = OrderSlip::getProductSlipDetail((int)$product['id_order_detail']); + if ($product['id_warehouse'] != 0) { + $warehouse = new Warehouse((int)$product['id_warehouse']); + $product['warehouse_name'] = $warehouse->name; + $warehouse_location = WarehouseProductLocation::getProductLocation($product['product_id'], $product['product_attribute_id'], $product['id_warehouse']); + if (!empty($warehouse_location)) { + $product['warehouse_location'] = $warehouse_location; + } else { + $product['warehouse_location'] = false; + } + } else { + $product['warehouse_name'] = '--'; + $product['warehouse_location'] = false; + } + + // Get invoices collection + $invoice_collection = $order->getInvoicesCollection(); + + $invoice_array = array(); + foreach ($invoice_collection as $invoice) { + /** @var OrderInvoice $invoice */ + $invoice->name = $invoice->getInvoiceNumberFormatted(Context::getContext()->language->id, (int)$order->id_shop); + $invoice_array[] = $invoice; + } + + // Assign to smarty informations in order to show the new product line + $this->context->smarty->assign(array( + 'product' => $product, + 'order' => $order, + 'currency' => new Currency($order->id_currency), + 'can_edit' => $this->tabAccess['edit'], + 'invoices_collection' => $invoice_collection, + 'current_id_lang' => Context::getContext()->language->id, + 'link' => Context::getContext()->link, + 'current_index' => self::$currentIndex, + 'display_warehouse' => (int)Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') + )); + + $this->sendChangedNotification($order); + $new_cart_rules = Context::getContext()->cart->getCartRules(); + sort($old_cart_rules); + sort($new_cart_rules); + $result = array_diff($new_cart_rules, $old_cart_rules); + $refresh = false; + + $res = true; + foreach ($result as $cart_rule) { + $refresh = true; + // Create OrderCartRule + $rule = new CartRule($cart_rule['id_cart_rule']); + $values = array( + 'tax_incl' => $rule->getContextualValue(true), + 'tax_excl' => $rule->getContextualValue(false) + ); + $order_cart_rule = new OrderCartRule(); + $order_cart_rule->id_order = $order->id; + $order_cart_rule->id_cart_rule = $cart_rule['id_cart_rule']; + $order_cart_rule->id_order_invoice = $order_invoice->id; + $order_cart_rule->name = $cart_rule['name']; + $order_cart_rule->value = $values['tax_incl']; + $order_cart_rule->value_tax_excl = $values['tax_excl']; + $res &= $order_cart_rule->add(); + + $order->total_discounts += $order_cart_rule->value; + $order->total_discounts_tax_incl += $order_cart_rule->value; + $order->total_discounts_tax_excl += $order_cart_rule->value_tax_excl; + $order->total_paid -= $order_cart_rule->value; + $order->total_paid_tax_incl -= $order_cart_rule->value; + $order->total_paid_tax_excl -= $order_cart_rule->value_tax_excl; + } + + // Update Order + $res &= $order->update(); + + + die(Tools::jsonEncode(array( + 'result' => true, + 'view' => $this->createTemplate('_product_line.tpl')->fetch(), + 'can_edit' => $this->tabAccess['add'], + 'order' => $order, + 'invoices' => $invoice_array, + 'documents_html' => $this->createTemplate('_documents.tpl')->fetch(), + 'shipping_html' => $this->createTemplate('_shipping.tpl')->fetch(), + 'discount_form_html' => $this->createTemplate('_discount_form.tpl')->fetch(), + 'refresh' => $refresh + ))); + } + + public function sendChangedNotification(Order $order = null) + { + if (is_null($order)) { + $order = new Order(Tools::getValue('id_order')); + } + + Hook::exec('actionOrderEdited', array('order' => $order)); + } + + public function ajaxProcessLoadProductInformation() + { + $order_detail = new OrderDetail(Tools::getValue('id_order_detail')); + if (!Validate::isLoadedObject($order_detail)) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('The OrderDetail object cannot be loaded.') + ))); + } + + $product = new Product($order_detail->product_id); + if (!Validate::isLoadedObject($product)) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('The product object cannot be loaded.') + ))); + } + + $address = new Address(Tools::getValue('id_address')); + if (!Validate::isLoadedObject($address)) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('The address object cannot be loaded.') + ))); + } + + die(Tools::jsonEncode(array( + 'result' => true, + 'product' => $product, + 'tax_rate' => $product->getTaxesRate($address), + 'price_tax_incl' => Product::getPriceStatic($product->id, true, $order_detail->product_attribute_id, 2), + 'price_tax_excl' => Product::getPriceStatic($product->id, false, $order_detail->product_attribute_id, 2), + 'reduction_percent' => $order_detail->reduction_percent + ))); + } + + public function ajaxProcessEditProductOnOrder() + { + // Return value + $res = true; + + $order = new Order((int)Tools::getValue('id_order')); + $order_detail = new OrderDetail((int)Tools::getValue('product_id_order_detail')); + if (Tools::isSubmit('product_invoice')) { + $order_invoice = new OrderInvoice((int)Tools::getValue('product_invoice')); + } + + // Check fields validity + $this->doEditProductValidation($order_detail, $order, isset($order_invoice) ? $order_invoice : null); + + // If multiple product_quantity, the order details concern a product customized + $product_quantity = 0; + if (is_array(Tools::getValue('product_quantity'))) { + foreach (Tools::getValue('product_quantity') as $id_customization => $qty) { + // Update quantity of each customization + Db::getInstance()->update('customization', array('quantity' => (int)$qty), 'id_customization = '.(int)$id_customization); + // Calculate the real quantity of the product + $product_quantity += $qty; + } + } else { + $product_quantity = Tools::getValue('product_quantity'); + } + + $product_price_tax_incl = Tools::ps_round(Tools::getValue('product_price_tax_incl'), 2); + $product_price_tax_excl = Tools::ps_round(Tools::getValue('product_price_tax_excl'), 2); + $total_products_tax_incl = $product_price_tax_incl * $product_quantity; + $total_products_tax_excl = $product_price_tax_excl * $product_quantity; + + // Calculate differences of price (Before / After) + $diff_price_tax_incl = $total_products_tax_incl - $order_detail->total_price_tax_incl; + $diff_price_tax_excl = $total_products_tax_excl - $order_detail->total_price_tax_excl; + + // Apply change on OrderInvoice + if (isset($order_invoice)) { + // If OrderInvoice to use is different, we update the old invoice and new invoice + if ($order_detail->id_order_invoice != $order_invoice->id) { + $old_order_invoice = new OrderInvoice($order_detail->id_order_invoice); + // We remove cost of products + $old_order_invoice->total_products -= $order_detail->total_price_tax_excl; + $old_order_invoice->total_products_wt -= $order_detail->total_price_tax_incl; + + $old_order_invoice->total_paid_tax_excl -= $order_detail->total_price_tax_excl; + $old_order_invoice->total_paid_tax_incl -= $order_detail->total_price_tax_incl; + + $res &= $old_order_invoice->update(); + + $order_invoice->total_products += $order_detail->total_price_tax_excl; + $order_invoice->total_products_wt += $order_detail->total_price_tax_incl; + + $order_invoice->total_paid_tax_excl += $order_detail->total_price_tax_excl; + $order_invoice->total_paid_tax_incl += $order_detail->total_price_tax_incl; + + $order_detail->id_order_invoice = $order_invoice->id; + } + } + + if ($diff_price_tax_incl != 0 && $diff_price_tax_excl != 0) { + $order_detail->unit_price_tax_excl = $product_price_tax_excl; + $order_detail->unit_price_tax_incl = $product_price_tax_incl; + + $order_detail->total_price_tax_incl += $diff_price_tax_incl; + $order_detail->total_price_tax_excl += $diff_price_tax_excl; + + if (isset($order_invoice)) { + // Apply changes on OrderInvoice + $order_invoice->total_products += $diff_price_tax_excl; + $order_invoice->total_products_wt += $diff_price_tax_incl; + + $order_invoice->total_paid_tax_excl += $diff_price_tax_excl; + $order_invoice->total_paid_tax_incl += $diff_price_tax_incl; + } + + // Apply changes on Order + $order = new Order($order_detail->id_order); + $order->total_products += $diff_price_tax_excl; + $order->total_products_wt += $diff_price_tax_incl; + + $order->total_paid += $diff_price_tax_incl; + $order->total_paid_tax_excl += $diff_price_tax_excl; + $order->total_paid_tax_incl += $diff_price_tax_incl; + + $res &= $order->update(); + } + + $old_quantity = $order_detail->product_quantity; + + $order_detail->product_quantity = $product_quantity; + $order_detail->reduction_percent = 0; + + // update taxes + $res &= $order_detail->updateTaxAmount($order); + + // Save order detail + $res &= $order_detail->update(); + + // Update weight SUM + $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); + if (Validate::isLoadedObject($order_carrier)) { + $order_carrier->weight = (float)$order->getTotalWeight(); + $res &= $order_carrier->update(); + if ($res) { + $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); + } + } + + // Save order invoice + if (isset($order_invoice)) { + $res &= $order_invoice->update(); + } + + // Update product available quantity + StockAvailable::updateQuantity($order_detail->product_id, $order_detail->product_attribute_id, ($old_quantity - $order_detail->product_quantity), $order->id_shop); + + $products = $this->getProducts($order); + // Get the last product + $product = $products[$order_detail->id]; + $resume = OrderSlip::getProductSlipResume($order_detail->id); + $product['quantity_refundable'] = $product['product_quantity'] - $resume['product_quantity']; + $product['amount_refundable'] = $product['total_price_tax_excl'] - $resume['amount_tax_excl']; + $product['amount_refund'] = Tools::displayPrice($resume['amount_tax_incl']); + $product['refund_history'] = OrderSlip::getProductSlipDetail($order_detail->id); + if ($product['id_warehouse'] != 0) { + $warehouse = new Warehouse((int)$product['id_warehouse']); + $product['warehouse_name'] = $warehouse->name; + $warehouse_location = WarehouseProductLocation::getProductLocation($product['product_id'], $product['product_attribute_id'], $product['id_warehouse']); + if (!empty($warehouse_location)) { + $product['warehouse_location'] = $warehouse_location; + } else { + $product['warehouse_location'] = false; + } + } else { + $product['warehouse_name'] = '--'; + $product['warehouse_location'] = false; + } + + // Get invoices collection + $invoice_collection = $order->getInvoicesCollection(); + + $invoice_array = array(); + foreach ($invoice_collection as $invoice) { + /** @var OrderInvoice $invoice */ + $invoice->name = $invoice->getInvoiceNumberFormatted(Context::getContext()->language->id, (int)$order->id_shop); + $invoice_array[] = $invoice; + } + + // Assign to smarty informations in order to show the new product line + $this->context->smarty->assign(array( + 'product' => $product, + 'order' => $order, + 'currency' => new Currency($order->id_currency), + 'can_edit' => $this->tabAccess['edit'], + 'invoices_collection' => $invoice_collection, + 'current_id_lang' => Context::getContext()->language->id, + 'link' => Context::getContext()->link, + 'current_index' => self::$currentIndex, + 'display_warehouse' => (int)Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') + )); + + if (!$res) { + die(Tools::jsonEncode(array( + 'result' => $res, + 'error' => Tools::displayError('An error occurred while editing the product line.') + ))); + } + + + if (is_array(Tools::getValue('product_quantity'))) { + $view = $this->createTemplate('_customized_data.tpl')->fetch(); + } else { + $view = $this->createTemplate('_product_line.tpl')->fetch(); + } + + $this->sendChangedNotification($order); + + die(Tools::jsonEncode(array( + 'result' => $res, + 'view' => $view, + 'can_edit' => $this->tabAccess['add'], + 'invoices_collection' => $invoice_collection, + 'order' => $order, + 'invoices' => $invoice_array, + 'documents_html' => $this->createTemplate('_documents.tpl')->fetch(), + 'shipping_html' => $this->createTemplate('_shipping.tpl')->fetch(), + 'customized_product' => is_array(Tools::getValue('product_quantity')) + ))); + } + + public function ajaxProcessDeleteProductLine() + { + $res = true; + + $order_detail = new OrderDetail((int)Tools::getValue('id_order_detail')); + $order = new Order((int)Tools::getValue('id_order')); + + $this->doDeleteProductLineValidation($order_detail, $order); + + // Update OrderInvoice of this OrderDetail + if ($order_detail->id_order_invoice != 0) { + $order_invoice = new OrderInvoice($order_detail->id_order_invoice); + $order_invoice->total_paid_tax_excl -= $order_detail->total_price_tax_excl; + $order_invoice->total_paid_tax_incl -= $order_detail->total_price_tax_incl; + $order_invoice->total_products -= $order_detail->total_price_tax_excl; + $order_invoice->total_products_wt -= $order_detail->total_price_tax_incl; + $res &= $order_invoice->update(); + } + + // Update Order + $order->total_paid -= $order_detail->total_price_tax_incl; + $order->total_paid_tax_incl -= $order_detail->total_price_tax_incl; + $order->total_paid_tax_excl -= $order_detail->total_price_tax_excl; + $order->total_products -= $order_detail->total_price_tax_excl; + $order->total_products_wt -= $order_detail->total_price_tax_incl; + + $res &= $order->update(); + + // Reinject quantity in stock + $this->reinjectQuantity($order_detail, $order_detail->product_quantity, true); + + // Update weight SUM + $order_carrier = new OrderCarrier((int)$order->getIdOrderCarrier()); + if (Validate::isLoadedObject($order_carrier)) { + $order_carrier->weight = (float)$order->getTotalWeight(); + $res &= $order_carrier->update(); + if ($res) { + $order->weight = sprintf("%.3f ".Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight); + } + } + + if (!$res) { + die(Tools::jsonEncode(array( + 'result' => $res, + 'error' => Tools::displayError('An error occurred while attempting to delete the product line.') + ))); + } + + // Get invoices collection + $invoice_collection = $order->getInvoicesCollection(); + + $invoice_array = array(); + foreach ($invoice_collection as $invoice) { + /** @var OrderInvoice $invoice */ + $invoice->name = $invoice->getInvoiceNumberFormatted(Context::getContext()->language->id, (int)$order->id_shop); + $invoice_array[] = $invoice; + } + + // Assign to smarty informations in order to show the new product line + $this->context->smarty->assign(array( + 'order' => $order, + 'currency' => new Currency($order->id_currency), + 'invoices_collection' => $invoice_collection, + 'current_id_lang' => Context::getContext()->language->id, + 'link' => Context::getContext()->link, + 'current_index' => self::$currentIndex + )); + + $this->sendChangedNotification($order); + + die(Tools::jsonEncode(array( + 'result' => $res, + 'order' => $order, + 'invoices' => $invoice_array, + 'documents_html' => $this->createTemplate('_documents.tpl')->fetch(), + 'shipping_html' => $this->createTemplate('_shipping.tpl')->fetch() + ))); + } + + protected function doEditProductValidation(OrderDetail $order_detail, Order $order, OrderInvoice $order_invoice = null) + { + if (!Validate::isLoadedObject($order_detail)) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('The Order Detail object could not be loaded.') + ))); + } + + if (!empty($order_invoice) && !Validate::isLoadedObject($order_invoice)) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('The invoice object cannot be loaded.') + ))); + } + + if (!Validate::isLoadedObject($order)) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('The order object cannot be loaded.') + ))); + } + + if ($order_detail->id_order != $order->id) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('You cannot edit the order detail for this order.') + ))); + } + + // We can't edit a delivered order + if ($order->hasBeenDelivered()) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('You cannot edit a delivered order.') + ))); + } + + if (!empty($order_invoice) && $order_invoice->id_order != Tools::getValue('id_order')) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('You cannot use this invoice for the order') + ))); + } + + // Clean price + $product_price_tax_incl = str_replace(',', '.', Tools::getValue('product_price_tax_incl')); + $product_price_tax_excl = str_replace(',', '.', Tools::getValue('product_price_tax_excl')); + + if (!Validate::isPrice($product_price_tax_incl) || !Validate::isPrice($product_price_tax_excl)) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Invalid price') + ))); + } + + if (!is_array(Tools::getValue('product_quantity')) && !Validate::isUnsignedInt(Tools::getValue('product_quantity'))) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Invalid quantity') + ))); + } elseif (is_array(Tools::getValue('product_quantity'))) { + foreach (Tools::getValue('product_quantity') as $qty) { + if (!Validate::isUnsignedInt($qty)) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Invalid quantity') + ))); + } + } + } + } + + protected function doDeleteProductLineValidation(OrderDetail $order_detail, Order $order) + { + if (!Validate::isLoadedObject($order_detail)) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('The Order Detail object could not be loaded.') + ))); + } + + if (!Validate::isLoadedObject($order)) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('The order object cannot be loaded.') + ))); + } + + if ($order_detail->id_order != $order->id) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('You cannot delete the order detail.') + ))); + } + + // We can't edit a delivered order + if ($order->hasBeenDelivered()) { + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('You cannot edit a delivered order.') + ))); + } + } + + /** + * @param Order $order + * @return array + */ + protected function getProducts($order) + { + $products = $order->getProducts(); + + foreach ($products as &$product) { + if ($product['image'] != null) { + $name = 'product_mini_'.(int)$product['product_id'].(isset($product['product_attribute_id']) ? '_'.(int)$product['product_attribute_id'] : '').'.jpg'; + // generate image cache, only for back office + $product['image_tag'] = ImageManager::thumbnail(_PS_IMG_DIR_.'p/'.$product['image']->getExistingImgPath().'.jpg', $name, 45, 'jpg'); + if (file_exists(_PS_TMP_IMG_DIR_.$name)) { + $product['image_size'] = getimagesize(_PS_TMP_IMG_DIR_.$name); + } else { + $product['image_size'] = false; + } + } + } + + ksort($products); + + return $products; + } + + /** + * @param OrderDetail $order_detail + * @param int $qty_cancel_product + * @param bool $delete + */ + protected function reinjectQuantity($order_detail, $qty_cancel_product, $delete = false) + { + // Reinject product + $reinjectable_quantity = (int)$order_detail->product_quantity - (int)$order_detail->product_quantity_reinjected; + $quantity_to_reinject = $qty_cancel_product > $reinjectable_quantity ? $reinjectable_quantity : $qty_cancel_product; + // @since 1.5.0 : Advanced Stock Management + $product_to_inject = new Product($order_detail->product_id, false, (int)$this->context->language->id, (int)$order_detail->id_shop); + + $product = new Product($order_detail->product_id, false, (int)$this->context->language->id, (int)$order_detail->id_shop); + + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management && $order_detail->id_warehouse != 0) { + $manager = StockManagerFactory::getManager(); + $movements = StockMvt::getNegativeStockMvts( + $order_detail->id_order, + $order_detail->product_id, + $order_detail->product_attribute_id, + $quantity_to_reinject + ); + $left_to_reinject = $quantity_to_reinject; + foreach ($movements as $movement) { + if ($left_to_reinject > $movement['physical_quantity']) { + $quantity_to_reinject = $movement['physical_quantity']; + } + + $left_to_reinject -= $quantity_to_reinject; + if (Pack::isPack((int)$product->id)) { + // Gets items + if ($product->pack_stock_type == 1 || $product->pack_stock_type == 2 || ($product->pack_stock_type == 3 && Configuration::get('PS_PACK_STOCK_TYPE') > 0)) { + $products_pack = Pack::getItems((int)$product->id, (int)Configuration::get('PS_LANG_DEFAULT')); + // Foreach item + foreach ($products_pack as $product_pack) { + if ($product_pack->advanced_stock_management == 1) { + $manager->addProduct( + $product_pack->id, + $product_pack->id_pack_product_attribute, + new Warehouse($movement['id_warehouse']), + $product_pack->pack_quantity * $quantity_to_reinject, + null, + $movement['price_te'], + true + ); + } + } + } + if ($product->pack_stock_type == 0 || $product->pack_stock_type == 2 || + ($product->pack_stock_type == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 0 || Configuration::get('PS_PACK_STOCK_TYPE') == 2))) { + $manager->addProduct( + $order_detail->product_id, + $order_detail->product_attribute_id, + new Warehouse($movement['id_warehouse']), + $quantity_to_reinject, + null, + $movement['price_te'], + true + ); + } + } else { + $manager->addProduct( + $order_detail->product_id, + $order_detail->product_attribute_id, + new Warehouse($movement['id_warehouse']), + $quantity_to_reinject, + null, + $movement['price_te'], + true + ); + } + } + + $id_product = $order_detail->product_id; + if ($delete) { + $order_detail->delete(); + } + StockAvailable::synchronize($id_product); + } elseif ($order_detail->id_warehouse == 0) { + StockAvailable::updateQuantity( + $order_detail->product_id, + $order_detail->product_attribute_id, + $quantity_to_reinject, + $order_detail->id_shop + ); + + if ($delete) { + $order_detail->delete(); + } + } else { + $this->errors[] = Tools::displayError('This product cannot be re-stocked.'); + } + } + + /** + * @param OrderInvoice $order_invoice + * @param float $value_tax_incl + * @param float $value_tax_excl + */ + protected function applyDiscountOnInvoice($order_invoice, $value_tax_incl, $value_tax_excl) + { + // Update OrderInvoice + $order_invoice->total_discount_tax_incl += $value_tax_incl; + $order_invoice->total_discount_tax_excl += $value_tax_excl; + $order_invoice->total_paid_tax_incl -= $value_tax_incl; + $order_invoice->total_paid_tax_excl -= $value_tax_excl; + $order_invoice->update(); + } + + public function ajaxProcessChangePaymentMethod() + { + $customer = new Customer(Tools::getValue('id_customer')); + $modules = Module::getAuthorizedModules($customer->id_default_group); + $authorized_modules = array(); + + if (!Validate::isLoadedObject($customer) || !is_array($modules)) { + die(Tools::jsonEncode(array('result' => false))); + } + + foreach ($modules as $module) { + $authorized_modules[] = (int)$module['id_module']; + } + + $payment_modules = array(); + + foreach (PaymentModule::getInstalledPaymentModules() as $p_module) { + if (in_array((int)$p_module['id_module'], $authorized_modules)) { + $payment_modules[] = Module::getInstanceById((int)$p_module['id_module']); + } + } + + $this->context->smarty->assign(array( + 'payment_modules' => $payment_modules, + )); + + die(Tools::jsonEncode(array( + 'result' => true, + 'view' => $this->createTemplate('_select_payment.tpl')->fetch(), + ))); + } } diff --git a/controllers/admin/AdminOutstandingController.php b/controllers/admin/AdminOutstandingController.php index 5cedcfb1..b112433a 100644 --- a/controllers/admin/AdminOutstandingController.php +++ b/controllers/admin/AdminOutstandingController.php @@ -29,145 +29,149 @@ */ class AdminOutstandingControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'order_invoice'; - $this->className = 'OrderInvoice'; - $this->addRowAction('view'); + public function __construct() + { + $this->bootstrap = true; + $this->table = 'order_invoice'; + $this->className = 'OrderInvoice'; + $this->addRowAction('view'); - $this->context = Context::getContext(); + $this->context = Context::getContext(); - $this->_select = '`id_order_invoice` AS `id_invoice`, + $this->_select = '`id_order_invoice` AS `id_invoice`, `id_order_invoice` AS `outstanding`, CONCAT(LEFT(c.`firstname`, 1), \'. \', c.`lastname`) AS `customer`, c.`outstanding_allow_amount`, r.`color`, rl.`name` AS `risk`'; - $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'orders` o ON (o.`id_order` = a.`id_order`) + $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'orders` o ON (o.`id_order` = a.`id_order`) LEFT JOIN `'._DB_PREFIX_.'customer` c ON (c.`id_customer` = o.`id_customer`) LEFT JOIN `'._DB_PREFIX_.'risk` r ON (r.`id_risk` = c.`id_risk`) LEFT JOIN `'._DB_PREFIX_.'risk_lang` rl ON (r.`id_risk` = rl.`id_risk` AND rl.`id_lang` = '.(int)$this->context->language->id.')'; - $this->_where = 'AND number > 0'; - $this->_use_found_rows = false; + $this->_where = 'AND number > 0'; + $this->_use_found_rows = false; - $risks = array(); - foreach (Risk::getRisks() as $risk) - { - /** @var Risk $risk */ - $risks[$risk->id] = $risk->name; - } + $risks = array(); + foreach (Risk::getRisks() as $risk) { + /** @var Risk $risk */ + $risks[$risk->id] = $risk->name; + } - $this->fields_list = array( - 'number' => array( - 'title' => $this->l('Invoice') - ), - 'date_add' => array( - 'title' => $this->l('Date'), - 'type' => 'date', - 'align' => 'right', - 'filter_key' => 'a!date_add' - ), - 'customer' => array( - 'title' => $this->l('Customer'), - 'filter_key' => 'customer', - 'tmpTableFilter' => true - ), - 'company' => array( - 'title' => $this->l('Company'), - 'align' => 'center' - ), - 'risk' => array( - 'title' => $this->l('Risk'), - 'align' => 'center', - 'orderby' => false, - 'type' => 'select', - 'color' => 'color', - 'list' => $risks, - 'filter_key' => 'r!id_risk', - 'filter_type' => 'int' - ), - 'outstanding_allow_amount' => array( - 'title' => $this->l('Outstanding Allowance'), - 'align' => 'center', - 'prefix' => '<b>', - 'suffix' => '</b>', - 'type' => 'price' - ), - 'outstanding' => array( - 'title' => $this->l('Current Outstanding'), - 'align' => 'center', - 'callback' => 'printOutstandingCalculation', - 'orderby' => false, - 'search' => false - ), - 'id_invoice' => array( - 'title' => $this->l('Invoice'), - 'align' => 'center', - 'callback' => 'printPDFIcons', - 'orderby' => false, - 'search' => false - ) - ); + $this->fields_list = array( + 'number' => array( + 'title' => $this->l('Invoice') + ), + 'date_add' => array( + 'title' => $this->l('Date'), + 'type' => 'date', + 'align' => 'right', + 'filter_key' => 'a!date_add' + ), + 'customer' => array( + 'title' => $this->l('Customer'), + 'filter_key' => 'customer', + 'tmpTableFilter' => true + ), + 'company' => array( + 'title' => $this->l('Company'), + 'align' => 'center' + ), + 'risk' => array( + 'title' => $this->l('Risk'), + 'align' => 'center', + 'orderby' => false, + 'type' => 'select', + 'color' => 'color', + 'list' => $risks, + 'filter_key' => 'r!id_risk', + 'filter_type' => 'int' + ), + 'outstanding_allow_amount' => array( + 'title' => $this->l('Outstanding Allowance'), + 'align' => 'center', + 'prefix' => '<b>', + 'suffix' => '</b>', + 'type' => 'price' + ), + 'outstanding' => array( + 'title' => $this->l('Current Outstanding'), + 'align' => 'center', + 'callback' => 'printOutstandingCalculation', + 'orderby' => false, + 'search' => false + ), + 'id_invoice' => array( + 'title' => $this->l('Invoice'), + 'align' => 'center', + 'callback' => 'printPDFIcons', + 'orderby' => false, + 'search' => false + ) + ); - parent::__construct(); - } + parent::__construct(); + } - /** - * Toolbar initialisation - * @return bool Force true (Hide New button) - */ - public function initToolbar() - { - return true; - } + /** + * Toolbar initialisation + * @return bool Force true (Hide New button) + */ + public function initToolbar() + { + return true; + } - /** - * Column callback for print PDF incon - * @param $id_invoice integer Invoice ID - * @param $tr array Row data - * @return string HTML content - */ - public function printPDFIcons($id_invoice, $tr) - { - $this->context->smarty->assign(array( - 'id_invoice' => $id_invoice - )); + /** + * Column callback for print PDF incon + * @param $id_invoice integer Invoice ID + * @param $tr array Row data + * @return string HTML content + */ + public function printPDFIcons($id_invoice, $tr) + { + $this->context->smarty->assign(array( + 'id_invoice' => $id_invoice + )); - return $this->createTemplate('_print_pdf_icon.tpl')->fetch(); - } + return $this->createTemplate('_print_pdf_icon.tpl')->fetch(); + } - public function printOutstandingCalculation($id_invoice, $tr) - { - $order_invoice = new OrderInvoice($id_invoice); - if (!Validate::isLoadedObject($order_invoice)) - throw new PrestaShopException('object OrderInvoice cannot be loaded'); - $order = new Order($order_invoice->id_order); - if (!Validate::isLoadedObject($order)) - throw new PrestaShopException('object Order cannot be loaded'); - $customer = new Customer((int)$order->id_customer); - if (!Validate::isLoadedObject($order_invoice)) - throw new PrestaShopException('object Customer cannot be loaded'); + public function printOutstandingCalculation($id_invoice, $tr) + { + $order_invoice = new OrderInvoice($id_invoice); + if (!Validate::isLoadedObject($order_invoice)) { + throw new PrestaShopException('object OrderInvoice cannot be loaded'); + } + $order = new Order($order_invoice->id_order); + if (!Validate::isLoadedObject($order)) { + throw new PrestaShopException('object Order cannot be loaded'); + } + $customer = new Customer((int)$order->id_customer); + if (!Validate::isLoadedObject($order_invoice)) { + throw new PrestaShopException('object Customer cannot be loaded'); + } - return '<b>'.Tools::displayPrice($customer->getOutstanding(), Context::getContext()->currency).'</b>'; - } + return '<b>'.Tools::displayPrice($customer->getOutstanding(), Context::getContext()->currency).'</b>'; + } - /** - * View render - * @throws PrestaShopException Invalid objects - */ - public function renderView() - { - $order_invoice = new OrderInvoice((int)Tools::getValue('id_order_invoice')); - if (!Validate::isLoadedObject($order_invoice)) - throw new PrestaShopException('object OrderInvoice cannot be loaded'); - $order = new Order($order_invoice->id_order); - if (!Validate::isLoadedObject($order)) - throw new PrestaShopException('object Order cannot be loaded'); + /** + * View render + * @throws PrestaShopException Invalid objects + */ + public function renderView() + { + $order_invoice = new OrderInvoice((int)Tools::getValue('id_order_invoice')); + if (!Validate::isLoadedObject($order_invoice)) { + throw new PrestaShopException('object OrderInvoice cannot be loaded'); + } + $order = new Order($order_invoice->id_order); + if (!Validate::isLoadedObject($order)) { + throw new PrestaShopException('object Order cannot be loaded'); + } - $link = $this->context->link->getAdminLink('AdminOrders'); - $link .= '&vieworder&id_order='.$order->id; - $this->redirect_after = $link; - $this->redirect(); - } + $link = $this->context->link->getAdminLink('AdminOrders'); + $link .= '&vieworder&id_order='.$order->id; + $this->redirect_after = $link; + $this->redirect(); + } } diff --git a/controllers/admin/AdminPPreferencesController.php b/controllers/admin/AdminPPreferencesController.php index dddfe90a..19810285 100644 --- a/controllers/admin/AdminPPreferencesController.php +++ b/controllers/admin/AdminPPreferencesController.php @@ -29,301 +29,297 @@ */ class AdminPPreferencesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->className = 'Configuration'; - $this->table = 'configuration'; + public function __construct() + { + $this->bootstrap = true; + $this->className = 'Configuration'; + $this->table = 'configuration'; - parent::__construct(); + parent::__construct(); - $warehouse_list = Warehouse::getWarehouses(); - $warehouse_no = array(array('id_warehouse' => 0,'name' => $this->l('No default warehouse (default setting)'))); - $warehouse_list = array_merge($warehouse_no, $warehouse_list); + $warehouse_list = Warehouse::getWarehouses(); + $warehouse_no = array(array('id_warehouse' => 0,'name' => $this->l('No default warehouse (default setting)'))); + $warehouse_list = array_merge($warehouse_no, $warehouse_list); - $this->fields_options = array( - 'products' => array( - 'title' => $this->l('Products (general)'), - 'fields' => array( - 'PS_CATALOG_MODE' => array( - 'title' => $this->l('Catalog mode'), - 'hint' => $this->l('When active, all shopping features will be disabled.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'required' => false, - 'type' => 'bool' - ), - 'PS_COMPARATOR_MAX_ITEM' => array( - 'title' => $this->l('Product comparison'), - 'hint' => $this->l('Set the maximum number of products that can be selected for comparison. Set to "0" to disable this feature.'), - 'validation' => 'isUnsignedId', - 'required' => true, - 'cast' => 'intval', - 'type' => 'text' - ), - 'PS_NB_DAYS_NEW_PRODUCT' => array( - 'title' => $this->l('Number of days for which the product is considered \'new\''), - 'validation' => 'isUnsignedInt', - 'cast' => 'intval', - 'type' => 'text' - ), - 'PS_CART_REDIRECT' => array( - 'title' => $this->l('Redirect after adding product to cart'), - 'hint' => $this->l('Only for non-AJAX versions of the cart.'), - 'cast' => 'intval', - 'show' => true, - 'required' => false, - 'type' => 'radio', - 'validation' => 'isBool', - 'choices' => array( - 0 => $this->l('Previous page'), - 1 => $this->l('Cart summary') - ) - ), - 'PS_PRODUCT_SHORT_DESC_LIMIT' => array( - 'title' => $this->l('Max size of short description'), - 'hint' => $this->l('Set the maximum size of product short description (in characters).'), - 'validation' => 'isInt', - 'cast' => 'intval', - 'type' => 'text', - 'suffix' => $this->l('characters'), - ), - 'PS_QTY_DISCOUNT_ON_COMBINATION' => array( - 'title' => $this->l('Quantity discounts based on'), - 'hint' => $this->l('How to calculate quantity discounts.'), - 'cast' => 'intval', - 'show' => true, - 'required' => false, - 'type' => 'radio', - 'validation' => 'isBool', - 'choices' => array( - 0 => $this->l('Products'), - 1 => $this->l('Combinations') - ) - ), - 'PS_FORCE_FRIENDLY_PRODUCT' => array( - 'title' => $this->l('Force update of friendly URL'), - 'hint' => $this->l('When active, friendly URL will be updated on every save.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'required' => false, - 'type' => 'bool' - ) - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'order_by_pagination' => array( - 'title' => $this->l('Pagination'), - 'fields' => array( - 'PS_PRODUCTS_PER_PAGE' => array( - 'title' => $this->l('Products per page'), - 'hint' => $this->l('Number of products displayed per page. Default is 10.'), - 'validation' => 'isUnsignedInt', - 'cast' => 'intval', - 'type' => 'text' - ), - 'PS_PRODUCTS_ORDER_BY' => array( - 'title' => $this->l('Default order by'), - 'hint' => $this->l('The order in which products are displayed in the product list.'), - 'type' => 'select', - 'list' => array( - array('id' => '0', 'name' => $this->l('Product name')), - array('id' => '1', 'name' => $this->l('Product price')), - array('id' => '2', 'name' => $this->l('Product add date')), - array('id' => '3', 'name' => $this->l('Product modified date')), - array('id' => '4', 'name' => $this->l('Position inside category')), - array('id' => '5', 'name' => $this->l('Manufacturer')), - array('id' => '6', 'name' => $this->l('Product quantity')), - array('id' => '7', 'name' => $this->l('Product reference')) - ), - 'identifier' => 'id' - ), - 'PS_PRODUCTS_ORDER_WAY' => array( - 'title' => $this->l('Default order method'), - 'hint' => $this->l('Default order method for product list.'), - 'type' => 'select', - 'list' => array( - array( - 'id' => '0', - 'name' => $this->l('Ascending') - ), - array( - 'id' => '1', - 'name' => $this->l('Descending') - ) - ), - 'identifier' => 'id' - ) - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'fo_product_page' => array( - 'title' => $this->l('Product page'), - 'fields' => array( - 'PS_DISPLAY_QTIES' => array( - 'title' => $this->l('Display available quantities on the product page'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'required' => false, - 'type' => 'bool' - ), - 'PS_LAST_QTIES' => array( - 'title' => $this->l('Display remaining quantities when the quantity is lower than'), - 'hint' => $this->l('Set to "0" to disable this feature.'), - 'validation' => 'isUnsignedId', - 'required' => true, - 'cast' => 'intval', - 'type' => 'text' - ), - 'PS_DISPLAY_JQZOOM' => array( - 'title' => $this->l('Enable JqZoom instead of Fancybox on the product page'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'required' => false, - 'type' => 'bool' - ), - 'PS_DISP_UNAVAILABLE_ATTR' => array( - 'title' => $this->l('Display unavailable product attributes on the product page'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'required' => false, - 'type' => 'bool' - ), - 'PS_ATTRIBUTE_CATEGORY_DISPLAY' => array( - 'title' => $this->l('Display the "add to cart" button when a product has attributes'), - 'hint' => $this->l('Display or hide the "add to cart" button on category pages for products that have attributes forcing customers to see product details.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_ATTRIBUTE_ANCHOR_SEPARATOR' => array( - 'title' => $this->l('Separator of attribute anchor on the product links'), - 'type' => 'select', - 'list' => array( - array('id' => '-', 'name' => '-'), - array('id' => ',', 'name' => ','), - ), - 'identifier' => 'id' - ), - 'PS_DISPLAY_DISCOUNT_PRICE' => array( - 'title' => $this->l('Display discounted price'), - 'desc' => $this->l('In the volume discounts board, display the new price with the applied discount instead of showing the discount (ie. "-5%").'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'required' => false, - 'type' => 'bool' - ), - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'stock' => array( - 'title' => $this->l('Products stock'), - 'fields' => array( - 'PS_ORDER_OUT_OF_STOCK' => array( - 'title' => $this->l('Allow ordering of out-of-stock products'), - 'hint' => $this->l('By default, the Add to Cart button is hidden when a product is unavailable. You can choose to have it displayed in all cases.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'required' => false, - 'type' => 'bool' - ), - 'PS_STOCK_MANAGEMENT' => array( - 'title' => $this->l('Enable stock management'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'required' => false, - 'type' => 'bool', - 'js' => array( - 'on' => 'onchange="stockManagementActivationAuthorization()"', - 'off' => 'onchange="stockManagementActivationAuthorization()"' - ) - ), - 'PS_ADVANCED_STOCK_MANAGEMENT' => array( - 'title' => $this->l('Enable advanced stock management'), - 'hint' => $this->l('Allows you to manage physical stock, warehouses and supply orders in a new Stock menu.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'required' => false, - 'type' => 'bool', - 'visibility' => Shop::CONTEXT_ALL, - 'js' => array( - 'on' => 'onchange="advancedStockManagementActivationAuthorization()"', - 'off' => 'onchange="advancedStockManagementActivationAuthorization()"' - ) - ), - 'PS_FORCE_ASM_NEW_PRODUCT' => array( - 'title' => $this->l('New products use advanced stock management'), - 'hint' => $this->l('New products will automatically use advanced stock management and depends on stock, but no warehouse will be selected'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'required' => false, - 'type' => 'bool', - 'visibility' => Shop::CONTEXT_ALL, - ), - 'PS_DEFAULT_WAREHOUSE_NEW_PRODUCT' => array( - 'title' => $this->l('Default warehouse on new products'), - 'hint' => $this->l('Automatically set a default warehouse when new product is created'), - 'type' => 'select', - 'list' => $warehouse_list, - 'identifier' => 'id_warehouse' - ), - 'PS_PACK_STOCK_TYPE' => array( - 'title' => $this->l('Default pack stock management'), - 'type' => 'select', - 'list' =>array( - array( - 'pack_stock' => 0, - 'name' => $this->l('Decrement pack only.') - ), - array( - 'pack_stock' => 1, - 'name' => $this->l('Decrement products in pack only.') - ), - array( - 'pack_stock' => 2, - 'name' => $this->l('Decrement both.') - ), - ), - 'identifier' => 'pack_stock', - ), - ), - 'bottom' => '<script type="text/javascript">stockManagementActivationAuthorization();advancedStockManagementActivationAuthorization();</script>', - 'submit' => array('title' => $this->l('Save')) - ), - ); - } + $this->fields_options = array( + 'products' => array( + 'title' => $this->l('Products (general)'), + 'fields' => array( + 'PS_CATALOG_MODE' => array( + 'title' => $this->l('Catalog mode'), + 'hint' => $this->l('When active, all shopping features will be disabled.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'required' => false, + 'type' => 'bool' + ), + 'PS_COMPARATOR_MAX_ITEM' => array( + 'title' => $this->l('Product comparison'), + 'hint' => $this->l('Set the maximum number of products that can be selected for comparison. Set to "0" to disable this feature.'), + 'validation' => 'isUnsignedId', + 'required' => true, + 'cast' => 'intval', + 'type' => 'text' + ), + 'PS_NB_DAYS_NEW_PRODUCT' => array( + 'title' => $this->l('Number of days for which the product is considered \'new\''), + 'validation' => 'isUnsignedInt', + 'cast' => 'intval', + 'type' => 'text' + ), + 'PS_CART_REDIRECT' => array( + 'title' => $this->l('Redirect after adding product to cart'), + 'hint' => $this->l('Only for non-AJAX versions of the cart.'), + 'cast' => 'intval', + 'show' => true, + 'required' => false, + 'type' => 'radio', + 'validation' => 'isBool', + 'choices' => array( + 0 => $this->l('Previous page'), + 1 => $this->l('Cart summary') + ) + ), + 'PS_PRODUCT_SHORT_DESC_LIMIT' => array( + 'title' => $this->l('Max size of short description'), + 'hint' => $this->l('Set the maximum size of product short description (in characters).'), + 'validation' => 'isInt', + 'cast' => 'intval', + 'type' => 'text', + 'suffix' => $this->l('characters'), + ), + 'PS_QTY_DISCOUNT_ON_COMBINATION' => array( + 'title' => $this->l('Quantity discounts based on'), + 'hint' => $this->l('How to calculate quantity discounts.'), + 'cast' => 'intval', + 'show' => true, + 'required' => false, + 'type' => 'radio', + 'validation' => 'isBool', + 'choices' => array( + 0 => $this->l('Products'), + 1 => $this->l('Combinations') + ) + ), + 'PS_FORCE_FRIENDLY_PRODUCT' => array( + 'title' => $this->l('Force update of friendly URL'), + 'hint' => $this->l('When active, friendly URL will be updated on every save.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'required' => false, + 'type' => 'bool' + ) + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'order_by_pagination' => array( + 'title' => $this->l('Pagination'), + 'fields' => array( + 'PS_PRODUCTS_PER_PAGE' => array( + 'title' => $this->l('Products per page'), + 'hint' => $this->l('Number of products displayed per page. Default is 10.'), + 'validation' => 'isUnsignedInt', + 'cast' => 'intval', + 'type' => 'text' + ), + 'PS_PRODUCTS_ORDER_BY' => array( + 'title' => $this->l('Default order by'), + 'hint' => $this->l('The order in which products are displayed in the product list.'), + 'type' => 'select', + 'list' => array( + array('id' => '0', 'name' => $this->l('Product name')), + array('id' => '1', 'name' => $this->l('Product price')), + array('id' => '2', 'name' => $this->l('Product add date')), + array('id' => '3', 'name' => $this->l('Product modified date')), + array('id' => '4', 'name' => $this->l('Position inside category')), + array('id' => '5', 'name' => $this->l('Manufacturer')), + array('id' => '6', 'name' => $this->l('Product quantity')), + array('id' => '7', 'name' => $this->l('Product reference')) + ), + 'identifier' => 'id' + ), + 'PS_PRODUCTS_ORDER_WAY' => array( + 'title' => $this->l('Default order method'), + 'hint' => $this->l('Default order method for product list.'), + 'type' => 'select', + 'list' => array( + array( + 'id' => '0', + 'name' => $this->l('Ascending') + ), + array( + 'id' => '1', + 'name' => $this->l('Descending') + ) + ), + 'identifier' => 'id' + ) + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'fo_product_page' => array( + 'title' => $this->l('Product page'), + 'fields' => array( + 'PS_DISPLAY_QTIES' => array( + 'title' => $this->l('Display available quantities on the product page'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'required' => false, + 'type' => 'bool' + ), + 'PS_LAST_QTIES' => array( + 'title' => $this->l('Display remaining quantities when the quantity is lower than'), + 'hint' => $this->l('Set to "0" to disable this feature.'), + 'validation' => 'isUnsignedId', + 'required' => true, + 'cast' => 'intval', + 'type' => 'text' + ), + 'PS_DISPLAY_JQZOOM' => array( + 'title' => $this->l('Enable JqZoom instead of Fancybox on the product page'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'required' => false, + 'type' => 'bool' + ), + 'PS_DISP_UNAVAILABLE_ATTR' => array( + 'title' => $this->l('Display unavailable product attributes on the product page'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'required' => false, + 'type' => 'bool' + ), + 'PS_ATTRIBUTE_CATEGORY_DISPLAY' => array( + 'title' => $this->l('Display the "add to cart" button when a product has attributes'), + 'hint' => $this->l('Display or hide the "add to cart" button on category pages for products that have attributes forcing customers to see product details.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_ATTRIBUTE_ANCHOR_SEPARATOR' => array( + 'title' => $this->l('Separator of attribute anchor on the product links'), + 'type' => 'select', + 'list' => array( + array('id' => '-', 'name' => '-'), + array('id' => ',', 'name' => ','), + ), + 'identifier' => 'id' + ), + 'PS_DISPLAY_DISCOUNT_PRICE' => array( + 'title' => $this->l('Display discounted price'), + 'desc' => $this->l('In the volume discounts board, display the new price with the applied discount instead of showing the discount (ie. "-5%").'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'required' => false, + 'type' => 'bool' + ), + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'stock' => array( + 'title' => $this->l('Products stock'), + 'fields' => array( + 'PS_ORDER_OUT_OF_STOCK' => array( + 'title' => $this->l('Allow ordering of out-of-stock products'), + 'hint' => $this->l('By default, the Add to Cart button is hidden when a product is unavailable. You can choose to have it displayed in all cases.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'required' => false, + 'type' => 'bool' + ), + 'PS_STOCK_MANAGEMENT' => array( + 'title' => $this->l('Enable stock management'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'required' => false, + 'type' => 'bool', + 'js' => array( + 'on' => 'onchange="stockManagementActivationAuthorization()"', + 'off' => 'onchange="stockManagementActivationAuthorization()"' + ) + ), + 'PS_ADVANCED_STOCK_MANAGEMENT' => array( + 'title' => $this->l('Enable advanced stock management'), + 'hint' => $this->l('Allows you to manage physical stock, warehouses and supply orders in a new Stock menu.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'required' => false, + 'type' => 'bool', + 'visibility' => Shop::CONTEXT_ALL, + 'js' => array( + 'on' => 'onchange="advancedStockManagementActivationAuthorization()"', + 'off' => 'onchange="advancedStockManagementActivationAuthorization()"' + ) + ), + 'PS_FORCE_ASM_NEW_PRODUCT' => array( + 'title' => $this->l('New products use advanced stock management'), + 'hint' => $this->l('New products will automatically use advanced stock management and depends on stock, but no warehouse will be selected'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'required' => false, + 'type' => 'bool', + 'visibility' => Shop::CONTEXT_ALL, + ), + 'PS_DEFAULT_WAREHOUSE_NEW_PRODUCT' => array( + 'title' => $this->l('Default warehouse on new products'), + 'hint' => $this->l('Automatically set a default warehouse when new product is created'), + 'type' => 'select', + 'list' => $warehouse_list, + 'identifier' => 'id_warehouse' + ), + 'PS_PACK_STOCK_TYPE' => array( + 'title' => $this->l('Default pack stock management'), + 'type' => 'select', + 'list' =>array( + array( + 'pack_stock' => 0, + 'name' => $this->l('Decrement pack only.') + ), + array( + 'pack_stock' => 1, + 'name' => $this->l('Decrement products in pack only.') + ), + array( + 'pack_stock' => 2, + 'name' => $this->l('Decrement both.') + ), + ), + 'identifier' => 'pack_stock', + ), + ), + 'bottom' => '<script type="text/javascript">stockManagementActivationAuthorization();advancedStockManagementActivationAuthorization();</script>', + 'submit' => array('title' => $this->l('Save')) + ), + ); + } - public function beforeUpdateOptions() - { - if (!Tools::getValue('PS_STOCK_MANAGEMENT', true)) - { - $_POST['PS_ORDER_OUT_OF_STOCK'] = 1; - $_POST['PS_DISPLAY_QTIES'] = 0; - } + public function beforeUpdateOptions() + { + if (!Tools::getValue('PS_STOCK_MANAGEMENT', true)) { + $_POST['PS_ORDER_OUT_OF_STOCK'] = 1; + $_POST['PS_DISPLAY_QTIES'] = 0; + } - // if advanced stock management is disabled, updates concerned tables - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') == 1 && (int)Tools::getValue('PS_ADVANCED_STOCK_MANAGEMENT') == 0) - { - $id_shop_list = Shop::getContextListShopID(); - $sql_shop = 'UPDATE `'._DB_PREFIX_.'product_shop` SET `advanced_stock_management` = 0 WHERE + // if advanced stock management is disabled, updates concerned tables + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') == 1 && (int)Tools::getValue('PS_ADVANCED_STOCK_MANAGEMENT') == 0) { + $id_shop_list = Shop::getContextListShopID(); + $sql_shop = 'UPDATE `'._DB_PREFIX_.'product_shop` SET `advanced_stock_management` = 0 WHERE `advanced_stock_management` = 1 AND (`id_shop` = '.implode(' OR `id_shop` = ', $id_shop_list).')'; - $sql_stock = 'UPDATE `'._DB_PREFIX_.'stock_available` SET `depends_on_stock` = 0, `quantity` = 0 + $sql_stock = 'UPDATE `'._DB_PREFIX_.'stock_available` SET `depends_on_stock` = 0, `quantity` = 0 WHERE `depends_on_stock` = 1 AND (`id_shop` = '.implode(' OR `id_shop` = ', $id_shop_list).')'; - $sql = 'UPDATE `'._DB_PREFIX_.'product` SET `advanced_stock_management` = 0 WHERE + $sql = 'UPDATE `'._DB_PREFIX_.'product` SET `advanced_stock_management` = 0 WHERE `advanced_stock_management` = 1 AND (`id_shop_default` = '.implode(' OR `id_shop_default` = ', $id_shop_list).')'; - Db::getInstance()->execute($sql_shop); - Db::getInstance()->execute($sql_stock); - Db::getInstance()->execute($sql); - } - - if (Tools::getIsset('PS_CATALOG_MODE')) - { - Tools::clearSmartyCache(); - Media::clearCache(); - } - } + Db::getInstance()->execute($sql_shop); + Db::getInstance()->execute($sql_stock); + Db::getInstance()->execute($sql); + } + if (Tools::getIsset('PS_CATALOG_MODE')) { + Tools::clearSmartyCache(); + Media::clearCache(); + } + } } diff --git a/controllers/admin/AdminPatternsController.php b/controllers/admin/AdminPatternsController.php index f0933fcc..ead0fad7 100644 --- a/controllers/admin/AdminPatternsController.php +++ b/controllers/admin/AdminPatternsController.php @@ -26,663 +26,663 @@ class AdminPatternsControllerCore extends AdminController { - public $name = "patterns"; + public $name = "patterns"; - public function __construct() - { - $this->bootstrap = true; - $this->show_toolbar = false; - $this->context = Context::getContext(); + public function __construct() + { + $this->bootstrap = true; + $this->show_toolbar = false; + $this->context = Context::getContext(); - parent::__construct(); - } + parent::__construct(); + } - public function viewAccess() - { - return true; - } + public function viewAccess() + { + return true; + } - public function renderForm() - { - $this->fields_value = array( - 'type_text' => 'with value', - 'type_text_readonly' => 'with value that you can\'t edit', - 'type_switch' => 1, - 'days' => 17, - 'months' => 3, - 'years' => 2014, - 'groupBox_1' => false, - 'groupBox_2' => true, - 'groupBox_3' => false, - 'groupBox_4' => true, - 'groupBox_5' => true, - 'groupBox_6' => false, - 'type_color' => '#8BC954', - 'tab_note' => 'The tabs are always pushed to the top of the form, wherever they are in the fields_form array.', - 'type_free' => '<p class="form-control-static">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc lacinia in enim iaculis malesuada. Quisque congue fermentum leo et porta. Pellentesque a quam dui. Pellentesque sed augue id sem aliquet faucibus eu vel odio. Nullam non libero volutpat, pulvinar turpis non, gravida mauris. Nullam tincidunt id est at euismod. Quisque euismod quam in pellentesque mollis. Nulla suscipit porttitor massa, nec eleifend risus egestas in. Aenean luctus porttitor tempus. Morbi dolor leo, dictum id interdum vel, semper ac est. Maecenas justo augue, accumsan in velit nec, consectetur fringilla orci. Nunc ut ante erat. Curabitur dolor augue, eleifend a luctus non, aliquet a mi. Curabitur ultricies lectus in rhoncus sodales. Maecenas quis dictum erat. Suspendisse blandit lacus sed felis facilisis, in interdum quam congue.<p>' - ); + public function renderForm() + { + $this->fields_value = array( + 'type_text' => 'with value', + 'type_text_readonly' => 'with value that you can\'t edit', + 'type_switch' => 1, + 'days' => 17, + 'months' => 3, + 'years' => 2014, + 'groupBox_1' => false, + 'groupBox_2' => true, + 'groupBox_3' => false, + 'groupBox_4' => true, + 'groupBox_5' => true, + 'groupBox_6' => false, + 'type_color' => '#8BC954', + 'tab_note' => 'The tabs are always pushed to the top of the form, wherever they are in the fields_form array.', + 'type_free' => '<p class="form-control-static">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc lacinia in enim iaculis malesuada. Quisque congue fermentum leo et porta. Pellentesque a quam dui. Pellentesque sed augue id sem aliquet faucibus eu vel odio. Nullam non libero volutpat, pulvinar turpis non, gravida mauris. Nullam tincidunt id est at euismod. Quisque euismod quam in pellentesque mollis. Nulla suscipit porttitor massa, nec eleifend risus egestas in. Aenean luctus porttitor tempus. Morbi dolor leo, dictum id interdum vel, semper ac est. Maecenas justo augue, accumsan in velit nec, consectetur fringilla orci. Nunc ut ante erat. Curabitur dolor augue, eleifend a luctus non, aliquet a mi. Curabitur ultricies lectus in rhoncus sodales. Maecenas quis dictum erat. Suspendisse blandit lacus sed felis facilisis, in interdum quam congue.<p>' + ); - $this->fields_form = array( - 'legend' => array( - 'title' => 'patterns of helper form.tpl', - 'icon' => 'icon-edit' - ), - 'tabs' => array( - 'small' => 'Small Inputs', - 'large' => 'Large Inputs', - ), - 'description' => 'You can use image instead of icon for the title.', - 'input' => array( - array( - 'type' => 'text', - 'label' => 'simple input text', - 'name' => 'type_text' - ), - array( - 'type' => 'text', - 'label' => 'input text with desc', - 'name' => 'type_text_desc', - 'desc' => 'desc input text' - ), - array( - 'type' => 'text', - 'label' => 'required input text', - 'name' => 'type_text_required', - 'required' => true - ), - array( - 'type' => 'text', - 'label' => 'input text with hint', - 'name' => 'type_text_hint', - 'hint' => 'hint input text' - ), - array( - 'type' => 'text', - 'label' => 'input text with prefix', - 'name' => 'type_text_prefix', - 'prefix' => 'prefix' - ), - array( - 'type' => 'text', - 'label' => 'input text with suffix', - 'name' => 'type_text_suffix', - 'suffix' => 'suffix' - ), - array( - 'type' => 'text', - 'label' => 'input text with placeholder', - 'name' => 'type_text_placeholder', - 'placeholder' => 'placeholder' - ), - array( - 'type' => 'text', - 'label' => 'input text with character counter', - 'name' => 'type_text_maxchar', - 'maxchar' => 30 - ), - array( - 'type' => 'text', - 'lang' => true, - 'label' => 'input text multilang', - 'name' => 'type_text_multilang' - ), - array( - 'type' => 'text', - 'label' => 'input readonly', - 'readonly' => true, - 'name' => 'type_text_readonly' - ), - array( - 'type' => 'text', - 'label' => 'input fixed-width-xs', - 'name' => 'type_text_xs', - 'class' => 'input fixed-width-xs' - ), - array( - 'type' => 'text', - 'label' => 'input fixed-width-sm', - 'name' => 'type_text_sm', - 'class' => 'input fixed-width-sm' - ), - array( - 'type' => 'text', - 'label' => 'input fixed-width-md', - 'name' => 'type_text_md', - 'class' => 'input fixed-width-md' - ), - array( - 'type' => 'text', - 'label' => 'input fixed-width-lg', - 'name' => 'type_text_lg', - 'class' => 'input fixed-width-lg' - ), - array( - 'type' => 'text', - 'label' => 'input fixed-width-xl', - 'name' => 'type_text_xl', - 'class' => 'input fixed-width-xl' - ), - array( - 'type' => 'text', - 'label' => 'input fixed-width-xxl', - 'name' => 'type_text_xxl', - 'class' => 'fixed-width-xxl' - ), - array( - 'type' => 'text', - 'label' => 'input fixed-width-sm', - 'name' => 'type_text_sm', - 'class' => 'input fixed-width-sm', - 'tab' => 'small', - ), - array( - 'type' => 'text', - 'label' => 'input fixed-width-md', - 'name' => 'type_text_md', - 'class' => 'input fixed-width-md', - 'tab' => 'small', - ), - array( - 'type' => 'text', - 'label' => 'input fixed-width-lg', - 'name' => 'type_text_lg', - 'class' => 'input fixed-width-lg', - 'tab' => 'large', - ), - array( - 'type' => 'text', - 'label' => 'input fixed-width-xl', - 'name' => 'type_text_xl', - 'class' => 'input fixed-width-xl', - 'tab' => 'large', - ), - array( - 'type' => 'text', - 'label' => 'input fixed-width-xxl', - 'name' => 'type_text_xxl', - 'class' => 'fixed-width-xxl', - 'tab' => 'large', - ), - array( - 'type' => 'free', - 'label' => 'About tabs', - 'name' => 'tab_note', - 'tab' => 'small', - ), - array( - 'type' => 'text', - 'label' => 'input fixed-width-md with prefix', - 'name' => 'type_text_md', - 'class' => 'input fixed-width-md', - 'prefix' => 'prefix' - ), - array( - 'type' => 'text', - 'label' => 'input fixed-width-md with sufix', - 'name' => 'type_text_md', - 'class' => 'input fixed-width-md', - 'suffix' => 'suffix' - ), - array( - 'type' => 'tags', - 'label' => 'input tags', - 'name' => 'type_text_tags' - ), - array( - 'type' => 'textbutton', - 'label' => 'input with button', - 'name' => 'type_textbutton', - 'button' => array( - 'label' => 'do something', - 'attributes' => array( - 'onclick' => 'alert(\'something done\');' - ) - ) - ), - array( - 'type' => 'select', - 'label' => 'select', - 'name' => 'type_select', - 'options' => array( - 'query' => Zone::getZones(), - 'id' => 'id_zone', - 'name' => 'name' - ), - ), - array( - 'type' => 'select', - 'label' => 'select with chosen', - 'name' => 'type_select_chosen', - 'class' => 'chosen', - 'options' => array( - 'query' => Country::getCountries((int)Context::getContext()->cookie->id_lang), - 'id' => 'id_zone', - 'name' => 'name' - ), - ), - array( - 'type' => 'select', - 'label' => 'select multiple with chosen', - 'name' => 'type_select_multiple_chosen', - 'class' => 'chosen', - 'multiple' => true, - 'options' => array( - 'query' => Country::getCountries((int)Context::getContext()->cookie->id_lang), - 'id' => 'id_zone', - 'name' => 'name' - ), - ), - array( - 'type' => 'radio', - 'label' => 'radios', - 'name' => 'type_radio', - 'values' => array( - array( - 'id' => 'type_male', - 'value' => 0, - 'label' => 'first' - ), - array( - 'id' => 'type_female', - 'value' => 1, - 'label' => 'second' - ), - array( - 'id' => 'type_neutral', - 'value' => 2, - 'label' => 'third' - ) - ) - ), - array( - 'type' => 'checkbox', - 'label' => 'checkbox', - 'name' => 'type_checkbox', - 'values' => array( - 'query' => Zone::getZones(), - 'id' => 'id_zone', - 'name' => 'name' - ) - ), - array( - 'type' => 'switch', - 'label' => 'switch', - 'name' => 'type_switch', - 'values' => array( - array( - 'id' => 'type_switch_on', - 'value' => 1 - ), - array( - 'id' => 'type_switch_off', - 'value' => 0 - ) - ) - ), - array( - 'type' => 'switch', - 'label' => 'switch disabled', - 'name' => 'type_switch_disabled', - 'disabled' => 'true', - 'values' => array( - array( - 'id' => 'type_switch_disabled_on', - 'value' => 1 - ), - array( - 'id' => 'type_switch_disabled_off', - 'value' => 0 - ) - ) - ), - array( - 'type' => 'textarea', - 'label' => 'text area (with autoresize)', - 'name' => 'type_textarea' - ), - array( - 'type' => 'textarea', - 'label' => 'text area with rich text editor', - 'name' => 'type_textarea_rte', - 'autoload_rte' => true - ), - array( - 'type' => 'password', - 'label' => 'input password', - 'name' => 'type_password' - ), - array( - 'type' => 'birthday', - 'label' => 'input birthday', - 'name' => 'type_birthday', - 'options' => array( - 'days' => Tools::dateDays(), - 'months' => Tools::dateMonths(), - 'years' => Tools::dateYears() - ) - ), - array( - 'type' => 'group', - 'label' => 'group', - 'name' => 'type_group', - 'values' => Group::getGroups(Context::getContext()->language->id) - ), - array( - 'type' => 'categories', - 'label' => 'tree categories', - 'name' => 'type_categories', - 'tree' => array( - 'root_category' => 1, - 'id' => 'id_category', - 'name' => 'name_category', - 'selected_categories' => array(3), - ) - ), - array( - 'type' => 'file', - 'label' => 'input file', - 'name' => 'type_file' - ), - array( - 'type' => 'color', - 'label' => 'input color', - 'name' => 'type_color' - ), - array( - 'type' => 'date', - 'label' => 'input date', - 'name' => 'type_date' - ), - array( - 'type' => 'datetime', - 'label' => 'input date and time', - 'name' => 'type_datetime' - ), - array( - 'type' => 'html', - 'name' => 'html_data', - 'html_content' => '<hr><strong>html:</strong> for writing free html like this <span class="label label-danger">i\'m a label</span> <span class="badge badge-info">i\'m a badge</span> <button type="button" class="btn btn-default">i\'m a button</button><hr>' - ), - array( - 'type' => 'free', - 'label' => 'input free', - 'name' => 'type_free' - ), - //... - ), - 'submit' => array( - 'title' => 'Save', - ), - 'buttons' => array(), - ); + $this->fields_form = array( + 'legend' => array( + 'title' => 'patterns of helper form.tpl', + 'icon' => 'icon-edit' + ), + 'tabs' => array( + 'small' => 'Small Inputs', + 'large' => 'Large Inputs', + ), + 'description' => 'You can use image instead of icon for the title.', + 'input' => array( + array( + 'type' => 'text', + 'label' => 'simple input text', + 'name' => 'type_text' + ), + array( + 'type' => 'text', + 'label' => 'input text with desc', + 'name' => 'type_text_desc', + 'desc' => 'desc input text' + ), + array( + 'type' => 'text', + 'label' => 'required input text', + 'name' => 'type_text_required', + 'required' => true + ), + array( + 'type' => 'text', + 'label' => 'input text with hint', + 'name' => 'type_text_hint', + 'hint' => 'hint input text' + ), + array( + 'type' => 'text', + 'label' => 'input text with prefix', + 'name' => 'type_text_prefix', + 'prefix' => 'prefix' + ), + array( + 'type' => 'text', + 'label' => 'input text with suffix', + 'name' => 'type_text_suffix', + 'suffix' => 'suffix' + ), + array( + 'type' => 'text', + 'label' => 'input text with placeholder', + 'name' => 'type_text_placeholder', + 'placeholder' => 'placeholder' + ), + array( + 'type' => 'text', + 'label' => 'input text with character counter', + 'name' => 'type_text_maxchar', + 'maxchar' => 30 + ), + array( + 'type' => 'text', + 'lang' => true, + 'label' => 'input text multilang', + 'name' => 'type_text_multilang' + ), + array( + 'type' => 'text', + 'label' => 'input readonly', + 'readonly' => true, + 'name' => 'type_text_readonly' + ), + array( + 'type' => 'text', + 'label' => 'input fixed-width-xs', + 'name' => 'type_text_xs', + 'class' => 'input fixed-width-xs' + ), + array( + 'type' => 'text', + 'label' => 'input fixed-width-sm', + 'name' => 'type_text_sm', + 'class' => 'input fixed-width-sm' + ), + array( + 'type' => 'text', + 'label' => 'input fixed-width-md', + 'name' => 'type_text_md', + 'class' => 'input fixed-width-md' + ), + array( + 'type' => 'text', + 'label' => 'input fixed-width-lg', + 'name' => 'type_text_lg', + 'class' => 'input fixed-width-lg' + ), + array( + 'type' => 'text', + 'label' => 'input fixed-width-xl', + 'name' => 'type_text_xl', + 'class' => 'input fixed-width-xl' + ), + array( + 'type' => 'text', + 'label' => 'input fixed-width-xxl', + 'name' => 'type_text_xxl', + 'class' => 'fixed-width-xxl' + ), + array( + 'type' => 'text', + 'label' => 'input fixed-width-sm', + 'name' => 'type_text_sm', + 'class' => 'input fixed-width-sm', + 'tab' => 'small', + ), + array( + 'type' => 'text', + 'label' => 'input fixed-width-md', + 'name' => 'type_text_md', + 'class' => 'input fixed-width-md', + 'tab' => 'small', + ), + array( + 'type' => 'text', + 'label' => 'input fixed-width-lg', + 'name' => 'type_text_lg', + 'class' => 'input fixed-width-lg', + 'tab' => 'large', + ), + array( + 'type' => 'text', + 'label' => 'input fixed-width-xl', + 'name' => 'type_text_xl', + 'class' => 'input fixed-width-xl', + 'tab' => 'large', + ), + array( + 'type' => 'text', + 'label' => 'input fixed-width-xxl', + 'name' => 'type_text_xxl', + 'class' => 'fixed-width-xxl', + 'tab' => 'large', + ), + array( + 'type' => 'free', + 'label' => 'About tabs', + 'name' => 'tab_note', + 'tab' => 'small', + ), + array( + 'type' => 'text', + 'label' => 'input fixed-width-md with prefix', + 'name' => 'type_text_md', + 'class' => 'input fixed-width-md', + 'prefix' => 'prefix' + ), + array( + 'type' => 'text', + 'label' => 'input fixed-width-md with sufix', + 'name' => 'type_text_md', + 'class' => 'input fixed-width-md', + 'suffix' => 'suffix' + ), + array( + 'type' => 'tags', + 'label' => 'input tags', + 'name' => 'type_text_tags' + ), + array( + 'type' => 'textbutton', + 'label' => 'input with button', + 'name' => 'type_textbutton', + 'button' => array( + 'label' => 'do something', + 'attributes' => array( + 'onclick' => 'alert(\'something done\');' + ) + ) + ), + array( + 'type' => 'select', + 'label' => 'select', + 'name' => 'type_select', + 'options' => array( + 'query' => Zone::getZones(), + 'id' => 'id_zone', + 'name' => 'name' + ), + ), + array( + 'type' => 'select', + 'label' => 'select with chosen', + 'name' => 'type_select_chosen', + 'class' => 'chosen', + 'options' => array( + 'query' => Country::getCountries((int)Context::getContext()->cookie->id_lang), + 'id' => 'id_zone', + 'name' => 'name' + ), + ), + array( + 'type' => 'select', + 'label' => 'select multiple with chosen', + 'name' => 'type_select_multiple_chosen', + 'class' => 'chosen', + 'multiple' => true, + 'options' => array( + 'query' => Country::getCountries((int)Context::getContext()->cookie->id_lang), + 'id' => 'id_zone', + 'name' => 'name' + ), + ), + array( + 'type' => 'radio', + 'label' => 'radios', + 'name' => 'type_radio', + 'values' => array( + array( + 'id' => 'type_male', + 'value' => 0, + 'label' => 'first' + ), + array( + 'id' => 'type_female', + 'value' => 1, + 'label' => 'second' + ), + array( + 'id' => 'type_neutral', + 'value' => 2, + 'label' => 'third' + ) + ) + ), + array( + 'type' => 'checkbox', + 'label' => 'checkbox', + 'name' => 'type_checkbox', + 'values' => array( + 'query' => Zone::getZones(), + 'id' => 'id_zone', + 'name' => 'name' + ) + ), + array( + 'type' => 'switch', + 'label' => 'switch', + 'name' => 'type_switch', + 'values' => array( + array( + 'id' => 'type_switch_on', + 'value' => 1 + ), + array( + 'id' => 'type_switch_off', + 'value' => 0 + ) + ) + ), + array( + 'type' => 'switch', + 'label' => 'switch disabled', + 'name' => 'type_switch_disabled', + 'disabled' => 'true', + 'values' => array( + array( + 'id' => 'type_switch_disabled_on', + 'value' => 1 + ), + array( + 'id' => 'type_switch_disabled_off', + 'value' => 0 + ) + ) + ), + array( + 'type' => 'textarea', + 'label' => 'text area (with autoresize)', + 'name' => 'type_textarea' + ), + array( + 'type' => 'textarea', + 'label' => 'text area with rich text editor', + 'name' => 'type_textarea_rte', + 'autoload_rte' => true + ), + array( + 'type' => 'password', + 'label' => 'input password', + 'name' => 'type_password' + ), + array( + 'type' => 'birthday', + 'label' => 'input birthday', + 'name' => 'type_birthday', + 'options' => array( + 'days' => Tools::dateDays(), + 'months' => Tools::dateMonths(), + 'years' => Tools::dateYears() + ) + ), + array( + 'type' => 'group', + 'label' => 'group', + 'name' => 'type_group', + 'values' => Group::getGroups(Context::getContext()->language->id) + ), + array( + 'type' => 'categories', + 'label' => 'tree categories', + 'name' => 'type_categories', + 'tree' => array( + 'root_category' => 1, + 'id' => 'id_category', + 'name' => 'name_category', + 'selected_categories' => array(3), + ) + ), + array( + 'type' => 'file', + 'label' => 'input file', + 'name' => 'type_file' + ), + array( + 'type' => 'color', + 'label' => 'input color', + 'name' => 'type_color' + ), + array( + 'type' => 'date', + 'label' => 'input date', + 'name' => 'type_date' + ), + array( + 'type' => 'datetime', + 'label' => 'input date and time', + 'name' => 'type_datetime' + ), + array( + 'type' => 'html', + 'name' => 'html_data', + 'html_content' => '<hr><strong>html:</strong> for writing free html like this <span class="label label-danger">i\'m a label</span> <span class="badge badge-info">i\'m a badge</span> <button type="button" class="btn btn-default">i\'m a button</button><hr>' + ), + array( + 'type' => 'free', + 'label' => 'input free', + 'name' => 'type_free' + ), + //... + ), + 'submit' => array( + 'title' => 'Save', + ), + 'buttons' => array(), + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function setMedia() - { - parent::setMedia(); - $this->addjQueryPlugin('tagify', null, false); - } + public function setMedia() + { + parent::setMedia(); + $this->addjQueryPlugin('tagify', null, false); + } - public function renderList() - { - $return = ''; + public function renderList() + { + $return = ''; - $return .= $this->renderListSimpleHeader(); - $return .= $this->renderListSmallColumns(); - $return .= $this->renderListWithParentClass(); + $return .= $this->renderListSimpleHeader(); + $return .= $this->renderListSmallColumns(); + $return .= $this->renderListWithParentClass(); - return $return; - } + return $return; + } - public function renderListSimpleHeader() - { - $content = array( - array( - "id_carrier" => 5, - "name" => "Lorem ipsum dolor, sit amet, consectetur adipiscing elit. Nunc lacinia in enim iaculis malesuada. Quisque congue ferm", - "type_name" => "Azerty", - "active" => 1, - ), - array( - "id_carrier" => 6, - "name" => "Lorem ipsum dolor sit amet, consectetur lacinia in enim iaculis malesuada. Quisque congue ferm", - "type_name" => "Qwerty", - "active" => 1, - ), - array( - "id_carrier" => 9, - "name" => "Lorem ipsum dolor sit amet: \ / : * ? \" < > |", - "type_name" => "Azerty", - "active" => 0, - ), - array( - "id_carrier" => 3, - "name" => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc lacinia in enim iaculis malesuada. Quisque congue ferm", - "type_name" => "Azerty", - "active" => 1, - ), - ); + public function renderListSimpleHeader() + { + $content = array( + array( + "id_carrier" => 5, + "name" => "Lorem ipsum dolor, sit amet, consectetur adipiscing elit. Nunc lacinia in enim iaculis malesuada. Quisque congue ferm", + "type_name" => "Azerty", + "active" => 1, + ), + array( + "id_carrier" => 6, + "name" => "Lorem ipsum dolor sit amet, consectetur lacinia in enim iaculis malesuada. Quisque congue ferm", + "type_name" => "Qwerty", + "active" => 1, + ), + array( + "id_carrier" => 9, + "name" => "Lorem ipsum dolor sit amet: \ / : * ? \" < > |", + "type_name" => "Azerty", + "active" => 0, + ), + array( + "id_carrier" => 3, + "name" => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc lacinia in enim iaculis malesuada. Quisque congue ferm", + "type_name" => "Azerty", + "active" => 1, + ), + ); - $fields_list = array( - 'id_carrier' => array( - 'title' => 'ID', - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => 'Name' - ), - 'type_name' => array( - 'title' => 'Type', - 'type' => 'text', - ), - 'active' => array( - 'title' => 'Status', - 'active' => 'status', - 'type' => 'bool', - ), - ); + $fields_list = array( + 'id_carrier' => array( + 'title' => 'ID', + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => 'Name' + ), + 'type_name' => array( + 'title' => 'Type', + 'type' => 'text', + ), + 'active' => array( + 'title' => 'Status', + 'active' => 'status', + 'type' => 'bool', + ), + ); - $helper = new HelperList(); - $helper->shopLinkType = ''; - $helper->simple_header = true; - $helper->actions = array("edit", "delete"); - $helper->show_toolbar = false; - $helper->module = $this; - $helper->listTotal = count($content); - $helper->identifier = 'id_carrier'; - $helper->title = 'This list use a simple Header with no toolbar'; - $helper->table = $this->name; - $helper->token = Tools::getAdminTokenLite('AdminModules'); - $helper->currentIndex = AdminController::$currentIndex.'&configure='.$this->name; + $helper = new HelperList(); + $helper->shopLinkType = ''; + $helper->simple_header = true; + $helper->actions = array("edit", "delete"); + $helper->show_toolbar = false; + $helper->module = $this; + $helper->listTotal = count($content); + $helper->identifier = 'id_carrier'; + $helper->title = 'This list use a simple Header with no toolbar'; + $helper->table = $this->name; + $helper->token = Tools::getAdminTokenLite('AdminModules'); + $helper->currentIndex = AdminController::$currentIndex.'&configure='.$this->name; - return $helper->generateList($content, $fields_list); - } + return $helper->generateList($content, $fields_list); + } - public function renderListSmallColumns() - { - $content = array( - array( - 'id' => 5, - 'badge_success' => 153, - 'badge_warning' => 6, - 'badge_danger' => -2, - 'text' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', - 'color_value' => 'red', - 'blue' => 'Content in custom color in blue field', - 'activeVisu_field' => 1, - 'editable_text' => "PrestaShop", - ), - array( - 'id' => 1, - 'badge_success' => 15561533, - 'badge_warning' => 0, - 'badge_danger' => 0, - 'text' => 'Lorem ip, consectetur adipiscing elit.', - 'color_value' => 'blue', - 'blue' => 'Content in custom color in blue field', - 'activeVisu_field' => 0, - 'editable_text' => "PrestaShop", - ), - array( - 'id' => 2, - 'badge_success' => 0, - 'badge_warning' => 65, - 'badge_danger' => -200, - 'text' => 'WITH VERY LONG TEXT: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. ', - 'color_value' => 'yellow', - 'blue' => 'Content in custom color in blue field', - 'activeVisu_field' => 1, - 'editable_text' => "PrestaShop Lorem ipsum dolor sit amet, consectetur adipiscing elit. ", - ), - array( - 'id' => 9, - 'badge_success' => 3, - 'badge_warning' => 2, - 'badge_danger' => 1, - 'text' => "WITH HTML: <br> <strong>strong</strong> <span style='background: black;'>span content</span>", - 'color_value' => '#CCCC99', - 'blue' => 'Content in custom color in blue field', - 'activeVisu_field' => 1, - 'editable_text' => "PrestaShop", - ), - ); + public function renderListSmallColumns() + { + $content = array( + array( + 'id' => 5, + 'badge_success' => 153, + 'badge_warning' => 6, + 'badge_danger' => -2, + 'text' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + 'color_value' => 'red', + 'blue' => 'Content in custom color in blue field', + 'activeVisu_field' => 1, + 'editable_text' => "PrestaShop", + ), + array( + 'id' => 1, + 'badge_success' => 15561533, + 'badge_warning' => 0, + 'badge_danger' => 0, + 'text' => 'Lorem ip, consectetur adipiscing elit.', + 'color_value' => 'blue', + 'blue' => 'Content in custom color in blue field', + 'activeVisu_field' => 0, + 'editable_text' => "PrestaShop", + ), + array( + 'id' => 2, + 'badge_success' => 0, + 'badge_warning' => 65, + 'badge_danger' => -200, + 'text' => 'WITH VERY LONG TEXT: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. ', + 'color_value' => 'yellow', + 'blue' => 'Content in custom color in blue field', + 'activeVisu_field' => 1, + 'editable_text' => "PrestaShop Lorem ipsum dolor sit amet, consectetur adipiscing elit. ", + ), + array( + 'id' => 9, + 'badge_success' => 3, + 'badge_warning' => 2, + 'badge_danger' => 1, + 'text' => "WITH HTML: <br> <strong>strong</strong> <span style='background: black;'>span content</span>", + 'color_value' => '#CCCC99', + 'blue' => 'Content in custom color in blue field', + 'activeVisu_field' => 1, + 'editable_text' => "PrestaShop", + ), + ); - $fields_list = array( - 'id' => array( - 'title' => 'ID', - 'align' => 'center', - 'class' => 'fixed-width-xs', - ), - 'badge_success' => array( - 'title' => "Success", - 'badge_success' => true, - ), - 'badge_warning' => array( - 'title' => "Warning", - 'badge_warning' => true, - ), - 'badge_danger' => array( - 'title' => "Danger", - 'badge_danger' => true, - ), - 'text' => array( - 'title' => "Content with prefix", - 'prefix' => "This is a prefix: ", - 'class' => "class-prefix", - ), - 'blue' => array( - 'title' => "Content with no link", - 'color' => "color_value", - 'class' => "class-custom-nolink", - ), - 'activeVisu_field' => array( - 'title' => "ActiveVisu", - 'activeVisu' => true, + $fields_list = array( + 'id' => array( + 'title' => 'ID', + 'align' => 'center', + 'class' => 'fixed-width-xs', + ), + 'badge_success' => array( + 'title' => "Success", + 'badge_success' => true, + ), + 'badge_warning' => array( + 'title' => "Warning", + 'badge_warning' => true, + ), + 'badge_danger' => array( + 'title' => "Danger", + 'badge_danger' => true, + ), + 'text' => array( + 'title' => "Content with prefix", + 'prefix' => "This is a prefix: ", + 'class' => "class-prefix", + ), + 'blue' => array( + 'title' => "Content with no link", + 'color' => "color_value", + 'class' => "class-custom-nolink", + ), + 'activeVisu_field' => array( + 'title' => "ActiveVisu", + 'activeVisu' => true, - ), - 'editable_text' => array( - 'title' => "edit this !", - 'type' => 'editable', - 'class' => 'another-custom_class', - ), - ); + ), + 'editable_text' => array( + 'title' => "edit this !", + 'type' => 'editable', + 'class' => 'another-custom_class', + ), + ); - $helper = new HelperList(); - $helper->shopLinkType = ''; - $helper->simple_header = false; - $helper->actions = array(); - $helper->show_toolbar = false; - $helper->module = $this; - $helper->listTotal = count($content); - $helper->identifier = 'id'; - $helper->title = 'This list shows a lot of small columns'; - $helper->table = $this->name; - $helper->token = Tools::getAdminTokenLite('AdminModules'); - $helper->currentIndex = AdminController::$currentIndex.'&configure='.$this->name; + $helper = new HelperList(); + $helper->shopLinkType = ''; + $helper->simple_header = false; + $helper->actions = array(); + $helper->show_toolbar = false; + $helper->module = $this; + $helper->listTotal = count($content); + $helper->identifier = 'id'; + $helper->title = 'This list shows a lot of small columns'; + $helper->table = $this->name; + $helper->token = Tools::getAdminTokenLite('AdminModules'); + $helper->currentIndex = AdminController::$currentIndex.'&configure='.$this->name; - return $helper->generateList($content, $fields_list); - } + return $helper->generateList($content, $fields_list); + } - public function renderListModel() - { - $content = array(); + public function renderListModel() + { + $content = array(); - $fields_list = array(); + $fields_list = array(); - $helper = new HelperList(); - $helper->shopLinkType = ''; - $helper->simple_header = true; - $helper->actions = null; - $helper->show_toolbar = false; - $helper->module = $this; - $helper->listTotal = count($content); - $helper->identifier = 'id_product_comment'; - $helper->title = 'Moderate Comments'; - $helper->table = $this->name; - $helper->token = Tools::getAdminTokenLite('AdminModules'); - $helper->currentIndex = AdminController::$currentIndex.'&configure='.$this->name; + $helper = new HelperList(); + $helper->shopLinkType = ''; + $helper->simple_header = true; + $helper->actions = null; + $helper->show_toolbar = false; + $helper->module = $this; + $helper->listTotal = count($content); + $helper->identifier = 'id_product_comment'; + $helper->title = 'Moderate Comments'; + $helper->table = $this->name; + $helper->token = Tools::getAdminTokenLite('AdminModules'); + $helper->currentIndex = AdminController::$currentIndex.'&configure='.$this->name; - return $helper->generateList($content, $fields_list); - } + return $helper->generateList($content, $fields_list); + } - public function renderListWithParentClass() - { - $this->bulk_actions = array( - 'delete' => array( - 'text' => 'Delete selected', - 'confirm' => 'Delete selected items?', - 'icon' => 'icon-trash' - ) - ); - $this->fields_list = array( - 'id_carrier' => array( - 'title' => 'ID', - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'image' => array( - 'title' => 'Logo', - 'align' => 'center', - 'image' => 's', - 'class' => 'fixed-width-xs', - 'orderby' => false, - 'search' => false - ), - 'name' => array( - 'title' => 'Name' - ), - ); + public function renderListWithParentClass() + { + $this->bulk_actions = array( + 'delete' => array( + 'text' => 'Delete selected', + 'confirm' => 'Delete selected items?', + 'icon' => 'icon-trash' + ) + ); + $this->fields_list = array( + 'id_carrier' => array( + 'title' => 'ID', + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'image' => array( + 'title' => 'Logo', + 'align' => 'center', + 'image' => 's', + 'class' => 'fixed-width-xs', + 'orderby' => false, + 'search' => false + ), + 'name' => array( + 'title' => 'Name' + ), + ); - return parent::renderList(); - } + return parent::renderList(); + } - public function renderOptions() - { - $this->fields_options = array( - 'general' => array( - 'title' => 'General', - 'icon' => 'icon-cogs', - 'fields' => array(), - 'submit' => array('title' => 'Save') - ) - ); - return parent::renderOptions(); - } + public function renderOptions() + { + $this->fields_options = array( + 'general' => array( + 'title' => 'General', + 'icon' => 'icon-cogs', + 'fields' => array(), + 'submit' => array('title' => 'Save') + ) + ); + return parent::renderOptions(); + } - public function initContent() - { - $this->display = 'view'; - $this->page_header_toolbar_title = $this->toolbar_title = 'Patterns design sample'; + public function initContent() + { + $this->display = 'view'; + $this->page_header_toolbar_title = $this->toolbar_title = 'Patterns design sample'; - parent::initContent(); + parent::initContent(); - $this->content .= $this->renderForm(); - $this->content .= $this->renderList(); - $this->content .= $this->renderOptions(); + $this->content .= $this->renderForm(); + $this->content .= $this->renderList(); + $this->content .= $this->renderOptions(); - $this->context->smarty->assign(array('content' => $this->content)); - } + $this->context->smarty->assign(array('content' => $this->content)); + } } diff --git a/controllers/admin/AdminPaymentController.php b/controllers/admin/AdminPaymentController.php index 0c171895..fc9b603f 100644 --- a/controllers/admin/AdminPaymentController.php +++ b/controllers/admin/AdminPaymentController.php @@ -26,275 +26,288 @@ class AdminPaymentControllerCore extends AdminController { - public $payment_modules = array(); + public $payment_modules = array(); - public function __construct() - { - $this->bootstrap = true; - parent::__construct(); + public function __construct() + { + $this->bootstrap = true; + parent::__construct(); - $shop_id = Context::getContext()->shop->id; + $shop_id = Context::getContext()->shop->id; - /* Get all modules then select only payment ones */ - $modules = Module::getModulesOnDisk(true); + /* Get all modules then select only payment ones */ + $modules = Module::getModulesOnDisk(true); - foreach ($modules as $module) - if ($module->tab == 'payments_gateways') - { - if ($module->id) - { - if (!get_class($module) == 'SimpleXMLElement') - $module->country = array(); - $countries = DB::getInstance()->executeS(' + foreach ($modules as $module) { + if ($module->tab == 'payments_gateways') { + if ($module->id) { + if (!get_class($module) == 'SimpleXMLElement') { + $module->country = array(); + } + $countries = DB::getInstance()->executeS(' SELECT id_country FROM '._DB_PREFIX_.'module_country WHERE id_module = '.(int)$module->id.' AND `id_shop`='.(int)$shop_id - ); - foreach ($countries as $country) - $module->country[] = $country['id_country']; + ); + foreach ($countries as $country) { + $module->country[] = $country['id_country']; + } - if (!get_class($module) == 'SimpleXMLElement') - $module->currency = array(); - $currencies = DB::getInstance()->executeS(' + if (!get_class($module) == 'SimpleXMLElement') { + $module->currency = array(); + } + $currencies = DB::getInstance()->executeS(' SELECT id_currency FROM '._DB_PREFIX_.'module_currency WHERE id_module = '.(int)$module->id.' AND `id_shop`='.(int)$shop_id - ); - foreach ($currencies as $currency) - $module->currency[] = $currency['id_currency']; + ); + foreach ($currencies as $currency) { + $module->currency[] = $currency['id_currency']; + } - if (!get_class($module) == 'SimpleXMLElement') - $module->group = array(); - $groups = DB::getInstance()->executeS(' + if (!get_class($module) == 'SimpleXMLElement') { + $module->group = array(); + } + $groups = DB::getInstance()->executeS(' SELECT id_group FROM '._DB_PREFIX_.'module_group WHERE id_module = '.(int)$module->id.' AND `id_shop`='.(int)$shop_id - ); - foreach ($groups as $group) - $module->group[] = $group['id_group']; - } - else - { - $module->country = null; - $module->currency = null; - $module->group = null; - } + ); + foreach ($groups as $group) { + $module->group[] = $group['id_group']; + } + } else { + $module->country = null; + $module->currency = null; + $module->group = null; + } - $this->payment_modules[] = $module; - } - } + $this->payment_modules[] = $module; + } + } + } - public function initToolbarTitle() - { - $this->toolbar_title = array_unique($this->breadcrumbs); - } + public function initToolbarTitle() + { + $this->toolbar_title = array_unique($this->breadcrumbs); + } - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); - $this->page_header_toolbar_btn = array(); - } + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); + $this->page_header_toolbar_btn = array(); + } - public function postProcess() - { - if (Tools::getValue('action') == 'GetModuleQuickView' && Tools::getValue('ajax') == '1') - $this->ajaxProcessGetModuleQuickView(); - if ($this->action) - $this->saveRestrictions($this->action); - } + public function postProcess() + { + if (Tools::getValue('action') == 'GetModuleQuickView' && Tools::getValue('ajax') == '1') { + $this->ajaxProcessGetModuleQuickView(); + } + if ($this->action) { + $this->saveRestrictions($this->action); + } + } - public function initProcess() - { - if ($this->tabAccess['edit'] === '1') - { - if (Tools::isSubmit('submitModulecountry')) - $this->action = 'country'; - elseif (Tools::isSubmit('submitModulecurrency')) - $this->action = 'currency'; - elseif (Tools::isSubmit('submitModulegroup')) - $this->action = 'group'; - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } + public function initProcess() + { + if ($this->tabAccess['edit'] === '1') { + if (Tools::isSubmit('submitModulecountry')) { + $this->action = 'country'; + } elseif (Tools::isSubmit('submitModulecurrency')) { + $this->action = 'currency'; + } elseif (Tools::isSubmit('submitModulegroup')) { + $this->action = 'group'; + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } - protected function saveRestrictions($type) - { - // Delete type restrictions for active module. - $modules = array(); - foreach ($this->payment_modules as $module) - if ($module->active) - $modules[] = (int)$module->id; + protected function saveRestrictions($type) + { + // Delete type restrictions for active module. + $modules = array(); + foreach ($this->payment_modules as $module) { + if ($module->active) { + $modules[] = (int)$module->id; + } + } - Db::getInstance()->execute(' + Db::getInstance()->execute(' DELETE FROM `'._DB_PREFIX_.'module_'.bqSQL($type).'` WHERE id_shop = '.Context::getContext()->shop->id.' AND `id_module` IN ('.implode(', ', $modules).')' - ); + ); - // Fill the new restriction selection for active module. - $values = array(); - foreach ($this->payment_modules as $module) - if ($module->active && isset($_POST[$module->name.'_'.$type.''])) - foreach ($_POST[$module->name.'_'.$type.''] as $selected) - $values[] = '('.(int)$module->id.', '.(int)Context::getContext()->shop->id.', '.(int)$selected.')'; + // Fill the new restriction selection for active module. + $values = array(); + foreach ($this->payment_modules as $module) { + if ($module->active && isset($_POST[$module->name.'_'.$type.''])) { + foreach ($_POST[$module->name.'_'.$type.''] as $selected) { + $values[] = '('.(int)$module->id.', '.(int)Context::getContext()->shop->id.', '.(int)$selected.')'; + } + } + } - if (count($values)) - Db::getInstance()->execute(' + if (count($values)) { + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'module_'.bqSQL($type).'` (`id_module`, `id_shop`, `id_'.bqSQL($type).'`) VALUES '.implode(',', $values)); + } - Tools::redirectAdmin(self::$currentIndex.'&conf=4'.'&token='.$this->token); - } + Tools::redirectAdmin(self::$currentIndex.'&conf=4'.'&token='.$this->token); + } - public function initContent() - { - $this->display = 'view'; - return parent::initContent(); - } + public function initContent() + { + $this->display = 'view'; + return parent::initContent(); + } - public function setMedia() - { - parent::setMedia(); - $this->addJqueryPlugin('fancybox'); - } + public function setMedia() + { + parent::setMedia(); + $this->addJqueryPlugin('fancybox'); + } - public function renderView() - { - $this->toolbar_title = $this->l('Payment'); - unset($this->toolbar_btn['back']); + public function renderView() + { + $this->toolbar_title = $this->l('Payment'); + unset($this->toolbar_btn['back']); - $shop_context = (!Shop::isFeatureActive() || Shop::getContext() == Shop::CONTEXT_SHOP); - if (!$shop_context) - { - $this->tpl_view_vars = array('shop_context' => $shop_context); - return parent::renderView(); - } + $shop_context = (!Shop::isFeatureActive() || Shop::getContext() == Shop::CONTEXT_SHOP); + if (!$shop_context) { + $this->tpl_view_vars = array('shop_context' => $shop_context); + return parent::renderView(); + } - // link to modules page - if (isset($this->payment_modules[0])) - $token_modules = Tools::getAdminToken('AdminModules'.(int)Tab::getIdFromClassName('AdminModules').(int)$this->context->employee->id); + // link to modules page + if (isset($this->payment_modules[0])) { + $token_modules = Tools::getAdminToken('AdminModules'.(int)Tab::getIdFromClassName('AdminModules').(int)$this->context->employee->id); + } - $display_restrictions = false; - foreach ($this->payment_modules as $module) - if ($module->active) - { - $display_restrictions = true; - break; - } + $display_restrictions = false; + foreach ($this->payment_modules as $module) { + if ($module->active) { + $display_restrictions = true; + break; + } + } - $lists = array( - array('items' => Currency::getCurrencies(), - 'title' => $this->l('Currency restrictions'), - 'desc' => $this->l('Please mark each checkbox for the currency, or currencies, in which you want the payment module(s) to be available.'), - 'name_id' => 'currency', - 'identifier' => 'id_currency', - 'icon' => 'icon-money', - ), - array('items' => Group::getGroups($this->context->language->id), - 'title' => $this->l('Group restrictions'), - 'desc' => $this->l('Please mark each checkbox for the customer group(s), in which you want the payment module(s) to be available.'), - 'name_id' => 'group', - 'identifier' => 'id_group', - 'icon' => 'icon-group', - ), - array('items' =>Country::getCountries($this->context->language->id), - 'title' => $this->l('Country restrictions'), - 'desc' => $this->l('Please mark each checkbox for the country, or countries, in which you want the payment module(s) to be available.'), - 'name_id' => 'country', - 'identifier' => 'id_country', - 'icon' => 'icon-globe', - ) - ); + $lists = array( + array('items' => Currency::getCurrencies(), + 'title' => $this->l('Currency restrictions'), + 'desc' => $this->l('Please mark each checkbox for the currency, or currencies, in which you want the payment module(s) to be available.'), + 'name_id' => 'currency', + 'identifier' => 'id_currency', + 'icon' => 'icon-money', + ), + array('items' => Group::getGroups($this->context->language->id), + 'title' => $this->l('Group restrictions'), + 'desc' => $this->l('Please mark each checkbox for the customer group(s), in which you want the payment module(s) to be available.'), + 'name_id' => 'group', + 'identifier' => 'id_group', + 'icon' => 'icon-group', + ), + array('items' =>Country::getCountries($this->context->language->id), + 'title' => $this->l('Country restrictions'), + 'desc' => $this->l('Please mark each checkbox for the country, or countries, in which you want the payment module(s) to be available.'), + 'name_id' => 'country', + 'identifier' => 'id_country', + 'icon' => 'icon-globe', + ) + ); - foreach ($lists as $key_list => $list) - { - $list['check_list'] = array(); - foreach ($list['items'] as $key_item => $item) - { - $name_id = $list['name_id']; + foreach ($lists as $key_list => $list) { + $list['check_list'] = array(); + foreach ($list['items'] as $key_item => $item) { + $name_id = $list['name_id']; - if ($name_id === 'currency' - && Tools::strpos($list['items'][$key_item]['name'], '('.$list['items'][$key_item]['iso_code'].')') === false) - $list['items'][$key_item]['name'] = sprintf($this->l('%1$s (%2$s)'), $list['items'][$key_item]['name'], - $list['items'][$key_item]['iso_code']); + if ($name_id === 'currency' + && Tools::strpos($list['items'][$key_item]['name'], '('.$list['items'][$key_item]['iso_code'].')') === false) { + $list['items'][$key_item]['name'] = sprintf($this->l('%1$s (%2$s)'), $list['items'][$key_item]['name'], + $list['items'][$key_item]['iso_code']); + } - foreach ($this->payment_modules as $key_module => $module) - { - if (isset($module->$name_id) && in_array($item['id_'.$name_id], $module->$name_id)) - $list['items'][$key_item]['check_list'][$key_module] = 'checked'; - else - $list['items'][$key_item]['check_list'][$key_module] = 'unchecked'; + foreach ($this->payment_modules as $key_module => $module) { + if (isset($module->$name_id) && in_array($item['id_'.$name_id], $module->$name_id)) { + $list['items'][$key_item]['check_list'][$key_module] = 'checked'; + } else { + $list['items'][$key_item]['check_list'][$key_module] = 'unchecked'; + } - if (!isset($module->$name_id)) - $module->$name_id = array(); - if (!isset($module->currencies_mode)) - $module->currencies_mode = ''; - if (!isset($module->currencies)) - $module->currencies = ''; + if (!isset($module->$name_id)) { + $module->$name_id = array(); + } + if (!isset($module->currencies_mode)) { + $module->currencies_mode = ''; + } + if (!isset($module->currencies)) { + $module->currencies = ''; + } - // If is a country list and the country is limited, remove it from list - if ($name_id == 'country' - && isset($module->limited_countries) - && !empty($module->limited_countries) - && is_array($module->limited_countries) - && !(in_array(strtoupper($item['iso_code']), array_map('strtoupper', $module->limited_countries)))) - $list['items'][$key_item]['check_list'][$key_module] = null; - } - } - // update list - $lists[$key_list] = $list; - } + // If is a country list and the country is limited, remove it from list + if ($name_id == 'country' + && isset($module->limited_countries) + && !empty($module->limited_countries) + && is_array($module->limited_countries) + && !(in_array(strtoupper($item['iso_code']), array_map('strtoupper', $module->limited_countries)))) { + $list['items'][$key_item]['check_list'][$key_module] = null; + } + } + } + // update list + $lists[$key_list] = $list; + } - $this->tpl_view_vars = array( - 'modules_list' => $this->renderModulesList(), - 'display_restrictions' => $display_restrictions, - 'lists' => $lists, - 'ps_base_uri' => __PS_BASE_URI__, - 'payment_modules' => $this->payment_modules, - 'url_submit' => self::$currentIndex.'&token='.$this->token, - 'shop_context' => $shop_context - ); + $this->tpl_view_vars = array( + 'modules_list' => $this->renderModulesList(), + 'display_restrictions' => $display_restrictions, + 'lists' => $lists, + 'ps_base_uri' => __PS_BASE_URI__, + 'payment_modules' => $this->payment_modules, + 'url_submit' => self::$currentIndex.'&token='.$this->token, + 'shop_context' => $shop_context + ); - return parent::renderView(); - } + return parent::renderView(); + } - public function renderModulesList() - { - if ($this->getModulesList($this->filter_modules_list)) - { - $active_list = array(); - foreach ($this->modules_list as $key => $module) - { - if (in_array($module->name, $this->list_partners_modules)) - $this->modules_list[$key]->type = 'addonsPartner'; - if (isset($module->description_full) && trim($module->description_full) != '') - $module->show_quick_view = true; + public function renderModulesList() + { + if ($this->getModulesList($this->filter_modules_list)) { + $active_list = array(); + foreach ($this->modules_list as $key => $module) { + if (in_array($module->name, $this->list_partners_modules)) { + $this->modules_list[$key]->type = 'addonsPartner'; + } + if (isset($module->description_full) && trim($module->description_full) != '') { + $module->show_quick_view = true; + } - if ($module->active) - $active_list[] = $module; - else - $unactive_list[] = $module; - } + if ($module->active) { + $active_list[] = $module; + } else { + $unactive_list[] = $module; + } + } - $helper = new Helper(); - $fetch = ''; + $helper = new Helper(); + $fetch = ''; - if (isset($active_list)) - { - $this->context->smarty->assign('panel_title', $this->l('Active payment')); - $fetch = $helper->renderModulesList($active_list); - } + if (isset($active_list)) { + $this->context->smarty->assign('panel_title', $this->l('Active payment')); + $fetch = $helper->renderModulesList($active_list); + } - $this->context->smarty->assign(array( - 'panel_title' => $this->l('Recommended payment gateways'), - 'view_all' => true - )); - $fetch .= $helper->renderModulesList($unactive_list); - return $fetch; - } - } + $this->context->smarty->assign(array( + 'panel_title' => $this->l('Recommended payment gateways'), + 'view_all' => true + )); + $fetch .= $helper->renderModulesList($unactive_list); + return $fetch; + } + } } - diff --git a/controllers/admin/AdminPdfController.php b/controllers/admin/AdminPdfController.php index d3ad4265..135e1bd2 100644 --- a/controllers/admin/AdminPdfController.php +++ b/controllers/admin/AdminPdfController.php @@ -26,171 +26,187 @@ class AdminPdfControllerCore extends AdminController { - public function postProcess() - { - parent::postProcess(); + public function postProcess() + { + parent::postProcess(); - // We want to be sure that displaying PDF is the last thing this controller will do - exit; - } + // We want to be sure that displaying PDF is the last thing this controller will do + exit; + } - public function initProcess() - { - parent::initProcess(); - $this->checkCacheFolder(); - $access = Profile::getProfileAccess($this->context->employee->id_profile, (int)Tab::getIdFromClassName('AdminOrders')); - if ($access['view'] === '1' && ($action = Tools::getValue('submitAction'))) - $this->action = $action; - else - $this->errors[] = Tools::displayError('You do not have permission to view this.'); - } + public function initProcess() + { + parent::initProcess(); + $this->checkCacheFolder(); + $access = Profile::getProfileAccess($this->context->employee->id_profile, (int)Tab::getIdFromClassName('AdminOrders')); + if ($access['view'] === '1' && ($action = Tools::getValue('submitAction'))) { + $this->action = $action; + } else { + $this->errors[] = Tools::displayError('You do not have permission to view this.'); + } + } - public function checkCacheFolder() - { - if (!is_dir(_PS_CACHE_DIR_.'tcpdf/')) - mkdir(_PS_CACHE_DIR_.'tcpdf/'); - } + public function checkCacheFolder() + { + if (!is_dir(_PS_CACHE_DIR_.'tcpdf/')) { + mkdir(_PS_CACHE_DIR_.'tcpdf/'); + } + } - public function processGenerateInvoicePdf() - { - if (Tools::isSubmit('id_order')) - $this->generateInvoicePDFByIdOrder(Tools::getValue('id_order')); - elseif (Tools::isSubmit('id_order_invoice')) - $this->generateInvoicePDFByIdOrderInvoice(Tools::getValue('id_order_invoice')); - else - die (Tools::displayError('The order ID -- or the invoice order ID -- is missing.')); - } + public function processGenerateInvoicePdf() + { + if (Tools::isSubmit('id_order')) { + $this->generateInvoicePDFByIdOrder(Tools::getValue('id_order')); + } elseif (Tools::isSubmit('id_order_invoice')) { + $this->generateInvoicePDFByIdOrderInvoice(Tools::getValue('id_order_invoice')); + } else { + die(Tools::displayError('The order ID -- or the invoice order ID -- is missing.')); + } + } - public function processGenerateOrderSlipPDF() - { - $order_slip = new OrderSlip((int)Tools::getValue('id_order_slip')); - $order = new Order((int)$order_slip->id_order); + public function processGenerateOrderSlipPDF() + { + $order_slip = new OrderSlip((int)Tools::getValue('id_order_slip')); + $order = new Order((int)$order_slip->id_order); - if (!Validate::isLoadedObject($order)) - die(Tools::displayError('The order cannot be found within your database.')); + if (!Validate::isLoadedObject($order)) { + die(Tools::displayError('The order cannot be found within your database.')); + } - $order->products = OrderSlip::getOrdersSlipProducts($order_slip->id, $order); - $this->generatePDF($order_slip, PDF::TEMPLATE_ORDER_SLIP); - } + $order->products = OrderSlip::getOrdersSlipProducts($order_slip->id, $order); + $this->generatePDF($order_slip, PDF::TEMPLATE_ORDER_SLIP); + } - public function processGenerateDeliverySlipPDF() - { - if (Tools::isSubmit('id_order')) - $this->generateDeliverySlipPDFByIdOrder((int)Tools::getValue('id_order')); - elseif (Tools::isSubmit('id_order_invoice')) - $this->generateDeliverySlipPDFByIdOrderInvoice((int)Tools::getValue('id_order_invoice')); - elseif (Tools::isSubmit('id_delivery')) - { - $order = Order::getByDelivery((int)Tools::getValue('id_delivery')); - $this->generateDeliverySlipPDFByIdOrder((int)$order->id); - } - else - die (Tools::displayError('The order ID -- or the invoice order ID -- is missing.')); - } + public function processGenerateDeliverySlipPDF() + { + if (Tools::isSubmit('id_order')) { + $this->generateDeliverySlipPDFByIdOrder((int)Tools::getValue('id_order')); + } elseif (Tools::isSubmit('id_order_invoice')) { + $this->generateDeliverySlipPDFByIdOrderInvoice((int)Tools::getValue('id_order_invoice')); + } elseif (Tools::isSubmit('id_delivery')) { + $order = Order::getByDelivery((int)Tools::getValue('id_delivery')); + $this->generateDeliverySlipPDFByIdOrder((int)$order->id); + } else { + die(Tools::displayError('The order ID -- or the invoice order ID -- is missing.')); + } + } - public function processGenerateInvoicesPDF() - { - $order_invoice_collection = OrderInvoice::getByDateInterval(Tools::getValue('date_from'), Tools::getValue('date_to')); + public function processGenerateInvoicesPDF() + { + $order_invoice_collection = OrderInvoice::getByDateInterval(Tools::getValue('date_from'), Tools::getValue('date_to')); - if (!count($order_invoice_collection)) - die(Tools::displayError('No invoice was found.')); + if (!count($order_invoice_collection)) { + die(Tools::displayError('No invoice was found.')); + } - $this->generatePDF($order_invoice_collection, PDF::TEMPLATE_INVOICE); - } + $this->generatePDF($order_invoice_collection, PDF::TEMPLATE_INVOICE); + } - public function processGenerateInvoicesPDF2() - { - $order_invoice_collection = array(); - foreach (explode('-', Tools::getValue('id_order_state')) as $id_order_state) - if (is_array($order_invoices = OrderInvoice::getByStatus((int)$id_order_state))) - $order_invoice_collection = array_merge($order_invoices, $order_invoice_collection); + public function processGenerateInvoicesPDF2() + { + $order_invoice_collection = array(); + foreach (explode('-', Tools::getValue('id_order_state')) as $id_order_state) { + if (is_array($order_invoices = OrderInvoice::getByStatus((int)$id_order_state))) { + $order_invoice_collection = array_merge($order_invoices, $order_invoice_collection); + } + } - if (!count($order_invoice_collection)) - die(Tools::displayError('No invoice was found.')); + if (!count($order_invoice_collection)) { + die(Tools::displayError('No invoice was found.')); + } - $this->generatePDF($order_invoice_collection, PDF::TEMPLATE_INVOICE); - } + $this->generatePDF($order_invoice_collection, PDF::TEMPLATE_INVOICE); + } - public function processGenerateOrderSlipsPDF() - { - $id_order_slips_list = OrderSlip::getSlipsIdByDate(Tools::getValue('date_from'), Tools::getValue('date_to')); - if (!count($id_order_slips_list)) - die (Tools::displayError('No order slips were found.')); + public function processGenerateOrderSlipsPDF() + { + $id_order_slips_list = OrderSlip::getSlipsIdByDate(Tools::getValue('date_from'), Tools::getValue('date_to')); + if (!count($id_order_slips_list)) { + die(Tools::displayError('No order slips were found.')); + } - $order_slips = array(); - foreach ($id_order_slips_list as $id_order_slips) - $order_slips[] = new OrderSlip((int)$id_order_slips); + $order_slips = array(); + foreach ($id_order_slips_list as $id_order_slips) { + $order_slips[] = new OrderSlip((int)$id_order_slips); + } - $this->generatePDF($order_slips, PDF::TEMPLATE_ORDER_SLIP); - } + $this->generatePDF($order_slips, PDF::TEMPLATE_ORDER_SLIP); + } - public function processGenerateDeliverySlipsPDF() - { - $order_invoice_collection = OrderInvoice::getByDeliveryDateInterval(Tools::getValue('date_from'), Tools::getValue('date_to')); + public function processGenerateDeliverySlipsPDF() + { + $order_invoice_collection = OrderInvoice::getByDeliveryDateInterval(Tools::getValue('date_from'), Tools::getValue('date_to')); - if (!count($order_invoice_collection)) - die(Tools::displayError('No invoice was found.')); + if (!count($order_invoice_collection)) { + die(Tools::displayError('No invoice was found.')); + } - $this->generatePDF($order_invoice_collection, PDF::TEMPLATE_DELIVERY_SLIP); - } + $this->generatePDF($order_invoice_collection, PDF::TEMPLATE_DELIVERY_SLIP); + } - public function processGenerateSupplyOrderFormPDF() - { - if (!Tools::isSubmit('id_supply_order')) - die (Tools::displayError('The supply order ID is missing.')); + public function processGenerateSupplyOrderFormPDF() + { + if (!Tools::isSubmit('id_supply_order')) { + die(Tools::displayError('The supply order ID is missing.')); + } - $id_supply_order = (int)Tools::getValue('id_supply_order'); - $supply_order = new SupplyOrder($id_supply_order); + $id_supply_order = (int)Tools::getValue('id_supply_order'); + $supply_order = new SupplyOrder($id_supply_order); - if (!Validate::isLoadedObject($supply_order)) - die(Tools::displayError('The supply order cannot be found within your database.')); + if (!Validate::isLoadedObject($supply_order)) { + die(Tools::displayError('The supply order cannot be found within your database.')); + } - $this->generatePDF($supply_order, PDF::TEMPLATE_SUPPLY_ORDER_FORM); - } + $this->generatePDF($supply_order, PDF::TEMPLATE_SUPPLY_ORDER_FORM); + } - public function generateDeliverySlipPDFByIdOrder($id_order) - { - $order = new Order((int)$id_order); - if (!Validate::isLoadedObject($order)) - throw new PrestaShopException('Can\'t load Order object'); + public function generateDeliverySlipPDFByIdOrder($id_order) + { + $order = new Order((int)$id_order); + if (!Validate::isLoadedObject($order)) { + throw new PrestaShopException('Can\'t load Order object'); + } - $order_invoice_collection = $order->getInvoicesCollection(); - $this->generatePDF($order_invoice_collection, PDF::TEMPLATE_DELIVERY_SLIP); - } + $order_invoice_collection = $order->getInvoicesCollection(); + $this->generatePDF($order_invoice_collection, PDF::TEMPLATE_DELIVERY_SLIP); + } - public function generateDeliverySlipPDFByIdOrderInvoice($id_order_invoice) - { - $order_invoice = new OrderInvoice((int)$id_order_invoice); - if (!Validate::isLoadedObject($order_invoice)) - throw new PrestaShopException('Can\'t load Order Invoice object'); + public function generateDeliverySlipPDFByIdOrderInvoice($id_order_invoice) + { + $order_invoice = new OrderInvoice((int)$id_order_invoice); + if (!Validate::isLoadedObject($order_invoice)) { + throw new PrestaShopException('Can\'t load Order Invoice object'); + } - $this->generatePDF($order_invoice, PDF::TEMPLATE_DELIVERY_SLIP); - } + $this->generatePDF($order_invoice, PDF::TEMPLATE_DELIVERY_SLIP); + } - public function generateInvoicePDFByIdOrder($id_order) - { - $order = new Order((int)$id_order); - if (!Validate::isLoadedObject($order)) - die(Tools::displayError('The order cannot be found within your database.')); + public function generateInvoicePDFByIdOrder($id_order) + { + $order = new Order((int)$id_order); + if (!Validate::isLoadedObject($order)) { + die(Tools::displayError('The order cannot be found within your database.')); + } - $order_invoice_list = $order->getInvoicesCollection(); - Hook::exec('actionPDFInvoiceRender', array('order_invoice_list' => $order_invoice_list)); - $this->generatePDF($order_invoice_list, PDF::TEMPLATE_INVOICE); - } + $order_invoice_list = $order->getInvoicesCollection(); + Hook::exec('actionPDFInvoiceRender', array('order_invoice_list' => $order_invoice_list)); + $this->generatePDF($order_invoice_list, PDF::TEMPLATE_INVOICE); + } - public function generateInvoicePDFByIdOrderInvoice($id_order_invoice) - { - $order_invoice = new OrderInvoice((int)$id_order_invoice); - if (!Validate::isLoadedObject($order_invoice)) - die(Tools::displayError('The order invoice cannot be found within your database.')); + public function generateInvoicePDFByIdOrderInvoice($id_order_invoice) + { + $order_invoice = new OrderInvoice((int)$id_order_invoice); + if (!Validate::isLoadedObject($order_invoice)) { + die(Tools::displayError('The order invoice cannot be found within your database.')); + } - Hook::exec('actionPDFInvoiceRender', array('order_invoice_list' => array($order_invoice))); - $this->generatePDF($order_invoice, PDF::TEMPLATE_INVOICE); - } + Hook::exec('actionPDFInvoiceRender', array('order_invoice_list' => array($order_invoice))); + $this->generatePDF($order_invoice, PDF::TEMPLATE_INVOICE); + } - public function generatePDF($object, $template) - { - $pdf = new PDF($object, $template, Context::getContext()->smarty); - $pdf->render(); - } + public function generatePDF($object, $template) + { + $pdf = new PDF($object, $template, Context::getContext()->smarty); + $pdf->render(); + } } diff --git a/controllers/admin/AdminPerformanceController.php b/controllers/admin/AdminPerformanceController.php index 798cf4d6..664b206b 100644 --- a/controllers/admin/AdminPerformanceController.php +++ b/controllers/admin/AdminPerformanceController.php @@ -29,1008 +29,1000 @@ */ class AdminPerformanceControllerCore extends AdminController { + public function __construct() + { + $this->bootstrap = true; + $this->className = 'Configuration'; + parent::__construct(); + } - public function __construct() - { - $this->bootstrap = true; - $this->className = 'Configuration'; - parent::__construct(); - } + public function initFieldsetSmarty() + { + $this->fields_form[0]['form'] = array( + 'legend' => array( + 'title' => $this->l('Smarty'), + 'icon' => 'icon-briefcase' + ), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'smarty_up' + ), + array( + 'type' => 'radio', + 'label' => $this->l('Template compilation'), + 'name' => 'smarty_force_compile', + 'values' => array( + array( + 'id' => 'smarty_force_compile_'._PS_SMARTY_NO_COMPILE_, + 'value' => _PS_SMARTY_NO_COMPILE_, + 'label' => $this->l('Never recompile template files'), + 'hint' => $this->l('This option should be used in a production environment.') + ), + array( + 'id' => 'smarty_force_compile_'._PS_SMARTY_CHECK_COMPILE_, + 'value' => _PS_SMARTY_CHECK_COMPILE_, + 'label' => $this->l('Recompile templates if the files have been updated'), + 'hint' => $this->l('Templates are recompiled when they are updated. If you experience compilation troubles when you update your template files, you should use Force Compile instead of this option. It should never be used in a production environment.') + ), + array( + 'id' => 'smarty_force_compile_'._PS_SMARTY_FORCE_COMPILE_, + 'value' => _PS_SMARTY_FORCE_COMPILE_, + 'label' => $this->l('Force compilation'), + 'hint' => $this->l('This forces Smarty to (re)compile templates on every invocation. This is handy for development and debugging. Note: This should never be used in a production environment.') + ) + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Cache'), + 'name' => 'smarty_cache', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'smarty_cache_1', + 'value' => 1, + 'label' => $this->l('Yes'), + ), + array( + 'id' => 'smarty_cache_0', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + 'hint' => $this->l('Should be enabled except for debugging.') + ), + array( + 'type' => 'radio', + 'label' => $this->l('Caching type'), + 'name' => 'smarty_caching_type', + 'values' => array( + array( + 'id' => 'smarty_caching_type_filesystem', + 'value' => 'filesystem', + 'label' => $this->l('File System').(is_writable(_PS_CACHE_DIR_.'smarty/cache') ? '' : ' '.sprintf($this->l('(the directory %s must be writable)'), realpath(_PS_CACHE_DIR_.'smarty/cache'))) + ), + array( + 'id' => 'smarty_caching_type_mysql', + 'value' => 'mysql', + 'label' => $this->l('MySQL') + ), - public function initFieldsetSmarty() - { - $this->fields_form[0]['form'] = array( - 'legend' => array( - 'title' => $this->l('Smarty'), - 'icon' => 'icon-briefcase' - ), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'smarty_up' - ), - array( - 'type' => 'radio', - 'label' => $this->l('Template compilation'), - 'name' => 'smarty_force_compile', - 'values' => array( - array( - 'id' => 'smarty_force_compile_'._PS_SMARTY_NO_COMPILE_, - 'value' => _PS_SMARTY_NO_COMPILE_, - 'label' => $this->l('Never recompile template files'), - 'hint' => $this->l('This option should be used in a production environment.') - ), - array( - 'id' => 'smarty_force_compile_'._PS_SMARTY_CHECK_COMPILE_, - 'value' => _PS_SMARTY_CHECK_COMPILE_, - 'label' => $this->l('Recompile templates if the files have been updated'), - 'hint' => $this->l('Templates are recompiled when they are updated. If you experience compilation troubles when you update your template files, you should use Force Compile instead of this option. It should never be used in a production environment.') - ), - array( - 'id' => 'smarty_force_compile_'._PS_SMARTY_FORCE_COMPILE_, - 'value' => _PS_SMARTY_FORCE_COMPILE_, - 'label' => $this->l('Force compilation'), - 'hint' => $this->l('This forces Smarty to (re)compile templates on every invocation. This is handy for development and debugging. Note: This should never be used in a production environment.') - ) - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Cache'), - 'name' => 'smarty_cache', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'smarty_cache_1', - 'value' => 1, - 'label' => $this->l('Yes'), - ), - array( - 'id' => 'smarty_cache_0', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - 'hint' => $this->l('Should be enabled except for debugging.') - ), - array( - 'type' => 'radio', - 'label' => $this->l('Caching type'), - 'name' => 'smarty_caching_type', - 'values' => array( - array( - 'id' => 'smarty_caching_type_filesystem', - 'value' => 'filesystem', - 'label' => $this->l('File System').(is_writable(_PS_CACHE_DIR_.'smarty/cache') ? '' : ' '.sprintf($this->l('(the directory %s must be writable)'), realpath(_PS_CACHE_DIR_.'smarty/cache'))) - ), - array( - 'id' => 'smarty_caching_type_mysql', - 'value' => 'mysql', - 'label' => $this->l('MySQL') - ), + ) + ), + array( + 'type' => 'radio', + 'label' => $this->l('Clear cache'), + 'name' => 'smarty_clear_cache', + 'values' => array( + array( + 'id' => 'smarty_clear_cache_never', + 'value' => 'never', + 'label' => $this->l('Never clear cache files'), + ), + array( + 'id' => 'smarty_clear_cache_everytime', + 'value' => 'everytime', + 'label' => $this->l('Clear cache everytime something has been modified'), + ), + ) + ), + ), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); - ) - ), - array( - 'type' => 'radio', - 'label' => $this->l('Clear cache'), - 'name' => 'smarty_clear_cache', - 'values' => array( - array( - 'id' => 'smarty_clear_cache_never', - 'value' => 'never', - 'label' => $this->l('Never clear cache files'), - ), - array( - 'id' => 'smarty_clear_cache_everytime', - 'value' => 'everytime', - 'label' => $this->l('Clear cache everytime something has been modified'), - ), - ) - ), - ), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); + $this->fields_value['smarty_force_compile'] = Configuration::get('PS_SMARTY_FORCE_COMPILE'); + $this->fields_value['smarty_cache'] = Configuration::get('PS_SMARTY_CACHE'); + $this->fields_value['smarty_caching_type'] = Configuration::get('PS_SMARTY_CACHING_TYPE'); + $this->fields_value['smarty_clear_cache'] = Configuration::get('PS_SMARTY_CLEAR_CACHE'); + $this->fields_value['smarty_console'] = Configuration::get('PS_SMARTY_CONSOLE'); + $this->fields_value['smarty_console_key'] = Configuration::get('PS_SMARTY_CONSOLE_KEY'); + } - $this->fields_value['smarty_force_compile'] = Configuration::get('PS_SMARTY_FORCE_COMPILE'); - $this->fields_value['smarty_cache'] = Configuration::get('PS_SMARTY_CACHE'); - $this->fields_value['smarty_caching_type'] = Configuration::get('PS_SMARTY_CACHING_TYPE'); - $this->fields_value['smarty_clear_cache'] = Configuration::get('PS_SMARTY_CLEAR_CACHE'); - $this->fields_value['smarty_console'] = Configuration::get('PS_SMARTY_CONSOLE'); - $this->fields_value['smarty_console_key'] = Configuration::get('PS_SMARTY_CONSOLE_KEY'); - } + public function initFieldsetDebugMode() + { + $this->fields_form[1]['form'] = array( + 'legend' => array( + 'title' => $this->l('Debug mode'), + 'icon' => 'icon-bug' + ), + 'input' => array( + array( + 'type' => 'switch', + 'label' => $this->l('Disable non PrestaShop modules'), + 'name' => 'native_module', + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'native_module_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'native_module_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Enable or disable non PrestaShop Modules.') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Disable all overrides'), + 'name' => 'overrides', + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'overrides_module_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'overrides_module_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Enable or disable all classes and controllers overrides.') + ), + ), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); - public function initFieldsetDebugMode() - { - $this->fields_form[1]['form'] = array( - 'legend' => array( - 'title' => $this->l('Debug mode'), - 'icon' => 'icon-bug' - ), - 'input' => array( - array( - 'type' => 'switch', - 'label' => $this->l('Disable non PrestaShop modules'), - 'name' => 'native_module', - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'native_module_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'native_module_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Enable or disable non PrestaShop Modules.') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Disable all overrides'), - 'name' => 'overrides', - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'overrides_module_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'overrides_module_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Enable or disable all classes and controllers overrides.') - ), - ), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); + $this->fields_value['native_module'] = Configuration::get('PS_DISABLE_NON_NATIVE_MODULE'); + $this->fields_value['overrides'] = Configuration::get('PS_DISABLE_OVERRIDES'); + } - $this->fields_value['native_module'] = Configuration::get('PS_DISABLE_NON_NATIVE_MODULE'); - $this->fields_value['overrides'] = Configuration::get('PS_DISABLE_OVERRIDES'); - } + public function initFieldsetFeaturesDetachables() + { + $this->fields_form[2]['form'] = array( + 'legend' => array( + 'title' => $this->l('Optional features'), + 'icon' => 'icon-puzzle-piece' + ), + 'description' => $this->l('Some features can be disabled in order to improve performance.'), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'features_detachables_up' + ), + array( + 'type' => 'switch', + 'label' => $this->l('Combinations'), + 'name' => 'combination', + 'is_bool' => true, + 'disabled' => Combination::isCurrentlyUsed(), + 'values' => array( + array( + 'id' => 'combination_1', + 'value' => 1, + 'label' => $this->l('Yes'), + ), + array( + 'id' => 'combination_0', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + 'hint' => $this->l('Choose "No" to disable Product Combinations.'), + 'desc' => Combination::isCurrentlyUsed() ? $this->l('You cannot set this parameter to No when combinations are already used by some of your products') : null + ), + array( + 'type' => 'switch', + 'label' => $this->l('Features'), + 'name' => 'feature', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'feature_1', + 'value' => 1, + 'label' => $this->l('Yes'), + ), + array( + 'id' => 'feature_0', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + 'hint' => $this->l('Choose "No" to disable Product Features.') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Customer Groups'), + 'name' => 'customer_group', + 'is_bool' => true, + 'disabled' => Group::isCurrentlyUsed(), + 'values' => array( + array( + 'id' => 'group_1', + 'value' => 1, + 'label' => $this->l('Yes'), + ), + array( + 'id' => 'group_0', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + 'hint' => $this->l('Choose "No" to disable Customer Groups.') + ) + ), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); - public function initFieldsetFeaturesDetachables() - { - $this->fields_form[2]['form'] = array( - 'legend' => array( - 'title' => $this->l('Optional features'), - 'icon' => 'icon-puzzle-piece' - ), - 'description' => $this->l('Some features can be disabled in order to improve performance.'), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'features_detachables_up' - ), - array( - 'type' => 'switch', - 'label' => $this->l('Combinations'), - 'name' => 'combination', - 'is_bool' => true, - 'disabled' => Combination::isCurrentlyUsed(), - 'values' => array( - array( - 'id' => 'combination_1', - 'value' => 1, - 'label' => $this->l('Yes'), - ), - array( - 'id' => 'combination_0', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - 'hint' => $this->l('Choose "No" to disable Product Combinations.'), - 'desc' => Combination::isCurrentlyUsed() ? $this->l('You cannot set this parameter to No when combinations are already used by some of your products') : null - ), - array( - 'type' => 'switch', - 'label' => $this->l('Features'), - 'name' => 'feature', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'feature_1', - 'value' => 1, - 'label' => $this->l('Yes'), - ), - array( - 'id' => 'feature_0', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - 'hint' => $this->l('Choose "No" to disable Product Features.') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Customer Groups'), - 'name' => 'customer_group', - 'is_bool' => true, - 'disabled' => Group::isCurrentlyUsed(), - 'values' => array( - array( - 'id' => 'group_1', - 'value' => 1, - 'label' => $this->l('Yes'), - ), - array( - 'id' => 'group_0', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - 'hint' => $this->l('Choose "No" to disable Customer Groups.') - ) - ), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); + $this->fields_value['combination'] = Combination::isFeatureActive(); + $this->fields_value['feature'] = Feature::isFeatureActive(); + $this->fields_value['customer_group'] = Group::isFeatureActive(); + } - $this->fields_value['combination'] = Combination::isFeatureActive(); - $this->fields_value['feature'] = Feature::isFeatureActive(); - $this->fields_value['customer_group'] = Group::isFeatureActive(); - } + public function initFieldsetCCC() + { + $this->fields_form[3]['form'] = array( + 'legend' => array( + 'title' => $this->l('CCC (Combine, Compress and Cache)'), + 'icon' => 'icon-fullscreen' + ), + 'description' => $this->l('CCC allows you to reduce the loading time of your page. With these settings you will gain performance without even touching the code of your theme. Make sure, however, that your theme is compatible with PrestaShop 1.4+. Otherwise, CCC will cause problems.'), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'ccc_up', + ), + array( + 'type' => 'switch', + 'label' => $this->l('Smart cache for CSS'), + 'name' => 'PS_CSS_THEME_CACHE', + 'values' => array( + array( + 'id' => 'PS_CSS_THEME_CACHE_1', + 'value' => 1, + 'label' => $this->l('Use CCC for CSS') + ), + array( + 'id' => 'PS_CSS_THEME_CACHE_0', + 'value' => 0, + 'label' => $this->l('Keep CSS as original') + ) + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Smart cache for JavaScript'), + 'name' => 'PS_JS_THEME_CACHE', + 'values' => array( + array( + 'id' => 'PS_JS_THEME_CACHE_1', + 'value' => 1, + 'label' => $this->l('Use CCC for JavaScript') + ), + array( + 'id' => 'PS_JS_THEME_CACHE_0', + 'value' => 0, + 'label' => $this->l('Keep JavaScript as original') + ) + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Minify HTML'), + 'name' => 'PS_HTML_THEME_COMPRESSION', + 'values' => array( + array( + 'id' => 'PS_HTML_THEME_COMPRESSION_1', + 'value' => 1, + 'label' => $this->l('Minify HTML after "Smarty compile" execution') + ), + array( + 'id' => 'PS_HTML_THEME_COMPRESSION_0', + 'value' => 0, + 'label' => $this->l('Keep HTML as original') + ) + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Compress inline JavaScript in HTML'), + 'name' => 'PS_JS_HTML_THEME_COMPRESSION', + 'values' => array( + array( + 'id' => 'PS_JS_HTML_THEME_COMPRESSION_1', + 'value' => 1, + 'label' => $this->l('Compress inline JavaScript in HTML after "Smarty compile" execution') + ), + array( + 'id' => 'PS_JS_HTML_THEME_COMPRESSION_0', + 'value' => 0, + 'label' => $this->l('Keep inline JavaScript in HTML as original') + ) + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Move JavaScript to the end'), + 'name' => 'PS_JS_DEFER', + 'values' => array( + array( + 'id' => 'PS_JS_DEFER_1', + 'value' => 1, + 'label' => $this->l('Move JavaScript to the end of the HTML document') + ), + array( + 'id' => 'PS_JS_DEFER_0', + 'value' => 0, + 'label' => $this->l('Keep JavaScript in HTML at its original position') + ) + ) + ), - public function initFieldsetCCC() - { - $this->fields_form[3]['form'] = array( - 'legend' => array( - 'title' => $this->l('CCC (Combine, Compress and Cache)'), - 'icon' => 'icon-fullscreen' - ), - 'description' => $this->l('CCC allows you to reduce the loading time of your page. With these settings you will gain performance without even touching the code of your theme. Make sure, however, that your theme is compatible with PrestaShop 1.4+. Otherwise, CCC will cause problems.'), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'ccc_up', - ), - array( - 'type' => 'switch', - 'label' => $this->l('Smart cache for CSS'), - 'name' => 'PS_CSS_THEME_CACHE', - 'values' => array( - array( - 'id' => 'PS_CSS_THEME_CACHE_1', - 'value' => 1, - 'label' => $this->l('Use CCC for CSS') - ), - array( - 'id' => 'PS_CSS_THEME_CACHE_0', - 'value' => 0, - 'label' => $this->l('Keep CSS as original') - ) - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Smart cache for JavaScript'), - 'name' => 'PS_JS_THEME_CACHE', - 'values' => array( - array( - 'id' => 'PS_JS_THEME_CACHE_1', - 'value' => 1, - 'label' => $this->l('Use CCC for JavaScript') - ), - array( - 'id' => 'PS_JS_THEME_CACHE_0', - 'value' => 0, - 'label' => $this->l('Keep JavaScript as original') - ) - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Minify HTML'), - 'name' => 'PS_HTML_THEME_COMPRESSION', - 'values' => array( - array( - 'id' => 'PS_HTML_THEME_COMPRESSION_1', - 'value' => 1, - 'label' => $this->l('Minify HTML after "Smarty compile" execution') - ), - array( - 'id' => 'PS_HTML_THEME_COMPRESSION_0', - 'value' => 0, - 'label' => $this->l('Keep HTML as original') - ) - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Compress inline JavaScript in HTML'), - 'name' => 'PS_JS_HTML_THEME_COMPRESSION', - 'values' => array( - array( - 'id' => 'PS_JS_HTML_THEME_COMPRESSION_1', - 'value' => 1, - 'label' => $this->l('Compress inline JavaScript in HTML after "Smarty compile" execution') - ), - array( - 'id' => 'PS_JS_HTML_THEME_COMPRESSION_0', - 'value' => 0, - 'label' => $this->l('Keep inline JavaScript in HTML as original') - ) - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Move JavaScript to the end'), - 'name' => 'PS_JS_DEFER', - 'values' => array( - array( - 'id' => 'PS_JS_DEFER_1', - 'value' => 1, - 'label' => $this->l('Move JavaScript to the end of the HTML document') - ), - array( - 'id' => 'PS_JS_DEFER_0', - 'value' => 0, - 'label' => $this->l('Keep JavaScript in HTML at its original position') - ) - ) - ), + ), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); - ), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); + if (!defined('_PS_HOST_MODE_')) { + $this->fields_form[3]['form']['input'][] = array( + 'type' => 'switch', + 'label' => $this->l('Apache optimization'), + 'name' => 'PS_HTACCESS_CACHE_CONTROL', + 'hint' => $this->l('This will add directives to your .htaccess file, which should improve caching and compression.'), + 'values' => array( + array( + 'id' => 'PS_HTACCESS_CACHE_CONTROL_1', + 'value' => 1, + 'label' => $this->l('Yes'), + ), + array( + 'id' => 'PS_HTACCESS_CACHE_CONTROL_0', + 'value' => 0, + 'label' => $this->l('No'), + ), + ), + ); + } - if (!defined('_PS_HOST_MODE_')) - $this->fields_form[3]['form']['input'][] = array( - 'type' => 'switch', - 'label' => $this->l('Apache optimization'), - 'name' => 'PS_HTACCESS_CACHE_CONTROL', - 'hint' => $this->l('This will add directives to your .htaccess file, which should improve caching and compression.'), - 'values' => array( - array( - 'id' => 'PS_HTACCESS_CACHE_CONTROL_1', - 'value' => 1, - 'label' => $this->l('Yes'), - ), - array( - 'id' => 'PS_HTACCESS_CACHE_CONTROL_0', - 'value' => 0, - 'label' => $this->l('No'), - ), - ), - ); + $this->fields_value['PS_CSS_THEME_CACHE'] = Configuration::get('PS_CSS_THEME_CACHE'); + $this->fields_value['PS_JS_THEME_CACHE'] = Configuration::get('PS_JS_THEME_CACHE'); + $this->fields_value['PS_HTML_THEME_COMPRESSION'] = Configuration::get('PS_HTML_THEME_COMPRESSION'); + $this->fields_value['PS_JS_HTML_THEME_COMPRESSION'] = Configuration::get('PS_JS_HTML_THEME_COMPRESSION'); + $this->fields_value['PS_HTACCESS_CACHE_CONTROL'] = Configuration::get('PS_HTACCESS_CACHE_CONTROL'); + $this->fields_value['PS_JS_DEFER'] = Configuration::get('PS_JS_DEFER'); + $this->fields_value['ccc_up'] = 1; + } - $this->fields_value['PS_CSS_THEME_CACHE'] = Configuration::get('PS_CSS_THEME_CACHE'); - $this->fields_value['PS_JS_THEME_CACHE'] = Configuration::get('PS_JS_THEME_CACHE'); - $this->fields_value['PS_HTML_THEME_COMPRESSION'] = Configuration::get('PS_HTML_THEME_COMPRESSION'); - $this->fields_value['PS_JS_HTML_THEME_COMPRESSION'] = Configuration::get('PS_JS_HTML_THEME_COMPRESSION'); - $this->fields_value['PS_HTACCESS_CACHE_CONTROL'] = Configuration::get('PS_HTACCESS_CACHE_CONTROL'); - $this->fields_value['PS_JS_DEFER'] = Configuration::get('PS_JS_DEFER'); - $this->fields_value['ccc_up'] = 1; - } + public function initFieldsetMediaServer() + { + $this->fields_form[4]['form'] = array( + 'legend' => array( + 'title' => $this->l('Media servers (use only with CCC)'), + 'icon' => 'icon-link' + ), + 'description' => $this->l('You must enter another domain, or subdomain, in order to use cookieless static content.'), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'media_server_up' + ), + array( + 'type' => 'text', + 'label' => $this->l('Media server #1'), + 'name' => '_MEDIA_SERVER_1_', + 'hint' => $this->l('Name of the second domain of your shop, (e.g. myshop-media-server-1.com). If you do not have another domain, leave this field blank.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Media server #2'), + 'name' => '_MEDIA_SERVER_2_', + 'hint' => $this->l('Name of the third domain of your shop, (e.g. myshop-media-server-2.com). If you do not have another domain, leave this field blank.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Media server #3'), + 'name' => '_MEDIA_SERVER_3_', + 'hint' => $this->l('Name of the fourth domain of your shop, (e.g. myshop-media-server-3.com). If you do not have another domain, leave this field blank.') + ), + ), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); - public function initFieldsetMediaServer() - { - $this->fields_form[4]['form'] = array( - 'legend' => array( - 'title' => $this->l('Media servers (use only with CCC)'), - 'icon' => 'icon-link' - ), - 'description' => $this->l('You must enter another domain, or subdomain, in order to use cookieless static content.'), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'media_server_up' - ), - array( - 'type' => 'text', - 'label' => $this->l('Media server #1'), - 'name' => '_MEDIA_SERVER_1_', - 'hint' => $this->l('Name of the second domain of your shop, (e.g. myshop-media-server-1.com). If you do not have another domain, leave this field blank.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Media server #2'), - 'name' => '_MEDIA_SERVER_2_', - 'hint' => $this->l('Name of the third domain of your shop, (e.g. myshop-media-server-2.com). If you do not have another domain, leave this field blank.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Media server #3'), - 'name' => '_MEDIA_SERVER_3_', - 'hint' => $this->l('Name of the fourth domain of your shop, (e.g. myshop-media-server-3.com). If you do not have another domain, leave this field blank.') - ), - ), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); + $this->fields_value['_MEDIA_SERVER_1_'] = Configuration::get('PS_MEDIA_SERVER_1'); + $this->fields_value['_MEDIA_SERVER_2_'] = Configuration::get('PS_MEDIA_SERVER_2'); + $this->fields_value['_MEDIA_SERVER_3_'] = Configuration::get('PS_MEDIA_SERVER_3'); + } - $this->fields_value['_MEDIA_SERVER_1_'] = Configuration::get('PS_MEDIA_SERVER_1'); - $this->fields_value['_MEDIA_SERVER_2_'] = Configuration::get('PS_MEDIA_SERVER_2'); - $this->fields_value['_MEDIA_SERVER_3_'] = Configuration::get('PS_MEDIA_SERVER_3'); - } + public function initFieldsetCiphering() + { + $phpdoc_langs = array('en', 'zh', 'fr', 'de', 'ja', 'pl', 'ro', 'ru', 'fa', 'es', 'tr'); + $php_lang = in_array($this->context->language->iso_code, $phpdoc_langs) ? $this->context->language->iso_code : 'en'; - public function initFieldsetCiphering() - { - $phpdoc_langs = array('en', 'zh', 'fr', 'de', 'ja', 'pl', 'ro', 'ru', 'fa', 'es', 'tr'); - $php_lang = in_array($this->context->language->iso_code, $phpdoc_langs) ? $this->context->language->iso_code : 'en'; + $warning_mcrypt = ' '.$this->l('(you must install the [a]Mcrypt extension[/a])'); + $warning_mcrypt = str_replace('[a]', '<a href="http://www.php.net/manual/'.substr($php_lang, 0, 2).'/book.mcrypt.php" target="_blank">', $warning_mcrypt); + $warning_mcrypt = str_replace('[/a]', '</a>', $warning_mcrypt); - $warning_mcrypt = ' '.$this->l('(you must install the [a]Mcrypt extension[/a])'); - $warning_mcrypt = str_replace('[a]', '<a href="http://www.php.net/manual/'.substr($php_lang, 0, 2).'/book.mcrypt.php" target="_blank">', $warning_mcrypt); - $warning_mcrypt = str_replace('[/a]', '</a>', $warning_mcrypt); + if (defined('_RIJNDAEL_KEY_') && defined('_RIJNDAEL_IV_')) { + $this->fields_form[5]['form'] = array( - if (defined('_RIJNDAEL_KEY_') && defined('_RIJNDAEL_IV_')) - $this->fields_form[5]['form'] = array( + 'legend' => array( + 'title' => $this->l('Ciphering'), + 'icon' => 'icon-desktop' + ), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'ciphering_up' + ), + array( + 'type' => 'radio', + 'label' => $this->l('Algorithm'), + 'name' => 'PS_CIPHER_ALGORITHM', + 'hint' => $this->l('Mcrypt is faster than our custom BlowFish class, but requires the "mcrypt" PHP extension. If you change this configuration, all cookies will be reset.'), + 'values' => array( + array( + 'id' => 'PS_CIPHER_ALGORITHM_1', + 'value' => 1, + 'label' => $this->l('Use Rijndael with mcrypt lib.').(!function_exists('mcrypt_encrypt') ? '' : $warning_mcrypt) + ), + array( + 'id' => 'PS_CIPHER_ALGORITHM_0', + 'value' => 0, + 'label' => $this->l('Use the custom BlowFish class.') + ) + ) + ) + ), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); + } - 'legend' => array( - 'title' => $this->l('Ciphering'), - 'icon' => 'icon-desktop' - ), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'ciphering_up' - ), - array( - 'type' => 'radio', - 'label' => $this->l('Algorithm'), - 'name' => 'PS_CIPHER_ALGORITHM', - 'hint' => $this->l('Mcrypt is faster than our custom BlowFish class, but requires the "mcrypt" PHP extension. If you change this configuration, all cookies will be reset.'), - 'values' => array( - array( - 'id' => 'PS_CIPHER_ALGORITHM_1', - 'value' => 1, - 'label' => $this->l('Use Rijndael with mcrypt lib.').(!function_exists('mcrypt_encrypt') ? '' : $warning_mcrypt) - ), - array( - 'id' => 'PS_CIPHER_ALGORITHM_0', - 'value' => 0, - 'label' => $this->l('Use the custom BlowFish class.') - ) - ) - ) - ), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); + $this->fields_value['PS_CIPHER_ALGORITHM'] = Configuration::get('PS_CIPHER_ALGORITHM'); + } - $this->fields_value['PS_CIPHER_ALGORITHM'] = Configuration::get('PS_CIPHER_ALGORITHM'); - } + public function initFieldsetCaching() + { + $phpdoc_langs = array('en', 'zh', 'fr', 'de', 'ja', 'pl', 'ro', 'ru', 'fa', 'es', 'tr'); + $php_lang = in_array($this->context->language->iso_code, $phpdoc_langs) ? $this->context->language->iso_code : 'en'; - public function initFieldsetCaching() - { - $phpdoc_langs = array('en', 'zh', 'fr', 'de', 'ja', 'pl', 'ro', 'ru', 'fa', 'es', 'tr'); - $php_lang = in_array($this->context->language->iso_code, $phpdoc_langs) ? $this->context->language->iso_code : 'en'; + $warning_memcache = ' '.$this->l('(you must install the [a]Memcache PECL extension[/a])'); + $warning_memcache = str_replace('[a]', '<a href="http://www.php.net/manual/'.substr($php_lang, 0, 2).'/memcache.installation.php" target="_blank">', $warning_memcache); + $warning_memcache = str_replace('[/a]', '</a>', $warning_memcache); - $warning_memcached = ' '.$this->l('(you must install the [a]Memcache PECL extension[/a])'); - $warning_memcached = str_replace('[a]', '<a href="http://www.php.net/manual/'.substr($php_lang, 0, 2).'/memcache.installation.php" target="_blank">', $warning_memcached); - $warning_memcached = str_replace('[/a]', '</a>', $warning_memcached); + $warning_memcached = ' '.$this->l('(you must install the [a]Memcached PECL extension[/a])'); + $warning_memcached = str_replace('[a]', '<a href="http://www.php.net/manual/'.substr($php_lang, 0, 2).'/memcached.installation.php" target="_blank">', $warning_memcached); + $warning_memcached = str_replace('[/a]', '</a>', $warning_memcached); - $warning_apc = ' '.$this->l('(you must install the [a]APC PECL extension[/a])'); - $warning_apc = str_replace('[a]', '<a href="http://php.net/manual/'.substr($php_lang, 0, 2).'/apc.installation.php" target="_blank">', $warning_apc); - $warning_apc = str_replace('[/a]', '</a>', $warning_apc); + $warning_apc = ' '.$this->l('(you must install the [a]APC PECL extension[/a])'); + $warning_apc = str_replace('[a]', '<a href="http://php.net/manual/'.substr($php_lang, 0, 2).'/apc.installation.php" target="_blank">', $warning_apc); + $warning_apc = str_replace('[/a]', '</a>', $warning_apc); - $warning_xcache = ' '.$this->l('(you must install the [a]Xcache extension[/a])'); - $warning_xcache = str_replace('[a]', '<a href="http://xcache.lighttpd.net" target="_blank">', $warning_xcache); - $warning_xcache = str_replace('[/a]', '</a>', $warning_xcache); + $warning_xcache = ' '.$this->l('(you must install the [a]Xcache extension[/a])'); + $warning_xcache = str_replace('[a]', '<a href="http://xcache.lighttpd.net" target="_blank">', $warning_xcache); + $warning_xcache = str_replace('[/a]', '</a>', $warning_xcache); - $warning_fs = ' '.sprintf($this->l('(the directory %s must be writable)'), realpath(_PS_CACHEFS_DIRECTORY_)); + $warning_fs = ' '.sprintf($this->l('(the directory %s must be writable)'), realpath(_PS_CACHEFS_DIRECTORY_)); - $this->fields_form[6]['form'] = array( - 'legend' => array( - 'title' => $this->l('Caching'), - 'icon' => 'icon-desktop' - ), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'cache_up' - ), - array( - 'type' => 'switch', - 'label' => $this->l('Use cache'), - 'name' => 'cache_active', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'cache_active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'cache_active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ) - ), - array( - 'type' => 'radio', - 'label' => $this->l('Caching system'), - 'name' => 'caching_system', - 'hint' => $this->l('The CacheFS system should be used only when the infrastructure contains one front-end server. If you are not sure, ask your hosting company.'), - 'values' => array( - array( - 'id' => 'CacheFs', - 'value' => 'CacheFs', - 'label' => $this->l('File System').(is_writable(_PS_CACHEFS_DIRECTORY_) ? '' : $warning_fs) - ), - array( - 'id' => 'CacheMemcache', - 'value' => 'CacheMemcache', - 'label' => $this->l('Memcached via PHP::Memcache').(extension_loaded('memcache') ? '' : $warning_memcached) - ), - array( - 'id' => 'CacheMemcached', - 'value' => 'CacheMemcached', - 'label' => $this->l('Memcached via PHP::Memcached').(extension_loaded('memcached') ? '' : $warning_memcached) - ), - array( - 'id' => 'CacheApc', - 'value' => 'CacheApc', - 'label' => $this->l('APC').(extension_loaded('apc') ? '' : $warning_apc) - ), - array( - 'id' => 'CacheXcache', - 'value' => 'CacheXcache', - 'label' => $this->l('Xcache').(extension_loaded('xcache') ? '' : $warning_xcache) - ), + $this->fields_form[6]['form'] = array( + 'legend' => array( + 'title' => $this->l('Caching'), + 'icon' => 'icon-desktop' + ), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'cache_up' + ), + array( + 'type' => 'switch', + 'label' => $this->l('Use cache'), + 'name' => 'cache_active', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'cache_active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'cache_active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ) + ), + array( + 'type' => 'radio', + 'label' => $this->l('Caching system'), + 'name' => 'caching_system', + 'hint' => $this->l('The CacheFS system should be used only when the infrastructure contains one front-end server. If you are not sure, ask your hosting company.'), + 'values' => array( + array( + 'id' => 'CacheFs', + 'value' => 'CacheFs', + 'label' => $this->l('File System').(is_writable(_PS_CACHEFS_DIRECTORY_) ? '' : $warning_fs) + ), + array( + 'id' => 'CacheMemcache', + 'value' => 'CacheMemcache', + 'label' => $this->l('Memcached via PHP::Memcache').(extension_loaded('memcache') ? '' : $warning_memcache) + ), + array( + 'id' => 'CacheMemcached', + 'value' => 'CacheMemcached', + 'label' => $this->l('Memcached via PHP::Memcached').(extension_loaded('memcached') ? '' : $warning_memcached) + ), + array( + 'id' => 'CacheApc', + 'value' => 'CacheApc', + 'label' => $this->l('APC').(extension_loaded('apc') ? '' : $warning_apc) + ), + array( + 'id' => 'CacheXcache', + 'value' => 'CacheXcache', + 'label' => $this->l('Xcache').(extension_loaded('xcache') ? '' : $warning_xcache) + ), - ) - ), - array( - 'type' => 'text', - 'label' => $this->l('Directory depth'), - 'name' => 'ps_cache_fs_directory_depth' - ), - ), - 'submit' => array( - 'title' => $this->l('Save') - ), - 'memcachedServers' => true - ); + ) + ), + array( + 'type' => 'text', + 'label' => $this->l('Directory depth'), + 'name' => 'ps_cache_fs_directory_depth' + ), + ), + 'submit' => array( + 'title' => $this->l('Save') + ), + 'memcachedServers' => true + ); - $depth = Configuration::get('PS_CACHEFS_DIRECTORY_DEPTH'); - $this->fields_value['cache_active'] = _PS_CACHE_ENABLED_; - $this->fields_value['caching_system'] = _PS_CACHING_SYSTEM_; - $this->fields_value['ps_cache_fs_directory_depth'] = $depth ? $depth : 1; + $depth = Configuration::get('PS_CACHEFS_DIRECTORY_DEPTH'); + $this->fields_value['cache_active'] = _PS_CACHE_ENABLED_; + $this->fields_value['caching_system'] = _PS_CACHING_SYSTEM_; + $this->fields_value['ps_cache_fs_directory_depth'] = $depth ? $depth : 1; - $this->tpl_form_vars['servers'] = CacheMemcache::getMemcachedServers(); - $this->tpl_form_vars['_PS_CACHE_ENABLED_'] = _PS_CACHE_ENABLED_; - } + $this->tpl_form_vars['servers'] = CacheMemcache::getMemcachedServers(); + $this->tpl_form_vars['_PS_CACHE_ENABLED_'] = _PS_CACHE_ENABLED_; + } - public function renderForm() - { - $this->initFieldsetSmarty(); - $this->initFieldsetDebugMode(); - $this->initFieldsetFeaturesDetachables(); - $this->initFieldsetCCC(); + public function renderForm() + { + $this->initFieldsetSmarty(); + $this->initFieldsetDebugMode(); + $this->initFieldsetFeaturesDetachables(); + $this->initFieldsetCCC(); - if (!defined('_PS_HOST_MODE_')) - { - $this->initFieldsetMediaServer(); - $this->initFieldsetCiphering(); - $this->initFieldsetCaching(); - } + if (!defined('_PS_HOST_MODE_')) { + $this->initFieldsetMediaServer(); + $this->initFieldsetCiphering(); + $this->initFieldsetCaching(); + } - // Reindex fields - $this->fields_form = array_values($this->fields_form); + // Reindex fields + $this->fields_form = array_values($this->fields_form); - // Activate multiple fieldset - $this->multiple_fieldsets = true; + // Activate multiple fieldset + $this->multiple_fieldsets = true; - return parent::renderForm(); - } + return parent::renderForm(); + } - public function initContent() - { - $this->initTabModuleList(); - $this->initToolbar(); - $this->initPageHeaderToolbar(); - $this->display = ''; - $this->content .= $this->renderForm(); + public function initContent() + { + $this->initTabModuleList(); + $this->initToolbar(); + $this->initPageHeaderToolbar(); + $this->display = ''; + $this->content .= $this->renderForm(); - $this->context->smarty->assign(array( - 'content' => $this->content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn, - 'title' => $this->page_header_toolbar_title, - 'toolbar_btn' => $this->page_header_toolbar_btn - )); - } + $this->context->smarty->assign(array( + 'content' => $this->content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn, + 'title' => $this->page_header_toolbar_title, + 'toolbar_btn' => $this->page_header_toolbar_btn + )); + } - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); - $this->page_header_toolbar_btn['clear_cache'] = array( - 'href' => self::$currentIndex.'&token='.$this->token.'&empty_smarty_cache=1', - 'desc' => $this->l('Clear cache'), - 'icon' => 'process-icon-eraser' - ); - } + $this->page_header_toolbar_btn['clear_cache'] = array( + 'href' => self::$currentIndex.'&token='.$this->token.'&empty_smarty_cache=1', + 'desc' => $this->l('Clear cache'), + 'icon' => 'process-icon-eraser' + ); + } - public function postProcess() - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } + public function postProcess() + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } - Hook::exec('action'.get_class($this).ucfirst($this->action).'Before', array('controller' => $this)); - if (Tools::isSubmit('submitAddServer')) - { - if ($this->tabAccess['add'] === '1') - { - if (!Tools::getValue('memcachedIp')) - $this->errors[] = Tools::displayError('The Memcached IP is missing.'); - if (!Tools::getValue('memcachedPort')) - $this->errors[] = Tools::displayError('The Memcached port is missing.'); - if (!Tools::getValue('memcachedWeight')) - $this->errors[] = Tools::displayError('The Memcached weight is missing.'); - if (!count($this->errors)) - { - if (CacheMemcache::addServer(pSQL(Tools::getValue('memcachedIp')), - (int)Tools::getValue('memcachedPort'), - (int)Tools::getValue('memcachedWeight'))) - Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getValue('token').'&conf=4'); - else - $this->errors[] = Tools::displayError('The Memcached server cannot be added.'); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } + Hook::exec('action'.get_class($this).ucfirst($this->action).'Before', array('controller' => $this)); + if (Tools::isSubmit('submitAddServer')) { + if ($this->tabAccess['add'] === '1') { + if (!Tools::getValue('memcachedIp')) { + $this->errors[] = Tools::displayError('The Memcached IP is missing.'); + } + if (!Tools::getValue('memcachedPort')) { + $this->errors[] = Tools::displayError('The Memcached port is missing.'); + } + if (!Tools::getValue('memcachedWeight')) { + $this->errors[] = Tools::displayError('The Memcached weight is missing.'); + } + if (!count($this->errors)) { + if (CacheMemcache::addServer(pSQL(Tools::getValue('memcachedIp')), + (int)Tools::getValue('memcachedPort'), + (int)Tools::getValue('memcachedWeight'))) { + Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getValue('token').'&conf=4'); + } else { + $this->errors[] = Tools::displayError('The Memcached server cannot be added.'); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } - if (Tools::getValue('deleteMemcachedServer')) - { - if ($this->tabAccess['add'] === '1') - { - if (CacheMemcache::deleteServer((int)Tools::getValue('deleteMemcachedServer'))) - Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getValue('token').'&conf=4'); - else - $this->errors[] = Tools::displayError('There was an error when attempting to delete the Memcached server.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } + if (Tools::getValue('deleteMemcachedServer')) { + if ($this->tabAccess['add'] === '1') { + if (CacheMemcache::deleteServer((int)Tools::getValue('deleteMemcachedServer'))) { + Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getValue('token').'&conf=4'); + } else { + $this->errors[] = Tools::displayError('There was an error when attempting to delete the Memcached server.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } - $redirectAdmin = false; - if ((bool)Tools::getValue('smarty_up')) - { - if ($this->tabAccess['edit'] === '1') - { - Configuration::updateValue('PS_SMARTY_FORCE_COMPILE', Tools::getValue('smarty_force_compile', _PS_SMARTY_NO_COMPILE_)); + $redirectAdmin = false; + if ((bool)Tools::getValue('smarty_up')) { + if ($this->tabAccess['edit'] === '1') { + Configuration::updateValue('PS_SMARTY_FORCE_COMPILE', Tools::getValue('smarty_force_compile', _PS_SMARTY_NO_COMPILE_)); - if (Configuration::get('PS_SMARTY_CACHE') != Tools::getValue('smarty_cache') || Configuration::get('PS_SMARTY_CACHING_TYPE') != Tools::getValue('smarty_caching_type')) - Tools::clearSmartyCache(); + if (Configuration::get('PS_SMARTY_CACHE') != Tools::getValue('smarty_cache') || Configuration::get('PS_SMARTY_CACHING_TYPE') != Tools::getValue('smarty_caching_type')) { + Tools::clearSmartyCache(); + } - Configuration::updateValue('PS_SMARTY_CACHE', Tools::getValue('smarty_cache', 0)); - Configuration::updateValue('PS_SMARTY_CACHING_TYPE', Tools::getValue('smarty_caching_type')); - Configuration::updateValue('PS_SMARTY_CLEAR_CACHE', Tools::getValue('smarty_clear_cache')); - $redirectAdmin = true; - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } + Configuration::updateValue('PS_SMARTY_CACHE', Tools::getValue('smarty_cache', 0)); + Configuration::updateValue('PS_SMARTY_CACHING_TYPE', Tools::getValue('smarty_caching_type')); + Configuration::updateValue('PS_SMARTY_CLEAR_CACHE', Tools::getValue('smarty_clear_cache')); + $redirectAdmin = true; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } - if ((bool)Tools::getValue('features_detachables_up')) - { - if ($this->tabAccess['edit'] === '1') - { - if (Tools::isSubmit('combination')) - if ((!Tools::getValue('combination') && Combination::isCurrentlyUsed()) === false) - Configuration::updateValue('PS_COMBINATION_FEATURE_ACTIVE', (bool)Tools::getValue('combination')); + if ((bool)Tools::getValue('features_detachables_up')) { + if ($this->tabAccess['edit'] === '1') { + if (Tools::isSubmit('combination')) { + if ((!Tools::getValue('combination') && Combination::isCurrentlyUsed()) === false) { + Configuration::updateValue('PS_COMBINATION_FEATURE_ACTIVE', (bool)Tools::getValue('combination')); + } + } - if (Tools::isSubmit('customer_group')) - if ((!Tools::getValue('customer_group') && Group::isCurrentlyUsed()) === false) - Configuration::updateValue('PS_GROUP_FEATURE_ACTIVE', (bool)Tools::getValue('customer_group')); + if (Tools::isSubmit('customer_group')) { + if ((!Tools::getValue('customer_group') && Group::isCurrentlyUsed()) === false) { + Configuration::updateValue('PS_GROUP_FEATURE_ACTIVE', (bool)Tools::getValue('customer_group')); + } + } - Configuration::updateValue('PS_FEATURE_FEATURE_ACTIVE', (bool)Tools::getValue('feature')); - $redirectAdmin = true; - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } + Configuration::updateValue('PS_FEATURE_FEATURE_ACTIVE', (bool)Tools::getValue('feature')); + $redirectAdmin = true; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } - if ((bool)Tools::getValue('ccc_up')) - { - if ($this->tabAccess['edit'] === '1') - { - $theme_cache_directory = _PS_ALL_THEMES_DIR_.$this->context->shop->theme_directory.'/cache/'; - if (((bool)Tools::getValue('PS_CSS_THEME_CACHE') || (bool)Tools::getValue('PS_JS_THEME_CACHE')) && !is_writable($theme_cache_directory)) - $this->errors[] = sprintf(Tools::displayError('To use Smart Cache directory %s must be writable.'), realpath($theme_cache_directory)); + if ((bool)Tools::getValue('ccc_up')) { + if ($this->tabAccess['edit'] === '1') { + $theme_cache_directory = _PS_ALL_THEMES_DIR_.$this->context->shop->theme_directory.'/cache/'; + if (((bool)Tools::getValue('PS_CSS_THEME_CACHE') || (bool)Tools::getValue('PS_JS_THEME_CACHE')) && !is_writable($theme_cache_directory)) { + $this->errors[] = sprintf(Tools::displayError('To use Smart Cache directory %s must be writable.'), realpath($theme_cache_directory)); + } - if ($tmp = (int)Tools::getValue('PS_CSS_THEME_CACHE')) - { - $version = (int)Configuration::get('PS_CCCCSS_VERSION'); - if (Configuration::get('PS_CSS_THEME_CACHE') != $tmp) - Configuration::updateValue('PS_CCCCSS_VERSION', ++$version); - } + if ($tmp = (int)Tools::getValue('PS_CSS_THEME_CACHE')) { + $version = (int)Configuration::get('PS_CCCCSS_VERSION'); + if (Configuration::get('PS_CSS_THEME_CACHE') != $tmp) { + Configuration::updateValue('PS_CCCCSS_VERSION', ++$version); + } + } - if ($tmp = (int)Tools::getValue('PS_JS_THEME_CACHE')) - { - $version = (int)Configuration::get('PS_CCCJS_VERSION'); - if (Configuration::get('PS_JS_THEME_CACHE') != $tmp) - Configuration::updateValue('PS_CCCJS_VERSION', ++$version); - } + if ($tmp = (int)Tools::getValue('PS_JS_THEME_CACHE')) { + $version = (int)Configuration::get('PS_CCCJS_VERSION'); + if (Configuration::get('PS_JS_THEME_CACHE') != $tmp) { + Configuration::updateValue('PS_CCCJS_VERSION', ++$version); + } + } - if (!Configuration::updateValue('PS_CSS_THEME_CACHE', (int)Tools::getValue('PS_CSS_THEME_CACHE')) || - !Configuration::updateValue('PS_JS_THEME_CACHE', (int)Tools::getValue('PS_JS_THEME_CACHE')) || - !Configuration::updateValue('PS_HTML_THEME_COMPRESSION', (int)Tools::getValue('PS_HTML_THEME_COMPRESSION')) || - !Configuration::updateValue('PS_JS_HTML_THEME_COMPRESSION', (int)Tools::getValue('PS_JS_HTML_THEME_COMPRESSION')) || - !Configuration::updateValue('PS_JS_DEFER', (int)Tools::getValue('PS_JS_DEFER')) || - !Configuration::updateValue('PS_HTACCESS_CACHE_CONTROL', (int)Tools::getValue('PS_HTACCESS_CACHE_CONTROL'))) - $this->errors[] = Tools::displayError('Unknown error.'); - else - { - $redirectAdmin = true; - if (Configuration::get('PS_HTACCESS_CACHE_CONTROL')) - { - if (is_writable(_PS_ROOT_DIR_.'/.htaccess')) - Tools::generateHtaccess(); - else - { - $message = $this->l('Before being able to use this tool, you need to:'); - $message .= '<br />- '.$this->l('Create a blank .htaccess in your root directory.'); - $message .= '<br />- '.$this->l('Give it write permissions (CHMOD 666 on Unix system).'); - $this->errors[] = Tools::displayError($message, false); - Configuration::updateValue('PS_HTACCESS_CACHE_CONTROL', false); - } - } - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } + if (!Configuration::updateValue('PS_CSS_THEME_CACHE', (int)Tools::getValue('PS_CSS_THEME_CACHE')) || + !Configuration::updateValue('PS_JS_THEME_CACHE', (int)Tools::getValue('PS_JS_THEME_CACHE')) || + !Configuration::updateValue('PS_HTML_THEME_COMPRESSION', (int)Tools::getValue('PS_HTML_THEME_COMPRESSION')) || + !Configuration::updateValue('PS_JS_HTML_THEME_COMPRESSION', (int)Tools::getValue('PS_JS_HTML_THEME_COMPRESSION')) || + !Configuration::updateValue('PS_JS_DEFER', (int)Tools::getValue('PS_JS_DEFER')) || + !Configuration::updateValue('PS_HTACCESS_CACHE_CONTROL', (int)Tools::getValue('PS_HTACCESS_CACHE_CONTROL'))) { + $this->errors[] = Tools::displayError('Unknown error.'); + } else { + $redirectAdmin = true; + if (Configuration::get('PS_HTACCESS_CACHE_CONTROL')) { + if (is_writable(_PS_ROOT_DIR_.'/.htaccess')) { + Tools::generateHtaccess(); + } else { + $message = $this->l('Before being able to use this tool, you need to:'); + $message .= '<br />- '.$this->l('Create a blank .htaccess in your root directory.'); + $message .= '<br />- '.$this->l('Give it write permissions (CHMOD 666 on Unix system).'); + $this->errors[] = Tools::displayError($message, false); + Configuration::updateValue('PS_HTACCESS_CACHE_CONTROL', false); + } + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } - if ((bool)Tools::getValue('media_server_up') && !defined('_PS_HOST_MODE_')) - { - if ($this->tabAccess['edit'] === '1') - { - if (Tools::getValue('_MEDIA_SERVER_1_') != null && !Validate::isFileName(Tools::getValue('_MEDIA_SERVER_1_'))) - $this->errors[] = Tools::displayError('Media server #1 is invalid'); - if (Tools::getValue('_MEDIA_SERVER_2_') != null && !Validate::isFileName(Tools::getValue('_MEDIA_SERVER_2_'))) - $this->errors[] = Tools::displayError('Media server #2 is invalid'); - if (Tools::getValue('_MEDIA_SERVER_3_') != null && !Validate::isFileName(Tools::getValue('_MEDIA_SERVER_3_'))) - $this->errors[] = Tools::displayError('Media server #3 is invalid'); - if (!count($this->errors)) - { - $base_urls = array(); - $base_urls['_MEDIA_SERVER_1_'] = Tools::getValue('_MEDIA_SERVER_1_'); - $base_urls['_MEDIA_SERVER_2_'] = Tools::getValue('_MEDIA_SERVER_2_'); - $base_urls['_MEDIA_SERVER_3_'] = Tools::getValue('_MEDIA_SERVER_3_'); - if ($base_urls['_MEDIA_SERVER_1_'] || $base_urls['_MEDIA_SERVER_2_'] || $base_urls['_MEDIA_SERVER_3_']) - Configuration::updateValue('PS_MEDIA_SERVERS', 1); - else - Configuration::updateValue('PS_MEDIA_SERVERS', 0); - rewriteSettingsFile($base_urls, null, null); - Configuration::updateValue('PS_MEDIA_SERVER_1', Tools::getValue('_MEDIA_SERVER_1_')); - Configuration::updateValue('PS_MEDIA_SERVER_2', Tools::getValue('_MEDIA_SERVER_2_')); - Configuration::updateValue('PS_MEDIA_SERVER_3', Tools::getValue('_MEDIA_SERVER_3_')); - Tools::clearSmartyCache(); - Media::clearCache(); + if ((bool)Tools::getValue('media_server_up') && !defined('_PS_HOST_MODE_')) { + if ($this->tabAccess['edit'] === '1') { + if (Tools::getValue('_MEDIA_SERVER_1_') != null && !Validate::isFileName(Tools::getValue('_MEDIA_SERVER_1_'))) { + $this->errors[] = Tools::displayError('Media server #1 is invalid'); + } + if (Tools::getValue('_MEDIA_SERVER_2_') != null && !Validate::isFileName(Tools::getValue('_MEDIA_SERVER_2_'))) { + $this->errors[] = Tools::displayError('Media server #2 is invalid'); + } + if (Tools::getValue('_MEDIA_SERVER_3_') != null && !Validate::isFileName(Tools::getValue('_MEDIA_SERVER_3_'))) { + $this->errors[] = Tools::displayError('Media server #3 is invalid'); + } + if (!count($this->errors)) { + $base_urls = array(); + $base_urls['_MEDIA_SERVER_1_'] = Tools::getValue('_MEDIA_SERVER_1_'); + $base_urls['_MEDIA_SERVER_2_'] = Tools::getValue('_MEDIA_SERVER_2_'); + $base_urls['_MEDIA_SERVER_3_'] = Tools::getValue('_MEDIA_SERVER_3_'); + if ($base_urls['_MEDIA_SERVER_1_'] || $base_urls['_MEDIA_SERVER_2_'] || $base_urls['_MEDIA_SERVER_3_']) { + Configuration::updateValue('PS_MEDIA_SERVERS', 1); + } else { + Configuration::updateValue('PS_MEDIA_SERVERS', 0); + } + rewriteSettingsFile($base_urls, null, null); + Configuration::updateValue('PS_MEDIA_SERVER_1', Tools::getValue('_MEDIA_SERVER_1_')); + Configuration::updateValue('PS_MEDIA_SERVER_2', Tools::getValue('_MEDIA_SERVER_2_')); + Configuration::updateValue('PS_MEDIA_SERVER_3', Tools::getValue('_MEDIA_SERVER_3_')); + Tools::clearSmartyCache(); + Media::clearCache(); - if (is_writable(_PS_ROOT_DIR_.'/.htaccess')) - { - Tools::generateHtaccess(null, null, null, '', null, array($base_urls['_MEDIA_SERVER_1_'], $base_urls['_MEDIA_SERVER_2_'], $base_urls['_MEDIA_SERVER_3_'])); - unset($this->_fieldsGeneral['_MEDIA_SERVER_1_']); - unset($this->_fieldsGeneral['_MEDIA_SERVER_2_']); - unset($this->_fieldsGeneral['_MEDIA_SERVER_3_']); - $redirectAdmin = true; - } - else - { - $message = $this->l('Before being able to use this tool, you need to:'); - $message .= '<br />- '.$this->l('Create a blank .htaccess in your root directory.'); - $message .= '<br />- '.$this->l('Give it write permissions (CHMOD 666 on Unix system).'); - $this->errors[] = Tools::displayError($message, false); - Configuration::updateValue('PS_HTACCESS_CACHE_CONTROL', false); - } - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - if ((bool)Tools::getValue('ciphering_up') && Configuration::get('PS_CIPHER_ALGORITHM') != (int)Tools::getValue('PS_CIPHER_ALGORITHM')) - { - if ($this->tabAccess['edit'] === '1') - { - $algo = (int)Tools::getValue('PS_CIPHER_ALGORITHM'); - $prev_settings = file_get_contents(_PS_ROOT_DIR_.'/config/settings.inc.php'); - $new_settings = $prev_settings; - if ($algo) - { - if (!function_exists('mcrypt_encrypt')) - $this->errors[] = Tools::displayError('The "Mcrypt" PHP extension is not activated on this server.'); - else - { - if (!strstr($new_settings, '_RIJNDAEL_KEY_')) - { - $key_size = mcrypt_get_key_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB); - $key = Tools::passwdGen($key_size); - $new_settings = preg_replace( - '/define\(\'_COOKIE_KEY_\', \'([a-z0-9=\/+-_]+)\'\);/i', - 'define(\'_COOKIE_KEY_\', \'\1\');'."\n".'define(\'_RIJNDAEL_KEY_\', \''.$key.'\');', - $new_settings - ); - } - if (!strstr($new_settings, '_RIJNDAEL_IV_')) - { - $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB); - $iv = base64_encode(mcrypt_create_iv($iv_size, MCRYPT_RAND)); - $new_settings = preg_replace( - '/define\(\'_COOKIE_IV_\', \'([a-z0-9=\/+-_]+)\'\);/i', - 'define(\'_COOKIE_IV_\', \'\1\');'."\n".'define(\'_RIJNDAEL_IV_\', \''.$iv.'\');', - $new_settings - ); - } - } - } - if (!count($this->errors)) - { - // If there is not settings file modification or if the backup and replacement of the settings file worked - if ($new_settings == $prev_settings || ( - copy(_PS_ROOT_DIR_.'/config/settings.inc.php', _PS_ROOT_DIR_.'/config/settings.old.php') - && (bool)file_put_contents(_PS_ROOT_DIR_.'/config/settings.inc.php', $new_settings) - )) - { - Configuration::updateValue('PS_CIPHER_ALGORITHM', $algo); - $redirectAdmin = true; - } - else - $this->errors[] = Tools::displayError('The settings file cannot be overwritten.'); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } + if (is_writable(_PS_ROOT_DIR_.'/.htaccess')) { + Tools::generateHtaccess(null, null, null, '', null, array($base_urls['_MEDIA_SERVER_1_'], $base_urls['_MEDIA_SERVER_2_'], $base_urls['_MEDIA_SERVER_3_'])); + unset($this->_fieldsGeneral['_MEDIA_SERVER_1_']); + unset($this->_fieldsGeneral['_MEDIA_SERVER_2_']); + unset($this->_fieldsGeneral['_MEDIA_SERVER_3_']); + $redirectAdmin = true; + } else { + $message = $this->l('Before being able to use this tool, you need to:'); + $message .= '<br />- '.$this->l('Create a blank .htaccess in your root directory.'); + $message .= '<br />- '.$this->l('Give it write permissions (CHMOD 666 on Unix system).'); + $this->errors[] = Tools::displayError($message, false); + Configuration::updateValue('PS_HTACCESS_CACHE_CONTROL', false); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + if ((bool)Tools::getValue('ciphering_up') && Configuration::get('PS_CIPHER_ALGORITHM') != (int)Tools::getValue('PS_CIPHER_ALGORITHM')) { + if ($this->tabAccess['edit'] === '1') { + $algo = (int)Tools::getValue('PS_CIPHER_ALGORITHM'); + $prev_settings = file_get_contents(_PS_ROOT_DIR_.'/config/settings.inc.php'); + $new_settings = $prev_settings; + if ($algo) { + if (!function_exists('mcrypt_encrypt')) { + $this->errors[] = Tools::displayError('The "Mcrypt" PHP extension is not activated on this server.'); + } else { + if (!strstr($new_settings, '_RIJNDAEL_KEY_')) { + $key_size = mcrypt_get_key_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB); + $key = Tools::passwdGen($key_size); + $new_settings = preg_replace( + '/define\(\'_COOKIE_KEY_\', \'([a-z0-9=\/+-_]+)\'\);/i', + 'define(\'_COOKIE_KEY_\', \'\1\');'."\n".'define(\'_RIJNDAEL_KEY_\', \''.$key.'\');', + $new_settings + ); + } + if (!strstr($new_settings, '_RIJNDAEL_IV_')) { + $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB); + $iv = base64_encode(mcrypt_create_iv($iv_size, MCRYPT_RAND)); + $new_settings = preg_replace( + '/define\(\'_COOKIE_IV_\', \'([a-z0-9=\/+-_]+)\'\);/i', + 'define(\'_COOKIE_IV_\', \'\1\');'."\n".'define(\'_RIJNDAEL_IV_\', \''.$iv.'\');', + $new_settings + ); + } + } + } + if (!count($this->errors)) { + // If there is not settings file modification or if the backup and replacement of the settings file worked + if ($new_settings == $prev_settings || ( + copy(_PS_ROOT_DIR_.'/config/settings.inc.php', _PS_ROOT_DIR_.'/config/settings.old.php') + && (bool)file_put_contents(_PS_ROOT_DIR_.'/config/settings.inc.php', $new_settings) + )) { + Configuration::updateValue('PS_CIPHER_ALGORITHM', $algo); + $redirectAdmin = true; + } else { + $this->errors[] = Tools::displayError('The settings file cannot be overwritten.'); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } - if ((bool)Tools::getValue('cache_up')) - { - if ($this->tabAccess['edit'] === '1') - { - $new_settings = $prev_settings = file_get_contents(_PS_ROOT_DIR_.'/config/settings.inc.php'); - $cache_active = (bool)Tools::getValue('cache_active'); + if ((bool)Tools::getValue('cache_up')) { + if ($this->tabAccess['edit'] === '1') { + $new_settings = $prev_settings = file_get_contents(_PS_ROOT_DIR_.'/config/settings.inc.php'); + $cache_active = (bool)Tools::getValue('cache_active'); - if ($caching_system = preg_replace('[^a-zA-Z0-9]', '', Tools::getValue('caching_system'))) - { - $new_settings = preg_replace( - '/define\(\'_PS_CACHING_SYSTEM_\', \'([a-z0-9=\/+-_]*)\'\);/Ui', - 'define(\'_PS_CACHING_SYSTEM_\', \''.$caching_system.'\');', - $new_settings - ); - } - else - { - $cache_active = false; - $this->errors[] = Tools::displayError('The caching system is missing.'); - } - if ($cache_active) - { - if ($caching_system == 'CacheMemcache' && !extension_loaded('memcache')) - $this->errors[] = Tools::displayError('To use Memcached, you must install the Memcache PECL extension on your server.').' + if ($caching_system = preg_replace('[^a-zA-Z0-9]', '', Tools::getValue('caching_system'))) { + $new_settings = preg_replace( + '/define\(\'_PS_CACHING_SYSTEM_\', \'([a-z0-9=\/+-_]*)\'\);/Ui', + 'define(\'_PS_CACHING_SYSTEM_\', \''.$caching_system.'\');', + $new_settings + ); + } else { + $cache_active = false; + $this->errors[] = Tools::displayError('The caching system is missing.'); + } + if ($cache_active) { + if ($caching_system == 'CacheMemcache' && !extension_loaded('memcache')) { + $this->errors[] = Tools::displayError('To use Memcached, you must install the Memcache PECL extension on your server.').' <a href="http://www.php.net/manual/en/memcache.installation.php">http://www.php.net/manual/en/memcache.installation.php</a>'; - elseif ($caching_system == 'CacheMemcached' && !extension_loaded('memcached')) - $this->errors[] = Tools::displayError('To use Memcached, you must install the Memcached PECL extension on your server.').' + } elseif ($caching_system == 'CacheMemcached' && !extension_loaded('memcached')) { + $this->errors[] = Tools::displayError('To use Memcached, you must install the Memcached PECL extension on your server.').' <a href="http://www.php.net/manual/en/memcached.installation.php">http://www.php.net/manual/en/memcached.installation.php</a>'; - elseif ($caching_system == 'CacheApc' && !extension_loaded('apc')) - $this->errors[] = Tools::displayError('To use APC cache, you must install the APC PECL extension on your server.').' + } elseif ($caching_system == 'CacheApc' && !extension_loaded('apc')) { + $this->errors[] = Tools::displayError('To use APC cache, you must install the APC PECL extension on your server.').' <a href="http://fr.php.net/manual/fr/apc.installation.php">http://fr.php.net/manual/fr/apc.installation.php</a>'; - elseif ($caching_system == 'CacheXcache' && !extension_loaded('xcache')) - $this->errors[] = Tools::displayError('To use Xcache, you must install the Xcache extension on your server.').' + } elseif ($caching_system == 'CacheXcache' && !extension_loaded('xcache')) { + $this->errors[] = Tools::displayError('To use Xcache, you must install the Xcache extension on your server.').' <a href="http://xcache.lighttpd.net">http://xcache.lighttpd.net</a>'; - elseif ($caching_system == 'CacheXcache' && !ini_get('xcache.var_size')) - $this->errors[] = Tools::displayError('To use Xcache, you must configure "xcache.var_size" for the Xcache extension (recommended value 16M to 64M).').' + } elseif ($caching_system == 'CacheXcache' && !ini_get('xcache.var_size')) { + $this->errors[] = Tools::displayError('To use Xcache, you must configure "xcache.var_size" for the Xcache extension (recommended value 16M to 64M).').' <a href="http://xcache.lighttpd.net/wiki/XcacheIni">http://xcache.lighttpd.net/wiki/XcacheIni</a>'; - elseif ($caching_system == 'CacheFs') - if (!is_dir(_PS_CACHEFS_DIRECTORY_)) - @mkdir(_PS_CACHEFS_DIRECTORY_, 0777, true); - elseif (!is_writable(_PS_CACHEFS_DIRECTORY_)) - $this->errors[] = sprintf(Tools::displayError('To use CacheFS, the directory %s must be writable.'), realpath(_PS_CACHEFS_DIRECTORY_)); + } elseif ($caching_system == 'CacheFs') { + if (!is_dir(_PS_CACHEFS_DIRECTORY_)) { + @mkdir(_PS_CACHEFS_DIRECTORY_, 0777, true); + } elseif (!is_writable(_PS_CACHEFS_DIRECTORY_)) { + $this->errors[] = sprintf(Tools::displayError('To use CacheFS, the directory %s must be writable.'), realpath(_PS_CACHEFS_DIRECTORY_)); + } + } - if ($caching_system == 'CacheFs') - { - if (!($depth = Tools::getValue('ps_cache_fs_directory_depth'))) - $this->errors[] = Tools::displayError('Please set a directory depth.'); - if (!count($this->errors)) - { - CacheFs::deleteCacheDirectory(); - CacheFs::createCacheDirectories((int)$depth); - Configuration::updateValue('PS_CACHEFS_DIRECTORY_DEPTH', (int)$depth); - } - } - elseif ($caching_system == 'CacheMemcache' && !_PS_CACHE_ENABLED_ && _PS_CACHING_SYSTEM_ == 'CacheMemcache') - Cache::getInstance()->flush(); - elseif ($caching_system == 'CacheMemcached' && !_PS_CACHE_ENABLED_ && _PS_CACHING_SYSTEM_ == 'CacheMemcached') - Cache::getInstance()->flush(); - } + if ($caching_system == 'CacheFs') { + if (!($depth = Tools::getValue('ps_cache_fs_directory_depth'))) { + $this->errors[] = Tools::displayError('Please set a directory depth.'); + } + if (!count($this->errors)) { + CacheFs::deleteCacheDirectory(); + CacheFs::createCacheDirectories((int)$depth); + Configuration::updateValue('PS_CACHEFS_DIRECTORY_DEPTH', (int)$depth); + } + } elseif ($caching_system == 'CacheMemcache' && !_PS_CACHE_ENABLED_ && _PS_CACHING_SYSTEM_ == 'CacheMemcache') { + Cache::getInstance()->flush(); + } elseif ($caching_system == 'CacheMemcached' && !_PS_CACHE_ENABLED_ && _PS_CACHING_SYSTEM_ == 'CacheMemcached') { + Cache::getInstance()->flush(); + } + } - if (!count($this->errors)) - { - $new_settings = preg_replace('/define\(\'_PS_CACHE_ENABLED_\', \'([01]?)\'\);/Ui', 'define(\'_PS_CACHE_ENABLED_\', \''.(int)$cache_active.'\');', $new_settings); - // If there is not settings file modification or if the backup and replacement of the settings file worked - if ($new_settings == $prev_settings || ( - copy(_PS_ROOT_DIR_.'/config/settings.inc.php', _PS_ROOT_DIR_.'/config/settings.old.php') - && (bool)file_put_contents(_PS_ROOT_DIR_.'/config/settings.inc.php', $new_settings) - )) - { - if (function_exists('opcache_invalidate')) - opcache_invalidate(_PS_ROOT_DIR_.'/config/settings.inc.php'); - $redirectAdmin = true; - } - else - $this->errors[] = Tools::displayError('The settings file cannot be overwritten.'); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } + if (!count($this->errors)) { + $new_settings = preg_replace('/define\(\'_PS_CACHE_ENABLED_\', \'([01]?)\'\);/Ui', 'define(\'_PS_CACHE_ENABLED_\', \''.(int)$cache_active.'\');', $new_settings); + // If there is not settings file modification or if the backup and replacement of the settings file worked + if ($new_settings == $prev_settings || ( + copy(_PS_ROOT_DIR_.'/config/settings.inc.php', _PS_ROOT_DIR_.'/config/settings.old.php') + && (bool)file_put_contents(_PS_ROOT_DIR_.'/config/settings.inc.php', $new_settings) + )) { + if (function_exists('opcache_invalidate')) { + opcache_invalidate(_PS_ROOT_DIR_.'/config/settings.inc.php'); + } + $redirectAdmin = true; + } else { + $this->errors[] = Tools::displayError('The settings file cannot be overwritten.'); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } - if ((bool)Tools::getValue('empty_smarty_cache')) - { - $redirectAdmin = true; - Tools::clearSmartyCache(); - Tools::clearXMLCache(); - Media::clearCache(); - Tools::generateIndex(); - } + if ((bool)Tools::getValue('empty_smarty_cache')) { + $redirectAdmin = true; + Tools::clearSmartyCache(); + Tools::clearXMLCache(); + Media::clearCache(); + Tools::generateIndex(); + } - if (Tools::isSubmit('submitAddconfiguration')) - { - Configuration::updateGlobalValue('PS_DISABLE_NON_NATIVE_MODULE', (int)Tools::getValue('native_module')); - Configuration::updateGlobalValue('PS_DISABLE_OVERRIDES', (int)Tools::getValue('overrides')); - Tools::generateIndex(); - } + if (Tools::isSubmit('submitAddconfiguration')) { + Configuration::updateGlobalValue('PS_DISABLE_NON_NATIVE_MODULE', (int)Tools::getValue('native_module')); + Configuration::updateGlobalValue('PS_DISABLE_OVERRIDES', (int)Tools::getValue('overrides')); + Tools::generateIndex(); + } - if ($redirectAdmin && (!isset($this->errors) || !count($this->errors))) - { - Hook::exec('action'.get_class($this).ucfirst($this->action).'After', array('controller' => $this, 'return' => '')); - Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getValue('token').'&conf=4'); - } - } + if ($redirectAdmin && (!isset($this->errors) || !count($this->errors))) { + Hook::exec('action'.get_class($this).ucfirst($this->action).'After', array('controller' => $this, 'return' => '')); + Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getValue('token').'&conf=4'); + } + } - public function displayAjaxTestServer() - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - die(Tools::displayError('This functionality has been disabled.')); - /* PrestaShop demo mode*/ - if (Tools::isSubmit('action') && Tools::getValue('action') == 'test_server') - { - $host = pSQL(Tools::getValue('sHost', '')); - $port = (int)Tools::getValue('sPort', 0); + public function displayAjaxTestServer() + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + die(Tools::displayError('This functionality has been disabled.')); + } + /* PrestaShop demo mode*/ + if (Tools::isSubmit('action') && Tools::getValue('action') == 'test_server') { + $host = pSQL(Tools::getValue('sHost', '')); + $port = (int)Tools::getValue('sPort', 0); + $type = Tools::getValue('type', ''); - if ($host != '' && $port != 0) - { - $res = 0; + if ($host != '' && $port != 0) { + $res = 0; - if (function_exists('memcache_get_server_status') && - function_exists('memcache_connect') && - @fsockopen($host, $port)) - { - $memcache = @memcache_connect($host, $port); - $res = @memcache_get_server_status($memcache, $host, $port); - } - die(Tools::jsonEncode(array($res))); - } - } - die; - } -} \ No newline at end of file + if ($type == 'memcached') { + if (extension_loaded('memcached') && + @fsockopen($host, $port) + ) { + $memcache = new Memcached(); + $memcache->addServer($host, $port); + + $res = in_array('255.255.255', $memcache->getVersion(), true) === false; + } + } else { + if (function_exists('memcache_get_server_status') && + function_exists('memcache_connect') && + @fsockopen($host, $port) + ) { + $memcache = @memcache_connect($host, $port); + $res = @memcache_get_server_status($memcache, $host, $port); + } + } + die(Tools::jsonEncode(array($res))); + } + } + die; + } +} diff --git a/controllers/admin/AdminPreferencesController.php b/controllers/admin/AdminPreferencesController.php index da3b1815..51dcab34 100644 --- a/controllers/admin/AdminPreferencesController.php +++ b/controllers/admin/AdminPreferencesController.php @@ -29,233 +29,218 @@ */ class AdminPreferencesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->context = Context::getContext(); - $this->className = 'Configuration'; - $this->table = 'configuration'; + public function __construct() + { + $this->bootstrap = true; + $this->context = Context::getContext(); + $this->className = 'Configuration'; + $this->table = 'configuration'; - // Prevent classes which extend AdminPreferences to load useless data - if (get_class($this) == 'AdminPreferencesController') - { - $round_mode = array( - array( - 'value' => PS_ROUND_HALF_UP, - 'name' => $this->l('Round up away from zero, when it is half way there (recommended)') - ), - array( - 'value' => PS_ROUND_HALF_DOWN, - 'name' => $this->l('Round down towards zero, when it is half way there') - ), - array( - 'value' => PS_ROUND_HALF_EVEN, - 'name' => $this->l('Round towards the next even value') - ), - array( - 'value' => PS_ROUND_HALF_ODD, - 'name' => $this->l('Round towards the next odd value') - ), - array( - 'value' => PS_ROUND_UP, - 'name' => $this->l('Round up to the nearest value') - ), - array( - 'value' => PS_ROUND_DOWN, - 'name' => $this->l('Round down to the nearest value') - ), - ); - $activities1 = array( - 0 => $this->l('-- Please choose your main activity --'), - 2 => $this->l('Animals and Pets'), - 3 => $this->l('Art and Culture'), - 4 => $this->l('Babies'), - 5 => $this->l('Beauty and Personal Care'), - 6 => $this->l('Cars'), - 7 => $this->l('Computer Hardware and Software'), - 8 => $this->l('Download'), - 9 => $this->l('Fashion and accessories'), - 10 => $this->l('Flowers, Gifts and Crafts'), - 11 => $this->l('Food and beverage'), - 12 => $this->l('HiFi, Photo and Video'), - 13 => $this->l('Home and Garden'), - 14 => $this->l('Home Appliances'), - 15 => $this->l('Jewelry'), - 1 => $this->l('Lingerie and Adult'), - 16 => $this->l('Mobile and Telecom'), - 17 => $this->l('Services'), - 18 => $this->l('Shoes and accessories'), - 19 => $this->l('Sport and Entertainment'), - 20 => $this->l('Travel') - ); - $activities2 = array(); - foreach ($activities1 as $value => $name) - $activities2[] = array('value' => $value, 'name' => $name); + // Prevent classes which extend AdminPreferences to load useless data + if (get_class($this) == 'AdminPreferencesController') { + $round_mode = array( + array( + 'value' => PS_ROUND_HALF_UP, + 'name' => $this->l('Round up away from zero, when it is half way there (recommended)') + ), + array( + 'value' => PS_ROUND_HALF_DOWN, + 'name' => $this->l('Round down towards zero, when it is half way there') + ), + array( + 'value' => PS_ROUND_HALF_EVEN, + 'name' => $this->l('Round towards the next even value') + ), + array( + 'value' => PS_ROUND_HALF_ODD, + 'name' => $this->l('Round towards the next odd value') + ), + array( + 'value' => PS_ROUND_UP, + 'name' => $this->l('Round up to the nearest value') + ), + array( + 'value' => PS_ROUND_DOWN, + 'name' => $this->l('Round down to the nearest value') + ), + ); + $activities1 = array( + 0 => $this->l('-- Please choose your main activity --'), + 2 => $this->l('Animals and Pets'), + 3 => $this->l('Art and Culture'), + 4 => $this->l('Babies'), + 5 => $this->l('Beauty and Personal Care'), + 6 => $this->l('Cars'), + 7 => $this->l('Computer Hardware and Software'), + 8 => $this->l('Download'), + 9 => $this->l('Fashion and accessories'), + 10 => $this->l('Flowers, Gifts and Crafts'), + 11 => $this->l('Food and beverage'), + 12 => $this->l('HiFi, Photo and Video'), + 13 => $this->l('Home and Garden'), + 14 => $this->l('Home Appliances'), + 15 => $this->l('Jewelry'), + 1 => $this->l('Lingerie and Adult'), + 16 => $this->l('Mobile and Telecom'), + 17 => $this->l('Services'), + 18 => $this->l('Shoes and accessories'), + 19 => $this->l('Sport and Entertainment'), + 20 => $this->l('Travel') + ); + $activities2 = array(); + foreach ($activities1 as $value => $name) { + $activities2[] = array('value' => $value, 'name' => $name); + } - $disable_ssl = false; + $fields = array( + 'PS_SSL_ENABLED' => array( + 'title' => $this->l('Enable SSL'), + 'desc' => $this->l('If you own an SSL certificate for your shop\'s domain name, you can activate SSL encryption (https://) for customer account identification and order processing.'), + 'hint' => $this->l('If you want to enable SSL on all the pages of your shop, activate the "Enable on all the pages" option below.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'default' => '0' + ), + ); - if (defined('_PS_HOST_DOMAINS_') && defined('_PS_HOST_MODE_') && _PS_HOST_MODE_) - { - $host_mode_domains = explode(',', (string)_PS_HOST_DOMAINS_); - $domain_parts = array_reverse(explode('.', $this->context->shop->domain_ssl)); + $fields['PS_SSL_ENABLED_EVERYWHERE'] = array( + 'title' => $this->l('Enable SSL on all pages'), + 'desc' => $this->l('When enabled, all the pages of your shop will be SSL-secured.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'default' => '0', + 'disabled' => (Tools::getValue('PS_SSL_ENABLED', Configuration::get('PS_SSL_ENABLED'))) ? false : true + ); - if (isset($host_mode_domains) && isset($domain_parts[1]) && isset($domain_parts[0]) - && !in_array($domain_parts[1].'.'.$domain_parts[0], $host_mode_domains)) - $disable_ssl = true; - } + $fields = array_merge($fields, array( + 'PS_TOKEN_ENABLE' => array( + 'title' => $this->l('Increase front office security'), + 'desc' => $this->l('Enable or disable token in the Front Office to improve PrestaShop\'s security.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'default' => '0', + 'visibility' => Shop::CONTEXT_ALL + ), + 'PS_ALLOW_HTML_IFRAME' => array( + 'title' => $this->l('Allow iframes on HTML fields'), + 'desc' => $this->l('Allow iframes on text fields like product description. We recommend that you leave this option disabled.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'default' => '0' + ), + 'PS_USE_HTMLPURIFIER' => array( + 'title' => $this->l('Use HTMLPurifier Library'), + 'desc' => $this->l('Clean the HTML content on text fields. We recommend that you leave this option enabled.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'default' => '0' + ), + 'PS_PRICE_ROUND_MODE' => array( + 'title' => $this->l('Round mode'), + 'desc' => $this->l('You can choose among 6 different ways of rounding prices. "Round up away from zero ..." is the recommended behavior.'), + 'validation' => 'isInt', + 'cast' => 'intval', + 'type' => 'select', + 'list' => $round_mode, + 'identifier' => 'value' + ), + 'PS_ROUND_TYPE' => array( + 'title' => $this->l('Round type'), + 'desc' => $this->l('You can choose when to round prices: either on each item, each line or the total (of an invoice, for example).'), + 'cast' => 'intval', + 'type' => 'select', + 'list' => array( + array( + 'name' => $this->l('Round on each item'), + 'id' => Order::ROUND_ITEM + ), + array( + 'name' => $this->l('Round on each line'), + 'id' => Order::ROUND_LINE + ), + array( + 'name' => $this->l('Round on the total'), + 'id' => Order::ROUND_TOTAL + ), + ), + 'identifier' => 'id' + ), + 'PS_PRICE_DISPLAY_PRECISION' => array( + 'title' => $this->l('Number of decimals'), + 'desc' => $this->l('Choose how many decimals you want to display'), + 'validation' => 'isUnsignedInt', + 'cast' => 'intval', + 'type' => 'text', + 'class' => 'fixed-width-xxl' + ), + 'PS_DISPLAY_SUPPLIERS' => array( + 'title' => $this->l('Display suppliers and manufacturers'), + 'desc' => $this->l('Enable suppliers and manufacturers pages on your front office even when their respective modules are disabled.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_DISPLAY_BEST_SELLERS' => array( + 'title' => $this->l('Display best sellers'), + 'desc' => $this->l('Enable best sellers page on your front office even when its respective module is disabled.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_MULTISHOP_FEATURE_ACTIVE' => array( + 'title' => $this->l('Enable Multistore'), + 'desc' => $this->l('The multistore feature allows you to manage several e-shops with one Back Office. If this feature is enabled, a "Multistore" page will be available in the "Advanced Parameters" menu.'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'visibility' => Shop::CONTEXT_ALL + ), + 'PS_SHOP_ACTIVITY' => array( + 'title' => $this->l('Main Shop Activity'), + 'validation' => 'isInt', + 'cast' => 'intval', + 'type' => 'select', + 'list' => $activities2, + 'identifier' => 'value' + ), + )); - $fields = array( - 'PS_SSL_ENABLED' => array( - 'title' => $this->l('Enable SSL'), - 'desc' => $disable_ssl - ? $this->l('It is not possible to enable SSL while you are using a custom domain name for your shop. SSL has thus been disabled.') - : $this->l('If your hosting provider allows SSL, you can activate SSL encryption (https://) for customer account identification and order processing.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'default' => '0', - 'disabled' => $disable_ssl - ), - ); + // No HTTPS activation if you haven't already. + if (!Tools::usingSecureMode() && !Configuration::get('PS_SSL_ENABLED')) { + $fields['PS_SSL_ENABLED']['type'] = 'disabled'; + $fields['PS_SSL_ENABLED']['disabled'] = '<a class="btn btn-link" href="https://'.Tools::getShopDomainSsl().Tools::safeOutput($_SERVER['REQUEST_URI']).'">'. + $this->l('Please click here to check if your shop supports HTTPS.').'</a>'; + } - if (Tools::getValue('PS_SSL_ENABLED', Configuration::get('PS_SSL_ENABLED'))) - $fields['PS_SSL_ENABLED_EVERYWHERE'] = array( - 'title' => $this->l('Force the SSL on all the pages'), - 'desc' => $this->l('Force all your store to use SSL.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'default' => '0' - ); + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('General'), + 'icon' => 'icon-cogs', + 'fields' => $fields, + 'submit' => array('title' => $this->l('Save')), + ), + ); + } - $fields = array_merge($fields, array( - 'PS_TOKEN_ENABLE' => array( - 'title' => $this->l('Increase front office security'), - 'desc' => $this->l('Enable or disable token in the Front Office to improve PrestaShop\'s security.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'default' => '0', - 'visibility' => Shop::CONTEXT_ALL - ), - 'PS_ALLOW_HTML_IFRAME' => array( - 'title' => $this->l('Allow iframes on HTML fields'), - 'desc' => $this->l('Allow iframes on text fields like product description. We recommend that you leave this option disabled.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'default' => '0' - ), - 'PS_USE_HTMLPURIFIER' => array( - 'title' => $this->l('Use HTMLPurifier Library'), - 'desc' => $this->l('Clean the HTML content on text fields. We recommend that you leave this option enabled.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'default' => '0' - ), - 'PS_PRICE_ROUND_MODE' => array( - 'title' => $this->l('Round mode'), - 'desc' => $this->l('You can choose among 6 different ways of rounding prices. "Round up away from zero ..." is the recommended behavior.'), - 'validation' => 'isInt', - 'cast' => 'intval', - 'type' => 'select', - 'list' => $round_mode, - 'identifier' => 'value' - ), - 'PS_ROUND_TYPE' => array( - 'title' => $this->l('Round type'), - 'desc' => $this->l('You can choose when to round prices: either on each item, each line or the total (of an invoice, for example).'), - 'cast' => 'intval', - 'type' => 'select', - 'list' => array( - array( - 'name' => $this->l('Round on each item'), - 'id' => Order::ROUND_ITEM - ), - array( - 'name' => $this->l('Round on each line'), - 'id' => Order::ROUND_LINE - ), - array( - 'name' => $this->l('Round on the total'), - 'id' => Order::ROUND_TOTAL - ), - ), - 'identifier' => 'id' - ), - 'PS_PRICE_DISPLAY_PRECISION' => array( - 'title' => $this->l('Number of decimals'), - 'desc' => $this->l('Choose how many decimals you want to display'), - 'validation' => 'isUnsignedInt', - 'cast' => 'intval', - 'type' => 'text', - 'class' => 'fixed-width-xxl' - ), - 'PS_DISPLAY_SUPPLIERS' => array( - 'title' => $this->l('Display suppliers and manufacturers'), - 'desc' => $this->l('Enable suppliers and manufacturers pages on your front office even when their respective modules are disabled.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_DISPLAY_BEST_SELLERS' => array( - 'title' => $this->l('Display best sellers'), - 'desc' => $this->l('Enable best sellers page on your front office even when its respective module is disabled.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_MULTISHOP_FEATURE_ACTIVE' => array( - 'title' => $this->l('Enable Multistore'), - 'desc' => $this->l('The multistore feature allows you to manage several e-shops with one Back Office. If this feature is enabled, a "Multistore" page will be available in the "Advanced Parameters" menu.'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'visibility' => Shop::CONTEXT_ALL - ), - 'PS_SHOP_ACTIVITY' => array( - 'title' => $this->l('Main Shop Activity'), - 'validation' => 'isInt', - 'cast' => 'intval', - 'type' => 'select', - 'list' => $activities2, - 'identifier' => 'value' - ), - )); + parent::__construct(); + } - // No HTTPS activation if you haven't already. - if (!Tools::usingSecureMode() && !Configuration::get('PS_SSL_ENABLED')) - { - $fields['PS_SSL_ENABLED']['type'] = 'disabled'; - $fields['PS_SSL_ENABLED']['disabled'] = '<a class="btn btn-link" href="https://'.Tools::getShopDomainSsl().Tools::safeOutput($_SERVER['REQUEST_URI']).'">'. - $this->l('Please click here to use HTTPS protocol before enabling SSL.').'</a>'; - } + /** + * Enable / disable multishop menu if multishop feature is activated + * + * @param string $value + */ + public function updateOptionPsMultishopFeatureActive($value) + { + Configuration::updateValue('PS_MULTISHOP_FEATURE_ACTIVE', $value); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('General'), - 'icon' => 'icon-cogs', - 'fields' => $fields, - 'submit' => array('title' => $this->l('Save')), - ), - ); - } - - parent::__construct(); - } - - /** - * Enable / disable multishop menu if multishop feature is activated - * - * @param string $value - */ - public function updateOptionPsMultishopFeatureActive($value) - { - Configuration::updateValue('PS_MULTISHOP_FEATURE_ACTIVE', $value); - - $tab = Tab::getInstanceFromClassName('AdminShopGroup'); - $tab->active = (bool)Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE'); - $tab->update(); - } + $tab = Tab::getInstanceFromClassName('AdminShopGroup'); + $tab->active = (bool)Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE'); + $tab->update(); + } } diff --git a/controllers/admin/AdminProductsController.php b/controllers/admin/AdminProductsController.php index a9308d84..d484acb0 100644 --- a/controllers/admin/AdminProductsController.php +++ b/controllers/admin/AdminProductsController.php @@ -29,2577 +29,2625 @@ */ class AdminProductsControllerCore extends AdminController { - /** @var int Max image size for upload - * As of 1.5 it is recommended to not set a limit to max image size - */ - protected $max_file_size = null; - protected $max_image_size = null; + /** @var int Max image size for upload + * As of 1.5 it is recommended to not set a limit to max image size + */ + protected $max_file_size = null; + protected $max_image_size = null; - protected $_category; - /** - * @var string name of the tab to display - */ - protected $tab_display; - protected $tab_display_module; + protected $_category; + /** + * @var string name of the tab to display + */ + protected $tab_display; + protected $tab_display_module; - /** - * The order in the array decides the order in the list of tab. If an element's value is a number, it will be preloaded. - * The tabs are preloaded from the smallest to the highest number. - * @var array Product tabs. - */ - protected $available_tabs = array(); + /** + * The order in the array decides the order in the list of tab. If an element's value is a number, it will be preloaded. + * The tabs are preloaded from the smallest to the highest number. + * @var array Product tabs. + */ + protected $available_tabs = array(); - protected $default_tab = 'Informations'; + protected $default_tab = 'Informations'; - protected $available_tabs_lang = array(); + protected $available_tabs_lang = array(); - protected $position_identifier = 'id_product'; + protected $position_identifier = 'id_product'; - protected $submitted_tabs; + protected $submitted_tabs; - protected $id_current_category; + protected $id_current_category; - public function __construct() - { - $this->bootstrap = true; - $this->table = 'product'; - $this->className = 'Product'; - $this->lang = true; - $this->explicitSelect = true; - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'icon' => 'icon-trash', - 'confirm' => $this->l('Delete selected items?') - ) - ); - if (!Tools::getValue('id_product')) - $this->multishop_context_group = false; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'product'; + $this->className = 'Product'; + $this->lang = true; + $this->explicitSelect = true; + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'icon' => 'icon-trash', + 'confirm' => $this->l('Delete selected items?') + ) + ); + if (!Tools::getValue('id_product')) { + $this->multishop_context_group = false; + } - parent::__construct(); + parent::__construct(); - $this->imageType = 'jpg'; - $this->_defaultOrderBy = 'position'; - $this->max_file_size = (int)(Configuration::get('PS_LIMIT_UPLOAD_FILE_VALUE') * 1000000); - $this->max_image_size = (int)Configuration::get('PS_PRODUCT_PICTURE_MAX_SIZE'); - $this->allow_export = true; + $this->imageType = 'jpg'; + $this->_defaultOrderBy = 'position'; + $this->max_file_size = (int)(Configuration::get('PS_LIMIT_UPLOAD_FILE_VALUE') * 1000000); + $this->max_image_size = (int)Configuration::get('PS_PRODUCT_PICTURE_MAX_SIZE'); + $this->allow_export = true; - // @since 1.5 : translations for tabs - $this->available_tabs_lang = array( - 'Informations' => $this->l('Information'), - 'Pack' => $this->l('Pack'), - 'VirtualProduct' => $this->l('Virtual Product'), - 'Prices' => $this->l('Prices'), - 'Seo' => $this->l('SEO'), - 'Images' => $this->l('Images'), - 'Associations' => $this->l('Associations'), - 'Shipping' => $this->l('Shipping'), - 'Combinations' => $this->l('Combinations'), - 'Features' => $this->l('Features'), - 'Customization' => $this->l('Customization'), - 'Attachments' => $this->l('Attachments'), - 'Quantities' => $this->l('Quantities'), - 'Suppliers' => $this->l('Suppliers'), - 'Warehouses' => $this->l('Warehouses'), - ); + // @since 1.5 : translations for tabs + $this->available_tabs_lang = array( + 'Informations' => $this->l('Information'), + 'Pack' => $this->l('Pack'), + 'VirtualProduct' => $this->l('Virtual Product'), + 'Prices' => $this->l('Prices'), + 'Seo' => $this->l('SEO'), + 'Images' => $this->l('Images'), + 'Associations' => $this->l('Associations'), + 'Shipping' => $this->l('Shipping'), + 'Combinations' => $this->l('Combinations'), + 'Features' => $this->l('Features'), + 'Customization' => $this->l('Customization'), + 'Attachments' => $this->l('Attachments'), + 'Quantities' => $this->l('Quantities'), + 'Suppliers' => $this->l('Suppliers'), + 'Warehouses' => $this->l('Warehouses'), + ); - $this->available_tabs = array('Quantities' => 6, 'Warehouses' => 14); - if ($this->context->shop->getContext() != Shop::CONTEXT_GROUP) - $this->available_tabs = array_merge($this->available_tabs, array( - 'Informations' => 0, - 'Pack' => 7, - 'VirtualProduct' => 8, - 'Prices' => 1, - 'Seo' => 2, - 'Associations' => 3, - 'Images' => 9, - 'Shipping' => 4, - 'Combinations' => 5, - 'Features' => 10, - 'Customization' => 11, - 'Attachments' => 12, - 'Suppliers' => 13, - )); + $this->available_tabs = array('Quantities' => 6, 'Warehouses' => 14); + if ($this->context->shop->getContext() != Shop::CONTEXT_GROUP) { + $this->available_tabs = array_merge($this->available_tabs, array( + 'Informations' => 0, + 'Pack' => 7, + 'VirtualProduct' => 8, + 'Prices' => 1, + 'Seo' => 2, + 'Associations' => 3, + 'Images' => 9, + 'Shipping' => 4, + 'Combinations' => 5, + 'Features' => 10, + 'Customization' => 11, + 'Attachments' => 12, + 'Suppliers' => 13, + )); + } - // Sort the tabs that need to be preloaded by their priority number - asort($this->available_tabs, SORT_NUMERIC); + // Sort the tabs that need to be preloaded by their priority number + asort($this->available_tabs, SORT_NUMERIC); - /* Adding tab if modules are hooked */ - $modules_list = Hook::getHookModuleExecList('displayAdminProductsExtra'); - if (is_array($modules_list) && count($modules_list) > 0) - foreach ($modules_list as $m) - { - $this->available_tabs['Module'.ucfirst($m['module'])] = 23; - $this->available_tabs_lang['Module'.ucfirst($m['module'])] = Module::getModuleName($m['module']); - } + /* Adding tab if modules are hooked */ + $modules_list = Hook::getHookModuleExecList('displayAdminProductsExtra'); + if (is_array($modules_list) && count($modules_list) > 0) { + foreach ($modules_list as $m) { + $this->available_tabs['Module'.ucfirst($m['module'])] = 23; + $this->available_tabs_lang['Module'.ucfirst($m['module'])] = Module::getModuleName($m['module']); + } + } - if (Tools::getValue('reset_filter_category')) - $this->context->cookie->id_category_products_filter = false; - if (Shop::isFeatureActive() && $this->context->cookie->id_category_products_filter) - { - $category = new Category((int)$this->context->cookie->id_category_products_filter); - if (!$category->inShop()) - { - $this->context->cookie->id_category_products_filter = false; - Tools::redirectAdmin($this->context->link->getAdminLink('AdminProducts')); - } - } - /* Join categories table */ - if ($id_category = (int)Tools::getValue('productFilter_cl!name')) - { - $this->_category = new Category((int)$id_category); - $_POST['productFilter_cl!name'] = $this->_category->name[$this->context->language->id]; - } - else - { - if ($id_category = (int)Tools::getValue('id_category')) - { - $this->id_current_category = $id_category; - $this->context->cookie->id_category_products_filter = $id_category; - } - elseif ($id_category = $this->context->cookie->id_category_products_filter) - $this->id_current_category = $id_category; - if ($this->id_current_category) - $this->_category = new Category((int)$this->id_current_category); - else - $this->_category = new Category(); - } + if (Tools::getValue('reset_filter_category')) { + $this->context->cookie->id_category_products_filter = false; + } + if (Shop::isFeatureActive() && $this->context->cookie->id_category_products_filter) { + $category = new Category((int)$this->context->cookie->id_category_products_filter); + if (!$category->inShop()) { + $this->context->cookie->id_category_products_filter = false; + Tools::redirectAdmin($this->context->link->getAdminLink('AdminProducts')); + } + } + /* Join categories table */ + if ($id_category = (int)Tools::getValue('productFilter_cl!name')) { + $this->_category = new Category((int)$id_category); + $_POST['productFilter_cl!name'] = $this->_category->name[$this->context->language->id]; + } else { + if ($id_category = (int)Tools::getValue('id_category')) { + $this->id_current_category = $id_category; + $this->context->cookie->id_category_products_filter = $id_category; + } elseif ($id_category = $this->context->cookie->id_category_products_filter) { + $this->id_current_category = $id_category; + } + if ($this->id_current_category) { + $this->_category = new Category((int)$this->id_current_category); + } else { + $this->_category = new Category(); + } + } - $join_category = false; - if (Validate::isLoadedObject($this->_category) && empty($this->_filter)) - $join_category = true; + $join_category = false; + if (Validate::isLoadedObject($this->_category) && empty($this->_filter)) { + $join_category = true; + } - $this->_join .= ' + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'stock_available` sav ON (sav.`id_product` = a.`id_product` AND sav.`id_product_attribute` = 0 '.StockAvailable::addSqlShopRestriction(null, null, 'sav').') '; - $alias = 'sa'; - $alias_image = 'image_shop'; + $alias = 'sa'; + $alias_image = 'image_shop'; - $id_shop = Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP? (int)$this->context->shop->id : 'a.id_shop_default'; - $this->_join .= ' JOIN `'._DB_PREFIX_.'product_shop` sa ON (a.`id_product` = sa.`id_product` AND sa.id_shop = '.$id_shop.') + $id_shop = Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP? (int)$this->context->shop->id : 'a.id_shop_default'; + $this->_join .= ' JOIN `'._DB_PREFIX_.'product_shop` sa ON (a.`id_product` = sa.`id_product` AND sa.id_shop = '.$id_shop.') LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON ('.$alias.'.`id_category_default` = cl.`id_category` AND b.`id_lang` = cl.`id_lang` AND cl.id_shop = '.$id_shop.') LEFT JOIN `'._DB_PREFIX_.'shop` shop ON (shop.id_shop = '.$id_shop.') LEFT JOIN `'._DB_PREFIX_.'image_shop` image_shop ON (image_shop.`id_product` = a.`id_product` AND image_shop.`cover` = 1 AND image_shop.id_shop = '.$id_shop.') LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_image` = image_shop.`id_image`) LEFT JOIN `'._DB_PREFIX_.'product_download` pd ON (pd.`id_product` = a.`id_product`)'; - $this->_select .= 'shop.`name` AS `shopname`, a.`id_shop_default`, '; - $this->_select .= $alias_image.'.`id_image` AS `id_image`, cl.`name` AS `name_category`, '.$alias.'.`price`, 0 AS `price_final`, a.`is_virtual`, pd.`nb_downloadable`, sav.`quantity` AS `sav_quantity`, '.$alias.'.`active`, IF(sav.`quantity`<=0, 1, 0) AS `badge_danger`'; - - if ($join_category) - { - $this->_join .= ' INNER JOIN `'._DB_PREFIX_.'category_product` cp ON (cp.`id_product` = a.`id_product` AND cp.`id_category` = '.(int)$this->_category->id.') '; - $this->_select .= ' , cp.`position`, '; - } - $this->_use_found_rows = false; - $this->_group = ''; - - $this->fields_list = array(); - $this->fields_list['id_product'] = array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs', - 'type' => 'int' - ); - $this->fields_list['image'] = array( - 'title' => $this->l('Image'), - 'align' => 'center', - 'image' => 'p', - 'orderby' => false, - 'filter' => false, - 'search' => false - ); - $this->fields_list['name'] = array( - 'title' => $this->l('Name'), - 'filter_key' => 'b!name' - ); - $this->fields_list['reference'] = array( - 'title' => $this->l('Reference'), - 'align' => 'left', - ); - - if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) - $this->fields_list['shopname'] = array( - 'title' => $this->l('Default shop'), - 'filter_key' => 'shop!name', - ); - else - $this->fields_list['name_category'] = array( - 'title' => $this->l('Category'), - 'filter_key' => 'cl!name', - ); - $this->fields_list['price'] = array( - 'title' => $this->l('Base price'), - 'type' => 'price', - 'align' => 'text-right', - 'filter_key' => 'a!price' - ); - $this->fields_list['price_final'] = array( - 'title' => $this->l('Final price'), - 'type' => 'price', - 'align' => 'text-right', - 'havingFilter' => true, - 'orderby' => false, - 'search' => false - ); - - if (Configuration::get('PS_STOCK_MANAGEMENT')) - $this->fields_list['sav_quantity'] = array( - 'title' => $this->l('Quantity'), - 'type' => 'int', - 'align' => 'text-right', - 'filter_key' => 'sav!quantity', - 'orderby' => true, - 'badge_danger' => true, - //'hint' => $this->l('This is the quantity available in the current shop/group.'), - ); - - $this->fields_list['active'] = array( - 'title' => $this->l('Status'), - 'active' => 'status', - 'filter_key' => $alias.'!active', - 'align' => 'text-center', - 'type' => 'bool', - 'class' => 'fixed-width-sm', - 'orderby' => false - ); - - if ($join_category && (int)$this->id_current_category) - $this->fields_list['position'] = array( - 'title' => $this->l('Position'), - 'filter_key' => 'cp!position', - 'align' => 'center', - 'position' => 'position' - ); - } - - public static function getQuantities($echo, $tr) - { - if ((int)$tr['is_virtual'] == 1 && $tr['nb_downloadable'] == 0) - return '∞'; - else - return $echo; - } - - public function setMedia() - { - parent::setMedia(); - - $bo_theme = ((Validate::isLoadedObject($this->context->employee) - && $this->context->employee->bo_theme) ? $this->context->employee->bo_theme : 'default'); - - if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR - .'template')) - $bo_theme = 'default'; - - $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.iframe-transport.js'); - $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload.js'); - $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload-process.js'); - $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload-validate.js'); - $this->addJs(__PS_BASE_URI__.'js/vendor/spin.js'); - $this->addJs(__PS_BASE_URI__.'js/vendor/ladda.js'); - } - - protected function _cleanMetaKeywords($keywords) - { - if (!empty($keywords) && $keywords != '') - { - $out = array(); - $words = explode(',', $keywords); - foreach ($words as $word_item) - { - $word_item = trim($word_item); - if (!empty($word_item) && $word_item != '') - $out[] = $word_item; - } - return ((count($out) > 0) ? implode(',', $out) : ''); - } - else - return ''; - } - - /** - * @param Product|ObjectModel $object - * @param string $table - */ - protected function copyFromPost(&$object, $table) - { - parent::copyFromPost($object, $table); - if (get_class($object) != 'Product') - return; - - /* Additional fields */ - foreach (Language::getIDs(false) as $id_lang) - if (isset($_POST['meta_keywords_'.$id_lang])) - { - $_POST['meta_keywords_'.$id_lang] = $this->_cleanMetaKeywords(Tools::strtolower($_POST['meta_keywords_'.$id_lang])); - // preg_replace('/ *,? +,* /', ',', strtolower($_POST['meta_keywords_'.$id_lang])); - $object->meta_keywords[$id_lang] = $_POST['meta_keywords_'.$id_lang]; - } - $_POST['width'] = empty($_POST['width']) ? '0' : str_replace(',', '.', $_POST['width']); - $_POST['height'] = empty($_POST['height']) ? '0' : str_replace(',', '.', $_POST['height']); - $_POST['depth'] = empty($_POST['depth']) ? '0' : str_replace(',', '.', $_POST['depth']); - $_POST['weight'] = empty($_POST['weight']) ? '0' : str_replace(',', '.', $_POST['weight']); - - if (Tools::getIsset('unit_price') != null) - $object->unit_price = str_replace(',', '.', Tools::getValue('unit_price')); - if (Tools::getIsset('ecotax') != null) - $object->ecotax = str_replace(',', '.', Tools::getValue('ecotax')); - - if ($this->isTabSubmitted('Informations')) - { - if ($this->checkMultishopBox('available_for_order', $this->context)) - $object->available_for_order = (int)Tools::getValue('available_for_order'); - - if ($this->checkMultishopBox('show_price', $this->context)) - $object->show_price = $object->available_for_order ? 1 : (int)Tools::getValue('show_price'); - - if ($this->checkMultishopBox('online_only', $this->context)) - $object->online_only = (int)Tools::getValue('online_only'); - } - if ($this->isTabSubmitted('Prices')) - $object->on_sale = (int)Tools::getValue('on_sale'); - } - - public function checkMultishopBox($field, $context = null) - { - static $checkbox = null; - static $shop_context = null; - - if ($context == null && $shop_context == null) - $context = Context::getContext(); - - if ($shop_context == null) - $shop_context = $context->shop->getContext(); - - if ($checkbox == null) - $checkbox = Tools::getValue('multishop_check', array()); - - if ($shop_context == Shop::CONTEXT_SHOP) - return true; - - if (isset($checkbox[$field]) && $checkbox[$field] == 1) - return true; - - return false; - } - - public function getList($id_lang, $orderBy = null, $orderWay = null, $start = 0, $limit = null, $id_lang_shop = null) - { - $orderByPriceFinal = (empty($orderBy) ? ($this->context->cookie->__get($this->table.'Orderby') ? $this->context->cookie->__get($this->table.'Orderby') : 'id_'.$this->table) : $orderBy); - $orderWayPriceFinal = (empty($orderWay) ? ($this->context->cookie->__get($this->table.'Orderway') ? $this->context->cookie->__get($this->table.'Orderby') : 'ASC') : $orderWay); - if ($orderByPriceFinal == 'price_final') - { - $orderBy = 'id_'.$this->table; - $orderWay = 'ASC'; - } - parent::getList($id_lang, $orderBy, $orderWay, $start, $limit, $this->context->shop->id); - - /* update product quantity with attributes ...*/ - $nb = count($this->_list); - if ($this->_list) - { - $context = $this->context->cloneContext(); - $context->shop = clone($context->shop); - /* update product final price */ - for ($i = 0; $i < $nb; $i++) - { - if (Context::getContext()->shop->getContext() != Shop::CONTEXT_SHOP) - $context->shop = new Shop((int)$this->_list[$i]['id_shop_default']); - - // convert price with the currency from context - $this->_list[$i]['price'] = Tools::convertPrice($this->_list[$i]['price'], $this->context->currency, true, $this->context); - $this->_list[$i]['price_tmp'] = Product::getPriceStatic($this->_list[$i]['id_product'], true, null, - (int)Configuration::get('PS_PRICE_DISPLAY_PRECISION'), null, false, true, 1, true, null, null, null, $nothing, true, true, - $context); - } - } - - if ($orderByPriceFinal == 'price_final') - { - if (strtolower($orderWayPriceFinal) == 'desc') - uasort($this->_list, 'cmpPriceDesc'); - else - uasort($this->_list, 'cmpPriceAsc'); - } - for ($i = 0; $this->_list && $i < $nb; $i++) - { - $this->_list[$i]['price_final'] = $this->_list[$i]['price_tmp']; - unset($this->_list[$i]['price_tmp']); - } - } - - protected function loadObject($opt = false) - { - $result = parent::loadObject($opt); - if ($result && Validate::isLoadedObject($this->object)) - { - if (Shop::getContext() == Shop::CONTEXT_SHOP && Shop::isFeatureActive() && !$this->object->isAssociatedToShop()) - { - $default_product = new Product((int)$this->object->id, false, null, (int)$this->object->id_shop_default); - $def = ObjectModel::getDefinition($this->object); - foreach ($def['fields'] as $field_name => $row) - { - if (is_array($default_product->$field_name)) - foreach ($default_product->$field_name as $key => $value) - $this->object->{$field_name}[$key] = $value; - else - $this->object->$field_name = $default_product->$field_name; - } - } - $this->object->loadStockData(); - } - return $result; - } - - public function ajaxProcessGetCategoryTree() - { - $category = Tools::getValue('category', Category::getRootCategory()->id); - $full_tree = Tools::getValue('fullTree', 0); - $use_check_box = Tools::getValue('useCheckBox', 1); - $selected = Tools::getValue('selected', array()); - $input_name = str_replace(array('[', ']'), '', Tools::getValue('inputName', null)); - - $tree = new HelperTreeCategories('subtree_associated_categories'); - $tree->setTemplate('subtree_associated_categories.tpl') - ->setUseCheckBox($use_check_box) - ->setUseSearch(true) - ->setSelectedCategories($selected) - ->setFullTree($full_tree) - ->setChildrenOnly(true) - ->setNoJS(true) - ->setRootCategory($category); - - if ($input_name) - $tree->setInputName($input_name); - - die($tree->render()); - } - - public function ajaxProcessGetCountriesOptions() - { - if (!$res = Country::getCountriesByIdShop((int)Tools::getValue('id_shop'), (int)$this->context->language->id)) - return; - - $tpl = $this->createTemplate('specific_prices_shop_update.tpl'); - $tpl->assign(array( - 'option_list' => $res, - 'key_id' => 'id_country', - 'key_value' => 'name' - ) - ); - - $this->content = $tpl->fetch(); - } - - public function ajaxProcessGetCurrenciesOptions() - { - if (!$res = Currency::getCurrenciesByIdShop((int)Tools::getValue('id_shop'))) - return; - - $tpl = $this->createTemplate('specific_prices_shop_update.tpl'); - $tpl->assign(array( - 'option_list' => $res, - 'key_id' => 'id_currency', - 'key_value' => 'name' - ) - ); - - $this->content = $tpl->fetch(); - } - - public function ajaxProcessGetGroupsOptions() - { - if (!$res = Group::getGroups((int)$this->context->language->id, (int)Tools::getValue('id_shop'))) - return; - - $tpl = $this->createTemplate('specific_prices_shop_update.tpl'); - $tpl->assign(array( - 'option_list' => $res, - 'key_id' => 'id_group', - 'key_value' => 'name' - ) - ); - - $this->content = $tpl->fetch(); - } - - public function processDeleteVirtualProduct() - { - if (!($id_product_download = ProductDownload::getIdFromIdProduct((int)Tools::getValue('id_product')))) - $this->errors[] = Tools::displayError('Cannot retrieve file'); - else - { - $product_download = new ProductDownload((int)$id_product_download); - - if (!$product_download->deleteFile((int)$id_product_download)) - $this->errors[] = Tools::displayError('Cannot delete file'); - else - $this->redirect_after = self::$currentIndex.'&id_product='.(int)Tools::getValue('id_product').'&updateproduct&key_tab=VirtualProduct&conf=1&token='.$this->token; - } - - $this->display = 'edit'; - $this->tab_display = 'VirtualProduct'; - } - - public function ajaxProcessAddAttachment() - { - if ($this->tabAccess['edit'] === '0') - return die(Tools::jsonEncode(array('error' => $this->l('You do not have the right permission')))); - if (isset($_FILES['attachment_file'])) - { - if ((int)$_FILES['attachment_file']['error'] === 1) - { - $_FILES['attachment_file']['error'] = array(); - - $max_upload = (int)ini_get('upload_max_filesize'); - $max_post = (int)ini_get('post_max_size'); - $upload_mb = min($max_upload, $max_post); - $_FILES['attachment_file']['error'][] = sprintf( - $this->l('File %1$s exceeds the size allowed by the server. The limit is set to %2$d MB.'), - '<b>'.$_FILES['attachment_file']['name'].'</b> ', - '<b>'.$upload_mb.'</b>' - ); - } - - $_FILES['attachment_file']['error'] = array(); - - $is_attachment_name_valid = false; - $attachment_names = Tools::getValue('attachment_name'); - $attachment_descriptions = Tools::getValue('attachment_description'); - - if (!isset($attachment_names) || !$attachment_names) - $attachment_names = array(); - - if (!isset($attachment_descriptions) || !$attachment_descriptions) - $attachment_descriptions = array(); - - foreach ($attachment_names as $lang => $name) - { - $language = Language::getLanguage((int)$lang); - - if (Tools::strlen($name) > 0) - $is_attachment_name_valid = true; - - if (!Validate::isGenericName($name)) - $_FILES['attachment_file']['error'][] = sprintf(Tools::displayError('Invalid name for %s language'), $language['name']); - elseif (Tools::strlen($name) > 32) - $_FILES['attachment_file']['error'][] = sprintf(Tools::displayError('The name for %1s language is too long (%2d chars max).'), $language['name'], 32); - } - - foreach ($attachment_descriptions as $lang => $description) - { - $language = Language::getLanguage((int)$lang); - - if (!Validate::isCleanHtml($description)) - $_FILES['attachment_file']['error'][] = sprintf(Tools::displayError('Invalid description for %s language'), $language['name']); - } - - if (!$is_attachment_name_valid) - $_FILES['attachment_file']['error'][] = Tools::displayError('An attachment name is required.'); - - if (empty($_FILES['attachment_file']['error'])) - { - if (is_uploaded_file($_FILES['attachment_file']['tmp_name'])) - { - if ($_FILES['attachment_file']['size'] > (Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024 * 1024)) - $_FILES['attachment_file']['error'][] = sprintf( - $this->l('The file is too large. Maximum size allowed is: %1$d kB. The file you are trying to upload is %2$d kB.'), - (Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024), - number_format(($_FILES['attachment_file']['size'] / 1024), 2, '.', '') - ); - else - { - do $uniqid = sha1(microtime()); - while (file_exists(_PS_DOWNLOAD_DIR_.$uniqid)); - if (!copy($_FILES['attachment_file']['tmp_name'], _PS_DOWNLOAD_DIR_.$uniqid)) - $_FILES['attachment_file']['error'][] = $this->l('File copy failed'); - @unlink($_FILES['attachment_file']['tmp_name']); - } - } - else - $_FILES['attachment_file']['error'][] = Tools::displayError('The file is missing.'); - - if (empty($_FILES['attachment_file']['error']) && isset($uniqid)) - { - $attachment = new Attachment(); - - foreach ($attachment_names as $lang => $name) - $attachment->name[(int)$lang] = $name; - - foreach ($attachment_descriptions as $lang => $description) - $attachment->description[(int)$lang] = $description; - - $attachment->file = $uniqid; - $attachment->mime = $_FILES['attachment_file']['type']; - $attachment->file_name = $_FILES['attachment_file']['name']; - - if (empty($attachment->mime) || Tools::strlen($attachment->mime) > 128) - $_FILES['attachment_file']['error'][] = Tools::displayError('Invalid file extension'); - if (!Validate::isGenericName($attachment->file_name)) - $_FILES['attachment_file']['error'][] = Tools::displayError('Invalid file name'); - if (Tools::strlen($attachment->file_name) > 128) - $_FILES['attachment_file']['error'][] = Tools::displayError('The file name is too long.'); - if (empty($this->errors)) - { - $res = $attachment->add(); - if (!$res) - $_FILES['attachment_file']['error'][] = Tools::displayError('This attachment was unable to be loaded into the database.'); - else - { - $_FILES['attachment_file']['id_attachment'] = $attachment->id; - $_FILES['attachment_file']['filename'] = $attachment->name[$this->context->employee->id_lang]; - $id_product = (int)Tools::getValue($this->identifier); - $res = $attachment->attachProduct($id_product); - if (!$res) - $_FILES['attachment_file']['error'][] = Tools::displayError('We were unable to associate this attachment to a product.'); - } - } - else - $_FILES['attachment_file']['error'][] = Tools::displayError('Invalid file'); - } - } - - die(Tools::jsonEncode($_FILES)); - } - } - - - /** - * Attach an existing attachment to the product - * - * @return void - */ - public function processAttachments() - { - if ($id = (int)Tools::getValue($this->identifier)) - { - $attachments = trim(Tools::getValue('arrayAttachments'), ','); - $attachments = explode(',', $attachments); - if (!Attachment::attachToProduct($id, $attachments)) - $this->errors[] = Tools::displayError('An error occurred while saving product attachments.'); - } - } - - public function processDuplicate() - { - if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product')))) - { - $id_product_old = $product->id; - if (empty($product->price) && Shop::getContext() == Shop::CONTEXT_GROUP) - { - $shops = ShopGroup::getShopsFromGroup(Shop::getContextShopGroupID()); - foreach ($shops as $shop) - if ($product->isAssociatedToShop($shop['id_shop'])) - { - $product_price = new Product($id_product_old, false, null, $shop['id_shop']); - $product->price = $product_price->price; - } - } - unset($product->id); - unset($product->id_product); - $product->indexed = 0; - $product->active = 0; - if ($product->add() - && Category::duplicateProductCategories($id_product_old, $product->id) - && Product::duplicateSuppliers($id_product_old, $product->id) - && ($combination_images = Product::duplicateAttributes($id_product_old, $product->id)) !== false - && GroupReduction::duplicateReduction($id_product_old, $product->id) - && Product::duplicateAccessories($id_product_old, $product->id) - && Product::duplicateFeatures($id_product_old, $product->id) - && Product::duplicateSpecificPrices($id_product_old, $product->id) - && Pack::duplicate($id_product_old, $product->id) - && Product::duplicateCustomizationFields($id_product_old, $product->id) - && Product::duplicateTags($id_product_old, $product->id) - && Product::duplicateDownload($id_product_old, $product->id)) - { - if ($product->hasAttributes()) - Product::updateDefaultAttribute($product->id); - - if (!Tools::getValue('noimage') && !Image::duplicateProductImages($id_product_old, $product->id, $combination_images)) - $this->errors[] = Tools::displayError('An error occurred while copying images.'); - else - { - Hook::exec('actionProductAdd', array('id_product' => (int)$product->id, 'product' => $product)); - if (in_array($product->visibility, array('both', 'search')) && Configuration::get('PS_SEARCH_INDEXATION')) - Search::indexation(false, $product->id); - $this->redirect_after = self::$currentIndex.(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '').'&conf=19&token='.$this->token; - } - } - else - $this->errors[] = Tools::displayError('An error occurred while creating an object.'); - } - } - - public function processDelete() - { - if (Validate::isLoadedObject($object = $this->loadObject()) && isset($this->fieldImageSettings)) - { - /** @var Product $object */ - // check if request at least one object with noZeroObject - if (isset($object->noZeroObject) && count($taxes = call_user_func(array($this->className, $object->noZeroObject))) <= 1) - $this->errors[] = Tools::displayError('You need at least one object.').' <b>'.$this->table.'</b><br />'.Tools::displayError('You cannot delete all of the items.'); - else - { - /* - * @since 1.5.0 - * It is NOT possible to delete a product if there are currently: - * - physical stock for this product - * - supply order(s) for this product - */ - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $object->advanced_stock_management) - { - $stock_manager = StockManagerFactory::getManager(); - $physical_quantity = $stock_manager->getProductPhysicalQuantities($object->id, 0); - $real_quantity = $stock_manager->getProductRealQuantities($object->id, 0); - if ($physical_quantity > 0 || $real_quantity > $physical_quantity) - $this->errors[] = Tools::displayError('You cannot delete this product because there is physical stock left.'); - } - - if (!count($this->errors)) - { - if ($object->delete()) - { - $id_category = (int)Tools::getValue('id_category'); - $category_url = empty($id_category) ? '' : '&id_category='.(int)$id_category; - PrestaShopLogger::addLog(sprintf($this->l('%s deletion', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$object->id, true, (int)$this->context->employee->id); - $this->redirect_after = self::$currentIndex.'&conf=1&token='.$this->token.$category_url; - } - else - $this->errors[] = Tools::displayError('An error occurred during deletion.'); - } - } - } - else - $this->errors[] = Tools::displayError('An error occurred while deleting the object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - } - - public function processImage() - { - $id_image = (int)Tools::getValue('id_image'); - $image = new Image((int)$id_image); - if (Validate::isLoadedObject($image)) - { - /* Update product image/legend */ - // @todo : move in processEditProductImage - if (Tools::getIsset('editImage')) - { - if ($image->cover) - $_POST['cover'] = 1; - - $_POST['id_image'] = $image->id; - } - - /* Choose product cover image */ - elseif (Tools::getIsset('coverImage')) - { - Image::deleteCover($image->id_product); - $image->cover = 1; - if (!$image->update()) - $this->errors[] = Tools::displayError('You cannot change the product\'s cover image.'); - else - { - $productId = (int)Tools::getValue('id_product'); - @unlink(_PS_TMP_IMG_DIR_.'product_'.$productId.'.jpg'); - @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.$productId.'_'.$this->context->shop->id.'.jpg'); - $this->redirect_after = self::$currentIndex.'&id_product='.$image->id_product.'&id_category='.(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '').'&action=Images&addproduct'.'&token='.$this->token; - } - } - - /* Choose product image position */ - elseif (Tools::getIsset('imgPosition') && Tools::getIsset('imgDirection')) - { - $image->updatePosition(Tools::getValue('imgDirection'), Tools::getValue('imgPosition')); - $this->redirect_after = self::$currentIndex.'&id_product='.$image->id_product.'&id_category='.(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '').'&add'.$this->table.'&action=Images&token='.$this->token; - } - } - else - $this->errors[] = Tools::displayError('The image could not be found. '); - } - - protected function processBulkDelete() - { - if ($this->tabAccess['delete'] === '1') - { - if (is_array($this->boxes) && !empty($this->boxes)) - { - $object = new $this->className(); - - if (isset($object->noZeroObject) && - // Check if all object will be deleted - (count(call_user_func(array($this->className, $object->noZeroObject))) <= 1 || count($_POST[$this->table.'Box']) == count(call_user_func(array($this->className, $object->noZeroObject))))) - $this->errors[] = Tools::displayError('You need at least one object.').' <b>'.$this->table.'</b><br />'.Tools::displayError('You cannot delete all of the items.'); - else - { - $success = 1; - $products = Tools::getValue($this->table.'Box'); - if (is_array($products) && ($count = count($products))) - { - // Deleting products can be quite long on a cheap server. Let's say 1.5 seconds by product (I've seen it!). - if (intval(ini_get('max_execution_time')) < round($count * 1.5)) - ini_set('max_execution_time', round($count * 1.5)); - - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - $stock_manager = StockManagerFactory::getManager(); - - foreach ($products as $id_product) - { - $product = new Product((int)$id_product); - /* - * @since 1.5.0 - * It is NOT possible to delete a product if there are currently: - * - physical stock for this product - * - supply order(s) for this product - */ - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management) - { - $physical_quantity = $stock_manager->getProductPhysicalQuantities($product->id, 0); - $real_quantity = $stock_manager->getProductRealQuantities($product->id, 0); - if ($physical_quantity > 0 || $real_quantity > $physical_quantity) - $this->errors[] = sprintf(Tools::displayError('You cannot delete the product #%d because there is physical stock left.'), $product->id); - } - if (!count($this->errors)) - { - if ($product->delete()) - PrestaShopLogger::addLog(sprintf($this->l('%s deletion', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$product->id, true, (int)$this->context->employee->id); - else - $success = false; - } - else - $success = 0; - } - } - - if ($success) - { - $id_category = (int)Tools::getValue('id_category'); - $category_url = empty($id_category) ? '' : '&id_category='.(int)$id_category; - $this->redirect_after = self::$currentIndex.'&conf=2&token='.$this->token.$category_url; - } - else - $this->errors[] = Tools::displayError('An error occurred while deleting this selection.'); - } - } - else - $this->errors[] = Tools::displayError('You must select at least one element to delete.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - - public function processProductAttribute() - { - // Don't process if the combination fields have not been submitted - if (!Combination::isFeatureActive() || !Tools::getValue('attribute_combination_list')) - return; - - if (Validate::isLoadedObject($product = $this->object)) - { - if ($this->isProductFieldUpdated('attribute_price') && (!Tools::getIsset('attribute_price') || Tools::getIsset('attribute_price') == null)) - $this->errors[] = Tools::displayError('The price attribute is required.'); - if (!Tools::getIsset('attribute_combination_list') || Tools::isEmpty(Tools::getValue('attribute_combination_list'))) - $this->errors[] = Tools::displayError('You must add at least one attribute.'); - - $array_checks = array( - 'reference' => 'isReference', - 'supplier_reference' => 'isReference', - 'location' => 'isReference', - 'ean13' => 'isEan13', - 'upc' => 'isUpc', - 'wholesale_price' => 'isPrice', - 'price' => 'isPrice', - 'ecotax' => 'isPrice', - 'quantity' => 'isInt', - 'weight' => 'isUnsignedFloat', - 'unit_price_impact' => 'isPrice', - 'default_on' => 'isBool', - 'minimal_quantity' => 'isUnsignedInt', - 'available_date' => 'isDateFormat' - ); - foreach ($array_checks as $property => $check) - if (Tools::getValue('attribute_'.$property) !== false && !call_user_func(array('Validate', $check), Tools::getValue('attribute_'.$property))) - $this->errors[] = sprintf(Tools::displayError('Field %s is not valid'), $property); - - if (!count($this->errors)) - { - if (!isset($_POST['attribute_wholesale_price'])) $_POST['attribute_wholesale_price'] = 0; - if (!isset($_POST['attribute_price_impact'])) $_POST['attribute_price_impact'] = 0; - if (!isset($_POST['attribute_weight_impact'])) $_POST['attribute_weight_impact'] = 0; - if (!isset($_POST['attribute_ecotax'])) $_POST['attribute_ecotax'] = 0; - if (Tools::getValue('attribute_default')) - $product->deleteDefaultAttributes(); - - // Change existing one - if (($id_product_attribute = (int)Tools::getValue('id_product_attribute')) || ($id_product_attribute = $product->productAttributeExists(Tools::getValue('attribute_combination_list'), false, null, true, true))) - { - if ($this->tabAccess['edit'] === '1') - { - if ($this->isProductFieldUpdated('available_date_attribute') && (Tools::getValue('available_date_attribute') != '' &&!Validate::isDateFormat(Tools::getValue('available_date_attribute')))) - $this->errors[] = Tools::displayError('Invalid date format.'); - else - { - $product->updateAttribute((int)$id_product_attribute, - $this->isProductFieldUpdated('attribute_wholesale_price') ? Tools::getValue('attribute_wholesale_price') : null, - $this->isProductFieldUpdated('attribute_price_impact') ? Tools::getValue('attribute_price') * Tools::getValue('attribute_price_impact') : null, - $this->isProductFieldUpdated('attribute_weight_impact') ? Tools::getValue('attribute_weight') * Tools::getValue('attribute_weight_impact') : null, - $this->isProductFieldUpdated('attribute_unit_impact') ? Tools::getValue('attribute_unity') * Tools::getValue('attribute_unit_impact') : null, - $this->isProductFieldUpdated('attribute_ecotax') ? Tools::getValue('attribute_ecotax') : null, - Tools::getValue('id_image_attr'), - Tools::getValue('attribute_reference'), - Tools::getValue('attribute_ean13'), - $this->isProductFieldUpdated('attribute_default') ? Tools::getValue('attribute_default') : null, - Tools::getValue('attribute_location'), - Tools::getValue('attribute_upc'), - $this->isProductFieldUpdated('attribute_minimal_quantity') ? Tools::getValue('attribute_minimal_quantity') : null, - $this->isProductFieldUpdated('available_date_attribute') ? Tools::getValue('available_date_attribute') : null, false); - StockAvailable::setProductDependsOnStock((int)$product->id, $product->depends_on_stock, null, (int)$id_product_attribute); - StockAvailable::setProductOutOfStock((int)$product->id, $product->out_of_stock, null, (int)$id_product_attribute); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - // Add new - else - { - if ($this->tabAccess['add'] === '1') - { - if ($product->productAttributeExists(Tools::getValue('attribute_combination_list'))) - $this->errors[] = Tools::displayError('This combination already exists.'); - else - { - $id_product_attribute = $product->addCombinationEntity( - Tools::getValue('attribute_wholesale_price'), - Tools::getValue('attribute_price') * Tools::getValue('attribute_price_impact'), - Tools::getValue('attribute_weight') * Tools::getValue('attribute_weight_impact'), - Tools::getValue('attribute_unity') * Tools::getValue('attribute_unit_impact'), - Tools::getValue('attribute_ecotax'), - 0, - Tools::getValue('id_image_attr'), - Tools::getValue('attribute_reference'), - null, - Tools::getValue('attribute_ean13'), - Tools::getValue('attribute_default'), - Tools::getValue('attribute_location'), - Tools::getValue('attribute_upc'), - Tools::getValue('attribute_minimal_quantity'), - Array(), - Tools::getValue('available_date_attribute') - ); - StockAvailable::setProductDependsOnStock((int)$product->id, $product->depends_on_stock, null, (int)$id_product_attribute); - StockAvailable::setProductOutOfStock((int)$product->id, $product->out_of_stock, null, (int)$id_product_attribute); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to').'<hr>'.Tools::displayError('edit here.'); - } - if (!count($this->errors)) - { - $combination = new Combination((int)$id_product_attribute); - $combination->setAttributes(Tools::getValue('attribute_combination_list')); - - // images could be deleted before - $id_images = Tools::getValue('id_image_attr'); - if (!empty($id_images)) - $combination->setImages($id_images); - - $product->checkDefaultAttributes(); - if (Tools::getValue('attribute_default')) - { - Product::updateDefaultAttribute((int)$product->id); - if (isset($id_product_attribute)) - $product->cache_default_attribute = (int)$id_product_attribute; - - if ($available_date = Tools::getValue('available_date_attribute')) - $product->setAvailableDate($available_date); - else - $product->setAvailableDate(); - } - } - } - } - } - - public function processFeatures() - { - if (!Feature::isFeatureActive()) - return; - - if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product')))) - { - // delete all objects - $product->deleteFeatures(); - - // add new objects - $languages = Language::getLanguages(false); - foreach ($_POST as $key => $val) - { - if (preg_match('/^feature_([0-9]+)_value/i', $key, $match)) - { - if ($val) - $product->addFeaturesToDB($match[1], $val); - else - { - if ($default_value = $this->checkFeatures($languages, $match[1])) - { - $id_value = $product->addFeaturesToDB($match[1], 0, 1); - foreach ($languages as $language) - { - if ($cust = Tools::getValue('custom_'.$match[1].'_'.(int)$language['id_lang'])) - $product->addFeaturesCustomToDB($id_value, (int)$language['id_lang'], $cust); - else - $product->addFeaturesCustomToDB($id_value, (int)$language['id_lang'], $default_value); - } - } - } - } - } - } - else - $this->errors[] = Tools::displayError('A product must be created before adding features.'); - } - - /** - * This function is never called at the moment (specific prices cannot be edited) - */ - public function processPricesModification() - { - $id_specific_prices = Tools::getValue('spm_id_specific_price'); - $id_combinations = Tools::getValue('spm_id_product_attribute'); - $id_shops = Tools::getValue('spm_id_shop'); - $id_currencies = Tools::getValue('spm_id_currency'); - $id_countries = Tools::getValue('spm_id_country'); - $id_groups = Tools::getValue('spm_id_group'); - $id_customers = Tools::getValue('spm_id_customer'); - $prices = Tools::getValue('spm_price'); - $from_quantities = Tools::getValue('spm_from_quantity'); - $reductions = Tools::getValue('spm_reduction'); - $reduction_types = Tools::getValue('spm_reduction_type'); - $froms = Tools::getValue('spm_from'); - $tos = Tools::getValue('spm_to'); - - foreach ($id_specific_prices as $key => $id_specific_price) - if ($reduction_types[$key] == 'percentage' && ((float)$reductions[$key] <= 0 || (float)$reductions[$key] > 100)) - $this->errors[] = Tools::displayError('Submitted reduction value (0-100) is out-of-range'); - elseif ($this->_validateSpecificPrice($id_shops[$key], $id_currencies[$key], $id_countries[$key], $id_groups[$key], $id_customers[$key], $prices[$key], $from_quantities[$key], $reductions[$key], $reduction_types[$key], $froms[$key], $tos[$key], $id_combinations[$key])) - { - $specific_price = new SpecificPrice((int)($id_specific_price)); - $specific_price->id_shop = (int)$id_shops[$key]; - $specific_price->id_product_attribute = (int)$id_combinations[$key]; - $specific_price->id_currency = (int)($id_currencies[$key]); - $specific_price->id_country = (int)($id_countries[$key]); - $specific_price->id_group = (int)($id_groups[$key]); - $specific_price->id_customer = (int)$id_customers[$key]; - $specific_price->price = (float)($prices[$key]); - $specific_price->from_quantity = (int)($from_quantities[$key]); - $specific_price->reduction = (float)($reduction_types[$key] == 'percentage' ? ($reductions[$key] / 100) : $reductions[$key]); - $specific_price->reduction_type = !$reductions[$key] ? 'amount' : $reduction_types[$key]; - $specific_price->from = !$froms[$key] ? '0000-00-00 00:00:00' : $froms[$key]; - $specific_price->to = !$tos[$key] ? '0000-00-00 00:00:00' : $tos[$key]; - if (!$specific_price->update()) - $this->errors[] = Tools::displayError('An error occurred while updating the specific price.'); - } - if (!count($this->errors)) - $this->redirect_after = self::$currentIndex.'&id_product='.(int)(Tools::getValue('id_product')).(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '').'&update'.$this->table.'&action=Prices&token='.$this->token; - - } - - public function processPriceAddition() - { - // Check if a specific price has been submitted - if (!Tools::getIsset('submitPriceAddition')) - return; - - $id_product = Tools::getValue('id_product'); - $id_product_attribute = Tools::getValue('sp_id_product_attribute'); - $id_shop = Tools::getValue('sp_id_shop'); - $id_currency = Tools::getValue('sp_id_currency'); - $id_country = Tools::getValue('sp_id_country'); - $id_group = Tools::getValue('sp_id_group'); - $id_customer = Tools::getValue('sp_id_customer'); - $price = Tools::getValue('leave_bprice') ? '-1' : Tools::getValue('sp_price'); - $from_quantity = Tools::getValue('sp_from_quantity'); - $reduction = (float)(Tools::getValue('sp_reduction')); - $reduction_tax = Tools::getValue('sp_reduction_tax'); - $reduction_type = !$reduction ? 'amount' : Tools::getValue('sp_reduction_type'); - $reduction_type = $reduction_type == '-' ? 'amount' : $reduction_type; - $from = Tools::getValue('sp_from'); - if (!$from) - $from = '0000-00-00 00:00:00'; - $to = Tools::getValue('sp_to'); - if (!$to) - $to = '0000-00-00 00:00:00'; - - if (($price == '-1') && ((float)$reduction == '0')) - $this->errors[] = Tools::displayError('No reduction value has been submitted'); - elseif (strtotime($to) < strtotime($from)) - $this->errors[] = Tools::displayError('Invalid date range'); - elseif ($reduction_type == 'percentage' && ((float)$reduction <= 0 || (float)$reduction > 100)) - $this->errors[] = Tools::displayError('Submitted reduction value (0-100) is out-of-range'); - elseif ($this->_validateSpecificPrice($id_shop, $id_currency, $id_country, $id_group, $id_customer, $price, $from_quantity, $reduction, $reduction_type, $from, $to, $id_product_attribute)) - { - $specificPrice = new SpecificPrice(); - $specificPrice->id_product = (int)$id_product; - $specificPrice->id_product_attribute = (int)$id_product_attribute; - $specificPrice->id_shop = (int)$id_shop; - $specificPrice->id_currency = (int)($id_currency); - $specificPrice->id_country = (int)($id_country); - $specificPrice->id_group = (int)($id_group); - $specificPrice->id_customer = (int)$id_customer; - $specificPrice->price = (float)($price); - $specificPrice->from_quantity = (int)($from_quantity); - $specificPrice->reduction = (float)($reduction_type == 'percentage' ? $reduction / 100 : $reduction); - $specificPrice->reduction_tax = $reduction_tax; - $specificPrice->reduction_type = $reduction_type; - $specificPrice->from = $from; - $specificPrice->to = $to; - if (!$specificPrice->add()) - $this->errors[] = Tools::displayError('An error occurred while updating the specific price.'); - } - } - - public function ajaxProcessDeleteSpecificPrice() - { - if ($this->tabAccess['delete'] === '1') - { - $id_specific_price = (int)Tools::getValue('id_specific_price'); - if (!$id_specific_price || !Validate::isUnsignedId($id_specific_price)) - $error = Tools::displayError('The specific price ID is invalid.'); - else - { - $specificPrice = new SpecificPrice((int)$id_specific_price); - if (!$specificPrice->delete()) - $error = Tools::displayError('An error occurred while attempting to delete the specific price.'); - } - } - else - $error = Tools::displayError('You do not have permission to delete this.'); - - if (isset($error)) - $json = array( - 'status' => 'error', - 'message'=> $error - ); - else - $json = array( - 'status' => 'ok', - 'message'=> $this->_conf[1] - ); - - die(Tools::jsonEncode($json)); - } - - public function processSpecificPricePriorities() - { - if (!($obj = $this->loadObject())) - return; - if (!$priorities = Tools::getValue('specificPricePriority')) - $this->errors[] = Tools::displayError('Please specify priorities.'); - elseif (Tools::isSubmit('specificPricePriorityToAll')) - { - if (!SpecificPrice::setPriorities($priorities)) - $this->errors[] = Tools::displayError('An error occurred while updating priorities.'); - else - $this->confirmations[] = $this->l('The price rule has successfully updated'); - } - elseif (!SpecificPrice::setSpecificPriority((int)$obj->id, $priorities)) - $this->errors[] = Tools::displayError('An error occurred while setting priorities.'); - } - - public function processCustomizationConfiguration() - { - $product = $this->object; - // Get the number of existing customization fields ($product->text_fields is the updated value, not the existing value) - $current_customization = $product->getCustomizationFieldIds(); - $files_count = 0; - $text_count = 0; - if (is_array($current_customization)) - { - foreach ($current_customization as $field) - { - if ($field['type'] == 1) - $text_count++; - else - $files_count++; - } - } - - if (!$product->createLabels((int)$product->uploadable_files - $files_count, (int)$product->text_fields - $text_count)) - $this->errors[] = Tools::displayError('An error occurred while creating customization fields.'); - if (!count($this->errors) && !$product->updateLabels()) - $this->errors[] = Tools::displayError('An error occurred while updating customization fields.'); - $product->customizable = ($product->uploadable_files > 0 || $product->text_fields > 0) ? 1 : 0; - if (($product->uploadable_files != $files_count || $product->text_fields != $text_count) && !count($this->errors) && !$product->update()) - $this->errors[] = Tools::displayError('An error occurred while updating the custom configuration.'); - } - - public function processProductCustomization() - { - if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product')))) - { - foreach ($_POST as $field => $value) - if (strncmp($field, 'label_', 6) == 0 && !Validate::isLabel($value)) - $this->errors[] = Tools::displayError('The label fields defined are invalid.'); - if (empty($this->errors) && !$product->updateLabels()) - $this->errors[] = Tools::displayError('An error occurred while updating customization fields.'); - if (empty($this->errors)) - $this->confirmations[] = $this->l('Update successful'); - } - else - $this->errors[] = Tools::displayError('A product must be created before adding customization.'); - } - - /** - * Overrides parent for custom redirect link - */ - public function processPosition() - { - /** @var Product $object */ - if (!Validate::isLoadedObject($object = $this->loadObject())) - { - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.'). - ' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - } - elseif (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) - $this->errors[] = Tools::displayError('Failed to update the position.'); - else - { - $category = new Category((int)Tools::getValue('id_category')); - if (Validate::isLoadedObject($category)) - Hook::exec('actionCategoryUpdate', array('category' => $category)); - $this->redirect_after = self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&action=Customization&conf=5'.(($id_category = (Tools::getIsset('id_category') ? (int)Tools::getValue('id_category') : '')) ? ('&id_category='.$id_category) : '').'&token='.Tools::getAdminTokenLite('AdminProducts'); - } - } - - public function initProcess() - { - if (Tools::isSubmit('submitAddproductAndStay') || Tools::isSubmit('submitAddproduct')) - { - $this->id_object = (int)Tools::getValue('id_product'); - $this->object = new Product($this->id_object); - - if ($this->isTabSubmitted('Informations') && $this->object->is_virtual && (int)Tools::getValue('type_product') != 2) - { - if ($id_product_download = (int)ProductDownload::getIdFromIdProduct($this->id_object)) - { - $product_download = new ProductDownload($id_product_download); - if (!$product_download->deleteFile($id_product_download)) - $this->errors[] = Tools::displayError('Cannot delete file'); - } - - } - } - - // Delete a product in the download folder - if (Tools::getValue('deleteVirtualProduct')) - { - if ($this->tabAccess['delete'] === '1') - $this->action = 'deleteVirtualProduct'; - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - // Product preview - elseif (Tools::isSubmit('submitAddProductAndPreview')) - { - $this->display = 'edit'; - $this->action = 'save'; - if (Tools::getValue('id_product')) - { - $this->id_object = Tools::getValue('id_product'); - $this->object = new Product((int)Tools::getValue('id_product')); - } - } - elseif (Tools::isSubmit('submitAttachments')) - { - if ($this->tabAccess['edit'] === '1') - { - $this->action = 'attachments'; - $this->tab_display = 'attachments'; - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - // Product duplication - elseif (Tools::getIsset('duplicate'.$this->table)) - { - if ($this->tabAccess['add'] === '1') - $this->action = 'duplicate'; - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - // Product images management - elseif (Tools::getValue('id_image') && Tools::getValue('ajax')) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'image'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - // Product attributes management - elseif (Tools::isSubmit('submitProductAttribute')) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'productAttribute'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - // Product features management - elseif (Tools::isSubmit('submitFeatures') || Tools::isSubmit('submitFeaturesAndStay')) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'features'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - // Product specific prices management NEVER USED - elseif (Tools::isSubmit('submitPricesModification')) - { - if ($this->tabAccess['add'] === '1') - $this->action = 'pricesModification'; - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - elseif (Tools::isSubmit('deleteSpecificPrice')) - { - if ($this->tabAccess['delete'] === '1') - $this->action = 'deleteSpecificPrice'; - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - elseif (Tools::isSubmit('submitSpecificPricePriorities')) - { - if ($this->tabAccess['edit'] === '1') - { - $this->action = 'specificPricePriorities'; - $this->tab_display = 'prices'; - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - // Customization management - elseif (Tools::isSubmit('submitCustomizationConfiguration')) - { - if ($this->tabAccess['edit'] === '1') - { - $this->action = 'customizationConfiguration'; - $this->tab_display = 'customization'; - $this->display = 'edit'; - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('submitProductCustomization')) - { - if ($this->tabAccess['edit'] === '1') - { - $this->action = 'productCustomization'; - $this->tab_display = 'customization'; - $this->display = 'edit'; - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('id_product')) - { - $post_max_size = Tools::getMaxUploadSize(Configuration::get('PS_LIMIT_UPLOAD_FILE_VALUE') * 1024 * 1024); - if ($post_max_size && isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] && $_SERVER['CONTENT_LENGTH'] > $post_max_size) - $this->errors[] = sprintf(Tools::displayError('The uploaded file exceeds the "Maximum size for a downloadable product" set in preferences (%1$dMB) or the post_max_size/ directive in php.ini (%2$dMB).'), number_format((Configuration::get('PS_LIMIT_UPLOAD_FILE_VALUE'))), ($post_max_size / 1024 / 1024)); - } - - if (!$this->action) - parent::initProcess(); - else - $this->id_object = (int)Tools::getValue($this->identifier); - - if (isset($this->available_tabs[Tools::getValue('key_tab')])) - $this->tab_display = Tools::getValue('key_tab'); - - // Set tab to display if not decided already - if (!$this->tab_display && $this->action) - if (in_array($this->action, array_keys($this->available_tabs))) - $this->tab_display = $this->action; - - // And if still not set, use default - if (!$this->tab_display) - { - if (in_array($this->default_tab, $this->available_tabs)) - $this->tab_display = $this->default_tab; - else - $this->tab_display = key($this->available_tabs); - } - } - - /** - * postProcess handle every checks before saving products information - * - * @return void - */ - public function postProcess() - { - if (!$this->redirect_after) - parent::postProcess(); - - if ($this->display == 'edit' || $this->display == 'add') - { - $this->addJqueryUI(array( - 'ui.core', - 'ui.widget' - )); - - $this->addjQueryPlugin(array( - 'autocomplete', - 'tablednd', - 'thickbox', - 'ajaxfileupload', - 'date', - 'tagify', - 'select2', - 'validate' - )); - - $this->addJS(array( - _PS_JS_DIR_.'admin/products.js', - _PS_JS_DIR_.'admin/attributes.js', - _PS_JS_DIR_.'admin/price.js', - _PS_JS_DIR_.'tiny_mce/tiny_mce.js', - _PS_JS_DIR_.'admin/tinymce.inc.js', - _PS_JS_DIR_.'admin/dnd.js', - _PS_JS_DIR_.'jquery/ui/jquery.ui.progressbar.min.js', - _PS_JS_DIR_.'vendor/spin.js', - _PS_JS_DIR_.'vendor/ladda.js' - )); - - $this->addJS(_PS_JS_DIR_.'jquery/plugins/select2/select2_locale_'.$this->context->language->iso_code.'.js'); - $this->addJS(_PS_JS_DIR_.'jquery/plugins/validate/localization/messages_'.$this->context->language->iso_code.'.js'); - - $this->addCSS(array( - _PS_JS_DIR_.'jquery/plugins/timepicker/jquery-ui-timepicker-addon.css' - )); - } - } - - public function ajaxProcessDeleteProductAttribute() - { - if (!Combination::isFeatureActive()) - return; - - if ($this->tabAccess['delete'] === '1') - { - $id_product = (int)Tools::getValue('id_product'); - $id_product_attribute = (int)Tools::getValue('id_product_attribute'); - - if ($id_product && Validate::isUnsignedId($id_product) && Validate::isLoadedObject($product = new Product($id_product))) - { - if (($depends_on_stock = StockAvailable::dependsOnStock($id_product)) && StockAvailable::getQuantityAvailableByProduct($id_product, $id_product_attribute)) - $json = array( - 'status' => 'error', - 'message'=> $this->l('It is not possible to delete a combination while it still has some quantities in the Advanced Stock Management. You must delete its stock first.') - ); - else - { - $product->deleteAttributeCombination((int)$id_product_attribute); - $product->checkDefaultAttributes(); - Tools::clearColorListCache((int)$product->id); - if (!$product->hasAttributes()) - { - $product->cache_default_attribute = 0; - $product->update(); - } - else - Product::updateDefaultAttribute($id_product); - - if ($depends_on_stock && !Stock::deleteStockByIds($id_product, $id_product_attribute)) - $json = array( - 'status' => 'error', - 'message'=> $this->l('Error while deleting the stock') - ); - else - $json = array( - 'status' => 'ok', - 'message'=> $this->_conf[1], - 'id_product_attribute' => (int)$id_product_attribute - ); - } - } - else - $json = array( - 'status' => 'error', - 'message'=> $this->l('You cannot delete this attribute.') - ); - } - else - $json = array( - 'status' => 'error', - 'message'=> $this->l('You do not have permission to delete this.') - ); - - die(Tools::jsonEncode($json)); - } - - public function ajaxProcessDefaultProductAttribute() - { - if ($this->tabAccess['edit'] === '1') - { - if (!Combination::isFeatureActive()) - return; - - if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product')))) - { - $product->deleteDefaultAttributes(); - $product->setDefaultAttribute((int)Tools::getValue('id_product_attribute')); - $json = array( - 'status' => 'ok', - 'message'=> $this->_conf[4] - ); - } - else - $json = array( - 'status' => 'error', - 'message'=> $this->l('You cannot make this the default attribute.') - ); - - die(Tools::jsonEncode($json)); - } - } - - public function ajaxProcessEditProductAttribute() - { - if ($this->tabAccess['edit'] === '1') - { - $id_product = (int)Tools::getValue('id_product'); - $id_product_attribute = (int)Tools::getValue('id_product_attribute'); - if ($id_product && Validate::isUnsignedId($id_product) && Validate::isLoadedObject($product = new Product((int)$id_product))) - { - $combinations = $product->getAttributeCombinationsById($id_product_attribute, $this->context->language->id); - foreach ($combinations as $key => $combination) - $combinations[$key]['attributes'][] = array($combination['group_name'], $combination['attribute_name'], $combination['id_attribute']); - - die(Tools::jsonEncode($combinations)); - } - } - } - - public function ajaxPreProcess() - { - if (Tools::getIsset('update'.$this->table) && Tools::getIsset('id_'.$this->table)) - { - $this->display = 'edit'; - $this->action = Tools::getValue('action'); - } - } - - public function ajaxProcessUpdateProductImageShopAsso() - { - $id_product = Tools::getValue('id_product'); - if (($id_image = Tools::getValue('id_image')) && ($id_shop = (int)Tools::getValue('id_shop'))) - if (Tools::getValue('active') == 'true') - $res = Db::getInstance()->execute('INSERT INTO '._DB_PREFIX_.'image_shop (`id_image`, `id_shop`, `cover`) VALUES('.(int)$id_image.', '.(int)$id_shop.', \'0\')'); - else - $res = Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'image_shop WHERE `id_image` = '.(int)$id_image.' AND `id_shop` = '.(int)$id_shop); - - // Clean covers in image table - $count_cover_image = Db::getInstance()->getValue(' + $this->_select .= 'shop.`name` AS `shopname`, a.`id_shop_default`, '; + $this->_select .= $alias_image.'.`id_image` AS `id_image`, cl.`name` AS `name_category`, '.$alias.'.`price`, 0 AS `price_final`, a.`is_virtual`, pd.`nb_downloadable`, sav.`quantity` AS `sav_quantity`, '.$alias.'.`active`, IF(sav.`quantity`<=0, 1, 0) AS `badge_danger`'; + + if ($join_category) { + $this->_join .= ' INNER JOIN `'._DB_PREFIX_.'category_product` cp ON (cp.`id_product` = a.`id_product` AND cp.`id_category` = '.(int)$this->_category->id.') '; + $this->_select .= ' , cp.`position`, '; + } + $this->_use_found_rows = false; + $this->_group = ''; + + $this->fields_list = array(); + $this->fields_list['id_product'] = array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs', + 'type' => 'int' + ); + $this->fields_list['image'] = array( + 'title' => $this->l('Image'), + 'align' => 'center', + 'image' => 'p', + 'orderby' => false, + 'filter' => false, + 'search' => false + ); + $this->fields_list['name'] = array( + 'title' => $this->l('Name'), + 'filter_key' => 'b!name' + ); + $this->fields_list['reference'] = array( + 'title' => $this->l('Reference'), + 'align' => 'left', + ); + + if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) { + $this->fields_list['shopname'] = array( + 'title' => $this->l('Default shop'), + 'filter_key' => 'shop!name', + ); + } else { + $this->fields_list['name_category'] = array( + 'title' => $this->l('Category'), + 'filter_key' => 'cl!name', + ); + } + $this->fields_list['price'] = array( + 'title' => $this->l('Base price'), + 'type' => 'price', + 'align' => 'text-right', + 'filter_key' => 'a!price' + ); + $this->fields_list['price_final'] = array( + 'title' => $this->l('Final price'), + 'type' => 'price', + 'align' => 'text-right', + 'havingFilter' => true, + 'orderby' => false, + 'search' => false + ); + + if (Configuration::get('PS_STOCK_MANAGEMENT')) { + $this->fields_list['sav_quantity'] = array( + 'title' => $this->l('Quantity'), + 'type' => 'int', + 'align' => 'text-right', + 'filter_key' => 'sav!quantity', + 'orderby' => true, + 'badge_danger' => true, + //'hint' => $this->l('This is the quantity available in the current shop/group.'), + ); + } + + $this->fields_list['active'] = array( + 'title' => $this->l('Status'), + 'active' => 'status', + 'filter_key' => $alias.'!active', + 'align' => 'text-center', + 'type' => 'bool', + 'class' => 'fixed-width-sm', + 'orderby' => false + ); + + if ($join_category && (int)$this->id_current_category) { + $this->fields_list['position'] = array( + 'title' => $this->l('Position'), + 'filter_key' => 'cp!position', + 'align' => 'center', + 'position' => 'position' + ); + } + } + + public static function getQuantities($echo, $tr) + { + if ((int)$tr['is_virtual'] == 1 && $tr['nb_downloadable'] == 0) { + return '∞'; + } else { + return $echo; + } + } + + public function setMedia() + { + parent::setMedia(); + + $bo_theme = ((Validate::isLoadedObject($this->context->employee) + && $this->context->employee->bo_theme) ? $this->context->employee->bo_theme : 'default'); + + if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$bo_theme.DIRECTORY_SEPARATOR + .'template')) { + $bo_theme = 'default'; + } + + $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.iframe-transport.js'); + $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload.js'); + $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload-process.js'); + $this->addJs(__PS_BASE_URI__.$this->admin_webpath.'/themes/'.$bo_theme.'/js/jquery.fileupload-validate.js'); + $this->addJs(__PS_BASE_URI__.'js/vendor/spin.js'); + $this->addJs(__PS_BASE_URI__.'js/vendor/ladda.js'); + } + + protected function _cleanMetaKeywords($keywords) + { + if (!empty($keywords) && $keywords != '') { + $out = array(); + $words = explode(',', $keywords); + foreach ($words as $word_item) { + $word_item = trim($word_item); + if (!empty($word_item) && $word_item != '') { + $out[] = $word_item; + } + } + return ((count($out) > 0) ? implode(',', $out) : ''); + } else { + return ''; + } + } + + /** + * @param Product|ObjectModel $object + * @param string $table + */ + protected function copyFromPost(&$object, $table) + { + parent::copyFromPost($object, $table); + if (get_class($object) != 'Product') { + return; + } + + /* Additional fields */ + foreach (Language::getIDs(false) as $id_lang) { + if (isset($_POST['meta_keywords_'.$id_lang])) { + $_POST['meta_keywords_'.$id_lang] = $this->_cleanMetaKeywords(Tools::strtolower($_POST['meta_keywords_'.$id_lang])); + // preg_replace('/ *,? +,* /', ',', strtolower($_POST['meta_keywords_'.$id_lang])); + $object->meta_keywords[$id_lang] = $_POST['meta_keywords_'.$id_lang]; + } + } + $_POST['width'] = empty($_POST['width']) ? '0' : str_replace(',', '.', $_POST['width']); + $_POST['height'] = empty($_POST['height']) ? '0' : str_replace(',', '.', $_POST['height']); + $_POST['depth'] = empty($_POST['depth']) ? '0' : str_replace(',', '.', $_POST['depth']); + $_POST['weight'] = empty($_POST['weight']) ? '0' : str_replace(',', '.', $_POST['weight']); + + if (Tools::getIsset('unit_price') != null) { + $object->unit_price = str_replace(',', '.', Tools::getValue('unit_price')); + } + if (Tools::getIsset('ecotax') != null) { + $object->ecotax = str_replace(',', '.', Tools::getValue('ecotax')); + } + + if ($this->isTabSubmitted('Informations')) { + if ($this->checkMultishopBox('available_for_order', $this->context)) { + $object->available_for_order = (int)Tools::getValue('available_for_order'); + } + + if ($this->checkMultishopBox('show_price', $this->context)) { + $object->show_price = $object->available_for_order ? 1 : (int)Tools::getValue('show_price'); + } + + if ($this->checkMultishopBox('online_only', $this->context)) { + $object->online_only = (int)Tools::getValue('online_only'); + } + } + if ($this->isTabSubmitted('Prices')) { + $object->on_sale = (int)Tools::getValue('on_sale'); + } + } + + public function checkMultishopBox($field, $context = null) + { + static $checkbox = null; + static $shop_context = null; + + if ($context == null && $shop_context == null) { + $context = Context::getContext(); + } + + if ($shop_context == null) { + $shop_context = $context->shop->getContext(); + } + + if ($checkbox == null) { + $checkbox = Tools::getValue('multishop_check', array()); + } + + if ($shop_context == Shop::CONTEXT_SHOP) { + return true; + } + + if (isset($checkbox[$field]) && $checkbox[$field] == 1) { + return true; + } + + return false; + } + + public function getList($id_lang, $orderBy = null, $orderWay = null, $start = 0, $limit = null, $id_lang_shop = null) + { + $orderByPriceFinal = (empty($orderBy) ? ($this->context->cookie->__get($this->table.'Orderby') ? $this->context->cookie->__get($this->table.'Orderby') : 'id_'.$this->table) : $orderBy); + $orderWayPriceFinal = (empty($orderWay) ? ($this->context->cookie->__get($this->table.'Orderway') ? $this->context->cookie->__get($this->table.'Orderby') : 'ASC') : $orderWay); + if ($orderByPriceFinal == 'price_final') { + $orderBy = 'id_'.$this->table; + $orderWay = 'ASC'; + } + parent::getList($id_lang, $orderBy, $orderWay, $start, $limit, $this->context->shop->id); + + /* update product quantity with attributes ...*/ + $nb = count($this->_list); + if ($this->_list) { + $context = $this->context->cloneContext(); + $context->shop = clone($context->shop); + /* update product final price */ + for ($i = 0; $i < $nb; $i++) { + if (Context::getContext()->shop->getContext() != Shop::CONTEXT_SHOP) { + $context->shop = new Shop((int)$this->_list[$i]['id_shop_default']); + } + + // convert price with the currency from context + $this->_list[$i]['price'] = Tools::convertPrice($this->_list[$i]['price'], $this->context->currency, true, $this->context); + $this->_list[$i]['price_tmp'] = Product::getPriceStatic($this->_list[$i]['id_product'], true, null, + (int)Configuration::get('PS_PRICE_DISPLAY_PRECISION'), null, false, true, 1, true, null, null, null, $nothing, true, true, + $context); + } + } + + if ($orderByPriceFinal == 'price_final') { + if (strtolower($orderWayPriceFinal) == 'desc') { + uasort($this->_list, 'cmpPriceDesc'); + } else { + uasort($this->_list, 'cmpPriceAsc'); + } + } + for ($i = 0; $this->_list && $i < $nb; $i++) { + $this->_list[$i]['price_final'] = $this->_list[$i]['price_tmp']; + unset($this->_list[$i]['price_tmp']); + } + } + + protected function loadObject($opt = false) + { + $result = parent::loadObject($opt); + if ($result && Validate::isLoadedObject($this->object)) { + if (Shop::getContext() == Shop::CONTEXT_SHOP && Shop::isFeatureActive() && !$this->object->isAssociatedToShop()) { + $default_product = new Product((int)$this->object->id, false, null, (int)$this->object->id_shop_default); + $def = ObjectModel::getDefinition($this->object); + foreach ($def['fields'] as $field_name => $row) { + if (is_array($default_product->$field_name)) { + foreach ($default_product->$field_name as $key => $value) { + $this->object->{$field_name}[$key] = $value; + } + } else { + $this->object->$field_name = $default_product->$field_name; + } + } + } + $this->object->loadStockData(); + } + return $result; + } + + public function ajaxProcessGetCategoryTree() + { + $category = Tools::getValue('category', Category::getRootCategory()->id); + $full_tree = Tools::getValue('fullTree', 0); + $use_check_box = Tools::getValue('useCheckBox', 1); + $selected = Tools::getValue('selected', array()); + $id_tree = Tools::getValue('type'); + $input_name = str_replace(array('[', ']'), '', Tools::getValue('inputName', null)); + + $tree = new HelperTreeCategories('subtree_associated_categories'); + $tree->setTemplate('subtree_associated_categories.tpl') + ->setUseCheckBox($use_check_box) + ->setUseSearch(true) + ->setIdTree($id_tree) + ->setSelectedCategories($selected) + ->setFullTree($full_tree) + ->setChildrenOnly(true) + ->setNoJS(true) + ->setRootCategory($category); + + if ($input_name) { + $tree->setInputName($input_name); + } + + die($tree->render()); + } + + public function ajaxProcessGetCountriesOptions() + { + if (!$res = Country::getCountriesByIdShop((int)Tools::getValue('id_shop'), (int)$this->context->language->id)) { + return; + } + + $tpl = $this->createTemplate('specific_prices_shop_update.tpl'); + $tpl->assign(array( + 'option_list' => $res, + 'key_id' => 'id_country', + 'key_value' => 'name' + ) + ); + + $this->content = $tpl->fetch(); + } + + public function ajaxProcessGetCurrenciesOptions() + { + if (!$res = Currency::getCurrenciesByIdShop((int)Tools::getValue('id_shop'))) { + return; + } + + $tpl = $this->createTemplate('specific_prices_shop_update.tpl'); + $tpl->assign(array( + 'option_list' => $res, + 'key_id' => 'id_currency', + 'key_value' => 'name' + ) + ); + + $this->content = $tpl->fetch(); + } + + public function ajaxProcessGetGroupsOptions() + { + if (!$res = Group::getGroups((int)$this->context->language->id, (int)Tools::getValue('id_shop'))) { + return; + } + + $tpl = $this->createTemplate('specific_prices_shop_update.tpl'); + $tpl->assign(array( + 'option_list' => $res, + 'key_id' => 'id_group', + 'key_value' => 'name' + ) + ); + + $this->content = $tpl->fetch(); + } + + public function processDeleteVirtualProduct() + { + if (!($id_product_download = ProductDownload::getIdFromIdProduct((int)Tools::getValue('id_product')))) { + $this->errors[] = Tools::displayError('Cannot retrieve file'); + } else { + $product_download = new ProductDownload((int)$id_product_download); + + if (!$product_download->deleteFile((int)$id_product_download)) { + $this->errors[] = Tools::displayError('Cannot delete file'); + } else { + $this->redirect_after = self::$currentIndex.'&id_product='.(int)Tools::getValue('id_product').'&updateproduct&key_tab=VirtualProduct&conf=1&token='.$this->token; + } + } + + $this->display = 'edit'; + $this->tab_display = 'VirtualProduct'; + } + + public function ajaxProcessAddAttachment() + { + if ($this->tabAccess['edit'] === '0') { + return die(Tools::jsonEncode(array('error' => $this->l('You do not have the right permission')))); + } + if (isset($_FILES['attachment_file'])) { + if ((int)$_FILES['attachment_file']['error'] === 1) { + $_FILES['attachment_file']['error'] = array(); + + $max_upload = (int)ini_get('upload_max_filesize'); + $max_post = (int)ini_get('post_max_size'); + $upload_mb = min($max_upload, $max_post); + $_FILES['attachment_file']['error'][] = sprintf( + $this->l('File %1$s exceeds the size allowed by the server. The limit is set to %2$d MB.'), + '<b>'.$_FILES['attachment_file']['name'].'</b> ', + '<b>'.$upload_mb.'</b>' + ); + } + + $_FILES['attachment_file']['error'] = array(); + + $is_attachment_name_valid = false; + $attachment_names = Tools::getValue('attachment_name'); + $attachment_descriptions = Tools::getValue('attachment_description'); + + if (!isset($attachment_names) || !$attachment_names) { + $attachment_names = array(); + } + + if (!isset($attachment_descriptions) || !$attachment_descriptions) { + $attachment_descriptions = array(); + } + + foreach ($attachment_names as $lang => $name) { + $language = Language::getLanguage((int)$lang); + + if (Tools::strlen($name) > 0) { + $is_attachment_name_valid = true; + } + + if (!Validate::isGenericName($name)) { + $_FILES['attachment_file']['error'][] = sprintf(Tools::displayError('Invalid name for %s language'), $language['name']); + } elseif (Tools::strlen($name) > 32) { + $_FILES['attachment_file']['error'][] = sprintf(Tools::displayError('The name for %1s language is too long (%2d chars max).'), $language['name'], 32); + } + } + + foreach ($attachment_descriptions as $lang => $description) { + $language = Language::getLanguage((int)$lang); + + if (!Validate::isCleanHtml($description)) { + $_FILES['attachment_file']['error'][] = sprintf(Tools::displayError('Invalid description for %s language'), $language['name']); + } + } + + if (!$is_attachment_name_valid) { + $_FILES['attachment_file']['error'][] = Tools::displayError('An attachment name is required.'); + } + + if (empty($_FILES['attachment_file']['error'])) { + if (is_uploaded_file($_FILES['attachment_file']['tmp_name'])) { + if ($_FILES['attachment_file']['size'] > (Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024 * 1024)) { + $_FILES['attachment_file']['error'][] = sprintf( + $this->l('The file is too large. Maximum size allowed is: %1$d kB. The file you are trying to upload is %2$d kB.'), + (Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024), + number_format(($_FILES['attachment_file']['size'] / 1024), 2, '.', '') + ); + } else { + do { + $uniqid = sha1(microtime()); + } while (file_exists(_PS_DOWNLOAD_DIR_.$uniqid)); + if (!copy($_FILES['attachment_file']['tmp_name'], _PS_DOWNLOAD_DIR_.$uniqid)) { + $_FILES['attachment_file']['error'][] = $this->l('File copy failed'); + } + @unlink($_FILES['attachment_file']['tmp_name']); + } + } else { + $_FILES['attachment_file']['error'][] = Tools::displayError('The file is missing.'); + } + + if (empty($_FILES['attachment_file']['error']) && isset($uniqid)) { + $attachment = new Attachment(); + + foreach ($attachment_names as $lang => $name) { + $attachment->name[(int)$lang] = $name; + } + + foreach ($attachment_descriptions as $lang => $description) { + $attachment->description[(int)$lang] = $description; + } + + $attachment->file = $uniqid; + $attachment->mime = $_FILES['attachment_file']['type']; + $attachment->file_name = $_FILES['attachment_file']['name']; + + if (empty($attachment->mime) || Tools::strlen($attachment->mime) > 128) { + $_FILES['attachment_file']['error'][] = Tools::displayError('Invalid file extension'); + } + if (!Validate::isGenericName($attachment->file_name)) { + $_FILES['attachment_file']['error'][] = Tools::displayError('Invalid file name'); + } + if (Tools::strlen($attachment->file_name) > 128) { + $_FILES['attachment_file']['error'][] = Tools::displayError('The file name is too long.'); + } + if (empty($this->errors)) { + $res = $attachment->add(); + if (!$res) { + $_FILES['attachment_file']['error'][] = Tools::displayError('This attachment was unable to be loaded into the database.'); + } else { + $_FILES['attachment_file']['id_attachment'] = $attachment->id; + $_FILES['attachment_file']['filename'] = $attachment->name[$this->context->employee->id_lang]; + $id_product = (int)Tools::getValue($this->identifier); + $res = $attachment->attachProduct($id_product); + if (!$res) { + $_FILES['attachment_file']['error'][] = Tools::displayError('We were unable to associate this attachment to a product.'); + } + } + } else { + $_FILES['attachment_file']['error'][] = Tools::displayError('Invalid file'); + } + } + } + + die(Tools::jsonEncode($_FILES)); + } + } + + + /** + * Attach an existing attachment to the product + * + * @return void + */ + public function processAttachments() + { + if ($id = (int)Tools::getValue($this->identifier)) { + $attachments = trim(Tools::getValue('arrayAttachments'), ','); + $attachments = explode(',', $attachments); + if (!Attachment::attachToProduct($id, $attachments)) { + $this->errors[] = Tools::displayError('An error occurred while saving product attachments.'); + } + } + } + + public function processDuplicate() + { + if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product')))) { + $id_product_old = $product->id; + if (empty($product->price) && Shop::getContext() == Shop::CONTEXT_GROUP) { + $shops = ShopGroup::getShopsFromGroup(Shop::getContextShopGroupID()); + foreach ($shops as $shop) { + if ($product->isAssociatedToShop($shop['id_shop'])) { + $product_price = new Product($id_product_old, false, null, $shop['id_shop']); + $product->price = $product_price->price; + } + } + } + unset($product->id); + unset($product->id_product); + $product->indexed = 0; + $product->active = 0; + if ($product->add() + && Category::duplicateProductCategories($id_product_old, $product->id) + && Product::duplicateSuppliers($id_product_old, $product->id) + && ($combination_images = Product::duplicateAttributes($id_product_old, $product->id)) !== false + && GroupReduction::duplicateReduction($id_product_old, $product->id) + && Product::duplicateAccessories($id_product_old, $product->id) + && Product::duplicateFeatures($id_product_old, $product->id) + && Product::duplicateSpecificPrices($id_product_old, $product->id) + && Pack::duplicate($id_product_old, $product->id) + && Product::duplicateCustomizationFields($id_product_old, $product->id) + && Product::duplicateTags($id_product_old, $product->id) + && Product::duplicateDownload($id_product_old, $product->id)) { + if ($product->hasAttributes()) { + Product::updateDefaultAttribute($product->id); + } + + if (!Tools::getValue('noimage') && !Image::duplicateProductImages($id_product_old, $product->id, $combination_images)) { + $this->errors[] = Tools::displayError('An error occurred while copying images.'); + } else { + Hook::exec('actionProductAdd', array('id_product' => (int)$product->id, 'product' => $product)); + if (in_array($product->visibility, array('both', 'search')) && Configuration::get('PS_SEARCH_INDEXATION')) { + Search::indexation(false, $product->id); + } + $this->redirect_after = self::$currentIndex.(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '').'&conf=19&token='.$this->token; + } + } else { + $this->errors[] = Tools::displayError('An error occurred while creating an object.'); + } + } + } + + public function processDelete() + { + if (Validate::isLoadedObject($object = $this->loadObject()) && isset($this->fieldImageSettings)) { + /** @var Product $object */ + // check if request at least one object with noZeroObject + if (isset($object->noZeroObject) && count($taxes = call_user_func(array($this->className, $object->noZeroObject))) <= 1) { + $this->errors[] = Tools::displayError('You need at least one object.').' <b>'.$this->table.'</b><br />'.Tools::displayError('You cannot delete all of the items.'); + } else { + /* + * @since 1.5.0 + * It is NOT possible to delete a product if there are currently: + * - physical stock for this product + * - supply order(s) for this product + */ + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $object->advanced_stock_management) { + $stock_manager = StockManagerFactory::getManager(); + $physical_quantity = $stock_manager->getProductPhysicalQuantities($object->id, 0); + $real_quantity = $stock_manager->getProductRealQuantities($object->id, 0); + if ($physical_quantity > 0 || $real_quantity > $physical_quantity) { + $this->errors[] = Tools::displayError('You cannot delete this product because there is physical stock left.'); + } + } + + if (!count($this->errors)) { + if ($object->delete()) { + $id_category = (int)Tools::getValue('id_category'); + $category_url = empty($id_category) ? '' : '&id_category='.(int)$id_category; + PrestaShopLogger::addLog(sprintf($this->l('%s deletion', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$object->id, true, (int)$this->context->employee->id); + $this->redirect_after = self::$currentIndex.'&conf=1&token='.$this->token.$category_url; + } else { + $this->errors[] = Tools::displayError('An error occurred during deletion.'); + } + } + } + } else { + $this->errors[] = Tools::displayError('An error occurred while deleting the object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } + } + + public function processImage() + { + $id_image = (int)Tools::getValue('id_image'); + $image = new Image((int)$id_image); + if (Validate::isLoadedObject($image)) { + /* Update product image/legend */ + // @todo : move in processEditProductImage + if (Tools::getIsset('editImage')) { + if ($image->cover) { + $_POST['cover'] = 1; + } + + $_POST['id_image'] = $image->id; + } elseif (Tools::getIsset('coverImage')) { + /* Choose product cover image */ + Image::deleteCover($image->id_product); + $image->cover = 1; + if (!$image->update()) { + $this->errors[] = Tools::displayError('You cannot change the product\'s cover image.'); + } else { + $productId = (int)Tools::getValue('id_product'); + @unlink(_PS_TMP_IMG_DIR_.'product_'.$productId.'.jpg'); + @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.$productId.'_'.$this->context->shop->id.'.jpg'); + $this->redirect_after = self::$currentIndex.'&id_product='.$image->id_product.'&id_category='.(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '').'&action=Images&addproduct'.'&token='.$this->token; + } + } elseif (Tools::getIsset('imgPosition') && Tools::getIsset('imgDirection')) { + /* Choose product image position */ + $image->updatePosition(Tools::getValue('imgDirection'), Tools::getValue('imgPosition')); + $this->redirect_after = self::$currentIndex.'&id_product='.$image->id_product.'&id_category='.(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '').'&add'.$this->table.'&action=Images&token='.$this->token; + } + } else { + $this->errors[] = Tools::displayError('The image could not be found. '); + } + } + + protected function processBulkDelete() + { + if ($this->tabAccess['delete'] === '1') { + if (is_array($this->boxes) && !empty($this->boxes)) { + $object = new $this->className(); + + if (isset($object->noZeroObject) && + // Check if all object will be deleted + (count(call_user_func(array($this->className, $object->noZeroObject))) <= 1 || count($_POST[$this->table.'Box']) == count(call_user_func(array($this->className, $object->noZeroObject))))) { + $this->errors[] = Tools::displayError('You need at least one object.').' <b>'.$this->table.'</b><br />'.Tools::displayError('You cannot delete all of the items.'); + } else { + $success = 1; + $products = Tools::getValue($this->table.'Box'); + if (is_array($products) && ($count = count($products))) { + // Deleting products can be quite long on a cheap server. Let's say 1.5 seconds by product (I've seen it!). + if (intval(ini_get('max_execution_time')) < round($count * 1.5)) { + ini_set('max_execution_time', round($count * 1.5)); + } + + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $stock_manager = StockManagerFactory::getManager(); + } + + foreach ($products as $id_product) { + $product = new Product((int)$id_product); + /* + * @since 1.5.0 + * It is NOT possible to delete a product if there are currently: + * - physical stock for this product + * - supply order(s) for this product + */ + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management) { + $physical_quantity = $stock_manager->getProductPhysicalQuantities($product->id, 0); + $real_quantity = $stock_manager->getProductRealQuantities($product->id, 0); + if ($physical_quantity > 0 || $real_quantity > $physical_quantity) { + $this->errors[] = sprintf(Tools::displayError('You cannot delete the product #%d because there is physical stock left.'), $product->id); + } + } + if (!count($this->errors)) { + if ($product->delete()) { + PrestaShopLogger::addLog(sprintf($this->l('%s deletion', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$product->id, true, (int)$this->context->employee->id); + } else { + $success = false; + } + } else { + $success = 0; + } + } + } + + if ($success) { + $id_category = (int)Tools::getValue('id_category'); + $category_url = empty($id_category) ? '' : '&id_category='.(int)$id_category; + $this->redirect_after = self::$currentIndex.'&conf=2&token='.$this->token.$category_url; + } else { + $this->errors[] = Tools::displayError('An error occurred while deleting this selection.'); + } + } + } else { + $this->errors[] = Tools::displayError('You must select at least one element to delete.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } + + public function processProductAttribute() + { + // Don't process if the combination fields have not been submitted + if (!Combination::isFeatureActive() || !Tools::getValue('attribute_combination_list')) { + return; + } + + if (Validate::isLoadedObject($product = $this->object)) { + if ($this->isProductFieldUpdated('attribute_price') && (!Tools::getIsset('attribute_price') || Tools::getIsset('attribute_price') == null)) { + $this->errors[] = Tools::displayError('The price attribute is required.'); + } + if (!Tools::getIsset('attribute_combination_list') || Tools::isEmpty(Tools::getValue('attribute_combination_list'))) { + $this->errors[] = Tools::displayError('You must add at least one attribute.'); + } + + $array_checks = array( + 'reference' => 'isReference', + 'supplier_reference' => 'isReference', + 'location' => 'isReference', + 'ean13' => 'isEan13', + 'upc' => 'isUpc', + 'wholesale_price' => 'isPrice', + 'price' => 'isPrice', + 'ecotax' => 'isPrice', + 'quantity' => 'isInt', + 'weight' => 'isUnsignedFloat', + 'unit_price_impact' => 'isPrice', + 'default_on' => 'isBool', + 'minimal_quantity' => 'isUnsignedInt', + 'available_date' => 'isDateFormat' + ); + foreach ($array_checks as $property => $check) { + if (Tools::getValue('attribute_'.$property) !== false && !call_user_func(array('Validate', $check), Tools::getValue('attribute_'.$property))) { + $this->errors[] = sprintf(Tools::displayError('Field %s is not valid'), $property); + } + } + + if (!count($this->errors)) { + if (!isset($_POST['attribute_wholesale_price'])) { + $_POST['attribute_wholesale_price'] = 0; + } + if (!isset($_POST['attribute_price_impact'])) { + $_POST['attribute_price_impact'] = 0; + } + if (!isset($_POST['attribute_weight_impact'])) { + $_POST['attribute_weight_impact'] = 0; + } + if (!isset($_POST['attribute_ecotax'])) { + $_POST['attribute_ecotax'] = 0; + } + if (Tools::getValue('attribute_default')) { + $product->deleteDefaultAttributes(); + } + + // Change existing one + if (($id_product_attribute = (int)Tools::getValue('id_product_attribute')) || ($id_product_attribute = $product->productAttributeExists(Tools::getValue('attribute_combination_list'), false, null, true, true))) { + if ($this->tabAccess['edit'] === '1') { + if ($this->isProductFieldUpdated('available_date_attribute') && (Tools::getValue('available_date_attribute') != '' &&!Validate::isDateFormat(Tools::getValue('available_date_attribute')))) { + $this->errors[] = Tools::displayError('Invalid date format.'); + } else { + $product->updateAttribute((int)$id_product_attribute, + $this->isProductFieldUpdated('attribute_wholesale_price') ? Tools::getValue('attribute_wholesale_price') : null, + $this->isProductFieldUpdated('attribute_price_impact') ? Tools::getValue('attribute_price') * Tools::getValue('attribute_price_impact') : null, + $this->isProductFieldUpdated('attribute_weight_impact') ? Tools::getValue('attribute_weight') * Tools::getValue('attribute_weight_impact') : null, + $this->isProductFieldUpdated('attribute_unit_impact') ? Tools::getValue('attribute_unity') * Tools::getValue('attribute_unit_impact') : null, + $this->isProductFieldUpdated('attribute_ecotax') ? Tools::getValue('attribute_ecotax') : null, + Tools::getValue('id_image_attr'), + Tools::getValue('attribute_reference'), + Tools::getValue('attribute_ean13'), + $this->isProductFieldUpdated('attribute_default') ? Tools::getValue('attribute_default') : null, + Tools::getValue('attribute_location'), + Tools::getValue('attribute_upc'), + $this->isProductFieldUpdated('attribute_minimal_quantity') ? Tools::getValue('attribute_minimal_quantity') : null, + $this->isProductFieldUpdated('available_date_attribute') ? Tools::getValue('available_date_attribute') : null, false); + StockAvailable::setProductDependsOnStock((int)$product->id, $product->depends_on_stock, null, (int)$id_product_attribute); + StockAvailable::setProductOutOfStock((int)$product->id, $product->out_of_stock, null, (int)$id_product_attribute); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } + // Add new + else { + if ($this->tabAccess['add'] === '1') { + if ($product->productAttributeExists(Tools::getValue('attribute_combination_list'))) { + $this->errors[] = Tools::displayError('This combination already exists.'); + } else { + $id_product_attribute = $product->addCombinationEntity( + Tools::getValue('attribute_wholesale_price'), + Tools::getValue('attribute_price') * Tools::getValue('attribute_price_impact'), + Tools::getValue('attribute_weight') * Tools::getValue('attribute_weight_impact'), + Tools::getValue('attribute_unity') * Tools::getValue('attribute_unit_impact'), + Tools::getValue('attribute_ecotax'), + 0, + Tools::getValue('id_image_attr'), + Tools::getValue('attribute_reference'), + null, + Tools::getValue('attribute_ean13'), + Tools::getValue('attribute_default'), + Tools::getValue('attribute_location'), + Tools::getValue('attribute_upc'), + Tools::getValue('attribute_minimal_quantity'), + array(), + Tools::getValue('available_date_attribute') + ); + StockAvailable::setProductDependsOnStock((int)$product->id, $product->depends_on_stock, null, (int)$id_product_attribute); + StockAvailable::setProductOutOfStock((int)$product->id, $product->out_of_stock, null, (int)$id_product_attribute); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to').'<hr>'.Tools::displayError('edit here.'); + } + } + if (!count($this->errors)) { + $combination = new Combination((int)$id_product_attribute); + $combination->setAttributes(Tools::getValue('attribute_combination_list')); + + // images could be deleted before + $id_images = Tools::getValue('id_image_attr'); + if (!empty($id_images)) { + $combination->setImages($id_images); + } + + $product->checkDefaultAttributes(); + if (Tools::getValue('attribute_default')) { + Product::updateDefaultAttribute((int)$product->id); + if (isset($id_product_attribute)) { + $product->cache_default_attribute = (int)$id_product_attribute; + } + + if ($available_date = Tools::getValue('available_date_attribute')) { + $product->setAvailableDate($available_date); + } else { + $product->setAvailableDate(); + } + } + } + } + } + } + + public function processFeatures() + { + if (!Feature::isFeatureActive()) { + return; + } + + if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product')))) { + // delete all objects + $product->deleteFeatures(); + + // add new objects + $languages = Language::getLanguages(false); + foreach ($_POST as $key => $val) { + if (preg_match('/^feature_([0-9]+)_value/i', $key, $match)) { + if ($val) { + $product->addFeaturesToDB($match[1], $val); + } else { + if ($default_value = $this->checkFeatures($languages, $match[1])) { + $id_value = $product->addFeaturesToDB($match[1], 0, 1); + foreach ($languages as $language) { + if ($cust = Tools::getValue('custom_'.$match[1].'_'.(int)$language['id_lang'])) { + $product->addFeaturesCustomToDB($id_value, (int)$language['id_lang'], $cust); + } else { + $product->addFeaturesCustomToDB($id_value, (int)$language['id_lang'], $default_value); + } + } + } + } + } + } + } else { + $this->errors[] = Tools::displayError('A product must be created before adding features.'); + } + } + + /** + * This function is never called at the moment (specific prices cannot be edited) + */ + public function processPricesModification() + { + $id_specific_prices = Tools::getValue('spm_id_specific_price'); + $id_combinations = Tools::getValue('spm_id_product_attribute'); + $id_shops = Tools::getValue('spm_id_shop'); + $id_currencies = Tools::getValue('spm_id_currency'); + $id_countries = Tools::getValue('spm_id_country'); + $id_groups = Tools::getValue('spm_id_group'); + $id_customers = Tools::getValue('spm_id_customer'); + $prices = Tools::getValue('spm_price'); + $from_quantities = Tools::getValue('spm_from_quantity'); + $reductions = Tools::getValue('spm_reduction'); + $reduction_types = Tools::getValue('spm_reduction_type'); + $froms = Tools::getValue('spm_from'); + $tos = Tools::getValue('spm_to'); + + foreach ($id_specific_prices as $key => $id_specific_price) { + if ($reduction_types[$key] == 'percentage' && ((float)$reductions[$key] <= 0 || (float)$reductions[$key] > 100)) { + $this->errors[] = Tools::displayError('Submitted reduction value (0-100) is out-of-range'); + } elseif ($this->_validateSpecificPrice($id_shops[$key], $id_currencies[$key], $id_countries[$key], $id_groups[$key], $id_customers[$key], $prices[$key], $from_quantities[$key], $reductions[$key], $reduction_types[$key], $froms[$key], $tos[$key], $id_combinations[$key])) { + $specific_price = new SpecificPrice((int)($id_specific_price)); + $specific_price->id_shop = (int)$id_shops[$key]; + $specific_price->id_product_attribute = (int)$id_combinations[$key]; + $specific_price->id_currency = (int)($id_currencies[$key]); + $specific_price->id_country = (int)($id_countries[$key]); + $specific_price->id_group = (int)($id_groups[$key]); + $specific_price->id_customer = (int)$id_customers[$key]; + $specific_price->price = (float)($prices[$key]); + $specific_price->from_quantity = (int)($from_quantities[$key]); + $specific_price->reduction = (float)($reduction_types[$key] == 'percentage' ? ($reductions[$key] / 100) : $reductions[$key]); + $specific_price->reduction_type = !$reductions[$key] ? 'amount' : $reduction_types[$key]; + $specific_price->from = !$froms[$key] ? '0000-00-00 00:00:00' : $froms[$key]; + $specific_price->to = !$tos[$key] ? '0000-00-00 00:00:00' : $tos[$key]; + if (!$specific_price->update()) { + $this->errors[] = Tools::displayError('An error occurred while updating the specific price.'); + } + } + } + if (!count($this->errors)) { + $this->redirect_after = self::$currentIndex.'&id_product='.(int)(Tools::getValue('id_product')).(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '').'&update'.$this->table.'&action=Prices&token='.$this->token; + } + } + + public function processPriceAddition() + { + // Check if a specific price has been submitted + if (!Tools::getIsset('submitPriceAddition')) { + return; + } + + $id_product = Tools::getValue('id_product'); + $id_product_attribute = Tools::getValue('sp_id_product_attribute'); + $id_shop = Tools::getValue('sp_id_shop'); + $id_currency = Tools::getValue('sp_id_currency'); + $id_country = Tools::getValue('sp_id_country'); + $id_group = Tools::getValue('sp_id_group'); + $id_customer = Tools::getValue('sp_id_customer'); + $price = Tools::getValue('leave_bprice') ? '-1' : Tools::getValue('sp_price'); + $from_quantity = Tools::getValue('sp_from_quantity'); + $reduction = (float)(Tools::getValue('sp_reduction')); + $reduction_tax = Tools::getValue('sp_reduction_tax'); + $reduction_type = !$reduction ? 'amount' : Tools::getValue('sp_reduction_type'); + $reduction_type = $reduction_type == '-' ? 'amount' : $reduction_type; + $from = Tools::getValue('sp_from'); + if (!$from) { + $from = '0000-00-00 00:00:00'; + } + $to = Tools::getValue('sp_to'); + if (!$to) { + $to = '0000-00-00 00:00:00'; + } + + if (($price == '-1') && ((float)$reduction == '0')) { + $this->errors[] = Tools::displayError('No reduction value has been submitted'); + } elseif (strtotime($to) < strtotime($from)) { + $this->errors[] = Tools::displayError('Invalid date range'); + } elseif ($reduction_type == 'percentage' && ((float)$reduction <= 0 || (float)$reduction > 100)) { + $this->errors[] = Tools::displayError('Submitted reduction value (0-100) is out-of-range'); + } elseif ($this->_validateSpecificPrice($id_shop, $id_currency, $id_country, $id_group, $id_customer, $price, $from_quantity, $reduction, $reduction_type, $from, $to, $id_product_attribute)) { + $specificPrice = new SpecificPrice(); + $specificPrice->id_product = (int)$id_product; + $specificPrice->id_product_attribute = (int)$id_product_attribute; + $specificPrice->id_shop = (int)$id_shop; + $specificPrice->id_currency = (int)($id_currency); + $specificPrice->id_country = (int)($id_country); + $specificPrice->id_group = (int)($id_group); + $specificPrice->id_customer = (int)$id_customer; + $specificPrice->price = (float)($price); + $specificPrice->from_quantity = (int)($from_quantity); + $specificPrice->reduction = (float)($reduction_type == 'percentage' ? $reduction / 100 : $reduction); + $specificPrice->reduction_tax = $reduction_tax; + $specificPrice->reduction_type = $reduction_type; + $specificPrice->from = $from; + $specificPrice->to = $to; + if (!$specificPrice->add()) { + $this->errors[] = Tools::displayError('An error occurred while updating the specific price.'); + } + } + } + + public function ajaxProcessDeleteSpecificPrice() + { + if ($this->tabAccess['delete'] === '1') { + $id_specific_price = (int)Tools::getValue('id_specific_price'); + if (!$id_specific_price || !Validate::isUnsignedId($id_specific_price)) { + $error = Tools::displayError('The specific price ID is invalid.'); + } else { + $specificPrice = new SpecificPrice((int)$id_specific_price); + if (!$specificPrice->delete()) { + $error = Tools::displayError('An error occurred while attempting to delete the specific price.'); + } + } + } else { + $error = Tools::displayError('You do not have permission to delete this.'); + } + + if (isset($error)) { + $json = array( + 'status' => 'error', + 'message'=> $error + ); + } else { + $json = array( + 'status' => 'ok', + 'message'=> $this->_conf[1] + ); + } + + die(Tools::jsonEncode($json)); + } + + public function processSpecificPricePriorities() + { + if (!($obj = $this->loadObject())) { + return; + } + if (!$priorities = Tools::getValue('specificPricePriority')) { + $this->errors[] = Tools::displayError('Please specify priorities.'); + } elseif (Tools::isSubmit('specificPricePriorityToAll')) { + if (!SpecificPrice::setPriorities($priorities)) { + $this->errors[] = Tools::displayError('An error occurred while updating priorities.'); + } else { + $this->confirmations[] = $this->l('The price rule has successfully updated'); + } + } elseif (!SpecificPrice::setSpecificPriority((int)$obj->id, $priorities)) { + $this->errors[] = Tools::displayError('An error occurred while setting priorities.'); + } + } + + public function processCustomizationConfiguration() + { + $product = $this->object; + // Get the number of existing customization fields ($product->text_fields is the updated value, not the existing value) + $current_customization = $product->getCustomizationFieldIds(); + $files_count = 0; + $text_count = 0; + if (is_array($current_customization)) { + foreach ($current_customization as $field) { + if ($field['type'] == 1) { + $text_count++; + } else { + $files_count++; + } + } + } + + if (!$product->createLabels((int)$product->uploadable_files - $files_count, (int)$product->text_fields - $text_count)) { + $this->errors[] = Tools::displayError('An error occurred while creating customization fields.'); + } + if (!count($this->errors) && !$product->updateLabels()) { + $this->errors[] = Tools::displayError('An error occurred while updating customization fields.'); + } + $product->customizable = ($product->uploadable_files > 0 || $product->text_fields > 0) ? 1 : 0; + if (($product->uploadable_files != $files_count || $product->text_fields != $text_count) && !count($this->errors) && !$product->update()) { + $this->errors[] = Tools::displayError('An error occurred while updating the custom configuration.'); + } + } + + public function processProductCustomization() + { + if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product')))) { + foreach ($_POST as $field => $value) { + if (strncmp($field, 'label_', 6) == 0 && !Validate::isLabel($value)) { + $this->errors[] = Tools::displayError('The label fields defined are invalid.'); + } + } + if (empty($this->errors) && !$product->updateLabels()) { + $this->errors[] = Tools::displayError('An error occurred while updating customization fields.'); + } + if (empty($this->errors)) { + $this->confirmations[] = $this->l('Update successful'); + } + } else { + $this->errors[] = Tools::displayError('A product must be created before adding customization.'); + } + } + + /** + * Overrides parent for custom redirect link + */ + public function processPosition() + { + /** @var Product $object */ + if (!Validate::isLoadedObject($object = $this->loadObject())) { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.'). + ' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } elseif (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) { + $this->errors[] = Tools::displayError('Failed to update the position.'); + } else { + $category = new Category((int)Tools::getValue('id_category')); + if (Validate::isLoadedObject($category)) { + Hook::exec('actionCategoryUpdate', array('category' => $category)); + } + $this->redirect_after = self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&action=Customization&conf=5'.(($id_category = (Tools::getIsset('id_category') ? (int)Tools::getValue('id_category') : '')) ? ('&id_category='.$id_category) : '').'&token='.Tools::getAdminTokenLite('AdminProducts'); + } + } + + public function initProcess() + { + if (Tools::isSubmit('submitAddproductAndStay') || Tools::isSubmit('submitAddproduct')) { + $this->id_object = (int)Tools::getValue('id_product'); + $this->object = new Product($this->id_object); + + if ($this->isTabSubmitted('Informations') && $this->object->is_virtual && (int)Tools::getValue('type_product') != 2) { + if ($id_product_download = (int)ProductDownload::getIdFromIdProduct($this->id_object)) { + $product_download = new ProductDownload($id_product_download); + if (!$product_download->deleteFile($id_product_download)) { + $this->errors[] = Tools::displayError('Cannot delete file'); + } + } + } + } + + // Delete a product in the download folder + if (Tools::getValue('deleteVirtualProduct')) { + if ($this->tabAccess['delete'] === '1') { + $this->action = 'deleteVirtualProduct'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } + // Product preview + elseif (Tools::isSubmit('submitAddProductAndPreview')) { + $this->display = 'edit'; + $this->action = 'save'; + if (Tools::getValue('id_product')) { + $this->id_object = Tools::getValue('id_product'); + $this->object = new Product((int)Tools::getValue('id_product')); + } + } elseif (Tools::isSubmit('submitAttachments')) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'attachments'; + $this->tab_display = 'attachments'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + // Product duplication + elseif (Tools::getIsset('duplicate'.$this->table)) { + if ($this->tabAccess['add'] === '1') { + $this->action = 'duplicate'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } + // Product images management + elseif (Tools::getValue('id_image') && Tools::getValue('ajax')) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'image'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + // Product attributes management + elseif (Tools::isSubmit('submitProductAttribute')) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'productAttribute'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + // Product features management + elseif (Tools::isSubmit('submitFeatures') || Tools::isSubmit('submitFeaturesAndStay')) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'features'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + // Product specific prices management NEVER USED + elseif (Tools::isSubmit('submitPricesModification')) { + if ($this->tabAccess['add'] === '1') { + $this->action = 'pricesModification'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } elseif (Tools::isSubmit('deleteSpecificPrice')) { + if ($this->tabAccess['delete'] === '1') { + $this->action = 'deleteSpecificPrice'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } elseif (Tools::isSubmit('submitSpecificPricePriorities')) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'specificPricePriorities'; + $this->tab_display = 'prices'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + // Customization management + elseif (Tools::isSubmit('submitCustomizationConfiguration')) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'customizationConfiguration'; + $this->tab_display = 'customization'; + $this->display = 'edit'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('submitProductCustomization')) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'productCustomization'; + $this->tab_display = 'customization'; + $this->display = 'edit'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('id_product')) { + $post_max_size = Tools::getMaxUploadSize(Configuration::get('PS_LIMIT_UPLOAD_FILE_VALUE') * 1024 * 1024); + if ($post_max_size && isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] && $_SERVER['CONTENT_LENGTH'] > $post_max_size) { + $this->errors[] = sprintf(Tools::displayError('The uploaded file exceeds the "Maximum size for a downloadable product" set in preferences (%1$dMB) or the post_max_size/ directive in php.ini (%2$dMB).'), number_format((Configuration::get('PS_LIMIT_UPLOAD_FILE_VALUE'))), ($post_max_size / 1024 / 1024)); + } + } + + if (!$this->action) { + parent::initProcess(); + } else { + $this->id_object = (int)Tools::getValue($this->identifier); + } + + if (isset($this->available_tabs[Tools::getValue('key_tab')])) { + $this->tab_display = Tools::getValue('key_tab'); + } + + // Set tab to display if not decided already + if (!$this->tab_display && $this->action) { + if (in_array($this->action, array_keys($this->available_tabs))) { + $this->tab_display = $this->action; + } + } + + // And if still not set, use default + if (!$this->tab_display) { + if (in_array($this->default_tab, $this->available_tabs)) { + $this->tab_display = $this->default_tab; + } else { + $this->tab_display = key($this->available_tabs); + } + } + } + + /** + * postProcess handle every checks before saving products information + * + * @return void + */ + public function postProcess() + { + if (!$this->redirect_after) { + parent::postProcess(); + } + + if ($this->display == 'edit' || $this->display == 'add') { + $this->addJqueryUI(array( + 'ui.core', + 'ui.widget' + )); + + $this->addjQueryPlugin(array( + 'autocomplete', + 'tablednd', + 'thickbox', + 'ajaxfileupload', + 'date', + 'tagify', + 'select2', + 'validate' + )); + + $this->addJS(array( + _PS_JS_DIR_.'admin/products.js', + _PS_JS_DIR_.'admin/attributes.js', + _PS_JS_DIR_.'admin/price.js', + _PS_JS_DIR_.'tiny_mce/tiny_mce.js', + _PS_JS_DIR_.'admin/tinymce.inc.js', + _PS_JS_DIR_.'admin/dnd.js', + _PS_JS_DIR_.'jquery/ui/jquery.ui.progressbar.min.js', + _PS_JS_DIR_.'vendor/spin.js', + _PS_JS_DIR_.'vendor/ladda.js' + )); + + $this->addJS(_PS_JS_DIR_.'jquery/plugins/select2/select2_locale_'.$this->context->language->iso_code.'.js'); + $this->addJS(_PS_JS_DIR_.'jquery/plugins/validate/localization/messages_'.$this->context->language->iso_code.'.js'); + + $this->addCSS(array( + _PS_JS_DIR_.'jquery/plugins/timepicker/jquery-ui-timepicker-addon.css' + )); + } + } + + public function ajaxProcessDeleteProductAttribute() + { + if (!Combination::isFeatureActive()) { + return; + } + + if ($this->tabAccess['delete'] === '1') { + $id_product = (int)Tools::getValue('id_product'); + $id_product_attribute = (int)Tools::getValue('id_product_attribute'); + + if ($id_product && Validate::isUnsignedId($id_product) && Validate::isLoadedObject($product = new Product($id_product))) { + if (($depends_on_stock = StockAvailable::dependsOnStock($id_product)) && StockAvailable::getQuantityAvailableByProduct($id_product, $id_product_attribute)) { + $json = array( + 'status' => 'error', + 'message'=> $this->l('It is not possible to delete a combination while it still has some quantities in the Advanced Stock Management. You must delete its stock first.') + ); + } else { + $product->deleteAttributeCombination((int)$id_product_attribute); + $product->checkDefaultAttributes(); + Tools::clearColorListCache((int)$product->id); + if (!$product->hasAttributes()) { + $product->cache_default_attribute = 0; + $product->update(); + } else { + Product::updateDefaultAttribute($id_product); + } + + if ($depends_on_stock && !Stock::deleteStockByIds($id_product, $id_product_attribute)) { + $json = array( + 'status' => 'error', + 'message'=> $this->l('Error while deleting the stock') + ); + } else { + $json = array( + 'status' => 'ok', + 'message'=> $this->_conf[1], + 'id_product_attribute' => (int)$id_product_attribute + ); + } + } + } else { + $json = array( + 'status' => 'error', + 'message'=> $this->l('You cannot delete this attribute.') + ); + } + } else { + $json = array( + 'status' => 'error', + 'message'=> $this->l('You do not have permission to delete this.') + ); + } + + die(Tools::jsonEncode($json)); + } + + public function ajaxProcessDefaultProductAttribute() + { + if ($this->tabAccess['edit'] === '1') { + if (!Combination::isFeatureActive()) { + return; + } + + if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product')))) { + $product->deleteDefaultAttributes(); + $product->setDefaultAttribute((int)Tools::getValue('id_product_attribute')); + $json = array( + 'status' => 'ok', + 'message'=> $this->_conf[4] + ); + } else { + $json = array( + 'status' => 'error', + 'message'=> $this->l('You cannot make this the default attribute.') + ); + } + + die(Tools::jsonEncode($json)); + } + } + + public function ajaxProcessEditProductAttribute() + { + if ($this->tabAccess['edit'] === '1') { + $id_product = (int)Tools::getValue('id_product'); + $id_product_attribute = (int)Tools::getValue('id_product_attribute'); + if ($id_product && Validate::isUnsignedId($id_product) && Validate::isLoadedObject($product = new Product((int)$id_product))) { + $combinations = $product->getAttributeCombinationsById($id_product_attribute, $this->context->language->id); + foreach ($combinations as $key => $combination) { + $combinations[$key]['attributes'][] = array($combination['group_name'], $combination['attribute_name'], $combination['id_attribute']); + } + + die(Tools::jsonEncode($combinations)); + } + } + } + + public function ajaxPreProcess() + { + if (Tools::getIsset('update'.$this->table) && Tools::getIsset('id_'.$this->table)) { + $this->display = 'edit'; + $this->action = Tools::getValue('action'); + } + } + + public function ajaxProcessUpdateProductImageShopAsso() + { + $id_product = Tools::getValue('id_product'); + if (($id_image = Tools::getValue('id_image')) && ($id_shop = (int)Tools::getValue('id_shop'))) { + if (Tools::getValue('active') == 'true') { + $res = Db::getInstance()->execute('INSERT INTO '._DB_PREFIX_.'image_shop (`id_image`, `id_shop`, `cover`) VALUES('.(int)$id_image.', '.(int)$id_shop.', NULL)'); + } else { + $res = Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'image_shop WHERE `id_image` = '.(int)$id_image.' AND `id_shop` = '.(int)$id_shop); + } + } + + // Clean covers in image table + $count_cover_image = Db::getInstance()->getValue(' SELECT COUNT(*) FROM '._DB_PREFIX_.'image i INNER JOIN '._DB_PREFIX_.'image_shop ish ON (i.id_image = ish.id_image AND ish.id_shop = '.(int)$id_shop.') WHERE i.cover = 1 AND `id_product` = '.(int)$id_product); - $id_image = Db::getInstance()->getValue(' + $id_image = Db::getInstance()->getValue(' SELECT i.`id_image` FROM '._DB_PREFIX_.'image i INNER JOIN '._DB_PREFIX_.'image_shop ish ON (i.id_image = ish.id_image AND ish.id_shop = '.(int)$id_shop.') WHERE `id_product` = '.(int)$id_product); - if ($count_cover_image < 1) - Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'image i SET i.cover = 1 WHERE i.id_image = '.(int)$id_image.' AND i.`id_product` = '.(int)$id_product.' LIMIT 1'); + if ($count_cover_image < 1) { + Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'image i SET i.cover = 1 WHERE i.id_image = '.(int)$id_image.' AND i.`id_product` = '.(int)$id_product.' LIMIT 1'); + } - if ($count_cover_image > 1) - Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'image i SET i.cover = 0 WHERE i.id_image <> '.(int)$id_image.' AND i.`id_product` = '.(int)$id_product); + if ($count_cover_image > 1) { + Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'image i SET i.cover = NULL WHERE i.id_image <> '.(int)$id_image.' AND i.`id_product` = '.(int)$id_product); + } - // Clean covers in image_shop table - $count_cover_image_shop = Db::getInstance()->getValue(' + // Clean covers in image_shop table + $count_cover_image_shop = Db::getInstance()->getValue(' SELECT COUNT(*) FROM '._DB_PREFIX_.'image_shop ish INNER JOIN '._DB_PREFIX_.'image i ON (i.id_image = ish.id_image AND i.`id_product` = '.(int)$id_product.') WHERE ish.id_shop = '.(int)$id_shop.' AND ish.cover = 1'); - if ($count_cover_image_shop < 1) - Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'image_shop ish SET ish.cover = 1 WHERE ish.id_image = '.(int)$id_image.' AND ish.id_shop = '.(int)$id_shop.' LIMIT 1'); - if ($count_cover_image_shop > 1) - Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'image_shop ish SET ish.cover = 0 WHERE ish.id_image <> '.(int)$id_image.' AND ish.cover = 1 AND ish.id_shop = '.(int)$id_shop.' LIMIT '.intval($count_cover_image_shop - 1)); + if ($count_cover_image_shop < 1) { + Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'image_shop ish SET ish.cover = 1 WHERE ish.id_image = '.(int)$id_image.' AND ish.id_shop = '.(int)$id_shop.' LIMIT 1'); + } + if ($count_cover_image_shop > 1) { + Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'image_shop ish SET ish.cover = NULL WHERE ish.id_image <> '.(int)$id_image.' AND ish.cover = 1 AND ish.id_shop = '.(int)$id_shop.' LIMIT '.intval($count_cover_image_shop - 1)); + } - if ($res) - $this->jsonConfirmation($this->_conf[27]); - else - $this->jsonError(Tools::displayError('An error occurred while attempting to associate this image with your shop. ')); - } + if ($res) { + $this->jsonConfirmation($this->_conf[27]); + } else { + $this->jsonError(Tools::displayError('An error occurred while attempting to associate this image with your shop. ')); + } + } - public function ajaxProcessUpdateImagePosition() - { - if ($this->tabAccess['edit'] === '0') - return die(Tools::jsonEncode(array('error' => $this->l('You do not have the right permission')))); - $res = false; - if ($json = Tools::getValue('json')) - { - $res = true; - $json = stripslashes($json); - $images = Tools::jsonDecode($json, true); - foreach ($images as $id => $position) - { - $img = new Image((int)$id); - $img->position = (int)$position; - $res &= $img->update(); - } - } - if ($res) - $this->jsonConfirmation($this->_conf[25]); - else - $this->jsonError(Tools::displayError('An error occurred while attempting to move this picture.')); - } + public function ajaxProcessUpdateImagePosition() + { + if ($this->tabAccess['edit'] === '0') { + return die(Tools::jsonEncode(array('error' => $this->l('You do not have the right permission')))); + } + $res = false; + if ($json = Tools::getValue('json')) { + $res = true; + $json = stripslashes($json); + $images = Tools::jsonDecode($json, true); + foreach ($images as $id => $position) { + $img = new Image((int)$id); + $img->position = (int)$position; + $res &= $img->update(); + } + } + if ($res) { + $this->jsonConfirmation($this->_conf[25]); + } else { + $this->jsonError(Tools::displayError('An error occurred while attempting to move this picture.')); + } + } - public function ajaxProcessUpdateCover() - { - if ($this->tabAccess['edit'] === '0') - return die(Tools::jsonEncode(array('error' => $this->l('You do not have the right permission')))); - Image::deleteCover((int)Tools::getValue('id_product')); - $img = new Image((int)Tools::getValue('id_image')); - $img->cover = 1; + public function ajaxProcessUpdateCover() + { + if ($this->tabAccess['edit'] === '0') { + return die(Tools::jsonEncode(array('error' => $this->l('You do not have the right permission')))); + } + Image::deleteCover((int)Tools::getValue('id_product')); + $img = new Image((int)Tools::getValue('id_image')); + $img->cover = 1; - @unlink(_PS_TMP_IMG_DIR_.'product_'.(int)$img->id_product.'.jpg'); - @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.(int)$img->id_product.'_'.$this->context->shop->id.'.jpg'); + @unlink(_PS_TMP_IMG_DIR_.'product_'.(int)$img->id_product.'.jpg'); + @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.(int)$img->id_product.'_'.$this->context->shop->id.'.jpg'); - if ($img->update()) - $this->jsonConfirmation($this->_conf[26]); - else - $this->jsonError(Tools::displayError('An error occurred while attempting to move this picture.')); - } + if ($img->update()) { + $this->jsonConfirmation($this->_conf[26]); + } else { + $this->jsonError(Tools::displayError('An error occurred while attempting to move this picture.')); + } + } - public function ajaxProcessDeleteProductImage() - { - $this->display = 'content'; - $res = true; - /* Delete product image */ - $image = new Image((int)Tools::getValue('id_image')); - $this->content['id'] = $image->id; - $res &= $image->delete(); - // if deleted image was the cover, change it to the first one - if (!Image::getCover($image->id_product)) - { - $res &= Db::getInstance()->execute(' + public function ajaxProcessDeleteProductImage() + { + $this->display = 'content'; + $res = true; + /* Delete product image */ + $image = new Image((int)Tools::getValue('id_image')); + $this->content['id'] = $image->id; + $res &= $image->delete(); + // if deleted image was the cover, change it to the first one + if (!Image::getCover($image->id_product)) { + $res &= Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'image_shop` image_shop, '._DB_PREFIX_.'image i SET image_shop.`cover` = 1, i.cover = 1 WHERE image_shop.`id_image` = (SELECT id_image FROM (SELECT image_shop.id_image FROM '._DB_PREFIX_.'image i'. - Shop::addSqlAssociation('image', 'i').' + Shop::addSqlAssociation('image', 'i').' WHERE i.id_product ='.(int)$image->id_product.' LIMIT 1 ) tmpImage) AND id_shop='.(int)$this->context->shop->id.' AND i.id_image = image_shop.id_image '); - } - - if (file_exists(_PS_TMP_IMG_DIR_.'product_'.$image->id_product.'.jpg')) - $res &= @unlink(_PS_TMP_IMG_DIR_.'product_'.$image->id_product.'.jpg'); - if (file_exists(_PS_TMP_IMG_DIR_.'product_mini_'.$image->id_product.'_'.$this->context->shop->id.'.jpg')) - $res &= @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.$image->id_product.'_'.$this->context->shop->id.'.jpg'); - - if ($res) - $this->jsonConfirmation($this->_conf[7]); - else - $this->jsonError(Tools::displayError('An error occurred while attempting to delete the product image.')); - } - - protected function _validateSpecificPrice($id_shop, $id_currency, $id_country, $id_group, $id_customer, $price, $from_quantity, $reduction, $reduction_type, $from, $to, $id_combination = 0) - { - if (!Validate::isUnsignedId($id_shop) || !Validate::isUnsignedId($id_currency) || !Validate::isUnsignedId($id_country) || !Validate::isUnsignedId($id_group) || !Validate::isUnsignedId($id_customer)) - $this->errors[] = Tools::displayError('Wrong IDs'); - elseif ((!isset($price) && !isset($reduction)) || (isset($price) && !Validate::isNegativePrice($price)) || (isset($reduction) && !Validate::isPrice($reduction))) - $this->errors[] = Tools::displayError('Invalid price/discount amount'); - elseif (!Validate::isUnsignedInt($from_quantity)) - $this->errors[] = Tools::displayError('Invalid quantity'); - elseif ($reduction && !Validate::isReductionType($reduction_type)) - $this->errors[] = Tools::displayError('Please select a discount type (amount or percentage).'); - elseif ($from && $to && (!Validate::isDateFormat($from) || !Validate::isDateFormat($to))) - $this->errors[] = Tools::displayError('The from/to date is invalid.'); - elseif (SpecificPrice::exists((int)$this->object->id, $id_combination, $id_shop, $id_group, $id_country, $id_currency, $id_customer, $from_quantity, $from, $to, false)) - $this->errors[] = Tools::displayError('A specific price already exists for these parameters.'); - else - return true; - return false; - } - - /* Checking customs feature */ - protected function checkFeatures($languages, $feature_id) - { - $rules = call_user_func(array('FeatureValue', 'getValidationRules'), 'FeatureValue'); - $feature = Feature::getFeature((int)Configuration::get('PS_LANG_DEFAULT'), $feature_id); - - foreach ($languages as $language) - if ($val = Tools::getValue('custom_'.$feature_id.'_'.$language['id_lang'])) - { - $current_language = new Language($language['id_lang']); - if (Tools::strlen($val) > $rules['sizeLang']['value']) - $this->errors[] = sprintf( - Tools::displayError('The name for feature %1$s is too long in %2$s.'), - ' <b>'.$feature['name'].'</b>', - $current_language->name - ); - elseif (!call_user_func(array('Validate', $rules['validateLang']['value']), $val)) - $this->errors[] = sprintf( - Tools::displayError('A valid name required for feature. %1$s in %2$s.'), - ' <b>'.$feature['name'].'</b>', - $current_language->name - ); - if (count($this->errors)) - return 0; - // Getting default language - if ($language['id_lang'] == Configuration::get('PS_LANG_DEFAULT')) - return $val; - } - return 0; - } - - /** - * Add or update a product image - * - * @param Product $product Product object to add image - * @param string $method - * - * @return int|false - */ - public function addProductImage($product, $method = 'auto') - { - /* Updating an existing product image */ - if ($id_image = (int)Tools::getValue('id_image')) - { - $image = new Image((int)$id_image); - if (!Validate::isLoadedObject($image)) - $this->errors[] = Tools::displayError('An error occurred while loading the object image.'); - else - { - if (($cover = Tools::getValue('cover')) == 1) - Image::deleteCover($product->id); - $image->cover = $cover; - $this->validateRules('Image'); - $this->copyFromPost($image, 'image'); - if (count($this->errors) || !$image->update()) - $this->errors[] = Tools::displayError('An error occurred while updating the image.'); - elseif (isset($_FILES['image_product']['tmp_name']) && $_FILES['image_product']['tmp_name'] != null) - $this->copyImage($product->id, $image->id, $method); - } - } - if (isset($image) && Validate::isLoadedObject($image) && !file_exists(_PS_PROD_IMG_DIR_.$image->getExistingImgPath().'.'.$image->image_format)) - $image->delete(); - if (count($this->errors)) - return false; - @unlink(_PS_TMP_IMG_DIR_.'product_'.$product->id.'.jpg'); - @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.$product->id.'_'.$this->context->shop->id.'.jpg'); - return ((isset($id_image) && is_int($id_image) && $id_image) ? $id_image : false); - } - - /** - * Copy a product image - * - * @param int $id_product Product Id for product image filename - * @param int $id_image Image Id for product image filename - * @param string $method - * - * @return void|false - * @throws PrestaShopException - */ - public function copyImage($id_product, $id_image, $method = 'auto') - { - if (!isset($_FILES['image_product']['tmp_name'])) - return false; - if ($error = ImageManager::validateUpload($_FILES['image_product'])) - $this->errors[] = $error; - else - { - $image = new Image($id_image); - - if (!$new_path = $image->getPathForCreation()) - $this->errors[] = Tools::displayError('An error occurred while attempting to create a new folder.'); - if (!($tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES['image_product']['tmp_name'], $tmpName)) - $this->errors[] = Tools::displayError('An error occurred during the image upload process.'); - elseif (!ImageManager::resize($tmpName, $new_path.'.'.$image->image_format)) - $this->errors[] = Tools::displayError('An error occurred while copying the image.'); - elseif ($method == 'auto') - { - $imagesTypes = ImageType::getImagesTypes('products'); - foreach ($imagesTypes as $k => $image_type) - { - if (!ImageManager::resize($tmpName, $new_path.'-'.stripslashes($image_type['name']).'.'.$image->image_format, $image_type['width'], $image_type['height'], $image->image_format)) - $this->errors[] = Tools::displayError('An error occurred while copying this image:').' '.stripslashes($image_type['name']); - } - } - - @unlink($tmpName); - Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_product)); - } - } - - protected function updateAssoShop($id_object) - { - //override AdminController::updateAssoShop() specifically for products because shop association is set with the context in ObjectModel - return; - } - - public function processAdd() - { - $this->checkProduct(); - - if (!empty($this->errors)) - { - $this->display = 'add'; - return false; - } - - $this->object = new $this->className(); - $this->_removeTaxFromEcotax(); - $this->copyFromPost($this->object, $this->table); - if ($this->object->add()) - { - PrestaShopLogger::addLog(sprintf($this->l('%s addition', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); - $this->addCarriers($this->object); - $this->updateAccessories($this->object); - $this->updatePackItems($this->object); - $this->updateDownloadProduct($this->object); - - if (Configuration::get('PS_FORCE_ASM_NEW_PRODUCT') && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $this->object->getType() != Product::PTYPE_VIRTUAL) - { - $this->object->advanced_stock_management = 1; - StockAvailable::setProductDependsOnStock($this->object->id, true, (int)$this->context->shop->id, 0); - $this->object->save(); - } - - if (empty($this->errors)) - { - $languages = Language::getLanguages(false); - if ($this->isProductFieldUpdated('category_box') && !$this->object->updateCategories(Tools::getValue('categoryBox'))) - $this->errors[] = Tools::displayError('An error occurred while linking the object.').' <b>'.$this->table.'</b> '.Tools::displayError('To categories'); - elseif (!$this->updateTags($languages, $this->object)) - $this->errors[] = Tools::displayError('An error occurred while adding tags.'); - else - { - Hook::exec('actionProductAdd', array('id_product' => (int)$this->object->id, 'product' => $this->object)); - if (in_array($this->object->visibility, array('both', 'search')) && Configuration::get('PS_SEARCH_INDEXATION')) - Search::indexation(false, $this->object->id); - } - - if (Configuration::get('PS_DEFAULT_WAREHOUSE_NEW_PRODUCT') != 0 && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $warehouse_location_entity = new WarehouseProductLocation(); - $warehouse_location_entity->id_product = $this->object->id; - $warehouse_location_entity->id_product_attribute = 0; - $warehouse_location_entity->id_warehouse = Configuration::get('PS_DEFAULT_WAREHOUSE_NEW_PRODUCT'); - $warehouse_location_entity->location = pSQL(''); - $warehouse_location_entity->save(); - } - - // Apply groups reductions - $this->object->setGroupReduction(); - - // Save and preview - if (Tools::isSubmit('submitAddProductAndPreview')) - $this->redirect_after = $this->getPreviewUrl($this->object); - - // Save and stay on same form - if ($this->display == 'edit') - $this->redirect_after = self::$currentIndex.'&id_product='.(int)$this->object->id - .(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '') - .'&updateproduct&conf=3&key_tab='.Tools::safeOutput(Tools::getValue('key_tab')).'&token='.$this->token; - else - // Default behavior (save and back) - $this->redirect_after = self::$currentIndex - .(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '') - .'&conf=3&token='.$this->token; - } - else - { - $this->object->delete(); - // if errors : stay on edit page - $this->display = 'edit'; - } - } - else - $this->errors[] = Tools::displayError('An error occurred while creating an object.').' <b>'.$this->table.'</b>'; - - return $this->object; - } - - protected function isTabSubmitted($tab_name) - { - if (!is_array($this->submitted_tabs)) - $this->submitted_tabs = Tools::getValue('submitted_tabs'); - - if (is_array($this->submitted_tabs) && in_array($tab_name, $this->submitted_tabs)) - return true; - - return false; - } - - public function processStatus() - { - $this->loadObject(true); - if (!Validate::isLoadedObject($this->object)) - return false; - if (($error = $this->object->validateFields(false, true)) !== true) - $this->errors[] = $error; - if (($error = $this->object->validateFieldsLang(false, true)) !== true) - $this->errors[] = $error; - - if (count($this->errors)) - return false; - - $res = parent::processStatus(); - - return $res; - } - - public function processUpdate() - { - $existing_product = $this->object; - - $this->checkProduct(); - - if (!empty($this->errors)) - { - $this->display = 'edit'; - return false; - } - - $id = (int)Tools::getValue('id_'.$this->table); - /* Update an existing product */ - if (isset($id) && !empty($id)) - { - /** @var Product $object */ - $object = new $this->className((int)$id); - $this->object = $object; - - if (Validate::isLoadedObject($object)) - { - $this->_removeTaxFromEcotax(); - $product_type_before = $object->getType(); - $this->copyFromPost($object, $this->table); - $object->indexed = 0; - - if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) - $object->setFieldsToUpdate((array)Tools::getValue('multishop_check', array())); - - // Duplicate combinations if not associated to shop - if ($this->context->shop->getContext() == Shop::CONTEXT_SHOP && !$object->isAssociatedToShop()) - { - $is_associated_to_shop = false; - $combinations = Product::getProductAttributesIds($object->id); - if ($combinations) - { - foreach ($combinations as $id_combination) - { - $combination = new Combination((int)$id_combination['id_product_attribute']); - $default_combination = new Combination((int)$id_combination['id_product_attribute'], null, (int)$this->object->id_shop_default); - - $def = ObjectModel::getDefinition($default_combination); - foreach ($def['fields'] as $field_name => $row) - $combination->$field_name = ObjectModel::formatValue($default_combination->$field_name, $def['fields'][$field_name]['type']); - - $combination->save(); - } - } - } - else - $is_associated_to_shop = true; - - if ($object->update()) - { - // If the product doesn't exist in the current shop but exists in another shop - if (Shop::getContext() == Shop::CONTEXT_SHOP && !$existing_product->isAssociatedToShop($this->context->shop->id)) - { - $out_of_stock = StockAvailable::outOfStock($existing_product->id, $existing_product->id_shop_default); - $depends_on_stock = StockAvailable::dependsOnStock($existing_product->id, $existing_product->id_shop_default); - StockAvailable::setProductOutOfStock((int)$this->object->id, $out_of_stock, $this->context->shop->id); - StockAvailable::setProductDependsOnStock((int)$this->object->id, $depends_on_stock, $this->context->shop->id); - } - - PrestaShopLogger::addLog(sprintf($this->l('%s modification', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); - if (in_array($this->context->shop->getContext(), array(Shop::CONTEXT_SHOP, Shop::CONTEXT_ALL))) - { - if ($this->isTabSubmitted('Shipping')) - $this->addCarriers(); - if ($this->isTabSubmitted('Associations')) - $this->updateAccessories($object); - if ($this->isTabSubmitted('Suppliers')) - $this->processSuppliers(); - if ($this->isTabSubmitted('Features')) - $this->processFeatures(); - if ($this->isTabSubmitted('Combinations')) - $this->processProductAttribute(); - if ($this->isTabSubmitted('Prices')) - { - $this->processPriceAddition(); - $this->processSpecificPricePriorities(); - } - if ($this->isTabSubmitted('Customization')) - $this->processCustomizationConfiguration(); - if ($this->isTabSubmitted('Attachments')) - $this->processAttachments(); - if ($this->isTabSubmitted('Images')) - $this->processImageLegends(); - - $this->updatePackItems($object); - // Disallow avanced stock management if the product become a pack - if ($product_type_before == Product::PTYPE_SIMPLE && $object->getType() == Product::PTYPE_PACK) - StockAvailable::setProductDependsOnStock((int)$object->id, false); - $this->updateDownloadProduct($object, 1); - $this->updateTags(Language::getLanguages(false), $object); - - if ($this->isProductFieldUpdated('category_box') && !$object->updateCategories(Tools::getValue('categoryBox'))) - $this->errors[] = Tools::displayError('An error occurred while linking the object.').' <b>'.$this->table.'</b> '.Tools::displayError('To categories'); - } - - if ($this->isTabSubmitted('Warehouses')) - $this->processWarehouses(); - if (empty($this->errors)) - { - if (in_array($object->visibility, array('both', 'search')) && Configuration::get('PS_SEARCH_INDEXATION')) - Search::indexation(false, $object->id); - - // Save and preview - if (Tools::isSubmit('submitAddProductAndPreview')) - $this->redirect_after = $this->getPreviewUrl($object); - else - { - $page = (int)Tools::getValue('page'); - // Save and stay on same form - if ($this->display == 'edit') - { - $this->confirmations[] = $this->l('Update successful'); - $this->redirect_after = self::$currentIndex.'&id_product='.(int)$this->object->id - .(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '') - .'&updateproduct&conf=4&key_tab='.Tools::safeOutput(Tools::getValue('key_tab')).($page > 1 ? '&page='.(int)$page : '').'&token='.$this->token; - } - else - // Default behavior (save and back) - $this->redirect_after = self::$currentIndex.(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '').'&conf=4'.($page > 1 ? '&submitFilterproduct='.(int)$page : '').'&token='.$this->token; - } - } - // if errors : stay on edit page - else - $this->display = 'edit'; - } - else - { - if (!$is_associated_to_shop && $combinations) - foreach ($combinations as $id_combination) - { - $combination = new Combination((int)$id_combination['id_product_attribute']); - $combination->delete(); - } - $this->errors[] = Tools::displayError('An error occurred while updating an object.').' <b>'.$this->table.'</b> ('.Db::getInstance()->getMsgError().')'; - } - } - else - $this->errors[] = Tools::displayError('An error occurred while updating an object.').' <b>'.$this->table.'</b> ('.Tools::displayError('The object cannot be loaded. ').')'; - return $object; - } - } - - /** - * Check that a saved product is valid - */ - public function checkProduct() - { - $className = 'Product'; - // @todo : the call_user_func seems to contains only statics values (className = 'Product') - $rules = call_user_func(array($this->className, 'getValidationRules'), $this->className); - $default_language = new Language((int)Configuration::get('PS_LANG_DEFAULT')); - $languages = Language::getLanguages(false); - - // Check required fields - foreach ($rules['required'] as $field) - { - if (!$this->isProductFieldUpdated($field)) - continue; - - if (($value = Tools::getValue($field)) == false && $value != '0') - { - if (Tools::getValue('id_'.$this->table) && $field == 'passwd') - continue; - $this->errors[] = sprintf( - Tools::displayError('The %s field is required.'), - call_user_func(array($className, 'displayFieldName'), $field, $className) - ); - } - } - - // Check multilingual required fields - foreach ($rules['requiredLang'] as $fieldLang) - if ($this->isProductFieldUpdated($fieldLang, $default_language->id) && !Tools::getValue($fieldLang.'_'.$default_language->id)) - $this->errors[] = sprintf( - Tools::displayError('This %1$s field is required at least in %2$s'), - call_user_func(array($className, 'displayFieldName'), $fieldLang, $className), - $default_language->name - ); - - // Check fields sizes - foreach ($rules['size'] as $field => $maxLength) - if ($this->isProductFieldUpdated($field) && ($value = Tools::getValue($field)) && Tools::strlen($value) > $maxLength) - $this->errors[] = sprintf( - Tools::displayError('The %1$s field is too long (%2$d chars max).'), - call_user_func(array($className, 'displayFieldName'), $field, $className), - $maxLength - ); - - if (Tools::getIsset('description_short') && $this->isProductFieldUpdated('description_short')) - { - $saveShort = Tools::getValue('description_short'); - $_POST['description_short'] = strip_tags(Tools::getValue('description_short')); - } - - // Check description short size without html - $limit = (int)Configuration::get('PS_PRODUCT_SHORT_DESC_LIMIT'); - if ($limit <= 0) $limit = 400; - foreach ($languages as $language) - if ($this->isProductFieldUpdated('description_short', $language['id_lang']) && ($value = Tools::getValue('description_short_'.$language['id_lang']))) - if (Tools::strlen(strip_tags($value)) > $limit) - $this->errors[] = sprintf( - Tools::displayError('This %1$s field (%2$s) is too long: %3$d chars max (current count %4$d).'), - call_user_func(array($className, 'displayFieldName'), 'description_short'), - $language['name'], - $limit, - Tools::strlen(strip_tags($value)) - ); - - // Check multilingual fields sizes - foreach ($rules['sizeLang'] as $fieldLang => $maxLength) - foreach ($languages as $language) - { - $value = Tools::getValue($fieldLang.'_'.$language['id_lang']); - if ($value && Tools::strlen($value) > $maxLength) - $this->errors[] = sprintf( - Tools::displayError('The %1$s field is too long (%2$d chars max).'), - call_user_func(array($className, 'displayFieldName'), $fieldLang, $className), - $maxLength - ); - } - - if ($this->isProductFieldUpdated('description_short') && isset($_POST['description_short'])) - $_POST['description_short'] = $saveShort; - - // Check fields validity - foreach ($rules['validate'] as $field => $function) - if ($this->isProductFieldUpdated($field) && ($value = Tools::getValue($field))) - { - $res = true; - if (Tools::strtolower($function) == 'iscleanhtml') - { - if (!Validate::$function($value, (int)Configuration::get('PS_ALLOW_HTML_IFRAME'))) - $res = false; - } - else - if (!Validate::$function($value)) - $res = false; - - if (!$res) - $this->errors[] = sprintf( - Tools::displayError('The %s field is invalid.'), - call_user_func(array($className, 'displayFieldName'), $field, $className) - ); - } - // Check multilingual fields validity - foreach ($rules['validateLang'] as $fieldLang => $function) - foreach ($languages as $language) - if ($this->isProductFieldUpdated($fieldLang, $language['id_lang']) && ($value = Tools::getValue($fieldLang.'_'.$language['id_lang']))) - if (!Validate::$function($value, (int)Configuration::get('PS_ALLOW_HTML_IFRAME'))) - $this->errors[] = sprintf( - Tools::displayError('The %1$s field (%2$s) is invalid.'), - call_user_func(array($className, 'displayFieldName'), $fieldLang, $className), - $language['name'] - ); - - // Categories - if ($this->isProductFieldUpdated('id_category_default') && (!Tools::isSubmit('categoryBox') || !count(Tools::getValue('categoryBox')))) - $this->errors[] = $this->l('Products must be in at least one category.'); - - if ($this->isProductFieldUpdated('id_category_default') && (!is_array(Tools::getValue('categoryBox')) || !in_array(Tools::getValue('id_category_default'), Tools::getValue('categoryBox')))) - $this->errors[] = $this->l('This product must be in the default category.'); - - // Tags - foreach ($languages as $language) - if ($value = Tools::getValue('tags_'.$language['id_lang'])) - if (!Validate::isTagsList($value)) - $this->errors[] = sprintf( - Tools::displayError('The tags list (%s) is invalid.'), - $language['name'] - ); - } - - /** - * Check if a field is edited (if the checkbox is checked) - * This method will do something only for multishop with a context all / group - * - * @param string $field Name of field - * @param int $id_lang - * @return bool - */ - protected function isProductFieldUpdated($field, $id_lang = null) - { - // Cache this condition to improve performances - static $is_activated = null; - if (is_null($is_activated)) - $is_activated = Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP && $this->id_object; - - if (!$is_activated) - return true; - - if (is_null($id_lang)) - return !empty($_POST['multishop_check'][$field]); - else - return !empty($_POST['multishop_check'][$field][$id_lang]); - } - - protected function _removeTaxFromEcotax() - { - if ($ecotax = Tools::getValue('ecotax')) - $_POST['ecotax'] = Tools::ps_round($ecotax / (1 + Tax::getProductEcotaxRate() / 100), 6); - } - - protected function _applyTaxToEcotax($product) - { - if ($product->ecotax) - $product->ecotax = Tools::ps_round($product->ecotax * (1 + Tax::getProductEcotaxRate() / 100), 2); - } - - /** - * Update product download - * - * @param Product $product - * @param int $edit - * - * @return bool - */ - public function updateDownloadProduct($product, $edit = 0) - { - if ((int)Tools::getValue('is_virtual_file') == 1) - { - if (isset($_FILES['virtual_product_file_uploader']) && $_FILES['virtual_product_file_uploader']['size'] > 0) - { - $virtual_product_filename = ProductDownload::getNewFilename(); - $helper = new HelperUploader('virtual_product_file_uploader'); - $helper->setPostMaxSize(Tools::getOctets(ini_get('upload_max_filesize'))) - ->setSavePath(_PS_DOWNLOAD_DIR_)->upload($_FILES['virtual_product_file_uploader'], $virtual_product_filename); - } - else - $virtual_product_filename = Tools::getValue('virtual_product_filename', ProductDownload::getNewFilename()); - - $product->setDefaultAttribute(0);//reset cache_default_attribute - if (Tools::getValue('virtual_product_expiration_date') && !Validate::isDate(Tools::getValue('virtual_product_expiration_date'))) - if (!Tools::getValue('virtual_product_expiration_date')) - { - $this->errors[] = Tools::displayError('The expiration-date attribute is required.'); - return false; - } - - // Trick's - if ($edit == 1) - { - $id_product_download = (int)ProductDownload::getIdFromIdProduct((int)$product->id); - if (!$id_product_download) - $id_product_download = (int)Tools::getValue('virtual_product_id'); - } - else - $id_product_download = Tools::getValue('virtual_product_id'); - - $is_shareable = Tools::getValue('virtual_product_is_shareable'); - $virtual_product_name = Tools::getValue('virtual_product_name'); - $virtual_product_nb_days = Tools::getValue('virtual_product_nb_days'); - $virtual_product_nb_downloable = Tools::getValue('virtual_product_nb_downloable'); - $virtual_product_expiration_date = Tools::getValue('virtual_product_expiration_date'); - - $download = new ProductDownload((int)$id_product_download); - $download->id_product = (int)$product->id; - $download->display_filename = $virtual_product_name; - $download->filename = $virtual_product_filename; - $download->date_add = date('Y-m-d H:i:s'); - $download->date_expiration = $virtual_product_expiration_date ? $virtual_product_expiration_date.' 23:59:59' : ''; - $download->nb_days_accessible = (int)$virtual_product_nb_days; - $download->nb_downloadable = (int)$virtual_product_nb_downloable; - $download->active = 1; - $download->is_shareable = (int)$is_shareable; - - if ($download->save()) - return true; - } - else - { - /* unactive download product if checkbox not checked */ - if ($edit == 1) - { - $id_product_download = (int)ProductDownload::getIdFromIdProduct((int)$product->id); - if (!$id_product_download) - $id_product_download = (int)Tools::getValue('virtual_product_id'); - } - else - $id_product_download = ProductDownload::getIdFromIdProduct($product->id); - - if (!empty($id_product_download)) - { - $product_download = new ProductDownload((int)$id_product_download); - $product_download->date_expiration = date('Y-m-d H:i:s', time() - 1); - $product_download->active = 0; - return $product_download->save(); - } - } - return false; - } - - /** - * Update product accessories - * - * @param object $product Product - */ - public function updateAccessories($product) - { - $product->deleteAccessories(); - if ($accessories = Tools::getValue('inputAccessories')) - { - $accessories_id = array_unique(explode('-', $accessories)); - if (count($accessories_id)) - { - array_pop($accessories_id); - $product->changeAccessories($accessories_id); - } - } - } - - /** - * Update product tags - * - * @param array $languages Array languages - * @param object $product Product - * @return bool Update result - */ - public function updateTags($languages, $product) - { - $tag_success = true; - /* Reset all tags for THIS product */ - if (!Tag::deleteTagsForProduct((int)$product->id)) - $this->errors[] = Tools::displayError('An error occurred while attempting to delete previous tags.'); - /* Assign tags to this product */ - foreach ($languages as $language) - if ($value = Tools::getValue('tags_'.$language['id_lang'])) - $tag_success &= Tag::addTags($language['id_lang'], (int)$product->id, $value); - - if (!$tag_success) - $this->errors[] = Tools::displayError('An error occurred while adding tags.'); - - return $tag_success; - } - - public function initContent($token = null) - { - if ($this->display == 'edit' || $this->display == 'add') - { - $this->fields_form = array(); - - // Check if Module - if (substr($this->tab_display, 0, 6) == 'Module') - { - $this->tab_display_module = strtolower(substr($this->tab_display, 6, Tools::strlen($this->tab_display) - 6)); - $this->tab_display = 'Modules'; - } - if (method_exists($this, 'initForm'.$this->tab_display)) - $this->tpl_form = strtolower($this->tab_display).'.tpl'; - - if ($this->ajax) - $this->content_only = true; - else - { - $product_tabs = array(); - - // tab_display defines which tab to display first - if (!method_exists($this, 'initForm'.$this->tab_display)) - $this->tab_display = $this->default_tab; - - $advanced_stock_management_active = Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'); - foreach ($this->available_tabs as $product_tab => $value) - { - // if it's the warehouses tab and advanced stock management is disabled, continue - if ($advanced_stock_management_active == 0 && $product_tab == 'Warehouses') - continue; - - $product_tabs[$product_tab] = array( - 'id' => $product_tab, - 'selected' => (strtolower($product_tab) == strtolower($this->tab_display) || (isset($this->tab_display_module) && 'module'.$this->tab_display_module == Tools::strtolower($product_tab))), - 'name' => $this->available_tabs_lang[$product_tab], - 'href' => $this->context->link->getAdminLink('AdminProducts').'&id_product='.(int)Tools::getValue('id_product').'&action='.$product_tab, - ); - } - $this->tpl_form_vars['product_tabs'] = $product_tabs; - } - } - else - { - if ($id_category = (int)$this->id_current_category) - self::$currentIndex .= '&id_category='.(int)$this->id_current_category; - - // If products from all categories are displayed, we don't want to use sorting by position - if (!$id_category) - { - $this->_defaultOrderBy = $this->identifier; - if ($this->context->cookie->{$this->table.'Orderby'} == 'position') - { - unset($this->context->cookie->{$this->table.'Orderby'}); - unset($this->context->cookie->{$this->table.'Orderway'}); - } - } - if (!$id_category) - $id_category = Configuration::get('PS_ROOT_CATEGORY'); - $this->tpl_list_vars['is_category_filter'] = (bool)$this->id_current_category; - - // Generate category selection tree - $tree = new HelperTreeCategories('categories-tree', $this->l('Filter by category')); - $tree->setAttribute('is_category_filter', (bool)$this->id_current_category) - ->setAttribute('base_url', preg_replace('#&id_category=[0-9]*#', '', self::$currentIndex).'&token='.$this->token) - ->setInputName('id-category') - ->setRootCategory(Configuration::get('PS_ROOT_CATEGORY')) - ->setSelectedCategories(array((int)$id_category)); - $this->tpl_list_vars['category_tree'] = $tree->render(); - - // used to build the new url when changing category - $this->tpl_list_vars['base_url'] = preg_replace('#&id_category=[0-9]*#', '', self::$currentIndex).'&token='.$this->token; - } - // @todo module free - $this->tpl_form_vars['vat_number'] = file_exists(_PS_MODULE_DIR_.'vatnumber/ajax.php'); - - parent::initContent(); - } - - public function renderKpis() - { - $time = time(); - $kpis = array(); - - /* The data generation is located in AdminStatsControllerCore */ - - if (Configuration::get('PS_STOCK_MANAGEMENT')) - { - $helper = new HelperKpi(); - $helper->id = 'box-products-stock'; - $helper->icon = 'icon-archive'; - $helper->color = 'color1'; - $helper->title = $this->l('Out of stock items', null, null, false); - if (ConfigurationKPI::get('PERCENT_PRODUCT_OUT_OF_STOCK') !== false) - $helper->value = ConfigurationKPI::get('PERCENT_PRODUCT_OUT_OF_STOCK'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=percent_product_out_of_stock'; - $helper->tooltip = $this->l('X% of your products for sale are out of stock.', null, null, false); - $helper->refresh = (bool)(ConfigurationKPI::get('PERCENT_PRODUCT_OUT_OF_STOCK_EXPIRE') < $time); - $helper->href = Context::getContext()->link->getAdminLink('AdminProducts').'&productFilter_sav!quantity=0&productFilter_active=1&submitFilterproduct=1'; - $kpis[] = $helper->generate(); - } - - $helper = new HelperKpi(); - $helper->id = 'box-avg-gross-margin'; - $helper->icon = 'icon-tags'; - $helper->color = 'color2'; - $helper->title = $this->l('Average Gross Margin', null, null, false); - if (ConfigurationKPI::get('PRODUCT_AVG_GROSS_MARGIN') !== false) - $helper->value = ConfigurationKPI::get('PRODUCT_AVG_GROSS_MARGIN'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=product_avg_gross_margin'; - $helper->tooltip = $this->l('The gross margin is the difference between the retail price and the wholesale price, on all your products for sale.', null, null, false); - $helper->refresh = (bool)(ConfigurationKPI::get('PRODUCT_AVG_GROSS_MARGIN_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-8020-sales-catalog'; - $helper->icon = 'icon-beaker'; - $helper->color = 'color3'; - $helper->title = $this->l('Purchased references', null, null, false); - $helper->subtitle = $this->l('30 days', null, null, false); - if (ConfigurationKPI::get('8020_SALES_CATALOG') !== false) - $helper->value = ConfigurationKPI::get('8020_SALES_CATALOG'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=8020_sales_catalog'; - $helper->tooltip = $this->l('X% of your references have been purchased for the past 30 days', null, null, false); - $helper->refresh = (bool)(ConfigurationKPI::get('8020_SALES_CATALOG_EXPIRE') < $time); - if (Module::isInstalled('statsbestproducts')) - $helper->href = Context::getContext()->link->getAdminLink('AdminStats').'&module=statsbestproducts&datepickerFrom='.date('Y-m-d', strtotime('-30 days')).'&datepickerTo='.date('Y-m-d'); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-disabled-products'; - $helper->icon = 'icon-off'; - $helper->color = 'color4'; - $helper->href = $this->context->link->getAdminLink('AdminProducts'); - $helper->title = $this->l('Disabled Products', null, null, false); - if (ConfigurationKPI::get('DISABLED_PRODUCTS') !== false) - $helper->value = ConfigurationKPI::get('DISABLED_PRODUCTS'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=disabled_products'; - $helper->refresh = (bool)(ConfigurationKPI::get('DISABLED_PRODUCTS_EXPIRE') < $time); - $helper->tooltip = $this->l('X% of your products are disabled and not visible to your customers', null, null, false); - $helper->href = Context::getContext()->link->getAdminLink('AdminProducts').'&productFilter_active=0&submitFilterproduct=1'; - $kpis[] = $helper->generate(); - - $helper = new HelperKpiRow(); - $helper->kpis = $kpis; - return $helper->generate(); - } - - public function renderList() - { - $this->addRowAction('edit'); - $this->addRowAction('preview'); - $this->addRowAction('duplicate'); - $this->addRowAction('delete'); - return parent::renderList(); - } - - public function ajaxProcessProductManufacturers() - { - $manufacturers = Manufacturer::getManufacturers(false, 0, true, false, false, false, true); - $jsonArray = array(); - - if ($manufacturers) - foreach ($manufacturers as $manufacturer) - { - $tmp = array("optionValue" => $manufacturer['id_manufacturer'], "optionDisplay" => htmlspecialchars(trim($manufacturer['name']))); - $jsonArray[] = Tools::jsonEncode($tmp); - } - - die('['.implode(',', $jsonArray).']'); - } - - /** - * Build a categories tree - * - * @param $id_obj - * @param array $indexedCategories Array with categories where product is indexed (in order to check checkbox) - * @param array $categories Categories to list - * @param $current - * @param null $id_category Current category ID - * @param null $id_category_default - * @param array $has_suite - * - * @return string - */ - public static function recurseCategoryForInclude($id_obj, $indexedCategories, $categories, $current, $id_category = null, $id_category_default = null, $has_suite = array()) - { - global $done; - static $irow; - $content = ''; - - if (!$id_category) - $id_category = (int)Configuration::get('PS_ROOT_CATEGORY'); - - if (!isset($done[$current['infos']['id_parent']])) - $done[$current['infos']['id_parent']] = 0; - $done[$current['infos']['id_parent']] += 1; - - $todo = count($categories[$current['infos']['id_parent']]); - $doneC = $done[$current['infos']['id_parent']]; - - $level = $current['infos']['level_depth'] + 1; - - $content .= ' + } + + if (file_exists(_PS_TMP_IMG_DIR_.'product_'.$image->id_product.'.jpg')) { + $res &= @unlink(_PS_TMP_IMG_DIR_.'product_'.$image->id_product.'.jpg'); + } + if (file_exists(_PS_TMP_IMG_DIR_.'product_mini_'.$image->id_product.'_'.$this->context->shop->id.'.jpg')) { + $res &= @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.$image->id_product.'_'.$this->context->shop->id.'.jpg'); + } + + if ($res) { + $this->jsonConfirmation($this->_conf[7]); + } else { + $this->jsonError(Tools::displayError('An error occurred while attempting to delete the product image.')); + } + } + + protected function _validateSpecificPrice($id_shop, $id_currency, $id_country, $id_group, $id_customer, $price, $from_quantity, $reduction, $reduction_type, $from, $to, $id_combination = 0) + { + if (!Validate::isUnsignedId($id_shop) || !Validate::isUnsignedId($id_currency) || !Validate::isUnsignedId($id_country) || !Validate::isUnsignedId($id_group) || !Validate::isUnsignedId($id_customer)) { + $this->errors[] = Tools::displayError('Wrong IDs'); + } elseif ((!isset($price) && !isset($reduction)) || (isset($price) && !Validate::isNegativePrice($price)) || (isset($reduction) && !Validate::isPrice($reduction))) { + $this->errors[] = Tools::displayError('Invalid price/discount amount'); + } elseif (!Validate::isUnsignedInt($from_quantity)) { + $this->errors[] = Tools::displayError('Invalid quantity'); + } elseif ($reduction && !Validate::isReductionType($reduction_type)) { + $this->errors[] = Tools::displayError('Please select a discount type (amount or percentage).'); + } elseif ($from && $to && (!Validate::isDateFormat($from) || !Validate::isDateFormat($to))) { + $this->errors[] = Tools::displayError('The from/to date is invalid.'); + } elseif (SpecificPrice::exists((int)$this->object->id, $id_combination, $id_shop, $id_group, $id_country, $id_currency, $id_customer, $from_quantity, $from, $to, false)) { + $this->errors[] = Tools::displayError('A specific price already exists for these parameters.'); + } else { + return true; + } + return false; + } + + /* Checking customs feature */ + protected function checkFeatures($languages, $feature_id) + { + $rules = call_user_func(array('FeatureValue', 'getValidationRules'), 'FeatureValue'); + $feature = Feature::getFeature((int)Configuration::get('PS_LANG_DEFAULT'), $feature_id); + + foreach ($languages as $language) { + if ($val = Tools::getValue('custom_'.$feature_id.'_'.$language['id_lang'])) { + $current_language = new Language($language['id_lang']); + if (Tools::strlen($val) > $rules['sizeLang']['value']) { + $this->errors[] = sprintf( + Tools::displayError('The name for feature %1$s is too long in %2$s.'), + ' <b>'.$feature['name'].'</b>', + $current_language->name + ); + } elseif (!call_user_func(array('Validate', $rules['validateLang']['value']), $val)) { + $this->errors[] = sprintf( + Tools::displayError('A valid name required for feature. %1$s in %2$s.'), + ' <b>'.$feature['name'].'</b>', + $current_language->name + ); + } + if (count($this->errors)) { + return 0; + } + // Getting default language + if ($language['id_lang'] == Configuration::get('PS_LANG_DEFAULT')) { + return $val; + } + } + } + return 0; + } + + /** + * Add or update a product image + * + * @param Product $product Product object to add image + * @param string $method + * + * @return int|false + */ + public function addProductImage($product, $method = 'auto') + { + /* Updating an existing product image */ + if ($id_image = (int)Tools::getValue('id_image')) { + $image = new Image((int)$id_image); + if (!Validate::isLoadedObject($image)) { + $this->errors[] = Tools::displayError('An error occurred while loading the object image.'); + } else { + if (($cover = Tools::getValue('cover')) == 1) { + Image::deleteCover($product->id); + } + $image->cover = $cover; + $this->validateRules('Image'); + $this->copyFromPost($image, 'image'); + if (count($this->errors) || !$image->update()) { + $this->errors[] = Tools::displayError('An error occurred while updating the image.'); + } elseif (isset($_FILES['image_product']['tmp_name']) && $_FILES['image_product']['tmp_name'] != null) { + $this->copyImage($product->id, $image->id, $method); + } + } + } + if (isset($image) && Validate::isLoadedObject($image) && !file_exists(_PS_PROD_IMG_DIR_.$image->getExistingImgPath().'.'.$image->image_format)) { + $image->delete(); + } + if (count($this->errors)) { + return false; + } + @unlink(_PS_TMP_IMG_DIR_.'product_'.$product->id.'.jpg'); + @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.$product->id.'_'.$this->context->shop->id.'.jpg'); + return ((isset($id_image) && is_int($id_image) && $id_image) ? $id_image : false); + } + + /** + * Copy a product image + * + * @param int $id_product Product Id for product image filename + * @param int $id_image Image Id for product image filename + * @param string $method + * + * @return void|false + * @throws PrestaShopException + */ + public function copyImage($id_product, $id_image, $method = 'auto') + { + if (!isset($_FILES['image_product']['tmp_name'])) { + return false; + } + if ($error = ImageManager::validateUpload($_FILES['image_product'])) { + $this->errors[] = $error; + } else { + $image = new Image($id_image); + + if (!$new_path = $image->getPathForCreation()) { + $this->errors[] = Tools::displayError('An error occurred while attempting to create a new folder.'); + } + if (!($tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES['image_product']['tmp_name'], $tmpName)) { + $this->errors[] = Tools::displayError('An error occurred during the image upload process.'); + } elseif (!ImageManager::resize($tmpName, $new_path.'.'.$image->image_format)) { + $this->errors[] = Tools::displayError('An error occurred while copying the image.'); + } elseif ($method == 'auto') { + $imagesTypes = ImageType::getImagesTypes('products'); + foreach ($imagesTypes as $k => $image_type) { + if (!ImageManager::resize($tmpName, $new_path.'-'.stripslashes($image_type['name']).'.'.$image->image_format, $image_type['width'], $image_type['height'], $image->image_format)) { + $this->errors[] = Tools::displayError('An error occurred while copying this image:').' '.stripslashes($image_type['name']); + } + } + } + + @unlink($tmpName); + Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_product)); + } + } + + protected function updateAssoShop($id_object) + { + //override AdminController::updateAssoShop() specifically for products because shop association is set with the context in ObjectModel + return; + } + + public function processAdd() + { + $this->checkProduct(); + + if (!empty($this->errors)) { + $this->display = 'add'; + return false; + } + + $this->object = new $this->className(); + $this->_removeTaxFromEcotax(); + $this->copyFromPost($this->object, $this->table); + if ($this->object->add()) { + PrestaShopLogger::addLog(sprintf($this->l('%s addition', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); + $this->addCarriers($this->object); + $this->updateAccessories($this->object); + $this->updatePackItems($this->object); + $this->updateDownloadProduct($this->object); + + if (Configuration::get('PS_FORCE_ASM_NEW_PRODUCT') && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $this->object->getType() != Product::PTYPE_VIRTUAL) { + $this->object->advanced_stock_management = 1; + $this->object->save(); + $id_shops = Shop::getContextListShopID(); + foreach ($id_shops as $id_shop) { + StockAvailable::setProductDependsOnStock($this->object->id, true, (int)$id_shop, 0); + } + } + + if (empty($this->errors)) { + $languages = Language::getLanguages(false); + if ($this->isProductFieldUpdated('category_box') && !$this->object->updateCategories(Tools::getValue('categoryBox'))) { + $this->errors[] = Tools::displayError('An error occurred while linking the object.').' <b>'.$this->table.'</b> '.Tools::displayError('To categories'); + } elseif (!$this->updateTags($languages, $this->object)) { + $this->errors[] = Tools::displayError('An error occurred while adding tags.'); + } else { + Hook::exec('actionProductAdd', array('id_product' => (int)$this->object->id, 'product' => $this->object)); + if (in_array($this->object->visibility, array('both', 'search')) && Configuration::get('PS_SEARCH_INDEXATION')) { + Search::indexation(false, $this->object->id); + } + } + + if (Configuration::get('PS_DEFAULT_WAREHOUSE_NEW_PRODUCT') != 0 && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $warehouse_location_entity = new WarehouseProductLocation(); + $warehouse_location_entity->id_product = $this->object->id; + $warehouse_location_entity->id_product_attribute = 0; + $warehouse_location_entity->id_warehouse = Configuration::get('PS_DEFAULT_WAREHOUSE_NEW_PRODUCT'); + $warehouse_location_entity->location = pSQL(''); + $warehouse_location_entity->save(); + } + + // Apply groups reductions + $this->object->setGroupReduction(); + + // Save and preview + if (Tools::isSubmit('submitAddProductAndPreview')) { + $this->redirect_after = $this->getPreviewUrl($this->object); + } + + // Save and stay on same form + if ($this->display == 'edit') { + $this->redirect_after = self::$currentIndex.'&id_product='.(int)$this->object->id + .(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '') + .'&updateproduct&conf=3&key_tab='.Tools::safeOutput(Tools::getValue('key_tab')).'&token='.$this->token; + } else { + // Default behavior (save and back) + $this->redirect_after = self::$currentIndex + .(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '') + .'&conf=3&token='.$this->token; + } + } else { + $this->object->delete(); + // if errors : stay on edit page + $this->display = 'edit'; + } + } else { + $this->errors[] = Tools::displayError('An error occurred while creating an object.').' <b>'.$this->table.'</b>'; + } + + return $this->object; + } + + protected function isTabSubmitted($tab_name) + { + if (!is_array($this->submitted_tabs)) { + $this->submitted_tabs = Tools::getValue('submitted_tabs'); + } + + if (is_array($this->submitted_tabs) && in_array($tab_name, $this->submitted_tabs)) { + return true; + } + + return false; + } + + public function processStatus() + { + $this->loadObject(true); + if (!Validate::isLoadedObject($this->object)) { + return false; + } + if (($error = $this->object->validateFields(false, true)) !== true) { + $this->errors[] = $error; + } + if (($error = $this->object->validateFieldsLang(false, true)) !== true) { + $this->errors[] = $error; + } + + if (count($this->errors)) { + return false; + } + + $res = parent::processStatus(); + + $query = trim(Tools::getValue('bo_query')); + $searchType = (int)Tools::getValue('bo_search_type'); + + if ($query) { + $this->redirect_after = preg_replace('/[\?|&](bo_query|bo_search_type)=([^&]*)/i', '', $this->redirect_after); + $this->redirect_after .= '&bo_query='.$query.'&bo_search_type='.$searchType; + } + + return $res; + } + + public function processUpdate() + { + $existing_product = $this->object; + + $this->checkProduct(); + + if (!empty($this->errors)) { + $this->display = 'edit'; + return false; + } + + $id = (int)Tools::getValue('id_'.$this->table); + /* Update an existing product */ + if (isset($id) && !empty($id)) { + /** @var Product $object */ + $object = new $this->className((int)$id); + $this->object = $object; + + if (Validate::isLoadedObject($object)) { + $this->_removeTaxFromEcotax(); + $product_type_before = $object->getType(); + $this->copyFromPost($object, $this->table); + $object->indexed = 0; + + if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) { + $object->setFieldsToUpdate((array)Tools::getValue('multishop_check', array())); + } + + // Duplicate combinations if not associated to shop + if ($this->context->shop->getContext() == Shop::CONTEXT_SHOP && !$object->isAssociatedToShop()) { + $is_associated_to_shop = false; + $combinations = Product::getProductAttributesIds($object->id); + if ($combinations) { + foreach ($combinations as $id_combination) { + $combination = new Combination((int)$id_combination['id_product_attribute']); + $default_combination = new Combination((int)$id_combination['id_product_attribute'], null, (int)$this->object->id_shop_default); + + $def = ObjectModel::getDefinition($default_combination); + foreach ($def['fields'] as $field_name => $row) { + $combination->$field_name = ObjectModel::formatValue($default_combination->$field_name, $def['fields'][$field_name]['type']); + } + + $combination->save(); + } + } + } else { + $is_associated_to_shop = true; + } + + if ($object->update()) { + // If the product doesn't exist in the current shop but exists in another shop + if (Shop::getContext() == Shop::CONTEXT_SHOP && !$existing_product->isAssociatedToShop($this->context->shop->id)) { + $out_of_stock = StockAvailable::outOfStock($existing_product->id, $existing_product->id_shop_default); + $depends_on_stock = StockAvailable::dependsOnStock($existing_product->id, $existing_product->id_shop_default); + StockAvailable::setProductOutOfStock((int)$this->object->id, $out_of_stock, $this->context->shop->id); + StockAvailable::setProductDependsOnStock((int)$this->object->id, $depends_on_stock, $this->context->shop->id); + } + + PrestaShopLogger::addLog(sprintf($this->l('%s modification', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); + if (in_array($this->context->shop->getContext(), array(Shop::CONTEXT_SHOP, Shop::CONTEXT_ALL))) { + if ($this->isTabSubmitted('Shipping')) { + $this->addCarriers(); + } + if ($this->isTabSubmitted('Associations')) { + $this->updateAccessories($object); + } + if ($this->isTabSubmitted('Suppliers')) { + $this->processSuppliers(); + } + if ($this->isTabSubmitted('Features')) { + $this->processFeatures(); + } + if ($this->isTabSubmitted('Combinations')) { + $this->processProductAttribute(); + } + if ($this->isTabSubmitted('Prices')) { + $this->processPriceAddition(); + $this->processSpecificPricePriorities(); + } + if ($this->isTabSubmitted('Customization')) { + $this->processCustomizationConfiguration(); + } + if ($this->isTabSubmitted('Attachments')) { + $this->processAttachments(); + } + if ($this->isTabSubmitted('Images')) { + $this->processImageLegends(); + } + + $this->updatePackItems($object); + // Disallow avanced stock management if the product become a pack + if ($product_type_before == Product::PTYPE_SIMPLE && $object->getType() == Product::PTYPE_PACK) { + StockAvailable::setProductDependsOnStock((int)$object->id, false); + } + $this->updateDownloadProduct($object, 1); + $this->updateTags(Language::getLanguages(false), $object); + + if ($this->isProductFieldUpdated('category_box') && !$object->updateCategories(Tools::getValue('categoryBox'))) { + $this->errors[] = Tools::displayError('An error occurred while linking the object.').' <b>'.$this->table.'</b> '.Tools::displayError('To categories'); + } + } + + if ($this->isTabSubmitted('Warehouses')) { + $this->processWarehouses(); + } + if (empty($this->errors)) { + if (in_array($object->visibility, array('both', 'search')) && Configuration::get('PS_SEARCH_INDEXATION')) { + Search::indexation(false, $object->id); + } + + // Save and preview + if (Tools::isSubmit('submitAddProductAndPreview')) { + $this->redirect_after = $this->getPreviewUrl($object); + } else { + $page = (int)Tools::getValue('page'); + // Save and stay on same form + if ($this->display == 'edit') { + $this->confirmations[] = $this->l('Update successful'); + $this->redirect_after = self::$currentIndex.'&id_product='.(int)$this->object->id + .(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '') + .'&updateproduct&conf=4&key_tab='.Tools::safeOutput(Tools::getValue('key_tab')).($page > 1 ? '&page='.(int)$page : '').'&token='.$this->token; + } else { + // Default behavior (save and back) + $this->redirect_after = self::$currentIndex.(Tools::getIsset('id_category') ? '&id_category='.(int)Tools::getValue('id_category') : '').'&conf=4'.($page > 1 ? '&submitFilterproduct='.(int)$page : '').'&token='.$this->token; + } + } + } + // if errors : stay on edit page + else { + $this->display = 'edit'; + } + } else { + if (!$is_associated_to_shop && $combinations) { + foreach ($combinations as $id_combination) { + $combination = new Combination((int)$id_combination['id_product_attribute']); + $combination->delete(); + } + } + $this->errors[] = Tools::displayError('An error occurred while updating an object.').' <b>'.$this->table.'</b> ('.Db::getInstance()->getMsgError().')'; + } + } else { + $this->errors[] = Tools::displayError('An error occurred while updating an object.').' <b>'.$this->table.'</b> ('.Tools::displayError('The object cannot be loaded. ').')'; + } + return $object; + } + } + + /** + * Check that a saved product is valid + */ + public function checkProduct() + { + $className = 'Product'; + // @todo : the call_user_func seems to contains only statics values (className = 'Product') + $rules = call_user_func(array($this->className, 'getValidationRules'), $this->className); + $default_language = new Language((int)Configuration::get('PS_LANG_DEFAULT')); + $languages = Language::getLanguages(false); + + // Check required fields + foreach ($rules['required'] as $field) { + if (!$this->isProductFieldUpdated($field)) { + continue; + } + + if (($value = Tools::getValue($field)) == false && $value != '0') { + if (Tools::getValue('id_'.$this->table) && $field == 'passwd') { + continue; + } + $this->errors[] = sprintf( + Tools::displayError('The %s field is required.'), + call_user_func(array($className, 'displayFieldName'), $field, $className) + ); + } + } + + // Check multilingual required fields + foreach ($rules['requiredLang'] as $fieldLang) { + if ($this->isProductFieldUpdated($fieldLang, $default_language->id) && !Tools::getValue($fieldLang.'_'.$default_language->id)) { + $this->errors[] = sprintf( + Tools::displayError('This %1$s field is required at least in %2$s'), + call_user_func(array($className, 'displayFieldName'), $fieldLang, $className), + $default_language->name + ); + } + } + + // Check fields sizes + foreach ($rules['size'] as $field => $maxLength) { + if ($this->isProductFieldUpdated($field) && ($value = Tools::getValue($field)) && Tools::strlen($value) > $maxLength) { + $this->errors[] = sprintf( + Tools::displayError('The %1$s field is too long (%2$d chars max).'), + call_user_func(array($className, 'displayFieldName'), $field, $className), + $maxLength + ); + } + } + + if (Tools::getIsset('description_short') && $this->isProductFieldUpdated('description_short')) { + $saveShort = Tools::getValue('description_short'); + $_POST['description_short'] = strip_tags(Tools::getValue('description_short')); + } + + // Check description short size without html + $limit = (int)Configuration::get('PS_PRODUCT_SHORT_DESC_LIMIT'); + if ($limit <= 0) { + $limit = 400; + } + foreach ($languages as $language) { + if ($this->isProductFieldUpdated('description_short', $language['id_lang']) && ($value = Tools::getValue('description_short_'.$language['id_lang']))) { + if (Tools::strlen(strip_tags($value)) > $limit) { + $this->errors[] = sprintf( + Tools::displayError('This %1$s field (%2$s) is too long: %3$d chars max (current count %4$d).'), + call_user_func(array($className, 'displayFieldName'), 'description_short'), + $language['name'], + $limit, + Tools::strlen(strip_tags($value)) + ); + } + } + } + + // Check multilingual fields sizes + foreach ($rules['sizeLang'] as $fieldLang => $maxLength) { + foreach ($languages as $language) { + $value = Tools::getValue($fieldLang.'_'.$language['id_lang']); + if ($value && Tools::strlen($value) > $maxLength) { + $this->errors[] = sprintf( + Tools::displayError('The %1$s field is too long (%2$d chars max).'), + call_user_func(array($className, 'displayFieldName'), $fieldLang, $className), + $maxLength + ); + } + } + } + + if ($this->isProductFieldUpdated('description_short') && isset($_POST['description_short'])) { + $_POST['description_short'] = $saveShort; + } + + // Check fields validity + foreach ($rules['validate'] as $field => $function) { + if ($this->isProductFieldUpdated($field) && ($value = Tools::getValue($field))) { + $res = true; + if (Tools::strtolower($function) == 'iscleanhtml') { + if (!Validate::$function($value, (int)Configuration::get('PS_ALLOW_HTML_IFRAME'))) { + $res = false; + } + } elseif (!Validate::$function($value)) { + $res = false; + } + + if (!$res) { + $this->errors[] = sprintf( + Tools::displayError('The %s field is invalid.'), + call_user_func(array($className, 'displayFieldName'), $field, $className) + ); + } + } + } + // Check multilingual fields validity + foreach ($rules['validateLang'] as $fieldLang => $function) { + foreach ($languages as $language) { + if ($this->isProductFieldUpdated($fieldLang, $language['id_lang']) && ($value = Tools::getValue($fieldLang.'_'.$language['id_lang']))) { + if (!Validate::$function($value, (int)Configuration::get('PS_ALLOW_HTML_IFRAME'))) { + $this->errors[] = sprintf( + Tools::displayError('The %1$s field (%2$s) is invalid.'), + call_user_func(array($className, 'displayFieldName'), $fieldLang, $className), + $language['name'] + ); + } + } + } + } + + // Categories + if ($this->isProductFieldUpdated('id_category_default') && (!Tools::isSubmit('categoryBox') || !count(Tools::getValue('categoryBox')))) { + $this->errors[] = $this->l('Products must be in at least one category.'); + } + + if ($this->isProductFieldUpdated('id_category_default') && (!is_array(Tools::getValue('categoryBox')) || !in_array(Tools::getValue('id_category_default'), Tools::getValue('categoryBox')))) { + $this->errors[] = $this->l('This product must be in the default category.'); + } + + // Tags + foreach ($languages as $language) { + if ($value = Tools::getValue('tags_'.$language['id_lang'])) { + if (!Validate::isTagsList($value)) { + $this->errors[] = sprintf( + Tools::displayError('The tags list (%s) is invalid.'), + $language['name'] + ); + } + } + } + } + + /** + * Check if a field is edited (if the checkbox is checked) + * This method will do something only for multishop with a context all / group + * + * @param string $field Name of field + * @param int $id_lang + * @return bool + */ + protected function isProductFieldUpdated($field, $id_lang = null) + { + // Cache this condition to improve performances + static $is_activated = null; + if (is_null($is_activated)) { + $is_activated = Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP && $this->id_object; + } + + if (!$is_activated) { + return true; + } + + if (is_null($id_lang)) { + return !empty($_POST['multishop_check'][$field]); + } else { + return !empty($_POST['multishop_check'][$field][$id_lang]); + } + } + + protected function _removeTaxFromEcotax() + { + if ($ecotax = Tools::getValue('ecotax')) { + $_POST['ecotax'] = Tools::ps_round($ecotax / (1 + Tax::getProductEcotaxRate() / 100), 6); + } + } + + protected function _applyTaxToEcotax($product) + { + if ($product->ecotax) { + $product->ecotax = Tools::ps_round($product->ecotax * (1 + Tax::getProductEcotaxRate() / 100), 2); + } + } + + /** + * Update product download + * + * @param Product $product + * @param int $edit + * + * @return bool + */ + public function updateDownloadProduct($product, $edit = 0) + { + if ((int)Tools::getValue('is_virtual_file') == 1) { + if (isset($_FILES['virtual_product_file_uploader']) && $_FILES['virtual_product_file_uploader']['size'] > 0) { + $virtual_product_filename = ProductDownload::getNewFilename(); + $helper = new HelperUploader('virtual_product_file_uploader'); + $helper->setPostMaxSize(Tools::getOctets(ini_get('upload_max_filesize'))) + ->setSavePath(_PS_DOWNLOAD_DIR_)->upload($_FILES['virtual_product_file_uploader'], $virtual_product_filename); + } else { + $virtual_product_filename = Tools::getValue('virtual_product_filename', ProductDownload::getNewFilename()); + } + + $product->setDefaultAttribute(0);//reset cache_default_attribute + if (Tools::getValue('virtual_product_expiration_date') && !Validate::isDate(Tools::getValue('virtual_product_expiration_date'))) { + if (!Tools::getValue('virtual_product_expiration_date')) { + $this->errors[] = Tools::displayError('The expiration-date attribute is required.'); + return false; + } + } + + // Trick's + if ($edit == 1) { + $id_product_download = (int)ProductDownload::getIdFromIdProduct((int)$product->id); + if (!$id_product_download) { + $id_product_download = (int)Tools::getValue('virtual_product_id'); + } + } else { + $id_product_download = Tools::getValue('virtual_product_id'); + } + + $is_shareable = Tools::getValue('virtual_product_is_shareable'); + $virtual_product_name = Tools::getValue('virtual_product_name'); + $virtual_product_nb_days = Tools::getValue('virtual_product_nb_days'); + $virtual_product_nb_downloable = Tools::getValue('virtual_product_nb_downloable'); + $virtual_product_expiration_date = Tools::getValue('virtual_product_expiration_date'); + + $download = new ProductDownload((int)$id_product_download); + $download->id_product = (int)$product->id; + $download->display_filename = $virtual_product_name; + $download->filename = $virtual_product_filename; + $download->date_add = date('Y-m-d H:i:s'); + $download->date_expiration = $virtual_product_expiration_date ? $virtual_product_expiration_date.' 23:59:59' : ''; + $download->nb_days_accessible = (int)$virtual_product_nb_days; + $download->nb_downloadable = (int)$virtual_product_nb_downloable; + $download->active = 1; + $download->is_shareable = (int)$is_shareable; + + if ($download->save()) { + return true; + } + } else { + /* unactive download product if checkbox not checked */ + if ($edit == 1) { + $id_product_download = (int)ProductDownload::getIdFromIdProduct((int)$product->id); + if (!$id_product_download) { + $id_product_download = (int)Tools::getValue('virtual_product_id'); + } + } else { + $id_product_download = ProductDownload::getIdFromIdProduct($product->id); + } + + if (!empty($id_product_download)) { + $product_download = new ProductDownload((int)$id_product_download); + $product_download->date_expiration = date('Y-m-d H:i:s', time() - 1); + $product_download->active = 0; + return $product_download->save(); + } + } + return false; + } + + /** + * Update product accessories + * + * @param object $product Product + */ + public function updateAccessories($product) + { + $product->deleteAccessories(); + if ($accessories = Tools::getValue('inputAccessories')) { + $accessories_id = array_unique(explode('-', $accessories)); + if (count($accessories_id)) { + array_pop($accessories_id); + $product->changeAccessories($accessories_id); + } + } + } + + /** + * Update product tags + * + * @param array $languages Array languages + * @param object $product Product + * @return bool Update result + */ + public function updateTags($languages, $product) + { + $tag_success = true; + /* Reset all tags for THIS product */ + if (!Tag::deleteTagsForProduct((int)$product->id)) { + $this->errors[] = Tools::displayError('An error occurred while attempting to delete previous tags.'); + } + /* Assign tags to this product */ + foreach ($languages as $language) { + if ($value = Tools::getValue('tags_'.$language['id_lang'])) { + $tag_success &= Tag::addTags($language['id_lang'], (int)$product->id, $value); + } + } + + if (!$tag_success) { + $this->errors[] = Tools::displayError('An error occurred while adding tags.'); + } + + return $tag_success; + } + + public function initContent($token = null) + { + if ($this->display == 'edit' || $this->display == 'add') { + $this->fields_form = array(); + + // Check if Module + if (substr($this->tab_display, 0, 6) == 'Module') { + $this->tab_display_module = strtolower(substr($this->tab_display, 6, Tools::strlen($this->tab_display) - 6)); + $this->tab_display = 'Modules'; + } + if (method_exists($this, 'initForm'.$this->tab_display)) { + $this->tpl_form = strtolower($this->tab_display).'.tpl'; + } + + if ($this->ajax) { + $this->content_only = true; + } else { + $product_tabs = array(); + + // tab_display defines which tab to display first + if (!method_exists($this, 'initForm'.$this->tab_display)) { + $this->tab_display = $this->default_tab; + } + + $advanced_stock_management_active = Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'); + foreach ($this->available_tabs as $product_tab => $value) { + // if it's the warehouses tab and advanced stock management is disabled, continue + if ($advanced_stock_management_active == 0 && $product_tab == 'Warehouses') { + continue; + } + + $product_tabs[$product_tab] = array( + 'id' => $product_tab, + 'selected' => (strtolower($product_tab) == strtolower($this->tab_display) || (isset($this->tab_display_module) && 'module'.$this->tab_display_module == Tools::strtolower($product_tab))), + 'name' => $this->available_tabs_lang[$product_tab], + 'href' => $this->context->link->getAdminLink('AdminProducts').'&id_product='.(int)Tools::getValue('id_product').'&action='.$product_tab, + ); + } + $this->tpl_form_vars['product_tabs'] = $product_tabs; + } + } else { + if ($id_category = (int)$this->id_current_category) { + self::$currentIndex .= '&id_category='.(int)$this->id_current_category; + } + + // If products from all categories are displayed, we don't want to use sorting by position + if (!$id_category) { + $this->_defaultOrderBy = $this->identifier; + if ($this->context->cookie->{$this->table.'Orderby'} == 'position') { + unset($this->context->cookie->{$this->table.'Orderby'}); + unset($this->context->cookie->{$this->table.'Orderway'}); + } + } + if (!$id_category) { + $id_category = Configuration::get('PS_ROOT_CATEGORY'); + } + $this->tpl_list_vars['is_category_filter'] = (bool)$this->id_current_category; + + // Generate category selection tree + $tree = new HelperTreeCategories('categories-tree', $this->l('Filter by category')); + $tree->setAttribute('is_category_filter', (bool)$this->id_current_category) + ->setAttribute('base_url', preg_replace('#&id_category=[0-9]*#', '', self::$currentIndex).'&token='.$this->token) + ->setInputName('id-category') + ->setRootCategory(Configuration::get('PS_ROOT_CATEGORY')) + ->setSelectedCategories(array((int)$id_category)); + $this->tpl_list_vars['category_tree'] = $tree->render(); + + // used to build the new url when changing category + $this->tpl_list_vars['base_url'] = preg_replace('#&id_category=[0-9]*#', '', self::$currentIndex).'&token='.$this->token; + } + // @todo module free + $this->tpl_form_vars['vat_number'] = file_exists(_PS_MODULE_DIR_.'vatnumber/ajax.php'); + + parent::initContent(); + } + + public function renderKpis() + { + $time = time(); + $kpis = array(); + + /* The data generation is located in AdminStatsControllerCore */ + + if (Configuration::get('PS_STOCK_MANAGEMENT')) { + $helper = new HelperKpi(); + $helper->id = 'box-products-stock'; + $helper->icon = 'icon-archive'; + $helper->color = 'color1'; + $helper->title = $this->l('Out of stock items', null, null, false); + if (ConfigurationKPI::get('PERCENT_PRODUCT_OUT_OF_STOCK') !== false) { + $helper->value = ConfigurationKPI::get('PERCENT_PRODUCT_OUT_OF_STOCK'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=percent_product_out_of_stock'; + $helper->tooltip = $this->l('X% of your products for sale are out of stock.', null, null, false); + $helper->refresh = (bool)(ConfigurationKPI::get('PERCENT_PRODUCT_OUT_OF_STOCK_EXPIRE') < $time); + $helper->href = Context::getContext()->link->getAdminLink('AdminProducts').'&productFilter_sav!quantity=0&productFilter_active=1&submitFilterproduct=1'; + $kpis[] = $helper->generate(); + } + + $helper = new HelperKpi(); + $helper->id = 'box-avg-gross-margin'; + $helper->icon = 'icon-tags'; + $helper->color = 'color2'; + $helper->title = $this->l('Average Gross Margin %', null, null, false); + if (ConfigurationKPI::get('PRODUCT_AVG_GROSS_MARGIN') !== false) { + $helper->value = ConfigurationKPI::get('PRODUCT_AVG_GROSS_MARGIN'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=product_avg_gross_margin'; + $helper->tooltip = $this->l('Gross margin expressed in percentage assesses how cost-effectively you sell your goods. Out of $100, you will retain $X to cover profit and expenses.', null, null, false); + $helper->refresh = (bool)(ConfigurationKPI::get('PRODUCT_AVG_GROSS_MARGIN_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-8020-sales-catalog'; + $helper->icon = 'icon-beaker'; + $helper->color = 'color3'; + $helper->title = $this->l('Purchased references', null, null, false); + $helper->subtitle = $this->l('30 days', null, null, false); + if (ConfigurationKPI::get('8020_SALES_CATALOG') !== false) { + $helper->value = ConfigurationKPI::get('8020_SALES_CATALOG'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=8020_sales_catalog'; + $helper->tooltip = $this->l('X% of your references have been purchased for the past 30 days', null, null, false); + $helper->refresh = (bool)(ConfigurationKPI::get('8020_SALES_CATALOG_EXPIRE') < $time); + if (Module::isInstalled('statsbestproducts')) { + $helper->href = Context::getContext()->link->getAdminLink('AdminStats').'&module=statsbestproducts&datepickerFrom='.date('Y-m-d', strtotime('-30 days')).'&datepickerTo='.date('Y-m-d'); + } + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-disabled-products'; + $helper->icon = 'icon-off'; + $helper->color = 'color4'; + $helper->href = $this->context->link->getAdminLink('AdminProducts'); + $helper->title = $this->l('Disabled Products', null, null, false); + if (ConfigurationKPI::get('DISABLED_PRODUCTS') !== false) { + $helper->value = ConfigurationKPI::get('DISABLED_PRODUCTS'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=disabled_products'; + $helper->refresh = (bool)(ConfigurationKPI::get('DISABLED_PRODUCTS_EXPIRE') < $time); + $helper->tooltip = $this->l('X% of your products are disabled and not visible to your customers', null, null, false); + $helper->href = Context::getContext()->link->getAdminLink('AdminProducts').'&productFilter_active=0&submitFilterproduct=1'; + $kpis[] = $helper->generate(); + + $helper = new HelperKpiRow(); + $helper->kpis = $kpis; + return $helper->generate(); + } + + public function renderList() + { + $this->addRowAction('edit'); + $this->addRowAction('preview'); + $this->addRowAction('duplicate'); + $this->addRowAction('delete'); + return parent::renderList(); + } + + public function ajaxProcessProductManufacturers() + { + $manufacturers = Manufacturer::getManufacturers(false, 0, true, false, false, false, true); + $jsonArray = array(); + + if ($manufacturers) { + foreach ($manufacturers as $manufacturer) { + $tmp = array("optionValue" => $manufacturer['id_manufacturer'], "optionDisplay" => htmlspecialchars(trim($manufacturer['name']))); + $jsonArray[] = Tools::jsonEncode($tmp); + } + } + + die('['.implode(',', $jsonArray).']'); + } + + /** + * Build a categories tree + * + * @param $id_obj + * @param array $indexedCategories Array with categories where product is indexed (in order to check checkbox) + * @param array $categories Categories to list + * @param $current + * @param null $id_category Current category ID + * @param null $id_category_default + * @param array $has_suite + * + * @return string + */ + public static function recurseCategoryForInclude($id_obj, $indexedCategories, $categories, $current, $id_category = null, $id_category_default = null, $has_suite = array()) + { + global $done; + static $irow; + $content = ''; + + if (!$id_category) { + $id_category = (int)Configuration::get('PS_ROOT_CATEGORY'); + } + + if (!isset($done[$current['infos']['id_parent']])) { + $done[$current['infos']['id_parent']] = 0; + } + $done[$current['infos']['id_parent']] += 1; + + $todo = count($categories[$current['infos']['id_parent']]); + $doneC = $done[$current['infos']['id_parent']]; + + $level = $current['infos']['level_depth'] + 1; + + $content .= ' <tr class="'.($irow++ % 2 ? 'alt_row' : '').'"> <td> <input type="checkbox" name="categoryBox[]" class="categoryBox'.($id_category_default == $id_category ? ' id_category_default' : '').'" id="categoryBox_'.$id_category.'" value="'.$id_category.'"'.((in_array($id_category, $indexedCategories) || ((int)(Tools::getValue('id_category')) == $id_category && !(int)($id_obj))) ? ' checked="checked"' : '').' /> @@ -2608,1014 +2656,1001 @@ class AdminProductsControllerCore extends AdminController '.$id_category.' </td> <td>'; - for ($i = 2; $i < $level; $i++) - $content .= '<img src="../img/admin/lvl_'.$has_suite[$i - 2].'.gif" alt="" />'; - $content .= '<img src="../img/admin/'.($level == 1 ? 'lv1.gif' : 'lv2_'.($todo == $doneC ? 'f' : 'b').'.gif').'" alt="" />   + for ($i = 2; $i < $level; $i++) { + $content .= '<img src="../img/admin/lvl_'.$has_suite[$i - 2].'.gif" alt="" />'; + } + $content .= '<img src="../img/admin/'.($level == 1 ? 'lv1.gif' : 'lv2_'.($todo == $doneC ? 'f' : 'b').'.gif').'" alt="" />   <label for="categoryBox_'.$id_category.'" class="t">'.stripslashes($current['infos']['name']).'</label></td> </tr>'; - if ($level > 1) - $has_suite[] = ($todo == $doneC ? 0 : 1); - if (isset($categories[$id_category])) - foreach ($categories[$id_category] as $key => $row) - if ($key != 'infos') - $content .= AdminProductsController::recurseCategoryForInclude($id_obj, $indexedCategories, $categories, $categories[$id_category][$key], $key, $id_category_default, $has_suite); - return $content; - } + if ($level > 1) { + $has_suite[] = ($todo == $doneC ? 0 : 1); + } + if (isset($categories[$id_category])) { + foreach ($categories[$id_category] as $key => $row) { + if ($key != 'infos') { + $content .= AdminProductsController::recurseCategoryForInclude($id_obj, $indexedCategories, $categories, $categories[$id_category][$key], $key, $id_category_default, $has_suite); + } + } + } + return $content; + } - protected function _displayDraftWarning($active) - { - $content = '<div class="warn draft" style="'.($active ? 'display:none' : '').'"> + protected function _displayDraftWarning($active) + { + $content = '<div class="warn draft" style="'.($active ? 'display:none' : '').'"> <span>'.$this->l('Your product will be saved as a draft.').'</span> <a href="#" class="btn btn-default pull-right" onclick="submitAddProductAndPreview()" ><i class="icon-external-link-sign"></i> '.$this->l('Save and preview').'</a> <input type="hidden" name="fakeSubmitAddProductAndPreview" id="fakeSubmitAddProductAndPreview" /> </div>'; - $this->tpl_form_vars['draft_warning'] = $content; - } + $this->tpl_form_vars['draft_warning'] = $content; + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_product'] = array( - 'href' => self::$currentIndex.'&addproduct&token='.$this->token, - 'desc' => $this->l('Add new product', null, null, false), - 'icon' => 'process-icon-new' - ); - if ($this->display == 'edit') - { - if (($product = $this->loadObject(true)) && $product->isAssociatedToShop()) - { - // adding button for preview this product - if ($url_preview = $this->getPreviewUrl($product)) - $this->page_header_toolbar_btn['preview'] = array( - 'short' => $this->l('Preview', null, null, false), - 'href' => $url_preview, - 'desc' => $this->l('Preview', null, null, false), - 'target' => true, - 'class' => 'previewUrl' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_product'] = array( + 'href' => self::$currentIndex.'&addproduct&token='.$this->token, + 'desc' => $this->l('Add new product', null, null, false), + 'icon' => 'process-icon-new' + ); + } + if ($this->display == 'edit') { + if (($product = $this->loadObject(true)) && $product->isAssociatedToShop()) { + // adding button for preview this product + if ($url_preview = $this->getPreviewUrl($product)) { + $this->page_header_toolbar_btn['preview'] = array( + 'short' => $this->l('Preview', null, null, false), + 'href' => $url_preview, + 'desc' => $this->l('Preview', null, null, false), + 'target' => true, + 'class' => 'previewUrl' + ); + } - $js = (bool)Image::getImages($this->context->language->id, (int)$product->id) ? - 'confirm_link(\'\', \''.$this->l('This will copy the images too. If you wish to proceed, click "Yes". If not, click "No".', null, true, false).'\', \''.$this->l('Yes', null, true, false).'\', \''.$this->l('No', null, true, false).'\', \''.$this->context->link->getAdminLink('AdminProducts', true).'&id_product='.(int)$product->id.'&duplicateproduct'.'\', \''.$this->context->link->getAdminLink('AdminProducts', true).'&id_product='.(int)$product->id.'&duplicateproduct&noimage=1'.'\')' - : - 'document.location = \''.$this->context->link->getAdminLink('AdminProducts', true).'&id_product='.(int)$product->id.'&duplicateproduct&noimage=1'.'\''; + $js = (bool)Image::getImages($this->context->language->id, (int)$product->id) ? + 'confirm_link(\'\', \''.$this->l('This will copy the images too. If you wish to proceed, click "Yes". If not, click "No".', null, true, false).'\', \''.$this->l('Yes', null, true, false).'\', \''.$this->l('No', null, true, false).'\', \''.$this->context->link->getAdminLink('AdminProducts', true).'&id_product='.(int)$product->id.'&duplicateproduct'.'\', \''.$this->context->link->getAdminLink('AdminProducts', true).'&id_product='.(int)$product->id.'&duplicateproduct&noimage=1'.'\')' + : + 'document.location = \''.$this->context->link->getAdminLink('AdminProducts', true).'&id_product='.(int)$product->id.'&duplicateproduct&noimage=1'.'\''; - // adding button for duplicate this product - if ($this->tabAccess['add']) - $this->page_header_toolbar_btn['duplicate'] = array( - 'short' => $this->l('Duplicate', null, null, false), - 'desc' => $this->l('Duplicate', null, null, false), - 'confirm' => 1, - 'js' => $js - ); + // adding button for duplicate this product + if ($this->tabAccess['add']) { + $this->page_header_toolbar_btn['duplicate'] = array( + 'short' => $this->l('Duplicate', null, null, false), + 'desc' => $this->l('Duplicate', null, null, false), + 'confirm' => 1, + 'js' => $js + ); + } - // adding button for preview this product statistics - if (file_exists(_PS_MODULE_DIR_.'statsproduct/statsproduct.php')) - $this->page_header_toolbar_btn['stats'] = array( - 'short' => $this->l('Statistics', null, null, false), - 'href' => $this->context->link->getAdminLink('AdminStats').'&module=statsproduct&id_product='.(int)$product->id, - 'desc' => $this->l('Product sales', null, null, false), - ); + // adding button for preview this product statistics + if (file_exists(_PS_MODULE_DIR_.'statsproduct/statsproduct.php')) { + $this->page_header_toolbar_btn['stats'] = array( + 'short' => $this->l('Statistics', null, null, false), + 'href' => $this->context->link->getAdminLink('AdminStats').'&module=statsproduct&id_product='.(int)$product->id, + 'desc' => $this->l('Product sales', null, null, false), + ); + } - // adding button for delete this product - if ($this->tabAccess['delete']) - $this->page_header_toolbar_btn['delete'] = array( - 'short' => $this->l('Delete', null, null, false), - 'href' => $this->context->link->getAdminLink('AdminProducts').'&id_product='.(int)$product->id.'&deleteproduct', - 'desc' => $this->l('Delete this product', null, null, false), - 'confirm' => 1, - 'js' => 'if (confirm(\''.$this->l('Delete product?', null, true, false).'\')){return true;}else{event.preventDefault();}' - ); - } - } - parent::initPageHeaderToolbar(); - } + // adding button for delete this product + if ($this->tabAccess['delete']) { + $this->page_header_toolbar_btn['delete'] = array( + 'short' => $this->l('Delete', null, null, false), + 'href' => $this->context->link->getAdminLink('AdminProducts').'&id_product='.(int)$product->id.'&deleteproduct', + 'desc' => $this->l('Delete this product', null, null, false), + 'confirm' => 1, + 'js' => 'if (confirm(\''.$this->l('Delete product?', null, true, false).'\')){return true;}else{event.preventDefault();}' + ); + } + } + } + parent::initPageHeaderToolbar(); + } - public function initToolbar() - { - parent::initToolbar(); - if ($this->display == 'edit' || $this->display == 'add') - { - $this->toolbar_btn['save'] = array( - 'short' => 'Save', - 'href' => '#', - 'desc' => $this->l('Save'), - ); + public function initToolbar() + { + parent::initToolbar(); + if ($this->display == 'edit' || $this->display == 'add') { + $this->toolbar_btn['save'] = array( + 'short' => 'Save', + 'href' => '#', + 'desc' => $this->l('Save'), + ); - $this->toolbar_btn['save-and-stay'] = array( - 'short' => 'SaveAndStay', - 'href' => '#', - 'desc' => $this->l('Save and stay'), - ); + $this->toolbar_btn['save-and-stay'] = array( + 'short' => 'SaveAndStay', + 'href' => '#', + 'desc' => $this->l('Save and stay'), + ); - // adding button for adding a new combination in Combination tab - $this->toolbar_btn['newCombination'] = array( - 'short' => 'New combination', - 'desc' => $this->l('New combination'), - 'class' => 'toolbar-new' - ); - } - elseif ($this->can_import) - $this->toolbar_btn['import'] = array( - 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=products', - 'desc' => $this->l('Import') - ); + // adding button for adding a new combination in Combination tab + $this->toolbar_btn['newCombination'] = array( + 'short' => 'New combination', + 'desc' => $this->l('New combination'), + 'class' => 'toolbar-new' + ); + } elseif ($this->can_import) { + $this->toolbar_btn['import'] = array( + 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=products', + 'desc' => $this->l('Import') + ); + } - $this->context->smarty->assign('toolbar_scroll', 1); - $this->context->smarty->assign('show_toolbar', 1); - $this->context->smarty->assign('toolbar_btn', $this->toolbar_btn); - } + $this->context->smarty->assign('toolbar_scroll', 1); + $this->context->smarty->assign('show_toolbar', 1); + $this->context->smarty->assign('toolbar_btn', $this->toolbar_btn); + } - /** - * renderForm contains all necessary initialization needed for all tabs - * - * @return string|void - * @throws PrestaShopException - */ - public function renderForm() - { - // This nice code (irony) is here to store the product name, because the row after will erase product name in multishop context - $this->product_name = $this->object->name[$this->context->language->id]; + /** + * renderForm contains all necessary initialization needed for all tabs + * + * @return string|void + * @throws PrestaShopException + */ + public function renderForm() + { + // This nice code (irony) is here to store the product name, because the row after will erase product name in multishop context + $this->product_name = $this->object->name[$this->context->language->id]; - if (!method_exists($this, 'initForm'.$this->tab_display)) - return; + if (!method_exists($this, 'initForm'.$this->tab_display)) { + return; + } - $product = $this->object; + $product = $this->object; - // Product for multishop - $this->context->smarty->assign('bullet_common_field', ''); - if (Shop::isFeatureActive() && $this->display == 'edit') - { - if (Shop::getContext() != Shop::CONTEXT_SHOP) - { - $this->context->smarty->assign(array( - 'display_multishop_checkboxes' => true, - 'multishop_check' => Tools::getValue('multishop_check'), - )); - } + // Product for multishop + $this->context->smarty->assign('bullet_common_field', ''); + if (Shop::isFeatureActive() && $this->display == 'edit') { + if (Shop::getContext() != Shop::CONTEXT_SHOP) { + $this->context->smarty->assign(array( + 'display_multishop_checkboxes' => true, + 'multishop_check' => Tools::getValue('multishop_check'), + )); + } - if (Shop::getContext() != Shop::CONTEXT_ALL) - { - $this->context->smarty->assign('bullet_common_field', '<i class="icon-circle text-orange"></i>'); - $this->context->smarty->assign('display_common_field', true); - } - } + if (Shop::getContext() != Shop::CONTEXT_ALL) { + $this->context->smarty->assign('bullet_common_field', '<i class="icon-circle text-orange"></i>'); + $this->context->smarty->assign('display_common_field', true); + } + } - $this->tpl_form_vars['tabs_preloaded'] = $this->available_tabs; + $this->tpl_form_vars['tabs_preloaded'] = $this->available_tabs; - $this->tpl_form_vars['product_type'] = (int)Tools::getValue('type_product', $product->getType()); + $this->tpl_form_vars['product_type'] = (int)Tools::getValue('type_product', $product->getType()); - $this->getLanguages(); + $this->getLanguages(); - $this->tpl_form_vars['id_lang_default'] = Configuration::get('PS_LANG_DEFAULT'); + $this->tpl_form_vars['id_lang_default'] = Configuration::get('PS_LANG_DEFAULT'); - $this->tpl_form_vars['currentIndex'] = self::$currentIndex; - $this->tpl_form_vars['display_multishop_checkboxes'] = (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP && $this->display == 'edit'); - $this->fields_form = array(''); + $this->tpl_form_vars['currentIndex'] = self::$currentIndex; + $this->tpl_form_vars['display_multishop_checkboxes'] = (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP && $this->display == 'edit'); + $this->fields_form = array(''); - $this->tpl_form_vars['token'] = $this->token; - $this->tpl_form_vars['combinationImagesJs'] = $this->getCombinationImagesJs(); - $this->tpl_form_vars['PS_ALLOW_ACCENTED_CHARS_URL'] = (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL'); - $this->tpl_form_vars['post_data'] = Tools::jsonEncode($_POST); - $this->tpl_form_vars['save_error'] = !empty($this->errors); - $this->tpl_form_vars['mod_evasive'] = Tools::apacheModExists('evasive'); - $this->tpl_form_vars['mod_security'] = Tools::apacheModExists('security'); - $this->tpl_form_vars['ps_force_friendly_product'] = Configuration::get('PS_FORCE_FRIENDLY_PRODUCT'); + $this->tpl_form_vars['token'] = $this->token; + $this->tpl_form_vars['combinationImagesJs'] = $this->getCombinationImagesJs(); + $this->tpl_form_vars['PS_ALLOW_ACCENTED_CHARS_URL'] = (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL'); + $this->tpl_form_vars['post_data'] = Tools::jsonEncode($_POST); + $this->tpl_form_vars['save_error'] = !empty($this->errors); + $this->tpl_form_vars['mod_evasive'] = Tools::apacheModExists('evasive'); + $this->tpl_form_vars['mod_security'] = Tools::apacheModExists('security'); + $this->tpl_form_vars['ps_force_friendly_product'] = Configuration::get('PS_FORCE_FRIENDLY_PRODUCT'); - // autoload rich text editor (tiny mce) - $this->tpl_form_vars['tinymce'] = true; - $iso = $this->context->language->iso_code; - $this->tpl_form_vars['iso'] = file_exists(_PS_CORE_DIR_.'/js/tiny_mce/langs/'.$iso.'.js') ? $iso : 'en'; - $this->tpl_form_vars['path_css'] = _THEME_CSS_DIR_; - $this->tpl_form_vars['ad'] = __PS_BASE_URI__.basename(_PS_ADMIN_DIR_); + // autoload rich text editor (tiny mce) + $this->tpl_form_vars['tinymce'] = true; + $iso = $this->context->language->iso_code; + $this->tpl_form_vars['iso'] = file_exists(_PS_CORE_DIR_.'/js/tiny_mce/langs/'.$iso.'.js') ? $iso : 'en'; + $this->tpl_form_vars['path_css'] = _THEME_CSS_DIR_; + $this->tpl_form_vars['ad'] = __PS_BASE_URI__.basename(_PS_ADMIN_DIR_); - if (Validate::isLoadedObject(($this->object))) - $id_product = (int)$this->object->id; - else - $id_product = (int)Tools::getvalue('id_product'); + if (Validate::isLoadedObject(($this->object))) { + $id_product = (int)$this->object->id; + } else { + $id_product = (int)Tools::getvalue('id_product'); + } - $page = (int)Tools::getValue('page'); + $page = (int)Tools::getValue('page'); - $this->tpl_form_vars['form_action'] = $this->context->link->getAdminLink('AdminProducts').'&'.($id_product ? 'id_product='.(int)$id_product : 'addproduct').($page > 1 ? '&page='.(int)$page : ''); - $this->tpl_form_vars['id_product'] = $id_product; + $this->tpl_form_vars['form_action'] = $this->context->link->getAdminLink('AdminProducts').'&'.($id_product ? 'id_product='.(int)$id_product : 'addproduct').($page > 1 ? '&page='.(int)$page : ''); + $this->tpl_form_vars['id_product'] = $id_product; - // Transform configuration option 'upload_max_filesize' in octets - $upload_max_filesize = Tools::getOctets(ini_get('upload_max_filesize')); + // Transform configuration option 'upload_max_filesize' in octets + $upload_max_filesize = Tools::getOctets(ini_get('upload_max_filesize')); - // Transform configuration option 'upload_max_filesize' in MegaOctets - $upload_max_filesize = ($upload_max_filesize / 1024) / 1024; + // Transform configuration option 'upload_max_filesize' in MegaOctets + $upload_max_filesize = ($upload_max_filesize / 1024) / 1024; - $this->tpl_form_vars['upload_max_filesize'] = $upload_max_filesize; - $this->tpl_form_vars['country_display_tax_label'] = $this->context->country->display_tax_label; - $this->tpl_form_vars['has_combinations'] = $this->object->hasAttributes(); - $this->product_exists_in_shop = true; + $this->tpl_form_vars['upload_max_filesize'] = $upload_max_filesize; + $this->tpl_form_vars['country_display_tax_label'] = $this->context->country->display_tax_label; + $this->tpl_form_vars['has_combinations'] = $this->object->hasAttributes(); + $this->product_exists_in_shop = true; - if ($this->display == 'edit' && Validate::isLoadedObject($product) && Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP && !$product->isAssociatedToShop($this->context->shop->id)) - { - $this->product_exists_in_shop = false; - if ($this->tab_display == 'Informations') - $this->displayWarning($this->l('Warning: The product does not exist in this shop')); + if ($this->display == 'edit' && Validate::isLoadedObject($product) && Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP && !$product->isAssociatedToShop($this->context->shop->id)) { + $this->product_exists_in_shop = false; + if ($this->tab_display == 'Informations') { + $this->displayWarning($this->l('Warning: The product does not exist in this shop')); + } - $default_product = new Product(); - $definition = ObjectModel::getDefinition($product); - foreach ($definition['fields'] as $field_name => $field) - if (isset($field['shop']) && $field['shop']) - $product->$field_name = ObjectModel::formatValue($default_product->$field_name, $field['type']); - } + $default_product = new Product(); + $definition = ObjectModel::getDefinition($product); + foreach ($definition['fields'] as $field_name => $field) { + if (isset($field['shop']) && $field['shop']) { + $product->$field_name = ObjectModel::formatValue($default_product->$field_name, $field['type']); + } + } + } - // let's calculate this once for all - if (!Validate::isLoadedObject($this->object) && Tools::getValue('id_product')) - $this->errors[] = 'Unable to load object'; - else - { - $this->_displayDraftWarning($this->object->active); + // let's calculate this once for all + if (!Validate::isLoadedObject($this->object) && Tools::getValue('id_product')) { + $this->errors[] = 'Unable to load object'; + } else { + $this->_displayDraftWarning($this->object->active); - // if there was an error while saving, we don't want to lose posted data - if (!empty($this->errors)) - $this->copyFromPost($this->object, $this->table); + // if there was an error while saving, we don't want to lose posted data + if (!empty($this->errors)) { + $this->copyFromPost($this->object, $this->table); + } - $this->initPack($this->object); - $this->{'initForm'.$this->tab_display}($this->object); - $this->tpl_form_vars['product'] = $this->object; + $this->initPack($this->object); + $this->{'initForm'.$this->tab_display}($this->object); + $this->tpl_form_vars['product'] = $this->object; - if ($this->ajax) - if (!isset($this->tpl_form_vars['custom_form'])) - throw new PrestaShopException('custom_form empty for action '.$this->tab_display); - else - return $this->tpl_form_vars['custom_form']; - } + if ($this->ajax) { + if (!isset($this->tpl_form_vars['custom_form'])) { + throw new PrestaShopException('custom_form empty for action '.$this->tab_display); + } else { + return $this->tpl_form_vars['custom_form']; + } + } + } - $parent = parent::renderForm(); - $this->addJqueryPlugin(array('autocomplete', 'fancybox', 'typewatch')); - return $parent; - } + $parent = parent::renderForm(); + $this->addJqueryPlugin(array('autocomplete', 'fancybox', 'typewatch')); + return $parent; + } - public function getPreviewUrl(Product $product) - { - $id_lang = Configuration::get('PS_LANG_DEFAULT', null, null, Context::getContext()->shop->id); + public function getPreviewUrl(Product $product) + { + $id_lang = Configuration::get('PS_LANG_DEFAULT', null, null, Context::getContext()->shop->id); - if (!ShopUrl::getMainShopDomain()) - return false; + if (!ShopUrl::getMainShopDomain()) { + return false; + } - $is_rewrite_active = (bool)Configuration::get('PS_REWRITING_SETTINGS'); - $preview_url = $this->context->link->getProductLink( - $product, - $this->getFieldValue($product, 'link_rewrite', $this->context->language->id), - Category::getLinkRewrite($this->getFieldValue($product, 'id_category_default'), $this->context->language->id), - null, - $id_lang, - (int)Context::getContext()->shop->id, - 0, - $is_rewrite_active - ); + $is_rewrite_active = (bool)Configuration::get('PS_REWRITING_SETTINGS'); + $preview_url = $this->context->link->getProductLink( + $product, + $this->getFieldValue($product, 'link_rewrite', $this->context->language->id), + Category::getLinkRewrite($this->getFieldValue($product, 'id_category_default'), $this->context->language->id), + null, + $id_lang, + (int)Context::getContext()->shop->id, + 0, + $is_rewrite_active + ); - if (!$product->active) - { - $admin_dir = dirname($_SERVER['PHP_SELF']); - $admin_dir = substr($admin_dir, strrpos($admin_dir, '/') + 1); - $preview_url .= ((strpos($preview_url, '?') === false) ? '?' : '&').'adtoken='.$this->token.'&ad='.$admin_dir.'&id_employee='.(int)$this->context->employee->id; - } + if (!$product->active) { + $admin_dir = dirname($_SERVER['PHP_SELF']); + $admin_dir = substr($admin_dir, strrpos($admin_dir, '/') + 1); + $preview_url .= ((strpos($preview_url, '?') === false) ? '?' : '&').'adtoken='.$this->token.'&ad='.$admin_dir.'&id_employee='.(int)$this->context->employee->id; + } - return $preview_url; - } + return $preview_url; + } - /** - * Post treatment for suppliers - */ - public function processSuppliers() - { - if ((int)Tools::getValue('supplier_loaded') === 1 && Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product')))) - { - // Get all id_product_attribute - $attributes = $product->getAttributesResume($this->context->language->id); - if (empty($attributes)) - $attributes[] = array( - 'id_product_attribute' => 0, - 'attribute_designation' => '' - ); + /** + * Post treatment for suppliers + */ + public function processSuppliers() + { + if ((int)Tools::getValue('supplier_loaded') === 1 && Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product')))) { + // Get all id_product_attribute + $attributes = $product->getAttributesResume($this->context->language->id); + if (empty($attributes)) { + $attributes[] = array( + 'id_product_attribute' => 0, + 'attribute_designation' => '' + ); + } - // Get all available suppliers - $suppliers = Supplier::getSuppliers(); + // Get all available suppliers + $suppliers = Supplier::getSuppliers(); - // Get already associated suppliers - $associated_suppliers = ProductSupplier::getSupplierCollection($product->id); + // Get already associated suppliers + $associated_suppliers = ProductSupplier::getSupplierCollection($product->id); - $suppliers_to_associate = array(); - $new_default_supplier = 0; + $suppliers_to_associate = array(); + $new_default_supplier = 0; - if (Tools::isSubmit('default_supplier')) - $new_default_supplier = (int)Tools::getValue('default_supplier'); + if (Tools::isSubmit('default_supplier')) { + $new_default_supplier = (int)Tools::getValue('default_supplier'); + } - // Get new associations - foreach ($suppliers as $supplier) - if (Tools::isSubmit('check_supplier_'.$supplier['id_supplier'])) - $suppliers_to_associate[] = $supplier['id_supplier']; + // Get new associations + foreach ($suppliers as $supplier) { + if (Tools::isSubmit('check_supplier_'.$supplier['id_supplier'])) { + $suppliers_to_associate[] = $supplier['id_supplier']; + } + } - // Delete already associated suppliers if needed - foreach ($associated_suppliers as $key => $associated_supplier) - { - /** @var ProductSupplier $associated_supplier */ - if (!in_array($associated_supplier->id_supplier, $suppliers_to_associate)) - { - $associated_supplier->delete(); - unset($associated_suppliers[$key]); - } - } + // Delete already associated suppliers if needed + foreach ($associated_suppliers as $key => $associated_supplier) { + /** @var ProductSupplier $associated_supplier */ + if (!in_array($associated_supplier->id_supplier, $suppliers_to_associate)) { + $associated_supplier->delete(); + unset($associated_suppliers[$key]); + } + } - // Associate suppliers - foreach ($suppliers_to_associate as $id) - { - $to_add = true; - foreach ($associated_suppliers as $as) - { - /** @var ProductSupplier $as */ - if ($id == $as->id_supplier) - $to_add = false; - } + // Associate suppliers + foreach ($suppliers_to_associate as $id) { + $to_add = true; + foreach ($associated_suppliers as $as) { + /** @var ProductSupplier $as */ + if ($id == $as->id_supplier) { + $to_add = false; + } + } - if ($to_add) - { - $product_supplier = new ProductSupplier(); - $product_supplier->id_product = $product->id; - $product_supplier->id_product_attribute = 0; - $product_supplier->id_supplier = $id; - if ($this->context->currency->id) - $product_supplier->id_currency = (int)$this->context->currency->id; - else - $product_supplier->id_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT'); - $product_supplier->save(); + if ($to_add) { + $product_supplier = new ProductSupplier(); + $product_supplier->id_product = $product->id; + $product_supplier->id_product_attribute = 0; + $product_supplier->id_supplier = $id; + if ($this->context->currency->id) { + $product_supplier->id_currency = (int)$this->context->currency->id; + } else { + $product_supplier->id_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT'); + } + $product_supplier->save(); - $associated_suppliers[] = $product_supplier; - foreach ($attributes as $attribute) - if ((int)$attribute['id_product_attribute'] > 0) - { - $product_supplier = new ProductSupplier(); - $product_supplier->id_product = $product->id; - $product_supplier->id_product_attribute = (int)$attribute['id_product_attribute']; - $product_supplier->id_supplier = $id; - $product_supplier->save(); - } - } - } + $associated_suppliers[] = $product_supplier; + foreach ($attributes as $attribute) { + if ((int)$attribute['id_product_attribute'] > 0) { + $product_supplier = new ProductSupplier(); + $product_supplier->id_product = $product->id; + $product_supplier->id_product_attribute = (int)$attribute['id_product_attribute']; + $product_supplier->id_supplier = $id; + $product_supplier->save(); + } + } + } + } - // Manage references and prices - foreach ($attributes as $attribute) - foreach ($associated_suppliers as $supplier) - { - /** @var ProductSupplier $supplier */ - if (Tools::isSubmit('supplier_reference_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier) || - (Tools::isSubmit('product_price_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier) && - Tools::isSubmit('product_price_currency_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier))) - { - $reference = pSQL( - Tools::getValue( - 'supplier_reference_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier, - '' - ) - ); + // Manage references and prices + foreach ($attributes as $attribute) { + foreach ($associated_suppliers as $supplier) { + /** @var ProductSupplier $supplier */ + if (Tools::isSubmit('supplier_reference_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier) || + (Tools::isSubmit('product_price_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier) && + Tools::isSubmit('product_price_currency_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier))) { + $reference = pSQL( + Tools::getValue( + 'supplier_reference_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier, + '' + ) + ); - $price = (float)str_replace( - array(' ', ','), - array('', '.'), - Tools::getValue( - 'product_price_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier, - 0 - ) - ); + $price = (float)str_replace( + array(' ', ','), + array('', '.'), + Tools::getValue( + 'product_price_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier, + 0 + ) + ); - $price = Tools::ps_round($price, 6); + $price = Tools::ps_round($price, 6); - $id_currency = (int)Tools::getValue( - 'product_price_currency_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier, - 0 - ); + $id_currency = (int)Tools::getValue( + 'product_price_currency_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier, + 0 + ); - if ($id_currency <= 0 || ( !($result = Currency::getCurrency($id_currency)) || empty($result) )) - $this->errors[] = Tools::displayError('The selected currency is not valid'); + if ($id_currency <= 0 || (!($result = Currency::getCurrency($id_currency)) || empty($result))) { + $this->errors[] = Tools::displayError('The selected currency is not valid'); + } - // Save product-supplier data - $product_supplier_id = (int)ProductSupplier::getIdByProductAndSupplier($product->id, $attribute['id_product_attribute'], $supplier->id_supplier); + // Save product-supplier data + $product_supplier_id = (int)ProductSupplier::getIdByProductAndSupplier($product->id, $attribute['id_product_attribute'], $supplier->id_supplier); - if (!$product_supplier_id) - { - $product->addSupplierReference($supplier->id_supplier, (int)$attribute['id_product_attribute'], $reference, (float)$price, (int)$id_currency); - if ($product->id_supplier == $supplier->id_supplier) - { - if ((int)$attribute['id_product_attribute'] > 0) - { - $data = array( - 'supplier_reference' => pSQL($reference), - 'wholesale_price' => (float)Tools::convertPrice($price, $id_currency) - ); - $where = ' + if (!$product_supplier_id) { + $product->addSupplierReference($supplier->id_supplier, (int)$attribute['id_product_attribute'], $reference, (float)$price, (int)$id_currency); + if ($product->id_supplier == $supplier->id_supplier) { + if ((int)$attribute['id_product_attribute'] > 0) { + $data = array( + 'supplier_reference' => pSQL($reference), + 'wholesale_price' => (float)Tools::convertPrice($price, $id_currency) + ); + $where = ' a.id_product = '.(int)$product->id.' AND a.id_product_attribute = '.(int)$attribute['id_product_attribute']; - ObjectModel::updateMultishopTable('Combination', $data, $where); - } - else - { - $product->wholesale_price = (float)Tools::convertPrice($price, $id_currency); //converted in the default currency - $product->supplier_reference = pSQL($reference); - $product->update(); - } - } - } - else - { - $product_supplier = new ProductSupplier($product_supplier_id); - $product_supplier->id_currency = (int)$id_currency; - $product_supplier->product_supplier_price_te = (float)$price; - $product_supplier->product_supplier_reference = pSQL($reference); - $product_supplier->update(); - - } - } - elseif (Tools::isSubmit('supplier_reference_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier)) - { - //int attribute with default values if possible - if ((int)$attribute['id_product_attribute'] > 0) - { - $product_supplier = new ProductSupplier(); - $product_supplier->id_product = $product->id; - $product_supplier->id_product_attribute = (int)$attribute['id_product_attribute']; - $product_supplier->id_supplier = $supplier->id_supplier; - $product_supplier->save(); - } - } - } - // Manage defaut supplier for product - if ($new_default_supplier != $product->id_supplier) - { - $this->object->id_supplier = $new_default_supplier; - $this->object->update(); - } - } - } - - /** - * Post treatment for warehouses - */ - public function processWarehouses() - { - if ((int)Tools::getValue('warehouse_loaded') === 1 && Validate::isLoadedObject($product = new Product((int)$id_product = Tools::getValue('id_product')))) - { - // Get all id_product_attribute - $attributes = $product->getAttributesResume($this->context->language->id); - if (empty($attributes)) - $attributes[] = array( - 'id_product_attribute' => 0, - 'attribute_designation' => '' - ); - - // Get all available warehouses - $warehouses = Warehouse::getWarehouses(true); - - // Get already associated warehouses - $associated_warehouses_collection = WarehouseProductLocation::getCollection($product->id); - - $elements_to_manage = array(); - - // get form inforamtion - foreach ($attributes as $attribute) - { - foreach ($warehouses as $warehouse) - { - $key = $warehouse['id_warehouse'].'_'.$product->id.'_'.$attribute['id_product_attribute']; - - // get elements to manage - if (Tools::isSubmit('check_warehouse_'.$key)) - { - $location = Tools::getValue('location_warehouse_'.$key, ''); - $elements_to_manage[$key] = $location; - } - } - } - - // Delete entry if necessary - foreach ($associated_warehouses_collection as $awc) - { - /** @var WarehouseProductLocation $awc */ - if (!array_key_exists($awc->id_warehouse.'_'.$awc->id_product.'_'.$awc->id_product_attribute, $elements_to_manage)) - $awc->delete(); - } - - // Manage locations - foreach ($elements_to_manage as $key => $location) - { - $params = explode('_', $key); - - $wpl_id = (int)WarehouseProductLocation::getIdByProductAndWarehouse((int)$params[1], (int)$params[2], (int)$params[0]); - - if (empty($wpl_id)) - { - //create new record - $warehouse_location_entity = new WarehouseProductLocation(); - $warehouse_location_entity->id_product = (int)$params[1]; - $warehouse_location_entity->id_product_attribute = (int)$params[2]; - $warehouse_location_entity->id_warehouse = (int)$params[0]; - $warehouse_location_entity->location = pSQL($location); - $warehouse_location_entity->save(); - } - else - { - $warehouse_location_entity = new WarehouseProductLocation((int)$wpl_id); - - $location = pSQL($location); - - if ($location != $warehouse_location_entity->location) - { - $warehouse_location_entity->location = pSQL($location); - $warehouse_location_entity->update(); - } - } - } - StockAvailable::synchronize((int)$id_product); - } - } - - /** - * @param Product $obj - * @throws Exception - * @throws PrestaShopException - * @throws SmartyException - */ - public function initFormAssociations($obj) - { - $product = $obj; - $data = $this->createTemplate($this->tpl_form); - // Prepare Categories tree for display in Associations tab - $root = Category::getRootCategory(); - $default_category = $this->context->cookie->id_category_products_filter ? $this->context->cookie->id_category_products_filter : Context::getContext()->shop->id_category; - if (!$product->id || !$product->isAssociatedToShop()) - $selected_cat = Category::getCategoryInformations(Tools::getValue('categoryBox', array($default_category)), $this->default_form_language); - else - { - if (Tools::isSubmit('categoryBox')) - $selected_cat = Category::getCategoryInformations(Tools::getValue('categoryBox', array($default_category)), $this->default_form_language); - else - $selected_cat = Product::getProductCategoriesFull($product->id, $this->default_form_language); - } - - // Multishop block - $data->assign('feature_shop_active', Shop::isFeatureActive()); - $helper = new HelperForm(); - if ($this->object && $this->object->id) - $helper->id = $this->object->id; - else - $helper->id = null; - $helper->table = $this->table; - $helper->identifier = $this->identifier; - - // Accessories block - $accessories = Product::getAccessoriesLight($this->context->language->id, $product->id); - - if ($post_accessories = Tools::getValue('inputAccessories')) - { - $post_accessories_tab = explode('-', $post_accessories); - foreach ($post_accessories_tab as $accessory_id) - if (!$this->haveThisAccessory($accessory_id, $accessories) && $accessory = Product::getAccessoryById($accessory_id)) - $accessories[] = $accessory; - } - $data->assign('accessories', $accessories); - - $product->manufacturer_name = Manufacturer::getNameById($product->id_manufacturer); - - $categories = array(); - foreach ($selected_cat as $key => $category) - $categories[] = $key; - - $tree = new HelperTreeCategories('associated-categories-tree', 'Associated categories'); - $tree->setTemplate('tree_associated_categories.tpl') - ->setHeaderTemplate('tree_associated_header.tpl') - ->setRootCategory($root->id) - ->setUseCheckBox(true) - ->setUseSearch(true) - ->setSelectedCategories($categories); - - $data->assign(array('default_category' => $default_category, - 'selected_cat_ids' => implode(',', array_keys($selected_cat)), - 'selected_cat' => $selected_cat, - 'id_category_default' => $product->getDefaultCategory(), - 'category_tree' => $tree->render(), - 'product' => $product, - 'link' => $this->context->link, - 'is_shop_context' => Shop::getContext() == Shop::CONTEXT_SHOP - )); - - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - /** - * @param Product $obj - * @throws Exception - * @throws SmartyException - */ - public function initFormPrices($obj) - { - $data = $this->createTemplate($this->tpl_form); - $product = $obj; - if ($obj->id) - { - $shops = Shop::getShops(); - $countries = Country::getCountries($this->context->language->id); - $groups = Group::getGroups($this->context->language->id); - $currencies = Currency::getCurrencies(); - $attributes = $obj->getAttributesGroups((int)$this->context->language->id); - $combinations = array(); - foreach ($attributes as $attribute) - { - $combinations[$attribute['id_product_attribute']]['id_product_attribute'] = $attribute['id_product_attribute']; - if (!isset($combinations[$attribute['id_product_attribute']]['attributes'])) - $combinations[$attribute['id_product_attribute']]['attributes'] = ''; - $combinations[$attribute['id_product_attribute']]['attributes'] .= $attribute['attribute_name'].' - '; - - $combinations[$attribute['id_product_attribute']]['price'] = Tools::displayPrice( - Tools::convertPrice( - Product::getPriceStatic((int)$obj->id, false, $attribute['id_product_attribute']), - $this->context->currency - ), $this->context->currency - ); - } - foreach ($combinations as &$combination) - $combination['attributes'] = rtrim($combination['attributes'], ' - '); - $data->assign('specificPriceModificationForm', $this->_displaySpecificPriceModificationForm( - $this->context->currency, $shops, $currencies, $countries, $groups) - ); - - $data->assign('ecotax_tax_excl', (int)$obj->ecotax); - $this->_applyTaxToEcotax($obj); - - $data->assign(array( - 'shops' => $shops, - 'admin_one_shop' => count($this->context->employee->getAssociatedShops()) == 1, - 'currencies' => $currencies, - 'countries' => $countries, - 'groups' => $groups, - 'combinations' => $combinations, - 'multi_shop' => Shop::isFeatureActive(), - 'link' => new Link(), - 'pack' => new Pack() - )); - } - else - { - $this->displayWarning($this->l('You must save this product before adding specific pricing')); - $product->id_tax_rules_group = (int)Product::getIdTaxRulesGroupMostUsed(); - $data->assign('ecotax_tax_excl', 0); - } - - $address = new Address(); - $address->id_country = (int)$this->context->country->id; - $tax_rules_groups = TaxRulesGroup::getTaxRulesGroups(true); - $tax_rates = array( - 0 => array ( - 'id_tax_rules_group' => 0, - 'rates' => array(0), - 'computation_method' => 0 - ) - ); - - foreach ($tax_rules_groups as $tax_rules_group) - { - $id_tax_rules_group = (int)$tax_rules_group['id_tax_rules_group']; - $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator(); - $tax_rates[$id_tax_rules_group] = array( - 'id_tax_rules_group' => $id_tax_rules_group, - 'rates' => array(), - 'computation_method' => (int)$tax_calculator->computation_method - ); - - if (isset($tax_calculator->taxes) && count($tax_calculator->taxes)) - foreach ($tax_calculator->taxes as $tax) - $tax_rates[$id_tax_rules_group]['rates'][] = (float)$tax->rate; - else - $tax_rates[$id_tax_rules_group]['rates'][] = 0; - } - - // prices part - $data->assign(array( - 'link' => $this->context->link, - 'currency' => $currency = $this->context->currency, - 'tax_rules_groups' => $tax_rules_groups, - 'taxesRatesByGroup' => $tax_rates, - 'ecotaxTaxRate' => Tax::getProductEcotaxRate(), - 'tax_exclude_taxe_option' => Tax::excludeTaxeOption(), - 'ps_use_ecotax' => Configuration::get('PS_USE_ECOTAX'), - )); - - $product->price = Tools::convertPrice($product->price, $this->context->currency, true, $this->context); - if ($product->unit_price_ratio != 0) - $data->assign('unit_price', Tools::ps_round($product->price / $product->unit_price_ratio, 6)); - else - $data->assign('unit_price', 0); - $data->assign('ps_tax', Configuration::get('PS_TAX')); - - $data->assign('country_display_tax_label', $this->context->country->display_tax_label); - $data->assign(array( - 'currency', $this->context->currency, - 'product' => $product, - 'token' => $this->token - )); - - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - public function initFormSeo($product) - { - if (!$this->default_form_language) - $this->getLanguages(); - - $data = $this->createTemplate($this->tpl_form); - - $context = Context::getContext(); - $rewritten_links = array(); - foreach ($this->_languages as $language) - { - $category = Category::getLinkRewrite((int)$product->id_category_default, (int)$language['id_lang']); - $rewritten_links[(int)$language['id_lang']] = explode( - '[REWRITE]', - $context->link->getProductLink($product, '[REWRITE]', $category, null, (int)$language['id_lang']) - ); - } - - $data->assign(array( - 'product' => $product, - 'languages' => $this->_languages, - 'id_lang' => $this->context->language->id, - 'ps_ssl_enabled' => Configuration::get('PS_SSL_ENABLED'), - 'curent_shop_url' => $this->context->shop->getBaseURL(), - 'default_form_language' => $this->default_form_language, - 'rewritten_links' => $rewritten_links - )); - - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - /** - * Get an array of pack items for display from the product object if specified, else from POST/GET values - * - * @param Product $product - * @return array of pack items - */ - public function getPackItems($product = null) - { - $pack_items = array(); - - if (!$product) - { - $names_input = Tools::getValue('namePackItems'); - $ids_input = Tools::getValue('inputPackItems'); - if (!$names_input || !$ids_input) - return array(); - // ids is an array of string with format : QTYxID - $ids = array_unique(explode('-', $ids_input)); - $names = array_unique(explode('¤', $names_input)); - - if (!empty($ids)) - { - $length = count($ids); - for ($i = 0; $i < $length; $i++) - { - if (!empty($ids[$i]) && !empty($names[$i])) - { - list($pack_items[$i]['pack_quantity'], $pack_items[$i]['id']) = explode('x', $ids[$i]); - $exploded_name = explode('x', $names[$i]); - $pack_items[$i]['name'] = $exploded_name[1]; - } - } - } - } - else - { - $i = 0; - foreach ($product->packItems as $pack_item) - { - $pack_items[$i]['id'] = $pack_item->id; - $pack_items[$i]['pack_quantity'] = $pack_item->pack_quantity; - $pack_items[$i]['name'] = $pack_item->name; - $pack_items[$i]['reference'] = $pack_item->reference; - $pack_items[$i]['id_product_attribute'] = isset($pack_item->id_pack_product_attribute) && $pack_item->id_pack_product_attribute ? $pack_item->id_pack_product_attribute : 0; - $cover = $pack_item->id_pack_product_attribute ? Product::getCombinationImageById($pack_item->id_pack_product_attribute, Context::getContext()->language->id) : Product::getCover($pack_item->id); - $pack_items[$i]['image'] = Context::getContext()->link->getImageLink($pack_item->link_rewrite, $cover['id_image'], 'home_default'); - // @todo: don't rely on 'home_default' - //$path_to_image = _PS_IMG_DIR_.'p/'.Image::getImgFolderStatic($cover['id_image']).(int)$cover['id_image'].'.jpg'; - //$pack_items[$i]['image'] = ImageManager::thumbnail($path_to_image, 'pack_mini_'.$pack_item->id.'_'.$this->context->shop->id.'.jpg', 120); - $i++; - } - } - return $pack_items; - } - - /** - * @param Product $product - * @throws Exception - * @throws SmartyException - */ - public function initFormPack($product) - { - $data = $this->createTemplate($this->tpl_form); - - // If pack items have been submitted, we want to display them instead of the actuel content of the pack - // in database. In case of a submit error, the posted data is not lost and can be sent again. - if (Tools::getValue('namePackItems')) - { - $input_pack_items = Tools::getValue('inputPackItems'); - $input_namepack_items = Tools::getValue('namePackItems'); - $pack_items = $this->getPackItems(); - } - else - { - $product->packItems = Pack::getItems($product->id, $this->context->language->id); - $pack_items = $this->getPackItems($product); - $input_namepack_items = ''; - $input_pack_items = ''; - foreach ($pack_items as $pack_item) - { - $input_pack_items .= $pack_item['pack_quantity'].'x'.$pack_item['id'].'x'.$pack_item['id_product_attribute'].'-'; - $input_namepack_items .= $pack_item['pack_quantity'].' x '.$pack_item['name'].'¤'; - } - } - - $data->assign(array( - 'input_pack_items' => $input_pack_items, - 'input_namepack_items' => $input_namepack_items, - 'pack_items' => $pack_items, - 'product_type' => (int)Tools::getValue('type_product', $product->getType()) - )); - - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - public function initFormVirtualProduct($product) - { - $data = $this->createTemplate($this->tpl_form); - - $currency = $this->context->currency; - - /* - * Form for adding a virtual product like software, mp3, etc... - */ - $product_download = new ProductDownload(); - if ($id_product_download = $product_download->getIdFromIdProduct($this->getFieldValue($product, 'id'))) - $product_download = new ProductDownload($id_product_download); - $product->{'productDownload'} = $product_download; - - if ($product->productDownload->id && empty($product->productDownload->display_filename)) - { - $this->errors[] = Tools::displayError('A file name is required in order to associate a file'); - $this->tab_display = 'VirtualProduct'; - } - - // @todo handle is_virtual with the value of the product - $exists_file = realpath(_PS_DOWNLOAD_DIR_).'/'.$product->productDownload->filename; - $data->assign('product_downloaded', $product->productDownload->id); - - if (!file_exists($exists_file) - && !empty($product->productDownload->display_filename) - && empty($product->cache_default_attribute)) - $msg = sprintf(Tools::displayError('File "%s" is missing'), - $product->productDownload->display_filename); - else - $msg = ''; - - $virtual_product_file_uploader = new HelperUploader('virtual_product_file_uploader'); - $virtual_product_file_uploader->setMultiple(false)->setUrl( - Context::getContext()->link->getAdminLink('AdminProducts').'&ajax=1&id_product='.(int)$product->id - .'&action=AddVirtualProductFile')->setPostMaxSize(Tools::getOctets(ini_get('upload_max_filesize'))) - ->setTemplate('virtual_product.tpl'); - - $data->assign(array( - 'download_product_file_missing' => $msg, - 'download_dir_writable' => ProductDownload::checkWritableDir(), - 'up_filename' => strval(Tools::getValue('virtual_product_filename')) - )); - - $product->productDownload->nb_downloadable = ($product->productDownload->id > 0) ? $product->productDownload->nb_downloadable : htmlentities(Tools::getValue('virtual_product_nb_downloable'), ENT_COMPAT, 'UTF-8'); - $product->productDownload->date_expiration = ($product->productDownload->id > 0) ? ((!empty($product->productDownload->date_expiration) && $product->productDownload->date_expiration != '0000-00-00 00:00:00') ? date('Y-m-d', strtotime($product->productDownload->date_expiration)) : '' ) : htmlentities(Tools::getValue('virtual_product_expiration_date'), ENT_COMPAT, 'UTF-8'); - $product->productDownload->nb_days_accessible = ($product->productDownload->id > 0) ? $product->productDownload->nb_days_accessible : htmlentities(Tools::getValue('virtual_product_nb_days'), ENT_COMPAT, 'UTF-8'); - $product->productDownload->is_shareable = $product->productDownload->id > 0 && $product->productDownload->is_shareable; - - $iso_tiny_mce = $this->context->language->iso_code; - $iso_tiny_mce = (file_exists(_PS_JS_DIR_.'tiny_mce/langs/'.$iso_tiny_mce.'.js') ? $iso_tiny_mce : 'en'); - $data->assign(array( - 'ad' => __PS_BASE_URI__.basename(_PS_ADMIN_DIR_), - 'iso_tiny_mce' => $iso_tiny_mce, - 'product' => $product, - 'token' => $this->token, - 'currency' => $currency, - 'link' => $this->context->link, - 'is_file' => $product->productDownload->checkFile(), - 'virtual_product_file_uploader' => $virtual_product_file_uploader->render() - )); - $data->assign($this->tpl_form_vars); - $this->tpl_form_vars['product'] = $product; - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - protected function _getFinalPrice($specific_price, $product_price, $tax_rate) - { - return $this->object->getPrice(false, $specific_price['id_product_attribute'], 2); - } - - protected function _displaySpecificPriceModificationForm($defaultCurrency, $shops, $currencies, $countries, $groups) - { - /** @var Product $obj */ - if (!($obj = $this->loadObject())) - return; - - $page = (int)Tools::getValue('page'); - $content = ''; - $specific_prices = SpecificPrice::getByProductId((int)$obj->id); - $specific_price_priorities = SpecificPrice::getPriority((int)$obj->id); - - $tmp = array(); - foreach ($shops as $shop) - $tmp[$shop['id_shop']] = $shop; - $shops = $tmp; - $tmp = array(); - foreach ($currencies as $currency) - $tmp[$currency['id_currency']] = $currency; - $currencies = $tmp; - - $tmp = array(); - foreach ($countries as $country) - $tmp[$country['id_country']] = $country; - $countries = $tmp; - - $tmp = array(); - foreach ($groups as $group) - $tmp[$group['id_group']] = $group; - $groups = $tmp; - - $length_before = strlen($content); - if (is_array($specific_prices) && count($specific_prices)) - { - $i = 0; - foreach ($specific_prices as $specific_price) - { - $id_currency = $specific_price['id_currency'] ? $specific_price['id_currency'] : $defaultCurrency->id; - if (!isset($currencies[$id_currency])) - continue; - - $current_specific_currency = $currencies[$id_currency]; - if ($specific_price['reduction_type'] == 'percentage') - $impact = '- '.($specific_price['reduction'] * 100).' %'; - elseif ($specific_price['reduction'] > 0) - { - $impact = '- '.Tools::displayPrice(Tools::ps_round($specific_price['reduction'], 2), $current_specific_currency).' '; - if ($specific_price['reduction_tax']) - $impact .= '('.$this->l('Tax incl.').')'; - else - $impact .= '('.$this->l('Tax excl.').')'; - } - else - $impact = '--'; - - if ($specific_price['from'] == '0000-00-00 00:00:00' && $specific_price['to'] == '0000-00-00 00:00:00') - $period = $this->l('Unlimited'); - else - $period = $this->l('From').' '.($specific_price['from'] != '0000-00-00 00:00:00' ? $specific_price['from'] : '0000-00-00 00:00:00').'<br />'.$this->l('To').' '.($specific_price['to'] != '0000-00-00 00:00:00' ? $specific_price['to'] : '0000-00-00 00:00:00'); - if ($specific_price['id_product_attribute']) - { - $combination = new Combination((int)$specific_price['id_product_attribute']); - $attributes = $combination->getAttributesName((int)$this->context->language->id); - $attributes_name = ''; - foreach ($attributes as $attribute) - $attributes_name .= $attribute['name'].' - '; - $attributes_name = rtrim($attributes_name, ' - '); - } - else - $attributes_name = $this->l('All combinations'); - - $rule = new SpecificPriceRule((int)$specific_price['id_specific_price_rule']); - $rule_name = ($rule->id ? $rule->name : '--'); - - if ($specific_price['id_customer']) - { - $customer = new Customer((int)$specific_price['id_customer']); - if (Validate::isLoadedObject($customer)) - $customer_full_name = $customer->firstname.' '.$customer->lastname; - unset($customer); - } - - if (!$specific_price['id_shop'] || in_array($specific_price['id_shop'], Shop::getContextListShopID())) - { - $content .= ' + ObjectModel::updateMultishopTable('Combination', $data, $where); + } else { + $product->wholesale_price = (float)Tools::convertPrice($price, $id_currency); //converted in the default currency + $product->supplier_reference = pSQL($reference); + $product->update(); + } + } + } else { + $product_supplier = new ProductSupplier($product_supplier_id); + $product_supplier->id_currency = (int)$id_currency; + $product_supplier->product_supplier_price_te = (float)$price; + $product_supplier->product_supplier_reference = pSQL($reference); + $product_supplier->update(); + } + } elseif (Tools::isSubmit('supplier_reference_'.$product->id.'_'.$attribute['id_product_attribute'].'_'.$supplier->id_supplier)) { + //int attribute with default values if possible + if ((int)$attribute['id_product_attribute'] > 0) { + $product_supplier = new ProductSupplier(); + $product_supplier->id_product = $product->id; + $product_supplier->id_product_attribute = (int)$attribute['id_product_attribute']; + $product_supplier->id_supplier = $supplier->id_supplier; + $product_supplier->save(); + } + } + } + } + // Manage defaut supplier for product + if ($new_default_supplier != $product->id_supplier) { + $this->object->id_supplier = $new_default_supplier; + $this->object->update(); + } + } + } + + /** + * Post treatment for warehouses + */ + public function processWarehouses() + { + if ((int)Tools::getValue('warehouse_loaded') === 1 && Validate::isLoadedObject($product = new Product((int)$id_product = Tools::getValue('id_product')))) { + // Get all id_product_attribute + $attributes = $product->getAttributesResume($this->context->language->id); + if (empty($attributes)) { + $attributes[] = array( + 'id_product_attribute' => 0, + 'attribute_designation' => '' + ); + } + + // Get all available warehouses + $warehouses = Warehouse::getWarehouses(true); + + // Get already associated warehouses + $associated_warehouses_collection = WarehouseProductLocation::getCollection($product->id); + + $elements_to_manage = array(); + + // get form inforamtion + foreach ($attributes as $attribute) { + foreach ($warehouses as $warehouse) { + $key = $warehouse['id_warehouse'].'_'.$product->id.'_'.$attribute['id_product_attribute']; + + // get elements to manage + if (Tools::isSubmit('check_warehouse_'.$key)) { + $location = Tools::getValue('location_warehouse_'.$key, ''); + $elements_to_manage[$key] = $location; + } + } + } + + // Delete entry if necessary + foreach ($associated_warehouses_collection as $awc) { + /** @var WarehouseProductLocation $awc */ + if (!array_key_exists($awc->id_warehouse.'_'.$awc->id_product.'_'.$awc->id_product_attribute, $elements_to_manage)) { + $awc->delete(); + } + } + + // Manage locations + foreach ($elements_to_manage as $key => $location) { + $params = explode('_', $key); + + $wpl_id = (int)WarehouseProductLocation::getIdByProductAndWarehouse((int)$params[1], (int)$params[2], (int)$params[0]); + + if (empty($wpl_id)) { + //create new record + $warehouse_location_entity = new WarehouseProductLocation(); + $warehouse_location_entity->id_product = (int)$params[1]; + $warehouse_location_entity->id_product_attribute = (int)$params[2]; + $warehouse_location_entity->id_warehouse = (int)$params[0]; + $warehouse_location_entity->location = pSQL($location); + $warehouse_location_entity->save(); + } else { + $warehouse_location_entity = new WarehouseProductLocation((int)$wpl_id); + + $location = pSQL($location); + + if ($location != $warehouse_location_entity->location) { + $warehouse_location_entity->location = pSQL($location); + $warehouse_location_entity->update(); + } + } + } + StockAvailable::synchronize((int)$id_product); + } + } + + /** + * @param Product $obj + * @throws Exception + * @throws PrestaShopException + * @throws SmartyException + */ + public function initFormAssociations($obj) + { + $product = $obj; + $data = $this->createTemplate($this->tpl_form); + // Prepare Categories tree for display in Associations tab + $root = Category::getRootCategory(); + $default_category = $this->context->cookie->id_category_products_filter ? $this->context->cookie->id_category_products_filter : Context::getContext()->shop->id_category; + if (!$product->id || !$product->isAssociatedToShop()) { + $selected_cat = Category::getCategoryInformations(Tools::getValue('categoryBox', array($default_category)), $this->default_form_language); + } else { + if (Tools::isSubmit('categoryBox')) { + $selected_cat = Category::getCategoryInformations(Tools::getValue('categoryBox', array($default_category)), $this->default_form_language); + } else { + $selected_cat = Product::getProductCategoriesFull($product->id, $this->default_form_language); + } + } + + // Multishop block + $data->assign('feature_shop_active', Shop::isFeatureActive()); + $helper = new HelperForm(); + if ($this->object && $this->object->id) { + $helper->id = $this->object->id; + } else { + $helper->id = null; + } + $helper->table = $this->table; + $helper->identifier = $this->identifier; + + // Accessories block + $accessories = Product::getAccessoriesLight($this->context->language->id, $product->id); + + if ($post_accessories = Tools::getValue('inputAccessories')) { + $post_accessories_tab = explode('-', $post_accessories); + foreach ($post_accessories_tab as $accessory_id) { + if (!$this->haveThisAccessory($accessory_id, $accessories) && $accessory = Product::getAccessoryById($accessory_id)) { + $accessories[] = $accessory; + } + } + } + $data->assign('accessories', $accessories); + + $product->manufacturer_name = Manufacturer::getNameById($product->id_manufacturer); + + $categories = array(); + foreach ($selected_cat as $key => $category) { + $categories[] = $key; + } + + $tree = new HelperTreeCategories('associated-categories-tree', 'Associated categories'); + $tree->setTemplate('tree_associated_categories.tpl') + ->setHeaderTemplate('tree_associated_header.tpl') + ->setRootCategory($root->id) + ->setUseCheckBox(true) + ->setUseSearch(true) + ->setSelectedCategories($categories); + + $data->assign(array('default_category' => $default_category, + 'selected_cat_ids' => implode(',', array_keys($selected_cat)), + 'selected_cat' => $selected_cat, + 'id_category_default' => $product->getDefaultCategory(), + 'category_tree' => $tree->render(), + 'product' => $product, + 'link' => $this->context->link, + 'is_shop_context' => Shop::getContext() == Shop::CONTEXT_SHOP + )); + + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + /** + * @param Product $obj + * @throws Exception + * @throws SmartyException + */ + public function initFormPrices($obj) + { + $data = $this->createTemplate($this->tpl_form); + $product = $obj; + if ($obj->id) { + $shops = Shop::getShops(); + $countries = Country::getCountries($this->context->language->id); + $groups = Group::getGroups($this->context->language->id); + $currencies = Currency::getCurrencies(); + $attributes = $obj->getAttributesGroups((int)$this->context->language->id); + $combinations = array(); + foreach ($attributes as $attribute) { + $combinations[$attribute['id_product_attribute']]['id_product_attribute'] = $attribute['id_product_attribute']; + if (!isset($combinations[$attribute['id_product_attribute']]['attributes'])) { + $combinations[$attribute['id_product_attribute']]['attributes'] = ''; + } + $combinations[$attribute['id_product_attribute']]['attributes'] .= $attribute['attribute_name'].' - '; + + $combinations[$attribute['id_product_attribute']]['price'] = Tools::displayPrice( + Tools::convertPrice( + Product::getPriceStatic((int)$obj->id, false, $attribute['id_product_attribute']), + $this->context->currency + ), $this->context->currency + ); + } + foreach ($combinations as &$combination) { + $combination['attributes'] = rtrim($combination['attributes'], ' - '); + } + $data->assign('specificPriceModificationForm', $this->_displaySpecificPriceModificationForm( + $this->context->currency, $shops, $currencies, $countries, $groups) + ); + + $data->assign('ecotax_tax_excl', (float)$obj->ecotax); + $this->_applyTaxToEcotax($obj); + + $data->assign(array( + 'shops' => $shops, + 'admin_one_shop' => count($this->context->employee->getAssociatedShops()) == 1, + 'currencies' => $currencies, + 'countries' => $countries, + 'groups' => $groups, + 'combinations' => $combinations, + 'multi_shop' => Shop::isFeatureActive(), + 'link' => new Link(), + 'pack' => new Pack() + )); + } else { + $this->displayWarning($this->l('You must save this product before adding specific pricing')); + $product->id_tax_rules_group = (int)Product::getIdTaxRulesGroupMostUsed(); + $data->assign('ecotax_tax_excl', 0); + } + + $address = new Address(); + $address->id_country = (int)$this->context->country->id; + $tax_rules_groups = TaxRulesGroup::getTaxRulesGroups(true); + $tax_rates = array( + 0 => array( + 'id_tax_rules_group' => 0, + 'rates' => array(0), + 'computation_method' => 0 + ) + ); + + foreach ($tax_rules_groups as $tax_rules_group) { + $id_tax_rules_group = (int)$tax_rules_group['id_tax_rules_group']; + $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator(); + $tax_rates[$id_tax_rules_group] = array( + 'id_tax_rules_group' => $id_tax_rules_group, + 'rates' => array(), + 'computation_method' => (int)$tax_calculator->computation_method + ); + + if (isset($tax_calculator->taxes) && count($tax_calculator->taxes)) { + foreach ($tax_calculator->taxes as $tax) { + $tax_rates[$id_tax_rules_group]['rates'][] = (float)$tax->rate; + } + } else { + $tax_rates[$id_tax_rules_group]['rates'][] = 0; + } + } + + // prices part + $data->assign(array( + 'link' => $this->context->link, + 'currency' => $currency = $this->context->currency, + 'tax_rules_groups' => $tax_rules_groups, + 'taxesRatesByGroup' => $tax_rates, + 'ecotaxTaxRate' => Tax::getProductEcotaxRate(), + 'tax_exclude_taxe_option' => Tax::excludeTaxeOption(), + 'ps_use_ecotax' => Configuration::get('PS_USE_ECOTAX'), + )); + + $product->price = Tools::convertPrice($product->price, $this->context->currency, true, $this->context); + if ($product->unit_price_ratio != 0) { + $data->assign('unit_price', Tools::ps_round($product->price / $product->unit_price_ratio, 6)); + } else { + $data->assign('unit_price', 0); + } + $data->assign('ps_tax', Configuration::get('PS_TAX')); + + $data->assign('country_display_tax_label', $this->context->country->display_tax_label); + $data->assign(array( + 'currency', $this->context->currency, + 'product' => $product, + 'token' => $this->token + )); + + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + public function initFormSeo($product) + { + if (!$this->default_form_language) { + $this->getLanguages(); + } + + $data = $this->createTemplate($this->tpl_form); + + $context = Context::getContext(); + $rewritten_links = array(); + foreach ($this->_languages as $language) { + $category = Category::getLinkRewrite((int)$product->id_category_default, (int)$language['id_lang']); + $rewritten_links[(int)$language['id_lang']] = explode( + '[REWRITE]', + $context->link->getProductLink($product, '[REWRITE]', $category, null, (int)$language['id_lang']) + ); + } + + $data->assign(array( + 'product' => $product, + 'languages' => $this->_languages, + 'id_lang' => $this->context->language->id, + 'ps_ssl_enabled' => Configuration::get('PS_SSL_ENABLED'), + 'curent_shop_url' => $this->context->shop->getBaseURL(), + 'default_form_language' => $this->default_form_language, + 'rewritten_links' => $rewritten_links + )); + + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + /** + * Get an array of pack items for display from the product object if specified, else from POST/GET values + * + * @param Product $product + * @return array of pack items + */ + public function getPackItems($product = null) + { + $pack_items = array(); + + if (!$product) { + $names_input = Tools::getValue('namePackItems'); + $ids_input = Tools::getValue('inputPackItems'); + if (!$names_input || !$ids_input) { + return array(); + } + // ids is an array of string with format : QTYxID + $ids = array_unique(explode('-', $ids_input)); + $names = array_unique(explode('¤', $names_input)); + + if (!empty($ids)) { + $length = count($ids); + for ($i = 0; $i < $length; $i++) { + if (!empty($ids[$i]) && !empty($names[$i])) { + list($pack_items[$i]['pack_quantity'], $pack_items[$i]['id']) = explode('x', $ids[$i]); + $exploded_name = explode('x', $names[$i]); + $pack_items[$i]['name'] = $exploded_name[1]; + } + } + } + } else { + $i = 0; + foreach ($product->packItems as $pack_item) { + $pack_items[$i]['id'] = $pack_item->id; + $pack_items[$i]['pack_quantity'] = $pack_item->pack_quantity; + $pack_items[$i]['name'] = $pack_item->name; + $pack_items[$i]['reference'] = $pack_item->reference; + $pack_items[$i]['id_product_attribute'] = isset($pack_item->id_pack_product_attribute) && $pack_item->id_pack_product_attribute ? $pack_item->id_pack_product_attribute : 0; + $cover = $pack_item->id_pack_product_attribute ? Product::getCombinationImageById($pack_item->id_pack_product_attribute, Context::getContext()->language->id) : Product::getCover($pack_item->id); + $pack_items[$i]['image'] = Context::getContext()->link->getImageLink($pack_item->link_rewrite, $cover['id_image'], 'home_default'); + // @todo: don't rely on 'home_default' + //$path_to_image = _PS_IMG_DIR_.'p/'.Image::getImgFolderStatic($cover['id_image']).(int)$cover['id_image'].'.jpg'; + //$pack_items[$i]['image'] = ImageManager::thumbnail($path_to_image, 'pack_mini_'.$pack_item->id.'_'.$this->context->shop->id.'.jpg', 120); + $i++; + } + } + return $pack_items; + } + + /** + * @param Product $product + * @throws Exception + * @throws SmartyException + */ + public function initFormPack($product) + { + $data = $this->createTemplate($this->tpl_form); + + // If pack items have been submitted, we want to display them instead of the actuel content of the pack + // in database. In case of a submit error, the posted data is not lost and can be sent again. + if (Tools::getValue('namePackItems')) { + $input_pack_items = Tools::getValue('inputPackItems'); + $input_namepack_items = Tools::getValue('namePackItems'); + $pack_items = $this->getPackItems(); + } else { + $product->packItems = Pack::getItems($product->id, $this->context->language->id); + $pack_items = $this->getPackItems($product); + $input_namepack_items = ''; + $input_pack_items = ''; + foreach ($pack_items as $pack_item) { + $input_pack_items .= $pack_item['pack_quantity'].'x'.$pack_item['id'].'x'.$pack_item['id_product_attribute'].'-'; + $input_namepack_items .= $pack_item['pack_quantity'].' x '.$pack_item['name'].'¤'; + } + } + + $data->assign(array( + 'input_pack_items' => $input_pack_items, + 'input_namepack_items' => $input_namepack_items, + 'pack_items' => $pack_items, + 'product_type' => (int)Tools::getValue('type_product', $product->getType()) + )); + + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + public function initFormVirtualProduct($product) + { + $data = $this->createTemplate($this->tpl_form); + + $currency = $this->context->currency; + + /* + * Form for adding a virtual product like software, mp3, etc... + */ + $product_download = new ProductDownload(); + if ($id_product_download = $product_download->getIdFromIdProduct($this->getFieldValue($product, 'id'))) { + $product_download = new ProductDownload($id_product_download); + } + $product->{'productDownload'} = $product_download; + + if ($product->productDownload->id && empty($product->productDownload->display_filename)) { + $this->errors[] = Tools::displayError('A file name is required in order to associate a file'); + $this->tab_display = 'VirtualProduct'; + } + + // @todo handle is_virtual with the value of the product + $exists_file = realpath(_PS_DOWNLOAD_DIR_).'/'.$product->productDownload->filename; + $data->assign('product_downloaded', $product->productDownload->id); + + if (!file_exists($exists_file) + && !empty($product->productDownload->display_filename) + && empty($product->cache_default_attribute)) { + $msg = sprintf(Tools::displayError('File "%s" is missing'), + $product->productDownload->display_filename); + } else { + $msg = ''; + } + + $virtual_product_file_uploader = new HelperUploader('virtual_product_file_uploader'); + $virtual_product_file_uploader->setMultiple(false)->setUrl( + Context::getContext()->link->getAdminLink('AdminProducts').'&ajax=1&id_product='.(int)$product->id + .'&action=AddVirtualProductFile')->setPostMaxSize(Tools::getOctets(ini_get('upload_max_filesize'))) + ->setTemplate('virtual_product.tpl'); + + $data->assign(array( + 'download_product_file_missing' => $msg, + 'download_dir_writable' => ProductDownload::checkWritableDir(), + 'up_filename' => strval(Tools::getValue('virtual_product_filename')) + )); + + $product->productDownload->nb_downloadable = ($product->productDownload->id > 0) ? $product->productDownload->nb_downloadable : htmlentities(Tools::getValue('virtual_product_nb_downloable'), ENT_COMPAT, 'UTF-8'); + $product->productDownload->date_expiration = ($product->productDownload->id > 0) ? ((!empty($product->productDownload->date_expiration) && $product->productDownload->date_expiration != '0000-00-00 00:00:00') ? date('Y-m-d', strtotime($product->productDownload->date_expiration)) : '') : htmlentities(Tools::getValue('virtual_product_expiration_date'), ENT_COMPAT, 'UTF-8'); + $product->productDownload->nb_days_accessible = ($product->productDownload->id > 0) ? $product->productDownload->nb_days_accessible : htmlentities(Tools::getValue('virtual_product_nb_days'), ENT_COMPAT, 'UTF-8'); + $product->productDownload->is_shareable = $product->productDownload->id > 0 && $product->productDownload->is_shareable; + + $iso_tiny_mce = $this->context->language->iso_code; + $iso_tiny_mce = (file_exists(_PS_JS_DIR_.'tiny_mce/langs/'.$iso_tiny_mce.'.js') ? $iso_tiny_mce : 'en'); + $data->assign(array( + 'ad' => __PS_BASE_URI__.basename(_PS_ADMIN_DIR_), + 'iso_tiny_mce' => $iso_tiny_mce, + 'product' => $product, + 'token' => $this->token, + 'currency' => $currency, + 'link' => $this->context->link, + 'is_file' => $product->productDownload->checkFile(), + 'virtual_product_file_uploader' => $virtual_product_file_uploader->render() + )); + $data->assign($this->tpl_form_vars); + $this->tpl_form_vars['product'] = $product; + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + protected function _getFinalPrice($specific_price, $product_price, $tax_rate) + { + return $this->object->getPrice(false, $specific_price['id_product_attribute'], 2); + } + + protected function _displaySpecificPriceModificationForm($defaultCurrency, $shops, $currencies, $countries, $groups) + { + /** @var Product $obj */ + if (!($obj = $this->loadObject())) { + return; + } + + $page = (int)Tools::getValue('page'); + $content = ''; + $specific_prices = SpecificPrice::getByProductId((int)$obj->id); + $specific_price_priorities = SpecificPrice::getPriority((int)$obj->id); + + $tmp = array(); + foreach ($shops as $shop) { + $tmp[$shop['id_shop']] = $shop; + } + $shops = $tmp; + $tmp = array(); + foreach ($currencies as $currency) { + $tmp[$currency['id_currency']] = $currency; + } + $currencies = $tmp; + + $tmp = array(); + foreach ($countries as $country) { + $tmp[$country['id_country']] = $country; + } + $countries = $tmp; + + $tmp = array(); + foreach ($groups as $group) { + $tmp[$group['id_group']] = $group; + } + $groups = $tmp; + + $length_before = strlen($content); + if (is_array($specific_prices) && count($specific_prices)) { + $i = 0; + foreach ($specific_prices as $specific_price) { + $id_currency = $specific_price['id_currency'] ? $specific_price['id_currency'] : $defaultCurrency->id; + if (!isset($currencies[$id_currency])) { + continue; + } + + $current_specific_currency = $currencies[$id_currency]; + if ($specific_price['reduction_type'] == 'percentage') { + $impact = '- '.($specific_price['reduction'] * 100).' %'; + } elseif ($specific_price['reduction'] > 0) { + $impact = '- '.Tools::displayPrice(Tools::ps_round($specific_price['reduction'], 2), $current_specific_currency).' '; + if ($specific_price['reduction_tax']) { + $impact .= '('.$this->l('Tax incl.').')'; + } else { + $impact .= '('.$this->l('Tax excl.').')'; + } + } else { + $impact = '--'; + } + + if ($specific_price['from'] == '0000-00-00 00:00:00' && $specific_price['to'] == '0000-00-00 00:00:00') { + $period = $this->l('Unlimited'); + } else { + $period = $this->l('From').' '.($specific_price['from'] != '0000-00-00 00:00:00' ? $specific_price['from'] : '0000-00-00 00:00:00').'<br />'.$this->l('To').' '.($specific_price['to'] != '0000-00-00 00:00:00' ? $specific_price['to'] : '0000-00-00 00:00:00'); + } + if ($specific_price['id_product_attribute']) { + $combination = new Combination((int)$specific_price['id_product_attribute']); + $attributes = $combination->getAttributesName((int)$this->context->language->id); + $attributes_name = ''; + foreach ($attributes as $attribute) { + $attributes_name .= $attribute['name'].' - '; + } + $attributes_name = rtrim($attributes_name, ' - '); + } else { + $attributes_name = $this->l('All combinations'); + } + + $rule = new SpecificPriceRule((int)$specific_price['id_specific_price_rule']); + $rule_name = ($rule->id ? $rule->name : '--'); + + if ($specific_price['id_customer']) { + $customer = new Customer((int)$specific_price['id_customer']); + if (Validate::isLoadedObject($customer)) { + $customer_full_name = $customer->firstname.' '.$customer->lastname; + } + unset($customer); + } + + if (!$specific_price['id_shop'] || in_array($specific_price['id_shop'], Shop::getContextListShopID())) { + $content .= ' <tr '.($i % 2 ? 'class="alt_row"' : '').'> <td>'.$rule_name.'</td> <td>'.$attributes_name.'</td>'; - $can_delete_specific_prices = true; - if (Shop::isFeatureActive()) - { - $id_shop_sp = $specific_price['id_shop']; - $can_delete_specific_prices = (count($this->context->employee->getAssociatedShops()) > 1 && !$id_shop_sp) || $id_shop_sp; - $content .= ' + $can_delete_specific_prices = true; + if (Shop::isFeatureActive()) { + $id_shop_sp = $specific_price['id_shop']; + $can_delete_specific_prices = (count($this->context->employee->getAssociatedShops()) > 1 && !$id_shop_sp) || $id_shop_sp; + $content .= ' <td>'.($id_shop_sp ? $shops[$id_shop_sp]['name'] : $this->l('All shops')).'</td>'; - } - $price = Tools::ps_round($specific_price['price'], 2); - $fixed_price = ($price == Tools::ps_round($obj->price, 2) || $specific_price['price'] == -1) ? '--' : Tools::displayPrice($price, $current_specific_currency); - $content .= ' + } + $price = Tools::ps_round($specific_price['price'], 2); + $fixed_price = ($price == Tools::ps_round($obj->price, 2) || $specific_price['price'] == -1) ? '--' : Tools::displayPrice($price, $current_specific_currency); + $content .= ' <td>'.($specific_price['id_currency'] ? $currencies[$specific_price['id_currency']]['name'] : $this->l('All currencies')).'</td> <td>'.($specific_price['id_country'] ? $countries[$specific_price['id_country']]['name'] : $this->l('All countries')).'</td> <td>'.($specific_price['id_group'] ? $groups[$specific_price['id_group']]['name'] : $this->l('All groups')).'</td> @@ -3626,19 +3661,20 @@ class AdminProductsControllerCore extends AdminController <td>'.$specific_price['from_quantity'].'</th> <td>'.((!$rule->id && $can_delete_specific_prices) ? '<a class="btn btn-default" name="delete_link" href="'.self::$currentIndex.'&id_product='.(int)Tools::getValue('id_product').'&action=deleteSpecificPrice&id_specific_price='.(int)($specific_price['id_specific_price']).'&token='.Tools::getValue('token').'"><i class="icon-trash"></i></a>': '').'</td> </tr>'; - $i++; - unset($customer_full_name); - } - } - } + $i++; + unset($customer_full_name); + } + } + } - if ($length_before === strlen($content)) - $content .= ' + if ($length_before === strlen($content)) { + $content .= ' <tr> <td class="text-center" colspan="13"><i class="icon-warning-sign"></i> '.$this->l('No specific prices.').'</td> </tr>'; + } - $content .= ' + $content .= ' </tbody> </table> </div> @@ -3649,38 +3685,38 @@ class AdminProductsControllerCore extends AdminController </div> </div>'; - $content .= ' + $content .= ' <script type="text/javascript"> var currencies = new Array(); currencies[0] = new Array(); currencies[0]["sign"] = "'.$defaultCurrency->sign.'"; currencies[0]["format"] = '.intval($defaultCurrency->format).'; '; - foreach ($currencies as $currency) - { - $content .= ' + foreach ($currencies as $currency) { + $content .= ' currencies['.$currency['id_currency'].'] = new Array(); currencies['.$currency['id_currency'].']["sign"] = "'.$currency['sign'].'"; currencies['.$currency['id_currency'].']["format"] = '.intval($currency['format']).'; '; - } - $content .= ' + } + $content .= ' </script> '; - // Not use id_customer - if ($specific_price_priorities[0] == 'id_customer') - unset($specific_price_priorities[0]); - // Reindex array starting from 0 - $specific_price_priorities = array_values($specific_price_priorities); + // Not use id_customer + if ($specific_price_priorities[0] == 'id_customer') { + unset($specific_price_priorities[0]); + } + // Reindex array starting from 0 + $specific_price_priorities = array_values($specific_price_priorities); - $content .= '<div class="panel"> + $content .= '<div class="panel"> <h3>'.$this->l('Priority management').'</h3> <div class="alert alert-info"> '.$this->l('Sometimes one customer can fit into multiple price rules. Priorities allow you to define which rule applies to the customer.').' </div>'; - $content .= ' + $content .= ' <div class="form-group"> <label class="control-label col-lg-3" for="specificPricePriority1">'.$this->l('Priorities').'</label> <div class="input-group col-lg-9"> @@ -3727,1292 +3763,1313 @@ class AdminProductsControllerCore extends AdminController </div> </div> '; - return $content; - } - - protected function _getCustomizationFieldIds($labels, $alreadyGenerated, $obj) - { - $customizableFieldIds = array(); - if (isset($labels[Product::CUSTOMIZE_FILE])) - foreach ($labels[Product::CUSTOMIZE_FILE] as $id_customization_field => $label) - $customizableFieldIds[] = 'label_'.Product::CUSTOMIZE_FILE.'_'.(int)($id_customization_field); - if (isset($labels[Product::CUSTOMIZE_TEXTFIELD])) - foreach ($labels[Product::CUSTOMIZE_TEXTFIELD] as $id_customization_field => $label) - $customizableFieldIds[] = 'label_'.Product::CUSTOMIZE_TEXTFIELD.'_'.(int)($id_customization_field); - $j = 0; - for ($i = $alreadyGenerated[Product::CUSTOMIZE_FILE]; $i < (int)($this->getFieldValue($obj, 'uploadable_files')); $i++) - $customizableFieldIds[] = 'newLabel_'.Product::CUSTOMIZE_FILE.'_'.$j++; - $j = 0; - for ($i = $alreadyGenerated[Product::CUSTOMIZE_TEXTFIELD]; $i < (int)($this->getFieldValue($obj, 'text_fields')); $i++) - $customizableFieldIds[] = 'newLabel_'.Product::CUSTOMIZE_TEXTFIELD.'_'.$j++; - return implode('¤', $customizableFieldIds); - } - - protected function _displayLabelField(&$label, $languages, $default_language, $type, $fieldIds, $id_customization_field) - { - foreach ($languages as $language) - $input_value[$language['id_lang']] = (isset($label[(int)($language['id_lang'])])) ? $label[(int)($language['id_lang'])]['name'] : ''; - - $required = (isset($label[(int)($language['id_lang'])])) ? $label[(int)($language['id_lang'])]['required'] : false; - - $template = $this->context->smarty->createTemplate('controllers/products/input_text_lang.tpl', - $this->context->smarty); - return '<div class="form-group">' - .'<div class="col-lg-6">' - .$template->assign(array( - 'languages' => $languages, - 'input_name' => 'label_'.$type.'_'.(int)($id_customization_field), - 'input_value' => $input_value - ))->fetch() - .'</div>' - .'<div class="col-lg-6">' - .'<div class="checkbox">' - .'<label for="require_'.$type.'_'.(int)($id_customization_field).'">' - .'<input type="checkbox" name="require_'.$type.'_'.(int)($id_customization_field).'" id="require_'.$type.'_'.(int)($id_customization_field).'" value="1" '.($required ? 'checked="checked"' : '').'/>' - .$this->l('Required') - .'</label>' - .'</div>' - .'</div>' - .'</div>'; - } - - protected function _displayLabelFields(&$obj, &$labels, $languages, $default_language, $type) - { - $content = ''; - $type = (int)($type); - $labelGenerated = array(Product::CUSTOMIZE_FILE => (isset($labels[Product::CUSTOMIZE_FILE]) ? count($labels[Product::CUSTOMIZE_FILE]) : 0), Product::CUSTOMIZE_TEXTFIELD => (isset($labels[Product::CUSTOMIZE_TEXTFIELD]) ? count($labels[Product::CUSTOMIZE_TEXTFIELD]) : 0)); - - $fieldIds = $this->_getCustomizationFieldIds($labels, $labelGenerated, $obj); - if (isset($labels[$type])) - foreach ($labels[$type] as $id_customization_field => $label) - $content .= $this->_displayLabelField($label, $languages, $default_language, $type, $fieldIds, (int)($id_customization_field)); - return $content; - } - - /** - * @param Product $obj - * @throws Exception - * @throws SmartyException - */ - public function initFormCustomization($obj) - { - $data = $this->createTemplate($this->tpl_form); - - if ((bool)$obj->id) - { - if ($this->product_exists_in_shop) - { - $labels = $obj->getCustomizationFields(); - - $has_file_labels = (int)$this->getFieldValue($obj, 'uploadable_files'); - $has_text_labels = (int)$this->getFieldValue($obj, 'text_fields'); - - $data->assign(array( - 'obj' => $obj, - 'table' => $this->table, - 'languages' => $this->_languages, - 'has_file_labels' => $has_file_labels, - 'display_file_labels' => $this->_displayLabelFields($obj, $labels, $this->_languages, Configuration::get('PS_LANG_DEFAULT'), Product::CUSTOMIZE_FILE), - 'has_text_labels' => $has_text_labels, - 'display_text_labels' => $this->_displayLabelFields($obj, $labels, $this->_languages, Configuration::get('PS_LANG_DEFAULT'), Product::CUSTOMIZE_TEXTFIELD), - 'uploadable_files' => (int)($this->getFieldValue($obj, 'uploadable_files') ? (int)$this->getFieldValue($obj, 'uploadable_files') : '0'), - 'text_fields' => (int)($this->getFieldValue($obj, 'text_fields') ? (int)$this->getFieldValue($obj, 'text_fields') : '0'), - )); - } - else - $this->displayWarning($this->l('You must save the product in this shop before adding customization.')); - } - else - $this->displayWarning($this->l('You must save this product before adding customization.')); - - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - public function initFormAttachments($obj) - { - if (!$this->default_form_language) - $this->getLanguages(); - - $data = $this->createTemplate($this->tpl_form); - $data->assign('default_form_language', $this->default_form_language); - - if ((bool)$obj->id) - { - if ($this->product_exists_in_shop) - { - $attachment_name = array(); - $attachment_description = array(); - foreach ($this->_languages as $language) - { - $attachment_name[$language['id_lang']] = ''; - $attachment_description[$language['id_lang']] = ''; - } - - $iso_tiny_mce = $this->context->language->iso_code; - $iso_tiny_mce = (file_exists(_PS_JS_DIR_.'tiny_mce/langs/'.$iso_tiny_mce.'.js') ? $iso_tiny_mce : 'en'); - - $attachment_uploader = new HelperUploader('attachment_file'); - $attachment_uploader->setMultiple(false)->setUseAjax(true)->setUrl( - Context::getContext()->link->getAdminLink('AdminProducts').'&ajax=1&id_product='.(int)$obj->id - .'&action=AddAttachment')->setPostMaxSize((Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024 * 1024)) - ->setTemplate('attachment_ajax.tpl'); - - $data->assign(array( - 'obj' => $obj, - 'table' => $this->table, - 'ad' => __PS_BASE_URI__.basename(_PS_ADMIN_DIR_), - 'iso_tiny_mce' => $iso_tiny_mce, - 'languages' => $this->_languages, - 'id_lang' => $this->context->language->id, - 'attach1' => Attachment::getAttachments($this->context->language->id, $obj->id, true), - 'attach2' => Attachment::getAttachments($this->context->language->id, $obj->id, false), - 'default_form_language' => (int)Configuration::get('PS_LANG_DEFAULT'), - 'attachment_name' => $attachment_name, - 'attachment_description' => $attachment_description, - 'attachment_uploader' => $attachment_uploader->render() - )); - } - else - $this->displayWarning($this->l('You must save the product in this shop before adding attachements.')); - } - else - $this->displayWarning($this->l('You must save this product before adding attachements.')); - - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - /** - * @param Product $product - * @throws Exception - * @throws SmartyException - */ - public function initFormInformations($product) - { - if (!$this->default_form_language) - $this->getLanguages(); - - $data = $this->createTemplate($this->tpl_form); - - $currency = $this->context->currency; - - $data->assign(array( - 'languages' => $this->_languages, - 'default_form_language' => $this->default_form_language, - 'currency' => $currency - )); - $this->object = $product; - //$this->display = 'edit'; - $data->assign('product_name_redirected', Product::getProductName((int)$product->id_product_redirected, null, (int)$this->context->language->id)); - /* - * Form for adding a virtual product like software, mp3, etc... - */ - $product_download = new ProductDownload(); - if ($id_product_download = $product_download->getIdFromIdProduct($this->getFieldValue($product, 'id'))) - $product_download = new ProductDownload($id_product_download); - - $product->{'productDownload'} = $product_download; - - $product_props = array(); - // global informations - array_push($product_props, 'reference', 'ean13', 'upc', - 'available_for_order', 'show_price', 'online_only', - 'id_manufacturer' - ); - - // specific / detailled information - array_push($product_props, - // physical product - 'width', 'height', 'weight', 'active', - // virtual product - 'is_virtual', 'cache_default_attribute', - // customization - 'uploadable_files', 'text_fields' - ); - // prices - array_push($product_props, - 'price', 'wholesale_price', 'id_tax_rules_group', 'unit_price_ratio', 'on_sale', - 'unity', 'minimum_quantity', 'additional_shipping_cost', - 'available_now', 'available_later', 'available_date' - ); - - if (Configuration::get('PS_USE_ECOTAX')) - array_push($product_props, 'ecotax'); - - foreach ($product_props as $prop) - $product->$prop = $this->getFieldValue($product, $prop); - - $product->name['class'] = 'updateCurrentText'; - if (!$product->id || Configuration::get('PS_FORCE_FRIENDLY_PRODUCT')) - $product->name['class'] .= ' copy2friendlyUrl'; - - $images = Image::getImages($this->context->language->id, $product->id); - - if (is_array($images)) - { - foreach ($images as $k => $image) - $images[$k]['src'] = $this->context->link->getImageLink($product->link_rewrite[$this->context->language->id], $product->id.'-'.$image['id_image'], ImageType::getFormatedName('small')); - $data->assign('images', $images); - } - $data->assign('imagesTypes', ImageType::getImagesTypes('products')); - - $product->tags = Tag::getProductTags($product->id); - - $data->assign('product_type', (int)Tools::getValue('type_product', $product->getType())); - $data->assign('is_in_pack', (int)Pack::isPacked($product->id)); - - $check_product_association_ajax = false; - if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL) - $check_product_association_ajax = true; - - // TinyMCE - $iso_tiny_mce = $this->context->language->iso_code; - $iso_tiny_mce = (file_exists(_PS_ROOT_DIR_.'/js/tiny_mce/langs/'.$iso_tiny_mce.'.js') ? $iso_tiny_mce : 'en'); - $data->assign(array( - 'ad' => dirname($_SERVER['PHP_SELF']), - 'iso_tiny_mce' => $iso_tiny_mce, - 'check_product_association_ajax' => $check_product_association_ajax, - 'id_lang' => $this->context->language->id, - 'product' => $product, - 'token' => $this->token, - 'currency' => $currency, - 'link' => $this->context->link, - 'PS_PRODUCT_SHORT_DESC_LIMIT' => Configuration::get('PS_PRODUCT_SHORT_DESC_LIMIT') ? Configuration::get('PS_PRODUCT_SHORT_DESC_LIMIT') : 400 - )); - $data->assign($this->tpl_form_vars); - - $this->tpl_form_vars['product'] = $product; - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - public function initFormShipping($obj) - { - $data = $this->createTemplate($this->tpl_form); - $data->assign(array( - 'product' => $obj, - 'ps_dimension_unit' => Configuration::get('PS_DIMENSION_UNIT'), - 'ps_weight_unit' => Configuration::get('PS_WEIGHT_UNIT'), - 'carrier_list' => $this->getCarrierList(), - 'currency' => $this->context->currency, - 'country_display_tax_label' => $this->context->country->display_tax_label - )); - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - protected function getCarrierList() - { - $carrier_list = Carrier::getCarriers($this->context->language->id, false, false, false, null, Carrier::ALL_CARRIERS); - - if ($product = $this->loadObject(true)) - { - /** @var Product $product */ - $carrier_selected_list = $product->getCarriers(); - foreach ($carrier_list as &$carrier) - foreach ($carrier_selected_list as $carrier_selected) - if ($carrier_selected['id_reference'] == $carrier['id_reference']) - { - $carrier['selected'] = true; - continue; - } - } - return $carrier_list; - } - - protected function addCarriers($product = null) - { - if (!isset($product)) - $product = new Product((int)Tools::getValue('id_product')); - - if (Validate::isLoadedObject($product)) - { - $carriers = array(); - - if (Tools::getValue('selectedCarriers')) - $carriers = Tools::getValue('selectedCarriers'); - - $product->setCarriers($carriers); - } - } - - public function ajaxProcessaddProductImage() - { - self::$currentIndex = 'index.php?tab=AdminProducts'; - $product = new Product((int)Tools::getValue('id_product')); - $legends = Tools::getValue('legend'); - - if (!is_array($legends)) - $legends = (array)$legends; - - if (!Validate::isLoadedObject($product)) - { - $files = array(); - $files[0]['error'] = Tools::displayError('Cannot add image because product creation failed.'); - } - - $image_uploader = new HelperImageUploader('file'); - $image_uploader->setAcceptTypes(array('jpeg', 'gif', 'png', 'jpg'))->setMaxSize($this->max_image_size); - $files = $image_uploader->process(); - - foreach ($files as &$file) - { - $image = new Image(); - $image->id_product = (int)($product->id); - $image->position = Image::getHighestPosition($product->id) + 1; - - foreach ($legends as $key => $legend) - if (!empty($legend)) - $image->legend[(int)$key] = $legend; - - if (!Image::getCover($image->id_product)) - $image->cover = 1; - else - $image->cover = 0; - - if (($validate = $image->validateFieldsLang(false, true)) !== true) - $file['error'] = Tools::displayError($validate); - - if (isset($file['error']) && (!is_numeric($file['error']) || $file['error'] != 0)) - continue; - - if (!$image->add()) - $file['error'] = Tools::displayError('Error while creating additional image'); - else - { - if (!$new_path = $image->getPathForCreation()) - { - $file['error'] = Tools::displayError('An error occurred during new folder creation'); - continue; - } - - $error = 0; - - if (!ImageManager::resize($file['save_path'], $new_path.'.'.$image->image_format, null, null, 'jpg', false, $error)) - { - switch ($error) - { - case ImageManager::ERROR_FILE_NOT_EXIST : - $file['error'] = Tools::displayError('An error occurred while copying image, the file does not exist anymore.'); - break; - - case ImageManager::ERROR_FILE_WIDTH : - $file['error'] = Tools::displayError('An error occurred while copying image, the file width is 0px.'); - break; - - case ImageManager::ERROR_MEMORY_LIMIT : - $file['error'] = Tools::displayError('An error occurred while copying image, check your memory limit.'); - break; - - default: - $file['error'] = Tools::displayError('An error occurred while copying image.'); - break; - } - continue; - } - else - { - $imagesTypes = ImageType::getImagesTypes('products'); - $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); - - foreach ($imagesTypes as $imageType) - { - if (!ImageManager::resize($file['save_path'], $new_path.'-'.stripslashes($imageType['name']).'.'.$image->image_format, $imageType['width'], $imageType['height'], $image->image_format)) - { - $file['error'] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']); - continue; - } - - if ($generate_hight_dpi_images) - if (!ImageManager::resize($file['save_path'], $new_path.'-'.stripslashes($imageType['name']).'2x.'.$image->image_format, (int)$imageType['width']*2, (int)$imageType['height']*2, $image->image_format)) - { - $file['error'] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']); - continue; - } - } - } - - unlink($file['save_path']); - //Necesary to prevent hacking - unset($file['save_path']); - Hook::exec('actionWatermark', array('id_image' => $image->id, 'id_product' => $product->id)); - - if (!$image->update()) - { - $file['error'] = Tools::displayError('Error while updating status'); - continue; - } - - // Associate image to shop from context - $shops = Shop::getContextListShopID(); - $image->associateTo($shops); - $json_shops = array(); - - foreach ($shops as $id_shop) - $json_shops[$id_shop] = true; - - $file['status'] = 'ok'; - $file['id'] = $image->id; - $file['position'] = $image->position; - $file['cover'] = $image->cover; - $file['legend'] = $image->legend; - $file['path'] = $image->getExistingImgPath(); - $file['shops'] = $json_shops; - - @unlink(_PS_TMP_IMG_DIR_.'product_'.(int)$product->id.'.jpg'); - @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.(int)$product->id.'_'.$this->context->shop->id.'.jpg'); - } - } - - die(Tools::jsonEncode(array($image_uploader->getName() => $files))); - } - - /** - * @param Product $obj - * @throws Exception - * @throws SmartyException - */ - public function initFormImages($obj) - { - $data = $this->createTemplate($this->tpl_form); - - if ((bool)$obj->id) - { - if ($this->product_exists_in_shop) - { - $data->assign('product', $this->loadObject()); - - $shops = false; - if (Shop::isFeatureActive()) - $shops = Shop::getShops(); - - if ($shops) - foreach ($shops as $key => $shop) - if (!$obj->isAssociatedToShop($shop['id_shop'])) - unset($shops[$key]); - - $data->assign('shops', $shops); - - $count_images = Db::getInstance()->getValue(' + return $content; + } + + protected function _getCustomizationFieldIds($labels, $alreadyGenerated, $obj) + { + $customizableFieldIds = array(); + if (isset($labels[Product::CUSTOMIZE_FILE])) { + foreach ($labels[Product::CUSTOMIZE_FILE] as $id_customization_field => $label) { + $customizableFieldIds[] = 'label_'.Product::CUSTOMIZE_FILE.'_'.(int)($id_customization_field); + } + } + if (isset($labels[Product::CUSTOMIZE_TEXTFIELD])) { + foreach ($labels[Product::CUSTOMIZE_TEXTFIELD] as $id_customization_field => $label) { + $customizableFieldIds[] = 'label_'.Product::CUSTOMIZE_TEXTFIELD.'_'.(int)($id_customization_field); + } + } + $j = 0; + for ($i = $alreadyGenerated[Product::CUSTOMIZE_FILE]; $i < (int)($this->getFieldValue($obj, 'uploadable_files')); $i++) { + $customizableFieldIds[] = 'newLabel_'.Product::CUSTOMIZE_FILE.'_'.$j++; + } + $j = 0; + for ($i = $alreadyGenerated[Product::CUSTOMIZE_TEXTFIELD]; $i < (int)($this->getFieldValue($obj, 'text_fields')); $i++) { + $customizableFieldIds[] = 'newLabel_'.Product::CUSTOMIZE_TEXTFIELD.'_'.$j++; + } + return implode('¤', $customizableFieldIds); + } + + protected function _displayLabelField(&$label, $languages, $default_language, $type, $fieldIds, $id_customization_field) + { + foreach ($languages as $language) { + $input_value[$language['id_lang']] = (isset($label[(int)($language['id_lang'])])) ? $label[(int)($language['id_lang'])]['name'] : ''; + } + + $required = (isset($label[(int)($language['id_lang'])])) ? $label[(int)($language['id_lang'])]['required'] : false; + + $template = $this->context->smarty->createTemplate('controllers/products/input_text_lang.tpl', + $this->context->smarty); + return '<div class="form-group">' + .'<div class="col-lg-6">' + .$template->assign(array( + 'languages' => $languages, + 'input_name' => 'label_'.$type.'_'.(int)($id_customization_field), + 'input_value' => $input_value + ))->fetch() + .'</div>' + .'<div class="col-lg-6">' + .'<div class="checkbox">' + .'<label for="require_'.$type.'_'.(int)($id_customization_field).'">' + .'<input type="checkbox" name="require_'.$type.'_'.(int)($id_customization_field).'" id="require_'.$type.'_'.(int)($id_customization_field).'" value="1" '.($required ? 'checked="checked"' : '').'/>' + .$this->l('Required') + .'</label>' + .'</div>' + .'</div>' + .'</div>'; + } + + protected function _displayLabelFields(&$obj, &$labels, $languages, $default_language, $type) + { + $content = ''; + $type = (int)($type); + $labelGenerated = array(Product::CUSTOMIZE_FILE => (isset($labels[Product::CUSTOMIZE_FILE]) ? count($labels[Product::CUSTOMIZE_FILE]) : 0), Product::CUSTOMIZE_TEXTFIELD => (isset($labels[Product::CUSTOMIZE_TEXTFIELD]) ? count($labels[Product::CUSTOMIZE_TEXTFIELD]) : 0)); + + $fieldIds = $this->_getCustomizationFieldIds($labels, $labelGenerated, $obj); + if (isset($labels[$type])) { + foreach ($labels[$type] as $id_customization_field => $label) { + $content .= $this->_displayLabelField($label, $languages, $default_language, $type, $fieldIds, (int)($id_customization_field)); + } + } + return $content; + } + + /** + * @param Product $obj + * @throws Exception + * @throws SmartyException + */ + public function initFormCustomization($obj) + { + $data = $this->createTemplate($this->tpl_form); + + if ((bool)$obj->id) { + if ($this->product_exists_in_shop) { + $labels = $obj->getCustomizationFields(); + + $has_file_labels = (int)$this->getFieldValue($obj, 'uploadable_files'); + $has_text_labels = (int)$this->getFieldValue($obj, 'text_fields'); + + $data->assign(array( + 'obj' => $obj, + 'table' => $this->table, + 'languages' => $this->_languages, + 'has_file_labels' => $has_file_labels, + 'display_file_labels' => $this->_displayLabelFields($obj, $labels, $this->_languages, Configuration::get('PS_LANG_DEFAULT'), Product::CUSTOMIZE_FILE), + 'has_text_labels' => $has_text_labels, + 'display_text_labels' => $this->_displayLabelFields($obj, $labels, $this->_languages, Configuration::get('PS_LANG_DEFAULT'), Product::CUSTOMIZE_TEXTFIELD), + 'uploadable_files' => (int)($this->getFieldValue($obj, 'uploadable_files') ? (int)$this->getFieldValue($obj, 'uploadable_files') : '0'), + 'text_fields' => (int)($this->getFieldValue($obj, 'text_fields') ? (int)$this->getFieldValue($obj, 'text_fields') : '0'), + )); + } else { + $this->displayWarning($this->l('You must save the product in this shop before adding customization.')); + } + } else { + $this->displayWarning($this->l('You must save this product before adding customization.')); + } + + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + public function initFormAttachments($obj) + { + if (!$this->default_form_language) { + $this->getLanguages(); + } + + $data = $this->createTemplate($this->tpl_form); + $data->assign('default_form_language', $this->default_form_language); + + if ((bool)$obj->id) { + if ($this->product_exists_in_shop) { + $attachment_name = array(); + $attachment_description = array(); + foreach ($this->_languages as $language) { + $attachment_name[$language['id_lang']] = ''; + $attachment_description[$language['id_lang']] = ''; + } + + $iso_tiny_mce = $this->context->language->iso_code; + $iso_tiny_mce = (file_exists(_PS_JS_DIR_.'tiny_mce/langs/'.$iso_tiny_mce.'.js') ? $iso_tiny_mce : 'en'); + + $attachment_uploader = new HelperUploader('attachment_file'); + $attachment_uploader->setMultiple(false)->setUseAjax(true)->setUrl( + Context::getContext()->link->getAdminLink('AdminProducts').'&ajax=1&id_product='.(int)$obj->id + .'&action=AddAttachment')->setPostMaxSize((Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024 * 1024)) + ->setTemplate('attachment_ajax.tpl'); + + $data->assign(array( + 'obj' => $obj, + 'table' => $this->table, + 'ad' => __PS_BASE_URI__.basename(_PS_ADMIN_DIR_), + 'iso_tiny_mce' => $iso_tiny_mce, + 'languages' => $this->_languages, + 'id_lang' => $this->context->language->id, + 'attach1' => Attachment::getAttachments($this->context->language->id, $obj->id, true), + 'attach2' => Attachment::getAttachments($this->context->language->id, $obj->id, false), + 'default_form_language' => (int)Configuration::get('PS_LANG_DEFAULT'), + 'attachment_name' => $attachment_name, + 'attachment_description' => $attachment_description, + 'attachment_uploader' => $attachment_uploader->render() + )); + } else { + $this->displayWarning($this->l('You must save the product in this shop before adding attachements.')); + } + } else { + $this->displayWarning($this->l('You must save this product before adding attachements.')); + } + + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + /** + * @param Product $product + * @throws Exception + * @throws SmartyException + */ + public function initFormInformations($product) + { + if (!$this->default_form_language) { + $this->getLanguages(); + } + + $data = $this->createTemplate($this->tpl_form); + + $currency = $this->context->currency; + + $data->assign(array( + 'languages' => $this->_languages, + 'default_form_language' => $this->default_form_language, + 'currency' => $currency + )); + $this->object = $product; + //$this->display = 'edit'; + $data->assign('product_name_redirected', Product::getProductName((int)$product->id_product_redirected, null, (int)$this->context->language->id)); + /* + * Form for adding a virtual product like software, mp3, etc... + */ + $product_download = new ProductDownload(); + if ($id_product_download = $product_download->getIdFromIdProduct($this->getFieldValue($product, 'id'))) { + $product_download = new ProductDownload($id_product_download); + } + + $product->{'productDownload'} = $product_download; + + $product_props = array(); + // global informations + array_push($product_props, 'reference', 'ean13', 'upc', + 'available_for_order', 'show_price', 'online_only', + 'id_manufacturer' + ); + + // specific / detailled information + array_push($product_props, + // physical product + 'width', 'height', 'weight', 'active', + // virtual product + 'is_virtual', 'cache_default_attribute', + // customization + 'uploadable_files', 'text_fields' + ); + // prices + array_push($product_props, + 'price', 'wholesale_price', 'id_tax_rules_group', 'unit_price_ratio', 'on_sale', + 'unity', 'minimum_quantity', 'additional_shipping_cost', + 'available_now', 'available_later', 'available_date' + ); + + if (Configuration::get('PS_USE_ECOTAX')) { + array_push($product_props, 'ecotax'); + } + + foreach ($product_props as $prop) { + $product->$prop = $this->getFieldValue($product, $prop); + } + + $product->name['class'] = 'updateCurrentText'; + if (!$product->id || Configuration::get('PS_FORCE_FRIENDLY_PRODUCT')) { + $product->name['class'] .= ' copy2friendlyUrl'; + } + + $images = Image::getImages($this->context->language->id, $product->id); + + if (is_array($images)) { + foreach ($images as $k => $image) { + $images[$k]['src'] = $this->context->link->getImageLink($product->link_rewrite[$this->context->language->id], $product->id.'-'.$image['id_image'], ImageType::getFormatedName('small')); + } + $data->assign('images', $images); + } + $data->assign('imagesTypes', ImageType::getImagesTypes('products')); + + $product->tags = Tag::getProductTags($product->id); + + $data->assign('product_type', (int)Tools::getValue('type_product', $product->getType())); + $data->assign('is_in_pack', (int)Pack::isPacked($product->id)); + + $check_product_association_ajax = false; + if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL) { + $check_product_association_ajax = true; + } + + // TinyMCE + $iso_tiny_mce = $this->context->language->iso_code; + $iso_tiny_mce = (file_exists(_PS_ROOT_DIR_.'/js/tiny_mce/langs/'.$iso_tiny_mce.'.js') ? $iso_tiny_mce : 'en'); + $data->assign(array( + 'ad' => dirname($_SERVER['PHP_SELF']), + 'iso_tiny_mce' => $iso_tiny_mce, + 'check_product_association_ajax' => $check_product_association_ajax, + 'id_lang' => $this->context->language->id, + 'product' => $product, + 'token' => $this->token, + 'currency' => $currency, + 'link' => $this->context->link, + 'PS_PRODUCT_SHORT_DESC_LIMIT' => Configuration::get('PS_PRODUCT_SHORT_DESC_LIMIT') ? Configuration::get('PS_PRODUCT_SHORT_DESC_LIMIT') : 400 + )); + $data->assign($this->tpl_form_vars); + + $this->tpl_form_vars['product'] = $product; + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + public function initFormShipping($obj) + { + $data = $this->createTemplate($this->tpl_form); + $data->assign(array( + 'product' => $obj, + 'ps_dimension_unit' => Configuration::get('PS_DIMENSION_UNIT'), + 'ps_weight_unit' => Configuration::get('PS_WEIGHT_UNIT'), + 'carrier_list' => $this->getCarrierList(), + 'currency' => $this->context->currency, + 'country_display_tax_label' => $this->context->country->display_tax_label + )); + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + protected function getCarrierList() + { + $carrier_list = Carrier::getCarriers($this->context->language->id, false, false, false, null, Carrier::ALL_CARRIERS); + + if ($product = $this->loadObject(true)) { + /** @var Product $product */ + $carrier_selected_list = $product->getCarriers(); + foreach ($carrier_list as &$carrier) { + foreach ($carrier_selected_list as $carrier_selected) { + if ($carrier_selected['id_reference'] == $carrier['id_reference']) { + $carrier['selected'] = true; + continue; + } + } + } + } + return $carrier_list; + } + + protected function addCarriers($product = null) + { + if (!isset($product)) { + $product = new Product((int)Tools::getValue('id_product')); + } + + if (Validate::isLoadedObject($product)) { + $carriers = array(); + + if (Tools::getValue('selectedCarriers')) { + $carriers = Tools::getValue('selectedCarriers'); + } + + $product->setCarriers($carriers); + } + } + + public function ajaxProcessaddProductImage() + { + self::$currentIndex = 'index.php?tab=AdminProducts'; + $product = new Product((int)Tools::getValue('id_product')); + $legends = Tools::getValue('legend'); + + if (!is_array($legends)) { + $legends = (array)$legends; + } + + if (!Validate::isLoadedObject($product)) { + $files = array(); + $files[0]['error'] = Tools::displayError('Cannot add image because product creation failed.'); + } + + $image_uploader = new HelperImageUploader('file'); + $image_uploader->setAcceptTypes(array('jpeg', 'gif', 'png', 'jpg'))->setMaxSize($this->max_image_size); + $files = $image_uploader->process(); + + foreach ($files as &$file) { + $image = new Image(); + $image->id_product = (int)($product->id); + $image->position = Image::getHighestPosition($product->id) + 1; + + foreach ($legends as $key => $legend) { + if (!empty($legend)) { + $image->legend[(int)$key] = $legend; + } + } + + if (!Image::getCover($image->id_product)) { + $image->cover = 1; + } else { + $image->cover = 0; + } + + if (($validate = $image->validateFieldsLang(false, true)) !== true) { + $file['error'] = Tools::displayError($validate); + } + + if (isset($file['error']) && (!is_numeric($file['error']) || $file['error'] != 0)) { + continue; + } + + if (!$image->add()) { + $file['error'] = Tools::displayError('Error while creating additional image'); + } else { + if (!$new_path = $image->getPathForCreation()) { + $file['error'] = Tools::displayError('An error occurred during new folder creation'); + continue; + } + + $error = 0; + + if (!ImageManager::resize($file['save_path'], $new_path.'.'.$image->image_format, null, null, 'jpg', false, $error)) { + switch ($error) { + case ImageManager::ERROR_FILE_NOT_EXIST : + $file['error'] = Tools::displayError('An error occurred while copying image, the file does not exist anymore.'); + break; + + case ImageManager::ERROR_FILE_WIDTH : + $file['error'] = Tools::displayError('An error occurred while copying image, the file width is 0px.'); + break; + + case ImageManager::ERROR_MEMORY_LIMIT : + $file['error'] = Tools::displayError('An error occurred while copying image, check your memory limit.'); + break; + + default: + $file['error'] = Tools::displayError('An error occurred while copying image.'); + break; + } + continue; + } else { + $imagesTypes = ImageType::getImagesTypes('products'); + $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); + + foreach ($imagesTypes as $imageType) { + if (!ImageManager::resize($file['save_path'], $new_path.'-'.stripslashes($imageType['name']).'.'.$image->image_format, $imageType['width'], $imageType['height'], $image->image_format)) { + $file['error'] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']); + continue; + } + + if ($generate_hight_dpi_images) { + if (!ImageManager::resize($file['save_path'], $new_path.'-'.stripslashes($imageType['name']).'2x.'.$image->image_format, (int)$imageType['width']*2, (int)$imageType['height']*2, $image->image_format)) { + $file['error'] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']); + continue; + } + } + } + } + + unlink($file['save_path']); + //Necesary to prevent hacking + unset($file['save_path']); + Hook::exec('actionWatermark', array('id_image' => $image->id, 'id_product' => $product->id)); + + if (!$image->update()) { + $file['error'] = Tools::displayError('Error while updating status'); + continue; + } + + // Associate image to shop from context + $shops = Shop::getContextListShopID(); + $image->associateTo($shops); + $json_shops = array(); + + foreach ($shops as $id_shop) { + $json_shops[$id_shop] = true; + } + + $file['status'] = 'ok'; + $file['id'] = $image->id; + $file['position'] = $image->position; + $file['cover'] = $image->cover; + $file['legend'] = $image->legend; + $file['path'] = $image->getExistingImgPath(); + $file['shops'] = $json_shops; + + @unlink(_PS_TMP_IMG_DIR_.'product_'.(int)$product->id.'.jpg'); + @unlink(_PS_TMP_IMG_DIR_.'product_mini_'.(int)$product->id.'_'.$this->context->shop->id.'.jpg'); + } + } + + die(Tools::jsonEncode(array($image_uploader->getName() => $files))); + } + + /** + * @param Product $obj + * @throws Exception + * @throws SmartyException + */ + public function initFormImages($obj) + { + $data = $this->createTemplate($this->tpl_form); + + if ((bool)$obj->id) { + if ($this->product_exists_in_shop) { + $data->assign('product', $this->loadObject()); + + $shops = false; + if (Shop::isFeatureActive()) { + $shops = Shop::getShops(); + } + + if ($shops) { + foreach ($shops as $key => $shop) { + if (!$obj->isAssociatedToShop($shop['id_shop'])) { + unset($shops[$key]); + } + } + } + + $data->assign('shops', $shops); + + $count_images = Db::getInstance()->getValue(' SELECT COUNT(id_product) FROM '._DB_PREFIX_.'image WHERE id_product = '.(int)$obj->id - ); - - $images = Image::getImages($this->context->language->id, $obj->id); - foreach ($images as $k => $image) - $images[$k] = new Image($image['id_image']); - - - if ($this->context->shop->getContext() == Shop::CONTEXT_SHOP) - $current_shop_id = (int)$this->context->shop->id; - else - $current_shop_id = 0; - - $languages = Language::getLanguages(true); - $image_uploader = new HelperImageUploader('file'); - $image_uploader->setMultiple(!(Tools::getUserBrowser() == 'Apple Safari' && Tools::getUserPlatform() == 'Windows')) - ->setUseAjax(true)->setUrl( - Context::getContext()->link->getAdminLink('AdminProducts').'&ajax=1&id_product='.(int)$obj->id - .'&action=addProductImage'); - - $data->assign(array( - 'countImages' => $count_images, - 'id_product' => (int)Tools::getValue('id_product'), - 'id_category_default' => (int)$this->_category->id, - 'images' => $images, - 'iso_lang' => $languages[0]['iso_code'], - 'token' => $this->token, - 'table' => $this->table, - 'max_image_size' => $this->max_image_size / 1024 / 1024, - 'up_filename' => (string)Tools::getValue('virtual_product_filename_attribute'), - 'currency' => $this->context->currency, - 'current_shop_id' => $current_shop_id, - 'languages' => $this->_languages, - 'default_language' => (int)Configuration::get('PS_LANG_DEFAULT'), - 'image_uploader' => $image_uploader->render() - )); - - $type = ImageType::getByNameNType('%', 'products', 'height'); - if (isset($type['name'])) - $data->assign('imageType', $type['name']); - else - $data->assign('imageType', ImageType::getFormatedName('small')); - } - else - $this->displayWarning($this->l('You must save the product in this shop before adding images.')); - } - else - $this->displayWarning($this->l('You must save this product before adding images.')); - - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - public function initFormCombinations($obj) - { - return $this->initFormAttributes($obj); - } - - /** - * @param Product $product - * @throws Exception - * @throws SmartyException - */ - public function initFormAttributes($product) - { - $data = $this->createTemplate($this->tpl_form); - if (!Combination::isFeatureActive()) - $this->displayWarning($this->l('This feature has been disabled. '). - ' <a href="index.php?tab=AdminPerformance&token='.Tools::getAdminTokenLite('AdminPerformance').'#featuresDetachables">'.$this->l('Performances').'</a>'); - elseif (Validate::isLoadedObject($product)) - { - if ($this->product_exists_in_shop) - { - if ($product->is_virtual) - { - $data->assign('product', $product); - $this->displayWarning($this->l('A virtual product cannot have combinations.')); - } - else - { - $attribute_js = array(); - $attributes = Attribute::getAttributes($this->context->language->id, true); - foreach ($attributes as $k => $attribute) - { - $attribute_js[$attribute['id_attribute_group']][$attribute['id_attribute']] = $attribute['name']; - natsort($attribute_js[$attribute['id_attribute_group']]); - } - - $currency = $this->context->currency; - - $data->assign('attributeJs', $attribute_js); - $data->assign('attributes_groups', AttributeGroup::getAttributesGroups($this->context->language->id)); - - $data->assign('currency', $currency); - - $images = Image::getImages($this->context->language->id, $product->id); - - $data->assign('tax_exclude_option', Tax::excludeTaxeOption()); - $data->assign('ps_weight_unit', Configuration::get('PS_WEIGHT_UNIT')); - - $data->assign('ps_use_ecotax', Configuration::get('PS_USE_ECOTAX')); - $data->assign('field_value_unity', $this->getFieldValue($product, 'unity')); - - $data->assign('reasons', $reasons = StockMvtReason::getStockMvtReasons($this->context->language->id)); - $data->assign('ps_stock_mvt_reason_default', $ps_stock_mvt_reason_default = Configuration::get('PS_STOCK_MVT_REASON_DEFAULT')); - $data->assign('minimal_quantity', $this->getFieldValue($product, 'minimal_quantity') ? $this->getFieldValue($product, 'minimal_quantity') : 1); - $data->assign('available_date', ($this->getFieldValue($product, 'available_date') != 0) ? stripslashes(htmlentities($this->getFieldValue($product, 'available_date'), $this->context->language->id)) : '0000-00-00'); - - $i = 0; - $type = ImageType::getByNameNType('%', 'products', 'height'); - if (isset($type['name'])) - $data->assign('imageType', $type['name']); - else - $data->assign('imageType', ImageType::getFormatedName('small')); - $data->assign('imageWidth', (isset($image_type['width']) ? (int)($image_type['width']) : 64) + 25); - foreach ($images as $k => $image) - { - $images[$k]['obj'] = new Image($image['id_image']); - ++$i; - } - $data->assign('images', $images); - - $data->assign($this->tpl_form_vars); - $data->assign(array( - 'list' => $this->renderListAttributes($product, $currency), - 'product' => $product, - 'id_category' => $product->getDefaultCategory(), - 'token_generator' => Tools::getAdminTokenLite('AdminAttributeGenerator'), - 'combination_exists' => (Shop::isFeatureActive() && (Shop::getContextShopGroup()->share_stock) && count(AttributeGroup::getAttributesGroups($this->context->language->id)) > 0 && $product->hasAttributes()) - )); - } - } - else - $this->displayWarning($this->l('You must save the product in this shop before adding combinations.')); - } - else - { - $data->assign('product', $product); - $this->displayWarning($this->l('You must save this product before adding combinations.')); - } - - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - /** - * @param Product $product - * @param Currency|array|int $currency - * @return string - */ - public function renderListAttributes($product, $currency) - { - $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?'))); - $this->addRowAction('edit'); - $this->addRowAction('default'); - $this->addRowAction('delete'); - - $default_class = 'highlighted'; - - $this->fields_list = array( - 'attributes' => array('title' => $this->l('Attribute - value pair'), 'align' => 'left'), - 'price' => array('title' => $this->l('Impact on price'), 'type' => 'price', 'align' => 'left'), - 'weight' => array('title' => $this->l('Impact on weight'), 'align' => 'left'), - 'reference' => array('title' => $this->l('Reference'), 'align' => 'left'), - 'ean13' => array('title' => $this->l('EAN-13'), 'align' => 'left'), - 'upc' => array('title' => $this->l('UPC'), 'align' => 'left') - ); - - if ($product->id) - { - /* Build attributes combinations */ - $combinations = $product->getAttributeCombinations($this->context->language->id); - $groups = array(); - $comb_array = array(); - if (is_array($combinations)) - { - $combination_images = $product->getCombinationImages($this->context->language->id); - foreach ($combinations as $k => $combination) - { - $price_to_convert = Tools::convertPrice($combination['price'], $currency); - $price = Tools::displayPrice($price_to_convert, $currency); - - $comb_array[$combination['id_product_attribute']]['id_product_attribute'] = $combination['id_product_attribute']; - $comb_array[$combination['id_product_attribute']]['attributes'][] = array($combination['group_name'], $combination['attribute_name'], $combination['id_attribute']); - $comb_array[$combination['id_product_attribute']]['wholesale_price'] = $combination['wholesale_price']; - $comb_array[$combination['id_product_attribute']]['price'] = $price; - $comb_array[$combination['id_product_attribute']]['weight'] = $combination['weight'].Configuration::get('PS_WEIGHT_UNIT'); - $comb_array[$combination['id_product_attribute']]['unit_impact'] = $combination['unit_price_impact']; - $comb_array[$combination['id_product_attribute']]['reference'] = $combination['reference']; - $comb_array[$combination['id_product_attribute']]['ean13'] = $combination['ean13']; - $comb_array[$combination['id_product_attribute']]['upc'] = $combination['upc']; - $comb_array[$combination['id_product_attribute']]['id_image'] = isset($combination_images[$combination['id_product_attribute']][0]['id_image']) ? $combination_images[$combination['id_product_attribute']][0]['id_image'] : 0; - $comb_array[$combination['id_product_attribute']]['available_date'] = strftime($combination['available_date']); - $comb_array[$combination['id_product_attribute']]['default_on'] = $combination['default_on']; - if ($combination['is_color_group']) - $groups[$combination['id_attribute_group']] = $combination['group_name']; - } - } - - if (isset($comb_array)) - { - foreach ($comb_array as $id_product_attribute => $product_attribute) - { - $list = ''; - - /* In order to keep the same attributes order */ - asort($product_attribute['attributes']); - - foreach ($product_attribute['attributes'] as $attribute) - $list .= $attribute[0].' - '.$attribute[1].', '; - - $list = rtrim($list, ', '); - $comb_array[$id_product_attribute]['image'] = $product_attribute['id_image'] ? new Image($product_attribute['id_image']) : false; - $comb_array[$id_product_attribute]['available_date'] = $product_attribute['available_date'] != 0 ? date('Y-m-d', strtotime($product_attribute['available_date'])) : '0000-00-00'; - $comb_array[$id_product_attribute]['attributes'] = $list; - $comb_array[$id_product_attribute]['name'] = $list; - - if ($product_attribute['default_on']) - $comb_array[$id_product_attribute]['class'] = $default_class; - } - } - } - - foreach ($this->actions_available as $action) - { - if (!in_array($action, $this->actions) && isset($this->$action) && $this->$action) - $this->actions[] = $action; - } - - $helper = new HelperList(); - $helper->identifier = 'id_product_attribute'; - $helper->table_id = 'combinations-list'; - $helper->token = $this->token; - $helper->currentIndex = self::$currentIndex; - $helper->no_link = true; - $helper->simple_header = true; - $helper->show_toolbar = false; - $helper->shopLinkType = $this->shopLinkType; - $helper->actions = $this->actions; - $helper->list_skip_actions = $this->list_skip_actions; - $helper->colorOnBackground = true; - $helper->override_folder = $this->tpl_folder.'combination/'; - - return $helper->generateList($comb_array, $this->fields_list); - } - - /** - * @param Product $obj - * @throws Exception - * @throws SmartyException - */ - public function initFormQuantities($obj) - { - if (!$this->default_form_language) - $this->getLanguages(); - - $data = $this->createTemplate($this->tpl_form); - $data->assign('default_form_language', $this->default_form_language); - - if ($obj->id) - { - if ($this->product_exists_in_shop) - { - // Get all id_product_attribute - $attributes = $obj->getAttributesResume($this->context->language->id); - if (empty($attributes)) - $attributes[] = array( - 'id_product_attribute' => 0, - 'attribute_designation' => '' - ); - - // Get available quantities - $available_quantity = array(); - $product_designation = array(); - - foreach ($attributes as $attribute) - { - // Get available quantity for the current product attribute in the current shop - $available_quantity[$attribute['id_product_attribute']] = isset($attribute['id_product_attribute']) && $attribute['id_product_attribute'] ? (int)$attribute['quantity'] : (int)$obj->quantity; - // Get all product designation - $product_designation[$attribute['id_product_attribute']] = rtrim( - $obj->name[$this->context->language->id].' - '.$attribute['attribute_designation'], - ' - ' - ); - } - - $show_quantities = true; - $shop_context = Shop::getContext(); - $shop_group = new ShopGroup((int)Shop::getContextShopGroupID()); - - // if we are in all shops context, it's not possible to manage quantities at this level - if (Shop::isFeatureActive() && $shop_context == Shop::CONTEXT_ALL) - $show_quantities = false; - // if we are in group shop context - elseif (Shop::isFeatureActive() && $shop_context == Shop::CONTEXT_GROUP) - { - // if quantities are not shared between shops of the group, it's not possible to manage them at group level - if (!$shop_group->share_stock) - $show_quantities = false; - } - // if we are in shop context - else - { - // if quantities are shared between shops of the group, it's not possible to manage them for a given shop - if ($shop_group->share_stock) - $show_quantities = false; - } - - $data->assign('ps_stock_management', Configuration::get('PS_STOCK_MANAGEMENT')); - $data->assign('has_attribute', $obj->hasAttributes()); - // Check if product has combination, to display the available date only for the product or for each combination - if (Combination::isFeatureActive()) - $data->assign('countAttributes', (int)Db::getInstance()->getValue('SELECT COUNT(id_product) FROM '._DB_PREFIX_.'product_attribute WHERE id_product = '.(int)$obj->id)); - else - $data->assign('countAttributes', false); - // if advanced stock management is active, checks associations - $advanced_stock_management_warning = false; - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $obj->advanced_stock_management) - { - $p_attributes = Product::getProductAttributesIds($obj->id); - $warehouses = array(); - - if (!$p_attributes) - $warehouses[] = Warehouse::getProductWarehouseList($obj->id, 0); - - foreach ($p_attributes as $p_attribute) - { - $ws = Warehouse::getProductWarehouseList($obj->id, $p_attribute['id_product_attribute']); - if ($ws) - $warehouses[] = $ws; - } - $warehouses = Tools::arrayUnique($warehouses); - - if (empty($warehouses)) - $advanced_stock_management_warning = true; - } - if ($advanced_stock_management_warning) - { - $this->displayWarning($this->l('If you wish to use the advanced stock management, you must:')); - $this->displayWarning('- '.$this->l('associate your products with warehouses.')); - $this->displayWarning('- '.$this->l('associate your warehouses with carriers.')); - $this->displayWarning('- '.$this->l('associate your warehouses with the appropriate shops.')); - } - - $pack_quantity = null; - // if product is a pack - if (Pack::isPack($obj->id)) - { - $items = Pack::getItems((int)$obj->id, Configuration::get('PS_LANG_DEFAULT')); - - // gets an array of quantities (quantity for the product / quantity in pack) - $pack_quantities = array(); - foreach ($items as $item) - { - /** @var Product $item */ - if (!$item->isAvailableWhenOutOfStock((int)$item->out_of_stock)) - { - $pack_id_product_attribute = Product::getDefaultAttribute($item->id, 1); - $pack_quantities[] = Product::getQuantity($item->id, $pack_id_product_attribute) / ($item->pack_quantity !== 0 ? $item->pack_quantity : 1); - } - } - - // gets the minimum - if (count($pack_quantities)) - { - $pack_quantity = $pack_quantities[0]; - foreach ($pack_quantities as $value) - { - if ($pack_quantity > $value) - $pack_quantity = $value; - } - } - - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && !Warehouse::getPackWarehouses((int)$obj->id)) - $this->displayWarning($this->l('You must have a common warehouse between this pack and its product.')); - } - - $data->assign(array( - 'attributes' => $attributes, - 'available_quantity' => $available_quantity, - 'pack_quantity' => $pack_quantity, - 'stock_management_active' => Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'), - 'product_designation' => $product_designation, - 'product' => $obj, - 'show_quantities' => $show_quantities, - 'order_out_of_stock' => Configuration::get('PS_ORDER_OUT_OF_STOCK'), - 'pack_stock_type' => Configuration::get('PS_PACK_STOCK_TYPE'), - 'token_preferences' => Tools::getAdminTokenLite('AdminPPreferences'), - 'token' => $this->token, - 'languages' => $this->_languages, - 'id_lang' => $this->context->language->id - )); - } - else - $this->displayWarning($this->l('You must save the product in this shop before managing quantities.')); - } - else - $this->displayWarning($this->l('You must save this product before managing quantities.')); - - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - /** - * @param Product $obj - * @throws Exception - * @throws SmartyException - */ - public function initFormSuppliers($obj) - { - $data = $this->createTemplate($this->tpl_form); - - if ($obj->id) - { - if ($this->product_exists_in_shop) - { - // Get all id_product_attribute - $attributes = $obj->getAttributesResume($this->context->language->id); - if (empty($attributes)) - $attributes[] = array( - 'id_product' => $obj->id, - 'id_product_attribute' => 0, - 'attribute_designation' => '' - ); - - $product_designation = array(); - - foreach ($attributes as $attribute) - $product_designation[$attribute['id_product_attribute']] = rtrim( - $obj->name[$this->context->language->id].' - '.$attribute['attribute_designation'], - ' - ' - ); - - // Get all available suppliers - $suppliers = Supplier::getSuppliers(); - - // Get already associated suppliers - $associated_suppliers = ProductSupplier::getSupplierCollection($obj->id); - - // Get already associated suppliers and force to retreive product declinaisons - $product_supplier_collection = ProductSupplier::getSupplierCollection($obj->id, false); - - $default_supplier = 0; - - foreach ($suppliers as &$supplier) - { - $supplier['is_selected'] = false; - $supplier['is_default'] = false; - - foreach ($associated_suppliers as $associated_supplier) - { - /** @var ProductSupplier $associated_supplier */ - if ($associated_supplier->id_supplier == $supplier['id_supplier']) - { - $associated_supplier->name = $supplier['name']; - $supplier['is_selected'] = true; - - if ($obj->id_supplier == $supplier['id_supplier']) - { - $supplier['is_default'] = true; - $default_supplier = $supplier['id_supplier']; - } - } - } - } - - $data->assign(array( - 'attributes' => $attributes, - 'suppliers' => $suppliers, - 'default_supplier' => $default_supplier, - 'associated_suppliers' => $associated_suppliers, - 'associated_suppliers_collection' => $product_supplier_collection, - 'product_designation' => $product_designation, - 'currencies' => Currency::getCurrencies(), - 'product' => $obj, - 'link' => $this->context->link, - 'token' => $this->token, - 'id_default_currency' => Configuration::get('PS_CURRENCY_DEFAULT'), - )); - } - else - $this->displayWarning($this->l('You must save the product in this shop before managing suppliers.')); - } - else - $this->displayWarning($this->l('You must save this product before managing suppliers.')); - - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - /** - * @param Product $obj - * @throws Exception - * @throws SmartyException - */ - public function initFormWarehouses($obj) - { - $data = $this->createTemplate($this->tpl_form); - - if ($obj->id) - { - if ($this->product_exists_in_shop) - { - // Get all id_product_attribute - $attributes = $obj->getAttributesResume($this->context->language->id); - if (empty($attributes)) - $attributes[] = array( - 'id_product' => $obj->id, - 'id_product_attribute' => 0, - 'attribute_designation' => '' - ); - - $product_designation = array(); - - foreach ($attributes as $attribute) - $product_designation[$attribute['id_product_attribute']] = rtrim( - $obj->name[$this->context->language->id].' - '.$attribute['attribute_designation'], - ' - ' - ); - - // Get all available warehouses - $warehouses = Warehouse::getWarehouses(true); - - // Get already associated warehouses - $associated_warehouses_collection = WarehouseProductLocation::getCollection($obj->id); - - $data->assign(array( - 'attributes' => $attributes, - 'warehouses' => $warehouses, - 'associated_warehouses' => $associated_warehouses_collection, - 'product_designation' => $product_designation, - 'product' => $obj, - 'link' => $this->context->link, - 'token' => $this->token - )); - } - else - $this->displayWarning($this->l('You must save the product in this shop before managing warehouses.')); - } - else - $this->displayWarning($this->l('You must save this product before managing warehouses.')); - - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - /** - * @param Product $obj - * @throws Exception - * @throws SmartyException - */ - public function initFormFeatures($obj) - { - if (!$this->default_form_language) - $this->getLanguages(); - - $data = $this->createTemplate($this->tpl_form); - $data->assign('default_form_language', $this->default_form_language); - $data->assign('languages', $this->_languages); - - if (!Feature::isFeatureActive()) - $this->displayWarning($this->l('This feature has been disabled. ').' <a href="index.php?tab=AdminPerformance&token='.Tools::getAdminTokenLite('AdminPerformance').'#featuresDetachables">'.$this->l('Performances').'</a>'); - else - { - if ($obj->id) - { - if ($this->product_exists_in_shop) - { - $features = Feature::getFeatures($this->context->language->id, (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP)); - - foreach ($features as $k => $tab_features) - { - $features[$k]['current_item'] = false; - $features[$k]['val'] = array(); - - $custom = true; - foreach ($obj->getFeatures() as $tab_products) - if ($tab_products['id_feature'] == $tab_features['id_feature']) - $features[$k]['current_item'] = $tab_products['id_feature_value']; - - $features[$k]['featureValues'] = FeatureValue::getFeatureValuesWithLang($this->context->language->id, (int)$tab_features['id_feature']); - if (count($features[$k]['featureValues'])) - foreach ($features[$k]['featureValues'] as $value) - if ($features[$k]['current_item'] == $value['id_feature_value']) - $custom = false; - - if ($custom) - { - $feature_values_lang = FeatureValue::getFeatureValueLang($features[$k]['current_item']); - foreach($feature_values_lang as $feature_value) - $features[$k]['val'][$feature_value['id_lang']] = $feature_value; - } - } - - $data->assign('available_features', $features); - $data->assign('product', $obj); - $data->assign('link', $this->context->link); - $data->assign('default_form_language', $this->default_form_language); - } - else - $this->displayWarning($this->l('You must save the product in this shop before adding features.')); - } - else - $this->displayWarning($this->l('You must save this product before adding features.')); - } - $this->tpl_form_vars['custom_form'] = $data->fetch(); - } - - public function ajaxProcessProductQuantity() - { - if ($this->tabAccess['edit'] === '0') - return die(Tools::jsonEncode(array('error' => $this->l('You do not have the right permission')))); - if (!Tools::getValue('actionQty')) - return Tools::jsonEncode(array('error' => $this->l('Undefined action'))); - - $product = new Product((int)Tools::getValue('id_product'), true); - switch (Tools::getValue('actionQty')) - { - case 'depends_on_stock': - if (Tools::getValue('value') === false) - die (Tools::jsonEncode(array('error' => $this->l('Undefined value')))); - if ((int)Tools::getValue('value') != 0 && (int)Tools::getValue('value') != 1) - die (Tools::jsonEncode(array('error' => $this->l('Incorrect value')))); - if (!$product->advanced_stock_management && (int)Tools::getValue('value') == 1) - die (Tools::jsonEncode(array('error' => $this->l('Not possible if advanced stock management is disabled. ')))); - if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && (int)Tools::getValue('value') == 1 && (Pack::isPack($product->id) && !Pack::allUsesAdvancedStockManagement($product->id) - && ($product->pack_stock_type == 2 || $product->pack_stock_type == 1 || - ($product->pack_stock_type == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 1 || Configuration::get('PS_PACK_STOCK_TYPE') == 2))))) - die (Tools::jsonEncode(array('error' => $this->l('You cannot use advanced stock management for this pack because').'<br />'. - $this->l('- advanced stock management is not enabled for these products').'<br />'. - $this->l('- you have chosen to decrement products quantities.')))); - - StockAvailable::setProductDependsOnStock($product->id, (int)Tools::getValue('value')); - break; - - case 'pack_stock_type': - $value = Tools::getValue('value'); - if ($value === false) - die (Tools::jsonEncode(array('error' => $this->l('Undefined value')))); - if ((int)$value != 0 && (int)$value != 1 - && (int)$value != 2 && (int)$value != 3) - die (Tools::jsonEncode(array('error' => $this->l('Incorrect value')))); - if ($product->depends_on_stock && !Pack::allUsesAdvancedStockManagement($product->id) && ((int)$value == 1 - || (int)$value == 2 || ((int)$value == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 1 || Configuration::get('PS_PACK_STOCK_TYPE') == 2)))) - die (Tools::jsonEncode(array('error' => $this->l('You cannot use this stock management option because:').'<br />'. - $this->l('- advanced stock management is not enabled for these products').'<br />'. - $this->l('- advanced stock management is enabled for the pack')))); - - Product::setPackStockType($product->id, $value); - break; - - case 'out_of_stock': - if (Tools::getValue('value') === false) - die (Tools::jsonEncode(array('error' => $this->l('Undefined value')))); - if (!in_array((int)Tools::getValue('value'), array(0, 1, 2))) - die (Tools::jsonEncode(array('error' => $this->l('Incorrect value')))); - - StockAvailable::setProductOutOfStock($product->id, (int)Tools::getValue('value')); - break; - - case 'set_qty': - if (Tools::getValue('value') === false || (!is_numeric(trim(Tools::getValue('value'))))) - die (Tools::jsonEncode(array('error' => $this->l('Undefined value')))); - if (Tools::getValue('id_product_attribute') === false) - die (Tools::jsonEncode(array('error' => $this->l('Undefined id product attribute')))); - - StockAvailable::setQuantity($product->id, (int)Tools::getValue('id_product_attribute'), (int)Tools::getValue('value')); - Hook::exec('actionProductUpdate', array('id_product' => (int)$product->id, 'product' => $product)); - - // Catch potential echo from modules - $error = ob_get_contents(); - if (!empty($error)) - { - ob_end_clean(); - die (Tools::jsonEncode(array('error' => $error))); - } - break; - case 'advanced_stock_management' : - if (Tools::getValue('value') === false) - die (Tools::jsonEncode(array('error' => $this->l('Undefined value')))); - if ((int)Tools::getValue('value') != 1 && (int)Tools::getValue('value') != 0) - die (Tools::jsonEncode(array('error' => $this->l('Incorrect value')))); - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && (int)Tools::getValue('value') == 1) - die (Tools::jsonEncode(array('error' => $this->l('Not possible if advanced stock management is disabled. ')))); - - $product->setAdvancedStockManagement((int)Tools::getValue('value')); - if (StockAvailable::dependsOnStock($product->id) == 1 && (int)Tools::getValue('value') == 0) - StockAvailable::setProductDependsOnStock($product->id, 0); - break; - - } - die(Tools::jsonEncode(array('error' => false))); - } - - public function getCombinationImagesJS() - { - /** @var Product $obj */ - if (!($obj = $this->loadObject(true))) - return; - - $content = 'var combination_images = new Array();'; - if (!$allCombinationImages = $obj->getCombinationImages($this->context->language->id)) - return $content; - foreach ($allCombinationImages as $id_product_attribute => $combination_images) - { - $i = 0; - $content .= 'combination_images['.(int)$id_product_attribute.'] = new Array();'; - foreach ($combination_images as $combination_image) - $content .= 'combination_images['.(int)$id_product_attribute.']['.$i++.'] = '.(int)$combination_image['id_image'].';'; - } - return $content; - } - - public function haveThisAccessory($accessory_id, $accessories) - { - foreach ($accessories as $accessory) - if ((int)$accessory['id_product'] == (int)$accessory_id) - return true; - return false; - } - - protected function initPack(Product $product) - { - $this->tpl_form_vars['is_pack'] = ($product->id && Pack::isPack($product->id)) || Tools::getValue('type_product') == Product::PTYPE_PACK; - $product->packItems = Pack::getItems($product->id, $this->context->language->id); - - $input_pack_items = ''; - if (Tools::getValue('inputPackItems')) - $input_pack_items = Tools::getValue('inputPackItems'); - else - foreach ($product->packItems as $pack_item) - $input_pack_items .= $pack_item->pack_quantity.'x'.$pack_item->id.'-'; - $this->tpl_form_vars['input_pack_items'] = $input_pack_items; - - $input_namepack_items = ''; - if (Tools::getValue('namePackItems')) - $input_namepack_items = Tools::getValue('namePackItems'); - else - foreach ($product->packItems as $pack_item) - $input_namepack_items .= $pack_item->pack_quantity.' x '.$pack_item->name.'¤'; - $this->tpl_form_vars['input_namepack_items'] = $input_namepack_items; - } - - /** - * AdminProducts display hook - * - * @param $obj - * - * @throws PrestaShopException - */ - public function initFormModules($obj) - { - $id_module = Db::getInstance()->getValue('SELECT `id_module` FROM `'._DB_PREFIX_.'module` WHERE `name` = \''.pSQL($this->tab_display_module).'\''); - $this->tpl_form_vars['custom_form'] = Hook::exec('displayAdminProductsExtra', array(), (int)$id_module); - } - - /** - * delete all items in pack, then check if type_product value is 2. - * if yes, add the pack items from input "inputPackItems" - * - * @param Product $product - * @return bool - */ - public function updatePackItems($product) - { - Pack::deleteItems($product->id); - // lines format: QTY x ID-QTY x ID - if (Tools::getValue('type_product') == Product::PTYPE_PACK) - { - $product->setDefaultAttribute(0);//reset cache_default_attribute - $items = Tools::getValue('inputPackItems'); - $lines = array_unique(explode('-', $items)); - - // lines is an array of string with format : QTYxIDxID_PRODUCT_ATTRIBUTE - if (count($lines)) - foreach ($lines as $line) - if (!empty($line)) - { - $item_id_attribute = 0; - count($array = explode('x', $line)) == 3 ? list($qty, $item_id, $item_id_attribute) = $array : list($qty, $item_id) = $array; - if ($qty > 0 && isset($item_id)) - { - if (Pack::isPack((int)$item_id)) - $this->errors[] = Tools::displayError('You can\'t add product packs into a pack'); - elseif (!Pack::addItem((int)$product->id, (int)$item_id, (int)$qty, (int)$item_id_attribute)) - $this->errors[] = Tools::displayError('An error occurred while attempting to add products to the pack.'); - } - } - } - } - - public function getL($key) - { - $trad = array( - 'Default category:' => $this->l('Default category'), - 'Catalog:' => $this->l('Catalog'), - 'Consider changing the default category.' => $this->l('Consider changing the default category.'), - 'ID' => $this->l('ID'), - 'Name' => $this->l('Name'), - 'Mark all checkbox(es) of categories in which product is to appear' => $this->l('Mark the checkbox of each categories in which this product will appear.') - ); - return $trad[$key]; - } - - protected function _displayUnavailableProductWarning() - { - $content = '<div class="alert"> + ); + + $images = Image::getImages($this->context->language->id, $obj->id); + foreach ($images as $k => $image) { + $images[$k] = new Image($image['id_image']); + } + + + if ($this->context->shop->getContext() == Shop::CONTEXT_SHOP) { + $current_shop_id = (int)$this->context->shop->id; + } else { + $current_shop_id = 0; + } + + $languages = Language::getLanguages(true); + $image_uploader = new HelperImageUploader('file'); + $image_uploader->setMultiple(!(Tools::getUserBrowser() == 'Apple Safari' && Tools::getUserPlatform() == 'Windows')) + ->setUseAjax(true)->setUrl( + Context::getContext()->link->getAdminLink('AdminProducts').'&ajax=1&id_product='.(int)$obj->id + .'&action=addProductImage'); + + $data->assign(array( + 'countImages' => $count_images, + 'id_product' => (int)Tools::getValue('id_product'), + 'id_category_default' => (int)$this->_category->id, + 'images' => $images, + 'iso_lang' => $languages[0]['iso_code'], + 'token' => $this->token, + 'table' => $this->table, + 'max_image_size' => $this->max_image_size / 1024 / 1024, + 'up_filename' => (string)Tools::getValue('virtual_product_filename_attribute'), + 'currency' => $this->context->currency, + 'current_shop_id' => $current_shop_id, + 'languages' => $this->_languages, + 'default_language' => (int)Configuration::get('PS_LANG_DEFAULT'), + 'image_uploader' => $image_uploader->render() + )); + + $type = ImageType::getByNameNType('%', 'products', 'height'); + if (isset($type['name'])) { + $data->assign('imageType', $type['name']); + } else { + $data->assign('imageType', ImageType::getFormatedName('small')); + } + } else { + $this->displayWarning($this->l('You must save the product in this shop before adding images.')); + } + } else { + $this->displayWarning($this->l('You must save this product before adding images.')); + } + + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + public function initFormCombinations($obj) + { + return $this->initFormAttributes($obj); + } + + /** + * @param Product $product + * @throws Exception + * @throws SmartyException + */ + public function initFormAttributes($product) + { + $data = $this->createTemplate($this->tpl_form); + if (!Combination::isFeatureActive()) { + $this->displayWarning($this->l('This feature has been disabled. '). + ' <a href="index.php?tab=AdminPerformance&token='.Tools::getAdminTokenLite('AdminPerformance').'#featuresDetachables">'.$this->l('Performances').'</a>'); + } elseif (Validate::isLoadedObject($product)) { + if ($this->product_exists_in_shop) { + if ($product->is_virtual) { + $data->assign('product', $product); + $this->displayWarning($this->l('A virtual product cannot have combinations.')); + } else { + $attribute_js = array(); + $attributes = Attribute::getAttributes($this->context->language->id, true); + foreach ($attributes as $k => $attribute) { + $attribute_js[$attribute['id_attribute_group']][$attribute['id_attribute']] = $attribute['name']; + natsort($attribute_js[$attribute['id_attribute_group']]); + } + + $currency = $this->context->currency; + + $data->assign('attributeJs', $attribute_js); + $data->assign('attributes_groups', AttributeGroup::getAttributesGroups($this->context->language->id)); + + $data->assign('currency', $currency); + + $images = Image::getImages($this->context->language->id, $product->id); + + $data->assign('tax_exclude_option', Tax::excludeTaxeOption()); + $data->assign('ps_weight_unit', Configuration::get('PS_WEIGHT_UNIT')); + + $data->assign('ps_use_ecotax', Configuration::get('PS_USE_ECOTAX')); + $data->assign('field_value_unity', $this->getFieldValue($product, 'unity')); + + $data->assign('reasons', $reasons = StockMvtReason::getStockMvtReasons($this->context->language->id)); + $data->assign('ps_stock_mvt_reason_default', $ps_stock_mvt_reason_default = Configuration::get('PS_STOCK_MVT_REASON_DEFAULT')); + $data->assign('minimal_quantity', $this->getFieldValue($product, 'minimal_quantity') ? $this->getFieldValue($product, 'minimal_quantity') : 1); + $data->assign('available_date', ($this->getFieldValue($product, 'available_date') != 0) ? stripslashes(htmlentities($this->getFieldValue($product, 'available_date'), $this->context->language->id)) : '0000-00-00'); + + $i = 0; + $type = ImageType::getByNameNType('%', 'products', 'height'); + if (isset($type['name'])) { + $data->assign('imageType', $type['name']); + } else { + $data->assign('imageType', ImageType::getFormatedName('small')); + } + $data->assign('imageWidth', (isset($image_type['width']) ? (int)($image_type['width']) : 64) + 25); + foreach ($images as $k => $image) { + $images[$k]['obj'] = new Image($image['id_image']); + ++$i; + } + $data->assign('images', $images); + + $data->assign($this->tpl_form_vars); + $data->assign(array( + 'list' => $this->renderListAttributes($product, $currency), + 'product' => $product, + 'id_category' => $product->getDefaultCategory(), + 'token_generator' => Tools::getAdminTokenLite('AdminAttributeGenerator'), + 'combination_exists' => (Shop::isFeatureActive() && (Shop::getContextShopGroup()->share_stock) && count(AttributeGroup::getAttributesGroups($this->context->language->id)) > 0 && $product->hasAttributes()) + )); + } + } else { + $this->displayWarning($this->l('You must save the product in this shop before adding combinations.')); + } + } else { + $data->assign('product', $product); + $this->displayWarning($this->l('You must save this product before adding combinations.')); + } + + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + /** + * @param Product $product + * @param Currency|array|int $currency + * @return string + */ + public function renderListAttributes($product, $currency) + { + $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?'))); + $this->addRowAction('edit'); + $this->addRowAction('default'); + $this->addRowAction('delete'); + + $default_class = 'highlighted'; + + $this->fields_list = array( + 'attributes' => array('title' => $this->l('Attribute - value pair'), 'align' => 'left'), + 'price' => array('title' => $this->l('Impact on price'), 'type' => 'price', 'align' => 'left'), + 'weight' => array('title' => $this->l('Impact on weight'), 'align' => 'left'), + 'reference' => array('title' => $this->l('Reference'), 'align' => 'left'), + 'ean13' => array('title' => $this->l('EAN-13'), 'align' => 'left'), + 'upc' => array('title' => $this->l('UPC'), 'align' => 'left') + ); + + if ($product->id) { + /* Build attributes combinations */ + $combinations = $product->getAttributeCombinations($this->context->language->id); + $groups = array(); + $comb_array = array(); + if (is_array($combinations)) { + $combination_images = $product->getCombinationImages($this->context->language->id); + foreach ($combinations as $k => $combination) { + $price_to_convert = Tools::convertPrice($combination['price'], $currency); + $price = Tools::displayPrice($price_to_convert, $currency); + + $comb_array[$combination['id_product_attribute']]['id_product_attribute'] = $combination['id_product_attribute']; + $comb_array[$combination['id_product_attribute']]['attributes'][] = array($combination['group_name'], $combination['attribute_name'], $combination['id_attribute']); + $comb_array[$combination['id_product_attribute']]['wholesale_price'] = $combination['wholesale_price']; + $comb_array[$combination['id_product_attribute']]['price'] = $price; + $comb_array[$combination['id_product_attribute']]['weight'] = $combination['weight'].Configuration::get('PS_WEIGHT_UNIT'); + $comb_array[$combination['id_product_attribute']]['unit_impact'] = $combination['unit_price_impact']; + $comb_array[$combination['id_product_attribute']]['reference'] = $combination['reference']; + $comb_array[$combination['id_product_attribute']]['ean13'] = $combination['ean13']; + $comb_array[$combination['id_product_attribute']]['upc'] = $combination['upc']; + $comb_array[$combination['id_product_attribute']]['id_image'] = isset($combination_images[$combination['id_product_attribute']][0]['id_image']) ? $combination_images[$combination['id_product_attribute']][0]['id_image'] : 0; + $comb_array[$combination['id_product_attribute']]['available_date'] = strftime($combination['available_date']); + $comb_array[$combination['id_product_attribute']]['default_on'] = $combination['default_on']; + if ($combination['is_color_group']) { + $groups[$combination['id_attribute_group']] = $combination['group_name']; + } + } + } + + if (isset($comb_array)) { + foreach ($comb_array as $id_product_attribute => $product_attribute) { + $list = ''; + + /* In order to keep the same attributes order */ + asort($product_attribute['attributes']); + + foreach ($product_attribute['attributes'] as $attribute) { + $list .= $attribute[0].' - '.$attribute[1].', '; + } + + $list = rtrim($list, ', '); + $comb_array[$id_product_attribute]['image'] = $product_attribute['id_image'] ? new Image($product_attribute['id_image']) : false; + $comb_array[$id_product_attribute]['available_date'] = $product_attribute['available_date'] != 0 ? date('Y-m-d', strtotime($product_attribute['available_date'])) : '0000-00-00'; + $comb_array[$id_product_attribute]['attributes'] = $list; + $comb_array[$id_product_attribute]['name'] = $list; + + if ($product_attribute['default_on']) { + $comb_array[$id_product_attribute]['class'] = $default_class; + } + } + } + } + + foreach ($this->actions_available as $action) { + if (!in_array($action, $this->actions) && isset($this->$action) && $this->$action) { + $this->actions[] = $action; + } + } + + $helper = new HelperList(); + $helper->identifier = 'id_product_attribute'; + $helper->table_id = 'combinations-list'; + $helper->token = $this->token; + $helper->currentIndex = self::$currentIndex; + $helper->no_link = true; + $helper->simple_header = true; + $helper->show_toolbar = false; + $helper->shopLinkType = $this->shopLinkType; + $helper->actions = $this->actions; + $helper->list_skip_actions = $this->list_skip_actions; + $helper->colorOnBackground = true; + $helper->override_folder = $this->tpl_folder.'combination/'; + + return $helper->generateList($comb_array, $this->fields_list); + } + + /** + * @param Product $obj + * @throws Exception + * @throws SmartyException + */ + public function initFormQuantities($obj) + { + if (!$this->default_form_language) { + $this->getLanguages(); + } + + $data = $this->createTemplate($this->tpl_form); + $data->assign('default_form_language', $this->default_form_language); + + if ($obj->id) { + if ($this->product_exists_in_shop) { + // Get all id_product_attribute + $attributes = $obj->getAttributesResume($this->context->language->id); + if (empty($attributes)) { + $attributes[] = array( + 'id_product_attribute' => 0, + 'attribute_designation' => '' + ); + } + + // Get available quantities + $available_quantity = array(); + $product_designation = array(); + + foreach ($attributes as $attribute) { + // Get available quantity for the current product attribute in the current shop + $available_quantity[$attribute['id_product_attribute']] = isset($attribute['id_product_attribute']) && $attribute['id_product_attribute'] ? (int)$attribute['quantity'] : (int)$obj->quantity; + // Get all product designation + $product_designation[$attribute['id_product_attribute']] = rtrim( + $obj->name[$this->context->language->id].' - '.$attribute['attribute_designation'], + ' - ' + ); + } + + $show_quantities = true; + $shop_context = Shop::getContext(); + $shop_group = new ShopGroup((int)Shop::getContextShopGroupID()); + + // if we are in all shops context, it's not possible to manage quantities at this level + if (Shop::isFeatureActive() && $shop_context == Shop::CONTEXT_ALL) { + $show_quantities = false; + } + // if we are in group shop context + elseif (Shop::isFeatureActive() && $shop_context == Shop::CONTEXT_GROUP) { + // if quantities are not shared between shops of the group, it's not possible to manage them at group level + if (!$shop_group->share_stock) { + $show_quantities = false; + } + } + // if we are in shop context + elseif (Shop::isFeatureActive()) { + // if quantities are shared between shops of the group, it's not possible to manage them for a given shop + if ($shop_group->share_stock) { + $show_quantities = false; + } + } + + $data->assign('ps_stock_management', Configuration::get('PS_STOCK_MANAGEMENT')); + $data->assign('has_attribute', $obj->hasAttributes()); + // Check if product has combination, to display the available date only for the product or for each combination + if (Combination::isFeatureActive()) { + $data->assign('countAttributes', (int)Db::getInstance()->getValue('SELECT COUNT(id_product) FROM '._DB_PREFIX_.'product_attribute WHERE id_product = '.(int)$obj->id)); + } else { + $data->assign('countAttributes', false); + } + // if advanced stock management is active, checks associations + $advanced_stock_management_warning = false; + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $obj->advanced_stock_management) { + $p_attributes = Product::getProductAttributesIds($obj->id); + $warehouses = array(); + + if (!$p_attributes) { + $warehouses[] = Warehouse::getProductWarehouseList($obj->id, 0); + } + + foreach ($p_attributes as $p_attribute) { + $ws = Warehouse::getProductWarehouseList($obj->id, $p_attribute['id_product_attribute']); + if ($ws) { + $warehouses[] = $ws; + } + } + $warehouses = Tools::arrayUnique($warehouses); + + if (empty($warehouses)) { + $advanced_stock_management_warning = true; + } + } + if ($advanced_stock_management_warning) { + $this->displayWarning($this->l('If you wish to use the advanced stock management, you must:')); + $this->displayWarning('- '.$this->l('associate your products with warehouses.')); + $this->displayWarning('- '.$this->l('associate your warehouses with carriers.')); + $this->displayWarning('- '.$this->l('associate your warehouses with the appropriate shops.')); + } + + $pack_quantity = null; + // if product is a pack + if (Pack::isPack($obj->id)) { + $items = Pack::getItems((int)$obj->id, Configuration::get('PS_LANG_DEFAULT')); + + // gets an array of quantities (quantity for the product / quantity in pack) + $pack_quantities = array(); + foreach ($items as $item) { + /** @var Product $item */ + if (!$item->isAvailableWhenOutOfStock((int)$item->out_of_stock)) { + $pack_id_product_attribute = Product::getDefaultAttribute($item->id, 1); + $pack_quantities[] = Product::getQuantity($item->id, $pack_id_product_attribute) / ($item->pack_quantity !== 0 ? $item->pack_quantity : 1); + } + } + + // gets the minimum + if (count($pack_quantities)) { + $pack_quantity = $pack_quantities[0]; + foreach ($pack_quantities as $value) { + if ($pack_quantity > $value) { + $pack_quantity = $value; + } + } + } + + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && !Warehouse::getPackWarehouses((int)$obj->id)) { + $this->displayWarning($this->l('You must have a common warehouse between this pack and its product.')); + } + } + + $data->assign(array( + 'attributes' => $attributes, + 'available_quantity' => $available_quantity, + 'pack_quantity' => $pack_quantity, + 'stock_management_active' => Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'), + 'product_designation' => $product_designation, + 'product' => $obj, + 'show_quantities' => $show_quantities, + 'order_out_of_stock' => Configuration::get('PS_ORDER_OUT_OF_STOCK'), + 'pack_stock_type' => Configuration::get('PS_PACK_STOCK_TYPE'), + 'token_preferences' => Tools::getAdminTokenLite('AdminPPreferences'), + 'token' => $this->token, + 'languages' => $this->_languages, + 'id_lang' => $this->context->language->id + )); + } else { + $this->displayWarning($this->l('You must save the product in this shop before managing quantities.')); + } + } else { + $this->displayWarning($this->l('You must save this product before managing quantities.')); + } + + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + /** + * @param Product $obj + * @throws Exception + * @throws SmartyException + */ + public function initFormSuppliers($obj) + { + $data = $this->createTemplate($this->tpl_form); + + if ($obj->id) { + if ($this->product_exists_in_shop) { + // Get all id_product_attribute + $attributes = $obj->getAttributesResume($this->context->language->id); + if (empty($attributes)) { + $attributes[] = array( + 'id_product' => $obj->id, + 'id_product_attribute' => 0, + 'attribute_designation' => '' + ); + } + + $product_designation = array(); + + foreach ($attributes as $attribute) { + $product_designation[$attribute['id_product_attribute']] = rtrim( + $obj->name[$this->context->language->id].' - '.$attribute['attribute_designation'], + ' - ' + ); + } + + // Get all available suppliers + $suppliers = Supplier::getSuppliers(); + + // Get already associated suppliers + $associated_suppliers = ProductSupplier::getSupplierCollection($obj->id); + + // Get already associated suppliers and force to retreive product declinaisons + $product_supplier_collection = ProductSupplier::getSupplierCollection($obj->id, false); + + $default_supplier = 0; + + foreach ($suppliers as &$supplier) { + $supplier['is_selected'] = false; + $supplier['is_default'] = false; + + foreach ($associated_suppliers as $associated_supplier) { + /** @var ProductSupplier $associated_supplier */ + if ($associated_supplier->id_supplier == $supplier['id_supplier']) { + $associated_supplier->name = $supplier['name']; + $supplier['is_selected'] = true; + + if ($obj->id_supplier == $supplier['id_supplier']) { + $supplier['is_default'] = true; + $default_supplier = $supplier['id_supplier']; + } + } + } + } + + $data->assign(array( + 'attributes' => $attributes, + 'suppliers' => $suppliers, + 'default_supplier' => $default_supplier, + 'associated_suppliers' => $associated_suppliers, + 'associated_suppliers_collection' => $product_supplier_collection, + 'product_designation' => $product_designation, + 'currencies' => Currency::getCurrencies(), + 'product' => $obj, + 'link' => $this->context->link, + 'token' => $this->token, + 'id_default_currency' => Configuration::get('PS_CURRENCY_DEFAULT'), + )); + } else { + $this->displayWarning($this->l('You must save the product in this shop before managing suppliers.')); + } + } else { + $this->displayWarning($this->l('You must save this product before managing suppliers.')); + } + + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + /** + * @param Product $obj + * @throws Exception + * @throws SmartyException + */ + public function initFormWarehouses($obj) + { + $data = $this->createTemplate($this->tpl_form); + + if ($obj->id) { + if ($this->product_exists_in_shop) { + // Get all id_product_attribute + $attributes = $obj->getAttributesResume($this->context->language->id); + if (empty($attributes)) { + $attributes[] = array( + 'id_product' => $obj->id, + 'id_product_attribute' => 0, + 'attribute_designation' => '' + ); + } + + $product_designation = array(); + + foreach ($attributes as $attribute) { + $product_designation[$attribute['id_product_attribute']] = rtrim( + $obj->name[$this->context->language->id].' - '.$attribute['attribute_designation'], + ' - ' + ); + } + + // Get all available warehouses + $warehouses = Warehouse::getWarehouses(true); + + // Get already associated warehouses + $associated_warehouses_collection = WarehouseProductLocation::getCollection($obj->id); + + $data->assign(array( + 'attributes' => $attributes, + 'warehouses' => $warehouses, + 'associated_warehouses' => $associated_warehouses_collection, + 'product_designation' => $product_designation, + 'product' => $obj, + 'link' => $this->context->link, + 'token' => $this->token + )); + } else { + $this->displayWarning($this->l('You must save the product in this shop before managing warehouses.')); + } + } else { + $this->displayWarning($this->l('You must save this product before managing warehouses.')); + } + + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + /** + * @param Product $obj + * @throws Exception + * @throws SmartyException + */ + public function initFormFeatures($obj) + { + if (!$this->default_form_language) { + $this->getLanguages(); + } + + $data = $this->createTemplate($this->tpl_form); + $data->assign('default_form_language', $this->default_form_language); + $data->assign('languages', $this->_languages); + + if (!Feature::isFeatureActive()) { + $this->displayWarning($this->l('This feature has been disabled. ').' <a href="index.php?tab=AdminPerformance&token='.Tools::getAdminTokenLite('AdminPerformance').'#featuresDetachables">'.$this->l('Performances').'</a>'); + } else { + if ($obj->id) { + if ($this->product_exists_in_shop) { + $features = Feature::getFeatures($this->context->language->id, (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP)); + + foreach ($features as $k => $tab_features) { + $features[$k]['current_item'] = false; + $features[$k]['val'] = array(); + + $custom = true; + foreach ($obj->getFeatures() as $tab_products) { + if ($tab_products['id_feature'] == $tab_features['id_feature']) { + $features[$k]['current_item'] = $tab_products['id_feature_value']; + } + } + + $features[$k]['featureValues'] = FeatureValue::getFeatureValuesWithLang($this->context->language->id, (int)$tab_features['id_feature']); + if (count($features[$k]['featureValues'])) { + foreach ($features[$k]['featureValues'] as $value) { + if ($features[$k]['current_item'] == $value['id_feature_value']) { + $custom = false; + } + } + } + + if ($custom) { + $feature_values_lang = FeatureValue::getFeatureValueLang($features[$k]['current_item']); + foreach ($feature_values_lang as $feature_value) { + $features[$k]['val'][$feature_value['id_lang']] = $feature_value; + } + } + } + + $data->assign('available_features', $features); + $data->assign('product', $obj); + $data->assign('link', $this->context->link); + $data->assign('default_form_language', $this->default_form_language); + } else { + $this->displayWarning($this->l('You must save the product in this shop before adding features.')); + } + } else { + $this->displayWarning($this->l('You must save this product before adding features.')); + } + } + $this->tpl_form_vars['custom_form'] = $data->fetch(); + } + + public function ajaxProcessProductQuantity() + { + if ($this->tabAccess['edit'] === '0') { + return die(Tools::jsonEncode(array('error' => $this->l('You do not have the right permission')))); + } + if (!Tools::getValue('actionQty')) { + return Tools::jsonEncode(array('error' => $this->l('Undefined action'))); + } + + $product = new Product((int)Tools::getValue('id_product'), true); + switch (Tools::getValue('actionQty')) { + case 'depends_on_stock': + if (Tools::getValue('value') === false) { + die(Tools::jsonEncode(array('error' => $this->l('Undefined value')))); + } + if ((int)Tools::getValue('value') != 0 && (int)Tools::getValue('value') != 1) { + die(Tools::jsonEncode(array('error' => $this->l('Incorrect value')))); + } + if (!$product->advanced_stock_management && (int)Tools::getValue('value') == 1) { + die(Tools::jsonEncode(array('error' => $this->l('Not possible if advanced stock management is disabled. ')))); + } + if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && (int)Tools::getValue('value') == 1 && (Pack::isPack($product->id) && !Pack::allUsesAdvancedStockManagement($product->id) + && ($product->pack_stock_type == 2 || $product->pack_stock_type == 1 || + ($product->pack_stock_type == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 1 || Configuration::get('PS_PACK_STOCK_TYPE') == 2))))) { + die(Tools::jsonEncode(array('error' => $this->l('You cannot use advanced stock management for this pack because').'<br />'. + $this->l('- advanced stock management is not enabled for these products').'<br />'. + $this->l('- you have chosen to decrement products quantities.')))); + } + + StockAvailable::setProductDependsOnStock($product->id, (int)Tools::getValue('value')); + break; + + case 'pack_stock_type': + $value = Tools::getValue('value'); + if ($value === false) { + die(Tools::jsonEncode(array('error' => $this->l('Undefined value')))); + } + if ((int)$value != 0 && (int)$value != 1 + && (int)$value != 2 && (int)$value != 3) { + die(Tools::jsonEncode(array('error' => $this->l('Incorrect value')))); + } + if ($product->depends_on_stock && !Pack::allUsesAdvancedStockManagement($product->id) && ((int)$value == 1 + || (int)$value == 2 || ((int)$value == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 1 || Configuration::get('PS_PACK_STOCK_TYPE') == 2)))) { + die(Tools::jsonEncode(array('error' => $this->l('You cannot use this stock management option because:').'<br />'. + $this->l('- advanced stock management is not enabled for these products').'<br />'. + $this->l('- advanced stock management is enabled for the pack')))); + } + + Product::setPackStockType($product->id, $value); + break; + + case 'out_of_stock': + if (Tools::getValue('value') === false) { + die(Tools::jsonEncode(array('error' => $this->l('Undefined value')))); + } + if (!in_array((int)Tools::getValue('value'), array(0, 1, 2))) { + die(Tools::jsonEncode(array('error' => $this->l('Incorrect value')))); + } + + StockAvailable::setProductOutOfStock($product->id, (int)Tools::getValue('value')); + break; + + case 'set_qty': + if (Tools::getValue('value') === false || (!is_numeric(trim(Tools::getValue('value'))))) { + die(Tools::jsonEncode(array('error' => $this->l('Undefined value')))); + } + if (Tools::getValue('id_product_attribute') === false) { + die(Tools::jsonEncode(array('error' => $this->l('Undefined id product attribute')))); + } + + StockAvailable::setQuantity($product->id, (int)Tools::getValue('id_product_attribute'), (int)Tools::getValue('value')); + Hook::exec('actionProductUpdate', array('id_product' => (int)$product->id, 'product' => $product)); + + // Catch potential echo from modules + $error = ob_get_contents(); + if (!empty($error)) { + ob_end_clean(); + die(Tools::jsonEncode(array('error' => $error))); + } + break; + case 'advanced_stock_management' : + if (Tools::getValue('value') === false) { + die(Tools::jsonEncode(array('error' => $this->l('Undefined value')))); + } + if ((int)Tools::getValue('value') != 1 && (int)Tools::getValue('value') != 0) { + die(Tools::jsonEncode(array('error' => $this->l('Incorrect value')))); + } + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && (int)Tools::getValue('value') == 1) { + die(Tools::jsonEncode(array('error' => $this->l('Not possible if advanced stock management is disabled. ')))); + } + + $product->setAdvancedStockManagement((int)Tools::getValue('value')); + if (StockAvailable::dependsOnStock($product->id) == 1 && (int)Tools::getValue('value') == 0) { + StockAvailable::setProductDependsOnStock($product->id, 0); + } + break; + + } + die(Tools::jsonEncode(array('error' => false))); + } + + public function getCombinationImagesJS() + { + /** @var Product $obj */ + if (!($obj = $this->loadObject(true))) { + return; + } + + $content = 'var combination_images = new Array();'; + if (!$allCombinationImages = $obj->getCombinationImages($this->context->language->id)) { + return $content; + } + foreach ($allCombinationImages as $id_product_attribute => $combination_images) { + $i = 0; + $content .= 'combination_images['.(int)$id_product_attribute.'] = new Array();'; + foreach ($combination_images as $combination_image) { + $content .= 'combination_images['.(int)$id_product_attribute.']['.$i++.'] = '.(int)$combination_image['id_image'].';'; + } + } + return $content; + } + + public function haveThisAccessory($accessory_id, $accessories) + { + foreach ($accessories as $accessory) { + if ((int)$accessory['id_product'] == (int)$accessory_id) { + return true; + } + } + return false; + } + + protected function initPack(Product $product) + { + $this->tpl_form_vars['is_pack'] = ($product->id && Pack::isPack($product->id)) || Tools::getValue('type_product') == Product::PTYPE_PACK; + $product->packItems = Pack::getItems($product->id, $this->context->language->id); + + $input_pack_items = ''; + if (Tools::getValue('inputPackItems')) { + $input_pack_items = Tools::getValue('inputPackItems'); + } else { + foreach ($product->packItems as $pack_item) { + $input_pack_items .= $pack_item->pack_quantity.'x'.$pack_item->id.'-'; + } + } + $this->tpl_form_vars['input_pack_items'] = $input_pack_items; + + $input_namepack_items = ''; + if (Tools::getValue('namePackItems')) { + $input_namepack_items = Tools::getValue('namePackItems'); + } else { + foreach ($product->packItems as $pack_item) { + $input_namepack_items .= $pack_item->pack_quantity.' x '.$pack_item->name.'¤'; + } + } + $this->tpl_form_vars['input_namepack_items'] = $input_namepack_items; + } + + /** + * AdminProducts display hook + * + * @param $obj + * + * @throws PrestaShopException + */ + public function initFormModules($obj) + { + $id_module = Db::getInstance()->getValue('SELECT `id_module` FROM `'._DB_PREFIX_.'module` WHERE `name` = \''.pSQL($this->tab_display_module).'\''); + $this->tpl_form_vars['custom_form'] = Hook::exec('displayAdminProductsExtra', array(), (int)$id_module); + } + + /** + * delete all items in pack, then check if type_product value is 2. + * if yes, add the pack items from input "inputPackItems" + * + * @param Product $product + * @return bool + */ + public function updatePackItems($product) + { + Pack::deleteItems($product->id); + // lines format: QTY x ID-QTY x ID + if (Tools::getValue('type_product') == Product::PTYPE_PACK) { + $product->setDefaultAttribute(0);//reset cache_default_attribute + $items = Tools::getValue('inputPackItems'); + $lines = array_unique(explode('-', $items)); + + // lines is an array of string with format : QTYxIDxID_PRODUCT_ATTRIBUTE + if (count($lines)) { + foreach ($lines as $line) { + if (!empty($line)) { + $item_id_attribute = 0; + count($array = explode('x', $line)) == 3 ? list($qty, $item_id, $item_id_attribute) = $array : list($qty, $item_id) = $array; + if ($qty > 0 && isset($item_id)) { + if (Pack::isPack((int)$item_id)) { + $this->errors[] = Tools::displayError('You can\'t add product packs into a pack'); + } elseif (!Pack::addItem((int)$product->id, (int)$item_id, (int)$qty, (int)$item_id_attribute)) { + $this->errors[] = Tools::displayError('An error occurred while attempting to add products to the pack.'); + } + } + } + } + } + } + } + + public function getL($key) + { + $trad = array( + 'Default category:' => $this->l('Default category'), + 'Catalog:' => $this->l('Catalog'), + 'Consider changing the default category.' => $this->l('Consider changing the default category.'), + 'ID' => $this->l('ID'), + 'Name' => $this->l('Name'), + 'Mark all checkbox(es) of categories in which product is to appear' => $this->l('Mark the checkbox of each categories in which this product will appear.') + ); + return $trad[$key]; + } + + protected function _displayUnavailableProductWarning() + { + $content = '<div class="alert"> <span>'.$this->l('Your product will be saved as a draft.').'</span> <a href="#" class="btn btn-default pull-right" onclick="submitAddProductAndPreview()" ><i class="icon-external-link-sign"></i> '.$this->l('Save and preview').'</a> <input type="hidden" name="fakeSubmitAddProductAndPreview" id="fakeSubmitAddProductAndPreview" /> </div>'; - $this->tpl_form_vars['warning_unavailable_product'] = $content; - } + $this->tpl_form_vars['warning_unavailable_product'] = $content; + } - public function ajaxProcessCheckProductName() - { - if ($this->tabAccess['view'] === '1') - { - $search = Tools::getValue('q'); - $id_lang = Tools::getValue('id_lang'); - $limit = Tools::getValue('limit'); - if (Context::getContext()->shop->getContext() != Shop::CONTEXT_SHOP) - $result = false; - else - $result = Db::getInstance()->executeS(' + public function ajaxProcessCheckProductName() + { + if ($this->tabAccess['view'] === '1') { + $search = Tools::getValue('q'); + $id_lang = Tools::getValue('id_lang'); + $limit = Tools::getValue('limit'); + if (Context::getContext()->shop->getContext() != Shop::CONTEXT_SHOP) { + $result = false; + } else { + $result = Db::getInstance()->executeS(' SELECT DISTINCT pl.`name`, p.`id_product`, pl.`id_shop` FROM `'._DB_PREFIX_.'product` p LEFT JOIN `'._DB_PREFIX_.'product_shop` ps ON (ps.id_product = p.id_product AND ps.id_shop ='.(int)Context::getContext()->shop->id.') @@ -5021,100 +5078,106 @@ class AdminProductsControllerCore extends AdminController WHERE pl.`name` LIKE "%'.pSQL($search).'%" AND ps.id_product IS NULL GROUP BY pl.`id_product` LIMIT '.(int)$limit); - die(Tools::jsonEncode($result)); - } - } + } + die(Tools::jsonEncode($result)); + } + } - public function ajaxProcessUpdatePositions() - { - if ($this->tabAccess['edit'] === '1') - { - $way = (int)(Tools::getValue('way')); - $id_product = (int)Tools::getValue('id_product'); - $id_category = (int)Tools::getValue('id_category'); - $positions = Tools::getValue('product'); - $page = (int)Tools::getValue('page'); - $selected_pagination = (int)Tools::getValue('selected_pagination'); + public function ajaxProcessUpdatePositions() + { + if ($this->tabAccess['edit'] === '1') { + $way = (int)(Tools::getValue('way')); + $id_product = (int)Tools::getValue('id_product'); + $id_category = (int)Tools::getValue('id_category'); + $positions = Tools::getValue('product'); + $page = (int)Tools::getValue('page'); + $selected_pagination = (int)Tools::getValue('selected_pagination'); - if (is_array($positions)) - foreach ($positions as $position => $value) - { - $pos = explode('_', $value); + if (is_array($positions)) { + foreach ($positions as $position => $value) { + $pos = explode('_', $value); - if ((isset($pos[1]) && isset($pos[2])) && ($pos[1] == $id_category && (int)$pos[2] === $id_product)) - { - if ($page > 1) - $position = $position + (($page - 1) * $selected_pagination); + if ((isset($pos[1]) && isset($pos[2])) && ($pos[1] == $id_category && (int)$pos[2] === $id_product)) { + if ($page > 1) { + $position = $position + (($page - 1) * $selected_pagination); + } - if ($product = new Product((int)$pos[2])) - if (isset($position) && $product->updatePosition($way, $position)) - { - $category = new Category((int)$id_category); - if (Validate::isLoadedObject($category)) - hook::Exec('categoryUpdate', array('category' => $category)); - echo 'ok position '.(int)$position.' for product '.(int)$pos[2]."\r\n"; - } - else - echo '{"hasError" : true, "errors" : "Can not update product '.(int)$id_product.' to position '.(int)$position.' "}'; - else - echo '{"hasError" : true, "errors" : "This product ('.(int)$id_product.') can t be loaded"}'; + if ($product = new Product((int)$pos[2])) { + if (isset($position) && $product->updatePosition($way, $position)) { + $category = new Category((int)$id_category); + if (Validate::isLoadedObject($category)) { + hook::Exec('categoryUpdate', array('category' => $category)); + } + echo 'ok position '.(int)$position.' for product '.(int)$pos[2]."\r\n"; + } else { + echo '{"hasError" : true, "errors" : "Can not update product '.(int)$id_product.' to position '.(int)$position.' "}'; + } + } else { + echo '{"hasError" : true, "errors" : "This product ('.(int)$id_product.') can t be loaded"}'; + } - break; - } - } - } - } + break; + } + } + } + } + } - public function ajaxProcessPublishProduct() - { - if ($this->tabAccess['edit'] === '1') - { - if ($id_product = (int)Tools::getValue('id_product')) - { - $bo_product_url = dirname($_SERVER['PHP_SELF']).'/index.php?tab=AdminProducts&id_product='.$id_product.'&updateproduct&token='.$this->token; + public function ajaxProcessPublishProduct() + { + if ($this->tabAccess['edit'] === '1') { + if ($id_product = (int)Tools::getValue('id_product')) { + $bo_product_url = dirname($_SERVER['PHP_SELF']).'/index.php?tab=AdminProducts&id_product='.$id_product.'&updateproduct&token='.$this->token; - if (Tools::getValue('redirect')) - die($bo_product_url); + if (Tools::getValue('redirect')) { + die($bo_product_url); + } - $product = new Product((int)$id_product); - if (!Validate::isLoadedObject($product)) - die('error: invalid id'); + $product = new Product((int)$id_product); + if (!Validate::isLoadedObject($product)) { + die('error: invalid id'); + } - $product->active = 1; + $product->active = 1; - if ($product->save()) - die($bo_product_url); - else - die('error: saving'); - } - } - } + if ($product->save()) { + die($bo_product_url); + } else { + die('error: saving'); + } + } + } + } - public function processImageLegends() - { - if (Tools::getValue('key_tab') == 'Images' && Tools::getValue('submitAddproductAndStay') == 'update_legends' && Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product')))) - { - $id_image = (int)Tools::getValue('id_caption'); - $language_ids = Language::getIDs(false); - foreach ($_POST as $key => $val) - if (preg_match('/^legend_([0-9]+)/i', $key, $match)) - foreach ($language_ids as $id_lang) - if ($val && $id_lang == $match[1]) - Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'image_lang SET legend = "'.pSQL($val).'" WHERE '.($id_image ? 'id_image = '.(int)$id_image : 'EXISTS (SELECT 1 FROM '._DB_PREFIX_.'image WHERE '._DB_PREFIX_.'image.id_image = '._DB_PREFIX_.'image_lang.id_image AND id_product = '.(int)$product->id.')').' AND id_lang = '.(int)$id_lang); - } - } + public function processImageLegends() + { + if (Tools::getValue('key_tab') == 'Images' && Tools::getValue('submitAddproductAndStay') == 'update_legends' && Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product')))) { + $id_image = (int)Tools::getValue('id_caption'); + $language_ids = Language::getIDs(false); + foreach ($_POST as $key => $val) { + if (preg_match('/^legend_([0-9]+)/i', $key, $match)) { + foreach ($language_ids as $id_lang) { + if ($val && $id_lang == $match[1]) { + Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'image_lang SET legend = "'.pSQL($val).'" WHERE '.($id_image ? 'id_image = '.(int)$id_image : 'EXISTS (SELECT 1 FROM '._DB_PREFIX_.'image WHERE '._DB_PREFIX_.'image.id_image = '._DB_PREFIX_.'image_lang.id_image AND id_product = '.(int)$product->id.')').' AND id_lang = '.(int)$id_lang); + } + } + } + } + } + } - public function displayPreviewLink($token = null, $id, $name = null) - { - $tpl = $this->createTemplate('helpers/list/list_action_preview.tpl'); - if (!array_key_exists('Bad SQL query', self::$cache_lang)) - self::$cache_lang['Preview'] = $this->l('Preview', 'Helper'); + public function displayPreviewLink($token = null, $id, $name = null) + { + $tpl = $this->createTemplate('helpers/list/list_action_preview.tpl'); + if (!array_key_exists('Bad SQL query', self::$cache_lang)) { + self::$cache_lang['Preview'] = $this->l('Preview', 'Helper'); + } - $tpl->assign(array( - 'href' => $this->getPreviewUrl(new Product((int)$id)), - 'action' => self::$cache_lang['Preview'], - )); + $tpl->assign(array( + 'href' => $this->getPreviewUrl(new Product((int)$id)), + 'action' => self::$cache_lang['Preview'], + )); - return $tpl->fetch(); - } + return $tpl->fetch(); + } } diff --git a/controllers/admin/AdminProfilesController.php b/controllers/admin/AdminProfilesController.php index e0c7b49d..262971cc 100644 --- a/controllers/admin/AdminProfilesController.php +++ b/controllers/admin/AdminProfilesController.php @@ -29,90 +29,90 @@ */ class AdminProfilesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->context = Context::getContext(); - $this->table = 'profile'; - $this->className = 'Profile'; - $this->multishop_context = Shop::CONTEXT_ALL; - $this->lang = true; - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->addRowActionSkipList('delete', array(1)); + public function __construct() + { + $this->bootstrap = true; + $this->context = Context::getContext(); + $this->table = 'profile'; + $this->className = 'Profile'; + $this->multishop_context = Shop::CONTEXT_ALL; + $this->lang = true; + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->addRowActionSkipList('delete', array(1)); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->fields_list = array( - 'id_profile' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array('title' => $this->l('Name')) - ); - - $this->identifier = 'id_profile'; + $this->fields_list = array( + 'id_profile' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array('title' => $this->l('Name')) + ); + + $this->identifier = 'id_profile'; - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Profile'), - 'icon' => 'icon-group' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'required' => true, - 'lang' => true, - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Profile'), + 'icon' => 'icon-group' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'required' => true, + 'lang' => true, + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - $list_profile = array(); - foreach (Profile::getProfiles($this->context->language->id) as $profil) - $list_profile[] = array('value' => $profil['id_profile'], 'name' => $profil['name']); + $list_profile = array(); + foreach (Profile::getProfiles($this->context->language->id) as $profil) { + $list_profile[] = array('value' => $profil['id_profile'], 'name' => $profil['name']); + } - parent::__construct(); - } + parent::__construct(); + } - public function postProcess() - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } - /* PrestaShop demo mode*/ + public function postProcess() + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } + /* PrestaShop demo mode*/ - if (isset($_GET['delete'.$this->table]) && $_GET[$this->identifier] == (int)(_PS_ADMIN_PROFILE_)) - $this->errors[] = $this->l('For security reasons, you cannot delete the Administrator\'s profile.'); - else - parent::postProcess(); - } + if (isset($_GET['delete'.$this->table]) && $_GET[$this->identifier] == (int)(_PS_ADMIN_PROFILE_)) { + $this->errors[] = $this->l('For security reasons, you cannot delete the Administrator\'s profile.'); + } else { + parent::postProcess(); + } + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_profile'] = array( - 'href' => self::$currentIndex.'&addprofile&token='.$this->token, - 'desc' => $this->l('Add new profile', null, null, false), - 'icon' => 'process-icon-new' - ); - - parent::initPageHeaderToolbar(); - } + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_profile'] = array( + 'href' => self::$currentIndex.'&addprofile&token='.$this->token, + 'desc' => $this->l('Add new profile', null, null, false), + 'icon' => 'process-icon-new' + ); + } + + parent::initPageHeaderToolbar(); + } } - - diff --git a/controllers/admin/AdminQuickAccessesController.php b/controllers/admin/AdminQuickAccessesController.php index 05ba2d72..9eb65745 100644 --- a/controllers/admin/AdminQuickAccessesController.php +++ b/controllers/admin/AdminQuickAccessesController.php @@ -29,221 +29,216 @@ */ class AdminQuickAccessesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'quick_access'; - $this->className = 'QuickAccess'; - $this->lang = true; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'quick_access'; + $this->className = 'QuickAccess'; + $this->lang = true; - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->context = Context::getContext(); + $this->context = Context::getContext(); - if (!Tools::getValue('realedit')) - $this->deleted = false; + if (!Tools::getValue('realedit')) { + $this->deleted = false; + } - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->fields_list = array( - 'id_quick_access' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Name') - ), - 'link' => array( - 'title' => $this->l('Link') - ), - 'new_window' => array( - 'title' => $this->l('New window'), - 'align' => 'center', - 'type' => 'bool', - 'active' => 'new_window', - 'class' => 'fixed-width-sm' - ) - ); + $this->fields_list = array( + 'id_quick_access' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Name') + ), + 'link' => array( + 'title' => $this->l('Link') + ), + 'new_window' => array( + 'title' => $this->l('New window'), + 'align' => 'center', + 'type' => 'bool', + 'active' => 'new_window', + 'class' => 'fixed-width-sm' + ) + ); - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Quick Access menu'), - 'icon' => 'icon-align-justify' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'lang' => true, - 'maxlength' => 32, - 'required' => true, - 'hint' => $this->l('Forbidden characters:').' <>;=#{}' - ), - array( - 'type' => 'text', - 'label' => $this->l('URL'), - 'name' => 'link', - 'maxlength' => 128, - 'required' => true, - 'hint' => $this->l('If it\'s a URL that comes from your Back Office, you MUST remove the security token.') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Open in new window'), - 'name' => 'new_window', - 'required' => false, - 'values' => array( - array( - 'id' => 'new_window_on', - 'value' => 1, - 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Enabled').'" title="'.$this->l('Enabled').'" />' - ), - array( - 'id' => 'new_window_off', - 'value' => 0, - 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('Disabled').'" title="'.$this->l('Disabled').'" />' - ) - ) - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Quick Access menu'), + 'icon' => 'icon-align-justify' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'lang' => true, + 'maxlength' => 32, + 'required' => true, + 'hint' => $this->l('Forbidden characters:').' <>;=#{}' + ), + array( + 'type' => 'text', + 'label' => $this->l('URL'), + 'name' => 'link', + 'maxlength' => 128, + 'required' => true, + 'hint' => $this->l('If it\'s a URL that comes from your Back Office, you MUST remove the security token.') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Open in new window'), + 'name' => 'new_window', + 'required' => false, + 'values' => array( + array( + 'id' => 'new_window_on', + 'value' => 1, + 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Enabled').'" title="'.$this->l('Enabled').'" />' + ), + array( + 'id' => 'new_window_off', + 'value' => 0, + 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('Disabled').'" title="'.$this->l('Disabled').'" />' + ) + ) + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_quick_access'] = array( - 'href' => self::$currentIndex.'&addquick_access&token='.$this->token, - 'desc' => $this->l('Add new quick access', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_quick_access'] = array( + 'href' => self::$currentIndex.'&addquick_access&token='.$this->token, + 'desc' => $this->l('Add new quick access', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function initProcess() - { - if ((isset($_GET['new_window'.$this->table]) || isset($_GET['new_window'])) && Tools::getValue($this->identifier)) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'newWindow'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } + public function initProcess() + { + if ((isset($_GET['new_window'.$this->table]) || isset($_GET['new_window'])) && Tools::getValue($this->identifier)) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'newWindow'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } - parent::initProcess(); - } + parent::initProcess(); + } - public function getQuickAccessesList() - { - $links = QuickAccess::getQuickAccesses($this->context->language->id); - return Tools::jsonEncode(array_map(array($this, 'getLinkToken'), $links)); - } + public function getQuickAccessesList() + { + $links = QuickAccess::getQuickAccesses($this->context->language->id); + return Tools::jsonEncode(array_map(array($this, 'getLinkToken'), $links)); + } - public function getLinkToken($item) - { - $url = parse_url($item['link']); - parse_str($url['query'], $query); - $controller = $query['controller']; - $item['token'] = Tools::getAdminTokenLite($controller); - return $item; - } + public function getLinkToken($item) + { + $url = parse_url($item['link']); + parse_str($url['query'], $query); + $controller = $query['controller']; + $item['token'] = Tools::getAdminTokenLite($controller); + return $item; + } - public function addQuickLink() - { - if (!isset($this->className) || empty($this->className)) - return false; - $this->validateRules(); + public function addQuickLink() + { + if (!isset($this->className) || empty($this->className)) { + return false; + } + $this->validateRules(); - if (count($this->errors) <= 0) - { - $this->object = new $this->className(); - $this->copyFromPost($this->object, $this->table); - $exists = Db::getInstance()->getValue('SELECT id_quick_access FROM '._DB_PREFIX_.'quick_access WHERE link = "'.pSQL($this->object->link).'"'); - if ($exists) - return true; - $this->beforeAdd($this->object); + if (count($this->errors) <= 0) { + $this->object = new $this->className(); + $this->copyFromPost($this->object, $this->table); + $exists = Db::getInstance()->getValue('SELECT id_quick_access FROM '._DB_PREFIX_.'quick_access WHERE link = "'.pSQL($this->object->link).'"'); + if ($exists) { + return true; + } + $this->beforeAdd($this->object); - if (method_exists($this->object, 'add') && !$this->object->add()) - { + if (method_exists($this->object, 'add') && !$this->object->add()) { + $this->errors[] = Tools::displayError('An error occurred while creating an object.'). + ' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>'; + } + /* voluntary do affectation here */ + elseif (($_POST[$this->identifier] = $this->object->id) && $this->postImage($this->object->id) && !count($this->errors) && $this->_redirect) { + PrestaShopLogger::addLog(sprintf($this->l('%s addition', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); + $this->afterAdd($this->object); + } + } - $this->errors[] = Tools::displayError('An error occurred while creating an object.'). - ' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>'; + $this->errors = array_unique($this->errors); + if (!empty($this->errors)) { + $this->errors['has_errors'] = true; + $this->ajaxDie(Tools::jsonEncode($this->errors)); + return false; + } + return $this->getQuickAccessesList(); + } - } - /* voluntary do affectation here */ - elseif (($_POST[$this->identifier] = $this->object->id) && $this->postImage($this->object->id) && !count($this->errors) && $this->_redirect) - { - PrestaShopLogger::addLog(sprintf($this->l('%s addition', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id); - $this->afterAdd($this->object); - } - } + public function processDelete() + { + parent::processDelete(); + return $this->getQuickAccessesList(); + } - $this->errors = array_unique($this->errors); - if (!empty($this->errors)) - { - $this->errors['has_errors'] = true; - $this->ajaxDie(Tools::jsonEncode($this->errors)); - return false; - } - return $this->getQuickAccessesList(); - } + public function ajaxProcessGetUrl() + { + if (Tools::strtolower(Tools::getValue('method')) === 'add') { + $params['new_window'] = 0; + $params['name_'.(int)Configuration::get('PS_LANG_DEFAULT')] = Tools::getValue('name'); + $params['link'] = 'index.php?'.Tools::getValue('url'); + $params['submitAddquick_access'] = 1; + unset($_POST['name']); + $_POST = array_merge($_POST, $params); + die($this->addQuickLink()); + } elseif (Tools::strtolower(Tools::getValue('method')) === 'remove') { + $params['deletequick_access'] = 1; + $_POST = array_merge($_POST, $params); + die($this->processDelete()); + } + } - public function processDelete() - { - parent::processDelete(); - return $this->getQuickAccessesList(); - } + public function processNewWindow() + { + if (Validate::isLoadedObject($object = $this->loadObject())) { + /** @var QuickAccess $object */ + if ($object->toggleNewWindow()) { + $this->redirect_after = self::$currentIndex.'&conf=5&token='.$this->token; + } else { + $this->errors[] = Tools::displayError('An error occurred while updating new window property.'); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the new window property for this object.'). + ' <b>'.$this->table.'</b> '. + Tools::displayError('(cannot load object)'); + } - public function ajaxProcessGetUrl() - { - if (Tools::strtolower(Tools::getValue('method')) === 'add') - { - $params['new_window'] = 0; - $params['name_'.(int)Configuration::get('PS_LANG_DEFAULT')] = Tools::getValue('name'); - $params['link'] = 'index.php?'.Tools::getValue('url'); - $params['submitAddquick_access'] = 1; - unset($_POST['name']); - $_POST = array_merge($_POST, $params); - die($this->addQuickLink()); - } - elseif (Tools::strtolower(Tools::getValue('method')) === 'remove') - { - $params['deletequick_access'] = 1; - $_POST = array_merge($_POST, $params); - die($this->processDelete()); - } - } - - public function processNewWindow() - { - if (Validate::isLoadedObject($object = $this->loadObject())) - { - /** @var QuickAccess $object */ - if ($object->toggleNewWindow()) - $this->redirect_after = self::$currentIndex.'&conf=5&token='.$this->token; - else - $this->errors[] = Tools::displayError('An error occurred while updating new window property.'); - } - else - $this->errors[] = Tools::displayError('An error occurred while updating the new window property for this object.'). - ' <b>'.$this->table.'</b> '. - Tools::displayError('(cannot load object)'); - - return $object; - } + return $object; + } } diff --git a/controllers/admin/AdminRangePriceController.php b/controllers/admin/AdminRangePriceController.php index 9596fd54..1196092a 100644 --- a/controllers/admin/AdminRangePriceController.php +++ b/controllers/admin/AdminRangePriceController.php @@ -29,123 +29,128 @@ */ class AdminRangePriceControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'range_price'; - $this->className = 'RangePrice'; - $this->lang = false; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'range_price'; + $this->className = 'RangePrice'; + $this->lang = false; - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?'))); + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?'))); - $this->fields_list = array( - 'id_range_price' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25), - 'carrier_name' => array('title' => $this->l('Carrier'), 'align' => 'left', 'width' => 'auto', 'filter_key' => 'ca!name'), - 'delimiter1' => array('title' => $this->l('From'), 'width' => 86, 'type' => 'price', 'align' => 'right'), - 'delimiter2' => array('title' => $this->l('To'), 'width' => 86, 'type' => 'price', 'align' => 'right')); + $this->fields_list = array( + 'id_range_price' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25), + 'carrier_name' => array('title' => $this->l('Carrier'), 'align' => 'left', 'width' => 'auto', 'filter_key' => 'ca!name'), + 'delimiter1' => array('title' => $this->l('From'), 'width' => 86, 'type' => 'price', 'align' => 'right'), + 'delimiter2' => array('title' => $this->l('To'), 'width' => 86, 'type' => 'price', 'align' => 'right')); - $this->_join = 'LEFT JOIN '._DB_PREFIX_.'carrier ca ON (ca.`id_carrier` = a.`id_carrier`)'; - $this->_select = 'ca.`name` AS carrier_name'; - $this->_where = 'AND ca.`deleted` = 0'; - $this->_use_found_rows = false; + $this->_join = 'LEFT JOIN '._DB_PREFIX_.'carrier ca ON (ca.`id_carrier` = a.`id_carrier`)'; + $this->_select = 'ca.`name` AS carrier_name'; + $this->_where = 'AND ca.`deleted` = 0'; + $this->_use_found_rows = false; - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - $this->page_header_toolbar_title = $this->l('Price ranges'); - $this->page_header_toolbar_btn['new_price_range'] = array( - 'href' => self::$currentIndex.'&addrange_price&token='.$this->token, - 'desc' => $this->l('Add new price range', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + $this->page_header_toolbar_title = $this->l('Price ranges'); + $this->page_header_toolbar_btn['new_price_range'] = array( + 'href' => self::$currentIndex.'&addrange_price&token='.$this->token, + 'desc' => $this->l('Add new price range', null, null, false), + 'icon' => 'process-icon-new' + ); - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderForm() - { - $currency = $this->context->currency; - $carriers = Carrier::getCarriers((int)Configuration::get('PS_LANG_DEFAULT'), true, false, false, null, Carrier::PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE); + public function renderForm() + { + $currency = $this->context->currency; + $carriers = Carrier::getCarriers((int)Configuration::get('PS_LANG_DEFAULT'), true, false, false, null, Carrier::PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE); - foreach ($carriers as $key => $carrier) - if ($carrier['is_free']) - unset($carriers[$key]); + foreach ($carriers as $key => $carrier) { + if ($carrier['is_free']) { + unset($carriers[$key]); + } + } - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Price ranges'), - 'icon' => 'icon-money' - ), - 'input' => array( - array( - 'type' => 'select', - 'label' => $this->l('Carrier'), - 'name' => 'id_carrier', - 'required' => false, - 'hint' => $this->l('You can apply this range to a different carrier by selecting its name.'), - 'options' => array( - 'query' => $carriers, - 'id' => 'id_carrier', - 'name' => 'name' - ), - 'empty_message' => '<p class="alert alert-block">'.$this->l('There is no carrier available for this price range.').'</p>' - ), - array( - 'type' => 'text', - 'label' => $this->l('From'), - 'name' => 'delimiter1', - 'required' => true, - 'suffix' => $currency->getSign('right').' '.$this->l('(Tax Incl.)'), - 'hint' => $this->l('Start range (included).'), - 'string_format' => '%.2f' - ), - array( - 'type' => 'text', - 'label' => $this->l('To'), - 'name' => 'delimiter2', - 'required' => true, - 'suffix' => $currency->getSign('right').' '.$this->l('(Tax Incl.)'), - 'hint' => $this->l('End range (excluded).'), - 'string_format' => '%.2f' - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - 'class' => 'btn btn-default' - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Price ranges'), + 'icon' => 'icon-money' + ), + 'input' => array( + array( + 'type' => 'select', + 'label' => $this->l('Carrier'), + 'name' => 'id_carrier', + 'required' => false, + 'hint' => $this->l('You can apply this range to a different carrier by selecting its name.'), + 'options' => array( + 'query' => $carriers, + 'id' => 'id_carrier', + 'name' => 'name' + ), + 'empty_message' => '<p class="alert alert-block">'.$this->l('There is no carrier available for this price range.').'</p>' + ), + array( + 'type' => 'text', + 'label' => $this->l('From'), + 'name' => 'delimiter1', + 'required' => true, + 'suffix' => $currency->getSign('right').' '.$this->l('(Tax Incl.)'), + 'hint' => $this->l('Start range (included).'), + 'string_format' => '%.2f' + ), + array( + 'type' => 'text', + 'label' => $this->l('To'), + 'name' => 'delimiter2', + 'required' => true, + 'suffix' => $currency->getSign('right').' '.$this->l('(Tax Incl.)'), + 'hint' => $this->l('End range (excluded).'), + 'string_format' => '%.2f' + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + 'class' => 'btn btn-default' + ) + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - if ($this->_list && is_array($this->_list)) - foreach ($this->_list as $key => $list) - if ($list['carrier_name'] == '0') - $this->_list[$key]['carrier_name'] = Carrier::getCarrierNameFromShopName(); - } + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + if ($this->_list && is_array($this->_list)) { + foreach ($this->_list as $key => $list) { + if ($list['carrier_name'] == '0') { + $this->_list[$key]['carrier_name'] = Carrier::getCarrierNameFromShopName(); + } + } + } + } - public function postProcess() - { - $id = (int)Tools::getValue('id_'.$this->table); - if (Tools::getValue('submitAdd'.$this->table)) - { - if (Tools::getValue('delimiter1') >= Tools::getValue('delimiter2')) - $this->errors[] = Tools::displayError('Invalid range'); - elseif (!$id && RangePrice::rangeExist((int)Tools::getValue('id_carrier'), (float)Tools::getValue('delimiter1'), (float)Tools::getValue('delimiter2'))) - $this->errors[] = Tools::displayError('The range already exists'); - elseif (RangePrice::isOverlapping((int)Tools::getValue('id_carrier'), (float)Tools::getValue('delimiter1'), (float)Tools::getValue('delimiter2'), ($id ? (int)$id : null))) - $this->errors[] = Tools::displayError('Error: Ranges are overlapping'); - elseif (!count($this->errors)) - parent::postProcess(); - } - else - parent::postProcess(); - } + public function postProcess() + { + $id = (int)Tools::getValue('id_'.$this->table); + if (Tools::getValue('submitAdd'.$this->table)) { + if (Tools::getValue('delimiter1') >= Tools::getValue('delimiter2')) { + $this->errors[] = Tools::displayError('Invalid range'); + } elseif (!$id && RangePrice::rangeExist((int)Tools::getValue('id_carrier'), (float)Tools::getValue('delimiter1'), (float)Tools::getValue('delimiter2'))) { + $this->errors[] = Tools::displayError('The range already exists'); + } elseif (RangePrice::isOverlapping((int)Tools::getValue('id_carrier'), (float)Tools::getValue('delimiter1'), (float)Tools::getValue('delimiter2'), ($id ? (int)$id : null))) { + $this->errors[] = Tools::displayError('Error: Ranges are overlapping'); + } elseif (!count($this->errors)) { + parent::postProcess(); + } + } else { + parent::postProcess(); + } + } } diff --git a/controllers/admin/AdminRangeWeightController.php b/controllers/admin/AdminRangeWeightController.php index 4d367f97..1f4d8c30 100644 --- a/controllers/admin/AdminRangeWeightController.php +++ b/controllers/admin/AdminRangeWeightController.php @@ -29,122 +29,125 @@ */ class AdminRangeWeightControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'range_weight'; - $this->className = 'RangeWeight'; - $this->lang = false; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'range_weight'; + $this->className = 'RangeWeight'; + $this->lang = false; - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?'))); + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?'))); - $this->fields_list = array( - 'id_range_weight' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25), - 'carrier_name' => array('title' => $this->l('Carrier'), 'align' => 'left', 'width' => 'auto', 'filter_key' => 'ca!name'), - 'delimiter1' => array('title' => $this->l('From'), 'width' => 86, 'type' => 'float', 'suffix' => Configuration::get('PS_WEIGHT_UNIT'), 'align' => 'right'), - 'delimiter2' => array('title' => $this->l('To'), 'width' => 86, 'type' => 'float', 'suffix' => Configuration::get('PS_WEIGHT_UNIT'), 'align' => 'right')); + $this->fields_list = array( + 'id_range_weight' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25), + 'carrier_name' => array('title' => $this->l('Carrier'), 'align' => 'left', 'width' => 'auto', 'filter_key' => 'ca!name'), + 'delimiter1' => array('title' => $this->l('From'), 'width' => 86, 'type' => 'float', 'suffix' => Configuration::get('PS_WEIGHT_UNIT'), 'align' => 'right'), + 'delimiter2' => array('title' => $this->l('To'), 'width' => 86, 'type' => 'float', 'suffix' => Configuration::get('PS_WEIGHT_UNIT'), 'align' => 'right')); - $this->_join = 'LEFT JOIN '._DB_PREFIX_.'carrier ca ON (ca.`id_carrier` = a.`id_carrier`)'; - $this->_select = 'ca.`name` AS carrier_name'; - $this->_where = 'AND ca.`deleted` = 0'; - $this->_use_found_rows = false; + $this->_join = 'LEFT JOIN '._DB_PREFIX_.'carrier ca ON (ca.`id_carrier` = a.`id_carrier`)'; + $this->_select = 'ca.`name` AS carrier_name'; + $this->_where = 'AND ca.`deleted` = 0'; + $this->_use_found_rows = false; - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - $this->page_header_toolbar_title = $this->l('Weight ranges'); - $this->page_header_toolbar_btn['new_weight_range'] = array( - 'href' => self::$currentIndex.'&addrange_weight&token='.$this->token, - 'desc' => $this->l('Add new weight range', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + $this->page_header_toolbar_title = $this->l('Weight ranges'); + $this->page_header_toolbar_btn['new_weight_range'] = array( + 'href' => self::$currentIndex.'&addrange_weight&token='.$this->token, + 'desc' => $this->l('Add new weight range', null, null, false), + 'icon' => 'process-icon-new' + ); - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderForm() - { - $carriers = Carrier::getCarriers($this->context->language->id, true, false, false, null, Carrier::PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE); - foreach ($carriers as $key => $carrier) - if ($carrier['is_free']) - unset($carriers[$key]); + public function renderForm() + { + $carriers = Carrier::getCarriers($this->context->language->id, true, false, false, null, Carrier::PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE); + foreach ($carriers as $key => $carrier) { + if ($carrier['is_free']) { + unset($carriers[$key]); + } + } - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Weight ranges'), - 'icon' => 'icon-suitcase' - ), - 'input' => array( - array( - 'type' => 'select', - 'label' => $this->l('Carrier'), - 'name' => 'id_carrier', - 'required' => false, - 'hint' => $this->l('You can apply this range to a different carrier by selecting its name.'), - 'options' => array( - 'query' => $carriers, - 'id' => 'id_carrier', - 'name' => 'name' - ), - 'empty_message' => '<p class="alert alert-block">'.$this->l('There is no carrier available for this weight range.').'</p>' - ), - array( - 'type' => 'text', - 'label' => $this->l('From'), - 'name' => 'delimiter1', - 'required' => true, - 'suffix' => Configuration::get('PS_WEIGHT_UNIT'), - 'hint' => $this->l('Start range (included).'), - ), - array( - 'type' => 'text', - 'label' => $this->l('To'), - 'name' => 'delimiter2', - 'required' => true, - 'suffix' => Configuration::get('PS_WEIGHT_UNIT'), - 'hint' => $this->l('End range (excluded).'), - ), - ), - 'submit' => array( - 'title' => $this->l(' Save '), - 'class' => 'btn btn-default' - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Weight ranges'), + 'icon' => 'icon-suitcase' + ), + 'input' => array( + array( + 'type' => 'select', + 'label' => $this->l('Carrier'), + 'name' => 'id_carrier', + 'required' => false, + 'hint' => $this->l('You can apply this range to a different carrier by selecting its name.'), + 'options' => array( + 'query' => $carriers, + 'id' => 'id_carrier', + 'name' => 'name' + ), + 'empty_message' => '<p class="alert alert-block">'.$this->l('There is no carrier available for this weight range.').'</p>' + ), + array( + 'type' => 'text', + 'label' => $this->l('From'), + 'name' => 'delimiter1', + 'required' => true, + 'suffix' => Configuration::get('PS_WEIGHT_UNIT'), + 'hint' => $this->l('Start range (included).'), + ), + array( + 'type' => 'text', + 'label' => $this->l('To'), + 'name' => 'delimiter2', + 'required' => true, + 'suffix' => Configuration::get('PS_WEIGHT_UNIT'), + 'hint' => $this->l('End range (excluded).'), + ), + ), + 'submit' => array( + 'title' => $this->l(' Save '), + 'class' => 'btn btn-default' + ) + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - if ($this->_list && is_array($this->_list)) - foreach ($this->_list as $key => $list) - if ($list['carrier_name'] == '0') - $this->_list[$key]['carrier_name'] = Carrier::getCarrierNameFromShopName(); - } + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + if ($this->_list && is_array($this->_list)) { + foreach ($this->_list as $key => $list) { + if ($list['carrier_name'] == '0') { + $this->_list[$key]['carrier_name'] = Carrier::getCarrierNameFromShopName(); + } + } + } + } - public function postProcess() - { - $id = (int)Tools::getValue('id_'.$this->table); - - if (Tools::getValue('submitAdd'.$this->table)) - { - if (Tools::getValue('delimiter1') >= Tools::getValue('delimiter2')) - $this->errors[] = Tools::displayError('Invalid range'); - elseif (!$id && RangeWeight::rangeExist((int)Tools::getValue('id_carrier'), (float)Tools::getValue('delimiter1'), (float)Tools::getValue('delimiter2'))) - $this->errors[] = Tools::displayError('The range already exists'); - elseif (RangeWeight::isOverlapping((int)Tools::getValue('id_carrier'), (float)Tools::getValue('delimiter1'), (float)Tools::getValue('delimiter2'), ($id ? (int)$id : null))) - $this->errors[] = Tools::displayError('Error: Ranges are overlapping'); - elseif (!count($this->errors)) - parent::postProcess(); - } - else - parent::postProcess(); - } + public function postProcess() + { + $id = (int)Tools::getValue('id_'.$this->table); + + if (Tools::getValue('submitAdd'.$this->table)) { + if (Tools::getValue('delimiter1') >= Tools::getValue('delimiter2')) { + $this->errors[] = Tools::displayError('Invalid range'); + } elseif (!$id && RangeWeight::rangeExist((int)Tools::getValue('id_carrier'), (float)Tools::getValue('delimiter1'), (float)Tools::getValue('delimiter2'))) { + $this->errors[] = Tools::displayError('The range already exists'); + } elseif (RangeWeight::isOverlapping((int)Tools::getValue('id_carrier'), (float)Tools::getValue('delimiter1'), (float)Tools::getValue('delimiter2'), ($id ? (int)$id : null))) { + $this->errors[] = Tools::displayError('Error: Ranges are overlapping'); + } elseif (!count($this->errors)) { + parent::postProcess(); + } + } else { + parent::postProcess(); + } + } } - - diff --git a/controllers/admin/AdminReferrersController.php b/controllers/admin/AdminReferrersController.php index fa8dbee1..f3adf5ac 100644 --- a/controllers/admin/AdminReferrersController.php +++ b/controllers/admin/AdminReferrersController.php @@ -24,32 +24,33 @@ * International Registered Trademark & Property of PrestaShop SA */ -if (!defined('_PS_ADMIN_DIR_')) define('_PS_ADMIN_DIR_', getcwd().'/..'); +if (!defined('_PS_ADMIN_DIR_')) { + define('_PS_ADMIN_DIR_', getcwd().'/..'); +} -if (Tools::getValue('token') == Tools::getAdminToken('AdminReferrers'.(int)Tab::getIdFromClassName('AdminReferrers').(int)Tools::getValue('id_employee'))) -{ - if (Tools::isSubmit('ajaxProductFilter')) - Referrer::getAjaxProduct( - (int)Tools::getValue('id_referrer'), - (int)Tools::getValue('id_product'), - new Employee((int)Tools::getValue('id_employee')) - ); - elseif (Tools::isSubmit('ajaxFillProducts')) - { - $json_array = array(); - $result = Db::getInstance()->executeS(' +if (Tools::getValue('token') == Tools::getAdminToken('AdminReferrers'.(int)Tab::getIdFromClassName('AdminReferrers').(int)Tools::getValue('id_employee'))) { + if (Tools::isSubmit('ajaxProductFilter')) { + Referrer::getAjaxProduct( + (int)Tools::getValue('id_referrer'), + (int)Tools::getValue('id_product'), + new Employee((int)Tools::getValue('id_employee')) + ); + } elseif (Tools::isSubmit('ajaxFillProducts')) { + $json_array = array(); + $result = Db::getInstance()->executeS(' SELECT p.id_product, pl.name FROM '._DB_PREFIX_.'product p LEFT JOIN '._DB_PREFIX_.'product_lang pl ON (p.id_product = pl.id_product AND pl.id_lang = '.(int)Tools::getValue('id_lang').') '.(Tools::getValue('filter') != 'undefined' ? 'WHERE name LIKE "%'.pSQL(Tools::getValue('filter')).'%"' : '') - ); + ); - foreach ($result as $row) - $json_array[] = '{id_product:'.(int)$row['id_product'].',name:\''.addslashes($row['name']).'\'}'; + foreach ($result as $row) { + $json_array[] = '{id_product:'.(int)$row['id_product'].',name:\''.addslashes($row['name']).'\'}'; + } - die ('['.implode(',', $json_array).']'); - } + die('['.implode(',', $json_array).']'); + } } /** @@ -57,440 +58,444 @@ if (Tools::getValue('token') == Tools::getAdminToken('AdminReferrers'.(int)Tab:: */ class AdminReferrersControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'referrer'; - $this->className = 'Referrer'; - $this->fields_list = array( - 'id_referrer' => array( - 'title' => $this->l('ID'), - 'width' => 25, - 'align' => 'center' - ), - 'name' => array( - 'title' => $this->l('Name'), - 'width' => 80 - ), - 'cache_visitors' => array( - 'title' => $this->l('Visitors'), - 'width' => 30, - 'align' => 'center' - ), - 'cache_visits' => array( - 'title' => $this->l('Visits'), - 'width' => 30, - 'align' => 'center' - ), - 'cache_pages' => array( - 'title' => $this->l('Pages'), - 'width' => 30, - 'align' => 'center' - ), - 'cache_registrations' => array( - 'title' => $this->l('Reg.'), - 'width' => 30, - 'align' => 'center' - ), - 'cache_orders' => array( - 'title' => $this->l('Orders'), - 'width' => 30, - 'align' => 'center' - ), - 'cache_sales' => array( - 'title' => $this->l('Sales'), - 'width' => 80, - 'align' => 'right', - 'prefix' => '<b>', - 'suffix' => '</b>', - 'price' => true - ), - 'cart' => array( - 'title' => $this->l('Avg. cart'), - 'width' => 50, - 'align' => 'right', - 'price' => true, - 'havingFilter' => true - ), - 'cache_reg_rate' => array( - 'title' => $this->l('Reg. rate'), - 'width' => 30, - 'align' => 'center' - ), - 'cache_order_rate' => array( - 'title' => $this->l('Order rate'), - 'width' => 30, - 'align' => 'center' - ), - 'fee0' => array( - 'title' => $this->l('Click'), - 'width' => 30, - 'align' => 'right', - 'price' => true, - 'havingFilter' => true - ), - 'fee1' => array( - 'title' => $this->l('Base'), - 'width' => 30, - 'align' => 'right', - 'price' => true, - 'havingFilter' => true - ), - 'fee2' => array( - 'title' => $this->l('Percent'), - 'width' => 30, - 'align' => 'right', - 'price' => true, - 'havingFilter' => true - ) - ); + public function __construct() + { + $this->bootstrap = true; + $this->table = 'referrer'; + $this->className = 'Referrer'; + $this->fields_list = array( + 'id_referrer' => array( + 'title' => $this->l('ID'), + 'width' => 25, + 'align' => 'center' + ), + 'name' => array( + 'title' => $this->l('Name'), + 'width' => 80 + ), + 'cache_visitors' => array( + 'title' => $this->l('Visitors'), + 'width' => 30, + 'align' => 'center' + ), + 'cache_visits' => array( + 'title' => $this->l('Visits'), + 'width' => 30, + 'align' => 'center' + ), + 'cache_pages' => array( + 'title' => $this->l('Pages'), + 'width' => 30, + 'align' => 'center' + ), + 'cache_registrations' => array( + 'title' => $this->l('Reg.'), + 'width' => 30, + 'align' => 'center' + ), + 'cache_orders' => array( + 'title' => $this->l('Orders'), + 'width' => 30, + 'align' => 'center' + ), + 'cache_sales' => array( + 'title' => $this->l('Sales'), + 'width' => 80, + 'align' => 'right', + 'prefix' => '<b>', + 'suffix' => '</b>', + 'price' => true + ), + 'cart' => array( + 'title' => $this->l('Avg. cart'), + 'width' => 50, + 'align' => 'right', + 'price' => true, + 'havingFilter' => true + ), + 'cache_reg_rate' => array( + 'title' => $this->l('Reg. rate'), + 'width' => 30, + 'align' => 'center' + ), + 'cache_order_rate' => array( + 'title' => $this->l('Order rate'), + 'width' => 30, + 'align' => 'center' + ), + 'fee0' => array( + 'title' => $this->l('Click'), + 'width' => 30, + 'align' => 'right', + 'price' => true, + 'havingFilter' => true + ), + 'fee1' => array( + 'title' => $this->l('Base'), + 'width' => 30, + 'align' => 'right', + 'price' => true, + 'havingFilter' => true + ), + 'fee2' => array( + 'title' => $this->l('Percent'), + 'width' => 30, + 'align' => 'right', + 'price' => true, + 'havingFilter' => true + ) + ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function setMedia() - { - parent::setMedia(); - $this->context->controller->addJqueryUI('ui.datepicker'); - } + public function setMedia() + { + parent::setMedia(); + $this->context->controller->addJqueryUI('ui.datepicker'); + } - public function initPageHeaderToolbar() - { - if(empty($this->display)) - $this->page_header_toolbar_btn['new_referrer'] = array( - 'href' => self::$currentIndex.'&addreferrer&token='.$this->token, - 'desc' => $this->l('Add new referrer', null, null, false), - 'icon' => 'process-icon-new' - ); - - parent::initPageHeaderToolbar(); - } + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_referrer'] = array( + 'href' => self::$currentIndex.'&addreferrer&token='.$this->token, + 'desc' => $this->l('Add new referrer', null, null, false), + 'icon' => 'process-icon-new' + ); + } + + parent::initPageHeaderToolbar(); + } - public function renderList() - { - // Display list Referrers: - $this->addRowAction('view'); - $this->addRowAction('edit'); - $this->addRowAction('delete'); + public function renderList() + { + // Display list Referrers: + $this->addRowAction('view'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->_select = 'SUM(sa.cache_visitors) AS cache_visitors, SUM(sa.cache_visits) AS cache_visits, SUM(sa.cache_pages) AS cache_pages, + $this->_select = 'SUM(sa.cache_visitors) AS cache_visitors, SUM(sa.cache_visits) AS cache_visits, SUM(sa.cache_pages) AS cache_pages, SUM(sa.cache_registrations) AS cache_registrations, SUM(sa.cache_orders) AS cache_orders, SUM(sa.cache_sales) AS cache_sales, IF(sa.cache_orders > 0, ROUND(sa.cache_sales/sa.cache_orders, 2), 0) as cart, (sa.cache_visits*click_fee) as fee0, (sa.cache_orders*base_fee) as fee1, (sa.cache_sales*percent_fee/100) as fee2'; - $this->_join = ' + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'referrer_shop` sa ON (sa.'.$this->identifier.' = a.'.$this->identifier.' AND sa.id_shop IN ('.implode(', ', Shop::getContextListShopID()).'))'; - $this->_group = 'GROUP BY sa.id_referrer'; + $this->_group = 'GROUP BY sa.id_referrer'; - $this->tpl_list_vars = array( - 'enable_calendar' => $this->enableCalendar(), - 'calendar_form' => $this->displayCalendar(), - 'settings_form' => $this->displaySettings() - ); + $this->tpl_list_vars = array( + 'enable_calendar' => $this->enableCalendar(), + 'calendar_form' => $this->displayCalendar(), + 'settings_form' => $this->displaySettings() + ); - return parent::renderList(); - } + return parent::renderList(); + } - public function renderForm() - { - $uri = Tools::getHttpHost(true, true).__PS_BASE_URI__; + public function renderForm() + { + $uri = Tools::getHttpHost(true, true).__PS_BASE_URI__; - $this->fields_form[0] = array('form' => array( - 'legend' => array( - 'title' => $this->l('Affiliate'), - 'icon' => 'icon-group' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'required' => true, - 'autocomplete' => false - ), - array( - 'type' => 'password', - 'label' => $this->l('Password'), - 'name' => 'passwd', - 'desc' => $this->l('Leave blank if no change.'), - 'autocomplete' => false - ) - ), - 'submit' => array('title' => $this->l('Save')), - )); + $this->fields_form[0] = array('form' => array( + 'legend' => array( + 'title' => $this->l('Affiliate'), + 'icon' => 'icon-group' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'required' => true, + 'autocomplete' => false + ), + array( + 'type' => 'password', + 'label' => $this->l('Password'), + 'name' => 'passwd', + 'desc' => $this->l('Leave blank if no change.'), + 'autocomplete' => false + ) + ), + 'submit' => array('title' => $this->l('Save')), + )); - if (Module::isInstalled('trackingfront')) - $this->fields_form[0]['form']['desc'] = array( - $this->l('Affiliates can access their data with this name and password.'), - $this->l('Front access:').' <a class="btn btn-link" href="'.$uri.'modules/trackingfront/stats.php" onclick="return !window.open(this.href);"><i class="icon-external-link-sign"></i> '.$uri.'modules/trackingfront/stats.php</a>' - ); - else - $this->fields_form[0]['form']['desc'] = array( - sprintf($this->l('Please install the "%s" module in order to give your affiliates access their own statistics.'), Module::getModuleName('trackingfront')) - ); + if (Module::isInstalled('trackingfront')) { + $this->fields_form[0]['form']['desc'] = array( + $this->l('Affiliates can access their data with this name and password.'), + $this->l('Front access:').' <a class="btn btn-link" href="'.$uri.'modules/trackingfront/stats.php" onclick="return !window.open(this.href);"><i class="icon-external-link-sign"></i> '.$uri.'modules/trackingfront/stats.php</a>' + ); + } else { + $this->fields_form[0]['form']['desc'] = array( + sprintf($this->l('Please install the "%s" module in order to give your affiliates access their own statistics.'), Module::getModuleName('trackingfront')) + ); + } - $this->fields_form[1] = array('form' => array( - 'legend' => array( - 'title' => $this->l('Commission plan'), - 'icon' => 'icon-dollar' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Click fee'), - 'name' => 'click_fee', - 'desc' => $this->l('Fee given for each visit.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Base fee'), - 'name' => 'base_fee', - 'desc' => $this->l('Fee given for each order placed.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Percent fee'), - 'name' => 'percent_fee', - 'desc' => $this->l('Percent of the sales.') - ) - ), - 'submit' => array('title' => $this->l('Save')) - )); + $this->fields_form[1] = array('form' => array( + 'legend' => array( + 'title' => $this->l('Commission plan'), + 'icon' => 'icon-dollar' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Click fee'), + 'name' => 'click_fee', + 'desc' => $this->l('Fee given for each visit.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Base fee'), + 'name' => 'base_fee', + 'desc' => $this->l('Fee given for each order placed.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Percent fee'), + 'name' => 'percent_fee', + 'desc' => $this->l('Percent of the sales.') + ) + ), + 'submit' => array('title' => $this->l('Save')) + )); - if (Shop::isFeatureActive()) - { - $this->fields_form[1]['form']['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + if (Shop::isFeatureActive()) { + $this->fields_form[1]['form']['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - $this->fields_form[2] = array('form' => array( - 'legend' => array( - 'title' => $this->l('Technical information -- Simple mode'), - 'icon' => 'icon-cogs' - ), - 'help' => true, - 'input' => array( - array( - 'type' => 'textarea', - 'label' => $this->l('Include'), - 'name' => 'http_referer_like', - 'cols' => 40, - 'rows' => 1, - 'legend' => $this->l('HTTP referrer') - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Exclude'), - 'name' => 'http_referer_like_not', - 'cols' => 40, - 'rows' => 1 - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Include'), - 'name' => 'request_uri_like', - 'cols' => 40, - 'rows' => 1, - 'legend' => $this->l('Request URI') - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Exclude'), - 'name' => 'request_uri_like_not', - 'cols' => 40, - 'rows' => 1 - ) - ), - 'desc' => $this->l('If you know how to use MySQL regular expressions, you can use the').' + $this->fields_form[2] = array('form' => array( + 'legend' => array( + 'title' => $this->l('Technical information -- Simple mode'), + 'icon' => 'icon-cogs' + ), + 'help' => true, + 'input' => array( + array( + 'type' => 'textarea', + 'label' => $this->l('Include'), + 'name' => 'http_referer_like', + 'cols' => 40, + 'rows' => 1, + 'legend' => $this->l('HTTP referrer') + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Exclude'), + 'name' => 'http_referer_like_not', + 'cols' => 40, + 'rows' => 1 + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Include'), + 'name' => 'request_uri_like', + 'cols' => 40, + 'rows' => 1, + 'legend' => $this->l('Request URI') + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Exclude'), + 'name' => 'request_uri_like_not', + 'cols' => 40, + 'rows' => 1 + ) + ), + 'desc' => $this->l('If you know how to use MySQL regular expressions, you can use the').' <a style="cursor: pointer; font-weight: bold;" onclick="$(\'#tracking_expert\').slideToggle();">'.$this->l('expert mode').'.</a>', - 'submit' => array( - 'title' => $this->l('Save'), - ) - )); + 'submit' => array( + 'title' => $this->l('Save'), + ) + )); - $this->fields_form[3] = array('form' => array( - 'legend' => array( - 'title' => $this->l('Technical information -- Expert mode'), - 'icon' => 'icon-cogs' - ), - 'input' => array( - array( - 'type' => 'textarea', - 'label' => $this->l('Include'), - 'name' => 'http_referer_regexp', - 'cols' => 40, - 'rows' => 1, - 'legend' => $this->l('HTTP referrer') - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Exclude'), - 'name' => 'http_referer_regexp_not', - 'cols' => 40, - 'rows' => 1 - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Include'), - 'name' => 'request_uri_regexp', - 'cols' => 40, - 'rows' => 1, - 'legend' => $this->l('Request URI') - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Exclude'), - 'name' => 'request_uri_regexp_not', - 'cols' => 40, - 'rows' => 1 - ) - ) - )); + $this->fields_form[3] = array('form' => array( + 'legend' => array( + 'title' => $this->l('Technical information -- Expert mode'), + 'icon' => 'icon-cogs' + ), + 'input' => array( + array( + 'type' => 'textarea', + 'label' => $this->l('Include'), + 'name' => 'http_referer_regexp', + 'cols' => 40, + 'rows' => 1, + 'legend' => $this->l('HTTP referrer') + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Exclude'), + 'name' => 'http_referer_regexp_not', + 'cols' => 40, + 'rows' => 1 + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Include'), + 'name' => 'request_uri_regexp', + 'cols' => 40, + 'rows' => 1, + 'legend' => $this->l('Request URI') + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Exclude'), + 'name' => 'request_uri_regexp_not', + 'cols' => 40, + 'rows' => 1 + ) + ) + )); - $this->multiple_fieldsets = true; + $this->multiple_fieldsets = true; - if (!($obj = $this->loadObject(true))) - return; + if (!($obj = $this->loadObject(true))) { + return; + } - $this->fields_value = array( - 'click_fee' => number_format((float)($this->getFieldValue($obj, 'click_fee')), 2), - 'base_fee' => number_format((float)($this->getFieldValue($obj, 'base_fee')), 2), - 'percent_fee' => number_format((float)($this->getFieldValue($obj, 'percent_fee')), 2), - 'http_referer_like' => str_replace('\\', '\\\\', htmlentities($this->getFieldValue($obj, 'http_referer_like'), ENT_COMPAT, 'UTF-8')), - 'http_referer_like_not' => str_replace('\\', '\\\\', htmlentities($this->getFieldValue($obj, 'http_referer_like_not'), ENT_COMPAT, 'UTF-8')), - 'request_uri_like' => str_replace('\\', '\\\\', htmlentities($this->getFieldValue($obj, 'request_uri_like'), ENT_COMPAT, 'UTF-8')), - 'request_uri_like_not' => str_replace('\\', '\\\\', htmlentities($this->getFieldValue($obj, 'request_uri_like_not'), ENT_COMPAT, 'UTF-8')) - ); + $this->fields_value = array( + 'click_fee' => number_format((float)($this->getFieldValue($obj, 'click_fee')), 2), + 'base_fee' => number_format((float)($this->getFieldValue($obj, 'base_fee')), 2), + 'percent_fee' => number_format((float)($this->getFieldValue($obj, 'percent_fee')), 2), + 'http_referer_like' => str_replace('\\', '\\\\', htmlentities($this->getFieldValue($obj, 'http_referer_like'), ENT_COMPAT, 'UTF-8')), + 'http_referer_like_not' => str_replace('\\', '\\\\', htmlentities($this->getFieldValue($obj, 'http_referer_like_not'), ENT_COMPAT, 'UTF-8')), + 'request_uri_like' => str_replace('\\', '\\\\', htmlentities($this->getFieldValue($obj, 'request_uri_like'), ENT_COMPAT, 'UTF-8')), + 'request_uri_like_not' => str_replace('\\', '\\\\', htmlentities($this->getFieldValue($obj, 'request_uri_like_not'), ENT_COMPAT, 'UTF-8')) + ); - $this->tpl_form_vars = array('uri' => $uri); + $this->tpl_form_vars = array('uri' => $uri); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function displayCalendar($action = null, $table = null, $identifier = null, $id = null) - { - return AdminReferrersController::displayCalendarForm(array( - 'Calendar' => $this->l('Calendar'), - 'Day' => $this->l('Today'), - 'Month' => $this->l('Month'), - 'Year' => $this->l('Year') - ), $this->token, $action, $table, $identifier, $id); - } + public function displayCalendar($action = null, $table = null, $identifier = null, $id = null) + { + return AdminReferrersController::displayCalendarForm(array( + 'Calendar' => $this->l('Calendar'), + 'Day' => $this->l('Today'), + 'Month' => $this->l('Month'), + 'Year' => $this->l('Year') + ), $this->token, $action, $table, $identifier, $id); + } - public static function displayCalendarForm($translations, $token, $action = null, $table = null, $identifier = null, $id = null) - { - $context = Context::getContext(); - $tpl = $context->controller->createTemplate('calendar.tpl'); + public static function displayCalendarForm($translations, $token, $action = null, $table = null, $identifier = null, $id = null) + { + $context = Context::getContext(); + $tpl = $context->controller->createTemplate('calendar.tpl'); - $context->controller->addJqueryUI('ui.datepicker'); + $context->controller->addJqueryUI('ui.datepicker'); - $tpl->assign(array( - 'current' => self::$currentIndex, - 'token' => $token, - 'action' => $action, - 'table' => $table, - 'identifier' => $identifier, - 'id' => $id, - 'translations' => $translations, - 'datepickerFrom' => Tools::getValue('datepickerFrom', $context->employee->stats_date_from), - 'datepickerTo' => Tools::getValue('datepickerTo', $context->employee->stats_date_to) - )); + $tpl->assign(array( + 'current' => self::$currentIndex, + 'token' => $token, + 'action' => $action, + 'table' => $table, + 'identifier' => $identifier, + 'id' => $id, + 'translations' => $translations, + 'datepickerFrom' => Tools::getValue('datepickerFrom', $context->employee->stats_date_from), + 'datepickerTo' => Tools::getValue('datepickerTo', $context->employee->stats_date_to) + )); - return $tpl->fetch(); - } + return $tpl->fetch(); + } - public function displaySettings() - { - if (!Tools::isSubmit('viewreferrer')) - { - $tpl = $this->createTemplate('form_settings.tpl'); + public function displaySettings() + { + if (!Tools::isSubmit('viewreferrer')) { + $tpl = $this->createTemplate('form_settings.tpl'); - $statsdata = Module::getInstanceByName('statsdata'); + $statsdata = Module::getInstanceByName('statsdata'); - $statsdata_name = false; - if (Validate::isLoadedObject($statsdata)) - $statsdata_name = $statsdata->displayName; - $tpl->assign(array( - 'statsdata_name' => $statsdata_name, - 'current' => self::$currentIndex, - 'token' => $this->token, - 'tracking_dt' => (int)Tools::getValue('tracking_dt', Configuration::get('TRACKING_DIRECT_TRAFFIC')) - )); + $statsdata_name = false; + if (Validate::isLoadedObject($statsdata)) { + $statsdata_name = $statsdata->displayName; + } + $tpl->assign(array( + 'statsdata_name' => $statsdata_name, + 'current' => self::$currentIndex, + 'token' => $this->token, + 'tracking_dt' => (int)Tools::getValue('tracking_dt', Configuration::get('TRACKING_DIRECT_TRAFFIC')) + )); - return $tpl->fetch(); - } - } + return $tpl->fetch(); + } + } - protected function enableCalendar() - { - return (!Tools::isSubmit('add'.$this->table) && !Tools::isSubmit('submitAdd'.$this->table) && !Tools::isSubmit('update'.$this->table)); - } + protected function enableCalendar() + { + return (!Tools::isSubmit('add'.$this->table) && !Tools::isSubmit('submitAdd'.$this->table) && !Tools::isSubmit('update'.$this->table)); + } - public function postProcess() - { - if ($this->enableCalendar()) - { - // Warning, instantiating a controller here changes the controller in the Context... - $calendar_tab = new AdminStatsController(); - $calendar_tab->postProcess(); - // ...so we set it back to the correct one here - $this->context->controller = $this; - } + public function postProcess() + { + if ($this->enableCalendar()) { + // Warning, instantiating a controller here changes the controller in the Context... + $calendar_tab = new AdminStatsController(); + $calendar_tab->postProcess(); + // ...so we set it back to the correct one here + $this->context->controller = $this; + } - if (Tools::isSubmit('submitSettings')) - if ($this->tabAccess['edit'] === '1') - if (Configuration::updateValue('TRACKING_DIRECT_TRAFFIC', (int)Tools::getValue('tracking_dt'))) - Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.Tools::getValue('token')); + if (Tools::isSubmit('submitSettings')) { + if ($this->tabAccess['edit'] === '1') { + if (Configuration::updateValue('TRACKING_DIRECT_TRAFFIC', (int)Tools::getValue('tracking_dt'))) { + Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.Tools::getValue('token')); + } + } + } - if (ModuleGraph::getDateBetween() != Configuration::get('PS_REFERRERS_CACHE_LIKE') || Tools::isSubmit('submitRefreshCache')) - Referrer::refreshCache(); - if (Tools::isSubmit('submitRefreshIndex')) - Referrer::refreshIndex(); + if (ModuleGraph::getDateBetween() != Configuration::get('PS_REFERRERS_CACHE_LIKE') || Tools::isSubmit('submitRefreshCache')) { + Referrer::refreshCache(); + } + if (Tools::isSubmit('submitRefreshIndex')) { + Referrer::refreshIndex(); + } - return parent::postProcess(); - } + return parent::postProcess(); + } - public function renderView() - { - $referrer = new Referrer((int)Tools::getValue('id_referrer')); + public function renderView() + { + $referrer = new Referrer((int)Tools::getValue('id_referrer')); - $display_tab = array( - 'uniqs' => $this->l('Unique visitors'), - 'visitors' => $this->l('Visitors'), - 'visits' => $this->l('Visits'), - 'pages' => $this->l('Pages viewed'), - 'registrations' => $this->l('Registrations'), - 'orders' => $this->l('Orders'), - 'sales' => $this->l('Sales'), - 'reg_rate' => $this->l('Registration rate'), - 'order_rate' => $this->l('Order rate'), - 'click_fee' => $this->l('Click fee'), - 'base_fee' => $this->l('Base fee'), - 'percent_fee' => $this->l('Percent fee')); + $display_tab = array( + 'uniqs' => $this->l('Unique visitors'), + 'visitors' => $this->l('Visitors'), + 'visits' => $this->l('Visits'), + 'pages' => $this->l('Pages viewed'), + 'registrations' => $this->l('Registrations'), + 'orders' => $this->l('Orders'), + 'sales' => $this->l('Sales'), + 'reg_rate' => $this->l('Registration rate'), + 'order_rate' => $this->l('Order rate'), + 'click_fee' => $this->l('Click fee'), + 'base_fee' => $this->l('Base fee'), + 'percent_fee' => $this->l('Percent fee')); - $this->tpl_view_vars = array( - 'enable_calendar' => $this->enableCalendar(), - 'calendar_form' => $this->displayCalendar($this->action, $this->table, $this->identifier, (int)Tools::getValue($this->identifier)), - 'referrer' => new Referrer((int)Tools::getValue('id_referrer')), - 'display_tab' => $display_tab, - 'id_employee' => (int)$this->context->employee->id, - 'id_lang' => (int)$this->context->language->id - ); + $this->tpl_view_vars = array( + 'enable_calendar' => $this->enableCalendar(), + 'calendar_form' => $this->displayCalendar($this->action, $this->table, $this->identifier, (int)Tools::getValue($this->identifier)), + 'referrer' => $referrer, + 'display_tab' => $display_tab, + 'id_employee' => (int)$this->context->employee->id, + 'id_lang' => (int)$this->context->language->id + ); - return parent::renderView(); - } + return parent::renderView(); + } } - - diff --git a/controllers/admin/AdminRequestSqlController.php b/controllers/admin/AdminRequestSqlController.php index 92018cab..344aedf2 100644 --- a/controllers/admin/AdminRequestSqlController.php +++ b/controllers/admin/AdminRequestSqlController.php @@ -29,91 +29,93 @@ */ class AdminRequestSqlControllerCore extends AdminController { - /** - * @var array : List of encoding type for a file - */ - public static $encoding_file = array( - array('value' => 1, 'name' => 'utf-8'), - array('value' => 2, 'name' => 'iso-8859-1') - ); + /** + * @var array : List of encoding type for a file + */ + public static $encoding_file = array( + array('value' => 1, 'name' => 'utf-8'), + array('value' => 2, 'name' => 'iso-8859-1') + ); - public function __construct() - { - $this->bootstrap = true; - $this->table = 'request_sql'; - $this->className = 'RequestSql'; - $this->lang = false; - $this->export = true; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'request_sql'; + $this->className = 'RequestSql'; + $this->lang = false; + $this->export = true; - $this->context = Context::getContext(); + $this->context = Context::getContext(); - $this->fields_list = array( - 'id_request_sql' => array('title' => $this->l('ID'), 'class' => 'fixed-width-xs'), - 'name' => array('title' => $this->l('SQL query Name')), - 'sql' => array('title' => $this->l('SQL query')) - ); + $this->fields_list = array( + 'id_request_sql' => array('title' => $this->l('ID'), 'class' => 'fixed-width-xs'), + 'name' => array('title' => $this->l('SQL query Name')), + 'sql' => array('title' => $this->l('SQL query')) + ); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Settings'), - 'fields' => array( - 'PS_ENCODING_FILE_MANAGER_SQL' => array( - 'title' => $this->l('Select your default file encoding'), - 'cast' => 'intval', - 'type' => 'select', - 'identifier' => 'value', - 'list' => self::$encoding_file, - 'visibility' => Shop::CONTEXT_ALL - ) - ), - 'submit' => array('title' => $this->l('Save')) - ) - ); + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Settings'), + 'fields' => array( + 'PS_ENCODING_FILE_MANAGER_SQL' => array( + 'title' => $this->l('Select your default file encoding'), + 'cast' => 'intval', + 'type' => 'select', + 'identifier' => 'value', + 'list' => self::$encoding_file, + 'visibility' => Shop::CONTEXT_ALL + ) + ), + 'submit' => array('title' => $this->l('Save')) + ) + ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function renderOptions() - { - // Set toolbar options - $this->display = 'options'; - $this->show_toolbar = true; - $this->toolbar_scroll = true; - $this->initToolbar(); + public function renderOptions() + { + // Set toolbar options + $this->display = 'options'; + $this->show_toolbar = true; + $this->toolbar_scroll = true; + $this->initToolbar(); - return parent::renderOptions(); - } + return parent::renderOptions(); + } - public function initToolbar() - { - if ($this->display == 'view' && $id_request = Tools::getValue('id_request_sql')) - $this->toolbar_btn['edit'] = array( - 'href' => self::$currentIndex.'&updaterequest_sql&token='.$this->token.'&id_request_sql='.(int)$id_request, - 'desc' => $this->l('Edit this SQL query') - ); + public function initToolbar() + { + if ($this->display == 'view' && $id_request = Tools::getValue('id_request_sql')) { + $this->toolbar_btn['edit'] = array( + 'href' => self::$currentIndex.'&updaterequest_sql&token='.$this->token.'&id_request_sql='.(int)$id_request, + 'desc' => $this->l('Edit this SQL query') + ); + } - parent::initToolbar(); + parent::initToolbar(); - if ($this->display == 'options') - unset($this->toolbar_btn['new']); - } + if ($this->display == 'options') { + unset($this->toolbar_btn['new']); + } + } - public function renderList() - { - // Set toolbar options - $this->display = null; - $this->initToolbar(); + public function renderList() + { + // Set toolbar options + $this->display = null; + $this->initToolbar(); - $this->displayWarning($this->l('When saving the query, only the "SELECT" SQL statement is allowed.')); - $this->displayInformation(' + $this->displayWarning($this->l('When saving the query, only the "SELECT" SQL statement is allowed.')); + $this->displayInformation(' <strong>'.$this->l('How do I create a new SQL query?').'</strong><br /> <ul> <li>'.$this->l('Click "Add New".').'</li> @@ -122,374 +124,370 @@ class AdminRequestSqlControllerCore extends AdminController <li>'.$this->l('You can also export the query results as a CSV file by clicking on the Export button: ').' <i class="icon-cloud-upload"></i></li> </ul>'); - $this->addRowAction('export'); - $this->addRowAction('view'); - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('export'); + $this->addRowAction('view'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - return parent::renderList(); - } + return parent::renderList(); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('SQL query'), - 'icon' => 'icon-cog' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('SQL query name'), - 'name' => 'name', - 'size' => 103, - 'required' => true - ), - array( - 'type' => 'textarea', - 'label' => $this->l('SQL query'), - 'name' => 'sql', - 'cols' => 100, - 'rows' => 10, - 'required' => true - ) - ), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('SQL query'), + 'icon' => 'icon-cog' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('SQL query name'), + 'name' => 'name', + 'size' => 103, + 'required' => true + ), + array( + 'type' => 'textarea', + 'label' => $this->l('SQL query'), + 'name' => 'sql', + 'cols' => 100, + 'rows' => 10, + 'required' => true + ) + ), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); - $request = new RequestSql(); - $this->tpl_form_vars = array('tables' => $request->getTables()); + $request = new RequestSql(); + $this->tpl_form_vars = array('tables' => $request->getTables()); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function postProcess() - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } - return parent::postProcess(); - } + public function postProcess() + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } + return parent::postProcess(); + } - /** - * method call when ajax request is made with the details row action - * @see AdminController::postProcess() - */ - public function ajaxProcess() - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - die(Tools::displayError('This functionality has been disabled.')); - if ($table = Tools::GetValue('table')) - { - $request_sql = new RequestSql(); - $attributes = $request_sql->getAttributesByTable($table); - foreach ($attributes as $key => $attribute) - { - unset($attributes[$key]['Null']); - unset($attributes[$key]['Key']); - unset($attributes[$key]['Default']); - unset($attributes[$key]['Extra']); - } - die(Tools::jsonEncode($attributes)); - } - } + /** + * method call when ajax request is made with the details row action + * @see AdminController::postProcess() + */ + public function ajaxProcess() + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + die(Tools::displayError('This functionality has been disabled.')); + } + if ($table = Tools::GetValue('table')) { + $request_sql = new RequestSql(); + $attributes = $request_sql->getAttributesByTable($table); + foreach ($attributes as $key => $attribute) { + unset($attributes[$key]['Null']); + unset($attributes[$key]['Key']); + unset($attributes[$key]['Default']); + unset($attributes[$key]['Extra']); + } + die(Tools::jsonEncode($attributes)); + } + } - public function renderView() - { - /** @var RequestSql $obj */ - if (!($obj = $this->loadObject(true))) - return; + public function renderView() + { + /** @var RequestSql $obj */ + if (!($obj = $this->loadObject(true))) { + return; + } - $view = array(); - if ($results = Db::getInstance()->executeS($obj->sql)) - { - foreach (array_keys($results[0]) as $key) - $tab_key[] = $key; + $view = array(); + if ($results = Db::getInstance()->executeS($obj->sql)) { + foreach (array_keys($results[0]) as $key) { + $tab_key[] = $key; + } - $view['name'] = $obj->name; - $view['key'] = $tab_key; - $view['results'] = $results; + $view['name'] = $obj->name; + $view['key'] = $tab_key; + $view['results'] = $results; - $this->toolbar_title = $obj->name; + $this->toolbar_title = $obj->name; - $request_sql = new RequestSql(); - $view['attributes'] = $request_sql->attributes; - } - else - $view['error'] = true; + $request_sql = new RequestSql(); + $view['attributes'] = $request_sql->attributes; + } else { + $view['error'] = true; + } - $this->tpl_view_vars = array( - 'view' => $view - ); - return parent::renderView(); - } + $this->tpl_view_vars = array( + 'view' => $view + ); + return parent::renderView(); + } - public function _childValidation() - { - if (Tools::getValue('submitAdd'.$this->table) && $sql = Tools::getValue('sql')) - { - $request_sql = new RequestSql(); - $parser = $request_sql->parsingSql($sql); - $validate = $request_sql->validateParser($parser, false, $sql); + public function _childValidation() + { + if (Tools::getValue('submitAdd'.$this->table) && $sql = Tools::getValue('sql')) { + $request_sql = new RequestSql(); + $parser = $request_sql->parsingSql($sql); + $validate = $request_sql->validateParser($parser, false, $sql); - if (!$validate || count($request_sql->error_sql)) - $this->displayError($request_sql->error_sql); - } - } + if (!$validate || count($request_sql->error_sql)) { + $this->displayError($request_sql->error_sql); + } + } + } - /** - * Display export action link - * - * @param $token - * @param int $id - * - * @return string - * @throws Exception - * @throws SmartyException - */ - public function displayExportLink($token, $id) - { - $tpl = $this->createTemplate('list_action_export.tpl'); + /** + * Display export action link + * + * @param $token + * @param int $id + * + * @return string + * @throws Exception + * @throws SmartyException + */ + public function displayExportLink($token, $id) + { + $tpl = $this->createTemplate('list_action_export.tpl'); - $tpl->assign(array( - 'href' => self::$currentIndex.'&token='.$this->token.'&'.$this->identifier.'='.$id.'&export'.$this->table.'=1', - 'action' => $this->l('Export') - )); + $tpl->assign(array( + 'href' => self::$currentIndex.'&token='.$this->token.'&'.$this->identifier.'='.$id.'&export'.$this->table.'=1', + 'action' => $this->l('Export') + )); - return $tpl->fetch(); - } + return $tpl->fetch(); + } - public function initProcess() - { - parent::initProcess(); - if (Tools::getValue('export'.$this->table)) - { - $this->display = 'export'; - $this->action = 'export'; - } - } + public function initProcess() + { + parent::initProcess(); + if (Tools::getValue('export'.$this->table)) { + $this->display = 'export'; + $this->action = 'export'; + } + } - public function initContent() - { - $this->initTabModuleList(); - // toolbar (save, cancel, new, ..) - $this->initToolbar(); - $this->initPageHeaderToolbar(); - if ($this->display == 'edit' || $this->display == 'add') - { - if (!$this->loadObject(true)) - return; + public function initContent() + { + $this->initTabModuleList(); + // toolbar (save, cancel, new, ..) + $this->initToolbar(); + $this->initPageHeaderToolbar(); + if ($this->display == 'edit' || $this->display == 'add') { + if (!$this->loadObject(true)) { + return; + } - $this->content .= $this->renderForm(); - } - elseif ($this->display == 'view') - { - // Some controllers use the view action without an object - if ($this->className) - $this->loadObject(true); - $this->content .= $this->renderView(); - } - elseif ($this->display == 'export') - $this->generateExport(); - elseif (!$this->ajax) - { - $this->content .= $this->renderList(); - $this->content .= $this->renderOptions(); - } + $this->content .= $this->renderForm(); + } elseif ($this->display == 'view') { + // Some controllers use the view action without an object + if ($this->className) { + $this->loadObject(true); + } + $this->content .= $this->renderView(); + } elseif ($this->display == 'export') { + $this->generateExport(); + } elseif (!$this->ajax) { + $this->content .= $this->renderList(); + $this->content .= $this->renderOptions(); + } - $this->context->smarty->assign(array( - 'content' => $this->content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } + $this->context->smarty->assign(array( + 'content' => $this->content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_request'] = array( - 'href' => self::$currentIndex.'&addrequest_sql&token='.$this->token, - 'desc' => $this->l('Add new SQL query', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_request'] = array( + 'href' => self::$currentIndex.'&addrequest_sql&token='.$this->token, + 'desc' => $this->l('Add new SQL query', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - /** - * Genrating a export file - */ - public function generateExport() - { - $id = Tools::getValue($this->identifier); - $export_dir = defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_.'/export/' : _PS_ADMIN_DIR_.'/export/'; - if (!Validate::isFileName($id)) - die(Tools::displayError()); - $file = 'request_sql_'.$id.'.csv'; - if ($csv = fopen($export_dir.$file, 'w')) - { - $sql = RequestSql::getRequestSqlById($id); + /** + * Genrating a export file + */ + public function generateExport() + { + $id = Tools::getValue($this->identifier); + $export_dir = defined('_PS_HOST_MODE_') ? _PS_ROOT_DIR_.'/export/' : _PS_ADMIN_DIR_.'/export/'; + if (!Validate::isFileName($id)) { + die(Tools::displayError()); + } + $file = 'request_sql_'.$id.'.csv'; + if ($csv = fopen($export_dir.$file, 'w')) { + $sql = RequestSql::getRequestSqlById($id); - if ($sql) - { - $results = Db::getInstance()->executeS($sql[0]['sql']); - foreach (array_keys($results[0]) as $key) - { - $tab_key[] = $key; - fputs($csv, $key.';'); - } - foreach ($results as $result) - { - fputs($csv, "\n"); - foreach ($tab_key as $name) - fputs($csv, '"'.strip_tags($result[$name]).'";'); - } - if (file_exists($export_dir.$file)) - { - $filesize = filesize($export_dir.$file); - $upload_max_filesize = Tools::convertBytes(ini_get('upload_max_filesize')); - if ($filesize < $upload_max_filesize) - { - if (Configuration::get('PS_ENCODING_FILE_MANAGER_SQL')) - $charset = Configuration::get('PS_ENCODING_FILE_MANAGER_SQL'); - else - $charset = self::$encoding_file[0]['name']; + if ($sql) { + $results = Db::getInstance()->executeS($sql[0]['sql']); + foreach (array_keys($results[0]) as $key) { + $tab_key[] = $key; + fputs($csv, $key.';'); + } + foreach ($results as $result) { + fputs($csv, "\n"); + foreach ($tab_key as $name) { + fputs($csv, '"'.strip_tags($result[$name]).'";'); + } + } + if (file_exists($export_dir.$file)) { + $filesize = filesize($export_dir.$file); + $upload_max_filesize = Tools::convertBytes(ini_get('upload_max_filesize')); + if ($filesize < $upload_max_filesize) { + if (Configuration::get('PS_ENCODING_FILE_MANAGER_SQL')) { + $charset = Configuration::get('PS_ENCODING_FILE_MANAGER_SQL'); + } else { + $charset = self::$encoding_file[0]['name']; + } - header('Content-Type: text/csv; charset='.$charset); - header('Cache-Control: no-store, no-cache'); - header('Content-Disposition: attachment; filename="'.$file.'"'); - header('Content-Length: '.$filesize); - readfile($export_dir.$file); - die(); - } - else - $this->errors[] = Tools::DisplayError('The file is too large and can not be downloaded. Please use the LIMIT clause in this query.'); - } - } - } - } + header('Content-Type: text/csv; charset='.$charset); + header('Cache-Control: no-store, no-cache'); + header('Content-Disposition: attachment; filename="'.$file.'"'); + header('Content-Length: '.$filesize); + readfile($export_dir.$file); + die(); + } else { + $this->errors[] = Tools::DisplayError('The file is too large and can not be downloaded. Please use the LIMIT clause in this query.'); + } + } + } + } + } - /** - * Display all errors - * - * @param $e : array of errors - */ - public function displayError($e) - { - foreach (array_keys($e) as $key) - { - switch ($key) - { - case 'checkedFrom': - if (isset($e[$key]['table'])) - $this->errors[] = sprintf(Tools::displayError('The "%s" table does not exist.'), $e[$key]['table']); - elseif (isset($e[$key]['attribut'])) - $this->errors[] = sprintf( - Tools::displayError('The "%1$s" attribute does not exist in the "%2$s" table.'), - $e[$key]['attribut'][0], - $e[$key]['attribut'][1] - ); - else - $this->errors[] = Tools::displayError('Undefined "checkedFrom" error'); - break; + /** + * Display all errors + * + * @param $e : array of errors + */ + public function displayError($e) + { + foreach (array_keys($e) as $key) { + switch ($key) { + case 'checkedFrom': + if (isset($e[$key]['table'])) { + $this->errors[] = sprintf(Tools::displayError('The "%s" table does not exist.'), $e[$key]['table']); + } elseif (isset($e[$key]['attribut'])) { + $this->errors[] = sprintf( + Tools::displayError('The "%1$s" attribute does not exist in the "%2$s" table.'), + $e[$key]['attribut'][0], + $e[$key]['attribut'][1] + ); + } else { + $this->errors[] = Tools::displayError('Undefined "checkedFrom" error'); + } + break; - case 'checkedSelect': - if (isset($e[$key]['table'])) - $this->errors[] = sprintf(Tools::displayError('The "%s" table does not exist.'), $e[$key]['table']); - elseif (isset($e[$key]['attribut'])) - $this->errors[] = sprintf( - Tools::displayError('The "%1$s" attribute does not exist in the "%2$s" table.'), - $e[$key]['attribut'][0], - $e[$key]['attribut'][1] - ); - elseif (isset($e[$key]['*'])) - $this->errors[] = Tools::displayError('The "*" operator cannot be used in a nested query.'); - else - $this->errors[] = Tools::displayError('Undefined "checkedSelect" error'); - break; + case 'checkedSelect': + if (isset($e[$key]['table'])) { + $this->errors[] = sprintf(Tools::displayError('The "%s" table does not exist.'), $e[$key]['table']); + } elseif (isset($e[$key]['attribut'])) { + $this->errors[] = sprintf( + Tools::displayError('The "%1$s" attribute does not exist in the "%2$s" table.'), + $e[$key]['attribut'][0], + $e[$key]['attribut'][1] + ); + } elseif (isset($e[$key]['*'])) { + $this->errors[] = Tools::displayError('The "*" operator cannot be used in a nested query.'); + } else { + $this->errors[] = Tools::displayError('Undefined "checkedSelect" error'); + } + break; - case 'checkedWhere': - if (isset($e[$key]['operator'])) - $this->errors[] = sprintf(Tools::displayError('The operator "%s" is incorrect.'), $e[$key]['operator']); - elseif (isset($e[$key]['attribut'])) - $this->errors[] = sprintf( - Tools::displayError('The "%1$s" attribute does not exist in the "%2$s" table.'), - $e[$key]['attribut'][0], - $e[$key]['attribut'][1] - ); - else - $this->errors[] = Tools::displayError('Undefined "checkedWhere" error'); - break; + case 'checkedWhere': + if (isset($e[$key]['operator'])) { + $this->errors[] = sprintf(Tools::displayError('The operator "%s" is incorrect.'), $e[$key]['operator']); + } elseif (isset($e[$key]['attribut'])) { + $this->errors[] = sprintf( + Tools::displayError('The "%1$s" attribute does not exist in the "%2$s" table.'), + $e[$key]['attribut'][0], + $e[$key]['attribut'][1] + ); + } else { + $this->errors[] = Tools::displayError('Undefined "checkedWhere" error'); + } + break; - case 'checkedHaving': - if (isset($e[$key]['operator'])) - $this->errors[] = sprintf(Tools::displayError('The "%s" operator is incorrect.'), $e[$key]['operator']); - elseif (isset($e[$key]['attribut'])) - $this->errors[] = sprintf( - Tools::displayError('The "%1$s" attribute does not exist in the "%2$s" table.'), - $e[$key]['attribut'][0], - $e[$key]['attribut'][1] - ); - else - $this->errors[] = Tools::displayError('Undefined "checkedHaving" error'); - break; + case 'checkedHaving': + if (isset($e[$key]['operator'])) { + $this->errors[] = sprintf(Tools::displayError('The "%s" operator is incorrect.'), $e[$key]['operator']); + } elseif (isset($e[$key]['attribut'])) { + $this->errors[] = sprintf( + Tools::displayError('The "%1$s" attribute does not exist in the "%2$s" table.'), + $e[$key]['attribut'][0], + $e[$key]['attribut'][1] + ); + } else { + $this->errors[] = Tools::displayError('Undefined "checkedHaving" error'); + } + break; - case 'checkedOrder': - if (isset($e[$key]['attribut'])) - $this->errors[] = sprintf( - Tools::displayError('The "%1$s" attribute does not exist in the "%2$s" table.'), - $e[$key]['attribut'][0], - $e[$key]['attribut'][1] - ); - else - $this->errors[] = Tools::displayError('Undefined "checkedOrder" error'); - break; + case 'checkedOrder': + if (isset($e[$key]['attribut'])) { + $this->errors[] = sprintf( + Tools::displayError('The "%1$s" attribute does not exist in the "%2$s" table.'), + $e[$key]['attribut'][0], + $e[$key]['attribut'][1] + ); + } else { + $this->errors[] = Tools::displayError('Undefined "checkedOrder" error'); + } + break; - case 'checkedGroupBy': - if (isset($e[$key]['attribut'])) - $this->errors[] = sprintf( - Tools::displayError('The "%1$s" attribute does not exist in the "%2$s" table.'), - $e[$key]['attribut'][0], - $e[$key]['attribut'][1] - ); - else - $this->errors[] = Tools::displayError('Undefined "checkedGroupBy" error'); - break; + case 'checkedGroupBy': + if (isset($e[$key]['attribut'])) { + $this->errors[] = sprintf( + Tools::displayError('The "%1$s" attribute does not exist in the "%2$s" table.'), + $e[$key]['attribut'][0], + $e[$key]['attribut'][1] + ); + } else { + $this->errors[] = Tools::displayError('Undefined "checkedGroupBy" error'); + } + break; - case 'checkedLimit': - $this->errors[] = Tools::displayError('The LIMIT clause must contain numeric arguments.'); - break; + case 'checkedLimit': + $this->errors[] = Tools::displayError('The LIMIT clause must contain numeric arguments.'); + break; - case 'returnNameTable': - if (isset($e[$key]['reference'])) - $this->errors[] = sprintf( - Tools::displayError('The "%1$s" reference does not exist in the "%2$s" table.'), - $e[$key]['reference'][0], - $e[$key]['attribut'][1] - ); - else - $this->errors[] = Tools::displayError('When multiple tables are used, each attribute must refer back to a table.'); - break; + case 'returnNameTable': + if (isset($e[$key]['reference'])) { + $this->errors[] = sprintf( + Tools::displayError('The "%1$s" reference does not exist in the "%2$s" table.'), + $e[$key]['reference'][0], + $e[$key]['attribut'][1] + ); + } else { + $this->errors[] = Tools::displayError('When multiple tables are used, each attribute must refer back to a table.'); + } + break; - case 'testedRequired': - $this->errors[] = sprintf(Tools::displayError('%s does not exist.'), $e[$key]); - break; + case 'testedRequired': + $this->errors[] = sprintf(Tools::displayError('%s does not exist.'), $e[$key]); + break; - case 'testedUnauthorized': - $this->errors[] = sprintf(Tools::displayError('Is an unauthorized keyword.'), $e[$key]); - break; - } - } - } + case 'testedUnauthorized': + $this->errors[] = sprintf(Tools::displayError('Is an unauthorized keyword.'), $e[$key]); + break; + } + } + } } - - diff --git a/controllers/admin/AdminReturnController.php b/controllers/admin/AdminReturnController.php index d32b6b32..fb4010cc 100644 --- a/controllers/admin/AdminReturnController.php +++ b/controllers/admin/AdminReturnController.php @@ -29,240 +29,236 @@ */ class AdminReturnControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->context = Context::getContext(); - $this->table = 'order_return'; - $this->className = 'OrderReturn'; - $this->colorOnBackground = true; - $this->_select = 'ors.color, orsl.`name`, o.`id_shop`'; - $this->_join = 'LEFT JOIN '._DB_PREFIX_.'order_return_state ors ON (ors.`id_order_return_state` = a.`state`)'; - $this->_join .= 'LEFT JOIN '._DB_PREFIX_.'order_return_state_lang orsl ON (orsl.`id_order_return_state` = a.`state` AND orsl.`id_lang` = '.(int)$this->context->language->id.')'; - $this->_join .= ' LEFT JOIN '._DB_PREFIX_.'orders o ON (o.`id_order` = a.`id_order`)'; + public function __construct() + { + $this->bootstrap = true; + $this->context = Context::getContext(); + $this->table = 'order_return'; + $this->className = 'OrderReturn'; + $this->colorOnBackground = true; + $this->_select = 'ors.color, orsl.`name`, o.`id_shop`'; + $this->_join = 'LEFT JOIN '._DB_PREFIX_.'order_return_state ors ON (ors.`id_order_return_state` = a.`state`)'; + $this->_join .= 'LEFT JOIN '._DB_PREFIX_.'order_return_state_lang orsl ON (orsl.`id_order_return_state` = a.`state` AND orsl.`id_lang` = '.(int)$this->context->language->id.')'; + $this->_join .= ' LEFT JOIN '._DB_PREFIX_.'orders o ON (o.`id_order` = a.`id_order`)'; - $this->fields_list = array( - 'id_order_return' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25), - 'id_order' => array('title' => $this->l('Order ID'), 'width' => 100, 'align' => 'center', 'filter_key'=>'a!id_order'), - 'name' => array('title' => $this->l('Status'),'color' => 'color', 'width' => 'auto', 'align' => 'left'), - 'date_add' => array('title' => $this->l('Date issued'), 'width' => 150, 'type' => 'date', 'align' => 'right', 'filter_key'=>'a!date_add'), - ); + $this->fields_list = array( + 'id_order_return' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25), + 'id_order' => array('title' => $this->l('Order ID'), 'width' => 100, 'align' => 'center', 'filter_key'=>'a!id_order'), + 'name' => array('title' => $this->l('Status'),'color' => 'color', 'width' => 'auto', 'align' => 'left'), + 'date_add' => array('title' => $this->l('Date issued'), 'width' => 150, 'type' => 'date', 'align' => 'right', 'filter_key'=>'a!date_add'), + ); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Merchandise return (RMA) options'), - 'fields' => array( - 'PS_ORDER_RETURN' => array( - 'title' => $this->l('Enable returns'), - 'desc' => $this->l('Would you like to allow merchandise returns in your shop?'), - 'cast' => 'intval', 'type' => 'bool'), - 'PS_ORDER_RETURN_NB_DAYS' => array( - 'title' => $this->l('Time limit of validity'), - 'desc' => $this->l('How many days after the delivery date does the customer have to return a product?'), - 'cast' => 'intval', - 'type' => 'text', - 'size' => '2'), - 'PS_RETURN_PREFIX' => array( - 'title' => $this->l('Returns prefix'), - 'desc' => $this->l('Prefix used for return name (e.g. RE00001).'), - 'size' => 6, - 'type' => 'textLang' - ), - ), - 'submit' => array('title' => $this->l('Save')) - ), - ); + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Merchandise return (RMA) options'), + 'fields' => array( + 'PS_ORDER_RETURN' => array( + 'title' => $this->l('Enable returns'), + 'desc' => $this->l('Would you like to allow merchandise returns in your shop?'), + 'cast' => 'intval', 'type' => 'bool'), + 'PS_ORDER_RETURN_NB_DAYS' => array( + 'title' => $this->l('Time limit of validity'), + 'desc' => $this->l('How many days after the delivery date does the customer have to return a product?'), + 'cast' => 'intval', + 'type' => 'text', + 'size' => '2'), + 'PS_RETURN_PREFIX' => array( + 'title' => $this->l('Returns prefix'), + 'desc' => $this->l('Prefix used for return name (e.g. RE00001).'), + 'size' => 6, + 'type' => 'textLang' + ), + ), + 'submit' => array('title' => $this->l('Save')) + ), + ); - parent::__construct(); + parent::__construct(); - $this->_where = Shop::addSqlRestriction(false, 'o'); - $this->_use_found_rows = false; - } + $this->_where = Shop::addSqlRestriction(false, 'o'); + $this->_use_found_rows = false; + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Return Merchandise Authorization (RMA)'), - 'image' => '../img/admin/return.gif' - ), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'id_order' - ), - array( - 'type' => 'hidden', - 'name' => 'id_customer' - ), - array( - 'type' => 'text_customer', - 'label' => $this->l('Customer'), - 'name' => '', - 'size' => '', - 'required' => false, - ), - array( - 'type' => 'text_order', - 'label' => $this->l('Order'), - 'name' => '', - 'size' => '', - 'required' => false, - ), - array( - 'type' => 'free', - 'label' => $this->l('Customer explanation'), - 'name' => 'question', - 'size' => '', - 'required' => false, - ), - array( - 'type' => 'select', - 'label' => $this->l('Status'), - 'name' => 'state', - 'required' => false, - 'options' => array( - 'query' => OrderReturnState::getOrderReturnStates($this->context->language->id), - 'id' => 'id_order_return_state', - 'name' => 'name' - ), - 'desc' => $this->l('Merchandise return (RMA) status.') - ), - array( - 'type' => 'list_products', - 'label' => $this->l('Products'), - 'name' => '', - 'size' => '', - 'required' => false, - 'desc' => $this->l('List of products in return package.') - ), - array( - 'type' => 'pdf_order_return', - 'label' => $this->l('Return slip'), - 'name' => '', - 'size' => '', - 'required' => false, - 'desc' => $this->l('The link is only available after validation and before the parcel gets delivered.') - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Return Merchandise Authorization (RMA)'), + 'image' => '../img/admin/return.gif' + ), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'id_order' + ), + array( + 'type' => 'hidden', + 'name' => 'id_customer' + ), + array( + 'type' => 'text_customer', + 'label' => $this->l('Customer'), + 'name' => '', + 'size' => '', + 'required' => false, + ), + array( + 'type' => 'text_order', + 'label' => $this->l('Order'), + 'name' => '', + 'size' => '', + 'required' => false, + ), + array( + 'type' => 'free', + 'label' => $this->l('Customer explanation'), + 'name' => 'question', + 'size' => '', + 'required' => false, + ), + array( + 'type' => 'select', + 'label' => $this->l('Status'), + 'name' => 'state', + 'required' => false, + 'options' => array( + 'query' => OrderReturnState::getOrderReturnStates($this->context->language->id), + 'id' => 'id_order_return_state', + 'name' => 'name' + ), + 'desc' => $this->l('Merchandise return (RMA) status.') + ), + array( + 'type' => 'list_products', + 'label' => $this->l('Products'), + 'name' => '', + 'size' => '', + 'required' => false, + 'desc' => $this->l('List of products in return package.') + ), + array( + 'type' => 'pdf_order_return', + 'label' => $this->l('Return slip'), + 'name' => '', + 'size' => '', + 'required' => false, + 'desc' => $this->l('The link is only available after validation and before the parcel gets delivered.') + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - $order = new Order($this->object->id_order); - $quantity_displayed = array(); - // Customized products */ - if ($returned_customizations = OrderReturn::getReturnedCustomizedProducts((int)($this->object->id_order))) - foreach ($returned_customizations as $returned_customization) - $quantity_displayed[(int)$returned_customization['id_order_detail']] = isset($quantity_displayed[(int)$returned_customization['id_order_detail']]) ? $quantity_displayed[(int)$returned_customization['id_order_detail']] + (int)$returned_customization['product_quantity'] : (int)$returned_customization['product_quantity']; + $order = new Order($this->object->id_order); + $quantity_displayed = array(); + // Customized products */ + if ($returned_customizations = OrderReturn::getReturnedCustomizedProducts((int)($this->object->id_order))) { + foreach ($returned_customizations as $returned_customization) { + $quantity_displayed[(int)$returned_customization['id_order_detail']] = isset($quantity_displayed[(int)$returned_customization['id_order_detail']]) ? $quantity_displayed[(int)$returned_customization['id_order_detail']] + (int)$returned_customization['product_quantity'] : (int)$returned_customization['product_quantity']; + } + } - // Classic products - $products = OrderReturn::getOrdersReturnProducts($this->object->id, $order); + // Classic products + $products = OrderReturn::getOrdersReturnProducts($this->object->id, $order); - // Prepare customer explanation for display - $this->object->question = '<span class="normal-text">'.nl2br($this->object->question).'</span>'; + // Prepare customer explanation for display + $this->object->question = '<span class="normal-text">'.nl2br($this->object->question).'</span>'; - $this->tpl_form_vars = array( - 'customer' => new Customer($this->object->id_customer), - 'url_customer' => 'index.php?tab=AdminCustomers&id_customer='.(int)$this->object->id_customer.'&viewcustomer&token='.Tools::getAdminToken('AdminCustomers'.(int)(Tab::getIdFromClassName('AdminCustomers')).(int)$this->context->employee->id), - 'text_order' => sprintf($this->l('Order #%1$d from %2$s'), $order->id, Tools::displayDate($order->date_upd)), - 'url_order' => 'index.php?tab=AdminOrders&id_order='.(int)$order->id.'&vieworder&token='.Tools::getAdminToken('AdminOrders'.(int)Tab::getIdFromClassName('AdminOrders').(int)$this->context->employee->id), - 'picture_folder' => _THEME_PROD_PIC_DIR_, - 'returnedCustomizations' => $returned_customizations, - 'customizedDatas' => Product::getAllCustomizedDatas((int)($order->id_cart)), - 'products' => $products, - 'quantityDisplayed' => $quantity_displayed, - 'id_order_return' => $this->object->id, - 'state_order_return' => $this->object->state, - ); + $this->tpl_form_vars = array( + 'customer' => new Customer($this->object->id_customer), + 'url_customer' => 'index.php?tab=AdminCustomers&id_customer='.(int)$this->object->id_customer.'&viewcustomer&token='.Tools::getAdminToken('AdminCustomers'.(int)(Tab::getIdFromClassName('AdminCustomers')).(int)$this->context->employee->id), + 'text_order' => sprintf($this->l('Order #%1$d from %2$s'), $order->id, Tools::displayDate($order->date_upd)), + 'url_order' => 'index.php?tab=AdminOrders&id_order='.(int)$order->id.'&vieworder&token='.Tools::getAdminToken('AdminOrders'.(int)Tab::getIdFromClassName('AdminOrders').(int)$this->context->employee->id), + 'picture_folder' => _THEME_PROD_PIC_DIR_, + 'returnedCustomizations' => $returned_customizations, + 'customizedDatas' => Product::getAllCustomizedDatas((int)($order->id_cart)), + 'products' => $products, + 'quantityDisplayed' => $quantity_displayed, + 'id_order_return' => $this->object->id, + 'state_order_return' => $this->object->state, + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function initToolbar() - { - // If display list, we don't want the "add" button - if (!$this->display || $this->display == 'list') - return; - elseif ($this->display != 'options') - $this->toolbar_btn['save-and-stay'] = array( - 'short' => 'SaveAndStay', - 'href' => '#', - 'desc' => $this->l('Save and stay'), - 'force_desc' => true, - ); + public function initToolbar() + { + // If display list, we don't want the "add" button + if (!$this->display || $this->display == 'list') { + return; + } elseif ($this->display != 'options') { + $this->toolbar_btn['save-and-stay'] = array( + 'short' => 'SaveAndStay', + 'href' => '#', + 'desc' => $this->l('Save and stay'), + 'force_desc' => true, + ); + } - parent::initToolbar(); - } + parent::initToolbar(); + } - public function postProcess() - { - $this->context = Context::getContext(); - if (Tools::isSubmit('deleteorder_return_detail')) - { - if ($this->tabAccess['delete'] === '1') - { - if (($id_order_detail = (int)(Tools::getValue('id_order_detail'))) && Validate::isUnsignedId($id_order_detail)) - { - if (($id_order_return = (int)(Tools::getValue('id_order_return'))) && Validate::isUnsignedId($id_order_return)) - { - $orderReturn = new OrderReturn($id_order_return); - if (!Validate::isLoadedObject($orderReturn)) - die(Tools::displayError()); - if ((int)($orderReturn->countProduct()) > 1) - { - if (OrderReturn::deleteOrderReturnDetail($id_order_return, $id_order_detail, (int)(Tools::getValue('id_customization', 0)))) - Tools::redirectAdmin(self::$currentIndex.'&conf=4token='.$this->token); - else - $this->errors[] = Tools::displayError('An error occurred while deleting the details of your order return.'); - } - else - $this->errors[] = Tools::displayError('You need at least one product.'); - } - else - $this->errors[] = Tools::displayError('The order return is invalid.'); - } - else - $this->errors[] = Tools::displayError('The order return content is invalid.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - elseif (Tools::isSubmit('submitAddorder_return') || Tools::isSubmit('submitAddorder_returnAndStay')) - { - if ($this->tabAccess['edit'] === '1') - { - if (($id_order_return = (int)(Tools::getValue('id_order_return'))) && Validate::isUnsignedId($id_order_return)) - { - $orderReturn = new OrderReturn($id_order_return); - $order = new Order($orderReturn->id_order); - $customer = new Customer($orderReturn->id_customer); - $orderReturn->state = (int)(Tools::getValue('state')); - if ($orderReturn->save()) - { - $orderReturnState = new OrderReturnState($orderReturn->state); - $vars = array( - '{lastname}' => $customer->lastname, - '{firstname}' => $customer->firstname, - '{id_order_return}' => $id_order_return, - '{state_order_return}' => (isset($orderReturnState->name[(int)$order->id_lang]) ? $orderReturnState->name[(int)$order->id_lang] : $orderReturnState->name[(int)Configuration::get('PS_LANG_DEFAULT')])); - Mail::Send((int)$order->id_lang, 'order_return_state', Mail::l('Your order return status has changed', $order->id_lang), - $vars, $customer->email, $customer->firstname.' '.$customer->lastname, null, null, null, - null, _PS_MAIL_DIR_, true, (int)$order->id_shop); + public function postProcess() + { + $this->context = Context::getContext(); + if (Tools::isSubmit('deleteorder_return_detail')) { + if ($this->tabAccess['delete'] === '1') { + if (($id_order_detail = (int)(Tools::getValue('id_order_detail'))) && Validate::isUnsignedId($id_order_detail)) { + if (($id_order_return = (int)(Tools::getValue('id_order_return'))) && Validate::isUnsignedId($id_order_return)) { + $orderReturn = new OrderReturn($id_order_return); + if (!Validate::isLoadedObject($orderReturn)) { + die(Tools::displayError()); + } + if ((int)($orderReturn->countProduct()) > 1) { + if (OrderReturn::deleteOrderReturnDetail($id_order_return, $id_order_detail, (int)(Tools::getValue('id_customization', 0)))) { + Tools::redirectAdmin(self::$currentIndex.'&conf=4token='.$this->token); + } else { + $this->errors[] = Tools::displayError('An error occurred while deleting the details of your order return.'); + } + } else { + $this->errors[] = Tools::displayError('You need at least one product.'); + } + } else { + $this->errors[] = Tools::displayError('The order return is invalid.'); + } + } else { + $this->errors[] = Tools::displayError('The order return content is invalid.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } elseif (Tools::isSubmit('submitAddorder_return') || Tools::isSubmit('submitAddorder_returnAndStay')) { + if ($this->tabAccess['edit'] === '1') { + if (($id_order_return = (int)(Tools::getValue('id_order_return'))) && Validate::isUnsignedId($id_order_return)) { + $orderReturn = new OrderReturn($id_order_return); + $order = new Order($orderReturn->id_order); + $customer = new Customer($orderReturn->id_customer); + $orderReturn->state = (int)(Tools::getValue('state')); + if ($orderReturn->save()) { + $orderReturnState = new OrderReturnState($orderReturn->state); + $vars = array( + '{lastname}' => $customer->lastname, + '{firstname}' => $customer->firstname, + '{id_order_return}' => $id_order_return, + '{state_order_return}' => (isset($orderReturnState->name[(int)$order->id_lang]) ? $orderReturnState->name[(int)$order->id_lang] : $orderReturnState->name[(int)Configuration::get('PS_LANG_DEFAULT')])); + Mail::Send((int)$order->id_lang, 'order_return_state', Mail::l('Your order return status has changed', $order->id_lang), + $vars, $customer->email, $customer->firstname.' '.$customer->lastname, null, null, null, + null, _PS_MAIL_DIR_, true, (int)$order->id_shop); - if (Tools::isSubmit('submitAddorder_returnAndStay')) - Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$this->token.'&updateorder_return&id_order_return='.(int)$id_order_return); - else - Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$this->token); - } - } - else - $this->errors[] = Tools::displayError('No order return ID has been specified.'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - parent::postProcess(); - } + if (Tools::isSubmit('submitAddorder_returnAndStay')) { + Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$this->token.'&updateorder_return&id_order_return='.(int)$id_order_return); + } else { + Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$this->token); + } + } + } else { + $this->errors[] = Tools::displayError('No order return ID has been specified.'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + parent::postProcess(); + } } diff --git a/controllers/admin/AdminScenesController.php b/controllers/admin/AdminScenesController.php index e808a2cb..28344393 100644 --- a/controllers/admin/AdminScenesController.php +++ b/controllers/admin/AdminScenesController.php @@ -29,138 +29,141 @@ */ class AdminScenesControllerCore extends AdminController { - public $bootstrap = true; + public $bootstrap = true; - public function __construct() - { - $this->table = 'scene'; - $this->className = 'Scene'; - $this->lang = true; - $this->addRowAction('edit'); - $this->addRowAction('delete'); + public function __construct() + { + $this->table = 'scene'; + $this->className = 'Scene'; + $this->lang = true; + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->identifier = 'id_scene'; - $this->fieldImageSettings = array( - array('name' => 'image', 'dir' => 'scenes'), - array('name' => 'thumb', 'dir' => 'scenes/thumbs') - ); + $this->identifier = 'id_scene'; + $this->fieldImageSettings = array( + array('name' => 'image', 'dir' => 'scenes'), + array('name' => 'thumb', 'dir' => 'scenes/thumbs') + ); - $this->fields_list = array( - 'id_scene' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Image Maps'), - 'filter_key' => 'b!name' - ), - 'active' => array( - 'title' => $this->l('Activated'), - 'align' => 'center', - 'class' => 'fixed-width-xs', - 'active' => 'status', - 'type' => 'bool', - 'orderby' => false - ) - ); + $this->fields_list = array( + 'id_scene' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Image Maps'), + 'filter_key' => 'b!name' + ), + 'active' => array( + 'title' => $this->l('Activated'), + 'align' => 'center', + 'class' => 'fixed-width-xs', + 'active' => 'status', + 'type' => 'bool', + 'orderby' => false + ) + ); - parent::__construct(); - } + parent::__construct(); + } - protected function afterImageUpload() - { - /* Generate image with differents size */ - if (!($obj = $this->loadObject(true))) - return; + protected function afterImageUpload() + { + /* Generate image with differents size */ + if (!($obj = $this->loadObject(true))) { + return; + } - if ($obj->id && (isset($_FILES['image']) || isset($_FILES['thumb']))) - { - $base_img_path = _PS_SCENE_IMG_DIR_.$obj->id.'.jpg'; - $images_types = ImageType::getImagesTypes('scenes'); + if ($obj->id && (isset($_FILES['image']) || isset($_FILES['thumb']))) { + $base_img_path = _PS_SCENE_IMG_DIR_.$obj->id.'.jpg'; + $images_types = ImageType::getImagesTypes('scenes'); - foreach ($images_types as $k => $image_type) - { - if ($image_type['name'] == 'm_scene_default') - { - if (isset($_FILES['thumb']) && !$_FILES['thumb']['error']) - $base_thumb_path = _PS_SCENE_THUMB_IMG_DIR_.$obj->id.'.jpg'; - else - $base_thumb_path = $base_img_path; - ImageManager::resize( - $base_thumb_path, - _PS_SCENE_THUMB_IMG_DIR_.$obj->id.'-'.stripslashes($image_type['name']).'.jpg', - (int)$image_type['width'], - (int)$image_type['height']); - } - elseif (isset($_FILES['image']) && isset($_FILES['image']['tmp_name']) && !$_FILES['image']['error']) - ImageManager::resize( - $base_img_path, - _PS_SCENE_IMG_DIR_.$obj->id.'-'.stripslashes($image_type['name']).'.jpg', - (int)$image_type['width'], - (int)$image_type['height']); - } - } + foreach ($images_types as $k => $image_type) { + if ($image_type['name'] == 'm_scene_default') { + if (isset($_FILES['thumb']) && !$_FILES['thumb']['error']) { + $base_thumb_path = _PS_SCENE_THUMB_IMG_DIR_.$obj->id.'.jpg'; + } else { + $base_thumb_path = $base_img_path; + } + ImageManager::resize( + $base_thumb_path, + _PS_SCENE_THUMB_IMG_DIR_.$obj->id.'-'.stripslashes($image_type['name']).'.jpg', + (int)$image_type['width'], + (int)$image_type['height']); + } elseif (isset($_FILES['image']) && isset($_FILES['image']['tmp_name']) && !$_FILES['image']['error']) { + ImageManager::resize( + $base_img_path, + _PS_SCENE_IMG_DIR_.$obj->id.'-'.stripslashes($image_type['name']).'.jpg', + (int)$image_type['width'], + (int)$image_type['height']); + } + } + } - return true; - } + return true; + } - public function renderForm() - { - $this->initFieldsForm(); + public function renderForm() + { + $this->initFieldsForm(); - /** @var Scene $obj */ - if (!($obj = $this->loadObject(true))) - return; + /** @var Scene $obj */ + if (!($obj = $this->loadObject(true))) { + return; + } - $this->tpl_form_vars['products'] = $obj->getProducts(true, $this->context->language->id, false, $this->context); + $this->tpl_form_vars['products'] = $obj->getProducts(true, $this->context->language->id, false, $this->context); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_scene'] = array( - 'href' => self::$currentIndex.'&addscene&token='.$this->token, - 'desc' => $this->l('Add new image map', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_scene'] = array( + 'href' => self::$currentIndex.'&addscene&token='.$this->token, + 'desc' => $this->l('Add new image map', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function initToolbar() - { - parent::initToolbar(); + public function initToolbar() + { + parent::initToolbar(); - if (in_array($this->display, array('add', 'edit'))) - $this->toolbar_btn = array_merge(array('save-and-stay' => array( - 'short' => 'SaveAndStay', - 'href' => '#', - 'desc' => $this->l('Save and stay'), - )), $this->toolbar_btn); - } + if (in_array($this->display, array('add', 'edit'))) { + $this->toolbar_btn = array_merge(array('save-and-stay' => array( + 'short' => 'SaveAndStay', + 'href' => '#', + 'desc' => $this->l('Save and stay'), + )), $this->toolbar_btn); + } + } - public function initFieldsForm() - { - $obj = $this->loadObject(true); - $scene_image_types = ImageType::getImagesTypes('scenes'); - $large_scene_image_type = null; - $thumb_scene_image_type = null; - foreach ($scene_image_types as $scene_image_type) - { - if ($scene_image_type['name'] == 'scene_default') - $large_scene_image_type = $scene_image_type; - if ($scene_image_type['name'] == 'm_scene_default') - $thumb_scene_image_type = $scene_image_type; - } - $fields_form = array( - 'legend' => array( - 'title' => $this->l('Image Maps'), - 'icon' => 'icon-picture', - ), - 'description' => ' + public function initFieldsForm() + { + $obj = $this->loadObject(true); + $scene_image_types = ImageType::getImagesTypes('scenes'); + $large_scene_image_type = null; + $thumb_scene_image_type = null; + foreach ($scene_image_types as $scene_image_type) { + if ($scene_image_type['name'] == 'scene_default') { + $large_scene_image_type = $scene_image_type; + } + if ($scene_image_type['name'] == 'm_scene_default') { + $thumb_scene_image_type = $scene_image_type; + } + } + $fields_form = array( + 'legend' => array( + 'title' => $this->l('Image Maps'), + 'icon' => 'icon-picture', + ), + 'description' => ' <h4>'.$this->l('How to map products in the image:').'</h4> <p> '.$this->l('When a customer hovers over the image, a pop-up appears displaying a brief description of the product.').' @@ -171,64 +174,63 @@ class AdminScenesControllerCore extends AdminController '.$this->l('Click the appropriate product and then click OK. Repeat these steps for each mapping zone you wish to create.').'<br/> '.$this->l('When you have finished mapping zones, click "Save Image Map."').' </p>', - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Image map name'), - 'name' => 'name', - 'lang' => true, - 'required' => true, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'switch', - 'label' => $this->l('Status'), - 'name' => 'active', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ) - ), - ), - 'submit' => array( - 'title' => $this->l('Save') - ), - ); - $this->fields_form = $fields_form; + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Image map name'), + 'name' => 'name', + 'lang' => true, + 'required' => true, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'switch', + 'label' => $this->l('Status'), + 'name' => 'active', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ) + ), + ), + 'submit' => array( + 'title' => $this->l('Save') + ), + ); + $this->fields_form = $fields_form; - $image_to_map_desc = ''; - $image_to_map_desc .= '<div class="help-block">'.$this->l('Format:').' JPG, GIF, PNG. '.$this->l('File size:').' ' - .(Tools::getMaxUploadSize() / 1024).''.$this->l('Kb max.').' ' - .sprintf($this->l('If an image is too large, it will be reduced to %1$d x %2$dpx (width x height).'), - $large_scene_image_type['width'], $large_scene_image_type['height']) - .$this->l('If an image is deemed too small, a white background will be added in order to achieve the correct image size.').'<br />'. - $this->l('Note: To change image dimensions, please change the \'large_scene\' image type settings to the desired size (in Back Office > Preferences > Images).') - .'</div>'; + $image_to_map_desc = ''; + $image_to_map_desc .= '<div class="help-block">'.$this->l('Format:').' JPG, GIF, PNG. '.$this->l('File size:').' ' + .(Tools::getMaxUploadSize() / 1024).''.$this->l('Kb max.').' ' + .sprintf($this->l('If an image is too large, it will be reduced to %1$d x %2$dpx (width x height).'), + $large_scene_image_type['width'], $large_scene_image_type['height']) + .$this->l('If an image is deemed too small, a white background will be added in order to achieve the correct image size.').'<br />'. + $this->l('Note: To change image dimensions, please change the \'large_scene\' image type settings to the desired size (in Back Office > Preferences > Images).') + .'</div>'; - if ($obj->id && file_exists(_PS_SCENE_IMG_DIR_.$obj->id.'-scene_default.jpg')) - { - $this->addJqueryPlugin('autocomplete'); - $this->addJqueryPlugin('imgareaselect'); - $this->addJs(_PS_JS_DIR_.'admin/scenes.js' ); - $image_to_map_desc .= '<div class="panel panel-default"><span class="thumbnail row-margin-bottom"><img id="large_scene_image" alt="" src="'. - _THEME_SCENE_DIR_.$obj->id.'-scene_default.jpg?rand='.(int)rand().'" /></span>'; + if ($obj->id && file_exists(_PS_SCENE_IMG_DIR_.$obj->id.'-scene_default.jpg')) { + $this->addJqueryPlugin('autocomplete'); + $this->addJqueryPlugin('imgareaselect'); + $this->addJs(_PS_JS_DIR_.'admin/scenes.js'); + $image_to_map_desc .= '<div class="panel panel-default"><span class="thumbnail row-margin-bottom"><img id="large_scene_image" alt="" src="'. + _THEME_SCENE_DIR_.$obj->id.'-scene_default.jpg?rand='.(int)rand().'" /></span>'; - $image_to_map_desc .= ' + $image_to_map_desc .= ' <div id="ajax_choose_product" class="row" style="display:none;"> <div class="col-lg-12"> <p class="alert alert-info">' - .$this->l('Begin typing the first few letters of the product name, then select the product you are looking for from the drop-down list:').' + .$this->l('Begin typing the first few letters of the product name, then select the product you are looking for from the drop-down list:').' </p> <div class="input-group row-margin-bottom"> <span class="input-group-addon"> @@ -242,86 +244,91 @@ class AdminScenesControllerCore extends AdminController </div> '; - if ($obj->id && file_exists(_PS_SCENE_IMG_DIR_.'thumbs/'.$obj->id.'-m_scene_default.jpg')) - $image_to_map_desc .= '</div><hr/><img class="thumbnail" id="large_scene_image" style="clear:both;border:1px solid black;" alt="" src="'._THEME_SCENE_DIR_.'thumbs/'.$obj->id.'-m_scene_default.jpg?rand='.(int)rand().'" />'; + if ($obj->id && file_exists(_PS_SCENE_IMG_DIR_.'thumbs/'.$obj->id.'-m_scene_default.jpg')) { + $image_to_map_desc .= '</div><hr/><img class="thumbnail" id="large_scene_image" style="clear:both;border:1px solid black;" alt="" src="'._THEME_SCENE_DIR_.'thumbs/'.$obj->id.'-m_scene_default.jpg?rand='.(int)rand().'" />'; + } - $img_alt_desc = ''; - $img_alt_desc .= $this->l('If you want to use a thumbnail other than one generated from simply reducing the mapped image, please upload it here.') - .'<br />'.$this->l('Format:').' JPG, GIF, PNG. ' - .$this->l('File size:').' '.(Tools::getMaxUploadSize() / 1024).''.$this->l('Kb max.').' ' - .sprintf($this->l('Automatically resized to %1$d x %2$dpx (width x height).'), - $thumb_scene_image_type['width'], $thumb_scene_image_type['height']).'.<br />' - .$this->l('Note: To change image dimensions, please change the \'m_scene_default\' image type settings to the desired size (in Back Office > Preferences > Images).'); + $img_alt_desc = ''; + $img_alt_desc .= $this->l('If you want to use a thumbnail other than one generated from simply reducing the mapped image, please upload it here.') + .'<br />'.$this->l('Format:').' JPG, GIF, PNG. ' + .$this->l('File size:').' '.(Tools::getMaxUploadSize() / 1024).''.$this->l('Kb max.').' ' + .sprintf($this->l('Automatically resized to %1$d x %2$dpx (width x height).'), + $thumb_scene_image_type['width'], $thumb_scene_image_type['height']).'.<br />' + .$this->l('Note: To change image dimensions, please change the \'m_scene_default\' image type settings to the desired size (in Back Office > Preferences > Images).'); - $input_img_alt = array( - 'type' => 'file', - 'label' => $this->l('Alternative thumbnail'), - 'name' => 'thumb', - 'desc' => $img_alt_desc - ); + $input_img_alt = array( + 'type' => 'file', + 'label' => $this->l('Alternative thumbnail'), + 'name' => 'thumb', + 'desc' => $img_alt_desc + ); - $selected_cat = array(); - if (Tools::isSubmit('categories')) - foreach (Tools::getValue('categories') as $row) - $selected_cat[] = $row; - elseif ($obj->id) - foreach (Scene::getIndexedCategories($obj->id) as $row) - $selected_cat[] = $row['id_category']; + $selected_cat = array(); + if (Tools::isSubmit('categories')) { + foreach (Tools::getValue('categories') as $row) { + $selected_cat[] = $row; + } + } elseif ($obj->id) { + foreach (Scene::getIndexedCategories($obj->id) as $row) { + $selected_cat[] = $row['id_category']; + } + } - $this->fields_form['input'][] = array( - 'type' => 'categories', - 'label' => $this->l('Categories'), - 'name' => 'categories', - 'tree' => array( - 'id' => 'categories-tree', - 'title' => 'Categories', - 'selected_categories' => $selected_cat, - 'use_search' => true, - 'use_checkbox' => true - ) - ); - } - else - $image_to_map_desc .= '<span>'.$this->l('Please add a picture to continue mapping the image.').'</span>'; + $this->fields_form['input'][] = array( + 'type' => 'categories', + 'label' => $this->l('Categories'), + 'name' => 'categories', + 'tree' => array( + 'id' => 'categories-tree', + 'title' => 'Categories', + 'selected_categories' => $selected_cat, + 'use_search' => true, + 'use_checkbox' => true + ) + ); + } else { + $image_to_map_desc .= '<span>'.$this->l('Please add a picture to continue mapping the image.').'</span>'; + } - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - $this->fields_form['input'][] = array( - 'type' => 'file', - 'label' => $this->l('Image to be mapped'), - 'name' => 'image', - 'display_image' => true, - 'desc' => $image_to_map_desc, - ); + $this->fields_form['input'][] = array( + 'type' => 'file', + 'label' => $this->l('Image to be mapped'), + 'name' => 'image', + 'display_image' => true, + 'desc' => $image_to_map_desc, + ); - if (isset($input_img_alt)) - $this->fields_form['input'][] = $input_img_alt; - } + if (isset($input_img_alt)) { + $this->fields_form['input'][] = $input_img_alt; + } + } - public function postProcess() - { - if (Tools::isSubmit('save_image_map')) - { - if (!Tools::isSubmit('categories') || !count(Tools::getValue('categories'))) - $this->errors[] = Tools::displayError('You should select at least one category.'); - if (!Tools::isSubmit('zones') || !count(Tools::getValue('zones'))) - $this->errors[] = Tools::displayError('You should create at least one zone.'); - } + public function postProcess() + { + if (Tools::isSubmit('save_image_map')) { + if (!Tools::isSubmit('categories') || !count(Tools::getValue('categories'))) { + $this->errors[] = Tools::displayError('You should select at least one category.'); + } + if (!Tools::isSubmit('zones') || !count(Tools::getValue('zones'))) { + $this->errors[] = Tools::displayError('You should create at least one zone.'); + } + } - if (Tools::isSubmit('delete'.$this->table)) - { - if (Validate::isLoadedObject($object = $this->loadObject())) - $object->deleteImage(false); - else - return false; - } - parent::postProcess(); - } -} \ No newline at end of file + if (Tools::isSubmit('delete'.$this->table)) { + if (Validate::isLoadedObject($object = $this->loadObject())) { + $object->deleteImage(false); + } else { + return false; + } + } + parent::postProcess(); + } +} diff --git a/controllers/admin/AdminSearchConfController.php b/controllers/admin/AdminSearchConfController.php index d37510b1..1eb1538f 100644 --- a/controllers/admin/AdminSearchConfController.php +++ b/controllers/admin/AdminSearchConfController.php @@ -29,50 +29,51 @@ */ class AdminSearchConfControllerCore extends AdminController { - protected $toolbar_scroll = false; + protected $toolbar_scroll = false; - public function __construct() - { - $this->bootstrap = true; - $this->table = 'alias'; - $this->className = 'Alias'; - $this->lang = false; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'alias'; + $this->className = 'Alias'; + $this->lang = false; - parent::__construct(); + parent::__construct(); - // Alias fields - $this->addRowAction('edit'); - $this->addRowAction('delete'); + // Alias fields + $this->addRowAction('edit'); + $this->addRowAction('delete'); - if (!Tools::getValue('realedit')) - $this->deleted = false; + if (!Tools::getValue('realedit')) { + $this->deleted = false; + } - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->fields_list = array( - 'alias' => array('title' => $this->l('Aliases')), - 'search' => array('title' => $this->l('Search')), - 'active' => array('title' => $this->l('Status'), 'class' => 'fixed-width-sm', 'align' => 'center', 'active' => 'status', 'type' => 'bool', 'orderby' => false) - ); + $this->fields_list = array( + 'alias' => array('title' => $this->l('Aliases')), + 'search' => array('title' => $this->l('Search')), + 'active' => array('title' => $this->l('Status'), 'class' => 'fixed-width-sm', 'align' => 'center', 'active' => 'status', 'type' => 'bool', 'orderby' => false) + ); - // Search options - $current_file_name = array_reverse(explode('/', $_SERVER['SCRIPT_NAME'])); - $cron_url = Tools::getHttpHost(true, true).__PS_BASE_URI__.basename(_PS_ADMIN_DIR_). - '/searchcron.php?full=1&token='.substr(_COOKIE_KEY_, 34, 8).(Shop::getContext() == Shop::CONTEXT_SHOP ? '&id_shop='.(int)Context::getContext()->shop->id : ''); + // Search options + $current_file_name = array_reverse(explode('/', $_SERVER['SCRIPT_NAME'])); + $cron_url = Tools::getHttpHost(true, true).__PS_BASE_URI__.basename(_PS_ADMIN_DIR_). + '/searchcron.php?full=1&token='.substr(_COOKIE_KEY_, 34, 8).(Shop::getContext() == Shop::CONTEXT_SHOP ? '&id_shop='.(int)Context::getContext()->shop->id : ''); - list($total, $indexed) = Db::getInstance()->getRow('SELECT COUNT(*) as "0", SUM(product_shop.indexed) as "1" FROM '._DB_PREFIX_.'product p '.Shop::addSqlAssociation('product', 'p').' WHERE product_shop.`visibility` IN ("both", "search") AND product_shop.`active` = 1'); + list($total, $indexed) = Db::getInstance()->getRow('SELECT COUNT(*) as "0", SUM(product_shop.indexed) as "1" FROM '._DB_PREFIX_.'product p '.Shop::addSqlAssociation('product', 'p').' WHERE product_shop.`visibility` IN ("both", "search") AND product_shop.`active` = 1'); - $this->fields_options = array( - 'indexation' => array( - 'title' => $this->l('Indexing'), - 'icon' => 'icon-cogs', - 'info' => '<p> + $this->fields_options = array( + 'indexation' => array( + 'title' => $this->l('Indexing'), + 'icon' => 'icon-cogs', + 'info' => '<p> '.$this->l('The "indexed" products have been analyzed by PrestaShop and will appear in the results of a front office search.').'<br /> '.$this->l('Indexed products').' <strong>'.(int)$indexed.' / '.(int)$total.'</strong>. </p> @@ -95,256 +96,261 @@ class AdminSearchConfControllerCore extends AdminController '.Tools::safeOutput($cron_url).' </a> </p><br />', - 'fields' => array( - 'PS_SEARCH_INDEXATION' => array( - 'title' => $this->l('Indexing'), - 'validation' => 'isBool', - 'type' => 'bool', - 'cast' => 'intval', - 'desc' => $this->l('Enable the automatic indexing of products. If you enable this feature, the products will be indexed in the search automatically when they are saved. If the feature is disabled, you will have to index products manually by using the links provided in the field set.') - ) - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'search' => array( - 'title' => $this->l('Search'), - 'icon' => 'icon-search', - 'fields' => array( - 'PS_SEARCH_AJAX' => array( - 'title' => $this->l('Ajax search'), - 'validation' => 'isBool', - 'type' => 'bool', - 'cast' => 'intval', - 'hint' => array( - $this->l('Enable ajax search for your visitors.'), - $this->l('With ajax search, the first 10 products matching the user query will appear in real time below the input field.') - ) - ), - 'PS_INSTANT_SEARCH' => array( - 'title' => $this->l('Instant search'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'hint' => array( - $this->l('Enable instant search for your visitors?'), - $this->l('With instant search, the results will appear immediately as the user writes a query.') - ) - ), - 'PS_SEARCH_START' => array( - 'title' => $this->l('Search within word'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'desc' => $this->l('By default, to search for “blouse”, you have to enter “blous”, “blo”, etc (beginning of the word) – but not “lous” (within the word).').'<br/>'. - $this->l('With this option enabled, it also gives the good result if you search for “lous”, “ouse”, or anything contained in the word.'), - 'hint' => array( - $this->l('Enable search within a whole word, rather than from its beginning only.'), - $this->l('It checks if the searched term is contained in the indexed word. This may be resource-consuming.') - ) - ), - 'PS_SEARCH_END' => array( - 'title' => $this->l('Search exact end match'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'desc' => $this->l('By default, if you search "book", you will have "book", "bookcase" and "bookend".').'<br/>'. - $this->l('With this option enabled, it only gives one result “book”, as exact end of the indexed word is matching.'), - 'hint' => array( - $this->l('Enable more precise search with the end of the word.'), - $this->l('It checks if the searched term is the exact end of the indexed word.') - ) - ), - 'PS_SEARCH_MINWORDLEN' => array( - 'title' => $this->l('Minimum word length (in characters)'), - 'hint' => $this->l('Only words this size or larger will be indexed.'), - 'validation' => 'isUnsignedInt', - 'type' => 'text', - 'cast' => 'intval' - ), - 'PS_SEARCH_BLACKLIST' => array( - 'title' => $this->l('Blacklisted words'), - 'validation' => 'isGenericName', - 'hint' => $this->l('Please enter the index words separated by a "|".'), - 'type' => 'textareaLang' - ) - ), - 'submit' => array('title' => $this->l('Save')) - ), - 'relevance' => array( - 'title' => $this->l('Weight'), - 'icon' => 'icon-cogs', - 'info' => - $this->l('The "weight" represents its importance and relevance for the ranking of the products when completing a new search.').'<br /> + 'fields' => array( + 'PS_SEARCH_INDEXATION' => array( + 'title' => $this->l('Indexing'), + 'validation' => 'isBool', + 'type' => 'bool', + 'cast' => 'intval', + 'desc' => $this->l('Enable the automatic indexing of products. If you enable this feature, the products will be indexed in the search automatically when they are saved. If the feature is disabled, you will have to index products manually by using the links provided in the field set.') + ) + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'search' => array( + 'title' => $this->l('Search'), + 'icon' => 'icon-search', + 'fields' => array( + 'PS_SEARCH_AJAX' => array( + 'title' => $this->l('Ajax search'), + 'validation' => 'isBool', + 'type' => 'bool', + 'cast' => 'intval', + 'hint' => array( + $this->l('Enable ajax search for your visitors.'), + $this->l('With ajax search, the first 10 products matching the user query will appear in real time below the input field.') + ) + ), + 'PS_INSTANT_SEARCH' => array( + 'title' => $this->l('Instant search'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'hint' => array( + $this->l('Enable instant search for your visitors?'), + $this->l('With instant search, the results will appear immediately as the user writes a query.') + ) + ), + 'PS_SEARCH_START' => array( + 'title' => $this->l('Search within word'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'desc' => $this->l('By default, to search for “blouse”, you have to enter “blous”, “blo”, etc (beginning of the word) – but not “lous” (within the word).').'<br/>'. + $this->l('With this option enabled, it also gives the good result if you search for “lous”, “ouse”, or anything contained in the word.'), + 'hint' => array( + $this->l('Enable search within a whole word, rather than from its beginning only.'), + $this->l('It checks if the searched term is contained in the indexed word. This may be resource-consuming.') + ) + ), + 'PS_SEARCH_END' => array( + 'title' => $this->l('Search exact end match'), + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool', + 'desc' => $this->l('By default, if you search "book", you will have "book", "bookcase" and "bookend".').'<br/>'. + $this->l('With this option enabled, it only gives one result “book”, as exact end of the indexed word is matching.'), + 'hint' => array( + $this->l('Enable more precise search with the end of the word.'), + $this->l('It checks if the searched term is the exact end of the indexed word.') + ) + ), + 'PS_SEARCH_MINWORDLEN' => array( + 'title' => $this->l('Minimum word length (in characters)'), + 'hint' => $this->l('Only words this size or larger will be indexed.'), + 'validation' => 'isUnsignedInt', + 'type' => 'text', + 'cast' => 'intval' + ), + 'PS_SEARCH_BLACKLIST' => array( + 'title' => $this->l('Blacklisted words'), + 'validation' => 'isGenericName', + 'hint' => $this->l('Please enter the index words separated by a "|".'), + 'type' => 'textareaLang' + ) + ), + 'submit' => array('title' => $this->l('Save')) + ), + 'relevance' => array( + 'title' => $this->l('Weight'), + 'icon' => 'icon-cogs', + 'info' => + $this->l('The "weight" represents its importance and relevance for the ranking of the products when completing a new search.').'<br /> '.$this->l('A word with a weight of eight will have four times more value than a word with a weight of two.').'<br /><br /> '.$this->l('We advise you to set a greater weight for words which appear in the name or reference of a product. This will allow the search results to be as precise and relevant as possible.').'<br /><br /> '.$this->l('Setting a weight to 0 will exclude that field from search index. Re-build of the entire index is required when changing to or from 0'), - 'fields' => array( - 'PS_SEARCH_WEIGHT_PNAME' => array( - 'title' => $this->l('Product name weight'), - 'validation' => 'isUnsignedInt', - 'type' => 'text', - 'cast' => 'intval' - ), - 'PS_SEARCH_WEIGHT_REF' => array( - 'title' => $this->l('Reference weight'), - 'validation' => 'isUnsignedInt', - 'type' => 'text', - 'cast' => 'intval' - ), - 'PS_SEARCH_WEIGHT_SHORTDESC' => array( - 'title' => $this->l('Short description weight'), - 'validation' => 'isUnsignedInt', - 'type' => 'text', - 'cast' => 'intval' - ), - 'PS_SEARCH_WEIGHT_DESC' => array( - 'title' => $this->l('Description weight'), - 'validation' => 'isUnsignedInt', - 'type' => 'text', - 'cast' => 'intval' - ), - 'PS_SEARCH_WEIGHT_CNAME' => array( - 'title' => $this->l('Category weight'), - 'validation' => 'isUnsignedInt', - 'type' => 'text', - 'cast' => 'intval' - ), - 'PS_SEARCH_WEIGHT_MNAME' => array( - 'title' => $this->l('Manufacturer weight'), - 'validation' => 'isUnsignedInt', - 'type' => 'text', - 'cast' => 'intval' - ), - 'PS_SEARCH_WEIGHT_TAG' => array( - 'title' => $this->l('Tags weight'), - 'validation' => 'isUnsignedInt', - 'type' => 'text', - 'cast' => 'intval' - ), - 'PS_SEARCH_WEIGHT_ATTRIBUTE' => array( - 'title' => $this->l('Attributes weight'), - 'validation' => 'isUnsignedInt', - 'type' => 'text', - 'cast' => 'intval' - ), - 'PS_SEARCH_WEIGHT_FEATURE' => array( - 'title' => $this->l('Features weight'), - 'validation' => 'isUnsignedInt', - 'type' => 'text', - 'cast' => 'intval' - ) - ), - 'submit' => array('title' => $this->l('Save')) - ), - ); - } + 'fields' => array( + 'PS_SEARCH_WEIGHT_PNAME' => array( + 'title' => $this->l('Product name weight'), + 'validation' => 'isUnsignedInt', + 'type' => 'text', + 'cast' => 'intval' + ), + 'PS_SEARCH_WEIGHT_REF' => array( + 'title' => $this->l('Reference weight'), + 'validation' => 'isUnsignedInt', + 'type' => 'text', + 'cast' => 'intval' + ), + 'PS_SEARCH_WEIGHT_SHORTDESC' => array( + 'title' => $this->l('Short description weight'), + 'validation' => 'isUnsignedInt', + 'type' => 'text', + 'cast' => 'intval' + ), + 'PS_SEARCH_WEIGHT_DESC' => array( + 'title' => $this->l('Description weight'), + 'validation' => 'isUnsignedInt', + 'type' => 'text', + 'cast' => 'intval' + ), + 'PS_SEARCH_WEIGHT_CNAME' => array( + 'title' => $this->l('Category weight'), + 'validation' => 'isUnsignedInt', + 'type' => 'text', + 'cast' => 'intval' + ), + 'PS_SEARCH_WEIGHT_MNAME' => array( + 'title' => $this->l('Manufacturer weight'), + 'validation' => 'isUnsignedInt', + 'type' => 'text', + 'cast' => 'intval' + ), + 'PS_SEARCH_WEIGHT_TAG' => array( + 'title' => $this->l('Tags weight'), + 'validation' => 'isUnsignedInt', + 'type' => 'text', + 'cast' => 'intval' + ), + 'PS_SEARCH_WEIGHT_ATTRIBUTE' => array( + 'title' => $this->l('Attributes weight'), + 'validation' => 'isUnsignedInt', + 'type' => 'text', + 'cast' => 'intval' + ), + 'PS_SEARCH_WEIGHT_FEATURE' => array( + 'title' => $this->l('Features weight'), + 'validation' => 'isUnsignedInt', + 'type' => 'text', + 'cast' => 'intval' + ) + ), + 'submit' => array('title' => $this->l('Save')) + ), + ); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_alias'] = array( - 'href' => self::$currentIndex.'&addalias&token='.$this->token, - 'desc' => $this->l('Add new alias', null, null, false), - 'icon' => 'process-icon-new' - ); - $this->identifier_name = 'alias'; - parent::initPageHeaderToolbar(); - if ($this->can_import) - $this->toolbar_btn['import'] = array( - 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=alias', - 'desc' => $this->l('Import', null, null, false) - ); - } + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_alias'] = array( + 'href' => self::$currentIndex.'&addalias&token='.$this->token, + 'desc' => $this->l('Add new alias', null, null, false), + 'icon' => 'process-icon-new' + ); + } + $this->identifier_name = 'alias'; + parent::initPageHeaderToolbar(); + if ($this->can_import) { + $this->toolbar_btn['import'] = array( + 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=alias', + 'desc' => $this->l('Import', null, null, false) + ); + } + } - public function initProcess() - { - parent::initProcess(); - // This is a composite page, we don't want the "options" display mode - if ($this->display == 'options') - $this->display = ''; - } + public function initProcess() + { + parent::initProcess(); + // This is a composite page, we don't want the "options" display mode + if ($this->display == 'options') { + $this->display = ''; + } + } - /** - * Function used to render the options for this controller - */ - public function renderOptions() - { - if ($this->fields_options && is_array($this->fields_options)) - { - $helper = new HelperOptions($this); - $this->setHelperDisplay($helper); - $helper->toolbar_scroll = true; - $helper->toolbar_btn = array('save' => array( - 'href' => '#', - 'desc' => $this->l('Save') - )); - $helper->id = $this->id; - $helper->tpl_vars = $this->tpl_option_vars; - $options = $helper->generateOptions($this->fields_options); + /** + * Function used to render the options for this controller + */ + public function renderOptions() + { + if ($this->fields_options && is_array($this->fields_options)) { + $helper = new HelperOptions($this); + $this->setHelperDisplay($helper); + $helper->toolbar_scroll = true; + $helper->toolbar_btn = array('save' => array( + 'href' => '#', + 'desc' => $this->l('Save') + )); + $helper->id = $this->id; + $helper->tpl_vars = $this->tpl_option_vars; + $options = $helper->generateOptions($this->fields_options); - return $options; - } - } + return $options; + } + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Aliases'), - 'icon' => 'icon-search' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Alias'), - 'name' => 'alias', - 'required' => true, - 'hint' => array( - $this->l('Enter each alias separated by a comma (e.g. \'prestshop,preztashop,prestasohp\').'), - $this->l('Forbidden characters: <>;=#{}') - ) - ), - array( - 'type' => 'text', - 'label' => $this->l('Result'), - 'name' => 'search', - 'required' => true, - 'hint' => $this->l('Search this word instead.') - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Aliases'), + 'icon' => 'icon-search' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Alias'), + 'name' => 'alias', + 'required' => true, + 'hint' => array( + $this->l('Enter each alias separated by a comma (e.g. \'prestshop,preztashop,prestasohp\').'), + $this->l('Forbidden characters: <>;=#{}') + ) + ), + array( + 'type' => 'text', + 'label' => $this->l('Result'), + 'name' => 'search', + 'required' => true, + 'hint' => $this->l('Search this word instead.') + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - $this->fields_value = array('alias' => $this->object->getAliases()); + $this->fields_value = array('alias' => $this->object->getAliases()); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function processSave() - { - $search = strval(Tools::getValue('search')); - $string = strval(Tools::getValue('alias')); - $aliases = explode(',', $string); - if (empty($search) || empty($string)) - $this->errors[] = $this->l('Aliases and results are both required.'); - if (!Validate::isValidSearch($search)) - $this->errors[] = $search.' '.$this->l('Is not a valid result'); - foreach ($aliases as $alias) - if (!Validate::isValidSearch($alias)) - $this->errors[] = $alias.' '.$this->l('Is not a valid alias'); + public function processSave() + { + $search = strval(Tools::getValue('search')); + $string = strval(Tools::getValue('alias')); + $aliases = explode(',', $string); + if (empty($search) || empty($string)) { + $this->errors[] = $this->l('Aliases and results are both required.'); + } + if (!Validate::isValidSearch($search)) { + $this->errors[] = $search.' '.$this->l('Is not a valid result'); + } + foreach ($aliases as $alias) { + if (!Validate::isValidSearch($alias)) { + $this->errors[] = $alias.' '.$this->l('Is not a valid alias'); + } + } - if (!count($this->errors)) - { - foreach ($aliases as $alias) - { - $obj = new Alias(null, trim($alias), trim($search)); - $obj->save(); - } - } + if (!count($this->errors)) { + foreach ($aliases as $alias) { + $obj = new Alias(null, trim($alias), trim($search)); + $obj->save(); + } + } - if (empty($this->errors)) - $this->confirmations[] = $this->l('Creation successful'); - } + if (empty($this->errors)) { + $this->confirmations[] = $this->l('Creation successful'); + } + } } diff --git a/controllers/admin/AdminSearchController.php b/controllers/admin/AdminSearchController.php index 416fe94a..d77809ff 100644 --- a/controllers/admin/AdminSearchController.php +++ b/controllers/admin/AdminSearchController.php @@ -26,404 +26,408 @@ class AdminSearchControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - parent::__construct(); - } + public function __construct() + { + $this->bootstrap = true; + parent::__construct(); + } - public function postProcess() - { - $this->context = Context::getContext(); - $this->query = trim(Tools::getValue('bo_query')); - $searchType = (int)Tools::getValue('bo_search_type'); - /* Handle empty search field */ - if (!empty($this->query)) - { - if (!$searchType && strlen($this->query) > 1) - $this->searchFeatures(); + public function postProcess() + { + $this->context = Context::getContext(); + $this->query = trim(Tools::getValue('bo_query')); + $searchType = (int)Tools::getValue('bo_search_type'); + /* Handle empty search field */ + if (!empty($this->query)) { + if (!$searchType && strlen($this->query) > 1) { + $this->searchFeatures(); + } - /* Product research */ - if (!$searchType || $searchType == 1) - { - /* Handle product ID */ - if ($searchType == 1 && (int)$this->query && Validate::isUnsignedInt((int)$this->query)) - if (($product = new Product($this->query)) && Validate::isLoadedObject($product)) - Tools::redirectAdmin('index.php?tab=AdminProducts&id_product='.(int)($product->id).'&token='.Tools::getAdminTokenLite('AdminProducts')); + /* Product research */ + if (!$searchType || $searchType == 1) { + /* Handle product ID */ + if ($searchType == 1 && (int)$this->query && Validate::isUnsignedInt((int)$this->query)) { + if (($product = new Product($this->query)) && Validate::isLoadedObject($product)) { + Tools::redirectAdmin('index.php?tab=AdminProducts&id_product='.(int)($product->id).'&token='.Tools::getAdminTokenLite('AdminProducts')); + } + } - /* Normal catalog search */ - $this->searchCatalog(); - } + /* Normal catalog search */ + $this->searchCatalog(); + } - /* Customer */ - if (!$searchType || $searchType == 2 || $searchType == 6) - { - if (!$searchType || $searchType == 2) - { - /* Handle customer ID */ - if ($searchType && (int)$this->query && Validate::isUnsignedInt((int)$this->query)) - if (($customer = new Customer($this->query)) && Validate::isLoadedObject($customer)) - Tools::redirectAdmin('index.php?tab=AdminCustomers&id_customer='.(int)$customer->id.'&viewcustomer'.'&token='.Tools::getAdminToken('AdminCustomers'.(int)Tab::getIdFromClassName('AdminCustomers').(int)$this->context->employee->id)); + /* Customer */ + if (!$searchType || $searchType == 2 || $searchType == 6) { + if (!$searchType || $searchType == 2) { + /* Handle customer ID */ + if ($searchType && (int)$this->query && Validate::isUnsignedInt((int)$this->query)) { + if (($customer = new Customer($this->query)) && Validate::isLoadedObject($customer)) { + Tools::redirectAdmin('index.php?tab=AdminCustomers&id_customer='.(int)$customer->id.'&viewcustomer'.'&token='.Tools::getAdminToken('AdminCustomers'.(int)Tab::getIdFromClassName('AdminCustomers').(int)$this->context->employee->id)); + } + } - /* Normal customer search */ - $this->searchCustomer(); - } + /* Normal customer search */ + $this->searchCustomer(); + } - if ($searchType == 6) - $this->searchIP(); - } + if ($searchType == 6) { + $this->searchIP(); + } + } - /* Order */ - if (!$searchType || $searchType == 3) - { - if (Validate::isUnsignedInt(trim($this->query)) && (int)$this->query && ($order = new Order((int)$this->query)) && Validate::isLoadedObject($order)) - { - if ($searchType == 3) - Tools::redirectAdmin('index.php?tab=AdminOrders&id_order='.(int)$order->id.'&vieworder'.'&token='.Tools::getAdminTokenLite('AdminOrders')); - else - { - $row = get_object_vars($order); - $row['id_order'] = $row['id']; - $customer = $order->getCustomer(); - $row['customer'] = $customer->firstname.' '.$customer->lastname; - $order_state = $order->getCurrentOrderState(); - $row['osname'] = $order_state->name[$this->context->language->id]; - $this->_list['orders'] = array($row); - } - } - else - { - $orders = Order::getByReference($this->query); - $nb_orders = count($orders); - if ($nb_orders == 1 && $searchType == 3) - Tools::redirectAdmin('index.php?tab=AdminOrders&id_order='.(int)$orders[0]->id.'&vieworder'.'&token='.Tools::getAdminTokenLite('AdminOrders')); - elseif ($nb_orders) - { - $this->_list['orders'] = array(); - foreach ($orders as $order) - { - /** @var Order $order */ - $row = get_object_vars($order); - $row['id_order'] = $row['id']; - $customer = $order->getCustomer(); - $row['customer'] = $customer->firstname.' '.$customer->lastname; - $order_state = $order->getCurrentOrderState(); - $row['osname'] = $order_state->name[$this->context->language->id]; - $this->_list['orders'][] = $row; - } - } - elseif ($searchType == 3) - $this->errors[] = Tools::displayError('No order was found with this ID:').' '.Tools::htmlentitiesUTF8($this->query); - } - } + /* Order */ + if (!$searchType || $searchType == 3) { + if (Validate::isUnsignedInt(trim($this->query)) && (int)$this->query && ($order = new Order((int)$this->query)) && Validate::isLoadedObject($order)) { + if ($searchType == 3) { + Tools::redirectAdmin('index.php?tab=AdminOrders&id_order='.(int)$order->id.'&vieworder'.'&token='.Tools::getAdminTokenLite('AdminOrders')); + } else { + $row = get_object_vars($order); + $row['id_order'] = $row['id']; + $customer = $order->getCustomer(); + $row['customer'] = $customer->firstname.' '.$customer->lastname; + $order_state = $order->getCurrentOrderState(); + $row['osname'] = $order_state->name[$this->context->language->id]; + $this->_list['orders'] = array($row); + } + } else { + $orders = Order::getByReference($this->query); + $nb_orders = count($orders); + if ($nb_orders == 1 && $searchType == 3) { + Tools::redirectAdmin('index.php?tab=AdminOrders&id_order='.(int)$orders[0]->id.'&vieworder'.'&token='.Tools::getAdminTokenLite('AdminOrders')); + } elseif ($nb_orders) { + $this->_list['orders'] = array(); + foreach ($orders as $order) { + /** @var Order $order */ + $row = get_object_vars($order); + $row['id_order'] = $row['id']; + $customer = $order->getCustomer(); + $row['customer'] = $customer->firstname.' '.$customer->lastname; + $order_state = $order->getCurrentOrderState(); + $row['osname'] = $order_state->name[$this->context->language->id]; + $this->_list['orders'][] = $row; + } + } elseif ($searchType == 3) { + $this->errors[] = Tools::displayError('No order was found with this ID:').' '.Tools::htmlentitiesUTF8($this->query); + } + } + } - /* Invoices */ - if ($searchType == 4) - { - if (Validate::isOrderInvoiceNumber($this->query) && ($invoice = OrderInvoice::getInvoiceByNumber($this->query))) - Tools::redirectAdmin($this->context->link->getAdminLink('AdminPdf').'&submitAction=generateInvoicePDF&id_order='.(int)($invoice->id_order)); - $this->errors[] = Tools::displayError('No invoice was found with this ID:').' '.Tools::htmlentitiesUTF8($this->query); - } + /* Invoices */ + if ($searchType == 4) { + if (Validate::isOrderInvoiceNumber($this->query) && ($invoice = OrderInvoice::getInvoiceByNumber($this->query))) { + Tools::redirectAdmin($this->context->link->getAdminLink('AdminPdf').'&submitAction=generateInvoicePDF&id_order='.(int)($invoice->id_order)); + } + $this->errors[] = Tools::displayError('No invoice was found with this ID:').' '.Tools::htmlentitiesUTF8($this->query); + } - /* Cart */ - if ($searchType == 5) - { - if ((int)$this->query && Validate::isUnsignedInt((int)$this->query) && ($cart = new Cart($this->query)) && Validate::isLoadedObject($cart)) - Tools::redirectAdmin('index.php?tab=AdminCarts&id_cart='.(int)($cart->id).'&viewcart'.'&token='.Tools::getAdminToken('AdminCarts'.(int)(Tab::getIdFromClassName('AdminCarts')).(int)$this->context->employee->id)); - $this->errors[] = Tools::displayError('No cart was found with this ID:').' '.Tools::htmlentitiesUTF8($this->query); - } - /* IP */ - // 6 - but it is included in the customer block + /* Cart */ + if ($searchType == 5) { + if ((int)$this->query && Validate::isUnsignedInt((int)$this->query) && ($cart = new Cart($this->query)) && Validate::isLoadedObject($cart)) { + Tools::redirectAdmin('index.php?tab=AdminCarts&id_cart='.(int)($cart->id).'&viewcart'.'&token='.Tools::getAdminToken('AdminCarts'.(int)(Tab::getIdFromClassName('AdminCarts')).(int)$this->context->employee->id)); + } + $this->errors[] = Tools::displayError('No cart was found with this ID:').' '.Tools::htmlentitiesUTF8($this->query); + } + /* IP */ + // 6 - but it is included in the customer block - /* Module search */ - if (!$searchType || $searchType == 7) - { - /* Handle module name */ - if ($searchType == 7 && Validate::isModuleName($this->query) AND ($module = Module::getInstanceByName($this->query)) && Validate::isLoadedObject($module)) - Tools::redirectAdmin('index.php?tab=AdminModules&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name).'&token='.Tools::getAdminTokenLite('AdminModules')); + /* Module search */ + if (!$searchType || $searchType == 7) { + /* Handle module name */ + if ($searchType == 7 && Validate::isModuleName($this->query) and ($module = Module::getInstanceByName($this->query)) && Validate::isLoadedObject($module)) { + Tools::redirectAdmin('index.php?tab=AdminModules&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name).'&token='.Tools::getAdminTokenLite('AdminModules')); + } - /* Normal catalog search */ - $this->searchModule(); - } - } - $this->display = 'view'; - } + /* Normal catalog search */ + $this->searchModule(); + } + } + $this->display = 'view'; + } - public function searchIP() - { - if (!ip2long(trim($this->query))) - { - $this->errors[] = Tools::displayError('This is not a valid IP address:').' '.Tools::htmlentitiesUTF8($this->query); - return; - } - $this->_list['customers'] = Customer::searchByIp($this->query); - } + public function searchIP() + { + if (!ip2long(trim($this->query))) { + $this->errors[] = Tools::displayError('This is not a valid IP address:').' '.Tools::htmlentitiesUTF8($this->query); + return; + } + $this->_list['customers'] = Customer::searchByIp($this->query); + } - /** - * Search a specific string in the products and categories - * - * @params string $query String to find in the catalog - */ - public function searchCatalog() - { - $this->context = Context::getContext(); - $this->_list['products'] = Product::searchByName($this->context->language->id, $this->query); - $this->_list['categories'] = Category::searchByName($this->context->language->id, $this->query); - } + /** + * Search a specific string in the products and categories + * + * @params string $query String to find in the catalog + */ + public function searchCatalog() + { + $this->context = Context::getContext(); + $this->_list['products'] = Product::searchByName($this->context->language->id, $this->query); + $this->_list['categories'] = Category::searchByName($this->context->language->id, $this->query); + } - /** - * Search a specific name in the customers - * - * @params string $query String to find in the catalog - */ - public function searchCustomer() - { - $this->_list['customers'] = Customer::searchByName($this->query); - } + /** + * Search a specific name in the customers + * + * @params string $query String to find in the catalog + */ + public function searchCustomer() + { + $this->_list['customers'] = Customer::searchByName($this->query); + } - public function searchModule() - { - $this->_list['modules'] = array(); - $all_modules = Module::getModulesOnDisk(true, true, Context::getContext()->employee->id); - foreach ($all_modules as $module) - if (stripos($module->name, $this->query) !== false || stripos($module->displayName, $this->query) !== false || stripos($module->description, $this->query) !== false) - { - $module->linkto = 'index.php?tab=AdminModules&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name).'&token='.Tools::getAdminTokenLite('AdminModules'); - $this->_list['modules'][] = $module; - } + public function searchModule() + { + $this->_list['modules'] = array(); + $all_modules = Module::getModulesOnDisk(true, true, Context::getContext()->employee->id); + foreach ($all_modules as $module) { + if (stripos($module->name, $this->query) !== false || stripos($module->displayName, $this->query) !== false || stripos($module->description, $this->query) !== false) { + $module->linkto = 'index.php?tab=AdminModules&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name).'&token='.Tools::getAdminTokenLite('AdminModules'); + $this->_list['modules'][] = $module; + } + } - if (!is_numeric(trim($this->query)) && !Validate::isEmail($this->query)) - { - $iso_lang = Tools::strtolower(Context::getContext()->language->iso_code); - $iso_country = Tools::strtolower(Country::getIsoById(Configuration::get('PS_COUNTRY_DEFAULT'))); - if (($json_content = Tools::file_get_contents('https://api-addons.prestashop.com/'._PS_VERSION_.'/search/'.urlencode($this->query).'/'.$iso_country.'/'.$iso_lang.'/')) != false) - { - $results = Tools::jsonDecode($json_content, true); - if (isset($results['id'])) - $this->_list['addons'] = array($results); - else - $this->_list['addons'] = $results; - } - } - } + if (!is_numeric(trim($this->query)) && !Validate::isEmail($this->query)) { + $iso_lang = Tools::strtolower(Context::getContext()->language->iso_code); + $iso_country = Tools::strtolower(Country::getIsoById(Configuration::get('PS_COUNTRY_DEFAULT'))); + if (($json_content = Tools::file_get_contents('https://api-addons.prestashop.com/'._PS_VERSION_.'/search/'.urlencode($this->query).'/'.$iso_country.'/'.$iso_lang.'/')) != false) { + $results = Tools::jsonDecode($json_content, true); + if (isset($results['id'])) { + $this->_list['addons'] = array($results); + } else { + $this->_list['addons'] = $results; + } + } + } + } - /** - * Search a feature in all store - * - * @params string $query String to find in the catalog - */ - public function searchFeatures() - { - $this->_list['features'] = array(); + /** + * Search a feature in all store + * + * @params string $query String to find in the catalog + */ + public function searchFeatures() + { + $this->_list['features'] = array(); - global $_LANGADM; - if ($_LANGADM === null) - return; + global $_LANGADM; + if ($_LANGADM === null) { + return; + } - $tabs = array(); - $key_match = array(); - $result = Db::getInstance()->executeS(' + $tabs = array(); + $key_match = array(); + $result = Db::getInstance()->executeS(' SELECT class_name, name FROM '._DB_PREFIX_.'tab t INNER JOIN '._DB_PREFIX_.'tab_lang tl ON (t.id_tab = tl.id_tab AND tl.id_lang = '.(int)$this->context->employee->id_lang.') LEFT JOIN '._DB_PREFIX_.'access a ON (a.id_tab = t.id_tab AND a.id_profile = '.(int)$this->context->employee->id_profile.') WHERE active = 1 '.($this->context->employee->id_profile != 1 ? 'AND view = 1' : ''). - (defined('_PS_HOST_MODE_') ? ' AND t.`hide_host_mode` = 0' : '') - ); - foreach ($result as $row) - { - $tabs[strtolower($row['class_name'])] = $row['name']; - $key_match[strtolower($row['class_name'])] = $row['class_name']; - } - foreach (AdminTab::$tabParenting as $key => $value) - { - $value = stripslashes($value); - if (!isset($tabs[strtolower($key)]) || !isset($tabs[strtolower($value)])) - continue; - $tabs[strtolower($key)] = $tabs[strtolower($value)]; - $key_match[strtolower($key)] = $key; - } + (defined('_PS_HOST_MODE_') ? ' AND t.`hide_host_mode` = 0' : '') + ); + foreach ($result as $row) { + $tabs[strtolower($row['class_name'])] = $row['name']; + $key_match[strtolower($row['class_name'])] = $row['class_name']; + } + foreach (AdminTab::$tabParenting as $key => $value) { + $value = stripslashes($value); + if (!isset($tabs[strtolower($key)]) || !isset($tabs[strtolower($value)])) { + continue; + } + $tabs[strtolower($key)] = $tabs[strtolower($value)]; + $key_match[strtolower($key)] = $key; + } - $this->_list['features'] = array(); - foreach ($_LANGADM as $key => $value) - { - if (stripos($value, $this->query) !== false) - { - $value = stripslashes($value); - $key = strtolower(substr($key, 0, -32)); - if (in_array($key, array('AdminTab', 'index'))) - continue; - // if class name doesn't exists, just ignore it - if (!isset($tabs[$key])) - continue; - if (!isset($this->_list['features'][$tabs[$key]])) - $this->_list['features'][$tabs[$key]] = array(); - $this->_list['features'][$tabs[$key]][] = array('link' => Context::getContext()->link->getAdminLink($key_match[$key]), 'value' => Tools::safeOutput($value)); - } - } - } + $this->_list['features'] = array(); + foreach ($_LANGADM as $key => $value) { + if (stripos($value, $this->query) !== false) { + $value = stripslashes($value); + $key = strtolower(substr($key, 0, -32)); + if (in_array($key, array('AdminTab', 'index'))) { + continue; + } + // if class name doesn't exists, just ignore it + if (!isset($tabs[$key])) { + continue; + } + if (!isset($this->_list['features'][$tabs[$key]])) { + $this->_list['features'][$tabs[$key]] = array(); + } + $this->_list['features'][$tabs[$key]][] = array('link' => Context::getContext()->link->getAdminLink($key_match[$key]), 'value' => Tools::safeOutput($value)); + } + } + } - protected function initOrderList() - { - $this->fields_list['orders'] = array( - 'reference' => array('title' => $this->l('Reference'), 'align' => 'center', 'width' => 65), - 'id_order' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25), - 'customer' => array('title' => $this->l('Customer')), - 'total_paid_tax_incl' => array('title' => $this->l('Total'), 'width' => 70, 'align' => 'right', 'type' => 'price', 'currency' => true), - 'payment' => array( 'title' => $this->l('Payment'), 'width' => 100), - 'osname' => array('title' => $this->l('Status'), 'width' => 280), - 'date_add' => array('title' => $this->l('Date'), 'width' => 130, 'align' => 'right', 'type' => 'datetime'), - ); - } + protected function initOrderList() + { + $this->fields_list['orders'] = array( + 'reference' => array('title' => $this->l('Reference'), 'align' => 'center', 'width' => 65), + 'id_order' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25), + 'customer' => array('title' => $this->l('Customer')), + 'total_paid_tax_incl' => array('title' => $this->l('Total'), 'width' => 70, 'align' => 'right', 'type' => 'price', 'currency' => true), + 'payment' => array( 'title' => $this->l('Payment'), 'width' => 100), + 'osname' => array('title' => $this->l('Status'), 'width' => 280), + 'date_add' => array('title' => $this->l('Date'), 'width' => 130, 'align' => 'right', 'type' => 'datetime'), + ); + } - protected function initCustomerList() - { - $genders_icon = array('default' => 'unknown.gif'); - $genders = array(0 => $this->l('?')); - foreach (Gender::getGenders() as $gender) - { - /** @var Gender $gender */ - $genders_icon[$gender->id] = '../genders/'.(int)$gender->id.'.jpg'; - $genders[$gender->id] = $gender->name; - } - $this->fields_list['customers'] = (array( - 'id_customer' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25), - 'id_gender' => array('title' => $this->l('Social title'), 'align' => 'center', 'icon' => $genders_icon, 'list' => $genders, 'width' => 25), - 'firstname' => array('title' => $this->l('First Name'), 'align' => 'left', 'width' => 150), - 'lastname' => array('title' => $this->l('Name'), 'align' => 'left', 'width' => 'auto'), - 'email' => array('title' => $this->l('Email address'), 'align' => 'left', 'width' => 250), - 'birthday' => array('title' => $this->l('Birth date'), 'align' => 'center', 'type' => 'date', 'width' => 75), - 'date_add' => array('title' => $this->l('Registration date'), 'align' => 'center', 'type' => 'date', 'width' => 75), - 'orders' => array('title' => $this->l('Orders'), 'align' => 'center', 'width' => 50), - 'active' => array('title' => $this->l('Enabled'),'align' => 'center','active' => 'status','type' => 'bool', 'width' => 25), - )); - } + protected function initCustomerList() + { + $genders_icon = array('default' => 'unknown.gif'); + $genders = array(0 => $this->l('?')); + foreach (Gender::getGenders() as $gender) { + /** @var Gender $gender */ + $genders_icon[$gender->id] = '../genders/'.(int)$gender->id.'.jpg'; + $genders[$gender->id] = $gender->name; + } + $this->fields_list['customers'] = (array( + 'id_customer' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25), + 'id_gender' => array('title' => $this->l('Social title'), 'align' => 'center', 'icon' => $genders_icon, 'list' => $genders, 'width' => 25), + 'firstname' => array('title' => $this->l('First Name'), 'align' => 'left', 'width' => 150), + 'lastname' => array('title' => $this->l('Name'), 'align' => 'left', 'width' => 'auto'), + 'email' => array('title' => $this->l('Email address'), 'align' => 'left', 'width' => 250), + 'birthday' => array('title' => $this->l('Birth date'), 'align' => 'center', 'type' => 'date', 'width' => 75), + 'date_add' => array('title' => $this->l('Registration date'), 'align' => 'center', 'type' => 'date', 'width' => 75), + 'orders' => array('title' => $this->l('Orders'), 'align' => 'center', 'width' => 50), + 'active' => array('title' => $this->l('Enabled'), 'align' => 'center', 'active' => 'status', 'type' => 'bool', 'width' => 25), + )); + } - protected function initProductList() - { - $this->show_toolbar = false; - $this->fields_list['products'] = array( - 'id_product' => array('title' => $this->l('ID'), 'width' => 25), - 'manufacturer_name' => array('title' => $this->l('Manufacturer'), 'align' => 'center', 'width' => 200), - 'reference' => array('title' => $this->l('Reference'), 'align' => 'center', 'width' => 150), - 'name' => array('title' => $this->l('Name'), 'width' => 'auto'), - 'price_tax_excl' => array('title' => $this->l('Price (tax excl.)'), 'align' => 'right', 'type' => 'price', 'width' => 60), - 'price_tax_incl' => array('title' => $this->l('Price (tax incl.)'), 'align' => 'right', 'type' => 'price', 'width' => 60), - 'active' => array('title' => $this->l('Active'), 'width' => 70, 'active' => 'status', 'align' => 'center', 'type' => 'bool') - ); - } + protected function initProductList() + { + $this->show_toolbar = false; + $this->fields_list['products'] = array( + 'id_product' => array('title' => $this->l('ID'), 'width' => 25), + 'manufacturer_name' => array('title' => $this->l('Manufacturer'), 'align' => 'center', 'width' => 200), + 'reference' => array('title' => $this->l('Reference'), 'align' => 'center', 'width' => 150), + 'name' => array('title' => $this->l('Name'), 'width' => 'auto'), + 'price_tax_excl' => array('title' => $this->l('Price (tax excl.)'), 'align' => 'right', 'type' => 'price', 'width' => 60), + 'price_tax_incl' => array('title' => $this->l('Price (tax incl.)'), 'align' => 'right', 'type' => 'price', 'width' => 60), + 'active' => array('title' => $this->l('Active'), 'width' => 70, 'active' => 'status', 'align' => 'center', 'type' => 'bool') + ); + } - public function setMedia() - { - parent::setMedia(); - $this->addJqueryPlugin('highlight'); - } + public function setMedia() + { + parent::setMedia(); + $this->addJqueryPlugin('highlight'); + } - /* Override because we don't want any buttons */ - public function initToolbar() - { - } + /* Override because we don't want any buttons */ + public function initToolbar() + { + } - public function initToolbarTitle() - { - $this->toolbar_title = $this->l('Search results', null, null, false); - } + public function initToolbarTitle() + { + $this->toolbar_title = $this->l('Search results', null, null, false); + } - public function renderView() - { - $this->tpl_view_vars['query'] = Tools::safeOutput($this->query); - $this->tpl_view_vars['show_toolbar'] = true; + public function renderView() + { + $this->tpl_view_vars['query'] = Tools::safeOutput($this->query); + $this->tpl_view_vars['show_toolbar'] = true; - if (count($this->errors)) - return parent::renderView(); - else - { - $nb_results = 0; - foreach ($this->_list as $list) - if ($list != false) - $nb_results += count($list); - $this->tpl_view_vars['nb_results'] = $nb_results; + if (count($this->errors)) { + return parent::renderView(); + } else { + $nb_results = 0; + foreach ($this->_list as $list) { + if ($list != false) { + $nb_results += count($list); + } + } + $this->tpl_view_vars['nb_results'] = $nb_results; - if (isset($this->_list['features']) && count($this->_list['features'])) - $this->tpl_view_vars['features'] = $this->_list['features']; - if (isset($this->_list['categories']) && count($this->_list['categories'])) - { - $categories = array(); - foreach ($this->_list['categories'] as $category) - $categories[] = getPath($this->context->link->getAdminLink('AdminCategories', false), $category['id_category']); - $this->tpl_view_vars['categories'] = $categories; - } - if (isset($this->_list['products']) && count($this->_list['products'])) - { - $view = ''; - $this->initProductList(); + if (isset($this->_list['features']) && count($this->_list['features'])) { + $this->tpl_view_vars['features'] = $this->_list['features']; + } + if (isset($this->_list['categories']) && count($this->_list['categories'])) { + $categories = array(); + foreach ($this->_list['categories'] as $category) { + $categories[] = getPath($this->context->link->getAdminLink('AdminCategories', false), $category['id_category']); + } + $this->tpl_view_vars['categories'] = $categories; + } + if (isset($this->_list['products']) && count($this->_list['products'])) { + $view = ''; + $this->initProductList(); - $helper = new HelperList(); - $helper->shopLinkType = ''; - $helper->simple_header = true; - $helper->identifier = 'id_product'; - $helper->actions = array('edit'); - $helper->show_toolbar = false; - $helper->table = 'product'; - $helper->currentIndex = $this->context->link->getAdminLink('AdminProducts', false); - $helper->token = Tools::getAdminTokenLite('AdminProducts'); + $helper = new HelperList(); + $helper->shopLinkType = ''; + $helper->simple_header = true; + $helper->identifier = 'id_product'; + $helper->actions = array('edit'); + $helper->show_toolbar = false; + $helper->table = 'product'; + $helper->currentIndex = $this->context->link->getAdminLink('AdminProducts', false); - if ($this->_list['products']) - $view = $helper->generateList($this->_list['products'], $this->fields_list['products']); + $query = trim(Tools::getValue('bo_query')); + $searchType = (int)Tools::getValue('bo_search_type'); - $this->tpl_view_vars['products'] = $view; - } - if (isset($this->_list['customers']) && count($this->_list['customers'])) - { - $view = ''; - $this->initCustomerList(); + if ($query) { + $helper->currentIndex .= '&bo_query='.$query.'&bo_search_type='.$searchType; + } - $helper = new HelperList(); - $helper->shopLinkType = ''; - $helper->simple_header = true; - $helper->identifier = 'id_customer'; - $helper->actions = array('edit', 'view'); - $helper->show_toolbar = false; - $helper->table = 'customer'; - $helper->currentIndex = $this->context->link->getAdminLink('AdminCustomers', false); - $helper->token = Tools::getAdminTokenLite('AdminCustomers'); + $helper->token = Tools::getAdminTokenLite('AdminProducts'); - if ($this->_list['customers']) - { - foreach ($this->_list['customers'] as $key => $val) - $this->_list['customers'][$key]['orders'] = Order::getCustomerNbOrders((int)$val['id_customer']); - $view = $helper->generateList($this->_list['customers'], $this->fields_list['customers']); - } - $this->tpl_view_vars['customers'] = $view; - } - if (isset($this->_list['orders']) && count($this->_list['orders'])) - { - $view = ''; - $this->initOrderList(); + if ($this->_list['products']) { + $view = $helper->generateList($this->_list['products'], $this->fields_list['products']); + } - $helper = new HelperList(); - $helper->shopLinkType = ''; - $helper->simple_header = true; - $helper->identifier = 'id_order'; - $helper->actions = array('view'); - $helper->show_toolbar = false; - $helper->table = 'order'; - $helper->currentIndex = $this->context->link->getAdminLink('AdminOrders', false); - $helper->token = Tools::getAdminTokenLite('AdminOrders'); + $this->tpl_view_vars['products'] = $view; + } + if (isset($this->_list['customers']) && count($this->_list['customers'])) { + $view = ''; + $this->initCustomerList(); - if ($this->_list['orders']) - $view = $helper->generateList($this->_list['orders'], $this->fields_list['orders']); - $this->tpl_view_vars['orders'] = $view; - } + $helper = new HelperList(); + $helper->shopLinkType = ''; + $helper->simple_header = true; + $helper->identifier = 'id_customer'; + $helper->actions = array('edit', 'view'); + $helper->show_toolbar = false; + $helper->table = 'customer'; + $helper->currentIndex = $this->context->link->getAdminLink('AdminCustomers', false); + $helper->token = Tools::getAdminTokenLite('AdminCustomers'); - if (isset($this->_list['modules']) && count($this->_list['modules'])) - $this->tpl_view_vars['modules'] = $this->_list['modules']; - if (isset($this->_list['addons']) && count($this->_list['addons'])) - $this->tpl_view_vars['addons'] = $this->_list['addons']; + if ($this->_list['customers']) { + foreach ($this->_list['customers'] as $key => $val) { + $this->_list['customers'][$key]['orders'] = Order::getCustomerNbOrders((int)$val['id_customer']); + } + $view = $helper->generateList($this->_list['customers'], $this->fields_list['customers']); + } + $this->tpl_view_vars['customers'] = $view; + } + if (isset($this->_list['orders']) && count($this->_list['orders'])) { + $view = ''; + $this->initOrderList(); - return parent::renderView(); - } - } + $helper = new HelperList(); + $helper->shopLinkType = ''; + $helper->simple_header = true; + $helper->identifier = 'id_order'; + $helper->actions = array('view'); + $helper->show_toolbar = false; + $helper->table = 'order'; + $helper->currentIndex = $this->context->link->getAdminLink('AdminOrders', false); + $helper->token = Tools::getAdminTokenLite('AdminOrders'); + + if ($this->_list['orders']) { + $view = $helper->generateList($this->_list['orders'], $this->fields_list['orders']); + } + $this->tpl_view_vars['orders'] = $view; + } + + if (isset($this->_list['modules']) && count($this->_list['modules'])) { + $this->tpl_view_vars['modules'] = $this->_list['modules']; + } + if (isset($this->_list['addons']) && count($this->_list['addons'])) { + $this->tpl_view_vars['addons'] = $this->_list['addons']; + } + + return parent::renderView(); + } + } } diff --git a/controllers/admin/AdminSearchEnginesController.php b/controllers/admin/AdminSearchEnginesController.php index b73cdf58..57b979fc 100644 --- a/controllers/admin/AdminSearchEnginesController.php +++ b/controllers/admin/AdminSearchEnginesController.php @@ -29,76 +29,76 @@ */ class AdminSearchEnginesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'search_engine'; - $this->className = 'SearchEngine'; - $this->lang = false; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'search_engine'; + $this->className = 'SearchEngine'; + $this->lang = false; - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->context = Context::getContext(); + $this->context = Context::getContext(); - if (!Tools::getValue('realedit')) - $this->deleted = false; + if (!Tools::getValue('realedit')) { + $this->deleted = false; + } - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->fields_list = array( - 'id_search_engine' => array('title' => $this->l('ID'), 'width' => 25), - 'server' => array('title' => $this->l('Server')), - 'getvar' => array('title' => $this->l('GET variable'), 'width' => 100) - ); + $this->fields_list = array( + 'id_search_engine' => array('title' => $this->l('ID'), 'width' => 25), + 'server' => array('title' => $this->l('Server')), + 'getvar' => array('title' => $this->l('GET variable'), 'width' => 100) + ); - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Referrer') - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Server'), - 'name' => 'server', - 'size' => 20, - 'required' => true - ), - array( - 'type' => 'text', - 'label' => $this->l('$_GET variable'), - 'name' => 'getvar', - 'size' => 40, - 'required' => true - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Referrer') + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Server'), + 'name' => 'server', + 'size' => 20, + 'required' => true + ), + array( + 'type' => 'text', + 'label' => $this->l('$_GET variable'), + 'name' => 'getvar', + 'size' => 40, + 'required' => true + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - if(empty($this->display)) - $this->page_header_toolbar_btn['new_search_engine'] = array( - 'href' => self::$currentIndex.'&addsearch_engine&token='.$this->token, - 'desc' => $this->l('Add new search engine', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_search_engine'] = array( + 'href' => self::$currentIndex.'&addsearch_engine&token='.$this->token, + 'desc' => $this->l('Add new search engine', null, null, false), + 'icon' => 'process-icon-new' + ); + } - $this->identifier_name = 'server'; - - parent::initPageHeaderToolbar(); - } + $this->identifier_name = 'server'; + + parent::initPageHeaderToolbar(); + } } - - diff --git a/controllers/admin/AdminShippingController.php b/controllers/admin/AdminShippingController.php index 1ab8eef3..fd38703b 100644 --- a/controllers/admin/AdminShippingController.php +++ b/controllers/admin/AdminShippingController.php @@ -26,156 +26,157 @@ class AdminShippingControllerCore extends AdminController { - protected $_fieldsHandling; + protected $_fieldsHandling; - public function __construct() - { - $this->bootstrap = true; - parent::__construct(); - $this->table = 'delivery'; + public function __construct() + { + $this->bootstrap = true; + parent::__construct(); + $this->table = 'delivery'; - $carriers = Carrier::getCarriers($this->context->language->id, true, false, false, null, Carrier::PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE); - foreach ($carriers as $key => $carrier) - if ($carrier['is_free']) - unset($carriers[$key]); + $carriers = Carrier::getCarriers($this->context->language->id, true, false, false, null, Carrier::PS_CARRIERS_AND_CARRIER_MODULES_NEED_RANGE); + foreach ($carriers as $key => $carrier) { + if ($carrier['is_free']) { + unset($carriers[$key]); + } + } - $carrier_default_sort = array( - array('value' => Carrier::SORT_BY_PRICE, 'name' => $this->l('Price')), - array('value' => Carrier::SORT_BY_POSITION, 'name' => $this->l('Position')) - ); + $carrier_default_sort = array( + array('value' => Carrier::SORT_BY_PRICE, 'name' => $this->l('Price')), + array('value' => Carrier::SORT_BY_POSITION, 'name' => $this->l('Position')) + ); - $carrier_default_order = array( - array('value' => Carrier::SORT_BY_ASC, 'name' => $this->l('Ascending')), - array('value' => Carrier::SORT_BY_DESC, 'name' => $this->l('Descending')) - ); + $carrier_default_order = array( + array('value' => Carrier::SORT_BY_ASC, 'name' => $this->l('Ascending')), + array('value' => Carrier::SORT_BY_DESC, 'name' => $this->l('Descending')) + ); - $this->fields_options = array( - 'handling' => array( - 'title' => $this->l('Handling'), - 'icon' => 'delivery', - 'fields' => array( - 'PS_SHIPPING_HANDLING' => array( - 'title' => $this->l('Handling charges'), - 'suffix' => $this->context->currency->getSign().' '.$this->l('(tax excl.)'), - 'cast' => 'floatval', - 'type' => 'text', - 'validation' => 'isPrice'), - 'PS_SHIPPING_FREE_PRICE' => array( - 'title' => $this->l('Free shipping starts at'), - 'suffix' => $this->context->currency->getSign(), - 'cast' => 'floatval', - 'type' => 'text', - 'validation' => 'isPrice'), - 'PS_SHIPPING_FREE_WEIGHT' => array( - 'title' => $this->l('Free shipping starts at'), - 'suffix' => Configuration::get('PS_WEIGHT_UNIT'), - 'cast' => 'floatval', - 'type' => 'text', - 'validation' => 'isUnsignedFloat'), - ), - 'description' => - '<ul> + $this->fields_options = array( + 'handling' => array( + 'title' => $this->l('Handling'), + 'icon' => 'delivery', + 'fields' => array( + 'PS_SHIPPING_HANDLING' => array( + 'title' => $this->l('Handling charges'), + 'suffix' => $this->context->currency->getSign().' '.$this->l('(tax excl.)'), + 'cast' => 'floatval', + 'type' => 'text', + 'validation' => 'isPrice'), + 'PS_SHIPPING_FREE_PRICE' => array( + 'title' => $this->l('Free shipping starts at'), + 'suffix' => $this->context->currency->getSign(), + 'cast' => 'floatval', + 'type' => 'text', + 'validation' => 'isPrice'), + 'PS_SHIPPING_FREE_WEIGHT' => array( + 'title' => $this->l('Free shipping starts at'), + 'suffix' => Configuration::get('PS_WEIGHT_UNIT'), + 'cast' => 'floatval', + 'type' => 'text', + 'validation' => 'isUnsignedFloat'), + ), + 'description' => + '<ul> <li>'.$this->l('If you set these parameters to 0, they will be disabled.').'</li> <li>'.$this->l('Coupons are not taken into account when calculating free shipping.').'</li> </ul>', - 'submit' => array('title' => $this->l('Save')) - ), - 'general' => array( - 'title' => $this->l('Carrier options'), - 'fields' => array( - 'PS_CARRIER_DEFAULT' => array( - 'title' => $this->l('Default carrier'), - 'desc' => $this->l('Your shop\'s default carrier'), - 'cast' => 'intval', - 'type' => 'select', - 'identifier' => 'id_carrier', - 'list' => array_merge( - array( - -1 => array('id_carrier' => -1, 'name' => $this->l('Best price')), - -2 => array('id_carrier' => -2, 'name' => $this->l('Best grade')) - ), - Carrier::getCarriers((int)Configuration::get('PS_LANG_DEFAULT'), true, false, false, null, Carrier::ALL_CARRIERS)) - ), - 'PS_CARRIER_DEFAULT_SORT' => array( - 'title' => $this->l('Sort by'), - 'desc' => $this->l('This will only be visible in the front office.'), - 'cast' => 'intval', - 'type' => 'select', - 'identifier' => 'value', - 'list' => $carrier_default_sort - ), - 'PS_CARRIER_DEFAULT_ORDER' => array( - 'title' => $this->l('Order by'), - 'desc' => $this->l('This will only be visible in the front office.'), - 'cast' => 'intval', - 'type' => 'select', - 'identifier' => 'value', - 'list' => $carrier_default_order - ), - ), - 'submit' => array('title' => $this->l('Save')) - ) - ); - } + 'submit' => array('title' => $this->l('Save')) + ), + 'general' => array( + 'title' => $this->l('Carrier options'), + 'fields' => array( + 'PS_CARRIER_DEFAULT' => array( + 'title' => $this->l('Default carrier'), + 'desc' => $this->l('Your shop\'s default carrier'), + 'cast' => 'intval', + 'type' => 'select', + 'identifier' => 'id_carrier', + 'list' => array_merge( + array( + -1 => array('id_carrier' => -1, 'name' => $this->l('Best price')), + -2 => array('id_carrier' => -2, 'name' => $this->l('Best grade')) + ), + Carrier::getCarriers((int)Configuration::get('PS_LANG_DEFAULT'), true, false, false, null, Carrier::ALL_CARRIERS)) + ), + 'PS_CARRIER_DEFAULT_SORT' => array( + 'title' => $this->l('Sort by'), + 'desc' => $this->l('This will only be visible in the front office.'), + 'cast' => 'intval', + 'type' => 'select', + 'identifier' => 'value', + 'list' => $carrier_default_sort + ), + 'PS_CARRIER_DEFAULT_ORDER' => array( + 'title' => $this->l('Order by'), + 'desc' => $this->l('This will only be visible in the front office.'), + 'cast' => 'intval', + 'type' => 'select', + 'identifier' => 'value', + 'list' => $carrier_default_order + ), + ), + 'submit' => array('title' => $this->l('Save')) + ) + ); + } - public function postProcess() - { - /* Shipping fees */ - if (Tools::isSubmit('submitFees'.$this->table)) - { - if ($this->tabAccess['edit'] === '1') - { - if (($id_carrier = (int)(Tools::getValue('id_carrier'))) && $id_carrier == ($id_carrier2 = (int)(Tools::getValue('id_carrier2')))) - { - $carrier = new Carrier($id_carrier); - if (Validate::isLoadedObject($carrier)) - { - /* Get configuration values */ - $shipping_method = $carrier->getShippingMethod(); - $rangeTable = $carrier->getRangeTable(); + public function postProcess() + { + /* Shipping fees */ + if (Tools::isSubmit('submitFees'.$this->table)) { + if ($this->tabAccess['edit'] === '1') { + if (($id_carrier = (int)(Tools::getValue('id_carrier'))) && $id_carrier == ($id_carrier2 = (int)(Tools::getValue('id_carrier2')))) { + $carrier = new Carrier($id_carrier); + if (Validate::isLoadedObject($carrier)) { + /* Get configuration values */ + $shipping_method = $carrier->getShippingMethod(); + $rangeTable = $carrier->getRangeTable(); - $carrier->deleteDeliveryPrice($rangeTable); - $currentList = Carrier::getDeliveryPriceByRanges($rangeTable, $id_carrier); + $carrier->deleteDeliveryPrice($rangeTable); + $currentList = Carrier::getDeliveryPriceByRanges($rangeTable, $id_carrier); - /* Build prices list */ - $priceList = array(); - foreach ($_POST as $key => $value) - if (strstr($key, 'fees_')) - { - $tmpArray = explode('_', $key); + /* Build prices list */ + $priceList = array(); + foreach ($_POST as $key => $value) { + if (strstr($key, 'fees_')) { + $tmpArray = explode('_', $key); - $price = number_format(abs(str_replace(',', '.', $value)), 6, '.', ''); - $current = 0; - foreach ($currentList as $item) - if ($item['id_zone'] == $tmpArray[1] && $item['id_'.$rangeTable] == $tmpArray[2]) - $current = $item; - if ($current && $price == $current['price']) - continue; + $price = number_format(abs(str_replace(',', '.', $value)), 6, '.', ''); + $current = 0; + foreach ($currentList as $item) { + if ($item['id_zone'] == $tmpArray[1] && $item['id_'.$rangeTable] == $tmpArray[2]) { + $current = $item; + } + } + if ($current && $price == $current['price']) { + continue; + } - $priceList[] = array( - 'id_range_price' => ($shipping_method == Carrier::SHIPPING_METHOD_PRICE) ? (int)$tmpArray[2] : null, - 'id_range_weight' => ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) ? (int)$tmpArray[2] : null, - 'id_carrier' => (int)$carrier->id, - 'id_zone' => (int)$tmpArray[1], - 'price' => $price, - ); - } - /* Update delivery prices */ - $carrier->addDeliveryPrice($priceList); - Tools::redirectAdmin(self::$currentIndex.'&conf=6&id_carrier='.$carrier->id.'&token='.$this->token); - } - else - $this->errors[] = Tools::displayError('An error occurred while attempting to update fees (cannot load carrier object).'); - } - elseif (isset($id_carrier2)) - $_POST['id_carrier'] = $id_carrier2; - else - $this->errors[] = Tools::displayError('An error occurred while attempting to update fees (cannot load carrier object).'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - else - return parent::postProcess(); - } -} \ No newline at end of file + $priceList[] = array( + 'id_range_price' => ($shipping_method == Carrier::SHIPPING_METHOD_PRICE) ? (int)$tmpArray[2] : null, + 'id_range_weight' => ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) ? (int)$tmpArray[2] : null, + 'id_carrier' => (int)$carrier->id, + 'id_zone' => (int)$tmpArray[1], + 'price' => $price, + ); + } + } + /* Update delivery prices */ + $carrier->addDeliveryPrice($priceList); + Tools::redirectAdmin(self::$currentIndex.'&conf=6&id_carrier='.$carrier->id.'&token='.$this->token); + } else { + $this->errors[] = Tools::displayError('An error occurred while attempting to update fees (cannot load carrier object).'); + } + } elseif (isset($id_carrier2)) { + $_POST['id_carrier'] = $id_carrier2; + } else { + $this->errors[] = Tools::displayError('An error occurred while attempting to update fees (cannot load carrier object).'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } else { + return parent::postProcess(); + } + } +} diff --git a/controllers/admin/AdminShopController.php b/controllers/admin/AdminShopController.php index e37f08a7..694be50a 100644 --- a/controllers/admin/AdminShopController.php +++ b/controllers/admin/AdminShopController.php @@ -29,178 +29,180 @@ */ class AdminShopControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->context = Context::getContext(); - $this->table = 'shop'; - $this->className = 'Shop'; - $this->multishop_context = Shop::CONTEXT_ALL; - - $this->id_shop_group = (int)Tools::getValue('id_shop_group'); + public function __construct() + { + $this->bootstrap = true; + $this->context = Context::getContext(); + $this->table = 'shop'; + $this->className = 'Shop'; + $this->multishop_context = Shop::CONTEXT_ALL; + + $this->id_shop_group = (int)Tools::getValue('id_shop_group'); - /* if $_GET['id_shop'] is transmitted, virtual url can be loaded in config.php, so we wether transmit shop_id in herfs */ - if ($this->id_shop = (int)Tools::getValue('shop_id')) - $_GET['id_shop'] = $this->id_shop; + /* if $_GET['id_shop'] is transmitted, virtual url can be loaded in config.php, so we wether transmit shop_id in herfs */ + if ($this->id_shop = (int)Tools::getValue('shop_id')) { + $_GET['id_shop'] = $this->id_shop; + } - $this->list_skip_actions['delete'] = array((int)Configuration::get('PS_SHOP_DEFAULT')); - $this->fields_list = array( - 'id_shop' => array( - 'title' => $this->l('Shop ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Shop name'), - 'filter_key' => 'a!name', - 'width' => 200, - ), - 'shop_group_name' => array( - 'title' => $this->l('Shop group'), - 'width' => 150, - 'filter_key' => 'gs!name' - ), - 'category_name' => array( - 'title' => $this->l('Root category'), - 'width' => 150, - 'filter_key' => 'cl!name' - ), - 'url' => array( - 'title' => $this->l('Main URL for this shop'), - 'havingFilter' => 'url', - ), - /*'active' => array( - 'title' => $this->l('Enabled'), - 'align' => 'center', - 'active' => 'status', - 'type' => 'bool', - 'orderby' => false, - 'filter_key' => 'active', - 'width' => 50, - )*/ - ); + $this->list_skip_actions['delete'] = array((int)Configuration::get('PS_SHOP_DEFAULT')); + $this->fields_list = array( + 'id_shop' => array( + 'title' => $this->l('Shop ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Shop name'), + 'filter_key' => 'a!name', + 'width' => 200, + ), + 'shop_group_name' => array( + 'title' => $this->l('Shop group'), + 'width' => 150, + 'filter_key' => 'gs!name' + ), + 'category_name' => array( + 'title' => $this->l('Root category'), + 'width' => 150, + 'filter_key' => 'cl!name' + ), + 'url' => array( + 'title' => $this->l('Main URL for this shop'), + 'havingFilter' => 'url', + ), + /*'active' => array( + 'title' => $this->l('Enabled'), + 'align' => 'center', + 'active' => 'status', + 'type' => 'bool', + 'orderby' => false, + 'filter_key' => 'active', + 'width' => 50, + )*/ + ); - parent::__construct(); - } + parent::__construct(); + } - public function viewAccess($disable = false) - { - return Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE'); - } + public function viewAccess($disable = false) + { + return Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE'); + } - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); - if (!$this->display && $this->id_shop_group) - { - if ($this->id_object) - $this->loadObject(); + if (!$this->display && $this->id_shop_group) { + if ($this->id_object) { + $this->loadObject(); + } - if (!$this->id_shop_group && $this->object && $this->object->id_shop_group) - $this->id_shop_group = $this->object->id_shop_group; + if (!$this->id_shop_group && $this->object && $this->object->id_shop_group) { + $this->id_shop_group = $this->object->id_shop_group; + } - $this->page_header_toolbar_btn['edit'] = array( - 'desc' => $this->l('Edit this shop group'), - 'href' => $this->context->link->getAdminLink('AdminShopGroup').'&updateshop_group&id_shop_group=' - .$this->id_shop_group, - ); + $this->page_header_toolbar_btn['edit'] = array( + 'desc' => $this->l('Edit this shop group'), + 'href' => $this->context->link->getAdminLink('AdminShopGroup').'&updateshop_group&id_shop_group=' + .$this->id_shop_group, + ); - $this->page_header_toolbar_btn['new'] = array( - 'desc' => $this->l('Add new shop'), - 'href' => $this->context->link->getAdminLink('AdminShop').'&add'.$this->table.'&id_shop_group=' - .$this->id_shop_group, - ); - } - } + $this->page_header_toolbar_btn['new'] = array( + 'desc' => $this->l('Add new shop'), + 'href' => $this->context->link->getAdminLink('AdminShop').'&add'.$this->table.'&id_shop_group=' + .$this->id_shop_group, + ); + } + } - public function initToolbar() - { - parent::initToolbar(); + public function initToolbar() + { + parent::initToolbar(); - if ($this->display != 'edit' && $this->display != 'add') - { - if ($this->id_object) - $this->loadObject(); + if ($this->display != 'edit' && $this->display != 'add') { + if ($this->id_object) { + $this->loadObject(); + } - if (!$this->id_shop_group && $this->object && $this->object->id_shop_group) - $this->id_shop_group = $this->object->id_shop_group; + if (!$this->id_shop_group && $this->object && $this->object->id_shop_group) { + $this->id_shop_group = $this->object->id_shop_group; + } - $this->toolbar_btn['new'] = array( - 'desc' => $this->l('Add new shop'), - 'href' => $this->context->link->getAdminLink('AdminShop').'&add'.$this->table.'&id_shop_group=' - .$this->id_shop_group, - ); - } - } + $this->toolbar_btn['new'] = array( + 'desc' => $this->l('Add new shop'), + 'href' => $this->context->link->getAdminLink('AdminShop').'&add'.$this->table.'&id_shop_group=' + .$this->id_shop_group, + ); + } + } - public function initContent() - { - parent::initContent(); + public function initContent() + { + parent::initContent(); - $this->addJqueryPlugin('cooki-plugin'); - $data = Shop::getTree(); + $this->addJqueryPlugin('cooki-plugin'); + $data = Shop::getTree(); - foreach ($data as $key_group => &$group) - foreach ($group['shops'] as $key_shop => &$shop) - { - $current_shop = new Shop($shop['id_shop']); - $urls = $current_shop->getUrls(); + foreach ($data as $key_group => &$group) { + foreach ($group['shops'] as $key_shop => &$shop) { + $current_shop = new Shop($shop['id_shop']); + $urls = $current_shop->getUrls(); - foreach ($urls as $key_url => &$url) - { - $title = $url['domain'].$url['physical_uri'].$url['virtual_uri']; - if (strlen($title) > 23) - $title = substr($title, 0, 23).'...'; + foreach ($urls as $key_url => &$url) { + $title = $url['domain'].$url['physical_uri'].$url['virtual_uri']; + if (strlen($title) > 23) { + $title = substr($title, 0, 23).'...'; + } - $url['name'] = $title; - $shop['urls'][$url['id_shop_url']] = $url; - } - } + $url['name'] = $title; + $shop['urls'][$url['id_shop_url']] = $url; + } + } + } - $shops_tree = new HelperTreeShops('shops-tree', $this->l('Multistore tree')); - $shops_tree->setNodeFolderTemplate('shop_tree_node_folder.tpl')->setNodeItemTemplate('shop_tree_node_item.tpl') - ->setHeaderTemplate('shop_tree_header.tpl')->setActions(array( - new TreeToolbarLink( - 'Collapse All', - '#', - '$(\'#'.$shops_tree->getId().'\').tree(\'collapseAll\'); return false;', - 'icon-collapse-alt'), - new TreeToolbarLink( - 'Expand All', - '#', - '$(\'#'.$shops_tree->getId().'\').tree(\'expandAll\'); return false;', - 'icon-expand-alt') - )) - ->setAttribute('url_shop_group', $this->context->link->getAdminLink('AdminShopGroup')) - ->setAttribute('url_shop', $this->context->link->getAdminLink('AdminShop')) - ->setAttribute('url_shop_url', $this->context->link->getAdminLink('AdminShopUrl')) - ->setData($data); - $shops_tree = $shops_tree->render(null, false, false); + $shops_tree = new HelperTreeShops('shops-tree', $this->l('Multistore tree')); + $shops_tree->setNodeFolderTemplate('shop_tree_node_folder.tpl')->setNodeItemTemplate('shop_tree_node_item.tpl') + ->setHeaderTemplate('shop_tree_header.tpl')->setActions(array( + new TreeToolbarLink( + 'Collapse All', + '#', + '$(\'#'.$shops_tree->getId().'\').tree(\'collapseAll\'); return false;', + 'icon-collapse-alt'), + new TreeToolbarLink( + 'Expand All', + '#', + '$(\'#'.$shops_tree->getId().'\').tree(\'expandAll\'); return false;', + 'icon-expand-alt') + )) + ->setAttribute('url_shop_group', $this->context->link->getAdminLink('AdminShopGroup')) + ->setAttribute('url_shop', $this->context->link->getAdminLink('AdminShop')) + ->setAttribute('url_shop_url', $this->context->link->getAdminLink('AdminShopUrl')) + ->setData($data); + $shops_tree = $shops_tree->render(null, false, false); - if ($this->display == 'edit') - $this->toolbar_title[] = $this->object->name; - elseif (!$this->display && $this->id_shop_group) - { - $group = new ShopGroup($this->id_shop_group); - $this->toolbar_title[] = $group->name; - } + if ($this->display == 'edit') { + $this->toolbar_title[] = $this->object->name; + } elseif (!$this->display && $this->id_shop_group) { + $group = new ShopGroup($this->id_shop_group); + $this->toolbar_title[] = $group->name; + } - $this->context->smarty->assign(array( - 'toolbar_scroll' => 1, - 'toolbar_btn' => $this->toolbar_btn, - 'title' => $this->toolbar_title, - 'shops_tree' => $shops_tree - )); - } + $this->context->smarty->assign(array( + 'toolbar_scroll' => 1, + 'toolbar_btn' => $this->toolbar_btn, + 'title' => $this->toolbar_title, + 'shops_tree' => $shops_tree + )); + } - public function renderList() - { - $this->addRowAction('edit'); - $this->addRowAction('delete'); + public function renderList() + { + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->_select = 'gs.name shop_group_name, cl.name category_name, CONCAT(\'http://\', su.domain, su.physical_uri, su.virtual_uri) AS url'; - $this->_join = ' + $this->_select = 'gs.name shop_group_name, cl.name category_name, CONCAT(\'http://\', su.domain, su.physical_uri, su.virtual_uri) AS url'; + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'shop_group` gs ON (a.id_shop_group = gs.id_shop_group) LEFT JOIN `'._DB_PREFIX_.'category_lang` cl @@ -208,639 +210,656 @@ class AdminShopControllerCore extends AdminController LEFT JOIN '._DB_PREFIX_.'shop_url su ON a.id_shop = su.id_shop AND su.main = 1 '; - $this->_group = 'GROUP BY a.id_shop'; + $this->_group = 'GROUP BY a.id_shop'; - if ($id_shop_group = (int)Tools::getValue('id_shop_group')) - $this->_where = 'AND a.id_shop_group = '.$id_shop_group; + if ($id_shop_group = (int)Tools::getValue('id_shop_group')) { + $this->_where = 'AND a.id_shop_group = '.$id_shop_group; + } - return parent::renderList(); - } + return parent::renderList(); + } - public function displayAjaxGetCategoriesFromRootCategory() - { - if (Tools::isSubmit('id_category')) - { - $selected_cat = array((int)Tools::getValue('id_category')); - $children = Category::getChildren((int)Tools::getValue('id_category'), $this->context->language->id); - foreach ($children as $child) - $selected_cat[] = $child['id_category']; + public function displayAjaxGetCategoriesFromRootCategory() + { + if (Tools::isSubmit('id_category')) { + $selected_cat = array((int)Tools::getValue('id_category')); + $children = Category::getChildren((int)Tools::getValue('id_category'), $this->context->language->id); + foreach ($children as $child) { + $selected_cat[] = $child['id_category']; + } - $helper = new HelperTreeCategories('categories-tree', null, (int)Tools::getValue('id_category'), null, false); - $this->content = $helper->setSelectedCategories($selected_cat)->setUseSearch(true)->setUseCheckBox(true) - ->render(); - } - parent::displayAjax(); - } + $helper = new HelperTreeCategories('categories-tree', null, (int)Tools::getValue('id_category'), null, false); + $this->content = $helper->setSelectedCategories($selected_cat)->setUseSearch(true)->setUseCheckBox(true) + ->render(); + } + parent::displayAjax(); + } - public function postProcess() - { - if (Tools::isSubmit('id_category_default')) - $_POST['id_category'] = Tools::getValue('id_category_default'); - /*if ((Tools::isSubmit('status') || - Tools::isSubmit('status'.$this->table) || - (Tools::isSubmit('submitAdd'.$this->table) && Tools::getValue($this->identifier) && !Tools::getValue('active'))) && - $this->loadObject() && $this->loadObject()->active) - { - if (Tools::getValue('id_shop') == Configuration::get('PS_SHOP_DEFAULT')) - $this->errors[] = Tools::displayError('You cannot disable the default shop.'); - elseif (Shop::getTotalShops() == 1) - $this->errors[] = Tools::displayError('You cannot disable the last shop.'); - }*/ - - if (Tools::isSubmit('submitAddshopAndStay') || Tools::isSubmit('submitAddshop')) - { - $shop_group = new ShopGroup((int)Tools::getValue('id_shop_group')); - if ($shop_group->shopNameExists(Tools::getValue('name'), (int)Tools::getValue('id_shop'))) - $this->errors[] = Tools::displayError('You cannot have two shops with the same name in the same group.'); - } + public function postProcess() + { + if (Tools::isSubmit('id_category_default')) { + $_POST['id_category'] = Tools::getValue('id_category_default'); + } + /*if ((Tools::isSubmit('status') || + Tools::isSubmit('status'.$this->table) || + (Tools::isSubmit('submitAdd'.$this->table) && Tools::getValue($this->identifier) && !Tools::getValue('active'))) && + $this->loadObject() && $this->loadObject()->active) + { + if (Tools::getValue('id_shop') == Configuration::get('PS_SHOP_DEFAULT')) + $this->errors[] = Tools::displayError('You cannot disable the default shop.'); + elseif (Shop::getTotalShops() == 1) + $this->errors[] = Tools::displayError('You cannot disable the last shop.'); + }*/ + + if (Tools::isSubmit('submitAddshopAndStay') || Tools::isSubmit('submitAddshop')) { + $shop_group = new ShopGroup((int)Tools::getValue('id_shop_group')); + if ($shop_group->shopNameExists(Tools::getValue('name'), (int)Tools::getValue('id_shop'))) { + $this->errors[] = Tools::displayError('You cannot have two shops with the same name in the same group.'); + } + } - if (count($this->errors)) - return false; + if (count($this->errors)) { + return false; + } - /** @var Shop|bool $result */ - $result = parent::postProcess(); + /** @var Shop|bool $result */ + $result = parent::postProcess(); - if ($result != false && (Tools::isSubmit('submitAddshopAndStay') || Tools::isSubmit('submitAddshop')) && (int)$result->id_category != (int)Configuration::get('PS_HOME_CATEGORY', null, null, (int)$result->id)) - Configuration::updateValue('PS_HOME_CATEGORY', (int)$result->id_category, false, null, (int)$result->id); + if ($result != false && (Tools::isSubmit('submitAddshopAndStay') || Tools::isSubmit('submitAddshop')) && (int)$result->id_category != (int)Configuration::get('PS_HOME_CATEGORY', null, null, (int)$result->id)) { + Configuration::updateValue('PS_HOME_CATEGORY', (int)$result->id_category, false, null, (int)$result->id); + } - if ($this->redirect_after) - $this->redirect_after .= '&id_shop_group='.$this->id_shop_group; + if ($this->redirect_after) { + $this->redirect_after .= '&id_shop_group='.$this->id_shop_group; + } - return $result; - } + return $result; + } - public function processDelete() - { - if (!Validate::isLoadedObject($object = $this->loadObject())) - $this->errors[] = Tools::displayError('Unable to load this shop.'); - elseif (!Shop::hasDependency($object->id)) - { - $result = Category::deleteCategoriesFromShop($object->id) && parent::processDelete(); - Tools::generateHtaccess(); - return $result; - } - else - $this->errors[] = Tools::displayError('You can\'t delete this shop (customer and/or order dependency).'); + public function processDelete() + { + if (!Validate::isLoadedObject($object = $this->loadObject())) { + $this->errors[] = Tools::displayError('Unable to load this shop.'); + } elseif (!Shop::hasDependency($object->id)) { + $result = Category::deleteCategoriesFromShop($object->id) && parent::processDelete(); + Tools::generateHtaccess(); + return $result; + } else { + $this->errors[] = Tools::displayError('You can\'t delete this shop (customer and/or order dependency).'); + } - return false; - } + return false; + } - /** - * @param Shop $new_shop - * @return bool - */ - protected function afterAdd($new_shop) - { - $import_data = Tools::getValue('importData', array()); + /** + * @param Shop $new_shop + * @return bool + */ + protected function afterAdd($new_shop) + { + $import_data = Tools::getValue('importData', array()); - // The root category should be at least imported - $new_shop->copyShopData((int)Tools::getValue('importFromShop'), $import_data); + // The root category should be at least imported + $new_shop->copyShopData((int)Tools::getValue('importFromShop'), $import_data); - // copy default data - if (!Tools::getValue('useImportData') || (is_array($import_data) && !isset($import_data['group']))) - { - $sql = 'INSERT INTO `'._DB_PREFIX_.'group_shop` (`id_shop`, `id_group`) + // copy default data + if (!Tools::getValue('useImportData') || (is_array($import_data) && !isset($import_data['group']))) { + $sql = 'INSERT INTO `'._DB_PREFIX_.'group_shop` (`id_shop`, `id_group`) VALUES ('.(int)$new_shop->id.', '.(int)Configuration::get('PS_UNIDENTIFIED_GROUP').'), ('.(int)$new_shop->id.', '.(int)Configuration::get('PS_GUEST_GROUP').'), ('.(int)$new_shop->id.', '.(int)Configuration::get('PS_CUSTOMER_GROUP').') '; - Db::getInstance()->execute($sql); - } + Db::getInstance()->execute($sql); + } - return parent::afterAdd($new_shop); - } + return parent::afterAdd($new_shop); + } - /** - * @param Shop $new_shop - * @return bool - */ - protected function afterUpdate($new_shop) - { - $categories = Tools::getValue('categoryBox'); + /** + * @param Shop $new_shop + * @return bool + */ + protected function afterUpdate($new_shop) + { + $categories = Tools::getValue('categoryBox'); - if (!is_array($categories)) - { - $this->errors[] = $this->l('Please create some sub-categories for this root category.'); - return false; - } + if (!is_array($categories)) { + $this->errors[] = $this->l('Please create some sub-categories for this root category.'); + return false; + } - array_unshift($categories, Configuration::get('PS_ROOT_CATEGORY')); + array_unshift($categories, Configuration::get('PS_ROOT_CATEGORY')); - if (!Category::updateFromShop($categories, $new_shop->id)) - $this->errors[] = $this->l('You need to select at least the root category.'); - if (Tools::getValue('useImportData') && ($import_data = Tools::getValue('importData')) && is_array($import_data)) - $new_shop->copyShopData((int)Tools::getValue('importFromShop'), $import_data); + if (!Category::updateFromShop($categories, $new_shop->id)) { + $this->errors[] = $this->l('You need to select at least the root category.'); + } + if (Tools::getValue('useImportData') && ($import_data = Tools::getValue('importData')) && is_array($import_data)) { + $new_shop->copyShopData((int)Tools::getValue('importFromShop'), $import_data); + } - if (Tools::isSubmit('submitAddshopAndStay') || Tools::isSubmit('submitAddshop')) - $this->redirect_after = self::$currentIndex.'&shop_id='.(int)$new_shop->id.'&conf=4&token='.$this->token; + if (Tools::isSubmit('submitAddshopAndStay') || Tools::isSubmit('submitAddshop')) { + $this->redirect_after = self::$currentIndex.'&shop_id='.(int)$new_shop->id.'&conf=4&token='.$this->token; + } - return parent::afterUpdate($new_shop); - } + return parent::afterUpdate($new_shop); + } - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - if (Shop::getContext() == Shop::CONTEXT_GROUP) - $this->_where .= ' AND a.id_shop_group = '.(int)Shop::getContextShopGroupID(); + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + if (Shop::getContext() == Shop::CONTEXT_GROUP) { + $this->_where .= ' AND a.id_shop_group = '.(int)Shop::getContextShopGroupID(); + } - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - $shop_delete_list = array(); + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + $shop_delete_list = array(); - // don't allow to remove shop which have dependencies (customers / orders / ... ) - foreach ($this->_list as &$shop) - { - if (Shop::hasDependency($shop['id_shop'])) - $shop_delete_list[] = $shop['id_shop']; - } - $this->context->smarty->assign('shops_having_dependencies', $shop_delete_list); - } + // don't allow to remove shop which have dependencies (customers / orders / ... ) + foreach ($this->_list as &$shop) { + if (Shop::hasDependency($shop['id_shop'])) { + $shop_delete_list[] = $shop['id_shop']; + } + } + $this->context->smarty->assign('shops_having_dependencies', $shop_delete_list); + } - public function renderForm() - { - /** @var Shop $obj */ - if (!($obj = $this->loadObject(true))) - return; + public function renderForm() + { + /** @var Shop $obj */ + if (!($obj = $this->loadObject(true))) { + return; + } - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Shop'), - 'icon' => 'icon-shopping-cart' - ), - 'identifier' => 'shop_id', - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Shop name'), - 'desc' => array($this->l('This field does not refer to the shop name visible in the front office.'), - sprintf($this->l('Follow %sthis link%s to edit the shop name used on the front office.'), '<a href="'.$this->context->link->getAdminLink('AdminStores').'#store_fieldset_general">', '</a>')), - 'name' => 'name', - 'required' => true, - ) - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Shop'), + 'icon' => 'icon-shopping-cart' + ), + 'identifier' => 'shop_id', + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Shop name'), + 'desc' => array($this->l('This field does not refer to the shop name visible in the front office.'), + sprintf($this->l('Follow %sthis link%s to edit the shop name used on the front office.'), '<a href="'.$this->context->link->getAdminLink('AdminStores').'#store_fieldset_general">', '</a>')), + 'name' => 'name', + 'required' => true, + ) + ) + ); - $display_group_list = true; - if ($this->display == 'edit') - { - $group = new ShopGroup($obj->id_shop_group); - if ($group->share_customer || $group->share_order || $group->share_stock) - $display_group_list = false; - } + $display_group_list = true; + if ($this->display == 'edit') { + $group = new ShopGroup($obj->id_shop_group); + if ($group->share_customer || $group->share_order || $group->share_stock) { + $display_group_list = false; + } + } - if ($display_group_list) - { - $options = array(); - foreach (ShopGroup::getShopGroups() as $group) - { - /** @var ShopGroup $group */ - if ($this->display == 'edit' && ($group->share_customer || $group->share_order || $group->share_stock) && ShopGroup::hasDependency($group->id)) - continue; + if ($display_group_list) { + $options = array(); + foreach (ShopGroup::getShopGroups() as $group) { + /** @var ShopGroup $group */ + if ($this->display == 'edit' && ($group->share_customer || $group->share_order || $group->share_stock) && ShopGroup::hasDependency($group->id)) { + continue; + } - $options[] = array( - 'id_shop_group' => $group->id, - 'name' => $group->name, - ); - } + $options[] = array( + 'id_shop_group' => $group->id, + 'name' => $group->name, + ); + } - if ($this->display == 'add') - $group_desc = $this->l('Warning: You won\'t be able to change the group of this shop if this shop belongs to a group with one of these options activated: Share Customers, Share Quantities or Share Orders.'); - else - $group_desc = $this->l('You can only move your shop to a shop group with all "share" options disabled -- or to a shop group with no customers/orders.'); + if ($this->display == 'add') { + $group_desc = $this->l('Warning: You won\'t be able to change the group of this shop if this shop belongs to a group with one of these options activated: Share Customers, Share Quantities or Share Orders.'); + } else { + $group_desc = $this->l('You can only move your shop to a shop group with all "share" options disabled -- or to a shop group with no customers/orders.'); + } - $this->fields_form['input'][] = array( - 'type' => 'select', - 'label' => $this->l('Shop group'), - 'desc' => $group_desc, - 'name' => 'id_shop_group', - 'options' => array( - 'query' => $options, - 'id' => 'id_shop_group', - 'name' => 'name', - ), - ); - } - else - { - $this->fields_form['input'][] = array( - 'type' => 'hidden', - 'name' => 'id_shop_group', - 'default' => $group->name - ); - $this->fields_form['input'][] = array( - 'type' => 'textShopGroup', - 'label' => $this->l('Shop group'), - 'desc' => $this->l('You can\'t edit the shop group because the current shop belongs to a group with the "share" option enabled.'), - 'name' => 'id_shop_group', - 'value' => $group->name - ); - } + $this->fields_form['input'][] = array( + 'type' => 'select', + 'label' => $this->l('Shop group'), + 'desc' => $group_desc, + 'name' => 'id_shop_group', + 'options' => array( + 'query' => $options, + 'id' => 'id_shop_group', + 'name' => 'name', + ), + ); + } else { + $this->fields_form['input'][] = array( + 'type' => 'hidden', + 'name' => 'id_shop_group', + 'default' => $group->name + ); + $this->fields_form['input'][] = array( + 'type' => 'textShopGroup', + 'label' => $this->l('Shop group'), + 'desc' => $this->l('You can\'t edit the shop group because the current shop belongs to a group with the "share" option enabled.'), + 'name' => 'id_shop_group', + 'value' => $group->name + ); + } - $categories = Category::getRootCategories($this->context->language->id); - $this->fields_form['input'][] = array( - 'type' => 'select', - 'label' => $this->l('Category root'), - 'desc' => sprintf($this->l('This is the root category of the store that you\'ve created. To define a new root category for your store, %splease click here%s.'), '<a href="'.$this->context->link->getAdminLink('AdminCategories').'&addcategoryroot" target="_blank">', '</a>'), - 'name' => 'id_category', - 'options' => array( - 'query' => $categories, - 'id' => 'id_category', - 'name' => 'name' - ) - ); + $categories = Category::getRootCategories($this->context->language->id); + $this->fields_form['input'][] = array( + 'type' => 'select', + 'label' => $this->l('Category root'), + 'desc' => sprintf($this->l('This is the root category of the store that you\'ve created. To define a new root category for your store, %splease click here%s.'), '<a href="'.$this->context->link->getAdminLink('AdminCategories').'&addcategoryroot" target="_blank">', '</a>'), + 'name' => 'id_category', + 'options' => array( + 'query' => $categories, + 'id' => 'id_category', + 'name' => 'name' + ) + ); - if (Tools::isSubmit('id_shop')) - { - $shop = new Shop((int)Tools::getValue('id_shop')); - $id_root = $shop->id_category; - } - else - $id_root = $categories[0]['id_category']; + if (Tools::isSubmit('id_shop')) { + $shop = new Shop((int)Tools::getValue('id_shop')); + $id_root = $shop->id_category; + } else { + $id_root = $categories[0]['id_category']; + } - $id_shop = (int)Tools::getValue('id_shop'); - self::$currentIndex = self::$currentIndex.'&id_shop_group='.(int)(Tools::getValue('id_shop_group') ? - Tools::getValue('id_shop_group') : (isset($obj->id_shop_group) ? $obj->id_shop_group : Shop::getContextShopGroupID())); - $shop = new Shop($id_shop); - $selected_cat = Shop::getCategories($id_shop); + $id_shop = (int)Tools::getValue('id_shop'); + self::$currentIndex = self::$currentIndex.'&id_shop_group='.(int)(Tools::getValue('id_shop_group') ? + Tools::getValue('id_shop_group') : (isset($obj->id_shop_group) ? $obj->id_shop_group : Shop::getContextShopGroupID())); + $shop = new Shop($id_shop); + $selected_cat = Shop::getCategories($id_shop); - if (empty($selected_cat)) - { - // get first category root and preselect all these children - $root_categories = Category::getRootCategories(); - $root_category = new Category($root_categories[0]['id_category']); - $children = $root_category->getAllChildren($this->context->language->id); - $selected_cat[] = $root_categories[0]['id_category']; - - foreach ($children as $child) - $selected_cat[] = $child->id; - } + if (empty($selected_cat)) { + // get first category root and preselect all these children + $root_categories = Category::getRootCategories(); + $root_category = new Category($root_categories[0]['id_category']); + $children = $root_category->getAllChildren($this->context->language->id); + $selected_cat[] = $root_categories[0]['id_category']; + + foreach ($children as $child) { + $selected_cat[] = $child->id; + } + } - if (Shop::getContext() == Shop::CONTEXT_SHOP && Tools::isSubmit('id_shop')) - $root_category = new Category($shop->id_category); - else - $root_category = new Category($id_root); + if (Shop::getContext() == Shop::CONTEXT_SHOP && Tools::isSubmit('id_shop')) { + $root_category = new Category($shop->id_category); + } else { + $root_category = new Category($id_root); + } - $this->fields_form['input'][] = array( - 'type' => 'categories', - 'name' => 'categoryBox', - 'label' => $this->l('Associated categories'), - 'tree' => array( - 'id' => 'categories-tree', - 'selected_categories' => $selected_cat, - 'root_category' => $root_category->id, - 'use_search' => true, - 'use_checkbox' => true - ), - 'desc' => $this->l('By selecting associated categories, you are choosing to share the categories between shops. Once associated between shops, any alteration of this category will impact every shop.') - ); - /*$this->fields_form['input'][] = array( - 'type' => 'switch', - 'label' => $this->l('Enabled'), - 'name' => 'active', - 'required' => true, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1 - ), - array( - 'id' => 'active_off', - 'value' => 0 - ) - ), - 'desc' => $this->l('Enable or disable your store?') - );*/ + $this->fields_form['input'][] = array( + 'type' => 'categories', + 'name' => 'categoryBox', + 'label' => $this->l('Associated categories'), + 'tree' => array( + 'id' => 'categories-tree', + 'selected_categories' => $selected_cat, + 'root_category' => $root_category->id, + 'use_search' => true, + 'use_checkbox' => true + ), + 'desc' => $this->l('By selecting associated categories, you are choosing to share the categories between shops. Once associated between shops, any alteration of this category will impact every shop.') + ); + /*$this->fields_form['input'][] = array( + 'type' => 'switch', + 'label' => $this->l('Enabled'), + 'name' => 'active', + 'required' => true, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1 + ), + array( + 'id' => 'active_off', + 'value' => 0 + ) + ), + 'desc' => $this->l('Enable or disable your store?') + );*/ - $themes = Theme::getThemes(); - if (!isset($obj->id_theme)) - foreach ($themes as $theme) - if (isset($theme->id)) - { - $id_theme = $theme->id; - break; - } + $themes = Theme::getThemes(); + if (!isset($obj->id_theme)) { + foreach ($themes as $theme) { + if (isset($theme->id)) { + $id_theme = $theme->id; + break; + } + } + } - $this->fields_form['input'][] = array( - 'type' => 'theme', - 'label' => $this->l('Theme'), - 'name' => 'theme', - 'values' => $themes - ); + $this->fields_form['input'][] = array( + 'type' => 'theme', + 'label' => $this->l('Theme'), + 'name' => 'theme', + 'values' => $themes + ); - $this->fields_form['submit'] = array( - 'title' => $this->l('Save'), - ); + $this->fields_form['submit'] = array( + 'title' => $this->l('Save'), + ); - if (Shop::getTotalShops() > 1 && $obj->id) - $disabled = array('active' => false); - else - $disabled = false; + if (Shop::getTotalShops() > 1 && $obj->id) { + $disabled = array('active' => false); + } else { + $disabled = false; + } - $import_data = array( - 'carrier' => $this->l('Carriers'), - 'cms' => $this->l('CMS pages'), - 'contact' => $this->l('Contact information'), - 'country' => $this->l('Countries'), - 'currency' => $this->l('Currencies'), - 'discount' => $this->l('Discount prices'), - 'employee' => $this->l('Employees'), - 'image' => $this->l('Images'), - 'lang' => $this->l('Languages'), - 'manufacturer' => $this->l('Manufacturers'), - 'module' => $this->l('Modules'), - 'hook_module' => $this->l('Module hooks'), - 'meta_lang' => $this->l('Meta information'), - 'product' => $this->l('Products'), - 'product_attribute' => $this->l('Product combinations'), - 'scene' => $this->l('Scenes'), - 'stock_available' => $this->l('Available quantities for sale'), - 'store' => $this->l('Stores'), - 'warehouse' => $this->l('Warehouses'), - 'webservice_account' => $this->l('Webservice accounts'), - 'attribute_group' => $this->l('Attribute groups'), - 'feature' => $this->l('Features'), - 'group' => $this->l('Customer groups'), - 'tax_rules_group' => $this->l('Tax rules groups'), - 'supplier' => $this->l('Suppliers'), - 'referrer' => $this->l('Referrers/affiliates'), - 'zone' => $this->l('Zones'), - 'cart_rule' => $this->l('Cart rules'), - ); - - // Hook for duplication of shop data - $modules_list = Hook::getHookModuleExecList('actionShopDataDuplication'); - if (is_array($modules_list) && count($modules_list) > 0) - foreach ($modules_list as $m) - $import_data['Module'.ucfirst($m['module'])] = Module::getModuleName($m['module']); + $import_data = array( + 'carrier' => $this->l('Carriers'), + 'cms' => $this->l('CMS pages'), + 'contact' => $this->l('Contact information'), + 'country' => $this->l('Countries'), + 'currency' => $this->l('Currencies'), + 'discount' => $this->l('Discount prices'), + 'employee' => $this->l('Employees'), + 'image' => $this->l('Images'), + 'lang' => $this->l('Languages'), + 'manufacturer' => $this->l('Manufacturers'), + 'module' => $this->l('Modules'), + 'hook_module' => $this->l('Module hooks'), + 'meta_lang' => $this->l('Meta information'), + 'product' => $this->l('Products'), + 'product_attribute' => $this->l('Product combinations'), + 'scene' => $this->l('Scenes'), + 'stock_available' => $this->l('Available quantities for sale'), + 'store' => $this->l('Stores'), + 'warehouse' => $this->l('Warehouses'), + 'webservice_account' => $this->l('Webservice accounts'), + 'attribute_group' => $this->l('Attribute groups'), + 'feature' => $this->l('Features'), + 'group' => $this->l('Customer groups'), + 'tax_rules_group' => $this->l('Tax rules groups'), + 'supplier' => $this->l('Suppliers'), + 'referrer' => $this->l('Referrers/affiliates'), + 'zone' => $this->l('Zones'), + 'cart_rule' => $this->l('Cart rules'), + ); + + // Hook for duplication of shop data + $modules_list = Hook::getHookModuleExecList('actionShopDataDuplication'); + if (is_array($modules_list) && count($modules_list) > 0) { + foreach ($modules_list as $m) { + $import_data['Module'.ucfirst($m['module'])] = Module::getModuleName($m['module']); + } + } - asort($import_data); - - if (!$this->object->id) - $this->fields_import_form = array( - 'radio' => array( - 'type' => 'radio', - 'label' => $this->l('Import data'), - 'name' => 'useImportData', - 'value' => 1 - ), - 'select' => array( - 'type' => 'select', - 'name' => 'importFromShop', - 'label' => $this->l('Choose the source shop'), - 'options' => array( - 'query' => Shop::getShops(false), - 'name' => 'name' - ) - ), - 'allcheckbox' => array( - 'type' => 'checkbox', - 'label' => $this->l('Choose data to import'), - 'values' => $import_data - ), - 'desc' => $this->l('Use this option to associate data (products, modules, etc.) the same way for each selected shop.') - ); + asort($import_data); + + if (!$this->object->id) { + $this->fields_import_form = array( + 'radio' => array( + 'type' => 'radio', + 'label' => $this->l('Import data'), + 'name' => 'useImportData', + 'value' => 1 + ), + 'select' => array( + 'type' => 'select', + 'name' => 'importFromShop', + 'label' => $this->l('Choose the source shop'), + 'options' => array( + 'query' => Shop::getShops(false), + 'name' => 'name' + ) + ), + 'allcheckbox' => array( + 'type' => 'checkbox', + 'label' => $this->l('Choose data to import'), + 'values' => $import_data + ), + 'desc' => $this->l('Use this option to associate data (products, modules, etc.) the same way for each selected shop.') + ); + } - $this->fields_value = array( + $this->fields_value = array( 'id_shop_group' => (Tools::getValue('id_shop_group') ? Tools::getValue('id_shop_group') : (isset($obj->id_shop_group)) ? $obj->id_shop_group : Shop::getContextShopGroupID()), 'id_category' => (Tools::getValue('id_category') ? Tools::getValue('id_category') : (isset($obj->id_category)) ? $obj->id_category : (int)Configuration::get('PS_HOME_CATEGORY')), - 'id_theme_checked' => (isset($obj->id_theme) ? $obj->id_theme : $id_theme) - ); + 'id_theme_checked' => (isset($obj->id_theme) ? $obj->id_theme : $id_theme) + ); - $ids_category = array(); - $shops = Shop::getShops(false); - foreach ($shops as $shop) - $ids_category[$shop['id_shop']] = $shop['id_category']; + $ids_category = array(); + $shops = Shop::getShops(false); + foreach ($shops as $shop) { + $ids_category[$shop['id_shop']] = $shop['id_category']; + } - $this->tpl_form_vars = array( - 'disabled' => $disabled, - 'checked' => (Tools::getValue('addshop') !== false) ? true : false, - 'defaultShop' => (int)Configuration::get('PS_SHOP_DEFAULT'), - 'ids_category' => $ids_category, - ); - if (isset($this->fields_import_form)) - $this->tpl_form_vars = array_merge($this->tpl_form_vars, array('form_import' => $this->fields_import_form)); + $this->tpl_form_vars = array( + 'disabled' => $disabled, + 'checked' => (Tools::getValue('addshop') !== false) ? true : false, + 'defaultShop' => (int)Configuration::get('PS_SHOP_DEFAULT'), + 'ids_category' => $ids_category, + ); + if (isset($this->fields_import_form)) { + $this->tpl_form_vars = array_merge($this->tpl_form_vars, array('form_import' => $this->fields_import_form)); + } - return parent::renderForm(); - } + return parent::renderForm(); + } - /** - * Object creation - */ - public function processAdd() - { - if (!Tools::getValue('categoryBox') || !in_array(Tools::getValue('id_category'), Tools::getValue('categoryBox'))) - $this->errors[] = $this->l('You need to select at least the root category.'); + /** + * Object creation + */ + public function processAdd() + { + if (!Tools::getValue('categoryBox') || !in_array(Tools::getValue('id_category'), Tools::getValue('categoryBox'))) { + $this->errors[] = $this->l('You need to select at least the root category.'); + } - if (Tools::isSubmit('id_category_default')) - $_POST['id_category'] = (int)Tools::getValue('id_category_default'); - - /* Checking fields validity */ - $this->validateRules(); + if (Tools::isSubmit('id_category_default')) { + $_POST['id_category'] = (int)Tools::getValue('id_category_default'); + } + + /* Checking fields validity */ + $this->validateRules(); - if (!count($this->errors)) - { - /** @var Shop $object */ - $object = new $this->className(); - $this->copyFromPost($object, $this->table); - $this->beforeAdd($object); - if (!$object->add()) - { - $this->errors[] = Tools::displayError('An error occurred while creating an object.'). - ' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>'; - } - /* voluntary do affectation here */ - elseif (($_POST[$this->identifier] = $object->id) && $this->postImage($object->id) && !count($this->errors) && $this->_redirect) - { - $parent_id = (int)Tools::getValue('id_parent', 1); - $this->afterAdd($object); - $this->updateAssoShop($object->id); - // Save and stay on same form - if (Tools::isSubmit('submitAdd'.$this->table.'AndStay')) - $this->redirect_after = self::$currentIndex.'&shop_id='.(int)$object->id.'&conf=3&update'.$this->table.'&token='.$this->token; - // Save and back to parent - if (Tools::isSubmit('submitAdd'.$this->table.'AndBackToParent')) - $this->redirect_after = self::$currentIndex.'&shop_id='.(int)$parent_id.'&conf=3&token='.$this->token; - // Default behavior (save and back) - if (empty($this->redirect_after)) - $this->redirect_after = self::$currentIndex.($parent_id ? '&shop_id='.$object->id : '').'&conf=3&token='.$this->token; - } - } + if (!count($this->errors)) { + /** @var Shop $object */ + $object = new $this->className(); + $this->copyFromPost($object, $this->table); + $this->beforeAdd($object); + if (!$object->add()) { + $this->errors[] = Tools::displayError('An error occurred while creating an object.'). + ' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>'; + } + /* voluntary do affectation here */ + elseif (($_POST[$this->identifier] = $object->id) && $this->postImage($object->id) && !count($this->errors) && $this->_redirect) { + $parent_id = (int)Tools::getValue('id_parent', 1); + $this->afterAdd($object); + $this->updateAssoShop($object->id); + // Save and stay on same form + if (Tools::isSubmit('submitAdd'.$this->table.'AndStay')) { + $this->redirect_after = self::$currentIndex.'&shop_id='.(int)$object->id.'&conf=3&update'.$this->table.'&token='.$this->token; + } + // Save and back to parent + if (Tools::isSubmit('submitAdd'.$this->table.'AndBackToParent')) { + $this->redirect_after = self::$currentIndex.'&shop_id='.(int)$parent_id.'&conf=3&token='.$this->token; + } + // Default behavior (save and back) + if (empty($this->redirect_after)) { + $this->redirect_after = self::$currentIndex.($parent_id ? '&shop_id='.$object->id : '').'&conf=3&token='.$this->token; + } + } + } - $this->errors = array_unique($this->errors); - if (count($this->errors) > 0) - { - $this->display = 'add'; - return; - } + $this->errors = array_unique($this->errors); + if (count($this->errors) > 0) { + $this->display = 'add'; + return; + } - $object->associateSuperAdmins(); + $object->associateSuperAdmins(); - $categories = Tools::getValue('categoryBox'); - array_unshift($categories, Configuration::get('PS_ROOT_CATEGORY')); - Category::updateFromShop($categories, $object->id); - if (Tools::getValue('useImportData') && ($import_data = Tools::getValue('importData')) && is_array($import_data) && isset($import_data['product'])) - { - ini_set('max_execution_time', 7200); // like searchcron.php - Search::indexation(true); - } - return $object; - } + $categories = Tools::getValue('categoryBox'); + array_unshift($categories, Configuration::get('PS_ROOT_CATEGORY')); + Category::updateFromShop($categories, $object->id); + if (Tools::getValue('useImportData') && ($import_data = Tools::getValue('importData')) && is_array($import_data) && isset($import_data['product'])) { + ini_set('max_execution_time', 7200); // like searchcron.php + Search::indexation(true); + } + return $object; + } - public function displayEditLink($token = null, $id, $name = null) - { - if ($this->tabAccess['edit'] == 1) - { - $tpl = $this->createTemplate('helpers/list/list_action_edit.tpl'); - if (!array_key_exists('Edit', self::$cache_lang)) - self::$cache_lang['Edit'] = $this->l('Edit', 'Helper'); - - $tpl->assign(array( - 'href' => $this->context->link->getAdminLink('AdminShop').'&shop_id='.(int)$id.'&update'.$this->table, - 'action' => self::$cache_lang['Edit'], - 'id' => $id - )); - - return $tpl->fetch(); - } - else - return; - } + public function displayEditLink($token = null, $id, $name = null) + { + if ($this->tabAccess['edit'] == 1) { + $tpl = $this->createTemplate('helpers/list/list_action_edit.tpl'); + if (!array_key_exists('Edit', self::$cache_lang)) { + self::$cache_lang['Edit'] = $this->l('Edit', 'Helper'); + } + + $tpl->assign(array( + 'href' => $this->context->link->getAdminLink('AdminShop').'&shop_id='.(int)$id.'&update'.$this->table, + 'action' => self::$cache_lang['Edit'], + 'id' => $id + )); + + return $tpl->fetch(); + } else { + return; + } + } - public function initCategoriesAssociation($id_root = null) - { - if (is_null($id_root)) - $id_root = Configuration::get('PS_ROOT_CATEGORY'); - $id_shop = (int)Tools::getValue('id_shop'); - $shop = new Shop($id_shop); - $selected_cat = Shop::getCategories($id_shop); - if (empty($selected_cat)) - { - // get first category root and preselect all these children - $root_categories = Category::getRootCategories(); - $root_category = new Category($root_categories[0]['id_category']); - $children = $root_category->getAllChildren($this->context->language->id); - $selected_cat[] = $root_categories[0]['id_category']; - - foreach ($children as $child) - $selected_cat[] = $child->id; - } - if (Shop::getContext() == Shop::CONTEXT_SHOP && Tools::isSubmit('id_shop')) - $root_category = new Category($shop->id_category); - else - $root_category = new Category($id_root); - $root_category = array('id_category' => $root_category->id, 'name' => $root_category->name[$this->context->language->id]); + public function initCategoriesAssociation($id_root = null) + { + if (is_null($id_root)) { + $id_root = Configuration::get('PS_ROOT_CATEGORY'); + } + $id_shop = (int)Tools::getValue('id_shop'); + $shop = new Shop($id_shop); + $selected_cat = Shop::getCategories($id_shop); + if (empty($selected_cat)) { + // get first category root and preselect all these children + $root_categories = Category::getRootCategories(); + $root_category = new Category($root_categories[0]['id_category']); + $children = $root_category->getAllChildren($this->context->language->id); + $selected_cat[] = $root_categories[0]['id_category']; + + foreach ($children as $child) { + $selected_cat[] = $child->id; + } + } + if (Shop::getContext() == Shop::CONTEXT_SHOP && Tools::isSubmit('id_shop')) { + $root_category = new Category($shop->id_category); + } else { + $root_category = new Category($id_root); + } + $root_category = array('id_category' => $root_category->id, 'name' => $root_category->name[$this->context->language->id]); - $helper = new Helper(); - return $helper->renderCategoryTree($root_category, $selected_cat, 'categoryBox', false, true); - } + $helper = new Helper(); + return $helper->renderCategoryTree($root_category, $selected_cat, 'categoryBox', false, true); + } - public function ajaxProcessTree() - { - $tree = array(); - $sql = 'SELECT g.id_shop_group, g.name as group_name, s.id_shop, s.name as shop_name, u.id_shop_url, u.domain, u.physical_uri, u.virtual_uri + public function ajaxProcessTree() + { + $tree = array(); + $sql = 'SELECT g.id_shop_group, g.name as group_name, s.id_shop, s.name as shop_name, u.id_shop_url, u.domain, u.physical_uri, u.virtual_uri FROM '._DB_PREFIX_.'shop_group g LEFT JOIN '._DB_PREFIX_.'shop s ON g.id_shop_group = s.id_shop_group LEFT JOIN '._DB_PREFIX_.'shop_url u ON u.id_shop = s.id_shop ORDER BY g.name, s.name, u.domain'; - $results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); - foreach ($results as $row) - { - $id_shop_group = $row['id_shop_group']; - $id_shop = $row['id_shop']; - $id_shop_url = $row['id_shop_url']; + $results = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); + foreach ($results as $row) { + $id_shop_group = $row['id_shop_group']; + $id_shop = $row['id_shop']; + $id_shop_url = $row['id_shop_url']; - // Group list - if (!isset($tree[$id_shop_group])) - $tree[$id_shop_group] = array( - 'data' => array( - 'title' => '<b>'.$this->l('Group').'</b> '.$row['group_name'], - 'icon' => 'themes/'.$this->context->employee->bo_theme.'/img/tree-multishop-groups.png', - 'attr' => array( - 'href' => $this->context->link->getAdminLink('AdminShop').'&id_shop_group='.$id_shop_group, - 'title' => sprintf($this->l('Click here to display the shops in the %s shop group', 'AdminShop', false, false), $row['group_name']), - ), - ), - 'attr' => array( - 'id' => 'tree-group-'.$id_shop_group, - ), - 'children' => array(), - ); + // Group list + if (!isset($tree[$id_shop_group])) { + $tree[$id_shop_group] = array( + 'data' => array( + 'title' => '<b>'.$this->l('Group').'</b> '.$row['group_name'], + 'icon' => 'themes/'.$this->context->employee->bo_theme.'/img/tree-multishop-groups.png', + 'attr' => array( + 'href' => $this->context->link->getAdminLink('AdminShop').'&id_shop_group='.$id_shop_group, + 'title' => sprintf($this->l('Click here to display the shops in the %s shop group', 'AdminShop', false, false), $row['group_name']), + ), + ), + 'attr' => array( + 'id' => 'tree-group-'.$id_shop_group, + ), + 'children' => array(), + ); + } - // Shop list - if (!$id_shop) - continue; + // Shop list + if (!$id_shop) { + continue; + } - if (!isset($tree[$id_shop_group]['children'][$id_shop])) - $tree[$id_shop_group]['children'][$id_shop] = array( - 'data' => array( - 'title' => $row['shop_name'], - 'icon' => 'themes/'.$this->context->employee->bo_theme.'/img/tree-multishop-shop.png', - 'attr' => array( - 'href' => $this->context->link->getAdminLink('AdminShopUrl').'&shop_id='.(int)$id_shop, - 'title' => sprintf($this->l('Click here to display the URLs of the %s shop', 'AdminShop', false, false), $row['shop_name']), - ) - ), - 'attr' => array( - 'id' => 'tree-shop-'.$id_shop, - ), - 'children' => array(), - ); - // Url list - if (!$id_shop_url) - continue; + if (!isset($tree[$id_shop_group]['children'][$id_shop])) { + $tree[$id_shop_group]['children'][$id_shop] = array( + 'data' => array( + 'title' => $row['shop_name'], + 'icon' => 'themes/'.$this->context->employee->bo_theme.'/img/tree-multishop-shop.png', + 'attr' => array( + 'href' => $this->context->link->getAdminLink('AdminShopUrl').'&shop_id='.(int)$id_shop, + 'title' => sprintf($this->l('Click here to display the URLs of the %s shop', 'AdminShop', false, false), $row['shop_name']), + ) + ), + 'attr' => array( + 'id' => 'tree-shop-'.$id_shop, + ), + 'children' => array(), + ); + } + // Url list + if (!$id_shop_url) { + continue; + } - if (!isset($tree[$id_shop_group]['children'][$id_shop]['children'][$id_shop_url])) - { - $url = $row['domain'].$row['physical_uri'].$row['virtual_uri']; - if (strlen($url) > 23) - $url = substr($url, 0, 23).'...'; + if (!isset($tree[$id_shop_group]['children'][$id_shop]['children'][$id_shop_url])) { + $url = $row['domain'].$row['physical_uri'].$row['virtual_uri']; + if (strlen($url) > 23) { + $url = substr($url, 0, 23).'...'; + } - $tree[$id_shop_group]['children'][$id_shop]['children'][$id_shop_url] = array( - 'data' => array( - 'title' => $url, - 'icon' => 'themes/'.$this->context->employee->bo_theme.'/img/tree-multishop-url.png', - 'attr' => array( - 'href' => $this->context->link->getAdminLink('AdminShopUrl').'&updateshop_url&id_shop_url='.$id_shop_url, - 'title' => $row['domain'].$row['physical_uri'].$row['virtual_uri'], - ) - ), - 'attr' => array( - 'id' => 'tree-url-'.$id_shop_url, - ), - ); - } - } + $tree[$id_shop_group]['children'][$id_shop]['children'][$id_shop_url] = array( + 'data' => array( + 'title' => $url, + 'icon' => 'themes/'.$this->context->employee->bo_theme.'/img/tree-multishop-url.png', + 'attr' => array( + 'href' => $this->context->link->getAdminLink('AdminShopUrl').'&updateshop_url&id_shop_url='.$id_shop_url, + 'title' => $row['domain'].$row['physical_uri'].$row['virtual_uri'], + ) + ), + 'attr' => array( + 'id' => 'tree-url-'.$id_shop_url, + ), + ); + } + } - // jstree need to have children as array and not object, so we use sort to get clean keys - // DO NOT REMOVE this code, even if it seems really strange ;) - sort($tree); - foreach ($tree as &$groups) - { - sort($groups['children']); - foreach ($groups['children'] as &$shops) - sort($shops['children']); - } + // jstree need to have children as array and not object, so we use sort to get clean keys + // DO NOT REMOVE this code, even if it seems really strange ;) + sort($tree); + foreach ($tree as &$groups) { + sort($groups['children']); + foreach ($groups['children'] as &$shops) { + sort($shops['children']); + } + } - $tree = array(array( - 'data' => array( - 'title' => '<b>'.$this->l('Shop groups list').'</b>', - 'icon' => 'themes/'.$this->context->employee->bo_theme.'/img/tree-multishop-root.png', - 'attr' => array( - 'href' => $this->context->link->getAdminLink('AdminShopGroup'), - 'title' => $this->l('Click here to display the list of shop groups', 'AdminShop', false, false), - ) - ), - 'attr' => array( - 'id' => 'tree-root', - ), - 'state' => 'open', - 'children' => $tree, - )); + $tree = array(array( + 'data' => array( + 'title' => '<b>'.$this->l('Shop groups list').'</b>', + 'icon' => 'themes/'.$this->context->employee->bo_theme.'/img/tree-multishop-root.png', + 'attr' => array( + 'href' => $this->context->link->getAdminLink('AdminShopGroup'), + 'title' => $this->l('Click here to display the list of shop groups', 'AdminShop', false, false), + ) + ), + 'attr' => array( + 'id' => 'tree-root', + ), + 'state' => 'open', + 'children' => $tree, + )); - die(Tools::jsonEncode($tree)); - } + die(Tools::jsonEncode($tree)); + } } diff --git a/controllers/admin/AdminShopGroupController.php b/controllers/admin/AdminShopGroupController.php index 09a08023..17c991c5 100644 --- a/controllers/admin/AdminShopGroupController.php +++ b/controllers/admin/AdminShopGroupController.php @@ -29,339 +29,343 @@ */ class AdminShopGroupControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'shop_group'; - $this->className = 'ShopGroup'; - $this->lang = false; - $this->multishop_context = Shop::CONTEXT_ALL; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'shop_group'; + $this->className = 'ShopGroup'; + $this->lang = false; + $this->multishop_context = Shop::CONTEXT_ALL; - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->context = Context::getContext(); + $this->context = Context::getContext(); - if (!Tools::getValue('realedit')) - $this->deleted = false; + if (!Tools::getValue('realedit')) { + $this->deleted = false; + } - $this->show_toolbar = false; + $this->show_toolbar = false; - $this->fields_list = array( - 'id_shop_group' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs', - ), - 'name' => array( - 'title' => $this->l('Shop group'), - 'width' => 'auto', - 'filter_key' => 'a!name', - ), - /*'active' => array( - 'title' => $this->l('Enabled'), - 'align' => 'center', - 'active' => 'status', - 'type' => 'bool', - 'orderby' => false, - 'filter_key' => 'active', - 'width' => 50, - ),*/ - ); + $this->fields_list = array( + 'id_shop_group' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs', + ), + 'name' => array( + 'title' => $this->l('Shop group'), + 'width' => 'auto', + 'filter_key' => 'a!name', + ), + /*'active' => array( + 'title' => $this->l('Enabled'), + 'align' => 'center', + 'active' => 'status', + 'type' => 'bool', + 'orderby' => false, + 'filter_key' => 'active', + 'width' => 50, + ),*/ + ); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Multistore options'), - 'fields' => array( - 'PS_SHOP_DEFAULT' => array( - 'title' => $this->l('Default shop'), - 'cast' => 'intval', - 'type' => 'select', - 'identifier' => 'id_shop', - 'list' => Shop::getShops(), - 'visibility' => Shop::CONTEXT_ALL - ) - ), - 'submit' => array('title' => $this->l('Save')) - ) - ); + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Multistore options'), + 'fields' => array( + 'PS_SHOP_DEFAULT' => array( + 'title' => $this->l('Default shop'), + 'cast' => 'intval', + 'type' => 'select', + 'identifier' => 'id_shop', + 'list' => Shop::getShops(), + 'visibility' => Shop::CONTEXT_ALL + ) + ), + 'submit' => array('title' => $this->l('Save')) + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function viewAccess($disable = false) - { - return Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE'); - } + public function viewAccess($disable = false) + { + return Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE'); + } - public function initContent() - { - parent::initContent(); + public function initContent() + { + parent::initContent(); - $this->addJqueryPlugin('cooki-plugin'); - $data = Shop::getTree(); + $this->addJqueryPlugin('cooki-plugin'); + $data = Shop::getTree(); - foreach ($data as $key_group => &$group) - foreach ($group['shops'] as $key_shop => &$shop) - { - $current_shop = new Shop($shop['id_shop']); - $urls = $current_shop->getUrls(); + foreach ($data as $key_group => &$group) { + foreach ($group['shops'] as $key_shop => &$shop) { + $current_shop = new Shop($shop['id_shop']); + $urls = $current_shop->getUrls(); - foreach ($urls as $key_url => &$url) - { - $title = $url['domain'].$url['physical_uri'].$url['virtual_uri']; - if (strlen($title) > 23) - $title = substr($title, 0, 23).'...'; + foreach ($urls as $key_url => &$url) { + $title = $url['domain'].$url['physical_uri'].$url['virtual_uri']; + if (strlen($title) > 23) { + $title = substr($title, 0, 23).'...'; + } - $url['name'] = $title; - $shop['urls'][$url['id_shop_url']] = $url; - } - } + $url['name'] = $title; + $shop['urls'][$url['id_shop_url']] = $url; + } + } + } - $shops_tree = new HelperTreeShops('shops-tree', $this->l('Multistore tree')); - $shops_tree->setNodeFolderTemplate('shop_tree_node_folder.tpl')->setNodeItemTemplate('shop_tree_node_item.tpl') - ->setHeaderTemplate('shop_tree_header.tpl')->setActions(array( - new TreeToolbarLink( - 'Collapse All', - '#', - '$(\'#'.$shops_tree->getId().'\').tree(\'collapseAll\'); return false;', - 'icon-collapse-alt'), - new TreeToolbarLink( - 'Expand All', - '#', - '$(\'#'.$shops_tree->getId().'\').tree(\'expandAll\'); return false;', - 'icon-expand-alt') - )) - ->setAttribute('url_shop_group', $this->context->link->getAdminLink('AdminShopGroup')) - ->setAttribute('url_shop', $this->context->link->getAdminLink('AdminShop')) - ->setAttribute('url_shop_url', $this->context->link->getAdminLink('AdminShopUrl')) - ->setData($data); - $shops_tree = $shops_tree->render(null, false, false); + $shops_tree = new HelperTreeShops('shops-tree', $this->l('Multistore tree')); + $shops_tree->setNodeFolderTemplate('shop_tree_node_folder.tpl')->setNodeItemTemplate('shop_tree_node_item.tpl') + ->setHeaderTemplate('shop_tree_header.tpl')->setActions(array( + new TreeToolbarLink( + 'Collapse All', + '#', + '$(\'#'.$shops_tree->getId().'\').tree(\'collapseAll\'); return false;', + 'icon-collapse-alt'), + new TreeToolbarLink( + 'Expand All', + '#', + '$(\'#'.$shops_tree->getId().'\').tree(\'expandAll\'); return false;', + 'icon-expand-alt') + )) + ->setAttribute('url_shop_group', $this->context->link->getAdminLink('AdminShopGroup')) + ->setAttribute('url_shop', $this->context->link->getAdminLink('AdminShop')) + ->setAttribute('url_shop_url', $this->context->link->getAdminLink('AdminShopUrl')) + ->setData($data); + $shops_tree = $shops_tree->render(null, false, false); - if ($this->display == 'edit') - $this->toolbar_title[] = $this->object->name; + if ($this->display == 'edit') { + $this->toolbar_title[] = $this->object->name; + } - $this->context->smarty->assign(array( - 'toolbar_scroll' => 1, - 'toolbar_btn' => $this->toolbar_btn, - 'title' => $this->toolbar_title, - 'shops_tree' => $shops_tree - )); - } + $this->context->smarty->assign(array( + 'toolbar_scroll' => 1, + 'toolbar_btn' => $this->toolbar_btn, + 'title' => $this->toolbar_title, + 'shops_tree' => $shops_tree + )); + } - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); - if ($this->display != 'add' && $this->display != 'edit') - { - $this->page_header_toolbar_btn['new'] = array( - 'desc' => $this->l('Add a new shop group'), - 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token - ); - $this->page_header_toolbar_btn['new_2'] = array( - 'desc' => $this->l('Add a new shop'), - 'href' => $this->context->link->getAdminLink('AdminShop').'&addshop', - 'imgclass' => 'new_2', - 'icon' => 'process-icon-new' - ); - } - } + if ($this->display != 'add' && $this->display != 'edit') { + $this->page_header_toolbar_btn['new'] = array( + 'desc' => $this->l('Add a new shop group'), + 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token + ); + $this->page_header_toolbar_btn['new_2'] = array( + 'desc' => $this->l('Add a new shop'), + 'href' => $this->context->link->getAdminLink('AdminShop').'&addshop', + 'imgclass' => 'new_2', + 'icon' => 'process-icon-new' + ); + } + } - public function initToolbar() - { - parent::initToolbar(); + public function initToolbar() + { + parent::initToolbar(); - if ($this->display != 'add' && $this->display != 'edit') - $this->toolbar_btn['new'] = array( - 'desc' => $this->l('Add a new shop group'), - 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token, - ); - } + if ($this->display != 'add' && $this->display != 'edit') { + $this->toolbar_btn['new'] = array( + 'desc' => $this->l('Add a new shop group'), + 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token, + ); + } + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Shop group'), - 'icon' => 'icon-shopping-cart' - ), - 'description' => $this->l('Warning: Enabling the "share customers" and "share orders" options is not recommended. Once activated and orders are created, you will not be able to disable these options. If you need these options, we recommend using several categories rather than several shops.'), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Shop group name'), - 'name' => 'name', - 'required' => true - ), - array( - 'type' => 'switch', - 'label' => $this->l('Share customers'), - 'name' => 'share_customer', - 'required' => true, - 'class' => 't', - 'is_bool' => true, - 'disabled' => ($this->id_object && $this->display == 'edit' && ShopGroup::hasDependency($this->id_object, 'customer')) ? true : false, - 'values' => array( - array( - 'id' => 'share_customer_on', - 'value' => 1 - ), - array( - 'id' => 'share_customer_off', - 'value' => 0 - ) - ), - 'desc' => $this->l('Once this option is enabled, the shops in this group will share customers. If a customer registers in any one of these shops, the account will automatically be available in the others shops of this group.').'<br/>'.$this->l('Warning: you will not be able to disable this option once you have registered customers.'), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Share available quantities to sell'), - 'name' => 'share_stock', - 'required' => true, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'share_stock_on', - 'value' => 1 - ), - array( - 'id' => 'share_stock_off', - 'value' => 0 - ) - ), - 'desc' => $this->l('Share available quantities between shops of this group. When changing this option, all available products quantities will be reset to 0.'), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Share orders'), - 'name' => 'share_order', - 'required' => true, - 'class' => 't', - 'is_bool' => true, - 'disabled' => ($this->id_object && $this->display == 'edit' && ShopGroup::hasDependency($this->id_object, 'order')) ? true : false, - 'values' => array( - array( - 'id' => 'share_order_on', - 'value' => 1 - ), - array( - 'id' => 'share_order_off', - 'value' => 0 - ) - ), - 'desc' => $this->l('Once this option is enabled (which is only possible if customers and available quantities are shared among shops), the customer\'s cart will be shared by all shops in this group. This way, any purchase started in one shop will be able to be completed in another shop from the same group.').'<br/>'.$this->l('Warning: You will not be able to disable this option once you\'ve started to accept orders.') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Status'), - 'name' => 'active', - 'required' => true, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1 - ), - array( - 'id' => 'active_off', - 'value' => 0 - ) - ), - 'desc' => $this->l('Enable or disable this shop group?') - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Shop group'), + 'icon' => 'icon-shopping-cart' + ), + 'description' => $this->l('Warning: Enabling the "share customers" and "share orders" options is not recommended. Once activated and orders are created, you will not be able to disable these options. If you need these options, we recommend using several categories rather than several shops.'), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Shop group name'), + 'name' => 'name', + 'required' => true + ), + array( + 'type' => 'switch', + 'label' => $this->l('Share customers'), + 'name' => 'share_customer', + 'required' => true, + 'class' => 't', + 'is_bool' => true, + 'disabled' => ($this->id_object && $this->display == 'edit' && ShopGroup::hasDependency($this->id_object, 'customer')) ? true : false, + 'values' => array( + array( + 'id' => 'share_customer_on', + 'value' => 1 + ), + array( + 'id' => 'share_customer_off', + 'value' => 0 + ) + ), + 'desc' => $this->l('Once this option is enabled, the shops in this group will share customers. If a customer registers in any one of these shops, the account will automatically be available in the others shops of this group.').'<br/>'.$this->l('Warning: you will not be able to disable this option once you have registered customers.'), + ), + array( + 'type' => 'switch', + 'label' => $this->l('Share available quantities to sell'), + 'name' => 'share_stock', + 'required' => true, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'share_stock_on', + 'value' => 1 + ), + array( + 'id' => 'share_stock_off', + 'value' => 0 + ) + ), + 'desc' => $this->l('Share available quantities between shops of this group. When changing this option, all available products quantities will be reset to 0.'), + ), + array( + 'type' => 'switch', + 'label' => $this->l('Share orders'), + 'name' => 'share_order', + 'required' => true, + 'class' => 't', + 'is_bool' => true, + 'disabled' => ($this->id_object && $this->display == 'edit' && ShopGroup::hasDependency($this->id_object, 'order')) ? true : false, + 'values' => array( + array( + 'id' => 'share_order_on', + 'value' => 1 + ), + array( + 'id' => 'share_order_off', + 'value' => 0 + ) + ), + 'desc' => $this->l('Once this option is enabled (which is only possible if customers and available quantities are shared among shops), the customer\'s cart will be shared by all shops in this group. This way, any purchase started in one shop will be able to be completed in another shop from the same group.').'<br/>'.$this->l('Warning: You will not be able to disable this option once you\'ve started to accept orders.') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Status'), + 'name' => 'active', + 'required' => true, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1 + ), + array( + 'id' => 'active_off', + 'value' => 0 + ) + ), + 'desc' => $this->l('Enable or disable this shop group?') + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - if (!($obj = $this->loadObject(true))) - return; + if (!($obj = $this->loadObject(true))) { + return; + } - if (Shop::getTotalShops() > 1 && $obj->id) - $disabled = array( - 'share_customer' => true, - 'share_stock' => true, - 'share_order' => true, - 'active' => false - ); - else - $disabled = false; + if (Shop::getTotalShops() > 1 && $obj->id) { + $disabled = array( + 'share_customer' => true, + 'share_stock' => true, + 'share_order' => true, + 'active' => false + ); + } else { + $disabled = false; + } - $default_shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); - $this->tpl_form_vars = array( - 'disabled' => $disabled, - 'checked' => (Tools::getValue('addshop_group') !== false) ? true : false, - 'defaultGroup' => $default_shop->id_shop_group, - ); + $default_shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); + $this->tpl_form_vars = array( + 'disabled' => $disabled, + 'checked' => (Tools::getValue('addshop_group') !== false) ? true : false, + 'defaultGroup' => $default_shop->id_shop_group, + ); - $this->fields_value = array( - 'active' => true - ); - return parent::renderForm(); - } + $this->fields_value = array( + 'active' => true + ); + return parent::renderForm(); + } - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - $shop_group_delete_list = array(); + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + $shop_group_delete_list = array(); - // test store authorized to remove - foreach ($this->_list as $shop_group) - { - $shops = Shop::getShops(true, $shop_group['id_shop_group']); - if (!empty($shops)) - $shop_group_delete_list[] = $shop_group['id_shop_group']; - } - $this->addRowActionSkipList('delete', $shop_group_delete_list); - } + // test store authorized to remove + foreach ($this->_list as $shop_group) { + $shops = Shop::getShops(true, $shop_group['id_shop_group']); + if (!empty($shops)) { + $shop_group_delete_list[] = $shop_group['id_shop_group']; + } + } + $this->addRowActionSkipList('delete', $shop_group_delete_list); + } - public function postProcess() - { - if (Tools::isSubmit('delete'.$this->table) || Tools::isSubmit('status') || Tools::isSubmit('status'.$this->table)) - { - /** @var ShopGroup $object */ - $object = $this->loadObject(); + public function postProcess() + { + if (Tools::isSubmit('delete'.$this->table) || Tools::isSubmit('status') || Tools::isSubmit('status'.$this->table)) { + /** @var ShopGroup $object */ + $object = $this->loadObject(); - if (ShopGroup::getTotalShopGroup() == 1) - $this->errors[] = Tools::displayError('You cannot delete or disable the last shop group.'); - elseif ($object->haveShops()) - $this->errors[] = Tools::displayError('You cannot delete or disable a shop group in use.'); + if (ShopGroup::getTotalShopGroup() == 1) { + $this->errors[] = Tools::displayError('You cannot delete or disable the last shop group.'); + } elseif ($object->haveShops()) { + $this->errors[] = Tools::displayError('You cannot delete or disable a shop group in use.'); + } - if (count($this->errors)) - return false; - } - return parent::postProcess(); - } + if (count($this->errors)) { + return false; + } + } + return parent::postProcess(); + } - protected function afterAdd($new_shop_group) - { - //Reset available quantitites - StockAvailable::resetProductFromStockAvailableByShopGroup($new_shop_group); - } + protected function afterAdd($new_shop_group) + { + //Reset available quantitites + StockAvailable::resetProductFromStockAvailableByShopGroup($new_shop_group); + } - protected function afterUpdate($new_shop_group) - { - //Reset available quantitites - StockAvailable::resetProductFromStockAvailableByShopGroup($new_shop_group); - } + protected function afterUpdate($new_shop_group) + { + //Reset available quantitites + StockAvailable::resetProductFromStockAvailableByShopGroup($new_shop_group); + } - public function renderOptions() - { - if ($this->fields_options && is_array($this->fields_options)) - { - $this->display = 'options'; - $this->show_toolbar = false; - $helper = new HelperOptions($this); - $this->setHelperDisplay($helper); - $helper->id = $this->id; - $helper->tpl_vars = $this->tpl_option_vars; - $options = $helper->generateOptions($this->fields_options); + public function renderOptions() + { + if ($this->fields_options && is_array($this->fields_options)) { + $this->display = 'options'; + $this->show_toolbar = false; + $helper = new HelperOptions($this); + $this->setHelperDisplay($helper); + $helper->id = $this->id; + $helper->tpl_vars = $this->tpl_option_vars; + $options = $helper->generateOptions($this->fields_options); - return $options; - } - } -} \ No newline at end of file + return $options; + } + } +} diff --git a/controllers/admin/AdminShopUrlController.php b/controllers/admin/AdminShopUrlController.php index 28c56388..0e9439cb 100644 --- a/controllers/admin/AdminShopUrlController.php +++ b/controllers/admin/AdminShopUrlController.php @@ -29,521 +29,536 @@ */ class AdminShopUrlControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'shop_url'; - $this->className = 'ShopUrl'; - $this->lang = false; - $this->requiredDatabase = true; - $this->multishop_context = Shop::CONTEXT_ALL; - $this->bulk_actions = array(); - - /* if $_GET['id_shop'] is transmitted, virtual url can be loaded in config.php, so we wether transmit shop_id in herfs */ - if ($this->id_shop = (int)Tools::getValue('shop_id')) - $_GET['id_shop'] = $this->id_shop; - else - $this->id_shop = (int)Tools::getValue('id_shop'); - - $this->context = Context::getContext(); - - if (!Tools::getValue('realedit')) - $this->deleted = false; - - $this->fields_list = array( - 'id_shop_url' => array( - 'title' => $this->l('Shop URL ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'shop_name' => array( - 'title' => $this->l('Shop name'), - 'filter_key' => 's!name' - ), - 'url' => array( - 'title' => $this->l('URL'), - 'filter_key' => 'url', - 'havingFilter' => true - ), - 'main' => array( - 'title' => $this->l('Is it the main URL?'), - 'align' => 'center', - 'activeVisu' => 'main', - 'active' => 'main', - 'type' => 'bool', - 'orderby' => false, - 'filter_key' => 'main', - 'class' => 'fixed-width-md' - ), - 'active' => array( - 'title' => $this->l('Enabled'), - 'align' => 'center', - 'active' => 'status', - 'type' => 'bool', - 'orderby' => false, - 'filter_key' => 'active', - 'class' => 'fixed-width-md' - ), - ); - - parent::__construct(); - } - - public function viewAccess($disable = false) - { - return Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE'); - } - - public function renderList() - { - $this->addRowActionSkipList('delete', array(1)); - - $this->addRowAction('edit'); - $this->addRowAction('delete'); - - $this->_select = 's.name AS shop_name, CONCAT(\'http://\', a.domain, a.physical_uri, a.virtual_uri) AS url'; - $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'shop` s ON (s.id_shop = a.id_shop)'; - - if ($id_shop = (int)Tools::getValue('id_shop')) - $this->_where = 'AND a.id_shop = '.$id_shop; - $this->_use_found_rows = false; - - return parent::renderList(); - } - - public function renderForm() - { - $update_htaccess = Tools::modRewriteActive() && ((file_exists('.htaccess') && is_writable('.htaccess')) || is_writable(dirname('.htaccess'))); - - $this->multiple_fieldsets = true; - if (!$update_htaccess) - $desc_virtual_uri = array( - '<span class="warning_mod_rewrite">'.$this->l('If you want to add a virtual URL, you need to activate URL rewriting on your web server and enable Friendly URL option.').'</span>' - ); - else - $desc_virtual_uri = array( - $this->l('You can use this option if you want to create a store with a URL that doesn\'t exist on your server (e.g. if you want your store to be available with the URL www.example.com/my-store/shoes/, you have to set shoes/ in this field, assuming that my-store/ is your Physical URL).'), - '<strong>'.$this->l('URL rewriting must be activated on your server to use this feature.').'</strong>' - ); - $this->fields_form = array( - array( - 'form' => array( - 'legend' => array( - 'title' => $this->l('URL options'), - 'icon' => 'icon-cogs' - ), - 'input' => array( - array( - 'type' => 'select', - 'label' => $this->l('Shop'), - 'name' => 'id_shop', - 'onchange' => 'checkMainUrlInfo(this.value);', - 'options' => array( - 'optiongroup' => array ( - 'query' => Shop::getTree(), - 'label' => 'name' - ), - 'options' => array ( - 'query' => 'shops', - 'id' => 'id_shop', - 'name' => 'name' - ) - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Is it the main URL for this shop?'), - 'name' => 'main', - 'is_bool' => true, - 'class' => 't', - 'values' => array( - array( - 'id' => 'main_on', - 'value' => 1 - ), - array( - 'id' => 'main_off', - 'value' => 0 - ) - ), - 'desc' => array( - $this->l('If you set this URL as the Main URL for the selected shop, all URLs set to this shop will be redirected to this URL (you can only have one Main URL per shop).'), - array( - 'text' => $this->l('Since the selected shop has no main URL, you have to set this URL as the Main URL.'), - 'id' => 'mainUrlInfo' - ), - array( - 'text' => $this->l('The selected shop already has a Main URL. Therefore, if you set this one as the Main URL, the older Main URL will be set as a regular URL.'), - 'id' => 'mainUrlInfoExplain' - ) - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Enabled'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'class' => 't', - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1 - ), - array( - 'id' => 'active_off', - 'value' => 0 - ) - ) - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ), - ), - ), - array( - 'form' => array( - 'legend' => array( - 'title' => $this->l('Shop URL'), - 'icon' => 'icon-shopping-cart' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Domain'), - 'name' => 'domain', - 'size' => 50, - ), - array( - 'type' => 'text', - 'label' => $this->l('SSL Domain'), - 'name' => 'domain_ssl', - 'size' => 50, - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ), - ), - ), - ); - - if (!defined('_PS_HOST_MODE_')) - $this->fields_form[1]['form']['input'] = array_merge($this->fields_form[1]['form']['input'], - array( - array( - 'type' => 'text', - 'label' => $this->l('Physical URL'), - 'name' => 'physical_uri', - 'desc' => $this->l('This is the physical folder for your store on the web server. Leave this field empty if your store is installed on the root path. For instance, if your store is available at www.example.com/my-store/, you must input my-store/ in this field.'), - 'size' => 50, - ) - ) - ); - - $this->fields_form[1]['form']['input'] = array_merge($this->fields_form[1]['form']['input'], - array( - array( - 'type' => 'text', - 'label' => $this->l('Virtual URL'), - 'name' => 'virtual_uri', - 'desc' => $desc_virtual_uri, - 'size' => 50, - 'hint' => (!$update_htaccess) ? $this->l('Warning: URL rewriting (e.g. mod_rewrite for Apache) seems to be disabled. If your Virtual URL doesn\'t work, please check with your hosting provider on how to activate URL rewriting.') : null, - ), - array( - 'type' => 'text', - 'label' => $this->l('Final URL'), - 'name' => 'final_url', - 'size' => 76, - 'readonly' => true - ), - ) - ); - - if (!($obj = $this->loadObject(true))) - return; - - self::$currentIndex = self::$currentIndex.($obj->id ? '&shop_id='.(int)$obj->id_shop : ''); - - $current_shop = Shop::initialize(); - - $list_shop_with_url = array(); - foreach (Shop::getShops(false, null, true) as $id) - $list_shop_with_url[$id] = (bool)count(ShopUrl::getShopUrls($id)); - - $this->tpl_form_vars = array( - 'js_shop_url' => Tools::jsonEncode($list_shop_with_url) - ); - - $this->fields_value = array( - 'domain' => trim(Validate::isLoadedObject($obj) ? $this->getFieldValue($obj, 'domain') : $current_shop->domain), - 'domain_ssl' => trim(Validate::isLoadedObject($obj) ? $this->getFieldValue($obj, 'domain_ssl') : $current_shop->domain_ssl), - 'physical_uri' => trim(Validate::isLoadedObject($obj) ? $this->getFieldValue($obj, 'physical_uri') : $current_shop->physical_uri), - 'active' => trim(Validate::isLoadedObject($obj) ? $this->getFieldValue($obj, 'active') : true) - ); - - return parent::renderForm(); - } - - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); - - if ($this->display != 'add' && $this->display != 'edit') - { - if ($this->id_object) - $this->loadObject(); - - if (!$this->id_shop && $this->object && $this->object->id_shop) - $this->id_shop = $this->object->id_shop; - - $this->page_header_toolbar_btn['edit'] = array( - 'desc' => $this->l('Edit this shop'), - 'href' => $this->context->link->getAdminLink('AdminShop').'&updateshop&shop_id='.(int)$this->id_shop, - ); - - $this->page_header_toolbar_btn['new'] = array( - 'desc' => $this->l('Add a new URL'), - 'href' => $this->context->link->getAdminLink('AdminShopUrl').'&add'.$this->table.'&shop_id='.(int)$this->id_shop, - ); - } - } - - public function initToolbar() - { - parent::initToolbar(); - - if ($this->display != 'add' && $this->display != 'edit') - { - if ($this->id_object) - $this->loadObject(); - - if (!$this->id_shop && $this->object && $this->object->id_shop) - $this->id_shop = $this->object->id_shop; - - $this->toolbar_btn['new'] = array( - 'desc' => $this->l('Add a new URL'), - 'href' => $this->context->link->getAdminLink('AdminShopUrl').'&add'.$this->table.'&shop_id='.(int)$this->id_shop, - ); - } - } - - public function initContent() - { - parent::initContent(); - - $this->addJqueryPlugin('cooki-plugin'); - $data = Shop::getTree(); - - foreach ($data as $key_group => &$group) - foreach ($group['shops'] as $key_shop => &$shop) - { - $current_shop = new Shop($shop['id_shop']); - $urls = $current_shop->getUrls(); - - foreach ($urls as $key_url => &$url) - { - $title = $url['domain'].$url['physical_uri'].$url['virtual_uri']; - if (strlen($title) > 23) - $title = substr($title, 0, 23).'...'; - - $url['name'] = $title; - $shop['urls'][$url['id_shop_url']] = $url; - } - } - - $shops_tree = new HelperTreeShops('shops-tree', $this->l('Multistore tree')); - $shops_tree->setNodeFolderTemplate('shop_tree_node_folder.tpl')->setNodeItemTemplate('shop_tree_node_item.tpl') - ->setHeaderTemplate('shop_tree_header.tpl')->setActions(array( - new TreeToolbarLink( - 'Collapse All', - '#', - '$(\'#'.$shops_tree->getId().'\').tree(\'collapseAll\'); return false;', - 'icon-collapse-alt'), - new TreeToolbarLink( - 'Expand All', - '#', - '$(\'#'.$shops_tree->getId().'\').tree(\'expandAll\'); return false;', - 'icon-expand-alt') - )) - ->setAttribute('url_shop_group', $this->context->link->getAdminLink('AdminShopGroup')) - ->setAttribute('url_shop', $this->context->link->getAdminLink('AdminShop')) - ->setAttribute('url_shop_url', $this->context->link->getAdminLink('AdminShopUrl')) - ->setData($data); - $shops_tree = $shops_tree->render(null, false, false); - - if (!$this->display && $this->id_shop) - { - $shop = new Shop($this->id_shop); - $this->toolbar_title[] = $shop->name; - } - - $this->context->smarty->assign(array( - 'toolbar_scroll' => 1, - 'toolbar_btn' => $this->toolbar_btn, - 'title' => $this->toolbar_title, - 'shops_tree' => $shops_tree - )); - } - - public function postProcess() - { - $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; - - $result = true; - - if ((Tools::isSubmit('status'.$this->table) || Tools::isSubmit('status')) && Tools::getValue($this->identifier)) - { - if ($this->tabAccess['edit'] === '1') - { - if (Validate::isLoadedObject($object = $this->loadObject())) - { - /** @var ShopUrl $object */ - if ($object->main) - $this->errors[] = Tools::displayError('You cannot disable the Main URL.'); - elseif ($object->toggleStatus()) - Tools::redirectAdmin(self::$currentIndex.'&conf=5&token='.$token); - else - $this->errors[] = Tools::displayError('An error occurred while updating the status.'); - } - else - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('main'.$this->table) && Tools::getValue($this->identifier)) - { - if ($this->tabAccess['edit'] === '1') - { - if (Validate::isLoadedObject($object = $this->loadObject())) - { - /** @var ShopUrl $object */ - if (!$object->main) - { - $result = $object->setMain(); - Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$token); - } - else - $this->errors[] = Tools::displayError('You cannot change a main URL to a non-main URL. You have to set another URL as your Main URL for the selected shop.'); - } - else - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - else - $result = parent::postProcess(); - - if ($this->redirect_after) - $this->redirect_after .= '&shop_id='.(int)$this->id_shop; - - return $result; - } - - public function processSave() - { - /** @var ShopUrl $object */ - $object = $this->loadObject(true); - if ($object->canAddThisUrl(Tools::getValue('domain'), Tools::getValue('domain_ssl'), Tools::getValue('physical_uri'), Tools::getValue('virtual_uri'))) - $this->errors[] = Tools::displayError('A shop URL that uses this domain already exists.'); - - $unallowed = str_replace('/', '', Tools::getValue('virtual_uri')); - if ($unallowed == 'c' || $unallowed == 'img' || is_numeric($unallowed)) - $this->errors[] = sprintf(Tools::displayError('A shop virtual URL can not be "%s"'), $unallowed); - $return = parent::processSave(); - if (!$this->errors) - { - Tools::generateHtaccess(); - Tools::clearSmartyCache(); - Media::clearCache(); - } - - return $return; - } - - public function processAdd() - { - /** @var ShopUrl $object */ - $object = $this->loadObject(true); - - if ($object->canAddThisUrl(Tools::getValue('domain'), Tools::getValue('domain_ssl'), Tools::getValue('physical_uri'), Tools::getValue('virtual_uri'))) - $this->errors[] = Tools::displayError('A shop URL that uses this domain already exists.'); - - if (Tools::getValue('main') && !Tools::getValue('active')) - $this->errors[] = Tools::displayError('You cannot disable the Main URL.'); - - return parent::processAdd(); - } - - public function processUpdate() - { - $this->redirect_shop_url = false; - $current_url = parse_url($_SERVER['REQUEST_URI']); - if (trim(dirname(dirname($current_url['path'])), '/') == trim($this->object->getBaseURI(), '/')) - $this->redirect_shop_url = true; - - /** @var ShopUrl $object */ - $object = $this->loadObject(true); - - if ($object->main && !Tools::getValue('main')) - $this->errors[] = Tools::displayError('You cannot change a main URL to a non-main URL. You have to set another URL as your Main URL for the selected shop.'); - - if (($object->main || Tools::getValue('main')) && !Tools::getValue('active')) - $this->errors[] = Tools::displayError('You cannot disable the Main URL.'); - - return parent::processUpdate(); - } - - /** - * @param ShopUrl $object - * @return void - */ - protected function afterUpdate($object) - { - if ($object->id && Tools::getValue('main')) - $object->setMain(); - - if ($this->redirect_shop_url) - $this->redirect_after = $object->getBaseURI().basename(_PS_ADMIN_DIR_).'/'.$this->context->link->getAdminLink('AdminShopUrl'); - } - - /** - * @param string $token - * @param int $id - * @param string $name - * @return mixed - */ - public function displayDeleteLink($token = null, $id, $name = null) - { - $tpl = $this->createTemplate('helpers/list/list_action_delete.tpl'); - - if (!array_key_exists('Delete', self::$cache_lang)) - self::$cache_lang['Delete'] = $this->l('Delete', 'Helper'); - - if (!array_key_exists('DeleteItem', self::$cache_lang)) - self::$cache_lang['DeleteItem'] = $this->l('Delete selected item?', 'Helper'); - - if (!array_key_exists('Name', self::$cache_lang)) - self::$cache_lang['Name'] = $this->l('Name:', 'Helper'); - - if (!is_null($name)) - $name = '\n\n'.self::$cache_lang['Name'].' '.$name; - - $data = array( - $this->identifier => $id, - 'href' => self::$currentIndex.'&'.$this->identifier.'='.$id.'&delete'.$this->table.'&shop_id='.(int)$this->id_shop.'&token='.($token != null ? $token : $this->token), - 'action' => self::$cache_lang['Delete'], - ); - - if ($this->specificConfirmDelete !== false) - $data['confirm'] = !is_null($this->specificConfirmDelete) ? '\r'.$this->specificConfirmDelete : self::$cache_lang['DeleteItem'].$name; - - $tpl->assign(array_merge($this->tpl_delete_link_vars, $data)); - - return $tpl->fetch(); - } + public function __construct() + { + $this->bootstrap = true; + $this->table = 'shop_url'; + $this->className = 'ShopUrl'; + $this->lang = false; + $this->requiredDatabase = true; + $this->multishop_context = Shop::CONTEXT_ALL; + $this->bulk_actions = array(); + + /* if $_GET['id_shop'] is transmitted, virtual url can be loaded in config.php, so we wether transmit shop_id in herfs */ + if ($this->id_shop = (int)Tools::getValue('shop_id')) { + $_GET['id_shop'] = $this->id_shop; + } else { + $this->id_shop = (int)Tools::getValue('id_shop'); + } + + $this->context = Context::getContext(); + + if (!Tools::getValue('realedit')) { + $this->deleted = false; + } + + $this->fields_list = array( + 'id_shop_url' => array( + 'title' => $this->l('Shop URL ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'shop_name' => array( + 'title' => $this->l('Shop name'), + 'filter_key' => 's!name' + ), + 'url' => array( + 'title' => $this->l('URL'), + 'filter_key' => 'url', + 'havingFilter' => true + ), + 'main' => array( + 'title' => $this->l('Is it the main URL?'), + 'align' => 'center', + 'activeVisu' => 'main', + 'active' => 'main', + 'type' => 'bool', + 'orderby' => false, + 'filter_key' => 'main', + 'class' => 'fixed-width-md' + ), + 'active' => array( + 'title' => $this->l('Enabled'), + 'align' => 'center', + 'active' => 'status', + 'type' => 'bool', + 'orderby' => false, + 'filter_key' => 'active', + 'class' => 'fixed-width-md' + ), + ); + + parent::__construct(); + } + + public function viewAccess($disable = false) + { + return Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE'); + } + + public function renderList() + { + $this->addRowActionSkipList('delete', array(1)); + + $this->addRowAction('edit'); + $this->addRowAction('delete'); + + $this->_select = 's.name AS shop_name, CONCAT(\'http://\', a.domain, a.physical_uri, a.virtual_uri) AS url'; + $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'shop` s ON (s.id_shop = a.id_shop)'; + + if ($id_shop = (int)Tools::getValue('id_shop')) { + $this->_where = 'AND a.id_shop = '.$id_shop; + } + $this->_use_found_rows = false; + + return parent::renderList(); + } + + public function renderForm() + { + $update_htaccess = Tools::modRewriteActive() && ((file_exists('.htaccess') && is_writable('.htaccess')) || is_writable(dirname('.htaccess'))); + + $this->multiple_fieldsets = true; + if (!$update_htaccess) { + $desc_virtual_uri = array( + '<span class="warning_mod_rewrite">'.$this->l('If you want to add a virtual URL, you need to activate URL rewriting on your web server and enable Friendly URL option.').'</span>' + ); + } else { + $desc_virtual_uri = array( + $this->l('You can use this option if you want to create a store with a URL that doesn\'t exist on your server (e.g. if you want your store to be available with the URL www.example.com/my-store/shoes/, you have to set shoes/ in this field, assuming that my-store/ is your Physical URL).'), + '<strong>'.$this->l('URL rewriting must be activated on your server to use this feature.').'</strong>' + ); + } + $this->fields_form = array( + array( + 'form' => array( + 'legend' => array( + 'title' => $this->l('URL options'), + 'icon' => 'icon-cogs' + ), + 'input' => array( + array( + 'type' => 'select', + 'label' => $this->l('Shop'), + 'name' => 'id_shop', + 'onchange' => 'checkMainUrlInfo(this.value);', + 'options' => array( + 'optiongroup' => array( + 'query' => Shop::getTree(), + 'label' => 'name' + ), + 'options' => array( + 'query' => 'shops', + 'id' => 'id_shop', + 'name' => 'name' + ) + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Is it the main URL for this shop?'), + 'name' => 'main', + 'is_bool' => true, + 'class' => 't', + 'values' => array( + array( + 'id' => 'main_on', + 'value' => 1 + ), + array( + 'id' => 'main_off', + 'value' => 0 + ) + ), + 'desc' => array( + $this->l('If you set this URL as the Main URL for the selected shop, all URLs set to this shop will be redirected to this URL (you can only have one Main URL per shop).'), + array( + 'text' => $this->l('Since the selected shop has no main URL, you have to set this URL as the Main URL.'), + 'id' => 'mainUrlInfo' + ), + array( + 'text' => $this->l('The selected shop already has a Main URL. Therefore, if you set this one as the Main URL, the older Main URL will be set as a regular URL.'), + 'id' => 'mainUrlInfoExplain' + ) + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Enabled'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'class' => 't', + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1 + ), + array( + 'id' => 'active_off', + 'value' => 0 + ) + ) + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ), + ), + ), + array( + 'form' => array( + 'legend' => array( + 'title' => $this->l('Shop URL'), + 'icon' => 'icon-shopping-cart' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Domain'), + 'name' => 'domain', + 'size' => 50, + ), + array( + 'type' => 'text', + 'label' => $this->l('SSL Domain'), + 'name' => 'domain_ssl', + 'size' => 50, + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ), + ), + ), + ); + + if (!defined('_PS_HOST_MODE_')) { + $this->fields_form[1]['form']['input'] = array_merge($this->fields_form[1]['form']['input'], + array( + array( + 'type' => 'text', + 'label' => $this->l('Physical URL'), + 'name' => 'physical_uri', + 'desc' => $this->l('This is the physical folder for your store on the web server. Leave this field empty if your store is installed on the root path. For instance, if your store is available at www.example.com/my-store/, you must input my-store/ in this field.'), + 'size' => 50, + ) + ) + ); + } + + $this->fields_form[1]['form']['input'] = array_merge($this->fields_form[1]['form']['input'], + array( + array( + 'type' => 'text', + 'label' => $this->l('Virtual URL'), + 'name' => 'virtual_uri', + 'desc' => $desc_virtual_uri, + 'size' => 50, + 'hint' => (!$update_htaccess) ? $this->l('Warning: URL rewriting (e.g. mod_rewrite for Apache) seems to be disabled. If your Virtual URL doesn\'t work, please check with your hosting provider on how to activate URL rewriting.') : null, + ), + array( + 'type' => 'text', + 'label' => $this->l('Final URL'), + 'name' => 'final_url', + 'size' => 76, + 'readonly' => true + ), + ) + ); + + if (!($obj = $this->loadObject(true))) { + return; + } + + self::$currentIndex = self::$currentIndex.($obj->id ? '&shop_id='.(int)$obj->id_shop : ''); + + $current_shop = Shop::initialize(); + + $list_shop_with_url = array(); + foreach (Shop::getShops(false, null, true) as $id) { + $list_shop_with_url[$id] = (bool)count(ShopUrl::getShopUrls($id)); + } + + $this->tpl_form_vars = array( + 'js_shop_url' => Tools::jsonEncode($list_shop_with_url) + ); + + $this->fields_value = array( + 'domain' => trim(Validate::isLoadedObject($obj) ? $this->getFieldValue($obj, 'domain') : $current_shop->domain), + 'domain_ssl' => trim(Validate::isLoadedObject($obj) ? $this->getFieldValue($obj, 'domain_ssl') : $current_shop->domain_ssl), + 'physical_uri' => trim(Validate::isLoadedObject($obj) ? $this->getFieldValue($obj, 'physical_uri') : $current_shop->physical_uri), + 'active' => trim(Validate::isLoadedObject($obj) ? $this->getFieldValue($obj, 'active') : true) + ); + + return parent::renderForm(); + } + + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); + + if ($this->display != 'add' && $this->display != 'edit') { + if ($this->id_object) { + $this->loadObject(); + } + + if (!$this->id_shop && $this->object && $this->object->id_shop) { + $this->id_shop = $this->object->id_shop; + } + + $this->page_header_toolbar_btn['edit'] = array( + 'desc' => $this->l('Edit this shop'), + 'href' => $this->context->link->getAdminLink('AdminShop').'&updateshop&shop_id='.(int)$this->id_shop, + ); + + $this->page_header_toolbar_btn['new'] = array( + 'desc' => $this->l('Add a new URL'), + 'href' => $this->context->link->getAdminLink('AdminShopUrl').'&add'.$this->table.'&shop_id='.(int)$this->id_shop, + ); + } + } + + public function initToolbar() + { + parent::initToolbar(); + + if ($this->display != 'add' && $this->display != 'edit') { + if ($this->id_object) { + $this->loadObject(); + } + + if (!$this->id_shop && $this->object && $this->object->id_shop) { + $this->id_shop = $this->object->id_shop; + } + + $this->toolbar_btn['new'] = array( + 'desc' => $this->l('Add a new URL'), + 'href' => $this->context->link->getAdminLink('AdminShopUrl').'&add'.$this->table.'&shop_id='.(int)$this->id_shop, + ); + } + } + + public function initContent() + { + parent::initContent(); + + $this->addJqueryPlugin('cooki-plugin'); + $data = Shop::getTree(); + + foreach ($data as $key_group => &$group) { + foreach ($group['shops'] as $key_shop => &$shop) { + $current_shop = new Shop($shop['id_shop']); + $urls = $current_shop->getUrls(); + + foreach ($urls as $key_url => &$url) { + $title = $url['domain'].$url['physical_uri'].$url['virtual_uri']; + if (strlen($title) > 23) { + $title = substr($title, 0, 23).'...'; + } + + $url['name'] = $title; + $shop['urls'][$url['id_shop_url']] = $url; + } + } + } + + $shops_tree = new HelperTreeShops('shops-tree', $this->l('Multistore tree')); + $shops_tree->setNodeFolderTemplate('shop_tree_node_folder.tpl')->setNodeItemTemplate('shop_tree_node_item.tpl') + ->setHeaderTemplate('shop_tree_header.tpl')->setActions(array( + new TreeToolbarLink( + 'Collapse All', + '#', + '$(\'#'.$shops_tree->getId().'\').tree(\'collapseAll\'); return false;', + 'icon-collapse-alt'), + new TreeToolbarLink( + 'Expand All', + '#', + '$(\'#'.$shops_tree->getId().'\').tree(\'expandAll\'); return false;', + 'icon-expand-alt') + )) + ->setAttribute('url_shop_group', $this->context->link->getAdminLink('AdminShopGroup')) + ->setAttribute('url_shop', $this->context->link->getAdminLink('AdminShop')) + ->setAttribute('url_shop_url', $this->context->link->getAdminLink('AdminShopUrl')) + ->setData($data); + $shops_tree = $shops_tree->render(null, false, false); + + if (!$this->display && $this->id_shop) { + $shop = new Shop($this->id_shop); + $this->toolbar_title[] = $shop->name; + } + + $this->context->smarty->assign(array( + 'toolbar_scroll' => 1, + 'toolbar_btn' => $this->toolbar_btn, + 'title' => $this->toolbar_title, + 'shops_tree' => $shops_tree + )); + } + + public function postProcess() + { + $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; + + $result = true; + + if ((Tools::isSubmit('status'.$this->table) || Tools::isSubmit('status')) && Tools::getValue($this->identifier)) { + if ($this->tabAccess['edit'] === '1') { + if (Validate::isLoadedObject($object = $this->loadObject())) { + /** @var ShopUrl $object */ + if ($object->main) { + $this->errors[] = Tools::displayError('You cannot disable the Main URL.'); + } elseif ($object->toggleStatus()) { + Tools::redirectAdmin(self::$currentIndex.'&conf=5&token='.$token); + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the status.'); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('main'.$this->table) && Tools::getValue($this->identifier)) { + if ($this->tabAccess['edit'] === '1') { + if (Validate::isLoadedObject($object = $this->loadObject())) { + /** @var ShopUrl $object */ + if (!$object->main) { + $result = $object->setMain(); + Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$token); + } else { + $this->errors[] = Tools::displayError('You cannot change a main URL to a non-main URL. You have to set another URL as your Main URL for the selected shop.'); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } else { + $result = parent::postProcess(); + } + + if ($this->redirect_after) { + $this->redirect_after .= '&shop_id='.(int)$this->id_shop; + } + + return $result; + } + + public function processSave() + { + /** @var ShopUrl $object */ + $object = $this->loadObject(true); + if ($object->canAddThisUrl(Tools::getValue('domain'), Tools::getValue('domain_ssl'), Tools::getValue('physical_uri'), Tools::getValue('virtual_uri'))) { + $this->errors[] = Tools::displayError('A shop URL that uses this domain already exists.'); + } + + $unallowed = str_replace('/', '', Tools::getValue('virtual_uri')); + if ($unallowed == 'c' || $unallowed == 'img' || is_numeric($unallowed)) { + $this->errors[] = sprintf(Tools::displayError('A shop virtual URL can not be "%s"'), $unallowed); + } + $return = parent::processSave(); + if (!$this->errors) { + Tools::generateHtaccess(); + Tools::clearSmartyCache(); + Media::clearCache(); + } + + return $return; + } + + public function processAdd() + { + /** @var ShopUrl $object */ + $object = $this->loadObject(true); + + if ($object->canAddThisUrl(Tools::getValue('domain'), Tools::getValue('domain_ssl'), Tools::getValue('physical_uri'), Tools::getValue('virtual_uri'))) { + $this->errors[] = Tools::displayError('A shop URL that uses this domain already exists.'); + } + + if (Tools::getValue('main') && !Tools::getValue('active')) { + $this->errors[] = Tools::displayError('You cannot disable the Main URL.'); + } + + return parent::processAdd(); + } + + public function processUpdate() + { + $this->redirect_shop_url = false; + $current_url = parse_url($_SERVER['REQUEST_URI']); + if (trim(dirname(dirname($current_url['path'])), '/') == trim($this->object->getBaseURI(), '/')) { + $this->redirect_shop_url = true; + } + + /** @var ShopUrl $object */ + $object = $this->loadObject(true); + + if ($object->main && !Tools::getValue('main')) { + $this->errors[] = Tools::displayError('You cannot change a main URL to a non-main URL. You have to set another URL as your Main URL for the selected shop.'); + } + + if (($object->main || Tools::getValue('main')) && !Tools::getValue('active')) { + $this->errors[] = Tools::displayError('You cannot disable the Main URL.'); + } + + return parent::processUpdate(); + } + + /** + * @param ShopUrl $object + * @return void + */ + protected function afterUpdate($object) + { + if ($object->id && Tools::getValue('main')) { + $object->setMain(); + } + + if ($this->redirect_shop_url) { + $this->redirect_after = $object->getBaseURI().basename(_PS_ADMIN_DIR_).'/'.$this->context->link->getAdminLink('AdminShopUrl'); + } + } + + /** + * @param string $token + * @param int $id + * @param string $name + * @return mixed + */ + public function displayDeleteLink($token = null, $id, $name = null) + { + $tpl = $this->createTemplate('helpers/list/list_action_delete.tpl'); + + if (!array_key_exists('Delete', self::$cache_lang)) { + self::$cache_lang['Delete'] = $this->l('Delete', 'Helper'); + } + + if (!array_key_exists('DeleteItem', self::$cache_lang)) { + self::$cache_lang['DeleteItem'] = $this->l('Delete selected item?', 'Helper'); + } + + if (!array_key_exists('Name', self::$cache_lang)) { + self::$cache_lang['Name'] = $this->l('Name:', 'Helper'); + } + + if (!is_null($name)) { + $name = '\n\n'.self::$cache_lang['Name'].' '.$name; + } + + $data = array( + $this->identifier => $id, + 'href' => self::$currentIndex.'&'.$this->identifier.'='.$id.'&delete'.$this->table.'&shop_id='.(int)$this->id_shop.'&token='.($token != null ? $token : $this->token), + 'action' => self::$cache_lang['Delete'], + ); + + if ($this->specificConfirmDelete !== false) { + $data['confirm'] = !is_null($this->specificConfirmDelete) ? '\r'.$this->specificConfirmDelete : self::$cache_lang['DeleteItem'].$name; + } + + $tpl->assign(array_merge($this->tpl_delete_link_vars, $data)); + + return $tpl->fetch(); + } } diff --git a/controllers/admin/AdminSlipController.php b/controllers/admin/AdminSlipController.php index cb003d82..b09d031e 100644 --- a/controllers/admin/AdminSlipController.php +++ b/controllers/admin/AdminSlipController.php @@ -29,174 +29,175 @@ */ class AdminSlipControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'order_slip'; - $this->className = 'OrderSlip'; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'order_slip'; + $this->className = 'OrderSlip'; - $this->_select = ' o.`id_shop`'; - $this->_join .= ' LEFT JOIN '._DB_PREFIX_.'orders o ON (o.`id_order` = a.`id_order`)'; - $this->_group = ' GROUP BY a.`id_order_slip`'; + $this->_select = ' o.`id_shop`'; + $this->_join .= ' LEFT JOIN '._DB_PREFIX_.'orders o ON (o.`id_order` = a.`id_order`)'; + $this->_group = ' GROUP BY a.`id_order_slip`'; - $this->fields_list = array( - 'id_order_slip' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'id_order' => array( - 'title' => $this->l('Order ID'), - 'align' => 'left', - 'class' => 'fixed-width-md' - ), - 'date_add' => array( - 'title' => $this->l('Date issued'), - 'type' => 'date', - 'align' => 'right' - ), - 'id_pdf' => array( - 'title' => $this->l('PDF'), - 'align' => 'center', - 'callback' => 'printPDFIcons', - 'orderby' => false, - 'search' => false, - 'remove_onclick' => true) - ); + $this->fields_list = array( + 'id_order_slip' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'id_order' => array( + 'title' => $this->l('Order ID'), + 'align' => 'left', + 'class' => 'fixed-width-md' + ), + 'date_add' => array( + 'title' => $this->l('Date issued'), + 'type' => 'date', + 'align' => 'right' + ), + 'id_pdf' => array( + 'title' => $this->l('PDF'), + 'align' => 'center', + 'callback' => 'printPDFIcons', + 'orderby' => false, + 'search' => false, + 'remove_onclick' => true) + ); - $this->_select = 'a.id_order_slip AS id_pdf'; - $this->optionTitle = $this->l('Slip'); + $this->_select = 'a.id_order_slip AS id_pdf'; + $this->optionTitle = $this->l('Slip'); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Credit slip options'), - 'fields' => array( - 'PS_CREDIT_SLIP_PREFIX' => array( - 'title' => $this->l('Credit slip prefix'), - 'desc' => $this->l('Prefix used for credit slips.'), - 'size' => 6, - 'type' => 'textLang' - ) - ), - 'submit' => array('title' => $this->l('Save')) - ) - ); + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Credit slip options'), + 'fields' => array( + 'PS_CREDIT_SLIP_PREFIX' => array( + 'title' => $this->l('Credit slip prefix'), + 'desc' => $this->l('Prefix used for credit slips.'), + 'size' => 6, + 'type' => 'textLang' + ) + ), + 'submit' => array('title' => $this->l('Save')) + ) + ); - parent::__construct(); + parent::__construct(); - $this->_where = Shop::addSqlRestriction(false, 'o'); - } + $this->_where = Shop::addSqlRestriction(false, 'o'); + } - public function initPageHeaderToolbar() - { - $this->page_header_toolbar_btn['generate_pdf'] = array( - 'href' => self::$currentIndex.'&token='.$this->token, - 'desc' => $this->l('Generate PDF', null, null, false), - 'icon' => 'process-icon-save-date' - ); + public function initPageHeaderToolbar() + { + $this->page_header_toolbar_btn['generate_pdf'] = array( + 'href' => self::$currentIndex.'&token='.$this->token, + 'desc' => $this->l('Generate PDF', null, null, false), + 'icon' => 'process-icon-save-date' + ); - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Print a PDF'), - 'icon' => 'icon-print' - ), - 'input' => array( - array( - 'type' => 'date', - 'label' => $this->l('From'), - 'name' => 'date_from', - 'maxlength' => 10, - 'required' => true, - 'hint' => $this->l('Format: 2011-12-31 (inclusive).') - ), - array( - 'type' => 'date', - 'label' => $this->l('To'), - 'name' => 'date_to', - 'maxlength' => 10, - 'required' => true, - 'hint' => $this->l('Format: 2012-12-31 (inclusive).') - ) - ), - 'submit' => array( - 'title' => $this->l('Generate PDF file'), - 'id' => 'submitPrint', - 'icon' => 'process-icon-download-alt' - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Print a PDF'), + 'icon' => 'icon-print' + ), + 'input' => array( + array( + 'type' => 'date', + 'label' => $this->l('From'), + 'name' => 'date_from', + 'maxlength' => 10, + 'required' => true, + 'hint' => $this->l('Format: 2011-12-31 (inclusive).') + ), + array( + 'type' => 'date', + 'label' => $this->l('To'), + 'name' => 'date_to', + 'maxlength' => 10, + 'required' => true, + 'hint' => $this->l('Format: 2012-12-31 (inclusive).') + ) + ), + 'submit' => array( + 'title' => $this->l('Generate PDF file'), + 'id' => 'submitPrint', + 'icon' => 'process-icon-download-alt' + ) + ); - $this->fields_value = array( - 'date_from' => date('Y-m-d'), - 'date_to' => date('Y-m-d') - ); + $this->fields_value = array( + 'date_from' => date('Y-m-d'), + 'date_to' => date('Y-m-d') + ); - $this->show_toolbar = false; - return parent::renderForm(); - } + $this->show_toolbar = false; + return parent::renderForm(); + } - public function postProcess() - { - if (Tools::getValue('submitAddorder_slip')) - { - if (!Validate::isDate(Tools::getValue('date_from'))) - $this->errors[] = $this->l('Invalid "From" date'); - if (!Validate::isDate(Tools::getValue('date_to'))) - $this->errors[] = $this->l('Invalid "To" date'); - if (!count($this->errors)) - { - $order_slips = OrderSlip::getSlipsIdByDate(Tools::getValue('date_from'), Tools::getValue('date_to')); - if (count($order_slips)) - Tools::redirectAdmin($this->context->link->getAdminLink('AdminPdf').'&submitAction=generateOrderSlipsPDF&date_from='.urlencode(Tools::getValue('date_from')).'&date_to='.urlencode(Tools::getValue('date_to'))); - $this->errors[] = $this->l('No order slips were found for this period.'); - } - } - else - return parent::postProcess(); - } + public function postProcess() + { + if (Tools::getValue('submitAddorder_slip')) { + if (!Validate::isDate(Tools::getValue('date_from'))) { + $this->errors[] = $this->l('Invalid "From" date'); + } + if (!Validate::isDate(Tools::getValue('date_to'))) { + $this->errors[] = $this->l('Invalid "To" date'); + } + if (!count($this->errors)) { + $order_slips = OrderSlip::getSlipsIdByDate(Tools::getValue('date_from'), Tools::getValue('date_to')); + if (count($order_slips)) { + Tools::redirectAdmin($this->context->link->getAdminLink('AdminPdf').'&submitAction=generateOrderSlipsPDF&date_from='.urlencode(Tools::getValue('date_from')).'&date_to='.urlencode(Tools::getValue('date_to'))); + } + $this->errors[] = $this->l('No order slips were found for this period.'); + } + } else { + return parent::postProcess(); + } + } - public function initContent() - { - $this->initTabModuleList(); - $this->initToolbar(); - $this->initPageHeaderToolbar(); - $this->content .= $this->renderList(); - $this->content .= $this->renderForm(); - $this->content .= $this->renderOptions(); + public function initContent() + { + $this->initTabModuleList(); + $this->initToolbar(); + $this->initPageHeaderToolbar(); + $this->content .= $this->renderList(); + $this->content .= $this->renderForm(); + $this->content .= $this->renderOptions(); - $this->context->smarty->assign(array( - 'content' => $this->content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } + $this->context->smarty->assign(array( + 'content' => $this->content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } - public function initToolbar() - { - $this->toolbar_btn['save-date'] = array( - 'href' => '#', - 'desc' => $this->l('Generate PDF file') - ); - } - - public function printPDFIcons($id_order_slip, $tr) - { - $order_slip = new OrderSlip((int)$id_order_slip); - if (!Validate::isLoadedObject($order_slip)) - return ''; + public function initToolbar() + { + $this->toolbar_btn['save-date'] = array( + 'href' => '#', + 'desc' => $this->l('Generate PDF file') + ); + } + + public function printPDFIcons($id_order_slip, $tr) + { + $order_slip = new OrderSlip((int)$id_order_slip); + if (!Validate::isLoadedObject($order_slip)) { + return ''; + } - $this->context->smarty->assign(array( - 'order_slip' => $order_slip, - 'tr' => $tr - )); + $this->context->smarty->assign(array( + 'order_slip' => $order_slip, + 'tr' => $tr + )); - return $this->createTemplate('_print_pdf_icon.tpl')->fetch(); - } + return $this->createTemplate('_print_pdf_icon.tpl')->fetch(); + } } - diff --git a/controllers/admin/AdminSpecificPriceRuleController.php b/controllers/admin/AdminSpecificPriceRuleController.php index 0eae1948..b6eccf78 100644 --- a/controllers/admin/AdminSpecificPriceRuleController.php +++ b/controllers/admin/AdminSpecificPriceRuleController.php @@ -29,342 +29,343 @@ */ class AdminSpecificPriceRuleControllerCore extends AdminController { - public $list_reduction_type; + public $list_reduction_type; - public function __construct() - { - $this->bootstrap = true; - $this->table = 'specific_price_rule'; - $this->className = 'SpecificPriceRule'; - $this->lang = false; - $this->multishop_context = Shop::CONTEXT_ALL; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'specific_price_rule'; + $this->className = 'SpecificPriceRule'; + $this->lang = false; + $this->multishop_context = Shop::CONTEXT_ALL; - /* if $_GET['id_shop'] is transmitted, virtual url can be loaded in config.php, so we wether transmit shop_id in herfs */ - if ($this->id_shop = (int)Tools::getValue('shop_id')) - { - $_GET['id_shop'] = $this->id_shop; - $_POST['id_shop'] = $this->id_shop; - } + /* if $_GET['id_shop'] is transmitted, virtual url can be loaded in config.php, so we wether transmit shop_id in herfs */ + if ($this->id_shop = (int)Tools::getValue('shop_id')) { + $_GET['id_shop'] = $this->id_shop; + $_POST['id_shop'] = $this->id_shop; + } - $this->list_reduction_type = array( - 'percentage' => $this->l('Percentage'), - 'amount' => $this->l('Amount') - ); + $this->list_reduction_type = array( + 'percentage' => $this->l('Percentage'), + 'amount' => $this->l('Amount') + ); - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->context = Context::getContext(); + $this->context = Context::getContext(); - $this->_select = 's.name shop_name, cu.name currency_name, cl.name country_name, gl.name group_name'; - $this->_join = 'LEFT JOIN '._DB_PREFIX_.'shop s ON (s.id_shop = a.id_shop) + $this->_select = 's.name shop_name, cu.name currency_name, cl.name country_name, gl.name group_name'; + $this->_join = 'LEFT JOIN '._DB_PREFIX_.'shop s ON (s.id_shop = a.id_shop) LEFT JOIN '._DB_PREFIX_.'currency cu ON (cu.id_currency = a.id_currency) LEFT JOIN '._DB_PREFIX_.'country_lang cl ON (cl.id_country = a.id_country AND cl.id_lang='.(int)$this->context->language->id.') LEFT JOIN '._DB_PREFIX_.'group_lang gl ON (gl.id_group = a.id_group AND gl.id_lang='.(int)$this->context->language->id.')'; - $this->_use_found_rows = false; + $this->_use_found_rows = false; - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->fields_list = array( - 'id_specific_price_rule' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Name'), - 'filter_key' => 'a!name', - 'width' => 'auto' - ), - 'shop_name' => array( - 'title' => $this->l('Shop'), - 'filter_key' => 's!name' - ), - 'currency_name' => array( - 'title' => $this->l('Currency'), - 'align' => 'center', - 'filter_key' => 'cu!name' - ), - 'country_name' => array( - 'title' => $this->l('Country'), - 'align' => 'center', - 'filter_key' => 'cl!name' - ), - 'group_name' => array( - 'title' => $this->l('Group'), - 'align' => 'center', - 'filter_key' => 'gl!name' - ), - 'from_quantity' => array( - 'title' => $this->l('From quantity'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'reduction_type' => array( - 'title' => $this->l('Reduction type'), - 'align' => 'center', - 'type' => 'select', - 'filter_key' => 'a!reduction_type', - 'list' => $this->list_reduction_type, - ), - 'reduction' => array( - 'title' => $this->l('Reduction'), - 'align' => 'center', - 'type' => 'decimal', - 'class' => 'fixed-width-xs' - ), - 'from' => array( - 'title' => $this->l('Beginning'), - 'align' => 'right', - 'type' => 'datetime', - ), - 'to' => array( - 'title' => $this->l('End'), - 'align' => 'right', - 'type' => 'datetime' - ), - ); + $this->fields_list = array( + 'id_specific_price_rule' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Name'), + 'filter_key' => 'a!name', + 'width' => 'auto' + ), + 'shop_name' => array( + 'title' => $this->l('Shop'), + 'filter_key' => 's!name' + ), + 'currency_name' => array( + 'title' => $this->l('Currency'), + 'align' => 'center', + 'filter_key' => 'cu!name' + ), + 'country_name' => array( + 'title' => $this->l('Country'), + 'align' => 'center', + 'filter_key' => 'cl!name' + ), + 'group_name' => array( + 'title' => $this->l('Group'), + 'align' => 'center', + 'filter_key' => 'gl!name' + ), + 'from_quantity' => array( + 'title' => $this->l('From quantity'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'reduction_type' => array( + 'title' => $this->l('Reduction type'), + 'align' => 'center', + 'type' => 'select', + 'filter_key' => 'a!reduction_type', + 'list' => $this->list_reduction_type, + ), + 'reduction' => array( + 'title' => $this->l('Reduction'), + 'align' => 'center', + 'type' => 'decimal', + 'class' => 'fixed-width-xs' + ), + 'from' => array( + 'title' => $this->l('Beginning'), + 'align' => 'right', + 'type' => 'datetime', + ), + 'to' => array( + 'title' => $this->l('End'), + 'align' => 'right', + 'type' => 'datetime' + ), + ); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_specific_price_rule'] = array( - 'href' => self::$currentIndex.'&addspecific_price_rule&token='.$this->token, - 'desc' => $this->l('Add new catalog price rule', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_specific_price_rule'] = array( + 'href' => self::$currentIndex.'&addspecific_price_rule&token='.$this->token, + 'desc' => $this->l('Add new catalog price rule', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - foreach ($this->_list as $k => $list) - if ($list['reduction_type'] == 'amount') - $this->_list[$k]['reduction_type'] = $this->list_reduction_type['amount']; - elseif ($list['reduction_type'] == 'percentage') - $this->_list[$k]['reduction_type'] = $this->list_reduction_type['percentage']; - } + foreach ($this->_list as $k => $list) { + if ($list['reduction_type'] == 'amount') { + $this->_list[$k]['reduction_type'] = $this->list_reduction_type['amount']; + } elseif ($list['reduction_type'] == 'percentage') { + $this->_list[$k]['reduction_type'] = $this->list_reduction_type['percentage']; + } + } + } - public function renderForm() - { - if (!$this->object->id) - $this->object->price = -1; + public function renderForm() + { + if (!$this->object->id) { + $this->object->price = -1; + } - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Catalog price rules'), - 'icon' => 'icon-dollar' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'maxlength' => 32, - 'required' => true, - 'hint' => $this->l('Forbidden characters').' <>;=#{}' - ), - array( - 'type' => 'select', - 'label' => $this->l('Shop'), - 'name' => 'shop_id', - 'options' => array( - 'query' => Shop::getShops(), - 'id' => 'id_shop', - 'name' => 'name' - ), - 'condition' => Shop::isFeatureActive(), - 'default_value' => Shop::getContextShopID() - ), - array( - 'type' => 'select', - 'label' => $this->l('Currency'), - 'name' => 'id_currency', - 'options' => array( - 'query' => array_merge(array(0 => array('id_currency' => 0, 'name' => $this->l('All currencies'))), Currency::getCurrencies()), - 'id' => 'id_currency', - 'name' => 'name' - ), - ), - array( - 'type' => 'select', - 'label' => $this->l('Country'), - 'name' => 'id_country', - 'options' => array( - 'query' => array_merge(array(0 => array('id_country' => 0, 'name' => $this->l('All countries'))), Country::getCountries((int)$this->context->language->id)), - 'id' => 'id_country', - 'name' => 'name' - ), - ), - array( - 'type' => 'select', - 'label' => $this->l('Group'), - 'name' => 'id_group', - 'options' => array( - 'query' => array_merge(array(0 => array('id_group' => 0, 'name' => $this->l('All groups'))), Group::getGroups((int)$this->context->language->id)), - 'id' => 'id_group', - 'name' => 'name' - ), - ), - array( - 'type' => 'text', - 'label' => $this->l('From quantity'), - 'name' => 'from_quantity', - 'maxlength' => 10, - 'required' => true, - ), - array( - 'type' => 'text', - 'label' => $this->l('Price (tax excl.)'), - 'name' => 'price', - 'disabled' => ($this->object->price == -1 ? 1 : 0), - 'maxlength' => 10, - 'suffix' => $this->context->currency->getSign('right'), + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Catalog price rules'), + 'icon' => 'icon-dollar' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'maxlength' => 32, + 'required' => true, + 'hint' => $this->l('Forbidden characters').' <>;=#{}' + ), + array( + 'type' => 'select', + 'label' => $this->l('Shop'), + 'name' => 'shop_id', + 'options' => array( + 'query' => Shop::getShops(), + 'id' => 'id_shop', + 'name' => 'name' + ), + 'condition' => Shop::isFeatureActive(), + 'default_value' => Shop::getContextShopID() + ), + array( + 'type' => 'select', + 'label' => $this->l('Currency'), + 'name' => 'id_currency', + 'options' => array( + 'query' => array_merge(array(0 => array('id_currency' => 0, 'name' => $this->l('All currencies'))), Currency::getCurrencies()), + 'id' => 'id_currency', + 'name' => 'name' + ), + ), + array( + 'type' => 'select', + 'label' => $this->l('Country'), + 'name' => 'id_country', + 'options' => array( + 'query' => array_merge(array(0 => array('id_country' => 0, 'name' => $this->l('All countries'))), Country::getCountries((int)$this->context->language->id)), + 'id' => 'id_country', + 'name' => 'name' + ), + ), + array( + 'type' => 'select', + 'label' => $this->l('Group'), + 'name' => 'id_group', + 'options' => array( + 'query' => array_merge(array(0 => array('id_group' => 0, 'name' => $this->l('All groups'))), Group::getGroups((int)$this->context->language->id)), + 'id' => 'id_group', + 'name' => 'name' + ), + ), + array( + 'type' => 'text', + 'label' => $this->l('From quantity'), + 'name' => 'from_quantity', + 'maxlength' => 10, + 'required' => true, + ), + array( + 'type' => 'text', + 'label' => $this->l('Price (tax excl.)'), + 'name' => 'price', + 'disabled' => ($this->object->price == -1 ? 1 : 0), + 'maxlength' => 10, + 'suffix' => $this->context->currency->getSign('right'), - ), - array( - 'type' => 'checkbox', - 'name' => 'leave_bprice', - 'values' => array( - 'query' => array( - array( - 'id' => 'on', - 'name' => $this->l('Leave base price'), - 'val' => '1', - 'checked' => '1' - ), - ), - 'id' => 'id', - 'name' => 'name' - ) - ), - array( - 'type' => 'datetime', - 'label' => $this->l('From'), - 'name' => 'from' - ), - array( - 'type' => 'datetime', - 'label' => $this->l('To'), - 'name' => 'to' - ), - array( - 'type' => 'select', - 'label' => $this->l('Reduction type'), - 'name' => 'reduction_type', - 'options' => array( - 'query' => array(array('reduction_type' => 'amount', 'name' => $this->l('Amount')), array('reduction_type' => 'percentage', 'name' => $this->l('Percentage'))), - 'id' => 'reduction_type', - 'name' => 'name' - ), - ), - array( - 'type' => 'select', - 'label' => $this->l('Reduction with or without taxes'), - 'name' => 'reduction_tax', - 'align' => 'center', - 'options' => array( - 'query' => array( - array('lab' => $this->l('Tax included'), 'val' => 1), - array('lab' => $this->l('Tax excluded'), 'val' => 0), - ), - 'id' => 'val', - 'name' => 'lab', - ) - ), - array( - 'type' => 'text', - 'label' => $this->l('Reduction'), - 'name' => 'reduction', - 'required' => true, - ), - ), - 'submit' => array( - 'title' => $this->l('Save') - ), - ); - if (($value = $this->getFieldValue($this->object, 'price')) != -1) - $price = number_format($value, 6); - else - $price = ''; + ), + array( + 'type' => 'checkbox', + 'name' => 'leave_bprice', + 'values' => array( + 'query' => array( + array( + 'id' => 'on', + 'name' => $this->l('Leave base price'), + 'val' => '1', + 'checked' => '1' + ), + ), + 'id' => 'id', + 'name' => 'name' + ) + ), + array( + 'type' => 'datetime', + 'label' => $this->l('From'), + 'name' => 'from' + ), + array( + 'type' => 'datetime', + 'label' => $this->l('To'), + 'name' => 'to' + ), + array( + 'type' => 'select', + 'label' => $this->l('Reduction type'), + 'name' => 'reduction_type', + 'options' => array( + 'query' => array(array('reduction_type' => 'amount', 'name' => $this->l('Amount')), array('reduction_type' => 'percentage', 'name' => $this->l('Percentage'))), + 'id' => 'reduction_type', + 'name' => 'name' + ), + ), + array( + 'type' => 'select', + 'label' => $this->l('Reduction with or without taxes'), + 'name' => 'reduction_tax', + 'align' => 'center', + 'options' => array( + 'query' => array( + array('lab' => $this->l('Tax included'), 'val' => 1), + array('lab' => $this->l('Tax excluded'), 'val' => 0), + ), + 'id' => 'val', + 'name' => 'lab', + ) + ), + array( + 'type' => 'text', + 'label' => $this->l('Reduction'), + 'name' => 'reduction', + 'required' => true, + ), + ), + 'submit' => array( + 'title' => $this->l('Save') + ), + ); + if (($value = $this->getFieldValue($this->object, 'price')) != -1) { + $price = number_format($value, 6); + } else { + $price = ''; + } - $this->fields_value = array( - 'price' => $price, - 'from_quantity' => (($value = $this->getFieldValue($this->object, 'from_quantity')) ? $value : 1), - 'reduction' => number_format((($value = $this->getFieldValue($this->object, 'reduction')) ? $value : 0), 6), - 'leave_bprice_on' => $price ? 0 : 1 - ); + $this->fields_value = array( + 'price' => $price, + 'from_quantity' => (($value = $this->getFieldValue($this->object, 'from_quantity')) ? $value : 1), + 'reduction' => number_format((($value = $this->getFieldValue($this->object, 'reduction')) ? $value : 0), 6), + 'leave_bprice_on' => $price ? 0 : 1 + ); - $attribute_groups = array(); - $attributes = Attribute::getAttributes((int)$this->context->language->id); - foreach ($attributes as $attribute) - { - if (!isset($attribute_groups[$attribute['id_attribute_group']])) - $attribute_groups[$attribute['id_attribute_group']] = array( - 'id_attribute_group' => $attribute['id_attribute_group'], - 'name' => $attribute['attribute_group'] - ); - $attribute_groups[$attribute['id_attribute_group']]['attributes'][] = array( - 'id_attribute' => $attribute['id_attribute'], - 'name' => $attribute['name'] - ); - } - $features = Feature::getFeatures((int)$this->context->language->id); - foreach ($features as &$feature) - $feature['values'] = FeatureValue::getFeatureValuesWithLang((int)$this->context->language->id, $feature['id_feature'], true); + $attribute_groups = array(); + $attributes = Attribute::getAttributes((int)$this->context->language->id); + foreach ($attributes as $attribute) { + if (!isset($attribute_groups[$attribute['id_attribute_group']])) { + $attribute_groups[$attribute['id_attribute_group']] = array( + 'id_attribute_group' => $attribute['id_attribute_group'], + 'name' => $attribute['attribute_group'] + ); + } + $attribute_groups[$attribute['id_attribute_group']]['attributes'][] = array( + 'id_attribute' => $attribute['id_attribute'], + 'name' => $attribute['name'] + ); + } + $features = Feature::getFeatures((int)$this->context->language->id); + foreach ($features as &$feature) { + $feature['values'] = FeatureValue::getFeatureValuesWithLang((int)$this->context->language->id, $feature['id_feature'], true); + } - $this->tpl_form_vars = array( - 'manufacturers' => Manufacturer::getManufacturers(), - 'suppliers' => Supplier::getSuppliers(), - 'attributes_group' => $attribute_groups, - 'features' => $features, - 'categories' => Category::getSimpleCategories((int)$this->context->language->id), - 'conditions' => $this->object->getConditions(), - 'is_multishop' => Shop::isFeatureActive() - ); - return parent::renderForm(); - } + $this->tpl_form_vars = array( + 'manufacturers' => Manufacturer::getManufacturers(), + 'suppliers' => Supplier::getSuppliers(), + 'attributes_group' => $attribute_groups, + 'features' => $features, + 'categories' => Category::getSimpleCategories((int)$this->context->language->id), + 'conditions' => $this->object->getConditions(), + 'is_multishop' => Shop::isFeatureActive() + ); + return parent::renderForm(); + } - public function processSave() - { - $_POST['price'] = Tools::getValue('leave_bprice_on') ? '-1' : Tools::getValue('price'); - if (Validate::isLoadedObject(($object = parent::processSave()))) - { - /** @var SpecificPriceRule $object */ - $object->deleteConditions(); - foreach ($_POST as $key => $values) - { - if (preg_match('/^condition_group_([0-9]+)$/Ui', $key, $condition_group)) - { - $conditions = array(); - foreach ($values as $value) - { - $condition = explode('_', $value); - $conditions[] = array('type' => $condition[0], 'value' => $condition[1]); - } - $object->addConditions($conditions); - } - } - $object->apply(); - return $object; - } - } + public function processSave() + { + $_POST['price'] = Tools::getValue('leave_bprice_on') ? '-1' : Tools::getValue('price'); + if (Validate::isLoadedObject(($object = parent::processSave()))) { + /** @var SpecificPriceRule $object */ + $object->deleteConditions(); + foreach ($_POST as $key => $values) { + if (preg_match('/^condition_group_([0-9]+)$/Ui', $key, $condition_group)) { + $conditions = array(); + foreach ($values as $value) { + $condition = explode('_', $value); + $conditions[] = array('type' => $condition[0], 'value' => $condition[1]); + } + $object->addConditions($conditions); + } + } + $object->apply(); + return $object; + } + } - public function postProcess() - { - Tools::clearSmartyCache(); - return parent::postProcess(); - } + public function postProcess() + { + Tools::clearSmartyCache(); + return parent::postProcess(); + } } diff --git a/controllers/admin/AdminStatesController.php b/controllers/admin/AdminStatesController.php index 841ba4d9..30de83e9 100644 --- a/controllers/admin/AdminStatesController.php +++ b/controllers/admin/AdminStatesController.php @@ -29,249 +29,249 @@ */ class AdminStatesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'state'; - $this->className = 'State'; - $this->lang = false; - $this->requiredDatabase = true; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'state'; + $this->className = 'State'; + $this->lang = false; + $this->requiredDatabase = true; - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->context = Context::getContext(); + $this->context = Context::getContext(); - if (!Tools::getValue('realedit')) - $this->deleted = false; + if (!Tools::getValue('realedit')) { + $this->deleted = false; + } - $this->bulk_actions = array( - 'delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?')), - 'affectzone' => array('text' => $this->l('Affect a new zone')) - ); + $this->bulk_actions = array( + 'delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?')), + 'affectzone' => array('text' => $this->l('Affect a new zone')) + ); - $this->_select = 'z.`name` AS zone, cl.`name` AS country'; - $this->_join = ' + $this->_select = 'z.`name` AS zone, cl.`name` AS country'; + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'zone` z ON (z.`id_zone` = a.`id_zone`) LEFT JOIN `'._DB_PREFIX_.'country_lang` cl ON (cl.`id_country` = a.`id_country` AND cl.id_lang = '.(int)$this->context->language->id.')'; - $this->_use_found_rows = false; + $this->_use_found_rows = false; - $countries_array = $zones_array = array(); - $this->zones = Zone::getZones(); - $this->countries = Country::getCountries($this->context->language->id, false, true, false); - foreach ($this->zones as $zone) - $zones_array[$zone['id_zone']] = $zone['name']; - foreach ($this->countries as $country) - $countries_array[$country['id_country']] = $country['name']; + $countries_array = $zones_array = array(); + $this->zones = Zone::getZones(); + $this->countries = Country::getCountries($this->context->language->id, false, true, false); + foreach ($this->zones as $zone) { + $zones_array[$zone['id_zone']] = $zone['name']; + } + foreach ($this->countries as $country) { + $countries_array[$country['id_country']] = $country['name']; + } - $this->fields_list = array( - 'id_state' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Name'), - 'filter_key' => 'a!name' - ), - 'iso_code' => array( - 'title' => $this->l('ISO code'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'zone' => array( - 'title' => $this->l('Zone'), - 'type' => 'select', - 'list' => $zones_array, - 'filter_key' => 'z!id_zone', - 'filter_type' => 'int', - 'order_key' => 'zone' - ), - 'country' => array( - 'title' => $this->l('Country'), - 'type' => 'select', - 'list' => $countries_array, - 'filter_key' => 'cl!id_country', - 'filter_type' => 'int', - 'order_key' => 'country' - ), - 'active' => array( - 'title' => $this->l('Enabled'), - 'active' => 'status', - 'filter_key' => 'a!active', - 'align' => 'center', - 'type' => 'bool', - 'orderby' => false, - 'class' => 'fixed-width-sm' - ) - ); + $this->fields_list = array( + 'id_state' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Name'), + 'filter_key' => 'a!name' + ), + 'iso_code' => array( + 'title' => $this->l('ISO code'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'zone' => array( + 'title' => $this->l('Zone'), + 'type' => 'select', + 'list' => $zones_array, + 'filter_key' => 'z!id_zone', + 'filter_type' => 'int', + 'order_key' => 'zone' + ), + 'country' => array( + 'title' => $this->l('Country'), + 'type' => 'select', + 'list' => $countries_array, + 'filter_key' => 'cl!id_country', + 'filter_type' => 'int', + 'order_key' => 'country' + ), + 'active' => array( + 'title' => $this->l('Enabled'), + 'active' => 'status', + 'filter_key' => 'a!active', + 'align' => 'center', + 'type' => 'bool', + 'orderby' => false, + 'class' => 'fixed-width-sm' + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_state'] = array( - 'href' => self::$currentIndex.'&addstate&token='.$this->token, - 'desc' => $this->l('Add new state', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_state'] = array( + 'href' => self::$currentIndex.'&addstate&token='.$this->token, + 'desc' => $this->l('Add new state', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('States'), - 'icon' => 'icon-globe' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'maxlength' => 32, - 'required' => true, - 'hint' => $this->l('Provide the State name to be display in addresses and on invoices.') - ), - array( - 'type' => 'text', - 'label' => $this->l('ISO code'), - 'name' => 'iso_code', - 'maxlength' => 7, - 'required' => true, - 'class' => 'uppercase', - 'hint' => $this->l('1 to 4 letter ISO code.').' '.$this->l('You can prefix it with the country ISO code if needed.') - ), - array( - 'type' => 'select', - 'label' => $this->l('Country'), - 'name' => 'id_country', - 'required' => true, - 'default_value' => (int)$this->context->country->id, - 'options' => array( - 'query' => Country::getCountries($this->context->language->id, false, true), - 'id' => 'id_country', - 'name' => 'name', - ), - 'hint' => $this->l('Country where the state is located.').' '.$this->l('Only the countries with the option "contains states" enabled are displayed.') - ), - array( - 'type' => 'select', - 'label' => $this->l('Zone'), - 'name' => 'id_zone', - 'required' => true, - 'options' => array( - 'query' => Zone::getZones(), - 'id' => 'id_zone', - 'name' => 'name' - ), - 'hint' => array( - $this->l('Geographical region where this state is located.'), - $this->l('Used for shipping') - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Status'), - 'name' => 'active', - 'required' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Enabled').'" title="'.$this->l('Enabled').'" />' - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('Disabled').'" title="'.$this->l('Disabled').'" />' - ) - ) - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('States'), + 'icon' => 'icon-globe' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'maxlength' => 32, + 'required' => true, + 'hint' => $this->l('Provide the State name to be display in addresses and on invoices.') + ), + array( + 'type' => 'text', + 'label' => $this->l('ISO code'), + 'name' => 'iso_code', + 'maxlength' => 7, + 'required' => true, + 'class' => 'uppercase', + 'hint' => $this->l('1 to 4 letter ISO code.').' '.$this->l('You can prefix it with the country ISO code if needed.') + ), + array( + 'type' => 'select', + 'label' => $this->l('Country'), + 'name' => 'id_country', + 'required' => true, + 'default_value' => (int)$this->context->country->id, + 'options' => array( + 'query' => Country::getCountries($this->context->language->id, false, true), + 'id' => 'id_country', + 'name' => 'name', + ), + 'hint' => $this->l('Country where the state is located.').' '.$this->l('Only the countries with the option "contains states" enabled are displayed.') + ), + array( + 'type' => 'select', + 'label' => $this->l('Zone'), + 'name' => 'id_zone', + 'required' => true, + 'options' => array( + 'query' => Zone::getZones(), + 'id' => 'id_zone', + 'name' => 'name' + ), + 'hint' => array( + $this->l('Geographical region where this state is located.'), + $this->l('Used for shipping') + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Status'), + 'name' => 'active', + 'required' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => '<img src="../img/admin/enabled.gif" alt="'.$this->l('Enabled').'" title="'.$this->l('Enabled').'" />' + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => '<img src="../img/admin/disabled.gif" alt="'.$this->l('Disabled').'" title="'.$this->l('Disabled').'" />' + ) + ) + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function postProcess() - { - if (Tools::isSubmit($this->table.'Orderby') || Tools::isSubmit($this->table.'Orderway')) - $this->filter = true; + public function postProcess() + { + if (Tools::isSubmit($this->table.'Orderby') || Tools::isSubmit($this->table.'Orderway')) { + $this->filter = true; + } - // Idiot-proof controls - if (!Tools::getValue('id_'.$this->table)) - { - if (Validate::isStateIsoCode(Tools::getValue('iso_code')) && State::getIdByIso(Tools::getValue('iso_code'), Tools::getValue('id_country'))) - $this->errors[] = Tools::displayError('This ISO code already exists. You cannot create two states with the same ISO code.'); - } - elseif (Validate::isStateIsoCode(Tools::getValue('iso_code'))) - { - $id_state = State::getIdByIso(Tools::getValue('iso_code'), Tools::getValue('id_country')); - if ($id_state && $id_state != Tools::getValue('id_'.$this->table)) - $this->errors[] = Tools::displayError('This ISO code already exists. You cannot create two states with the same ISO code.'); - } + // Idiot-proof controls + if (!Tools::getValue('id_'.$this->table)) { + if (Validate::isStateIsoCode(Tools::getValue('iso_code')) && State::getIdByIso(Tools::getValue('iso_code'), Tools::getValue('id_country'))) { + $this->errors[] = Tools::displayError('This ISO code already exists. You cannot create two states with the same ISO code.'); + } + } elseif (Validate::isStateIsoCode(Tools::getValue('iso_code'))) { + $id_state = State::getIdByIso(Tools::getValue('iso_code'), Tools::getValue('id_country')); + if ($id_state && $id_state != Tools::getValue('id_'.$this->table)) { + $this->errors[] = Tools::displayError('This ISO code already exists. You cannot create two states with the same ISO code.'); + } + } - /* Delete state */ - if (Tools::isSubmit('delete'.$this->table)) - { - if ($this->tabAccess['delete'] === '1') - { - if (Validate::isLoadedObject($object = $this->loadObject())) - { - /** @var State $object */ - if (!$object->isUsed()) - { - if ($object->delete()) - Tools::redirectAdmin(self::$currentIndex.'&conf=1&token='.(Tools::getValue('token') ? Tools::getValue('token') : $this->token)); - $this->errors[] = Tools::displayError('An error occurred during deletion.'); - } - else - $this->errors[] = Tools::displayError('This state was used in at least one address. It cannot be removed.'); - } - else - $this->errors[] = Tools::displayError('An error occurred while deleting the object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } + /* Delete state */ + if (Tools::isSubmit('delete'.$this->table)) { + if ($this->tabAccess['delete'] === '1') { + if (Validate::isLoadedObject($object = $this->loadObject())) { + /** @var State $object */ + if (!$object->isUsed()) { + if ($object->delete()) { + Tools::redirectAdmin(self::$currentIndex.'&conf=1&token='.(Tools::getValue('token') ? Tools::getValue('token') : $this->token)); + } + $this->errors[] = Tools::displayError('An error occurred during deletion.'); + } else { + $this->errors[] = Tools::displayError('This state was used in at least one address. It cannot be removed.'); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while deleting the object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } - if (!count($this->errors)) - parent::postProcess(); - } + if (!count($this->errors)) { + parent::postProcess(); + } + } - protected function displayAjaxStates() - { - $states = Db::getInstance()->executeS(' + protected function displayAjaxStates() + { + $states = Db::getInstance()->executeS(' SELECT s.id_state, s.name FROM '._DB_PREFIX_.'state s LEFT JOIN '._DB_PREFIX_.'country c ON (s.`id_country` = c.`id_country`) WHERE s.id_country = '.(int)(Tools::getValue('id_country')).' AND s.active = 1 AND c.`contains_states` = 1 ORDER BY s.`name` ASC'); - if (is_array($states) AND !empty($states)) - { - $list = ''; - if ((bool)Tools::getValue('no_empty') != true) - { - $empty_value = (Tools::isSubmit('empty_value')) ? Tools::getValue('empty_value') : '-'; - $list = '<option value="0">'.Tools::htmlentitiesUTF8($empty_value).'</option>'."\n"; - } + if (is_array($states) and !empty($states)) { + $list = ''; + if ((bool)Tools::getValue('no_empty') != true) { + $empty_value = (Tools::isSubmit('empty_value')) ? Tools::getValue('empty_value') : '-'; + $list = '<option value="0">'.Tools::htmlentitiesUTF8($empty_value).'</option>'."\n"; + } - foreach ($states as $state) - $list .= '<option value="'.(int)($state['id_state']).'"'.((isset($_GET['id_state']) AND $_GET['id_state'] == $state['id_state']) ? ' selected="selected"' : '').'>'.$state['name'].'</option>'."\n"; - } - else - $list = 'false'; - - die($list); - } + foreach ($states as $state) { + $list .= '<option value="'.(int)($state['id_state']).'"'.((isset($_GET['id_state']) and $_GET['id_state'] == $state['id_state']) ? ' selected="selected"' : '').'>'.$state['name'].'</option>'."\n"; + } + } else { + $list = 'false'; + } + die($list); + } } diff --git a/controllers/admin/AdminStatsController.php b/controllers/admin/AdminStatsController.php index 5837f38a..b2645efb 100644 --- a/controllers/admin/AdminStatsController.php +++ b/controllers/admin/AdminStatsController.php @@ -26,305 +26,306 @@ class AdminStatsControllerCore extends AdminStatsTabController { - public static function getVisits($unique = false, $date_from, $date_to, $granularity = false) - { - $visits = ($granularity == false) ? 0 : array(); - /** @var Gapi $gapi */ - $gapi = Module::isInstalled('gapi') ? Module::getInstanceByName('gapi') : false; - if (Validate::isLoadedObject($gapi) && $gapi->isConfigured()) - { - $metric = $unique ? 'visitors' : 'visits'; - if ($result = $gapi->requestReportData($granularity ? 'ga:date' : '', 'ga:'.$metric, $date_from, $date_to, null, null, 1, 5000)) - foreach ($result as $row) - if ($granularity == 'day') - $visits[strtotime(preg_replace('/^([0-9]{4})([0-9]{2})([0-9]{2})$/', '$1-$2-$3', $row['dimensions']['date']))] = $row['metrics'][$metric]; - elseif ($granularity == 'month') - { - if (!isset($visits[strtotime(preg_replace('/^([0-9]{4})([0-9]{2})([0-9]{2})$/', '$1-$2-01', $row['dimensions']['date']))])) - $visits[strtotime(preg_replace('/^([0-9]{4})([0-9]{2})([0-9]{2})$/', '$1-$2-01', $row['dimensions']['date']))] = 0; - $visits[strtotime(preg_replace('/^([0-9]{4})([0-9]{2})([0-9]{2})$/', '$1-$2-01', $row['dimensions']['date']))] += $row['metrics'][$metric]; - } - else - $visits = $row['metrics'][$metric]; - } - else - { - if ($granularity == 'day') - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' + public static function getVisits($unique = false, $date_from, $date_to, $granularity = false) + { + $visits = ($granularity == false) ? 0 : array(); + /** @var Gapi $gapi */ + $gapi = Module::isInstalled('gapi') ? Module::getInstanceByName('gapi') : false; + if (Validate::isLoadedObject($gapi) && $gapi->isConfigured()) { + $metric = $unique ? 'visitors' : 'visits'; + if ($result = $gapi->requestReportData($granularity ? 'ga:date' : '', 'ga:'.$metric, $date_from, $date_to, null, null, 1, 5000)) { + foreach ($result as $row) { + if ($granularity == 'day') { + $visits[strtotime(preg_replace('/^([0-9]{4})([0-9]{2})([0-9]{2})$/', '$1-$2-$3', $row['dimensions']['date']))] = $row['metrics'][$metric]; + } elseif ($granularity == 'month') { + if (!isset($visits[strtotime(preg_replace('/^([0-9]{4})([0-9]{2})([0-9]{2})$/', '$1-$2-01', $row['dimensions']['date']))])) { + $visits[strtotime(preg_replace('/^([0-9]{4})([0-9]{2})([0-9]{2})$/', '$1-$2-01', $row['dimensions']['date']))] = 0; + } + $visits[strtotime(preg_replace('/^([0-9]{4})([0-9]{2})([0-9]{2})$/', '$1-$2-01', $row['dimensions']['date']))] += $row['metrics'][$metric]; + } else { + $visits = $row['metrics'][$metric]; + } + } + } + } else { + if ($granularity == 'day') { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT LEFT(`date_add`, 10) as date, COUNT('.($unique ? 'DISTINCT id_guest' : '*').') as visits FROM `'._DB_PREFIX_.'connections` WHERE `date_add` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" '.Shop::addSqlRestriction().' GROUP BY LEFT(`date_add`, 10)'); - foreach ($result as $row) - $visits[strtotime($row['date'])] = $row['visits']; - } - elseif ($granularity == 'month') - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' + foreach ($result as $row) { + $visits[strtotime($row['date'])] = $row['visits']; + } + } elseif ($granularity == 'month') { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT LEFT(`date_add`, 7) as date, COUNT('.($unique ? 'DISTINCT id_guest' : '*').') as visits FROM `'._DB_PREFIX_.'connections` WHERE `date_add` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" '.Shop::addSqlRestriction().' GROUP BY LEFT(`date_add`, 7)'); - foreach ($result as $row) - $visits[strtotime($row['date'].'-01')] = $row['visits']; - } - else - $visits = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + foreach ($result as $row) { + $visits[strtotime($row['date'].'-01')] = $row['visits']; + } + } else { + $visits = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT('.($unique ? 'DISTINCT id_guest' : '*').') as visits FROM `'._DB_PREFIX_.'connections` WHERE `date_add` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" '.Shop::addSqlRestriction()); - } - return $visits; - } + } + } + return $visits; + } - public static function getAbandonedCarts($date_from, $date_to) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getAbandonedCarts($date_from, $date_to) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(DISTINCT id_guest) FROM `'._DB_PREFIX_.'cart` WHERE `date_add` BETWEEN "'.pSQL($date_from).'" AND "'.pSQL($date_to).'" AND NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'orders` WHERE `'._DB_PREFIX_.'orders`.id_cart = `'._DB_PREFIX_.'cart`.id_cart) '.Shop::addSqlRestriction()); - } + } - public static function getInstalledModules() - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getInstalledModules() + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(DISTINCT m.`id_module`) FROM `'._DB_PREFIX_.'module` m '.Shop::addSqlAssociation('module', 'm')); - } + } - public static function getDisabledModules() - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getDisabledModules() + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'module` m '.Shop::addSqlAssociation('module', 'm', false).' WHERE module_shop.id_module IS NULL OR m.active = 0'); - } + } - public static function getModulesToUpdate() - { - $context = Context::getContext(); - $logged_on_addons = false; - if (isset($context->cookie->username_addons) && isset($context->cookie->password_addons) - && !empty($context->cookie->username_addons) && !empty($context->cookie->password_addons)) - $logged_on_addons = true; - $modules = Module::getModulesOnDisk(true, $logged_on_addons, $context->employee->id); - $upgrade_available = 0; - foreach ($modules as $km => $module) - if ($module->installed && isset($module->version_addons) && $module->version_addons) // SimpleXMLElement - ++$upgrade_available; - return $upgrade_available; - } + public static function getModulesToUpdate() + { + $context = Context::getContext(); + $logged_on_addons = false; + if (isset($context->cookie->username_addons) && isset($context->cookie->password_addons) + && !empty($context->cookie->username_addons) && !empty($context->cookie->password_addons)) { + $logged_on_addons = true; + } + $modules = Module::getModulesOnDisk(true, $logged_on_addons, $context->employee->id); + $upgrade_available = 0; + foreach ($modules as $km => $module) { + if ($module->installed && isset($module->version_addons) && $module->version_addons) { // SimpleXMLElement + ++$upgrade_available; + } + } + return $upgrade_available; + } - public static function getPercentProductStock() - { - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + public static function getPercentProductStock() + { + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT SUM(IF(IFNULL(stock.quantity, 0) > 0, 1, 0)) as with_stock, COUNT(*) as products FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON p.id_product = pa.id_product '.Product::sqlStock('p', 'pa').' WHERE product_shop.active = 1'); - return round($row['products'] ? 100 * $row['with_stock'] / $row['products'] : 0, 2).'%'; - } + return round($row['products'] ? 100 * $row['with_stock'] / $row['products'] : 0, 2).'%'; + } - public static function getPercentProductOutOfStock() - { - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + public static function getPercentProductOutOfStock() + { + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT SUM(IF(IFNULL(stock.quantity, 0) = 0, 1, 0)) as without_stock, COUNT(*) as products FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON p.id_product = pa.id_product '.Product::sqlStock('p', 'pa').' WHERE product_shop.active = 1'); - return round($row['products'] ? 100 * $row['without_stock'] / $row['products'] : 0, 2).'%'; - } + return round($row['products'] ? 100 * $row['without_stock'] / $row['products'] : 0, 2).'%'; + } - public static function getProductAverageGrossMargin() - { - $sql = 'SELECT AVG(1 - (IF(IFNULL(product_attribute_shop.wholesale_price, 0) = 0, product_shop.wholesale_price,product_attribute_shop.wholesale_price) / (IFNULL(product_attribute_shop.price, 0) + product_shop.price))) + public static function getProductAverageGrossMargin() + { + $sql = 'SELECT AVG(1 - (IF(IFNULL(product_attribute_shop.wholesale_price, 0) = 0, product_shop.wholesale_price,product_attribute_shop.wholesale_price) / (IFNULL(product_attribute_shop.price, 0) + product_shop.price))) FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON p.id_product = pa.id_product '.Shop::addSqlAssociation('product_attribute', 'pa', false).' WHERE product_shop.active = 1'; - $value = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); - return round(100 * $value, 2).'%'; - } + $value = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); + return round(100 * $value, 2).'%'; + } - public static function getDisabledCategories() - { - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getDisabledCategories() + { + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'category` c '.Shop::addSqlAssociation('category', 'c').' WHERE c.active = 0'); - } + } - public static function getTotalCategories() - { - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getTotalCategories() + { + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'category` c '.Shop::addSqlAssociation('category', 'c')); - } + } - public static function getDisabledProducts() - { - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getDisabledProducts() + { + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' WHERE product_shop.active = 0'); - } + } - public static function getTotalProducts() - { - return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getTotalProducts() + { + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p')); - } + } - public static function getTotalSales($date_from, $date_to, $granularity = false) - { - if ($granularity == 'day') - { - $sales = array(); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' + public static function getTotalSales($date_from, $date_to, $granularity = false) + { + if ($granularity == 'day') { + $sales = array(); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT LEFT(`invoice_date`, 10) as date, SUM(total_paid_tax_excl / o.conversion_rate) as sales FROM `'._DB_PREFIX_.'orders` o LEFT JOIN `'._DB_PREFIX_.'order_state` os ON o.current_state = os.id_order_state WHERE `invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" AND os.logable = 1 '.Shop::addSqlRestriction(false, 'o').' GROUP BY LEFT(`invoice_date`, 10)'); - foreach ($result as $row) - $sales[strtotime($row['date'])] = $row['sales']; - return $sales; - } - elseif ($granularity == 'month') - { - $sales = array(); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' + foreach ($result as $row) { + $sales[strtotime($row['date'])] = $row['sales']; + } + return $sales; + } elseif ($granularity == 'month') { + $sales = array(); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT LEFT(`invoice_date`, 7) as date, SUM(total_paid_tax_excl / o.conversion_rate) as sales FROM `'._DB_PREFIX_.'orders` o LEFT JOIN `'._DB_PREFIX_.'order_state` os ON o.current_state = os.id_order_state WHERE `invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" AND os.logable = 1 '.Shop::addSqlRestriction(false, 'o').' GROUP BY LEFT(`invoice_date`, 7)'); - foreach ($result as $row) - $sales[strtotime($row['date'].'-01')] = $row['sales']; - return $sales; - } - else - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + foreach ($result as $row) { + $sales[strtotime($row['date'].'-01')] = $row['sales']; + } + return $sales; + } else { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT SUM(total_paid_tax_excl / o.conversion_rate) FROM `'._DB_PREFIX_.'orders` o LEFT JOIN `'._DB_PREFIX_.'order_state` os ON o.current_state = os.id_order_state WHERE `invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" AND os.logable = 1 '.Shop::addSqlRestriction(false, 'o')); - } + } + } - public static function get8020SalesCatalog($date_from, $date_to) - { - $distinct_products = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function get8020SalesCatalog($date_from, $date_to) + { + $distinct_products = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(DISTINCT od.product_id) FROM `'._DB_PREFIX_.'orders` o LEFT JOIN `'._DB_PREFIX_.'order_detail` od ON o.id_order = od.id_order WHERE `invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" '.Shop::addSqlRestriction(false, 'o')); - if (!$distinct_products) - return '0%'; - return round(100 * $distinct_products / AdminStatsController::getTotalProducts()).'%'; - } + if (!$distinct_products) { + return '0%'; + } + return round(100 * $distinct_products / AdminStatsController::getTotalProducts()).'%'; + } - public static function getOrders($date_from, $date_to, $granularity = false) - { - if ($granularity == 'day') - { - $orders = array(); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' + public static function getOrders($date_from, $date_to, $granularity = false) + { + if ($granularity == 'day') { + $orders = array(); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT LEFT(`invoice_date`, 10) as date, COUNT(*) as orders FROM `'._DB_PREFIX_.'orders` o LEFT JOIN `'._DB_PREFIX_.'order_state` os ON o.current_state = os.id_order_state WHERE `invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" AND os.logable = 1 '.Shop::addSqlRestriction(false, 'o').' GROUP BY LEFT(`invoice_date`, 10)'); - foreach ($result as $row) - $orders[strtotime($row['date'])] = $row['orders']; - return $orders; - } - elseif ($granularity == 'month') - { - $orders = array(); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' + foreach ($result as $row) { + $orders[strtotime($row['date'])] = $row['orders']; + } + return $orders; + } elseif ($granularity == 'month') { + $orders = array(); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT LEFT(`invoice_date`, 7) as date, COUNT(*) as orders FROM `'._DB_PREFIX_.'orders` o LEFT JOIN `'._DB_PREFIX_.'order_state` os ON o.current_state = os.id_order_state WHERE `invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" AND os.logable = 1 '.Shop::addSqlRestriction(false, 'o').' GROUP BY LEFT(`invoice_date`, 7)'); - foreach ($result as $row) - $orders[strtotime($row['date'].'-01')] = $row['orders']; - return $orders; - } - else - $orders = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + foreach ($result as $row) { + $orders[strtotime($row['date'].'-01')] = $row['orders']; + } + return $orders; + } else { + $orders = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(*) as orders FROM `'._DB_PREFIX_.'orders` o LEFT JOIN `'._DB_PREFIX_.'order_state` os ON o.current_state = os.id_order_state WHERE `invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" AND os.logable = 1 '.Shop::addSqlRestriction(false, 'o')); + } - return $orders; - } + return $orders; + } - public static function getEmptyCategories() - { - $total = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getEmptyCategories() + { + $total = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'category` c '.Shop::addSqlAssociation('category', 'c').' AND c.active = 1 AND c.nright = c.nleft + 1'); - $used = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + $used = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(DISTINCT cp.id_category) FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON c.id_category = cp.id_category '.Shop::addSqlAssociation('category', 'c').' AND c.active = 1 AND c.nright = c.nleft + 1'); - return intval($total - $used); - } + return intval($total - $used); + } - public static function getCustomerMainGender() - { - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + public static function getCustomerMainGender() + { + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT SUM(IF(g.id_gender IS NOT NULL, 1, 0)) as total, SUM(IF(type = 0, 1, 0)) as male, SUM(IF(type = 1, 1, 0)) as female, SUM(IF(type = 2, 1, 0)) as neutral FROM `'._DB_PREFIX_.'customer` c LEFT JOIN `'._DB_PREFIX_.'gender` g ON c.id_gender = g.id_gender WHERE c.active = 1 '.Shop::addSqlRestriction()); - if (!$row['total']) - return false; - elseif ($row['male'] > $row['female'] && $row['male'] >= $row['neutral']) - return array('type' => 'male', 'value' => round(100 * $row['male'] / $row['total'])); - elseif ($row['female'] >= $row['male'] && $row['female'] >= $row['neutral']) - return array('type' => 'female', 'value' => round(100 * $row['female'] / $row['total'])); - return array('type' => 'neutral', 'value' => round(100 * $row['neutral'] / $row['total'])); - } + if (!$row['total']) { + return false; + } elseif ($row['male'] > $row['female'] && $row['male'] >= $row['neutral']) { + return array('type' => 'male', 'value' => round(100 * $row['male'] / $row['total'])); + } elseif ($row['female'] >= $row['male'] && $row['female'] >= $row['neutral']) { + return array('type' => 'female', 'value' => round(100 * $row['female'] / $row['total'])); + } + return array('type' => 'neutral', 'value' => round(100 * $row['neutral'] / $row['total'])); + } - public static function getBestCategory($date_from, $date_to) - { - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getBestCategory($date_from, $date_to) + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT ca.`id_category` FROM `'._DB_PREFIX_.'category` ca LEFT JOIN `'._DB_PREFIX_.'category_product` capr ON ca.`id_category` = capr.`id_category` @@ -345,41 +346,42 @@ class AdminStatsControllerCore extends AdminStatsTabController WHERE ca.`level_depth` > 1 GROUP BY ca.`id_category` ORDER BY SUM(t.`totalPriceSold`) DESC'); - } + } - public static function getMainCountry($date_from, $date_to) - { - $total_orders = AdminStatsController::getOrders($date_from, $date_to); - if (!$total_orders) - return false; - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + public static function getMainCountry($date_from, $date_to) + { + $total_orders = AdminStatsController::getOrders($date_from, $date_to); + if (!$total_orders) { + return false; + } + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT a.id_country, COUNT(*) as orders FROM `'._DB_PREFIX_.'orders` o LEFT JOIN `'._DB_PREFIX_.'address` a ON o.id_address_delivery = a.id_address WHERE `invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" '.Shop::addSqlRestriction()); - $row['orders'] = round(100 * $row['orders'] / $total_orders, 1); - return $row; - } + $row['orders'] = round(100 * $row['orders'] / $total_orders, 1); + return $row; + } - public static function getAverageCustomerAge() - { - $value = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + public static function getAverageCustomerAge() + { + $value = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT AVG(DATEDIFF("'.date('Y-m-d').' 00:00:00", birthday)) FROM `'._DB_PREFIX_.'customer` c WHERE active = 1 AND birthday IS NOT NULL AND birthday != "0000-00-00" '.Shop::addSqlRestriction()); - return round($value / 365); - } + return round($value / 365); + } - public static function getPendingMessages() - { - return CustomerThread::getTotalCustomerThreads('status LIKE "%pending%" OR status = "open"'.Shop::addSqlRestriction()); - } + public static function getPendingMessages() + { + return CustomerThread::getTotalCustomerThreads('status LIKE "%pending%" OR status = "open"'.Shop::addSqlRestriction()); + } - public static function getAverageMessageResponseTime($date_from, $date_to) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getAverageMessageResponseTime($date_from, $date_to) + { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT MIN(cm1.date_add) as question, MIN(cm2.date_add) as reply FROM `'._DB_PREFIX_.'customer_message` cm1 INNER JOIN `'._DB_PREFIX_.'customer_message` cm2 ON (cm1.id_customer_thread = cm2.id_customer_thread AND cm1.date_add < cm2.date_add) @@ -388,21 +390,21 @@ class AdminStatsControllerCore extends AdminStatsTabController AND cm1.id_employee = 0 AND cm2.id_employee != 0 '.Shop::addSqlRestriction().' GROUP BY cm1.id_customer_thread'); - $total_questions = $total_replies = $threads = 0; - foreach ($result as $row) - { - ++$threads; - $total_questions += strtotime($row['question']); - $total_replies += strtotime($row['reply']); - } - if (!$threads) - return 0; - return round(($total_replies - $total_questions) / $threads / 3600, 1); - } + $total_questions = $total_replies = $threads = 0; + foreach ($result as $row) { + ++$threads; + $total_questions += strtotime($row['question']); + $total_replies += strtotime($row['reply']); + } + if (!$threads) { + return 0; + } + return round(($total_replies - $total_questions) / $threads / 3600, 1); + } - public static function getMessagesPerThread($date_from, $date_to) - { - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + public static function getMessagesPerThread($date_from, $date_to) + { + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT COUNT(*) as messages FROM `'._DB_PREFIX_.'customer_thread` ct LEFT JOIN `'._DB_PREFIX_.'customer_message` cm ON (ct.id_customer_thread = cm.id_customer_thread) @@ -410,23 +412,22 @@ class AdminStatsControllerCore extends AdminStatsTabController '.Shop::addSqlRestriction().' AND status = "closed" GROUP BY ct.id_customer_thread'); - $threads = $messages = 0; - foreach ($result as $row) - { - ++$threads; - $messages += $row['messages']; - } - if (!$threads) - return 0; - return round($messages / $threads, 1); - } + $threads = $messages = 0; + foreach ($result as $row) { + ++$threads; + $messages += $row['messages']; + } + if (!$threads) { + return 0; + } + return round($messages / $threads, 1); + } - public static function getPurchases($date_from, $date_to, $granularity = false) - { - if ($granularity == 'day') - { - $purchases = array(); - $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' + public static function getPurchases($date_from, $date_to, $granularity = false) + { + if ($granularity == 'day') { + $purchases = array(); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT LEFT(`invoice_date`, 10) as date, SUM(od.`product_quantity` * IF( @@ -440,12 +441,12 @@ class AdminStatsControllerCore extends AdminStatsTabController WHERE `invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" AND os.logable = 1 '.Shop::addSqlRestriction(false, 'o').' GROUP BY LEFT(`invoice_date`, 10)'); - foreach ($result as $row) - $purchases[strtotime($row['date'])] = $row['total_purchase_price']; - return $purchases; - } - else - return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + foreach ($result as $row) { + $purchases[strtotime($row['date'])] = $row['total_purchase_price']; + } + return $purchases; + } else { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT SUM(od.`product_quantity` * IF( od.`purchase_supplier_price` > 0, od.`purchase_supplier_price` / `conversion_rate`, @@ -456,13 +457,14 @@ class AdminStatsControllerCore extends AdminStatsTabController LEFT JOIN `'._DB_PREFIX_.'order_state` os ON o.current_state = os.id_order_state WHERE `invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" AND os.logable = 1 '.Shop::addSqlRestriction(false, 'o')); - } + } + } - public static function getExpenses($date_from, $date_to, $granularity = false) - { - $expenses = ($granularity == 'day' ? array() : 0); + public static function getExpenses($date_from, $date_to, $granularity = false) + { + $expenses = ($granularity == 'day' ? array() : 0); - $orders = Db::getInstance()->ExecuteS(' + $orders = Db::getInstance()->ExecuteS(' SELECT LEFT(`invoice_date`, 10) as date, total_paid_tax_incl / o.conversion_rate as total_paid_tax_incl, @@ -477,326 +479,322 @@ class AdminStatsControllerCore extends AdminStatsTabController LEFT JOIN `'._DB_PREFIX_.'order_state` os ON o.current_state = os.id_order_state WHERE `invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" AND os.logable = 1 '.Shop::addSqlRestriction(false, 'o')); - foreach ($orders as $order) - { - // Add flat fees for this order - $flat_fees = Configuration::get('CONF_ORDER_FIXED') + ( - $order['id_currency'] == Configuration::get('PS_CURRENCY_DEFAULT') - ? Configuration::get('CONF_'.strtoupper($order['module']).'_FIXED') - : Configuration::get('CONF_'.strtoupper($order['module']).'_FIXED_FOREIGN') - ); + foreach ($orders as $order) { + // Add flat fees for this order + $flat_fees = Configuration::get('CONF_ORDER_FIXED') + ( + $order['id_currency'] == Configuration::get('PS_CURRENCY_DEFAULT') + ? Configuration::get('CONF_'.strtoupper($order['module']).'_FIXED') + : Configuration::get('CONF_'.strtoupper($order['module']).'_FIXED_FOREIGN') + ); - // Add variable fees for this order - $var_fees = $order['total_paid_tax_incl'] * ( - $order['id_currency'] == Configuration::get('PS_CURRENCY_DEFAULT') - ? Configuration::get('CONF_'.strtoupper($order['module']).'_VAR') - : Configuration::get('CONF_'.strtoupper($order['module']).'_VAR_FOREIGN') - ) / 100; + // Add variable fees for this order + $var_fees = $order['total_paid_tax_incl'] * ( + $order['id_currency'] == Configuration::get('PS_CURRENCY_DEFAULT') + ? Configuration::get('CONF_'.strtoupper($order['module']).'_VAR') + : Configuration::get('CONF_'.strtoupper($order['module']).'_VAR_FOREIGN') + ) / 100; - // Add shipping fees for this order - $shipping_fees = $order['total_shipping_tax_excl'] * ( - $order['id_country'] == Configuration::get('PS_COUNTRY_DEFAULT') - ? Configuration::get('CONF_'.strtoupper($order['carrier_reference']).'_SHIP') - : Configuration::get('CONF_'.strtoupper($order['carrier_reference']).'_SHIP_OVERSEAS') - ) / 100; + // Add shipping fees for this order + $shipping_fees = $order['total_shipping_tax_excl'] * ( + $order['id_country'] == Configuration::get('PS_COUNTRY_DEFAULT') + ? Configuration::get('CONF_'.strtoupper($order['carrier_reference']).'_SHIP') + : Configuration::get('CONF_'.strtoupper($order['carrier_reference']).'_SHIP_OVERSEAS') + ) / 100; - // Tally up these fees - if ($granularity == 'day') - { - if (!isset($expenses[strtotime($order['date'])])) - $expenses[strtotime($order['date'])] = 0; - $expenses[strtotime($order['date'])] += $flat_fees + $var_fees + $shipping_fees; - } - else - $expenses += $flat_fees + $var_fees + $shipping_fees; - } - return $expenses; - } + // Tally up these fees + if ($granularity == 'day') { + if (!isset($expenses[strtotime($order['date'])])) { + $expenses[strtotime($order['date'])] = 0; + } + $expenses[strtotime($order['date'])] += $flat_fees + $var_fees + $shipping_fees; + } else { + $expenses += $flat_fees + $var_fees + $shipping_fees; + } + } + return $expenses; + } - public function displayAjaxGetKpi() - { - $currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); - switch (Tools::getValue('kpi')) - { - case 'conversion_rate': - $visitors = AdminStatsController::getVisits(true, date('Y-m-d', strtotime('-31 day')), date('Y-m-d', strtotime('-1 day')), false /*'day'*/); - $orders = AdminStatsController::getOrders(date('Y-m-d', strtotime('-31 day')), date('Y-m-d', strtotime('-1 day')), false /*'day'*/); + public function displayAjaxGetKpi() + { + $currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); + switch (Tools::getValue('kpi')) { + case 'conversion_rate': + $visitors = AdminStatsController::getVisits(true, date('Y-m-d', strtotime('-31 day')), date('Y-m-d', strtotime('-1 day')), false /*'day'*/); + $orders = AdminStatsController::getOrders(date('Y-m-d', strtotime('-31 day')), date('Y-m-d', strtotime('-1 day')), false /*'day'*/); - // $data = array(); - // $from = strtotime(date('Y-m-d 00:00:00', strtotime('-31 day'))); - // $to = strtotime(date('Y-m-d 23:59:59', strtotime('-1 day'))); - // for ($date = $from; $date <= $to; $date = strtotime('+1 day', $date)) - // if (isset($visitors[$date]) && $visitors[$date]) - // $data[$date] = round(100 * ((isset($orders[$date]) && $orders[$date]) ? $orders[$date] : 0) / $visitors[$date], 2); - // else - // $data[$date] = 0; + // $data = array(); + // $from = strtotime(date('Y-m-d 00:00:00', strtotime('-31 day'))); + // $to = strtotime(date('Y-m-d 23:59:59', strtotime('-1 day'))); + // for ($date = $from; $date <= $to; $date = strtotime('+1 day', $date)) + // if (isset($visitors[$date]) && $visitors[$date]) + // $data[$date] = round(100 * ((isset($orders[$date]) && $orders[$date]) ? $orders[$date] : 0) / $visitors[$date], 2); + // else + // $data[$date] = 0; - $visits_sum = $visitors; //array_sum($visitors); - $orders_sum = $orders; //array_sum($orders); - if ($visits_sum) - $value = round(100 * $orders_sum / $visits_sum, 2); - elseif ($orders_sum) - $value = '∞'; - else - $value = 0; - $value .= '%'; + $visits_sum = $visitors; //array_sum($visitors); + $orders_sum = $orders; //array_sum($orders); + if ($visits_sum) { + $value = round(100 * $orders_sum / $visits_sum, 2); + } elseif ($orders_sum) { + $value = '∞'; + } else { + $value = 0; + } + $value .= '%'; - // ConfigurationKPI::updateValue('CONVERSION_RATE_CHART', Tools::jsonEncode($data)); - ConfigurationKPI::updateValue('CONVERSION_RATE', $value); - ConfigurationKPI::updateValue('CONVERSION_RATE_EXPIRE', strtotime(date('Y-m-d 00:00:00', strtotime('+1 day')))); - break; + // ConfigurationKPI::updateValue('CONVERSION_RATE_CHART', Tools::jsonEncode($data)); + ConfigurationKPI::updateValue('CONVERSION_RATE', $value); + ConfigurationKPI::updateValue('CONVERSION_RATE_EXPIRE', strtotime(date('Y-m-d 00:00:00', strtotime('+1 day')))); + break; - case 'abandoned_cart': - $value = AdminStatsController::getAbandonedCarts(date('Y-m-d H:i:s', strtotime('-2 day')), date('Y-m-d H:i:s', strtotime('-1 day'))); - ConfigurationKPI::updateValue('ABANDONED_CARTS', $value); - ConfigurationKPI::updateValue('ABANDONED_CARTS_EXPIRE', strtotime('+1 hour')); - break; + case 'abandoned_cart': + $value = AdminStatsController::getAbandonedCarts(date('Y-m-d H:i:s', strtotime('-2 day')), date('Y-m-d H:i:s', strtotime('-1 day'))); + ConfigurationKPI::updateValue('ABANDONED_CARTS', $value); + ConfigurationKPI::updateValue('ABANDONED_CARTS_EXPIRE', strtotime('+1 hour')); + break; - case 'installed_modules': - $value = AdminStatsController::getInstalledModules(); - ConfigurationKPI::updateValue('INSTALLED_MODULES', $value); - ConfigurationKPI::updateValue('INSTALLED_MODULES_EXPIRE', strtotime('+2 min')); - break; + case 'installed_modules': + $value = AdminStatsController::getInstalledModules(); + ConfigurationKPI::updateValue('INSTALLED_MODULES', $value); + ConfigurationKPI::updateValue('INSTALLED_MODULES_EXPIRE', strtotime('+2 min')); + break; - case 'disabled_modules': - $value = AdminStatsController::getDisabledModules(); - ConfigurationKPI::updateValue('DISABLED_MODULES', $value); - ConfigurationKPI::updateValue('DISABLED_MODULES_EXPIRE', strtotime('+2 min')); - break; + case 'disabled_modules': + $value = AdminStatsController::getDisabledModules(); + ConfigurationKPI::updateValue('DISABLED_MODULES', $value); + ConfigurationKPI::updateValue('DISABLED_MODULES_EXPIRE', strtotime('+2 min')); + break; - case 'update_modules': - $value = AdminStatsController::getModulesToUpdate(); - ConfigurationKPI::updateValue('UPDATE_MODULES', $value); - ConfigurationKPI::updateValue('UPDATE_MODULES_EXPIRE', strtotime('+2 min')); - break; + case 'update_modules': + $value = AdminStatsController::getModulesToUpdate(); + ConfigurationKPI::updateValue('UPDATE_MODULES', $value); + ConfigurationKPI::updateValue('UPDATE_MODULES_EXPIRE', strtotime('+2 min')); + break; - case 'percent_product_stock': - $value = AdminStatsController::getPercentProductStock(); - ConfigurationKPI::updateValue('PERCENT_PRODUCT_STOCK', $value); - ConfigurationKPI::updateValue('PERCENT_PRODUCT_STOCK_EXPIRE', strtotime('+4 hour')); - break; + case 'percent_product_stock': + $value = AdminStatsController::getPercentProductStock(); + ConfigurationKPI::updateValue('PERCENT_PRODUCT_STOCK', $value); + ConfigurationKPI::updateValue('PERCENT_PRODUCT_STOCK_EXPIRE', strtotime('+4 hour')); + break; - case 'percent_product_out_of_stock': - $value = AdminStatsController::getPercentProductOutOfStock(); - ConfigurationKPI::updateValue('PERCENT_PRODUCT_OUT_OF_STOCK', $value); - ConfigurationKPI::updateValue('PERCENT_PRODUCT_OUT_OF_STOCK_EXPIRE', strtotime('+4 hour')); - break; + case 'percent_product_out_of_stock': + $value = AdminStatsController::getPercentProductOutOfStock(); + ConfigurationKPI::updateValue('PERCENT_PRODUCT_OUT_OF_STOCK', $value); + ConfigurationKPI::updateValue('PERCENT_PRODUCT_OUT_OF_STOCK_EXPIRE', strtotime('+4 hour')); + break; - case 'product_avg_gross_margin': - $value = AdminStatsController::getProductAverageGrossMargin(); - ConfigurationKPI::updateValue('PRODUCT_AVG_GROSS_MARGIN', $value); - ConfigurationKPI::updateValue('PRODUCT_AVG_GROSS_MARGIN_EXPIRE', strtotime('+6 hour')); - break; + case 'product_avg_gross_margin': + $value = AdminStatsController::getProductAverageGrossMargin(); + ConfigurationKPI::updateValue('PRODUCT_AVG_GROSS_MARGIN', $value); + ConfigurationKPI::updateValue('PRODUCT_AVG_GROSS_MARGIN_EXPIRE', strtotime('+6 hour')); + break; - case 'disabled_categories': - $value = AdminStatsController::getDisabledCategories(); - ConfigurationKPI::updateValue('DISABLED_CATEGORIES', $value); - ConfigurationKPI::updateValue('DISABLED_CATEGORIES_EXPIRE', strtotime('+2 hour')); - break; + case 'disabled_categories': + $value = AdminStatsController::getDisabledCategories(); + ConfigurationKPI::updateValue('DISABLED_CATEGORIES', $value); + ConfigurationKPI::updateValue('DISABLED_CATEGORIES_EXPIRE', strtotime('+2 hour')); + break; - case 'disabled_products': - $value = round(100 * AdminStatsController::getDisabledProducts() / AdminStatsController::getTotalProducts(), 2).'%'; - ConfigurationKPI::updateValue('DISABLED_PRODUCTS', $value); - ConfigurationKPI::updateValue('DISABLED_PRODUCTS_EXPIRE', strtotime('+2 hour')); - break; + case 'disabled_products': + $value = round(100 * AdminStatsController::getDisabledProducts() / AdminStatsController::getTotalProducts(), 2).'%'; + ConfigurationKPI::updateValue('DISABLED_PRODUCTS', $value); + ConfigurationKPI::updateValue('DISABLED_PRODUCTS_EXPIRE', strtotime('+2 hour')); + break; - case '8020_sales_catalog': - $value = AdminStatsController::get8020SalesCatalog(date('Y-m-d', strtotime('-30 days')), date('Y-m-d')); - $value = sprintf($this->l('%d%% of your Catalog'), $value); - ConfigurationKPI::updateValue('8020_SALES_CATALOG', $value); - ConfigurationKPI::updateValue('8020_SALES_CATALOG_EXPIRE', strtotime('+12 hour')); - break; + case '8020_sales_catalog': + $value = AdminStatsController::get8020SalesCatalog(date('Y-m-d', strtotime('-30 days')), date('Y-m-d')); + $value = sprintf($this->l('%d%% of your Catalog'), $value); + ConfigurationKPI::updateValue('8020_SALES_CATALOG', $value); + ConfigurationKPI::updateValue('8020_SALES_CATALOG_EXPIRE', strtotime('+12 hour')); + break; - case 'empty_categories': - $value = AdminStatsController::getEmptyCategories(); - ConfigurationKPI::updateValue('EMPTY_CATEGORIES', $value); - ConfigurationKPI::updateValue('EMPTY_CATEGORIES_EXPIRE', strtotime('+2 hour')); - break; + case 'empty_categories': + $value = AdminStatsController::getEmptyCategories(); + ConfigurationKPI::updateValue('EMPTY_CATEGORIES', $value); + ConfigurationKPI::updateValue('EMPTY_CATEGORIES_EXPIRE', strtotime('+2 hour')); + break; - case 'customer_main_gender': - $value = AdminStatsController::getCustomerMainGender(); + case 'customer_main_gender': + $value = AdminStatsController::getCustomerMainGender(); - if ($value === false) - $value = $this->l('No customers', null, null, false); - elseif ($value['type'] == 'female') - $value = sprintf($this->l('%d%% Female Customers', null, null, false), $value['value']); - elseif ($value['type'] == 'male') - $value = sprintf($this->l('%d%% Male Customers', null, null, false), $value['value']); - else - $value = sprintf($this->l('%d%% Neutral Customers', null, null, false), $value['value']); + if ($value === false) { + $value = $this->l('No customers', null, null, false); + } elseif ($value['type'] == 'female') { + $value = sprintf($this->l('%d%% Female Customers', null, null, false), $value['value']); + } elseif ($value['type'] == 'male') { + $value = sprintf($this->l('%d%% Male Customers', null, null, false), $value['value']); + } else { + $value = sprintf($this->l('%d%% Neutral Customers', null, null, false), $value['value']); + } - ConfigurationKPI::updateValue('CUSTOMER_MAIN_GENDER', array($this->context->language->id => $value)); - ConfigurationKPI::updateValue('CUSTOMER_MAIN_GENDER_EXPIRE', array($this->context->language->id => strtotime('+1 day'))); - break; + ConfigurationKPI::updateValue('CUSTOMER_MAIN_GENDER', array($this->context->language->id => $value)); + ConfigurationKPI::updateValue('CUSTOMER_MAIN_GENDER_EXPIRE', array($this->context->language->id => strtotime('+1 day'))); + break; - case 'avg_customer_age': - $value = sprintf($this->l('%d years', null, null, false), AdminStatsController::getAverageCustomerAge(), 1); - ConfigurationKPI::updateValue('AVG_CUSTOMER_AGE', array($this->context->language->id => $value)); - ConfigurationKPI::updateValue('AVG_CUSTOMER_AGE_EXPIRE', array($this->context->language->id => strtotime('+1 day'))); - break; + case 'avg_customer_age': + $value = sprintf($this->l('%d years', null, null, false), AdminStatsController::getAverageCustomerAge(), 1); + ConfigurationKPI::updateValue('AVG_CUSTOMER_AGE', array($this->context->language->id => $value)); + ConfigurationKPI::updateValue('AVG_CUSTOMER_AGE_EXPIRE', array($this->context->language->id => strtotime('+1 day'))); + break; - case 'pending_messages': - $value = (int)AdminStatsController::getPendingMessages(); - ConfigurationKPI::updateValue('PENDING_MESSAGES', $value); - ConfigurationKPI::updateValue('PENDING_MESSAGES_EXPIRE', strtotime('+5 min')); - break; + case 'pending_messages': + $value = (int)AdminStatsController::getPendingMessages(); + ConfigurationKPI::updateValue('PENDING_MESSAGES', $value); + ConfigurationKPI::updateValue('PENDING_MESSAGES_EXPIRE', strtotime('+5 min')); + break; - case 'avg_msg_response_time': - $value = sprintf($this->l('%.1f hours', null, null, false), AdminStatsController::getAverageMessageResponseTime(date('Y-m-d', strtotime('-31 day')), date('Y-m-d', strtotime('-1 day')))); - ConfigurationKPI::updateValue('AVG_MSG_RESPONSE_TIME', $value); - ConfigurationKPI::updateValue('AVG_MSG_RESPONSE_TIME_EXPIRE', strtotime('+4 hour')); - break; + case 'avg_msg_response_time': + $value = sprintf($this->l('%.1f hours', null, null, false), AdminStatsController::getAverageMessageResponseTime(date('Y-m-d', strtotime('-31 day')), date('Y-m-d', strtotime('-1 day')))); + ConfigurationKPI::updateValue('AVG_MSG_RESPONSE_TIME', $value); + ConfigurationKPI::updateValue('AVG_MSG_RESPONSE_TIME_EXPIRE', strtotime('+4 hour')); + break; - case 'messages_per_thread': - $value = round(AdminStatsController::getMessagesPerThread(date('Y-m-d', strtotime('-31 day')), date('Y-m-d', strtotime('-1 day'))), 1); - ConfigurationKPI::updateValue('MESSAGES_PER_THREAD', $value); - ConfigurationKPI::updateValue('MESSAGES_PER_THREAD_EXPIRE', strtotime('+12 hour')); - break; + case 'messages_per_thread': + $value = round(AdminStatsController::getMessagesPerThread(date('Y-m-d', strtotime('-31 day')), date('Y-m-d', strtotime('-1 day'))), 1); + ConfigurationKPI::updateValue('MESSAGES_PER_THREAD', $value); + ConfigurationKPI::updateValue('MESSAGES_PER_THREAD_EXPIRE', strtotime('+12 hour')); + break; - case 'newsletter_registrations': - $value = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + case 'newsletter_registrations': + $value = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'customer` WHERE newsletter = 1 '.Shop::addSqlRestriction(Shop::SHARE_ORDER)); - if (Module::isInstalled('blocknewsletter')) - { - $value += Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + if (Module::isInstalled('blocknewsletter')) { + $value += Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'newsletter` WHERE active = 1 '.Shop::addSqlRestriction(Shop::SHARE_ORDER)); - } + } - ConfigurationKPI::updateValue('NEWSLETTER_REGISTRATIONS', $value); - ConfigurationKPI::updateValue('NEWSLETTER_REGISTRATIONS_EXPIRE', strtotime('+6 hour')); - break; + ConfigurationKPI::updateValue('NEWSLETTER_REGISTRATIONS', $value); + ConfigurationKPI::updateValue('NEWSLETTER_REGISTRATIONS_EXPIRE', strtotime('+6 hour')); + break; - case 'enabled_languages': - $value = Language::countActiveLanguages(); - ConfigurationKPI::updateValue('ENABLED_LANGUAGES', $value); - ConfigurationKPI::updateValue('ENABLED_LANGUAGES_EXPIRE', strtotime('+1 min')); - break; + case 'enabled_languages': + $value = Language::countActiveLanguages(); + ConfigurationKPI::updateValue('ENABLED_LANGUAGES', $value); + ConfigurationKPI::updateValue('ENABLED_LANGUAGES_EXPIRE', strtotime('+1 min')); + break; - case 'frontoffice_translations': - $themes = Theme::getThemes(); - $languages = Language::getLanguages(); - $total = $translated = 0; - foreach ($themes as $theme) - { - /** @var Theme $theme */ - foreach ($languages as $language) - { - $kpi_key = substr(strtoupper($theme->name.'_'.$language['iso_code']), 0, 16); - $total += ConfigurationKPI::get('TRANSLATE_TOTAL_'.$kpi_key); - $translated += ConfigurationKPI::get('TRANSLATE_DONE_'.$kpi_key); - } - } - $value = 0; - if ($translated) - $value = round(100 * $translated / $total, 1); - $value .= '%'; - ConfigurationKPI::updateValue('FRONTOFFICE_TRANSLATIONS', $value); - ConfigurationKPI::updateValue('FRONTOFFICE_TRANSLATIONS_EXPIRE', strtotime('+2 min')); - break; + case 'frontoffice_translations': + $themes = Theme::getThemes(); + $languages = Language::getLanguages(); + $total = $translated = 0; + foreach ($themes as $theme) { + /** @var Theme $theme */ + foreach ($languages as $language) { + $kpi_key = substr(strtoupper($theme->name.'_'.$language['iso_code']), 0, 16); + $total += ConfigurationKPI::get('TRANSLATE_TOTAL_'.$kpi_key); + $translated += ConfigurationKPI::get('TRANSLATE_DONE_'.$kpi_key); + } + } + $value = 0; + if ($translated) { + $value = round(100 * $translated / $total, 1); + } + $value .= '%'; + ConfigurationKPI::updateValue('FRONTOFFICE_TRANSLATIONS', $value); + ConfigurationKPI::updateValue('FRONTOFFICE_TRANSLATIONS_EXPIRE', strtotime('+2 min')); + break; - case 'main_country': - if (!($row = AdminStatsController::getMainCountry(date('Y-m-d', strtotime('-30 day')), date('Y-m-d')))) - $value = $this->l('No orders', null, null, false); - else - { - $country = new Country($row['id_country'], $this->context->language->id); - $value = sprintf($this->l('%d%% %s', null, null, false), $row['orders'], $country->name); - } + case 'main_country': + if (!($row = AdminStatsController::getMainCountry(date('Y-m-d', strtotime('-30 day')), date('Y-m-d')))) { + $value = $this->l('No orders', null, null, false); + } else { + $country = new Country($row['id_country'], $this->context->language->id); + $value = sprintf($this->l('%d%% %s', null, null, false), $row['orders'], $country->name); + } - ConfigurationKPI::updateValue('MAIN_COUNTRY', array($this->context->language->id => $value)); - ConfigurationKPI::updateValue('MAIN_COUNTRY_EXPIRE', array($this->context->language->id => strtotime('+1 day'))); - break; + ConfigurationKPI::updateValue('MAIN_COUNTRY', array($this->context->language->id => $value)); + ConfigurationKPI::updateValue('MAIN_COUNTRY_EXPIRE', array($this->context->language->id => strtotime('+1 day'))); + break; - case 'orders_per_customer': - $value = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + case 'orders_per_customer': + $value = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'customer` c WHERE c.active = 1 '.Shop::addSqlRestriction()); - if ($value) - { - $orders = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' + if ($value) { + $orders = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'orders` o WHERE o.valid = 1 '.Shop::addSqlRestriction()); - $value = round($orders / $value, 2); - } + $value = round($orders / $value, 2); + } - ConfigurationKPI::updateValue('ORDERS_PER_CUSTOMER', $value); - ConfigurationKPI::updateValue('ORDERS_PER_CUSTOMER_EXPIRE', strtotime('+1 day')); - break; + ConfigurationKPI::updateValue('ORDERS_PER_CUSTOMER', $value); + ConfigurationKPI::updateValue('ORDERS_PER_CUSTOMER_EXPIRE', strtotime('+1 day')); + break; - case 'average_order_value': - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + case 'average_order_value': + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT COUNT(`id_order`) as orders, SUM(`total_paid_tax_excl` / `conversion_rate`) as total_paid_tax_excl FROM `'._DB_PREFIX_.'orders` WHERE `invoice_date` BETWEEN "'.pSQL(date('Y-m-d', strtotime('-31 day'))).' 00:00:00" AND "'.pSQL(date('Y-m-d', strtotime('-1 day'))).' 23:59:59" '.Shop::addSqlRestriction()); - $value = Tools::displayPrice($row['orders'] ? $row['total_paid_tax_excl'] / $row['orders'] : 0, $currency); - ConfigurationKPI::updateValue('AVG_ORDER_VALUE', $value); - ConfigurationKPI::updateValue('AVG_ORDER_VALUE_EXPIRE', strtotime(date('Y-m-d 00:00:00', strtotime('+1 day')))); - break; + $value = Tools::displayPrice($row['orders'] ? $row['total_paid_tax_excl'] / $row['orders'] : 0, $currency); + ConfigurationKPI::updateValue('AVG_ORDER_VALUE', $value); + ConfigurationKPI::updateValue('AVG_ORDER_VALUE_EXPIRE', strtotime(date('Y-m-d 00:00:00', strtotime('+1 day')))); + break; - case 'netprofit_visit': - $date_from = date('Y-m-d', strtotime('-31 day')); - $date_to = date('Y-m-d', strtotime('-1 day')); + case 'netprofit_visit': + $date_from = date('Y-m-d', strtotime('-31 day')); + $date_to = date('Y-m-d', strtotime('-1 day')); - $total_visitors = AdminStatsController::getVisits(false, $date_from, $date_to); - $net_profits = AdminStatsController::getTotalSales($date_from, $date_to); - $net_profits -= AdminStatsController::getExpenses($date_from, $date_to); - $net_profits -= AdminStatsController::getPurchases($date_from, $date_to); + $total_visitors = AdminStatsController::getVisits(false, $date_from, $date_to); + $net_profits = AdminStatsController::getTotalSales($date_from, $date_to); + $net_profits -= AdminStatsController::getExpenses($date_from, $date_to); + $net_profits -= AdminStatsController::getPurchases($date_from, $date_to); - if ($total_visitors) - $value = Tools::displayPrice($net_profits / $total_visitors, $currency); - elseif ($net_profits) - $value = '∞'; - else - $value = Tools::displayPrice(0, $currency); + if ($total_visitors) { + $value = Tools::displayPrice($net_profits / $total_visitors, $currency); + } elseif ($net_profits) { + $value = '∞'; + } else { + $value = Tools::displayPrice(0, $currency); + } - ConfigurationKPI::updateValue('NETPROFIT_VISIT', $value); - ConfigurationKPI::updateValue('NETPROFIT_VISIT_EXPIRE', strtotime(date('Y-m-d 00:00:00', strtotime('+1 day')))); - break; + ConfigurationKPI::updateValue('NETPROFIT_VISIT', $value); + ConfigurationKPI::updateValue('NETPROFIT_VISIT_EXPIRE', strtotime(date('Y-m-d 00:00:00', strtotime('+1 day')))); + break; - case 'products_per_category': - $products = AdminStatsController::getTotalProducts(); - $categories = AdminStatsController::getTotalCategories(); - $value = round($products / $categories); - ConfigurationKPI::updateValue('PRODUCTS_PER_CATEGORY', $value); - ConfigurationKPI::updateValue('PRODUCTS_PER_CATEGORY_EXPIRE', strtotime('+1 hour')); - break; + case 'products_per_category': + $products = AdminStatsController::getTotalProducts(); + $categories = AdminStatsController::getTotalCategories(); + $value = round($products / $categories); + ConfigurationKPI::updateValue('PRODUCTS_PER_CATEGORY', $value); + ConfigurationKPI::updateValue('PRODUCTS_PER_CATEGORY_EXPIRE', strtotime('+1 hour')); + break; - case 'top_category': - if (!($id_category = AdminStatsController::getBestCategory(date('Y-m-d', strtotime('-1 month')), date('Y-m-d')))) - $value = $this->l('No category', null, null, false); - else - { - $category = new Category($id_category, $this->context->language->id); - $value = $category->name; - } + case 'top_category': + if (!($id_category = AdminStatsController::getBestCategory(date('Y-m-d', strtotime('-1 month')), date('Y-m-d')))) { + $value = $this->l('No category', null, null, false); + } else { + $category = new Category($id_category, $this->context->language->id); + $value = $category->name; + } - ConfigurationKPI::updateValue('TOP_CATEGORY', array($this->context->language->id => $value)); - ConfigurationKPI::updateValue('TOP_CATEGORY_EXPIRE', array($this->context->language->id => strtotime('+1 day'))); - break; + ConfigurationKPI::updateValue('TOP_CATEGORY', array($this->context->language->id => $value)); + ConfigurationKPI::updateValue('TOP_CATEGORY_EXPIRE', array($this->context->language->id => strtotime('+1 day'))); + break; - default: - $value = false; - } - if ($value !== false) - { - $array = array('value' => $value); - if (isset($data)) - $array['data'] = $data; - die(Tools::jsonEncode($array)); - } - die(Tools::jsonEncode(array('has_errors' => true))); - } + default: + $value = false; + } + if ($value !== false) { + $array = array('value' => $value); + if (isset($data)) { + $array['data'] = $data; + } + die(Tools::jsonEncode($array)); + } + die(Tools::jsonEncode(array('has_errors' => true))); + } } diff --git a/controllers/admin/AdminStatsTabController.php b/controllers/admin/AdminStatsTabController.php index 97d9a827..b7352243 100644 --- a/controllers/admin/AdminStatsTabController.php +++ b/controllers/admin/AdminStatsTabController.php @@ -26,163 +26,161 @@ abstract class AdminStatsTabControllerCore extends AdminPreferencesControllerCore { - public function init() - { - parent::init(); + public function init() + { + parent::init(); - $this->action = 'view'; - $this->display = 'view'; - } + $this->action = 'view'; + $this->display = 'view'; + } - public function initContent() - { - if ($this->ajax) - return; + public function initContent() + { + if ($this->ajax) { + return; + } - $this->initTabModuleList(); - $this->addToolBarModulesListButton(); - $this->toolbar_title = $this->l('Stats', 'AdminStatsTab'); - $this->initPageHeaderToolbar(); - if ($this->display == 'view') - { - // Some controllers use the view action without an object - if ($this->className) - $this->loadObject(true); - $this->content .= $this->renderView(); - } - - $this->content .= $this->displayMenu(); - $this->content .= $this->displayCalendar(); - $this->content .= $this->displayStats(); + $this->initTabModuleList(); + $this->addToolBarModulesListButton(); + $this->toolbar_title = $this->l('Stats', 'AdminStatsTab'); + $this->initPageHeaderToolbar(); + if ($this->display == 'view') { + // Some controllers use the view action without an object + if ($this->className) { + $this->loadObject(true); + } + $this->content .= $this->renderView(); + } + + $this->content .= $this->displayMenu(); + $this->content .= $this->displayCalendar(); + $this->content .= $this->displayStats(); - $this->context->smarty->assign(array( - 'content' => $this->content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } + $this->context->smarty->assign(array( + 'content' => $this->content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); - unset($this->page_header_toolbar_btn['back']); - } + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); + unset($this->page_header_toolbar_btn['back']); + } - public function displayCalendar() - { - return AdminStatsTabController::displayCalendarForm(array( - 'Calendar' => $this->l('Calendar', 'AdminStatsTab'), - 'Day' => $this->l('Day', 'AdminStatsTab'), - 'Month' => $this->l('Month', 'AdminStatsTab'), - 'Year' => $this->l('Year', 'AdminStatsTab'), - 'From' => $this->l('From:', 'AdminStatsTab'), - 'To' => $this->l('To:', 'AdminStatsTab'), - 'Save' => $this->l('Save', 'AdminStatsTab') - ), $this->token); - } + public function displayCalendar() + { + return AdminStatsTabController::displayCalendarForm(array( + 'Calendar' => $this->l('Calendar', 'AdminStatsTab'), + 'Day' => $this->l('Day', 'AdminStatsTab'), + 'Month' => $this->l('Month', 'AdminStatsTab'), + 'Year' => $this->l('Year', 'AdminStatsTab'), + 'From' => $this->l('From:', 'AdminStatsTab'), + 'To' => $this->l('To:', 'AdminStatsTab'), + 'Save' => $this->l('Save', 'AdminStatsTab') + ), $this->token); + } - public static function displayCalendarForm($translations, $token, $action = null, $table = null, $identifier = null, $id = null) - { - $context = Context::getContext(); + public static function displayCalendarForm($translations, $token, $action = null, $table = null, $identifier = null, $id = null) + { + $context = Context::getContext(); - $tpl = $context->controller->createTemplate('calendar.tpl'); + $tpl = $context->controller->createTemplate('calendar.tpl'); - $context->controller->addJqueryUI('ui.datepicker'); + $context->controller->addJqueryUI('ui.datepicker'); - if ($identifier === null && Tools::getValue('module')) - { - $identifier = 'module'; - $id = Tools::getValue('module'); - } - - $action = Context::getContext()->link->getAdminLink('AdminStats'); - $action .= ($action && $table ? '&'.Tools::safeOutput($action) : ''); - $action .= ($identifier && $id ? '&'.Tools::safeOutput($identifier).'='.(int)$id : ''); - $module = Tools::getValue('module'); - $action .= ($module ? '&module='.Tools::safeOutput($module) : ''); - $action .= (($id_product = Tools::getValue('id_product')) ? '&id_product='.Tools::safeOutput($id_product) : ''); - $tpl->assign(array( - 'current' => self::$currentIndex, - 'token' => $token, - 'action' => $action, - 'table' => $table, - 'identifier' => $identifier, - 'id' => $id, - 'translations' => $translations, - 'datepickerFrom' => Tools::getValue('datepickerFrom', $context->employee->stats_date_from), - 'datepickerTo' => Tools::getValue('datepickerTo', $context->employee->stats_date_to) - )); + if ($identifier === null && Tools::getValue('module')) { + $identifier = 'module'; + $id = Tools::getValue('module'); + } + + $action = Context::getContext()->link->getAdminLink('AdminStats'); + $action .= ($action && $table ? '&'.Tools::safeOutput($action) : ''); + $action .= ($identifier && $id ? '&'.Tools::safeOutput($identifier).'='.(int)$id : ''); + $module = Tools::getValue('module'); + $action .= ($module ? '&module='.Tools::safeOutput($module) : ''); + $action .= (($id_product = Tools::getValue('id_product')) ? '&id_product='.Tools::safeOutput($id_product) : ''); + $tpl->assign(array( + 'current' => self::$currentIndex, + 'token' => $token, + 'action' => $action, + 'table' => $table, + 'identifier' => $identifier, + 'id' => $id, + 'translations' => $translations, + 'datepickerFrom' => Tools::getValue('datepickerFrom', $context->employee->stats_date_from), + 'datepickerTo' => Tools::getValue('datepickerTo', $context->employee->stats_date_to) + )); - return $tpl->fetch(); - } + return $tpl->fetch(); + } - /* Not used anymore, but still work */ - protected function displayEngines() - { - $tpl = $this->createTemplate('engines.tpl'); + /* Not used anymore, but still work */ + protected function displayEngines() + { + $tpl = $this->createTemplate('engines.tpl'); - $autoclean_period = array( - 'never' => $this->l('Never', 'AdminStatsTab'), - 'week' => $this->l('Week', 'AdminStatsTab'), - 'month' => $this->l('Month', 'AdminStatsTab'), - 'year' => $this->l('Year', 'AdminStatsTab') - ); + $autoclean_period = array( + 'never' => $this->l('Never', 'AdminStatsTab'), + 'week' => $this->l('Week', 'AdminStatsTab'), + 'month' => $this->l('Month', 'AdminStatsTab'), + 'year' => $this->l('Year', 'AdminStatsTab') + ); - $tpl->assign(array( - 'current' => self::$currentIndex, - 'token' => $this->token, - 'graph_engine' => Configuration::get('PS_STATS_RENDER'), - 'grid_engine' => Configuration::get('PS_STATS_GRID_RENDER'), - 'auto_clean' => Configuration::get('PS_STATS_OLD_CONNECT_AUTO_CLEAN'), - 'array_graph_engines' => ModuleGraphEngine::getGraphEngines(), - 'array_grid_engines' => ModuleGridEngine::getGridEngines(), - 'array_auto_clean' => $autoclean_period, - )); + $tpl->assign(array( + 'current' => self::$currentIndex, + 'token' => $this->token, + 'graph_engine' => Configuration::get('PS_STATS_RENDER'), + 'grid_engine' => Configuration::get('PS_STATS_GRID_RENDER'), + 'auto_clean' => Configuration::get('PS_STATS_OLD_CONNECT_AUTO_CLEAN'), + 'array_graph_engines' => ModuleGraphEngine::getGraphEngines(), + 'array_grid_engines' => ModuleGridEngine::getGridEngines(), + 'array_auto_clean' => $autoclean_period, + )); - return $tpl->fetch(); - } + return $tpl->fetch(); + } - public function displayMenu() - { - $tpl = $this->createTemplate('menu.tpl'); + public function displayMenu() + { + $tpl = $this->createTemplate('menu.tpl'); - $modules = $this->getModules(); - $module_instance = array(); - foreach ($modules as $m => $module) - { - if ($module_instance[$module['name']] = Module::getInstanceByName($module['name'])) - $modules[$m]['displayName'] = $module_instance[$module['name']]->displayName; - else - { - unset($module_instance[$module['name']]); - unset($modules[$m]); - } - } + $modules = $this->getModules(); + $module_instance = array(); + foreach ($modules as $m => $module) { + if ($module_instance[$module['name']] = Module::getInstanceByName($module['name'])) { + $modules[$m]['displayName'] = $module_instance[$module['name']]->displayName; + } else { + unset($module_instance[$module['name']]); + unset($modules[$m]); + } + } - uasort($modules, array($this, 'checkModulesNames')); + uasort($modules, array($this, 'checkModulesNames')); - $tpl->assign(array( - 'current' => self::$currentIndex, - 'current_module_name' => Tools::getValue('module', 'statsforecast'), - 'token' => $this->token, - 'modules' => $modules, - 'module_instance' => $module_instance - )); + $tpl->assign(array( + 'current' => self::$currentIndex, + 'current_module_name' => Tools::getValue('module', 'statsforecast'), + 'token' => $this->token, + 'modules' => $modules, + 'module_instance' => $module_instance + )); - return $tpl->fetch(); - } - - public function checkModulesNames($a, $b) - { - return (bool)($a['displayName'] > $b['displayName']); - } + return $tpl->fetch(); + } + + public function checkModulesNames($a, $b) + { + return (bool)($a['displayName'] > $b['displayName']); + } - protected function getModules() - { - $sql = 'SELECT h.`name` AS hook, m.`name` + protected function getModules() + { + $sql = 'SELECT h.`name` AS hook, m.`name` FROM `'._DB_PREFIX_.'module` m LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_module` = m.`id_module` LEFT JOIN `'._DB_PREFIX_.'hook` h ON hm.`id_hook` = h.`id_hook` @@ -190,133 +188,127 @@ abstract class AdminStatsTabControllerCore extends AdminPreferencesControllerCor AND m.`active` = 1 GROUP BY hm.id_module ORDER BY hm.`position`'; - return Db::getInstance()->executeS($sql); - } + return Db::getInstance()->executeS($sql); + } - public function displayStats() - { - $tpl = $this->createTemplate('stats.tpl'); + public function displayStats() + { + $tpl = $this->createTemplate('stats.tpl'); - if ((!($module_name = Tools::getValue('module')) || !Validate::isModuleName($module_name)) && ($module_instance = Module::getInstanceByName('statsforecast')) && $module_instance->active) - $module_name = 'statsforecast'; + if ((!($module_name = Tools::getValue('module')) || !Validate::isModuleName($module_name)) && ($module_instance = Module::getInstanceByName('statsforecast')) && $module_instance->active) { + $module_name = 'statsforecast'; + } - if ($module_name) - { - $_GET['module'] = $module_name; + if ($module_name) { + $_GET['module'] = $module_name; - if (!isset($module_instance)) - $module_instance = Module::getInstanceByName($module_name); - - if ($module_instance && $module_instance->active) - $hook = Hook::exec('displayAdminStatsModules', null, $module_instance->id); - } + if (!isset($module_instance)) { + $module_instance = Module::getInstanceByName($module_name); + } + + if ($module_instance && $module_instance->active) { + $hook = Hook::exec('displayAdminStatsModules', null, $module_instance->id); + } + } - $tpl->assign(array( - 'module_name' => $module_name, - 'module_instance' => isset($module_instance) ? $module_instance : null, - 'hook' => isset($hook) ? $hook : null - )); + $tpl->assign(array( + 'module_name' => $module_name, + 'module_instance' => isset($module_instance) ? $module_instance : null, + 'hook' => isset($hook) ? $hook : null + )); - return $tpl->fetch(); - } + return $tpl->fetch(); + } - public function postProcess() - { - $this->context = Context::getContext(); - - $this->processDateRange(); - - if (Tools::getValue('submitSettings')) - { - if ($this->tabAccess['edit'] === '1') - { - self::$currentIndex .= '&module='.Tools::getValue('module'); - Configuration::updateValue('PS_STATS_RENDER', Tools::getValue('PS_STATS_RENDER', Configuration::get('PS_STATS_RENDER'))); - Configuration::updateValue('PS_STATS_GRID_RENDER', Tools::getValue('PS_STATS_GRID_RENDER', Configuration::get('PS_STATS_GRID_RENDER'))); - Configuration::updateValue('PS_STATS_OLD_CONNECT_AUTO_CLEAN', Tools::getValue('PS_STATS_OLD_CONNECT_AUTO_CLEAN', Configuration::get('PS_STATS_OLD_CONNECT_AUTO_CLEAN'))); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - } - - public function processDateRange() - { - if (Tools::isSubmit('submitDatePicker')) - { - if ((!Validate::isDate($from = Tools::getValue('datepickerFrom')) || !Validate::isDate($to = Tools::getValue('datepickerTo'))) || (strtotime($from) > strtotime($to))) - $this->errors[] = Tools::displayError('The specified date is invalid.'); - } - if (Tools::isSubmit('submitDateDay')) - { - $from = date('Y-m-d'); - $to = date('Y-m-d'); - } - if (Tools::isSubmit('submitDateDayPrev')) - { - $yesterday = time() - 60 * 60 * 24; - $from = date('Y-m-d', $yesterday); - $to = date('Y-m-d', $yesterday); - } - if (Tools::isSubmit('submitDateMonth')) - { - $from = date('Y-m-01'); - $to = date('Y-m-t'); - } - if (Tools::isSubmit('submitDateMonthPrev')) - { - $m = (date('m') == 1 ? 12 : date('m') - 1); - $y = ($m == 12 ? date('Y') - 1 : date('Y')); - $from = $y.'-'.$m.'-01'; - $to = $y.'-'.$m.date('-t', mktime(12, 0, 0, $m, 15, $y)); - } - if (Tools::isSubmit('submitDateYear')) - { - $from = date('Y-01-01'); - $to = date('Y-12-31'); - } - if (Tools::isSubmit('submitDateYearPrev')) - { - $from = (date('Y') - 1).date('-01-01'); - $to = (date('Y') - 1).date('-12-31'); - } - if (isset($from) && isset($to) && !count($this->errors)) - { - $this->context->employee->stats_date_from = $from; - $this->context->employee->stats_date_to = $to; - $this->context->employee->update(); - if (!$this->isXmlHttpRequest()) - Tools::redirectAdmin($_SERVER['REQUEST_URI']); - } - } - - public function ajaxProcessSetDashboardDateRange() - { - $this->processDateRange(); - - if ($this->isXmlHttpRequest()) - { - if (is_array($this->errors) && count($this->errors)) - die(Tools::jsonEncode(array( - 'has_errors' => true, - 'errors' => array($this->errors), - 'date_from' => $this->context->employee->stats_date_from, - 'date_to' => $this->context->employee->stats_date_to) - )); - else - die(Tools::jsonEncode(array( - 'has_errors' => false, - 'date_from' => $this->context->employee->stats_date_from, - 'date_to' => $this->context->employee->stats_date_to) - )); - } - } + public function postProcess() + { + $this->context = Context::getContext(); + + $this->processDateRange(); + + if (Tools::getValue('submitSettings')) { + if ($this->tabAccess['edit'] === '1') { + self::$currentIndex .= '&module='.Tools::getValue('module'); + Configuration::updateValue('PS_STATS_RENDER', Tools::getValue('PS_STATS_RENDER', Configuration::get('PS_STATS_RENDER'))); + Configuration::updateValue('PS_STATS_GRID_RENDER', Tools::getValue('PS_STATS_GRID_RENDER', Configuration::get('PS_STATS_GRID_RENDER'))); + Configuration::updateValue('PS_STATS_OLD_CONNECT_AUTO_CLEAN', Tools::getValue('PS_STATS_OLD_CONNECT_AUTO_CLEAN', Configuration::get('PS_STATS_OLD_CONNECT_AUTO_CLEAN'))); + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + } + + public function processDateRange() + { + if (Tools::isSubmit('submitDatePicker')) { + if ((!Validate::isDate($from = Tools::getValue('datepickerFrom')) || !Validate::isDate($to = Tools::getValue('datepickerTo'))) || (strtotime($from) > strtotime($to))) { + $this->errors[] = Tools::displayError('The specified date is invalid.'); + } + } + if (Tools::isSubmit('submitDateDay')) { + $from = date('Y-m-d'); + $to = date('Y-m-d'); + } + if (Tools::isSubmit('submitDateDayPrev')) { + $yesterday = time() - 60 * 60 * 24; + $from = date('Y-m-d', $yesterday); + $to = date('Y-m-d', $yesterday); + } + if (Tools::isSubmit('submitDateMonth')) { + $from = date('Y-m-01'); + $to = date('Y-m-t'); + } + if (Tools::isSubmit('submitDateMonthPrev')) { + $m = (date('m') == 1 ? 12 : date('m') - 1); + $y = ($m == 12 ? date('Y') - 1 : date('Y')); + $from = $y.'-'.$m.'-01'; + $to = $y.'-'.$m.date('-t', mktime(12, 0, 0, $m, 15, $y)); + } + if (Tools::isSubmit('submitDateYear')) { + $from = date('Y-01-01'); + $to = date('Y-12-31'); + } + if (Tools::isSubmit('submitDateYearPrev')) { + $from = (date('Y') - 1).date('-01-01'); + $to = (date('Y') - 1).date('-12-31'); + } + if (isset($from) && isset($to) && !count($this->errors)) { + $this->context->employee->stats_date_from = $from; + $this->context->employee->stats_date_to = $to; + $this->context->employee->update(); + if (!$this->isXmlHttpRequest()) { + Tools::redirectAdmin($_SERVER['REQUEST_URI']); + } + } + } + + public function ajaxProcessSetDashboardDateRange() + { + $this->processDateRange(); + + if ($this->isXmlHttpRequest()) { + if (is_array($this->errors) && count($this->errors)) { + die(Tools::jsonEncode(array( + 'has_errors' => true, + 'errors' => array($this->errors), + 'date_from' => $this->context->employee->stats_date_from, + 'date_to' => $this->context->employee->stats_date_to) + )); + } else { + die(Tools::jsonEncode(array( + 'has_errors' => false, + 'date_from' => $this->context->employee->stats_date_from, + 'date_to' => $this->context->employee->stats_date_to) + )); + } + } + } - protected function getDate() - { - $year = isset($this->context->cookie->stats_year) ? $this->context->cookie->stats_year : date('Y'); - $month = isset($this->context->cookie->stats_month) ? sprintf('%02d', $this->context->cookie->stats_month) : '%'; - $day = isset($this->context->cookie->stats_day) ? sprintf('%02d', $this->context->cookie->stats_day) : '%'; - return $year.'-'.$month.'-'.$day; - } + protected function getDate() + { + $year = isset($this->context->cookie->stats_year) ? $this->context->cookie->stats_year : date('Y'); + $month = isset($this->context->cookie->stats_month) ? sprintf('%02d', $this->context->cookie->stats_month) : '%'; + $day = isset($this->context->cookie->stats_day) ? sprintf('%02d', $this->context->cookie->stats_day) : '%'; + return $year.'-'.$month.'-'.$day; + } } diff --git a/controllers/admin/AdminStatusesController.php b/controllers/admin/AdminStatusesController.php index e2bc8069..cfc439ac 100644 --- a/controllers/admin/AdminStatusesController.php +++ b/controllers/admin/AdminStatusesController.php @@ -29,647 +29,655 @@ */ class AdminStatusesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'order_state'; - $this->className = 'OrderState'; - $this->lang = true; - $this->deleted = false; - $this->colorOnBackground = false; - $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?'))); - $this->context = Context::getContext(); - $this->multishop_context = Shop::CONTEXT_ALL; - $this->imageType = 'gif'; - $this->fieldImageSettings = array( - 'name' => 'icon', - 'dir' => 'os' - ); - parent::__construct(); - } + public function __construct() + { + $this->bootstrap = true; + $this->table = 'order_state'; + $this->className = 'OrderState'; + $this->lang = true; + $this->deleted = false; + $this->colorOnBackground = false; + $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?'))); + $this->context = Context::getContext(); + $this->multishop_context = Shop::CONTEXT_ALL; + $this->imageType = 'gif'; + $this->fieldImageSettings = array( + 'name' => 'icon', + 'dir' => 'os' + ); + parent::__construct(); + } - public function init() - { - if (Tools::isSubmit('addorder_return_state')) - $this->display = 'add'; - if (Tools::isSubmit('updateorder_return_state')) - $this->display = 'edit'; + public function init() + { + if (Tools::isSubmit('addorder_return_state')) { + $this->display = 'add'; + } + if (Tools::isSubmit('updateorder_return_state')) { + $this->display = 'edit'; + } - return parent::init(); - } + return parent::init(); + } - /** - * init all variables to render the order status list - */ - protected function initOrderStatutsList() - { - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->addRowActionSkipList('delete', range(1, 14)); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash', - ) - ); + /** + * init all variables to render the order status list + */ + protected function initOrderStatutsList() + { + $this->fields_list = array( + 'id_order_state' => array( + 'title' => $this->l('ID'), + 'align' => 'text-center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Name'), + 'width' => 'auto', + 'color' => 'color' + ), + 'logo' => array( + 'title' => $this->l('Icon'), + 'align' => 'text-center', + 'image' => 'os', + 'orderby' => false, + 'search' => false, + 'class' => 'fixed-width-xs' + ), + 'send_email' => array( + 'title' => $this->l('Send email to customer'), + 'align' => 'text-center', + 'active' => 'sendEmail', + 'type' => 'bool', + 'ajax' => true, + 'orderby' => false, + 'class' => 'fixed-width-sm' + ), + 'delivery' => array( + 'title' => $this->l('Delivery'), + 'align' => 'text-center', + 'active' => 'delivery', + 'type' => 'bool', + 'ajax' => true, + 'orderby' => false, + 'class' => 'fixed-width-sm' + ) + , + 'invoice' => array( + 'title' => $this->l('Invoice'), + 'align' => 'text-center', + 'active' => 'invoice', + 'type' => 'bool', + 'ajax' => true, + 'orderby' => false, + 'class' => 'fixed-width-sm' + ), + 'template' => array( + 'title' => $this->l('Email template') + ) + ); + } - $this->fields_list = array( - 'id_order_state' => array( - 'title' => $this->l('ID'), - 'align' => 'text-center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Name'), - 'width' => 'auto', - 'color' => 'color' - ), - 'logo' => array( - 'title' => $this->l('Icon'), - 'align' => 'text-center', - 'image' => 'os', - 'orderby' => false, - 'search' => false, - 'class' => 'fixed-width-xs' - ), - 'send_email' => array( - 'title' => $this->l('Send email to customer'), - 'align' => 'text-center', - 'active' => 'sendEmail', - 'type' => 'bool', - 'ajax' => true, - 'orderby' => false, - 'class' => 'fixed-width-sm' - ), - 'delivery' => array( - 'title' => $this->l('Delivery'), - 'align' => 'text-center', - 'active' => 'delivery', - 'type' => 'bool', - 'ajax' => true, - 'orderby' => false, - 'class' => 'fixed-width-sm' - ) - , - 'invoice' => array( - 'title' => $this->l('Invoice'), - 'align' => 'text-center', - 'active' => 'invoice', - 'type' => 'bool', - 'ajax' => true, - 'orderby' => false, - 'class' => 'fixed-width-sm' - ), - 'template' => array( - 'title' => $this->l('Email template') - ) - ); - } + /** + * init all variables to render the order return list + */ + protected function initOrdersReturnsList() + { + $this->table = 'order_return_state'; + $this->className = 'OrderReturnState'; + $this->_defaultOrderBy = $this->identifier = 'id_order_return_state'; + $this->list_id = 'order_return_state'; + $this->deleted = false; + $this->_orderBy = null; - /** - * init all variables to render the order return list - */ - protected function initOrdersReturnsList() - { - $this->table = 'order_return_state'; - $this->className = 'OrderReturnState'; - $this->_defaultOrderBy = $this->identifier = 'id_order_return_state'; - $this->list_id = 'order_return_state'; - $this->deleted = false; - $this->_orderBy = null; + $this->fields_list = array( + 'id_order_return_state' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Name'), + 'align' => 'left', + 'width' => 'auto', + 'color' => 'color' + ) + ); + } - $this->addRowAction('editstatus'); - $this->addRowActionSkipList('delete', array(1, 2, 3, 4, 5)); + protected function initOrderReturnsForm() + { + $id_order_return_state = (int)Tools::getValue('id_order_return_state'); - $this->fields_list = array( - 'id_order_return_state' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Name'), - 'align' => 'left', - 'width' => 'auto', - 'color' => 'color' - ) - ); - } + // Create Object OrderReturnState + $order_return_state = new OrderReturnState($id_order_return_state); - protected function initOrderReturnsForm() - { - $id_order_return_state = (int)Tools::getValue('id_order_return_state'); + //init field form variable for order return form + $this->fields_form = array(); - // Create Object OrderReturnState - $order_return_state = new OrderReturnState($id_order_return_state); + //$this->initToolbar(); + $this->getlanguages(); + $helper = new HelperForm(); + $helper->currentIndex = self::$currentIndex; + $helper->token = $this->token; + $helper->table = 'order_return_state'; + $helper->identifier = 'id_order_return_state'; + $helper->id = $order_return_state->id; + $helper->toolbar_scroll = false; + $helper->languages = $this->_languages; + $helper->default_form_language = $this->default_form_language; + $helper->allow_employee_form_lang = $this->allow_employee_form_lang; - //init field form variable for order return form - $this->fields_form = array(); + if ($order_return_state->id) { + $helper->fields_value = array( + 'name' => $this->getFieldValue($order_return_state, 'name'), + 'color' => $this->getFieldValue($order_return_state, 'color'), + ); + } else { + $helper->fields_value = array( + 'name' => $this->getFieldValue($order_return_state, 'name'), + 'color' => "#ffffff", + ); + } - //$this->initToolbar(); - $this->getlanguages(); - $helper = new HelperForm(); - $helper->currentIndex = self::$currentIndex; - $helper->token = $this->token; - $helper->table = 'order_return_state'; - $helper->identifier = 'id_order_return_state'; - $helper->id = $order_return_state->id; - $helper->toolbar_scroll = false; - $helper->languages = $this->_languages; - $helper->default_form_language = $this->default_form_language; - $helper->allow_employee_form_lang = $this->allow_employee_form_lang; + $helper->toolbar_btn = $this->toolbar_btn; + $helper->title = $this->l('Edit Return Status'); + return $helper; + } - if ($order_return_state->id) - $helper->fields_value = array( - 'name' => $this->getFieldValue($order_return_state, 'name'), - 'color' => $this->getFieldValue($order_return_state, 'color'), - ); - else - $helper->fields_value = array( - 'name' => $this->getFieldValue($order_return_state, 'name'), - 'color' => "#ffffff", - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_order_state'] = array( + 'href' => self::$currentIndex.'&addorder_state&token='.$this->token, + 'desc' => $this->l('Add new order status', null, null, false), + 'icon' => 'process-icon-new' + ); + $this->page_header_toolbar_btn['new_order_return_state'] = array( + 'href' => self::$currentIndex.'&addorder_return_state&token='.$this->token, + 'desc' => $this->l('Add new order return status', null, null, false), + 'icon' => 'process-icon-new' + ); + } - $helper->toolbar_btn = $this->toolbar_btn; - $helper->title = $this->l('Edit Return Status'); - return $helper; - } + parent::initPageHeaderToolbar(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - { - $this->page_header_toolbar_btn['new_order_state'] = array( - 'href' => self::$currentIndex.'&addorder_state&token='.$this->token, - 'desc' => $this->l('Add new order status', null, null, false), - 'icon' => 'process-icon-new' - ); - $this->page_header_toolbar_btn['new_order_return_state'] = array( - 'href' => self::$currentIndex.'&addorder_return_state&token='.$this->token, - 'desc' => $this->l('Add new order return status', null, null, false), - 'icon' => 'process-icon-new' - ); - } + /** + * Function used to render the list to display for this controller + */ + public function renderList() + { + //init and render the first list + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->addRowActionSkipList('delete', range(1, 14)); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash', + ) + ); + $this->initOrderStatutsList(); + $lists = parent::renderList(); - parent::initPageHeaderToolbar(); - } + //init and render the second list + $this->list_skip_actions = array(); + $this->_filter = false; + $this->addRowActionSkipList('delete', array(1, 2, 3, 4, 5)); + $this->initOrdersReturnsList(); + $this->checkFilterForOrdersReturnsList(); - /** - * Function used to render the list to display for this controller - */ - public function renderList() - { - //init and render the first list - $this->initOrderStatutsList(); - $lists = parent::renderList(); + // call postProcess() to take care of actions and filters + $this->postProcess(); + $this->toolbar_title = $this->l('Return statuses'); - //init and render the second list - $this->list_skip_actions = array(); - $this->_filter = false; - $this->initOrdersReturnsList(); + parent::initToolbar(); + $lists .= parent::renderList(); - // call postProcess() to take care of actions and filters - $this->postProcess(); - $this->toolbar_title = $this->l('Return statuses'); - $this->checkFilterForOrdersReturnsList(); + return $lists; + } - parent::initToolbar(); - $lists .= parent::renderList(); + protected function checkFilterForOrdersReturnsList() + { + // test if a filter is applied for this list + if (Tools::isSubmit('submitFilter'.$this->table) || $this->context->cookie->{'submitFilter'.$this->table} !== false) { + $this->filter = true; + } - return $lists; - } + // test if a filter reset request is required for this list + if (isset($_POST['submitReset'.$this->table])) { + $this->action = 'reset_filters'; + } else { + $this->action = ''; + } + } - protected function checkFilterForOrdersReturnsList() - { - // test if a filter is applied for this list - if (Tools::isSubmit('submitFilter'.$this->table) || $this->context->cookie->{'submitFilter'.$this->table} !== false) - $this->filter = true; + public function renderForm() + { + $this->fields_form = array( + 'tinymce' => true, + 'legend' => array( + 'title' => $this->l('Order status'), + 'icon' => 'icon-time' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Status name'), + 'name' => 'name', + 'lang' => true, + 'required' => true, + 'hint' => array( + $this->l('Order status (e.g. \'Pending\').'), + $this->l('Invalid characters: numbers and').' !<>,;?=+()@#"{}_$%:' + ) + ), + array( + 'type' => 'file', + 'label' => $this->l('Icon'), + 'name' => 'icon', + 'hint' => $this->l('Upload an icon from your computer (File type: .gif, suggested size: 16x16).') + ), + array( + 'type' => 'color', + 'label' => $this->l('Color'), + 'name' => 'color', + 'hint' => $this->l('Status will be highlighted in this color. HTML colors only.').' "lightblue", "#CC6600")' + ), + array( + 'type' => 'checkbox', + 'name' => 'logable', + 'values' => array( + 'query' => array( + array('id' => 'on', 'name' => $this->l('Consider the associated order as validated.'), 'val' => '1'), + ), + 'id' => 'id', + 'name' => 'name' + ) + ), + array( + 'type' => 'checkbox', + 'name' => 'invoice', + 'values' => array( + 'query' => array( + array('id' => 'on', 'name' => $this->l('Allow a customer to download and view PDF versions of his/her invoices.'), 'val' => '1'), + ), + 'id' => 'id', + 'name' => 'name' + ) + ), + array( + 'type' => 'checkbox', + 'name' => 'hidden', + 'values' => array( + 'query' => array( + array('id' => 'on', 'name' => $this->l('Hide this status in all customer orders.'), 'val' => '1'), + ), + 'id' => 'id', + 'name' => 'name' + ) + ), + array( + 'type' => 'checkbox', + 'name' => 'send_email', + 'values' => array( + 'query' => array( + array('id' => 'on', 'name' => $this->l('Send an email to the customer when his/her order status has changed.'), 'val' => '1'), + ), + 'id' => 'id', + 'name' => 'name' + ) + ), + array( + 'type' => 'checkbox', + 'name' => 'pdf_invoice', + 'values' => array( + 'query' => array( + array('id' => 'on', 'name' => $this->l('Attach invoice PDF to email.'), 'val' => '1'), + ), + 'id' => 'id', + 'name' => 'name' + ), + ), + array( + 'type' => 'checkbox', + 'name' => 'pdf_delivery', + 'values' => array( + 'query' => array( + array('id' => 'on', 'name' => $this->l('Attach delivery slip PDF to email.'), 'val' => '1'), + ), + 'id' => 'id', + 'name' => 'name' + ), + ), + array( + 'type' => 'checkbox', + 'name' => 'shipped', + 'values' => array( + 'query' => array( + array('id' => 'on', 'name' => $this->l('Set the order as shipped.'), 'val' => '1'), + ), + 'id' => 'id', + 'name' => 'name' + ) + ), + array( + 'type' => 'checkbox', + 'name' => 'paid', + 'values' => array( + 'query' => array( + array('id' => 'on', 'name' => $this->l('Set the order as paid.'), 'val' => '1'), + ), + 'id' => 'id', + 'name' => 'name' + ) + ), + array( + 'type' => 'checkbox', + 'name' => 'delivery', + 'values' => array( + 'query' => array( + array('id' => 'on', 'name' => $this->l('Show delivery PDF.'), 'val' => '1'), + ), + 'id' => 'id', + 'name' => 'name' + ) + ), + array( + 'type' => 'select_template', + 'label' => $this->l('Template'), + 'name' => 'template', + 'lang' => true, + 'options' => array( + 'query' => $this->getTemplates(), + 'id' => 'id', + 'name' => 'name', + 'folder' => 'folder' + ), + 'hint' => array( + $this->l('Only letters, numbers and underscores ("_") are allowed.'), + $this->l('Email template for both .html and .txt.') + ) + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - // test if a filter reset request is required for this list - if (isset($_POST['submitReset'.$this->table])) - $this->action = 'reset_filters'; - else - $this->action = ''; + if (Tools::isSubmit('updateorder_state') || Tools::isSubmit('addorder_state')) { + return $this->renderOrderStatusForm(); + } elseif (Tools::isSubmit('updateorder_return_state') || Tools::isSubmit('addorder_return_state')) { + return $this->renderOrderReturnsForm(); + } else { + return parent::renderForm(); + } + } - } + protected function renderOrderStatusForm() + { + if (!($obj = $this->loadObject(true))) { + return; + } - public function renderForm() - { - $this->fields_form = array( - 'tinymce' => true, - 'legend' => array( - 'title' => $this->l('Order status'), - 'icon' => 'icon-time' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Status name'), - 'name' => 'name', - 'lang' => true, - 'required' => true, - 'hint' => array( - $this->l('Order status (e.g. \'Pending\').'), - $this->l('Invalid characters: numbers and').' !<>,;?=+()@#"{}_$%:' - ) - ), - array( - 'type' => 'file', - 'label' => $this->l('Icon'), - 'name' => 'icon', - 'hint' => $this->l('Upload an icon from your computer (File type: .gif, suggested size: 16x16).') - ), - array( - 'type' => 'color', - 'label' => $this->l('Color'), - 'name' => 'color', - 'hint' => $this->l('Status will be highlighted in this color. HTML colors only.').' "lightblue", "#CC6600")' - ), - array( - 'type' => 'checkbox', - 'name' => 'logable', - 'values' => array( - 'query' => array( - array('id' => 'on', 'name' => $this->l('Consider the associated order as validated.'), 'val' => '1'), - ), - 'id' => 'id', - 'name' => 'name' - ) - ), - array( - 'type' => 'checkbox', - 'name' => 'invoice', - 'values' => array( - 'query' => array( - array('id' => 'on', 'name' => $this->l('Allow a customer to download and view PDF versions of his/her invoices.'), 'val' => '1'), - ), - 'id' => 'id', - 'name' => 'name' - ) - ), - array( - 'type' => 'checkbox', - 'name' => 'hidden', - 'values' => array( - 'query' => array( - array('id' => 'on', 'name' => $this->l('Hide this status in all customer orders.'), 'val' => '1'), - ), - 'id' => 'id', - 'name' => 'name' - ) - ), - array( - 'type' => 'checkbox', - 'name' => 'send_email', - 'values' => array( - 'query' => array( - array('id' => 'on', 'name' => $this->l('Send an email to the customer when his/her order status has changed.'), 'val' => '1'), - ), - 'id' => 'id', - 'name' => 'name' - ) - ), - array( - 'type' => 'checkbox', - 'name' => 'pdf_invoice', - 'values' => array( - 'query' => array( - array('id' => 'on', 'name' => $this->l('Attach invoice PDF to email.'), 'val' => '1'), - ), - 'id' => 'id', - 'name' => 'name' - ), - ), - array( - 'type' => 'checkbox', - 'name' => 'pdf_delivery', - 'values' => array( - 'query' => array( - array('id' => 'on', 'name' => $this->l('Attach delivery slip PDF to email.'), 'val' => '1'), - ), - 'id' => 'id', - 'name' => 'name' - ), - ), - array( - 'type' => 'checkbox', - 'name' => 'shipped', - 'values' => array( - 'query' => array( - array('id' => 'on', 'name' => $this->l('Set the order as shipped.'), 'val' => '1'), - ), - 'id' => 'id', - 'name' => 'name' - ) - ), - array( - 'type' => 'checkbox', - 'name' => 'paid', - 'values' => array( - 'query' => array( - array('id' => 'on', 'name' => $this->l('Set the order as paid.'), 'val' => '1'), - ), - 'id' => 'id', - 'name' => 'name' - ) - ), - array( - 'type' => 'checkbox', - 'name' => 'delivery', - 'values' => array( - 'query' => array( - array('id' => 'on', 'name' => $this->l('Show delivery PDF.'), 'val' => '1'), - ), - 'id' => 'id', - 'name' => 'name' - ) - ), - array( - 'type' => 'select_template', - 'label' => $this->l('Template'), - 'name' => 'template', - 'lang' => true, - 'options' => array( - 'query' => $this->getTemplates(), - 'id' => 'id', - 'name' => 'name', - 'folder' => 'folder' - ), - 'hint' => array( - $this->l('Only letters, numbers and underscores ("_") are allowed.'), - $this->l('Email template for both .html and .txt.') - ) - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + $this->fields_value = array( + 'logable_on' => $this->getFieldValue($obj, 'logable'), + 'invoice_on' => $this->getFieldValue($obj, 'invoice'), + 'hidden_on' => $this->getFieldValue($obj, 'hidden'), + 'send_email_on' => $this->getFieldValue($obj, 'send_email'), + 'shipped_on' => $this->getFieldValue($obj, 'shipped'), + 'paid_on' => $this->getFieldValue($obj, 'paid'), + 'delivery_on' => $this->getFieldValue($obj, 'delivery'), + 'pdf_delivery_on' => $this->getFieldValue($obj, 'pdf_delivery'), + 'pdf_invoice_on' => $this->getFieldValue($obj, 'pdf_invoice'), + ); - if (Tools::isSubmit('updateorder_state') || Tools::isSubmit('addorder_state')) - return $this->renderOrderStatusForm(); - elseif (Tools::isSubmit('updateorder_return_state') || Tools::isSubmit('addorder_return_state')) - return $this->renderOrderReturnsForm(); - else - return parent::renderForm(); - } + if ($this->getFieldValue($obj, 'color') !== false) { + $this->fields_value['color'] = $this->getFieldValue($obj, 'color'); + } else { + $this->fields_value['color'] = "#ffffff"; + } - protected function renderOrderStatusForm() - { - if (!($obj = $this->loadObject(true))) - return; + return parent::renderForm(); + } - $this->fields_value = array( - 'logable_on' => $this->getFieldValue($obj, 'logable'), - 'invoice_on' => $this->getFieldValue($obj, 'invoice'), - 'hidden_on' => $this->getFieldValue($obj, 'hidden'), - 'send_email_on' => $this->getFieldValue($obj, 'send_email'), - 'shipped_on' => $this->getFieldValue($obj, 'shipped'), - 'paid_on' => $this->getFieldValue($obj, 'paid'), - 'delivery_on' => $this->getFieldValue($obj, 'delivery'), - 'pdf_delivery_on' => $this->getFieldValue($obj, 'pdf_delivery'), - 'pdf_invoice_on' => $this->getFieldValue($obj, 'pdf_invoice'), - ); + protected function renderOrderReturnsForm() + { + $helper = $this->initOrderReturnsForm(); + $helper->show_cancel_button = true; - if ($this->getFieldValue($obj, 'color') !== false) - $this->fields_value['color'] = $this->getFieldValue($obj, 'color'); - else - $this->fields_value['color'] = "#ffffff"; + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } + if (!Validate::isCleanHtml($back)) { + die(Tools::displayError()); + } - return parent::renderForm(); - } + $helper->back_url = $back; - protected function renderOrderReturnsForm() - { - $helper = $this->initOrderReturnsForm(); - $helper->show_cancel_button = true; + $this->fields_form[0]['form'] = array( + 'tinymce' => true, + 'legend' => array( + 'title' => $this->l('Return status'), + 'icon' => 'icon-time' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Status name'), + 'name' => 'name', + 'lang' => true, + 'required' => true, + 'hint' => array( + $this->l('Order\'s return status name.'), + $this->l('Invalid characters: numbers and').' !<>,;?=+()@#"�{}_$%:' + ) + ), + array( + 'type' => 'color', + 'label' => $this->l('Color'), + 'name' => 'color', + 'hint' => $this->l('Status will be highlighted in this color. HTML colors only.').' "lightblue", "#CC6600")' + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); + return $helper->generateForm($this->fields_form); + } - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; - if (!Validate::isCleanHtml($back)) - die(Tools::displayError()); + protected function getTemplates() + { + $theme = new Theme($this->context->shop->id_theme); + $default_path = '../mails/'; + $theme_path = '../themes/'.$theme->directory.'/mails/'; // Mail templates can also be found in the theme folder - $helper->back_url = $back; + $array = array(); + foreach (Language::getLanguages(true) as $language) { + $iso_code = $language['iso_code']; - $this->fields_form[0]['form'] = array( - 'tinymce' => true, - 'legend' => array( - 'title' => $this->l('Return status'), - 'icon' => 'icon-time' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Status name'), - 'name' => 'name', - 'lang' => true, - 'required' => true, - 'hint' => array( - $this->l('Order\'s return status name.'), - $this->l('Invalid characters: numbers and').' !<>,;?=+()@#"�{}_$%:' - ) - ), - array( - 'type' => 'color', - 'label' => $this->l('Color'), - 'name' => 'color', - 'hint' => $this->l('Status will be highlighted in this color. HTML colors only.').' "lightblue", "#CC6600")' - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); - return $helper->generateForm($this->fields_form); - } + // If there is no folder for the given iso_code in /mails or in /themes/[theme_name]/mails, we bypass this language + if (!@filemtime(_PS_ADMIN_DIR_.'/'.$default_path.$iso_code) && !@filemtime(_PS_ADMIN_DIR_.'/'.$theme_path.$iso_code)) { + continue; + } - protected function getTemplates() - { - $theme = new Theme($this->context->shop->id_theme); - $default_path = '../mails/'; - $theme_path = '../themes/'.$theme->directory.'/mails/'; // Mail templates can also be found in the theme folder + $theme_templates_dir = _PS_ADMIN_DIR_.'/'.$theme_path.$iso_code; + $theme_templates = is_dir($theme_templates_dir) ? scandir($theme_templates_dir) : array(); + // We merge all available emails in one array + $templates = array_unique(array_merge(scandir(_PS_ADMIN_DIR_.'/'.$default_path.$iso_code), $theme_templates)); + foreach ($templates as $key => $template) { + if (!strncmp(strrev($template), 'lmth.', 5)) { + $search_result = array_search($template, $theme_templates); + $array[$iso_code][] = array( + 'id' => substr($template, 0, -5), + 'name' => substr($template, 0, -5), + 'folder' => ((!empty($search_result)?$theme_path:$default_path)) + ); + } + } + } - $array = array(); - foreach(Language::getLanguages(true) as $language) - { - $iso_code = $language['iso_code']; + return $array; + } - // If there is no folder for the given iso_code in /mails or in /themes/[theme_name]/mails, we bypass this language - if (!@filemtime(_PS_ADMIN_DIR_.'/'.$default_path.$iso_code) && !@filemtime(_PS_ADMIN_DIR_.'/'.$theme_path.$iso_code)) - continue; - - $theme_templates_dir = _PS_ADMIN_DIR_.'/'.$theme_path.$iso_code; - $theme_templates = is_dir($theme_templates_dir) ? scandir($theme_templates_dir) : array(); - // We merge all available emails in one array - $templates = array_unique(array_merge(scandir(_PS_ADMIN_DIR_.'/'.$default_path.$iso_code), $theme_templates)); - foreach ($templates as $key => $template) - if (!strncmp(strrev($template), 'lmth.', 5)) - { - $search_result = array_search($template, $theme_templates); - $array[$iso_code][] = array( - 'id' => substr($template, 0, -5), - 'name' => substr($template, 0, -5), - 'folder' => ((!empty($search_result)?$theme_path:$default_path)) - ); - } - } + public function postProcess() + { + if (Tools::isSubmit($this->table.'Orderby') || Tools::isSubmit($this->table.'Orderway')) { + $this->filter = true; + } - return $array; - } + if (Tools::isSubmit('submitAddorder_return_state')) { + $id_order_return_state = Tools::getValue('id_order_return_state'); - public function postProcess() - { - if (Tools::isSubmit($this->table.'Orderby') || Tools::isSubmit($this->table.'Orderway')) - $this->filter = true; + // Create Object OrderReturnState + $order_return_state = new OrderReturnState((int)$id_order_return_state); - if (Tools::isSubmit('submitAddorder_return_state')) - { - $id_order_return_state = Tools::getValue('id_order_return_state'); + $order_return_state->color = Tools::getValue('color'); + $order_return_state->name = array(); + foreach (Language::getIDs(false) as $id_lang) { + $order_return_state->name[$id_lang] = Tools::getValue('name_'.$id_lang); + } - // Create Object OrderReturnState - $order_return_state = new OrderReturnState((int)$id_order_return_state); + // Update object + if (!$order_return_state->save()) { + $this->errors[] = Tools::displayError('An error has occurred: Can\'t save the current order\'s return status.'); + } else { + Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$this->token); + } + } - $order_return_state->color = Tools::getValue('color'); - $order_return_state->name = array(); - foreach (Language::getIDs(false) as $id_lang) - $order_return_state->name[$id_lang] = Tools::getValue('name_'.$id_lang); + if (Tools::isSubmit('submitBulkdeleteorder_return_state')) { + $this->className = 'OrderReturnState'; + $this->table = 'order_return_state'; + $this->boxes = Tools::getValue('order_return_stateBox'); + parent::processBulkDelete(); + } - // Update object - if (!$order_return_state->save()) - $this->errors[] = Tools::displayError('An error has occurred: Can\'t save the current order\'s return status.'); - else - Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$this->token); - } + if (Tools::isSubmit('deleteorder_return_state')) { + $id_order_return_state = Tools::getValue('id_order_return_state'); - if (Tools::isSubmit('submitBulkdeleteorder_return_state')) - { - $this->className = 'OrderReturnState'; - $this->table = 'order_return_state'; - $this->boxes = Tools::getValue('order_return_stateBox'); - parent::processBulkDelete(); - } + // Create Object OrderReturnState + $order_return_state = new OrderReturnState((int)$id_order_return_state); - if (Tools::isSubmit('deleteorder_return_state')) - { - $id_order_return_state = Tools::getValue('id_order_return_state'); + if (!$order_return_state->delete()) { + $this->errors[] = Tools::displayError('An error has occurred: Can\'t delete the current order\'s return status.'); + } else { + Tools::redirectAdmin(self::$currentIndex.'&conf=1&token='.$this->token); + } + } - // Create Object OrderReturnState - $order_return_state = new OrderReturnState((int)$id_order_return_state); + if (Tools::isSubmit('submitAdd'.$this->table)) { + $this->deleted = false; // Disabling saving historisation + $_POST['invoice'] = (int)Tools::getValue('invoice_on'); + $_POST['logable'] = (int)Tools::getValue('logable_on'); + $_POST['send_email'] = (int)Tools::getValue('send_email_on'); + $_POST['hidden'] = (int)Tools::getValue('hidden_on'); + $_POST['shipped'] = (int)Tools::getValue('shipped_on'); + $_POST['paid'] = (int)Tools::getValue('paid_on'); + $_POST['delivery'] = (int)Tools::getValue('delivery_on'); + $_POST['pdf_delivery'] = (int)Tools::getValue('pdf_delivery_on'); + $_POST['pdf_invoice'] = (int)Tools::getValue('pdf_invoice_on'); + if (!$_POST['send_email']) { + foreach (Language::getIDs(false) as $id_lang) { + $_POST['template_'.$id_lang] = ''; + } + } - if (!$order_return_state->delete()) - $this->errors[] = Tools::displayError('An error has occurred: Can\'t delete the current order\'s return status.'); - else - Tools::redirectAdmin(self::$currentIndex.'&conf=1&token='.$this->token); - } + return parent::postProcess(); + } elseif (Tools::isSubmit('delete'.$this->table)) { + $order_state = new OrderState(Tools::getValue('id_order_state'), $this->context->language->id); + if (!$order_state->isRemovable()) { + $this->errors[] = $this->l('For security reasons, you cannot delete default order statuses.'); + } else { + return parent::postProcess(); + } + } elseif (Tools::isSubmit('submitBulkdelete'.$this->table)) { + foreach (Tools::getValue($this->table.'Box') as $selection) { + $order_state = new OrderState((int)$selection, $this->context->language->id); + if (!$order_state->isRemovable()) { + $this->errors[] = $this->l('For security reasons, you cannot delete default order statuses.'); + break; + } + } - if (Tools::isSubmit('submitAdd'.$this->table)) - { - $this->deleted = false; // Disabling saving historisation - $_POST['invoice'] = (int)Tools::getValue('invoice_on'); - $_POST['logable'] = (int)Tools::getValue('logable_on'); - $_POST['send_email'] = (int)Tools::getValue('send_email_on'); - $_POST['hidden'] = (int)Tools::getValue('hidden_on'); - $_POST['shipped'] = (int)Tools::getValue('shipped_on'); - $_POST['paid'] = (int)Tools::getValue('paid_on'); - $_POST['delivery'] = (int)Tools::getValue('delivery_on'); - $_POST['pdf_delivery'] = (int)Tools::getValue('pdf_delivery_on'); - $_POST['pdf_invoice'] = (int)Tools::getValue('pdf_invoice_on'); - if (!$_POST['send_email']) - foreach (Language::getIDs(false) as $id_lang) - $_POST['template_'.$id_lang] = ''; + if (!count($this->errors)) { + return parent::postProcess(); + } + } else { + return parent::postProcess(); + } + } - return parent::postProcess(); - } - elseif (Tools::isSubmit('delete'.$this->table)) - { - $order_state = new OrderState(Tools::getValue('id_order_state'), $this->context->language->id); - if (!$order_state->isRemovable()) - $this->errors[] = $this->l('For security reasons, you cannot delete default order statuses.'); - else - return parent::postProcess(); - } - elseif (Tools::isSubmit('submitBulkdelete'.$this->table)) - { - foreach (Tools::getValue($this->table.'Box') as $selection) - { - $order_state = new OrderState((int)$selection, $this->context->language->id); - if (!$order_state->isRemovable()) - { - $this->errors[] = $this->l('For security reasons, you cannot delete default order statuses.'); - break; - } - } + protected function filterToField($key, $filter) + { + if ($this->table == 'order_state') { + $this->initOrderStatutsList(); + } elseif ($this->table == 'order_return_state') { + $this->initOrdersReturnsList(); + } - if (!count($this->errors)) - return parent::postProcess(); - } - else - return parent::postProcess(); - } + return parent::filterToField($key, $filter); + } - protected function filterToField($key, $filter) - { - if ($this->table == 'order_state') - $this->initOrderStatutsList(); - elseif ($this->table == 'order_return_state') - $this->initOrdersReturnsList(); - return parent::filterToField($key, $filter); - } + protected function afterImageUpload() + { + parent::afterImageUpload(); - protected function afterImageUpload() - { - parent::afterImageUpload(); + if (($id_order_state = (int)Tools::getValue('id_order_state')) && + isset($_FILES) && count($_FILES) && file_exists(_PS_ORDER_STATE_IMG_DIR_.$id_order_state.'.gif')) { + $current_file = _PS_TMP_IMG_DIR_.'order_state_mini_'.$id_order_state.'_'.$this->context->shop->id.'.gif'; - if (($id_order_state = (int)Tools::getValue('id_order_state')) && - isset($_FILES) && count($_FILES) && file_exists(_PS_ORDER_STATE_IMG_DIR_.$id_order_state.'.gif')) - { - $current_file = _PS_TMP_IMG_DIR_.'order_state_mini_'.$id_order_state.'_'.$this->context->shop->id.'.gif'; + if (file_exists($current_file)) { + unlink($current_file); + } + } - if (file_exists($current_file)) - unlink($current_file); - } + return true; + } - return true; - } + public function ajaxProcessSendEmailOrderState() + { + $id_order_state = (int)Tools::getValue('id_order_state'); - public function ajaxProcessSendEmailOrderState() - { - $id_order_state = (int)Tools::getValue('id_order_state'); + $sql = 'UPDATE '._DB_PREFIX_.'order_state SET `send_email`= NOT `send_email` WHERE id_order_state='.$id_order_state; + $result = Db::getInstance()->execute($sql); - $sql = 'UPDATE '._DB_PREFIX_.'order_state SET `send_email`= NOT `send_email` WHERE id_order_state='.$id_order_state; - $result = Db::getInstance()->execute($sql); + if ($result) { + echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); + } else { + echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); + } + } - if ($result) - echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); - else - echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); - } + public function ajaxProcessDeliveryOrderState() + { + $id_order_state = (int)Tools::getValue('id_order_state'); - public function ajaxProcessDeliveryOrderState() - { - $id_order_state = (int)Tools::getValue('id_order_state'); + $sql = 'UPDATE '._DB_PREFIX_.'order_state SET `delivery`= NOT `delivery` WHERE id_order_state='.$id_order_state; + $result = Db::getInstance()->execute($sql); - $sql = 'UPDATE '._DB_PREFIX_.'order_state SET `delivery`= NOT `delivery` WHERE id_order_state='.$id_order_state; - $result = Db::getInstance()->execute($sql); + if ($result) { + echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); + } else { + echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); + } + } - if ($result) - echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); - else - echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); - } + public function ajaxProcessInvoiceOrderState() + { + $id_order_state = (int)Tools::getValue('id_order_state'); - public function ajaxProcessInvoiceOrderState() - { - $id_order_state = (int)Tools::getValue('id_order_state'); + $sql = 'UPDATE '._DB_PREFIX_.'order_state SET `invoice`= NOT `invoice` WHERE id_order_state='.$id_order_state; + $result = Db::getInstance()->execute($sql); - $sql = 'UPDATE '._DB_PREFIX_.'order_state SET `invoice`= NOT `invoice` WHERE id_order_state='.$id_order_state; - $result = Db::getInstance()->execute($sql); - - if ($result) - echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); - else - echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); - } + if ($result) { + echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); + } else { + echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); + } + } } diff --git a/controllers/admin/AdminStockConfigurationController.php b/controllers/admin/AdminStockConfigurationController.php index aae259e5..53528634 100644 --- a/controllers/admin/AdminStockConfigurationController.php +++ b/controllers/admin/AdminStockConfigurationController.php @@ -30,606 +30,608 @@ */ class AdminStockConfigurationControllerCore extends AdminController { - /* - * By default, we use StockMvtReason as the table / className - */ - public function __construct() - { - $this->bootstrap = true; - $this->context = Context::getContext(); - $this->table = 'stock_mvt_reason'; - $this->className = 'StockMvtReason'; - $this->lang = true; - $this->multishop_context = Shop::CONTEXT_ALL; + /* + * By default, we use StockMvtReason as the table / className + */ + public function __construct() + { + $this->bootstrap = true; + $this->context = Context::getContext(); + $this->table = 'stock_mvt_reason'; + $this->className = 'StockMvtReason'; + $this->lang = true; + $this->multishop_context = Shop::CONTEXT_ALL; - // defines fields - $this->fields_list = array( - 'id_stock_mvt_reason' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs', - 'search' => false, - ), - 'sign' => array( - 'title' => $this->l('Action'), - 'align' => 'center', - 'type' => 'select', - 'filter_key' => 'a!sign', - 'list' => array( - '1' => $this->l('Increase'), - '-1' => $this->l('Decrease'), - ), - 'icon' => array( - -1 => 'remove_stock.png', - 1 => 'add_stock.png' - ), - 'orderby' => false, - 'class' => 'fixed-width-sm', - 'search' => false, - ), - 'name' => array( - 'title' => $this->l('Name'), - 'filter_key' => 'b!name', - 'search' => false, - ), - ); + // defines fields + $this->fields_list = array( + 'id_stock_mvt_reason' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs', + 'search' => false, + ), + 'sign' => array( + 'title' => $this->l('Action'), + 'align' => 'center', + 'type' => 'select', + 'filter_key' => 'a!sign', + 'list' => array( + '1' => $this->l('Increase'), + '-1' => $this->l('Decrease'), + ), + 'icon' => array( + -1 => 'remove_stock.png', + 1 => 'add_stock.png' + ), + 'orderby' => false, + 'class' => 'fixed-width-sm', + 'search' => false, + ), + 'name' => array( + 'title' => $this->l('Name'), + 'filter_key' => 'b!name', + 'search' => false, + ), + ); - // loads labels (incremenation) - $reasons_inc = StockMvtReason::getStockMvtReasonsWithFilter($this->context->language->id, - array(Configuration::get('PS_STOCK_MVT_TRANSFER_TO')), 1); - // loads labaels (decremenation) - $reasons_dec = StockMvtReason::getStockMvtReasonsWithFilter($this->context->language->id, - array(Configuration::get('PS_STOCK_MVT_TRANSFER_FROM')), -1); + // loads labels (incremenation) + $reasons_inc = StockMvtReason::getStockMvtReasonsWithFilter($this->context->language->id, + array(Configuration::get('PS_STOCK_MVT_TRANSFER_TO')), 1); + // loads labaels (decremenation) + $reasons_dec = StockMvtReason::getStockMvtReasonsWithFilter($this->context->language->id, + array(Configuration::get('PS_STOCK_MVT_TRANSFER_FROM')), -1); - // defines options for StockMvt - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Options'), - 'fields' => array( - 'PS_STOCK_MVT_INC_REASON_DEFAULT' => array( - 'title' => $this->l('Default label for increasing stock'), - 'cast' => 'intval', - 'type' => 'select', - 'list' => $reasons_inc, - 'identifier' => 'id_stock_mvt_reason', - 'visibility' => Shop::CONTEXT_ALL - ), - 'PS_STOCK_MVT_DEC_REASON_DEFAULT' => array( - 'title' => $this->l('Default label for decreasing stock'), - 'cast' => 'intval', - 'type' => 'select', - 'list' => $reasons_dec, - 'identifier' => 'id_stock_mvt_reason', - 'visibility' => Shop::CONTEXT_ALL - ), - 'PS_STOCK_CUSTOMER_ORDER_REASON' => array( - 'title' => $this->l('Default label for decreasing stock when a customer order is shipped'), - 'cast' => 'intval', - 'type' => 'select', - 'list' => $reasons_dec, - 'identifier' => 'id_stock_mvt_reason', - 'visibility' => Shop::CONTEXT_ALL - ), - 'PS_STOCK_MVT_SUPPLY_ORDER' => array( - 'title' => $this->l('Default label for increasing stock when a supply order is received'), - 'cast' => 'intval', - 'type' => 'select', - 'list' => $reasons_inc, - 'identifier' => 'id_stock_mvt_reason', - 'visibility' => Shop::CONTEXT_ALL - ), - ), - 'submit' => array('title' => $this->l('Save')), - ) - ); + // defines options for StockMvt + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Options'), + 'fields' => array( + 'PS_STOCK_MVT_INC_REASON_DEFAULT' => array( + 'title' => $this->l('Default label for increasing stock'), + 'cast' => 'intval', + 'type' => 'select', + 'list' => $reasons_inc, + 'identifier' => 'id_stock_mvt_reason', + 'visibility' => Shop::CONTEXT_ALL + ), + 'PS_STOCK_MVT_DEC_REASON_DEFAULT' => array( + 'title' => $this->l('Default label for decreasing stock'), + 'cast' => 'intval', + 'type' => 'select', + 'list' => $reasons_dec, + 'identifier' => 'id_stock_mvt_reason', + 'visibility' => Shop::CONTEXT_ALL + ), + 'PS_STOCK_CUSTOMER_ORDER_REASON' => array( + 'title' => $this->l('Default label for decreasing stock when a customer order is shipped'), + 'cast' => 'intval', + 'type' => 'select', + 'list' => $reasons_dec, + 'identifier' => 'id_stock_mvt_reason', + 'visibility' => Shop::CONTEXT_ALL + ), + 'PS_STOCK_MVT_SUPPLY_ORDER' => array( + 'title' => $this->l('Default label for increasing stock when a supply order is received'), + 'cast' => 'intval', + 'type' => 'select', + 'list' => $reasons_inc, + 'identifier' => 'id_stock_mvt_reason', + 'visibility' => Shop::CONTEXT_ALL + ), + ), + 'submit' => array('title' => $this->l('Save')), + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function init() - { - // if we are managing the second list (i.e. supply order status) - if (Tools::isSubmit('submitAddsupply_order_state') || - Tools::isSubmit('addsupply_order_state') || - Tools::isSubmit('updatesupply_order_state') || - Tools::isSubmit('deletesupply_order_state')) - { - $this->table = 'supply_order_state'; - $this->className = 'SupplyOrderState'; - $this->identifier = 'id_supply_order_state'; - $this->display = 'edit'; - } - parent::init(); - } + public function init() + { + // if we are managing the second list (i.e. supply order status) + if (Tools::isSubmit('submitAddsupply_order_state') || + Tools::isSubmit('addsupply_order_state') || + Tools::isSubmit('updatesupply_order_state') || + Tools::isSubmit('deletesupply_order_state')) { + $this->table = 'supply_order_state'; + $this->className = 'SupplyOrderState'; + $this->identifier = 'id_supply_order_state'; + $this->display = 'edit'; + } + parent::init(); + } - /** - * AdminController::renderForm() override - * @see AdminController::renderForm() - */ - public function renderForm() - { - // if we are managing StockMvtReason - if (Tools::isSubmit('addstock_mvt_reason') || - Tools::isSubmit('updatestock_mvt_reason') || - Tools::isSubmit('submitAddstock_mvt_reason') || - Tools::isSubmit('submitUpdatestock_mvt_reason')) - { - $this->toolbar_title = $this->l('Stock: Add stock movement label'); + /** + * AdminController::renderForm() override + * @see AdminController::renderForm() + */ + public function renderForm() + { + // if we are managing StockMvtReason + if (Tools::isSubmit('addstock_mvt_reason') || + Tools::isSubmit('updatestock_mvt_reason') || + Tools::isSubmit('submitAddstock_mvt_reason') || + Tools::isSubmit('submitUpdatestock_mvt_reason')) { + $this->toolbar_title = $this->l('Stock: Add stock movement label'); - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Stock Movement label'), - 'icon' => 'icon-pencil' - ), - 'input' => array( - array( - 'type' => 'text', - 'lang' => true, - 'label' => $this->l('Name'), - 'name' => 'name', - 'required' => true - ), - array( - 'type' => 'select', - 'label' => $this->l('Action'), - 'name' => 'sign', - 'required' => true, - 'options' => array( - 'query' => array( - array( - 'id' => '1', - 'name' => $this->l('Increase stock') - ), - array( - 'id' => '-1', - 'name' => $this->l('Decrease stock') - ), - ), - 'id' => 'id', - 'name' => 'name' - ), - 'desc' => $this->l('Does this label indicate a stock increase or a stock decrease?') - ), - ), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); - } - // else, if we are managing Supply Order Status - elseif (Tools::isSubmit('addsupply_order_state') || - Tools::isSubmit('updatesupply_order_state') || - Tools::isSubmit('submitAddsupply_order_state') || - Tools::isSubmit('submitUpdatesupply_order_state')) - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Supply Order Status'), - 'icon' => 'icon-pencil' - ), - 'input' => array( - array( - 'type' => 'text', - 'lang' => true, - 'label' => $this->l('Status'), - 'name' => 'name', - 'required' => true - ), - array( - 'type' => 'color', - 'label' => $this->l('Color'), - 'name' => 'color', - 'hint' => $this->l('Status will be highlighted in this color. HTML colors only.'), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Editable'), - 'name' => 'editable', - 'required' => true, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - 'hint' => $this->l('Is it is possible to edit the order? Keep in mind that an editable order cannot be sent to the supplier.') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Delivery note'), - 'name' => 'delivery_note', - 'required' => true, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - 'hint' => $this->l('Is it possible to generate a delivery note for the order?') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Delivery status'), - 'name' => 'receipt_state', - 'required' => true, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - 'hint' => $this->l('Indicates whether the supplies have been either partially or completely received. This will allow you to know if ordered products have to be added to the corresponding warehouse.'), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Awaiting delivery'), - 'name' => 'pending_receipt', - 'required' => true, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - 'hint' => $this->l('Indicates that you are awaiting delivery of supplies.') - ), - ), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Stock Movement label'), + 'icon' => 'icon-pencil' + ), + 'input' => array( + array( + 'type' => 'text', + 'lang' => true, + 'label' => $this->l('Name'), + 'name' => 'name', + 'required' => true + ), + array( + 'type' => 'select', + 'label' => $this->l('Action'), + 'name' => 'sign', + 'required' => true, + 'options' => array( + 'query' => array( + array( + 'id' => '1', + 'name' => $this->l('Increase stock') + ), + array( + 'id' => '-1', + 'name' => $this->l('Decrease stock') + ), + ), + 'id' => 'id', + 'name' => 'name' + ), + 'desc' => $this->l('Does this label indicate a stock increase or a stock decrease?') + ), + ), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); + } + // else, if we are managing Supply Order Status + elseif (Tools::isSubmit('addsupply_order_state') || + Tools::isSubmit('updatesupply_order_state') || + Tools::isSubmit('submitAddsupply_order_state') || + Tools::isSubmit('submitUpdatesupply_order_state')) { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Supply Order Status'), + 'icon' => 'icon-pencil' + ), + 'input' => array( + array( + 'type' => 'text', + 'lang' => true, + 'label' => $this->l('Status'), + 'name' => 'name', + 'required' => true + ), + array( + 'type' => 'color', + 'label' => $this->l('Color'), + 'name' => 'color', + 'hint' => $this->l('Status will be highlighted in this color. HTML colors only.'), + ), + array( + 'type' => 'switch', + 'label' => $this->l('Editable'), + 'name' => 'editable', + 'required' => true, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + 'hint' => $this->l('Is it is possible to edit the order? Keep in mind that an editable order cannot be sent to the supplier.') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Delivery note'), + 'name' => 'delivery_note', + 'required' => true, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + 'hint' => $this->l('Is it possible to generate a delivery note for the order?') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Delivery status'), + 'name' => 'receipt_state', + 'required' => true, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + 'hint' => $this->l('Indicates whether the supplies have been either partially or completely received. This will allow you to know if ordered products have to be added to the corresponding warehouse.'), + ), + array( + 'type' => 'switch', + 'label' => $this->l('Awaiting delivery'), + 'name' => 'pending_receipt', + 'required' => true, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + 'hint' => $this->l('Indicates that you are awaiting delivery of supplies.') + ), + ), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); - if (Tools::isSubmit('addsupply_order_state')) - $this->toolbar_title = $this->l('Stock: Add supply order status'); - else - { - $this->toolbar_title = $this->l('Stock: Update supply order status'); + if (Tools::isSubmit('addsupply_order_state')) { + $this->toolbar_title = $this->l('Stock: Add supply order status'); + } else { + $this->toolbar_title = $this->l('Stock: Update supply order status'); - $id_supply_order_state = Tools::getValue('id_supply_order_state', 0); + $id_supply_order_state = Tools::getValue('id_supply_order_state', 0); - // only some fields are editable for initial states - if (in_array($id_supply_order_state, array(1, 2, 3, 4, 5, 6))) - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Supply order status'), - 'icon' => 'icon-pencil' - ), - 'input' => array( - array( - 'type' => 'text', - 'lang' => true, - 'label' => $this->l('Status'), - 'name' => 'name', - 'required' => true - ), - array( - 'type' => 'color', - 'label' => $this->l('Color'), - 'name' => 'color', - 'desc' => $this->l('Status will be highlighted in this color. HTML colors only.'), - ), - ), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); - } + // only some fields are editable for initial states + if (in_array($id_supply_order_state, array(1, 2, 3, 4, 5, 6))) { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Supply order status'), + 'icon' => 'icon-pencil' + ), + 'input' => array( + array( + 'type' => 'text', + 'lang' => true, + 'label' => $this->l('Status'), + 'name' => 'name', + 'required' => true + ), + array( + 'type' => 'color', + 'label' => $this->l('Color'), + 'name' => 'color', + 'desc' => $this->l('Status will be highlighted in this color. HTML colors only.'), + ), + ), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); + } - if (!($obj = new SupplyOrderState((int)$id_supply_order_state))) - return; + if (!($obj = new SupplyOrderState((int)$id_supply_order_state))) { + return; + } - $this->fields_value = array( - 'color' => $obj->color, - 'editable' => $obj->editable, - 'delivery_note' => $obj->delivery_note, - 'receipt_state' => $obj->receipt_state, - 'pending_receipt' => $obj->pending_receipt, - ); - foreach ($this->getLanguages() as $language) - $this->fields_value['name'][$language['id_lang']] = $this->getFieldValue($obj, 'name', $language['id_lang']); - } - } + $this->fields_value = array( + 'color' => $obj->color, + 'editable' => $obj->editable, + 'delivery_note' => $obj->delivery_note, + 'receipt_state' => $obj->receipt_state, + 'pending_receipt' => $obj->pending_receipt, + ); + foreach ($this->getLanguages() as $language) { + $this->fields_value['name'][$language['id_lang']] = $this->getFieldValue($obj, 'name', $language['id_lang']); + } + } + } - return parent::renderForm(); - } + return parent::renderForm(); + } - /** - * AdminController::renderList() override - * @see AdminController::renderList() - */ - public function renderList() - { - /** - * General messages displayed for all lists - */ - $this->displayInformation($this->l('This interface allows you to configure your supply order status and stock movement labels.').'<br />'); + /** + * AdminController::renderList() override + * @see AdminController::renderList() + */ + public function renderList() + { + /** + * General messages displayed for all lists + */ + $this->displayInformation($this->l('This interface allows you to configure your supply order status and stock movement labels.').'<br />'); - // Checks access - if (!($this->tabAccess['add'] === '1')) - unset($this->toolbar_btn['new']); + // Checks access + if (!($this->tabAccess['add'] === '1')) { + unset($this->toolbar_btn['new']); + } - /** - * First list - * Stock Mvt Labels/Reasons - */ - $first_list = null; - $this->list_no_link = true; - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->addRowActionSkipList('delete', array(1, 2, 3, 4, 5, 6, 7, 8)); - $this->_where = ' AND a.deleted = 0'; - $this->_use_found_rows = false; + /** + * First list + * Stock Mvt Labels/Reasons + */ + $first_list = null; + $this->list_no_link = true; + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->addRowActionSkipList('delete', array(1, 2, 3, 4, 5, 6, 7, 8)); + $this->_where = ' AND a.deleted = 0'; + $this->_use_found_rows = false; - $this->toolbar_title = $this->l('Stock: Stock movement labels'); - $first_list = parent::renderList(); + $this->toolbar_title = $this->l('Stock: Stock movement labels'); + $first_list = parent::renderList(); - /** - * Second list - * Supply Order Status/State - */ - $second_list = null; - unset($this->_select, $this->_where, $this->_join, $this->_group, $this->_filterHaving, $this->_filter, $this->list_skip_actions['delete'], $this->list_skip_actions['edit'], $this->list_id); + /** + * Second list + * Supply Order Status/State + */ + $second_list = null; + unset($this->_select, $this->_where, $this->_join, $this->_group, $this->_filterHaving, $this->_filter, $this->list_skip_actions['delete'], $this->list_skip_actions['edit'], $this->list_id); - // generates the actual second list - $second_list = $this->initSupplyOrderStatusList(); + // generates the actual second list + $second_list = $this->initSupplyOrderStatusList(); - // resets default table and className for options list management - $this->table = 'stock_mvt_reason'; - $this->className = 'StockMvtReason'; + // resets default table and className for options list management + $this->table = 'stock_mvt_reason'; + $this->className = 'StockMvtReason'; - // returns the final list - return $second_list.$first_list; - } + // returns the final list + return $second_list.$first_list; + } - /* - * Help function for AdminStockConfigurationController::renderList() - * @see AdminStockConfigurationController::renderList() - */ - public function initSupplyOrderStatusList() - { - $this->table = 'supply_order_state'; - $this->className = 'SupplyOrderState'; - $this->identifier = 'id_supply_order_state'; - $this->_defaultOrderBy = 'id_supply_order_state'; - $this->lang = true; - $this->list_no_link = true; - $this->_orderBy = null; - $this->addRowActionSkipList('delete', array(1, 2, 3, 4, 5, 6)); - $this->toolbar_title = $this->l('Stock: Supply order status'); - $this->initToolbar(); + /* + * Help function for AdminStockConfigurationController::renderList() + * @see AdminStockConfigurationController::renderList() + */ + public function initSupplyOrderStatusList() + { + $this->table = 'supply_order_state'; + $this->className = 'SupplyOrderState'; + $this->identifier = 'id_supply_order_state'; + $this->_defaultOrderBy = 'id_supply_order_state'; + $this->lang = true; + $this->list_no_link = true; + $this->_orderBy = null; + $this->addRowActionSkipList('delete', array(1, 2, 3, 4, 5, 6)); + $this->toolbar_title = $this->l('Stock: Supply order status'); + $this->initToolbar(); - $this->fields_list = array( - 'name' => array( - 'title' => $this->l('Name'), - 'color' => 'color', - 'search' => false, - ), - 'editable' => array( - 'title' => $this->l('Supply order can be edited?'), - 'align' => 'center', - 'active' => 'editable', - 'type' => 'bool', - 'orderby' => false, - 'class' => 'fixed-width-sm', - 'ajax' => true, - 'search' => false, - ), - 'delivery_note' => array( - 'title' => $this->l('Delivery note is available?'), - 'align' => 'center', - 'active' => 'deliveryNote', - 'type' => 'bool', - 'orderby' => false, - 'class' => 'fixed-width-sm', - 'ajax' => true, - 'search' => false, - ), - 'pending_receipt' => array( - 'title' => $this->l('Delivery is expected?'), - 'align' => 'center', - 'active' => 'pendingReceipt', - 'type' => 'bool', - 'orderby' => false, - 'class' => 'fixed-width-sm', - 'ajax' => true, - 'search' => false, - ), - 'receipt_state' => array( - 'title' => $this->l('Stock has been delivered?'), - 'align' => 'center', - 'active' => 'receiptState', - 'type' => 'bool', - 'orderby' => false, - 'class' => 'fixed-width-sm', - 'ajax' => true, - 'search' => false, - ), - 'enclosed' => array( - 'title' => $this->l('Order is closed?'), - 'align' => 'center', - 'active' => 'enclosed', - 'type' => 'bool', - 'orderby' => false, - 'class' => 'fixed-width-sm', - 'ajax' => true, - 'search' => false, - ), - ); + $this->fields_list = array( + 'name' => array( + 'title' => $this->l('Name'), + 'color' => 'color', + 'search' => false, + ), + 'editable' => array( + 'title' => $this->l('Supply order can be edited?'), + 'align' => 'center', + 'active' => 'editable', + 'type' => 'bool', + 'orderby' => false, + 'class' => 'fixed-width-sm', + 'ajax' => true, + 'search' => false, + ), + 'delivery_note' => array( + 'title' => $this->l('Delivery note is available?'), + 'align' => 'center', + 'active' => 'deliveryNote', + 'type' => 'bool', + 'orderby' => false, + 'class' => 'fixed-width-sm', + 'ajax' => true, + 'search' => false, + ), + 'pending_receipt' => array( + 'title' => $this->l('Delivery is expected?'), + 'align' => 'center', + 'active' => 'pendingReceipt', + 'type' => 'bool', + 'orderby' => false, + 'class' => 'fixed-width-sm', + 'ajax' => true, + 'search' => false, + ), + 'receipt_state' => array( + 'title' => $this->l('Stock has been delivered?'), + 'align' => 'center', + 'active' => 'receiptState', + 'type' => 'bool', + 'orderby' => false, + 'class' => 'fixed-width-sm', + 'ajax' => true, + 'search' => false, + ), + 'enclosed' => array( + 'title' => $this->l('Order is closed?'), + 'align' => 'center', + 'active' => 'enclosed', + 'type' => 'bool', + 'orderby' => false, + 'class' => 'fixed-width-sm', + 'ajax' => true, + 'search' => false, + ), + ); - return parent::renderList(); - } + return parent::renderList(); + } - /** - * AdminController::postProcess() override - * @see AdminController::postProcess() - */ - public function postProcess() - { - // SupplyOrderState - if (Tools::isSubmit('submitAddsupply_order_state') || - Tools::isSubmit('deletesupply_order_state') || - Tools::isSubmit('submitUpdatesupply_order_state')) - { - if (Tools::isSubmit('deletesupply_order_state')) - $this->action = 'delete'; - else - $this->action = 'save'; - $this->table = 'supply_order_state'; - $this->className = 'SupplyOrderState'; - $this->identifier = 'id_supply_order_state'; - $this->_defaultOrderBy = 'id_supply_order_state'; - } - // StockMvtReason - elseif (Tools::isSubmit('delete'.$this->table)) - $this->deleted = true; + /** + * AdminController::postProcess() override + * @see AdminController::postProcess() + */ + public function postProcess() + { + // SupplyOrderState + if (Tools::isSubmit('submitAddsupply_order_state') || + Tools::isSubmit('deletesupply_order_state') || + Tools::isSubmit('submitUpdatesupply_order_state')) { + if (Tools::isSubmit('deletesupply_order_state')) { + $this->action = 'delete'; + } else { + $this->action = 'save'; + } + $this->table = 'supply_order_state'; + $this->className = 'SupplyOrderState'; + $this->identifier = 'id_supply_order_state'; + $this->_defaultOrderBy = 'id_supply_order_state'; + } + // StockMvtReason + elseif (Tools::isSubmit('delete'.$this->table)) { + $this->deleted = true; + } - return parent::postProcess(); - } + return parent::postProcess(); + } - /** - * AdminController::getList() override - * @see AdminController::getList() - * - * @param int $id_lang - * @param string|null $order_by - * @param string|null $order_way - * @param int $start - * @param int|null $limit - * @param int|bool $id_lang_shop - * - * @throws PrestaShopException - */ - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + /** + * AdminController::getList() override + * @see AdminController::getList() + * + * @param int $id_lang + * @param string|null $order_by + * @param string|null $order_way + * @param int $start + * @param int|null $limit + * @param int|bool $id_lang_shop + * + * @throws PrestaShopException + */ + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - //If there is a field product_name in the list, check if this field is null and display standard message - foreach ($this->fields_list as $key => $value) - if ($key == 'product_name') - { - $nb_items = count($this->_list); + //If there is a field product_name in the list, check if this field is null and display standard message + foreach ($this->fields_list as $key => $value) { + if ($key == 'product_name') { + $nb_items = count($this->_list); - for ($i = 0; $i < $nb_items; ++$i) - { - $item = &$this->_list[$i]; + for ($i = 0; $i < $nb_items; ++$i) { + $item = &$this->_list[$i]; - if (empty($item['product_name'])) - $item['product_name'] = $this->l('The name of this product is not available. It may have been deleted from the system.'); - } - } - } - - public function initContent() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate the Advanced Stock Management feature before you can use this feature.'); - return false; - } - parent::initContent(); - } - - public function initProcess() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate the Advanced Stock Management feature before you can use this feature.'); - return false; - } - parent::initProcess(); - } + if (empty($item['product_name'])) { + $item['product_name'] = $this->l('The name of this product is not available. It may have been deleted from the system.'); + } + } + } + } + } + + public function initContent() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate the Advanced Stock Management feature before you can use this feature.'); + return false; + } + parent::initContent(); + } + + public function initProcess() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate the Advanced Stock Management feature before you can use this feature.'); + return false; + } + parent::initProcess(); + } - public function ajaxProcessEditableSupplyOrderState() - { - $id_supply_order_state = (int)Tools::getValue('id_supply_order_state'); + public function ajaxProcessEditableSupplyOrderState() + { + $id_supply_order_state = (int)Tools::getValue('id_supply_order_state'); - $sql = 'UPDATE '._DB_PREFIX_.'supply_order_state SET `editable` = NOT `editable` WHERE id_supply_order_state='.$id_supply_order_state; - $result = Db::getInstance()->execute($sql); + $sql = 'UPDATE '._DB_PREFIX_.'supply_order_state SET `editable` = NOT `editable` WHERE id_supply_order_state='.$id_supply_order_state; + $result = Db::getInstance()->execute($sql); - if ($result) - echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); - else - echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); - } + if ($result) { + echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); + } else { + echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); + } + } - public function ajaxProcessDeliveryNoteSupplyOrderState() - { - $id_supply_order_state = (int)Tools::getValue('id_supply_order_state'); + public function ajaxProcessDeliveryNoteSupplyOrderState() + { + $id_supply_order_state = (int)Tools::getValue('id_supply_order_state'); - $sql = 'UPDATE '._DB_PREFIX_.'supply_order_state SET `delivery_note` = NOT `delivery_note` WHERE id_supply_order_state='.$id_supply_order_state; - $result = Db::getInstance()->execute($sql); + $sql = 'UPDATE '._DB_PREFIX_.'supply_order_state SET `delivery_note` = NOT `delivery_note` WHERE id_supply_order_state='.$id_supply_order_state; + $result = Db::getInstance()->execute($sql); - if ($result) - echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); - else - echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); - } + if ($result) { + echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); + } else { + echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); + } + } - public function ajaxProcessPendingReceiptSupplyOrderState() - { - $id_supply_order_state = (int)Tools::getValue('id_supply_order_state'); + public function ajaxProcessPendingReceiptSupplyOrderState() + { + $id_supply_order_state = (int)Tools::getValue('id_supply_order_state'); - $sql = 'UPDATE '._DB_PREFIX_.'supply_order_state SET `pending_receipt` = NOT `pending_receipt` WHERE id_supply_order_state='.$id_supply_order_state; - $result = Db::getInstance()->execute($sql); + $sql = 'UPDATE '._DB_PREFIX_.'supply_order_state SET `pending_receipt` = NOT `pending_receipt` WHERE id_supply_order_state='.$id_supply_order_state; + $result = Db::getInstance()->execute($sql); - if ($result) - echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); - else - echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); - } + if ($result) { + echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); + } else { + echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); + } + } - public function ajaxProcessReceiptStateSupplyOrderState() - { - $id_supply_order_state = (int)Tools::getValue('id_supply_order_state'); + public function ajaxProcessReceiptStateSupplyOrderState() + { + $id_supply_order_state = (int)Tools::getValue('id_supply_order_state'); - $sql = 'UPDATE '._DB_PREFIX_.'supply_order_state SET `receipt_state` = NOT `receipt_state` WHERE id_supply_order_state='.$id_supply_order_state; - $result = Db::getInstance()->execute($sql); + $sql = 'UPDATE '._DB_PREFIX_.'supply_order_state SET `receipt_state` = NOT `receipt_state` WHERE id_supply_order_state='.$id_supply_order_state; + $result = Db::getInstance()->execute($sql); - if ($result) - echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); - else - echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); - } + if ($result) { + echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); + } else { + echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); + } + } - public function ajaxProcessEnclosedSupplyOrderState() - { - $id_supply_order_state = (int)Tools::getValue('id_supply_order_state'); + public function ajaxProcessEnclosedSupplyOrderState() + { + $id_supply_order_state = (int)Tools::getValue('id_supply_order_state'); - $sql = 'UPDATE '._DB_PREFIX_.'supply_order_state SET `enclosed`= NOT `enclosed` WHERE id_supply_order_state='.$id_supply_order_state; - $result = Db::getInstance()->execute($sql); + $sql = 'UPDATE '._DB_PREFIX_.'supply_order_state SET `enclosed`= NOT `enclosed` WHERE id_supply_order_state='.$id_supply_order_state; + $result = Db::getInstance()->execute($sql); - if ($result) - echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); - else - echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); - } + if ($result) { + echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); + } else { + echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); + } + } } diff --git a/controllers/admin/AdminStockCoverController.php b/controllers/admin/AdminStockCoverController.php index 514a1d57..2e053714 100644 --- a/controllers/admin/AdminStockCoverController.php +++ b/controllers/admin/AdminStockCoverController.php @@ -30,379 +30,376 @@ */ class AdminStockCoverControllerCore extends AdminController { - protected $stock_cover_warehouses; - protected $stock_cover_periods; + protected $stock_cover_warehouses; + protected $stock_cover_periods; - public function __construct() - { - $this->bootstrap = true; - $this->context = Context::getContext(); - $this->table = 'product'; - $this->className = 'Product'; - $this->list_id = 'product'; - $this->lang = true; - $this->colorOnBackground = true; - $this->multishop_context = Shop::CONTEXT_ALL; - $this->tpl_list_vars['show_filter'] = true; + public function __construct() + { + $this->bootstrap = true; + $this->context = Context::getContext(); + $this->table = 'product'; + $this->className = 'Product'; + $this->list_id = 'product'; + $this->lang = true; + $this->colorOnBackground = true; + $this->multishop_context = Shop::CONTEXT_ALL; + $this->tpl_list_vars['show_filter'] = true; - $this->fields_list = array( - 'reference' => array( - 'title' => $this->l('Reference'), - 'align' => 'center', - 'filter_key' => 'a!reference' - ), - 'ean13' => array( - 'title' => $this->l('EAN13'), - 'align' => 'center', - 'filter_key' => 'a!ean13' - ), - 'upc' => array( - 'title' => $this->l('UPC'), - 'align' => 'center', - 'filter_key' => 'a!upc' - ), - 'name' => array( - 'title' => $this->l('Name'), - 'filter_key' => 'b!name' - ), - 'qty_sold' => array( - 'title' => $this->l('Quantity sold'), - 'orderby' => false, - 'search' => false, - 'hint' => $this->l('Quantity sold during the defined period.'), - ), - 'coverage' => array( - 'title' => $this->l('Coverage'), - 'orderby' => false, - 'search' => false, - 'hint' => $this->l('Days left before your stock runs out.'), - ), - 'stock' => array( - 'title' => $this->l('Quantity'), - 'orderby' => false, - 'search' => false, - 'hint' => $this->l('Physical (usable) quantity.') - ), - ); + $this->fields_list = array( + 'reference' => array( + 'title' => $this->l('Reference'), + 'align' => 'center', + 'filter_key' => 'a!reference' + ), + 'ean13' => array( + 'title' => $this->l('EAN13'), + 'align' => 'center', + 'filter_key' => 'a!ean13' + ), + 'upc' => array( + 'title' => $this->l('UPC'), + 'align' => 'center', + 'filter_key' => 'a!upc' + ), + 'name' => array( + 'title' => $this->l('Name'), + 'filter_key' => 'b!name' + ), + 'qty_sold' => array( + 'title' => $this->l('Quantity sold'), + 'orderby' => false, + 'search' => false, + 'hint' => $this->l('Quantity sold during the defined period.'), + ), + 'coverage' => array( + 'title' => $this->l('Coverage'), + 'orderby' => false, + 'search' => false, + 'hint' => $this->l('Days left before your stock runs out.'), + ), + 'stock' => array( + 'title' => $this->l('Quantity'), + 'orderby' => false, + 'search' => false, + 'hint' => $this->l('Physical (usable) quantity.') + ), + ); - // pre-defines coverage periods - $this->stock_cover_periods = array( - $this->l('One week') => 7, - $this->l('Two weeks') => 14, - $this->l('Three weeks') => 21, - $this->l('One month') => 31, - $this->l('Six months') => 186, - $this->l('One year') => 365 - ); + // pre-defines coverage periods + $this->stock_cover_periods = array( + $this->l('One week') => 7, + $this->l('Two weeks') => 14, + $this->l('Three weeks') => 21, + $this->l('One month') => 31, + $this->l('Six months') => 186, + $this->l('One year') => 365 + ); - // gets the list of warehouses available - $this->stock_cover_warehouses = Warehouse::getWarehouses(true); - // gets the final list of warehouses - array_unshift($this->stock_cover_warehouses, array('id_warehouse' => -1, 'name' => $this->l('All Warehouses'))); + // gets the list of warehouses available + $this->stock_cover_warehouses = Warehouse::getWarehouses(true); + // gets the final list of warehouses + array_unshift($this->stock_cover_warehouses, array('id_warehouse' => -1, 'name' => $this->l('All Warehouses'))); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - $this->page_header_toolbar_title = $this->l('Stock coverage'); + public function initPageHeaderToolbar() + { + $this->page_header_toolbar_title = $this->l('Stock coverage'); - if ($this->display == 'details') - $this->page_header_toolbar_btn['back_to_list'] = array( - 'href' => Context::getContext()->link->getAdminLink('AdminStockCover') - .(Tools::getValue('coverage_period') ? '&coverage_period='.Tools::getValue('coverage_period') : '') - .(Tools::getValue('warn_days') ? '&warn_days='.Tools::getValue('warn_days') : '') - .(Tools::getValue('id_warehouse') ? '&id_warehouse='.Tools::getValue('id_warehouse') : ''), - 'desc' => $this->l('Back to list', null, null, false), - 'icon' => 'process-icon-back' - ); + if ($this->display == 'details') { + $this->page_header_toolbar_btn['back_to_list'] = array( + 'href' => Context::getContext()->link->getAdminLink('AdminStockCover') + .(Tools::getValue('coverage_period') ? '&coverage_period='.Tools::getValue('coverage_period') : '') + .(Tools::getValue('warn_days') ? '&warn_days='.Tools::getValue('warn_days') : '') + .(Tools::getValue('id_warehouse') ? '&id_warehouse='.Tools::getValue('id_warehouse') : ''), + 'desc' => $this->l('Back to list', null, null, false), + 'icon' => 'process-icon-back' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderDetails() - { - if (Tools::isSubmit('id_product')) // if a product id is submit - { - $this->lang = false; - $this->list_id = 'details'; - $this->tpl_list_vars['show_filter'] = false; - $this->actions = array(); - $this->list_simple_header = true; - $this->table = 'product_attribute'; - $lang_id = (int)$this->context->language->id; - $id_product = (int)Tools::getValue('id_product'); - $period = (Tools::getValue('period') ? (int)Tools::getValue('period') : 7); - $warehouse = Tools::getValue('id_warehouse', -1); - $where_warehouse = ''; - if ($warehouse != -1) - $where_warehouse = ' AND s.id_warehouse = '.(int)$warehouse; + public function renderDetails() + { + if (Tools::isSubmit('id_product')) { + // if a product id is submit - $this->_select = 'a.id_product_attribute as id, a.id_product, stock_view.reference, stock_view.ean13, + $this->lang = false; + $this->list_id = 'details'; + $this->tpl_list_vars['show_filter'] = false; + $this->actions = array(); + $this->list_simple_header = true; + $this->table = 'product_attribute'; + $lang_id = (int)$this->context->language->id; + $id_product = (int)Tools::getValue('id_product'); + $period = (Tools::getValue('period') ? (int)Tools::getValue('period') : 7); + $warehouse = Tools::getValue('id_warehouse', -1); + $where_warehouse = ''; + if ($warehouse != -1) { + $where_warehouse = ' AND s.id_warehouse = '.(int)$warehouse; + } + + $this->_select = 'a.id_product_attribute as id, a.id_product, stock_view.reference, stock_view.ean13, stock_view.upc, stock_view.usable_quantity as stock'; - $this->_join = ' INNER JOIN + $this->_join = ' INNER JOIN ( SELECT SUM(s.usable_quantity) as usable_quantity, s.id_product_attribute, s.reference, s.ean13, s.upc FROM '._DB_PREFIX_.'stock s WHERE s.id_product = '.(int)$id_product. - $where_warehouse.' + $where_warehouse.' GROUP BY s.id_product_attribute ) stock_view ON (stock_view.id_product_attribute = a.id_product_attribute)'; - $this->_where = 'AND a.id_product = '.(int)$id_product; - $this->_group = 'GROUP BY a.id_product_attribute'; - return parent::renderList(); - } - } + $this->_where = 'AND a.id_product = '.(int)$id_product; + $this->_group = 'GROUP BY a.id_product_attribute'; + return parent::renderList(); + } + } - /** - * AdminController::renderList() override - * @see AdminController::renderList() - */ - public function renderList() - { - $this->addRowAction('details'); + /** + * AdminController::renderList() override + * @see AdminController::renderList() + */ + public function renderList() + { + $this->addRowAction('details'); - $this->toolbar_btn = array(); + $this->toolbar_btn = array(); - // disables link - $this->list_no_link = true; + // disables link + $this->list_no_link = true; - // query - $this->_select = 'a.id_product as id, COUNT(pa.id_product_attribute) as variations, SUM(s.usable_quantity) as stock'; - $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (pa.id_product = a.id_product) + // query + $this->_select = 'a.id_product as id, COUNT(pa.id_product_attribute) as variations, SUM(s.usable_quantity) as stock'; + $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (pa.id_product = a.id_product) '.Shop::addSqlAssociation('product_attribute', 'pa', false).' INNER JOIN `'._DB_PREFIX_.'stock` s ON (s.id_product = a.id_product)'; - $this->_group = 'GROUP BY a.id_product'; + $this->_group = 'GROUP BY a.id_product'; - self::$currentIndex .= '&coverage_period='.(int)$this->getCurrentCoveragePeriod().'&warn_days='.(int)$this->getCurrentWarning(); - if ($this->getCurrentCoverageWarehouse() != -1) - { - $this->_where .= ' AND s.id_warehouse = '.(int)$this->getCurrentCoverageWarehouse(); - self::$currentIndex .= '&id_warehouse='.(int)$this->getCurrentCoverageWarehouse(); - } + self::$currentIndex .= '&coverage_period='.(int)$this->getCurrentCoveragePeriod().'&warn_days='.(int)$this->getCurrentWarning(); + if ($this->getCurrentCoverageWarehouse() != -1) { + $this->_where .= ' AND s.id_warehouse = '.(int)$this->getCurrentCoverageWarehouse(); + self::$currentIndex .= '&id_warehouse='.(int)$this->getCurrentCoverageWarehouse(); + } - // Hack for multi shop .. - $this->_where .= ' AND b.id_shop = 1'; + // Hack for multi shop .. + $this->_where .= ' AND b.id_shop = 1'; - $this->tpl_list_vars['stock_cover_periods'] = $this->stock_cover_periods; - $this->tpl_list_vars['stock_cover_cur_period'] = $this->getCurrentCoveragePeriod(); - $this->tpl_list_vars['stock_cover_warehouses'] = $this->stock_cover_warehouses; - $this->tpl_list_vars['stock_cover_cur_warehouse'] = $this->getCurrentCoverageWarehouse(); - $this->tpl_list_vars['stock_cover_warn_days'] = $this->getCurrentWarning(); - $this->ajax_params = array( - 'period' => $this->getCurrentCoveragePeriod(), - 'id_warehouse' => $this->getCurrentCoverageWarehouse(), - 'warn_days' => $this->getCurrentWarning() - ); + $this->tpl_list_vars['stock_cover_periods'] = $this->stock_cover_periods; + $this->tpl_list_vars['stock_cover_cur_period'] = $this->getCurrentCoveragePeriod(); + $this->tpl_list_vars['stock_cover_warehouses'] = $this->stock_cover_warehouses; + $this->tpl_list_vars['stock_cover_cur_warehouse'] = $this->getCurrentCoverageWarehouse(); + $this->tpl_list_vars['stock_cover_warn_days'] = $this->getCurrentWarning(); + $this->ajax_params = array( + 'period' => $this->getCurrentCoveragePeriod(), + 'id_warehouse' => $this->getCurrentCoverageWarehouse(), + 'warn_days' => $this->getCurrentWarning() + ); - $this->displayInformation($this->l('Considering the coverage period chosen and the quantity of products/combinations that you sold.')); - $this->displayInformation($this->l('This interface gives you an idea of when a product will run out of stock.')); + $this->displayInformation($this->l('Considering the coverage period chosen and the quantity of products/combinations that you sold.')); + $this->displayInformation($this->l('This interface gives you an idea of when a product will run out of stock.')); - return parent::renderList(); - } + return parent::renderList(); + } - /** - * AdminController::getList() override - * @see AdminController::getList() - * - * @param int $id_lang - * @param string|null $order_by - * @param string|null $order_way - * @param int $start - * @param int|null $limit - * @param int|bool $id_lang_shop - * - * @throws PrestaShopException - */ - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + /** + * AdminController::getList() override + * @see AdminController::getList() + * + * @param int $id_lang + * @param string|null $order_by + * @param string|null $order_way + * @param int $start + * @param int|null $limit + * @param int|bool $id_lang_shop + * + * @throws PrestaShopException + */ + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - if ($this->display == 'details') - { - $nb_items = count($this->_list); + if ($this->display == 'details') { + $nb_items = count($this->_list); - for ($i = 0; $i < $nb_items; ++$i) - { - $item = &$this->_list[$i]; - $item['name'] = Product::getProductName($item['id_product'], $item['id']); + for ($i = 0; $i < $nb_items; ++$i) { + $item = &$this->_list[$i]; + $item['name'] = Product::getProductName($item['id_product'], $item['id']); - // computes coverage - $coverage = StockManagerFactory::getManager()->getProductCoverage( - $item['id_product'], - $item['id'], - (Tools::getValue('period') ? (int)Tools::getValue('period') : 7), - (($this->getCurrentCoverageWarehouse() == -1) ? null : Tools::getValue('id_warehouse', -1)) - ); - if ($coverage != -1) // if coverage is available - { - if ($coverage < $this->getCurrentWarning()) // if highlight needed - $item['color'] = '#BDE5F8'; - $item['coverage'] = $coverage; - } - else // infinity - $item['coverage'] = '--'; + // computes coverage + $coverage = StockManagerFactory::getManager()->getProductCoverage( + $item['id_product'], + $item['id'], + (Tools::getValue('period') ? (int)Tools::getValue('period') : 7), + (($this->getCurrentCoverageWarehouse() == -1) ? null : Tools::getValue('id_warehouse', -1)) + ); + if ($coverage != -1) { + // if coverage is available - // computes quantity sold - $qty_sold = $this->getQuantitySold($item['id_product'], $item['id'], $this->getCurrentCoveragePeriod()); - if (!$qty_sold) - $item['qty_sold'] = '--'; - else - $item['qty_sold'] = $qty_sold; - } - } - else - { - $nb_items = count($this->_list); - for ($i = 0; $i < $nb_items; ++$i) - { - $item = &$this->_list[$i]; - if (array_key_exists('variations', $item) && (int)$item['variations'] <= 0) - { - // computes coverage and displays (highlights if needed) - $coverage = StockManagerFactory::getManager()->getProductCoverage( - $item['id'], - 0, - $this->getCurrentCoveragePeriod(), - (($this->getCurrentCoverageWarehouse() == -1) ? null : $this->getCurrentCoverageWarehouse()) - ); - if ($coverage != -1) // coverage is available - { - if ($coverage < $this->getCurrentWarning()) - $item['color'] = '#BDE5F8'; + if ($coverage < $this->getCurrentWarning()) { // if highlight needed + $item['color'] = '#BDE5F8'; + } + $item['coverage'] = $coverage; + } else { // infinity + $item['coverage'] = '--'; + } - $item['coverage'] = $coverage; - } - else // infinity - $item['coverage'] = '--'; + // computes quantity sold + $qty_sold = $this->getQuantitySold($item['id_product'], $item['id'], $this->getCurrentCoveragePeriod()); + if (!$qty_sold) { + $item['qty_sold'] = '--'; + } else { + $item['qty_sold'] = $qty_sold; + } + } + } else { + $nb_items = count($this->_list); + for ($i = 0; $i < $nb_items; ++$i) { + $item = &$this->_list[$i]; + if (array_key_exists('variations', $item) && (int)$item['variations'] <= 0) { + // computes coverage and displays (highlights if needed) + $coverage = StockManagerFactory::getManager()->getProductCoverage( + $item['id'], + 0, + $this->getCurrentCoveragePeriod(), + (($this->getCurrentCoverageWarehouse() == -1) ? null : $this->getCurrentCoverageWarehouse()) + ); + if ($coverage != -1) { + // coverage is available - // computes quantity sold - $qty_sold = $this->getQuantitySold($item['id'], 0, $this->getCurrentCoveragePeriod()); - if (!$qty_sold) - $item['qty_sold'] = '--'; - else - $item['qty_sold'] = $qty_sold; + if ($coverage < $this->getCurrentWarning()) { + $item['color'] = '#BDE5F8'; + } - // removes 'details' action on products without attributes - $this->addRowActionSkipList('details', array($item['id'])); + $item['coverage'] = $coverage; + } else { // infinity + $item['coverage'] = '--'; + } + // computes quantity sold + $qty_sold = $this->getQuantitySold($item['id'], 0, $this->getCurrentCoveragePeriod()); + if (!$qty_sold) { + $item['qty_sold'] = '--'; + } else { + $item['qty_sold'] = $qty_sold; + } - } - else - { - $item['stock'] = $this->l('See details'); - $item['reference'] = '--'; - $item['ean13'] = '--'; - $item['upc'] = '--'; - } - } - } - } + // removes 'details' action on products without attributes + $this->addRowActionSkipList('details', array($item['id'])); + } else { + $item['stock'] = $this->l('See details'); + $item['reference'] = '--'; + $item['ean13'] = '--'; + $item['upc'] = '--'; + } + } + } + } - /** - * Gets the current coverage period used - * - * @return int coverage period - */ - protected function getCurrentCoveragePeriod() - { - static $coverage_period = 0; + /** + * Gets the current coverage period used + * + * @return int coverage period + */ + protected function getCurrentCoveragePeriod() + { + static $coverage_period = 0; - if ($coverage_period == 0) - { - $coverage_period = 7; // Week by default - if ((int)Tools::getValue('coverage_period')) - $coverage_period = (int)Tools::getValue('coverage_period'); - } - return $coverage_period; - } + if ($coverage_period == 0) { + $coverage_period = 7; // Week by default + if ((int)Tools::getValue('coverage_period')) { + $coverage_period = (int)Tools::getValue('coverage_period'); + } + } + return $coverage_period; + } - /** - * Gets the current warehouse used - * - * @return int id_warehouse - */ - protected function getCurrentCoverageWarehouse() - { - static $warehouse = 0; + /** + * Gets the current warehouse used + * + * @return int id_warehouse + */ + protected function getCurrentCoverageWarehouse() + { + static $warehouse = 0; - if ($warehouse == 0) - { - $warehouse = -1; // all warehouses - if ((int)Tools::getValue('id_warehouse')) - $warehouse = (int)Tools::getValue('id_warehouse'); - } - return $warehouse; - } + if ($warehouse == 0) { + $warehouse = -1; // all warehouses + if ((int)Tools::getValue('id_warehouse')) { + $warehouse = (int)Tools::getValue('id_warehouse'); + } + } + return $warehouse; + } - /** - * Gets the current warning - * - * @return int warn_days - */ - protected function getCurrentWarning() - { - static $warning = 0; + /** + * Gets the current warning + * + * @return int warn_days + */ + protected function getCurrentWarning() + { + static $warning = 0; - if ($warning == 0) - { - $warning = 0; - if (Tools::getValue('warn_days') && Validate::isInt(Tools::getValue('warn_days'))) - $warning = (int)Tools::getValue('warn_days'); - } - return $warning; - } + if ($warning == 0) { + $warning = 0; + if (Tools::getValue('warn_days') && Validate::isInt(Tools::getValue('warn_days'))) { + $warning = (int)Tools::getValue('warn_days'); + } + } + return $warning; + } - /** - * For a given product, and a given period, returns the quantity sold - * - * @param int $id_product - * @param int $id_product_attribute - * @param int $coverage - * @return int $quantity - */ - protected function getQuantitySold($id_product, $id_product_attribute, $coverage) - { - $query = new DbQuery(); - $query->select('SUM(od.product_quantity)'); - $query->from('order_detail', 'od'); - $query->leftJoin('orders', 'o', 'od.id_order = o.id_order'); - $query->leftJoin('order_history', 'oh', 'o.date_upd = oh.date_add'); - $query->leftJoin('order_state', 'os', 'os.id_order_state = oh.id_order_state'); - $query->where('od.product_id = '.(int)$id_product); - $query->where('od.product_attribute_id = '.(int)$id_product_attribute); - $query->where('TO_DAYS("'.date('Y-m-d').' 00:00:00") - TO_DAYS(oh.date_add) <= '.(int)$coverage); - $query->where('o.valid = 1'); - $query->where('os.logable = 1 AND os.delivery = 1 AND os.shipped = 1'); + /** + * For a given product, and a given period, returns the quantity sold + * + * @param int $id_product + * @param int $id_product_attribute + * @param int $coverage + * @return int $quantity + */ + protected function getQuantitySold($id_product, $id_product_attribute, $coverage) + { + $query = new DbQuery(); + $query->select('SUM(od.product_quantity)'); + $query->from('order_detail', 'od'); + $query->leftJoin('orders', 'o', 'od.id_order = o.id_order'); + $query->leftJoin('order_history', 'oh', 'o.date_upd = oh.date_add'); + $query->leftJoin('order_state', 'os', 'os.id_order_state = oh.id_order_state'); + $query->where('od.product_id = '.(int)$id_product); + $query->where('od.product_attribute_id = '.(int)$id_product_attribute); + $query->where('TO_DAYS("'.date('Y-m-d').' 00:00:00") - TO_DAYS(oh.date_add) <= '.(int)$coverage); + $query->where('o.valid = 1'); + $query->where('os.logable = 1 AND os.delivery = 1 AND os.shipped = 1'); - $quantity = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); - return $quantity; - } - - public function initContent() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); - return false; - } - parent::initContent(); - } - - public function initProcess() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); - return false; - } + $quantity = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + return $quantity; + } + + public function initContent() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); + return false; + } + parent::initContent(); + } + + public function initProcess() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); + return false; + } - if (Tools::isSubmit('detailsproduct')) - $this->list_id = 'details'; - else - $this->list_id = 'product'; + if (Tools::isSubmit('detailsproduct')) { + $this->list_id = 'details'; + } else { + $this->list_id = 'product'; + } - parent::initProcess(); - } + parent::initProcess(); + } } diff --git a/controllers/admin/AdminStockInstantStateController.php b/controllers/admin/AdminStockInstantStateController.php index 864cf31a..7ac82f02 100644 --- a/controllers/admin/AdminStockInstantStateController.php +++ b/controllers/admin/AdminStockInstantStateController.php @@ -30,533 +30,524 @@ */ class AdminStockInstantStateControllerCore extends AdminController { - protected $stock_instant_state_warehouses = array(); + protected $stock_instant_state_warehouses = array(); - public function __construct() - { - $this->bootstrap = true; - $this->context = Context::getContext(); - $this->table = 'stock'; - $this->list_id = 'stock'; - $this->className = 'Stock'; - $this->tpl_list_vars['show_filter'] = true; - $this->lang = false; - $this->multishop_context = Shop::CONTEXT_ALL; + public function __construct() + { + $this->bootstrap = true; + $this->context = Context::getContext(); + $this->table = 'stock'; + $this->list_id = 'stock'; + $this->className = 'Stock'; + $this->tpl_list_vars['show_filter'] = true; + $this->lang = false; + $this->multishop_context = Shop::CONTEXT_ALL; - $this->fields_list = array( - 'reference' => array( - 'title' => $this->l('Reference'), - 'align' => 'center', - 'havingFilter' => true - ), - 'ean13' => array( - 'title' => $this->l('EAN13'), - 'align' => 'center', - ), - 'upc' => array( - 'title' => $this->l('UPC'), - 'align' => 'center', - ), - 'name' => array( - 'title' => $this->l('Name'), - 'havingFilter' => true - ), - 'price_te' => array( - 'title' => $this->l('Price (tax excl.)'), - 'orderby' => true, - 'search' => false, - 'type' => 'price', - 'currency' => true, - ), - 'valuation' => array( - 'title' => $this->l('Valuation'), - 'orderby' => false, - 'search' => false, - 'type' => 'price', - 'currency' => true, - 'hint' => $this->l('Total value of the physical quantity. The sum (for all prices) is not available for all warehouses, please filter by warehouse.') - ), - 'physical_quantity' => array( - 'title' => $this->l('Physical quantity'), - 'class' => 'fixed-width-xs', - 'align' => 'center', - 'orderby' => true, - 'search' => false - ), - 'usable_quantity' => array( - 'title' => $this->l('Usable quantity'), - 'class' => 'fixed-width-xs', - 'align' => 'center', - 'orderby' => true, - 'search' => false, - ), - 'real_quantity' => array( - 'title' => $this->l('Real quantity'), - 'class' => 'fixed-width-xs', - 'align' => 'center', - 'orderby' => false, - 'search' => false, - 'hint' => $this->l('Physical quantity (usable) - Client orders + Supply Orders'), - ), - ); + $this->fields_list = array( + 'reference' => array( + 'title' => $this->l('Reference'), + 'align' => 'center', + 'havingFilter' => true + ), + 'ean13' => array( + 'title' => $this->l('EAN13'), + 'align' => 'center', + ), + 'upc' => array( + 'title' => $this->l('UPC'), + 'align' => 'center', + ), + 'name' => array( + 'title' => $this->l('Name'), + 'havingFilter' => true + ), + 'price_te' => array( + 'title' => $this->l('Price (tax excl.)'), + 'orderby' => true, + 'search' => false, + 'type' => 'price', + 'currency' => true, + ), + 'valuation' => array( + 'title' => $this->l('Valuation'), + 'orderby' => false, + 'search' => false, + 'type' => 'price', + 'currency' => true, + 'hint' => $this->l('Total value of the physical quantity. The sum (for all prices) is not available for all warehouses, please filter by warehouse.') + ), + 'physical_quantity' => array( + 'title' => $this->l('Physical quantity'), + 'class' => 'fixed-width-xs', + 'align' => 'center', + 'orderby' => true, + 'search' => false + ), + 'usable_quantity' => array( + 'title' => $this->l('Usable quantity'), + 'class' => 'fixed-width-xs', + 'align' => 'center', + 'orderby' => true, + 'search' => false, + ), + 'real_quantity' => array( + 'title' => $this->l('Real quantity'), + 'class' => 'fixed-width-xs', + 'align' => 'center', + 'orderby' => false, + 'search' => false, + 'hint' => $this->l('Physical quantity (usable) - Client orders + Supply Orders'), + ), + ); - $this->addRowAction('details'); - $this->stock_instant_state_warehouses = Warehouse::getWarehouses(true); - array_unshift($this->stock_instant_state_warehouses, array('id_warehouse' => -1, 'name' => $this->l('All Warehouses'))); + $this->addRowAction('details'); + $this->stock_instant_state_warehouses = Warehouse::getWarehouses(true); + array_unshift($this->stock_instant_state_warehouses, array('id_warehouse' => -1, 'name' => $this->l('All Warehouses'))); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - $this->page_header_toolbar_title = $this->l('Instant stock status'); + public function initPageHeaderToolbar() + { + $this->page_header_toolbar_title = $this->l('Instant stock status'); - if ($this->display == 'details') - $this->page_header_toolbar_btn['back_to_list'] = array( - 'href' => Context::getContext()->link->getAdminLink('AdminStockInstantState').(Tools::getValue('id_warehouse') ? '&id_warehouse='.Tools::getValue('id_warehouse') : ''), - 'desc' => $this->l('Back to list', null, null, false), - 'icon' => 'process-icon-back' - ); - elseif (Tools::isSubmit('id_warehouse') && (int)Tools::getValue('id_warehouse') != -1) - { - $this->page_header_toolbar_btn['export-stock-state-quantities-csv'] = array( - 'short' => $this->l('Export this list as CSV', null, null, false), - 'href' => $this->context->link->getAdminLink('AdminStockInstantState').'&csv_quantities&id_warehouse='.(int)$this->getCurrentCoverageWarehouse(), - 'desc' => $this->l('Export Quantities (CSV)', null, null, false), - 'class' => 'process-icon-export' - ); + if ($this->display == 'details') { + $this->page_header_toolbar_btn['back_to_list'] = array( + 'href' => Context::getContext()->link->getAdminLink('AdminStockInstantState').(Tools::getValue('id_warehouse') ? '&id_warehouse='.Tools::getValue('id_warehouse') : ''), + 'desc' => $this->l('Back to list', null, null, false), + 'icon' => 'process-icon-back' + ); + } elseif (Tools::isSubmit('id_warehouse') && (int)Tools::getValue('id_warehouse') != -1) { + $this->page_header_toolbar_btn['export-stock-state-quantities-csv'] = array( + 'short' => $this->l('Export this list as CSV', null, null, false), + 'href' => $this->context->link->getAdminLink('AdminStockInstantState').'&csv_quantities&id_warehouse='.(int)$this->getCurrentCoverageWarehouse(), + 'desc' => $this->l('Export Quantities (CSV)', null, null, false), + 'class' => 'process-icon-export' + ); - $this->page_header_toolbar_btn['export-stock-state-prices-csv'] = array( - 'short' => $this->l('Export this list as CSV', null, null, false), - 'href' => $this->context->link->getAdminLink('AdminStockInstantState').'&csv_prices&id_warehouse='.(int)$this->getCurrentCoverageWarehouse(), - 'desc' => $this->l('Export Prices (CSV)', null, null, false), - 'class' => 'process-icon-export' - ); - } + $this->page_header_toolbar_btn['export-stock-state-prices-csv'] = array( + 'short' => $this->l('Export this list as CSV', null, null, false), + 'href' => $this->context->link->getAdminLink('AdminStockInstantState').'&csv_prices&id_warehouse='.(int)$this->getCurrentCoverageWarehouse(), + 'desc' => $this->l('Export Prices (CSV)', null, null, false), + 'class' => 'process-icon-export' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - /** - * AdminController::renderList() override - * @see AdminController::renderList() - */ - public function renderList() - { - // query - $this->_select = ' + /** + * AdminController::renderList() override + * @see AdminController::renderList() + */ + public function renderList() + { + // query + $this->_select = ' IFNULL(CONCAT(pl.name, \' : \', GROUP_CONCAT(DISTINCT agl.`name`, \' - \', al.name SEPARATOR \', \')),pl.name) as name, w.id_currency'; - $this->_group = 'GROUP BY a.id_product, a.id_product_attribute'; + $this->_group = 'GROUP BY a.id_product, a.id_product_attribute'; - $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'warehouse` w ON (w.id_warehouse = a.id_warehouse)'; - $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON ( + $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'warehouse` w ON (w.id_warehouse = a.id_warehouse)'; + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON ( a.id_product = pl.id_product AND pl.id_lang = '.(int)$this->context->language->id.' )'; - $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON (pac.id_product_attribute = a.id_product_attribute)'; - $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'attribute` atr ON (atr.id_attribute = pac.id_attribute)'; - $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al ON ( + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON (pac.id_product_attribute = a.id_product_attribute)'; + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'attribute` atr ON (atr.id_attribute = pac.id_attribute)'; + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al ON ( al.id_attribute = pac.id_attribute AND al.id_lang = '.(int)$this->context->language->id.' )'; - $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl ON ( + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl ON ( agl.id_attribute_group = atr.id_attribute_group AND agl.id_lang = '.(int)$this->context->language->id.' )'; - if ($this->getCurrentCoverageWarehouse() != -1) - { - $this->_where .= ' AND a.id_warehouse = '.$this->getCurrentCoverageWarehouse(); - self::$currentIndex .= '&id_warehouse='.(int)$this->getCurrentCoverageWarehouse(); - } + if ($this->getCurrentCoverageWarehouse() != -1) { + $this->_where .= ' AND a.id_warehouse = '.$this->getCurrentCoverageWarehouse(); + self::$currentIndex .= '&id_warehouse='.(int)$this->getCurrentCoverageWarehouse(); + } - // toolbar btn - $this->toolbar_btn = array(); - // disables link - $this->list_no_link = true; + // toolbar btn + $this->toolbar_btn = array(); + // disables link + $this->list_no_link = true; - // smarty - $this->tpl_list_vars['stock_instant_state_warehouses'] = $this->stock_instant_state_warehouses; - $this->tpl_list_vars['stock_instant_state_cur_warehouse'] = $this->getCurrentCoverageWarehouse(); - // adds ajax params - $this->ajax_params = array('id_warehouse' => $this->getCurrentCoverageWarehouse()); + // smarty + $this->tpl_list_vars['stock_instant_state_warehouses'] = $this->stock_instant_state_warehouses; + $this->tpl_list_vars['stock_instant_state_cur_warehouse'] = $this->getCurrentCoverageWarehouse(); + // adds ajax params + $this->ajax_params = array('id_warehouse' => $this->getCurrentCoverageWarehouse()); - // displays help information - $this->displayInformation($this->l('This interface allows you to display detailed information about your stock per warehouse.')); + // displays help information + $this->displayInformation($this->l('This interface allows you to display detailed information about your stock per warehouse.')); - // sets toolbar - $this->initToolbar(); + // sets toolbar + $this->initToolbar(); - $list = parent::renderList(); + $list = parent::renderList(); - // if export requested - if ((Tools::isSubmit('csv_quantities') || Tools::isSubmit('csv_prices')) && - (int)Tools::getValue('id_warehouse') != -1) - { - if (count($this->_list) > 0) - { - $this->renderCSV(); - die; - } - else - $this->displayWarning($this->l('There is nothing to export as CSV.')); - } + // if export requested + if ((Tools::isSubmit('csv_quantities') || Tools::isSubmit('csv_prices')) && + (int)Tools::getValue('id_warehouse') != -1) { + if (count($this->_list) > 0) { + $this->renderCSV(); + die; + } else { + $this->displayWarning($this->l('There is nothing to export as CSV.')); + } + } - return $list; - } + return $list; + } - public function renderDetails() - { - if (Tools::isSubmit('id_stock')) // if a product id is submit - { - $this->lang = false; - $this->table = 'stock'; - $this->list_id = 'details'; - $this->tpl_list_vars['show_filter'] = false; - $lang_id = (int)$this->context->language->id; - $this->actions = array(); - $this->list_simple_header = true; - $ids = explode('_', Tools::getValue('id_stock')); + public function renderDetails() + { + if (Tools::isSubmit('id_stock')) { + // if a product id is submit - if (count($ids) != 2) - die; + $this->lang = false; + $this->table = 'stock'; + $this->list_id = 'details'; + $this->tpl_list_vars['show_filter'] = false; + $lang_id = (int)$this->context->language->id; + $this->actions = array(); + $this->list_simple_header = true; + $ids = explode('_', Tools::getValue('id_stock')); - $id_product = $ids[0]; - $id_product_attribute = $ids[1]; - $id_warehouse = Tools::getValue('id_warehouse', -1); - $this->_select = 'IFNULL(CONCAT(pl.name, \' : \', GROUP_CONCAT(DISTINCT agl.`name`, \' - \', al.name SEPARATOR \', \')),pl.name) as name, + if (count($ids) != 2) { + die; + } + + $id_product = $ids[0]; + $id_product_attribute = $ids[1]; + $id_warehouse = Tools::getValue('id_warehouse', -1); + $this->_select = 'IFNULL(CONCAT(pl.name, \' : \', GROUP_CONCAT(DISTINCT agl.`name`, \' - \', al.name SEPARATOR \', \')),pl.name) as name, w.id_currency, a.price_te'; - $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'warehouse` AS w ON w.id_warehouse = a.id_warehouse'; - $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON ( + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'warehouse` AS w ON w.id_warehouse = a.id_warehouse'; + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON ( a.id_product = pl.id_product AND pl.id_lang = '.(int)$this->context->language->id.' )'; - $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON (pac.id_product_attribute = a.id_product_attribute)'; - $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'attribute` atr ON (atr.id_attribute = pac.id_attribute)'; - $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al ON ( + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON (pac.id_product_attribute = a.id_product_attribute)'; + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'attribute` atr ON (atr.id_attribute = pac.id_attribute)'; + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al ON ( al.id_attribute = pac.id_attribute AND al.id_lang = '.(int)$this->context->language->id.' )'; - $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl ON ( + $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl ON ( agl.id_attribute_group = atr.id_attribute_group AND agl.id_lang = '.(int)$this->context->language->id.' )'; - $this->_where = 'AND a.id_product = '.(int)$id_product.' AND a.id_product_attribute = '.(int)$id_product_attribute; + $this->_where = 'AND a.id_product = '.(int)$id_product.' AND a.id_product_attribute = '.(int)$id_product_attribute; - if ($id_warehouse != -1) - $this->_where .= ' AND a.id_warehouse = '.(int)$id_warehouse; + if ($id_warehouse != -1) { + $this->_where .= ' AND a.id_warehouse = '.(int)$id_warehouse; + } - $this->_group = 'GROUP BY a.price_te'; + $this->_group = 'GROUP BY a.price_te'; - self::$currentIndex = self::$currentIndex.'&id_stock='.Tools::getValue('id_stock').'&detailsstock'; - return parent::renderList(); - } - } + self::$currentIndex = self::$currentIndex.'&id_stock='.Tools::getValue('id_stock').'&detailsstock'; + return parent::renderList(); + } + } - /** - * AdminController::getList() override - * @see AdminController::getList() - * - * @param int $id_lang - * @param string|null $order_by - * @param string|null $order_way - * @param int $start - * @param int|null $limit - * @param int|bool $id_lang_shop - * - * @throws PrestaShopException - */ - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - if (Tools::isSubmit('id_stock')) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + /** + * AdminController::getList() override + * @see AdminController::getList() + * + * @param int $id_lang + * @param string|null $order_by + * @param string|null $order_way + * @param int $start + * @param int|null $limit + * @param int|bool $id_lang_shop + * + * @throws PrestaShopException + */ + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + if (Tools::isSubmit('id_stock')) { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - $nb_items = count($this->_list); + $nb_items = count($this->_list); - for ($i = 0; $i < $nb_items; $i++) - { - $item = &$this->_list[$i]; - $manager = StockManagerFactory::getManager(); + for ($i = 0; $i < $nb_items; $i++) { + $item = &$this->_list[$i]; + $manager = StockManagerFactory::getManager(); - // gets quantities and valuation - $query = new DbQuery(); - $query->select('SUM(physical_quantity) as physical_quantity'); - $query->select('SUM(usable_quantity) as usable_quantity'); - $query->select('SUM(price_te * physical_quantity) as valuation'); - $query->from('stock'); - $query->where('id_product = '.(int)$item['id_product'].' AND id_product_attribute = '.(int)$item['id_product_attribute']); + // gets quantities and valuation + $query = new DbQuery(); + $query->select('SUM(physical_quantity) as physical_quantity'); + $query->select('SUM(usable_quantity) as usable_quantity'); + $query->select('SUM(price_te * physical_quantity) as valuation'); + $query->from('stock'); + $query->where('id_product = '.(int)$item['id_product'].' AND id_product_attribute = '.(int)$item['id_product_attribute']); - if ($this->getCurrentCoverageWarehouse() != -1) - $query->where('id_warehouse = '.(int)$this->getCurrentCoverageWarehouse()); + if ($this->getCurrentCoverageWarehouse() != -1) { + $query->where('id_warehouse = '.(int)$this->getCurrentCoverageWarehouse()); + } - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query); + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query); - $item['physical_quantity'] = $res['physical_quantity']; - $item['usable_quantity'] = $res['usable_quantity']; - $item['valuation'] = $res['valuation']; - $item['real_quantity'] = $manager->getProductRealQuantities( - $item['id_product'], - $item['id_product_attribute'], - ($this->getCurrentCoverageWarehouse() == -1 ? null : array($this->getCurrentCoverageWarehouse())), - true - ); - } - } - else - { - if ((Tools::isSubmit('csv_quantities') || Tools::isSubmit('csv_prices')) && - (int)Tools::getValue('id_warehouse') != -1) - $limit = false; + $item['physical_quantity'] = $res['physical_quantity']; + $item['usable_quantity'] = $res['usable_quantity']; + $item['valuation'] = $res['valuation']; + $item['real_quantity'] = $manager->getProductRealQuantities( + $item['id_product'], + $item['id_product_attribute'], + ($this->getCurrentCoverageWarehouse() == -1 ? null : array($this->getCurrentCoverageWarehouse())), + true + ); + } + } else { + if ((Tools::isSubmit('csv_quantities') || Tools::isSubmit('csv_prices')) && + (int)Tools::getValue('id_warehouse') != -1) { + $limit = false; + } - $order_by_valuation = false; - $order_by_real_quantity = false; + $order_by_valuation = false; + $order_by_real_quantity = false; - if ($this->context->cookie->{$this->table.'Orderby'} == 'valuation') - { - unset($this->context->cookie->{$this->table.'Orderby'}); - $order_by_valuation = true; - } - elseif ($this->context->cookie->{$this->table.'Orderby'} == 'real_quantity') - { - unset($this->context->cookie->{$this->table.'Orderby'}); - $order_by_real_quantity = true; - } + if ($this->context->cookie->{$this->table.'Orderby'} == 'valuation') { + unset($this->context->cookie->{$this->table.'Orderby'}); + $order_by_valuation = true; + } elseif ($this->context->cookie->{$this->table.'Orderby'} == 'real_quantity') { + unset($this->context->cookie->{$this->table.'Orderby'}); + $order_by_real_quantity = true; + } - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - $nb_items = count($this->_list); + $nb_items = count($this->_list); - for ($i = 0; $i < $nb_items; ++$i) - { - $item = &$this->_list[$i]; + for ($i = 0; $i < $nb_items; ++$i) { + $item = &$this->_list[$i]; - $item['price_te'] = '--'; - $item[$this->identifier] = $item['id_product'].'_'.$item['id_product_attribute']; + $item['price_te'] = '--'; + $item[$this->identifier] = $item['id_product'].'_'.$item['id_product_attribute']; - // gets stock manager - $manager = StockManagerFactory::getManager(); + // gets stock manager + $manager = StockManagerFactory::getManager(); - // gets quantities and valuation - $query = new DbQuery(); - $query->select('SUM(physical_quantity) as physical_quantity'); - $query->select('SUM(usable_quantity) as usable_quantity'); - $query->select('SUM(price_te * physical_quantity) as valuation'); - $query->from('stock'); - $query->where('id_product = '.(int)$item['id_product'].' AND id_product_attribute = '.(int)$item['id_product_attribute']); + // gets quantities and valuation + $query = new DbQuery(); + $query->select('SUM(physical_quantity) as physical_quantity'); + $query->select('SUM(usable_quantity) as usable_quantity'); + $query->select('SUM(price_te * physical_quantity) as valuation'); + $query->from('stock'); + $query->where('id_product = '.(int)$item['id_product'].' AND id_product_attribute = '.(int)$item['id_product_attribute']); - if ($this->getCurrentCoverageWarehouse() != -1) - $query->where('id_warehouse = '.(int)$this->getCurrentCoverageWarehouse()); + if ($this->getCurrentCoverageWarehouse() != -1) { + $query->where('id_warehouse = '.(int)$this->getCurrentCoverageWarehouse()); + } - $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query); + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query); - $item['physical_quantity'] = $res['physical_quantity']; - $item['usable_quantity'] = $res['usable_quantity']; + $item['physical_quantity'] = $res['physical_quantity']; + $item['usable_quantity'] = $res['usable_quantity']; - // gets real_quantity depending on the warehouse - $item['real_quantity'] = $manager->getProductRealQuantities($item['id_product'], - $item['id_product_attribute'], - ($this->getCurrentCoverageWarehouse() == -1 ? null : array($this->getCurrentCoverageWarehouse())), - true); + // gets real_quantity depending on the warehouse + $item['real_quantity'] = $manager->getProductRealQuantities($item['id_product'], + $item['id_product_attribute'], + ($this->getCurrentCoverageWarehouse() == -1 ? null : array($this->getCurrentCoverageWarehouse())), + true); - // removes the valuation if the filter corresponds to 'all warehouses' - if ($this->getCurrentCoverageWarehouse() == -1) - $item['valuation'] = 'N/A'; - else - $item['valuation'] = $res['valuation']; - } + // removes the valuation if the filter corresponds to 'all warehouses' + if ($this->getCurrentCoverageWarehouse() == -1) { + $item['valuation'] = 'N/A'; + } else { + $item['valuation'] = $res['valuation']; + } + } - if ($this->getCurrentCoverageWarehouse() != -1 && $order_by_valuation) - usort($this->_list, array($this, 'valuationCmp')); - elseif ($order_by_real_quantity) - usort($this->_list, array($this, 'realQuantityCmp')); - } - } + if ($this->getCurrentCoverageWarehouse() != -1 && $order_by_valuation) { + usort($this->_list, array($this, 'valuationCmp')); + } elseif ($order_by_real_quantity) { + usort($this->_list, array($this, 'realQuantityCmp')); + } + } + } - /** - * CMP - * - * @param array $n - * @param array $m - * - * @return bool - */ - public function valuationCmp($n, $m) - { - if ($this->context->cookie->{$this->table.'Orderway'} == 'desc') - return $n['valuation'] > $m['valuation']; - else - return $n['valuation'] < $m['valuation']; - } + /** + * CMP + * + * @param array $n + * @param array $m + * + * @return bool + */ + public function valuationCmp($n, $m) + { + if ($this->context->cookie->{$this->table.'Orderway'} == 'desc') { + return $n['valuation'] > $m['valuation']; + } else { + return $n['valuation'] < $m['valuation']; + } + } - /** - * CMP - * - * @param array $n - * @param array $m - * - * @return bool - */ - public function realQuantityCmp($n, $m) - { - if ($this->context->cookie->{$this->table.'Orderway'} == 'desc') - return $n['real_quantity'] > $m['real_quantity']; - else - return $n['real_quantity'] < $m['real_quantity']; - } + /** + * CMP + * + * @param array $n + * @param array $m + * + * @return bool + */ + public function realQuantityCmp($n, $m) + { + if ($this->context->cookie->{$this->table.'Orderway'} == 'desc') { + return $n['real_quantity'] > $m['real_quantity']; + } else { + return $n['real_quantity'] < $m['real_quantity']; + } + } - /** - * Gets the current warehouse used - * - * @return int id_warehouse - */ - protected function getCurrentCoverageWarehouse() - { - static $warehouse = 0; + /** + * Gets the current warehouse used + * + * @return int id_warehouse + */ + protected function getCurrentCoverageWarehouse() + { + static $warehouse = 0; - if ($warehouse == 0) - { - $warehouse = -1; // all warehouses - if ((int)Tools::getValue('id_warehouse')) - $warehouse = (int)Tools::getValue('id_warehouse'); - } - return $warehouse; - } + if ($warehouse == 0) { + $warehouse = -1; // all warehouses + if ((int)Tools::getValue('id_warehouse')) { + $warehouse = (int)Tools::getValue('id_warehouse'); + } + } + return $warehouse; + } - /** - * @see AdminController::initToolbar(); - */ - public function initToolbar() - { - if (Tools::isSubmit('id_warehouse') && (int)Tools::getValue('id_warehouse') != -1) - { - $this->toolbar_btn['export-stock-state-quantities-csv'] = array( - 'short' => 'Export this list as CSV', - 'href' => $this->context->link->getAdminLink('AdminStockInstantState').'&csv_quantities&id_warehouse='.(int)$this->getCurrentCoverageWarehouse(), - 'desc' => $this->l('Export Quantities (CSV)'), - 'class' => 'process-icon-export' - ); + /** + * @see AdminController::initToolbar(); + */ + public function initToolbar() + { + if (Tools::isSubmit('id_warehouse') && (int)Tools::getValue('id_warehouse') != -1) { + $this->toolbar_btn['export-stock-state-quantities-csv'] = array( + 'short' => 'Export this list as CSV', + 'href' => $this->context->link->getAdminLink('AdminStockInstantState').'&csv_quantities&id_warehouse='.(int)$this->getCurrentCoverageWarehouse(), + 'desc' => $this->l('Export Quantities (CSV)'), + 'class' => 'process-icon-export' + ); - $this->toolbar_btn['export-stock-state-prices-csv'] = array( - 'short' => 'Export this list as CSV', - 'href' => $this->context->link->getAdminLink('AdminStockInstantState').'&csv_prices&id_warehouse='.(int)$this->getCurrentCoverageWarehouse(), - 'desc' => $this->l('Export Prices (CSV)'), - 'class' => 'process-icon-export' - ); - } - parent::initToolbar(); - unset($this->toolbar_btn['new']); - } + $this->toolbar_btn['export-stock-state-prices-csv'] = array( + 'short' => 'Export this list as CSV', + 'href' => $this->context->link->getAdminLink('AdminStockInstantState').'&csv_prices&id_warehouse='.(int)$this->getCurrentCoverageWarehouse(), + 'desc' => $this->l('Export Prices (CSV)'), + 'class' => 'process-icon-export' + ); + } + parent::initToolbar(); + unset($this->toolbar_btn['new']); + } - /** - * Exports CSV - */ - public function renderCSV() - { - if (count($this->_list) <= 0) - return; + /** + * Exports CSV + */ + public function renderCSV() + { + if (count($this->_list) <= 0) { + return; + } - // sets warehouse id and warehouse name - $id_warehouse = (int)Tools::getValue('id_warehouse'); - $warehouse_name = Warehouse::getWarehouseNameById($id_warehouse); + // sets warehouse id and warehouse name + $id_warehouse = (int)Tools::getValue('id_warehouse'); + $warehouse_name = Warehouse::getWarehouseNameById($id_warehouse); - // if quantities requested - if (Tools::isSubmit('csv_quantities')) - { - // filename - $filename = $this->l('stock_instant_state_quantities').'_'.$warehouse_name.'.csv'; + // if quantities requested + if (Tools::isSubmit('csv_quantities')) { + // filename + $filename = $this->l('stock_instant_state_quantities').'_'.$warehouse_name.'.csv'; - // header - header('Content-type: text/csv'); - header('Cache-Control: no-store, no-cache must-revalidate'); - header('Content-disposition: attachment; filename="'.$filename); + // header + header('Content-type: text/csv'); + header('Cache-Control: no-store, no-cache must-revalidate'); + header('Content-disposition: attachment; filename="'.$filename); - // puts keys - $keys = array('id_product', 'id_product_attribute', 'reference', 'ean13', 'upc', 'name', 'physical_quantity', 'usable_quantity', 'real_quantity'); - echo sprintf("%s\n", implode(';', $keys)); + // puts keys + $keys = array('id_product', 'id_product_attribute', 'reference', 'ean13', 'upc', 'name', 'physical_quantity', 'usable_quantity', 'real_quantity'); + echo sprintf("%s\n", implode(';', $keys)); - // puts rows - foreach ($this->_list as $row) - { - $row_csv = array($row['id_product'], $row['id_product_attribute'], $row['reference'], - $row['ean13'], $row['upc'], $row['name'], - $row['physical_quantity'], $row['usable_quantity'], $row['real_quantity'] - ); + // puts rows + foreach ($this->_list as $row) { + $row_csv = array($row['id_product'], $row['id_product_attribute'], $row['reference'], + $row['ean13'], $row['upc'], $row['name'], + $row['physical_quantity'], $row['usable_quantity'], $row['real_quantity'] + ); - // puts one row - echo sprintf("%s\n", implode(';', array_map(array('CSVCore', 'wrap'), $row_csv))); - } - } - // if prices requested - elseif (Tools::isSubmit('csv_prices')) - { - // sets filename - $filename = $this->l('stock_instant_state_prices').'_'.$warehouse_name.'.csv'; + // puts one row + echo sprintf("%s\n", implode(';', array_map(array('CSVCore', 'wrap'), $row_csv))); + } + } + // if prices requested + elseif (Tools::isSubmit('csv_prices')) { + // sets filename + $filename = $this->l('stock_instant_state_prices').'_'.$warehouse_name.'.csv'; - // header - header('Content-type: text/csv'); - header('Cache-Control: no-store, no-cache must-revalidate'); - header('Content-disposition: attachment; filename="'.$filename); + // header + header('Content-type: text/csv'); + header('Cache-Control: no-store, no-cache must-revalidate'); + header('Content-disposition: attachment; filename="'.$filename); - // puts keys - $keys = array('id_product', 'id_product_attribute', 'reference', 'ean13', 'upc', 'name', 'price_te', 'physical_quantity', 'usable_quantity'); - echo sprintf("%s\n", implode(';', $keys)); + // puts keys + $keys = array('id_product', 'id_product_attribute', 'reference', 'ean13', 'upc', 'name', 'price_te', 'physical_quantity', 'usable_quantity'); + echo sprintf("%s\n", implode(';', $keys)); - foreach ($this->_list as $row) - { - $id_product = (int)$row['id_product']; - $id_product_attribute = (int)$row['id_product_attribute']; + foreach ($this->_list as $row) { + $id_product = (int)$row['id_product']; + $id_product_attribute = (int)$row['id_product_attribute']; - // gets prices - $query = new DbQuery(); - $query->select('s.price_te, SUM(s.physical_quantity) as physical_quantity, SUM(s.usable_quantity) as usable_quantity'); - $query->from('stock', 's'); - $query->leftJoin('warehouse', 'w', 'w.id_warehouse = s.id_warehouse'); - $query->where('s.id_product = '.$id_product.' AND s.id_product_attribute = '.$id_product_attribute); - $query->where('s.id_warehouse = '.$id_warehouse); - $query->groupBy('s.price_te'); - $datas = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + // gets prices + $query = new DbQuery(); + $query->select('s.price_te, SUM(s.physical_quantity) as physical_quantity, SUM(s.usable_quantity) as usable_quantity'); + $query->from('stock', 's'); + $query->leftJoin('warehouse', 'w', 'w.id_warehouse = s.id_warehouse'); + $query->where('s.id_product = '.$id_product.' AND s.id_product_attribute = '.$id_product_attribute); + $query->where('s.id_warehouse = '.$id_warehouse); + $query->groupBy('s.price_te'); + $datas = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - // puts data - foreach ($datas as $data) - { - $row_csv = array($row['id_product'], $row['id_product_attribute'], $row['reference'], - $row['ean13'], $row['upc'], $row['name'], - $data['price_te'], $data['physical_quantity'], $data['usable_quantity']); + // puts data + foreach ($datas as $data) { + $row_csv = array($row['id_product'], $row['id_product_attribute'], $row['reference'], + $row['ean13'], $row['upc'], $row['name'], + $data['price_te'], $data['physical_quantity'], $data['usable_quantity']); - // puts one row - echo sprintf("%s\n", implode(';', array_map(array('CSVCore', 'wrap'), $row_csv))); - } - } - } - } + // puts one row + echo sprintf("%s\n", implode(';', array_map(array('CSVCore', 'wrap'), $row_csv))); + } + } + } + } - public function initContent() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); - return false; - } - parent::initContent(); - } + public function initContent() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); + return false; + } + parent::initContent(); + } - public function initProcess() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); - return false; - } + public function initProcess() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); + return false; + } - if (Tools::isSubmit('detailsproduct')) - $this->list_id = 'details'; - else - $this->list_id = 'stock'; - - parent::initProcess(); - } + if (Tools::isSubmit('detailsproduct')) { + $this->list_id = 'details'; + } else { + $this->list_id = 'stock'; + } + parent::initProcess(); + } } diff --git a/controllers/admin/AdminStockManagementController.php b/controllers/admin/AdminStockManagementController.php index e094ad9a..d2364d2b 100644 --- a/controllers/admin/AdminStockManagementController.php +++ b/controllers/admin/AdminStockManagementController.php @@ -30,1128 +30,1122 @@ */ class AdminStockManagementControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->context = Context::getContext(); - $this->table = 'product'; - $this->list_id = 'product'; - $this->className = 'Product'; - $this->lang = true; - $this->multishop_context = Shop::CONTEXT_ALL; + public function __construct() + { + $this->bootstrap = true; + $this->context = Context::getContext(); + $this->table = 'product'; + $this->list_id = 'product'; + $this->className = 'Product'; + $this->lang = true; + $this->multishop_context = Shop::CONTEXT_ALL; - $this->fields_list = array( - 'reference' => array( - 'title' => $this->l('Product reference'), - 'filter_key' => 'a!reference' - ), - 'ean13' => array( - 'title' => $this->l('EAN-13 or JAN barcode'), - 'filter_key' => 'a!ean13' - ), - 'upc' => array( - 'title' => $this->l('UPC barcode'), - 'filter_key' => 'a!upc' - ), - 'name' => array( - 'title' => $this->l('Name') - ), - 'stock' => array( - 'title' => $this->l('Quantity'), - 'orderby' => false, - 'filter' => false, - 'search' => false, - 'class' => 'fixed-width-sm', - 'align' => 'center', - 'hint' => $this->l('Quantity total for all warehouses.') - ), - ); + $this->fields_list = array( + 'reference' => array( + 'title' => $this->l('Product reference'), + 'filter_key' => 'a!reference' + ), + 'ean13' => array( + 'title' => $this->l('EAN-13 or JAN barcode'), + 'filter_key' => 'a!ean13' + ), + 'upc' => array( + 'title' => $this->l('UPC barcode'), + 'filter_key' => 'a!upc' + ), + 'name' => array( + 'title' => $this->l('Name') + ), + 'stock' => array( + 'title' => $this->l('Quantity'), + 'orderby' => false, + 'filter' => false, + 'search' => false, + 'class' => 'fixed-width-sm', + 'align' => 'center', + 'hint' => $this->l('Quantity total for all warehouses.') + ), + ); - parent::__construct(); + parent::__construct(); - // overrides confirmation messages specifically for this controller - $this->_conf = array( - 1 => $this->l('The product was successfully added to your stock.'), - 2 => $this->l('The product was successfully removed from your stock.'), - 3 => $this->l('The transfer was successfully completed.'), - ); - } + // overrides confirmation messages specifically for this controller + $this->_conf = array( + 1 => $this->l('The product was successfully added to your stock.'), + 2 => $this->l('The product was successfully removed from your stock.'), + 3 => $this->l('The transfer was successfully completed.'), + ); + } - public function initPageHeaderToolbar() - { - if ($this->display == 'details') - $this->page_header_toolbar_btn['back_to_list'] = array( - 'href' => Context::getContext()->link->getAdminLink('AdminStockManagement'), - 'desc' => $this->l('Back to list', null, null, false), - 'icon' => 'process-icon-back' - ); + public function initPageHeaderToolbar() + { + if ($this->display == 'details') { + $this->page_header_toolbar_btn['back_to_list'] = array( + 'href' => Context::getContext()->link->getAdminLink('AdminStockManagement'), + 'desc' => $this->l('Back to list', null, null, false), + 'icon' => 'process-icon-back' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - /** - * AdminController::renderList() override - * @see AdminController::renderList() - */ - public function renderList() - { - // sets actions - $this->addRowAction('details'); - $this->addRowAction('addstock'); - $this->addRowAction('removestock'); + /** + * AdminController::renderList() override + * @see AdminController::renderList() + */ + public function renderList() + { + // sets actions + $this->addRowAction('details'); + $this->addRowAction('addstock'); + $this->addRowAction('removestock'); - if (count(Warehouse::getWarehouses()) > 1) - $this->addRowAction('transferstock'); + if (count(Warehouse::getWarehouses()) > 1) { + $this->addRowAction('transferstock'); + } - // no link on list rows - $this->list_no_link = true; + // no link on list rows + $this->list_no_link = true; - // inits toolbar - $this->toolbar_btn = array(); + // inits toolbar + $this->toolbar_btn = array(); - // overrides query - $this->_select = 'a.id_product as id, COUNT(pa.id_product_attribute) as variations'; - $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (pa.id_product = a.id_product)'.Shop::addSqlAssociation('product_attribute', 'pa', false); - $this->_where = 'AND a.is_virtual = 0'; - $this->_group = 'GROUP BY a.id_product'; + // overrides query + $this->_select = 'a.id_product as id, COUNT(pa.id_product_attribute) as variations'; + $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (pa.id_product = a.id_product)'.Shop::addSqlAssociation('product_attribute', 'pa', false); + $this->_where = 'AND a.is_virtual = 0'; + $this->_group = 'GROUP BY a.id_product'; - // displays informations - $this->displayInformation($this->l('This interface allows you to manage product stock and their variations.').'<br />'); - $this->displayInformation($this->l('Through this interface, you can increase and decrease product stock for an given warehouse.')); - $this->displayInformation($this->l('Furthermore, you can move product quantities between warehouses, or within one warehouse.').'<br />'); - $this->displayInformation($this->l('If you want to increase quantities of multiple products at once, you can use the "Supply orders" page under the "Stock" menu.').'<br />'); - $this->displayInformation($this->l('Finally, you need to provide the quantity that you\'ll be adding: "Usable for sale" means that this quantity will be available in your shop(s), otherwise it will be considered reserved (i.e. for other purposes).')); + // displays informations + $this->displayInformation($this->l('This interface allows you to manage product stock and their variations.').'<br />'); + $this->displayInformation($this->l('Through this interface, you can increase and decrease product stock for an given warehouse.')); + $this->displayInformation($this->l('Furthermore, you can move product quantities between warehouses, or within one warehouse.').'<br />'); + $this->displayInformation($this->l('If you want to increase quantities of multiple products at once, you can use the "Supply orders" page under the "Stock" menu.').'<br />'); + $this->displayInformation($this->l('Finally, you need to provide the quantity that you\'ll be adding: "Usable for sale" means that this quantity will be available in your shop(s), otherwise it will be considered reserved (i.e. for other purposes).')); - return parent::renderList(); - } + return parent::renderList(); + } - /** - * AdminController::renderForm() override - * @see AdminController::renderForm() - */ - public function renderForm() - { - // gets the product - $id_product = (int)Tools::getValue('id_product'); - $id_product_attribute = (int)Tools::getValue('id_product_attribute'); + /** + * AdminController::renderForm() override + * @see AdminController::renderForm() + */ + public function renderForm() + { + // gets the product + $id_product = (int)Tools::getValue('id_product'); + $id_product_attribute = (int)Tools::getValue('id_product_attribute'); - // gets warehouses - $warehouses_add = $warehouses_remove = Warehouse::getWarehousesByProductId($id_product, $id_product_attribute); + // gets warehouses + $warehouses_add = $warehouses_remove = Warehouse::getWarehousesByProductId($id_product, $id_product_attribute); - // displays warning if no warehouses - if (!$warehouses_add) - $this->displayWarning($this->l('You must choose a warehouses before adding stock. See Stock/Warehouses.')); + // displays warning if no warehouses + if (!$warehouses_add) { + $this->displayWarning($this->l('You must choose a warehouses before adding stock. See Stock/Warehouses.')); + } - //get currencies list + //get currencies list $currencies = Currency::getCurrencies(); $id_default_currency = Configuration::get('PS_CURRENCY_DEFAULT'); $default_currency = Currency::getCurrency($id_default_currency); - if ($default_currency) + if ($default_currency) { $currencies = array_merge(array($default_currency, '-'), $currencies); - - // switch, in order to display the form corresponding to the current action - switch ($this->display) - { - case 'addstock' : - // gets the last stock mvt for this product, so we can display the last unit price te and the last quantity added - $last_sm_unit_price_te = $this->l('N/A'); - $last_sm_quantity = 0; - $last_sm_quantity_is_usable = -1; - $last_sm = StockMvt::getLastPositiveStockMvt($id_product, $id_product_attribute); - - // if there is a stock mvt - if ($last_sm != false) - { - $last_sm_currency = new Currency((int)$last_sm['id_currency']); - $last_sm_quantity = (int)$last_sm['physical_quantity']; - $last_sm_quantity_is_usable = (int)$last_sm['is_usable']; - if (Validate::isLoadedObject($last_sm_currency)) - $last_sm_unit_price_te = Tools::displayPrice((float)$last_sm['price_te'], $last_sm_currency); - } - - $this->displayInformation($this->l('Moving the mouse cursor over the quantity and price fields will give you the details about the last stock movement.')); - // fields in the form - $this->fields_form[]['form'] = array( - 'legend' => array( - 'title' => $this->l('Add a product to your stock.'), - 'icon' => 'icon-long-arrow-up' - ), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'is_post', - ), - array( - 'type' => 'hidden', - 'name' => 'id_product', - ), - array( - 'type' => 'hidden', - 'name' => 'id_product_attribute', - ), - array( - 'type' => 'hidden', - 'name' => 'check', - ), - array( - 'type' => 'text', - 'label' => $this->l('Product reference'), - 'name' => 'reference', - 'disabled' => true, - ), - array( - 'type' => 'text', - 'label' => $this->l('EAN-13 or JAN barcode'), - 'name' => 'ean13', - 'disabled' => true, - ), - array( - 'type' => 'text', - 'label' => $this->l('UPC barcode'), - 'name' => 'upc', - 'disabled' => true, - ), - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'disabled' => true, - ), - array( - 'type' => 'text', - 'label' => $this->l('Quantity to add'), - 'name' => 'quantity', - 'maxlength' => 6, - 'required' => true, - 'hint' => array( - $this->l('Indicate the physical quantity of this product that you want to add.'), - $this->l('Last physical quantity added: %s items (usable for sale: %s).'), - ($last_sm_quantity > 0 ? $last_sm_quantity : $this->l('N/A')), - ($last_sm_quantity > 0 ? ($last_sm_quantity_is_usable >= 0 ? $this->l('Yes') : $this->l('No')) : $this->l('N/A'))), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Usable for sale?'), - 'name' => 'usable', - 'required' => true, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Is this quantity ready to be displayed in your shop, or is it reserved in the warehouse for other purposes?') - ), - array( - 'type' => 'select', - 'label' => $this->l('Warehouse'), - 'name' => 'id_warehouse', - 'required' => true, - 'options' => array( - 'query' => $warehouses_add, - 'id' => 'id_warehouse', - 'name' => 'name' - ), - 'hint' => $this->l('Please select the warehouse that you\'ll be adding products to.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Unit price (tax excl.)'), - 'name' => 'price', - 'required' => true, - 'size' => 10, - 'maxlength' => 10, - 'hint' => array( - $this->l('Unit purchase price or unit manufacturing cost for this product (tax excl.).'), - sprintf($this->l('Last unit price (tax excl.): %s.'), $last_sm_unit_price_te), - ) - ), - array( - 'type' => 'select', - 'label' => $this->l('Currency'), - 'name' => 'id_currency', - 'required' => true, - 'options' => array( - 'query' => $currencies, - 'id' => 'id_currency', - 'name' => 'name' - ), - 'hint' => $this->l('The currency associated to the product unit price.'), - ), - array( - 'type' => 'select', - 'label' => $this->l('Label'), - 'name' => 'id_stock_mvt_reason', - 'required' => true, - 'options' => array( - 'query' => StockMvtReason::getStockMvtReasonsWithFilter($this->context->language->id, - array(Configuration::get('PS_STOCK_MVT_TRANSFER_TO')), - 1), - 'id' => 'id_stock_mvt_reason', - 'name' => 'name' - ), - 'hint' => $this->l('Label used in stock movements.'), - ), - ), - 'submit' => array( - 'title' => $this->l('Add to stock') - ) - ); - $this->fields_value['usable'] = 1; - break; - - case 'removestock' : - $this->fields_form[]['form'] = array( - 'legend' => array( - 'title' => $this->l('Remove the product from your stock.'), - 'icon' => 'icon-long-arrow-down' - ), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'is_post', - ), - array( - 'type' => 'hidden', - 'name' => 'id_product', - ), - array( - 'type' => 'hidden', - 'name' => 'id_product_attribute', - ), - array( - 'type' => 'hidden', - 'name' => 'check', - ), - array( - 'type' => 'text', - 'label' => $this->l('Product reference'), - 'name' => 'reference', - 'disabled' => true, - ), - array( - 'type' => 'text', - 'label' => $this->l('EAN-13 or JAN barcode'), - 'name' => 'ean13', - 'disabled' => true, - ), - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'disabled' => true, - ), - array( - 'type' => 'text', - 'label' => $this->l('Quantity to remove'), - 'name' => 'quantity', - 'maxlength' => 6, - 'required' => true, - 'hint' => $this->l('Indicate the physical quantity of this product that you want to remove.'), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Usable for sale'), - 'name' => 'usable', - 'required' => true, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Do you want to remove this quantity from the usable quantity (yes) or the physical quantity (no)?') - ), - array( - 'type' => 'select', - 'label' => $this->l('Warehouse'), - 'name' => 'id_warehouse', - 'required' => true, - 'options' => array( - 'query' => $warehouses_remove, - 'id' => 'id_warehouse', - 'name' => 'name' - ), - 'hint' => $this->l('Select the warehouse you\'d like to remove the product from.') - ), - array( - 'type' => 'select', - 'label' => $this->l('Label'), - 'name' => 'id_stock_mvt_reason', - 'required' => true, - 'options' => array( - 'query' => StockMvtReason::getStockMvtReasonsWithFilter($this->context->language->id, - array(Configuration::get('PS_STOCK_MVT_TRANSFER_FROM')), - -1), - 'id' => 'id_stock_mvt_reason', - 'name' => 'name' - ), - 'hint' => $this->l('Label used in stock movements.'), - ), - ), - 'submit' => array( - 'title' => $this->l('Remove from stock') - ) - ); - break; - - case 'transferstock' : - $this->fields_form[]['form'] = array( - 'legend' => array( - 'title' => $this->l('Transfer a product from one warehouse to another'), - 'icon' => 'icon-share-alt' - ), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'is_post', - ), - array( - 'type' => 'hidden', - 'name' => 'id_product', - ), - array( - 'type' => 'hidden', - 'name' => 'id_product_attribute', - ), - array( - 'type' => 'hidden', - 'name' => 'check', - ), - array( - 'type' => 'text', - 'label' => $this->l('Product reference'), - 'name' => 'reference', - 'disabled' => true, - ), - array( - 'type' => 'text', - 'label' => $this->l('EAN-13 or JAN barcode'), - 'name' => 'ean13', - 'disabled' => true, - ), - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'disabled' => true, - ), - array( - 'type' => 'text', - 'label' => $this->l('Quantity to transfer'), - 'name' => 'quantity', - 'maxlength' => 6, - 'required' => true, - 'hint' => $this->l('Indicate the physical quantity of this product that you want to transfer.') - ), - array( - 'type' => 'select', - 'label' => $this->l('Source warehouse'), - 'name' => 'id_warehouse_from', - 'required' => true, - 'options' => array( - 'query' => $warehouses_remove, - 'id' => 'id_warehouse', - 'name' => 'name' - ), - 'hint' => $this->l('Select the warehouse you\'d like to transfer the product from.') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Is this product usable for sale in your source warehouse?'), - 'name' => 'usable_from', - 'required' => true, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - 'hint' => $this->l('Is this the usable quantity for sale?') - ), - array( - 'type' => 'select', - 'label' => $this->l('Destination warehouse'), - 'name' => 'id_warehouse_to', - 'required' => true, - 'options' => array( - 'query' => $warehouses_add, - 'id' => 'id_warehouse', - 'name' => 'name' - ), - 'hint' => $this->l('Select the warehouse you\'d like to transfer your product(s) to. ') - ), - array( - 'type' => 'switch', - 'label' => $this->l('Is this product usable for sale in your destination warehouse?'), - 'name' => 'usable_to', - 'required' => true, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - 'hint' => $this->l('Do you want it to be for sale/usable?') - ), - ), - 'submit' => array( - 'title' => $this->l('Transfer') - ) - ); - break; - } - - $this->initToolbar(); - } - - /** - * AdminController::postProcess() override - * @see AdminController::postProcess() - */ - public function postProcess() - { - parent::postProcess(); - - // Checks access - if (Tools::isSubmit('addStock') && !($this->tabAccess['add'] === '1')) - $this->errors[] = Tools::displayError('You do not have the required permission to add stock.'); - if (Tools::isSubmit('removeStock') && !($this->tabAccess['delete'] === '1')) - $this->errors[] = Tools::displayError('You do not have the required permission to delete stock'); - if (Tools::isSubmit('transferStock') && !($this->tabAccess['edit'] === '1')) - $this->errors[] = Tools::displayError('You do not have the required permission to transfer stock.'); - - if (count($this->errors)) - return; - - // Global checks when add / remove / transfer product - if ((Tools::isSubmit('addstock') || Tools::isSubmit('removestock') || Tools::isSubmit('transferstock') ) && Tools::isSubmit('is_post')) - { - // get product ID - $id_product = (int)Tools::getValue('id_product', 0); - if ($id_product <= 0) - $this->errors[] = Tools::displayError('The selected product is not valid.'); - - // get product_attribute ID - $id_product_attribute = (int)Tools::getValue('id_product_attribute', 0); - - // check the product hash - $check = Tools::getValue('check', ''); - $check_valid = md5(_COOKIE_KEY_.$id_product.$id_product_attribute); - if ($check != $check_valid) - $this->errors[] = Tools::displayError('The selected product is not valid.'); - - // get quantity and check that the post value is really an integer - // If it's not, we have nothing to do - $quantity = Tools::getValue('quantity', 0); - if (!is_numeric($quantity) || (int)$quantity <= 0) - $this->errors[] = Tools::displayError('The quantity value is not valid.'); - $quantity = (int)$quantity; - - $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; - $redirect = self::$currentIndex.'&token='.$token; - } - - // Global checks when add / remove product - if ((Tools::isSubmit('addstock') || Tools::isSubmit('removestock') ) && Tools::isSubmit('is_post')) - { - // get warehouse id - $id_warehouse = (int)Tools::getValue('id_warehouse', 0); - if ($id_warehouse <= 0 || !Warehouse::exists($id_warehouse)) - $this->errors[] = Tools::displayError('The selected warehouse is not valid.'); - - // get stock movement reason id - $id_stock_mvt_reason = (int)Tools::getValue('id_stock_mvt_reason', 0); - if ($id_stock_mvt_reason <= 0 || !StockMvtReason::exists($id_stock_mvt_reason)) - $this->errors[] = Tools::displayError('The reason is not valid.'); - - // get usable flag - $usable = Tools::getValue('usable', null); - if (is_null($usable)) - $this->errors[] = Tools::displayError('You have to specify whether the product quantity is usable for sale on shops or not.'); - $usable = (bool)$usable; - } - - if (Tools::isSubmit('addstock') && Tools::isSubmit('is_post')) - { - // get product unit price - $price = str_replace(',', '.', Tools::getValue('price', 0)); - if (!is_numeric($price)) - $this->errors[] = Tools::displayError('The product price is not valid.'); - $price = round(floatval($price), 6); - - // get product unit price currency id - $id_currency = (int)Tools::getValue('id_currency', 0); - if ($id_currency <= 0 || ( !($result = Currency::getCurrency($id_currency)) || empty($result) )) - $this->errors[] = Tools::displayError('The selected currency is not valid.'); - - // if all is ok, add stock - if (count($this->errors) == 0) - { - $warehouse = new Warehouse($id_warehouse); - - // convert price to warehouse currency if needed - if ($id_currency != $warehouse->id_currency) - { - // First convert price to the default currency - $price_converted_to_default_currency = Tools::convertPrice($price, $id_currency, false); - - // Convert the new price from default currency to needed currency - $price = Tools::convertPrice($price_converted_to_default_currency, $warehouse->id_currency, true); - } - - // add stock - $stock_manager = StockManagerFactory::getManager(); - - if ($stock_manager->addProduct($id_product, $id_product_attribute, $warehouse, $quantity, $id_stock_mvt_reason, $price, $usable)) - { - // Create warehouse_product_location entry if we add stock to a new warehouse - $id_wpl = (int)WarehouseProductLocation::getIdByProductAndWarehouse($id_product, $id_product_attribute, $id_warehouse); - if(!$id_wpl) - { - $wpl = new WarehouseProductLocation(); - $wpl->id_product = (int)$id_product; - $wpl->id_product_attribute = (int)$id_product_attribute; - $wpl->id_warehouse = (int)$id_warehouse; - $wpl->save(); - } - - StockAvailable::synchronize($id_product); - - if (Tools::isSubmit('addstockAndStay')) - { - $redirect = self::$currentIndex.'&id_product='.(int)$id_product; - if ($id_product_attribute) - $redirect .= '&id_product_attribute='.(int)$id_product_attribute; - $redirect .= '&addstock&token='.$token; - } - Tools::redirectAdmin($redirect.'&conf=1'); - } - else - $this->errors[] = Tools::displayError('An error occurred. No stock was added.'); - } - } - - if (Tools::isSubmit('removestock') && Tools::isSubmit('is_post')) - { - // if all is ok, remove stock - if (count($this->errors) == 0) - { - $warehouse = new Warehouse($id_warehouse); - - // remove stock - $stock_manager = StockManagerFactory::getManager(); - $removed_products = $stock_manager->removeProduct($id_product, $id_product_attribute, $warehouse, $quantity, $id_stock_mvt_reason, $usable); - - if (count($removed_products) > 0) - { - StockAvailable::synchronize($id_product); - Tools::redirectAdmin($redirect.'&conf=2'); - } - else - { - $physical_quantity_in_stock = (int)$stock_manager->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id), false); - $usable_quantity_in_stock = (int)$stock_manager->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id), true); - $not_usable_quantity = ($physical_quantity_in_stock - $usable_quantity_in_stock); - if ($usable_quantity_in_stock < $quantity) - $this->errors[] = sprintf(Tools::displayError('You don\'t have enough usable quantity. Cannot remove %d items out of %d.'), (int)$quantity, (int)$usable_quantity_in_stock); - elseif ($not_usable_quantity < $quantity) - $this->errors[] = sprintf(Tools::displayError('You don\'t have enough usable quantity. Cannot remove %d items out of %d.'), (int)$quantity, (int)$not_usable_quantity); - else - $this->errors[] = Tools::displayError('It is not possible to remove the specified quantity. Therefore no stock was removed.'); - } - } - } - - if (Tools::isSubmit('transferstock') && Tools::isSubmit('is_post')) - { - // get source warehouse id - $id_warehouse_from = (int)Tools::getValue('id_warehouse_from', 0); - if ($id_warehouse_from <= 0 || !Warehouse::exists($id_warehouse_from)) - $this->errors[] = Tools::displayError('The source warehouse is not valid.'); - - // get destination warehouse id - $id_warehouse_to = (int)Tools::getValue('id_warehouse_to', 0); - if ($id_warehouse_to <= 0 || !Warehouse::exists($id_warehouse_to)) - $this->errors[] = Tools::displayError('The destination warehouse is not valid.'); - - // get usable flag for source warehouse - $usable_from = Tools::getValue('usable_from', null); - if (is_null($usable_from)) - $this->errors[] = Tools::displayError('You have to specify whether the product quantity in your source warehouse(s) is ready for sale or not.'); - $usable_from = (bool)$usable_from; - - // get usable flag for destination warehouse - $usable_to = Tools::getValue('usable_to', null); - if (is_null($usable_to)) - $this->errors[] = Tools::displayError('You have to specify whether the product quantity in your destination warehouse(s) is ready for sale or not.'); - $usable_to = (bool)$usable_to; - - // if we can process stock transfers - if (count($this->errors) == 0) - { - // transfer stock - $stock_manager = StockManagerFactory::getManager(); - - $is_transfer = $stock_manager->transferBetweenWarehouses( - $id_product, - $id_product_attribute, - $quantity, - $id_warehouse_from, - $id_warehouse_to, - $usable_from, - $usable_to - ); - StockAvailable::synchronize($id_product); - if ($is_transfer) - Tools::redirectAdmin($redirect.'&conf=3'); - else - $this->errors[] = Tools::displayError('It is not possible to transfer the specified quantity. No stock was transferred.'); - } - } - } - - /** - * assign default action in toolbar_btn smarty var, if they are not set. - * uses override to specifically add, modify or remove items - * - */ - public function initToolbar() - { - switch ($this->display) - { - case 'addstock': - $this->toolbar_btn['save-and-stay'] = array( - 'short' => 'SaveAndStay', - 'href' => '#', - 'desc' => $this->l('Save and stay'), - ); - case 'removestock': - case 'transferstock': - $this->toolbar_btn['save'] = array( - 'href' => '#', - 'desc' => $this->l('Save') - ); - - // Default cancel button - like old back link - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; - - $this->toolbar_btn['cancel'] = array( - 'href' => $back, - 'desc' => $this->l('Cancel') - ); - break; - - default: - parent::initToolbar(); - } - } - - /** - * AdminController::init() override - * @see AdminController::init() - */ - public function init() - { - parent::init(); - - if (Tools::isSubmit('addstock')) - { - $this->display = 'addstock'; - $this->toolbar_title = $this->l('Stock: Add a product'); - } - - if (Tools::isSubmit('removestock')) - { - $this->display = 'removestock'; - $this->toolbar_title = $this->l('Stock: Remove a product'); - } - - if (Tools::isSubmit('transferstock')) - { - $this->display = 'transferstock'; - $this->toolbar_title = $this->l('Stock: Transfer a product'); - } - } - - public function renderDetails() - { - if (Tools::isSubmit('id_product')) - { - // override attributes - $this->identifier = 'id_product_attribute'; - $this->list_id = 'product_attribute'; - $this->lang = false; - - $this->addRowAction('addstock'); - $this->addRowAction('removestock'); - - if (count(Warehouse::getWarehouses()) > 1) - $this->addRowAction('transferstock'); - - // no link on list rows - $this->list_no_link = true; - - // inits toolbar - $this->toolbar_btn = array(); - - // get current lang id - $lang_id = (int)$this->context->language->id; - - // Get product id - $product_id = (int)Tools::getValue('id_product'); - - // Load product attributes with sql override - $this->table = 'product_attribute'; - $this->list_id = 'product_attribute'; - $this->_select = 'a.id_product_attribute as id, a.id_product, a.reference, a.ean13, a.upc'; - $this->_where = 'AND a.id_product = '.$product_id; - $this->_group = 'GROUP BY a.id_product_attribute'; - - $this->fields_list = array( - 'reference' => array( - 'title' => $this->l('Product reference'), - 'filter_key' => 'a!reference' - ), - 'ean13' => array( - 'title' => $this->l('EAN-13 or JAN barcode'), - 'filter_key' => 'a!ean13' - ), - 'upc' => array( - 'title' => $this->l('UPC barcode'), - 'filter_key' => 'a!upc' - ), - 'name' => array( - 'title' => $this->l('Name'), - 'orderby' => false, - 'filter' => false, - 'search' => false - ), - 'stock' => array( - 'title' => $this->l('Quantity'), - 'orderby' => false, - 'filter' => false, - 'search' => false, - 'class' => 'fixed-width-sm', - 'align' => 'center', - 'hint' => $this->l('Quantitity total for all warehouses.') - ), - ); - - self::$currentIndex = self::$currentIndex.'&id_product='.(int)$product_id.'&detailsproduct'; - $this->processFilter(); - return parent::renderList(); - } - } - - /** - * AdminController::getList() override - * @see AdminController::getList() - * - * @param int $id_lang - * @param string|null $order_by - * @param string|null $order_way - * @param int $start - * @param int|null $limit - * @param int|bool $id_lang_shop - * - * @throws PrestaShopException - */ - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - - // Check each row to see if there are combinations and get the correct action in consequence - $nb_items = count($this->_list); - - for ($i = 0; $i < $nb_items; $i++) - { - $item = &$this->_list[$i]; - - // if it's an ajax request we have to consider manipulating a product variation - if (Tools::isSubmit('id_product')) - { - $item['name'] = Product::getProductName($item['id_product'], $item['id']); - // no details for this row - $this->addRowActionSkipList('details', array($item['id'])); - - // specify actions in function of stock - $this->skipActionByStock($item, true); - - } - // If current product has variations - elseif (array_key_exists('variations', $item) && (int)$item['variations'] > 0) - { - // we have to desactivate stock actions on current row - $this->addRowActionSkipList('addstock', array($item['id'])); - $this->addRowActionSkipList('removestock', array($item['id'])); - $this->addRowActionSkipList('transferstock', array($item['id'])); - - // does not display these informaions because this product has combinations - $item['reference'] = '--'; - $item['ean13'] = '--'; - $item['upc'] = '--'; - } - else - { - //there are no variations of current product, so we don't want to show details action - $this->addRowActionSkipList('details', array($item['id'])); - - // specify actions in function of stock - $this->skipActionByStock($item, false); - } - // Checks access - if (!($this->tabAccess['add'] === '1')) - $this->addRowActionSkipList('addstock', array($item['id'])); - if (!($this->tabAccess['delete'] === '1')) - $this->addRowActionSkipList('removestock', array($item['id'])); - if (!($this->tabAccess['edit'] === '1')) - $this->addRowActionSkipList('transferstock', array($item['id'])); - } - } - - /** - * Check stock for a given product or product attribute - * and manage available actions in consequence - * - * @param array $item Reference to the current item - * @param bool $is_product_variation Specify if it's a product or a product variation - */ - protected function skipActionByStock(&$item, $is_product_variation = false) - { - $stock_manager = StockManagerFactory::getManager(); - - //get stocks for this product - if ($is_product_variation) - $stock = $stock_manager->getProductPhysicalQuantities($item['id_product'], $item['id']); - else - $stock = $stock_manager->getProductPhysicalQuantities($item['id'], 0); - - //affects stock to the list for display - $item['stock'] = $stock; - - if ($stock <= 0) - { - //there is no stock, we can only add stock - $this->addRowActionSkipList('removestock', array($item['id'])); - $this->addRowActionSkipList('transferstock', array($item['id'])); - } - } - - /** - * AdminController::initContent() override - * @see AdminController::initContent() - */ - public function initContent() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate the Advanced Stock Management feature prior to using this feature.'); - return false; - } - - // Manage the add stock form - if ($this->display == 'addstock' || $this->display == 'removestock' || $this->display == 'transferstock') - { - if (Tools::isSubmit('id_product') || Tools::isSubmit('id_product_attribute')) - { - // get id product and product attribute if possible - $id_product = (int)Tools::getValue('id_product', 0); - $id_product_attribute = (int)Tools::getValue('id_product_attribute', 0); - - $product_is_valid = false; - $is_pack = false; - $is_virtual = false; - $lang_id = $this->context->language->id; - $default_wholesale_price = 0; - - // try to load product attribute first - if ($id_product_attribute > 0) - { - // try to load product attribute - $combination = new Combination($id_product_attribute); - if (Validate::isLoadedObject($combination)) - { - $product_is_valid = true; - $id_product = $combination->id_product; - $reference = $combination->reference; - $ean13 = $combination->ean13; - $upc = $combination->upc; - $manufacturer_reference = $combination->supplier_reference; - - // get the full name for this combination - $query = new DbQuery(); - - $query->select('IFNULL(CONCAT(pl.`name`, \' : \', GROUP_CONCAT(agl.`name`, \' - \', al.`name` SEPARATOR \', \')),pl.`name`) as name'); - $query->from('product_attribute', 'a'); - $query->join('INNER JOIN '._DB_PREFIX_.'product_lang pl ON (pl.`id_product` = a.`id_product` AND pl.`id_lang` = '.(int)$lang_id.') + } + + // switch, in order to display the form corresponding to the current action + switch ($this->display) { + case 'addstock' : + // gets the last stock mvt for this product, so we can display the last unit price te and the last quantity added + $last_sm_unit_price_te = $this->l('N/A'); + $last_sm_quantity = 0; + $last_sm_quantity_is_usable = -1; + $last_sm = StockMvt::getLastPositiveStockMvt($id_product, $id_product_attribute); + + // if there is a stock mvt + if ($last_sm != false) { + $last_sm_currency = new Currency((int)$last_sm['id_currency']); + $last_sm_quantity = (int)$last_sm['physical_quantity']; + $last_sm_quantity_is_usable = (int)$last_sm['is_usable']; + if (Validate::isLoadedObject($last_sm_currency)) { + $last_sm_unit_price_te = Tools::displayPrice((float)$last_sm['price_te'], $last_sm_currency); + } + } + + $this->displayInformation($this->l('Moving the mouse cursor over the quantity and price fields will give you the details about the last stock movement.')); + // fields in the form + $this->fields_form[]['form'] = array( + 'legend' => array( + 'title' => $this->l('Add a product to your stock.'), + 'icon' => 'icon-long-arrow-up' + ), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'is_post', + ), + array( + 'type' => 'hidden', + 'name' => 'id_product', + ), + array( + 'type' => 'hidden', + 'name' => 'id_product_attribute', + ), + array( + 'type' => 'hidden', + 'name' => 'check', + ), + array( + 'type' => 'text', + 'label' => $this->l('Product reference'), + 'name' => 'reference', + 'disabled' => true, + ), + array( + 'type' => 'text', + 'label' => $this->l('EAN-13 or JAN barcode'), + 'name' => 'ean13', + 'disabled' => true, + ), + array( + 'type' => 'text', + 'label' => $this->l('UPC barcode'), + 'name' => 'upc', + 'disabled' => true, + ), + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'disabled' => true, + ), + array( + 'type' => 'text', + 'label' => $this->l('Quantity to add'), + 'name' => 'quantity', + 'maxlength' => 6, + 'required' => true, + 'hint' => array( + $this->l('Indicate the physical quantity of this product that you want to add.'), + $this->l('Last physical quantity added: %s items (usable for sale: %s).'), + ($last_sm_quantity > 0 ? $last_sm_quantity : $this->l('N/A')), + ($last_sm_quantity > 0 ? ($last_sm_quantity_is_usable >= 0 ? $this->l('Yes') : $this->l('No')) : $this->l('N/A'))), + ), + array( + 'type' => 'switch', + 'label' => $this->l('Usable for sale?'), + 'name' => 'usable', + 'required' => true, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Is this quantity ready to be displayed in your shop, or is it reserved in the warehouse for other purposes?') + ), + array( + 'type' => 'select', + 'label' => $this->l('Warehouse'), + 'name' => 'id_warehouse', + 'required' => true, + 'options' => array( + 'query' => $warehouses_add, + 'id' => 'id_warehouse', + 'name' => 'name' + ), + 'hint' => $this->l('Please select the warehouse that you\'ll be adding products to.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Unit price (tax excl.)'), + 'name' => 'price', + 'required' => true, + 'size' => 10, + 'maxlength' => 10, + 'hint' => array( + $this->l('Unit purchase price or unit manufacturing cost for this product (tax excl.).'), + sprintf($this->l('Last unit price (tax excl.): %s.'), $last_sm_unit_price_te), + ) + ), + array( + 'type' => 'select', + 'label' => $this->l('Currency'), + 'name' => 'id_currency', + 'required' => true, + 'options' => array( + 'query' => $currencies, + 'id' => 'id_currency', + 'name' => 'name' + ), + 'hint' => $this->l('The currency associated to the product unit price.'), + ), + array( + 'type' => 'select', + 'label' => $this->l('Label'), + 'name' => 'id_stock_mvt_reason', + 'required' => true, + 'options' => array( + 'query' => StockMvtReason::getStockMvtReasonsWithFilter($this->context->language->id, + array(Configuration::get('PS_STOCK_MVT_TRANSFER_TO')), + 1), + 'id' => 'id_stock_mvt_reason', + 'name' => 'name' + ), + 'hint' => $this->l('Label used in stock movements.'), + ), + ), + 'submit' => array( + 'title' => $this->l('Add to stock') + ) + ); + $this->fields_value['usable'] = 1; + break; + + case 'removestock' : + $this->fields_form[]['form'] = array( + 'legend' => array( + 'title' => $this->l('Remove the product from your stock.'), + 'icon' => 'icon-long-arrow-down' + ), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'is_post', + ), + array( + 'type' => 'hidden', + 'name' => 'id_product', + ), + array( + 'type' => 'hidden', + 'name' => 'id_product_attribute', + ), + array( + 'type' => 'hidden', + 'name' => 'check', + ), + array( + 'type' => 'text', + 'label' => $this->l('Product reference'), + 'name' => 'reference', + 'disabled' => true, + ), + array( + 'type' => 'text', + 'label' => $this->l('EAN-13 or JAN barcode'), + 'name' => 'ean13', + 'disabled' => true, + ), + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'disabled' => true, + ), + array( + 'type' => 'text', + 'label' => $this->l('Quantity to remove'), + 'name' => 'quantity', + 'maxlength' => 6, + 'required' => true, + 'hint' => $this->l('Indicate the physical quantity of this product that you want to remove.'), + ), + array( + 'type' => 'switch', + 'label' => $this->l('Usable for sale'), + 'name' => 'usable', + 'required' => true, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Do you want to remove this quantity from the usable quantity (yes) or the physical quantity (no)?') + ), + array( + 'type' => 'select', + 'label' => $this->l('Warehouse'), + 'name' => 'id_warehouse', + 'required' => true, + 'options' => array( + 'query' => $warehouses_remove, + 'id' => 'id_warehouse', + 'name' => 'name' + ), + 'hint' => $this->l('Select the warehouse you\'d like to remove the product from.') + ), + array( + 'type' => 'select', + 'label' => $this->l('Label'), + 'name' => 'id_stock_mvt_reason', + 'required' => true, + 'options' => array( + 'query' => StockMvtReason::getStockMvtReasonsWithFilter($this->context->language->id, + array(Configuration::get('PS_STOCK_MVT_TRANSFER_FROM')), + -1), + 'id' => 'id_stock_mvt_reason', + 'name' => 'name' + ), + 'hint' => $this->l('Label used in stock movements.'), + ), + ), + 'submit' => array( + 'title' => $this->l('Remove from stock') + ) + ); + break; + + case 'transferstock' : + $this->fields_form[]['form'] = array( + 'legend' => array( + 'title' => $this->l('Transfer a product from one warehouse to another'), + 'icon' => 'icon-share-alt' + ), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'is_post', + ), + array( + 'type' => 'hidden', + 'name' => 'id_product', + ), + array( + 'type' => 'hidden', + 'name' => 'id_product_attribute', + ), + array( + 'type' => 'hidden', + 'name' => 'check', + ), + array( + 'type' => 'text', + 'label' => $this->l('Product reference'), + 'name' => 'reference', + 'disabled' => true, + ), + array( + 'type' => 'text', + 'label' => $this->l('EAN-13 or JAN barcode'), + 'name' => 'ean13', + 'disabled' => true, + ), + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'disabled' => true, + ), + array( + 'type' => 'text', + 'label' => $this->l('Quantity to transfer'), + 'name' => 'quantity', + 'maxlength' => 6, + 'required' => true, + 'hint' => $this->l('Indicate the physical quantity of this product that you want to transfer.') + ), + array( + 'type' => 'select', + 'label' => $this->l('Source warehouse'), + 'name' => 'id_warehouse_from', + 'required' => true, + 'options' => array( + 'query' => $warehouses_remove, + 'id' => 'id_warehouse', + 'name' => 'name' + ), + 'hint' => $this->l('Select the warehouse you\'d like to transfer the product from.') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Is this product usable for sale in your source warehouse?'), + 'name' => 'usable_from', + 'required' => true, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + 'hint' => $this->l('Is this the usable quantity for sale?') + ), + array( + 'type' => 'select', + 'label' => $this->l('Destination warehouse'), + 'name' => 'id_warehouse_to', + 'required' => true, + 'options' => array( + 'query' => $warehouses_add, + 'id' => 'id_warehouse', + 'name' => 'name' + ), + 'hint' => $this->l('Select the warehouse you\'d like to transfer your product(s) to. ') + ), + array( + 'type' => 'switch', + 'label' => $this->l('Is this product usable for sale in your destination warehouse?'), + 'name' => 'usable_to', + 'required' => true, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + 'hint' => $this->l('Do you want it to be for sale/usable?') + ), + ), + 'submit' => array( + 'title' => $this->l('Transfer') + ) + ); + break; + } + + $this->initToolbar(); + } + + /** + * AdminController::postProcess() override + * @see AdminController::postProcess() + */ + public function postProcess() + { + parent::postProcess(); + + // Checks access + if (Tools::isSubmit('addStock') && !($this->tabAccess['add'] === '1')) { + $this->errors[] = Tools::displayError('You do not have the required permission to add stock.'); + } + if (Tools::isSubmit('removeStock') && !($this->tabAccess['delete'] === '1')) { + $this->errors[] = Tools::displayError('You do not have the required permission to delete stock'); + } + if (Tools::isSubmit('transferStock') && !($this->tabAccess['edit'] === '1')) { + $this->errors[] = Tools::displayError('You do not have the required permission to transfer stock.'); + } + + if (count($this->errors)) { + return; + } + + // Global checks when add / remove / transfer product + if ((Tools::isSubmit('addstock') || Tools::isSubmit('removestock') || Tools::isSubmit('transferstock')) && Tools::isSubmit('is_post')) { + // get product ID + $id_product = (int)Tools::getValue('id_product', 0); + if ($id_product <= 0) { + $this->errors[] = Tools::displayError('The selected product is not valid.'); + } + + // get product_attribute ID + $id_product_attribute = (int)Tools::getValue('id_product_attribute', 0); + + // check the product hash + $check = Tools::getValue('check', ''); + $check_valid = md5(_COOKIE_KEY_.$id_product.$id_product_attribute); + if ($check != $check_valid) { + $this->errors[] = Tools::displayError('The selected product is not valid.'); + } + + // get quantity and check that the post value is really an integer + // If it's not, we have nothing to do + $quantity = Tools::getValue('quantity', 0); + if (!is_numeric($quantity) || (int)$quantity <= 0) { + $this->errors[] = Tools::displayError('The quantity value is not valid.'); + } + $quantity = (int)$quantity; + + $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; + $redirect = self::$currentIndex.'&token='.$token; + } + + // Global checks when add / remove product + if ((Tools::isSubmit('addstock') || Tools::isSubmit('removestock')) && Tools::isSubmit('is_post')) { + // get warehouse id + $id_warehouse = (int)Tools::getValue('id_warehouse', 0); + if ($id_warehouse <= 0 || !Warehouse::exists($id_warehouse)) { + $this->errors[] = Tools::displayError('The selected warehouse is not valid.'); + } + + // get stock movement reason id + $id_stock_mvt_reason = (int)Tools::getValue('id_stock_mvt_reason', 0); + if ($id_stock_mvt_reason <= 0 || !StockMvtReason::exists($id_stock_mvt_reason)) { + $this->errors[] = Tools::displayError('The reason is not valid.'); + } + + // get usable flag + $usable = Tools::getValue('usable', null); + if (is_null($usable)) { + $this->errors[] = Tools::displayError('You have to specify whether the product quantity is usable for sale on shops or not.'); + } + $usable = (bool)$usable; + } + + if (Tools::isSubmit('addstock') && Tools::isSubmit('is_post')) { + // get product unit price + $price = str_replace(',', '.', Tools::getValue('price', 0)); + if (!is_numeric($price)) { + $this->errors[] = Tools::displayError('The product price is not valid.'); + } + $price = round(floatval($price), 6); + + // get product unit price currency id + $id_currency = (int)Tools::getValue('id_currency', 0); + if ($id_currency <= 0 || (!($result = Currency::getCurrency($id_currency)) || empty($result))) { + $this->errors[] = Tools::displayError('The selected currency is not valid.'); + } + + // if all is ok, add stock + if (count($this->errors) == 0) { + $warehouse = new Warehouse($id_warehouse); + + // convert price to warehouse currency if needed + if ($id_currency != $warehouse->id_currency) { + // First convert price to the default currency + $price_converted_to_default_currency = Tools::convertPrice($price, $id_currency, false); + + // Convert the new price from default currency to needed currency + $price = Tools::convertPrice($price_converted_to_default_currency, $warehouse->id_currency, true); + } + + // add stock + $stock_manager = StockManagerFactory::getManager(); + + if ($stock_manager->addProduct($id_product, $id_product_attribute, $warehouse, $quantity, $id_stock_mvt_reason, $price, $usable)) { + // Create warehouse_product_location entry if we add stock to a new warehouse + $id_wpl = (int)WarehouseProductLocation::getIdByProductAndWarehouse($id_product, $id_product_attribute, $id_warehouse); + if (!$id_wpl) { + $wpl = new WarehouseProductLocation(); + $wpl->id_product = (int)$id_product; + $wpl->id_product_attribute = (int)$id_product_attribute; + $wpl->id_warehouse = (int)$id_warehouse; + $wpl->save(); + } + + StockAvailable::synchronize($id_product); + + if (Tools::isSubmit('addstockAndStay')) { + $redirect = self::$currentIndex.'&id_product='.(int)$id_product; + if ($id_product_attribute) { + $redirect .= '&id_product_attribute='.(int)$id_product_attribute; + } + $redirect .= '&addstock&token='.$token; + } + Tools::redirectAdmin($redirect.'&conf=1'); + } else { + $this->errors[] = Tools::displayError('An error occurred. No stock was added.'); + } + } + } + + if (Tools::isSubmit('removestock') && Tools::isSubmit('is_post')) { + // if all is ok, remove stock + if (count($this->errors) == 0) { + $warehouse = new Warehouse($id_warehouse); + + // remove stock + $stock_manager = StockManagerFactory::getManager(); + $removed_products = $stock_manager->removeProduct($id_product, $id_product_attribute, $warehouse, $quantity, $id_stock_mvt_reason, $usable); + + if (count($removed_products) > 0) { + StockAvailable::synchronize($id_product); + Tools::redirectAdmin($redirect.'&conf=2'); + } else { + $physical_quantity_in_stock = (int)$stock_manager->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id), false); + $usable_quantity_in_stock = (int)$stock_manager->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id), true); + $not_usable_quantity = ($physical_quantity_in_stock - $usable_quantity_in_stock); + if ($usable_quantity_in_stock < $quantity) { + $this->errors[] = sprintf(Tools::displayError('You don\'t have enough usable quantity. Cannot remove %d items out of %d.'), (int)$quantity, (int)$usable_quantity_in_stock); + } elseif ($not_usable_quantity < $quantity) { + $this->errors[] = sprintf(Tools::displayError('You don\'t have enough usable quantity. Cannot remove %d items out of %d.'), (int)$quantity, (int)$not_usable_quantity); + } else { + $this->errors[] = Tools::displayError('It is not possible to remove the specified quantity. Therefore no stock was removed.'); + } + } + } + } + + if (Tools::isSubmit('transferstock') && Tools::isSubmit('is_post')) { + // get source warehouse id + $id_warehouse_from = (int)Tools::getValue('id_warehouse_from', 0); + if ($id_warehouse_from <= 0 || !Warehouse::exists($id_warehouse_from)) { + $this->errors[] = Tools::displayError('The source warehouse is not valid.'); + } + + // get destination warehouse id + $id_warehouse_to = (int)Tools::getValue('id_warehouse_to', 0); + if ($id_warehouse_to <= 0 || !Warehouse::exists($id_warehouse_to)) { + $this->errors[] = Tools::displayError('The destination warehouse is not valid.'); + } + + // get usable flag for source warehouse + $usable_from = Tools::getValue('usable_from', null); + if (is_null($usable_from)) { + $this->errors[] = Tools::displayError('You have to specify whether the product quantity in your source warehouse(s) is ready for sale or not.'); + } + $usable_from = (bool)$usable_from; + + // get usable flag for destination warehouse + $usable_to = Tools::getValue('usable_to', null); + if (is_null($usable_to)) { + $this->errors[] = Tools::displayError('You have to specify whether the product quantity in your destination warehouse(s) is ready for sale or not.'); + } + $usable_to = (bool)$usable_to; + + // if we can process stock transfers + if (count($this->errors) == 0) { + // transfer stock + $stock_manager = StockManagerFactory::getManager(); + + $is_transfer = $stock_manager->transferBetweenWarehouses( + $id_product, + $id_product_attribute, + $quantity, + $id_warehouse_from, + $id_warehouse_to, + $usable_from, + $usable_to + ); + StockAvailable::synchronize($id_product); + if ($is_transfer) { + Tools::redirectAdmin($redirect.'&conf=3'); + } else { + $this->errors[] = Tools::displayError('It is not possible to transfer the specified quantity. No stock was transferred.'); + } + } + } + } + + /** + * assign default action in toolbar_btn smarty var, if they are not set. + * uses override to specifically add, modify or remove items + * + */ + public function initToolbar() + { + switch ($this->display) { + case 'addstock': + $this->toolbar_btn['save-and-stay'] = array( + 'short' => 'SaveAndStay', + 'href' => '#', + 'desc' => $this->l('Save and stay'), + ); + case 'removestock': + case 'transferstock': + $this->toolbar_btn['save'] = array( + 'href' => '#', + 'desc' => $this->l('Save') + ); + + // Default cancel button - like old back link + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } + + $this->toolbar_btn['cancel'] = array( + 'href' => $back, + 'desc' => $this->l('Cancel') + ); + break; + + default: + parent::initToolbar(); + } + } + + /** + * AdminController::init() override + * @see AdminController::init() + */ + public function init() + { + parent::init(); + + if (Tools::isSubmit('addstock')) { + $this->display = 'addstock'; + $this->toolbar_title = $this->l('Stock: Add a product'); + } + + if (Tools::isSubmit('removestock')) { + $this->display = 'removestock'; + $this->toolbar_title = $this->l('Stock: Remove a product'); + } + + if (Tools::isSubmit('transferstock')) { + $this->display = 'transferstock'; + $this->toolbar_title = $this->l('Stock: Transfer a product'); + } + } + + public function renderDetails() + { + if (Tools::isSubmit('id_product')) { + // override attributes + $this->identifier = 'id_product_attribute'; + $this->list_id = 'product_attribute'; + $this->lang = false; + + $this->addRowAction('addstock'); + $this->addRowAction('removestock'); + + if (count(Warehouse::getWarehouses()) > 1) { + $this->addRowAction('transferstock'); + } + + // no link on list rows + $this->list_no_link = true; + + // inits toolbar + $this->toolbar_btn = array(); + + // get current lang id + $lang_id = (int)$this->context->language->id; + + // Get product id + $product_id = (int)Tools::getValue('id_product'); + + // Load product attributes with sql override + $this->table = 'product_attribute'; + $this->list_id = 'product_attribute'; + $this->_select = 'a.id_product_attribute as id, a.id_product, a.reference, a.ean13, a.upc'; + $this->_where = 'AND a.id_product = '.$product_id; + $this->_group = 'GROUP BY a.id_product_attribute'; + + $this->fields_list = array( + 'reference' => array( + 'title' => $this->l('Product reference'), + 'filter_key' => 'a!reference' + ), + 'ean13' => array( + 'title' => $this->l('EAN-13 or JAN barcode'), + 'filter_key' => 'a!ean13' + ), + 'upc' => array( + 'title' => $this->l('UPC barcode'), + 'filter_key' => 'a!upc' + ), + 'name' => array( + 'title' => $this->l('Name'), + 'orderby' => false, + 'filter' => false, + 'search' => false + ), + 'stock' => array( + 'title' => $this->l('Quantity'), + 'orderby' => false, + 'filter' => false, + 'search' => false, + 'class' => 'fixed-width-sm', + 'align' => 'center', + 'hint' => $this->l('Quantitity total for all warehouses.') + ), + ); + + self::$currentIndex = self::$currentIndex.'&id_product='.(int)$product_id.'&detailsproduct'; + $this->processFilter(); + return parent::renderList(); + } + } + + /** + * AdminController::getList() override + * @see AdminController::getList() + * + * @param int $id_lang + * @param string|null $order_by + * @param string|null $order_way + * @param int $start + * @param int|null $limit + * @param int|bool $id_lang_shop + * + * @throws PrestaShopException + */ + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + + // Check each row to see if there are combinations and get the correct action in consequence + $nb_items = count($this->_list); + + for ($i = 0; $i < $nb_items; $i++) { + $item = &$this->_list[$i]; + + // if it's an ajax request we have to consider manipulating a product variation + if (Tools::isSubmit('id_product')) { + $item['name'] = Product::getProductName($item['id_product'], $item['id']); + // no details for this row + $this->addRowActionSkipList('details', array($item['id'])); + + // specify actions in function of stock + $this->skipActionByStock($item, true); + } + // If current product has variations + elseif (array_key_exists('variations', $item) && (int)$item['variations'] > 0) { + // we have to desactivate stock actions on current row + $this->addRowActionSkipList('addstock', array($item['id'])); + $this->addRowActionSkipList('removestock', array($item['id'])); + $this->addRowActionSkipList('transferstock', array($item['id'])); + + // does not display these informaions because this product has combinations + $item['reference'] = '--'; + $item['ean13'] = '--'; + $item['upc'] = '--'; + } else { + //there are no variations of current product, so we don't want to show details action + $this->addRowActionSkipList('details', array($item['id'])); + + // specify actions in function of stock + $this->skipActionByStock($item, false); + } + // Checks access + if (!($this->tabAccess['add'] === '1')) { + $this->addRowActionSkipList('addstock', array($item['id'])); + } + if (!($this->tabAccess['delete'] === '1')) { + $this->addRowActionSkipList('removestock', array($item['id'])); + } + if (!($this->tabAccess['edit'] === '1')) { + $this->addRowActionSkipList('transferstock', array($item['id'])); + } + } + } + + /** + * Check stock for a given product or product attribute + * and manage available actions in consequence + * + * @param array $item Reference to the current item + * @param bool $is_product_variation Specify if it's a product or a product variation + */ + protected function skipActionByStock(&$item, $is_product_variation = false) + { + $stock_manager = StockManagerFactory::getManager(); + + //get stocks for this product + if ($is_product_variation) { + $stock = $stock_manager->getProductPhysicalQuantities($item['id_product'], $item['id']); + } else { + $stock = $stock_manager->getProductPhysicalQuantities($item['id'], 0); + } + + //affects stock to the list for display + $item['stock'] = $stock; + + if ($stock <= 0) { + //there is no stock, we can only add stock + $this->addRowActionSkipList('removestock', array($item['id'])); + $this->addRowActionSkipList('transferstock', array($item['id'])); + } + } + + /** + * AdminController::initContent() override + * @see AdminController::initContent() + */ + public function initContent() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate the Advanced Stock Management feature prior to using this feature.'); + return false; + } + + // Manage the add stock form + if ($this->display == 'addstock' || $this->display == 'removestock' || $this->display == 'transferstock') { + if (Tools::isSubmit('id_product') || Tools::isSubmit('id_product_attribute')) { + // get id product and product attribute if possible + $id_product = (int)Tools::getValue('id_product', 0); + $id_product_attribute = (int)Tools::getValue('id_product_attribute', 0); + + $product_is_valid = false; + $is_pack = false; + $is_virtual = false; + $lang_id = $this->context->language->id; + $default_wholesale_price = 0; + + // try to load product attribute first + if ($id_product_attribute > 0) { + // try to load product attribute + $combination = new Combination($id_product_attribute); + if (Validate::isLoadedObject($combination)) { + $product_is_valid = true; + $id_product = $combination->id_product; + $reference = $combination->reference; + $ean13 = $combination->ean13; + $upc = $combination->upc; + $manufacturer_reference = $combination->supplier_reference; + + // get the full name for this combination + $query = new DbQuery(); + + $query->select('IFNULL(CONCAT(pl.`name`, \' : \', GROUP_CONCAT(agl.`name`, \' - \', al.`name` SEPARATOR \', \')),pl.`name`) as name'); + $query->from('product_attribute', 'a'); + $query->join('INNER JOIN '._DB_PREFIX_.'product_lang pl ON (pl.`id_product` = a.`id_product` AND pl.`id_lang` = '.(int)$lang_id.') LEFT JOIN '._DB_PREFIX_.'product_attribute_combination pac ON (pac.`id_product_attribute` = a.`id_product_attribute`) LEFT JOIN '._DB_PREFIX_.'attribute atr ON (atr.`id_attribute` = pac.`id_attribute`) LEFT JOIN '._DB_PREFIX_.'attribute_lang al ON (al.`id_attribute` = atr.`id_attribute` AND al.`id_lang` = '.(int)$lang_id.') LEFT JOIN '._DB_PREFIX_.'attribute_group_lang agl ON (agl.`id_attribute_group` = atr.`id_attribute_group` AND agl.`id_lang` = '.(int)$lang_id.')' - ); - $query->where('a.`id_product_attribute` = '.$id_product_attribute); - $name = Db::getInstance()->getValue($query); - $p = new Product($id_product, false, $lang_id); - $default_wholesale_price = $combination->wholesale_price > 0 ? $combination->wholesale_price : $p->wholesale_price; - } - } - // try to load a simple product - else - { - $product = new Product($id_product, false, $lang_id); - if (is_int($product->id)) - { - $product_is_valid = true; - $reference = $product->reference; - $ean13 = $product->ean13; - $upc = $product->upc; - $name = $product->name; - $manufacturer_reference = $product->supplier_reference; - $is_pack = $product->cache_is_pack; - $is_virtual = $product->is_virtual; - $default_wholesale_price = $product->wholesale_price; - } - } + ); + $query->where('a.`id_product_attribute` = '.$id_product_attribute); + $name = Db::getInstance()->getValue($query); + $p = new Product($id_product, false, $lang_id); + $default_wholesale_price = $combination->wholesale_price > 0 ? $combination->wholesale_price : $p->wholesale_price; + } + } + // try to load a simple product + else { + $product = new Product($id_product, false, $lang_id); + if (is_int($product->id)) { + $product_is_valid = true; + $reference = $product->reference; + $ean13 = $product->ean13; + $upc = $product->upc; + $name = $product->name; + $manufacturer_reference = $product->supplier_reference; + $is_pack = $product->cache_is_pack; + $is_virtual = $product->is_virtual; + $default_wholesale_price = $product->wholesale_price; + } + } - if ($product_is_valid === true && $is_virtual == false) - { - // init form - $this->renderForm(); - $this->getlanguages(); + if ($product_is_valid === true && $is_virtual == false) { + // init form + $this->renderForm(); + $this->getlanguages(); - $helper = new HelperForm(); + $helper = new HelperForm(); - $this->initPageHeaderToolbar(); + $this->initPageHeaderToolbar(); - // Check if form template has been overriden - if (file_exists($this->context->smarty->getTemplateDir(0).'/'.$this->tpl_folder.'form.tpl')) - $helper->tpl = $this->tpl_folder.'form.tpl'; + // Check if form template has been overriden + if (file_exists($this->context->smarty->getTemplateDir(0).'/'.$this->tpl_folder.'form.tpl')) { + $helper->tpl = $this->tpl_folder.'form.tpl'; + } - $this->setHelperDisplay($helper); - $helper->submit_action = $this->display; - $helper->id = null; // no display standard hidden field in the form - $helper->languages = $this->_languages; - $helper->default_form_language = $this->default_form_language; - $helper->allow_employee_form_lang = $this->allow_employee_form_lang; - $helper->show_cancel_button = true; - $helper->back_url = $this->context->link->getAdminLink('AdminStockManagement'); + $this->setHelperDisplay($helper); + $helper->submit_action = $this->display; + $helper->id = null; // no display standard hidden field in the form + $helper->languages = $this->_languages; + $helper->default_form_language = $this->default_form_language; + $helper->allow_employee_form_lang = $this->allow_employee_form_lang; + $helper->show_cancel_button = true; + $helper->back_url = $this->context->link->getAdminLink('AdminStockManagement'); - $helper->fields_value = array( - 'id_product' => $id_product, - 'id_product_attribute' => $id_product_attribute, - 'reference' => $reference, - 'manufacturer_reference' => $manufacturer_reference, - 'name' => $name, - 'ean13' => $ean13, - 'upc' => $upc, - 'check' => md5(_COOKIE_KEY_.$id_product.$id_product_attribute), - 'quantity' => Tools::getValue('quantity', ''), - 'id_warehouse' => Tools::getValue('id_warehouse', ''), - 'usable' => $this->fields_value['usable'] ? $this->fields_value['usable'] : Tools::getValue('usable', 1), - 'price' => Tools::getValue('price', (float)Tools::convertPrice($default_wholesale_price, null)), - 'id_currency' => Tools::getValue('id_currency', ''), - 'id_stock_mvt_reason' => Tools::getValue('id_stock_mvt_reason', ''), - 'is_post' => 1, - ); + $helper->fields_value = array( + 'id_product' => $id_product, + 'id_product_attribute' => $id_product_attribute, + 'reference' => $reference, + 'manufacturer_reference' => $manufacturer_reference, + 'name' => $name, + 'ean13' => $ean13, + 'upc' => $upc, + 'check' => md5(_COOKIE_KEY_.$id_product.$id_product_attribute), + 'quantity' => Tools::getValue('quantity', ''), + 'id_warehouse' => Tools::getValue('id_warehouse', ''), + 'usable' => $this->fields_value['usable'] ? $this->fields_value['usable'] : Tools::getValue('usable', 1), + 'price' => Tools::getValue('price', (float)Tools::convertPrice($default_wholesale_price, null)), + 'id_currency' => Tools::getValue('id_currency', ''), + 'id_stock_mvt_reason' => Tools::getValue('id_stock_mvt_reason', ''), + 'is_post' => 1, + ); - if ($this->display == 'addstock') - $_POST['id_product'] = (int)$id_product; + if ($this->display == 'addstock') { + $_POST['id_product'] = (int)$id_product; + } - if ($this->display == 'transferstock') - { - $helper->fields_value['id_warehouse_from'] = Tools::getValue('id_warehouse_from', ''); - $helper->fields_value['id_warehouse_to'] = Tools::getValue('id_warehouse_to', ''); - $helper->fields_value['usable_from'] = Tools::getValue('usable_from', '1'); - $helper->fields_value['usable_to'] = Tools::getValue('usable_to', '1'); - } + if ($this->display == 'transferstock') { + $helper->fields_value['id_warehouse_from'] = Tools::getValue('id_warehouse_from', ''); + $helper->fields_value['id_warehouse_to'] = Tools::getValue('id_warehouse_to', ''); + $helper->fields_value['usable_from'] = Tools::getValue('usable_from', '1'); + $helper->fields_value['usable_to'] = Tools::getValue('usable_to', '1'); + } - $this->content .= $helper->generateForm($this->fields_form); + $this->content .= $helper->generateForm($this->fields_form); - $this->context->smarty->assign(array( - 'content' => $this->content, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } - else - $this->errors[] = Tools::displayError('The specified product is not valid.'); - } - } - else - { - parent::initContent(); - } - } + $this->context->smarty->assign(array( + 'content' => $this->content, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } else { + $this->errors[] = Tools::displayError('The specified product is not valid.'); + } + } + } else { + parent::initContent(); + } + } - /** - * Display addstock action link - * @param string $token the token to add to the link - * @param int $id the identifier to add to the link - * @return string - */ - public function displayAddstockLink($token = null, $id) - { - if (!array_key_exists('AddStock', self::$cache_lang)) + /** + * Display addstock action link + * @param string $token the token to add to the link + * @param int $id the identifier to add to the link + * @return string + */ + public function displayAddstockLink($token = null, $id) + { + if (!array_key_exists('AddStock', self::$cache_lang)) { self::$cache_lang['AddStock'] = $this->l('Add stock'); + } $this->context->smarty->assign(array( 'href' => self::$currentIndex. - '&'.$this->identifier.'='.$id. - '&addstock&token='.($token != null ? $token : $this->token), + '&'.$this->identifier.'='.$id. + '&addstock&token='.($token != null ? $token : $this->token), 'action' => self::$cache_lang['AddStock'], )); return $this->context->smarty->fetch('helpers/list/list_action_addstock.tpl'); - } + } /** - * Display removestock action link - * @param string $token the token to add to the link - * @param int $id the identifier to add to the link - * @return string - */ + * Display removestock action link + * @param string $token the token to add to the link + * @param int $id the identifier to add to the link + * @return string + */ public function displayRemovestockLink($token = null, $id) { - if (!array_key_exists('RemoveStock', self::$cache_lang)) + if (!array_key_exists('RemoveStock', self::$cache_lang)) { self::$cache_lang['RemoveStock'] = $this->l('Remove stock'); + } $this->context->smarty->assign(array( 'href' => self::$currentIndex. - '&'.$this->identifier.'='.$id. - '&removestock&token='.($token != null ? $token : $this->token), + '&'.$this->identifier.'='.$id. + '&removestock&token='.($token != null ? $token : $this->token), 'action' => self::$cache_lang['RemoveStock'], )); @@ -1159,44 +1153,44 @@ class AdminStockManagementControllerCore extends AdminController } /** - * Display transferstock action link - * @param string $token the token to add to the link - * @param int $id the identifier to add to the link - * @return string - */ + * Display transferstock action link + * @param string $token the token to add to the link + * @param int $id the identifier to add to the link + * @return string + */ public function displayTransferstockLink($token = null, $id) { - if (!array_key_exists('TransferStock', self::$cache_lang)) + if (!array_key_exists('TransferStock', self::$cache_lang)) { self::$cache_lang['TransferStock'] = $this->l('Transfer stock'); + } $this->context->smarty->assign(array( 'href' => self::$currentIndex. - '&'.$this->identifier.'='.$id. - '&transferstock&token='.($token != null ? $token : $this->token), + '&'.$this->identifier.'='.$id. + '&transferstock&token='.($token != null ? $token : $this->token), 'action' => self::$cache_lang['TransferStock'], )); return $this->context->smarty->fetch('helpers/list/list_action_transferstock.tpl'); } - public function initProcess() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management prior to using this feature.'); - return false; - } + public function initProcess() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management prior to using this feature.'); + return false; + } - if (Tools::getIsset('detailsproduct')) - { - $this->list_id = 'product_attribute'; + if (Tools::getIsset('detailsproduct')) { + $this->list_id = 'product_attribute'; - if (isset($_POST['submitReset'.$this->list_id])) - $this->processResetFilters(); - } - else - $this->list_id = 'product'; + if (isset($_POST['submitReset'.$this->list_id])) { + $this->processResetFilters(); + } + } else { + $this->list_id = 'product'; + } - parent::initProcess(); - } + parent::initProcess(); + } } diff --git a/controllers/admin/AdminStockMvtController.php b/controllers/admin/AdminStockMvtController.php index ced5c572..307dd9d5 100644 --- a/controllers/admin/AdminStockMvtController.php +++ b/controllers/admin/AdminStockMvtController.php @@ -30,113 +30,114 @@ */ class AdminStockMvtControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->context = Context::getContext(); - $this->table = 'stock_mvt'; - $this->className = 'StockMvt'; - $this->identifier = 'id_stock_mvt'; - $this->lang = false; - $this->multishop_context = Shop::CONTEXT_ALL; + public function __construct() + { + $this->bootstrap = true; + $this->context = Context::getContext(); + $this->table = 'stock_mvt'; + $this->className = 'StockMvt'; + $this->identifier = 'id_stock_mvt'; + $this->lang = false; + $this->multishop_context = Shop::CONTEXT_ALL; - $this->list_no_link = true; - $this->displayInformation($this->l('This interface allows you to display the stock movement for a selected warehouse.').'<br />'); + $this->list_no_link = true; + $this->displayInformation($this->l('This interface allows you to display the stock movement for a selected warehouse.').'<br />'); - $this->fields_list = array( - 'product_reference' => array( - 'title' => $this->l('Reference'), - 'havingFilter' => true - ), - 'product_ean13' => array( - 'title' => $this->l('EAN 13'), - 'havingFilter' => true - ), - 'product_upc' => array( - 'title' => $this->l('UPC'), - 'havingFilter' => true - ), - 'product_name' => array( - 'title' => $this->l('Name'), - 'havingFilter' => true - ), - 'warehouse_name' => array( - 'title' => $this->l('Warehouse'), - 'havingFilter' => false, - 'orderby' => true, - 'search' => false, - ), - 'sign' => array( - 'title' => $this->l('Sign'), - 'align' => 'center', - 'type' => 'select', - 'filter_key' => 'a!sign', - 'list' => array( - '1' => $this->l('Increase'), - '-1' => $this->l('Decrease'), - ), - 'icon' => array( - -1 => 'remove_stock.png', - 1 => 'add_stock.png' - ), - 'class' => 'fixed-width-xs' - ), - 'physical_quantity' => array( - 'title' => $this->l('Quantity'), - 'align' => 'center', - 'filter_key' => 'a!physical_quantity', - 'class' => 'fixed-width-sm' - ), - 'price_te' => array( - 'title' => $this->l('Price (tax excl.)'), - 'type' => 'price', - 'currency' => true, - 'filter_key' => 'a!price_te' - ), - 'reason' => array( - 'title' => $this->l('Label'), - 'havingFilter' => true - ), - 'employee' => array( - 'title' => $this->l('Employee'), - 'havingFilter' => true - ), - 'date_add' => array( - 'title' => $this->l('Date'), - 'type' => 'datetime', - 'filter_key' => 'a!date_add' - ), - ); + $this->fields_list = array( + 'product_reference' => array( + 'title' => $this->l('Reference'), + 'havingFilter' => true + ), + 'product_ean13' => array( + 'title' => $this->l('EAN 13'), + 'havingFilter' => true + ), + 'product_upc' => array( + 'title' => $this->l('UPC'), + 'havingFilter' => true + ), + 'product_name' => array( + 'title' => $this->l('Name'), + 'havingFilter' => true + ), + 'warehouse_name' => array( + 'title' => $this->l('Warehouse'), + 'havingFilter' => false, + 'orderby' => true, + 'search' => false, + ), + 'sign' => array( + 'title' => $this->l('Sign'), + 'align' => 'center', + 'type' => 'select', + 'filter_key' => 'a!sign', + 'list' => array( + '1' => $this->l('Increase'), + '-1' => $this->l('Decrease'), + ), + 'icon' => array( + -1 => 'remove_stock.png', + 1 => 'add_stock.png' + ), + 'class' => 'fixed-width-xs' + ), + 'physical_quantity' => array( + 'title' => $this->l('Quantity'), + 'align' => 'center', + 'filter_key' => 'a!physical_quantity', + 'class' => 'fixed-width-sm' + ), + 'price_te' => array( + 'title' => $this->l('Price (tax excl.)'), + 'type' => 'price', + 'currency' => true, + 'filter_key' => 'a!price_te' + ), + 'reason' => array( + 'title' => $this->l('Label'), + 'havingFilter' => true + ), + 'employee' => array( + 'title' => $this->l('Employee'), + 'havingFilter' => true + ), + 'date_add' => array( + 'title' => $this->l('Date'), + 'type' => 'datetime', + 'filter_key' => 'a!date_add' + ), + ); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - $this->page_header_toolbar_title = $this->l('Stock movement'); + public function initPageHeaderToolbar() + { + $this->page_header_toolbar_title = $this->l('Stock movement'); - if (Tools::isSubmit('id_warehouse') && (int)Tools::getValue('id_warehouse') != -1) - $this->page_header_toolbar_btn['export-stock-mvt-csv'] = array( - 'short' => $this->l('Export this list as CSV', null, null, false), - 'href' => $this->context->link->getAdminLink('AdminStockMvt').'&csv&id_warehouse='.(int)$this->getCurrentWarehouseId(), - 'desc' => $this->l('Export (CSV)', null, null, false), - 'imgclass' => 'export' - ); + if (Tools::isSubmit('id_warehouse') && (int)Tools::getValue('id_warehouse') != -1) { + $this->page_header_toolbar_btn['export-stock-mvt-csv'] = array( + 'short' => $this->l('Export this list as CSV', null, null, false), + 'href' => $this->context->link->getAdminLink('AdminStockMvt').'&csv&id_warehouse='.(int)$this->getCurrentWarehouseId(), + 'desc' => $this->l('Export (CSV)', null, null, false), + 'imgclass' => 'export' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - /** - * AdminController::renderList() override - * @see AdminController::renderList() - */ - public function renderList() - { - // removes toolbar btn - $this->toolbar_btn = array(); + /** + * AdminController::renderList() override + * @see AdminController::renderList() + */ + public function renderList() + { + // removes toolbar btn + $this->toolbar_btn = array(); - // overrides select - $this->_select = ' + // overrides select + $this->_select = ' CONCAT(pl.name, \' \', GROUP_CONCAT(IFNULL(al.name, \'\'), \'\')) product_name, CONCAT(a.employee_lastname, \' \', a.employee_firstname) as employee, mrl.name as reason, @@ -146,8 +147,8 @@ class AdminStockMvtControllerCore extends AdminController w.id_currency as id_currency, w.name as warehouse_name'; - // overrides join - $this->_join = 'INNER JOIN '._DB_PREFIX_.'stock stock ON a.id_stock = stock.id_stock + // overrides join + $this->_join = 'INNER JOIN '._DB_PREFIX_.'stock stock ON a.id_stock = stock.id_stock LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON ( stock.id_product = pl.id_product AND pl.id_lang = '.(int)$this->context->language->id.Shop::addSqlRestrictionOnLang('pl').' @@ -163,173 +164,170 @@ class AdminStockMvtControllerCore extends AdminController AND pac.id_product_attribute <> 0 AND al.id_lang = '.(int)$this->context->language->id.' )'; - // overrides group - $this->_group = 'GROUP BY a.id_stock_mvt'; + // overrides group + $this->_group = 'GROUP BY a.id_stock_mvt'; - // overrides where depending on the warehouse - $id_warehouse = (int)$this->getCurrentWarehouseId(); - if ($id_warehouse > 0) - { - $this->_where = ' AND w.id_warehouse = '.$id_warehouse; - self::$currentIndex .= '&id_warehouse='.$id_warehouse; - } + // overrides where depending on the warehouse + $id_warehouse = (int)$this->getCurrentWarehouseId(); + if ($id_warehouse > 0) { + $this->_where = ' AND w.id_warehouse = '.$id_warehouse; + self::$currentIndex .= '&id_warehouse='.$id_warehouse; + } - // sets the current warehouse - $this->tpl_list_vars['current_warehouse'] = $this->getCurrentWarehouseId(); + // sets the current warehouse + $this->tpl_list_vars['current_warehouse'] = $this->getCurrentWarehouseId(); - // sets the list of warehouses - $warehouses = Warehouse::getWarehouses(true); - array_unshift($warehouses, array('id_warehouse' => -1, 'name' => $this->l('All Warehouses'))); - $this->tpl_list_vars['list_warehouses'] = $warehouses; + // sets the list of warehouses + $warehouses = Warehouse::getWarehouses(true); + array_unshift($warehouses, array('id_warehouse' => -1, 'name' => $this->l('All Warehouses'))); + $this->tpl_list_vars['list_warehouses'] = $warehouses; - // sets toolbar - $this->initToolbar(); + // sets toolbar + $this->initToolbar(); - // renders list - $list = parent::renderList(); + // renders list + $list = parent::renderList(); - // if export requested - if (Tools::isSubmit('csv')) - { - if (count($this->_list) > 0) - { - $this->renderCSV(); - die; - } - else - $this->displayWarning($this->l('There is nothing to export as a CSV.')); - } + // if export requested + if (Tools::isSubmit('csv')) { + if (count($this->_list) > 0) { + $this->renderCSV(); + die; + } else { + $this->displayWarning($this->l('There is nothing to export as a CSV.')); + } + } - return $list; - } + return $list; + } - /** - * Gets the current warehouse for this controller - * - * @return int warehouse_id - */ - protected function getCurrentWarehouseId() - { - static $warehouse = 0; + /** + * Gets the current warehouse for this controller + * + * @return int warehouse_id + */ + protected function getCurrentWarehouseId() + { + static $warehouse = 0; - if ($warehouse == 0) - { - $warehouse = -1; - if ((int)Tools::getValue('id_warehouse')) - $warehouse = (int)Tools::getValue('id_warehouse'); - } + if ($warehouse == 0) { + $warehouse = -1; + if ((int)Tools::getValue('id_warehouse')) { + $warehouse = (int)Tools::getValue('id_warehouse'); + } + } - return $warehouse; - } + return $warehouse; + } - /** - * AdminController::getList() override - * @see AdminController::getList() - * - * @param int $id_lang - * @param string|null $order_by - * @param string|null $order_way - * @param int $start - * @param int|null $limit - * @param int|bool $id_lang_shop - * - * @throws PrestaShopException - */ - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - if (Tools::isSubmit('csv')) - $limit = false; + /** + * AdminController::getList() override + * @see AdminController::getList() + * + * @param int $id_lang + * @param string|null $order_by + * @param string|null $order_way + * @param int $start + * @param int|null $limit + * @param int|bool $id_lang_shop + * + * @throws PrestaShopException + */ + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + if (Tools::isSubmit('csv')) { + $limit = false; + } - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - //If there is a field product_name in the list, check if this field is null and display standard message - foreach ($this->fields_list as $key => $value) - if ($key == 'product_name') - { - $nb_items = count($this->_list); + //If there is a field product_name in the list, check if this field is null and display standard message + foreach ($this->fields_list as $key => $value) { + if ($key == 'product_name') { + $nb_items = count($this->_list); - for ($i = 0; $i < $nb_items; ++$i) - { - $item = &$this->_list[$i]; + for ($i = 0; $i < $nb_items; ++$i) { + $item = &$this->_list[$i]; - if (empty($item['product_name'])) - $item['product_name'] = $this->l('The name of this product is not available. It may have been deleted from the system.'); - } - } - } + if (empty($item['product_name'])) { + $item['product_name'] = $this->l('The name of this product is not available. It may have been deleted from the system.'); + } + } + } + } + } - /** - * @see AdminController::initToolbar(); - */ - public function initToolbar() - { - if (Tools::isSubmit('id_warehouse') && (int)Tools::getValue('id_warehouse') != -1) - $this->toolbar_btn['export-stock-mvt-csv'] = array( - 'short' => 'Export this list as CSV', - 'href' => $this->context->link->getAdminLink('AdminStockMvt').'&csv&id_warehouse='.(int)$this->getCurrentWarehouseId(), - 'desc' => $this->l('Export (CSV)'), - 'imgclass' => 'export' - ); + /** + * @see AdminController::initToolbar(); + */ + public function initToolbar() + { + if (Tools::isSubmit('id_warehouse') && (int)Tools::getValue('id_warehouse') != -1) { + $this->toolbar_btn['export-stock-mvt-csv'] = array( + 'short' => 'Export this list as CSV', + 'href' => $this->context->link->getAdminLink('AdminStockMvt').'&csv&id_warehouse='.(int)$this->getCurrentWarehouseId(), + 'desc' => $this->l('Export (CSV)'), + 'imgclass' => 'export' + ); + } - parent::initToolbar(); - unset($this->toolbar_btn['new']); - } + parent::initToolbar(); + unset($this->toolbar_btn['new']); + } - /** - * Exports CSV - */ - public function renderCSV() - { - if (!$this->_list) - return; + /** + * Exports CSV + */ + public function renderCSV() + { + if (!$this->_list) { + return; + } - // header - if (Tools::getValue('id_warehouse') != -1) - $filename = $this->l('stock_mvt').'_'.Warehouse::getWarehouseNameById((int)Tools::getValue('id_warehouse')).'.csv'; - else - $filename = $this->l('stock_mvt').'.csv'; - header('Content-type: text/csv'); - header('Cache-Control: no-store, no-cache'); + // header + if (Tools::getValue('id_warehouse') != -1) { + $filename = $this->l('stock_mvt').'_'.Warehouse::getWarehouseNameById((int)Tools::getValue('id_warehouse')).'.csv'; + } else { + $filename = $this->l('stock_mvt').'.csv'; + } + header('Content-type: text/csv'); + header('Cache-Control: no-store, no-cache'); header('Content-disposition: attachment; filename="'.$filename); - // puts keys - $keys = array('id_order', 'id_supply_order', 'emloyee_firstname', 'employee_lastname', 'physical_quantity', - 'date_add', 'sign', 'price_te', 'product_name', 'label', 'product_reference', 'product_ean13', 'product_upc'); - echo sprintf("%s\n", implode(';', $keys)); + // puts keys + $keys = array('id_order', 'id_supply_order', 'emloyee_firstname', 'employee_lastname', 'physical_quantity', + 'date_add', 'sign', 'price_te', 'product_name', 'label', 'product_reference', 'product_ean13', 'product_upc'); + echo sprintf("%s\n", implode(';', $keys)); - // puts rows - foreach ($this->_list as $row) - { - $row_csv = array($row['id_order'], $row['id_supply_order'], $row['employee_firstname'], - $row['employee_lastname'], $row['physical_quantity'], $row['date_add'], - $row['sign'], $row['price_te'], $row['product_name'], - $row['reason'], $row['product_reference'], $row['product_ean13'], $row['product_upc'] - ); - - // puts one row - echo sprintf("%s\n", implode(';', array_map(array('CSVCore', 'wrap'), $row_csv))); - } - } - - public function initContent() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); - return false; - } - parent::initContent(); - } - - public function initProcess() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); - return false; - } - parent::initProcess(); - } + // puts rows + foreach ($this->_list as $row) { + $row_csv = array($row['id_order'], $row['id_supply_order'], $row['employee_firstname'], + $row['employee_lastname'], $row['physical_quantity'], $row['date_add'], + $row['sign'], $row['price_te'], $row['product_name'], + $row['reason'], $row['product_reference'], $row['product_ean13'], $row['product_upc'] + ); + // puts one row + echo sprintf("%s\n", implode(';', array_map(array('CSVCore', 'wrap'), $row_csv))); + } + } + + public function initContent() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); + return false; + } + parent::initContent(); + } + + public function initProcess() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); + return false; + } + parent::initProcess(); + } } diff --git a/controllers/admin/AdminStoresController.php b/controllers/admin/AdminStoresController.php index 45d1c078..a36b8d54 100644 --- a/controllers/admin/AdminStoresController.php +++ b/controllers/admin/AdminStoresController.php @@ -29,556 +29,565 @@ */ class AdminStoresControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'store'; - $this->className = 'Store'; - $this->lang = false; - $this->toolbar_scroll = false; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'store'; + $this->className = 'Store'; + $this->lang = false; + $this->toolbar_scroll = false; - $this->context = Context::getContext(); + $this->context = Context::getContext(); - if (!Tools::getValue('realedit')) - $this->deleted = false; + if (!Tools::getValue('realedit')) { + $this->deleted = false; + } - $this->fieldImageSettings = array( - 'name' => 'image', - 'dir' => 'st' - ); + $this->fieldImageSettings = array( + 'name' => 'image', + 'dir' => 'st' + ); - $this->fields_list = array( - 'id_store' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'name' => array('title' => $this->l('Name'), 'filter_key' => 'a!name'), - 'address1' => array('title' => $this->l('Address'), 'filter_key' => 'a!address1'), - 'city' => array('title' => $this->l('City')), - 'postcode' => array('title' => $this->l('Zip/postal code')), - 'state' => array('title' => $this->l('State'), 'filter_key' => 'st!name'), - 'country' => array('title' => $this->l('Country'), 'filter_key' => 'cl!name'), - 'phone' => array('title' => $this->l('Phone')), - 'fax' => array('title' => $this->l('Fax')), - 'active' => array('title' => $this->l('Enabled'), 'align' => 'center', 'active' => 'status', 'type' => 'bool', 'orderby' => false) - ); + $this->fields_list = array( + 'id_store' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'name' => array('title' => $this->l('Name'), 'filter_key' => 'a!name'), + 'address1' => array('title' => $this->l('Address'), 'filter_key' => 'a!address1'), + 'city' => array('title' => $this->l('City')), + 'postcode' => array('title' => $this->l('Zip/postal code')), + 'state' => array('title' => $this->l('State'), 'filter_key' => 'st!name'), + 'country' => array('title' => $this->l('Country'), 'filter_key' => 'cl!name'), + 'phone' => array('title' => $this->l('Phone')), + 'fax' => array('title' => $this->l('Fax')), + 'active' => array('title' => $this->l('Enabled'), 'align' => 'center', 'active' => 'status', 'type' => 'bool', 'orderby' => false) + ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Parameters'), - 'fields' => array( - 'PS_STORES_DISPLAY_FOOTER' => array( - 'title' => $this->l('Display in the footer'), - 'hint' => $this->l('Display a link to the store locator in the footer.'), - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_STORES_DISPLAY_SITEMAP' => array( - 'title' => $this->l('Display in the sitemap page'), - 'hint' => $this->l('Display a link to the store locator in the sitemap page.'), - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_STORES_SIMPLIFIED' => array( - 'title' => $this->l('Show a simplified store locator'), - 'hint' => $this->l('No map, no search, only a store directory.'), - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_STORES_CENTER_LAT' => array( - 'title' => $this->l('Default latitude'), - 'hint' => $this->l('Used for the initial position of the map.'), - 'cast' => 'floatval', - 'type' => 'text', - 'size' => '10' - ), - 'PS_STORES_CENTER_LONG' => array( - 'title' => $this->l('Default longitude'), - 'hint' => $this->l('Used for the initial position of the map.'), - 'cast' => 'floatval', - 'type' => 'text', - 'size' => '10' - ) - ), - 'submit' => array('title' => $this->l('Save')) - ) - ); + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Parameters'), + 'fields' => array( + 'PS_STORES_DISPLAY_FOOTER' => array( + 'title' => $this->l('Display in the footer'), + 'hint' => $this->l('Display a link to the store locator in the footer.'), + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_STORES_DISPLAY_SITEMAP' => array( + 'title' => $this->l('Display in the sitemap page'), + 'hint' => $this->l('Display a link to the store locator in the sitemap page.'), + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_STORES_SIMPLIFIED' => array( + 'title' => $this->l('Show a simplified store locator'), + 'hint' => $this->l('No map, no search, only a store directory.'), + 'cast' => 'intval', + 'type' => 'bool' + ), + 'PS_STORES_CENTER_LAT' => array( + 'title' => $this->l('Default latitude'), + 'hint' => $this->l('Used for the initial position of the map.'), + 'cast' => 'floatval', + 'type' => 'text', + 'size' => '10' + ), + 'PS_STORES_CENTER_LONG' => array( + 'title' => $this->l('Default longitude'), + 'hint' => $this->l('Used for the initial position of the map.'), + 'cast' => 'floatval', + 'type' => 'text', + 'size' => '10' + ) + ), + 'submit' => array('title' => $this->l('Save')) + ) + ); - parent::__construct(); + parent::__construct(); - $this->_buildOrderedFieldsShop($this->_getDefaultFieldsContent()); - } + $this->_buildOrderedFieldsShop($this->_getDefaultFieldsContent()); + } - public function renderOptions() - { - // Set toolbar options - $this->display = 'options'; - $this->show_toolbar = true; - $this->toolbar_scroll = true; - $this->initToolbar(); + public function renderOptions() + { + // Set toolbar options + $this->display = 'options'; + $this->show_toolbar = true; + $this->toolbar_scroll = true; + $this->initToolbar(); - return parent::renderOptions(); - } + return parent::renderOptions(); + } - public function initToolbar() - { - parent::initToolbar(); + public function initToolbar() + { + parent::initToolbar(); - if ($this->display == 'options') - unset($this->toolbar_btn['new']); - elseif ($this->display != 'add' && $this->display != 'edit') - unset($this->toolbar_btn['save']); - } + if ($this->display == 'options') { + unset($this->toolbar_btn['new']); + } elseif ($this->display != 'add' && $this->display != 'edit') { + unset($this->toolbar_btn['save']); + } + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_store'] = array( - 'href' => self::$currentIndex.'&addstore&token='.$this->token, - 'desc' => $this->l('Add new store', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_store'] = array( + 'href' => self::$currentIndex.'&addstore&token='.$this->token, + 'desc' => $this->l('Add new store', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderList() - { - // Set toolbar options - $this->display = null; - $this->initToolbar(); + public function renderList() + { + // Set toolbar options + $this->display = null; + $this->initToolbar(); - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->_select = 'cl.`name` country, st.`name` state'; - $this->_join = ' + $this->_select = 'cl.`name` country, st.`name` state'; + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'country_lang` cl ON (cl.`id_country` = a.`id_country` AND cl.`id_lang` = '.(int)$this->context->language->id.') LEFT JOIN `'._DB_PREFIX_.'state` st ON (st.`id_state` = a.`id_state`)'; - return parent::renderList(); - } + return parent::renderList(); + } - public function renderForm() - { - if (!($obj = $this->loadObject(true))) - return; + public function renderForm() + { + if (!($obj = $this->loadObject(true))) { + return; + } - $image = _PS_STORE_IMG_DIR_.$obj->id.'.jpg'; - $image_url = ImageManager::thumbnail($image, $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, - $this->imageType, true, true); - $image_size = file_exists($image) ? filesize($image) / 1000 : false; + $image = _PS_STORE_IMG_DIR_.$obj->id.'.jpg'; + $image_url = ImageManager::thumbnail($image, $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, + $this->imageType, true, true); + $image_size = file_exists($image) ? filesize($image) / 1000 : false; - $tmp_addr = new Address(); - $res = $tmp_addr->getFieldsRequiredDatabase(); - $required_fields = array(); - foreach ($res as $row) - $required_fields[(int)$row['id_required_field']] = $row['field_name']; + $tmp_addr = new Address(); + $res = $tmp_addr->getFieldsRequiredDatabase(); + $required_fields = array(); + foreach ($res as $row) { + $required_fields[(int)$row['id_required_field']] = $row['field_name']; + } - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Stores'), - 'icon' => 'icon-home' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'required' => false, - 'hint' => array( - $this->l('Store name (e.g. City Center Mall Store).'), - $this->l('Allowed characters: letters, spaces and %s') - ) - ), - array( - 'type' => 'text', - 'label' => $this->l('Address'), - 'name' => 'address1', - 'required' => true - ), - array( - 'type' => 'text', - 'label' => $this->l('Address (2)'), - 'name' => 'address2' - ), - array( - 'type' => 'text', - 'label' => $this->l('Zip/postal Code'), - 'name' => 'postcode', - 'required' => in_array('postcode', $required_fields) - ), - array( - 'type' => 'text', - 'label' => $this->l('City'), - 'name' => 'city', - 'required' => true - ), - array( - 'type' => 'select', - 'label' => $this->l('Country'), - 'name' => 'id_country', - 'required' => true, - 'default_value' => (int)$this->context->country->id, - 'options' => array( - 'query' => Country::getCountries($this->context->language->id), - 'id' => 'id_country', - 'name' => 'name', - ) - ), - array( - 'type' => 'select', - 'label' => $this->l('State'), - 'name' => 'id_state', - 'required' => true, - 'options' => array( - 'id' => 'id_state', - 'name' => 'name', + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Stores'), + 'icon' => 'icon-home' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'required' => false, + 'hint' => array( + $this->l('Store name (e.g. City Center Mall Store).'), + $this->l('Allowed characters: letters, spaces and %s') + ) + ), + array( + 'type' => 'text', + 'label' => $this->l('Address'), + 'name' => 'address1', + 'required' => true + ), + array( + 'type' => 'text', + 'label' => $this->l('Address (2)'), + 'name' => 'address2' + ), + array( + 'type' => 'text', + 'label' => $this->l('Zip/postal Code'), + 'name' => 'postcode', + 'required' => in_array('postcode', $required_fields) + ), + array( + 'type' => 'text', + 'label' => $this->l('City'), + 'name' => 'city', + 'required' => true + ), + array( + 'type' => 'select', + 'label' => $this->l('Country'), + 'name' => 'id_country', + 'required' => true, + 'default_value' => (int)$this->context->country->id, + 'options' => array( + 'query' => Country::getCountries($this->context->language->id), + 'id' => 'id_country', + 'name' => 'name', + ) + ), + array( + 'type' => 'select', + 'label' => $this->l('State'), + 'name' => 'id_state', + 'required' => true, + 'options' => array( + 'id' => 'id_state', + 'name' => 'name', 'query' => null - ) - ), - array( - 'type' => 'latitude', - 'label' => $this->l('Latitude / Longitude'), - 'name' => 'latitude', - 'required' => true, - 'maxlength' => 12, - 'hint' => $this->l('Store coordinates (e.g. 45.265469/-47.226478).') - ), - array( - 'type' => 'text', - 'label' => $this->l('Phone'), - 'name' => 'phone' - ), - array( - 'type' => 'text', - 'label' => $this->l('Fax'), - 'name' => 'fax' - ), - array( - 'type' => 'text', - 'label' => $this->l('Email address'), - 'name' => 'email' - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Note'), - 'name' => 'note', - 'cols' => 42, - 'rows' => 4 - ), - array( - 'type' => 'switch', - 'label' => $this->l('Status'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Whether or not to display this store.') - ), - array( - 'type' => 'file', - 'label' => $this->l('Picture'), - 'name' => 'image', - 'display_image' => true, - 'image' => $image_url ? $image_url : false, - 'size' => $image_size, - 'hint' => $this->l('Storefront picture.') - ) - ), - 'hours' => array( - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + ) + ), + array( + 'type' => 'latitude', + 'label' => $this->l('Latitude / Longitude'), + 'name' => 'latitude', + 'required' => true, + 'maxlength' => 12, + 'hint' => $this->l('Store coordinates (e.g. 45.265469/-47.226478).') + ), + array( + 'type' => 'text', + 'label' => $this->l('Phone'), + 'name' => 'phone' + ), + array( + 'type' => 'text', + 'label' => $this->l('Fax'), + 'name' => 'fax' + ), + array( + 'type' => 'text', + 'label' => $this->l('Email address'), + 'name' => 'email' + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Note'), + 'name' => 'note', + 'cols' => 42, + 'rows' => 4 + ), + array( + 'type' => 'switch', + 'label' => $this->l('Status'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Whether or not to display this store.') + ), + array( + 'type' => 'file', + 'label' => $this->l('Picture'), + 'name' => 'image', + 'display_image' => true, + 'image' => $image_url ? $image_url : false, + 'size' => $image_size, + 'hint' => $this->l('Storefront picture.') + ) + ), + 'hours' => array( + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - $days = array(); - $days[1] = $this->l('Monday'); - $days[2] = $this->l('Tuesday'); - $days[3] = $this->l('Wednesday'); - $days[4] = $this->l('Thursday'); - $days[5] = $this->l('Friday'); - $days[6] = $this->l('Saturday'); - $days[7] = $this->l('Sunday'); + $days = array(); + $days[1] = $this->l('Monday'); + $days[2] = $this->l('Tuesday'); + $days[3] = $this->l('Wednesday'); + $days[4] = $this->l('Thursday'); + $days[5] = $this->l('Friday'); + $days[6] = $this->l('Saturday'); + $days[7] = $this->l('Sunday'); - $hours = $this->getFieldValue($obj, 'hours'); - if (!empty($hours)) - $hours_unserialized = Tools::unSerialize($hours); + $hours = $this->getFieldValue($obj, 'hours'); + if (!empty($hours)) { + $hours_unserialized = Tools::unSerialize($hours); + } - $this->fields_value = array( - 'latitude' => $this->getFieldValue($obj, 'latitude') ? $this->getFieldValue($obj, 'latitude') : Configuration::get('PS_STORES_CENTER_LAT'), - 'longitude' => $this->getFieldValue($obj, 'longitude') ? $this->getFieldValue($obj, 'longitude') : Configuration::get('PS_STORES_CENTER_LONG'), - 'days' => $days, - 'hours' => isset($hours_unserialized) ? $hours_unserialized : false - ); + $this->fields_value = array( + 'latitude' => $this->getFieldValue($obj, 'latitude') ? $this->getFieldValue($obj, 'latitude') : Configuration::get('PS_STORES_CENTER_LAT'), + 'longitude' => $this->getFieldValue($obj, 'longitude') ? $this->getFieldValue($obj, 'longitude') : Configuration::get('PS_STORES_CENTER_LONG'), + 'days' => $days, + 'hours' => isset($hours_unserialized) ? $hours_unserialized : false + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function postProcess() - { - if (isset($_POST['submitAdd'.$this->table])) - { - /* Cleaning fields */ - foreach ($_POST as $kp => $vp) - if (!in_array($kp, array('checkBoxShopGroupAsso_store', 'checkBoxShopAsso_store'))) - $_POST[$kp] = trim($vp); + public function postProcess() + { + if (isset($_POST['submitAdd'.$this->table])) { + /* Cleaning fields */ + foreach ($_POST as $kp => $vp) { + if (!in_array($kp, array('checkBoxShopGroupAsso_store', 'checkBoxShopAsso_store'))) { + $_POST[$kp] = trim($vp); + } + } - /* Rewrite latitude and longitude to 8 digits */ - $_POST['latitude'] = number_format((float)$_POST['latitude'], 8); - $_POST['longitude'] = number_format((float)$_POST['longitude'], 8); + /* Rewrite latitude and longitude to 8 digits */ + $_POST['latitude'] = number_format((float)$_POST['latitude'], 8); + $_POST['longitude'] = number_format((float)$_POST['longitude'], 8); - /* If the selected country does not contain states */ - $id_state = (int)Tools::getValue('id_state'); - $id_country = (int)Tools::getValue('id_country'); - $country = new Country((int)$id_country); + /* If the selected country does not contain states */ + $id_state = (int)Tools::getValue('id_state'); + $id_country = (int)Tools::getValue('id_country'); + $country = new Country((int)$id_country); - if ($id_country && $country && !(int)$country->contains_states && $id_state) - $this->errors[] = Tools::displayError('You\'ve selected a state for a country that does not contain states.'); + if ($id_country && $country && !(int)$country->contains_states && $id_state) { + $this->errors[] = Tools::displayError('You\'ve selected a state for a country that does not contain states.'); + } - /* If the selected country contains states, then a state have to be selected */ - if ((int)$country->contains_states && !$id_state) - $this->errors[] = Tools::displayError('An address located in a country containing states must have a state selected.'); + /* If the selected country contains states, then a state have to be selected */ + if ((int)$country->contains_states && !$id_state) { + $this->errors[] = Tools::displayError('An address located in a country containing states must have a state selected.'); + } - $latitude = (float)Tools::getValue('latitude'); - $longitude = (float)Tools::getValue('longitude'); + $latitude = (float)Tools::getValue('latitude'); + $longitude = (float)Tools::getValue('longitude'); - if (empty($latitude) || empty($longitude)) - $this->errors[] = Tools::displayError('Latitude and longitude are required.'); + if (empty($latitude) || empty($longitude)) { + $this->errors[] = Tools::displayError('Latitude and longitude are required.'); + } - $postcode = Tools::getValue('postcode'); - /* Check zip code format */ - if ($country->zip_code_format && !$country->checkZipCode($postcode)) - $this->errors[] = Tools::displayError('Your Zip/postal code is incorrect.').'<br />'.Tools::displayError('It must be entered as follows:').' '.str_replace('C', $country->iso_code, str_replace('N', '0', str_replace('L', 'A', $country->zip_code_format))); - elseif(empty($postcode) && $country->need_zip_code) - $this->errors[] = Tools::displayError('A Zip/postal code is required.'); - elseif ($postcode && !Validate::isPostCode($postcode)) - $this->errors[] = Tools::displayError('The Zip/postal code is invalid.'); + $postcode = Tools::getValue('postcode'); + /* Check zip code format */ + if ($country->zip_code_format && !$country->checkZipCode($postcode)) { + $this->errors[] = Tools::displayError('Your Zip/postal code is incorrect.').'<br />'.Tools::displayError('It must be entered as follows:').' '.str_replace('C', $country->iso_code, str_replace('N', '0', str_replace('L', 'A', $country->zip_code_format))); + } elseif (empty($postcode) && $country->need_zip_code) { + $this->errors[] = Tools::displayError('A Zip/postal code is required.'); + } elseif ($postcode && !Validate::isPostCode($postcode)) { + $this->errors[] = Tools::displayError('The Zip/postal code is invalid.'); + } - /* Store hours */ - $_POST['hours'] = array(); - for ($i = 1; $i < 8; $i++) - $_POST['hours'][] .= Tools::getValue('hours_'.(int)$i); - $_POST['hours'] = serialize($_POST['hours']); - } + /* Store hours */ + $_POST['hours'] = array(); + for ($i = 1; $i < 8; $i++) { + $_POST['hours'][] .= Tools::getValue('hours_'.(int)$i); + } + $_POST['hours'] = serialize($_POST['hours']); + } - if (!count($this->errors)) - parent::postProcess(); - else - $this->display = 'add'; - } + if (!count($this->errors)) { + parent::postProcess(); + } else { + $this->display = 'add'; + } + } - protected function postImage($id) - { - $ret = parent::postImage($id); - $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); + protected function postImage($id) + { + $ret = parent::postImage($id); + $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); - if (($id_store = (int)Tools::getValue('id_store')) && isset($_FILES) && count($_FILES) && file_exists(_PS_STORE_IMG_DIR_.$id_store.'.jpg')) - { - $images_types = ImageType::getImagesTypes('stores'); - foreach ($images_types as $k => $image_type) - { - ImageManager::resize(_PS_STORE_IMG_DIR_.$id_store.'.jpg', - _PS_STORE_IMG_DIR_.$id_store.'-'.stripslashes($image_type['name']).'.jpg', - (int)$image_type['width'], (int)$image_type['height'] - ); + if (($id_store = (int)Tools::getValue('id_store')) && isset($_FILES) && count($_FILES) && file_exists(_PS_STORE_IMG_DIR_.$id_store.'.jpg')) { + $images_types = ImageType::getImagesTypes('stores'); + foreach ($images_types as $k => $image_type) { + ImageManager::resize(_PS_STORE_IMG_DIR_.$id_store.'.jpg', + _PS_STORE_IMG_DIR_.$id_store.'-'.stripslashes($image_type['name']).'.jpg', + (int)$image_type['width'], (int)$image_type['height'] + ); - if ($generate_hight_dpi_images) - ImageManager::resize(_PS_STORE_IMG_DIR_.$id_store.'.jpg', - _PS_STORE_IMG_DIR_.$id_store.'-'.stripslashes($image_type['name']).'2x.jpg', - (int)$image_type['width']*2, (int)$image_type['height']*2 - ); - } - } - return $ret; - } + if ($generate_hight_dpi_images) { + ImageManager::resize(_PS_STORE_IMG_DIR_.$id_store.'.jpg', + _PS_STORE_IMG_DIR_.$id_store.'-'.stripslashes($image_type['name']).'2x.jpg', + (int)$image_type['width']*2, (int)$image_type['height']*2 + ); + } + } + } + return $ret; + } - protected function _getDefaultFieldsContent() - { - $this->context = Context::getContext(); - $countryList = array(); - $countryList[] = array('id' => '0', 'name' => $this->l('Choose your country')); - foreach (Country::getCountries($this->context->language->id) as $country) - $countryList[] = array('id' => $country['id_country'], 'name' => $country['name']); - $stateList = array(); - $stateList[] = array('id' => '0', 'name' => $this->l('Choose your state (if applicable)')); - foreach (State::getStates($this->context->language->id) as $state) - $stateList[] = array('id' => $state['id_state'], 'name' => $state['name']); + protected function _getDefaultFieldsContent() + { + $this->context = Context::getContext(); + $countryList = array(); + $countryList[] = array('id' => '0', 'name' => $this->l('Choose your country')); + foreach (Country::getCountries($this->context->language->id) as $country) { + $countryList[] = array('id' => $country['id_country'], 'name' => $country['name']); + } + $stateList = array(); + $stateList[] = array('id' => '0', 'name' => $this->l('Choose your state (if applicable)')); + foreach (State::getStates($this->context->language->id) as $state) { + $stateList[] = array('id' => $state['id_state'], 'name' => $state['name']); + } - $formFields = array( - 'PS_SHOP_NAME' => array( - 'title' => $this->l('Shop name'), - 'hint' => $this->l('Displayed in emails and page titles.'), - 'validation' => 'isGenericName', - 'required' => true, - 'type' => 'text', - 'no_escape' => true, - ), - 'PS_SHOP_EMAIL' => array('title' => $this->l('Shop email'), - 'hint' => $this->l('Displayed in emails sent to customers.'), - 'validation' => 'isEmail', - 'required' => true, - 'type' => 'text' - ), - 'PS_SHOP_DETAILS' => array( - 'title' => $this->l('Registration number'), - 'hint' => $this->l('Shop registration information (e.g. SIRET or RCS).'), - 'validation' => 'isGenericName', - 'type' => 'textarea', - 'cols' => 30, - 'rows' => 5 - ), - 'PS_SHOP_ADDR1' => array( - 'title' => $this->l('Shop address line 1'), - 'validation' => 'isAddress', - 'type' => 'text' - ), - 'PS_SHOP_ADDR2' => array( - 'title' => $this->l('Shop address line 2'), - 'validation' => 'isAddress', - 'type' => 'text' - ), - 'PS_SHOP_CODE' => array( - 'title' => $this->l('Zip/postal code'), - 'validation' => 'isGenericName', - 'type' => 'text' - ), - 'PS_SHOP_CITY' => array( - 'title' => $this->l('City'), - 'validation' => 'isGenericName', - 'type' => 'text' - ), - 'PS_SHOP_COUNTRY_ID' => array( - 'title' => $this->l('Country'), - 'validation' => 'isInt', - 'type' => 'select', - 'list' => $countryList, - 'identifier' => 'id', - 'cast' => 'intval', - 'defaultValue' => (int)$this->context->country->id - ), - 'PS_SHOP_STATE_ID' => array( - 'title' => $this->l('State'), - 'validation' => 'isInt', - 'type' => 'select', - 'list' => $stateList, - 'identifier' => 'id', - 'cast' => 'intval' - ), - 'PS_SHOP_PHONE' => array( - 'title' => $this->l('Phone'), - 'validation' => 'isGenericName', - 'type' => 'text' - ), - 'PS_SHOP_FAX' => array( - 'title' => $this->l('Fax'), - 'validation' => 'isGenericName', - 'type' => 'text' - ), - ); + $formFields = array( + 'PS_SHOP_NAME' => array( + 'title' => $this->l('Shop name'), + 'hint' => $this->l('Displayed in emails and page titles.'), + 'validation' => 'isGenericName', + 'required' => true, + 'type' => 'text', + 'no_escape' => true, + ), + 'PS_SHOP_EMAIL' => array('title' => $this->l('Shop email'), + 'hint' => $this->l('Displayed in emails sent to customers.'), + 'validation' => 'isEmail', + 'required' => true, + 'type' => 'text' + ), + 'PS_SHOP_DETAILS' => array( + 'title' => $this->l('Registration number'), + 'hint' => $this->l('Shop registration information (e.g. SIRET or RCS).'), + 'validation' => 'isGenericName', + 'type' => 'textarea', + 'cols' => 30, + 'rows' => 5 + ), + 'PS_SHOP_ADDR1' => array( + 'title' => $this->l('Shop address line 1'), + 'validation' => 'isAddress', + 'type' => 'text' + ), + 'PS_SHOP_ADDR2' => array( + 'title' => $this->l('Shop address line 2'), + 'validation' => 'isAddress', + 'type' => 'text' + ), + 'PS_SHOP_CODE' => array( + 'title' => $this->l('Zip/postal code'), + 'validation' => 'isGenericName', + 'type' => 'text' + ), + 'PS_SHOP_CITY' => array( + 'title' => $this->l('City'), + 'validation' => 'isGenericName', + 'type' => 'text' + ), + 'PS_SHOP_COUNTRY_ID' => array( + 'title' => $this->l('Country'), + 'validation' => 'isInt', + 'type' => 'select', + 'list' => $countryList, + 'identifier' => 'id', + 'cast' => 'intval', + 'defaultValue' => (int)$this->context->country->id + ), + 'PS_SHOP_STATE_ID' => array( + 'title' => $this->l('State'), + 'validation' => 'isInt', + 'type' => 'select', + 'list' => $stateList, + 'identifier' => 'id', + 'cast' => 'intval' + ), + 'PS_SHOP_PHONE' => array( + 'title' => $this->l('Phone'), + 'validation' => 'isGenericName', + 'type' => 'text' + ), + 'PS_SHOP_FAX' => array( + 'title' => $this->l('Fax'), + 'validation' => 'isGenericName', + 'type' => 'text' + ), + ); - return $formFields; - } + return $formFields; + } - protected function _buildOrderedFieldsShop($formFields) - { - // You cannot do that, because the fields must be sorted for the country you've selected. - // Simple example: the current country is France, where we don't display the state. You choose "US" as a country in the form. The state is not dsplayed at the right place... + protected function _buildOrderedFieldsShop($formFields) + { + // You cannot do that, because the fields must be sorted for the country you've selected. + // Simple example: the current country is France, where we don't display the state. You choose "US" as a country in the form. The state is not dsplayed at the right place... - // $associatedOrderKey = array( - // 'PS_SHOP_NAME' => 'company', - // 'PS_SHOP_ADDR1' => 'address1', - // 'PS_SHOP_ADDR2' => 'address2', - // 'PS_SHOP_CITY' => 'city', - // 'PS_SHOP_STATE_ID' => 'State:name', - // 'PS_SHOP_CODE' => 'postcode', - // 'PS_SHOP_COUNTRY_ID' => 'Country:name', - // 'PS_SHOP_PHONE' => 'phone'); - // $fields = array(); - // $orderedFields = AddressFormat::getOrderedAddressFields(Configuration::get('PS_SHOP_COUNTRY_ID'), false, true); - // foreach ($orderedFields as $lineFields) - // if (($patterns = explode(' ', $lineFields))) - // foreach ($patterns as $pattern) - // if (($key = array_search($pattern, $associatedOrderKey))) - // $fields[$key] = $formFields[$key]; - // foreach ($formFields as $key => $value) - // if (!isset($fields[$key])) - // $fields[$key] = $formFields[$key]; + // $associatedOrderKey = array( + // 'PS_SHOP_NAME' => 'company', + // 'PS_SHOP_ADDR1' => 'address1', + // 'PS_SHOP_ADDR2' => 'address2', + // 'PS_SHOP_CITY' => 'city', + // 'PS_SHOP_STATE_ID' => 'State:name', + // 'PS_SHOP_CODE' => 'postcode', + // 'PS_SHOP_COUNTRY_ID' => 'Country:name', + // 'PS_SHOP_PHONE' => 'phone'); + // $fields = array(); + // $orderedFields = AddressFormat::getOrderedAddressFields(Configuration::get('PS_SHOP_COUNTRY_ID'), false, true); + // foreach ($orderedFields as $lineFields) + // if (($patterns = explode(' ', $lineFields))) + // foreach ($patterns as $pattern) + // if (($key = array_search($pattern, $associatedOrderKey))) + // $fields[$key] = $formFields[$key]; + // foreach ($formFields as $key => $value) + // if (!isset($fields[$key])) + // $fields[$key] = $formFields[$key]; - $fields = $formFields; - $this->fields_options['contact'] = array( - 'title' => $this->l('Contact details'), - 'icon' => 'icon-user', - 'fields' => $fields, - 'submit' => array('title' => $this->l('Save')) - ); - } + $fields = $formFields; + $this->fields_options['contact'] = array( + 'title' => $this->l('Contact details'), + 'icon' => 'icon-user', + 'fields' => $fields, + 'submit' => array('title' => $this->l('Save')) + ); + } - public function beforeUpdateOptions() - { - if (isset($_POST['PS_SHOP_STATE_ID']) && $_POST['PS_SHOP_STATE_ID'] != '0') - { - $sql = 'SELECT `active` FROM `'._DB_PREFIX_.'state` + public function beforeUpdateOptions() + { + if (isset($_POST['PS_SHOP_STATE_ID']) && $_POST['PS_SHOP_STATE_ID'] != '0') { + $sql = 'SELECT `active` FROM `'._DB_PREFIX_.'state` WHERE `id_country` = '.(int)Tools::getValue('PS_SHOP_COUNTRY_ID').' AND `id_state` = '.(int)Tools::getValue('PS_SHOP_STATE_ID'); - $isStateOk = Db::getInstance()->getValue($sql); - if ($isStateOk != 1) - $this->errors[] = Tools::displayError('The specified state is not located in this country.'); - } - } + $isStateOk = Db::getInstance()->getValue($sql); + if ($isStateOk != 1) { + $this->errors[] = Tools::displayError('The specified state is not located in this country.'); + } + } + } - public function updateOptionPsShopCountryId($value) - { - if (!$this->errors && $value) - { - $country = new Country($value, $this->context->language->id); - if ($country->id) - { - Configuration::updateValue('PS_SHOP_COUNTRY_ID', $value); - Configuration::updateValue('PS_SHOP_COUNTRY', pSQL($country->name)); - } - } - } + public function updateOptionPsShopCountryId($value) + { + if (!$this->errors && $value) { + $country = new Country($value, $this->context->language->id); + if ($country->id) { + Configuration::updateValue('PS_SHOP_COUNTRY_ID', $value); + Configuration::updateValue('PS_SHOP_COUNTRY', pSQL($country->name)); + } + } + } - public function updateOptionPsShopStateId($value) - { - if (!$this->errors && $value) - { - $state = new State($value); - if ($state->id) - { - Configuration::updateValue('PS_SHOP_STATE_ID', $value); - Configuration::updateValue('PS_SHOP_STATE', pSQL($state->name)); - } - } - } + public function updateOptionPsShopStateId($value) + { + if (!$this->errors && $value) { + $state = new State($value); + if ($state->id) { + Configuration::updateValue('PS_SHOP_STATE_ID', $value); + Configuration::updateValue('PS_SHOP_STATE', pSQL($state->name)); + } + } + } } diff --git a/controllers/admin/AdminSuppliersController.php b/controllers/admin/AdminSuppliersController.php index f2494b4c..a2ad5f2f 100644 --- a/controllers/admin/AdminSuppliersController.php +++ b/controllers/admin/AdminSuppliersController.php @@ -29,535 +29,524 @@ */ class AdminSuppliersControllerCore extends AdminController { - public $bootstrap = true ; + public $bootstrap = true ; - public function __construct() - { - $this->table = 'supplier'; - $this->className = 'Supplier'; + public function __construct() + { + $this->table = 'supplier'; + $this->className = 'Supplier'; - $this->addRowAction('view'); - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->allow_export = true; + $this->addRowAction('view'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->allow_export = true; - $this->_defaultOrderBy = 'name'; - $this->_defaultOrderWay = 'ASC'; + $this->_defaultOrderBy = 'name'; + $this->_defaultOrderWay = 'ASC'; - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'icon' => 'icon-trash', - 'confirm' => $this->l('Delete selected items?') - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'icon' => 'icon-trash', + 'confirm' => $this->l('Delete selected items?') + ) + ); - $this->_select = 'COUNT(DISTINCT ps.`id_product`) AS products'; - $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'product_supplier` ps ON (a.`id_supplier` = ps.`id_supplier`)'; - $this->_group = 'GROUP BY a.`id_supplier`'; + $this->_select = 'COUNT(DISTINCT ps.`id_product`) AS products'; + $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'product_supplier` ps ON (a.`id_supplier` = ps.`id_supplier`)'; + $this->_group = 'GROUP BY a.`id_supplier`'; - $this->fieldImageSettings = array('name' => 'logo', 'dir' => 'su'); + $this->fieldImageSettings = array('name' => 'logo', 'dir' => 'su'); - $this->fields_list = array( - 'id_supplier' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'logo' => array('title' => $this->l('Logo'), 'align' => 'center', 'image' => 'su', 'orderby' => false, 'search' => false), - 'name' => array('title' => $this->l('Name')), - 'products' => array('title' => $this->l('Number of products'), 'align' => 'right', 'filter_type' => 'int', 'tmpTableFilter' => true), - 'active' => array('title' => $this->l('Enabled'), 'align' => 'center', 'active' => 'status', 'type' => 'bool', 'orderby' => false, 'class' => 'fixed-width-xs') - ); + $this->fields_list = array( + 'id_supplier' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'logo' => array('title' => $this->l('Logo'), 'align' => 'center', 'image' => 'su', 'orderby' => false, 'search' => false), + 'name' => array('title' => $this->l('Name')), + 'products' => array('title' => $this->l('Number of products'), 'align' => 'right', 'filter_type' => 'int', 'tmpTableFilter' => true), + 'active' => array('title' => $this->l('Enabled'), 'align' => 'center', 'active' => 'status', 'type' => 'bool', 'orderby' => false, 'class' => 'fixed-width-xs') + ); - parent::__construct(); - } + parent::__construct(); + } - public function setMedia() - { - parent::setMedia(); - $this->addJqueryUi('ui.widget'); - $this->addJqueryPlugin('tagify'); - } + public function setMedia() + { + parent::setMedia(); + $this->addJqueryUi('ui.widget'); + $this->addJqueryPlugin('tagify'); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_supplier'] = array( - 'href' => self::$currentIndex.'&addsupplier&token='.$this->token, - 'desc' => $this->l('Add new supplier', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_supplier'] = array( + 'href' => self::$currentIndex.'&addsupplier&token='.$this->token, + 'desc' => $this->l('Add new supplier', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderForm() - { - // loads current warehouse - if (!($obj = $this->loadObject(true))) - return; + public function renderForm() + { + // loads current warehouse + if (!($obj = $this->loadObject(true))) { + return; + } - $image = _PS_SUPP_IMG_DIR_.$obj->id.'.jpg'; - $image_url = ImageManager::thumbnail($image, $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, - $this->imageType, true, true); - $image_size = file_exists($image) ? filesize($image) / 1000 : false; + $image = _PS_SUPP_IMG_DIR_.$obj->id.'.jpg'; + $image_url = ImageManager::thumbnail($image, $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, + $this->imageType, true, true); + $image_size = file_exists($image) ? filesize($image) / 1000 : false; - $tmp_addr = new Address(); - $res = $tmp_addr->getFieldsRequiredDatabase(); - $required_fields = array(); - foreach ($res as $row) - $required_fields[(int)$row['id_required_field']] = $row['field_name']; + $tmp_addr = new Address(); + $res = $tmp_addr->getFieldsRequiredDatabase(); + $required_fields = array(); + foreach ($res as $row) { + $required_fields[(int)$row['id_required_field']] = $row['field_name']; + } - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Suppliers'), - 'icon' => 'icon-truck' - ), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'id_address', - ), - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'required' => true, - 'col' => 4, - 'hint' => $this->l('Invalid characters:').' <>;=#{}', - ), - (in_array('company', $required_fields) ? - array( - 'type' => 'text', - 'label' => $this->l('Company'), - 'name' => 'company', - 'display' => in_array('company', $required_fields), - 'required' => in_array('company', $required_fields), - 'maxlength' => 16, - 'col' => 4, - 'hint' => $this->l('Company name for this supplier') - ) - : null - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Description'), - 'name' => 'description', - 'lang' => true, - 'hint' => array( - $this->l('Invalid characters:').' <>;=#{}', - $this->l('Will appear in the list of suppliers.') - ), - 'autoload_rte' => 'rte' //Enable TinyMCE editor for short description - ), - array( - 'type' => 'text', - 'label' => $this->l('Phone'), - 'name' => 'phone', - 'required' => in_array('phone', $required_fields), - 'maxlength' => 16, - 'col' => 4, - 'hint' => $this->l('Phone number for this supplier') - ), - array( - 'type' => 'text', - 'label' => $this->l('Mobile phone'), - 'name' => 'phone_mobile', - 'required' => in_array('phone_mobile', $required_fields), - 'maxlength' => 16, - 'col' => 4, - 'hint' => $this->l('Mobile phone number for this supplier.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Address'), - 'name' => 'address', - 'maxlength' => 128, - 'col' => 6, - 'required' => true - ), - array( - 'type' => 'text', - 'label' => $this->l('Address').' (2)', - 'name' => 'address2', - 'required' => in_array('address2', $required_fields), - 'col' => 6, - 'maxlength' => 128, - ), - array( - 'type' => 'text', - 'label' => $this->l('Zip/postal code'), - 'name' => 'postcode', - 'required' => in_array('postcode', $required_fields), - 'maxlength' => 12, - 'col' => 2, - ), - array( - 'type' => 'text', - 'label' => $this->l('City'), - 'name' => 'city', - 'maxlength' => 32, - 'col' => 4, - 'required' => true, - ), - array( - 'type' => 'select', - 'label' => $this->l('Country'), - 'name' => 'id_country', - 'required' => true, - 'col' => 4, - 'default_value' => (int)$this->context->country->id, - 'options' => array( - 'query' => Country::getCountries($this->context->language->id, false), - 'id' => 'id_country', - 'name' => 'name', - ), - ), - array( - 'type' => 'select', - 'label' => $this->l('State'), - 'name' => 'id_state', - 'col' => 4, - 'options' => array( - 'id' => 'id_state', - 'query' => array(), - 'name' => 'name' - ) - ), - array( - 'type' => 'file', - 'label' => $this->l('Logo'), - 'name' => 'logo', - 'display_image' => true, - 'image' => $image_url ? $image_url : false, - 'size' => $image_size, - 'hint' => $this->l('Upload a supplier logo from your computer.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Meta title'), - 'name' => 'meta_title', - 'lang' => true, - 'col' => 4, - 'hint' => $this->l('Forbidden characters:').' <>;=#{}' - ), - array( - 'type' => 'text', - 'label' => $this->l('Meta description'), - 'name' => 'meta_description', - 'lang' => true, - 'col' => 6, - 'hint' => $this->l('Forbidden characters:').' <>;=#{}' - ), - array( - 'type' => 'tags', - 'label' => $this->l('Meta keywords'), - 'name' => 'meta_keywords', - 'lang' => true, - 'col' => 6, - 'hint' => array( - $this->l('To add "tags" click in the field, write something and then press "Enter".'), - $this->l('Forbidden characters:').' <>;=#{}' - ) - ), - array( - 'type' => 'switch', - 'label' => $this->l('Enable'), - 'name' => 'active', - 'required' => false, - 'class' => 't', - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ) - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Suppliers'), + 'icon' => 'icon-truck' + ), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'id_address', + ), + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'required' => true, + 'col' => 4, + 'hint' => $this->l('Invalid characters:').' <>;=#{}', + ), + (in_array('company', $required_fields) ? + array( + 'type' => 'text', + 'label' => $this->l('Company'), + 'name' => 'company', + 'display' => in_array('company', $required_fields), + 'required' => in_array('company', $required_fields), + 'maxlength' => 16, + 'col' => 4, + 'hint' => $this->l('Company name for this supplier') + ) + : null + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Description'), + 'name' => 'description', + 'lang' => true, + 'hint' => array( + $this->l('Invalid characters:').' <>;=#{}', + $this->l('Will appear in the list of suppliers.') + ), + 'autoload_rte' => 'rte' //Enable TinyMCE editor for short description + ), + array( + 'type' => 'text', + 'label' => $this->l('Phone'), + 'name' => 'phone', + 'required' => in_array('phone', $required_fields), + 'maxlength' => 16, + 'col' => 4, + 'hint' => $this->l('Phone number for this supplier') + ), + array( + 'type' => 'text', + 'label' => $this->l('Mobile phone'), + 'name' => 'phone_mobile', + 'required' => in_array('phone_mobile', $required_fields), + 'maxlength' => 16, + 'col' => 4, + 'hint' => $this->l('Mobile phone number for this supplier.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Address'), + 'name' => 'address', + 'maxlength' => 128, + 'col' => 6, + 'required' => true + ), + array( + 'type' => 'text', + 'label' => $this->l('Address').' (2)', + 'name' => 'address2', + 'required' => in_array('address2', $required_fields), + 'col' => 6, + 'maxlength' => 128, + ), + array( + 'type' => 'text', + 'label' => $this->l('Zip/postal code'), + 'name' => 'postcode', + 'required' => in_array('postcode', $required_fields), + 'maxlength' => 12, + 'col' => 2, + ), + array( + 'type' => 'text', + 'label' => $this->l('City'), + 'name' => 'city', + 'maxlength' => 32, + 'col' => 4, + 'required' => true, + ), + array( + 'type' => 'select', + 'label' => $this->l('Country'), + 'name' => 'id_country', + 'required' => true, + 'col' => 4, + 'default_value' => (int)$this->context->country->id, + 'options' => array( + 'query' => Country::getCountries($this->context->language->id, false), + 'id' => 'id_country', + 'name' => 'name', + ), + ), + array( + 'type' => 'select', + 'label' => $this->l('State'), + 'name' => 'id_state', + 'col' => 4, + 'options' => array( + 'id' => 'id_state', + 'query' => array(), + 'name' => 'name' + ) + ), + array( + 'type' => 'file', + 'label' => $this->l('Logo'), + 'name' => 'logo', + 'display_image' => true, + 'image' => $image_url ? $image_url : false, + 'size' => $image_size, + 'hint' => $this->l('Upload a supplier logo from your computer.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Meta title'), + 'name' => 'meta_title', + 'lang' => true, + 'col' => 4, + 'hint' => $this->l('Forbidden characters:').' <>;=#{}' + ), + array( + 'type' => 'text', + 'label' => $this->l('Meta description'), + 'name' => 'meta_description', + 'lang' => true, + 'col' => 6, + 'hint' => $this->l('Forbidden characters:').' <>;=#{}' + ), + array( + 'type' => 'tags', + 'label' => $this->l('Meta keywords'), + 'name' => 'meta_keywords', + 'lang' => true, + 'col' => 6, + 'hint' => array( + $this->l('To add "tags" click in the field, write something and then press "Enter".'), + $this->l('Forbidden characters:').' <>;=#{}' + ) + ), + array( + 'type' => 'switch', + 'label' => $this->l('Enable'), + 'name' => 'active', + 'required' => false, + 'class' => 't', + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ) + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - // loads current address for this supplier - if possible - $address = null; - if (isset($obj->id)) - { - $id_address = Address::getAddressIdBySupplierId($obj->id); + // loads current address for this supplier - if possible + $address = null; + if (isset($obj->id)) { + $id_address = Address::getAddressIdBySupplierId($obj->id); - if ($id_address > 0) - $address = new Address((int)$id_address); - } + if ($id_address > 0) { + $address = new Address((int)$id_address); + } + } - // force specific fields values (address) - if ($address != null) - { - $this->fields_value = array( - 'id_address' => $address->id, - 'phone' => $address->phone, - 'phone_mobile' => $address->phone_mobile, - 'address' => $address->address1, - 'address2' => $address->address2, - 'postcode' => $address->postcode, - 'city' => $address->city, - 'id_country' => $address->id_country, - 'id_state' => $address->id_state, - ); - } - else - $this->fields_value = array( - 'id_address' => 0, - 'id_country' => Configuration::get('PS_COUNTRY_DEFAULT') - ); + // force specific fields values (address) + if ($address != null) { + $this->fields_value = array( + 'id_address' => $address->id, + 'phone' => $address->phone, + 'phone_mobile' => $address->phone_mobile, + 'address' => $address->address1, + 'address2' => $address->address2, + 'postcode' => $address->postcode, + 'city' => $address->city, + 'id_country' => $address->id_country, + 'id_state' => $address->id_state, + ); + } else { + $this->fields_value = array( + 'id_address' => 0, + 'id_country' => Configuration::get('PS_COUNTRY_DEFAULT') + ); + } - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - return parent::renderForm(); - } + return parent::renderForm(); + } - /** - * AdminController::initToolbar() override - * @see AdminController::initToolbar() - * - */ - public function initToolbar() - { - parent::initToolbar(); - $this->addPageHeaderToolBarModulesListButton(); + /** + * AdminController::initToolbar() override + * @see AdminController::initToolbar() + * + */ + public function initToolbar() + { + parent::initToolbar(); + $this->addPageHeaderToolBarModulesListButton(); - if (empty($this->display) && $this->can_import) - $this->toolbar_btn['import'] = array( - 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=suppliers', - 'desc' => $this->l('Import') - ); - } + if (empty($this->display) && $this->can_import) { + $this->toolbar_btn['import'] = array( + 'href' => $this->context->link->getAdminLink('AdminImport', true).'&import_type=suppliers', + 'desc' => $this->l('Import') + ); + } + } - public function renderView() - { - $this->initTabModuleList(); - $this->toolbar_title = $this->object->name; - $products = $this->object->getProductsLite($this->context->language->id); - $total_product = count($products); + public function renderView() + { + $this->initTabModuleList(); + $this->toolbar_title = $this->object->name; + $products = $this->object->getProductsLite($this->context->language->id); + $total_product = count($products); - for ($i = 0; $i < $total_product; $i++) - { - $products[$i] = new Product($products[$i]['id_product'], false, $this->context->language->id); - $products[$i]->loadStockData(); - // Build attributes combinations - $combinations = $products[$i]->getAttributeCombinations($this->context->language->id); - foreach ($combinations as $k => $combination) - { - $comb_infos = Supplier::getProductInformationsBySupplier($this->object->id, - $products[$i]->id, - $combination['id_product_attribute']); - $comb_array[$combination['id_product_attribute']]['product_supplier_reference'] = $comb_infos['product_supplier_reference']; - $comb_array[$combination['id_product_attribute']]['product_supplier_price_te'] = Tools::displayPrice($comb_infos['product_supplier_price_te'], new Currency($comb_infos['id_currency'])); - $comb_array[$combination['id_product_attribute']]['reference'] = $combination['reference']; - $comb_array[$combination['id_product_attribute']]['ean13'] = $combination['ean13']; - $comb_array[$combination['id_product_attribute']]['upc'] = $combination['upc']; - $comb_array[$combination['id_product_attribute']]['quantity'] = $combination['quantity']; - $comb_array[$combination['id_product_attribute']]['attributes'][] = array( - $combination['group_name'], - $combination['attribute_name'], - $combination['id_attribute'] - ); - } + for ($i = 0; $i < $total_product; $i++) { + $products[$i] = new Product($products[$i]['id_product'], false, $this->context->language->id); + $products[$i]->loadStockData(); + // Build attributes combinations + $combinations = $products[$i]->getAttributeCombinations($this->context->language->id); + foreach ($combinations as $k => $combination) { + $comb_infos = Supplier::getProductInformationsBySupplier($this->object->id, + $products[$i]->id, + $combination['id_product_attribute']); + $comb_array[$combination['id_product_attribute']]['product_supplier_reference'] = $comb_infos['product_supplier_reference']; + $comb_array[$combination['id_product_attribute']]['product_supplier_price_te'] = Tools::displayPrice($comb_infos['product_supplier_price_te'], new Currency($comb_infos['id_currency'])); + $comb_array[$combination['id_product_attribute']]['reference'] = $combination['reference']; + $comb_array[$combination['id_product_attribute']]['ean13'] = $combination['ean13']; + $comb_array[$combination['id_product_attribute']]['upc'] = $combination['upc']; + $comb_array[$combination['id_product_attribute']]['quantity'] = $combination['quantity']; + $comb_array[$combination['id_product_attribute']]['attributes'][] = array( + $combination['group_name'], + $combination['attribute_name'], + $combination['id_attribute'] + ); + } - if (isset($comb_array)) - { - foreach ($comb_array as $key => $product_attribute) - { - $list = ''; - foreach ($product_attribute['attributes'] as $attribute) - $list .= $attribute[0].' - '.$attribute[1].', '; - $comb_array[$key]['attributes'] = rtrim($list, ', '); - } - isset($comb_array) ? $products[$i]->combination = $comb_array : ''; - unset($comb_array); - } - else - { - $product_infos = Supplier::getProductInformationsBySupplier($this->object->id, - $products[$i]->id, - 0); - $products[$i]->product_supplier_reference = $product_infos['product_supplier_reference']; - $products[$i]->product_supplier_price_te = Tools::displayPrice($product_infos['product_supplier_price_te'], new Currency($product_infos['id_currency'])); - } - } + if (isset($comb_array)) { + foreach ($comb_array as $key => $product_attribute) { + $list = ''; + foreach ($product_attribute['attributes'] as $attribute) { + $list .= $attribute[0].' - '.$attribute[1].', '; + } + $comb_array[$key]['attributes'] = rtrim($list, ', '); + } + isset($comb_array) ? $products[$i]->combination = $comb_array : ''; + unset($comb_array); + } else { + $product_infos = Supplier::getProductInformationsBySupplier($this->object->id, + $products[$i]->id, + 0); + $products[$i]->product_supplier_reference = $product_infos['product_supplier_reference']; + $products[$i]->product_supplier_price_te = Tools::displayPrice($product_infos['product_supplier_price_te'], new Currency($product_infos['id_currency'])); + } + } - $this->tpl_view_vars = array( - 'supplier' => $this->object, - 'products' => $products, - 'stock_management' => Configuration::get('PS_STOCK_MANAGEMENT'), - 'shopContext' => Shop::getContext(), - ); + $this->tpl_view_vars = array( + 'supplier' => $this->object, + 'products' => $products, + 'stock_management' => Configuration::get('PS_STOCK_MANAGEMENT'), + 'shopContext' => Shop::getContext(), + ); - return parent::renderView(); - } + return parent::renderView(); + } - protected function afterImageUpload() - { - $return = true; - $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); + protected function afterImageUpload() + { + $return = true; + $generate_hight_dpi_images = (bool)Configuration::get('PS_HIGHT_DPI'); - /* Generate image with differents size */ - if (($id_supplier = (int)Tools::getValue('id_supplier')) && - isset($_FILES) && count($_FILES) && file_exists(_PS_SUPP_IMG_DIR_.$id_supplier.'.jpg')) - { - $images_types = ImageType::getImagesTypes('suppliers'); - foreach ($images_types as $k => $image_type) - { - $file = _PS_SUPP_IMG_DIR_.$id_supplier.'.jpg'; - if (!ImageManager::resize($file, _PS_SUPP_IMG_DIR_.$id_supplier.'-'.stripslashes($image_type['name']).'.jpg', (int)$image_type['width'], (int)$image_type['height'])) - $return = false; + /* Generate image with differents size */ + if (($id_supplier = (int)Tools::getValue('id_supplier')) && + isset($_FILES) && count($_FILES) && file_exists(_PS_SUPP_IMG_DIR_.$id_supplier.'.jpg')) { + $images_types = ImageType::getImagesTypes('suppliers'); + foreach ($images_types as $k => $image_type) { + $file = _PS_SUPP_IMG_DIR_.$id_supplier.'.jpg'; + if (!ImageManager::resize($file, _PS_SUPP_IMG_DIR_.$id_supplier.'-'.stripslashes($image_type['name']).'.jpg', (int)$image_type['width'], (int)$image_type['height'])) { + $return = false; + } - if ($generate_hight_dpi_images) - if (!ImageManager::resize($file, _PS_SUPP_IMG_DIR_.$id_supplier.'-'.stripslashes($image_type['name']).'2x.jpg', (int)$image_type['width']*2, (int)$image_type['height']*2)) - $return = false; - } + if ($generate_hight_dpi_images) { + if (!ImageManager::resize($file, _PS_SUPP_IMG_DIR_.$id_supplier.'-'.stripslashes($image_type['name']).'2x.jpg', (int)$image_type['width']*2, (int)$image_type['height']*2)) { + $return = false; + } + } + } - $current_logo_file = _PS_TMP_IMG_DIR_.'supplier_mini_'.$id_supplier.'_'.$this->context->shop->id.'.jpg'; + $current_logo_file = _PS_TMP_IMG_DIR_.'supplier_mini_'.$id_supplier.'_'.$this->context->shop->id.'.jpg'; - if (file_exists($current_logo_file)) - unlink($current_logo_file); - } - return $return; - } + if (file_exists($current_logo_file)) { + unlink($current_logo_file); + } + } + return $return; + } - /** - * AdminController::postProcess() override - * @see AdminController::postProcess() - */ - public function postProcess() - { - // checks access - if (Tools::isSubmit('submitAdd'.$this->table) && !($this->tabAccess['add'] === '1')) - { - $this->errors[] = Tools::displayError('You do not have permission to add suppliers.'); - return parent::postProcess(); - } + /** + * AdminController::postProcess() override + * @see AdminController::postProcess() + */ + public function postProcess() + { + // checks access + if (Tools::isSubmit('submitAdd'.$this->table) && !($this->tabAccess['add'] === '1')) { + $this->errors[] = Tools::displayError('You do not have permission to add suppliers.'); + return parent::postProcess(); + } - if (Tools::isSubmit('submitAdd'.$this->table)) - { - if (Tools::isSubmit('id_supplier') && !($obj = $this->loadObject(true))) - return; + if (Tools::isSubmit('submitAdd'.$this->table)) { + if (Tools::isSubmit('id_supplier') && !($obj = $this->loadObject(true))) { + return; + } - // updates/creates address if it does not exist - if (Tools::isSubmit('id_address') && (int)Tools::getValue('id_address') > 0) - $address = new Address((int)Tools::getValue('id_address')); // updates address - else - $address = new Address(); // creates address + // updates/creates address if it does not exist + if (Tools::isSubmit('id_address') && (int)Tools::getValue('id_address') > 0) { + $address = new Address((int)Tools::getValue('id_address')); + } // updates address + else { + $address = new Address(); + } // creates address - $address->alias = Tools::getValue('name', null); - $address->lastname = 'supplier'; // skip problem with numeric characters in supplier name - $address->firstname = 'supplier'; // skip problem with numeric characters in supplier name - $address->address1 = Tools::getValue('address', null); - $address->address2 = Tools::getValue('address2', null); - $address->postcode = Tools::getValue('postcode', null); - $address->phone = Tools::getValue('phone', null); - $address->phone_mobile = Tools::getValue('phone_mobile', null); - $address->id_country = Tools::getValue('id_country', null); - $address->id_state = Tools::getValue('id_state', null); - $address->city = Tools::getValue('city', null); + $address->alias = Tools::getValue('name', null); + $address->lastname = 'supplier'; // skip problem with numeric characters in supplier name + $address->firstname = 'supplier'; // skip problem with numeric characters in supplier name + $address->address1 = Tools::getValue('address', null); + $address->address2 = Tools::getValue('address2', null); + $address->postcode = Tools::getValue('postcode', null); + $address->phone = Tools::getValue('phone', null); + $address->phone_mobile = Tools::getValue('phone_mobile', null); + $address->id_country = Tools::getValue('id_country', null); + $address->id_state = Tools::getValue('id_state', null); + $address->city = Tools::getValue('city', null); - $validation = $address->validateController(); + $validation = $address->validateController(); - // checks address validity - if (count($validation) > 0) - { - foreach ($validation as $item) - $this->errors[] = $item; - $this->errors[] = Tools::displayError('The address is not correct. Please make sure all of the required fields are completed.'); - } - else - { - if (Tools::isSubmit('id_address') && Tools::getValue('id_address') > 0) - $address->update(); - else - { - $address->save(); - $_POST['id_address'] = $address->id; - } - } - return parent::postProcess(); - } - elseif (Tools::isSubmit('delete'.$this->table)) - { - if (!($obj = $this->loadObject(true))) - return; - elseif (SupplyOrder::supplierHasPendingOrders($obj->id)) - $this->errors[] = $this->l('It is not possible to delete a supplier if there are pending supplier orders.'); - else - { - //delete all product_supplier linked to this supplier - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'product_supplier` WHERE `id_supplier`='.(int)$obj->id); + // checks address validity + if (count($validation) > 0) { + foreach ($validation as $item) { + $this->errors[] = $item; + } + $this->errors[] = Tools::displayError('The address is not correct. Please make sure all of the required fields are completed.'); + } else { + if (Tools::isSubmit('id_address') && Tools::getValue('id_address') > 0) { + $address->update(); + } else { + $address->save(); + $_POST['id_address'] = $address->id; + } + } + return parent::postProcess(); + } elseif (Tools::isSubmit('delete'.$this->table)) { + if (!($obj = $this->loadObject(true))) { + return; + } elseif (SupplyOrder::supplierHasPendingOrders($obj->id)) { + $this->errors[] = $this->l('It is not possible to delete a supplier if there are pending supplier orders.'); + } else { + //delete all product_supplier linked to this supplier + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'product_supplier` WHERE `id_supplier`='.(int)$obj->id); - $id_address = Address::getAddressIdBySupplierId($obj->id); - $address = new Address($id_address); - if (Validate::isLoadedObject($address)) - { - $address->deleted = 1; - $address->save(); - } - return parent::postProcess(); - } - } - else - return parent::postProcess(); - } + $id_address = Address::getAddressIdBySupplierId($obj->id); + $address = new Address($id_address); + if (Validate::isLoadedObject($address)) { + $address->deleted = 1; + $address->save(); + } + return parent::postProcess(); + } + } else { + return parent::postProcess(); + } + } - /** - * @see AdminController::afterAdd() - * - * @param Supplier $object - * - * @return bool - */ - protected function afterAdd($object) - { - $id_address = (int)$_POST['id_address']; - $address = new Address($id_address); - if (Validate::isLoadedObject($address)) - { - $address->id_supplier = $object->id; - $address->save(); - } + /** + * @see AdminController::afterAdd() + * + * @param Supplier $object + * + * @return bool + */ + protected function afterAdd($object) + { + $id_address = (int)$_POST['id_address']; + $address = new Address($id_address); + if (Validate::isLoadedObject($address)) { + $address->id_supplier = $object->id; + $address->save(); + } - return true; - } - - /** - * @see AdminController::afterUpdate() - * - * @param Supplier $object - * - * @return bool - */ - protected function afterUpdate($object) - { - $id_address = (int)$_POST['id_address']; - $address = new Address($id_address); - if (Validate::isLoadedObject($address)) - { - if ($address->id_supplier != $object->id) - { - $address->id_supplier = $object->id; - $address->save(); - } - } - return true; - } + return true; + } + /** + * @see AdminController::afterUpdate() + * + * @param Supplier $object + * + * @return bool + */ + protected function afterUpdate($object) + { + $id_address = (int)$_POST['id_address']; + $address = new Address($id_address); + if (Validate::isLoadedObject($address)) { + if ($address->id_supplier != $object->id) { + $address->id_supplier = $object->id; + $address->save(); + } + } + return true; + } } diff --git a/controllers/admin/AdminSupplyOrdersController.php b/controllers/admin/AdminSupplyOrdersController.php index 6358d418..56d3bc96 100644 --- a/controllers/admin/AdminSupplyOrdersController.php +++ b/controllers/admin/AdminSupplyOrdersController.php @@ -30,445 +30,441 @@ */ class AdminSupplyOrdersControllerCore extends AdminController { - /** - * @var array List of warehouses - */ - protected $warehouses; + /** + * @var array List of warehouses + */ + protected $warehouses; - public function __construct() - { - $this->bootstrap = true; - $this->context = Context::getContext(); - $this->table = 'supply_order'; + public function __construct() + { + $this->bootstrap = true; + $this->context = Context::getContext(); + $this->table = 'supply_order'; - $this->className = 'SupplyOrder'; - $this->identifier = 'id_supply_order'; - $this->lang = false; - $this->is_template_list = false; - $this->multishop_context = Shop::CONTEXT_ALL; + $this->className = 'SupplyOrder'; + $this->identifier = 'id_supply_order'; + $this->lang = false; + $this->is_template_list = false; + $this->multishop_context = Shop::CONTEXT_ALL; - $this->addRowAction('updatereceipt'); - $this->addRowAction('changestate'); - $this->addRowAction('edit'); - $this->addRowAction('view'); - $this->addRowAction('details'); - $this->list_no_link = true; + $this->addRowAction('updatereceipt'); + $this->addRowAction('changestate'); + $this->addRowAction('edit'); + $this->addRowAction('view'); + $this->addRowAction('details'); + $this->list_no_link = true; - $this->fields_list = array( - 'reference' => array( - 'title' => $this->l('Reference'), - 'havingFilter' => true - ), - 'supplier' => array( - 'title' => $this->l('Supplier'), - 'filter_key' => 's!name' - ), - 'warehouse' => array( - 'title' => $this->l('Warehouse'), - 'filter_key' => 'w!name' - ), - 'state' => array( - 'title' => $this->l('Status'), - 'filter_key' => 'stl!name', - 'color' => 'color', - ), - 'date_add' => array( - 'title' => $this->l('Creation'), - 'align' => 'left', - 'type' => 'date', - 'havingFilter' => true, - 'filter_key' => 'a!date_add' - ), - 'date_upd' => array( - 'title' => $this->l('Last modification'), - 'align' => 'left', - 'type' => 'date', - 'havingFilter' => true, - 'filter_key' => 'a!date_upd' - ), - 'date_delivery_expected' => array( - 'title' => $this->l('Delivery (expected)'), - 'align' => 'left', - 'type' => 'date', - 'havingFilter' => true, - 'filter_key' => 'a!date_delivery_expected' - ), - 'id_export' => array( - 'title' => $this->l('Export'), - 'callback' => 'printExportIcons', - 'orderby' => false, - 'search' => false - ), - ); + $this->fields_list = array( + 'reference' => array( + 'title' => $this->l('Reference'), + 'havingFilter' => true + ), + 'supplier' => array( + 'title' => $this->l('Supplier'), + 'filter_key' => 's!name' + ), + 'warehouse' => array( + 'title' => $this->l('Warehouse'), + 'filter_key' => 'w!name' + ), + 'state' => array( + 'title' => $this->l('Status'), + 'filter_key' => 'stl!name', + 'color' => 'color', + ), + 'date_add' => array( + 'title' => $this->l('Creation'), + 'align' => 'left', + 'type' => 'date', + 'havingFilter' => true, + 'filter_key' => 'a!date_add' + ), + 'date_upd' => array( + 'title' => $this->l('Last modification'), + 'align' => 'left', + 'type' => 'date', + 'havingFilter' => true, + 'filter_key' => 'a!date_upd' + ), + 'date_delivery_expected' => array( + 'title' => $this->l('Delivery (expected)'), + 'align' => 'left', + 'type' => 'date', + 'havingFilter' => true, + 'filter_key' => 'a!date_delivery_expected' + ), + 'id_export' => array( + 'title' => $this->l('Export'), + 'callback' => 'printExportIcons', + 'orderby' => false, + 'search' => false + ), + ); - // gets the list of warehouses available - $this->warehouses = Warehouse::getWarehouses(true); - // gets the final list of warehouses - array_unshift($this->warehouses, array('id_warehouse' => -1, 'name' => $this->l('All Warehouses'))); + // gets the list of warehouses available + $this->warehouses = Warehouse::getWarehouses(true); + // gets the final list of warehouses + array_unshift($this->warehouses, array('id_warehouse' => -1, 'name' => $this->l('All Warehouses'))); - parent::__construct(); - } + parent::__construct(); + } - /** - * AdminController::init() override - * @see AdminController::init() - */ - public function init() - { - if (Tools::isSubmit('submitFilterorders')) - $this->list_id = 'orders'; - elseif (Tools::isSubmit('submitFiltertemplates')) - $this->list_id = 'templates'; + /** + * AdminController::init() override + * @see AdminController::init() + */ + public function init() + { + if (Tools::isSubmit('submitFilterorders')) { + $this->list_id = 'orders'; + } elseif (Tools::isSubmit('submitFiltertemplates')) { + $this->list_id = 'templates'; + } - parent::init(); + parent::init(); - if (Tools::isSubmit('addsupply_order') || - Tools::isSubmit('submitAddsupply_order') || - (Tools::isSubmit('updatesupply_order') && Tools::isSubmit('id_supply_order'))) - { - // override table, lang, className and identifier for the current controller - $this->table = 'supply_order'; - $this->className = 'SupplyOrder'; - $this->identifier = 'id_supply_order'; - $this->lang = false; + if (Tools::isSubmit('addsupply_order') || + Tools::isSubmit('submitAddsupply_order') || + (Tools::isSubmit('updatesupply_order') && Tools::isSubmit('id_supply_order'))) { + // override table, lang, className and identifier for the current controller + $this->table = 'supply_order'; + $this->className = 'SupplyOrder'; + $this->identifier = 'id_supply_order'; + $this->lang = false; - $this->action = 'new'; - $this->display = 'add'; + $this->action = 'new'; + $this->display = 'add'; - if (Tools::isSubmit('updatesupply_order')) - if ($this->tabAccess['edit'] === '1') - $this->display = 'edit'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } + if (Tools::isSubmit('updatesupply_order')) { + if ($this->tabAccess['edit'] === '1') { + $this->display = 'edit'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + } - if (Tools::isSubmit('update_receipt') && Tools::isSubmit('id_supply_order')) - { - // change the display type in order to add specific actions to - $this->display = 'update_receipt'; + if (Tools::isSubmit('update_receipt') && Tools::isSubmit('id_supply_order')) { + // change the display type in order to add specific actions to + $this->display = 'update_receipt'; - // display correct toolBar - $this->initToolbar(); - } - } + // display correct toolBar + $this->initToolbar(); + } + } - public function initPageHeaderToolbar() - { - if ($this->display == 'details') - $this->page_header_toolbar_btn['back'] = array( - 'href' => Context::getContext()->link->getAdminLink('AdminSupplyOrders'), - 'desc' => $this->l('Back to list', null, null, false), - 'icon' => 'process-icon-back' - ); - elseif (empty($this->display)) - { - $this->page_header_toolbar_btn['new_supply_order'] = array( - 'href' => self::$currentIndex.'&addsupply_order&token='.$this->token, - 'desc' => $this->l('Add new supply order', null, null, false), - 'icon' => 'process-icon-new' - ); - $this->page_header_toolbar_btn['new_supply_order_template'] = array( - 'href' => self::$currentIndex.'&addsupply_order&mod=template&token='.$this->token, - 'desc' => $this->l('Add new supply order template', null, null, false), - 'icon' => 'process-icon-new' - ); - } + public function initPageHeaderToolbar() + { + if ($this->display == 'details') { + $this->page_header_toolbar_btn['back'] = array( + 'href' => Context::getContext()->link->getAdminLink('AdminSupplyOrders'), + 'desc' => $this->l('Back to list', null, null, false), + 'icon' => 'process-icon-back' + ); + } elseif (empty($this->display)) { + $this->page_header_toolbar_btn['new_supply_order'] = array( + 'href' => self::$currentIndex.'&addsupply_order&token='.$this->token, + 'desc' => $this->l('Add new supply order', null, null, false), + 'icon' => 'process-icon-new' + ); + $this->page_header_toolbar_btn['new_supply_order_template'] = array( + 'href' => self::$currentIndex.'&addsupply_order&mod=template&token='.$this->token, + 'desc' => $this->l('Add new supply order template', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - /** - * AdminController::renderForm() override - * @see AdminController::renderForm() - */ - public function renderForm() - { - if (Tools::isSubmit('addsupply_order') || - Tools::isSubmit('updatesupply_order') || - Tools::isSubmit('submitAddsupply_order') || - Tools::isSubmit('submitUpdatesupply_order')) - { + /** + * AdminController::renderForm() override + * @see AdminController::renderForm() + */ + public function renderForm() + { + if (Tools::isSubmit('addsupply_order') || + Tools::isSubmit('updatesupply_order') || + Tools::isSubmit('submitAddsupply_order') || + Tools::isSubmit('submitUpdatesupply_order')) { + if (Tools::isSubmit('addsupply_order') || Tools::isSubmit('submitAddsupply_order')) { + $this->toolbar_title = $this->l('Stock: Create a new supply order'); + } - if (Tools::isSubmit('addsupply_order') || Tools::isSubmit('submitAddsupply_order')) - $this->toolbar_title = $this->l('Stock: Create a new supply order'); + $update = false; + if (Tools::isSubmit('updatesupply_order') || Tools::isSubmit('submitUpdatesupply_order')) { + $this->toolbar_title = $this->l('Stock: Manage supply orders'); + $update = true; + } - $update = false; - if (Tools::isSubmit('updatesupply_order') || Tools::isSubmit('submitUpdatesupply_order')) - { - $this->toolbar_title = $this->l('Stock: Manage supply orders'); - $update = true; - } + if (Tools::isSubmit('mod') && Tools::getValue('mod') === 'template' || $this->object->is_template) { + $this->toolbar_title .= ' ('.$this->l('template').')'; + } - if (Tools::isSubmit('mod') && Tools::getValue('mod') === 'template' || $this->object->is_template) - $this->toolbar_title .= ' ('.$this->l('template').')'; + $this->addJqueryUI('ui.datepicker'); - $this->addJqueryUI('ui.datepicker'); + //get warehouses list + $warehouses = Warehouse::getWarehouses(true); - //get warehouses list - $warehouses = Warehouse::getWarehouses(true); + // displays warning if there are no warehouses + if (!$warehouses) { + $this->displayWarning($this->l('You must have at least one warehouse. See Stock/Warehouses')); + } - // displays warning if there are no warehouses - if (!$warehouses) - $this->displayWarning($this->l('You must have at least one warehouse. See Stock/Warehouses')); + //get currencies list + $currencies = Currency::getCurrencies(false, true, true); - //get currencies list - $currencies = Currency::getCurrencies(false, true, true); + //get suppliers list + $suppliers = array_unique(Supplier::getSuppliers(), SORT_REGULAR); - //get suppliers list - $suppliers = array_unique(Supplier::getSuppliers(), SORT_REGULAR); + //get languages list + $languages = Language::getLanguages(true); - //get languages list - $languages = Language::getLanguages(true); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Order information'), + 'icon' => 'icon-pencil' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Reference'), + 'name' => 'reference', + 'required' => true, + 'hint' => $this->l('The reference number for your order.'), + ), + array( + 'type' => 'select', + 'label' => $this->l('Supplier'), + 'name' => 'id_supplier', + 'required' => true, + 'options' => array( + 'query' => $suppliers, + 'id' => 'id_supplier', + 'name' => 'name' + ), + 'hint' => array( + $this->l('Select the supplier you\'ll be purchasing from.'), + $this->l('Warning: All products already added to the order will be removed.') + ) + ), + array( + 'type' => 'select', + 'label' => $this->l('Warehouse'), + 'name' => 'id_warehouse', + 'required' => true, + 'options' => array( + 'query' => $warehouses, + 'id' => 'id_warehouse', + 'name' => 'name' + ), + 'hint' => $this->l('Which warehouse will the order be sent to?'), + ), + array( + 'type' => 'select', + 'label' => $this->l('Currency'), + 'name' => 'id_currency', + 'required' => true, + 'options' => array( + 'query' => $currencies, + 'id' => 'id_currency', + 'name' => 'name' + ), + 'hint' => array( + $this->l('The currency of the order.'), + $this->l('Warning: All products already added to the order will be removed.') + ) + ), + array( + 'type' => 'select', + 'label' => $this->l('Order Language'), + 'name' => 'id_lang', + 'required' => true, + 'options' => array( + 'query' => $languages, + 'id' => 'id_lang', + 'name' => 'name' + ), + 'hint' => $this->l('The language of the order.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Global discount percentage'), + 'name' => 'discount_rate', + 'required' => false, + 'hint' => $this->l('This is the global discount percentage for the order.'), + ), + array( + 'type' => 'text', + 'label' => $this->l('Automatically load products'), + 'name' => 'load_products', + 'required' => false, + 'hint' => array( + $this->l('This will reset the order.'), + $this->l('If a value specified, each of your current product (from the selected supplier and warehouse) with a quantity lower than or equal to this value will be loaded. This means that PrestaShop will pre-fill this order with the products that are low on quantity.'), + ), + ), + ), + 'submit' => (!$update ? array('title' => $this->l('Save order')) : array()), + 'buttons' => (!$update ? + array( + 'save-and-stay' => array( + 'title' => $this->l('Save order and stay'), + 'name' => 'submitAddsupply_orderAndStay', + 'type' => 'submit', + 'class' => 'btn btn-default pull-right', + 'icon' => 'process-icon-save' + ) + ) : array()) + ); - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Order information'), - 'icon' => 'icon-pencil' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Reference'), - 'name' => 'reference', - 'required' => true, - 'hint' => $this->l('The reference number for your order.'), - ), - array( - 'type' => 'select', - 'label' => $this->l('Supplier'), - 'name' => 'id_supplier', - 'required' => true, - 'options' => array( - 'query' => $suppliers, - 'id' => 'id_supplier', - 'name' => 'name' - ), - 'hint' => array( - $this->l('Select the supplier you\'ll be purchasing from.'), - $this->l('Warning: All products already added to the order will be removed.') - ) - ), - array( - 'type' => 'select', - 'label' => $this->l('Warehouse'), - 'name' => 'id_warehouse', - 'required' => true, - 'options' => array( - 'query' => $warehouses, - 'id' => 'id_warehouse', - 'name' => 'name' - ), - 'hint' => $this->l('Which warehouse will the order be sent to?'), - ), - array( - 'type' => 'select', - 'label' => $this->l('Currency'), - 'name' => 'id_currency', - 'required' => true, - 'options' => array( - 'query' => $currencies, - 'id' => 'id_currency', - 'name' => 'name' - ), - 'hint' => array( - $this->l('The currency of the order.'), - $this->l('Warning: All products already added to the order will be removed.') - ) - ), - array( - 'type' => 'select', - 'label' => $this->l('Order Language'), - 'name' => 'id_lang', - 'required' => true, - 'options' => array( - 'query' => $languages, - 'id' => 'id_lang', - 'name' => 'name' - ), - 'hint' => $this->l('The language of the order.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Global discount percentage'), - 'name' => 'discount_rate', - 'required' => false, - 'hint' => $this->l('This is the global discount percentage for the order.'), - ), - array( - 'type' => 'text', - 'label' => $this->l('Automatically load products'), - 'name' => 'load_products', - 'required' => false, - 'hint' => array( - $this->l('This will reset the order.'), - $this->l('If a value specified, each of your current product (from the selected supplier and warehouse) with a quantity lower than or equal to this value will be loaded. This means that PrestaShop will pre-fill this order with the products that are low on quantity.'), - ), - ), - ), - 'submit' => (!$update ? array('title' => $this->l('Save order')) : array()), - 'buttons' => (!$update ? - array( - 'save-and-stay' => array( - 'title' => $this->l('Save order and stay'), - 'name' => 'submitAddsupply_orderAndStay', - 'type' => 'submit', - 'class' => 'btn btn-default pull-right', - 'icon' => 'process-icon-save' - ) - ) : array()) - ); + if (Tools::isSubmit('mod') && Tools::getValue('mod') === 'template' || $this->object->is_template) { + $this->fields_form['input'][] = array( + 'type' => 'hidden', + 'name' => 'is_template' + ); - if (Tools::isSubmit('mod') && Tools::getValue('mod') === 'template' || $this->object->is_template) - { + $this->fields_form['input'][] = array( + 'type' => 'hidden', + 'name' => 'date_delivery_expected', + ); + } else { + $this->fields_form['input'][] = array( + 'type' => 'date', + 'label' => $this->l('Expected delivery date'), + 'name' => 'date_delivery_expected', + 'required' => true, + 'desc' => $this->l('The expected delivery date for this order is...'), + ); + } - $this->fields_form['input'][] = array( - 'type' => 'hidden', - 'name' => 'is_template' - ); + //specific discount display + if (isset($this->object->discount_rate)) { + $this->object->discount_rate = Tools::ps_round($this->object->discount_rate, 4); + } - $this->fields_form['input'][] = array( - 'type' => 'hidden', - 'name' => 'date_delivery_expected', - ); - } - else - { - $this->fields_form['input'][] = array( - 'type' => 'date', - 'label' => $this->l('Expected delivery date'), - 'name' => 'date_delivery_expected', - 'required' => true, - 'desc' => $this->l('The expected delivery date for this order is...'), - ); - } + //specific date display - //specific discount display - if (isset($this->object->discount_rate)) - $this->object->discount_rate = Tools::ps_round($this->object->discount_rate, 4); + if (isset($this->object->date_delivery_expected)) { + $date = explode(' ', $this->object->date_delivery_expected); + if ($date) { + $this->object->date_delivery_expected = $date[0]; + } + } - //specific date display + $this->displayInformation( + $this->l('If you wish to order products, they have to be available for the specified supplier/warehouse.') + .' '. + $this->l('See Catalog/Products/[Your Product]/Suppliers & Warehouses.') + .'<br />'. + $this->l('Changing the currency or the supplier will reset the order.') + .'<br />' + .'<br />'. + $this->l('Please note that you can only order from one supplier at a time.') + ); + return parent::renderForm(); + } + } - if (isset($this->object->date_delivery_expected)) - { - $date = explode(' ', $this->object->date_delivery_expected); - if ($date) - $this->object->date_delivery_expected = $date[0]; - } + /** + * AdminController::getList() override + * @see AdminController::getList() + * + * @param int $id_lang + * @param string|null $order_by + * @param string|null $order_way + * @param int $start + * @param int|null $limit + * @param int|bool $id_lang_shop + * + * @throws PrestaShopException + */ + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + if (Tools::isSubmit('csv_orders') || Tools::isSubmit('csv_orders_details') || Tools::isSubmit('csv_order_details')) { + $limit = false; + } - $this->displayInformation( - $this->l('If you wish to order products, they have to be available for the specified supplier/warehouse.') - .' '. - $this->l('See Catalog/Products/[Your Product]/Suppliers & Warehouses.') - .'<br />'. - $this->l('Changing the currency or the supplier will reset the order.') - .'<br />' - .'<br />'. - $this->l('Please note that you can only order from one supplier at a time.') - ); - return parent::renderForm(); - } + // defines button specific for non-template supply orders + if (!$this->is_template_list && $this->display != 'details') { + // adds export csv buttons + $this->toolbar_btn['export-csv-orders'] = array( + 'short' => 'Export Orders', + 'href' => $this->context->link->getAdminLink('AdminSupplyOrders').'&csv_orders&id_warehouse='.$this->getCurrentWarehouse(), + 'desc' => $this->l('Export Orders (CSV)'), + 'class' => 'process-icon-export' + ); - } + $this->toolbar_btn['export-csv-details'] = array( + 'short' => 'Export Orders Details', + 'href' => $this->context->link->getAdminLink('AdminSupplyOrders').'&csv_orders_details&id_warehouse='.$this->getCurrentWarehouse(), + 'desc' => $this->l('Export Orders Details (CSV)'), + 'class' => 'process-icon-export' + ); - /** - * AdminController::getList() override - * @see AdminController::getList() - * - * @param int $id_lang - * @param string|null $order_by - * @param string|null $order_way - * @param int $start - * @param int|null $limit - * @param int|bool $id_lang_shop - * - * @throws PrestaShopException - */ - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - if (Tools::isSubmit('csv_orders') || Tools::isSubmit('csv_orders_details') || Tools::isSubmit('csv_order_details')) - $limit = false; + unset($this->toolbar_btn['new']); + if ($this->tabAccess['add'] === '1') { + $this->toolbar_btn['new'] = array( + 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token, + 'desc' => $this->l('Add New') + ); + } + } - // defines button specific for non-template supply orders - if (!$this->is_template_list && $this->display != 'details') - { - // adds export csv buttons - $this->toolbar_btn['export-csv-orders'] = array( - 'short' => 'Export Orders', - 'href' => $this->context->link->getAdminLink('AdminSupplyOrders').'&csv_orders&id_warehouse='.$this->getCurrentWarehouse(), - 'desc' => $this->l('Export Orders (CSV)'), - 'class' => 'process-icon-export' - ); + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - $this->toolbar_btn['export-csv-details'] = array( - 'short' => 'Export Orders Details', - 'href' => $this->context->link->getAdminLink('AdminSupplyOrders').'&csv_orders_details&id_warehouse='.$this->getCurrentWarehouse(), - 'desc' => $this->l('Export Orders Details (CSV)'), - 'class' => 'process-icon-export' - ); + // adds colors depending on the receipt state + if ($order_by == 'quantity_expected') { + $nb_items = count($this->_list); + for ($i = 0; $i < $nb_items; ++$i) { + $item = &$this->_list[$i]; + if ($item['quantity_received'] == $item['quantity_expected']) { + $item['color'] = '#00bb35'; + } elseif ($item['quantity_received'] > $item['quantity_expected']) { + $item['color'] = '#fb0008'; + } + } + } - unset($this->toolbar_btn['new']); - if ($this->tabAccess['add'] === '1') - { - $this->toolbar_btn['new'] = array( - 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token, - 'desc' => $this->l('Add New') - ); - } - } + // actions filters on supply orders list + if ($this->table == 'supply_order') { + $nb_items = count($this->_list); - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + for ($i = 0; $i < $nb_items; $i++) { + // if the current state doesn't allow order edit, skip the edit action + if ($this->_list[$i]['editable'] == 0) { + $this->addRowActionSkipList('edit', $this->_list[$i]['id_supply_order']); + } + if ($this->_list[$i]['enclosed'] == 1 && $this->_list[$i]['receipt_state'] == 0) { + $this->addRowActionSkipList('changestate', $this->_list[$i]['id_supply_order']); + } + if (1 != $this->_list[$i]['pending_receipt']) { + $this->addRowActionSkipList('updatereceipt', $this->_list[$i]['id_supply_order']); + } + } + } + } - // adds colors depending on the receipt state - if ($order_by == 'quantity_expected') - { - $nb_items = count($this->_list); - for ($i = 0; $i < $nb_items; ++$i) - { - $item = &$this->_list[$i]; - if ($item['quantity_received'] == $item['quantity_expected']) - $item['color'] = '#00bb35'; - elseif ($item['quantity_received'] > $item['quantity_expected']) - $item['color'] = '#fb0008'; - } - } + /** + * AdminController::renderList() override + * @see AdminController::renderList() + */ + public function renderList() + { + $this->displayInformation($this->l('This interface allows you to manage supply orders.').'<br />'); + $this->displayInformation($this->l('You can create pre-filled order templates, from which you can build actual orders much quicker.').'<br />'); - // actions filters on supply orders list - if ($this->table == 'supply_order') - { - $nb_items = count($this->_list); + if (count($this->warehouses) <= 1) { + $this->displayWarning($this->l('You must choose at least one warehouse before creating supply orders. For more information, see Stock/Warehouses.')); + } - for ($i = 0; $i < $nb_items; $i++) - { - // if the current state doesn't allow order edit, skip the edit action - if ($this->_list[$i]['editable'] == 0) - $this->addRowActionSkipList('edit', $this->_list[$i]['id_supply_order']); - if ($this->_list[$i]['enclosed'] == 1 && $this->_list[$i]['receipt_state'] == 0) - $this->addRowActionSkipList('changestate', $this->_list[$i]['id_supply_order']); - if (1 != $this->_list[$i]['pending_receipt']) - $this->addRowActionSkipList('updatereceipt', $this->_list[$i]['id_supply_order']); - } - } - } + // assigns warehouses + $this->tpl_list_vars['warehouses'] = $this->warehouses; + $this->tpl_list_vars['current_warehouse'] = $this->getCurrentWarehouse(); + $this->tpl_list_vars['filter_status'] = $this->getFilterStatus(); - /** - * AdminController::renderList() override - * @see AdminController::renderList() - */ - public function renderList() - { - $this->displayInformation($this->l('This interface allows you to manage supply orders.').'<br />'); - $this->displayInformation($this->l('You can create pre-filled order templates, from which you can build actual orders much quicker.').'<br />'); - - if (count($this->warehouses) <= 1) - $this->displayWarning($this->l('You must choose at least one warehouse before creating supply orders. For more information, see Stock/Warehouses.')); - - // assigns warehouses - $this->tpl_list_vars['warehouses'] = $this->warehouses; - $this->tpl_list_vars['current_warehouse'] = $this->getCurrentWarehouse(); - $this->tpl_list_vars['filter_status'] = $this->getFilterStatus(); - - // overrides query - $this->_select = ' + // overrides query + $this->_select = ' s.name AS supplier, w.name AS warehouse, stl.name AS state, @@ -480,7 +476,7 @@ class AdminSupplyOrdersControllerCore extends AdminController st.color AS color, a.id_supply_order as id_export'; - $this->_join = ' + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'supply_order_state_lang` stl ON ( a.id_supply_order_state = stl.id_supply_order_state @@ -490,369 +486,361 @@ class AdminSupplyOrdersControllerCore extends AdminController LEFT JOIN `'._DB_PREFIX_.'supplier` s ON a.id_supplier = s.id_supplier LEFT JOIN `'._DB_PREFIX_.'warehouse` w ON (w.id_warehouse = a.id_warehouse)'; - $this->_where = ' AND a.is_template = 0'; + $this->_where = ' AND a.is_template = 0'; - if ($this->getCurrentWarehouse() != -1) - { - $this->_where .= ' AND a.id_warehouse = '.$this->getCurrentWarehouse(); - self::$currentIndex .= '&id_warehouse='.(int)$this->getCurrentWarehouse(); - } + if ($this->getCurrentWarehouse() != -1) { + $this->_where .= ' AND a.id_warehouse = '.$this->getCurrentWarehouse(); + self::$currentIndex .= '&id_warehouse='.(int)$this->getCurrentWarehouse(); + } - if ($this->getFilterStatus() != 0) - { - $this->_where .= ' AND st.enclosed != 1'; - self::$currentIndex .= '&filter_status=on'; - } + if ($this->getFilterStatus() != 0) { + $this->_where .= ' AND st.enclosed != 1'; + self::$currentIndex .= '&filter_status=on'; + } - $this->list_id = 'orders'; - $this->_filterHaving = null; + $this->list_id = 'orders'; + $this->_filterHaving = null; - if (Tools::isSubmit('submitFilter'.$this->list_id) - || $this->context->cookie->{'submitFilter'.$this->list_id} !== false - || Tools::getValue($this->list_id.'Orderby') - || Tools::getValue($this->list_id.'Orderway')) - { - $this->filter = true; - parent::processFilter(); - } + if (Tools::isSubmit('submitFilter'.$this->list_id) + || $this->context->cookie->{'submitFilter'.$this->list_id} !== false + || Tools::getValue($this->list_id.'Orderby') + || Tools::getValue($this->list_id.'Orderway')) { + $this->filter = true; + parent::processFilter(); + } - $first_list = parent::renderList(); + $first_list = parent::renderList(); - if (Tools::isSubmit('csv_orders') || Tools::isSubmit('csv_orders_details') || Tools::isSubmit('csv_order_details')) - { - if (count($this->_list) > 0) - { - $this->renderCSV(); - die; - } - else - $this->displayWarning($this->l('There is nothing to export as a CSV file.')); - } + if (Tools::isSubmit('csv_orders') || Tools::isSubmit('csv_orders_details') || Tools::isSubmit('csv_order_details')) { + if (count($this->_list) > 0) { + $this->renderCSV(); + die; + } else { + $this->displayWarning($this->l('There is nothing to export as a CSV file.')); + } + } - // second list : templates - $second_list = null; - $this->is_template_list = true; - unset($this->tpl_list_vars['warehouses']); - unset($this->tpl_list_vars['current_warehouse']); - unset($this->tpl_list_vars['filter_status']); + // second list : templates + $second_list = null; + $this->is_template_list = true; + unset($this->tpl_list_vars['warehouses']); + unset($this->tpl_list_vars['current_warehouse']); + unset($this->tpl_list_vars['filter_status']); - // unsets actions - $this->actions = array(); - unset($this->toolbar_btn['export-csv-orders']); - unset($this->toolbar_btn['export-csv-details']); - // adds actions - $this->addRowAction('view'); - $this->addRowAction('edit'); - $this->addRowAction('createsupplyorder'); - $this->addRowAction('delete'); - // unsets some fields - unset($this->fields_list['state'], - $this->fields_list['date_upd'], - $this->fields_list['id_pdf'], - $this->fields_list['date_delivery_expected'], - $this->fields_list['id_export']); + // unsets actions + $this->actions = array(); + unset($this->toolbar_btn['export-csv-orders']); + unset($this->toolbar_btn['export-csv-details']); + // adds actions + $this->addRowAction('view'); + $this->addRowAction('edit'); + $this->addRowAction('createsupplyorder'); + $this->addRowAction('delete'); + // unsets some fields + unset($this->fields_list['state'], + $this->fields_list['date_upd'], + $this->fields_list['id_pdf'], + $this->fields_list['date_delivery_expected'], + $this->fields_list['id_export']); - // $this->fields_list['date_add']['align'] = 'left'; + // $this->fields_list['date_add']['align'] = 'left'; - // adds filter, to gets only templates - unset($this->_where); - $this->_where = ' AND a.is_template = 1'; + // adds filter, to gets only templates + unset($this->_where); + $this->_where = ' AND a.is_template = 1'; - if ($this->getCurrentWarehouse() != -1) - $this->_where .= ' AND a.id_warehouse = '.$this->getCurrentWarehouse(); + if ($this->getCurrentWarehouse() != -1) { + $this->_where .= ' AND a.id_warehouse = '.$this->getCurrentWarehouse(); + } - // re-defines toolbar & buttons - $this->toolbar_title = $this->l('Stock: Supply order templates'); - $this->initToolbar(); - unset($this->toolbar_btn['new']); - $this->toolbar_btn['new'] = array( - 'href' => self::$currentIndex.'&add'.$this->table.'&mod=template&token='.$this->token, - 'desc' => $this->l('Add new template'), - 'imgclass' => 'new_1', - 'class' => 'process-icon-new' - ); + // re-defines toolbar & buttons + $this->toolbar_title = $this->l('Stock: Supply order templates'); + $this->initToolbar(); + unset($this->toolbar_btn['new']); + $this->toolbar_btn['new'] = array( + 'href' => self::$currentIndex.'&add'.$this->table.'&mod=template&token='.$this->token, + 'desc' => $this->l('Add new template'), + 'imgclass' => 'new_1', + 'class' => 'process-icon-new' + ); - $this->list_id = 'templates'; - $this->_filterHaving = null; + $this->list_id = 'templates'; + $this->_filterHaving = null; - if (Tools::isSubmit('submitFilter'.$this->list_id) - || $this->context->cookie->{'submitFilter'.$this->list_id} !== false - || Tools::getValue($this->list_id.'Orderby') - || Tools::getValue($this->list_id.'Orderway')) - { - $this->filter = true; - parent::processFilter(); - } - // inits list - $second_list = parent::renderList(); + if (Tools::isSubmit('submitFilter'.$this->list_id) + || $this->context->cookie->{'submitFilter'.$this->list_id} !== false + || Tools::getValue($this->list_id.'Orderby') + || Tools::getValue($this->list_id.'Orderway')) { + $this->filter = true; + parent::processFilter(); + } + // inits list + $second_list = parent::renderList(); - return $first_list.$second_list; - } + return $first_list.$second_list; + } - /** - * Init the content of change state action - */ - public function initChangeStateContent() - { - $id_supply_order = (int)Tools::getValue('id_supply_order', 0); + /** + * Init the content of change state action + */ + public function initChangeStateContent() + { + $id_supply_order = (int)Tools::getValue('id_supply_order', 0); - if ($id_supply_order <= 0) - { - $this->errors[] = Tools::displayError('The specified supply order is not valid'); - return parent::initContent(); - } + if ($id_supply_order <= 0) { + $this->errors[] = Tools::displayError('The specified supply order is not valid'); + return parent::initContent(); + } - $supply_order = new SupplyOrder($id_supply_order); - $supply_order_state = new SupplyOrderState($supply_order->id_supply_order_state); + $supply_order = new SupplyOrder($id_supply_order); + $supply_order_state = new SupplyOrderState($supply_order->id_supply_order_state); - if (!Validate::isLoadedObject($supply_order) || !Validate::isLoadedObject($supply_order_state)) - { - $this->errors[] = Tools::displayError('The specified supply order is not valid'); - return parent::initContent(); - } + if (!Validate::isLoadedObject($supply_order) || !Validate::isLoadedObject($supply_order_state)) { + $this->errors[] = Tools::displayError('The specified supply order is not valid'); + return parent::initContent(); + } - // change the display type in order to add specific actions to - $this->display = 'update_order_state'; - // overrides parent::initContent(); - $this->initToolbar(); - $this->initPageHeaderToolbar(); + // change the display type in order to add specific actions to + $this->display = 'update_order_state'; + // overrides parent::initContent(); + $this->initToolbar(); + $this->initPageHeaderToolbar(); - // given the current state, loads available states - $states = SupplyOrderState::getSupplyOrderStates($supply_order->id_supply_order_state); + // given the current state, loads available states + $states = SupplyOrderState::getSupplyOrderStates($supply_order->id_supply_order_state); - // gets the state that are not allowed - $allowed_states = array(); - foreach ($states as &$state) - { - $allowed_states[] = $state['id_supply_order_state']; - $state['allowed'] = 1; - } - $not_allowed_states = SupplyOrderState::getStates($allowed_states); + // gets the state that are not allowed + $allowed_states = array(); + foreach ($states as &$state) { + $allowed_states[] = $state['id_supply_order_state']; + $state['allowed'] = 1; + } + $not_allowed_states = SupplyOrderState::getStates($allowed_states); - // generates the final list of states - $index = count($allowed_states); - foreach ($not_allowed_states as &$not_allowed_state) - { - $not_allowed_state['allowed'] = 0; - $states[$index] = $not_allowed_state; - ++$index; - } + // generates the final list of states + $index = count($allowed_states); + foreach ($not_allowed_states as &$not_allowed_state) { + $not_allowed_state['allowed'] = 0; + $states[$index] = $not_allowed_state; + ++$index; + } - // loads languages - $this->getlanguages(); + // loads languages + $this->getlanguages(); - // defines the fields of the form to display - $this->fields_form[0]['form'] = array( - 'legend' => array( - 'title' => $this->l('Supply order status'), - 'icon' => 'icon-pencil' - ), - 'input' => array(), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); + // defines the fields of the form to display + $this->fields_form[0]['form'] = array( + 'legend' => array( + 'title' => $this->l('Supply order status'), + 'icon' => 'icon-pencil' + ), + 'input' => array(), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); - $this->displayInformation($this->l('Be careful when changing status. Some of those changes cannot be canceled. ')); + $this->displayInformation($this->l('Be careful when changing status. Some of those changes cannot be canceled. ')); - // sets up the helper - $helper = new HelperForm(); - $helper->submit_action = 'submitChangestate'; - $helper->currentIndex = self::$currentIndex; - $helper->toolbar_btn = $this->toolbar_btn; - $helper->toolbar_scroll = false; - $helper->token = $this->token; - $helper->id = null; // no display standard hidden field in the form - $helper->languages = $this->_languages; - $helper->default_form_language = $this->default_form_language; - $helper->allow_employee_form_lang = $this->allow_employee_form_lang; - $helper->title = sprintf($this->l('Stock: Change supply order status #%s'), $supply_order->reference); - $helper->show_cancel_button = true; - $helper->override_folder = 'supply_orders_change_state/'; + // sets up the helper + $helper = new HelperForm(); + $helper->submit_action = 'submitChangestate'; + $helper->currentIndex = self::$currentIndex; + $helper->toolbar_btn = $this->toolbar_btn; + $helper->toolbar_scroll = false; + $helper->token = $this->token; + $helper->id = null; // no display standard hidden field in the form + $helper->languages = $this->_languages; + $helper->default_form_language = $this->default_form_language; + $helper->allow_employee_form_lang = $this->allow_employee_form_lang; + $helper->title = sprintf($this->l('Stock: Change supply order status #%s'), $supply_order->reference); + $helper->show_cancel_button = true; + $helper->override_folder = 'supply_orders_change_state/'; - // assigns our content - $helper->tpl_vars['show_change_state_form'] = true; - $helper->tpl_vars['supply_order_state'] = $supply_order_state; - $helper->tpl_vars['supply_order'] = $supply_order; - $helper->tpl_vars['supply_order_states'] = $states; + // assigns our content + $helper->tpl_vars['show_change_state_form'] = true; + $helper->tpl_vars['supply_order_state'] = $supply_order_state; + $helper->tpl_vars['supply_order'] = $supply_order; + $helper->tpl_vars['supply_order_states'] = $states; - // generates the form to display - $content = $helper->generateForm($this->fields_form); + // generates the form to display + $content = $helper->generateForm($this->fields_form); - $this->context->smarty->assign(array( - 'content' => $content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } + $this->context->smarty->assign(array( + 'content' => $content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } - /** - * Init the content of change state action - */ - public function initUpdateSupplyOrderContent() - { - $this->addJqueryPlugin('autocomplete'); + /** + * Init the content of change state action + */ + public function initUpdateSupplyOrderContent() + { + $this->addJqueryPlugin('autocomplete'); - // load supply order - $id_supply_order = (int)Tools::getValue('id_supply_order', null); + // load supply order + $id_supply_order = (int)Tools::getValue('id_supply_order', null); - if ($id_supply_order != null) - { - $supply_order = new SupplyOrder($id_supply_order); + if ($id_supply_order != null) { + $supply_order = new SupplyOrder($id_supply_order); - $currency = new Currency($supply_order->id_currency); + $currency = new Currency($supply_order->id_currency); - if (Validate::isLoadedObject($supply_order)) - { - // load products of this order - $products = $supply_order->getEntries(); - $product_ids = array(); + if (Validate::isLoadedObject($supply_order)) { + // load products of this order + $products = $supply_order->getEntries(); + $product_ids = array(); - if (isset($this->order_products_errors) && is_array($this->order_products_errors)) - { - //for each product in error array, check if it is in products array, and remove it to conserve last user values - foreach ($this->order_products_errors as $pe) - foreach ($products as $index_p => $p) - if (($p['id_product'] == $pe['id_product']) && ($p['id_product_attribute'] == $pe['id_product_attribute'])) - unset($products[$index_p]); + if (isset($this->order_products_errors) && is_array($this->order_products_errors)) { + //for each product in error array, check if it is in products array, and remove it to conserve last user values + foreach ($this->order_products_errors as $pe) { + foreach ($products as $index_p => $p) { + if (($p['id_product'] == $pe['id_product']) && ($p['id_product_attribute'] == $pe['id_product_attribute'])) { + unset($products[$index_p]); + } + } + } - // then merge arrays - $products = array_merge($this->order_products_errors, $products); - } + // then merge arrays + $products = array_merge($this->order_products_errors, $products); + } - foreach ($products as &$item) - { - // calculate md5 checksum on each product for use in tpl - $item['checksum'] = md5(_COOKIE_KEY_.$item['id_product'].'_'.$item['id_product_attribute']); - $item['unit_price_te'] = Tools::ps_round($item['unit_price_te'], 2); + foreach ($products as &$item) { + // calculate md5 checksum on each product for use in tpl + $item['checksum'] = md5(_COOKIE_KEY_.$item['id_product'].'_'.$item['id_product_attribute']); + $item['unit_price_te'] = Tools::ps_round($item['unit_price_te'], 2); - // add id to ids list - $product_ids[] = $item['id_product'].'_'.$item['id_product_attribute']; - } + // add id to ids list + $product_ids[] = $item['id_product'].'_'.$item['id_product_attribute']; + } - $this->tpl_form_vars['products_list'] = $products; - $this->tpl_form_vars['product_ids'] = implode($product_ids, '|'); - $this->tpl_form_vars['product_ids_to_delete'] = ''; - $this->tpl_form_vars['supplier_id'] = $supply_order->id_supplier; - $this->tpl_form_vars['currency'] = $currency; - } - } + $this->tpl_form_vars['products_list'] = $products; + $this->tpl_form_vars['product_ids'] = implode($product_ids, '|'); + $this->tpl_form_vars['product_ids_to_delete'] = ''; + $this->tpl_form_vars['supplier_id'] = $supply_order->id_supplier; + $this->tpl_form_vars['currency'] = $currency; + } + } - $this->tpl_form_vars['content'] = $this->content; - $this->tpl_form_vars['token'] = $this->token; - $this->tpl_form_vars['show_product_management_form'] = true; + $this->tpl_form_vars['content'] = $this->content; + $this->tpl_form_vars['token'] = $this->token; + $this->tpl_form_vars['show_product_management_form'] = true; - // call parent initcontent to render standard form content - parent::initContent(); - } + // call parent initcontent to render standard form content + parent::initContent(); + } - /** - * Inits the content of 'update_receipt' action - * Called in initContent() - * @see AdminSuppliersOrders::initContent() - */ - public function initUpdateReceiptContent() - { - $id_supply_order = (int)Tools::getValue('id_supply_order', null); + /** + * Inits the content of 'update_receipt' action + * Called in initContent() + * @see AdminSuppliersOrders::initContent() + */ + public function initUpdateReceiptContent() + { + $id_supply_order = (int)Tools::getValue('id_supply_order', null); - // if there is no order to fetch - if (null == $id_supply_order) - return parent::initContent(); + // if there is no order to fetch + if (null == $id_supply_order) { + return parent::initContent(); + } - $supply_order = new SupplyOrder($id_supply_order); + $supply_order = new SupplyOrder($id_supply_order); - // if it's not a valid order - if (!Validate::isLoadedObject($supply_order)) - return parent::initContent(); + // if it's not a valid order + if (!Validate::isLoadedObject($supply_order)) { + return parent::initContent(); + } - $this->initPageHeaderToolbar(); + $this->initPageHeaderToolbar(); - // re-defines fields_list - $this->fields_list = array( - 'supplier_reference' => array( - 'title' => $this->l('Supplier reference'), - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - 'reference' => array( - 'title' => $this->l('Reference'), - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - 'ean13' => array( - 'title' => $this->l('EAN-13 or JAN barcode'), - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - 'upc' => array( - 'title' => $this->l('UPC barcode'), - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - 'name' => array( - 'title' => $this->l('Name'), - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - 'quantity_received_today' => array( - 'title' => $this->l('Quantity received today?'), - 'type' => 'editable', - 'orderby' => false, - 'filter' => false, - 'search' => false, - 'hint' => $this->l('The quantity of supplies that you received today.'), - ), - 'quantity_received' => array( - 'title' => $this->l('Quantity received'), - 'orderby' => false, - 'filter' => false, - 'search' => false, - 'badge_danger' => true, - 'badge_success' => true, - 'hint' => $this->l('The quantity of supplies that you received so far (today and the days before, if it applies).'), - ), - 'quantity_expected' => array( - 'title' => $this->l('Quantity expected'), - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - 'quantity_left' => array( - 'title' => $this->l('Quantity left'), - 'orderby' => false, - 'filter' => false, - 'search' => false, - 'hint' => $this->l('The quantity of supplies left to receive for this order.'), - ) - ); + // re-defines fields_list + $this->fields_list = array( + 'supplier_reference' => array( + 'title' => $this->l('Supplier reference'), + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + 'reference' => array( + 'title' => $this->l('Reference'), + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + 'ean13' => array( + 'title' => $this->l('EAN-13 or JAN barcode'), + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + 'upc' => array( + 'title' => $this->l('UPC barcode'), + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + 'name' => array( + 'title' => $this->l('Name'), + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + 'quantity_received_today' => array( + 'title' => $this->l('Quantity received today?'), + 'type' => 'editable', + 'orderby' => false, + 'filter' => false, + 'search' => false, + 'hint' => $this->l('The quantity of supplies that you received today.'), + ), + 'quantity_received' => array( + 'title' => $this->l('Quantity received'), + 'orderby' => false, + 'filter' => false, + 'search' => false, + 'badge_danger' => true, + 'badge_success' => true, + 'hint' => $this->l('The quantity of supplies that you received so far (today and the days before, if it applies).'), + ), + 'quantity_expected' => array( + 'title' => $this->l('Quantity expected'), + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + 'quantity_left' => array( + 'title' => $this->l('Quantity left'), + 'orderby' => false, + 'filter' => false, + 'search' => false, + 'hint' => $this->l('The quantity of supplies left to receive for this order.'), + ) + ); - // attributes override - unset($this->_select, $this->_join, $this->_where, $this->_orderBy, $this->_orderWay, $this->_group, $this->_filterHaving, $this->_filter); - $this->table = 'supply_order_detail'; - $this->identifier = 'id_supply_order_detail'; - $this->className = 'SupplyOrderDetail'; - $this->list_simple_header = false; - $this->list_no_link = true; - $this->colorOnBackground = true; - $this->row_hover = false; - $this->bulk_actions = array('Update' => array('text' => $this->l('Update selected'), 'confirm' => $this->l('Update selected items?'))); - $this->addRowAction('details'); + // attributes override + unset($this->_select, $this->_join, $this->_where, $this->_orderBy, $this->_orderWay, $this->_group, $this->_filterHaving, $this->_filter); + $this->table = 'supply_order_detail'; + $this->identifier = 'id_supply_order_detail'; + $this->className = 'SupplyOrderDetail'; + $this->list_simple_header = false; + $this->list_no_link = true; + $this->colorOnBackground = true; + $this->row_hover = false; + $this->bulk_actions = array('Update' => array('text' => $this->l('Update selected'), 'confirm' => $this->l('Update selected items?'))); + $this->addRowAction('details'); - // sets toolbar title with order reference - $this->toolbar_title = sprintf($this->l('Receipt of products for supply order #%s'), $supply_order->reference); + // sets toolbar title with order reference + $this->toolbar_title = sprintf($this->l('Receipt of products for supply order #%s'), $supply_order->reference); - $this->lang = false; - $lang_id = (int)$this->context->language->id; //employee lang + $this->lang = false; + $lang_id = (int)$this->context->language->id; //employee lang - // gets values corresponding to fields_list - $this->_select = ' + // gets values corresponding to fields_list + $this->_select = ' a.id_supply_order_detail as id, a.quantity_received as quantity_received, a.quantity_expected as quantity_expected, @@ -861,676 +849,664 @@ class AdminSupplyOrdersControllerCore extends AdminController IF (a.quantity_expected = a.quantity_received, 1, 0) badge_success, IF (a.quantity_expected > a.quantity_received, 1, 0) badge_danger'; - $this->_where = 'AND a.`id_supply_order` = '.(int)$id_supply_order; - - $this->_group = 'GROUP BY a.id_supply_order_detail'; - - // gets the list ordered by price desc, without limit - $this->getList($lang_id, 'quantity_expected', 'DESC', 0, Tools::getValue('supply_order_pagination'), false); - - // defines action for POST - $action = '&id_supply_order='.$id_supply_order.'&update_receipt=1'; - - // unsets some buttons - unset($this->toolbar_btn['export-csv-orders']); - unset($this->toolbar_btn['export-csv-details']); - unset($this->toolbar_btn['new']); - - $this->toolbar_btn['back'] = array( - 'desc' => $this->l('Back'), - 'href' => $this->context->link->getAdminLink('AdminSupplyOrders') - ); - - // renders list - $helper = new HelperList(); - $this->setHelperDisplay($helper); - $helper->actions = array('details'); - $helper->force_show_bulk_actions = true; - $helper->override_folder = 'supply_orders_receipt_history/'; - $helper->toolbar_btn = $this->toolbar_btn; - $helper->list_id = 'supply_order_detail'; - - $helper->ajax_params = array( - 'display_product_history' => 1, - ); - - $helper->currentIndex = self::$currentIndex.$action; - - // display these global order informations - $this->displayInformation($this->l('This interface allows you to update the quantities of this ongoing order.').'<br />'); - $this->displayInformation($this->l('Be careful! Once you update, you cannot go back unless you add new negative stock movements.').'<br />'); - $this->displayInformation($this->l('A green line means that you\'ve received exactly the quantity you expected. A red line means that you\'ve received more than expected.').'<br />'); - - // generates content - $content = $helper->generateList($this->_list, $this->fields_list); - - // assigns var - $this->context->smarty->assign(array( - 'content' => $content, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } - - /** - * AdminController::initContent() override - * @see AdminController::initContent() - */ - public function initContent() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = - $this->l('You need to activate the Advanced Stock Management feature prior to using this feature.'); - return false; - } - // Manage the add stock form - if (Tools::isSubmit('changestate')) - $this->initChangeStateContent(); - elseif (Tools::isSubmit('update_receipt') && Tools::isSubmit('id_supply_order') && !Tools::isSubmit('detailssupply_order_detail')) - $this->initUpdateReceiptContent(); - elseif (Tools::isSubmit('viewsupply_order') && Tools::isSubmit('id_supply_order')) - { - $this->action = 'view'; - $this->display = 'view'; - parent::initContent(); - } - elseif (Tools::isSubmit('updatesupply_order')) - $this->initUpdateSupplyOrderContent(); - else - { - if (Tools::isSubmit('detailssupply_order_detail')) - { - $this->action = 'details'; - $this->display = 'details'; - } - parent::initContent(); - } - } - - /** - * Ths method manage associated products to the order when updating it - */ - public function manageOrderProducts() - { - // load supply order - $id_supply_order = (int)Tools::getValue('id_supply_order', null); - $products_already_in_order = array(); - - if ($id_supply_order != null) - { - $supply_order = new SupplyOrder($id_supply_order); - - if (Validate::isLoadedObject($supply_order)) - { - // tests if the supplier or currency have changed in the supply order - $new_supplier_id = (int)Tools::getValue('id_supplier'); - $new_currency_id = (int)Tools::getValue('id_currency'); - - if (($new_supplier_id != $supply_order->id_supplier) || - ($new_currency_id != $supply_order->id_currency)) - { - // resets all products in this order - $supply_order->resetProducts(); - } - else - { - $products_already_in_order = $supply_order->getEntries(); - $currency = new Currency($supply_order->id_ref_currency); - - // gets all product ids to manage - $product_ids_str = Tools::getValue('product_ids', null); - $product_ids = explode('|', $product_ids_str); - $product_ids_to_delete_str = Tools::getValue('product_ids_to_delete', null); - $product_ids_to_delete = array_unique(explode('|', $product_ids_to_delete_str)); - - //delete products that are not managed anymore - foreach ($products_already_in_order as $paio) - { - $product_ok = false; - - foreach ($product_ids_to_delete as $id) - { - $id_check = $paio['id_product'].'_'.$paio['id_product_attribute']; - if ($id_check == $id) - $product_ok = true; - } - - if ($product_ok === true) - { - $entry = new SupplyOrderDetail($paio['id_supply_order_detail']); - $entry->delete(); - } - } - - // manage each product - foreach ($product_ids as $id) - { - $errors = array(); - - // check if a checksum is available for this product and test it - $check = Tools::getValue('input_check_'.$id, ''); - $check_valid = md5(_COOKIE_KEY_.$id); - - if ($check_valid != $check) - continue; - - $pos = strpos($id, '_'); - if ($pos === false) - continue; - - // Load / Create supply order detail - $entry = new SupplyOrderDetail(); - $id_supply_order_detail = (int)Tools::getValue('input_id_'.$id, 0); - if ($id_supply_order_detail > 0) - { - $existing_entry = new SupplyOrderDetail($id_supply_order_detail); - if (Validate::isLoadedObject($supply_order)) - $entry = &$existing_entry; - } - - // get product informations - $entry->id_product = substr($id, 0, $pos); - $entry->id_product_attribute = substr($id, $pos + 1); - $entry->unit_price_te = (float)str_replace(array(' ', ','), array('', '.'), Tools::getValue('input_unit_price_te_'.$id, 0)); - $entry->quantity_expected = (int)str_replace(array(' ', ','), array('', '.'), Tools::getValue('input_quantity_expected_'.$id, 0)); - $entry->discount_rate = (float)str_replace(array(' ', ','), array('', '.'), Tools::getValue('input_discount_rate_'.$id, 0)); - $entry->tax_rate = (float)str_replace(array(' ', ','), array('', '.'), Tools::getValue('input_tax_rate_'.$id, 0)); - $entry->reference = Tools::getValue('input_reference_'.$id, ''); - $entry->supplier_reference = Tools::getValue('input_supplier_reference_'.$id, ''); - $entry->ean13 = Tools::getValue('input_ean13_'.$id, ''); - $entry->upc = Tools::getValue('input_upc_'.$id, ''); - - //get the product name in the order language - $entry->name = Product::getProductName($entry->id_product, $entry->id_product_attribute, $supply_order->id_lang); - - if (empty($entry->name)) - $entry->name = ''; - - if ($entry->supplier_reference == null) - $entry->supplier_reference = ''; - - $entry->exchange_rate = $currency->conversion_rate; - $entry->id_currency = $currency->id; - $entry->id_supply_order = $supply_order->id; - - $errors = $entry->validateController(); - - //get the product name displayed in the backoffice according to the employee language - $entry->name_displayed = Tools::getValue('input_name_displayed_'.$id, ''); - - // if there is a problem, handle error for the current product - if (count($errors) > 0) - { - // add the product to error array => display again product line - $this->order_products_errors[] = array( - 'id_product' => $entry->id_product, - 'id_product_attribute' => $entry->id_product_attribute, - 'unit_price_te' => $entry->unit_price_te, - 'quantity_expected' => $entry->quantity_expected, - 'discount_rate' => $entry->discount_rate, - 'tax_rate' => $entry->tax_rate, - 'name' => $entry->name, - 'name_displayed' => $entry->name_displayed, - 'reference' => $entry->reference, - 'supplier_reference' => $entry->supplier_reference, - 'ean13' => $entry->ean13, - 'upc' => $entry->upc, - ); - - $error_str = '<ul>'; - foreach ($errors as $e) - $error_str .= '<li>'.sprintf($this->l('Field: %s'), $e).'</li>'; - $error_str .= '</ul>'; - - $this->errors[] = sprintf(Tools::displayError('Please verify the product information for "%s":'), $entry->name).' ' - .$error_str; - } - else - $entry->save(); - } - } - } - } - } - - /** - * AdminController::postProcess() override - * @see AdminController::postProcess() - */ - public function postProcess() - { - $this->is_editing_order = false; - - // Checks access - if (Tools::isSubmit('submitAddsupply_order') && !($this->tabAccess['add'] === '1')) - $this->errors[] = Tools::displayError('You do not have permission to add a supply order.'); - if (Tools::isSubmit('submitBulkUpdatesupply_order_detail') && !($this->tabAccess['edit'] === '1')) - $this->errors[] = Tools::displayError('You do not have permission to edit an order.'); - - // Trick to use both Supply Order as template and actual orders - if (Tools::isSubmit('is_template')) - $_GET['mod'] = 'template'; - - // checks if supply order reference is unique - if (Tools::isSubmit('reference')) - { - // gets the reference - $ref = pSQL(Tools::getValue('reference')); - - if (Tools::getValue('id_supply_order') != 0 && SupplyOrder::getReferenceById((int)Tools::getValue('id_supply_order')) != $ref) - { - if ((int)SupplyOrder::exists($ref) != 0) - $this->errors[] = Tools::displayError('The reference has to be unique.'); - } - elseif (Tools::getValue('id_supply_order') == 0 && (int)SupplyOrder::exists($ref) != 0) - $this->errors[] = Tools::displayError('The reference has to be unique.'); - } - - if ($this->errors) - return; - - // Global checks when add / update a supply order - if (Tools::isSubmit('submitAddsupply_order') || Tools::isSubmit('submitAddsupply_orderAndStay')) - { - $this->action = 'save'; - $this->is_editing_order = true; - - // get supplier ID - $id_supplier = (int)Tools::getValue('id_supplier', 0); - if ($id_supplier <= 0 || !Supplier::supplierExists($id_supplier)) - $this->errors[] = Tools::displayError('The selected supplier is not valid.'); - - // get warehouse id - $id_warehouse = (int)Tools::getValue('id_warehouse', 0); - if ($id_warehouse <= 0 || !Warehouse::exists($id_warehouse)) - $this->errors[] = Tools::displayError('The selected warehouse is not valid.'); - - // get currency id - $id_currency = (int)Tools::getValue('id_currency', 0); - if ($id_currency <= 0 || ( !($result = Currency::getCurrency($id_currency)) || empty($result) )) - $this->errors[] = Tools::displayError('The selected currency is not valid.'); - - // get delivery date - if (Tools::getValue('mod') != 'template' && strtotime(Tools::getValue('date_delivery_expected')) <= strtotime('-1 day')) - $this->errors[] = Tools::displayError('The specified date cannot be in the past.'); - - // gets threshold - $quantity_threshold = Tools::getValue('load_products'); - - if (is_numeric($quantity_threshold)) - $quantity_threshold = (int)$quantity_threshold; - else - $quantity_threshold = null; - - if (!count($this->errors)) - { - // forces date for templates - if (Tools::isSubmit('is_template') && !Tools::getValue('date_delivery_expected')) - $_POST['date_delivery_expected'] = date('Y-m-d h:i:s'); - - // specify initial state - $_POST['id_supply_order_state'] = 1; //defaut creation state - - // specify global reference currency - $_POST['id_ref_currency'] = Currency::getDefaultCurrency()->id; - - // specify supplier name - $_POST['supplier_name'] = Supplier::getNameById($id_supplier); - - //specific discount check - $_POST['discount_rate'] = (float)str_replace(array(' ', ','), array('', '.'), Tools::getValue('discount_rate', 0)); - } - - // manage each associated product - $this->manageOrderProducts(); - - // if the threshold is defined and we are saving the order - if (Tools::isSubmit('submitAddsupply_order') && Validate::isInt($quantity_threshold)) - $this->loadProducts((int)$quantity_threshold); - } - - // Manage state change - if (Tools::isSubmit('submitChangestate') - && Tools::isSubmit('id_supply_order') - && Tools::isSubmit('id_supply_order_state')) - { - if ($this->tabAccess['edit'] != '1') - $this->errors[] = Tools::displayError('You do not have permission to change the order status.'); - - // get state ID - $id_state = (int)Tools::getValue('id_supply_order_state', 0); - if ($id_state <= 0) - $this->errors[] = Tools::displayError('The selected supply order status is not valid.'); - - // get supply order ID - $id_supply_order = (int)Tools::getValue('id_supply_order', 0); - if ($id_supply_order <= 0) - $this->errors[] = Tools::displayError('The supply order ID is not valid.'); - - if (!count($this->errors)) - { - // try to load supply order - $supply_order = new SupplyOrder($id_supply_order); - - if (Validate::isLoadedObject($supply_order)) - { - // get valid available possible states for this order - $states = SupplyOrderState::getSupplyOrderStates($supply_order->id_supply_order_state); - - foreach ($states as $state) - { - // if state is valid, change it in the order - if ($id_state == $state['id_supply_order_state']) - { - - $new_state = new SupplyOrderState($id_state); - $old_state = new SupplyOrderState($supply_order->id_supply_order_state); - - // special case of validate state - check if there are products in the order and the required state is not an enclosed state - if ($supply_order->isEditable() && !$supply_order->hasEntries() && !$new_state->enclosed) - $this->errors[] = Tools::displayError('It is not possible to change the status of this order because you did not order any products.'); - - if (!count($this->errors)) - { - $supply_order->id_supply_order_state = $state['id_supply_order_state']; - if ($supply_order->save()) - { - if ($new_state->pending_receipt) - { - $supply_order_details = $supply_order->getEntries(); - foreach ($supply_order_details as $supply_order_detail) - { - $is_present = Stock::productIsPresentInStock($supply_order_detail['id_product'], $supply_order_detail['id_product_attribute'], $supply_order->id_warehouse); - if (!$is_present) - { - $stock = new Stock(); - - $stock_params = array( - 'id_product_attribute' => $supply_order_detail['id_product_attribute'], - 'id_product' => $supply_order_detail['id_product'], - 'physical_quantity' => 0, - 'price_te' => $supply_order_detail['price_te'], - 'usable_quantity' => 0, - 'id_warehouse' => $supply_order->id_warehouse - ); - - // saves stock in warehouse - $stock->hydrate($stock_params); - $stock->add(); - } - } - } - - // if pending_receipt, - // or if the order is being canceled, - // or if the order is received completely - // synchronizes StockAvailable - if (($new_state->pending_receipt && !$new_state->receipt_state) || - (($old_state->receipt_state || $old_state->pending_receipt) && $new_state->enclosed && !$new_state->receipt_state) || - ($new_state->receipt_state && $new_state->enclosed)) - { - $supply_order_details = $supply_order->getEntries(); - $products_done = array(); - foreach ($supply_order_details as $supply_order_detail) - { - if (!in_array($supply_order_detail['id_product'], $products_done)) - { - StockAvailable::synchronize($supply_order_detail['id_product']); - $products_done[] = $supply_order_detail['id_product']; - } - } - } - - $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; - $redirect = self::$currentIndex.'&token='.$token; - $this->redirect_after = $redirect.'&conf=5'; - } - } - } - } - } - else - $this->errors[] = Tools::displayError('The selected supplier is not valid.'); - } - } - - // updates receipt - if (Tools::isSubmit('submitBulkUpdatesupply_order_detail') && Tools::isSubmit('id_supply_order')) - $this->postProcessUpdateReceipt(); - - // use template to create a supply order - if (Tools::isSubmit('create_supply_order') && Tools::isSubmit('id_supply_order')) - $this->postProcessCopyFromTemplate(); - - if ((!count($this->errors) && $this->is_editing_order) || !$this->is_editing_order) - parent::postProcess(); - } - - /** - * Exports CSV - */ - protected function renderCSV() - { - // exports orders - if (Tools::isSubmit('csv_orders')) - { - $ids = array(); - foreach ($this->_list as $entry) - $ids[] = $entry['id_supply_order']; - - if (count($ids) <= 0) - return; - - $id_lang = Context::getContext()->language->id; - $orders = new PrestaShopCollection('SupplyOrder', $id_lang); - $orders->where('is_template', '=', false); - $orders->where('id_supply_order', 'in', $ids); - $id_warehouse = $this->getCurrentWarehouse(); - if ($id_warehouse != -1) - $orders->where('id_warehouse', '=', $id_warehouse); - $orders->getAll(); - $csv = new CSV($orders, $this->l('supply_orders')); - $csv->export(); - } - // exports details for all orders - elseif (Tools::isSubmit('csv_orders_details')) - { - // header - header('Content-type: text/csv'); - header('Content-Type: application/force-download; charset=UTF-8'); - header('Cache-Control: no-store, no-cache'); - header('Content-disposition: attachment; filename="'.$this->l('supply_orders_details').'.csv"'); - - // echoes details - $ids = array(); - foreach ($this->_list as $entry) - $ids[] = $entry['id_supply_order']; - - if (count($ids) <= 0) - return; - - // for each supply order - $keys = array('id_product', 'id_product_attribute', 'reference', 'supplier_reference', 'ean13', 'upc', 'name', - 'unit_price_te', 'quantity_expected', 'quantity_received', 'price_te', 'discount_rate', 'discount_value_te', - 'price_with_discount_te', 'tax_rate', 'tax_value', 'price_ti', 'tax_value_with_order_discount', - 'price_with_order_discount_te', 'id_supply_order'); - echo sprintf("%s\n", implode(';', array_map(array('CSVCore', 'wrap'), $keys))); - - // overrides keys (in order to add FORMAT calls) - $keys = array('sod.id_product', 'sod.id_product_attribute', 'sod.reference', 'sod.supplier_reference', 'sod.ean13', - 'sod.upc', 'sod.name', - 'FORMAT(sod.unit_price_te, 2)', 'sod.quantity_expected', 'sod.quantity_received', 'FORMAT(sod.price_te, 2)', - 'FORMAT(sod.discount_rate, 2)', 'FORMAT(sod.discount_value_te, 2)', - 'FORMAT(sod.price_with_discount_te, 2)', 'FORMAT(sod.tax_rate, 2)', 'FORMAT(sod.tax_value, 2)', - 'FORMAT(sod.price_ti, 2)', 'FORMAT(sod.tax_value_with_order_discount, 2)', - 'FORMAT(sod.price_with_order_discount_te, 2)', 'sod.id_supply_order'); - foreach ($ids as $id) - { - $query = new DbQuery(); - $query->select(implode(', ', $keys)); - $query->from('supply_order_detail', 'sod'); - $query->leftJoin('supply_order', 'so', 'so.id_supply_order = sod.id_supply_order'); - $id_warehouse = $this->getCurrentWarehouse(); - if ($id_warehouse != -1) - $query->where('so.id_warehouse = '.(int)$id_warehouse); - $query->where('sod.id_supply_order = '.(int)$id); - $query->orderBy('sod.id_supply_order_detail DESC'); - $resource = Db::getInstance()->query($query); - // gets details - while ($row = Db::getInstance()->nextRow($resource)) - echo sprintf("%s\n", implode(';', array_map(array('CSVCore', 'wrap'), $row))); - } - - } - // exports details for the given order - elseif (Tools::isSubmit('csv_order_details') && Tools::getValue('id_supply_order')) - { - $supply_order = new SupplyOrder((int)Tools::getValue('id_supply_order')); - if (Validate::isLoadedObject($supply_order)) - { - $details = $supply_order->getEntriesCollection(); - $details->getAll(); - $csv = new CSV($details, $this->l('supply_order').'_'.$supply_order->reference.'_details'); - $csv->export(); - } - } - } - - /** - * Helper function for AdminSupplyOrdersController::postProcess() - * - * @see AdminSupplyOrdersController::postProcess() - */ - protected function postProcessUpdateReceipt() - { - // gets all box selected - $rows = Tools::getValue('supply_order_detailBox'); - if (!$rows) - { - $this->errors[] = Tools::displayError('You did not select any products to update.'); - return; - } - - // final array with id_supply_order_detail and value to update - $to_update = array(); - // gets quantity for each id_order_detail - foreach ($rows as $row) - { - if (Tools::getValue('quantity_received_today_'.$row)) - $to_update[$row] = (int)Tools::getValue('quantity_received_today_'.$row); - } - - // checks if there is something to update - if (!count($to_update)) - { - $this->errors[] = Tools::displayError('You did not select any products to update.'); - return; - } - - $supply_order = new SupplyOrder((int)Tools::getValue('id_supply_order')); - - foreach ($to_update as $id_supply_order_detail => $quantity) - { - $supply_order_detail = new SupplyOrderDetail($id_supply_order_detail); - - if (Validate::isLoadedObject($supply_order_detail) && Validate::isLoadedObject($supply_order)) - { - // checks if quantity is valid - // It's possible to receive more quantity than expected in case of a shipping error from the supplier - if (!Validate::isInt($quantity) || $quantity <= 0) - $this->errors[] = sprintf(Tools::displayError('Quantity (%d) for product #%d is not valid'), - (int)$quantity, (int)$id_supply_order_detail); - else // everything is valid : updates - { - // creates the history - $supplier_receipt_history = new SupplyOrderReceiptHistory(); - $supplier_receipt_history->id_supply_order_detail = (int)$id_supply_order_detail; - $supplier_receipt_history->id_employee = (int)$this->context->employee->id; - $supplier_receipt_history->employee_firstname = pSQL($this->context->employee->firstname); - $supplier_receipt_history->employee_lastname = pSQL($this->context->employee->lastname); - $supplier_receipt_history->id_supply_order_state = (int)$supply_order->id_supply_order_state; - $supplier_receipt_history->quantity = (int)$quantity; - - // updates quantity received - $supply_order_detail->quantity_received += (int)$quantity; - - // if current state is "Pending receipt", then we sets it to "Order received in part" - if (3 == $supply_order->id_supply_order_state) - $supply_order->id_supply_order_state = 4; - - // Adds to stock - $warehouse = new Warehouse($supply_order->id_warehouse); - if (!Validate::isLoadedObject($warehouse)) - { - $this->errors[] = Tools::displayError('The warehouse could not be loaded.'); - return; - } - - $price = $supply_order_detail->unit_price_te; - // converts the unit price to the warehouse currency if needed - if ($supply_order->id_currency != $warehouse->id_currency) - { - // first, converts the price to the default currency - $price_converted_to_default_currency = Tools::convertPrice($supply_order_detail->unit_price_te, - $supply_order->id_currency, false); - - // then, converts the newly calculated pri-ce from the default currency to the needed currency - $price = Tools::ps_round(Tools::convertPrice($price_converted_to_default_currency, - $warehouse->id_currency, true), 6); - } - - $manager = StockManagerFactory::getManager(); - $res = $manager->addProduct($supply_order_detail->id_product, - $supply_order_detail->id_product_attribute, $warehouse, (int)$quantity, - Configuration::get('PS_STOCK_MVT_SUPPLY_ORDER'), $price, true, $supply_order->id); - - $location = Warehouse::getProductLocation($supply_order_detail->id_product, - $supply_order_detail->id_product_attribute, $warehouse->id); - - $res = Warehouse::setProductlocation($supply_order_detail->id_product, - $supply_order_detail->id_product_attribute, $warehouse->id, $location ? $location : ''); - - if ($res) - { - $supplier_receipt_history->add(); - $supply_order_detail->save(); - StockAvailable::synchronize($supply_order_detail->id_product); - } - else - $this->errors[] = Tools::displayError('Something went wrong when setting warehouse on product record'); - } - } - } - - $supply_order->id_supply_order_state = ($supply_order->id_supply_order_state == 4 && $supply_order->getAllPendingQuantity() > 0) ? 4 : 5; - $supply_order->save(); - - if (!count($this->errors)) - { - // display confirm message - $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; - $redirect = self::$currentIndex.'&token='.$token; - $this->redirect_after = $redirect.'&conf=4'; - } - } + $this->_where = 'AND a.`id_supply_order` = '.(int)$id_supply_order; + + $this->_group = 'GROUP BY a.id_supply_order_detail'; + + // gets the list ordered by price desc, without limit + $this->getList($lang_id, 'quantity_expected', 'DESC', 0, Tools::getValue('supply_order_pagination'), false); + + // defines action for POST + $action = '&id_supply_order='.$id_supply_order.'&update_receipt=1'; + + // unsets some buttons + unset($this->toolbar_btn['export-csv-orders']); + unset($this->toolbar_btn['export-csv-details']); + unset($this->toolbar_btn['new']); + + $this->toolbar_btn['back'] = array( + 'desc' => $this->l('Back'), + 'href' => $this->context->link->getAdminLink('AdminSupplyOrders') + ); + + // renders list + $helper = new HelperList(); + $this->setHelperDisplay($helper); + $helper->actions = array('details'); + $helper->force_show_bulk_actions = true; + $helper->override_folder = 'supply_orders_receipt_history/'; + $helper->toolbar_btn = $this->toolbar_btn; + $helper->list_id = 'supply_order_detail'; + + $helper->ajax_params = array( + 'display_product_history' => 1, + ); + + $helper->currentIndex = self::$currentIndex.$action; + + // display these global order informations + $this->displayInformation($this->l('This interface allows you to update the quantities of this ongoing order.').'<br />'); + $this->displayInformation($this->l('Be careful! Once you update, you cannot go back unless you add new negative stock movements.').'<br />'); + $this->displayInformation($this->l('A green line means that you\'ve received exactly the quantity you expected. A red line means that you\'ve received more than expected.').'<br />'); + + // generates content + $content = $helper->generateList($this->_list, $this->fields_list); + + // assigns var + $this->context->smarty->assign(array( + 'content' => $content, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } /** - * Display state action link - * @param string $token the token to add to the link - * @param int $id the identifier to add to the link - * @return string - */ + * AdminController::initContent() override + * @see AdminController::initContent() + */ + public function initContent() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = + $this->l('You need to activate the Advanced Stock Management feature prior to using this feature.'); + return false; + } + // Manage the add stock form + if (Tools::isSubmit('changestate')) { + $this->initChangeStateContent(); + } elseif (Tools::isSubmit('update_receipt') && Tools::isSubmit('id_supply_order') && !Tools::isSubmit('detailssupply_order_detail')) { + $this->initUpdateReceiptContent(); + } elseif (Tools::isSubmit('viewsupply_order') && Tools::isSubmit('id_supply_order')) { + $this->action = 'view'; + $this->display = 'view'; + parent::initContent(); + } elseif (Tools::isSubmit('updatesupply_order')) { + $this->initUpdateSupplyOrderContent(); + } else { + if (Tools::isSubmit('detailssupply_order_detail')) { + $this->action = 'details'; + $this->display = 'details'; + } + parent::initContent(); + } + } + + /** + * Ths method manage associated products to the order when updating it + */ + public function manageOrderProducts() + { + // load supply order + $id_supply_order = (int)Tools::getValue('id_supply_order', null); + $products_already_in_order = array(); + + if ($id_supply_order != null) { + $supply_order = new SupplyOrder($id_supply_order); + + if (Validate::isLoadedObject($supply_order)) { + // tests if the supplier or currency have changed in the supply order + $new_supplier_id = (int)Tools::getValue('id_supplier'); + $new_currency_id = (int)Tools::getValue('id_currency'); + + if (($new_supplier_id != $supply_order->id_supplier) || + ($new_currency_id != $supply_order->id_currency)) { + // resets all products in this order + $supply_order->resetProducts(); + } else { + $products_already_in_order = $supply_order->getEntries(); + $currency = new Currency($supply_order->id_ref_currency); + + // gets all product ids to manage + $product_ids_str = Tools::getValue('product_ids', null); + $product_ids = explode('|', $product_ids_str); + $product_ids_to_delete_str = Tools::getValue('product_ids_to_delete', null); + $product_ids_to_delete = array_unique(explode('|', $product_ids_to_delete_str)); + + //delete products that are not managed anymore + foreach ($products_already_in_order as $paio) { + $product_ok = false; + + foreach ($product_ids_to_delete as $id) { + $id_check = $paio['id_product'].'_'.$paio['id_product_attribute']; + if ($id_check == $id) { + $product_ok = true; + } + } + + if ($product_ok === true) { + $entry = new SupplyOrderDetail($paio['id_supply_order_detail']); + $entry->delete(); + } + } + + // manage each product + foreach ($product_ids as $id) { + $errors = array(); + + // check if a checksum is available for this product and test it + $check = Tools::getValue('input_check_'.$id, ''); + $check_valid = md5(_COOKIE_KEY_.$id); + + if ($check_valid != $check) { + continue; + } + + $pos = strpos($id, '_'); + if ($pos === false) { + continue; + } + + // Load / Create supply order detail + $entry = new SupplyOrderDetail(); + $id_supply_order_detail = (int)Tools::getValue('input_id_'.$id, 0); + if ($id_supply_order_detail > 0) { + $existing_entry = new SupplyOrderDetail($id_supply_order_detail); + if (Validate::isLoadedObject($supply_order)) { + $entry = &$existing_entry; + } + } + + // get product informations + $entry->id_product = substr($id, 0, $pos); + $entry->id_product_attribute = substr($id, $pos + 1); + $entry->unit_price_te = (float)str_replace(array(' ', ','), array('', '.'), Tools::getValue('input_unit_price_te_'.$id, 0)); + $entry->quantity_expected = (int)str_replace(array(' ', ','), array('', '.'), Tools::getValue('input_quantity_expected_'.$id, 0)); + $entry->discount_rate = (float)str_replace(array(' ', ','), array('', '.'), Tools::getValue('input_discount_rate_'.$id, 0)); + $entry->tax_rate = (float)str_replace(array(' ', ','), array('', '.'), Tools::getValue('input_tax_rate_'.$id, 0)); + $entry->reference = Tools::getValue('input_reference_'.$id, ''); + $entry->supplier_reference = Tools::getValue('input_supplier_reference_'.$id, ''); + $entry->ean13 = Tools::getValue('input_ean13_'.$id, ''); + $entry->upc = Tools::getValue('input_upc_'.$id, ''); + + //get the product name in the order language + $entry->name = Product::getProductName($entry->id_product, $entry->id_product_attribute, $supply_order->id_lang); + + if (empty($entry->name)) { + $entry->name = ''; + } + + if ($entry->supplier_reference == null) { + $entry->supplier_reference = ''; + } + + $entry->exchange_rate = $currency->conversion_rate; + $entry->id_currency = $currency->id; + $entry->id_supply_order = $supply_order->id; + + $errors = $entry->validateController(); + + //get the product name displayed in the backoffice according to the employee language + $entry->name_displayed = Tools::getValue('input_name_displayed_'.$id, ''); + + // if there is a problem, handle error for the current product + if (count($errors) > 0) { + // add the product to error array => display again product line + $this->order_products_errors[] = array( + 'id_product' => $entry->id_product, + 'id_product_attribute' => $entry->id_product_attribute, + 'unit_price_te' => $entry->unit_price_te, + 'quantity_expected' => $entry->quantity_expected, + 'discount_rate' => $entry->discount_rate, + 'tax_rate' => $entry->tax_rate, + 'name' => $entry->name, + 'name_displayed' => $entry->name_displayed, + 'reference' => $entry->reference, + 'supplier_reference' => $entry->supplier_reference, + 'ean13' => $entry->ean13, + 'upc' => $entry->upc, + ); + + $error_str = '<ul>'; + foreach ($errors as $e) { + $error_str .= '<li>'.sprintf($this->l('Field: %s'), $e).'</li>'; + } + $error_str .= '</ul>'; + + $this->errors[] = sprintf(Tools::displayError('Please verify the product information for "%s":'), $entry->name).' ' + .$error_str; + } else { + $entry->save(); + } + } + } + } + } + } + + /** + * AdminController::postProcess() override + * @see AdminController::postProcess() + */ + public function postProcess() + { + $this->is_editing_order = false; + + // Checks access + if (Tools::isSubmit('submitAddsupply_order') && !($this->tabAccess['add'] === '1')) { + $this->errors[] = Tools::displayError('You do not have permission to add a supply order.'); + } + if (Tools::isSubmit('submitBulkUpdatesupply_order_detail') && !($this->tabAccess['edit'] === '1')) { + $this->errors[] = Tools::displayError('You do not have permission to edit an order.'); + } + + // Trick to use both Supply Order as template and actual orders + if (Tools::isSubmit('is_template')) { + $_GET['mod'] = 'template'; + } + + // checks if supply order reference is unique + if (Tools::isSubmit('reference')) { + // gets the reference + $ref = pSQL(Tools::getValue('reference')); + + if (Tools::getValue('id_supply_order') != 0 && SupplyOrder::getReferenceById((int)Tools::getValue('id_supply_order')) != $ref) { + if ((int)SupplyOrder::exists($ref) != 0) { + $this->errors[] = Tools::displayError('The reference has to be unique.'); + } + } elseif (Tools::getValue('id_supply_order') == 0 && (int)SupplyOrder::exists($ref) != 0) { + $this->errors[] = Tools::displayError('The reference has to be unique.'); + } + } + + if ($this->errors) { + return; + } + + // Global checks when add / update a supply order + if (Tools::isSubmit('submitAddsupply_order') || Tools::isSubmit('submitAddsupply_orderAndStay')) { + $this->action = 'save'; + $this->is_editing_order = true; + + // get supplier ID + $id_supplier = (int)Tools::getValue('id_supplier', 0); + if ($id_supplier <= 0 || !Supplier::supplierExists($id_supplier)) { + $this->errors[] = Tools::displayError('The selected supplier is not valid.'); + } + + // get warehouse id + $id_warehouse = (int)Tools::getValue('id_warehouse', 0); + if ($id_warehouse <= 0 || !Warehouse::exists($id_warehouse)) { + $this->errors[] = Tools::displayError('The selected warehouse is not valid.'); + } + + // get currency id + $id_currency = (int)Tools::getValue('id_currency', 0); + if ($id_currency <= 0 || (!($result = Currency::getCurrency($id_currency)) || empty($result))) { + $this->errors[] = Tools::displayError('The selected currency is not valid.'); + } + + // get delivery date + if (Tools::getValue('mod') != 'template' && strtotime(Tools::getValue('date_delivery_expected')) <= strtotime('-1 day')) { + $this->errors[] = Tools::displayError('The specified date cannot be in the past.'); + } + + // gets threshold + $quantity_threshold = Tools::getValue('load_products'); + + if (is_numeric($quantity_threshold)) { + $quantity_threshold = (int)$quantity_threshold; + } else { + $quantity_threshold = null; + } + + if (!count($this->errors)) { + // forces date for templates + if (Tools::isSubmit('is_template') && !Tools::getValue('date_delivery_expected')) { + $_POST['date_delivery_expected'] = date('Y-m-d h:i:s'); + } + + // specify initial state + $_POST['id_supply_order_state'] = 1; //defaut creation state + + // specify global reference currency + $_POST['id_ref_currency'] = Currency::getDefaultCurrency()->id; + + // specify supplier name + $_POST['supplier_name'] = Supplier::getNameById($id_supplier); + + //specific discount check + $_POST['discount_rate'] = (float)str_replace(array(' ', ','), array('', '.'), Tools::getValue('discount_rate', 0)); + } + + // manage each associated product + $this->manageOrderProducts(); + + // if the threshold is defined and we are saving the order + if (Tools::isSubmit('submitAddsupply_order') && Validate::isInt($quantity_threshold)) { + $this->loadProducts((int)$quantity_threshold); + } + } + + // Manage state change + if (Tools::isSubmit('submitChangestate') + && Tools::isSubmit('id_supply_order') + && Tools::isSubmit('id_supply_order_state')) { + if ($this->tabAccess['edit'] != '1') { + $this->errors[] = Tools::displayError('You do not have permission to change the order status.'); + } + + // get state ID + $id_state = (int)Tools::getValue('id_supply_order_state', 0); + if ($id_state <= 0) { + $this->errors[] = Tools::displayError('The selected supply order status is not valid.'); + } + + // get supply order ID + $id_supply_order = (int)Tools::getValue('id_supply_order', 0); + if ($id_supply_order <= 0) { + $this->errors[] = Tools::displayError('The supply order ID is not valid.'); + } + + if (!count($this->errors)) { + // try to load supply order + $supply_order = new SupplyOrder($id_supply_order); + + if (Validate::isLoadedObject($supply_order)) { + // get valid available possible states for this order + $states = SupplyOrderState::getSupplyOrderStates($supply_order->id_supply_order_state); + + foreach ($states as $state) { + // if state is valid, change it in the order + if ($id_state == $state['id_supply_order_state']) { + $new_state = new SupplyOrderState($id_state); + $old_state = new SupplyOrderState($supply_order->id_supply_order_state); + + // special case of validate state - check if there are products in the order and the required state is not an enclosed state + if ($supply_order->isEditable() && !$supply_order->hasEntries() && !$new_state->enclosed) { + $this->errors[] = Tools::displayError('It is not possible to change the status of this order because you did not order any products.'); + } + + if (!count($this->errors)) { + $supply_order->id_supply_order_state = $state['id_supply_order_state']; + if ($supply_order->save()) { + if ($new_state->pending_receipt) { + $supply_order_details = $supply_order->getEntries(); + foreach ($supply_order_details as $supply_order_detail) { + $is_present = Stock::productIsPresentInStock($supply_order_detail['id_product'], $supply_order_detail['id_product_attribute'], $supply_order->id_warehouse); + if (!$is_present) { + $stock = new Stock(); + + $stock_params = array( + 'id_product_attribute' => $supply_order_detail['id_product_attribute'], + 'id_product' => $supply_order_detail['id_product'], + 'physical_quantity' => 0, + 'price_te' => $supply_order_detail['price_te'], + 'usable_quantity' => 0, + 'id_warehouse' => $supply_order->id_warehouse + ); + + // saves stock in warehouse + $stock->hydrate($stock_params); + $stock->add(); + } + } + } + + // if pending_receipt, + // or if the order is being canceled, + // or if the order is received completely + // synchronizes StockAvailable + if (($new_state->pending_receipt && !$new_state->receipt_state) || + (($old_state->receipt_state || $old_state->pending_receipt) && $new_state->enclosed && !$new_state->receipt_state) || + ($new_state->receipt_state && $new_state->enclosed)) { + $supply_order_details = $supply_order->getEntries(); + $products_done = array(); + foreach ($supply_order_details as $supply_order_detail) { + if (!in_array($supply_order_detail['id_product'], $products_done)) { + StockAvailable::synchronize($supply_order_detail['id_product']); + $products_done[] = $supply_order_detail['id_product']; + } + } + } + + $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; + $redirect = self::$currentIndex.'&token='.$token; + $this->redirect_after = $redirect.'&conf=5'; + } + } + } + } + } else { + $this->errors[] = Tools::displayError('The selected supplier is not valid.'); + } + } + } + + // updates receipt + if (Tools::isSubmit('submitBulkUpdatesupply_order_detail') && Tools::isSubmit('id_supply_order')) { + $this->postProcessUpdateReceipt(); + } + + // use template to create a supply order + if (Tools::isSubmit('create_supply_order') && Tools::isSubmit('id_supply_order')) { + $this->postProcessCopyFromTemplate(); + } + + if ((!count($this->errors) && $this->is_editing_order) || !$this->is_editing_order) { + parent::postProcess(); + } + } + + /** + * Exports CSV + */ + protected function renderCSV() + { + // exports orders + if (Tools::isSubmit('csv_orders')) { + $ids = array(); + foreach ($this->_list as $entry) { + $ids[] = $entry['id_supply_order']; + } + + if (count($ids) <= 0) { + return; + } + + $id_lang = Context::getContext()->language->id; + $orders = new PrestaShopCollection('SupplyOrder', $id_lang); + $orders->where('is_template', '=', false); + $orders->where('id_supply_order', 'in', $ids); + $id_warehouse = $this->getCurrentWarehouse(); + if ($id_warehouse != -1) { + $orders->where('id_warehouse', '=', $id_warehouse); + } + $orders->getAll(); + $csv = new CSV($orders, $this->l('supply_orders')); + $csv->export(); + } + // exports details for all orders + elseif (Tools::isSubmit('csv_orders_details')) { + // header + header('Content-type: text/csv'); + header('Content-Type: application/force-download; charset=UTF-8'); + header('Cache-Control: no-store, no-cache'); + header('Content-disposition: attachment; filename="'.$this->l('supply_orders_details').'.csv"'); + + // echoes details + $ids = array(); + foreach ($this->_list as $entry) { + $ids[] = $entry['id_supply_order']; + } + + if (count($ids) <= 0) { + return; + } + + // for each supply order + $keys = array('id_product', 'id_product_attribute', 'reference', 'supplier_reference', 'ean13', 'upc', 'name', + 'unit_price_te', 'quantity_expected', 'quantity_received', 'price_te', 'discount_rate', 'discount_value_te', + 'price_with_discount_te', 'tax_rate', 'tax_value', 'price_ti', 'tax_value_with_order_discount', + 'price_with_order_discount_te', 'id_supply_order'); + echo sprintf("%s\n", implode(';', array_map(array('CSVCore', 'wrap'), $keys))); + + // overrides keys (in order to add FORMAT calls) + $keys = array('sod.id_product', 'sod.id_product_attribute', 'sod.reference', 'sod.supplier_reference', 'sod.ean13', + 'sod.upc', 'sod.name', + 'FORMAT(sod.unit_price_te, 2)', 'sod.quantity_expected', 'sod.quantity_received', 'FORMAT(sod.price_te, 2)', + 'FORMAT(sod.discount_rate, 2)', 'FORMAT(sod.discount_value_te, 2)', + 'FORMAT(sod.price_with_discount_te, 2)', 'FORMAT(sod.tax_rate, 2)', 'FORMAT(sod.tax_value, 2)', + 'FORMAT(sod.price_ti, 2)', 'FORMAT(sod.tax_value_with_order_discount, 2)', + 'FORMAT(sod.price_with_order_discount_te, 2)', 'sod.id_supply_order'); + foreach ($ids as $id) { + $query = new DbQuery(); + $query->select(implode(', ', $keys)); + $query->from('supply_order_detail', 'sod'); + $query->leftJoin('supply_order', 'so', 'so.id_supply_order = sod.id_supply_order'); + $id_warehouse = $this->getCurrentWarehouse(); + if ($id_warehouse != -1) { + $query->where('so.id_warehouse = '.(int)$id_warehouse); + } + $query->where('sod.id_supply_order = '.(int)$id); + $query->orderBy('sod.id_supply_order_detail DESC'); + $resource = Db::getInstance()->query($query); + // gets details + while ($row = Db::getInstance()->nextRow($resource)) { + echo sprintf("%s\n", implode(';', array_map(array('CSVCore', 'wrap'), $row))); + } + } + } + // exports details for the given order + elseif (Tools::isSubmit('csv_order_details') && Tools::getValue('id_supply_order')) { + $supply_order = new SupplyOrder((int)Tools::getValue('id_supply_order')); + if (Validate::isLoadedObject($supply_order)) { + $details = $supply_order->getEntriesCollection(); + $details->getAll(); + $csv = new CSV($details, $this->l('supply_order').'_'.$supply_order->reference.'_details'); + $csv->export(); + } + } + } + + /** + * Helper function for AdminSupplyOrdersController::postProcess() + * + * @see AdminSupplyOrdersController::postProcess() + */ + protected function postProcessUpdateReceipt() + { + // gets all box selected + $rows = Tools::getValue('supply_order_detailBox'); + if (!$rows) { + $this->errors[] = Tools::displayError('You did not select any products to update.'); + return; + } + + // final array with id_supply_order_detail and value to update + $to_update = array(); + // gets quantity for each id_order_detail + foreach ($rows as $row) { + if (Tools::getValue('quantity_received_today_'.$row)) { + $to_update[$row] = (int)Tools::getValue('quantity_received_today_'.$row); + } + } + + // checks if there is something to update + if (!count($to_update)) { + $this->errors[] = Tools::displayError('You did not select any products to update.'); + return; + } + + $supply_order = new SupplyOrder((int)Tools::getValue('id_supply_order')); + + foreach ($to_update as $id_supply_order_detail => $quantity) { + $supply_order_detail = new SupplyOrderDetail($id_supply_order_detail); + + if (Validate::isLoadedObject($supply_order_detail) && Validate::isLoadedObject($supply_order)) { + // checks if quantity is valid + // It's possible to receive more quantity than expected in case of a shipping error from the supplier + if (!Validate::isInt($quantity) || $quantity <= 0) { + $this->errors[] = sprintf(Tools::displayError('Quantity (%d) for product #%d is not valid'), + (int)$quantity, (int)$id_supply_order_detail); + } else { + // everything is valid : updates + + // creates the history + $supplier_receipt_history = new SupplyOrderReceiptHistory(); + $supplier_receipt_history->id_supply_order_detail = (int)$id_supply_order_detail; + $supplier_receipt_history->id_employee = (int)$this->context->employee->id; + $supplier_receipt_history->employee_firstname = pSQL($this->context->employee->firstname); + $supplier_receipt_history->employee_lastname = pSQL($this->context->employee->lastname); + $supplier_receipt_history->id_supply_order_state = (int)$supply_order->id_supply_order_state; + $supplier_receipt_history->quantity = (int)$quantity; + + // updates quantity received + $supply_order_detail->quantity_received += (int)$quantity; + + // if current state is "Pending receipt", then we sets it to "Order received in part" + if (3 == $supply_order->id_supply_order_state) { + $supply_order->id_supply_order_state = 4; + } + + // Adds to stock + $warehouse = new Warehouse($supply_order->id_warehouse); + if (!Validate::isLoadedObject($warehouse)) { + $this->errors[] = Tools::displayError('The warehouse could not be loaded.'); + return; + } + + $price = $supply_order_detail->unit_price_te; + // converts the unit price to the warehouse currency if needed + if ($supply_order->id_currency != $warehouse->id_currency) { + // first, converts the price to the default currency + $price_converted_to_default_currency = Tools::convertPrice($supply_order_detail->unit_price_te, + $supply_order->id_currency, false); + + // then, converts the newly calculated pri-ce from the default currency to the needed currency + $price = Tools::ps_round(Tools::convertPrice($price_converted_to_default_currency, + $warehouse->id_currency, true), 6); + } + + $manager = StockManagerFactory::getManager(); + $res = $manager->addProduct($supply_order_detail->id_product, + $supply_order_detail->id_product_attribute, $warehouse, (int)$quantity, + Configuration::get('PS_STOCK_MVT_SUPPLY_ORDER'), $price, true, $supply_order->id); + + $location = Warehouse::getProductLocation($supply_order_detail->id_product, + $supply_order_detail->id_product_attribute, $warehouse->id); + + $res = Warehouse::setProductlocation($supply_order_detail->id_product, + $supply_order_detail->id_product_attribute, $warehouse->id, $location ? $location : ''); + + if ($res) { + $supplier_receipt_history->add(); + $supply_order_detail->save(); + StockAvailable::synchronize($supply_order_detail->id_product); + } else { + $this->errors[] = Tools::displayError('Something went wrong when setting warehouse on product record'); + } + } + } + } + + $supply_order->id_supply_order_state = ($supply_order->id_supply_order_state == 4 && $supply_order->getAllPendingQuantity() > 0) ? 4 : 5; + $supply_order->save(); + + if (!count($this->errors)) { + // display confirm message + $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; + $redirect = self::$currentIndex.'&token='.$token; + $this->redirect_after = $redirect.'&conf=4'; + } + } + + /** + * Display state action link + * @param string $token the token to add to the link + * @param int $id the identifier to add to the link + * @return string + */ public function displayUpdateReceiptLink($token = null, $id) { - if (!array_key_exists('Receipt', self::$cache_lang)) + if (!array_key_exists('Receipt', self::$cache_lang)) { self::$cache_lang['Receipt'] = $this->l('Update ongoing receipt of products'); + } $this->context->smarty->assign(array( 'href' => self::$currentIndex. - '&'.$this->identifier.'='.$id. - '&update_receipt&token='.($token != null ? $token : $this->token), + '&'.$this->identifier.'='.$id. + '&update_receipt&token='.($token != null ? $token : $this->token), 'action' => self::$cache_lang['Receipt'], )); @@ -1538,20 +1514,21 @@ class AdminSupplyOrdersControllerCore extends AdminController } /** - * Display receipt action link - * @param string $token the token to add to the link - * @param int $id the identifier to add to the link - * @return string - */ + * Display receipt action link + * @param string $token the token to add to the link + * @param int $id the identifier to add to the link + * @return string + */ public function displayChangestateLink($token = null, $id) { - if (!array_key_exists('State', self::$cache_lang)) + if (!array_key_exists('State', self::$cache_lang)) { self::$cache_lang['State'] = $this->l('Change status'); + } $this->context->smarty->assign(array( 'href' => self::$currentIndex. - '&'.$this->identifier.'='.$id. - '&changestate&token='.($token != null ? $token : $this->token), + '&'.$this->identifier.'='.$id. + '&changestate&token='.($token != null ? $token : $this->token), 'action' => self::$cache_lang['State'], )); @@ -1559,76 +1536,77 @@ class AdminSupplyOrdersControllerCore extends AdminController } /** - * Display state action link - * @param string $token the token to add to the link - * @param int $id the identifier to add to the link - * @return string - */ + * Display state action link + * @param string $token the token to add to the link + * @param int $id the identifier to add to the link + * @return string + */ public function displayCreateSupplyOrderLink($token = null, $id) { - if (!array_key_exists('CreateSupplyOrder', self::$cache_lang)) + if (!array_key_exists('CreateSupplyOrder', self::$cache_lang)) { self::$cache_lang['CreateSupplyOrder'] = $this->l('Use this template to create a supply order'); + } - if (!array_key_exists('CreateSupplyOrderConfirm', self::$cache_lang)) + if (!array_key_exists('CreateSupplyOrderConfirm', self::$cache_lang)) { self::$cache_lang['CreateSupplyOrderConfirm'] = $this->l('Are you sure you want to use this template?'); + } $this->context->smarty->assign(array( 'href' => self::$currentIndex. - '&'.$this->identifier.'='.$id. - '&create_supply_order&token='.($token != null ? $token : $this->token), - 'confirm' => self::$cache_lang['CreateSupplyOrderConfirm'], + '&'.$this->identifier.'='.$id. + '&create_supply_order&token='.($token != null ? $token : $this->token), + 'confirm' => self::$cache_lang['CreateSupplyOrderConfirm'], 'action' => self::$cache_lang['CreateSupplyOrder'], )); return $this->context->smarty->fetch('helpers/list/list_action_supply_order_create_from_template.tpl'); } - public function renderDetails() - { - // tests if an id is submit - if (Tools::isSubmit('id_supply_order') && !Tools::isSubmit('display_product_history')) - { - // overrides attributes - $this->identifier = 'id_supply_order_history'; - $this->table = 'supply_order_history'; - $this->lang = false; - $this->actions = array(); - $this->toolbar_btn = array(); - $this->list_simple_header = true; - // gets current lang id - $lang_id = (int)$this->context->language->id; - // gets supply order id - $id_supply_order = (int)Tools::getValue('id_supply_order'); + public function renderDetails() + { + // tests if an id is submit + if (Tools::isSubmit('id_supply_order') && !Tools::isSubmit('display_product_history')) { + // overrides attributes + $this->identifier = 'id_supply_order_history'; + $this->table = 'supply_order_history'; + $this->lang = false; + $this->actions = array(); + $this->toolbar_btn = array(); + $this->list_simple_header = true; + // gets current lang id + $lang_id = (int)$this->context->language->id; + // gets supply order id + $id_supply_order = (int)Tools::getValue('id_supply_order'); - // creates new fields_list - $this->fields_list = array( - 'history_date' => array( - 'title' => $this->l('Last update'), - 'align' => 'left', - 'type' => 'datetime', - 'havingFilter' => true - ), - 'history_employee' => array( - 'title' => $this->l('Employee'), - 'align' => 'left', - 'havingFilter' => true - ), - 'history_state_name' => array( - 'title' => $this->l('Status'), - 'align' => 'left', - 'color' => 'color', - 'havingFilter' => true - ), - ); - // loads history of the given order - unset($this->_select, $this->_join, $this->_where, $this->_orderBy, $this->_orderWay, $this->_group, $this->_filterHaving, $this->_filter); - $this->_select = ' + // creates new fields_list + $this->fields_list = array( + 'history_date' => array( + 'title' => $this->l('Last update'), + 'align' => 'left', + 'type' => 'datetime', + 'havingFilter' => true + ), + 'history_employee' => array( + 'title' => $this->l('Employee'), + 'align' => 'left', + 'havingFilter' => true + ), + 'history_state_name' => array( + 'title' => $this->l('Status'), + 'align' => 'left', + 'color' => 'color', + 'havingFilter' => true + ), + ); + // loads history of the given order + unset($this->_select, $this->_join, $this->_where, $this->_orderBy, $this->_orderWay, $this->_group, $this->_filterHaving, $this->_filter); + $this->_select = ' a.`date_add` as history_date, CONCAT(a.`employee_lastname`, \' \', a.`employee_firstname`) as history_employee, sosl.`name` as history_state_name, sos.`color` as color'; - $this->_join = ' + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'supply_order_state` sos ON (a.`id_state` = sos.`id_supply_order_state`) LEFT JOIN `'._DB_PREFIX_.'supply_order_state_lang` sosl ON ( @@ -1636,77 +1614,76 @@ class AdminSupplyOrdersControllerCore extends AdminController AND sosl.`id_lang` = '.(int)$lang_id.' )'; - $this->_where = 'AND a.`id_supply_order` = '.(int)$id_supply_order; - $this->_orderBy = 'a.date_add'; - $this->_orderWay = 'DESC'; + $this->_where = 'AND a.`id_supply_order` = '.(int)$id_supply_order; + $this->_orderBy = 'a.date_add'; + $this->_orderWay = 'DESC'; - return parent::renderList(); - } - elseif (Tools::isSubmit('id_supply_order') && Tools::isSubmit('display_product_history')) - { - $this->identifier = 'id_supply_order_receipt_history'; - $this->table = 'supply_order_receipt_history'; - $this->actions = array(); - $this->toolbar_btn = array(); - $this->list_simple_header = true; - $this->lang = false; - $lang_id = (int)$this->context->language->id; - $id_supply_order_detail = (int)Tools::getValue('id_supply_order'); + return parent::renderList(); + } elseif (Tools::isSubmit('id_supply_order') && Tools::isSubmit('display_product_history')) { + $this->identifier = 'id_supply_order_receipt_history'; + $this->table = 'supply_order_receipt_history'; + $this->actions = array(); + $this->toolbar_btn = array(); + $this->list_simple_header = true; + $this->lang = false; + $lang_id = (int)$this->context->language->id; + $id_supply_order_detail = (int)Tools::getValue('id_supply_order'); - unset($this->fields_list); - $this->fields_list = array( - 'date_add' => array( - 'title' => $this->l('Last update'), - 'align' => 'left', - 'type' => 'datetime', - 'havingFilter' => true - ), - 'employee' => array( - 'title' => $this->l('Employee'), - 'align' => 'left', - 'havingFilter' => true - ), - 'quantity' => array( - 'title' => $this->l('Quantity received'), - 'align' => 'left', - 'havingFilter' => true - ), - ); + unset($this->fields_list); + $this->fields_list = array( + 'date_add' => array( + 'title' => $this->l('Last update'), + 'align' => 'left', + 'type' => 'datetime', + 'havingFilter' => true + ), + 'employee' => array( + 'title' => $this->l('Employee'), + 'align' => 'left', + 'havingFilter' => true + ), + 'quantity' => array( + 'title' => $this->l('Quantity received'), + 'align' => 'left', + 'havingFilter' => true + ), + ); - // loads history of the given order - unset($this->_select, $this->_join, $this->_where, $this->_orderBy, $this->_orderWay, $this->_group, $this->_filterHaving, $this->_filter); - $this->_select = 'CONCAT(a.`employee_lastname`, \' \', a.`employee_firstname`) as employee'; - $this->_where = 'AND a.`id_supply_order_detail` = '.(int)$id_supply_order_detail; - $this->_orderBy = 'a.date_add'; - $this->_orderWay = 'DESC'; + // loads history of the given order + unset($this->_select, $this->_join, $this->_where, $this->_orderBy, $this->_orderWay, $this->_group, $this->_filterHaving, $this->_filter); + $this->_select = 'CONCAT(a.`employee_lastname`, \' \', a.`employee_firstname`) as employee'; + $this->_where = 'AND a.`id_supply_order_detail` = '.(int)$id_supply_order_detail; + $this->_orderBy = 'a.date_add'; + $this->_orderWay = 'DESC'; - return parent::renderList(); - } - } + return parent::renderList(); + } + } - /** - * method call when ajax request is made for search product to add to the order - * @TODO - Update this method to retreive the reference, ean13, upc corresponding to a product attribute - */ - public function ajaxProcessSearchProduct() - { - // Get the search pattern - $pattern = pSQL(Tools::getValue('q', false)); + /** + * method call when ajax request is made for search product to add to the order + * @TODO - Update this method to retreive the reference, ean13, upc corresponding to a product attribute + */ + public function ajaxProcessSearchProduct() + { + // Get the search pattern + $pattern = pSQL(Tools::getValue('q', false)); - if (!$pattern || $pattern == '' || strlen($pattern) < 1) - die(); + if (!$pattern || $pattern == '' || strlen($pattern) < 1) { + die(); + } - // get supplier id - $id_supplier = (int)Tools::getValue('id_supplier', false); + // get supplier id + $id_supplier = (int)Tools::getValue('id_supplier', false); - // gets the currency - $id_currency = (int)Tools::getValue('id_currency', false); + // gets the currency + $id_currency = (int)Tools::getValue('id_currency', false); - // get lang from context - $id_lang = (int)Context::getContext()->language->id; + // get lang from context + $id_lang = (int)Context::getContext()->language->id; - $query = new DbQuery(); - $query->select(' + $query = new DbQuery(); + $query->select(' CONCAT(p.id_product, \'_\', IFNULL(pa.id_product_attribute, \'0\')) as id, ps.product_supplier_reference as supplier_reference, IFNULL(pa.reference, IFNULL(p.reference, \'\')) as reference, @@ -1715,359 +1692,368 @@ class AdminSupplyOrdersControllerCore extends AdminController md5(CONCAT(\''._COOKIE_KEY_.'\', p.id_product, \'_\', IFNULL(pa.id_product_attribute, \'0\'))) as checksum, IFNULL(CONCAT(pl.name, \' : \', GROUP_CONCAT(DISTINCT agl.name, \' - \', al.name order by agl.name SEPARATOR \', \')), pl.name) as name '); - $query->from('product', 'p'); - $query->innerJoin('product_lang', 'pl', 'pl.id_product = p.id_product AND pl.id_lang = '.$id_lang); - $query->leftJoin('product_attribute', 'pa', 'pa.id_product = p.id_product'); - $query->leftJoin('product_attribute_combination', 'pac', 'pac.id_product_attribute = pa.id_product_attribute'); - $query->leftJoin('attribute', 'atr', 'atr.id_attribute = pac.id_attribute'); - $query->leftJoin('attribute_lang', 'al', 'al.id_attribute = atr.id_attribute AND al.id_lang = '.$id_lang); - $query->leftJoin('attribute_group_lang', 'agl', 'agl.id_attribute_group = atr.id_attribute_group AND agl.id_lang = '.$id_lang); - $query->leftJoin('product_supplier', 'ps', 'ps.id_product = p.id_product AND ps.id_product_attribute = IFNULL(pa.id_product_attribute, 0)'); - $query->where('(pl.name LIKE \'%'.$pattern.'%\' OR p.reference LIKE \'%'.$pattern.'%\' OR ps.product_supplier_reference LIKE \'%'.$pattern.'%\')'); - $query->where('NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'product_download` pd WHERE (pd.id_product = p.id_product))'); - $query->where('p.is_virtual = 0 AND p.cache_is_pack = 0'); + $query->from('product', 'p'); + $query->innerJoin('product_lang', 'pl', 'pl.id_product = p.id_product AND pl.id_lang = '.$id_lang); + $query->leftJoin('product_attribute', 'pa', 'pa.id_product = p.id_product'); + $query->leftJoin('product_attribute_combination', 'pac', 'pac.id_product_attribute = pa.id_product_attribute'); + $query->leftJoin('attribute', 'atr', 'atr.id_attribute = pac.id_attribute'); + $query->leftJoin('attribute_lang', 'al', 'al.id_attribute = atr.id_attribute AND al.id_lang = '.$id_lang); + $query->leftJoin('attribute_group_lang', 'agl', 'agl.id_attribute_group = atr.id_attribute_group AND agl.id_lang = '.$id_lang); + $query->leftJoin('product_supplier', 'ps', 'ps.id_product = p.id_product AND ps.id_product_attribute = IFNULL(pa.id_product_attribute, 0)'); + $query->where('(pl.name LIKE \'%'.$pattern.'%\' OR p.reference LIKE \'%'.$pattern.'%\' OR ps.product_supplier_reference LIKE \'%'.$pattern.'%\')'); + $query->where('NOT EXISTS (SELECT 1 FROM `'._DB_PREFIX_.'product_download` pd WHERE (pd.id_product = p.id_product))'); + $query->where('p.is_virtual = 0 AND p.cache_is_pack = 0'); - if ($id_supplier) - $query->where('ps.id_supplier = '.$id_supplier.' OR p.id_supplier = '.$id_supplier); + if ($id_supplier) { + $query->where('ps.id_supplier = '.$id_supplier.' OR p.id_supplier = '.$id_supplier); + } - $query->groupBy('p.id_product, pa.id_product_attribute'); - $items = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + $query->groupBy('p.id_product, pa.id_product_attribute'); + $items = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - foreach ($items as &$item) - { - $ids = explode('_', $item['id']); - $prices = ProductSupplier::getProductSupplierPrice($ids[0], $ids[1], $id_supplier, true); - if (count($prices)) - $item['unit_price_te'] = Tools::convertPriceFull($prices['product_supplier_price_te'], new Currency((int)$prices['id_currency']), - new Currency($id_currency) - ); - } - if ($items) - die(Tools::jsonEncode($items)); + foreach ($items as &$item) { + $ids = explode('_', $item['id']); + $prices = ProductSupplier::getProductSupplierPrice($ids[0], $ids[1], $id_supplier, true); + if (count($prices)) { + $item['unit_price_te'] = Tools::convertPriceFull($prices['product_supplier_price_te'], new Currency((int)$prices['id_currency']), + new Currency($id_currency) + ); + } + } + if ($items) { + die(Tools::jsonEncode($items)); + } - die(1); - } + die(1); + } - /** - * @see AdminController::renderView() - */ - public function renderView() - { - $this->show_toolbar = true; - $this->toolbar_scroll = false; - $this->table = 'supply_order_detail'; - $this->identifier = 'id_supply_order_detail'; - $this->className = 'SupplyOrderDetail'; - $this->colorOnBackground = false; - $this->lang = false; - $this->list_simple_header = true; - $this->list_no_link = true; + /** + * @see AdminController::renderView() + */ + public function renderView() + { + $this->show_toolbar = true; + $this->toolbar_scroll = false; + $this->table = 'supply_order_detail'; + $this->identifier = 'id_supply_order_detail'; + $this->className = 'SupplyOrderDetail'; + $this->colorOnBackground = false; + $this->lang = false; + $this->list_simple_header = true; + $this->list_no_link = true; - // gets the id supplier to view - $id_supply_order = (int)Tools::getValue('id_supply_order'); + // gets the id supplier to view + $id_supply_order = (int)Tools::getValue('id_supply_order'); - // gets global order information - $supply_order = new SupplyOrder((int)$id_supply_order); + // gets global order information + $supply_order = new SupplyOrder((int)$id_supply_order); - if (Validate::isLoadedObject($supply_order)) - { - if (!$supply_order->is_template) - $this->displayInformation($this->l('This interface allows you to display detailed information about your order.').'<br />'); - else - $this->displayInformation($this->l('This interface allows you to display detailed information about your order template.').'<br />'); + if (Validate::isLoadedObject($supply_order)) { + if (!$supply_order->is_template) { + $this->displayInformation($this->l('This interface allows you to display detailed information about your order.').'<br />'); + } else { + $this->displayInformation($this->l('This interface allows you to display detailed information about your order template.').'<br />'); + } - $lang_id = (int)$supply_order->id_lang; + $lang_id = (int)$supply_order->id_lang; - // just in case.. - unset($this->_select, $this->_join, $this->_where, $this->_orderBy, $this->_orderWay, $this->_group, $this->_filterHaving, $this->_filter); + // just in case.. + unset($this->_select, $this->_join, $this->_where, $this->_orderBy, $this->_orderWay, $this->_group, $this->_filterHaving, $this->_filter); - // gets all information on the products ordered - $this->_where = 'AND a.`id_supply_order` = '.(int)$id_supply_order; + // gets all information on the products ordered + $this->_where = 'AND a.`id_supply_order` = '.(int)$id_supply_order; - // gets the list ordered by price desc, without limit - $this->getList($lang_id, 'price_te', 'DESC', 0, false, false); + // gets the list ordered by price desc, without limit + $this->getList($lang_id, 'price_te', 'DESC', 0, false, false); - // gets the currency used in this order - $currency = new Currency($supply_order->id_currency); + // gets the currency used in this order + $currency = new Currency($supply_order->id_currency); - // gets the warehouse where products will be received - $warehouse = new Warehouse($supply_order->id_warehouse); + // gets the warehouse where products will be received + $warehouse = new Warehouse($supply_order->id_warehouse); - // sets toolbar title with order reference - if (!$supply_order->is_template) - $this->toolbar_title = sprintf($this->l('Details on supply order #%s'), $supply_order->reference); - else - $this->toolbar_title = sprintf($this->l('Details on supply order template #%s'), $supply_order->reference); - // re-defines fields_list - $this->fields_list = array( - 'supplier_reference' => array( - 'title' => $this->l('Supplier Reference'), - 'align' => 'center', - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - 'reference' => array( - 'title' => $this->l('Reference'), - 'align' => 'center', - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - 'ean13' => array( - 'title' => $this->l('EAN-13 or JAN barcode'), - 'align' => 'center', - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - 'upc' => array( - 'title' => $this->l('UPC barcode'), - 'align' => 'center', - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - 'name' => array( - 'title' => $this->l('Name'), - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - 'unit_price_te' => array( - 'title' => $this->l('Unit price (tax excl.)'), - 'align' => 'right', - 'orderby' => false, - 'filter' => false, - 'search' => false, - 'type' => 'price', - 'currency' => true, - ), - 'quantity_expected' => array( - 'title' => $this->l('Quantity'), - 'align' => 'right', - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - 'price_te' => array( - 'title' => $this->l('Price (tax excl.)'), - 'align' => 'right', - 'orderby' => false, - 'filter' => false, - 'search' => false, - 'type' => 'price', - 'currency' => true, - ), - 'discount_rate' => array( - 'title' => $this->l('Discount percentage'), - 'align' => 'right', - 'orderby' => false, - 'filter' => false, - 'search' => false, - 'suffix' => '%', - ), - 'discount_value_te' => array( - 'title' => $this->l('Discount value (tax excl.)'), - 'align' => 'right', - 'orderby' => false, - 'filter' => false, - 'search' => false, - 'type' => 'price', - 'currency' => true, - ), - 'price_with_discount_te' => array( - 'title' => $this->l('Price with product discount (tax excl.)'), - 'align' => 'right', - 'orderby' => false, - 'filter' => false, - 'search' => false, - 'type' => 'price', - 'currency' => true, - ), - 'tax_rate' => array( - 'title' => $this->l('Tax rate'), - 'align' => 'right', - 'orderby' => false, - 'filter' => false, - 'search' => false, - 'suffix' => '%', - ), - 'tax_value' => array( - 'title' => $this->l('Tax value'), - 'align' => 'right', - 'orderby' => false, - 'filter' => false, - 'search' => false, - 'type' => 'price', - 'currency' => true, - ), - 'price_ti' => array( - 'title' => $this->l('Price (tax incl.)'), - 'align' => 'right', - 'orderby' => false, - 'filter' => false, - 'search' => false, - 'type' => 'price', - 'currency' => true, - ), - ); + // sets toolbar title with order reference + if (!$supply_order->is_template) { + $this->toolbar_title = sprintf($this->l('Details on supply order #%s'), $supply_order->reference); + } else { + $this->toolbar_title = sprintf($this->l('Details on supply order template #%s'), $supply_order->reference); + } + // re-defines fields_list + $this->fields_list = array( + 'supplier_reference' => array( + 'title' => $this->l('Supplier Reference'), + 'align' => 'center', + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + 'reference' => array( + 'title' => $this->l('Reference'), + 'align' => 'center', + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + 'ean13' => array( + 'title' => $this->l('EAN-13 or JAN barcode'), + 'align' => 'center', + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + 'upc' => array( + 'title' => $this->l('UPC barcode'), + 'align' => 'center', + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + 'name' => array( + 'title' => $this->l('Name'), + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + 'unit_price_te' => array( + 'title' => $this->l('Unit price (tax excl.)'), + 'align' => 'right', + 'orderby' => false, + 'filter' => false, + 'search' => false, + 'type' => 'price', + 'currency' => true, + ), + 'quantity_expected' => array( + 'title' => $this->l('Quantity'), + 'align' => 'right', + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + 'price_te' => array( + 'title' => $this->l('Price (tax excl.)'), + 'align' => 'right', + 'orderby' => false, + 'filter' => false, + 'search' => false, + 'type' => 'price', + 'currency' => true, + ), + 'discount_rate' => array( + 'title' => $this->l('Discount percentage'), + 'align' => 'right', + 'orderby' => false, + 'filter' => false, + 'search' => false, + 'suffix' => '%', + ), + 'discount_value_te' => array( + 'title' => $this->l('Discount value (tax excl.)'), + 'align' => 'right', + 'orderby' => false, + 'filter' => false, + 'search' => false, + 'type' => 'price', + 'currency' => true, + ), + 'price_with_discount_te' => array( + 'title' => $this->l('Price with product discount (tax excl.)'), + 'align' => 'right', + 'orderby' => false, + 'filter' => false, + 'search' => false, + 'type' => 'price', + 'currency' => true, + ), + 'tax_rate' => array( + 'title' => $this->l('Tax rate'), + 'align' => 'right', + 'orderby' => false, + 'filter' => false, + 'search' => false, + 'suffix' => '%', + ), + 'tax_value' => array( + 'title' => $this->l('Tax value'), + 'align' => 'right', + 'orderby' => false, + 'filter' => false, + 'search' => false, + 'type' => 'price', + 'currency' => true, + ), + 'price_ti' => array( + 'title' => $this->l('Price (tax incl.)'), + 'align' => 'right', + 'orderby' => false, + 'filter' => false, + 'search' => false, + 'type' => 'price', + 'currency' => true, + ), + ); - //some staff before render list - foreach ($this->_list as &$item) - { - $item['discount_rate'] = Tools::ps_round($item['discount_rate'], 4); - $item['tax_rate'] = Tools::ps_round($item['tax_rate'], 4); - $item['id_currency'] = $currency->id; - } + //some staff before render list + foreach ($this->_list as &$item) { + $item['discount_rate'] = Tools::ps_round($item['discount_rate'], 4); + $item['tax_rate'] = Tools::ps_round($item['tax_rate'], 4); + $item['id_currency'] = $currency->id; + } - // unsets some buttons - unset($this->toolbar_btn['export-csv-orders']); - unset($this->toolbar_btn['export-csv-details']); - unset($this->toolbar_btn['new']); + // unsets some buttons + unset($this->toolbar_btn['export-csv-orders']); + unset($this->toolbar_btn['export-csv-details']); + unset($this->toolbar_btn['new']); - // renders list - $helper = new HelperList(); - $this->setHelperDisplay($helper); - $helper->actions = array(); - $helper->show_toolbar = false; - $helper->toolbar_btn = $this->toolbar_btn; + // renders list + $helper = new HelperList(); + $this->setHelperDisplay($helper); + $helper->actions = array(); + $helper->show_toolbar = false; + $helper->toolbar_btn = $this->toolbar_btn; - $content = $helper->generateList($this->_list, $this->fields_list); + $content = $helper->generateList($this->_list, $this->fields_list); - // display these global order informations - $this->tpl_view_vars = array( - 'supply_order_detail_content' => $content, - 'supply_order_warehouse' => (Validate::isLoadedObject($warehouse) ? $warehouse->name : ''), - 'supply_order_reference' => $supply_order->reference, - 'supply_order_supplier_name' => $supply_order->supplier_name, - 'supply_order_creation_date' => Tools::displayDate($supply_order->date_add,null , false), - 'supply_order_last_update' => Tools::displayDate($supply_order->date_upd,null , false), - 'supply_order_expected' => Tools::displayDate($supply_order->date_delivery_expected,null , false), - 'supply_order_discount_rate' => Tools::ps_round($supply_order->discount_rate, 2), - 'supply_order_total_te' => Tools::displayPrice($supply_order->total_te, $currency), - 'supply_order_discount_value_te' => Tools::displayPrice($supply_order->discount_value_te, $currency), - 'supply_order_total_with_discount_te' => Tools::displayPrice($supply_order->total_with_discount_te, $currency), - 'supply_order_total_tax' => Tools::displayPrice($supply_order->total_tax, $currency), - 'supply_order_total_ti' => Tools::displayPrice($supply_order->total_ti, $currency), - 'supply_order_currency' => $currency, - 'is_template' => $supply_order->is_template, - ); - } + // display these global order informations + $this->tpl_view_vars = array( + 'supply_order_detail_content' => $content, + 'supply_order_warehouse' => (Validate::isLoadedObject($warehouse) ? $warehouse->name : ''), + 'supply_order_reference' => $supply_order->reference, + 'supply_order_supplier_name' => $supply_order->supplier_name, + 'supply_order_creation_date' => Tools::displayDate($supply_order->date_add, null, false), + 'supply_order_last_update' => Tools::displayDate($supply_order->date_upd, null, false), + 'supply_order_expected' => Tools::displayDate($supply_order->date_delivery_expected, null, false), + 'supply_order_discount_rate' => Tools::ps_round($supply_order->discount_rate, 2), + 'supply_order_total_te' => Tools::displayPrice($supply_order->total_te, $currency), + 'supply_order_discount_value_te' => Tools::displayPrice($supply_order->discount_value_te, $currency), + 'supply_order_total_with_discount_te' => Tools::displayPrice($supply_order->total_with_discount_te, $currency), + 'supply_order_total_tax' => Tools::displayPrice($supply_order->total_tax, $currency), + 'supply_order_total_ti' => Tools::displayPrice($supply_order->total_ti, $currency), + 'supply_order_currency' => $currency, + 'is_template' => $supply_order->is_template, + ); + } - return parent::renderView(); - } + return parent::renderView(); + } - /** - * Callback used to display custom content for a given field - * @param int $id_supply_order - * @param string $tr - * @return string $content - */ - public function printExportIcons($id_supply_order, $tr) - { - $supply_order = new SupplyOrder((int)$id_supply_order); + /** + * Callback used to display custom content for a given field + * @param int $id_supply_order + * @param string $tr + * @return string $content + */ + public function printExportIcons($id_supply_order, $tr) + { + $supply_order = new SupplyOrder((int)$id_supply_order); - if (!Validate::isLoadedObject($supply_order)) - return; + if (!Validate::isLoadedObject($supply_order)) { + return; + } - $supply_order_state = new SupplyOrderState($supply_order->id_supply_order_state); - if (!Validate::isLoadedObject($supply_order_state)) - return; + $supply_order_state = new SupplyOrderState($supply_order->id_supply_order_state); + if (!Validate::isLoadedObject($supply_order_state)) { + return; + } - $content = ''; - if ($supply_order_state->editable == false) - $content .= '<a class="btn btn-default" href="'.$this->context->link->getAdminLink('AdminPdf') - .'&submitAction=generateSupplyOrderFormPDF&id_supply_order='.(int)$supply_order->id.'" title="'.$this->l('Export as PDF') - .'"><i class="icon-print"></i></a>'; - if ($supply_order_state->enclosed == true && $supply_order_state->receipt_state == true) - $content .= ' <a href="'.$this->context->link->getAdminLink('AdminSupplyOrders').'&id_supply_order='.(int)$supply_order->id.' + $content = ''; + if ($supply_order_state->editable == false) { + $content .= '<a class="btn btn-default" href="'.$this->context->link->getAdminLink('AdminPdf') + .'&submitAction=generateSupplyOrderFormPDF&id_supply_order='.(int)$supply_order->id.'" title="'.$this->l('Export as PDF') + .'"><i class="icon-print"></i></a>'; + } + if ($supply_order_state->enclosed == true && $supply_order_state->receipt_state == true) { + $content .= ' <a href="'.$this->context->link->getAdminLink('AdminSupplyOrders').'&id_supply_order='.(int)$supply_order->id.' &csv_order_details" class="btn btn-default" title='.$this->l('Export as CSV').'"> <i class="icon-table"></i></a>'; + } - return $content; - } + return $content; + } - /** - * Assigns default actions in toolbar_btn smarty var, if they are not set. - * uses override to specifically add, modify or remove items - * @see AdminSupplier::initToolbar() - */ - public function initToolbar() - { - switch ($this->display) - { - case 'update_order_state': - $this->toolbar_btn['save'] = array( - 'href' => '#', - 'desc' => $this->l('Save') - ); + /** + * Assigns default actions in toolbar_btn smarty var, if they are not set. + * uses override to specifically add, modify or remove items + * @see AdminSupplier::initToolbar() + */ + public function initToolbar() + { + switch ($this->display) { + case 'update_order_state': + $this->toolbar_btn['save'] = array( + 'href' => '#', + 'desc' => $this->l('Save') + ); - case 'update_receipt': - // Default cancel button - like old back link - if (!isset($this->no_back) || $this->no_back == false) - { - $back = Tools::safeOutput(Tools::getValue('back', '')); - if (empty($back)) - $back = self::$currentIndex.'&token='.$this->token; + case 'update_receipt': + // Default cancel button - like old back link + if (!isset($this->no_back) || $this->no_back == false) { + $back = Tools::safeOutput(Tools::getValue('back', '')); + if (empty($back)) { + $back = self::$currentIndex.'&token='.$this->token; + } - $this->toolbar_btn['cancel'] = array( - 'href' => $back, - 'desc' => $this->l('Cancel') - ); - } - break; + $this->toolbar_btn['cancel'] = array( + 'href' => $back, + 'desc' => $this->l('Cancel') + ); + } + break; - case 'add': - case 'edit': - $this->toolbar_btn['save-and-stay'] = array( - 'href' => '#', - 'desc' => $this->l('Save and stay') - ); - default: - parent::initToolbar(); - } - } + case 'add': + case 'edit': + $this->toolbar_btn['save-and-stay'] = array( + 'href' => '#', + 'desc' => $this->l('Save and stay') + ); + default: + parent::initToolbar(); + } + } - /** - * Overrides AdminController::afterAdd() - * @see AdminController::afterAdd() - * @param ObjectModel $object - * @return bool - */ - protected function afterAdd($object) - { - if (is_numeric(Tools::getValue('load_products'))) - $this->loadProducts((int)Tools::getValue('load_products')); + /** + * Overrides AdminController::afterAdd() + * @see AdminController::afterAdd() + * @param ObjectModel $object + * @return bool + */ + protected function afterAdd($object) + { + if (is_numeric(Tools::getValue('load_products'))) { + $this->loadProducts((int)Tools::getValue('load_products')); + } - $this->object = $object; - return true; - } + $this->object = $object; + return true; + } - /** - * Loads products which quantity (hysical quantity) is equal or less than $threshold - * @param int $threshold - */ - protected function loadProducts($threshold) - { - // if there is already an order - if (Tools::getValue('id_supply_order')) - $supply_order = new SupplyOrder((int)Tools::getValue('id_supply_order')); - else // else, we just created a new order - $supply_order = $this->object; + /** + * Loads products which quantity (hysical quantity) is equal or less than $threshold + * @param int $threshold + */ + protected function loadProducts($threshold) + { + // if there is already an order + if (Tools::getValue('id_supply_order')) { + $supply_order = new SupplyOrder((int)Tools::getValue('id_supply_order')); + } else { // else, we just created a new order + $supply_order = $this->object; + } - // if order is not valid, return; - if (!Validate::isLoadedObject($supply_order)) - return; + // if order is not valid, return; + if (!Validate::isLoadedObject($supply_order)) { + return; + } - // resets products if needed - if (Tools::getValue('id_supply_order')) - $supply_order->resetProducts(); + // resets products if needed + if (Tools::getValue('id_supply_order')) { + $supply_order->resetProducts(); + } - // gets products - $query = new DbQuery(); - $query->select(' + // gets products + $query = new DbQuery(); + $query->select(' ps.id_product, ps.id_product_attribute, ps.product_supplier_reference as supplier_reference, @@ -2076,170 +2062,165 @@ class AdminSupplyOrdersControllerCore extends AdminController IFNULL(pa.reference, IFNULL(p.reference, \'\')) as reference, IFNULL(pa.ean13, IFNULL(p.ean13, \'\')) as ean13, IFNULL(pa.upc, IFNULL(p.upc, \'\')) as upc'); - $query->from('product_supplier', 'ps'); - $query->leftJoin('stock', 's', ' - s.id_product = ps.id_product - AND s.id_product_attribute = ps.id_product_attribute - AND s.id_warehouse = '.(int)$supply_order->id_warehouse); - $query->innerJoin('warehouse_product_location', 'wpl', ' + $query->from('product_supplier', 'ps'); + $query->innerJoin('warehouse_product_location', 'wpl', ' wpl.id_product = ps.id_product AND wpl.id_product_attribute = ps.id_product_attribute AND wpl.id_warehouse = '.(int)$supply_order->id_warehouse.' '); - $query->leftJoin('product', 'p', 'p.id_product = ps.id_product'); - $query->leftJoin('product_attribute', 'pa', ' + $query->leftJoin('product', 'p', 'p.id_product = ps.id_product'); + $query->leftJoin('product_attribute', 'pa', ' pa.id_product_attribute = ps.id_product_attribute AND p.id_product = ps.id_product '); - $query->where('ps.id_supplier = '.(int)$supply_order->id_supplier); + $query->where('ps.id_supplier = '.(int)$supply_order->id_supplier); - // gets items - $items = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + // gets items + $items = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - // loads order currency - $order_currency = new Currency($supply_order->id_currency); - if (!Validate::isLoadedObject($order_currency)) - return; + // loads order currency + $order_currency = new Currency($supply_order->id_currency); + if (!Validate::isLoadedObject($order_currency)) { + return; + } - $manager = StockManagerFactory::getManager(); - foreach ($items as $item) - { - $diff = (int)$threshold; + $manager = StockManagerFactory::getManager(); + foreach ($items as $item) { + $diff = (int)$threshold; - if ($supply_order->is_template != 1) - { - $real_quantity = (int)$manager->getProductRealQuantities($item['id_product'], $item['id_product_attribute'], - $supply_order->id_warehouse, true); - $diff = (int)$threshold - (int)$real_quantity; - } + if ($supply_order->is_template != 1) { + $real_quantity = (int)$manager->getProductRealQuantities($item['id_product'], $item['id_product_attribute'], + $supply_order->id_warehouse, true); + $diff = (int)$threshold - (int)$real_quantity; + } - if ($diff >= 0) - { - // sets supply_order_detail - $supply_order_detail = new SupplyOrderDetail(); - $supply_order_detail->id_supply_order = $supply_order->id; - $supply_order_detail->id_currency = $order_currency->id; - $supply_order_detail->id_product = $item['id_product']; - $supply_order_detail->id_product_attribute = $item['id_product_attribute']; - $supply_order_detail->reference = $item['reference']; - $supply_order_detail->supplier_reference = $item['supplier_reference']; - $supply_order_detail->name = Product::getProductName($item['id_product'], $item['id_product_attribute'], $supply_order->id_lang); - $supply_order_detail->ean13 = $item['ean13']; - $supply_order_detail->upc = $item['upc']; - $supply_order_detail->quantity_expected = ((int)$diff == 0) ? 1 : (int)$diff; - $supply_order_detail->exchange_rate = $order_currency->conversion_rate; + if ($diff >= 0) { + // sets supply_order_detail + $supply_order_detail = new SupplyOrderDetail(); + $supply_order_detail->id_supply_order = $supply_order->id; + $supply_order_detail->id_currency = $order_currency->id; + $supply_order_detail->id_product = $item['id_product']; + $supply_order_detail->id_product_attribute = $item['id_product_attribute']; + $supply_order_detail->reference = $item['reference']; + $supply_order_detail->supplier_reference = $item['supplier_reference']; + $supply_order_detail->name = Product::getProductName($item['id_product'], $item['id_product_attribute'], $supply_order->id_lang); + $supply_order_detail->ean13 = $item['ean13']; + $supply_order_detail->upc = $item['upc']; + $supply_order_detail->quantity_expected = ((int)$diff == 0) ? 1 : (int)$diff; + $supply_order_detail->exchange_rate = $order_currency->conversion_rate; - $product_currency = new Currency($item['id_currency']); - if (Validate::isLoadedObject($product_currency)) - $supply_order_detail->unit_price_te = Tools::convertPriceFull($item['unit_price_te'], $product_currency, $order_currency); - else - $supply_order_detail->unit_price_te = 0; - $supply_order_detail->save(); - unset($product_currency); - } - } + $product_currency = new Currency($item['id_currency']); + if (Validate::isLoadedObject($product_currency)) { + $supply_order_detail->unit_price_te = Tools::convertPriceFull($item['unit_price_te'], $product_currency, $order_currency); + } else { + $supply_order_detail->unit_price_te = 0; + } + $supply_order_detail->save(); + unset($product_currency); + } + } - // updates supply order - $supply_order->update(); + // updates supply order + $supply_order->update(); + } - } + /** + * Overrides AdminController::beforeAdd() + * @see AdminController::beforeAdd() + * + * @param SupplyOrder $object + * + * @return true + */ + public function beforeAdd($object) + { + if (Tools::isSubmit('is_template')) { + $object->is_template = 1; + } - /** - * Overrides AdminController::beforeAdd() - * @see AdminController::beforeAdd() - * - * @param SupplyOrder $object - * - * @return true - */ - public function beforeAdd($object) - { - if (Tools::isSubmit('is_template')) - $object->is_template = 1; + return true; + } - return true; - } + /** + * Helper function for AdminSupplyOrdersController::postProcess() + * @see AdminSupplyOrdersController::postProcess() + */ + protected function postProcessCopyFromTemplate() + { + // gets SupplyOrder and checks if it is valid + $id_supply_order = (int)Tools::getValue('id_supply_order'); + $supply_order = new SupplyOrder($id_supply_order); + if (!Validate::isLoadedObject($supply_order)) { + $this->errors[] = Tools::displayError('This template could not be copied.'); + } - /** - * Helper function for AdminSupplyOrdersController::postProcess() - * @see AdminSupplyOrdersController::postProcess() - */ - protected function postProcessCopyFromTemplate() - { - // gets SupplyOrder and checks if it is valid - $id_supply_order = (int)Tools::getValue('id_supply_order'); - $supply_order = new SupplyOrder($id_supply_order); - if (!Validate::isLoadedObject($supply_order)) - $this->errors[] = Tools::displayError('This template could not be copied.'); + // gets SupplyOrderDetail + $entries = $supply_order->getEntriesCollection($supply_order->id_lang); - // gets SupplyOrderDetail - $entries = $supply_order->getEntriesCollection($supply_order->id_lang); + // updates SupplyOrder so that it is not a template anymore + $language = new Language($supply_order->id_lang); + $ref = $supply_order->reference; + $ref .= ' ('.date($language->date_format_full).')'; + $supply_order->reference = $ref; + $supply_order->is_template = 0; + $supply_order->id = (int)0; + $supply_order->save(); - // updates SupplyOrder so that it is not a template anymore - $language = new Language($supply_order->id_lang); - $ref = $supply_order->reference; - $ref .= ' ('.date($language->date_format_full).')'; - $supply_order->reference = $ref; - $supply_order->is_template = 0; - $supply_order->id = (int)0; - $supply_order->save(); + // copies SupplyOrderDetail + foreach ($entries as $entry) { + $entry->id_supply_order = $supply_order->id; + $entry->id = (int)0; + $entry->save(); + } - // copies SupplyOrderDetail - foreach ($entries as $entry) - { - $entry->id_supply_order = $supply_order->id; - $entry->id = (int)0; - $entry->save(); - } + // redirect when done + $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; + $redirect = self::$currentIndex.'&token='.$token; + $this->redirect_after = $redirect.'&conf=19'; + } - // redirect when done - $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; - $redirect = self::$currentIndex.'&token='.$token; - $this->redirect_after = $redirect.'&conf=19'; - } + /** + * Gets the current warehouse used + * + * @return int id_warehouse + */ + protected function getCurrentWarehouse() + { + static $warehouse = 0; - /** - * Gets the current warehouse used - * - * @return int id_warehouse - */ - protected function getCurrentWarehouse() - { - static $warehouse = 0; + if ($warehouse == 0) { + $warehouse = -1; // all warehouses + if ((int)Tools::getValue('id_warehouse')) { + $warehouse = (int)Tools::getValue('id_warehouse'); + } + } + return $warehouse; + } - if ($warehouse == 0) - { - $warehouse = -1; // all warehouses - if ((int)Tools::getValue('id_warehouse')) - $warehouse = (int)Tools::getValue('id_warehouse'); - } - return $warehouse; - } + /** + * Gets the current filter used + * + * @return int status + */ + protected function getFilterStatus() + { + static $status = 0; - /** - * Gets the current filter used - * - * @return int status - */ - protected function getFilterStatus() - { - static $status = 0; + $status = 0; + if (Tools::getValue('filter_status') === 'on') { + $status = 1; + } - $status = 0; - if (Tools::getValue('filter_status') === 'on') - $status = 1; + return $status; + } - return $status; - } - - public function initProcess() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = - $this->l('You need to activate advanced stock management prior to using this feature.'); - return false; - } - parent::initProcess(); - } + public function initProcess() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = + $this->l('You need to activate advanced stock management prior to using this feature.'); + return false; + } + parent::initProcess(); + } } diff --git a/controllers/admin/AdminTabsController.php b/controllers/admin/AdminTabsController.php index ade5fc46..ebb43aa6 100644 --- a/controllers/admin/AdminTabsController.php +++ b/controllers/admin/AdminTabsController.php @@ -29,354 +29,349 @@ */ class AdminTabsControllerCore extends AdminController { - protected $position_identifier = 'id_tab'; + protected $position_identifier = 'id_tab'; - public function __construct() - { - $this->bootstrap = true; - $this->context = Context::getContext(); - $this->multishop_context = Shop::CONTEXT_ALL; - $this->table = 'tab'; - $this->list_id = 'tab'; - $this->className = 'Tab'; - $this->lang = true; - $this->fieldImageSettings = array( - 'name' => 'icon', - 'dir' => 't' - ); - $this->imageType = 'gif'; - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); - $this->fields_list = array( - 'id_tab' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Name') - ), - 'class_name' => array( - 'title' => $this->l('Class') - ), - 'module' => array( - 'title' => $this->l('Module') - ), - 'active' => array( - 'title' => $this->l('Enabled'), - 'align' => 'center', - 'active' => 'status', - 'type' => 'bool', - 'orderby' => false - ), - 'position' => array( - 'title' => $this->l('Position'), - 'filter_key' => 'a!position', - 'position' => 'position', - 'align' => 'center', - 'class' => 'fixed-width-md' - ) - ); + public function __construct() + { + $this->bootstrap = true; + $this->context = Context::getContext(); + $this->multishop_context = Shop::CONTEXT_ALL; + $this->table = 'tab'; + $this->list_id = 'tab'; + $this->className = 'Tab'; + $this->lang = true; + $this->fieldImageSettings = array( + 'name' => 'icon', + 'dir' => 't' + ); + $this->imageType = 'gif'; + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); + $this->fields_list = array( + 'id_tab' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Name') + ), + 'class_name' => array( + 'title' => $this->l('Class') + ), + 'module' => array( + 'title' => $this->l('Module') + ), + 'active' => array( + 'title' => $this->l('Enabled'), + 'align' => 'center', + 'active' => 'status', + 'type' => 'bool', + 'orderby' => false + ), + 'position' => array( + 'title' => $this->l('Position'), + 'filter_key' => 'a!position', + 'position' => 'position', + 'align' => 'center', + 'class' => 'fixed-width-md' + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - $this->page_header_toolbar_title = $this->l('Menus'); + public function initPageHeaderToolbar() + { + $this->page_header_toolbar_title = $this->l('Menus'); - if ($this->display == 'details') - $this->page_header_toolbar_btn['back_to_list'] = array( - 'href' => Context::getContext()->link->getAdminLink('AdminTabs'), - 'desc' => $this->l('Back to list', null, null, false), - 'icon' => 'process-icon-back' - ); - elseif(empty($this->display)) - $this->page_header_toolbar_btn['new_menu'] = array( - 'href' => self::$currentIndex.'&addtab&token='.$this->token, - 'desc' => $this->l('Add new menu', null, null, false), - 'icon' => 'process-icon-new' - ); + if ($this->display == 'details') { + $this->page_header_toolbar_btn['back_to_list'] = array( + 'href' => Context::getContext()->link->getAdminLink('AdminTabs'), + 'desc' => $this->l('Back to list', null, null, false), + 'icon' => 'process-icon-back' + ); + } elseif (empty($this->display)) { + $this->page_header_toolbar_btn['new_menu'] = array( + 'href' => self::$currentIndex.'&addtab&token='.$this->token, + 'desc' => $this->l('Add new menu', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - /** - * AdminController::renderForm() override - * @see AdminController::renderForm() - */ - public function renderForm() - { - $tabs = Tab::getTabs($this->context->language->id, 0); - // If editing, we clean itself - if (Tools::isSubmit('id_tab')) - foreach ($tabs as $key => $tab) - if ($tab['id_tab'] == Tools::getValue('id_tab')) - unset($tabs[$key]); + /** + * AdminController::renderForm() override + * @see AdminController::renderForm() + */ + public function renderForm() + { + $tabs = Tab::getTabs($this->context->language->id, 0); + // If editing, we clean itself + if (Tools::isSubmit('id_tab')) { + foreach ($tabs as $key => $tab) { + if ($tab['id_tab'] == Tools::getValue('id_tab')) { + unset($tabs[$key]); + } + } + } - // added category "Home" in var $tabs - $tab_zero = array( - 'id_tab' => 0, - 'name' => $this->l('Home') - ); - array_unshift($tabs, $tab_zero); + // added category "Home" in var $tabs + $tab_zero = array( + 'id_tab' => 0, + 'name' => $this->l('Home') + ); + array_unshift($tabs, $tab_zero); - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Menus'), - 'icon' => 'icon-list-ul' - ), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'position', - 'required' => false - ), - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'lang' => true, - 'required' => true, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'text', - 'label' => $this->l('Class'), - 'name' => 'class_name', - 'required' => true - ), - array( - 'type' => 'text', - 'label' => $this->l('Module'), - 'name' => 'module' - ), - array( - 'type' => 'switch', - 'label' => $this->l('Status'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Show or hide menu.') - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Menus'), + 'icon' => 'icon-list-ul' + ), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'position', + 'required' => false + ), + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'lang' => true, + 'required' => true, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'text', + 'label' => $this->l('Class'), + 'name' => 'class_name', + 'required' => true + ), + array( + 'type' => 'text', + 'label' => $this->l('Module'), + 'name' => 'module' + ), + array( + 'type' => 'switch', + 'label' => $this->l('Status'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Show or hide menu.') + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - $display_parent = true; - if (Validate::isLoadedObject($this->object) && !class_exists($this->object->class_name.'Controller')) - $display_parent = false; + $display_parent = true; + if (Validate::isLoadedObject($this->object) && !class_exists($this->object->class_name.'Controller')) { + $display_parent = false; + } - if ($display_parent) - $this->fields_form['input'][] = array( - 'type' => 'select', - 'label' => $this->l('Parent'), - 'name' => 'id_parent', - 'options' => array( - 'query' => $tabs, - 'id' => 'id_tab', - 'name' => 'name' - ) - ); + if ($display_parent) { + $this->fields_form['input'][] = array( + 'type' => 'select', + 'label' => $this->l('Parent'), + 'name' => 'id_parent', + 'options' => array( + 'query' => $tabs, + 'id' => 'id_tab', + 'name' => 'name' + ) + ); + } - return parent::renderForm(); - } + return parent::renderForm(); + } - /** - * AdminController::renderList() override - * @see AdminController::renderList() - */ - public function renderList() - { - $this->addRowAction('edit'); - $this->addRowAction('details'); - $this->addRowAction('delete'); + /** + * AdminController::renderList() override + * @see AdminController::renderList() + */ + public function renderList() + { + $this->addRowAction('edit'); + $this->addRowAction('details'); + $this->addRowAction('delete'); - $this->_where = 'AND a.`id_parent` = 0'; - $this->_orderBy = 'position'; + $this->_where = 'AND a.`id_parent` = 0'; + $this->_orderBy = 'position'; - return parent::renderList(); - } + return parent::renderList(); + } - public function initProcess() - { - if (Tools::getIsset('details'.$this->table)) - { - $this->list_id = 'details'; + public function initProcess() + { + if (Tools::getIsset('details'.$this->table)) { + $this->list_id = 'details'; - if (isset($_POST['submitReset'.$this->list_id])) - $this->processResetFilters(); - } - else - $this->list_id = 'tab'; + if (isset($_POST['submitReset'.$this->list_id])) { + $this->processResetFilters(); + } + } else { + $this->list_id = 'tab'; + } - return parent::initProcess(); - } + return parent::initProcess(); + } - public function renderDetails() - { - if (($id = Tools::getValue('id_tab'))) - { - $this->lang = false; - $this->list_id = 'details'; - $this->addRowAction('edit'); - $this->addRowAction('delete'); - $this->toolbar_btn = array(); + public function renderDetails() + { + if (($id = Tools::getValue('id_tab'))) { + $this->lang = false; + $this->list_id = 'details'; + $this->addRowAction('edit'); + $this->addRowAction('delete'); + $this->toolbar_btn = array(); - /** @var Tab $tab */ - $tab = $this->loadObject($id); - $this->toolbar_title = $tab->name[$this->context->employee->id_lang]; + /** @var Tab $tab */ + $tab = $this->loadObject($id); + $this->toolbar_title = $tab->name[$this->context->employee->id_lang]; - $this->_select = 'b.*'; - $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'tab_lang` b ON (b.`id_tab` = a.`id_tab` AND b.`id_lang` = '.$this->context->language->id.')'; - $this->_where = 'AND a.`id_parent` = '.(int)$id; - $this->_orderBy = 'position'; - $this->_use_found_rows = false; + $this->_select = 'b.*'; + $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'tab_lang` b ON (b.`id_tab` = a.`id_tab` AND b.`id_lang` = '.$this->context->language->id.')'; + $this->_where = 'AND a.`id_parent` = '.(int)$id; + $this->_orderBy = 'position'; + $this->_use_found_rows = false; - self::$currentIndex = self::$currentIndex.'&details'.$this->table; - $this->processFilter(); - return parent::renderList(); - } - } + self::$currentIndex = self::$currentIndex.'&details'.$this->table; + $this->processFilter(); + return parent::renderList(); + } + } - public function postProcess() - { - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } - /* PrestaShop demo mode*/ + public function postProcess() + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } + /* PrestaShop demo mode*/ - if (($id_tab = (int)Tools::getValue('id_tab')) && ($direction = Tools::getValue('move')) && Validate::isLoadedObject($tab = new Tab($id_tab))) - { - if ($tab->move($direction)) - Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); - } - elseif (Tools::getValue('position') && !Tools::isSubmit('submitAdd'.$this->table)) - { - if ($this->tabAccess['edit'] !== '1') - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - elseif (!Validate::isLoadedObject($object = new Tab((int)Tools::getValue($this->identifier)))) - $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.'). - ' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - if (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) - $this->errors[] = Tools::displayError('Failed to update the position.'); - else - Tools::redirectAdmin(self::$currentIndex.'&conf=5&token='.Tools::getAdminTokenLite('AdminTabs')); - } - elseif (Tools::isSubmit('submitAdd'.$this->table) && Tools::getValue('id_tab') === Tools::getValue('id_parent')) - $this->errors[] = Tools::displayError('You can\'t put this menu inside itself. '); - elseif (Tools::isSubmit('submitAdd'.$this->table) && $id_parent = (int)Tools::getValue('id_parent')) - $this->redirect_after = self::$currentIndex.'&id_'.$this->table.'='.$id_parent.'&details'.$this->table.'&conf=4&token='.$this->token; - elseif (isset($_GET['details'.$this->table]) && is_array($this->bulk_actions)) - { - $submit_bulk_actions = array_merge(array( - 'enableSelection' => array( - 'text' => $this->l('Enable selection'), - 'icon' => 'icon-power-off text-success' - ), - 'disableSelection' => array( - 'text' => $this->l('Disable selection'), - 'icon' => 'icon-power-off text-danger' - ) - ), $this->bulk_actions); - foreach ($submit_bulk_actions as $bulk_action => $params) - { - if (Tools::isSubmit('submitBulk'.$bulk_action.$this->table) || Tools::isSubmit('submitBulk'.$bulk_action)) - { - if ($this->tabAccess['edit'] === '1') - { - $this->action = 'bulk'.$bulk_action; - $this->boxes = Tools::getValue($this->list_id.'Box'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - break; - } - elseif (Tools::isSubmit('submitBulk')) - { - if ($this->tabAccess['edit'] === '1') - { - $this->action = 'bulk'.Tools::getValue('select_submitBulk'); - $this->boxes = Tools::getValue($this->list_id.'Box'); - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - break; - } - } - } - else - { - // Temporary add the position depend of the selection of the parent category - if (!Tools::isSubmit('id_tab')) // @todo Review - $_POST['position'] = Tab::getNbTabs(Tools::getValue('id_parent')); - } + if (($id_tab = (int)Tools::getValue('id_tab')) && ($direction = Tools::getValue('move')) && Validate::isLoadedObject($tab = new Tab($id_tab))) { + if ($tab->move($direction)) { + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } + } elseif (Tools::getValue('position') && !Tools::isSubmit('submitAdd'.$this->table)) { + if ($this->tabAccess['edit'] !== '1') { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } elseif (!Validate::isLoadedObject($object = new Tab((int)Tools::getValue($this->identifier)))) { + $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.'). + ' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } + if (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position'))) { + $this->errors[] = Tools::displayError('Failed to update the position.'); + } else { + Tools::redirectAdmin(self::$currentIndex.'&conf=5&token='.Tools::getAdminTokenLite('AdminTabs')); + } + } elseif (Tools::isSubmit('submitAdd'.$this->table) && Tools::getValue('id_tab') === Tools::getValue('id_parent')) { + $this->errors[] = Tools::displayError('You can\'t put this menu inside itself. '); + } elseif (Tools::isSubmit('submitAdd'.$this->table) && $id_parent = (int)Tools::getValue('id_parent')) { + $this->redirect_after = self::$currentIndex.'&id_'.$this->table.'='.$id_parent.'&details'.$this->table.'&conf=4&token='.$this->token; + } elseif (isset($_GET['details'.$this->table]) && is_array($this->bulk_actions)) { + $submit_bulk_actions = array_merge(array( + 'enableSelection' => array( + 'text' => $this->l('Enable selection'), + 'icon' => 'icon-power-off text-success' + ), + 'disableSelection' => array( + 'text' => $this->l('Disable selection'), + 'icon' => 'icon-power-off text-danger' + ) + ), $this->bulk_actions); + foreach ($submit_bulk_actions as $bulk_action => $params) { + if (Tools::isSubmit('submitBulk'.$bulk_action.$this->table) || Tools::isSubmit('submitBulk'.$bulk_action)) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'bulk'.$bulk_action; + $this->boxes = Tools::getValue($this->list_id.'Box'); + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + break; + } elseif (Tools::isSubmit('submitBulk')) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'bulk'.Tools::getValue('select_submitBulk'); + $this->boxes = Tools::getValue($this->list_id.'Box'); + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + break; + } + } + } else { + // Temporary add the position depend of the selection of the parent category + if (!Tools::isSubmit('id_tab')) { // @todo Review + $_POST['position'] = Tab::getNbTabs(Tools::getValue('id_parent')); + } + } - if (!count($this->errors)) - parent::postProcess(); + if (!count($this->errors)) { + parent::postProcess(); + } + } - } + protected function afterImageUpload() + { + /** @var Tab $obj */ + if (!($obj = $this->loadObject(true))) { + return; + } + @rename(_PS_IMG_DIR_.'t/'.$obj->id.'.gif', _PS_IMG_DIR_.'t/'.$obj->class_name.'.gif'); + } - protected function afterImageUpload() - { - /** @var Tab $obj */ - if (!($obj = $this->loadObject(true))) - return; - @rename(_PS_IMG_DIR_.'t/'.$obj->id.'.gif', _PS_IMG_DIR_.'t/'.$obj->class_name.'.gif'); - } + public function ajaxProcessUpdatePositions() + { + $way = (int)(Tools::getValue('way')); + $id_tab = (int)(Tools::getValue('id')); + $positions = Tools::getValue('tab'); - public function ajaxProcessUpdatePositions() - { - $way = (int)(Tools::getValue('way')); - $id_tab = (int)(Tools::getValue('id')); - $positions = Tools::getValue('tab'); + // when changing positions in a tab sub-list, the first array value is empty and needs to be removed + if (!$positions[0]) { + unset($positions[0]); + // reset indexation from 0 + $positions = array_merge($positions); + } - // when changing positions in a tab sub-list, the first array value is empty and needs to be removed - if (!$positions[0]) - { - unset($positions[0]); - // reset indexation from 0 - $positions = array_merge($positions); - } + foreach ($positions as $position => $value) { + $pos = explode('_', $value); - foreach ($positions as $position => $value) - { - $pos = explode('_', $value); + if (isset($pos[2]) && (int)$pos[2] === $id_tab) { + if ($tab = new Tab((int)$pos[2])) { + if (isset($position) && $tab->updatePosition($way, $position)) { + echo 'ok position '.(int)$position.' for tab '.(int)$pos[1].'\r\n'; + } else { + echo '{"hasError" : true, "errors" : "Can not update tab '.(int)$id_tab.' to position '.(int)$position.' "}'; + } + } else { + echo '{"hasError" : true, "errors" : "This tab ('.(int)$id_tab.') can t be loaded"}'; + } - if (isset($pos[2]) && (int)$pos[2] === $id_tab) - { - if ($tab = new Tab((int)$pos[2])) - if (isset($position) && $tab->updatePosition($way, $position)) - echo 'ok position '.(int)$position.' for tab '.(int)$pos[1].'\r\n'; - else - echo '{"hasError" : true, "errors" : "Can not update tab '.(int)$id_tab.' to position '.(int)$position.' "}'; - else - echo '{"hasError" : true, "errors" : "This tab ('.(int)$id_tab.') can t be loaded"}'; - - break; - } - } - } + break; + } + } + } } diff --git a/controllers/admin/AdminTagsController.php b/controllers/admin/AdminTagsController.php index 5adc4be4..9c85c1eb 100644 --- a/controllers/admin/AdminTagsController.php +++ b/controllers/admin/AdminTagsController.php @@ -29,137 +29,140 @@ */ class AdminTagsControllerCore extends AdminController { - public $bootstrap = true; + public $bootstrap = true; - public function __construct() - { - $this->table = 'tag'; - $this->className = 'Tag'; + public function __construct() + { + $this->table = 'tag'; + $this->className = 'Tag'; - $this->fields_list = array( - 'id_tag' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'lang' => array( - 'title' => $this->l('Language'), - 'filter_key' => 'l!name' - ), - 'name' => array( - 'title' => $this->l('Name'), - 'filter_key' => 'a!name' - ), - 'products' => array( - 'title' => $this->l('Products'), - 'align' => 'center', - 'class' => 'fixed-width-xs', - 'havingFilter' => true - ) - ); + $this->fields_list = array( + 'id_tag' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'lang' => array( + 'title' => $this->l('Language'), + 'filter_key' => 'l!name' + ), + 'name' => array( + 'title' => $this->l('Name'), + 'filter_key' => 'a!name' + ), + 'products' => array( + 'title' => $this->l('Products'), + 'align' => 'center', + 'class' => 'fixed-width-xs', + 'havingFilter' => true + ) + ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'icon' => 'icon-trash', - 'confirm' => $this->l('Delete selected items?') - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'icon' => 'icon-trash', + 'confirm' => $this->l('Delete selected items?') + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_tag'] = array( - 'href' => self::$currentIndex.'&addtag&token='.$this->token, - 'desc' => $this->l('Add new tag', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_tag'] = array( + 'href' => self::$currentIndex.'&addtag&token='.$this->token, + 'desc' => $this->l('Add new tag', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderList() - { - $this->addRowAction('edit'); - $this->addRowAction('delete'); + public function renderList() + { + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->_select = 'l.name as lang, COUNT(pt.id_product) as products'; - $this->_join = ' + $this->_select = 'l.name as lang, COUNT(pt.id_product) as products'; + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'product_tag` pt ON (a.`id_tag` = pt.`id_tag`) LEFT JOIN `'._DB_PREFIX_.'lang` l ON (l.`id_lang` = a.`id_lang`)'; - $this->_group = 'GROUP BY a.name, a.id_lang'; + $this->_group = 'GROUP BY a.name, a.id_lang'; - return parent::renderList(); - } + return parent::renderList(); + } - public function postProcess() - { - if ($this->tabAccess['edit'] === '1' && Tools::getValue('submitAdd'.$this->table)) - { - if (($id = (int)Tools::getValue($this->identifier)) && ($obj = new $this->className($id)) && Validate::isLoadedObject($obj)) - { - /** @var Tag $obj */ - $previous_products = $obj->getProducts(); - $removed_products = array(); + public function postProcess() + { + if ($this->tabAccess['edit'] === '1' && Tools::getValue('submitAdd'.$this->table)) { + if (($id = (int)Tools::getValue($this->identifier)) && ($obj = new $this->className($id)) && Validate::isLoadedObject($obj)) { + /** @var Tag $obj */ + $previous_products = $obj->getProducts(); + $removed_products = array(); - foreach ($previous_products as $product) - if (!in_array($product['id_product'], $_POST['products'])) - $removed_products[] = $product['id_product']; + foreach ($previous_products as $product) { + if (!in_array($product['id_product'], $_POST['products'])) { + $removed_products[] = $product['id_product']; + } + } - if (Configuration::get('PS_SEARCH_INDEXATION')) - Search::removeProductsSearchIndex($removed_products); + if (Configuration::get('PS_SEARCH_INDEXATION')) { + Search::removeProductsSearchIndex($removed_products); + } - $obj->setProducts($_POST['products']); - } - } + $obj->setProducts($_POST['products']); + } + } - return parent::postProcess(); - } + return parent::postProcess(); + } - public function renderForm() - { - /** @var Tag $obj */ - if (!($obj = $this->loadObject(true))) - return; + public function renderForm() + { + /** @var Tag $obj */ + if (!($obj = $this->loadObject(true))) { + return; + } - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Tag'), - 'icon' => 'icon-tag' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'required' => true - ), - array( - 'type' => 'select', - 'label' => $this->l('Language'), - 'name' => 'id_lang', - 'required' => true, - 'options' => array( - 'query' => Language::getLanguages(false), - 'id' => 'id_lang', - 'name' => 'name' - ) - ), - ), - 'selects' => array( - 'products' => $obj->getProducts(true), - 'products_unselected' => $obj->getProducts(false) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Tag'), + 'icon' => 'icon-tag' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'required' => true + ), + array( + 'type' => 'select', + 'label' => $this->l('Language'), + 'name' => 'id_lang', + 'required' => true, + 'options' => array( + 'query' => Language::getLanguages(false), + 'id' => 'id_lang', + 'name' => 'name' + ) + ), + ), + 'selects' => array( + 'products' => $obj->getProducts(true), + 'products_unselected' => $obj->getProducts(false) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); - return parent::renderForm(); - } -} \ No newline at end of file + return parent::renderForm(); + } +} diff --git a/controllers/admin/AdminTaxRulesGroupController.php b/controllers/admin/AdminTaxRulesGroupController.php index d1392dae..a7dd3fb7 100644 --- a/controllers/admin/AdminTaxRulesGroupController.php +++ b/controllers/admin/AdminTaxRulesGroupController.php @@ -29,549 +29,540 @@ */ class AdminTaxRulesGroupControllerCore extends AdminController { - public $tax_rule; - public $selected_countries = array(); - public $selected_states = array(); - public $errors_tax_rule; + public $tax_rule; + public $selected_countries = array(); + public $selected_states = array(); + public $errors_tax_rule; - public function __construct() - { - $this->bootstrap = true; - $this->table = 'tax_rules_group'; - $this->className = 'TaxRulesGroup'; - $this->lang = false; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'tax_rules_group'; + $this->className = 'TaxRulesGroup'; + $this->lang = false; - $this->context = Context::getContext(); + $this->context = Context::getContext(); - $this->fields_list = array( - 'id_tax_rules_group' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Name') - ), - 'active' => array( - 'title' => $this->l('Enabled'), - 'active' => 'status', - 'type' => 'bool', - 'orderby' => false, - 'align' => 'center', - 'class' => 'fixed-width-sm' - ) - ); + $this->fields_list = array( + 'id_tax_rules_group' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Name') + ), + 'active' => array( + 'title' => $this->l('Enabled'), + 'active' => 'status', + 'type' => 'bool', + 'orderby' => false, + 'align' => 'center', + 'class' => 'fixed-width-sm' + ) + ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->_where .= ' AND a.deleted = 0'; + $this->_where .= ' AND a.deleted = 0'; - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_tax_rules_group'] = array( - 'href' => self::$currentIndex.'&addtax_rules_group&token='.$this->token, - 'desc' => $this->l('Add new tax rules group', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_tax_rules_group'] = array( + 'href' => self::$currentIndex.'&addtax_rules_group&token='.$this->token, + 'desc' => $this->l('Add new tax rules group', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderList() - { - $this->addRowAction('edit'); - $this->addRowAction('delete'); + public function renderList() + { + $this->addRowAction('edit'); + $this->addRowAction('delete'); - return parent::renderList(); - } + return parent::renderList(); + } - public function initRulesList($id_group) - { - $this->table = 'tax_rule'; - $this->list_id = 'tax_rule'; - $this->identifier = 'id_tax_rule'; - $this->className = 'TaxRule'; - $this->lang = false; - $this->list_simple_header = false; - $this->toolbar_btn = null; - $this->list_no_link = true; + public function initRulesList($id_group) + { + $this->table = 'tax_rule'; + $this->list_id = 'tax_rule'; + $this->identifier = 'id_tax_rule'; + $this->className = 'TaxRule'; + $this->lang = false; + $this->list_simple_header = false; + $this->toolbar_btn = null; + $this->list_no_link = true; - $this->bulk_actions = array( - 'delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?'), 'icon' => 'icon-trash') - ); + $this->bulk_actions = array( + 'delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?'), 'icon' => 'icon-trash') + ); - $this->fields_list = array( - 'country_name' => array( - 'title' => $this->l('Country') - ), - 'state_name' => array( - 'title' => $this->l('State') - ), - 'zipcode' => array( - 'title' => $this->l('Zip/Postal code'), - 'class' => 'fixed-width-md' - ), - 'behavior' => array( - 'title' => $this->l('Behavior') - ), - 'rate' => array( - 'title' => $this->l('Tax'), - 'class' => 'fixed-width-sm' - ), - 'description' => array( - 'title' => $this->l('Description') - ) - ); + $this->fields_list = array( + 'country_name' => array( + 'title' => $this->l('Country') + ), + 'state_name' => array( + 'title' => $this->l('State') + ), + 'zipcode' => array( + 'title' => $this->l('Zip/Postal code'), + 'class' => 'fixed-width-md' + ), + 'behavior' => array( + 'title' => $this->l('Behavior') + ), + 'rate' => array( + 'title' => $this->l('Tax'), + 'class' => 'fixed-width-sm' + ), + 'description' => array( + 'title' => $this->l('Description') + ) + ); - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->_select = ' + $this->_select = ' c.`name` AS country_name, s.`name` AS state_name, CONCAT_WS(" - ", a.`zipcode_from`, a.`zipcode_to`) AS zipcode, t.rate'; - $this->_join = ' + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'country_lang` c ON (a.`id_country` = c.`id_country` AND id_lang = '.(int)$this->context->language->id.') LEFT JOIN `'._DB_PREFIX_.'state` s ON (a.`id_state` = s.`id_state`) LEFT JOIN `'._DB_PREFIX_.'tax` t ON (a.`id_tax` = t.`id_tax`)'; - $this->_where = 'AND `id_tax_rules_group` = '.(int)$id_group; - $this->_use_found_rows = false; + $this->_where = 'AND `id_tax_rules_group` = '.(int)$id_group; + $this->_use_found_rows = false; - $this->show_toolbar = false; - $this->tpl_list_vars = array('id_tax_rules_group' => (int)$id_group); + $this->show_toolbar = false; + $this->tpl_list_vars = array('id_tax_rules_group' => (int)$id_group); - $this->_filter = false; + $this->_filter = false; - return parent::renderList(); - } + return parent::renderList(); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Tax Rules'), - 'icon' => 'icon-money' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'required' => true, - 'hint' => $this->l('Invalid characters:').' <>;=#{}' - ), - array( - 'type' => 'switch', - 'label' => $this->l('Enable'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ) - ) - ), - 'submit' => array( - 'title' => $this->l('Save and stay'), - 'stay' => true - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Tax Rules'), + 'icon' => 'icon-money' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'required' => true, + 'hint' => $this->l('Invalid characters:').' <>;=#{}' + ), + array( + 'type' => 'switch', + 'label' => $this->l('Enable'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ) + ) + ), + 'submit' => array( + 'title' => $this->l('Save and stay'), + 'stay' => true + ) + ); - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - if (!($obj = $this->loadObject(true))) - return; - if (!isset($obj->id)) - { - $this->no_back = false; - $content = parent::renderForm(); - } - else - { - $this->no_back = true; - $this->page_header_toolbar_btn['new'] = array( - 'href' => '#', - 'desc' => $this->l('Add a new tax rule') - ); - $content = parent::renderForm(); - $this->tpl_folder = 'tax_rules/'; - $content .= $this->initRuleForm(); + if (!($obj = $this->loadObject(true))) { + return; + } + if (!isset($obj->id)) { + $this->no_back = false; + $content = parent::renderForm(); + } else { + $this->no_back = true; + $this->page_header_toolbar_btn['new'] = array( + 'href' => '#', + 'desc' => $this->l('Add a new tax rule') + ); + $content = parent::renderForm(); + $this->tpl_folder = 'tax_rules/'; + $content .= $this->initRuleForm(); - // We change the variable $ tpl_folder to avoid the overhead calling the file in list_action_edit.tpl in intList (); + // We change the variable $ tpl_folder to avoid the overhead calling the file in list_action_edit.tpl in intList (); - $content .= $this->initRulesList((int)$obj->id); - } - return $content; - } + $content .= $this->initRulesList((int)$obj->id); + } + return $content; + } - public function initRuleForm() - { - $this->fields_form[0]['form'] = array( - 'legend' => array( - 'title' => $this->l('New tax rule'), - 'icon' => 'icon-money' - ), - 'input' => array( - array( - 'type' => 'select', - 'label' => $this->l('Country'), - 'name' => 'country', - 'id' => 'country', - 'options' => array( - 'query' => Country::getCountries($this->context->language->id), - 'id' => 'id_country', - 'name' => 'name', - 'default' => array( - 'value' => 0, - 'label' => $this->l('All', 'AdminTaxRulesGroupController') - ) - ) - ), - array( - 'type' => 'select', - 'label' => $this->l('State'), - 'name' => 'states[]', - 'id' => 'states', - 'multiple' => true, - 'options' => array( - 'query' => array(), - 'id' => 'id_state', - 'name' => 'name', - 'default' => array( - 'value' => 0, - 'label' => $this->l('All', 'AdminTaxRulesGroupController') - ) - ) - ), - array( - 'type' => 'hidden', - 'name' => 'action' - ), - array( - 'type' => 'text', - 'label' => $this->l('Zip/postal code range'), - 'name' => 'zipcode', - 'required' => false, - 'hint' => $this->l('You can define a range of Zip/postal codes (e.g., 75000-75015) or simply use one Zip/postal code.') - ), - array( - 'type' => 'select', - 'label' => $this->l('Behavior'), - 'name' => 'behavior', - 'required' => false, - 'options' => array( - 'query' => array( - array( - 'id' => 0, - 'name' => $this->l('This tax only') - ), - array( - 'id' => 1, - 'name' => $this->l('Combine') - ), - array( - 'id' => 2, - 'name' => $this->l('One after another') - ) - ), - 'id' => 'id', - 'name' => 'name' - ), - 'hint' => array( - $this->l('You must define the behavior if an address matches multiple rules:').'<br>', - $this->l('- This tax only: Will apply only this tax').'<br>', - $this->l('- Combine: Combine taxes (e.g.: 10% + 5% = 15%)').'<br>', - $this->l('- One after another: Apply taxes one after another (e.g.: 0 + 10% = 0 + 5% = 5.5)') - ) - ), - array( - 'type' => 'select', - 'label' => $this->l('Tax'), - 'name' => 'id_tax', - 'required' => false, - 'options' => array( - 'query' => Tax::getTaxes((int)$this->context->language->id), - 'id' => 'id_tax', - 'name' => 'name', - 'default' => array( - 'value' => 0, - 'label' => $this->l('No Tax') - ) - ), - 'hint' => sprintf($this->l('(Total tax: %s)'), '9%') - ), - array( - 'type' => 'text', - 'label' => $this->l('Description'), - 'name' => 'description', - ) - ), - 'submit' => array( - 'title' => $this->l('Save and stay'), - 'stay' => true - ) - ); + public function initRuleForm() + { + $this->fields_form[0]['form'] = array( + 'legend' => array( + 'title' => $this->l('New tax rule'), + 'icon' => 'icon-money' + ), + 'input' => array( + array( + 'type' => 'select', + 'label' => $this->l('Country'), + 'name' => 'country', + 'id' => 'country', + 'options' => array( + 'query' => Country::getCountries($this->context->language->id), + 'id' => 'id_country', + 'name' => 'name', + 'default' => array( + 'value' => 0, + 'label' => $this->l('All', 'AdminTaxRulesGroupController') + ) + ) + ), + array( + 'type' => 'select', + 'label' => $this->l('State'), + 'name' => 'states[]', + 'id' => 'states', + 'multiple' => true, + 'options' => array( + 'query' => array(), + 'id' => 'id_state', + 'name' => 'name', + 'default' => array( + 'value' => 0, + 'label' => $this->l('All', 'AdminTaxRulesGroupController') + ) + ) + ), + array( + 'type' => 'hidden', + 'name' => 'action' + ), + array( + 'type' => 'text', + 'label' => $this->l('Zip/postal code range'), + 'name' => 'zipcode', + 'required' => false, + 'hint' => $this->l('You can define a range of Zip/postal codes (e.g., 75000-75015) or simply use one Zip/postal code.') + ), + array( + 'type' => 'select', + 'label' => $this->l('Behavior'), + 'name' => 'behavior', + 'required' => false, + 'options' => array( + 'query' => array( + array( + 'id' => 0, + 'name' => $this->l('This tax only') + ), + array( + 'id' => 1, + 'name' => $this->l('Combine') + ), + array( + 'id' => 2, + 'name' => $this->l('One after another') + ) + ), + 'id' => 'id', + 'name' => 'name' + ), + 'hint' => array( + $this->l('You must define the behavior if an address matches multiple rules:').'<br>', + $this->l('- This tax only: Will apply only this tax').'<br>', + $this->l('- Combine: Combine taxes (e.g.: 10% + 5% = 15%)').'<br>', + $this->l('- One after another: Apply taxes one after another (e.g.: 0 + 10% = 0 + 5% = 5.5)') + ) + ), + array( + 'type' => 'select', + 'label' => $this->l('Tax'), + 'name' => 'id_tax', + 'required' => false, + 'options' => array( + 'query' => Tax::getTaxes((int)$this->context->language->id), + 'id' => 'id_tax', + 'name' => 'name', + 'default' => array( + 'value' => 0, + 'label' => $this->l('No Tax') + ) + ), + 'hint' => sprintf($this->l('(Total tax: %s)'), '9%') + ), + array( + 'type' => 'text', + 'label' => $this->l('Description'), + 'name' => 'description', + ) + ), + 'submit' => array( + 'title' => $this->l('Save and stay'), + 'stay' => true + ) + ); - if (!($obj = $this->loadObject(true))) - return; + if (!($obj = $this->loadObject(true))) { + return; + } - $this->fields_value = array( - 'action' => 'create_rule', - 'id_tax_rules_group' => $obj->id, - 'id_tax_rule' => '' - ); + $this->fields_value = array( + 'action' => 'create_rule', + 'id_tax_rules_group' => $obj->id, + 'id_tax_rule' => '' + ); - $this->getlanguages(); - $helper = new HelperForm(); - $helper->override_folder = $this->tpl_folder; - $helper->currentIndex = self::$currentIndex; - $helper->token = $this->token; - $helper->table = 'tax_rule'; - $helper->identifier = 'id_tax_rule'; - $helper->id = $obj->id; - $helper->toolbar_scroll = true; - $helper->show_toolbar = true; - $helper->languages = $this->_languages; - $helper->default_form_language = $this->default_form_language; - $helper->allow_employee_form_lang = $this->allow_employee_form_lang; - $helper->fields_value = $this->getFieldsValue($this->object); - $helper->toolbar_btn['save_new_rule'] = array( - 'href' => self::$currentIndex.'&id_tax_rules_group='.$obj->id.'&action=create_rule&token='.$this->token, - 'desc' => 'Save tax rule', - 'class' => 'process-icon-save' - ); - $helper->submit_action = 'create_rule'; + $this->getlanguages(); + $helper = new HelperForm(); + $helper->override_folder = $this->tpl_folder; + $helper->currentIndex = self::$currentIndex; + $helper->token = $this->token; + $helper->table = 'tax_rule'; + $helper->identifier = 'id_tax_rule'; + $helper->id = $obj->id; + $helper->toolbar_scroll = true; + $helper->show_toolbar = true; + $helper->languages = $this->_languages; + $helper->default_form_language = $this->default_form_language; + $helper->allow_employee_form_lang = $this->allow_employee_form_lang; + $helper->fields_value = $this->getFieldsValue($this->object); + $helper->toolbar_btn['save_new_rule'] = array( + 'href' => self::$currentIndex.'&id_tax_rules_group='.$obj->id.'&action=create_rule&token='.$this->token, + 'desc' => 'Save tax rule', + 'class' => 'process-icon-save' + ); + $helper->submit_action = 'create_rule'; - return $helper->generateForm($this->fields_form); - } + return $helper->generateForm($this->fields_form); + } - public function initProcess() - { - if (Tools::isSubmit('deletetax_rule')) - { - if ($this->tabAccess['delete'] === '1') - $this->action = 'delete_tax_rule'; - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - elseif (Tools::isSubmit('submitBulkdeletetax_rule')) - { - if ($this->tabAccess['delete'] === '1') - $this->action = 'bulk_delete_tax_rules'; - else - $this->errors[] = Tools::displayError('You do not have permission to delete this.'); - } - elseif (Tools::getValue('action') == 'create_rule') - { - if ($this->tabAccess['add'] === '1') - $this->action = 'create_rule'; - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - else - parent::initProcess(); + public function initProcess() + { + if (Tools::isSubmit('deletetax_rule')) { + if ($this->tabAccess['delete'] === '1') { + $this->action = 'delete_tax_rule'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } elseif (Tools::isSubmit('submitBulkdeletetax_rule')) { + if ($this->tabAccess['delete'] === '1') { + $this->action = 'bulk_delete_tax_rules'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to delete this.'); + } + } elseif (Tools::getValue('action') == 'create_rule') { + if ($this->tabAccess['add'] === '1') { + $this->action = 'create_rule'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } else { + parent::initProcess(); + } + } - } + protected function processCreateRule() + { + $zip_code = Tools::getValue('zipcode'); + $id_rule = (int)Tools::getValue('id_tax_rule'); + $id_tax = (int)Tools::getValue('id_tax'); + $id_tax_rules_group = (int)Tools::getValue('id_tax_rules_group'); + $behavior = (int)Tools::getValue('behavior'); + $description = pSQL(Tools::getValue('description')); - protected function processCreateRule() - { - $zip_code = Tools::getValue('zipcode'); - $id_rule = (int)Tools::getValue('id_tax_rule'); - $id_tax = (int)Tools::getValue('id_tax'); - $id_tax_rules_group = (int)Tools::getValue('id_tax_rules_group'); - $behavior = (int)Tools::getValue('behavior'); - $description = pSQL(Tools::getValue('description')); + if ((int)($id_country = Tools::getValue('country')) == 0) { + $countries = Country::getCountries($this->context->language->id); + $this->selected_countries = array(); + foreach ($countries as $country) { + $this->selected_countries[] = (int)$country['id_country']; + } + } else { + $this->selected_countries = array($id_country); + } + $this->selected_states = Tools::getValue('states'); - if ((int)($id_country = Tools::getValue('country')) == 0) - { - $countries = Country::getCountries($this->context->language->id); - $this->selected_countries = array(); - foreach ($countries as $country) - $this->selected_countries[] = (int)$country['id_country']; - } - else - $this->selected_countries = array($id_country); - $this->selected_states = Tools::getValue('states'); + if (empty($this->selected_states) || count($this->selected_states) == 0) { + $this->selected_states = array(0); + } + $tax_rules_group = new TaxRulesGroup((int)$id_tax_rules_group); + foreach ($this->selected_countries as $id_country) { + $first = true; + foreach ($this->selected_states as $id_state) { + if ($tax_rules_group->hasUniqueTaxRuleForCountry($id_country, $id_state, $id_rule)) { + $this->errors[] = Tools::displayError('A tax rule already exists for this country/state with tax only behavior.'); + continue; + } + $tr = new TaxRule(); - if (empty($this->selected_states) || count($this->selected_states) == 0) - $this->selected_states = array(0); - $tax_rules_group = new TaxRulesGroup((int)$id_tax_rules_group); - foreach ($this->selected_countries as $id_country) - { - $first = true; - foreach ($this->selected_states as $id_state) - { - if ($tax_rules_group->hasUniqueTaxRuleForCountry($id_country, $id_state, $id_rule)) - { - $this->errors[] = Tools::displayError('A tax rule already exists for this country/state with tax only behavior.'); - continue; - } - $tr = new TaxRule(); + // update or creation? + if (isset($id_rule) && $first) { + $tr->id = $id_rule; + $first = false; + } - // update or creation? - if (isset($id_rule) && $first) - { - $tr->id = $id_rule; - $first = false; - } + $tr->id_tax = $id_tax; + $tax_rules_group = new TaxRulesGroup((int)$id_tax_rules_group); + $tr->id_tax_rules_group = (int)$tax_rules_group->id; + $tr->id_country = (int)$id_country; + $tr->id_state = (int)$id_state; + list($tr->zipcode_from, $tr->zipcode_to) = $tr->breakDownZipCode($zip_code); - $tr->id_tax = $id_tax; - $tax_rules_group = new TaxRulesGroup((int)$id_tax_rules_group); - $tr->id_tax_rules_group = (int)$tax_rules_group->id; - $tr->id_country = (int)$id_country; - $tr->id_state = (int)$id_state; - list($tr->zipcode_from, $tr->zipcode_to) = $tr->breakDownZipCode($zip_code); + // Construct Object Country + $country = new Country((int)$id_country, (int)$this->context->language->id); - // Construct Object Country - $country = new Country((int)$id_country, (int)$this->context->language->id); + if ($zip_code && $country->need_zip_code) { + if ($country->zip_code_format) { + foreach (array($tr->zipcode_from, $tr->zipcode_to) as $zip_code) { + if ($zip_code) { + if (!$country->checkZipCode($zip_code)) { + $this->errors[] = sprintf( + Tools::displayError('The Zip/postal code is invalid. It must be typed as follows: %s for %s.'), + str_replace('C', $country->iso_code, str_replace('N', '0', str_replace('L', 'A', $country->zip_code_format))), $country->name + ); + } + } + } + } + } - if ($zip_code && $country->need_zip_code) - { - if ($country->zip_code_format) - { - foreach (array($tr->zipcode_from, $tr->zipcode_to) as $zip_code) - if ($zip_code) - if (!$country->checkZipCode($zip_code)) - { - $this->errors[] = sprintf( - Tools::displayError('The Zip/postal code is invalid. It must be typed as follows: %s for %s.'), - str_replace('C', $country->iso_code, str_replace('N', '0', str_replace('L', 'A', $country->zip_code_format))), $country->name - ); - } - } - } + $tr->behavior = (int)$behavior; + $tr->description = $description; + $this->tax_rule = $tr; + $_POST['id_state'] = $tr->id_state; - $tr->behavior = (int)$behavior; - $tr->description = $description; - $this->tax_rule = $tr; - $_POST['id_state'] = $tr->id_state; + $this->errors = array_merge($this->errors, $this->validateTaxRule($tr)); - $this->errors = array_merge($this->errors, $this->validateTaxRule($tr)); + if (count($this->errors) == 0) { + $tax_rules_group = $this->updateTaxRulesGroup($tax_rules_group); + $tr->id = (int)$tax_rules_group->getIdTaxRuleGroupFromHistorizedId((int)$tr->id); + $tr->id_tax_rules_group = (int)$tax_rules_group->id; - if (count($this->errors) == 0) - { - $tax_rules_group = $this->updateTaxRulesGroup($tax_rules_group); - $tr->id = (int)$tax_rules_group->getIdTaxRuleGroupFromHistorizedId((int)$tr->id); - $tr->id_tax_rules_group = (int)$tax_rules_group->id; + if (!$tr->save()) { + $this->errors[] = Tools::displayError('An error has occurred: Cannot save the current tax rule.'); + } + } + } + } - if (!$tr->save()) - $this->errors[] = Tools::displayError('An error has occurred: Cannot save the current tax rule.'); - } - } - } + if (count($this->errors) == 0) { + Tools::redirectAdmin( + self::$currentIndex.'&'.$this->identifier.'='.(int)$tax_rules_group->id.'&conf=4&update'.$this->table.'&token='.$this->token + ); + } else { + $this->display = 'edit'; + } + } - if (count($this->errors) == 0) - Tools::redirectAdmin( - self::$currentIndex.'&'.$this->identifier.'='.(int)$tax_rules_group->id.'&conf=4&update'.$this->table.'&token='.$this->token - ); - else - $this->display = 'edit'; - } + protected function processBulkDeleteTaxRules() + { + $this->deleteTaxRule(Tools::getValue('tax_ruleBox')); + } - protected function processBulkDeleteTaxRules() - { - $this->deleteTaxRule(Tools::getValue('tax_ruleBox')); - } + protected function processDeleteTaxRule() + { + $this->deleteTaxRule(array(Tools::getValue('id_tax_rule'))); + } - protected function processDeleteTaxRule() - { - $this->deleteTaxRule(array(Tools::getValue('id_tax_rule'))); - } + protected function deleteTaxRule(array $id_tax_rule_list) + { + $result = true; - protected function deleteTaxRule(array $id_tax_rule_list) - { - $result = true; + foreach ($id_tax_rule_list as $id_tax_rule) { + $tax_rule = new TaxRule((int)$id_tax_rule); + if (Validate::isLoadedObject($tax_rule)) { + $tax_rules_group = new TaxRulesGroup((int)$tax_rule->id_tax_rules_group); + $tax_rules_group = $this->updateTaxRulesGroup($tax_rules_group); + $tax_rule = new TaxRule($tax_rules_group->getIdTaxRuleGroupFromHistorizedId((int)$id_tax_rule)); + if (Validate::isLoadedObject($tax_rule)) { + $result &= $tax_rule->delete(); + } + } + } - foreach ($id_tax_rule_list as $id_tax_rule) - { - $tax_rule = new TaxRule((int)$id_tax_rule); - if (Validate::isLoadedObject($tax_rule)) - { - $tax_rules_group = new TaxRulesGroup((int)$tax_rule->id_tax_rules_group); - $tax_rules_group = $this->updateTaxRulesGroup($tax_rules_group); - $tax_rule = new TaxRule($tax_rules_group->getIdTaxRuleGroupFromHistorizedId((int)$id_tax_rule)); - if (Validate::isLoadedObject($tax_rule)) - $result &= $tax_rule->delete(); - } - } + Tools::redirectAdmin( + self::$currentIndex.'&'.$this->identifier.'='.(int)$tax_rules_group->id.'&conf=4&update'.$this->table.'&token='.$this->token + ); + } - Tools::redirectAdmin( - self::$currentIndex.'&'.$this->identifier.'='.(int)$tax_rules_group->id.'&conf=4&update'.$this->table.'&token='.$this->token - ); - } + /** + * Check if the tax rule could be added in the database + * + * @param TaxRule $tr + * + * @return array + */ + protected function validateTaxRule(TaxRule $tr) + { + // @TODO: check if the rule already exists + return $tr->validateController(); + } - /** - * Check if the tax rule could be added in the database - * - * @param TaxRule $tr - * - * @return array - */ - protected function validateTaxRule(TaxRule $tr) - { - // @TODO: check if the rule already exists - return $tr->validateController(); - } + protected function displayAjaxUpdateTaxRule() + { + if ($this->tabAccess['view'] === '1') { + $id_tax_rule = Tools::getValue('id_tax_rule'); + $tax_rules = new TaxRule((int)$id_tax_rule); + $output = array(); + foreach ($tax_rules as $key => $result) { + $output[$key] = $result; + } + die(Tools::jsonEncode($output)); + } + } - protected function displayAjaxUpdateTaxRule() - { - if ($this->tabAccess['view'] === '1') - { - $id_tax_rule = Tools::getValue('id_tax_rule'); - $tax_rules = new TaxRule((int)$id_tax_rule); - $output = array(); - foreach ($tax_rules as $key => $result) - $output[$key] = $result; - die(Tools::jsonEncode($output)); - } - } + /** + * @param TaxRulesGroup $object + * + * @return TaxRulesGroup + */ + protected function updateTaxRulesGroup($object) + { + static $tax_rules_group = null; + if ($tax_rules_group === null) { + $object->update(); + $tax_rules_group = $object; + } - /** - * @param TaxRulesGroup $object - * - * @return TaxRulesGroup - */ - protected function updateTaxRulesGroup($object) - { - static $tax_rules_group = null; - if ($tax_rules_group === null) - { - $object->update(); - $tax_rules_group = $object; - } - - return $tax_rules_group; - } + return $tax_rules_group; + } } diff --git a/controllers/admin/AdminTaxesController.php b/controllers/admin/AdminTaxesController.php index 7fd4130f..9c28a8cb 100644 --- a/controllers/admin/AdminTaxesController.php +++ b/controllers/admin/AdminTaxesController.php @@ -29,265 +29,269 @@ */ class AdminTaxesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'tax'; - $this->className = 'Tax'; - $this->lang = true; - $this->addRowAction('edit'); - $this->addRowAction('delete'); + public function __construct() + { + $this->bootstrap = true; + $this->table = 'tax'; + $this->className = 'Tax'; + $this->lang = true; + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->fields_list = array( - 'id_tax' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), - 'name' => array('title' => $this->l('Name'), 'width' => 'auto'), - 'rate' => array('title' => $this->l('Rate'), 'align' => 'center', 'suffix' => '%' , 'class' => 'fixed-width-md'), - 'active' => array('title' => $this->l('Enabled'), 'width' => 25, 'align' => 'center', 'active' => 'status', 'type' => 'bool', 'orderby' => false, 'class' => 'fixed-width-sm', 'remove_onclick' => true) - ); + $this->fields_list = array( + 'id_tax' => array('title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs'), + 'name' => array('title' => $this->l('Name'), 'width' => 'auto'), + 'rate' => array('title' => $this->l('Rate'), 'align' => 'center', 'suffix' => '%' , 'class' => 'fixed-width-md'), + 'active' => array('title' => $this->l('Enabled'), 'width' => 25, 'align' => 'center', 'active' => 'status', 'type' => 'bool', 'orderby' => false, 'class' => 'fixed-width-sm', 'remove_onclick' => true) + ); - $ecotax_desc = ''; - if (Configuration::get('PS_USE_ECOTAX')) - $ecotax_desc = $this->l('If you disable the ecotax, the ecotax for all your products will be set to 0.'); + $ecotax_desc = ''; + if (Configuration::get('PS_USE_ECOTAX')) { + $ecotax_desc = $this->l('If you disable the ecotax, the ecotax for all your products will be set to 0.'); + } - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Tax options'), - 'fields' => array( - 'PS_TAX' => array( - 'title' => $this->l('Enable tax'), - 'desc' => $this->l('Select whether or not to include tax on purchases.'), - 'cast' => 'intval', 'type' => 'bool'), - 'PS_TAX_DISPLAY' => array( - 'title' => $this->l('Display tax in the shopping cart'), - 'desc' => $this->l('Select whether or not to display tax on a distinct line in the cart.'), - 'cast' => 'intval', - 'type' => 'bool'), - 'PS_TAX_ADDRESS_TYPE' => array( - 'title' => $this->l('Based on'), - 'cast' => 'pSQL', - 'type' => 'select', - 'list' => array( - array( - 'name' => $this->l('Invoice address'), - 'id' => 'id_address_invoice' - ), - array( - 'name' => $this->l('Delivery address'), - 'id' => 'id_address_delivery') - ), - 'identifier' => 'id' - ), - 'PS_USE_ECOTAX' => array( - 'title' => $this->l('Use ecotax'), - 'desc' => $ecotax_desc, - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - ), - 'submit' => array('title' => $this->l('Save')) - ), - ); + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Tax options'), + 'fields' => array( + 'PS_TAX' => array( + 'title' => $this->l('Enable tax'), + 'desc' => $this->l('Select whether or not to include tax on purchases.'), + 'cast' => 'intval', 'type' => 'bool'), + 'PS_TAX_DISPLAY' => array( + 'title' => $this->l('Display tax in the shopping cart'), + 'desc' => $this->l('Select whether or not to display tax on a distinct line in the cart.'), + 'cast' => 'intval', + 'type' => 'bool'), + 'PS_TAX_ADDRESS_TYPE' => array( + 'title' => $this->l('Based on'), + 'cast' => 'pSQL', + 'type' => 'select', + 'list' => array( + array( + 'name' => $this->l('Invoice address'), + 'id' => 'id_address_invoice' + ), + array( + 'name' => $this->l('Delivery address'), + 'id' => 'id_address_delivery') + ), + 'identifier' => 'id' + ), + 'PS_USE_ECOTAX' => array( + 'title' => $this->l('Use ecotax'), + 'desc' => $ecotax_desc, + 'validation' => 'isBool', + 'cast' => 'intval', + 'type' => 'bool' + ), + ), + 'submit' => array('title' => $this->l('Save')) + ), + ); - if (Configuration::get('PS_USE_ECOTAX') || Tools::getValue('PS_USE_ECOTAX')) - $this->fields_options['general']['fields']['PS_ECOTAX_TAX_RULES_GROUP_ID'] = array( - 'title' => $this->l('Ecotax'), - 'hint' => $this->l('Define the ecotax (e.g. French ecotax: 19.6%).'), - 'cast' => 'intval', - 'type' => 'select', - 'identifier' => 'id_tax_rules_group', - 'list' => TaxRulesGroup::getTaxRulesGroupsForOptions() - ); + if (Configuration::get('PS_USE_ECOTAX') || Tools::getValue('PS_USE_ECOTAX')) { + $this->fields_options['general']['fields']['PS_ECOTAX_TAX_RULES_GROUP_ID'] = array( + 'title' => $this->l('Ecotax'), + 'hint' => $this->l('Define the ecotax (e.g. French ecotax: 19.6%).'), + 'cast' => 'intval', + 'type' => 'select', + 'identifier' => 'id_tax_rules_group', + 'list' => TaxRulesGroup::getTaxRulesGroupsForOptions() + ); + } - parent::__construct(); + parent::__construct(); - $this->_where .= ' AND a.deleted = 0'; - } + $this->_where .= ' AND a.deleted = 0'; + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_tax'] = array( - 'href' => self::$currentIndex.'&addtax&token='.$this->token, - 'desc' => $this->l('Add new tax', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_tax'] = array( + 'href' => self::$currentIndex.'&addtax&token='.$this->token, + 'desc' => $this->l('Add new tax', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - /** - * Display delete action link - * - * @param string|null $token - * @param int $id - * - * @return string - * @throws Exception - * @throws SmartyException - */ - public function displayDeleteLink($token = null, $id) - { - if (!array_key_exists('Delete', self::$cache_lang)) - self::$cache_lang['Delete'] = $this->l('Delete'); + /** + * Display delete action link + * + * @param string|null $token + * @param int $id + * + * @return string + * @throws Exception + * @throws SmartyException + */ + public function displayDeleteLink($token = null, $id) + { + if (!array_key_exists('Delete', self::$cache_lang)) { + self::$cache_lang['Delete'] = $this->l('Delete'); + } - if (!array_key_exists('DeleteItem', self::$cache_lang)) - self::$cache_lang['DeleteItem'] = $this->l('Delete item #', __CLASS__, true, false); + if (!array_key_exists('DeleteItem', self::$cache_lang)) { + self::$cache_lang['DeleteItem'] = $this->l('Delete item #', __CLASS__, true, false); + } - if (TaxRule::isTaxInUse($id)) - $confirm = $this->l('This tax is currently in use as a tax rule. Are you sure you\'d like to continue?', null, true, false); + if (TaxRule::isTaxInUse($id)) { + $confirm = $this->l('This tax is currently in use as a tax rule. Are you sure you\'d like to continue?', null, true, false); + } - $this->context->smarty->assign(array( - 'href' => self::$currentIndex.'&'.$this->identifier.'='.$id.'&delete'.$this->table.'&token='.($token != null ? $token : $this->token), - 'confirm' => (isset($confirm) ? '\r'.$confirm : self::$cache_lang['DeleteItem'].$id.' ? '), - 'action' => self::$cache_lang['Delete'], - )); + $this->context->smarty->assign(array( + 'href' => self::$currentIndex.'&'.$this->identifier.'='.$id.'&delete'.$this->table.'&token='.($token != null ? $token : $this->token), + 'confirm' => (isset($confirm) ? '\r'.$confirm : self::$cache_lang['DeleteItem'].$id.' ? '), + 'action' => self::$cache_lang['Delete'], + )); - return $this->context->smarty->fetch('helpers/list/list_action_delete.tpl'); - } + return $this->context->smarty->fetch('helpers/list/list_action_delete.tpl'); + } - /** - * Fetch the template for action enable - * - * @param string $token - * @param int $id - * @param int $value state enabled or not - * @param string $active status - * @param int $id_category - * @param int $id_product - */ - public function displayEnableLink($token, $id, $value, $active, $id_category = null, $id_product = null) - { - if ($value && TaxRule::isTaxInUse($id)) - $confirm = $this->l('This tax is currently in use as a tax rule. If you continue, this tax will be removed from the tax rule. Are you sure you\'d like to continue?', null, true, false); - $tpl_enable = $this->context->smarty->createTemplate('helpers/list/list_action_enable.tpl'); - $tpl_enable->assign(array( - 'enabled' => (bool)$value, - 'url_enable' => self::$currentIndex.'&'.$this->identifier.'='.(int)$id.'&'.$active.$this->table. - ((int)$id_category && (int)$id_product ? '&id_category='.(int)$id_category : '').'&token='.($token != null ? $token : $this->token), - 'confirm' => isset($confirm) ? $confirm : null, - )); + /** + * Fetch the template for action enable + * + * @param string $token + * @param int $id + * @param int $value state enabled or not + * @param string $active status + * @param int $id_category + * @param int $id_product + */ + public function displayEnableLink($token, $id, $value, $active, $id_category = null, $id_product = null) + { + if ($value && TaxRule::isTaxInUse($id)) { + $confirm = $this->l('This tax is currently in use as a tax rule. If you continue, this tax will be removed from the tax rule. Are you sure you\'d like to continue?', null, true, false); + } + $tpl_enable = $this->context->smarty->createTemplate('helpers/list/list_action_enable.tpl'); + $tpl_enable->assign(array( + 'enabled' => (bool)$value, + 'url_enable' => self::$currentIndex.'&'.$this->identifier.'='.(int)$id.'&'.$active.$this->table. + ((int)$id_category && (int)$id_product ? '&id_category='.(int)$id_category : '').'&token='.($token != null ? $token : $this->token), + 'confirm' => isset($confirm) ? $confirm : null, + )); - return $tpl_enable->fetch(); - } + return $tpl_enable->fetch(); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Taxes'), - 'icon' => 'icon-money' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'required' => true, - 'lang' => true, - 'hint' => $this->l('Tax name to display in carts and on invoices (e.g. "VAT").').' - '.$this->l('Invalid characters').' <>;=#{}' - ), - array( - 'type' => 'text', - 'label' => $this->l('Rate'), - 'name' => 'rate', - 'maxlength' => 6, - 'required' => true, - 'hint' => $this->l('Format: XX.XX or XX.XXX (e.g. 19.60 or 13.925)').' - '.$this->l('Invalid characters').' <>;=#{}' - ), - array( - 'type' => 'switch', - 'label' => $this->l('Enable'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ) - ) - ), - 'submit' => array( - 'title' => $this->l('Save') - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Taxes'), + 'icon' => 'icon-money' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'required' => true, + 'lang' => true, + 'hint' => $this->l('Tax name to display in carts and on invoices (e.g. "VAT").').' - '.$this->l('Invalid characters').' <>;=#{}' + ), + array( + 'type' => 'text', + 'label' => $this->l('Rate'), + 'name' => 'rate', + 'maxlength' => 6, + 'required' => true, + 'hint' => $this->l('Format: XX.XX or XX.XXX (e.g. 19.60 or 13.925)').' - '.$this->l('Invalid characters').' <>;=#{}' + ), + array( + 'type' => 'switch', + 'label' => $this->l('Enable'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ) + ) + ), + 'submit' => array( + 'title' => $this->l('Save') + ) + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function postProcess() - { - if ($this->action == 'save') - { - /* Checking fields validity */ - $this->validateRules(); - if (!count($this->errors)) - { - $id = (int)(Tools::getValue('id_'.$this->table)); + public function postProcess() + { + if ($this->action == 'save') { + /* Checking fields validity */ + $this->validateRules(); + if (!count($this->errors)) { + $id = (int)(Tools::getValue('id_'.$this->table)); - /* Object update */ - if (isset($id) && !empty($id)) - { - /** @var Tax $object */ - $object = new $this->className($id); - if (Validate::isLoadedObject($object)) - { - $this->copyFromPost($object, $this->table); - $result = $object->update(false, false); + /* Object update */ + if (isset($id) && !empty($id)) { + /** @var Tax $object */ + $object = new $this->className($id); + if (Validate::isLoadedObject($object)) { + $this->copyFromPost($object, $this->table); + $result = $object->update(false, false); - if (!$result) - $this->errors[] = Tools::displayError('An error occurred while updating an object.').' <b>'.$this->table.'</b>'; - elseif ($this->postImage($object->id)) - Tools::redirectAdmin(self::$currentIndex.'&id_'.$this->table.'='.$object->id.'&conf=4'.'&token='.$this->token); - } - else - $this->errors[] = Tools::displayError('An error occurred while updating an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); - } + if (!$result) { + $this->errors[] = Tools::displayError('An error occurred while updating an object.').' <b>'.$this->table.'</b>'; + } elseif ($this->postImage($object->id)) { + Tools::redirectAdmin(self::$currentIndex.'&id_'.$this->table.'='.$object->id.'&conf=4'.'&token='.$this->token); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while updating an object.').' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)'); + } + } - /* Object creation */ - else - { - /** @var Tax $object */ - $object = new $this->className(); - $this->copyFromPost($object, $this->table); - if (!$object->add()) - $this->errors[] = Tools::displayError('An error occurred while creating an object.').' <b>'.$this->table.'</b>'; - elseif (($_POST['id_'.$this->table] = $object->id /* voluntary */) && $this->postImage($object->id) && $this->_redirect) - Tools::redirectAdmin(self::$currentIndex.'&id_'.$this->table.'='.$object->id.'&conf=3'.'&token='.$this->token); - } - } - } - else - parent::postProcess(); - } + /* Object creation */ + else { + /** @var Tax $object */ + $object = new $this->className(); + $this->copyFromPost($object, $this->table); + if (!$object->add()) { + $this->errors[] = Tools::displayError('An error occurred while creating an object.').' <b>'.$this->table.'</b>'; + } elseif (($_POST['id_'.$this->table] = $object->id /* voluntary */) && $this->postImage($object->id) && $this->_redirect) { + Tools::redirectAdmin(self::$currentIndex.'&id_'.$this->table.'='.$object->id.'&conf=3'.'&token='.$this->token); + } + } + } + } else { + parent::postProcess(); + } + } - public function updateOptionPsUseEcotax($value) - { - $old_value = (int)Configuration::get('PS_USE_ECOTAX'); + public function updateOptionPsUseEcotax($value) + { + $old_value = (int)Configuration::get('PS_USE_ECOTAX'); - if ($old_value != $value) - { - // Reset ecotax - if ($value == 0) - Product::resetEcoTax(); + if ($old_value != $value) { + // Reset ecotax + if ($value == 0) { + Product::resetEcoTax(); + } - Configuration::updateValue('PS_USE_ECOTAX', (int)$value); - } - } -} \ No newline at end of file + Configuration::updateValue('PS_USE_ECOTAX', (int)$value); + } + } +} diff --git a/controllers/admin/AdminThemesController.php b/controllers/admin/AdminThemesController.php index 783bfcc0..e790eb98 100644 --- a/controllers/admin/AdminThemesController.php +++ b/controllers/admin/AdminThemesController.php @@ -29,1043 +29,1033 @@ */ class AdminThemesControllerCore extends AdminController { - const MAX_NAME_LENGTH = 128; + const MAX_NAME_LENGTH = 128; - public function __construct() - { - $this->bootstrap = true; - parent::__construct(); - } + public function __construct() + { + $this->bootstrap = true; + parent::__construct(); + } - /** - * This value is used in isThemeCompatible method. only version node with an - * higher version number will be used in [theme]/config.xml - * - * @since 1.4.0.11, check theme compatibility 1.4 - * @var string - */ - public static $check_features_version = '1.4'; + /** + * This value is used in isThemeCompatible method. only version node with an + * higher version number will be used in [theme]/config.xml + * + * @since 1.4.0.11, check theme compatibility 1.4 + * @var string + */ + public static $check_features_version = '1.4'; - /** - * Multidimensional array used to check [theme]/config.xml values, - * and also checks prestashop current configuration if not match. - * - * @var array - */ - public static $check_features = array( - 'ccc' => array( - 'attributes' => array( - 'available' => array( - 'value' => 'true', - /* - * accepted attribute value if value doesn't match, prestashop configuration value must have those values - */ - 'check_if_not_valid' => array( - 'PS_CSS_THEME_CACHE' => 0, - 'PS_JS_THEME_CACHE' => 0, - 'PS_HTML_THEME_COMPRESSION' => 0, - 'PS_JS_HTML_THEME_COMPRESSION' => 0, - ), - ), - ), - 'error' => 'This theme may not correctly use PrestaShop\'s "combine, compress and cache" options.', - 'tab' => 'AdminPerformance', - ), - 'guest_checkout' => array( - 'attributes' => array( - 'available' => array( - 'value' => 'true', - 'check_if_not_valid' => array('PS_GUEST_CHECKOUT_ENABLED' => 0) - ), - ), - 'error' => 'This theme may not correctly use PrestaShop\'s "guest checkout" feature.', - 'tab' => 'AdminPreferences', - ), - 'one_page_checkout' => array( - 'attributes' => array( - 'available' => array( - 'value' => 'true', - 'check_if_not_valid' => array('PS_ORDER_PROCESS_TYPE' => 0), - ), - ), - 'error' => 'This theme may not correctly use PrestaShop\'s "one-page checkout" feature.', - 'tab' => 'AdminPreferences', - ), - 'store_locator' => array( - 'attributes' => array( - 'available' => array( - 'value' => 'true', - 'check_if_not_valid' => array( - 'PS_STORES_SIMPLIFIED' => 0, - 'PS_STORES_DISPLAY_FOOTER' => 0 - ), - ) - ), - 'error' => 'This theme may not correctly use PrestaShop\'s "store locator" feature.', - 'tab' => 'AdminStores', - ) - ); + /** + * Multidimensional array used to check [theme]/config.xml values, + * and also checks prestashop current configuration if not match. + * + * @var array + */ + public static $check_features = array( + 'ccc' => array( + 'attributes' => array( + 'available' => array( + 'value' => 'true', + /* + * accepted attribute value if value doesn't match, prestashop configuration value must have those values + */ + 'check_if_not_valid' => array( + 'PS_CSS_THEME_CACHE' => 0, + 'PS_JS_THEME_CACHE' => 0, + 'PS_HTML_THEME_COMPRESSION' => 0, + 'PS_JS_HTML_THEME_COMPRESSION' => 0, + ), + ), + ), + 'error' => 'This theme may not correctly use PrestaShop\'s "combine, compress and cache" options.', + 'tab' => 'AdminPerformance', + ), + 'guest_checkout' => array( + 'attributes' => array( + 'available' => array( + 'value' => 'true', + 'check_if_not_valid' => array('PS_GUEST_CHECKOUT_ENABLED' => 0) + ), + ), + 'error' => 'This theme may not correctly use PrestaShop\'s "guest checkout" feature.', + 'tab' => 'AdminPreferences', + ), + 'one_page_checkout' => array( + 'attributes' => array( + 'available' => array( + 'value' => 'true', + 'check_if_not_valid' => array('PS_ORDER_PROCESS_TYPE' => 0), + ), + ), + 'error' => 'This theme may not correctly use PrestaShop\'s "one-page checkout" feature.', + 'tab' => 'AdminPreferences', + ), + 'store_locator' => array( + 'attributes' => array( + 'available' => array( + 'value' => 'true', + 'check_if_not_valid' => array( + 'PS_STORES_SIMPLIFIED' => 0, + 'PS_STORES_DISPLAY_FOOTER' => 0 + ), + ) + ), + 'error' => 'This theme may not correctly use PrestaShop\'s "store locator" feature.', + 'tab' => 'AdminStores', + ) + ); - public $className = 'Theme'; - public $table = 'theme'; - protected $toolbar_scroll = false; - private $img_error; + public $className = 'Theme'; + public $table = 'theme'; + protected $toolbar_scroll = false; + private $img_error; - public function init() - { - // No cache for auto-refresh uploaded logo - header('Cache-Control: no-cache, must-revalidate'); - header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); + public function init() + { + // No cache for auto-refresh uploaded logo + header('Cache-Control: no-cache, must-revalidate'); + header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); - parent::init(); - $this->can_display_themes = (!Shop::isFeatureActive() || Shop::getContext() == Shop::CONTEXT_SHOP); + parent::init(); + $this->can_display_themes = (!Shop::isFeatureActive() || Shop::getContext() == Shop::CONTEXT_SHOP); - libxml_use_internal_errors(true); + libxml_use_internal_errors(true); - // Download user themes from Addons - if ($this->logged_on_addons) - $this->downloadAddonsThemes(); + // Download user themes from Addons + if ($this->logged_on_addons) { + $this->downloadAddonsThemes(); + } - // Employee languages used for link and utm_source - $lang = new Language($this->context->language->id); - $iso_lang_uc = strtoupper($lang->iso_code); + // Employee languages used for link and utm_source + $lang = new Language($this->context->language->id); + $iso_lang_uc = strtoupper($lang->iso_code); - $this->fields_options = array( - 'appearance' => array( - 'title' => $this->l('Your current theme'), - 'icon' => 'icon-html5', - 'tabs' => array( - 'logo' => $this->l('Logo'), - 'logo2' => $this->l('Invoice & Email Logos'), - 'icons' => $this->l('Icons'), - 'mobile' => $this->l('Mobile'), - ), - 'fields' => array( - 'PS_LOGO' => array( - 'title' => $this->l('Header logo'), - 'hint' => $this->l('Will appear on main page. Recommended height: 52px. Maximum height on default theme: 65px.'), - 'type' => 'file', - 'name' => 'PS_LOGO', - 'tab' => 'logo', - 'thumb' => _PS_IMG_.Configuration::get('PS_LOGO') - ), - 'PS_LOGO_MOBILE' => array( - 'title' => $this->l('Header logo for mobile'), - 'desc' => ((Configuration::get('PS_LOGO_MOBILE') === false) ? '<span class="light-warning">'.$this->l('Warning: No mobile logo has been defined. The header logo will be used instead.').'</span><br />' : ''), - 'hint' => $this->l('Will appear on the main page of your mobile template. If left undefined, the header logo will be used.'), - 'type' => 'file', - 'name' => 'PS_LOGO_MOBILE', - 'tab' => 'mobile', - 'thumb' => (Configuration::get('PS_LOGO_MOBILE') !== false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_MOBILE'))) ? _PS_IMG_.Configuration::get('PS_LOGO_MOBILE') : _PS_IMG_.Configuration::get('PS_LOGO') - ), - 'PS_LOGO_MAIL' => array( - 'title' => $this->l('Mail logo'), - 'desc' => ((Configuration::get('PS_LOGO_MAIL') === false) ? '<span class="light-warning">'.$this->l('Warning: if no email logo is available, the main logo will be used instead.').'</span><br />' : ''), - 'hint' => $this->l('Will appear on email headers. If undefined, the header logo will be used.'), - 'type' => 'file', - 'name' => 'PS_LOGO_MAIL', - 'tab' => 'logo2', - 'thumb' => (Configuration::get('PS_LOGO_MAIL') !== false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_MAIL'))) ? _PS_IMG_.Configuration::get('PS_LOGO_MAIL') : _PS_IMG_.Configuration::get('PS_LOGO') - ), - 'PS_LOGO_INVOICE' => array( - 'title' => $this->l('Invoice logo'), - 'desc' => ((Configuration::get('PS_LOGO_INVOICE') === false) ? '<span class="light-warning">'.$this->l('Warning: if no invoice logo is available, the main logo will be used instead.').'</span><br />' : ''), - 'hint' => $this->l('Will appear on invoice headers.').' '.$this->l('Warning: you can use a PNG file for transparency, but it can take up to 1 second per page for processing. Please consider using JPG instead.'), - 'type' => 'file', - 'name' => 'PS_LOGO_INVOICE', - 'tab' => 'logo2', - 'thumb' => (Configuration::get('PS_LOGO_INVOICE') !== false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_INVOICE'))) ? _PS_IMG_.Configuration::get('PS_LOGO_INVOICE') : _PS_IMG_.Configuration::get('PS_LOGO') - ), - 'PS_FAVICON' => array( - 'title' => $this->l('Favicon'), - 'hint' => $this->l('Will appear in the address bar of your web browser.'), - 'type' => 'file', - 'name' => 'PS_FAVICON', - 'tab' => 'icons', - 'thumb' => _PS_IMG_.Configuration::get('PS_FAVICON').(Tools::getValue('conf') ? sprintf('?%04d', rand(0, 9999)) : '') - ), - 'PS_STORES_ICON' => array( - 'title' => $this->l('Store icon'), - 'hint' => $this->l('Will appear on the store locator (inside Google Maps).').'<br />'.$this->l('Suggested size: 30x30, transparent GIF.'), - 'type' => 'file', - 'name' => 'PS_STORES_ICON', - 'tab' => 'icons', - 'thumb' => _PS_IMG_.Configuration::get('PS_STORES_ICON') - ), - 'PS_ALLOW_MOBILE_DEVICE' => array( - 'title' => $this->l('Enable the mobile theme'), - 'hint' => $this->l('Allows visitors browsing on mobile devices to view a lighter version of your website.'), - 'type' => 'radio', - 'required' => true, - 'validation' => 'isGenericName', - 'tab' => 'mobile', - 'choices' => array( - 0 => $this->l('I\'d like to disable it.'), - 1 => $this->l('I\'d like to enable it only on smartphones.'), - 2 => $this->l('I\'d like to enable it only on tablets.'), - 3 => $this->l('I\'d like to enable it on both smartphones and tablets.') - ) - ), - ), - 'after_tabs' => array( - 'cur_theme' => Theme::getThemeInfo($this->context->shop->id_theme), - ), - 'submit' => array('title' => $this->l('Save')), - 'buttons' => array( - 'storeLink' => array( - 'title' => $this->l('Visit the theme catalog'), - 'icon' => 'process-icon-themes', - 'href' => 'http://addons.prestashop.com/en/3-templates-prestashop' - .'?utm_source=back-office&utm_medium=theme-button' - .'&utm_campaign=back-office-'.$iso_lang_uc - .'&utm_content='.(defined('_PS_HOST_MODE_') ? 'cloud' : 'download'), - 'js' => 'return !window.open(this.href)' - ) - ) - ), - ); + $this->fields_options = array( + 'appearance' => array( + 'title' => $this->l('Your current theme'), + 'icon' => 'icon-html5', + 'tabs' => array( + 'logo' => $this->l('Logo'), + 'logo2' => $this->l('Invoice & Email Logos'), + 'icons' => $this->l('Icons'), + 'mobile' => $this->l('Mobile'), + ), + 'fields' => array( + 'PS_LOGO' => array( + 'title' => $this->l('Header logo'), + 'hint' => $this->l('Will appear on main page. Recommended height: 52px. Maximum height on default theme: 65px.'), + 'type' => 'file', + 'name' => 'PS_LOGO', + 'tab' => 'logo', + 'thumb' => _PS_IMG_.Configuration::get('PS_LOGO') + ), + 'PS_LOGO_MOBILE' => array( + 'title' => $this->l('Header logo for mobile'), + 'desc' => ((Configuration::get('PS_LOGO_MOBILE') === false) ? '<span class="light-warning">'.$this->l('Warning: No mobile logo has been defined. The header logo will be used instead.').'</span><br />' : ''), + 'hint' => $this->l('Will appear on the main page of your mobile template. If left undefined, the header logo will be used.'), + 'type' => 'file', + 'name' => 'PS_LOGO_MOBILE', + 'tab' => 'mobile', + 'thumb' => (Configuration::get('PS_LOGO_MOBILE') !== false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_MOBILE'))) ? _PS_IMG_.Configuration::get('PS_LOGO_MOBILE') : _PS_IMG_.Configuration::get('PS_LOGO') + ), + 'PS_LOGO_MAIL' => array( + 'title' => $this->l('Mail logo'), + 'desc' => ((Configuration::get('PS_LOGO_MAIL') === false) ? '<span class="light-warning">'.$this->l('Warning: if no email logo is available, the main logo will be used instead.').'</span><br />' : ''), + 'hint' => $this->l('Will appear on email headers. If undefined, the header logo will be used.'), + 'type' => 'file', + 'name' => 'PS_LOGO_MAIL', + 'tab' => 'logo2', + 'thumb' => (Configuration::get('PS_LOGO_MAIL') !== false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_MAIL'))) ? _PS_IMG_.Configuration::get('PS_LOGO_MAIL') : _PS_IMG_.Configuration::get('PS_LOGO') + ), + 'PS_LOGO_INVOICE' => array( + 'title' => $this->l('Invoice logo'), + 'desc' => ((Configuration::get('PS_LOGO_INVOICE') === false) ? '<span class="light-warning">'.$this->l('Warning: if no invoice logo is available, the main logo will be used instead.').'</span><br />' : ''), + 'hint' => $this->l('Will appear on invoice headers.').' '.$this->l('Warning: you can use a PNG file for transparency, but it can take up to 1 second per page for processing. Please consider using JPG instead.'), + 'type' => 'file', + 'name' => 'PS_LOGO_INVOICE', + 'tab' => 'logo2', + 'thumb' => (Configuration::get('PS_LOGO_INVOICE') !== false && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_INVOICE'))) ? _PS_IMG_.Configuration::get('PS_LOGO_INVOICE') : _PS_IMG_.Configuration::get('PS_LOGO') + ), + 'PS_FAVICON' => array( + 'title' => $this->l('Favicon'), + 'hint' => $this->l('Will appear in the address bar of your web browser.'), + 'type' => 'file', + 'name' => 'PS_FAVICON', + 'tab' => 'icons', + 'thumb' => _PS_IMG_.Configuration::get('PS_FAVICON').(Tools::getValue('conf') ? sprintf('?%04d', rand(0, 9999)) : '') + ), + 'PS_STORES_ICON' => array( + 'title' => $this->l('Store icon'), + 'hint' => $this->l('Will appear on the store locator (inside Google Maps).').'<br />'.$this->l('Suggested size: 30x30, transparent GIF.'), + 'type' => 'file', + 'name' => 'PS_STORES_ICON', + 'tab' => 'icons', + 'thumb' => _PS_IMG_.Configuration::get('PS_STORES_ICON') + ), + 'PS_ALLOW_MOBILE_DEVICE' => array( + 'title' => $this->l('Enable the mobile theme'), + 'hint' => $this->l('Allows visitors browsing on mobile devices to view a lighter version of your website.'), + 'type' => 'radio', + 'required' => true, + 'validation' => 'isGenericName', + 'tab' => 'mobile', + 'choices' => array( + 0 => $this->l('I\'d like to disable it.'), + 1 => $this->l('I\'d like to enable it only on smartphones.'), + 2 => $this->l('I\'d like to enable it only on tablets.'), + 3 => $this->l('I\'d like to enable it on both smartphones and tablets.') + ) + ), + ), + 'after_tabs' => array( + 'cur_theme' => Theme::getThemeInfo($this->context->shop->id_theme), + ), + 'submit' => array('title' => $this->l('Save')), + 'buttons' => array( + 'storeLink' => array( + 'title' => $this->l('Visit the theme catalog'), + 'icon' => 'process-icon-themes', + 'href' => 'http://addons.prestashop.com/en/3-templates-prestashop' + .'?utm_source=back-office&utm_medium=theme-button' + .'&utm_campaign=back-office-'.$iso_lang_uc + .'&utm_content='.(defined('_PS_HOST_MODE_') ? 'cloud' : 'download'), + 'js' => 'return !window.open(this.href)' + ) + ) + ), + ); - $installed_theme = Theme::getAllThemes(array($this->context->shop->id_theme)); - $non_installed_theme = ($this->context->mode == Context::MODE_HOST) ? array() : Theme::getNonInstalledTheme(); - if (count($installed_theme) || !empty($non_installed_theme)) - { - $this->fields_options['theme'] = array( - 'title' => sprintf($this->l('Select a theme for the "%s" shop'), $this->context->shop->name), - 'description' => (!$this->can_display_themes) ? $this->l('You must select a shop from the above list if you wish to choose a theme.') : '', - 'fields' => array( - 'theme_for_shop' => array( - 'type' => 'theme', - 'themes' => $installed_theme, - 'not_installed' => $non_installed_theme, - 'id_theme' => $this->context->shop->id_theme, - 'can_display_themes' => $this->can_display_themes, - 'no_multishop_checkbox' => true - ), - ), - ); - } - } + $installed_theme = Theme::getAllThemes(array($this->context->shop->id_theme)); + $non_installed_theme = ($this->context->mode == Context::MODE_HOST) ? array() : Theme::getNonInstalledTheme(); + if (count($installed_theme) || !empty($non_installed_theme)) { + $this->fields_options['theme'] = array( + 'title' => sprintf($this->l('Select a theme for the "%s" shop'), $this->context->shop->name), + 'description' => (!$this->can_display_themes) ? $this->l('You must select a shop from the above list if you wish to choose a theme.') : '', + 'fields' => array( + 'theme_for_shop' => array( + 'type' => 'theme', + 'themes' => $installed_theme, + 'not_installed' => $non_installed_theme, + 'id_theme' => $this->context->shop->id_theme, + 'can_display_themes' => $this->can_display_themes, + 'no_multishop_checkbox' => true + ), + ), + ); + } + } - public function renderForm() - { - $get_available_themes = Theme::getAvailable(false); - $available_theme_dir = array(); - $selected_theme_dir = null; - $metas = Meta::getMetas(); - $formated_metas = array(); + public function renderForm() + { + $get_available_themes = Theme::getAvailable(false); + $available_theme_dir = array(); + $selected_theme_dir = null; + $metas = Meta::getMetas(); + $formated_metas = array(); - $image_url = false; - if ($this->object) - { - if ((int)$this->object->id > 0) - { - $theme = New Theme((int)$this->object->id); - $theme_metas = Db::getInstance()->executeS('SELECT ml.`title`, m.`page`, tm.`left_column` as `left`, tm.`right_column` as `right`, m.`id_meta`, tm.`id_theme_meta` + $image_url = false; + if ($this->object) { + if ((int)$this->object->id > 0) { + $theme = new Theme((int)$this->object->id); + $theme_metas = Db::getInstance()->executeS('SELECT ml.`title`, m.`page`, tm.`left_column` as `left`, tm.`right_column` as `right`, m.`id_meta`, tm.`id_theme_meta` FROM '._DB_PREFIX_.'theme_meta as tm LEFT JOIN '._DB_PREFIX_.'meta m ON (m.`id_meta` = tm.`id_meta`) LEFT JOIN '._DB_PREFIX_.'meta_lang ml ON(ml.id_meta = m.id_meta AND ml.id_lang = '.(int)$this->context->language->id. - ((int)Context::getContext()->shop->id ? ' AND id_shop = '.(int)Context::getContext()->shop->id : '').') + ((int)Context::getContext()->shop->id ? ' AND id_shop = '.(int)Context::getContext()->shop->id : '').') WHERE tm.`id_theme` = '.(int)$this->object->id); - // if no theme_meta are found, we must create them - if (empty($theme_metas)) - { - $metas = Db::getInstance()->executeS('SELECT id_meta FROM '._DB_PREFIX_.'meta'); - $metas_default = array(); - foreach ($metas as $meta) - { - $tmp_meta['id_meta'] = (int)$meta['id_meta']; - $tmp_meta['left'] = 1; - $tmp_meta['right'] = 1; - $metas_default[] = $tmp_meta; - } - $theme->updateMetas($metas_default); - $theme_metas = Db::getInstance()->executeS('SELECT ml.`title`, m.`page`, tm.`left_column` as `left`, tm.`right_column` as `right`, m.`id_meta`, tm.`id_theme_meta` + // if no theme_meta are found, we must create them + if (empty($theme_metas)) { + $metas = Db::getInstance()->executeS('SELECT id_meta FROM '._DB_PREFIX_.'meta'); + $metas_default = array(); + foreach ($metas as $meta) { + $tmp_meta['id_meta'] = (int)$meta['id_meta']; + $tmp_meta['left'] = 1; + $tmp_meta['right'] = 1; + $metas_default[] = $tmp_meta; + } + $theme->updateMetas($metas_default); + $theme_metas = Db::getInstance()->executeS('SELECT ml.`title`, m.`page`, tm.`left_column` as `left`, tm.`right_column` as `right`, m.`id_meta`, tm.`id_theme_meta` FROM '._DB_PREFIX_.'theme_meta as tm LEFT JOIN '._DB_PREFIX_.'meta m ON (m.`id_meta` = tm.`id_meta`) LEFT JOIN '._DB_PREFIX_.'meta_lang ml ON(ml.id_meta = m.id_meta AND ml.id_lang = '.(int)$this->context->language->id.') WHERE tm.`id_theme` = '.(int)$this->object->id); - } - - $image_url = '<img alt="preview" src="'.__PS_BASE_URI__.'themes/'.$theme->directory.'/preview.jpg">'; - - foreach ($theme_metas as $key => &$meta) - if (!isset($meta['title']) || !$meta['title'] || $meta['title'] == '') - $meta['title'] = $meta['page']; - - $formated_metas = $theme_metas; - } - $selected_theme_dir = $this->object->directory; - } - - foreach ($get_available_themes as $k => $dirname) - { - $available_theme_dir[$k]['value'] = $dirname; - $available_theme_dir[$k]['label'] = $dirname; - $available_theme_dir[$k]['id'] = $dirname; - }; - - $this->fields_form = array( - 'tinymce' => false, - 'legend' => array( - 'title' => $this->l('Theme'), - 'icon' => 'icon-picture' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name of the theme'), - 'name' => 'name', - 'required' => true, - 'hint' => $this->l('Invalid characters:').' <>;=#{}', - ), - array( - 'type' => 'file', - 'label' => $this->l('Preview image for the theme'), - 'name' => 'image_preview', - 'display_image' => true, - 'hint' => sprintf($this->l('Maximum image size: %1s'), Tools::formatBytes(Tools::getMaxUploadSize())), - 'image' => $image_url, - ), - array( - 'type' => 'switch', - 'label' => $this->l('Default left column'), - 'name' => 'default_left_column', - 'hint' => $this->l('Choose a default behavior when displaying the column in a new page added by you or by a module.'), - 'values' => array( - array( - 'id' => 'default_left_column_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'default_left_column_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Default right column'), - 'name' => 'default_right_column', - 'hint' => $this->l('Choose a default behavior when displaying the column in a new page added by you or by a module.'), - 'values' => array( - array( - 'id' => 'default_right_column_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'default_right_column_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - ), - array( - 'type' => 'text', - 'label' => $this->l('Number of products per page'), - 'name' => 'product_per_page', - 'hint' => $this->l('This value will be used when activating the theme.'), - ) - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ); - // adding a new theme, you can create a directory, and copy from an existing theme - if ($this->display == 'add' || !Validate::isLoadedObject($this->object)) - { - $this->fields_form['input'][] = array( - 'type' => 'text', - 'label' => $this->l('Name of the theme\'s directory'), - 'name' => 'directory', - 'required' => true, - 'hint' => $this->l('If the directory does not exist, PrestaShop will create it automatically.'), - ); - - $theme_query = Theme::getThemes(); - $this->fields_form['input'][] = array( - 'type' => 'select', - 'name' => 'based_on', - 'label' => $this->l('Copy missing files from existing theme'), - 'hint' => $this->l('If you create a new theme from scratch, it is recommended that you use the files from the default theme as a foundation.'), - 'options' => array( - 'id' => 'id', - 'name' => 'name', - 'default' => array( - 'value' => 0, - 'label' => '-' - ), - 'query' => $theme_query, - ) - ); - - $this->fields_form['input'][] = array( - 'type' => 'switch', - 'label' => $this->l('Responsive'), - 'name' => 'responsive', - 'hint' => $this->l('Please indicate if the theme is adapted to all screen sizes (mobile, tablet, desktop).'), - 'values' => array( - array( - 'id' => 'responsive_on', - 'value' => 1, - 'label' => $this->l('Yes') - ), - array( - 'id' => 'responsive_off', - 'value' => 0, - 'label' => $this->l('No') - ) - ), - ); - } - else - $this->fields_form['input'][] = array( - 'type' => 'radio', - 'label' => $this->l('Directory'), - 'name' => 'directory', - 'required' => true, - 'br' => true, - 'values' => $available_theme_dir, - 'selected' => $selected_theme_dir, - 'hint' => $this->l('Please select a valid theme directory.'), - ); - - $list = ''; - if (Tools::getIsset('update'.$this->table)) - { - $fields_list = array( - 'title' => array( - 'title' => $this->l('Meta'), - 'align' => 'center', - 'width' => 'auto' - ), - 'left' => array( - 'title' => $this->l('Left column'), - 'active' => 'left', - 'type' => 'bool', - 'ajax' => true - ), - 'right' => array( - 'title' => $this->l('Right column'), - 'active' => 'right', - 'type' => 'bool', - 'ajax' => true - ), - ); - $helper_list = New HelperList(); - $helper_list->tpl_vars = array('icon' => 'icon-columns'); - $helper_list->title = $this->l('Appearance of columns'); - $helper_list->no_link = true; - $helper_list->shopLinkType = ''; - $helper_list->identifier = 'id_theme_meta'; - $helper_list->table = 'meta'; - $helper_list->tpl_vars['show_filters'] = false; - $helper_list->currentIndex = $this->context->link->getAdminLink('AdminThemes', false); - $helper_list->token = Tools::getAdminTokenLite('AdminThemes'); - $list = $helper_list->generateList($formated_metas, $fields_list); - } - - return parent::renderForm().$list; - } - - public function renderList() - { - return parent::renderList(); - } - - /** - * copy $base_theme_dir into $target_theme_dir. - * - * @param string $base_theme_dir relative path to base dir - * @param string $target_theme_dir relative path to target dir - * - * @return bool true if success - */ - protected static function copyTheme($base_theme_dir, $target_theme_dir) - { - $res = true; - $base_theme_dir = Tools::normalizeDirectory($base_theme_dir); - $base_dir = _PS_ALL_THEMES_DIR_.$base_theme_dir; - $target_theme_dir = Tools::normalizeDirectory($target_theme_dir); - $target_dir = _PS_ALL_THEMES_DIR_.$target_theme_dir; - $files = scandir($base_dir); - - foreach ($files as $file) - { - if (!in_array($file[0], array('.', '..', '.svn'))) - { - if (is_dir($base_dir.$file)) - { - if (!is_dir($target_dir.$file)) - mkdir($target_dir.$file, Theme::$access_rights); - - $res &= AdminThemesController::copyTheme($base_theme_dir.$file, $target_theme_dir.$file); - } - elseif (!file_exists($target_dir.$file)) - $res &= copy($base_dir.$file, $target_dir.$file); - } - } - - return $res; - } - - public function downloadAddonsThemes() - { - if (!$this->logged_on_addons) - return false; - - if (!$this->isFresh(Theme::CACHE_FILE_CUSTOMER_THEMES_LIST, 86400)) - file_put_contents(_PS_ROOT_DIR_.Theme::CACHE_FILE_CUSTOMER_THEMES_LIST, Tools::addonsRequest('customer_themes')); - - $customer_themes_list = file_get_contents(_PS_ROOT_DIR_.Theme::CACHE_FILE_CUSTOMER_THEMES_LIST); - if (!empty($customer_themes_list) && $customer_themes_list_xml = simplexml_load_string($customer_themes_list)) - { - foreach ($customer_themes_list_xml->theme as $addons_theme) - { - //get addons theme if folder does not exist - $ids_themes = Tools::unSerialize(Configuration::get('PS_ADDONS_THEMES_IDS')); - - if (!is_array($ids_themes) || (is_array($ids_themes) && !in_array((string)$addons_theme->id, $ids_themes))) - { - $zip_content = Tools::addonsRequest('module', array( - 'id_module' => pSQL($addons_theme->id), - 'username_addons' => pSQL(trim($this->context->cookie->username_addons)), - 'password_addons' => pSQL(trim($this->context->cookie->password_addons))) - ); - - $uniqid = uniqid(); - $sandbox = _PS_CACHE_DIR_.'sandbox'.DIRECTORY_SEPARATOR.$uniqid.DIRECTORY_SEPARATOR; - mkdir($sandbox); - - file_put_contents($sandbox.(string)$addons_theme->name.'.zip', $zip_content); - - if ($this->extractTheme($sandbox.(string)$addons_theme->name.'.zip', $sandbox)) - if ($theme_directory = $this->installTheme(Theme::UPLOADED_THEME_DIR_NAME, $sandbox, false)) - $ids_themes[$theme_directory] = (string)$addons_theme->id; - - Tools::deleteDirectory($sandbox); - } - Configuration::updateValue('PS_ADDONS_THEMES_IDS', serialize($ids_themes)); - } - } - } - - public function processAdd() - { - if (Tools::getValue('directory') == '' || Tools::getValue('name') == '') - { - $this->errors[] = $this->l('Form invalid'); - $this->display = 'form'; - return false; - } - if (($new_dir = Tools::getValue('directory')) != '') - { - if (!Validate::isDirName($new_dir)) - { - $this->display = 'add'; - - return !($this->errors[] = sprintf(Tools::displayError('"%s" is not a valid directory name'), $new_dir)); - } - if (Theme::getByDirectory($new_dir)) - { - $this->display = 'add'; - - return !($this->errors[] = Tools::displayError('A directory with this name already exists.')); - } - - if (mkdir(_PS_ALL_THEMES_DIR_.$new_dir, Theme::$access_rights)) - $this->confirmations[] = $this->l('The directory was successfully created.'); - - if (0 !== $id_based = (int)Tools::getValue('based_on')) - { - $base_theme = new Theme($id_based); - $this->copyTheme($base_theme->directory, $new_dir); - $base_theme = new Theme((int)Tools::getValue('based_on')); - } - - if (isset($_FILES['image_preview']) && $_FILES['image_preview']['error'] == 0) - { - if (@getimagesize($_FILES['image_preview']['tmp_name']) && !ImageManager::validateUpload($_FILES['image_preview'], Tools::getMaxUploadSize())) - move_uploaded_file($_FILES['image_preview']['tmp_name'], _PS_ALL_THEMES_DIR_.$new_dir.'/preview.jpg'); - else - { - $this->errors[] = $this->l('Image is not valid.'); - $this->display = 'form'; - - return false; - } - } - } - - /** @var Theme $theme */ - $theme = parent::processAdd(); - if ((int)$theme->product_per_page == 0) - { - $theme->product_per_page = 1; - $theme->save(); - } - if (is_object($theme) && (int)$theme->id > 0) - { - - $metas = Meta::getMetas(); - - foreach ($metas as &$meta) - { - $meta['left'] = $theme->default_left_column; - $meta['right'] = $theme->default_right_column; - - } - $theme->updateMetas($metas, true); - } - - return $theme; - } - - public function processUpdate() - { - if (Tools::getIsset('id_theme') && Tools::getIsset('name') && Tools::getIsset('directory')) - { - - $theme = New Theme((int)Tools::getValue('id_theme')); - $theme->name = Tools::getValue('name'); - $theme->directory = Tools::getValue('directory'); - $theme->default_left_column = Tools::getValue('default_left_column'); - $theme->default_right_column = Tools::getValue('default_right_column'); - $nb_product_per_page = (int)Tools::getValue('product_per_page'); - if ($nb_product_per_page == 0) - $nb_product_per_page = 1; - - $theme->product_per_page = $nb_product_per_page; - - if ($this->context->shop->id_theme == (int)Tools::getValue('id_theme')) - Configuration::updateValue('PS_PRODUCTS_PER_PAGE', $nb_product_per_page); - - if (isset($_FILES['image_preview']) && $_FILES['image_preview']['error'] == 0) - { - if (@getimagesize($_FILES['image_preview']['tmp_name']) && !ImageManager::validateUpload($_FILES['image_preview'], 300000)) - move_uploaded_file($_FILES['image_preview']['tmp_name'], _PS_ALL_THEMES_DIR_.$theme->directory.'/preview.jpg'); - else - { - $this->errors[] = $this->l('Image is not valid.'); - $this->display = 'form'; - - return false; - } - } - $theme->update(); - } - Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminThemes').'&conf=29'); - } - - protected function processUpdateOptions() - { - parent::processUpdateOptions(); - - if (!count($this->errors)) - Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminThemes').'&conf=6'); - } - - public function processDelete() - { - /** @var Theme $obj */ - $obj = $this->loadObject(); - if ($obj) - { - - if ($obj->isUsed()) - { - $this->errors[] = $this->l('The theme is being used by at least one shop. Please choose another theme before continuing.'); - - return false; - } - $themes = array(); - foreach (Theme::getThemes() as $theme) - { - /** @var Theme $theme */ - if ($theme->id != $obj->id) - $themes[] = $theme->directory; - } - - if (is_dir(_PS_ALL_THEMES_DIR_.$obj->directory) && !in_array($obj->directory, $themes)) - Tools::deleteDirectory(_PS_ALL_THEMES_DIR_.$obj->directory.'/'); - - $ids_themes = Tools::unSerialize(Configuration::get('PS_ADDONS_THEMES_IDS')); - if (array_key_exists($obj->directory, $ids_themes)) - unset($ids_themes[$obj->directory]); - - $obj->removeMetas(); - } - elseif ($obj === false && $theme_dir = Tools::getValue('theme_dir')) - { - $theme_dir = basename($theme_dir); - if (Tools::deleteDirectory(_PS_ALL_THEMES_DIR_.$theme_dir.'/')) - Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminThemes').'&conf=2'); - else - $this->errors[] = Tools::displayError('The folder cannot be deleted'); - } - - return parent::processDelete(); - } - - public function initPageHeaderToolbar() - { - parent::initPageHeaderToolbar(); - - if (empty($this->display)) - { - $this->page_header_toolbar_btn['import_theme'] = array( - 'href' => self::$currentIndex.'&action=importtheme&token='.$this->token, - 'desc' => $this->l('Add new theme', null, null, false), - 'icon' => 'process-icon-new' - ); - - if ($this->context->mode) - unset($this->toolbar_btn['new']); - - $this->page_header_toolbar_btn['export_theme'] = array( - 'href' => self::$currentIndex.'&action=exporttheme&token='.$this->token, - 'desc' => $this->l('Export theme', null, null, false), - 'icon' => 'process-icon-export' - ); - } - - if ($this->display == 'importtheme') - $this->toolbar_title[] = $this->l('Import theme'); - elseif ($this->display == 'exporttheme') - $this->toolbar_title[] = $this->l('Export theme'); - else - $this->toolbar_title[] = $this->l('Theme'); - - $title = implode(' '.Configuration::get('PS_NAVIGATION_PIPE').' ', $this->toolbar_title); - $this->page_header_toolbar_title = $title; - } - - private function checkParentClass($name) - { - if (!$obj = Module::getInstanceByName($name)) - return false; - if (is_callable(array($obj, 'validateOrder'))) - return false; - if (is_callable(array($obj, 'getDateBetween'))) - return false; - if (is_callable(array($obj, 'getGridEngines'))) - return false; - if (is_callable(array($obj, 'getGraphEngines'))) - return false; - if (is_callable(array($obj, 'hookAdminStatsModules'))) - return false; - else - return true; - } - - private function checkNames() - { - $author = Tools::getValue('name'); - $theme_name = Tools::getValue('theme_name'); - - if (!$author || !Validate::isGenericName($author) || strlen($author) > self::MAX_NAME_LENGTH) - $this->errors[] = $this->l('Please enter a valid author name'); - elseif (!$theme_name || !Validate::isGenericName($theme_name) || strlen($theme_name) > self::MAX_NAME_LENGTH) - $this->errors[] = $this->l('Please enter a valid theme name'); - - if (count($this->errors) > 0) - return false; - - return true; - } - - private function checkDocumentation() - { - $extensions = array( - '.pdf', - '.txt' - ); - - if (isset($_FILES['documentation']) && $_FILES['documentation']['name'] != '') - { - $extension = strrchr($_FILES['documentation']['name'], '.'); - $name = Tools::getValue('documentationName'); - - if (!in_array($extension, $extensions)) - $this->errors[] = $this->l('File extension must be .txt or .pdf'); - elseif ($_FILES['documentation']['error'] > 0) - $this->errors[] = $this->l('An error occurred during documentation upload'); - elseif ($_FILES['documentation']['size'] > 1048576) - $this->errors[] = $this->l('An error occurred while uploading the documentation. Maximum size allowed is 1MB.'); - elseif (!$name || !Validate::isGenericName($name) || strlen($name) > self::MAX_NAME_LENGTH) - $this->errors[] = $this->l('Please enter a valid documentation name'); - } - - if (count($this->errors) > 0) - return false; - - return true; - } - - private function checkVersionsAndCompatibility() - { - $exp = '#^[0-9]+[.]+[0-9.]*[0-9]$#'; - - if (!preg_match('#^[0-9][.][0-9]$#', Tools::getValue('theme_version')) || - !preg_match($exp, Tools::getValue('compa_from')) || !preg_match($exp, Tools::getValue('compa_to')) || - version_compare(Tools::getValue('compa_from'), Tools::getValue('compa_to')) == 1 - ) - $this->errors[] = $this->l('Syntax error on version field. Only digits and periods (.) are allowed, and the compatibility version should be increasing or at least be equal to the previous version.'); - - if (count($this->errors) > 0) - return false; - - return true; - } - - private function checkPostedDatas() - { - $mail = Tools::getValue('email'); - $website = Tools::getValue('website'); - - if ($mail && !preg_match('#^[\w.-]+@[\w.-]+\.[a-zA-Z]{2,6}$#', $mail)) - $this->errors[] = $this->l('There is an error in your email syntax!'); - elseif ($website && (!Validate::isURL($website) || !Validate::isAbsoluteUrl($website))) - $this->errors[] = $this->l('There is an error in your URL syntax!'); - elseif (!$this->checkVersionsAndCompatibility() || !$this->checkNames() || !$this->checkDocumentation()) - return false; - else - return true; - - return false; - } - - /** - * @param ZipArchive $obj - * @param string $file - * @param string $server_path - * @param string $archive_path - */ - private function archiveThisFile($obj, $file, $server_path, $archive_path) - { - if (is_dir($server_path.$file)) - { - $dir = scandir($server_path.$file); - foreach ($dir as $row) - { - if ($row != '.' && $row != '..') - $this->archiveThisFile($obj, $row, $server_path.$file.'/', $archive_path.$file.'/'); - } - } - elseif (!$obj->addFile($server_path.$file, $archive_path.$file)) - $this->error = true; - } - - private function generateArchive() - { - $zip = new ZipArchive(); - $zip_file_name = md5(time()).'.zip'; - if ($zip->open(_PS_CACHE_DIR_.$zip_file_name, ZipArchive::OVERWRITE | ZipArchive::CREATE) === true) - { - if (!$zip->addFromString('Config.xml', $this->xml_file)) - $this->errors[] = $this->l('Cannot create config file.'); - - if (isset($_FILES['documentation'])) - if (!empty($_FILES['documentation']['tmp_name']) && - !empty($_FILES['documentation']['name']) && - !$zip->addFile($_FILES['documentation']['tmp_name'], 'doc/'.$_FILES['documentation']['name'])) - $this->errors[] = $this->l('Cannot copy documentation.'); - - $given_path = realpath(_PS_ALL_THEMES_DIR_.Tools::getValue('theme_directory')); - - if ($given_path !== false) - { - $ps_all_theme_dir_lenght = strlen(realpath(_PS_ALL_THEMES_DIR_)); - $to_compare_path = substr($given_path, 0, $ps_all_theme_dir_lenght); - if ($to_compare_path != realpath(_PS_ALL_THEMES_DIR_)) - $this->errors[] = $this->l('Wrong theme directory path'); - else - { - $this->archiveThisFile($zip, Tools::getValue('theme_directory'), _PS_ALL_THEMES_DIR_, 'themes/'); - foreach ($this->to_export as $row) - { - if (!in_array($row, $this->native_modules)) - $this->archiveThisFile($zip, $row, _PS_ROOT_DIR_.'/modules/', 'modules/'); - } - } - } - else - $this->errors[] = $this->l('Wrong theme directory path'); - - $zip->close(); - - if (!$this->errors) - { - if (ob_get_length() > 0) - ob_end_clean(); - - ob_start(); - header('Pragma: public'); - header('Expires: 0'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Cache-Control: public'); - header('Content-Description: File Transfer'); - header('Content-type: application/octet-stream'); - header('Content-Disposition: attachment; filename="'.$zip_file_name.'"'); - header('Content-Transfer-Encoding: binary'); - ob_end_flush(); - readfile(_PS_CACHE_DIR_.$zip_file_name); - @unlink(_PS_CACHE_DIR_.$zip_file_name); - exit; - } - } - - $this->errors[] = $this->l('An error occurred during the archive generation'); - } - - private function generateXML($theme_to_export, $metas) - { - $theme = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><!-- Copyright PrestaShop --><theme></theme>'); - $theme->addAttribute('version', Tools::getValue('theme_version')); - $theme->addAttribute('name', Tools::htmlentitiesUTF8(Tools::getValue('theme_name'))); - $theme->addAttribute('directory', Tools::htmlentitiesUTF8(Tools::getValue('theme_directory'))); - $author = $theme->addChild('author'); - $author->addAttribute('name', Tools::htmlentitiesUTF8(Tools::getValue('name'))); - $author->addAttribute('email', Tools::htmlentitiesUTF8(Tools::getValue('email'))); - $author->addAttribute('url', Tools::htmlentitiesUTF8(Tools::getValue('website'))); - - $descriptions = $theme->addChild('descriptions'); - $languages = Language::getLanguages(); - foreach ($languages as $language) - { - $val = Tools::htmlentitiesUTF8(Tools::getValue('body_title_'.$language['id_lang'])); - $description = $descriptions->addChild('description', Tools::htmlentitiesUTF8($val)); - $description->addAttribute('iso', $language['iso_code']); - } - - - $variations = $theme->addChild('variations'); - - $variation = $variations->addChild('variation'); - $variation->addAttribute('name', Tools::htmlentitiesUTF8(Tools::getValue('theme_name'))); - $variation->addAttribute('directory', Tools::getValue('theme_directory')); - $variation->addAttribute('responsive', $theme_to_export->responsive); - $variation->addAttribute('default_left_column', $theme_to_export->default_left_column); - $variation->addAttribute('default_right_column', $theme_to_export->default_right_column); - $variation->addAttribute('product_per_page', $theme_to_export->product_per_page); - $variation->addAttribute('from', Tools::getValue('compa_from')); - $variation->addAttribute('to', Tools::getValue('compa_to')); - - $docs = $theme->addChild('docs'); - if (isset($this->user_doc)) - foreach ($this->user_doc as $row) - { - $array = explode('¤', $row); - $doc = $docs->addChild('doc'); - $doc->addAttribute('name', $array[0]); - $doc->addAttribute('path', $array[1]); - } - - $metas_xml = $theme->addChild('metas'); - - foreach ($metas as $row) - { - $meta_obj = New Meta((int)$row['id_meta']); - - $meta_xml = $metas_xml->addChild('meta'); - $meta_xml->addAttribute('meta_page', $meta_obj->page); - $meta_xml->addAttribute('left', $row['left_column']); - $meta_xml->addAttribute('right', $row['right_column']); - } - $modules = $theme->addChild('modules'); - if (isset($this->to_export)) - foreach ($this->to_export as $row) - { - if (!in_array($row, $this->native_modules)) - { - $module = $modules->addChild('module'); - $module->addAttribute('action', 'install'); - $module->addAttribute('name', $row); - } - } - foreach ($this->to_enable as $row) - { - $module = $modules->addChild('module'); - $module->addAttribute('action', 'enable'); - $module->addAttribute('name', $row); - } - foreach ($this->to_disable as $row) - { - $module = $modules->addChild('module'); - $module->addAttribute('action', 'disable'); - $module->addAttribute('name', $row); - } - - $hooks = $modules->addChild('hooks'); - foreach ($this->to_hook as $row) - { - $array = explode(';', $row); - $hook = $hooks->addChild('hook'); - $hook->addAttribute('module', $array[0]); - $hook->addAttribute('hook', $array[1]); - $hook->addAttribute('position', $array[2]); - if (!empty($array[3])) - $hook->addAttribute('exceptions', $array[3]); - } - - $images = $theme->addChild('images'); - foreach ($this->image_list as $row) - { - $array = explode(';', $row); - $image = $images->addChild('image'); - $image->addAttribute('name', Tools::htmlentitiesUTF8($array[0])); - $image->addAttribute('width', $array[1]); - $image->addAttribute('height', $array[2]); - $image->addAttribute('products', $array[3]); - $image->addAttribute('categories', $array[4]); - $image->addAttribute('manufacturers', $array[5]); - $image->addAttribute('suppliers', $array[6]); - $image->addAttribute('scenes', $array[7]); - } - $this->xml_file = $theme->asXML(); - } - - public function processExportTheme() - { - if (Tools::isSubmit('name')) - { - if ($this->checkPostedDatas()) - { - $filename = Tools::htmlentitiesUTF8($_FILES['documentation']['name']); - $name = Tools::htmlentitiesUTF8(Tools::getValue('documentationName')); - $this->user_doc = array($name.'¤doc/'.$filename); - - - $table = Db::getInstance()->executeS(' + } + + $image_url = '<img alt="preview" src="'.__PS_BASE_URI__.'themes/'.$theme->directory.'/preview.jpg">'; + + foreach ($theme_metas as $key => &$meta) { + if (!isset($meta['title']) || !$meta['title'] || $meta['title'] == '') { + $meta['title'] = $meta['page']; + } + } + + $formated_metas = $theme_metas; + } + $selected_theme_dir = $this->object->directory; + } + + foreach ($get_available_themes as $k => $dirname) { + $available_theme_dir[$k]['value'] = $dirname; + $available_theme_dir[$k]['label'] = $dirname; + $available_theme_dir[$k]['id'] = $dirname; + }; + + $this->fields_form = array( + 'tinymce' => false, + 'legend' => array( + 'title' => $this->l('Theme'), + 'icon' => 'icon-picture' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name of the theme'), + 'name' => 'name', + 'required' => true, + 'hint' => $this->l('Invalid characters:').' <>;=#{}', + ), + array( + 'type' => 'file', + 'label' => $this->l('Preview image for the theme'), + 'name' => 'image_preview', + 'display_image' => true, + 'hint' => sprintf($this->l('Maximum image size: %1s'), Tools::formatBytes(Tools::getMaxUploadSize())), + 'image' => $image_url, + ), + array( + 'type' => 'switch', + 'label' => $this->l('Default left column'), + 'name' => 'default_left_column', + 'hint' => $this->l('Choose a default behavior when displaying the column in a new page added by you or by a module.'), + 'values' => array( + array( + 'id' => 'default_left_column_on', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'default_left_column_off', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + ), + array( + 'type' => 'switch', + 'label' => $this->l('Default right column'), + 'name' => 'default_right_column', + 'hint' => $this->l('Choose a default behavior when displaying the column in a new page added by you or by a module.'), + 'values' => array( + array( + 'id' => 'default_right_column_on', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'default_right_column_off', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + ), + array( + 'type' => 'text', + 'label' => $this->l('Number of products per page'), + 'name' => 'product_per_page', + 'hint' => $this->l('This value will be used when activating the theme.'), + ) + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ); + // adding a new theme, you can create a directory, and copy from an existing theme + if ($this->display == 'add' || !Validate::isLoadedObject($this->object)) { + $this->fields_form['input'][] = array( + 'type' => 'text', + 'label' => $this->l('Name of the theme\'s directory'), + 'name' => 'directory', + 'required' => true, + 'hint' => $this->l('If the directory does not exist, PrestaShop will create it automatically.'), + ); + + $theme_query = Theme::getThemes(); + $this->fields_form['input'][] = array( + 'type' => 'select', + 'name' => 'based_on', + 'label' => $this->l('Copy missing files from existing theme'), + 'hint' => $this->l('If you create a new theme from scratch, it is recommended that you use the files from the default theme as a foundation.'), + 'options' => array( + 'id' => 'id', + 'name' => 'name', + 'default' => array( + 'value' => 0, + 'label' => '-' + ), + 'query' => $theme_query, + ) + ); + + $this->fields_form['input'][] = array( + 'type' => 'switch', + 'label' => $this->l('Responsive'), + 'name' => 'responsive', + 'hint' => $this->l('Please indicate if the theme is adapted to all screen sizes (mobile, tablet, desktop).'), + 'values' => array( + array( + 'id' => 'responsive_on', + 'value' => 1, + 'label' => $this->l('Yes') + ), + array( + 'id' => 'responsive_off', + 'value' => 0, + 'label' => $this->l('No') + ) + ), + ); + } else { + $this->fields_form['input'][] = array( + 'type' => 'radio', + 'label' => $this->l('Directory'), + 'name' => 'directory', + 'required' => true, + 'br' => true, + 'values' => $available_theme_dir, + 'selected' => $selected_theme_dir, + 'hint' => $this->l('Please select a valid theme directory.'), + ); + } + + $list = ''; + if (Tools::getIsset('update'.$this->table)) { + $fields_list = array( + 'title' => array( + 'title' => $this->l('Meta'), + 'align' => 'center', + 'width' => 'auto' + ), + 'left' => array( + 'title' => $this->l('Left column'), + 'active' => 'left', + 'type' => 'bool', + 'ajax' => true + ), + 'right' => array( + 'title' => $this->l('Right column'), + 'active' => 'right', + 'type' => 'bool', + 'ajax' => true + ), + ); + $helper_list = new HelperList(); + $helper_list->tpl_vars = array('icon' => 'icon-columns'); + $helper_list->title = $this->l('Appearance of columns'); + $helper_list->no_link = true; + $helper_list->shopLinkType = ''; + $helper_list->identifier = 'id_theme_meta'; + $helper_list->table = 'meta'; + $helper_list->tpl_vars['show_filters'] = false; + $helper_list->currentIndex = $this->context->link->getAdminLink('AdminThemes', false); + $helper_list->token = Tools::getAdminTokenLite('AdminThemes'); + $list = $helper_list->generateList($formated_metas, $fields_list); + } + + return parent::renderForm().$list; + } + + public function renderList() + { + return parent::renderList(); + } + + /** + * copy $base_theme_dir into $target_theme_dir. + * + * @param string $base_theme_dir relative path to base dir + * @param string $target_theme_dir relative path to target dir + * + * @return bool true if success + */ + protected static function copyTheme($base_theme_dir, $target_theme_dir) + { + $res = true; + $base_theme_dir = Tools::normalizeDirectory($base_theme_dir); + $base_dir = _PS_ALL_THEMES_DIR_.$base_theme_dir; + $target_theme_dir = Tools::normalizeDirectory($target_theme_dir); + $target_dir = _PS_ALL_THEMES_DIR_.$target_theme_dir; + $files = scandir($base_dir); + + foreach ($files as $file) { + if (!in_array($file[0], array('.', '..', '.svn'))) { + if (is_dir($base_dir.$file)) { + if (!is_dir($target_dir.$file)) { + mkdir($target_dir.$file, Theme::$access_rights); + } + + $res &= AdminThemesController::copyTheme($base_theme_dir.$file, $target_theme_dir.$file); + } elseif (!file_exists($target_dir.$file)) { + $res &= copy($base_dir.$file, $target_dir.$file); + } + } + } + + return $res; + } + + public function downloadAddonsThemes() + { + if (!$this->logged_on_addons) { + return false; + } + + if (!$this->isFresh(Theme::CACHE_FILE_CUSTOMER_THEMES_LIST, 86400)) { + file_put_contents(_PS_ROOT_DIR_.Theme::CACHE_FILE_CUSTOMER_THEMES_LIST, Tools::addonsRequest('customer_themes')); + } + + $customer_themes_list = file_get_contents(_PS_ROOT_DIR_.Theme::CACHE_FILE_CUSTOMER_THEMES_LIST); + if (!empty($customer_themes_list) && $customer_themes_list_xml = @simplexml_load_string($customer_themes_list)) { + foreach ($customer_themes_list_xml->theme as $addons_theme) { + //get addons theme if folder does not exist + $ids_themes = Tools::unSerialize(Configuration::get('PS_ADDONS_THEMES_IDS')); + + if (!is_array($ids_themes) || (is_array($ids_themes) && !in_array((string)$addons_theme->id, $ids_themes))) { + $zip_content = Tools::addonsRequest( + 'module', + array( + 'id_module' => pSQL($addons_theme->id), + 'username_addons' => pSQL(trim($this->context->cookie->username_addons)), + 'password_addons' => pSQL(trim($this->context->cookie->password_addons)) + ) + ); + + $uniqid = uniqid(); + $sandbox = _PS_CACHE_DIR_.'sandbox'.DIRECTORY_SEPARATOR.$uniqid.DIRECTORY_SEPARATOR; + mkdir($sandbox); + + file_put_contents($sandbox.(string)$addons_theme->name.'.zip', $zip_content); + + if ($this->extractTheme($sandbox.(string)$addons_theme->name.'.zip', $sandbox)) { + if ($theme_directory = $this->installTheme(Theme::UPLOADED_THEME_DIR_NAME, $sandbox, false)) { + $ids_themes[$theme_directory] = (string)$addons_theme->id; + } + } + + Tools::deleteDirectory($sandbox); + } + Configuration::updateValue('PS_ADDONS_THEMES_IDS', serialize($ids_themes)); + } + } + } + + public function processAdd() + { + if (Tools::getValue('directory') == '' || Tools::getValue('name') == '') { + $this->errors[] = $this->l('Form invalid'); + $this->display = 'form'; + return false; + } + if (($new_dir = Tools::getValue('directory')) != '') { + if (!Validate::isDirName($new_dir)) { + $this->display = 'add'; + + return !($this->errors[] = sprintf(Tools::displayError('"%s" is not a valid directory name'), $new_dir)); + } + if (Theme::getByDirectory($new_dir)) { + $this->display = 'add'; + + return !($this->errors[] = Tools::displayError('A directory with this name already exists.')); + } + + if (mkdir(_PS_ALL_THEMES_DIR_.$new_dir, Theme::$access_rights)) { + $this->confirmations[] = $this->l('The directory was successfully created.'); + } + + if (0 !== $id_based = (int)Tools::getValue('based_on')) { + $base_theme = new Theme($id_based); + $this->copyTheme($base_theme->directory, $new_dir); + $base_theme = new Theme((int)Tools::getValue('based_on')); + } + + if (isset($_FILES['image_preview']) && $_FILES['image_preview']['error'] == 0) { + if (@getimagesize($_FILES['image_preview']['tmp_name']) && !ImageManager::validateUpload($_FILES['image_preview'], Tools::getMaxUploadSize())) { + move_uploaded_file($_FILES['image_preview']['tmp_name'], _PS_ALL_THEMES_DIR_.$new_dir.'/preview.jpg'); + } else { + $this->errors[] = $this->l('Image is not valid.'); + $this->display = 'form'; + + return false; + } + } + } + + /** @var Theme $theme */ + $theme = parent::processAdd(); + if ((int)$theme->product_per_page == 0) { + $theme->product_per_page = 1; + $theme->save(); + } + if (is_object($theme) && (int)$theme->id > 0) { + $metas = Meta::getMetas(); + + foreach ($metas as &$meta) { + $meta['left'] = $theme->default_left_column; + $meta['right'] = $theme->default_right_column; + } + $theme->updateMetas($metas, true); + } + + return $theme; + } + + public function processUpdate() + { + if (Tools::getIsset('id_theme') && Tools::getIsset('name') && Tools::getIsset('directory')) { + $theme = new Theme((int)Tools::getValue('id_theme')); + $theme->name = Tools::getValue('name'); + $theme->directory = Tools::getValue('directory'); + $theme->default_left_column = Tools::getValue('default_left_column'); + $theme->default_right_column = Tools::getValue('default_right_column'); + $nb_product_per_page = (int)Tools::getValue('product_per_page'); + if ($nb_product_per_page == 0) { + $nb_product_per_page = 1; + } + + $theme->product_per_page = $nb_product_per_page; + + if ($this->context->shop->id_theme == (int)Tools::getValue('id_theme')) { + Configuration::updateValue('PS_PRODUCTS_PER_PAGE', $nb_product_per_page); + } + + if (isset($_FILES['image_preview']) && $_FILES['image_preview']['error'] == 0) { + if (@getimagesize($_FILES['image_preview']['tmp_name']) && !ImageManager::validateUpload($_FILES['image_preview'], 300000)) { + move_uploaded_file($_FILES['image_preview']['tmp_name'], _PS_ALL_THEMES_DIR_.$theme->directory.'/preview.jpg'); + } else { + $this->errors[] = $this->l('Image is not valid.'); + $this->display = 'form'; + + return false; + } + } + $theme->update(); + } + Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminThemes').'&conf=29'); + } + + protected function processUpdateOptions() + { + parent::processUpdateOptions(); + + if (!count($this->errors)) { + Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminThemes').'&conf=6'); + } + } + + public function processDelete() + { + /** @var Theme $obj */ + $obj = $this->loadObject(); + if ($obj) { + if ($obj->isUsed()) { + $this->errors[] = $this->l('The theme is being used by at least one shop. Please choose another theme before continuing.'); + + return false; + } + $themes = array(); + foreach (Theme::getThemes() as $theme) { + /** @var Theme $theme */ + if ($theme->id != $obj->id) { + $themes[] = $theme->directory; + } + } + + if (is_dir(_PS_ALL_THEMES_DIR_.$obj->directory) && !in_array($obj->directory, $themes)) { + Tools::deleteDirectory(_PS_ALL_THEMES_DIR_.$obj->directory.'/'); + } + + $ids_themes = Tools::unSerialize(Configuration::get('PS_ADDONS_THEMES_IDS')); + if (array_key_exists($obj->directory, $ids_themes)) { + unset($ids_themes[$obj->directory]); + } + + $obj->removeMetas(); + } elseif ($obj === false && $theme_dir = Tools::getValue('theme_dir')) { + $theme_dir = basename($theme_dir); + if (Tools::deleteDirectory(_PS_ALL_THEMES_DIR_.$theme_dir.'/')) { + Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminThemes').'&conf=2'); + } else { + $this->errors[] = Tools::displayError('The folder cannot be deleted'); + } + } + + return parent::processDelete(); + } + + public function initPageHeaderToolbar() + { + parent::initPageHeaderToolbar(); + + if (empty($this->display)) { + $this->page_header_toolbar_btn['import_theme'] = array( + 'href' => self::$currentIndex.'&action=importtheme&token='.$this->token, + 'desc' => $this->l('Add new theme', null, null, false), + 'icon' => 'process-icon-new' + ); + + if ($this->context->mode) { + unset($this->toolbar_btn['new']); + } + + $this->page_header_toolbar_btn['export_theme'] = array( + 'href' => self::$currentIndex.'&action=exporttheme&token='.$this->token, + 'desc' => $this->l('Export theme', null, null, false), + 'icon' => 'process-icon-export' + ); + } + + if ($this->display == 'importtheme') { + $this->toolbar_title[] = $this->l('Import theme'); + } elseif ($this->display == 'exporttheme') { + $this->toolbar_title[] = $this->l('Export theme'); + } else { + $this->toolbar_title[] = $this->l('Theme'); + } + + $title = implode(' '.Configuration::get('PS_NAVIGATION_PIPE').' ', $this->toolbar_title); + $this->page_header_toolbar_title = $title; + } + + private function checkParentClass($name) + { + if (!$obj = Module::getInstanceByName($name)) { + return false; + } + if (is_callable(array($obj, 'validateOrder'))) { + return false; + } + if (is_callable(array($obj, 'getDateBetween'))) { + return false; + } + if (is_callable(array($obj, 'getGridEngines'))) { + return false; + } + if (is_callable(array($obj, 'getGraphEngines'))) { + return false; + } + if (is_callable(array($obj, 'hookAdminStatsModules'))) { + return false; + } else { + return true; + } + } + + private function checkNames() + { + $author = Tools::getValue('name'); + $theme_name = Tools::getValue('theme_name'); + + if (!$author || !Validate::isGenericName($author) || strlen($author) > self::MAX_NAME_LENGTH) { + $this->errors[] = $this->l('Please enter a valid author name'); + } elseif (!$theme_name || !Validate::isGenericName($theme_name) || strlen($theme_name) > self::MAX_NAME_LENGTH) { + $this->errors[] = $this->l('Please enter a valid theme name'); + } + + if (count($this->errors) > 0) { + return false; + } + + return true; + } + + private function checkDocumentation() + { + $extensions = array( + '.pdf', + '.txt' + ); + + if (isset($_FILES['documentation']) && $_FILES['documentation']['name'] != '') { + $extension = strrchr($_FILES['documentation']['name'], '.'); + $name = Tools::getValue('documentationName'); + + if (!in_array($extension, $extensions)) { + $this->errors[] = $this->l('File extension must be .txt or .pdf'); + } elseif ($_FILES['documentation']['error'] > 0) { + $this->errors[] = $this->l('An error occurred during documentation upload'); + } elseif ($_FILES['documentation']['size'] > 1048576) { + $this->errors[] = $this->l('An error occurred while uploading the documentation. Maximum size allowed is 1MB.'); + } elseif (!$name || !Validate::isGenericName($name) || strlen($name) > self::MAX_NAME_LENGTH) { + $this->errors[] = $this->l('Please enter a valid documentation name'); + } + } + + if (count($this->errors) > 0) { + return false; + } + + return true; + } + + private function checkVersionsAndCompatibility() + { + $exp = '#^[0-9]+[.]+[0-9.]*[0-9]$#'; + + if (!preg_match('#^[0-9][.][0-9]$#', Tools::getValue('theme_version')) || + !preg_match($exp, Tools::getValue('compa_from')) || !preg_match($exp, Tools::getValue('compa_to')) || + version_compare(Tools::getValue('compa_from'), Tools::getValue('compa_to')) == 1 + ) { + $this->errors[] = $this->l('Syntax error on version field. Only digits and periods (.) are allowed, and the compatibility version should be increasing or at least be equal to the previous version.'); + } + + if (count($this->errors) > 0) { + return false; + } + + return true; + } + + private function checkPostedDatas() + { + $mail = Tools::getValue('email'); + $website = Tools::getValue('website'); + + if ($mail && !preg_match('#^[\w.-]+@[\w.-]+\.[a-zA-Z]{2,6}$#', $mail)) { + $this->errors[] = $this->l('There is an error in your email syntax!'); + } elseif ($website && (!Validate::isURL($website) || !Validate::isAbsoluteUrl($website))) { + $this->errors[] = $this->l('There is an error in your URL syntax!'); + } elseif (!$this->checkVersionsAndCompatibility() || !$this->checkNames() || !$this->checkDocumentation()) { + return false; + } else { + return true; + } + + return false; + } + + /** + * @param ZipArchive $obj + * @param string $file + * @param string $server_path + * @param string $archive_path + */ + private function archiveThisFile($obj, $file, $server_path, $archive_path) + { + if (is_dir($server_path.$file)) { + $dir = scandir($server_path.$file); + foreach ($dir as $row) { + if ($row[0] != '.') { + $this->archiveThisFile($obj, $row, $server_path.$file.'/', $archive_path.$file.'/'); + } + } + } elseif (!$obj->addFile($server_path.$file, $archive_path.$file)) { + $this->error = true; + } + } + + private function generateArchive() + { + $zip = new ZipArchive(); + $zip_file_name = md5(time()).'.zip'; + if ($zip->open(_PS_CACHE_DIR_.$zip_file_name, ZipArchive::OVERWRITE | ZipArchive::CREATE) === true) { + if (!$zip->addFromString('Config.xml', $this->xml_file)) { + $this->errors[] = $this->l('Cannot create config file.'); + } + + if (isset($_FILES['documentation'])) { + if (!empty($_FILES['documentation']['tmp_name']) && + !empty($_FILES['documentation']['name']) && + !$zip->addFile($_FILES['documentation']['tmp_name'], 'doc/'.$_FILES['documentation']['name'])) { + $this->errors[] = $this->l('Cannot copy documentation.'); + } + } + + $given_path = realpath(_PS_ALL_THEMES_DIR_.Tools::getValue('theme_directory')); + + if ($given_path !== false) { + $ps_all_theme_dir_lenght = strlen(realpath(_PS_ALL_THEMES_DIR_)); + $to_compare_path = substr($given_path, 0, $ps_all_theme_dir_lenght); + if ($to_compare_path != realpath(_PS_ALL_THEMES_DIR_)) { + $this->errors[] = $this->l('Wrong theme directory path'); + } else { + $this->archiveThisFile($zip, Tools::getValue('theme_directory'), _PS_ALL_THEMES_DIR_, 'themes/'); + foreach ($this->to_export as $row) { + if (!in_array($row, $this->native_modules)) { + $this->archiveThisFile($zip, $row, _PS_ROOT_DIR_.'/modules/', 'modules/'); + } + } + } + } else { + $this->errors[] = $this->l('Wrong theme directory path'); + } + + $zip->close(); + + if (!is_file(_PS_CACHE_DIR_.$zip_file_name)) { + $this->errors[] = $this->l(sprintf('Could not create %1s', _PS_CACHE_DIR_.$zip_file_name)); + } + + if (!$this->errors) { + if (ob_get_length() > 0) { + ob_end_clean(); + } + + ob_start(); + header('Pragma: public'); + header('Expires: 0'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Cache-Control: public'); + header('Content-Description: File Transfer'); + header('Content-type: application/octet-stream'); + header('Content-Disposition: attachment; filename="'.$zip_file_name.'"'); + header('Content-Transfer-Encoding: binary'); + ob_end_flush(); + readfile(_PS_CACHE_DIR_.$zip_file_name); + @unlink(_PS_CACHE_DIR_.$zip_file_name); + exit; + } + } + + $this->errors[] = $this->l('An error occurred during the archive generation'); + } + + private function generateXML($theme_to_export, $metas) + { + $theme = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><!-- Copyright PrestaShop --><theme></theme>'); + $theme->addAttribute('version', Tools::getValue('theme_version')); + $theme->addAttribute('name', Tools::htmlentitiesUTF8(Tools::getValue('theme_name'))); + $theme->addAttribute('directory', Tools::htmlentitiesUTF8(Tools::getValue('theme_directory'))); + $author = $theme->addChild('author'); + $author->addAttribute('name', Tools::htmlentitiesUTF8(Tools::getValue('name'))); + $author->addAttribute('email', Tools::htmlentitiesUTF8(Tools::getValue('email'))); + $author->addAttribute('url', Tools::htmlentitiesUTF8(Tools::getValue('website'))); + + $descriptions = $theme->addChild('descriptions'); + $languages = Language::getLanguages(); + foreach ($languages as $language) { + $val = Tools::htmlentitiesUTF8(Tools::getValue('body_title_'.$language['id_lang'])); + $description = $descriptions->addChild('description', Tools::htmlentitiesUTF8($val)); + $description->addAttribute('iso', $language['iso_code']); + } + + + $variations = $theme->addChild('variations'); + + $variation = $variations->addChild('variation'); + $variation->addAttribute('name', Tools::htmlentitiesUTF8(Tools::getValue('theme_name'))); + $variation->addAttribute('directory', Tools::getValue('theme_directory')); + $variation->addAttribute('responsive', $theme_to_export->responsive); + $variation->addAttribute('default_left_column', $theme_to_export->default_left_column); + $variation->addAttribute('default_right_column', $theme_to_export->default_right_column); + $variation->addAttribute('product_per_page', $theme_to_export->product_per_page); + $variation->addAttribute('from', Tools::getValue('compa_from')); + $variation->addAttribute('to', Tools::getValue('compa_to')); + + $docs = $theme->addChild('docs'); + if (isset($this->user_doc)) { + foreach ($this->user_doc as $row) { + $array = explode('¤', $row); + $doc = $docs->addChild('doc'); + $doc->addAttribute('name', $array[0]); + $doc->addAttribute('path', $array[1]); + } + } + + $metas_xml = $theme->addChild('metas'); + + foreach ($metas as $row) { + $meta_obj = new Meta((int)$row['id_meta']); + + $meta_xml = $metas_xml->addChild('meta'); + $meta_xml->addAttribute('meta_page', $meta_obj->page); + $meta_xml->addAttribute('left', $row['left_column']); + $meta_xml->addAttribute('right', $row['right_column']); + } + $modules = $theme->addChild('modules'); + if (isset($this->to_export)) { + foreach ($this->to_export as $row) { + if (!in_array($row, $this->native_modules)) { + $module = $modules->addChild('module'); + $module->addAttribute('action', 'install'); + $module->addAttribute('name', $row); + } + } + } + foreach ($this->to_enable as $row) { + $module = $modules->addChild('module'); + $module->addAttribute('action', 'enable'); + $module->addAttribute('name', $row); + } + foreach ($this->to_disable as $row) { + $module = $modules->addChild('module'); + $module->addAttribute('action', 'disable'); + $module->addAttribute('name', $row); + } + + $hooks = $modules->addChild('hooks'); + foreach ($this->to_hook as $row) { + $array = explode(';', $row); + $hook = $hooks->addChild('hook'); + $hook->addAttribute('module', $array[0]); + $hook->addAttribute('hook', $array[1]); + $hook->addAttribute('position', $array[2]); + if (!empty($array[3])) { + $hook->addAttribute('exceptions', $array[3]); + } + } + + $images = $theme->addChild('images'); + foreach ($this->image_list as $row) { + $array = explode(';', $row); + $image = $images->addChild('image'); + $image->addAttribute('name', Tools::htmlentitiesUTF8($array[0])); + $image->addAttribute('width', $array[1]); + $image->addAttribute('height', $array[2]); + $image->addAttribute('products', $array[3]); + $image->addAttribute('categories', $array[4]); + $image->addAttribute('manufacturers', $array[5]); + $image->addAttribute('suppliers', $array[6]); + $image->addAttribute('scenes', $array[7]); + } + $this->xml_file = $theme->asXML(); + } + + public function processExportTheme() + { + if (Tools::isSubmit('name')) { + if ($this->checkPostedDatas()) { + $filename = Tools::htmlentitiesUTF8($_FILES['documentation']['name']); + $name = Tools::htmlentitiesUTF8(Tools::getValue('documentationName')); + $this->user_doc = array($name.'¤doc/'.$filename); + + + $table = Db::getInstance()->executeS(' SELECT name, width, height, products, categories, manufacturers, suppliers, scenes FROM `'._DB_PREFIX_.'image_type`'); - $this->image_list = array(); - foreach ($table as $row) - { - $this->image_list[] = $row['name'].';'.$row['width'].';'.$row['height'].';'. - ($row['products'] == 1 ? 'true' : 'false').';'. - ($row['categories'] == 1 ? 'true' : 'false').';'. - ($row['manufacturers'] == 1 ? 'true' : 'false').';'. - ($row['suppliers'] == 1 ? 'true' : 'false').';'. - ($row['scenes'] == 1 ? 'true' : 'false'); - } + $this->image_list = array(); + foreach ($table as $row) { + $this->image_list[] = $row['name'].';'.$row['width'].';'.$row['height'].';'. + ($row['products'] == 1 ? 'true' : 'false').';'. + ($row['categories'] == 1 ? 'true' : 'false').';'. + ($row['manufacturers'] == 1 ? 'true' : 'false').';'. + ($row['suppliers'] == 1 ? 'true' : 'false').';'. + ($row['scenes'] == 1 ? 'true' : 'false'); + } - $id_shop = Db::getInstance()->getValue('SELECT `id_shop` FROM `'._DB_PREFIX_.'shop` WHERE `id_theme` = '.(int)Tools::getValue('id_theme_export')); + $id_shop = Db::getInstance()->getValue('SELECT `id_shop` FROM `'._DB_PREFIX_.'shop` WHERE `id_theme` = '.(int)Tools::getValue('id_theme_export')); - // Select the list of module for this shop - $this->module_list = Db::getInstance()->executeS(' + // Select the list of module for this shop + $this->module_list = Db::getInstance()->executeS(' SELECT m.`id_module`, m.`name`, m.`active`, ms.`id_shop` FROM `'._DB_PREFIX_.'module` m LEFT JOIN `'._DB_PREFIX_.'module_shop` ms On (m.`id_module` = ms.`id_module`) WHERE ms.`id_shop` = '.(int)$id_shop.' '); - // Select the list of hook for this shop - $this->hook_list = Db::getInstance()->executeS(' + // Select the list of hook for this shop + $this->hook_list = Db::getInstance()->executeS(' SELECT h.`id_hook`, h.`name` as name_hook, hm.`position`, hm.`id_module`, m.`name` as name_module, GROUP_CONCAT(hme.`file_name`, ",") as exceptions FROM `'._DB_PREFIX_.'hook` h LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_hook` = h.`id_hook` @@ -1076,95 +1066,97 @@ class AdminThemesControllerCore extends AdminController ORDER BY `name_module` '); - $this->native_modules = $this->getNativeModule(); + $this->native_modules = $this->getNativeModule(); - foreach ($this->hook_list as &$row) - $row['exceptions'] = trim(preg_replace('/(,,+)/', ',', $row['exceptions']), ','); + foreach ($this->hook_list as &$row) { + $row['exceptions'] = trim(preg_replace('/(,,+)/', ',', $row['exceptions']), ','); + } - $this->to_install = array(); - $this->to_enable = array(); - $this->to_hook = array(); + $this->to_install = array(); + $this->to_enable = array(); + $this->to_hook = array(); - foreach ($this->module_list as $array) - { - if (!self::checkParentClass($array['name'])) - continue; - if (in_array($array['name'], $this->native_modules)) - { - if ($array['active'] == 1) - $this->to_enable[] = $array['name']; - else - $this->to_disable[] = $array['name']; - } - elseif ($array['active'] == 1) - $this->to_install[] = $array['name']; - } - foreach ($this->native_modules as $str) - { - $flag = 0; - if (!self::checkParentClass($str)) - continue; - foreach ($this->module_list as $tmp) - { - if (in_array($str, $tmp)) - { - $flag = 1; - break; - } - } - if ($flag == 0) - $this->to_disable[] = $str; - } + foreach ($this->module_list as $array) { + if (!self::checkParentClass($array['name'])) { + continue; + } + if (in_array($array['name'], $this->native_modules)) { + if ($array['active'] == 1) { + $this->to_enable[] = $array['name']; + } else { + $this->to_disable[] = $array['name']; + } + } elseif ($array['active'] == 1) { + $this->to_install[] = $array['name']; + } + } + foreach ($this->native_modules as $str) { + $flag = 0; + if (!self::checkParentClass($str)) { + continue; + } + foreach ($this->module_list as $tmp) { + if (in_array($str, $tmp)) { + $flag = 1; + break; + } + } + if ($flag == 0) { + $this->to_disable[] = $str; + } + } - foreach ($_POST as $key => $value) - if (strncmp($key, 'modulesToExport_module', strlen('modulesToExport_module')) == 0) - $this->to_export[] = $value; + foreach ($_POST as $key => $value) { + if (strncmp($key, 'modulesToExport_module', strlen('modulesToExport_module')) == 0) { + $this->to_export[] = $value; + } + } - if ($this->to_install) - foreach ($this->to_install as $string) - { - foreach ($this->hook_list as $tmp) - { - if ($tmp['name_module'] == $string) - $this->to_hook[] = $string.';'.$tmp['name_hook'].';'.$tmp['position'].';'.$tmp['exceptions']; - } - } - if ($this->to_enable) - foreach ($this->to_enable as $string) - { - foreach ($this->hook_list as $tmp) - { - if ($tmp['name_module'] == $string) - $this->to_hook[] = $string.';'.$tmp['name_hook'].';'.$tmp['position'].';'.$tmp['exceptions']; - } - } + if ($this->to_install) { + foreach ($this->to_install as $string) { + foreach ($this->hook_list as $tmp) { + if ($tmp['name_module'] == $string) { + $this->to_hook[] = $string.';'.$tmp['name_hook'].';'.$tmp['position'].';'.$tmp['exceptions']; + } + } + } + } + if ($this->to_enable) { + foreach ($this->to_enable as $string) { + foreach ($this->hook_list as $tmp) { + if ($tmp['name_module'] == $string) { + $this->to_hook[] = $string.';'.$tmp['name_hook'].';'.$tmp['position'].';'.$tmp['exceptions']; + } + } + } + } - $theme_to_export = New Theme((int)Tools::getValue('id_theme_export')); - $metas = $theme_to_export->getMetas(); + $theme_to_export = new Theme((int)Tools::getValue('id_theme_export')); + $metas = $theme_to_export->getMetas(); - $this->generateXML($theme_to_export, $metas); - $this->generateArchive(); - } - else - $this->display = 'exporttheme'; - } - else - $this->display = 'exporttheme'; - } + $this->generateXML($theme_to_export, $metas); + $this->generateArchive(); + } else { + $this->display = 'exporttheme'; + } + } else { + $this->display = 'exporttheme'; + } + } - private function renderExportTheme1() - { - $to_install = array(); + private function renderExportTheme1() + { + $to_install = array(); - $module_list = Db::getInstance()->executeS(' + $module_list = Db::getInstance()->executeS(' SELECT m.`id_module`, m.`name`, m.`active`, ms.`id_shop` FROM `'._DB_PREFIX_.'module` m LEFT JOIN `'._DB_PREFIX_.'module_shop` ms On (m.`id_module` = ms.`id_module`) WHERE ms.`id_shop` = '.(int)$this->context->shop->id.' '); - // Select the list of hook for this shop - $hook_list = Db::getInstance()->executeS(' + // Select the list of hook for this shop + $hook_list = Db::getInstance()->executeS(' SELECT h.`id_hook`, h.`name` as name_hook, hm.`position`, hm.`id_module`, m.`name` as name_module, GROUP_CONCAT(hme.`file_name`, ",") as exceptions FROM `'._DB_PREFIX_.'hook` h LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_hook` = h.`id_hook` @@ -1175,1212 +1167,1221 @@ class AdminThemesControllerCore extends AdminController ORDER BY `name_module` '); - foreach ($hook_list as &$row) - $row['exceptions'] = trim(preg_replace('/(,,+)/', ',', $row['exceptions']), ','); - - $native_modules = $this->getNativeModule(); - - foreach ($module_list as $array) - { - if (!self::checkParentClass($array['name'])) - continue; - if (in_array($array['name'], $native_modules)) - { - if ($array['active'] == 1) - $to_enable[] = $array['name']; - else - $to_disable[] = $array['name']; - } - elseif ($array['active'] == 1) - $to_install[] = $array['name']; - } - foreach ($native_modules as $str) - { - $flag = 0; - if (!$this->checkParentClass($str)) - continue; - foreach ($module_list as $tmp) - { - if (in_array($str, $tmp)) - { - $flag = 1; - break; - } - } - if ($flag == 0) - $to_disable[] = $str; - } - - $employee = $this->context->employee; - $mail = Tools::getValue('email') ? Tools::getValue('email') : $employee->email; - $author = Tools::getValue('author_name') ? Tools::getValue('author_name') : $employee->firstname.' '.$employee->lastname; - $website = Tools::getValue('website') ? Tools::getValue('website') : Tools::getHttpHost(true); - - $this->formatHelperArray($to_install); - - $theme = New Theme(Tools::getValue('id_theme_export')); - - $fields_form = array( - 'form' => array( - 'tinymce' => false, - 'legend' => array( - 'title' => $this->l('Theme configuration'), - 'icon' => 'icon-picture' - ), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'id_theme_export' - ), - array( - 'type' => 'text', - 'name' => 'name', - 'label' => $this->l('Name'), - ), - array( - 'type' => 'text', - 'name' => 'email', - 'label' => $this->l('Email'), - ), - array( - 'type' => 'text', - 'name' => 'website', - 'label' => $this->l('Website'), - ), - array( - 'type' => 'text', - 'name' => 'theme_name', - 'label' => $this->l('Theme name'), - ), - array( - 'type' => 'text', - 'name' => 'theme_directory', - 'label' => $this->l('Theme directory'), - ), - array( - 'type' => 'text', - 'name' => 'body_title', - 'lang' => true, - 'label' => $this->l('Description'), - ), - array( - 'type' => 'text', - 'name' => 'theme_version', - 'label' => $this->l('Theme version'), - ), - array( - 'type' => 'text', - 'name' => 'compa_from', - 'label' => $this->l('Compatible from'), - ), - array( - 'type' => 'text', - 'name' => 'compa_to', - 'label' => $this->l('Compatible to'), - ), - array( - 'type' => 'file', - 'name' => 'documentation', - 'label' => $this->l('Documentation'), - ), - array( - 'type' => 'text', - 'name' => 'documentationName', - 'label' => $this->l('Documentation name'), - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ) - ); - - if (count($to_install) > 0) - { - foreach ($to_install as $module) - $fields_value['modulesToExport_module'.$module] = true; - - $fields_form['form']['input'][] = array( - 'type' => 'checkbox', - 'label' => $this->l('Select the theme\'s modules that you wish to export'), - 'values' => array( - 'query' => $this->formatHelperArray($to_install), - 'id' => 'id', - 'name' => 'name' - ), - 'name' => 'modulesToExport', - ); - } - - $default_language = (int)$this->context->language->id; - $languages = $this->getLanguages(); - - foreach ($languages as $language) - $fields_value['body_title'][$language['id_lang']] = ''; - - $helper = new HelperForm(); - $helper->languages = $languages; - $helper->default_form_language = $default_language; - $fields_value['name'] = $author; - $fields_value['email'] = $mail; - $fields_value['website'] = $website; - $fields_value['theme_name'] = $theme->name; - $fields_value['theme_directory'] = $theme->directory; - $fields_value['theme_version'] = '1.0'; - $fields_value['compa_from'] = _PS_VERSION_; - $fields_value['compa_to'] = _PS_VERSION_; - $fields_value['id_theme_export'] = Tools::getValue('id_theme_export'); - $fields_value['documentationName'] = $this->l('documentation'); - - $toolbar_btn['save'] = array( - 'href' => '', - 'desc' => $this->l('Save') - ); - - $helper->currentIndex = $this->context->link->getAdminLink('AdminThemes', false).'&action=exporttheme'; - $helper->token = Tools::getAdminTokenLite('AdminThemes'); - $helper->show_toolbar = true; - $helper->fields_value = $fields_value; - $helper->toolbar_btn = $toolbar_btn; - $helper->override_folder = $this->tpl_folder; - - return $helper->generateForm(array($fields_form)); - } - - public function renderExportTheme() - { - if (Tools::getIsset('id_theme_export') && (int)Tools::getValue('id_theme_export') > 0) - return $this->renderExportTheme1(); - - $theme_list = Theme::getThemes(); - $fields_form = array( - 'form' => array( - 'tinymce' => false, - 'legend' => array( - 'title' => $this->l('Theme'), - 'icon' => 'icon-picture' - ), - 'input' => array( - array( - 'type' => 'select', - 'name' => 'id_theme_export', - 'label' => $this->l('Choose the theme that you want to export'), - 'options' => array( - 'id' => 'id', - 'name' => 'name', - 'query' => $theme_list, - ) - - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ) - ); - - $toolbar_btn['save'] = array( - 'href' => '#', - 'desc' => $this->l('Export') - ); - - $fields_value['id_theme_export'] = array(); - $helper = new HelperForm(); - - $helper->currentIndex = $this->context->link->getAdminLink('AdminThemes', false).'&action=exporttheme'; - $helper->token = Tools::getAdminTokenLite('AdminThemes'); - $helper->show_toolbar = true; - $helper->fields_value = $fields_value; - $helper->toolbar_btn = $toolbar_btn; - $helper->override_folder = $this->tpl_folder; - - return $helper->generateForm(array($fields_form)); - } - - private function checkXmlFields($xml_file) - { - if (!file_exists($xml_file) || !$xml = simplexml_load_file($xml_file)) - return false; - if (!$xml['version'] || !$xml['name']) - return false; - foreach ($xml->variations->variation as $val) - { - if (!$val['name'] || !$val['directory'] || !$val['from'] || !$val['to']) - return false; - } - foreach ($xml->modules->module as $val) - { - if (!$val['action'] || !$val['name']) - return false; - } - foreach ($xml->modules->hooks->hook as $val) - { - if (!$val['module'] || !$val['hook'] || !$val['position']) - return false; - } - - return true; - } - - private function recurseCopy($src, $dst) - { - if (!$dir = opendir($src)) - return; - if (!file_exists($dst)) - mkdir($dst); - while (($file = readdir($dir)) !== false) - { - if (strncmp($file, '.', 1) != 0) - { - if (is_dir($src.'/'.$file)) - self::recurseCopy($src.'/'.$file, $dst.'/'.$file); - elseif (is_readable($src.'/'.$file) && $file != 'Thumbs.db' && $file != '.DS_Store' && substr($file, -1) != '~') - copy($src.'/'.$file, $dst.'/'.$file); - } - } - closedir($dir); - } - - public function processImportTheme() - { - $this->display = 'importtheme'; - - if ($this->context->mode == Context::MODE_HOST) - return true; - - if (isset($_FILES['themearchive']) && isset($_POST['filename']) && Tools::isSubmit('theme_archive_server')) - { - $uniqid = uniqid(); - $sandbox = _PS_CACHE_DIR_.'sandbox'.DIRECTORY_SEPARATOR.$uniqid.DIRECTORY_SEPARATOR; - mkdir($sandbox); - $archive_uploaded = false; - - if (Tools::getValue('filename') != '') - { - $uploader = new Uploader('themearchive'); - $uploader->setCheckFileSize(false); - $uploader->setAcceptTypes(array('zip')); - $uploader->setSavePath($sandbox); - $file = $uploader->process(Theme::UPLOADED_THEME_DIR_NAME.'.zip'); - - if ($file[0]['error'] === 0) - { - if (Tools::ZipTest($sandbox.Theme::UPLOADED_THEME_DIR_NAME.'.zip')) - $archive_uploaded = true; - else - $this->errors[] = $this->l('Zip file seems to be broken'); - } - else - $this->errors[] = $file[0]['error']; - - } - elseif (Tools::getValue('themearchiveUrl') != '') - { - if (!Validate::isModuleUrl($url = Tools::getValue('themearchiveUrl'), $this->errors)) - $this->errors[] = $this->l('Only zip files are allowed'); - elseif (!Tools::copy($url, $sandbox.Theme::UPLOADED_THEME_DIR_NAME.'.zip')) - $this->errors[] = $this->l('Error during the file download'); - elseif (Tools::ZipTest($sandbox.Theme::UPLOADED_THEME_DIR_NAME.'.zip')) - $archive_uploaded = true; - else - $this->errors[] = $this->l('Zip file seems to be broken'); - } - elseif (Tools::getValue('theme_archive_server') != '') - { - $filename = _PS_ALL_THEMES_DIR_.Tools::getValue('theme_archive_server'); - if (substr($filename, -4) != '.zip') - $this->errors[] = $this->l('Only zip files are allowed'); - elseif (!copy($filename, $sandbox.Theme::UPLOADED_THEME_DIR_NAME.'.zip')) - $this->errors[] = $this->l('An error has occurred during the file copy.'); - elseif (Tools::ZipTest($sandbox.Theme::UPLOADED_THEME_DIR_NAME.'.zip')) - $archive_uploaded = true; - else - $this->errors[] = $this->l('Zip file seems to be broken'); - } - else - $this->errors[] = $this->l('You must upload or enter a location of your zip'); - - if ($archive_uploaded) - if ($this->extractTheme($sandbox.Theme::UPLOADED_THEME_DIR_NAME.'.zip', $sandbox)) - $this->installTheme(Theme::UPLOADED_THEME_DIR_NAME, $sandbox); - - Tools::deleteDirectory($sandbox); - - if (count($this->errors) > 0) - $this->display = 'importtheme'; - else - Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminThemes').'&conf=18'); - } - } - - protected function extractTheme($theme_zip_file, $sandbox) - { - if (Tools::ZipExtract($theme_zip_file, $sandbox.Theme::UPLOADED_THEME_DIR_NAME.'/')) - return true; - - $this->errors[] = $this->l('Error during zip extraction'); - return false; - } - - protected function installTheme($theme_dir, $sandbox = false, $redirect = true) - { - if (!$sandbox) - { - $uniqid = uniqid(); - $sandbox = _PS_CACHE_DIR_.'sandbox'.DIRECTORY_SEPARATOR.$uniqid.DIRECTORY_SEPARATOR; - mkdir($sandbox); - Tools::recurseCopy(_PS_ALL_THEMES_DIR_.$theme_dir, $sandbox.$theme_dir); - } - - $xml_file = $sandbox.$theme_dir.'/Config.xml'; - if (!$this->checkXmlFields($xml_file)) - $this->errors[] = $this->l('Bad configuration file'); - else - { - $imported_theme = $this->importThemeXmlConfig(simplexml_load_file($xml_file)); - foreach ($imported_theme as $theme) - { - if (Validate::isLoadedObject($theme)) - { - if (!copy($sandbox.$theme_dir.'/Config.xml', _PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml')) - $this->errors[] = $this->l('Can\'t copy configuration file'); - - $target_dir = _PS_ALL_THEMES_DIR_.$theme->directory; - if (file_exists($target_dir)) - Tools::deleteDirectory($target_dir); - - $theme_doc_dir = $target_dir.'/docs/'; - if (file_exists($theme_doc_dir)) - Tools::deleteDirectory($theme_doc_dir); - - mkdir($target_dir); - mkdir($theme_doc_dir); - - Tools::recurseCopy($sandbox.$theme_dir.'/themes/'.$theme->directory.'/', $target_dir.'/'); - Tools::recurseCopy($sandbox.$theme_dir.'/doc/', $theme_doc_dir); - Tools::recurseCopy($sandbox.$theme_dir.'/modules/', _PS_MODULE_DIR_); - } - else - $this->errors[] = $theme; - } - } - - Tools::deleteDirectory($sandbox); - - if (!count($this->errors)) - { - if ($redirect) - Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminThemes').'&conf=18'); - else - return true; - } - else - return false; - } - - protected function isThemeInstalled($theme_name) - { - $themes = Theme::getThemes(); - - foreach ($themes as $theme_object) - { - /** @var Theme $theme_object */ - if ($theme_object->name == $theme_name) - return true; - } - return false; - } - - /** - * @param SimpleXMLElement $xml - * @param bool $theme_dir only used if the theme directory to import is already located on the shop - * - * @return array|string return array of themes on success, otherwise the error as a string is returned - */ - protected function importThemeXmlConfig(SimpleXMLElement $xml, $theme_dir = false) - { - $attr = $xml->attributes(); - $th_name = (string)$attr->name; - if ($this->isThemeInstalled($th_name)) - return array(sprintf($this->l('Theme %s already installed.'), $th_name)); - - $new_theme_array = array(); - foreach ($xml->variations->variation as $variation) - { - $name = strval($variation['name']); - - $new_theme = new Theme(); - $new_theme->name = $name; - - $new_theme->directory = strval($variation['directory']); - - if ($theme_dir) - { - $new_theme->name = $theme_dir; - $new_theme->directory = $theme_dir; - } - - if ($this->isThemeInstalled($new_theme->name)) - continue; - - $new_theme->product_per_page = Configuration::get('PS_PRODUCTS_PER_PAGE'); - - if (isset($variation['product_per_page'])) - $new_theme->product_per_page = intval($variation['product_per_page']); - - $new_theme->responsive = false; - if (isset($variation['responsive'])) - $new_theme->responsive = (bool)strval($variation['responsive']); - - $new_theme->default_left_column = true; - $new_theme->default_right_column = true; - - if (isset($variation['default_left_column'])) - $new_theme->default_left_column = (bool)strval($variation['default_left_column']); - - if (isset($variation['default_right_column'])) - $new_theme->default_right_column = (bool)strval($variation['default_right_column']); - - $fill_default_meta = true; - $metas_xml = array(); - if ($xml->metas->meta) - { - foreach ($xml->metas->meta as $meta) - { - $meta_id = Db::getInstance()->getValue('SELECT id_meta FROM '._DB_PREFIX_.'meta WHERE page=\''.pSQL($meta['meta_page']).'\''); - if ((int)$meta_id > 0) - { - $tmp_meta = array(); - $tmp_meta['id_meta'] = (int)$meta_id; - $tmp_meta['left'] = intval($meta['left']); - $tmp_meta['right'] = intval($meta['right']); - $metas_xml[(int)$meta_id] = $tmp_meta; - } - } - $fill_default_meta = false; - if (count($xml->metas->meta) < (int)Db::getInstance()->getValue('SELECT count(*) FROM '._DB_PREFIX_.'meta')) - $fill_default_meta = true; - - } - - if ($fill_default_meta == true) - { - $metas = Db::getInstance()->executeS('SELECT id_meta FROM '._DB_PREFIX_.'meta'); - foreach ($metas as $meta) - { - if (!isset($metas_xml[(int)$meta['id_meta']])) - { - $tmp_meta['id_meta'] = (int)$meta['id_meta']; - $tmp_meta['left'] = $new_theme->default_left_column; - $tmp_meta['right'] = $new_theme->default_right_column; - $metas_xml[(int)$meta['id_meta']] = $tmp_meta; - } - } - } - - if (!is_dir(_PS_ALL_THEMES_DIR_.$new_theme->directory)) - if (!mkdir(_PS_ALL_THEMES_DIR_.$new_theme->directory)) - return sprintf($this->l('Error while creating %s directory'), _PS_ALL_THEMES_DIR_.$new_theme->directory); - - $new_theme->add(); - - if ($new_theme->id > 0) - { - $new_theme->updateMetas($metas_xml); - $new_theme_array[] = $new_theme; - } - else - $new_theme_array[] = sprintf($this->l('Error while installing theme %s'), $new_theme->name); - - } - - return $new_theme_array; - } - - public function renderImportTheme() - { - $fields_form = array(); - - $toolbar_btn['save'] = array( - 'href' => '#', - 'desc' => $this->l('Save') - ); - - if ($this->context->mode != Context::MODE_HOST) - { - $fields_form[0] = array( - 'form' => array( - 'tinymce' => false, - 'legend' => array( - 'title' => $this->l('Import from your computer'), - 'icon' => 'icon-picture' - ), - 'input' => array( - array( - 'type' => 'file', - 'label' => $this->l('Zip file'), - 'desc' => $this->l('Browse your computer files and select the Zip file for your new theme.'), - 'name' => 'themearchive' - ), - ), - 'submit' => array( - 'id' => 'zip', - 'title' => $this->l('Save'), - ) - ), - ); - - $fields_form[1] = array( - 'form' => array( - 'tinymce' => false, - 'legend' => array( - 'title' => $this->l('Import from the web'), - 'icon' => 'icon-picture' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Archive URL'), - 'desc' => $this->l('Indicate the complete URL to an online Zip file that contains your new theme. For instance, "http://example.com/files/theme.zip".'), - 'name' => 'themearchiveUrl' - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ), - ); - - $theme_archive_server = array(); - $files = scandir(_PS_ALL_THEMES_DIR_); - $theme_archive_server[] = '-'; - - foreach ($files as $file) - { - if (is_file(_PS_ALL_THEMES_DIR_.$file) && substr(_PS_ALL_THEMES_DIR_.$file, -4) == '.zip') - { - $theme_archive_server[] = array( - 'id' => basename(_PS_ALL_THEMES_DIR_.$file), - 'name' => basename(_PS_ALL_THEMES_DIR_.$file) - ); - } - } - - $fields_form[2] = array( - 'form' => array( - 'tinymce' => false, - 'legend' => array( - 'title' => $this->l('Import from FTP'), - 'icon' => 'icon-picture' - ), - 'input' => array( - array( - 'type' => 'select', - 'label' => $this->l('Select the archive'), - 'name' => 'theme_archive_server', - 'desc' => $this->l('This selector lists the Zip files that you uploaded in the \'/themes\' folder.'), - 'options' => array( - 'id' => 'id', - 'name' => 'name', - 'query' => $theme_archive_server, - ) - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ) - ), - ); - } - - $this->context->smarty->assign( - array( - 'import_theme' => true, - 'logged_on_addons' => $this->logged_on_addons, - 'iso_code' => $this->context->language->iso_code, - 'add_new_theme_href' => self::$currentIndex.'&addtheme&token='.$this->token, - 'add_new_theme_label' => $this->l('Create a new theme'), - ) - ); - - $create_new_theme_panel = $this->context->smarty->fetch('controllers/themes/helpers/view/importtheme_view.tpl'); - - $helper = new HelperForm(); - - $helper->currentIndex = $this->context->link->getAdminLink('AdminThemes', false).'&action=importtheme'; - $helper->token = Tools::getAdminTokenLite('AdminThemes'); - $helper->show_toolbar = true; - $helper->toolbar_btn = $toolbar_btn; - $helper->fields_value['themearchiveUrl'] = ''; - $helper->fields_value['theme_archive_server'] = array(); - $helper->multiple_fieldsets = true; - $helper->override_folder = $this->tpl_folder; - $helper->languages = $this->getLanguages(); - $helper->default_form_language = (int)$this->context->language->id; - - return $helper->generateForm($fields_form).$create_new_theme_panel; - } - - public function initContent() - { - if ($this->display == 'list') - $this->display = ''; - if (isset($this->display) && method_exists($this, 'render'.$this->display)) - { - $this->content .= $this->initPageHeaderToolbar(); - - $this->content .= $this->{'render'.$this->display}(); - $this->context->smarty->assign(array( - 'content' => $this->content, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } - else - { - $content = ''; - if (Configuration::hasKey('PS_LOGO') && trim(Configuration::get('PS_LOGO')) != '' - && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO')) && filesize(_PS_IMG_DIR_.Configuration::get('PS_LOGO'))) - { - list($width, $height, $type, $attr) = getimagesize(_PS_IMG_DIR_.Configuration::get('PS_LOGO')); - Configuration::updateValue('SHOP_LOGO_HEIGHT', (int)round($height)); - Configuration::updateValue('SHOP_LOGO_WIDTH', (int)round($width)); - } - if (Configuration::get('PS_LOGO_MOBILE') && trim(Configuration::get('PS_LOGO_MOBILE')) != '' - && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_MOBILE')) && filesize(_PS_IMG_DIR_.Configuration::get('PS_LOGO_MOBILE'))) - { - list($width, $height, $type, $attr) = getimagesize(_PS_IMG_DIR_.Configuration::get('PS_LOGO_MOBILE')); - Configuration::updateValue('SHOP_LOGO_MOBILE_HEIGHT', (int)round($height)); - Configuration::updateValue('SHOP_LOGO_MOBILE_WIDTH', (int)round($width)); - } - - $this->content .= $content; - - return parent::initContent(); - } - } - - public function ajaxProcessGetAddonsThemes() - { - $parent_domain = Tools::getHttpHost(true).substr($_SERVER['REQUEST_URI'], 0, -1 * strlen(basename($_SERVER['REQUEST_URI']))); - $iso_lang = $this->context->language->iso_code; - $iso_currency = $this->context->currency->iso_code; - $iso_country = $this->context->country->iso_code; - $activity = Configuration::get('PS_SHOP_ACTIVITY'); - $addons_url = 'http://addons.prestashop.com/iframe/search-1.6.php?psVersion='._PS_VERSION_.'&onlyThemes=1&isoLang='.$iso_lang.'&isoCurrency='.$iso_currency.'&isoCountry='.$iso_country.'&activity='.(int)$activity.'&parentUrl='.$parent_domain; - - die(Tools::file_get_contents($addons_url)); - } - - /** - * This function checks if the theme designer has thunk to make his theme compatible 1.4, - * and noticed it on the $theme_dir/config.xml file. If not, some new functionnalities has - * to be desactivated - * - * @since 1.4 - * - * @param string $theme_dir theme directory - * - * @return bool Validity is ok or not - */ - protected function _isThemeCompatible($theme_dir) - { - $return = true; - $check_version = AdminThemes::$check_features_version; - - if (!is_file(_PS_ALL_THEMES_DIR_.$theme_dir.'/config.xml')) - { - $this->errors[] = Tools::displayError('The config.xml file is missing in your theme path.').'<br/>'; - $xml = null; - } - else - { - $xml = @simplexml_load_file(_PS_ALL_THEMES_DIR_.$theme_dir.'/config.xml'); - if (!$xml) - $this->errors[] = Tools::displayError('The config.xml file in your theme path is not a valid XML file.').'<br/>'; - } - // will be set to false if any version node in xml is correct - $xml_version_too_old = true; - - // foreach version in xml file, - // node means feature, attributes has to match - // the corresponding value in AdminThemes::$check_features[feature] array - $xmlArray = simpleXMLToArray($xml); - foreach ($xmlArray as $version) - { - if (isset($version['value']) && version_compare($version['value'], $check_version) >= 0) - { - foreach (AdminThemes::$check_features as $codeFeature => $arrConfigToCheck) - { - foreach ($arrConfigToCheck['attributes'] as $attr => $v) - { - if (!isset($version[$codeFeature]) || !isset($version[$codeFeature][$attr]) || $version[$codeFeature][$attr] != $v['value']) - if (!$this->_checkConfigForFeatures($codeFeature, $attr)) // feature missing in config.xml file, or wrong attribute value - $return = false; - } - } - $xml_version_too_old = false; - } - } - if ($xml_version_too_old && !$this->_checkConfigForFeatures(array_keys(AdminThemes::$check_features))) - { - $this->errors[] .= Tools::displayError('The config.xml file has not been created for this version of PrestaShop.'); - $return = false; - } - - return $return; - } - - /** - * _checkConfigForFeatures - * - * @param array $arrFeatures array of feature code to check - * @param mixed $configItem will precise the attribute which not matches. If empty, will check every attributes - * - * @return bool Error message, or null if disabled - */ - protected function _checkConfigForFeatures($arrFeatures, $configItem = array()) - { - $return = true; - if (is_array($configItem)) - { - foreach ($arrFeatures as $feature) - { - if (!count($configItem)) - $configItem = array_keys(AdminThemes::$check_features[$feature]['attributes']); - } - foreach ($configItem as $attr) - { - $check = $this->_checkConfigForFeatures($arrFeatures, $attr); - if ($check == false) - $return = false; - } - - return $return; - } - - $return = true; - if (!is_array($arrFeatures)) - $arrFeatures = array($arrFeatures); - - foreach ($arrFeatures as $feature) - { - $arrConfigToCheck = AdminThemes::$check_features[$feature]['attributes'][$configItem]['check_if_not_valid']; - foreach ($arrConfigToCheck as $config_key => $config_val) - { - $config_get = Configuration::get($config_key); - if ($config_get != $config_val) - { - $this->errors[] = Tools::displayError(AdminThemes::$check_features[$feature]['error']).'.' - .(!empty(AdminThemes::$check_features[$feature]['tab']) - ? ' <a href="?tab='.AdminThemes::$check_features[$feature]['tab'].'&token=' - .Tools::getAdminTokenLite(AdminThemes::$check_features[$feature]['tab']).'" ><u>' - .Tools::displayError('You can disable this function.') - .'</u></a>' : '' - ).'<br/>'; - $return = false; - break; // break for this attributes - } - } - } - - return $return; - } - - /** - * - * @param int $type - * $type = 0 both native & partner (default) - * $type = 1 native - * $type = 2 partner - * - * - * @return array - */ - private function getNativeModule($type = 0) - { - $xml = simplexml_load_string(Tools::file_get_contents(_PS_API_URL_.'/xml/modules_list_16.xml')); - - if ($xml) - { - $natives = array(); - - switch ($type) - { - case 0: - foreach ($xml->modules as $row) - foreach ($row->module as $row2) - $natives[] = (string)$row2['name']; - break; - case 1: - foreach ($xml->modules as $row) - if ($row['type'] == 'native') - foreach ($row->module as $row2) - $natives[] = (string)$row2['name']; - break; - case 2: - foreach ($xml->modules as $row) - if ($row['type'] == 'partner') - foreach ($row->module as $row2) - $natives[] = (string)$row2['name']; - break; - } - - if (count($natives) > 0) - return $natives; - } - - return array( - 'addsharethis', - 'bankwire', - 'blockadvertising', - 'blockbanner', - 'blockbestsellers', - 'blockcart', - 'blockcategories', - 'blockcms', - 'blockcmsinfo', - 'blockcontact', - 'blockcontactinfos', - 'blockcurrencies', - 'blockcustomerprivacy', - 'blockfacebook', - 'blocklanguages', - 'blocklayered', - 'blocklink', - 'blockmanufacturer', - 'blockmyaccount', - 'blockmyaccountfooter', - 'blocknewproducts', - 'blocknewsletter', - 'blockpaymentlogo', - 'blockpermanentlinks', - 'blockreinsurance', - 'blockrss', - 'blocksearch', - 'blocksharefb', - 'blocksocial', - 'blockspecials', - 'blockstore', - 'blocksupplier', - 'blocktags', - 'blocktopmenu', - 'blockuserinfo', - 'blockviewed', - 'blockwishlist', - 'carriercompare', - 'cashondelivery', - 'cheque', - 'crossselling', - 'dashactivity', - 'dashgoals', - 'dashproducts', - 'dashtrends', - 'dateofdelivery', - 'editorial', - 'favoriteproducts', - 'feeder', - 'followup', - 'gapi', - 'graphnvd3', - 'gridhtml', - 'homefeatured', - 'homeslider', - 'loyalty', - 'mailalerts', - 'newsletter', - 'pagesnotfound', - 'productcomments', - 'productpaymentlogos', - 'productscategory', - 'producttooltip', - 'pscleaner', - 'referralprogram', - 'sekeywords', - 'sendtoafriend', - 'socialsharing', - 'statsbestcategories', - 'statsbestcustomers', - 'statsbestmanufacturers', - 'statsbestproducts', - 'statsbestsuppliers', - 'statsbestvouchers', - 'statscarrier', - 'statscatalog', - 'statscheckup', - 'statsdata', - 'statsequipment', - 'statsforecast', - 'statslive', - 'statsnewsletter', - 'statsorigin', - 'statspersonalinfos', - 'statsproduct', - 'statsregistrations', - 'statssales', - 'statssearch', - 'statsstock', - 'statsvisits', - 'themeconfigurator', - 'trackingfront', - 'vatnumber', - 'watermark' - ); - } - - private function getModules($xml) - { - $native_modules = $this->getNativeModule(); - $theme_module = array(); - - $theme_module['to_install'] = array(); - $theme_module['to_enable'] = array(); - $theme_module['to_disable'] = array(); - foreach ($xml->modules->module as $row) - { - if (strval($row['action']) == 'install' && !in_array(strval($row['name']), $native_modules)) - $theme_module['to_install'][] = strval($row['name']); - elseif (strval($row['action']) == 'enable') - $theme_module['to_enable'][] = strval($row['name']); - elseif (strval($row['action']) == 'disable') - $theme_module['to_disable'][] = strval($row['name']); - } - - return $theme_module; - } - - private function formatHelperArray($origin_arr) - { - $fmt_arr = array(); - foreach ($origin_arr as $module) - { - $display_name = $module; - - $module_obj = Module::getInstanceByName($module); - if (Validate::isLoadedObject($module_obj)) - $display_name = $module_obj->displayName; - - $tmp = array(); - $tmp['id'] = 'module'.$module; - $tmp['val'] = $module; - $tmp['name'] = $display_name; - $fmt_arr[] = $tmp; - } - - return $fmt_arr; - } - - private function formatHelperValuesArray($originArr) - { - $fmtArr = array(); - foreach ($originArr as $key => $type) - foreach ($type as $module) - $fmtArr[$key.'_module'.$module] = true; - - return $fmtArr; - } - - public function renderChooseThemeModule() - { - $theme = New Theme((int)Tools::getValue('id_theme')); - - $xml = false; - if (file_exists(_PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml')) - $xml = simplexml_load_file(_PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml'); - elseif (file_exists(_PS_ROOT_DIR_.'/config/xml/themes/default.xml')) - $xml = simplexml_load_file(_PS_ROOT_DIR_.'/config/xml/themes/default.xml'); - - if ($xml) - { - $theme_module = $this->getModules($xml); - - $toolbar_btn['save'] = array( - 'href' => '#', - 'desc' => $this->l('Save') - ); - - $to_install = array(); - $to_enable = array(); - $to_disable = array(); - - if (isset($theme_module['to_install'])) - $to_install = $this->formatHelperArray($theme_module['to_install']); - if (isset($theme_module['to_enable'])) - $to_enable = $this->formatHelperArray($theme_module['to_enable']); - if (isset($theme_module['to_disable'])) - $to_disable = $this->formatHelperArray($theme_module['to_disable']); - - $fields_form = array( - 'form' => array( - 'tinymce' => false, - 'legend' => array( - 'title' => $this->l('Modules to install'), - 'icon' => 'icon-picture' - ), - 'description' => $this->l('Themes often include their own modules in order to work properly. This option enables you to choose which modules should be enabled and which should be disabled. If you are unsure of what to do next, just press the "Save" button and proceed to the next step.'), - 'input' => array( - array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso_theme' - ), - array( - 'type' => 'hidden', - 'name' => 'id_theme', - ), - ), - 'submit' => array( - 'title' => $this->l('Save'), - ), - ) - ); - - if (count($to_install) > 0) - $fields_form['form']['input'][] = array( - 'type' => 'checkbox', - 'label' => $this->l('Select the theme\'s modules you wish to install'), - 'values' => array( - 'query' => $to_install, - 'id' => 'id', - 'name' => 'name' - ), - 'name' => 'to_install', - 'expand' => array( - 'print_total' => count($to_install), - 'default' => 'show', - 'show' => array('text' => $this->l('Show'), 'icon' => 'plus-sign-alt'), - 'hide' => array('text' => $this->l('Hide'), 'icon' => 'minus-sign-alt') - ), - ); - if (count($to_enable) > 0) - $fields_form['form']['input'][] = array( - 'type' => 'checkbox', - 'label' => $this->l('Select the theme\'s modules you wish to enable'), - 'values' => array( - 'query' => $to_enable, - 'id' => 'id', - 'name' => 'name' - ), - 'name' => 'to_enable', - 'expand' => array( - 'print_total' => count($to_enable), - 'default' => 'show', - 'show' => array('text' => $this->l('Show'), 'icon' => 'plus-sign-alt'), - 'hide' => array('text' => $this->l('Hide'), 'icon' => 'minus-sign-alt') - ), - ); - if (count($to_disable) > 0) - $fields_form['form']['input'][] = array( - 'type' => 'checkbox', - 'label' => $this->l('Select the theme\'s modules you wish to disable'), - 'values' => array( - 'query' => $to_disable, - 'id' => 'id', - 'name' => 'name' - ), - 'name' => 'to_disable', - 'expand' => array( - 'print_total' => count($to_disable), - 'default' => 'show', - 'show' => array('text' => $this->l('Show'), 'icon' => 'plus-sign-alt'), - 'hide' => array('text' => $this->l('Hide'), 'icon' => 'minus-sign-alt') - ), - ); - $shops = array(); - $shop = New Shop(Configuration::get('PS_SHOP_DEFAULT')); - $tmp['id_shop'] = $shop->id; - $tmp['id_theme'] = $shop->id_theme; - $shops[] = $tmp; - - if (Shop::isFeatureActive()) - $shops = Shop::getShops(); - - $current_shop = Context::getContext()->shop->id; - - foreach ($shops as $shop) - { - $shop_theme = New Theme((int)$shop['id_theme']); - if ((int)Tools::getValue('id_theme') == (int)$shop['id_theme']) - continue; - - $old_xml_name = 'default.xml'; - if (file_exists(_PS_ROOT_DIR_.'/config/xml/themes/'.$shop_theme->directory.'.xml')) - $old_xml_name = $shop_theme->directory.'.xml'; - - $shop_xml = simplexml_load_file(_PS_ROOT_DIR_.'/config/xml/themes/'.$old_xml_name); - $theme_shop_module = $this->getModules($shop_xml); - - $to_shop_uninstall = array_merge($theme_shop_module['to_install'], $theme_shop_module['to_enable']); - - $to_shop_uninstall = preg_grep('/dash/', $to_shop_uninstall, PREG_GREP_INVERT); - - $to_shop_uninstall_clean = array_diff($to_shop_uninstall, $theme_module['to_enable']); - - $to_shop_uninstall_formated = $this->formatHelperArray($to_shop_uninstall_clean); - - if (count($to_shop_uninstall_formated) == 0) - continue; - - $class = ''; - if ($shop['id_shop'] == $current_shop) - $theme_module['to_disable_shop'.$shop['id_shop']] = array_merge($theme_shop_module['to_install'], $to_shop_uninstall_clean); - else - $class = 'hide'; - - $fields_form['form']['input'][] = array( - 'type' => 'checkbox', - 'label' => sprintf($this->l('Select the modules from the old %1s theme that you wish to disable'), $shop_theme->directory), - 'form_group_class' => $class, - 'values' => array( - 'query' => $to_shop_uninstall_formated, - 'id' => 'id', - 'name' => 'name' - ), - 'expand' => array( - 'print_total' => count($to_shop_uninstall_formated), - 'default' => 'show', - 'show' => array('text' => $this->l('Show'), 'icon' => 'plus-sign-alt'), - 'hide' => array('text' => $this->l('Hide'), 'icon' => 'minus-sign-alt') - ), - 'name' => 'to_disable_shop'.$shop['id_shop'] - ); - - } - - $fields_value = $this->formatHelperValuesArray($theme_module); - - $fields_value['id_theme'] = (int)Tools::getValue('id_theme'); - - $helper = new HelperForm(); - - $helper->currentIndex = $this->context->link->getAdminLink('AdminThemes', false).'&action=ThemeInstall'; - $helper->token = Tools::getAdminTokenLite('AdminThemes'); - $helper->submit_action = ''; - $helper->show_toolbar = true; - $helper->toolbar_btn = $toolbar_btn; - $helper->fields_value = $fields_value; - $helper->languages = $this->getLanguages(); - $helper->default_form_language = (int)$this->context->language->id; - $helper->table = 'theme'; - - $helper->override_folder = $this->tpl_folder; - - return $helper->generateForm(array($fields_form)); - } - - Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminThemes')); - } - - private function updateImages($xml) - { - $return = array(); - - if (isset($xml->images->image)) - foreach ($xml->images->image as $row) - { - Db::getInstance()->delete('image_type', '`name` = \''.pSQL($row['name']).'\''); - Db::getInstance()->execute(' + foreach ($hook_list as &$row) { + $row['exceptions'] = trim(preg_replace('/(,,+)/', ',', $row['exceptions']), ','); + } + + $native_modules = $this->getNativeModule(); + + foreach ($module_list as $array) { + if (!self::checkParentClass($array['name'])) { + continue; + } + if (in_array($array['name'], $native_modules)) { + if ($array['active'] == 1) { + $to_enable[] = $array['name']; + } else { + $to_disable[] = $array['name']; + } + } elseif ($array['active'] == 1) { + $to_install[] = $array['name']; + } + } + foreach ($native_modules as $str) { + $flag = 0; + if (!$this->checkParentClass($str)) { + continue; + } + foreach ($module_list as $tmp) { + if (in_array($str, $tmp)) { + $flag = 1; + break; + } + } + if ($flag == 0) { + $to_disable[] = $str; + } + } + + $employee = $this->context->employee; + $mail = Tools::getValue('email') ? Tools::getValue('email') : $employee->email; + $author = Tools::getValue('author_name') ? Tools::getValue('author_name') : $employee->firstname.' '.$employee->lastname; + $website = Tools::getValue('website') ? Tools::getValue('website') : Tools::getHttpHost(true); + + $this->formatHelperArray($to_install); + + $theme = new Theme(Tools::getValue('id_theme_export')); + + $fields_form = array( + 'form' => array( + 'tinymce' => false, + 'legend' => array( + 'title' => $this->l('Theme configuration'), + 'icon' => 'icon-picture' + ), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'id_theme_export' + ), + array( + 'type' => 'text', + 'name' => 'name', + 'label' => $this->l('Name'), + ), + array( + 'type' => 'text', + 'name' => 'email', + 'label' => $this->l('Email'), + ), + array( + 'type' => 'text', + 'name' => 'website', + 'label' => $this->l('Website'), + ), + array( + 'type' => 'text', + 'name' => 'theme_name', + 'label' => $this->l('Theme name'), + ), + array( + 'type' => 'text', + 'name' => 'theme_directory', + 'label' => $this->l('Theme directory'), + ), + array( + 'type' => 'text', + 'name' => 'body_title', + 'lang' => true, + 'label' => $this->l('Description'), + ), + array( + 'type' => 'text', + 'name' => 'theme_version', + 'label' => $this->l('Theme version'), + ), + array( + 'type' => 'text', + 'name' => 'compa_from', + 'label' => $this->l('Compatible from'), + ), + array( + 'type' => 'text', + 'name' => 'compa_to', + 'label' => $this->l('Compatible to'), + ), + array( + 'type' => 'file', + 'name' => 'documentation', + 'label' => $this->l('Documentation'), + ), + array( + 'type' => 'text', + 'name' => 'documentationName', + 'label' => $this->l('Documentation name'), + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ) + ); + + if (count($to_install) > 0) { + foreach ($to_install as $module) { + $fields_value['modulesToExport_module'.$module] = true; + } + + $fields_form['form']['input'][] = array( + 'type' => 'checkbox', + 'label' => $this->l('Select the theme\'s modules that you wish to export'), + 'values' => array( + 'query' => $this->formatHelperArray($to_install), + 'id' => 'id', + 'name' => 'name' + ), + 'name' => 'modulesToExport', + ); + } + + $default_language = (int)$this->context->language->id; + $languages = $this->getLanguages(); + + foreach ($languages as $language) { + $fields_value['body_title'][$language['id_lang']] = ''; + } + + $helper = new HelperForm(); + $helper->languages = $languages; + $helper->default_form_language = $default_language; + $fields_value['name'] = $author; + $fields_value['email'] = $mail; + $fields_value['website'] = $website; + $fields_value['theme_name'] = $theme->name; + $fields_value['theme_directory'] = $theme->directory; + $fields_value['theme_version'] = '1.0'; + $fields_value['compa_from'] = _PS_VERSION_; + $fields_value['compa_to'] = _PS_VERSION_; + $fields_value['id_theme_export'] = Tools::getValue('id_theme_export'); + $fields_value['documentationName'] = $this->l('documentation'); + + $toolbar_btn['save'] = array( + 'href' => '', + 'desc' => $this->l('Save') + ); + + $helper->currentIndex = $this->context->link->getAdminLink('AdminThemes', false).'&action=exporttheme'; + $helper->token = Tools::getAdminTokenLite('AdminThemes'); + $helper->show_toolbar = true; + $helper->fields_value = $fields_value; + $helper->toolbar_btn = $toolbar_btn; + $helper->override_folder = $this->tpl_folder; + + return $helper->generateForm(array($fields_form)); + } + + public function renderExportTheme() + { + if (Tools::getIsset('id_theme_export') && (int)Tools::getValue('id_theme_export') > 0) { + return $this->renderExportTheme1(); + } + + $theme_list = Theme::getThemes(); + $fields_form = array( + 'form' => array( + 'tinymce' => false, + 'legend' => array( + 'title' => $this->l('Theme'), + 'icon' => 'icon-picture' + ), + 'input' => array( + array( + 'type' => 'select', + 'name' => 'id_theme_export', + 'label' => $this->l('Choose the theme that you want to export'), + 'options' => array( + 'id' => 'id', + 'name' => 'name', + 'query' => $theme_list, + ) + + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ) + ); + + $toolbar_btn['save'] = array( + 'href' => '#', + 'desc' => $this->l('Export') + ); + + $fields_value['id_theme_export'] = array(); + $helper = new HelperForm(); + + $helper->currentIndex = $this->context->link->getAdminLink('AdminThemes', false).'&action=exporttheme'; + $helper->token = Tools::getAdminTokenLite('AdminThemes'); + $helper->show_toolbar = true; + $helper->fields_value = $fields_value; + $helper->toolbar_btn = $toolbar_btn; + $helper->override_folder = $this->tpl_folder; + + return $helper->generateForm(array($fields_form)); + } + + private function checkXmlFields($xml_file) + { + if (!file_exists($xml_file) || !$xml = @simplexml_load_file($xml_file)) { + return false; + } + if (!$xml['version'] || !$xml['name']) { + return false; + } + foreach ($xml->variations->variation as $val) { + if (!$val['name'] || !$val['directory'] || !$val['from'] || !$val['to']) { + return false; + } + } + foreach ($xml->modules->module as $val) { + if (!$val['action'] || !$val['name']) { + return false; + } + } + foreach ($xml->modules->hooks->hook as $val) { + if (!$val['module'] || !$val['hook'] || !$val['position']) { + return false; + } + } + + return true; + } + + private function recurseCopy($src, $dst) + { + if (!$dir = opendir($src)) { + return; + } + if (!file_exists($dst)) { + mkdir($dst); + } + while (($file = readdir($dir)) !== false) { + if (strncmp($file, '.', 1) != 0) { + if (is_dir($src.'/'.$file)) { + self::recurseCopy($src.'/'.$file, $dst.'/'.$file); + } elseif (is_readable($src.'/'.$file) && $file != 'Thumbs.db' && $file != '.DS_Store' && substr($file, -1) != '~') { + copy($src.'/'.$file, $dst.'/'.$file); + } + } + } + closedir($dir); + } + + public function processImportTheme() + { + $this->display = 'importtheme'; + + if ($this->context->mode == Context::MODE_HOST) { + return true; + } + + if (isset($_FILES['themearchive']) && isset($_POST['filename']) && Tools::isSubmit('theme_archive_server')) { + $uniqid = uniqid(); + $sandbox = _PS_CACHE_DIR_.'sandbox'.DIRECTORY_SEPARATOR.$uniqid.DIRECTORY_SEPARATOR; + mkdir($sandbox); + $archive_uploaded = false; + + if (Tools::getValue('filename') != '') { + $uploader = new Uploader('themearchive'); + $uploader->setCheckFileSize(false); + $uploader->setAcceptTypes(array('zip')); + $uploader->setSavePath($sandbox); + $file = $uploader->process(Theme::UPLOADED_THEME_DIR_NAME.'.zip'); + + if ($file[0]['error'] === 0) { + if (Tools::ZipTest($sandbox.Theme::UPLOADED_THEME_DIR_NAME.'.zip')) { + $archive_uploaded = true; + } else { + $this->errors[] = $this->l('Zip file seems to be broken'); + } + } else { + $this->errors[] = $file[0]['error']; + } + } elseif (Tools::getValue('themearchiveUrl') != '') { + if (!Validate::isModuleUrl($url = Tools::getValue('themearchiveUrl'), $this->errors)) { + $this->errors[] = $this->l('Only zip files are allowed'); + } elseif (!Tools::copy($url, $sandbox.Theme::UPLOADED_THEME_DIR_NAME.'.zip')) { + $this->errors[] = $this->l('Error during the file download'); + } elseif (Tools::ZipTest($sandbox.Theme::UPLOADED_THEME_DIR_NAME.'.zip')) { + $archive_uploaded = true; + } else { + $this->errors[] = $this->l('Zip file seems to be broken'); + } + } elseif (Tools::getValue('theme_archive_server') != '') { + $filename = _PS_ALL_THEMES_DIR_.Tools::getValue('theme_archive_server'); + if (substr($filename, -4) != '.zip') { + $this->errors[] = $this->l('Only zip files are allowed'); + } elseif (!copy($filename, $sandbox.Theme::UPLOADED_THEME_DIR_NAME.'.zip')) { + $this->errors[] = $this->l('An error has occurred during the file copy.'); + } elseif (Tools::ZipTest($sandbox.Theme::UPLOADED_THEME_DIR_NAME.'.zip')) { + $archive_uploaded = true; + } else { + $this->errors[] = $this->l('Zip file seems to be broken'); + } + } else { + $this->errors[] = $this->l('You must upload or enter a location of your zip'); + } + + if ($archive_uploaded) { + if ($this->extractTheme($sandbox.Theme::UPLOADED_THEME_DIR_NAME.'.zip', $sandbox)) { + $this->installTheme(Theme::UPLOADED_THEME_DIR_NAME, $sandbox); + } + } + + Tools::deleteDirectory($sandbox); + + if (count($this->errors) > 0) { + $this->display = 'importtheme'; + } else { + Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminThemes').'&conf=18'); + } + } + } + + protected function extractTheme($theme_zip_file, $sandbox) + { + if (Tools::ZipExtract($theme_zip_file, $sandbox.Theme::UPLOADED_THEME_DIR_NAME.'/')) { + return true; + } + + $this->errors[] = $this->l('Error during zip extraction'); + return false; + } + + protected function installTheme($theme_dir, $sandbox = false, $redirect = true) + { + if (!$sandbox) { + $uniqid = uniqid(); + $sandbox = _PS_CACHE_DIR_.'sandbox'.DIRECTORY_SEPARATOR.$uniqid.DIRECTORY_SEPARATOR; + mkdir($sandbox); + Tools::recurseCopy(_PS_ALL_THEMES_DIR_.$theme_dir, $sandbox.$theme_dir); + } + + $xml_file = $sandbox.$theme_dir.'/Config.xml'; + if (!$this->checkXmlFields($xml_file)) { + $this->errors[] = $this->l('Bad configuration file'); + } else { + $imported_theme = $this->importThemeXmlConfig(simplexml_load_file($xml_file)); + foreach ($imported_theme as $theme) { + if (Validate::isLoadedObject($theme)) { + if (!copy($sandbox.$theme_dir.'/Config.xml', _PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml')) { + $this->errors[] = $this->l('Can\'t copy configuration file'); + } + + $target_dir = _PS_ALL_THEMES_DIR_.$theme->directory; + if (file_exists($target_dir)) { + Tools::deleteDirectory($target_dir); + } + + $theme_doc_dir = $target_dir.'/docs/'; + if (file_exists($theme_doc_dir)) { + Tools::deleteDirectory($theme_doc_dir); + } + + mkdir($target_dir); + mkdir($theme_doc_dir); + + Tools::recurseCopy($sandbox.$theme_dir.'/themes/'.$theme->directory.'/', $target_dir.'/'); + Tools::recurseCopy($sandbox.$theme_dir.'/doc/', $theme_doc_dir); + Tools::recurseCopy($sandbox.$theme_dir.'/modules/', _PS_MODULE_DIR_); + } else { + $this->errors[] = $theme; + } + } + } + + Tools::deleteDirectory($sandbox); + + if (!count($this->errors)) { + if ($redirect) { + Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminThemes').'&conf=18'); + } else { + return true; + } + } else { + return false; + } + } + + protected function isThemeInstalled($theme_name) + { + $themes = Theme::getThemes(); + + foreach ($themes as $theme_object) { + /** @var Theme $theme_object */ + if ($theme_object->name == $theme_name) { + return true; + } + } + return false; + } + + /** + * @param SimpleXMLElement $xml + * @param bool $theme_dir only used if the theme directory to import is already located on the shop + * + * @return array|string return array of themes on success, otherwise the error as a string is returned + */ + protected function importThemeXmlConfig(SimpleXMLElement $xml, $theme_dir = false) + { + $attr = $xml->attributes(); + $th_name = (string)$attr->name; + if ($this->isThemeInstalled($th_name)) { + return array(sprintf($this->l('Theme %s already installed.'), $th_name)); + } + + $new_theme_array = array(); + foreach ($xml->variations->variation as $variation) { + $name = strval($variation['name']); + + $new_theme = new Theme(); + $new_theme->name = $name; + + $new_theme->directory = strval($variation['directory']); + + if ($theme_dir) { + $new_theme->name = $theme_dir; + $new_theme->directory = $theme_dir; + } + + if ($this->isThemeInstalled($new_theme->name)) { + continue; + } + + $new_theme->product_per_page = Configuration::get('PS_PRODUCTS_PER_PAGE'); + + if (isset($variation['product_per_page'])) { + $new_theme->product_per_page = intval($variation['product_per_page']); + } + + $new_theme->responsive = false; + if (isset($variation['responsive'])) { + $new_theme->responsive = (bool)strval($variation['responsive']); + } + + $new_theme->default_left_column = true; + $new_theme->default_right_column = true; + + if (isset($variation['default_left_column'])) { + $new_theme->default_left_column = (bool)strval($variation['default_left_column']); + } + + if (isset($variation['default_right_column'])) { + $new_theme->default_right_column = (bool)strval($variation['default_right_column']); + } + + $fill_default_meta = true; + $metas_xml = array(); + if ($xml->metas->meta) { + foreach ($xml->metas->meta as $meta) { + $meta_id = Db::getInstance()->getValue('SELECT id_meta FROM '._DB_PREFIX_.'meta WHERE page=\''.pSQL($meta['meta_page']).'\''); + if ((int)$meta_id > 0) { + $tmp_meta = array(); + $tmp_meta['id_meta'] = (int)$meta_id; + $tmp_meta['left'] = intval($meta['left']); + $tmp_meta['right'] = intval($meta['right']); + $metas_xml[(int)$meta_id] = $tmp_meta; + } + } + $fill_default_meta = false; + if (count($xml->metas->meta) < (int)Db::getInstance()->getValue('SELECT count(*) FROM '._DB_PREFIX_.'meta')) { + $fill_default_meta = true; + } + } + + if ($fill_default_meta == true) { + $metas = Db::getInstance()->executeS('SELECT id_meta FROM '._DB_PREFIX_.'meta'); + foreach ($metas as $meta) { + if (!isset($metas_xml[(int)$meta['id_meta']])) { + $tmp_meta['id_meta'] = (int)$meta['id_meta']; + $tmp_meta['left'] = $new_theme->default_left_column; + $tmp_meta['right'] = $new_theme->default_right_column; + $metas_xml[(int)$meta['id_meta']] = $tmp_meta; + } + } + } + + if (!is_dir(_PS_ALL_THEMES_DIR_.$new_theme->directory)) { + if (!mkdir(_PS_ALL_THEMES_DIR_.$new_theme->directory)) { + return sprintf($this->l('Error while creating %s directory'), _PS_ALL_THEMES_DIR_.$new_theme->directory); + } + } + + $new_theme->add(); + + if ($new_theme->id > 0) { + $new_theme->updateMetas($metas_xml); + $new_theme_array[] = $new_theme; + } else { + $new_theme_array[] = sprintf($this->l('Error while installing theme %s'), $new_theme->name); + } + } + + return $new_theme_array; + } + + public function renderImportTheme() + { + $fields_form = array(); + + $toolbar_btn['save'] = array( + 'href' => '#', + 'desc' => $this->l('Save') + ); + + if ($this->context->mode != Context::MODE_HOST) { + $fields_form[0] = array( + 'form' => array( + 'tinymce' => false, + 'legend' => array( + 'title' => $this->l('Import from your computer'), + 'icon' => 'icon-picture' + ), + 'input' => array( + array( + 'type' => 'file', + 'label' => $this->l('Zip file'), + 'desc' => $this->l('Browse your computer files and select the Zip file for your new theme.'), + 'name' => 'themearchive' + ), + ), + 'submit' => array( + 'id' => 'zip', + 'title' => $this->l('Save'), + ) + ), + ); + + $fields_form[1] = array( + 'form' => array( + 'tinymce' => false, + 'legend' => array( + 'title' => $this->l('Import from the web'), + 'icon' => 'icon-picture' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Archive URL'), + 'desc' => $this->l('Indicate the complete URL to an online Zip file that contains your new theme. For instance, "http://example.com/files/theme.zip".'), + 'name' => 'themearchiveUrl' + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ), + ); + + $theme_archive_server = array(); + $files = scandir(_PS_ALL_THEMES_DIR_); + $theme_archive_server[] = '-'; + + foreach ($files as $file) { + if (is_file(_PS_ALL_THEMES_DIR_.$file) && substr(_PS_ALL_THEMES_DIR_.$file, -4) == '.zip') { + $theme_archive_server[] = array( + 'id' => basename(_PS_ALL_THEMES_DIR_.$file), + 'name' => basename(_PS_ALL_THEMES_DIR_.$file) + ); + } + } + + $fields_form[2] = array( + 'form' => array( + 'tinymce' => false, + 'legend' => array( + 'title' => $this->l('Import from FTP'), + 'icon' => 'icon-picture' + ), + 'input' => array( + array( + 'type' => 'select', + 'label' => $this->l('Select the archive'), + 'name' => 'theme_archive_server', + 'desc' => $this->l('This selector lists the Zip files that you uploaded in the \'/themes\' folder.'), + 'options' => array( + 'id' => 'id', + 'name' => 'name', + 'query' => $theme_archive_server, + ) + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ) + ), + ); + } + + $this->context->smarty->assign( + array( + 'import_theme' => true, + 'logged_on_addons' => $this->logged_on_addons, + 'iso_code' => $this->context->language->iso_code, + 'add_new_theme_href' => self::$currentIndex.'&addtheme&token='.$this->token, + 'add_new_theme_label' => $this->l('Create a new theme'), + ) + ); + + $create_new_theme_panel = $this->context->smarty->fetch('controllers/themes/helpers/view/importtheme_view.tpl'); + + $helper = new HelperForm(); + + $helper->currentIndex = $this->context->link->getAdminLink('AdminThemes', false).'&action=importtheme'; + $helper->token = Tools::getAdminTokenLite('AdminThemes'); + $helper->show_toolbar = true; + $helper->toolbar_btn = $toolbar_btn; + $helper->fields_value['themearchiveUrl'] = ''; + $helper->fields_value['theme_archive_server'] = array(); + $helper->multiple_fieldsets = true; + $helper->override_folder = $this->tpl_folder; + $helper->languages = $this->getLanguages(); + $helper->default_form_language = (int)$this->context->language->id; + + return $helper->generateForm($fields_form).$create_new_theme_panel; + } + + public function initContent() + { + if ($this->display == 'list') { + $this->display = ''; + } + if (isset($this->display) && method_exists($this, 'render'.$this->display)) { + $this->content .= $this->initPageHeaderToolbar(); + + $this->content .= $this->{'render'.$this->display}(); + $this->context->smarty->assign(array( + 'content' => $this->content, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } else { + $content = ''; + if (Configuration::hasKey('PS_LOGO') && trim(Configuration::get('PS_LOGO')) != '' + && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO')) && filesize(_PS_IMG_DIR_.Configuration::get('PS_LOGO'))) { + list($width, $height, $type, $attr) = getimagesize(_PS_IMG_DIR_.Configuration::get('PS_LOGO')); + Configuration::updateValue('SHOP_LOGO_HEIGHT', (int)round($height)); + Configuration::updateValue('SHOP_LOGO_WIDTH', (int)round($width)); + } + if (Configuration::get('PS_LOGO_MOBILE') && trim(Configuration::get('PS_LOGO_MOBILE')) != '' + && file_exists(_PS_IMG_DIR_.Configuration::get('PS_LOGO_MOBILE')) && filesize(_PS_IMG_DIR_.Configuration::get('PS_LOGO_MOBILE'))) { + list($width, $height, $type, $attr) = getimagesize(_PS_IMG_DIR_.Configuration::get('PS_LOGO_MOBILE')); + Configuration::updateValue('SHOP_LOGO_MOBILE_HEIGHT', (int)round($height)); + Configuration::updateValue('SHOP_LOGO_MOBILE_WIDTH', (int)round($width)); + } + + $this->content .= $content; + + return parent::initContent(); + } + } + + public function ajaxProcessGetAddonsThemes() + { + $parent_domain = Tools::getHttpHost(true).substr($_SERVER['REQUEST_URI'], 0, -1 * strlen(basename($_SERVER['REQUEST_URI']))); + $iso_lang = $this->context->language->iso_code; + $iso_currency = $this->context->currency->iso_code; + $iso_country = $this->context->country->iso_code; + $activity = Configuration::get('PS_SHOP_ACTIVITY'); + $addons_url = 'http://addons.prestashop.com/iframe/search-1.6.php?psVersion='._PS_VERSION_.'&onlyThemes=1&isoLang='.$iso_lang.'&isoCurrency='.$iso_currency.'&isoCountry='.$iso_country.'&activity='.(int)$activity.'&parentUrl='.$parent_domain; + + die(Tools::file_get_contents($addons_url)); + } + + /** + * This function checks if the theme designer has thunk to make his theme compatible 1.4, + * and noticed it on the $theme_dir/config.xml file. If not, some new functionnalities has + * to be desactivated + * + * @since 1.4 + * + * @param string $theme_dir theme directory + * + * @return bool Validity is ok or not + */ + protected function _isThemeCompatible($theme_dir) + { + $return = true; + $check_version = AdminThemes::$check_features_version; + + if (!is_file(_PS_ALL_THEMES_DIR_.$theme_dir.'/config.xml')) { + $this->errors[] = Tools::displayError('The config.xml file is missing in your theme path.').'<br/>'; + $xml = null; + } else { + $xml = @simplexml_load_file(_PS_ALL_THEMES_DIR_.$theme_dir.'/config.xml'); + if (!$xml) { + $this->errors[] = Tools::displayError('The config.xml file in your theme path is not a valid XML file.').'<br/>'; + } + } + // will be set to false if any version node in xml is correct + $xml_version_too_old = true; + + // foreach version in xml file, + // node means feature, attributes has to match + // the corresponding value in AdminThemes::$check_features[feature] array + $xmlArray = simpleXMLToArray($xml); + foreach ($xmlArray as $version) { + if (isset($version['value']) && version_compare($version['value'], $check_version) >= 0) { + foreach (AdminThemes::$check_features as $codeFeature => $arrConfigToCheck) { + foreach ($arrConfigToCheck['attributes'] as $attr => $v) { + if (!isset($version[$codeFeature]) || !isset($version[$codeFeature][$attr]) || $version[$codeFeature][$attr] != $v['value']) { + if (!$this->_checkConfigForFeatures($codeFeature, $attr)) { // feature missing in config.xml file, or wrong attribute value + $return = false; + } + } + } + } + $xml_version_too_old = false; + } + } + if ($xml_version_too_old && !$this->_checkConfigForFeatures(array_keys(AdminThemes::$check_features))) { + $this->errors[] .= Tools::displayError('The config.xml file has not been created for this version of PrestaShop.'); + $return = false; + } + + return $return; + } + + /** + * _checkConfigForFeatures + * + * @param array $arrFeatures array of feature code to check + * @param mixed $configItem will precise the attribute which not matches. If empty, will check every attributes + * + * @return bool Error message, or null if disabled + */ + protected function _checkConfigForFeatures($arrFeatures, $configItem = array()) + { + $return = true; + if (is_array($configItem)) { + foreach ($arrFeatures as $feature) { + if (!count($configItem)) { + $configItem = array_keys(AdminThemes::$check_features[$feature]['attributes']); + } + } + foreach ($configItem as $attr) { + $check = $this->_checkConfigForFeatures($arrFeatures, $attr); + if ($check == false) { + $return = false; + } + } + + return $return; + } + + $return = true; + if (!is_array($arrFeatures)) { + $arrFeatures = array($arrFeatures); + } + + foreach ($arrFeatures as $feature) { + $arrConfigToCheck = AdminThemes::$check_features[$feature]['attributes'][$configItem]['check_if_not_valid']; + foreach ($arrConfigToCheck as $config_key => $config_val) { + $config_get = Configuration::get($config_key); + if ($config_get != $config_val) { + $this->errors[] = Tools::displayError(AdminThemes::$check_features[$feature]['error']).'.' + .(!empty(AdminThemes::$check_features[$feature]['tab']) + ? ' <a href="?tab='.AdminThemes::$check_features[$feature]['tab'].'&token=' + .Tools::getAdminTokenLite(AdminThemes::$check_features[$feature]['tab']).'" ><u>' + .Tools::displayError('You can disable this function.') + .'</u></a>' : '' + ).'<br/>'; + $return = false; + break; // break for this attributes + } + } + } + + return $return; + } + + /** + * + * @param int $type + * $type = 0 both native & partner (default) + * $type = 1 native + * $type = 2 partner + * + * + * @return array + */ + private function getNativeModule($type = 0) + { + $xml = @simplexml_load_string(Tools::file_get_contents(_PS_API_URL_.'/xml/modules_list_16.xml')); + + if ($xml) { + $natives = array(); + + switch ($type) { + case 0: + foreach ($xml->modules as $row) { + foreach ($row->module as $row2) { + $natives[] = (string)$row2['name']; + } + } + break; + case 1: + foreach ($xml->modules as $row) { + if ($row['type'] == 'native') { + foreach ($row->module as $row2) { + $natives[] = (string)$row2['name']; + } + } + } + break; + case 2: + foreach ($xml->modules as $row) { + if ($row['type'] == 'partner') { + foreach ($row->module as $row2) { + $natives[] = (string)$row2['name']; + } + } + } + break; + } + + if (count($natives) > 0) { + return $natives; + } + } + + return array( + 'addsharethis', + 'bankwire', + 'blockadvertising', + 'blockbanner', + 'blockbestsellers', + 'blockcart', + 'blockcategories', + 'blockcms', + 'blockcmsinfo', + 'blockcontact', + 'blockcontactinfos', + 'blockcurrencies', + 'blockcustomerprivacy', + 'blockfacebook', + 'blocklanguages', + 'blocklayered', + 'blocklink', + 'blockmanufacturer', + 'blockmyaccount', + 'blockmyaccountfooter', + 'blocknewproducts', + 'blocknewsletter', + 'blockpaymentlogo', + 'blockpermanentlinks', + 'blockreinsurance', + 'blockrss', + 'blocksearch', + 'blocksharefb', + 'blocksocial', + 'blockspecials', + 'blockstore', + 'blocksupplier', + 'blocktags', + 'blocktopmenu', + 'blockuserinfo', + 'blockviewed', + 'blockwishlist', + 'carriercompare', + 'cashondelivery', + 'cheque', + 'crossselling', + 'dashactivity', + 'dashgoals', + 'dashproducts', + 'dashtrends', + 'dateofdelivery', + 'editorial', + 'favoriteproducts', + 'feeder', + 'followup', + 'gapi', + 'graphnvd3', + 'gridhtml', + 'homefeatured', + 'homeslider', + 'loyalty', + 'mailalerts', + 'newsletter', + 'pagesnotfound', + 'productcomments', + 'productpaymentlogos', + 'productscategory', + 'producttooltip', + 'pscleaner', + 'referralprogram', + 'sekeywords', + 'sendtoafriend', + 'socialsharing', + 'statsbestcategories', + 'statsbestcustomers', + 'statsbestmanufacturers', + 'statsbestproducts', + 'statsbestsuppliers', + 'statsbestvouchers', + 'statscarrier', + 'statscatalog', + 'statscheckup', + 'statsdata', + 'statsequipment', + 'statsforecast', + 'statslive', + 'statsnewsletter', + 'statsorigin', + 'statspersonalinfos', + 'statsproduct', + 'statsregistrations', + 'statssales', + 'statssearch', + 'statsstock', + 'statsvisits', + 'themeconfigurator', + 'trackingfront', + 'vatnumber', + 'watermark' + ); + } + + private function getModules($xml) + { + $native_modules = $this->getNativeModule(); + $theme_module = array(); + + $theme_module['to_install'] = array(); + $theme_module['to_enable'] = array(); + $theme_module['to_disable'] = array(); + foreach ($xml->modules->module as $row) { + if (strval($row['action']) == 'install' && !in_array(strval($row['name']), $native_modules)) { + $theme_module['to_install'][] = strval($row['name']); + } elseif (strval($row['action']) == 'enable') { + $theme_module['to_enable'][] = strval($row['name']); + } elseif (strval($row['action']) == 'disable') { + $theme_module['to_disable'][] = strval($row['name']); + } + } + + return $theme_module; + } + + private function formatHelperArray($origin_arr) + { + $fmt_arr = array(); + foreach ($origin_arr as $module) { + $display_name = $module; + + $module_obj = Module::getInstanceByName($module); + if (Validate::isLoadedObject($module_obj)) { + $display_name = $module_obj->displayName; + } + + $tmp = array(); + $tmp['id'] = 'module'.$module; + $tmp['val'] = $module; + $tmp['name'] = $display_name; + $fmt_arr[] = $tmp; + } + + return $fmt_arr; + } + + private function formatHelperValuesArray($originArr) + { + $fmtArr = array(); + foreach ($originArr as $key => $type) { + foreach ($type as $module) { + $fmtArr[$key.'_module'.$module] = true; + } + } + + return $fmtArr; + } + + public function renderChooseThemeModule() + { + $theme = new Theme((int)Tools::getValue('id_theme')); + + $xml = false; + if (file_exists(_PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml')) { + $xml = @simplexml_load_file(_PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml'); + } elseif (file_exists(_PS_ROOT_DIR_.'/config/xml/themes/default.xml')) { + $xml = @simplexml_load_file(_PS_ROOT_DIR_.'/config/xml/themes/default.xml'); + } + + if ($xml) { + $theme_module = $this->getModules($xml); + + $toolbar_btn['save'] = array( + 'href' => '#', + 'desc' => $this->l('Save') + ); + + $to_install = array(); + $to_enable = array(); + $to_disable = array(); + + if (isset($theme_module['to_install'])) { + $to_install = $this->formatHelperArray($theme_module['to_install']); + } + if (isset($theme_module['to_enable'])) { + $to_enable = $this->formatHelperArray($theme_module['to_enable']); + } + if (isset($theme_module['to_disable'])) { + $to_disable = $this->formatHelperArray($theme_module['to_disable']); + } + + $fields_form = array( + 'form' => array( + 'tinymce' => false, + 'legend' => array( + 'title' => $this->l('Modules to install'), + 'icon' => 'icon-picture' + ), + 'description' => $this->l('Themes often include their own modules in order to work properly. This option enables you to choose which modules should be enabled and which should be disabled. If you are unsure of what to do next, just press the "Save" button and proceed to the next step.'), + 'input' => array( + array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso_theme' + ), + array( + 'type' => 'hidden', + 'name' => 'id_theme', + ), + ), + 'submit' => array( + 'title' => $this->l('Save'), + ), + ) + ); + + if (count($to_install) > 0) { + $fields_form['form']['input'][] = array( + 'type' => 'checkbox', + 'label' => $this->l('Select the theme\'s modules you wish to install'), + 'values' => array( + 'query' => $to_install, + 'id' => 'id', + 'name' => 'name' + ), + 'name' => 'to_install', + 'expand' => array( + 'print_total' => count($to_install), + 'default' => 'show', + 'show' => array('text' => $this->l('Show'), 'icon' => 'plus-sign-alt'), + 'hide' => array('text' => $this->l('Hide'), 'icon' => 'minus-sign-alt') + ), + ); + } + if (count($to_enable) > 0) { + $fields_form['form']['input'][] = array( + 'type' => 'checkbox', + 'label' => $this->l('Select the theme\'s modules you wish to enable'), + 'values' => array( + 'query' => $to_enable, + 'id' => 'id', + 'name' => 'name' + ), + 'name' => 'to_enable', + 'expand' => array( + 'print_total' => count($to_enable), + 'default' => 'show', + 'show' => array('text' => $this->l('Show'), 'icon' => 'plus-sign-alt'), + 'hide' => array('text' => $this->l('Hide'), 'icon' => 'minus-sign-alt') + ), + ); + } + if (count($to_disable) > 0) { + $fields_form['form']['input'][] = array( + 'type' => 'checkbox', + 'label' => $this->l('Select the theme\'s modules you wish to disable'), + 'values' => array( + 'query' => $to_disable, + 'id' => 'id', + 'name' => 'name' + ), + 'name' => 'to_disable', + 'expand' => array( + 'print_total' => count($to_disable), + 'default' => 'show', + 'show' => array('text' => $this->l('Show'), 'icon' => 'plus-sign-alt'), + 'hide' => array('text' => $this->l('Hide'), 'icon' => 'minus-sign-alt') + ), + ); + } + $shops = array(); + $shop = new Shop(Configuration::get('PS_SHOP_DEFAULT')); + $tmp['id_shop'] = $shop->id; + $tmp['id_theme'] = $shop->id_theme; + $shops[] = $tmp; + + if (Shop::isFeatureActive()) { + $shops = Shop::getShops(); + } + + $current_shop = Context::getContext()->shop->id; + + foreach ($shops as $shop) { + $shop_theme = new Theme((int)$shop['id_theme']); + if ((int)Tools::getValue('id_theme') == (int)$shop['id_theme']) { + continue; + } + + $old_xml_name = 'default.xml'; + if (file_exists(_PS_ROOT_DIR_.'/config/xml/themes/'.$shop_theme->directory.'.xml')) { + $old_xml_name = $shop_theme->directory.'.xml'; + } + + $shop_xml = @simplexml_load_file(_PS_ROOT_DIR_.'/config/xml/themes/'.$old_xml_name); + + if (!$shop_xml) { + continue; + } + + $theme_shop_module = $this->getModules($shop_xml); + + $to_shop_uninstall = array_merge($theme_shop_module['to_install'], $theme_shop_module['to_enable']); + + $to_shop_uninstall = preg_grep('/dash/', $to_shop_uninstall, PREG_GREP_INVERT); + + $to_shop_uninstall_clean = array_diff($to_shop_uninstall, $theme_module['to_enable']); + + $to_shop_uninstall_formated = $this->formatHelperArray($to_shop_uninstall_clean); + + if (count($to_shop_uninstall_formated) == 0) { + continue; + } + + $class = ''; + if ($shop['id_shop'] == $current_shop) { + $theme_module['to_disable_shop'.$shop['id_shop']] = array_merge($theme_shop_module['to_install'], $to_shop_uninstall_clean); + } else { + $class = 'hide'; + } + + $fields_form['form']['input'][] = array( + 'type' => 'checkbox', + 'label' => sprintf($this->l('Select the modules from the old %1s theme that you wish to disable'), $shop_theme->directory), + 'form_group_class' => $class, + 'values' => array( + 'query' => $to_shop_uninstall_formated, + 'id' => 'id', + 'name' => 'name' + ), + 'expand' => array( + 'print_total' => count($to_shop_uninstall_formated), + 'default' => 'show', + 'show' => array('text' => $this->l('Show'), 'icon' => 'plus-sign-alt'), + 'hide' => array('text' => $this->l('Hide'), 'icon' => 'minus-sign-alt') + ), + 'name' => 'to_disable_shop'.$shop['id_shop'] + ); + } + + $fields_value = $this->formatHelperValuesArray($theme_module); + + $fields_value['id_theme'] = (int)Tools::getValue('id_theme'); + + $helper = new HelperForm(); + + $helper->currentIndex = $this->context->link->getAdminLink('AdminThemes', false).'&action=ThemeInstall'; + $helper->token = Tools::getAdminTokenLite('AdminThemes'); + $helper->submit_action = ''; + $helper->show_toolbar = true; + $helper->toolbar_btn = $toolbar_btn; + $helper->fields_value = $fields_value; + $helper->languages = $this->getLanguages(); + $helper->default_form_language = (int)$this->context->language->id; + $helper->table = 'theme'; + + $helper->override_folder = $this->tpl_folder; + + return $helper->generateForm(array($fields_form)); + } + + Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminThemes')); + } + + private function updateImages($xml) + { + $return = array(); + + if (isset($xml->images->image)) { + foreach ($xml->images->image as $row) { + Db::getInstance()->delete('image_type', '`name` = \''.pSQL($row['name']).'\''); + Db::getInstance()->execute(' INSERT INTO `'._DB_PREFIX_.'image_type` (`name`, `width`, `height`, `products`, `categories`, `manufacturers`, `suppliers`, `scenes`) VALUES (\''.pSQL($row['name']).'\', '.(int)$row['width'].', @@ -2391,602 +2392,587 @@ class AdminThemesControllerCore extends AdminController '.($row['suppliers'] == 'true' ? 1 : 0).', '.($row['scenes'] == 'true' ? 1 : 0).')'); - $return['ok'][] = array( - 'name' => strval($row['name']), - 'width' => (int)$row['width'], - 'height' => (int)$row['height'] - ); - } + $return['ok'][] = array( + 'name' => strval($row['name']), + 'width' => (int)$row['width'], + 'height' => (int)$row['height'] + ); + } + } - return $return; - } + return $return; + } - private function hookModule($id_module, $module_hooks, $shop) - { - Db::getInstance()->execute('INSERT IGNORE INTO '._DB_PREFIX_.'module_shop (id_module, id_shop) VALUES('.(int)$id_module.', '.(int)$shop.')'); + private function hookModule($id_module, $module_hooks, $shop) + { + Db::getInstance()->execute('INSERT IGNORE INTO '._DB_PREFIX_.'module_shop (id_module, id_shop) VALUES('.(int)$id_module.', '.(int)$shop.')'); - Db::getInstance()->execute($sql = 'DELETE FROM `'._DB_PREFIX_.'hook_module` WHERE `id_module` = '.(int)$id_module.' AND id_shop = '.(int)$shop); + Db::getInstance()->execute($sql = 'DELETE FROM `'._DB_PREFIX_.'hook_module` WHERE `id_module` = '.(int)$id_module.' AND id_shop = '.(int)$shop); - foreach ($module_hooks as $hooks) - { - foreach ($hooks as $hook) - { - $sql_hook_module = 'INSERT INTO `'._DB_PREFIX_.'hook_module` (`id_module`, `id_shop`, `id_hook`, `position`) + foreach ($module_hooks as $hooks) { + foreach ($hooks as $hook) { + $sql_hook_module = 'INSERT INTO `'._DB_PREFIX_.'hook_module` (`id_module`, `id_shop`, `id_hook`, `position`) VALUES ('.(int)$id_module.', '.(int)$shop.', '.(int)Hook::getIdByName($hook['hook']).', '.(int)$hook['position'].')'; - if (count($hook['exceptions']) > 0) - { - foreach ($hook['exceptions'] as $exception) - { - $sql_hook_module_except = 'INSERT INTO `'._DB_PREFIX_.'hook_module_exceptions` (`id_module`, `id_hook`, `file_name`) VALUES ('.(int)$id_module.', '.(int)Hook::getIdByName($hook['hook']).', "'.pSQL($exception).'")'; - Db::getInstance()->execute($sql_hook_module_except); - } - } - Db::getInstance()->execute($sql_hook_module); - } - } - } - - public function processThemeInstall() - { - $shops_asso = $this->context->employee->getAssociatedShops(); - if (Shop::isFeatureActive() && !Tools::getIsset('checkBoxShopAsso_theme') && count($shops_asso) > 1) - { - $this->errors[] = $this->l('You must choose at least one shop.'); - $this->display = 'ChooseThemeModule'; - - return; - } - - $theme = New Theme((int)Tools::getValue('id_theme')); - - if (count($shops_asso) == 1) - $shops = $shops_asso; - else - { - $shops = array(Configuration::get('PS_SHOP_DEFAULT')); - if (Tools::isSubmit('checkBoxShopAsso_theme')) - $shops = Tools::getValue('checkBoxShopAsso_theme'); - } - - $xml = false; - if (file_exists(_PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml')) - $xml = simplexml_load_file(_PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml'); - elseif (file_exists(_PS_ROOT_DIR_.'/config/xml/themes/default.xml')) - $xml = simplexml_load_file(_PS_ROOT_DIR_.'/config/xml/themes/default.xml'); - - if ($xml) - { - $module_hook = array(); - foreach ($xml->modules->hooks->hook as $row) - { - $name = strval($row['module']); - - $exceptions = (isset($row['exceptions']) ? explode(',', strval($row['exceptions'])) : array()); - - $module_hook[$name]['hook'][] = array( - 'hook' => strval($row['hook']), - 'position' => strval($row['position']), - 'exceptions' => $exceptions - ); - } - - $this->img_error = $this->updateImages($xml); - - $this->modules_errors = array(); - foreach ($shops as $id_shop) - { - foreach ($_POST as $key => $value) - { - if (strncmp($key, 'to_install', strlen('to_install')) == 0) - { - $module = Module::getInstanceByName($value); - if ($module) - { - $is_installed_success = true; - if (!Module::isInstalled($module->name)) - $is_installed_success = $module->install(); - if ($is_installed_success) - { - if (!Module::isEnabled($module->name)) - $module->enable(); - - if ((int)$module->id > 0 && isset($module_hook[$module->name])) - $this->hookModule($module->id, $module_hook[$module->name], $id_shop); - } - else - $this->modules_errors[] = array('module_name' => $module->name, 'errors' => $module->getErrors()); - - unset($module_hook[$module->name]); - } - - } - elseif (strncmp($key, 'to_enable', strlen('to_enable')) == 0) - { - $module = Module::getInstanceByName($value); - if ($module) - { - $is_installed_success = true; - if (!Module::isInstalled($module->name)) - $is_installed_success = $module->install(); - - if ($is_installed_success) - { - if (!Module::isEnabled($module->name)) - $module->enable(); - - if ((int)$module->id > 0 && isset($module_hook[$module->name])) - $this->hookModule($module->id, $module_hook[$module->name], $id_shop); - } - else - $this->modules_errors[] = array('module_name' => $module->name, 'errors' => $module->getErrors()); - - unset($module_hook[$module->name]); - } - - } - elseif (strncmp($key, 'to_disable', strlen('to_disable')) == 0) - { - $key_exploded = explode('_', $key); - $id_shop_module = (int)substr($key_exploded[2], 4); - - if ((int)$id_shop_module > 0 && $id_shop_module != (int)$id_shop) - continue; - - $module_obj = Module::getInstanceByName($value); - if (Validate::isLoadedObject($module_obj)) - { - if (Module::isEnabled($module_obj->name)) - $module_obj->disable(); - - unset($module_hook[$module_obj->name]); - } - } - } - $shop = New Shop((int)$id_shop); - $shop->id_theme = (int)Tools::getValue('id_theme'); - $this->context->shop->id_theme = $shop->id_theme; - $this->context->shop->update(); - $shop->save(); - - if (Shop::isFeatureActive()) - Configuration::updateValue('PS_PRODUCTS_PER_PAGE', (int)$theme->product_per_page, false, null, (int)$id_shop); - else - Configuration::updateValue('PS_PRODUCTS_PER_PAGE', (int)$theme->product_per_page); - } - - $this->doc = array(); - foreach ($xml->docs->doc as $row) - $this->doc[strval($row['name'])] = __PS_BASE_URI__.'themes/'.$theme->directory.'/docs/'.basename(strval($row['path'])); - } - - Tools::clearCache($this->context->smarty); - $this->theme_name = $theme->name; - $this->display = 'view'; - } - - public function renderView() - { - $this->tpl_view_vars = array( - 'doc' => $this->doc, - 'theme_name' => $this->theme_name, - 'img_error' => $this->img_error, - 'modules_errors' => $this->modules_errors, - 'back_link' => Context::getContext()->link->getAdminLink('AdminThemes'), - 'image_link' => Context::getContext()->link->getAdminLink('AdminImages') - ); - - return parent::renderView(); - } - - /** - * This functions make checks about AdminThemes configuration edition only. - * - * @since 1.4 - */ - public function postProcess() - { - if (Tools::isSubmit('submitOptionstheme') && Tools::isSubmit('id_theme') && !Tools::isSubmit('deletetheme') - && Tools::getValue('action') != 'ThemeInstall' && $this->context->shop->id_theme != Tools::getValue('id_theme')) - $this->display = 'ChooseThemeModule'; - elseif (Tools::isSubmit('installThemeFromFolder') && ($this->context->mode != Context::MODE_HOST)) - { - $theme_dir = Tools::getValue('theme_dir'); - $this->installTheme($theme_dir); - } - else - { - // new check compatibility theme feature (1.4) : - $val = Tools::getValue('PS_THEME'); - Configuration::updateValue('PS_IMG_UPDATE_TIME', time()); - if (!empty($val) && !$this->_isThemeCompatible($val)) // don't submit if errors - unset($_POST['submitThemes'.$this->table]); - Tools::clearCache($this->context->smarty); - - return parent::postProcess(); - } - } - - /** - * Update PS_LOGO - */ - public function updateOptionPsLogo() - { - $this->updateLogo('PS_LOGO', 'logo'); - } - - /** - * Update PS_LOGO_MOBILE - */ - public function updateOptionPsLogoMobile() - { - $this->updateLogo('PS_LOGO_MOBILE', 'logo_mobile'); - } - - /** - * Update PS_LOGO_MAIL - */ - public function updateOptionPsLogoMail() - { - $this->updateLogo('PS_LOGO_MAIL', 'logo_mail'); - } - - /** - * Update PS_LOGO_INVOICE - */ - public function updateOptionPsLogoInvoice() - { - $this->updateLogo('PS_LOGO_INVOICE', 'logo_invoice'); - } - - /** - * Update PS_STORES_ICON - */ - public function updateOptionPsStoresIcon() - { - $this->updateLogo('PS_STORES_ICON', 'logo_stores'); - } - - /** - * Generic function which allows logo upload - * - * @param $field_name - * @param $logo_prefix - * - * @return bool - */ - protected function updateLogo($field_name, $logo_prefix) - { - $id_shop = Context::getContext()->shop->id; - if (isset($_FILES[$field_name]['tmp_name']) && $_FILES[$field_name]['tmp_name'] && $_FILES[$field_name]['size']) - { - if ($error = ImageManager::validateUpload($_FILES[$field_name], Tools::getMaxUploadSize())) - { - $this->errors[] = $error; - return false; - } - $tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS'); - - if (!$tmp_name || !move_uploaded_file($_FILES[$field_name]['tmp_name'], $tmp_name)) - return false; - - $ext = ($field_name == 'PS_STORES_ICON') ? '.gif' : '.jpg'; - $logo_name = Tools::link_rewrite(Context::getContext()->shop->name).'-' - .$logo_prefix.'-'.(int)Configuration::get('PS_IMG_UPDATE_TIME').(int)$id_shop.$ext; - - if (Context::getContext()->shop->getContext() == Shop::CONTEXT_ALL || $id_shop == 0 - || Shop::isFeatureActive() == false) - $logo_name = Tools::link_rewrite(Context::getContext()->shop->name).'-' - .$logo_prefix.'-'.(int)Configuration::get('PS_IMG_UPDATE_TIME').$ext; - - if ($field_name == 'PS_STORES_ICON') - { - if (!@ImageManager::resize($tmp_name, _PS_IMG_DIR_.$logo_name, null, null, 'gif', true)) - $this->errors[] = Tools::displayError('An error occurred while attempting to copy your logo.'); - } - else - { - if (!@ImageManager::resize($tmp_name, _PS_IMG_DIR_.$logo_name)) - $this->errors[] = Tools::displayError('An error occurred while attempting to copy your logo.'); - } - $id_shop = null; - $id_shop_group = null; - if (!count($this->errors) && @filemtime(_PS_IMG_DIR_.Configuration::get($field_name))) - { - if (Shop::isFeatureActive()) - { - if (Shop::getContext() == Shop::CONTEXT_SHOP) - { - $id_shop = Shop::getContextShopID(); - $id_shop_group = Shop::getContextShopGroupID(); - Shop::setContext(Shop::CONTEXT_ALL); - $logo_all = Configuration::get($field_name); - Shop::setContext(Shop::CONTEXT_GROUP); - $logo_group = Configuration::get($field_name); - Shop::setContext(Shop::CONTEXT_SHOP); - $logo_shop = Configuration::get($field_name); - if ($logo_all != $logo_shop && $logo_group != $logo_shop && $logo_shop != false) - @unlink(_PS_IMG_DIR_.Configuration::get($field_name)); - } - elseif (Shop::getContext() == Shop::CONTEXT_GROUP) - { - $id_shop_group = Shop::getContextShopGroupID(); - Shop::setContext(Shop::CONTEXT_ALL); - $logo_all = Configuration::get($field_name); - Shop::setContext(Shop::CONTEXT_GROUP); - if ($logo_all != Configuration::get($field_name)) - @unlink(_PS_IMG_DIR_.Configuration::get($field_name)); - } - } - else - @unlink(_PS_IMG_DIR_.Configuration::get($field_name)); - } - Configuration::updateValue($field_name, $logo_name, false, $id_shop_group, $id_shop); - @unlink($tmp_name); - } - } - - /** - * Update PS_FAVICON - */ - public function updateOptionPsFavicon() - { - $id_shop = Context::getContext()->shop->id; - if ($id_shop == Configuration::get('PS_SHOP_DEFAULT')) - $this->uploadIco('PS_FAVICON', _PS_IMG_DIR_.'favicon.ico'); - if ($this->uploadIco('PS_FAVICON', _PS_IMG_DIR_.'favicon-'.(int)$id_shop.'.ico')) - Configuration::updateValue('PS_FAVICON', 'favicon-'.(int)$id_shop.'.ico'); - - Configuration::updateGlobalValue('PS_FAVICON', 'favicon.ico'); - $this->redirect_after = self::$currentIndex.'&token='.$this->token; - } - - /** - * Update theme for current shop - */ - public function updateOptionThemeForShop() - { - if (!$this->can_display_themes) - return; - - $id_theme = (int)Tools::getValue('id_theme'); - if ($id_theme && $this->context->shop->id_theme != $id_theme) - { - $this->context->shop->id_theme = $id_theme; - $this->context->shop->update(); - $this->redirect_after = self::$currentIndex.'&token='.$this->token; - } - } - - protected function uploadIco($name, $dest) - { - if (isset($_FILES[$name]['tmp_name']) && !empty($_FILES[$name]['tmp_name'])) - { - // Check ico validity - if ($error = ImageManager::validateIconUpload($_FILES[$name])) - $this->errors[] = $error; - - // Copy new ico - elseif (!copy($_FILES[$name]['tmp_name'], $dest)) - $this->errors[] = sprintf(Tools::displayError('An error occurred while uploading the favicon: cannot copy file "%s" to folder "%s".'), $_FILES[$name]['tmp_name'], $dest); - } - - return !count($this->errors); - } - - public function initProcess() - { - if ((isset($_GET['responsive'.$this->table]) || isset($_GET['responsive'])) && Tools::getValue($this->identifier)) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'responsive'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif ((isset($_GET['default_left_column'.$this->table]) || isset($_GET['default_left_column'])) && Tools::getValue($this->identifier)) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'defaultleftcolumn'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif ((isset($_GET['default_right_column'.$this->table]) || isset($_GET['default_right_column'])) && Tools::getValue($this->identifier)) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'defaultrightcolumn'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::getIsset('id_theme_meta') && Tools::getIsset('leftmeta')) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'leftmeta'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::getIsset('id_theme_meta') && Tools::getIsset('rightmeta')) - { - if ($this->tabAccess['edit'] === '1') - $this->action = 'rightmeta'; - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - - parent::initProcess(); - // This is a composite page, we don't want the "options" display mode - if ($this->display == 'options' || $this->display == 'list') - $this->display = ''; - } - - public function printResponsiveIcon($value) - { - return ($value ? '<span class="list-action-enable action-enabled"><i class="icon-check"></i></span>' : '<span class="list-action-enable action-disabled"><i class="icon-remove"></i></span>'); - } - - public function processResponsive() - { - if (Validate::isLoadedObject($object = $this->loadObject())) - { - /** @var Theme $object */ - if ($object->toggleResponsive()) - $this->redirect_after = self::$currentIndex.'&conf=5&token='.$this->token; - else - $this->errors[] = Tools::displayError('An error occurred while updating responsive status.'); - } - else - $this->errors[] = Tools::displayError('An error occurred while updating the responsive status for this object.'). - ' <b>'.$this->table.'</b> '. - Tools::displayError('(cannot load object)'); - - return $object; - } - - public function processDefaultLeftColumn() - { - if (Validate::isLoadedObject($object = $this->loadObject())) - { - /** @var Theme $object */ - if ($object->toggleDefaultLeftColumn()) - $this->redirect_after = self::$currentIndex.'&conf=5&token='.$this->token; - else - $this->errors[] = Tools::displayError('An error occurred while updating default left column status.'); - } - else - $this->errors[] = Tools::displayError('An error occurred while updating the default left column status for this object.'). - ' <b>'.$this->table.'</b> '. - Tools::displayError('(cannot load object)'); - - return $object; - } - - public function processDefaultRightColumn() - { - if (Validate::isLoadedObject($object = $this->loadObject())) - { - /** @var Theme $object */ - if ($object->toggleDefaultRightColumn()) - $this->redirect_after = self::$currentIndex.'&conf=5&token='.$this->token; - else - $this->errors[] = Tools::displayError('An error occurred while updating default right column status.'); - } - else - $this->errors[] = Tools::displayError('An error occurred while updating the default right column status for this object.'). - ' <b>'.$this->table.'</b> '. - Tools::displayError('(cannot load object)'); - - return $object; - } - - public function ajaxProcessLeftMeta() - { - $theme_meta = Db::getInstance()->getRow( - 'SELECT * FROM '._DB_PREFIX_.'theme_meta WHERE id_theme_meta = '.(int)Tools::getValue('id_theme_meta') - ); - - $result = false; - if ($theme_meta) - { - $sql = 'UPDATE '._DB_PREFIX_.'theme_meta SET left_column='.(int)!(bool)$theme_meta['left_column'].' WHERE id_theme_meta='.(int)Tools::getValue('id_theme_meta'); - $result = Db::getInstance()->execute($sql); - } - - if ($result) - echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); - else - echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); - } - - public function processLeftMeta() - { - $theme_meta = Db::getInstance()->getRow( - 'SELECT * FROM '._DB_PREFIX_.'theme_meta WHERE id_theme_meta = '.(int)Tools::getValue('id_theme_meta') - ); - - $result = false; - if ($theme_meta) - { - $sql = 'UPDATE '._DB_PREFIX_.'theme_meta SET left_column='.(int)!(bool)$theme_meta['left_column'].' WHERE id_theme_meta='.(int)Tools::getValue('id_theme_meta'); - $result = Db::getInstance()->execute($sql); - } - - if ($result) - $this->redirect_after = self::$currentIndex.'&updatetheme&id_theme='.$theme_meta['id_theme'].'&conf=5&token='.$this->token; - else - $this->errors[] = Tools::displayError('An error occurred while updating this meta.'); - } - - public function ajaxProcessRightMeta() - { - $theme_meta = Db::getInstance()->getRow( - 'SELECT * FROM '._DB_PREFIX_.'theme_meta WHERE id_theme_meta = '.(int)Tools::getValue('id_theme_meta') - ); - - $result = false; - if ($theme_meta) - { - $sql = 'UPDATE '._DB_PREFIX_.'theme_meta SET right_column='.(int)!(bool)$theme_meta['right_column'].' WHERE id_theme_meta='.(int)Tools::getValue('id_theme_meta'); - $result = Db::getInstance()->execute($sql); - } - - if ($result) - echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); - else - echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); - } - - public function processRightMeta() - { - $theme_meta = Db::getInstance()->getRow( - 'SELECT * FROM '._DB_PREFIX_.'theme_meta WHERE id_theme_meta = '.(int)Tools::getValue('id_theme_meta') - ); - - $result = false; - if ($theme_meta) - { - $sql = 'UPDATE '._DB_PREFIX_.'theme_meta SET right_column='.(int)!(bool)$theme_meta['right_column'].' WHERE id_theme_meta='.(int)Tools::getValue('id_theme_meta'); - $result = Db::getInstance()->execute($sql); - } - - if ($result) - $this->redirect_after = self::$currentIndex.'&updatetheme&id_theme='.$theme_meta['id_theme'].'&conf=5&token='.$this->token; - else - $this->errors[] = Tools::displayError('An error occurred while updating this meta.'); - } - - - /** - * Function used to render the options for this controller - */ - public function renderOptions() - { - if (isset($this->display) && method_exists($this, 'render'.$this->display)) - return $this->{'render'.$this->display}(); - if ($this->fields_options && is_array($this->fields_options)) - { - $helper = new HelperOptions($this); - $this->setHelperDisplay($helper); - $helper->toolbar_scroll = true; - $helper->title = $this->l('Theme appearance'); - $helper->toolbar_btn = array( - 'save' => array( - 'href' => '#', - 'desc' => $this->l('Save') - ) - ); - $helper->id = $this->id; - $helper->tpl_vars = $this->tpl_option_vars; - $options = $helper->generateOptions($this->fields_options); - - return $options; - } - } - - public function setMedia() - { - parent::setMedia(); - $this->addJS(_PS_JS_DIR_.'admin/themes.js'); - - if ($this->context->mode == Context::MODE_HOST && Tools::getValue('action') == 'importtheme') - $this->addJS(_PS_JS_DIR_.'admin/addons.js'); - } + if (count($hook['exceptions']) > 0) { + foreach ($hook['exceptions'] as $exception) { + $sql_hook_module_except = 'INSERT INTO `'._DB_PREFIX_.'hook_module_exceptions` (`id_module`, `id_hook`, `file_name`) VALUES ('.(int)$id_module.', '.(int)Hook::getIdByName($hook['hook']).', "'.pSQL($exception).'")'; + Db::getInstance()->execute($sql_hook_module_except); + } + } + Db::getInstance()->execute($sql_hook_module); + } + } + } + + public function processThemeInstall() + { + $shops_asso = $this->context->employee->getAssociatedShops(); + if (Shop::isFeatureActive() && !Tools::getIsset('checkBoxShopAsso_theme') && count($shops_asso) > 1) { + $this->errors[] = $this->l('You must choose at least one shop.'); + $this->display = 'ChooseThemeModule'; + + return; + } + + $theme = new Theme((int)Tools::getValue('id_theme')); + + if (count($shops_asso) == 1) { + $shops = $shops_asso; + } else { + $shops = array(Configuration::get('PS_SHOP_DEFAULT')); + if (Tools::isSubmit('checkBoxShopAsso_theme')) { + $shops = Tools::getValue('checkBoxShopAsso_theme'); + } + } + + $xml = false; + if (file_exists(_PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml')) { + $xml = @simplexml_load_file(_PS_ROOT_DIR_.'/config/xml/themes/'.$theme->directory.'.xml'); + } elseif (file_exists(_PS_ROOT_DIR_.'/config/xml/themes/default.xml')) { + $xml = @simplexml_load_file(_PS_ROOT_DIR_.'/config/xml/themes/default.xml'); + } + + if ($xml) { + $module_hook = array(); + foreach ($xml->modules->hooks->hook as $row) { + $name = strval($row['module']); + + $exceptions = (isset($row['exceptions']) ? explode(',', strval($row['exceptions'])) : array()); + + $module_hook[$name]['hook'][] = array( + 'hook' => strval($row['hook']), + 'position' => strval($row['position']), + 'exceptions' => $exceptions + ); + } + + $this->img_error = $this->updateImages($xml); + + $this->modules_errors = array(); + foreach ($shops as $id_shop) { + foreach ($_POST as $key => $value) { + if (strncmp($key, 'to_install', strlen('to_install')) == 0) { + $module = Module::getInstanceByName($value); + if ($module) { + $is_installed_success = true; + if (!Module::isInstalled($module->name)) { + $is_installed_success = $module->install(); + } + if ($is_installed_success) { + if (!Module::isEnabled($module->name)) { + $module->enable(); + } + + if ((int)$module->id > 0 && isset($module_hook[$module->name])) { + $this->hookModule($module->id, $module_hook[$module->name], $id_shop); + } + } else { + $this->modules_errors[] = array('module_name' => $module->name, 'errors' => $module->getErrors()); + } + + unset($module_hook[$module->name]); + } + } elseif (strncmp($key, 'to_enable', strlen('to_enable')) == 0) { + $module = Module::getInstanceByName($value); + if ($module) { + $is_installed_success = true; + if (!Module::isInstalled($module->name)) { + $is_installed_success = $module->install(); + } + + if ($is_installed_success) { + if (!Module::isEnabled($module->name)) { + $module->enable(); + } + + if ((int)$module->id > 0 && isset($module_hook[$module->name])) { + $this->hookModule($module->id, $module_hook[$module->name], $id_shop); + } + } else { + $this->modules_errors[] = array('module_name' => $module->name, 'errors' => $module->getErrors()); + } + + unset($module_hook[$module->name]); + } + } elseif (strncmp($key, 'to_disable', strlen('to_disable')) == 0) { + $key_exploded = explode('_', $key); + $id_shop_module = (int)substr($key_exploded[2], 4); + + if ((int)$id_shop_module > 0 && $id_shop_module != (int)$id_shop) { + continue; + } + + $module_obj = Module::getInstanceByName($value); + if (Validate::isLoadedObject($module_obj)) { + if (Module::isEnabled($module_obj->name)) { + $module_obj->disable(); + } + + unset($module_hook[$module_obj->name]); + } + } + } + $shop = new Shop((int)$id_shop); + $shop->id_theme = (int)Tools::getValue('id_theme'); + $this->context->shop->id_theme = $shop->id_theme; + $this->context->shop->update(); + $shop->save(); + + if (Shop::isFeatureActive()) { + Configuration::updateValue('PS_PRODUCTS_PER_PAGE', (int)$theme->product_per_page, false, null, (int)$id_shop); + } else { + Configuration::updateValue('PS_PRODUCTS_PER_PAGE', (int)$theme->product_per_page); + } + } + + $this->doc = array(); + foreach ($xml->docs->doc as $row) { + $this->doc[strval($row['name'])] = __PS_BASE_URI__.'themes/'.$theme->directory.'/docs/'.basename(strval($row['path'])); + } + } + + Tools::clearCache($this->context->smarty); + $this->theme_name = $theme->name; + $this->display = 'view'; + } + + public function renderView() + { + $this->tpl_view_vars = array( + 'doc' => $this->doc, + 'theme_name' => $this->theme_name, + 'img_error' => $this->img_error, + 'modules_errors' => $this->modules_errors, + 'back_link' => Context::getContext()->link->getAdminLink('AdminThemes'), + 'image_link' => Context::getContext()->link->getAdminLink('AdminImages') + ); + + return parent::renderView(); + } + + /** + * This functions make checks about AdminThemes configuration edition only. + * + * @since 1.4 + */ + public function postProcess() + { + if (Tools::isSubmit('submitOptionstheme') && Tools::isSubmit('id_theme') && !Tools::isSubmit('deletetheme') + && Tools::getValue('action') != 'ThemeInstall' && $this->context->shop->id_theme != Tools::getValue('id_theme')) { + $this->display = 'ChooseThemeModule'; + } elseif (Tools::isSubmit('installThemeFromFolder') && ($this->context->mode != Context::MODE_HOST)) { + $theme_dir = Tools::getValue('theme_dir'); + $this->installTheme($theme_dir); + } else { + // new check compatibility theme feature (1.4) : + $val = Tools::getValue('PS_THEME'); + Configuration::updateValue('PS_IMG_UPDATE_TIME', time()); + if (!empty($val) && !$this->_isThemeCompatible($val)) { // don't submit if errors + unset($_POST['submitThemes'.$this->table]); + } + Tools::clearCache($this->context->smarty); + + return parent::postProcess(); + } + } + + /** + * Update PS_LOGO + */ + public function updateOptionPsLogo() + { + $this->updateLogo('PS_LOGO', 'logo'); + } + + /** + * Update PS_LOGO_MOBILE + */ + public function updateOptionPsLogoMobile() + { + $this->updateLogo('PS_LOGO_MOBILE', 'logo_mobile'); + } + + /** + * Update PS_LOGO_MAIL + */ + public function updateOptionPsLogoMail() + { + $this->updateLogo('PS_LOGO_MAIL', 'logo_mail'); + } + + /** + * Update PS_LOGO_INVOICE + */ + public function updateOptionPsLogoInvoice() + { + $this->updateLogo('PS_LOGO_INVOICE', 'logo_invoice'); + } + + /** + * Update PS_STORES_ICON + */ + public function updateOptionPsStoresIcon() + { + $this->updateLogo('PS_STORES_ICON', 'logo_stores'); + } + + /** + * Generic function which allows logo upload + * + * @param $field_name + * @param $logo_prefix + * + * @return bool + */ + protected function updateLogo($field_name, $logo_prefix) + { + $id_shop = Context::getContext()->shop->id; + if (isset($_FILES[$field_name]['tmp_name']) && $_FILES[$field_name]['tmp_name'] && $_FILES[$field_name]['size']) { + if ($error = ImageManager::validateUpload($_FILES[$field_name], Tools::getMaxUploadSize())) { + $this->errors[] = $error; + return false; + } + $tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS'); + + if (!$tmp_name || !move_uploaded_file($_FILES[$field_name]['tmp_name'], $tmp_name)) { + return false; + } + + $ext = ($field_name == 'PS_STORES_ICON') ? '.gif' : '.jpg'; + $logo_name = Tools::link_rewrite(Context::getContext()->shop->name).'-' + .$logo_prefix.'-'.(int)Configuration::get('PS_IMG_UPDATE_TIME').(int)$id_shop.$ext; + + if (Context::getContext()->shop->getContext() == Shop::CONTEXT_ALL || $id_shop == 0 + || Shop::isFeatureActive() == false) { + $logo_name = Tools::link_rewrite(Context::getContext()->shop->name).'-' + .$logo_prefix.'-'.(int)Configuration::get('PS_IMG_UPDATE_TIME').$ext; + } + + if ($field_name == 'PS_STORES_ICON') { + if (!@ImageManager::resize($tmp_name, _PS_IMG_DIR_.$logo_name, null, null, 'gif', true)) { + $this->errors[] = Tools::displayError('An error occurred while attempting to copy your logo.'); + } + } else { + if (!@ImageManager::resize($tmp_name, _PS_IMG_DIR_.$logo_name)) { + $this->errors[] = Tools::displayError('An error occurred while attempting to copy your logo.'); + } + } + $id_shop = null; + $id_shop_group = null; + if (!count($this->errors) && @filemtime(_PS_IMG_DIR_.Configuration::get($field_name))) { + if (Shop::isFeatureActive()) { + if (Shop::getContext() == Shop::CONTEXT_SHOP) { + $id_shop = Shop::getContextShopID(); + $id_shop_group = Shop::getContextShopGroupID(); + Shop::setContext(Shop::CONTEXT_ALL); + $logo_all = Configuration::get($field_name); + Shop::setContext(Shop::CONTEXT_GROUP); + $logo_group = Configuration::get($field_name); + Shop::setContext(Shop::CONTEXT_SHOP); + $logo_shop = Configuration::get($field_name); + if ($logo_all != $logo_shop && $logo_group != $logo_shop && $logo_shop != false) { + @unlink(_PS_IMG_DIR_.Configuration::get($field_name)); + } + } elseif (Shop::getContext() == Shop::CONTEXT_GROUP) { + $id_shop_group = Shop::getContextShopGroupID(); + Shop::setContext(Shop::CONTEXT_ALL); + $logo_all = Configuration::get($field_name); + Shop::setContext(Shop::CONTEXT_GROUP); + if ($logo_all != Configuration::get($field_name)) { + @unlink(_PS_IMG_DIR_.Configuration::get($field_name)); + } + } + } else { + @unlink(_PS_IMG_DIR_.Configuration::get($field_name)); + } + } + Configuration::updateValue($field_name, $logo_name, false, $id_shop_group, $id_shop); + Hook::exec('actionAdminThemesControllerUpdate_optionsAfter'); + @unlink($tmp_name); + } + } + + /** + * Update PS_FAVICON + */ + public function updateOptionPsFavicon() + { + $id_shop = Context::getContext()->shop->id; + if ($id_shop == Configuration::get('PS_SHOP_DEFAULT')) { + $this->uploadIco('PS_FAVICON', _PS_IMG_DIR_.'favicon.ico'); + } + if ($this->uploadIco('PS_FAVICON', _PS_IMG_DIR_.'favicon-'.(int)$id_shop.'.ico')) { + Configuration::updateValue('PS_FAVICON', 'favicon-'.(int)$id_shop.'.ico'); + } + + Configuration::updateGlobalValue('PS_FAVICON', 'favicon.ico'); + $this->redirect_after = self::$currentIndex.'&token='.$this->token; + } + + /** + * Update theme for current shop + */ + public function updateOptionThemeForShop() + { + if (!$this->can_display_themes) { + return; + } + + $id_theme = (int)Tools::getValue('id_theme'); + if ($id_theme && $this->context->shop->id_theme != $id_theme) { + $this->context->shop->id_theme = $id_theme; + $this->context->shop->update(); + $this->redirect_after = self::$currentIndex.'&token='.$this->token; + } + } + + protected function uploadIco($name, $dest) + { + if (isset($_FILES[$name]['tmp_name']) && !empty($_FILES[$name]['tmp_name'])) { + // Check ico validity + if ($error = ImageManager::validateIconUpload($_FILES[$name])) { + $this->errors[] = $error; + } elseif (!copy($_FILES[$name]['tmp_name'], $dest)) { + // Copy new ico + $this->errors[] = sprintf(Tools::displayError('An error occurred while uploading the favicon: cannot copy file "%s" to folder "%s".'), $_FILES[$name]['tmp_name'], $dest); + } + } + + return !count($this->errors); + } + + public function initProcess() + { + if ((isset($_GET['responsive'.$this->table]) || isset($_GET['responsive'])) && Tools::getValue($this->identifier)) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'responsive'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif ((isset($_GET['default_left_column'.$this->table]) || isset($_GET['default_left_column'])) && Tools::getValue($this->identifier)) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'defaultleftcolumn'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif ((isset($_GET['default_right_column'.$this->table]) || isset($_GET['default_right_column'])) && Tools::getValue($this->identifier)) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'defaultrightcolumn'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::getIsset('id_theme_meta') && Tools::getIsset('leftmeta')) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'leftmeta'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::getIsset('id_theme_meta') && Tools::getIsset('rightmeta')) { + if ($this->tabAccess['edit'] === '1') { + $this->action = 'rightmeta'; + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + + parent::initProcess(); + // This is a composite page, we don't want the "options" display mode + if ($this->display == 'options' || $this->display == 'list') { + $this->display = ''; + } + } + + public function printResponsiveIcon($value) + { + return ($value ? '<span class="list-action-enable action-enabled"><i class="icon-check"></i></span>' : '<span class="list-action-enable action-disabled"><i class="icon-remove"></i></span>'); + } + + public function processResponsive() + { + if (Validate::isLoadedObject($object = $this->loadObject())) { + /** @var Theme $object */ + if ($object->toggleResponsive()) { + $this->redirect_after = self::$currentIndex.'&conf=5&token='.$this->token; + } else { + $this->errors[] = Tools::displayError('An error occurred while updating responsive status.'); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the responsive status for this object.'). + ' <b>'.$this->table.'</b> '. + Tools::displayError('(cannot load object)'); + } + + return $object; + } + + public function processDefaultLeftColumn() + { + if (Validate::isLoadedObject($object = $this->loadObject())) { + /** @var Theme $object */ + if ($object->toggleDefaultLeftColumn()) { + $this->redirect_after = self::$currentIndex.'&conf=5&token='.$this->token; + } else { + $this->errors[] = Tools::displayError('An error occurred while updating default left column status.'); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the default left column status for this object.'). + ' <b>'.$this->table.'</b> '. + Tools::displayError('(cannot load object)'); + } + + return $object; + } + + public function processDefaultRightColumn() + { + if (Validate::isLoadedObject($object = $this->loadObject())) { + /** @var Theme $object */ + if ($object->toggleDefaultRightColumn()) { + $this->redirect_after = self::$currentIndex.'&conf=5&token='.$this->token; + } else { + $this->errors[] = Tools::displayError('An error occurred while updating default right column status.'); + } + } else { + $this->errors[] = Tools::displayError('An error occurred while updating the default right column status for this object.'). + ' <b>'.$this->table.'</b> '. + Tools::displayError('(cannot load object)'); + } + + return $object; + } + + public function ajaxProcessLeftMeta() + { + $theme_meta = Db::getInstance()->getRow( + 'SELECT * FROM '._DB_PREFIX_.'theme_meta WHERE id_theme_meta = '.(int)Tools::getValue('id_theme_meta') + ); + + $result = false; + if ($theme_meta) { + $sql = 'UPDATE '._DB_PREFIX_.'theme_meta SET left_column='.(int)!(bool)$theme_meta['left_column'].' WHERE id_theme_meta='.(int)Tools::getValue('id_theme_meta'); + $result = Db::getInstance()->execute($sql); + } + + if ($result) { + echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); + } else { + echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); + } + } + + public function processLeftMeta() + { + $theme_meta = Db::getInstance()->getRow( + 'SELECT * FROM '._DB_PREFIX_.'theme_meta WHERE id_theme_meta = '.(int)Tools::getValue('id_theme_meta') + ); + + $result = false; + if ($theme_meta) { + $sql = 'UPDATE '._DB_PREFIX_.'theme_meta SET left_column='.(int)!(bool)$theme_meta['left_column'].' WHERE id_theme_meta='.(int)Tools::getValue('id_theme_meta'); + $result = Db::getInstance()->execute($sql); + } + + if ($result) { + $this->redirect_after = self::$currentIndex.'&updatetheme&id_theme='.$theme_meta['id_theme'].'&conf=5&token='.$this->token; + } else { + $this->errors[] = Tools::displayError('An error occurred while updating this meta.'); + } + } + + public function ajaxProcessRightMeta() + { + $theme_meta = Db::getInstance()->getRow( + 'SELECT * FROM '._DB_PREFIX_.'theme_meta WHERE id_theme_meta = '.(int)Tools::getValue('id_theme_meta') + ); + + $result = false; + if ($theme_meta) { + $sql = 'UPDATE '._DB_PREFIX_.'theme_meta SET right_column='.(int)!(bool)$theme_meta['right_column'].' WHERE id_theme_meta='.(int)Tools::getValue('id_theme_meta'); + $result = Db::getInstance()->execute($sql); + } + + if ($result) { + echo json_encode(array('success' => 1, 'text' => $this->l('The status has been updated successfully.'))); + } else { + echo json_encode(array('success' => 0, 'text' => $this->l('An error occurred while updating this meta.'))); + } + } + + public function processRightMeta() + { + $theme_meta = Db::getInstance()->getRow( + 'SELECT * FROM '._DB_PREFIX_.'theme_meta WHERE id_theme_meta = '.(int)Tools::getValue('id_theme_meta') + ); + + $result = false; + if ($theme_meta) { + $sql = 'UPDATE '._DB_PREFIX_.'theme_meta SET right_column='.(int)!(bool)$theme_meta['right_column'].' WHERE id_theme_meta='.(int)Tools::getValue('id_theme_meta'); + $result = Db::getInstance()->execute($sql); + } + + if ($result) { + $this->redirect_after = self::$currentIndex.'&updatetheme&id_theme='.$theme_meta['id_theme'].'&conf=5&token='.$this->token; + } else { + $this->errors[] = Tools::displayError('An error occurred while updating this meta.'); + } + } + + + /** + * Function used to render the options for this controller + */ + public function renderOptions() + { + if (isset($this->display) && method_exists($this, 'render'.$this->display)) { + return $this->{'render'.$this->display}(); + } + if ($this->fields_options && is_array($this->fields_options)) { + $helper = new HelperOptions($this); + $this->setHelperDisplay($helper); + $helper->toolbar_scroll = true; + $helper->title = $this->l('Theme appearance'); + $helper->toolbar_btn = array( + 'save' => array( + 'href' => '#', + 'desc' => $this->l('Save') + ) + ); + $helper->id = $this->id; + $helper->tpl_vars = $this->tpl_option_vars; + $options = $helper->generateOptions($this->fields_options); + + return $options; + } + } + + public function setMedia() + { + parent::setMedia(); + $this->addJS(_PS_JS_DIR_.'admin/themes.js'); + + if ($this->context->mode == Context::MODE_HOST && Tools::getValue('action') == 'importtheme') { + $this->addJS(_PS_JS_DIR_.'admin/addons.js'); + } + } } diff --git a/controllers/admin/AdminTrackingController.php b/controllers/admin/AdminTrackingController.php index d5bd41be..c36a5fd9 100644 --- a/controllers/admin/AdminTrackingController.php +++ b/controllers/admin/AdminTrackingController.php @@ -29,130 +29,130 @@ */ class AdminTrackingControllerCore extends AdminController { - public $bootstrap = true; + public $bootstrap = true; - /** @var HelperList */ - protected $_helper_list; + /** @var HelperList */ + protected $_helper_list; - public function postprocess() - { - if (Tools::getValue('id_product') && Tools::isSubmit('statusproduct')) - { - $this->table = 'product'; - $this->identifier = 'id_product'; - $this->action = 'status'; - $this->className = 'Product'; - } - elseif (Tools::getValue('id_category') && Tools::isSubmit('statuscategory')) - { - $this->table = 'category'; - $this->identifier = 'id_category'; - $this->action = 'status'; - $this->className = 'Category'; - } + public function postprocess() + { + if (Tools::getValue('id_product') && Tools::isSubmit('statusproduct')) { + $this->table = 'product'; + $this->identifier = 'id_product'; + $this->action = 'status'; + $this->className = 'Product'; + } elseif (Tools::getValue('id_category') && Tools::isSubmit('statuscategory')) { + $this->table = 'category'; + $this->identifier = 'id_category'; + $this->action = 'status'; + $this->className = 'Category'; + } - $this->list_no_link = true; + $this->list_no_link = true; - parent::postprocess(); - } + parent::postprocess(); + } - public function initContent() - { - $this->initTabModuleList(); - $this->initPageHeaderToolbar(); + public function initContent() + { + $this->initTabModuleList(); + $this->initPageHeaderToolbar(); - if ($id_category = Tools::getValue('id_category') && Tools::getIsset('viewcategory')) - Tools::redirectAdmin($this->context->link->getAdminLink('AdminProducts').'&id_category='.(int)$id_category.'&viewcategory'); + if ($id_category = Tools::getValue('id_category') && Tools::getIsset('viewcategory')) { + Tools::redirectAdmin($this->context->link->getAdminLink('AdminProducts').'&id_category='.(int)$id_category.'&viewcategory'); + } - $this->_helper_list = new HelperList(); + $this->_helper_list = new HelperList(); - if (!Configuration::get('PS_STOCK_MANAGEMENT')) - $this->warnings[] = $this->l('List of products without available quantities for sale are not displayed because stock management is disabled.'); + if (!Configuration::get('PS_STOCK_MANAGEMENT')) { + $this->warnings[] = $this->l('List of products without available quantities for sale are not displayed because stock management is disabled.'); + } - $methods = get_class_methods($this); - $tpl_vars['arrayList'] = array(); - foreach ($methods as $method_name) - if (preg_match('#getCustomList(.+)#', $method_name, $matches)) - { - $this->clearListOptions(); - $this->content .= call_user_func(array($this,$matches[0])); - } - $this->context->smarty->assign(array( - 'content' => $this->content, - 'url_post' => self::$currentIndex.'&token='.$this->token, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn - )); - } + $methods = get_class_methods($this); + $tpl_vars['arrayList'] = array(); + foreach ($methods as $method_name) { + if (preg_match('#getCustomList(.+)#', $method_name, $matches)) { + $this->clearListOptions(); + $this->content .= call_user_func(array($this, $matches[0])); + } + } + $this->context->smarty->assign(array( + 'content' => $this->content, + 'url_post' => self::$currentIndex.'&token='.$this->token, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn + )); + } - public function getCustomListCategoriesEmpty() - { - $this->table = 'category'; - $this->list_id = 'empty_categories'; - $this->lang = true; - $this->className = 'Category'; - $this->identifier = 'id_category'; - $this->_orderBy = 'id_category'; - $this->_orderWay = 'DESC'; - $this->_list_index = 'index.php?controller=AdminCategories'; - $this->_list_token = Tools::getAdminTokenLite('AdminCategories'); + public function getCustomListCategoriesEmpty() + { + $this->table = 'category'; + $this->list_id = 'empty_categories'; + $this->lang = true; + $this->className = 'Category'; + $this->identifier = 'id_category'; + $this->_orderBy = 'id_category'; + $this->_orderWay = 'DESC'; + $this->_list_index = 'index.php?controller=AdminCategories'; + $this->_list_token = Tools::getAdminTokenLite('AdminCategories'); - $this->addRowAction('edit'); - $this->addRowAction('view'); - $this->addRowAction('delete'); - $this->addRowActionSkipList('delete', array((int)Configuration::get('PS_ROOT_CATEGORY'))); - $this->addRowActionSkipList('edit', array((int)Configuration::get('PS_ROOT_CATEGORY'))); + $this->addRowAction('edit'); + $this->addRowAction('view'); + $this->addRowAction('delete'); + $this->addRowActionSkipList('delete', array((int)Configuration::get('PS_ROOT_CATEGORY'))); + $this->addRowActionSkipList('edit', array((int)Configuration::get('PS_ROOT_CATEGORY'))); - $this->fields_list = (array( - 'id_category' => array('title' => $this->l('ID'), 'class' => 'fixed-width-xs', 'align' => 'center'), - 'name' => array('title' => $this->l('Name'), 'filter_key' => 'b!name'), - 'description' => array('title' => $this->l('Description'), 'callback' => 'getDescriptionClean'), - 'active' => array('title' => $this->l('Status'), 'type' => 'bool', 'active' => 'status', 'align' => 'center', 'class' => 'fixed-width-xs') - )); - $this->clearFilters(); + $this->fields_list = (array( + 'id_category' => array('title' => $this->l('ID'), 'class' => 'fixed-width-xs', 'align' => 'center'), + 'name' => array('title' => $this->l('Name'), 'filter_key' => 'b!name'), + 'description' => array('title' => $this->l('Description'), 'callback' => 'getDescriptionClean'), + 'active' => array('title' => $this->l('Status'), 'type' => 'bool', 'active' => 'status', 'align' => 'center', 'class' => 'fixed-width-xs') + )); + $this->clearFilters(); - $this->_join = Shop::addSqlAssociation('category', 'a'); - $this->_filter = ' AND NOT EXISTS ( + $this->_join = Shop::addSqlAssociation('category', 'a'); + $this->_filter = ' AND NOT EXISTS ( SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp WHERE a.`id_category` = cp.id_category ) AND a.`id_category` != '.(int)Configuration::get('PS_ROOT_CATEGORY'); - $this->toolbar_title = $this->l('List of empty categories:'); - return $this->renderList(); - } + $this->toolbar_title = $this->l('List of empty categories:'); + return $this->renderList(); + } - public function getCustomListProductsAttributesNoStock() - { - if (!Configuration::get('PS_STOCK_MANAGEMENT')) - return; + public function getCustomListProductsAttributesNoStock() + { + if (!Configuration::get('PS_STOCK_MANAGEMENT')) { + return; + } - $this->table = 'product'; - $this->list_id = 'no_stock_products_attributes'; - $this->lang = true; - $this->identifier = 'id_product'; - $this->_orderBy = 'id_product'; - $this->_orderWay = 'DESC'; - $this->className = 'Product'; - $this->_list_index = 'index.php?controller=AdminProducts'; - $this->_list_token = Tools::getAdminTokenLite('AdminProducts'); - $this->show_toolbar = false; + $this->table = 'product'; + $this->list_id = 'no_stock_products_attributes'; + $this->lang = true; + $this->identifier = 'id_product'; + $this->_orderBy = 'id_product'; + $this->_orderWay = 'DESC'; + $this->className = 'Product'; + $this->_list_index = 'index.php?controller=AdminProducts'; + $this->_list_token = Tools::getAdminTokenLite('AdminProducts'); + $this->show_toolbar = false; - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->fields_list = array( - 'id_product' => array('title' => $this->l('ID'), 'class' => 'fixed-width-xs', 'align' => 'center'), - 'reference' => array('title' => $this->l('Reference')), - 'name' => array('title' => $this->l('Name'), 'filter_key' => 'b!name'), - 'active' => array('title' => $this->l('Status'), 'type' => 'bool', 'active' => 'status', 'align' => 'center', 'class' => 'fixed-width-xs') - ); + $this->fields_list = array( + 'id_product' => array('title' => $this->l('ID'), 'class' => 'fixed-width-xs', 'align' => 'center'), + 'reference' => array('title' => $this->l('Reference')), + 'name' => array('title' => $this->l('Name'), 'filter_key' => 'b!name'), + 'active' => array('title' => $this->l('Status'), 'type' => 'bool', 'active' => 'status', 'align' => 'center', 'class' => 'fixed-width-xs') + ); - $this->clearFilters(); + $this->clearFilters(); - $this->_join = Shop::addSqlAssociation('product', 'a'); - $this->_filter = 'AND EXISTS ( + $this->_join = Shop::addSqlAssociation('product', 'a'); + $this->_filter = 'AND EXISTS ( SELECT 1 FROM `'._DB_PREFIX_.'product` p '.Product::sqlStock('p').' @@ -162,39 +162,40 @@ class AdminTrackingControllerCore extends AdminController ) AND IFNULL(stock.quantity, 0) <= 0 )'; - $this->toolbar_title = $this->l('List of products with attributes but without available quantities for sale:'); - return $this->renderList(); - } + $this->toolbar_title = $this->l('List of products with attributes but without available quantities for sale:'); + return $this->renderList(); + } - public function getCustomListProductsNoStock() - { - if (!Configuration::get('PS_STOCK_MANAGEMENT')) - return; + public function getCustomListProductsNoStock() + { + if (!Configuration::get('PS_STOCK_MANAGEMENT')) { + return; + } - $this->table = 'product'; - $this->list_id = 'no_stock_products'; - $this->className = 'Product'; - $this->lang = true; - $this->identifier = 'id_product'; - $this->_orderBy = 'id_product'; - $this->_orderWay = 'DESC'; - $this->show_toolbar = false; - $this->_list_index = 'index.php?controller=AdminProducts'; - $this->_list_token = Tools::getAdminTokenLite('AdminProducts'); + $this->table = 'product'; + $this->list_id = 'no_stock_products'; + $this->className = 'Product'; + $this->lang = true; + $this->identifier = 'id_product'; + $this->_orderBy = 'id_product'; + $this->_orderWay = 'DESC'; + $this->show_toolbar = false; + $this->_list_index = 'index.php?controller=AdminProducts'; + $this->_list_token = Tools::getAdminTokenLite('AdminProducts'); - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->fields_list = array( - 'id_product' => array('title' => $this->l('ID'), 'class' => 'fixed-width-xs', 'align' => 'center'), - 'reference' => array('title' => $this->l('Reference')), - 'name' => array('title' => $this->l('Name')), - 'active' => array('title' => $this->l('Status'), 'type' => 'bool', 'active' => 'status', 'align' => 'center', 'class' => 'fixed-width-xs') - ); - $this->clearFilters(); + $this->fields_list = array( + 'id_product' => array('title' => $this->l('ID'), 'class' => 'fixed-width-xs', 'align' => 'center'), + 'reference' => array('title' => $this->l('Reference')), + 'name' => array('title' => $this->l('Name')), + 'active' => array('title' => $this->l('Status'), 'type' => 'bool', 'active' => 'status', 'align' => 'center', 'class' => 'fixed-width-xs') + ); + $this->clearFilters(); - $this->_join = Shop::addSqlAssociation('product', 'a'); - $this->_filter = 'AND EXISTS ( + $this->_join = Shop::addSqlAssociation('product', 'a'); + $this->_filter = 'AND EXISTS ( SELECT 1 FROM `'._DB_PREFIX_.'product` p '.Product::sqlStock('p').' @@ -205,138 +206,142 @@ class AdminTrackingControllerCore extends AdminController AND IFNULL(stock.quantity, 0) <= 0 )'; - $this->toolbar_title = $this->l('List of products without attributes and without available quantities for sale:'); - return $this->renderList(); - } + $this->toolbar_title = $this->l('List of products without attributes and without available quantities for sale:'); + return $this->renderList(); + } - public function getCustomListProductsDisabled() - { - $this->table = 'product'; - $this->list_id = 'disabled_products'; - $this->className = 'Product'; - $this->lang = true; - $this->identifier = 'id_product'; - $this->_orderBy = 'id_product'; - $this->_orderWay = 'DESC'; - $this->_filter = 'AND product_shop.`active` = 0'; - $this->show_toolbar = false; - $this->_list_index = 'index.php?controller=AdminProducts'; - $this->_list_token = Tools::getAdminTokenLite('AdminProducts'); + public function getCustomListProductsDisabled() + { + $this->table = 'product'; + $this->list_id = 'disabled_products'; + $this->className = 'Product'; + $this->lang = true; + $this->identifier = 'id_product'; + $this->_orderBy = 'id_product'; + $this->_orderWay = 'DESC'; + $this->_filter = 'AND product_shop.`active` = 0'; + $this->show_toolbar = false; + $this->_list_index = 'index.php?controller=AdminProducts'; + $this->_list_token = Tools::getAdminTokenLite('AdminProducts'); - $this->addRowAction('edit'); - $this->addRowAction('delete'); + $this->addRowAction('edit'); + $this->addRowAction('delete'); - $this->fields_list = array( - 'id_product' => array('title' => $this->l('ID'), 'class' => 'fixed-width-xs', 'align' => 'center'), - 'reference' => array('title' => $this->l('Reference')), - 'name' => array('title' => $this->l('Name'), 'filter_key' => 'b!name') - ); + $this->fields_list = array( + 'id_product' => array('title' => $this->l('ID'), 'class' => 'fixed-width-xs', 'align' => 'center'), + 'reference' => array('title' => $this->l('Reference')), + 'name' => array('title' => $this->l('Name'), 'filter_key' => 'b!name') + ); - $this->clearFilters(); + $this->clearFilters(); - $this->_join = Shop::addSqlAssociation('product', 'a'); - $this->toolbar_title = $this->l('List of disabled products:'); - return $this->renderList(); - } + $this->_join = Shop::addSqlAssociation('product', 'a'); + $this->toolbar_title = $this->l('List of disabled products:'); + return $this->renderList(); + } - public function renderList() - { - $this->processFilter(); + public function renderList() + { + $this->processFilter(); - if (!($this->fields_list && is_array($this->fields_list))) - return false; - $this->getList($this->context->language->id); + if (!($this->fields_list && is_array($this->fields_list))) { + return false; + } + $this->getList($this->context->language->id); - $helper = new HelperList(); + $helper = new HelperList(); - // Empty list is ok - if (!is_array($this->_list)) - { - $this->displayWarning($this->l('Bad SQL query', 'Helper').'<br />'.htmlspecialchars($this->_list_error)); - return false; - } + // Empty list is ok + if (!is_array($this->_list)) { + $this->displayWarning($this->l('Bad SQL query', 'Helper').'<br />'.htmlspecialchars($this->_list_error)); + return false; + } - $this->setHelperDisplay($helper); - $helper->tpl_vars = $this->tpl_list_vars; - $helper->tpl_delete_link_vars = $this->tpl_delete_link_vars; + $this->setHelperDisplay($helper); + $helper->tpl_vars = $this->tpl_list_vars; + $helper->tpl_delete_link_vars = $this->tpl_delete_link_vars; - // For compatibility reasons, we have to check standard actions in class attributes - foreach ($this->actions_available as $action) - { - if (!in_array($action, $this->actions) && isset($this->$action) && $this->$action) - $this->actions[] = $action; - } - $helper->is_cms = $this->is_cms; - $list = $helper->generateList($this->_list, $this->fields_list); + // For compatibility reasons, we have to check standard actions in class attributes + foreach ($this->actions_available as $action) { + if (!in_array($action, $this->actions) && isset($this->$action) && $this->$action) { + $this->actions[] = $action; + } + } + $helper->is_cms = $this->is_cms; + $list = $helper->generateList($this->_list, $this->fields_list); - return $list; - } + return $list; + } - public function displayEnableLink($token, $id, $value, $active, $id_category = null, $id_product = null) - { - $this->_helper_list->currentIndex = $this->_list_index; - $this->_helper_list->identifier = $this->identifier; - $this->_helper_list->table = $this->table; + public function displayEnableLink($token, $id, $value, $active, $id_category = null, $id_product = null) + { + $this->_helper_list->currentIndex = $this->_list_index; + $this->_helper_list->identifier = $this->identifier; + $this->_helper_list->table = $this->table; - return $this->_helper_list->displayEnableLink($this->_list_token, $id, $value, $active, $id_category, $id_product); - } + return $this->_helper_list->displayEnableLink($this->_list_token, $id, $value, $active, $id_category, $id_product); + } - public function displayDeleteLink($token = null, $id, $name = null) - { - $this->_helper_list->currentIndex = $this->_list_index; - $this->_helper_list->identifier = $this->identifier; - $this->_helper_list->table = $this->table; + public function displayDeleteLink($token = null, $id, $name = null) + { + $this->_helper_list->currentIndex = $this->_list_index; + $this->_helper_list->identifier = $this->identifier; + $this->_helper_list->table = $this->table; - return $this->_helper_list->displayDeleteLink($this->_list_token, $id, $name); - } + return $this->_helper_list->displayDeleteLink($this->_list_token, $id, $name); + } - public function displayEditLink($token = null, $id, $name = null) - { - $this->_helper_list->currentIndex = $this->_list_index; - $this->_helper_list->identifier = $this->identifier; - $this->_helper_list->table = $this->table; + public function displayEditLink($token = null, $id, $name = null) + { + $this->_helper_list->currentIndex = $this->_list_index; + $this->_helper_list->identifier = $this->identifier; + $this->_helper_list->table = $this->table; - return $this->_helper_list->displayEditLink($this->_list_token, $id, $name); - } + return $this->_helper_list->displayEditLink($this->_list_token, $id, $name); + } - protected function clearFilters() - { - if (Tools::isSubmit('submitResetempty_categories')) - $this->processResetFilters('empty_categories'); + protected function clearFilters() + { + if (Tools::isSubmit('submitResetempty_categories')) { + $this->processResetFilters('empty_categories'); + } - if (Tools::isSubmit('submitResetno_stock_products_attributes')) - $this->processResetFilters('no_stock_products_attributes'); + if (Tools::isSubmit('submitResetno_stock_products_attributes')) { + $this->processResetFilters('no_stock_products_attributes'); + } - if (Tools::isSubmit('submitResetno_stock_products')) - $this->processResetFilters('no_stock_products'); + if (Tools::isSubmit('submitResetno_stock_products')) { + $this->processResetFilters('no_stock_products'); + } - if (Tools::isSubmit('submitResetdisabled_products')) - $this->processResetFilters('disabled_products'); - } + if (Tools::isSubmit('submitResetdisabled_products')) { + $this->processResetFilters('disabled_products'); + } + } - public function clearListOptions() - { - $this->table = ''; - $this->actions = array(); - $this->list_skip_actions = array(); - $this->lang = false; - $this->identifier = ''; - $this->_orderBy = ''; - $this->_orderWay = ''; - $this->_filter = ''; - $this->_group = ''; - $this->_where = ''; - $this->list_title = $this->l('Product disabled'); - } + public function clearListOptions() + { + $this->table = ''; + $this->actions = array(); + $this->list_skip_actions = array(); + $this->lang = false; + $this->identifier = ''; + $this->_orderBy = ''; + $this->_orderWay = ''; + $this->_filter = ''; + $this->_group = ''; + $this->_where = ''; + $this->list_title = $this->l('Product disabled'); + } - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, Context::getContext()->shop->id); - } + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, Context::getContext()->shop->id); + } - public static function getDescriptionClean($description) - { - return Tools::getDescriptionClean($description); - } + public static function getDescriptionClean($description) + { + return Tools::getDescriptionClean($description); + } } diff --git a/controllers/admin/AdminTranslationsController.php b/controllers/admin/AdminTranslationsController.php index 2e63a5aa..2d4baf09 100644 --- a/controllers/admin/AdminTranslationsController.php +++ b/controllers/admin/AdminTranslationsController.php @@ -26,1549 +26,1550 @@ class AdminTranslationsControllerCore extends AdminController { - /** Name of theme by default */ - const DEFAULT_THEME_NAME = _PS_DEFAULT_THEME_NAME_; - const TEXTAREA_SIZED = 70; - - /** @var string : Link which list all pack of language */ - protected $link_lang_pack = 'http://www.prestashop.com/download/lang_packs/get_each_language_pack.php'; - - /** @var int : number of sentence which can be translated */ - protected $total_expression = 0; - - /** @var int : number of sentence which aren't translated */ - protected $missing_translations = 0; - - /** @var array : List of ISO code for all languages */ - protected $all_iso_lang = array(); - - /** @var array */ - protected $modules_translations = array(); - - /** @var array : List of folder which must be ignored */ - protected static $ignore_folder = array('.', '..', '.svn', '.git', '.htaccess', 'index.php'); - - /** @var array : List of theme by translation type : FRONT, BACK, ERRORS... */ - protected $translations_informations = array(); - - /** @var array : List of all languages */ - protected $languages; - - /** @var array : List of all themes */ - protected $themes; - - /** @var string : Directory of selected theme */ - protected $theme_selected; - - /** @var string : Name of translations type */ - protected $type_selected; - - /** @var Language object : Language for the selected language */ - protected $lang_selected; - - /** @var bool : Is true if number of var exceed the suhosin request or post limit */ - protected $post_limit_exceed = false; - - public function __construct() - { - $this->bootstrap = true; - $this->multishop_context = Shop::CONTEXT_ALL; - $this->table = 'translations'; - - parent::__construct(); - } - - /* - * Set the type which is selected - */ - public function setTypeSelected($type_selected) - { - $this->type_selected = $type_selected; - } - - /** - * AdminController::initContent() override - * @see AdminController::initContent() - */ - public function initContent() - { - $this->initTabModuleList(); - $this->initPageHeaderToolbar(); - - if (!is_null($this->type_selected)) - { - $method_name = 'initForm'.$this->type_selected; - if (method_exists($this, $method_name)) - $this->content = $this->initForm($method_name); - else - { - $this->errors[] = sprintf(Tools::displayError('"%s" does not exist.'), $this->type_selected); - $this->content = $this->initMain(); - } - } - else - $this->content = $this->initMain(); - - $this->context->smarty->assign(array( - 'content' => $this->content, - 'show_page_header_toolbar' => $this->show_page_header_toolbar, - 'page_header_toolbar_title' => $this->page_header_toolbar_title, - 'page_header_toolbar_btn' => $this->page_header_toolbar_btn)); - } - - /** - * This function create vars by default and call the good method for generate form - * - * @param $method_name - * @return mixed Call the method $this->method_name() - */ - public function initForm($method_name) - { - // Create a title for each translation page - $title = sprintf( - $this->l('%1$s (Language: %2$s, Theme: %3$s)'), - $this->translations_informations[$this->type_selected]['name'], - $this->lang_selected->name, - $this->theme_selected ? $this->theme_selected : $this->l('none') - ); - - // Set vars for all forms - $this->tpl_view_vars = array( - 'lang' => $this->lang_selected->iso_code, - 'title' => $title, - 'type' => $this->type_selected, - 'theme' => $this->theme_selected, - 'post_limit_exceeded' => $this->post_limit_exceed, - 'url_submit' => self::$currentIndex.'&submitTranslations'.ucfirst($this->type_selected).'=1&token='.$this->token, - 'toggle_button' => $this->displayToggleButton(), - 'textarea_sized' => AdminTranslationsControllerCore::TEXTAREA_SIZED - ); - - // Call method initForm for a type - return $this->{$method_name}(); - } - - /** - * AdminController::initToolbar() override - * @see AdminController::initToolbar() - */ - public function initToolbar() - { - $this->toolbar_btn['save-and-stay'] = array( - 'short' => 'SaveAndStay', - 'href' => '#', - 'desc' => $this->l('Save and stay'), - ); - $this->toolbar_btn['save'] = array( - 'href' => '#', - 'desc' => $this->l('Update translations') - ); - $this->toolbar_btn['cancel'] = array( - 'href' => self::$currentIndex.'&token='.$this->token, - 'desc' => $this->l('Cancel') - ); - } - - /** - * Generate the Main page - */ - public function initMain() - { - // Block add/update a language - $packs_to_install = array(); - $packs_to_update = array(); - $token = Tools::getAdminToken('AdminLanguages'.(int)Tab::getIdFromClassName('AdminLanguages').(int)$this->context->employee->id); - $file_name = $this->link_lang_pack.'?version='._PS_VERSION_; - $array_stream_context = @stream_context_create(array('http' => array('method' => 'GET', 'timeout' => 8))); - if ($lang_packs = Tools::file_get_contents($file_name, false, $array_stream_context)) - // Notice : for php < 5.2 compatibility, Tools::jsonDecode. The second parameter to true will set us - if ($lang_packs != '' && $lang_packs = Tools::jsonDecode($lang_packs, true)) - foreach ($lang_packs as $key => $lang_pack) - { - if (!Language::isInstalled($lang_pack['iso_code'])) - $packs_to_install[$key] = $lang_pack; - else - $packs_to_update[$key] = $lang_pack; - } - - $this->tpl_view_vars = array( - 'theme_default' => self::DEFAULT_THEME_NAME, - 'theme_lang_dir' =>_THEME_LANG_DIR_, - 'token' => $this->token, - 'languages' => $this->languages, - 'translations_type' => $this->translations_informations, - 'packs_to_install' => $packs_to_install, - 'packs_to_update' => $packs_to_update, - 'url_submit' => self::$currentIndex.'&token='.$this->token, - 'themes' => $this->themes, - 'id_theme_current' => $this->context->shop->id_theme, - 'url_create_language' => 'index.php?controller=AdminLanguages&addlang&token='.$token, - ); - - $this->toolbar_scroll = false; - $this->base_tpl_view = 'main.tpl'; - - $this->content .= $this->renderKpis(); - $this->content .= parent::renderView(); - - return $this->content; - } - - /** - * This method merge each arrays of modules translation in the array of modules translations - */ - protected function getModuleTranslations() - { - global $_MODULE; - $name_var = $this->translations_informations[$this->type_selected]['var']; - - if (!isset($_MODULE) && !isset($GLOBALS[$name_var])) - $GLOBALS[$name_var] = array(); - elseif (isset($_MODULE)) - if (is_array($GLOBALS[$name_var]) && is_array($_MODULE)) - $GLOBALS[$name_var] = array_merge($GLOBALS[$name_var], $_MODULE); - else - $GLOBALS[$name_var] = $_MODULE; - } - - /** - * This method is only used by AdminTranslations::submitCopyLang(). - * - * It try to create folder in new theme. - * - * When a translation file is copied for a module, its translation key is wrong. - * We have to change the translation key and rewrite the file. - * - * @param string $dest file name - * @return bool - */ - protected function checkDirAndCreate($dest) - { - $bool = true; - - // To get only folder path - $path = dirname($dest); - - // If folder wasn't already added - // Do not use Tools::file_exists_cache because it changes over time! - if (!file_exists($path)) - if (!mkdir($path, 0777, true)) - { - $bool &= false; - $this->errors[] = sprintf($this->l('Cannot create the folder "%s". Please check your directory writing permissions.'), $path); - } - - return $bool; - } - - /** - * Read the Post var and write the translation file. - * This method overwrites the old translation file. - * - * @param bool $override_file Set true if this file is a override - * - * @throws PrestaShopException - */ - protected function writeTranslationFile($override_file = false) - { - $type = Tools::toCamelCase($this->type_selected, true); - - if (isset($this->translations_informations[$this->type_selected])) - $translation_informations = $this->translations_informations[$this->type_selected]; - else - return; - - if ($override_file) - $file_path = $translation_informations['override']['dir'].$translation_informations['override']['file']; - else - $file_path = $translation_informations['dir'].$translation_informations['file']; - - if ($file_path && !file_exists($file_path)) - { - if (!file_exists(dirname($file_path)) && !mkdir(dirname($file_path), 0777, true)) - throw new PrestaShopException(sprintf(Tools::displayError('Directory "%s" cannot be created'), dirname($file_path))); - elseif (!touch($file_path)) - throw new PrestaShopException(sprintf(Tools::displayError('File "%s" cannot be created'), $file_path)); - } - - $thm_name = str_replace('.', '', Tools::getValue('theme')); - $kpi_key = substr(strtoupper($thm_name.'_'.Tools::getValue('lang')), 0, 16); - - if ($fd = fopen($file_path, 'w')) - { - // Get value of button save and stay - $save_and_stay = Tools::isSubmit('submitTranslations'.$type.'AndStay'); - - // Get language - $lang = strtolower(Tools::getValue('lang')); - - // Unset all POST which are not translations - unset( - $_POST['submitTranslations'.$type], - $_POST['submitTranslations'.$type.'AndStay'], - $_POST['lang'], - $_POST['token'], - $_POST['theme'], - $_POST['type'] - ); - - // Get all POST which aren't empty - $to_insert = array(); - foreach ($_POST as $key => $value) - if (!empty($value)) - $to_insert[$key] = $value; - - ConfigurationKPI::updateValue('FRONTOFFICE_TRANSLATIONS_EXPIRE', time()); - ConfigurationKPI::updateValue('TRANSLATE_TOTAL_'.$kpi_key, count($_POST)); - ConfigurationKPI::updateValue('TRANSLATE_DONE_'.$kpi_key, count($to_insert)); - - // translations array is ordered by key (easy merge) - ksort($to_insert); - $tab = $translation_informations['var']; - fwrite($fd, "<?php\n\nglobal \$".$tab.";\n\$".$tab." = array();\n"); - foreach ($to_insert as $key => $value) - fwrite($fd, '$'.$tab.'[\''.pSQL($key, true).'\'] = \''.pSQL($value, true).'\';'."\n"); - fwrite($fd, "\n?>"); - fclose($fd); - - // Redirect - if ($save_and_stay) - $this->redirect(true); - else - $this->redirect(); - } - else - throw new PrestaShopException(sprintf(Tools::displayError('Cannot write this file: "%s"'), $file_path)); - } - - public function submitCopyLang() - { - if (!($from_lang = Tools::getValue('fromLang')) || !($to_lang = Tools::getValue('toLang'))) - $this->errors[] = $this->l('You must select two languages in order to copy data from one to another.'); - elseif (!($from_theme = Tools::getValue('fromTheme')) || !($to_theme = Tools::getValue('toTheme'))) - $this->errors[] = $this->l('You must select two themes in order to copy data from one to another.'); - elseif (!Language::copyLanguageData(Language::getIdByIso($from_lang), Language::getIdByIso($to_lang))) - $this->errors[] = $this->l('An error occurred while copying data.'); - elseif ($from_lang == $to_lang && $from_theme == $to_theme) - $this->errors[] = $this->l('There is nothing to copy (same language and theme).'); - else - { - $theme_exists = array('from_theme' => false, 'to_theme' => false); - foreach ($this->themes as $theme) - { - if ($theme->directory == $from_theme) - $theme_exists['from_theme'] = true; - if ($theme->directory == $to_theme) - $theme_exists['to_theme'] = true; - } - if ($theme_exists['from_theme'] == false || $theme_exists['to_theme'] == false) - $this->errors[] = $this->l('Theme(s) not found'); - } - if (count($this->errors)) - return; - - $bool = true; - $items = Language::getFilesList($from_lang, $from_theme, $to_lang, $to_theme, false, false, true); - foreach ($items as $source => $dest) - { - if (!$this->checkDirAndCreate($dest)) - $this->errors[] = sprintf($this->l('Impossible to create the directory "%s".'), $dest); - elseif (!copy($source, $dest)) - $this->errors[] = sprintf($this->l('Impossible to copy "%s" to "%s".'), $source, $dest); - elseif (strpos($dest, 'modules') && basename($source) === $from_lang.'.php' && $bool !== false) - if (!$this->changeModulesKeyTranslation($dest, $from_theme, $to_theme)) - $this->errors[] = sprintf($this->l('Impossible to translate "$dest".'), $dest); - } - if (!count($this->errors)) - $this->redirect(false, 14); - $this->errors[] = $this->l('A part of the data has been copied but some of the language files could not be found.'); - } - - /** - * Change the key translation to according it to theme name. - * - * @param string $path - * @param string $theme_from - * @param string $theme_to - * @return bool - */ - public function changeModulesKeyTranslation($path, $theme_from, $theme_to) - { - $content = file_get_contents($path); - $arr_replace = array(); - $bool_flag = true; - if (preg_match_all('#\$_MODULE\[\'([^\']+)\'\]#Ui', $content, $matches)) - { - foreach ($matches[1] as $key => $value) - $arr_replace[$value] = str_replace($theme_from, $theme_to, $value); - $content = str_replace(array_keys($arr_replace), array_values($arr_replace), $content); - $bool_flag = (file_put_contents($path, $content) === false) ? false : true; - } - return $bool_flag; - } - - public function exportTabs() - { - // Get name tabs by iso code - $tabs = Tab::getTabs($this->lang_selected->id); - - // Get name of the default tabs - $tabs_default_lang = Tab::getTabs(1); - - $tabs_default = array(); - foreach ($tabs_default_lang as $tab) - $tabs_default[$tab['class_name']] = pSQL($tab['name']); - - // Create content - $content = "<?php\n\n\$_TABS = array();"; - if (!empty($tabs)) - foreach ($tabs as $tab) - { - /** - * We don't export tab translations that are identical to the default - * tab translations to avoid a problem that would occur in the followin scenario: - * - * 1) install PrestaShop in, say, Spanish => tabs are by default in Spanish - * 2) create a new language, say, Klingon => tabs are populated using the default, Spanish, tabs - * 3) export the Klingon language pack - * - * => Since you have not yet translated the tabs into Klingon, - * without the condition below, you would get tabs exported, but in Spanish. - * This would lead to a Klingon pack actually containing Spanish. - * - * This has caused many issues in the past, so, as a precaution, tabs from - * the default language are not exported. - * - */ - if ($tabs_default[$tab['class_name']] != pSQL($tab['name'])) - $content .= "\n\$_TABS['".$tab['class_name']."'] = '".pSQL($tab['name'])."';"; - } - $content .= "\n\nreturn \$_TABS;"; - - $dir = _PS_TRANSLATIONS_DIR_.$this->lang_selected->iso_code.DIRECTORY_SEPARATOR; - $path = $dir.'tabs.php'; - - // Check if tabs.php exists for the selected Iso Code - if (!Tools::file_exists_cache($dir)) - if (!mkdir($dir, 0777, true)) - throw new PrestaShopException('The file '.$dir.' cannot be created.'); - if (!file_put_contents($path, $content)) - throw new PrestaShopException('File "'.$path.'" does not exist and cannot be created in '.$dir); - if (!is_writable($path)) - $this->displayWarning(sprintf(Tools::displayError('This file must be writable: %s'), $path)); - } - - public function submitExportLang() - { - if ($this->lang_selected->iso_code && $this->theme_selected) - { - $this->exportTabs(); - $items = array_flip(Language::getFilesList($this->lang_selected->iso_code, $this->theme_selected, false, false, false, false, true)); - $file_name = _PS_TRANSLATIONS_DIR_.'/export/'.$this->lang_selected->iso_code.'.gzip'; - require_once(_PS_TOOL_DIR_.'tar/Archive_Tar.php'); - $gz = new Archive_Tar($file_name, true); - if ($gz->createModify($items, null, _PS_ROOT_DIR_)) - { - ob_start(); - header('Pragma: public'); - header('Expires: 0'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Cache-Control: public'); - header('Content-Description: File Transfer'); - header('Content-type: application/octet-stream'); - header('Content-Disposition: attachment; filename="'.$this->lang_selected->iso_code.'.gzip'.'"'); - header('Content-Transfer-Encoding: binary'); - ob_end_flush(); - readfile($file_name); - @unlink($file_name); - exit; - } - $this->errors[] = Tools::displayError('An error occurred while creating archive.'); - } - $this->errors[] = Tools::displayError('Please select a language and a theme.'); - } - - public static function checkAndAddMailsFiles($iso_code, $files_list) - { - if (Language::getIdByIso('en')) - $default_language = 'en'; - else - $default_language = Language::getIsoById((int)Configuration::get('PS_LANG_DEFAULT')); - - if (!$default_language || !Validate::isLanguageIsoCode($default_language)) - return false; - - // 1 - Scan mails files - $mails = array(); - if (Tools::file_exists_cache(_PS_MAIL_DIR_.$default_language.'/')) - $mails = scandir(_PS_MAIL_DIR_.$default_language.'/'); - - $mails_new_lang = array(); - - // Get all email files - foreach ($files_list as $file) - { - if (preg_match('#^mails\/([a-z0-9]+)\/#Ui', $file['filename'], $matches)) - { - $slash_pos = strrpos($file['filename'], '/'); - $mails_new_lang[] = substr($file['filename'], -(strlen($file['filename']) - $slash_pos - 1)); - } - } - - // Get the difference - $arr_mails_needed = array_diff($mails, $mails_new_lang); - - // Add mails files - foreach ($arr_mails_needed as $mail_to_add) - if (!in_array($mail_to_add, self::$ignore_folder)) - @copy(_PS_MAIL_DIR_.$default_language.'/'.$mail_to_add, _PS_MAIL_DIR_.$iso_code.'/'.$mail_to_add); - - // 2 - Scan modules files - $modules = scandir(_PS_MODULE_DIR_); - - $module_mail_en = array(); - $module_mail_iso_code = array(); - - foreach ($modules as $module) - { - if (!in_array($module, self::$ignore_folder) && Tools::file_exists_cache(_PS_MODULE_DIR_.$module.'/mails/'.$default_language.'/')) - { - $arr_files = scandir(_PS_MODULE_DIR_.$module.'/mails/'.$default_language.'/'); - - foreach ($arr_files as $file) - { - if (!in_array($file, self::$ignore_folder)) - { - if (Tools::file_exists_cache(_PS_MODULE_DIR_.$module.'/mails/'.$default_language.'/'.$file)) - $module_mail_en[] = _PS_MODULE_DIR_.$module.'/mails/ISO_CODE/'.$file; - - if (Tools::file_exists_cache(_PS_MODULE_DIR_.$module.'/mails/'.$iso_code.'/'.$file)) - $module_mail_iso_code[] = _PS_MODULE_DIR_.$module.'/mails/ISO_CODE/'.$file; - } - } - } - } - - // Get the difference in this modules - $arr_modules_mails_needed = array_diff($module_mail_en, $module_mail_iso_code); - - // Add mails files for this modules - foreach ($arr_modules_mails_needed as $file) - { - $file_en = str_replace('ISO_CODE', $default_language, $file); - $file_iso_code = str_replace('ISO_CODE', $iso_code, $file); - $dir_iso_code = substr($file_iso_code, 0, -(strlen($file_iso_code) - strrpos($file_iso_code, '/') - 1)); - - if (!file_exists($dir_iso_code)) - { - mkdir($dir_iso_code); - file_put_contents($dir_iso_code.'/index.php', Tools::getDefaultIndexContent()); - } - - if (Tools::file_exists_cache($file_en)) - copy($file_en, $file_iso_code); - } - } - - /** - * Move theme translations in selected themes - * - * @param array $files - * @param array $themes_selected - */ - public function checkAndAddThemesFiles($files, $themes_selected) - { - foreach ($files as $file) - { - // Check if file is a file theme - if (preg_match('#^themes\/([a-z0-9]+)\/lang\/#Ui', $file['filename'], $matches)) - { - $slash_pos = strrpos($file['filename'], '/'); - $name_file = substr($file['filename'], -(strlen($file['filename']) - $slash_pos - 1)); - $name_default_theme = $matches[1]; - $deleted_old_theme = false; - - // Get the old file theme - if (file_exists(_PS_THEME_DIR_.'lang/'.$name_file)) - $theme_file_old = _PS_THEME_DIR_.'lang/'.$name_file; - else - { - $deleted_old_theme = true; - $theme_file_old = str_replace(self::DEFAULT_THEME_NAME, $name_default_theme, _PS_THEME_DIR_.'lang/'.$name_file); - } - - // Move the old file theme in the new folder - foreach ($themes_selected as $theme_name) - if (file_exists($theme_file_old)) - copy($theme_file_old, str_replace($name_default_theme, $theme_name, $theme_file_old)); - - if ($deleted_old_theme) - @unlink($theme_file_old); - } - } - } - - /** - * Add new translations tabs by code ISO - * - * @param array $iso_code - * @param array $files - * - * @return array - */ - public static function addNewTabs($iso_code, $files) - { - $errors = array(); - - foreach ($files as $file) - { - // Check if file is a file theme - if (preg_match('#^translations\/'.$iso_code.'\/tabs.php#Ui', $file['filename'], $matches) && Validate::isLanguageIsoCode($iso_code)) - { - // Include array width new translations tabs - $_TABS = array(); - clearstatcache(); - if (file_exists(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$file['filename'])) - include_once(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$file['filename']); - - if (is_array($_TABS) && count($_TABS)) - { - foreach ($_TABS as $class_name => $translations) - { - // Get instance of this tab by class name - $tab = Tab::getInstanceFromClassName($class_name); - //Check if class name exists - if (isset($tab->class_name) && !empty($tab->class_name)) - { - $id_lang = Language::getIdByIso($iso_code, true); - $tab->name[(int)$id_lang] = $translations; - - // Do not crash at intall - if (!isset($tab->name[Configuration::get('PS_LANG_DEFAULT')])) - $tab->name[(int)Configuration::get('PS_LANG_DEFAULT')] = $translations; - - if (!Validate::isGenericName($tab->name[(int)$id_lang])) - $errors[] = sprintf(Tools::displayError('Tab "%s" is not valid'), $tab->name[(int)$id_lang]); - else - $tab->update(); - } - } - } - } - } - - return $errors; - } - - public static function checkTranslationFile($content) - { - $lines = array_map('trim', explode("\n", $content)); - $global = false; - foreach ($lines as $line) - { - // PHP tags - if (in_array($line, array('<?php', '?>', ''))) - continue; - - // Global variable declaration - if (!$global && preg_match('/^global\s+\$([a-z0-9-_]+)\s*;$/i', $line, $matches)) - { - $global = $matches[1]; - continue; - } - // Global variable initialization - if ($global != false && preg_match('/^\$'.preg_quote($global, '/').'\s*=\s*array\(\s*\)\s*;$/i', $line)) - continue; - - // Global variable initialization without declaration - if (!$global && preg_match('/^\$([a-z0-9-_]+)\s*=\s*array\(\s*\)\s*;$/i', $line, $matches)) - { - $global = $matches[1]; - continue; - } - - // Assignation - if (preg_match('/^\$'.preg_quote($global, '/').'\[\''._PS_TRANS_PATTERN_.'\'\]\s*=\s*\''._PS_TRANS_PATTERN_.'\'\s*;$/i', $line)) - continue; - - // Sometimes the global variable is returned... - if (preg_match('/^return\s+\$'.preg_quote($global, '/').'\s*;$/i', $line, $matches)) - continue; - return false; - } - return true; - } - - public function submitImportLang() - { - if (!isset($_FILES['file']['tmp_name']) || !$_FILES['file']['tmp_name']) - $this->errors[] = Tools::displayError('No file has been selected.'); - else - { - require_once(_PS_TOOL_DIR_.'tar/Archive_Tar.php'); - $gz = new Archive_Tar($_FILES['file']['tmp_name'], true); - $filename = $_FILES['file']['name']; - $iso_code = str_replace(array('.tar.gz', '.gzip'), '', $filename); - if (Validate::isLangIsoCode($iso_code)) - { - $themes_selected = Tools::getValue('theme', array(self::DEFAULT_THEME_NAME)); - $files_list = AdminTranslationsController::filterTranslationFiles($gz->listContent()); - $files_paths = AdminTranslationsController::filesListToPaths($files_list); - - $uniqid = uniqid(); - $sandbox = _PS_CACHE_DIR_.'sandbox'.DIRECTORY_SEPARATOR.$uniqid.DIRECTORY_SEPARATOR; - if ($gz->extractList($files_paths, $sandbox)) - { - foreach ($files_list as $file2check) - { - //don't validate index.php, will be overwrite when extract in translation directory - if (pathinfo($file2check['filename'], PATHINFO_BASENAME) == 'index.php') - continue; - - if (preg_match('@^[0-9a-z-_/\\\\]+\.php$@i', $file2check['filename'])) - { - if (!@filemtime($sandbox.$file2check['filename']) || !AdminTranslationsController::checkTranslationFile(file_get_contents($sandbox.$file2check['filename']))) - $this->errors[] = sprintf(Tools::displayError('Validation failed for: %s'), $file2check['filename']); - } - elseif (!preg_match('@mails[0-9a-z-_/\\\\]+\.(html|tpl|txt)$@i', $file2check['filename'])) - $this->errors[] = sprintf(Tools::displayError('Unidentified file found: %s'), $file2check['filename']); - } - Tools::deleteDirectory($sandbox, true); - } - - $i = 0; - $tmp_array = array(); - foreach ($files_paths as $files_path) - { - $path = dirname($files_path); - if (is_dir(_PS_TRANSLATIONS_DIR_.'../'.$path) && !is_writable(_PS_TRANSLATIONS_DIR_.'../'.$path) && !in_array($path, $tmp_array)) - { - $this->errors[] = (!$i++? Tools::displayError('The archive cannot be extracted.').' ' : '').Tools::displayError('The server does not have permissions for writing.').' '.sprintf(Tools::displayError('Please check rights for %s'), $path); - $tmp_array[] = $path; - } - - } - - if (count($this->errors)) - return false; - - if ($error = $gz->extractList($files_paths, _PS_TRANSLATIONS_DIR_.'../')) - { - if (is_object($error) && !empty($error->message)) - $this->errors[] = Tools::displayError('The archive cannot be extracted.'). ' '.$error->message; - else - { - foreach ($files_list as $file2check) - if (pathinfo($file2check['filename'], PATHINFO_BASENAME) == 'index.php' && file_put_contents(_PS_TRANSLATIONS_DIR_.'../'.$file2check['filename'], Tools::getDefaultIndexContent())) - continue; - - // Clear smarty modules cache - Tools::clearCache(); - - if (Validate::isLanguageFileName($filename)) - { - if (!Language::checkAndAddLanguage($iso_code)) - $conf = 20; - else - { - // Reset cache - Language::loadLanguages(); - - AdminTranslationsController::checkAndAddMailsFiles($iso_code, $files_list); - $this->checkAndAddThemesFiles($files_list, $themes_selected); - $tab_errors = AdminTranslationsController::addNewTabs($iso_code, $files_list); - - if (count($tab_errors)) - { - $this->errors += $tab_errors; - return false; - } - } - } - $this->redirect(false, (isset($conf) ? $conf : '15')); - } - } - $this->errors[] = Tools::displayError('The archive cannot be extracted.'); - } - else - $this->errors[] = sprintf(Tools::displayError('ISO CODE invalid "%1$s" for the following file: "%2$s"'), $iso_code, $filename); - } - } - - /** - * Filter the translation files contained in a .gzip pack - * and return only the ones that we want. - * - * Right now the function only needs to check that - * the modules for which we want to add translations - * are present on the shop (installed or not). - * - * @param array $list Is the output of Archive_Tar::listContent() - * - * @return array - */ - public static function filterTranslationFiles($list) - { - $kept = array(); - foreach ($list as $file) - { - if ('index.php' == basename($file['filename'])) - continue; - if (preg_match('#^modules/([^/]+)/#', $file['filename'], $m)) - { - if (is_dir(_PS_MODULE_DIR_.$m[1])) - $kept[] = $file; - } - else - $kept[] = $file; - } - return $kept; - } - - /** - * Turn the list returned by - * AdminTranslationsController::filterTranslationFiles() - * into a list of paths that can be passed to - * Archive_Tar::extractList() - * - * @param array $list - * - * @return array - */ - public static function filesListToPaths($list) - { - $paths = array(); - foreach ($list as $item) - $paths[] = $item['filename']; - return $paths; - } - - public function submitAddLang() - { - $arr_import_lang = explode('|', Tools::getValue('params_import_language')); /* 0 = Language ISO code, 1 = PS version */ - if (Validate::isLangIsoCode($arr_import_lang[0])) - { - $array_stream_context = @stream_context_create(array('http' => array('method' => 'GET', 'timeout' => 10))); - $content = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/gzip/'.$arr_import_lang[1].'/'.Tools::strtolower($arr_import_lang[0]).'.gzip', false, $array_stream_context); - if ($content) - { - $file = _PS_TRANSLATIONS_DIR_.$arr_import_lang[0].'.gzip'; - if ((bool)@file_put_contents($file, $content)) - { - require_once(_PS_TOOL_DIR_.'/tar/Archive_Tar.php'); - $gz = new Archive_Tar($file, true); - if (_PS_MODE_DEV_) - $gz->setErrorHandling(PEAR_ERROR_TRIGGER, E_USER_WARNING); - $files_list = AdminTranslationsController::filterTranslationFiles($gz->listContent()); - - if ($error = $gz->extractList(AdminTranslationsController::filesListToPaths($files_list), _PS_TRANSLATIONS_DIR_.'../')) - { - if (is_object($error) && !empty($error->message)) - $this->errors[] = Tools::displayError('The archive cannot be extracted.'). ' '.$error->message; - else - { - if (!Language::checkAndAddLanguage($arr_import_lang[0])) - $conf = 20; - else - { - // Reset cache - Language::loadLanguages(); - // Clear smarty modules cache - Tools::clearCache(); - - AdminTranslationsController::checkAndAddMailsFiles($arr_import_lang[0], $files_list); - if ($tab_errors = AdminTranslationsController::addNewTabs($arr_import_lang[0], $files_list)) - $this->errors += $tab_errors; - } - if (!unlink($file)) - $this->errors[] = sprintf(Tools::displayError('Cannot delete the archive %s.'), $file); - - $this->redirect(false, (isset($conf) ? $conf : '15')); - } - } - else - { - $this->errors[] = sprintf(Tools::displayError('Cannot decompress the translation file for the following language: %s'), $arr_import_lang[0]); - $checks= array(); - foreach ($files_list as $f) - if (isset($f['filename'])) - { - if (is_file(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$f['filename']) && !is_writable(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$f['filename'])) - $checks[] = dirname($f['filename']); - elseif (is_dir(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$f['filename']) && !is_writable(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.dirname($f['filename']))) - $checks[] = dirname($f['filename']); - } - - $checks = array_unique($checks); - foreach ($checks as $check) - $this->errors[] = sprintf(Tools::displayError('Please check rights for folder and files in %s'), $check); - if (!unlink($file)) - $this->errors[] = sprintf(Tools::displayError('Cannot delete the archive %s.'), $file); - } - } - else - $this->errors[] = Tools::displayError('The server does not have permissions for writing.').' '.sprintf(Tools::displayError('Please check rights for %s'), dirname($file)); - } - else - $this->errors[] = Tools::displayError('Language not found.'); - } - else - $this->errors[] = Tools::displayError('Invalid parameter.'); - } - - /** - * This method check each file (tpl or php file), get its sentences to translate, - * compare with posted values and write in iso code translation file. - * - * @param string $file_name - * @param array $files - * @param string $theme_name - * @param string $module_name - * @param string|bool $dir - * - * @throws PrestaShopException - */ - protected function findAndWriteTranslationsIntoFile($file_name, $files, $theme_name, $module_name, $dir = false) - { - // These static vars allow to use file to write just one time. - static $cache_file = array(); - static $str_write = ''; - static $array_check_duplicate = array(); - - // Set file_name in static var, this allow to open and wright the file just one time - if (!isset($cache_file[$theme_name.'-'.$file_name])) - { - $str_write = ''; - $cache_file[$theme_name.'-'.$file_name] = true; - if (!Tools::file_exists_cache(dirname($file_name))) - mkdir(dirname($file_name), 0777, true); - if (!Tools::file_exists_cache($file_name)) - file_put_contents($file_name, ''); - if (!is_writable($file_name)) - throw new PrestaShopException(sprintf( - Tools::displayError('Cannot write to the theme\'s language file (%s). Please check writing permissions.'), - $file_name - )); - - // this string is initialized one time for a file - $str_write .= "<?php\n\nglobal \$_MODULE;\n\$_MODULE = array();\n"; - $array_check_duplicate = array(); - } - - foreach ($files as $file) - { - if (preg_match('/^(.*)\.(tpl|php)$/', $file) && Tools::file_exists_cache($dir.$file) && !in_array($file, self::$ignore_folder)) - { - // Get content for this file - $content = file_get_contents($dir.$file); - - // Get file type - $type_file = substr($file, -4) == '.tpl' ? 'tpl' : 'php'; - - // Parse this content - $matches = $this->userParseFile($content, $this->type_selected, $type_file, $module_name); - - // Write each translation on its module file - $template_name = substr(basename($file), 0, -4); - - foreach ($matches as $key) - { - if ($theme_name) - { - $post_key = md5(strtolower($module_name).'_'.strtolower($theme_name).'_'.strtolower($template_name).'_'.md5($key)); - $pattern = '\'<{'.strtolower($module_name).'}'.strtolower($theme_name).'>'.strtolower($template_name).'_'.md5($key).'\''; - } - else - { - $post_key = md5(strtolower($module_name).'_'.strtolower($template_name).'_'.md5($key)); - $pattern = '\'<{'.strtolower($module_name).'}prestashop>'.strtolower($template_name).'_'.md5($key).'\''; - } - - if (array_key_exists($post_key, $_POST) && !in_array($pattern, $array_check_duplicate)) - { - if ($_POST[$post_key] == '') - continue; - $array_check_duplicate[] = $pattern; - $str_write .= '$_MODULE['.$pattern.'] = \''.pSQL(str_replace(array("\r\n", "\r", "\n"), ' ', $_POST[$post_key])).'\';'."\n"; - $this->total_expression++; - } - } - } - } - - if (isset($cache_file[$theme_name.'-'.$file_name]) && $str_write != "<?php\n\nglobal \$_MODULE;\n\$_MODULE = array();\n") - file_put_contents($file_name, $str_write); - } - - /** - * Clear the list of module file by type (file or directory) - * - * @param $files : list of files - * @param string $type_clear (file|directory) - * @param string $path - * @return array : list of a good files - */ - public function clearModuleFiles($files, $type_clear = 'file', $path = '') - { - // List of directory which not must be parsed - $arr_exclude = array('img', 'js', 'mails','override'); - - // List of good extention files - $arr_good_ext = array('.tpl', '.php'); - - foreach ($files as $key => $file) - { - if ($file{0} === '.' || in_array(substr($file, 0, strrpos($file, '.')), $this->all_iso_lang)) - unset($files[$key]); - elseif ($type_clear === 'file' && !in_array(substr($file, strrpos($file, '.')), $arr_good_ext)) - unset($files[$key]); - elseif ($type_clear === 'directory' && (!is_dir($path.$file) || in_array($file, $arr_exclude))) - unset($files[$key]); - } - - return $files; - } - - /** - * This method get translation for each files of a module, - * compare with global $_MODULES array and fill AdminTranslations::modules_translations array - * With key as English sentences and values as their iso code translations. - * - * @param array $files - * @param string $theme_name - * @param string $module_name - * @param string|bool $dir - */ - protected function findAndFillTranslations($files, $theme_name, $module_name, $dir = false) - { - $name_var = $this->translations_informations[$this->type_selected]['var']; - - // added for compatibility - $GLOBALS[$name_var] = array_change_key_case($GLOBALS[$name_var]); - - // Thank to this var similar keys are not duplicate - // in AndminTranslation::modules_translations array - // see below - $array_check_duplicate = array(); - foreach ($files as $file) - { - if ((preg_match('/^(.*).tpl$/', $file) || preg_match('/^(.*).php$/', $file)) && Tools::file_exists_cache($file_path = $dir.$file)) - { - // Get content for this file - $content = file_get_contents($file_path); - - // Module files can now be ignored by adding this string in a file - if (strpos($content, 'IGNORE_THIS_FILE_FOR_TRANSLATION') !== false) - continue; - - // Get file type - $type_file = substr($file, -4) == '.tpl' ? 'tpl' : 'php'; - - // Parse this content - $matches = $this->userParseFile($content, $this->type_selected, $type_file, $module_name); - - // Write each translation on its module file - $template_name = substr(basename($file), 0, -4); - - foreach ($matches as $key) - { - $md5_key = md5($key); - $module_key = '<{'.Tools::strtolower($module_name).'}'.strtolower($theme_name).'>'.Tools::strtolower($template_name).'_'.$md5_key; - $default_key = '<{'.Tools::strtolower($module_name).'}prestashop>'.Tools::strtolower($template_name).'_'.$md5_key; - // to avoid duplicate entry - if (!in_array($module_key, $array_check_duplicate)) - { - $array_check_duplicate[] = $module_key; - if (!isset($this->modules_translations[$theme_name][$module_name][$template_name][$key]['trad'])) - $this->total_expression++; - if ($theme_name && array_key_exists($module_key, $GLOBALS[$name_var])) - $this->modules_translations[$theme_name][$module_name][$template_name][$key]['trad'] = html_entity_decode($GLOBALS[$name_var][$module_key], ENT_COMPAT, 'UTF-8'); - elseif (array_key_exists($default_key, $GLOBALS[$name_var])) - $this->modules_translations[$theme_name][$module_name][$template_name][$key]['trad'] = html_entity_decode($GLOBALS[$name_var][$default_key], ENT_COMPAT, 'UTF-8'); - else - { - $this->modules_translations[$theme_name][$module_name][$template_name][$key]['trad'] = ''; - $this->missing_translations++; - } - $this->modules_translations[$theme_name][$module_name][$template_name][$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); - } - } - } - } - } - - /** - * Get list of files which must be parsed by directory and by type of translations - * - * @return array : list of files by directory - */ - public function getFileToParseByTypeTranslation() - { - $directories = array(); - - switch ($this->type_selected) - { - case 'front': - $directories['tpl'] = array(_PS_ALL_THEMES_DIR_ => scandir(_PS_ALL_THEMES_DIR_)); - self::$ignore_folder[] = 'modules'; - $directories['tpl'] = array_merge($directories['tpl'], $this->listFiles(_PS_THEME_SELECTED_DIR_)); - if (isset($directories['tpl'][_PS_THEME_SELECTED_DIR_.'pdf/'])) - unset($directories['tpl'][_PS_THEME_SELECTED_DIR_.'pdf/']); - - if (Tools::file_exists_cache(_PS_THEME_OVERRIDE_DIR_)) - $directories['tpl'] = array_merge($directories['tpl'], $this->listFiles(_PS_THEME_OVERRIDE_DIR_)); - - break; - - case 'back': - $directories = array( - 'php' => array( - _PS_ADMIN_CONTROLLER_DIR_ => scandir(_PS_ADMIN_CONTROLLER_DIR_), - _PS_OVERRIDE_DIR_.'controllers/admin/' => scandir(_PS_OVERRIDE_DIR_.'controllers/admin/'), - _PS_CLASS_DIR_.'helper/' => scandir(_PS_CLASS_DIR_.'helper/'), - _PS_CLASS_DIR_.'controller/' => array('AdminController.php'), - _PS_CLASS_DIR_ => array('PaymentModule.php') - ), - 'tpl' => $this->listFiles(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes/'), - 'specific' => array( - _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR => array( - 'header.inc.php', - 'footer.inc.php', - 'index.php', - 'functions.php' - ) - ) - ); - - // For translate the template which are overridden - if (file_exists(_PS_OVERRIDE_DIR_.'controllers'.DIRECTORY_SEPARATOR.'admin'.DIRECTORY_SEPARATOR.'templates')) - $directories['tpl'] = array_merge($directories['tpl'], $this->listFiles(_PS_OVERRIDE_DIR_.'controllers'.DIRECTORY_SEPARATOR.'admin'.DIRECTORY_SEPARATOR.'templates')); - - break; - - case 'errors': - $directories['php'] = array( - _PS_ROOT_DIR_ => scandir(_PS_ROOT_DIR_), - _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR => scandir(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR), - _PS_FRONT_CONTROLLER_DIR_ => scandir(_PS_FRONT_CONTROLLER_DIR_), - _PS_ADMIN_CONTROLLER_DIR_ => scandir(_PS_ADMIN_CONTROLLER_DIR_), - _PS_OVERRIDE_DIR_.'controllers/front/' => scandir(_PS_OVERRIDE_DIR_.'controllers/front/'), - _PS_OVERRIDE_DIR_.'controllers/admin/' => scandir(_PS_OVERRIDE_DIR_.'controllers/admin/') - ); - - // Get all files for folders classes/ and override/classes/ recursively - $directories['php'] = array_merge($directories['php'], $this->listFiles(_PS_CLASS_DIR_, array(), 'php')); - $directories['php'] = array_merge($directories['php'], $this->listFiles(_PS_OVERRIDE_DIR_.'classes/', array(), 'php')); - break; - - case 'fields': - $directories['php'] = $this->listFiles(_PS_CLASS_DIR_, array(), 'php'); - break; - - case 'pdf': - $tpl_theme = Tools::file_exists_cache(_PS_THEME_SELECTED_DIR_.'pdf/') ? scandir(_PS_THEME_SELECTED_DIR_.'pdf/') : array(); - $directories = array( - 'php' => array( - _PS_CLASS_DIR_.'pdf/' => scandir(_PS_CLASS_DIR_.'pdf/'), - _PS_OVERRIDE_DIR_.'classes/pdf/' => scandir(_PS_OVERRIDE_DIR_.'classes/pdf/') - ), - 'tpl' => array( - _PS_PDF_DIR_ => scandir(_PS_PDF_DIR_), - _PS_THEME_SELECTED_DIR_.'pdf/' => $tpl_theme - ) - ); - $directories['tpl'] = array_merge($directories['tpl'], $this->getModulesHasPDF()); - $directories['php'] = array_merge($directories['php'], $this->getModulesHasPDF(true)); - break; - - case 'mails': - $directories['php'] = array( - _PS_FRONT_CONTROLLER_DIR_ => scandir(_PS_FRONT_CONTROLLER_DIR_), - _PS_ADMIN_CONTROLLER_DIR_ => scandir(_PS_ADMIN_CONTROLLER_DIR_), - _PS_OVERRIDE_DIR_.'controllers/front/' => scandir(_PS_OVERRIDE_DIR_.'controllers/front/'), - _PS_OVERRIDE_DIR_.'controllers/admin/' => scandir(_PS_OVERRIDE_DIR_.'controllers/admin/'), - _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR => scandir(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR), - _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'tabs/' => scandir(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'/tabs') - ); - - // Get all files for folders classes/ and override/classes/ recursively - $directories['php'] = array_merge($directories['php'], $this->listFiles(_PS_CLASS_DIR_, array(), 'php')); - $directories['php'] = array_merge($directories['php'], $this->listFiles(_PS_OVERRIDE_DIR_.'classes/', array(), 'php')); - $directories['php'] = array_merge($directories['php'], $this->getModulesHasMails()); - break; - - } - - return $directories; - } - - /** - * This method parse a file by type of translation and type file - * - * @param $content - * @param $type_translation : front, back, errors, modules... - * @param string|bool $type_file : (tpl|php) - * @param string $module_name : name of the module - * @return array - */ - protected function userParseFile($content, $type_translation, $type_file = false, $module_name = '') - { - switch ($type_translation) - { - case 'front': - // Parsing file in Front office - $regex = '/\{l\s*s=([\'\"])'._PS_TRANS_PATTERN_.'\1(\s*sprintf=.*)?(\s*js=1)?\s*\}/U'; - break; - - case 'back': - // Parsing file in Back office - if ($type_file == 'php') - $regex = '/this->l\((\')'._PS_TRANS_PATTERN_.'\'[\)|\,]/U'; - elseif ($type_file == 'specific') - $regex = '/Translate::getAdminTranslation\((\')'._PS_TRANS_PATTERN_.'\'(?:,.*)*\)/U'; - else - $regex = '/\{l\s*s\s*=([\'\"])'._PS_TRANS_PATTERN_.'\1(\s*sprintf=.*)?(\s*js=1)?(\s*slashes=1)?.*\}/U'; - break; - - case 'errors': - // Parsing file for all errors syntax - $regex = '/Tools::displayError\((\')'._PS_TRANS_PATTERN_.'\'(,\s*(.+))?\)/U'; - break; - - case 'modules': - // Parsing modules file - if ($type_file == 'php') - $regex = '/->l\((\')'._PS_TRANS_PATTERN_.'\'(, ?\'(.+)\')?(, ?(.+))?\)/U'; - else - // In tpl file look for something that should contain mod='module_name' according to the documentation - $regex = '/\{l\s*s=([\'\"])'._PS_TRANS_PATTERN_.'\1.*\s+mod=\''.$module_name.'\'.*\}/U'; - break; - - case 'pdf': - // Parsing PDF file - if ($type_file == 'php') - $regex = '/HTMLTemplate.*::l\((\')'._PS_TRANS_PATTERN_.'\'[\)|\,]/U'; - else - $regex = '/\{l\s*s=([\'\"])'._PS_TRANS_PATTERN_.'\1(\s*sprintf=.*)?(\s*js=1)?(\s*pdf=\'true\')?\s*\}/U'; - break; - } - - if (!is_array($regex)) - $regex = array($regex); - - $strings = array(); - foreach ($regex as $regex_row) - { - $matches = array(); - $n = preg_match_all($regex_row, $content, $matches); - for ($i = 0; $i < $n; $i += 1) - { - $quote = $matches[1][$i]; - $string = $matches[2][$i]; - - if ($quote === '"') - { - // Escape single quotes because the core will do it when looking for the translation of this string - $string = str_replace('\'', '\\\'', $string); - // Unescape double quotes - $string = preg_replace('/\\\\+"/', '"', $string); - } - - $strings[] = $string; - } - } - - return array_unique($strings); - } - - /** - * Get all translations informations for all type of translations - * - * array( - * 'type' => array( - * 'name' => string : title for the translation type, - * 'var' => string : name of var for the translation file, - * 'dir' => string : dir of translation file - * 'file' => string : file name of translation file - * ) - * ) - */ - public function getTranslationsInformations() - { - $this->translations_informations = array( - 'front' => array( - 'name' => $this->l('Front office translations'), - 'var' => '_LANG', - 'dir' => defined('_PS_THEME_SELECTED_DIR_') ? _PS_THEME_SELECTED_DIR_.'lang/' : '', - 'file' => $this->lang_selected->iso_code.'.php' - ), - 'back' => array( - 'name' => $this->l('Back office translations'), - 'var' => '_LANGADM', - 'dir' => _PS_TRANSLATIONS_DIR_.$this->lang_selected->iso_code.'/', - 'file' => 'admin.php' - ), - 'errors' => array( - 'name' => $this->l('Error message translations'), - 'var' => '_ERRORS', - 'dir' => _PS_TRANSLATIONS_DIR_.$this->lang_selected->iso_code.'/', - 'file' => 'errors.php' - ), - 'fields' => array( - 'name' => $this->l('Field name translations'), - 'var' => '_FIELDS', - 'dir' => _PS_TRANSLATIONS_DIR_.$this->lang_selected->iso_code.'/', - 'file' => 'fields.php' - ), - 'modules' => array( - 'name' => $this->l('Installed modules translations'), - 'var' => '_MODULES', - 'dir' => _PS_MODULE_DIR_, - 'file' => '' - ), - 'pdf' => array( - 'name' => $this->l('PDF translations'), - 'var' => '_LANGPDF', - 'dir' => _PS_TRANSLATIONS_DIR_.$this->lang_selected->iso_code.'/', - 'file' => 'pdf.php' - ), - 'mails' => array( - 'name' => $this->l('Email templates translations'), - 'var' => '_LANGMAIL', - 'dir' => _PS_MAIL_DIR_.$this->lang_selected->iso_code.'/', - 'file' => 'lang.php' - ) - ); - - if (defined('_PS_THEME_SELECTED_DIR_')) - { - $this->translations_informations['modules']['override'] = array('dir' => _PS_THEME_SELECTED_DIR_.'modules/', 'file' => ''); - $this->translations_informations['pdf']['override'] = array('dir' => _PS_THEME_SELECTED_DIR_.'pdf/lang/', 'file' => $this->lang_selected->iso_code.'.php'); - $this->translations_informations['mails']['override'] = array('dir' => _PS_THEME_SELECTED_DIR_.'mails/'.$this->lang_selected->iso_code.'/', 'file' => 'lang.php'); - } - } - - /** - * Get all informations on : languages, theme and the translation type. - */ - public function getInformations() - { - // Get all Languages - $this->languages = Language::getLanguages(false); - - // Get all iso_code of languages - foreach ($this->languages as $language) - $this->all_iso_lang[] = $language['iso_code']; - - // Get all themes - $this->themes = Theme::getThemes(); - - // Get folder name of theme - if (($theme = Tools::getValue('theme')) && !is_array($theme)) - { - $theme_exists = $this->theme_exists($theme); - if (!$theme_exists) - throw new PrestaShopException(sprintf(Tools::displayError('Invalid theme "%s"'), Tools::safeOutput($theme))); - $this->theme_selected = Tools::safeOutput($theme); - } - - // Set the path of selected theme - if ($this->theme_selected) - define('_PS_THEME_SELECTED_DIR_', _PS_ROOT_DIR_.'/themes/'.$this->theme_selected.'/'); - else - define('_PS_THEME_SELECTED_DIR_', ''); - - // Get type of translation - if (($type = Tools::getValue('type')) && !is_array($type)) - $this->type_selected = strtolower(Tools::safeOutput($type)); - - // Get selected language - if (Tools::getValue('lang') || Tools::getValue('iso_code')) - { - $iso_code = Tools::getValue('lang') ? Tools::getValue('lang') : Tools::getValue('iso_code'); - - if (!Validate::isLangIsoCode($iso_code) || !in_array($iso_code, $this->all_iso_lang)) - throw new PrestaShopException(sprintf(Tools::displayError('Invalid iso code "%s"'), Tools::safeOutput($iso_code))); - - $this->lang_selected = new Language((int)Language::getIdByIso($iso_code)); - } - else - $this->lang_selected = new Language((int)Language::getIdByIso('en')); - - // Get all information for translations - $this->getTranslationsInformations(); - } - - public function renderKpis() - { - $time = time(); - $kpis = array(); - - /* The data generation is located in AdminStatsControllerCore */ - - $helper = new HelperKpi(); - $helper->id = 'box-languages'; - $helper->icon = 'icon-microphone'; - $helper->color = 'color1'; - $helper->href = $this->context->link->getAdminLink('AdminLanguages'); - $helper->title = $this->l('Enabled Languages', null, null, false); - if (ConfigurationKPI::get('ENABLED_LANGUAGES') !== false) - $helper->value = ConfigurationKPI::get('ENABLED_LANGUAGES'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=enabled_languages'; - $helper->refresh = (bool)(ConfigurationKPI::get('ENABLED_LANGUAGES_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-country'; - $helper->icon = 'icon-home'; - $helper->color = 'color2'; - $helper->title = $this->l('Main Country', null, null, false); - $helper->subtitle = $this->l('30 Days', null, null, false); - if (ConfigurationKPI::get('MAIN_COUNTRY', $this->context->language->id) !== false) - $helper->value = ConfigurationKPI::get('MAIN_COUNTRY', $this->context->language->id); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=main_country'; - $helper->refresh = (bool)(ConfigurationKPI::get('MAIN_COUNTRY_EXPIRE', $this->context->language->id) < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpi(); - $helper->id = 'box-translations'; - $helper->icon = 'icon-list'; - $helper->color = 'color3'; - $helper->title = $this->l('Front office Translations', null, null, false); - if (ConfigurationKPI::get('FRONTOFFICE_TRANSLATIONS') !== false) - $helper->value = ConfigurationKPI::get('FRONTOFFICE_TRANSLATIONS'); - $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=frontoffice_translations'; - $helper->refresh = (bool)(ConfigurationKPI::get('FRONTOFFICE_TRANSLATIONS_EXPIRE') < $time); - $kpis[] = $helper->generate(); - - $helper = new HelperKpiRow(); - $helper->kpis = $kpis; - return $helper->generate(); - } - - /** - * AdminController::postProcess() override - * @see AdminController::postProcess() - */ - public function postProcess() - { - $this->getInformations(); - - /* PrestaShop demo mode */ - if (_PS_MODE_DEMO_) - { - $this->errors[] = Tools::displayError('This functionality has been disabled.'); - return; - } - /* PrestaShop demo mode */ - - try { - - if (Tools::isSubmit('submitCopyLang')) - { - if ($this->tabAccess['add'] === '1') - $this->submitCopyLang(); - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - elseif (Tools::isSubmit('submitExport')) - { - if ($this->tabAccess['add'] === '1') - $this->submitExportLang(); - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - elseif (Tools::isSubmit('submitImport')) - { - if ($this->tabAccess['add'] === '1') - $this->submitImportLang(); - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - elseif (Tools::isSubmit('submitAddLanguage')) - { - if ($this->tabAccess['add'] === '1') - $this->submitAddLang(); - else - $this->errors[] = Tools::displayError('You do not have permission to add this.'); - } - elseif (Tools::isSubmit('submitTranslationsPdf')) - { - if ($this->tabAccess['edit'] === '1') - // Only the PrestaShop team should write the translations into the _PS_TRANSLATIONS_DIR_ - if (!$this->theme_selected) - $this->writeTranslationFile(); - else - $this->writeTranslationFile(true); - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('submitTranslationsBack') || Tools::isSubmit('submitTranslationsErrors') || Tools::isSubmit('submitTranslationsFields') || Tools::isSubmit('submitTranslationsFront')) - { - if ($this->tabAccess['edit'] === '1') - $this->writeTranslationFile(); - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('submitTranslationsMails') || Tools::isSubmit('submitTranslationsMailsAndStay')) - { - if ($this->tabAccess['edit'] === '1') - $this->submitTranslationsMails(); - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - elseif (Tools::isSubmit('submitTranslationsModules')) - { - if ($this->tabAccess['edit'] === '1') - { - // Get list of modules - if ($modules = $this->getListModules()) - { - // Get files of all modules - $arr_files = $this->getAllModuleFiles($modules, null, $this->lang_selected->iso_code, true); - - // Find and write all translation modules files - foreach ($arr_files as $value) - $this->findAndWriteTranslationsIntoFile($value['file_name'], $value['files'], $value['theme'], $value['module'], $value['dir']); - - // Clear modules cache - Tools::clearCache(); - - // Redirect - if (Tools::getIsset('submitTranslationsModulesAndStay')) - $this->redirect(true); - else - $this->redirect(); - } - } - else - $this->errors[] = Tools::displayError('You do not have permission to edit this.'); - } - } catch (PrestaShopException $e) { - $this->errors[] = $e->getMessage(); - } - } - - /** - * This method redirect in the translation main page or in the translation page - * - * @param bool $save_and_stay : true if the user has clicked on the button "save and stay" - * @param bool $conf : id of confirmation message - */ - protected function redirect($save_and_stay = false, $conf = false) - { - $conf = !$conf ? 4 : $conf; - $url_base = self::$currentIndex.'&token='.$this->token.'&conf='.$conf; - if ($save_and_stay) - Tools::redirectAdmin($url_base.'&lang='.$this->lang_selected->iso_code.'&type='.$this->type_selected.'&theme='.$this->theme_selected); - else - Tools::redirectAdmin($url_base); - } - - protected function getMailPattern() - { - // Let the indentation like it. - return '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd"> + /** Name of theme by default */ + const DEFAULT_THEME_NAME = _PS_DEFAULT_THEME_NAME_; + const TEXTAREA_SIZED = 70; + + /** @var string : Link which list all pack of language */ + protected $link_lang_pack = 'http://www.prestashop.com/download/lang_packs/get_each_language_pack.php'; + + /** @var int : number of sentence which can be translated */ + protected $total_expression = 0; + + /** @var int : number of sentence which aren't translated */ + protected $missing_translations = 0; + + /** @var array : List of ISO code for all languages */ + protected $all_iso_lang = array(); + + /** @var array */ + protected $modules_translations = array(); + + /** @var array : List of folder which must be ignored */ + protected static $ignore_folder = array('.', '..', '.svn', '.git', '.htaccess', 'index.php'); + + /** @var array : List of theme by translation type : FRONT, BACK, ERRORS... */ + protected $translations_informations = array(); + + /** @var array : List of all languages */ + protected $languages; + + /** @var array : List of all themes */ + protected $themes; + + /** @var string : Directory of selected theme */ + protected $theme_selected; + + /** @var string : Name of translations type */ + protected $type_selected; + + /** @var Language object : Language for the selected language */ + protected $lang_selected; + + /** @var bool : Is true if number of var exceed the suhosin request or post limit */ + protected $post_limit_exceed = false; + + public function __construct() + { + $this->bootstrap = true; + $this->multishop_context = Shop::CONTEXT_ALL; + $this->table = 'translations'; + + parent::__construct(); + } + + /* + * Set the type which is selected + */ + public function setTypeSelected($type_selected) + { + $this->type_selected = $type_selected; + } + + /** + * AdminController::initContent() override + * @see AdminController::initContent() + */ + public function initContent() + { + $this->initTabModuleList(); + $this->initPageHeaderToolbar(); + + if (!is_null($this->type_selected)) { + $method_name = 'initForm'.$this->type_selected; + if (method_exists($this, $method_name)) { + $this->content = $this->initForm($method_name); + } else { + $this->errors[] = sprintf(Tools::displayError('"%s" does not exist.'), $this->type_selected); + $this->content = $this->initMain(); + } + } else { + $this->content = $this->initMain(); + } + + $this->context->smarty->assign(array( + 'content' => $this->content, + 'show_page_header_toolbar' => $this->show_page_header_toolbar, + 'page_header_toolbar_title' => $this->page_header_toolbar_title, + 'page_header_toolbar_btn' => $this->page_header_toolbar_btn)); + } + + /** + * This function create vars by default and call the good method for generate form + * + * @param $method_name + * @return mixed Call the method $this->method_name() + */ + public function initForm($method_name) + { + // Create a title for each translation page + $title = sprintf( + $this->l('%1$s (Language: %2$s, Theme: %3$s)'), + $this->translations_informations[$this->type_selected]['name'], + $this->lang_selected->name, + $this->theme_selected ? $this->theme_selected : $this->l('none') + ); + + // Set vars for all forms + $this->tpl_view_vars = array( + 'lang' => $this->lang_selected->iso_code, + 'title' => $title, + 'type' => $this->type_selected, + 'theme' => $this->theme_selected, + 'post_limit_exceeded' => $this->post_limit_exceed, + 'url_submit' => self::$currentIndex.'&submitTranslations'.ucfirst($this->type_selected).'=1&token='.$this->token, + 'toggle_button' => $this->displayToggleButton(), + 'textarea_sized' => AdminTranslationsControllerCore::TEXTAREA_SIZED + ); + + // Call method initForm for a type + return $this->{$method_name}(); + } + + /** + * AdminController::initToolbar() override + * @see AdminController::initToolbar() + */ + public function initToolbar() + { + $this->toolbar_btn['save-and-stay'] = array( + 'short' => 'SaveAndStay', + 'href' => '#', + 'desc' => $this->l('Save and stay'), + ); + $this->toolbar_btn['save'] = array( + 'href' => '#', + 'desc' => $this->l('Update translations') + ); + $this->toolbar_btn['cancel'] = array( + 'href' => self::$currentIndex.'&token='.$this->token, + 'desc' => $this->l('Cancel') + ); + } + + /** + * Generate the Main page + */ + public function initMain() + { + // Block add/update a language + $packs_to_install = array(); + $packs_to_update = array(); + $token = Tools::getAdminToken('AdminLanguages'.(int)Tab::getIdFromClassName('AdminLanguages').(int)$this->context->employee->id); + $file_name = $this->link_lang_pack.'?version='._PS_VERSION_; + $array_stream_context = @stream_context_create(array('http' => array('method' => 'GET', 'timeout' => 8))); + if ($lang_packs = Tools::file_get_contents($file_name, false, $array_stream_context)) { + // Notice : for php < 5.2 compatibility, Tools::jsonDecode. The second parameter to true will set us + if ($lang_packs != '' && $lang_packs = Tools::jsonDecode($lang_packs, true)) { + foreach ($lang_packs as $key => $lang_pack) { + if (!Language::isInstalled($lang_pack['iso_code'])) { + $packs_to_install[$key] = $lang_pack; + } else { + $packs_to_update[$key] = $lang_pack; + } + } + } + } + + $this->tpl_view_vars = array( + 'theme_default' => self::DEFAULT_THEME_NAME, + 'theme_lang_dir' =>_THEME_LANG_DIR_, + 'token' => $this->token, + 'languages' => $this->languages, + 'translations_type' => $this->translations_informations, + 'packs_to_install' => $packs_to_install, + 'packs_to_update' => $packs_to_update, + 'url_submit' => self::$currentIndex.'&token='.$this->token, + 'themes' => $this->themes, + 'id_theme_current' => $this->context->shop->id_theme, + 'url_create_language' => 'index.php?controller=AdminLanguages&addlang&token='.$token, + ); + + $this->toolbar_scroll = false; + $this->base_tpl_view = 'main.tpl'; + + $this->content .= $this->renderKpis(); + $this->content .= parent::renderView(); + + return $this->content; + } + + /** + * This method merge each arrays of modules translation in the array of modules translations + */ + protected function getModuleTranslations() + { + global $_MODULE; + $name_var = $this->translations_informations[$this->type_selected]['var']; + + if (!isset($_MODULE) && !isset($GLOBALS[$name_var])) { + $GLOBALS[$name_var] = array(); + } elseif (isset($_MODULE)) { + if (is_array($GLOBALS[$name_var]) && is_array($_MODULE)) { + $GLOBALS[$name_var] = array_merge($GLOBALS[$name_var], $_MODULE); + } else { + $GLOBALS[$name_var] = $_MODULE; + } + } + } + + /** + * This method is only used by AdminTranslations::submitCopyLang(). + * + * It try to create folder in new theme. + * + * When a translation file is copied for a module, its translation key is wrong. + * We have to change the translation key and rewrite the file. + * + * @param string $dest file name + * @return bool + */ + protected function checkDirAndCreate($dest) + { + $bool = true; + + // To get only folder path + $path = dirname($dest); + + // If folder wasn't already added + // Do not use Tools::file_exists_cache because it changes over time! + if (!file_exists($path)) { + if (!mkdir($path, 0777, true)) { + $bool &= false; + $this->errors[] = sprintf($this->l('Cannot create the folder "%s". Please check your directory writing permissions.'), $path); + } + } + + return $bool; + } + + /** + * Read the Post var and write the translation file. + * This method overwrites the old translation file. + * + * @param bool $override_file Set true if this file is a override + * + * @throws PrestaShopException + */ + protected function writeTranslationFile($override_file = false) + { + $type = Tools::toCamelCase($this->type_selected, true); + + if (isset($this->translations_informations[$this->type_selected])) { + $translation_informations = $this->translations_informations[$this->type_selected]; + } else { + return; + } + + if ($override_file) { + $file_path = $translation_informations['override']['dir'].$translation_informations['override']['file']; + } else { + $file_path = $translation_informations['dir'].$translation_informations['file']; + } + + if ($file_path && !file_exists($file_path)) { + if (!file_exists(dirname($file_path)) && !mkdir(dirname($file_path), 0777, true)) { + throw new PrestaShopException(sprintf(Tools::displayError('Directory "%s" cannot be created'), dirname($file_path))); + } elseif (!touch($file_path)) { + throw new PrestaShopException(sprintf(Tools::displayError('File "%s" cannot be created'), $file_path)); + } + } + + $thm_name = str_replace('.', '', Tools::getValue('theme')); + $kpi_key = substr(strtoupper($thm_name.'_'.Tools::getValue('lang')), 0, 16); + + if ($fd = fopen($file_path, 'w')) { + // Get value of button save and stay + $save_and_stay = Tools::isSubmit('submitTranslations'.$type.'AndStay'); + + // Get language + $lang = strtolower(Tools::getValue('lang')); + + // Unset all POST which are not translations + unset( + $_POST['submitTranslations'.$type], + $_POST['submitTranslations'.$type.'AndStay'], + $_POST['lang'], + $_POST['token'], + $_POST['theme'], + $_POST['type'] + ); + + // Get all POST which aren't empty + $to_insert = array(); + foreach ($_POST as $key => $value) { + if (!empty($value)) { + $to_insert[$key] = $value; + } + } + + ConfigurationKPI::updateValue('FRONTOFFICE_TRANSLATIONS_EXPIRE', time()); + ConfigurationKPI::updateValue('TRANSLATE_TOTAL_'.$kpi_key, count($_POST)); + ConfigurationKPI::updateValue('TRANSLATE_DONE_'.$kpi_key, count($to_insert)); + + // translations array is ordered by key (easy merge) + ksort($to_insert); + $tab = $translation_informations['var']; + fwrite($fd, "<?php\n\nglobal \$".$tab.";\n\$".$tab." = array();\n"); + foreach ($to_insert as $key => $value) { + fwrite($fd, '$'.$tab.'[\''.pSQL($key, true).'\'] = \''.pSQL($value, true).'\';'."\n"); + } + fwrite($fd, "\n?>"); + fclose($fd); + + // Redirect + if ($save_and_stay) { + $this->redirect(true); + } else { + $this->redirect(); + } + } else { + throw new PrestaShopException(sprintf(Tools::displayError('Cannot write this file: "%s"'), $file_path)); + } + } + + public function submitCopyLang() + { + if (!($from_lang = Tools::getValue('fromLang')) || !($to_lang = Tools::getValue('toLang'))) { + $this->errors[] = $this->l('You must select two languages in order to copy data from one to another.'); + } elseif (!($from_theme = Tools::getValue('fromTheme')) || !($to_theme = Tools::getValue('toTheme'))) { + $this->errors[] = $this->l('You must select two themes in order to copy data from one to another.'); + } elseif (!Language::copyLanguageData(Language::getIdByIso($from_lang), Language::getIdByIso($to_lang))) { + $this->errors[] = $this->l('An error occurred while copying data.'); + } elseif ($from_lang == $to_lang && $from_theme == $to_theme) { + $this->errors[] = $this->l('There is nothing to copy (same language and theme).'); + } else { + $theme_exists = array('from_theme' => false, 'to_theme' => false); + foreach ($this->themes as $theme) { + if ($theme->directory == $from_theme) { + $theme_exists['from_theme'] = true; + } + if ($theme->directory == $to_theme) { + $theme_exists['to_theme'] = true; + } + } + if ($theme_exists['from_theme'] == false || $theme_exists['to_theme'] == false) { + $this->errors[] = $this->l('Theme(s) not found'); + } + } + if (count($this->errors)) { + return; + } + + $bool = true; + $items = Language::getFilesList($from_lang, $from_theme, $to_lang, $to_theme, false, false, true); + foreach ($items as $source => $dest) { + if (!$this->checkDirAndCreate($dest)) { + $this->errors[] = sprintf($this->l('Impossible to create the directory "%s".'), $dest); + } elseif (!copy($source, $dest)) { + $this->errors[] = sprintf($this->l('Impossible to copy "%s" to "%s".'), $source, $dest); + } elseif (strpos($dest, 'modules') && basename($source) === $from_lang.'.php' && $bool !== false) { + if (!$this->changeModulesKeyTranslation($dest, $from_theme, $to_theme)) { + $this->errors[] = sprintf($this->l('Impossible to translate "$dest".'), $dest); + } + } + } + if (!count($this->errors)) { + $this->redirect(false, 14); + } + $this->errors[] = $this->l('A part of the data has been copied but some of the language files could not be found.'); + } + + /** + * Change the key translation to according it to theme name. + * + * @param string $path + * @param string $theme_from + * @param string $theme_to + * @return bool + */ + public function changeModulesKeyTranslation($path, $theme_from, $theme_to) + { + $content = file_get_contents($path); + $arr_replace = array(); + $bool_flag = true; + if (preg_match_all('#\$_MODULE\[\'([^\']+)\'\]#Ui', $content, $matches)) { + foreach ($matches[1] as $key => $value) { + $arr_replace[$value] = str_replace($theme_from, $theme_to, $value); + } + $content = str_replace(array_keys($arr_replace), array_values($arr_replace), $content); + $bool_flag = (file_put_contents($path, $content) === false) ? false : true; + } + return $bool_flag; + } + + public function exportTabs() + { + // Get name tabs by iso code + $tabs = Tab::getTabs($this->lang_selected->id); + + // Get name of the default tabs + $tabs_default_lang = Tab::getTabs(1); + + $tabs_default = array(); + foreach ($tabs_default_lang as $tab) { + $tabs_default[$tab['class_name']] = pSQL($tab['name']); + } + + // Create content + $content = "<?php\n\n\$_TABS = array();"; + if (!empty($tabs)) { + foreach ($tabs as $tab) { + /** + * We don't export tab translations that are identical to the default + * tab translations to avoid a problem that would occur in the followin scenario: + * + * 1) install PrestaShop in, say, Spanish => tabs are by default in Spanish + * 2) create a new language, say, Klingon => tabs are populated using the default, Spanish, tabs + * 3) export the Klingon language pack + * + * => Since you have not yet translated the tabs into Klingon, + * without the condition below, you would get tabs exported, but in Spanish. + * This would lead to a Klingon pack actually containing Spanish. + * + * This has caused many issues in the past, so, as a precaution, tabs from + * the default language are not exported. + * + */ + if ($tabs_default[$tab['class_name']] != pSQL($tab['name'])) { + $content .= "\n\$_TABS['".$tab['class_name']."'] = '".pSQL($tab['name'])."';"; + } + } + } + $content .= "\n\nreturn \$_TABS;"; + + $dir = _PS_TRANSLATIONS_DIR_.$this->lang_selected->iso_code.DIRECTORY_SEPARATOR; + $path = $dir.'tabs.php'; + + // Check if tabs.php exists for the selected Iso Code + if (!Tools::file_exists_cache($dir)) { + if (!mkdir($dir, 0777, true)) { + throw new PrestaShopException('The file '.$dir.' cannot be created.'); + } + } + if (!file_put_contents($path, $content)) { + throw new PrestaShopException('File "'.$path.'" does not exist and cannot be created in '.$dir); + } + if (!is_writable($path)) { + $this->displayWarning(sprintf(Tools::displayError('This file must be writable: %s'), $path)); + } + } + + public function submitExportLang() + { + if ($this->lang_selected->iso_code && $this->theme_selected) { + $this->exportTabs(); + $items = array_flip(Language::getFilesList($this->lang_selected->iso_code, $this->theme_selected, false, false, false, false, true)); + $file_name = _PS_TRANSLATIONS_DIR_.'/export/'.$this->lang_selected->iso_code.'.gzip'; + require_once(_PS_TOOL_DIR_.'tar/Archive_Tar.php'); + $gz = new Archive_Tar($file_name, true); + if ($gz->createModify($items, null, _PS_ROOT_DIR_)) { + ob_start(); + header('Pragma: public'); + header('Expires: 0'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Cache-Control: public'); + header('Content-Description: File Transfer'); + header('Content-type: application/octet-stream'); + header('Content-Disposition: attachment; filename="'.$this->lang_selected->iso_code.'.gzip'.'"'); + header('Content-Transfer-Encoding: binary'); + ob_end_flush(); + readfile($file_name); + @unlink($file_name); + exit; + } + $this->errors[] = Tools::displayError('An error occurred while creating archive.'); + } + $this->errors[] = Tools::displayError('Please select a language and a theme.'); + } + + public static function checkAndAddMailsFiles($iso_code, $files_list) + { + if (Language::getIdByIso('en')) { + $default_language = 'en'; + } else { + $default_language = Language::getIsoById((int)Configuration::get('PS_LANG_DEFAULT')); + } + + if (!$default_language || !Validate::isLanguageIsoCode($default_language)) { + return false; + } + + // 1 - Scan mails files + $mails = array(); + if (Tools::file_exists_cache(_PS_MAIL_DIR_.$default_language.'/')) { + $mails = scandir(_PS_MAIL_DIR_.$default_language.'/'); + } + + $mails_new_lang = array(); + + // Get all email files + foreach ($files_list as $file) { + if (preg_match('#^mails\/([a-z0-9]+)\/#Ui', $file['filename'], $matches)) { + $slash_pos = strrpos($file['filename'], '/'); + $mails_new_lang[] = substr($file['filename'], -(strlen($file['filename']) - $slash_pos - 1)); + } + } + + // Get the difference + $arr_mails_needed = array_diff($mails, $mails_new_lang); + + // Add mails files + foreach ($arr_mails_needed as $mail_to_add) { + if (!in_array($mail_to_add, self::$ignore_folder)) { + @copy(_PS_MAIL_DIR_.$default_language.'/'.$mail_to_add, _PS_MAIL_DIR_.$iso_code.'/'.$mail_to_add); + } + } + + // 2 - Scan modules files + $modules = scandir(_PS_MODULE_DIR_); + + $module_mail_en = array(); + $module_mail_iso_code = array(); + + foreach ($modules as $module) { + if (!in_array($module, self::$ignore_folder) && Tools::file_exists_cache(_PS_MODULE_DIR_.$module.'/mails/'.$default_language.'/')) { + $arr_files = scandir(_PS_MODULE_DIR_.$module.'/mails/'.$default_language.'/'); + + foreach ($arr_files as $file) { + if (!in_array($file, self::$ignore_folder)) { + if (Tools::file_exists_cache(_PS_MODULE_DIR_.$module.'/mails/'.$default_language.'/'.$file)) { + $module_mail_en[] = _PS_MODULE_DIR_.$module.'/mails/ISO_CODE/'.$file; + } + + if (Tools::file_exists_cache(_PS_MODULE_DIR_.$module.'/mails/'.$iso_code.'/'.$file)) { + $module_mail_iso_code[] = _PS_MODULE_DIR_.$module.'/mails/ISO_CODE/'.$file; + } + } + } + } + } + + // Get the difference in this modules + $arr_modules_mails_needed = array_diff($module_mail_en, $module_mail_iso_code); + + // Add mails files for this modules + foreach ($arr_modules_mails_needed as $file) { + $file_en = str_replace('ISO_CODE', $default_language, $file); + $file_iso_code = str_replace('ISO_CODE', $iso_code, $file); + $dir_iso_code = substr($file_iso_code, 0, -(strlen($file_iso_code) - strrpos($file_iso_code, '/') - 1)); + + if (!file_exists($dir_iso_code)) { + mkdir($dir_iso_code); + file_put_contents($dir_iso_code.'/index.php', Tools::getDefaultIndexContent()); + } + + if (Tools::file_exists_cache($file_en)) { + copy($file_en, $file_iso_code); + } + } + } + + /** + * Move theme translations in selected themes + * + * @param array $files + * @param array $themes_selected + */ + public function checkAndAddThemesFiles($files, $themes_selected) + { + foreach ($files as $file) { + // Check if file is a file theme + if (preg_match('#^themes\/([a-z0-9]+)\/lang\/#Ui', $file['filename'], $matches)) { + $slash_pos = strrpos($file['filename'], '/'); + $name_file = substr($file['filename'], -(strlen($file['filename']) - $slash_pos - 1)); + $name_default_theme = $matches[1]; + $deleted_old_theme = false; + + // Get the old file theme + if (file_exists(_PS_THEME_DIR_.'lang/'.$name_file)) { + $theme_file_old = _PS_THEME_DIR_.'lang/'.$name_file; + } else { + $deleted_old_theme = true; + $theme_file_old = str_replace(self::DEFAULT_THEME_NAME, $name_default_theme, _PS_THEME_DIR_.'lang/'.$name_file); + } + + // Move the old file theme in the new folder + foreach ($themes_selected as $theme_name) { + if (file_exists($theme_file_old)) { + copy($theme_file_old, str_replace($name_default_theme, $theme_name, $theme_file_old)); + } + } + + if ($deleted_old_theme) { + @unlink($theme_file_old); + } + } + } + } + + /** + * Add new translations tabs by code ISO + * + * @param array $iso_code + * @param array $files + * + * @return array + */ + public static function addNewTabs($iso_code, $files) + { + $errors = array(); + + foreach ($files as $file) { + // Check if file is a file theme + if (preg_match('#^translations\/'.$iso_code.'\/tabs.php#Ui', $file['filename'], $matches) && Validate::isLanguageIsoCode($iso_code)) { + // Include array width new translations tabs + $_TABS = array(); + clearstatcache(); + if (file_exists(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$file['filename'])) { + include_once(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$file['filename']); + } + + if (is_array($_TABS) && count($_TABS)) { + foreach ($_TABS as $class_name => $translations) { + // Get instance of this tab by class name + $tab = Tab::getInstanceFromClassName($class_name); + //Check if class name exists + if (isset($tab->class_name) && !empty($tab->class_name)) { + $id_lang = Language::getIdByIso($iso_code, true); + $tab->name[(int)$id_lang] = $translations; + + // Do not crash at intall + if (!isset($tab->name[Configuration::get('PS_LANG_DEFAULT')])) { + $tab->name[(int)Configuration::get('PS_LANG_DEFAULT')] = $translations; + } + + if (!Validate::isGenericName($tab->name[(int)$id_lang])) { + $errors[] = sprintf(Tools::displayError('Tab "%s" is not valid'), $tab->name[(int)$id_lang]); + } else { + $tab->update(); + } + } + } + } + } + } + + return $errors; + } + + public static function checkTranslationFile($content) + { + $lines = array_map('trim', explode("\n", $content)); + $global = false; + foreach ($lines as $line) { + // PHP tags + if (in_array($line, array('<?php', '?>', ''))) { + continue; + } + + // Global variable declaration + if (!$global && preg_match('/^global\s+\$([a-z0-9-_]+)\s*;$/i', $line, $matches)) { + $global = $matches[1]; + continue; + } + // Global variable initialization + if ($global != false && preg_match('/^\$'.preg_quote($global, '/').'\s*=\s*array\(\s*\)\s*;$/i', $line)) { + continue; + } + + // Global variable initialization without declaration + if (!$global && preg_match('/^\$([a-z0-9-_]+)\s*=\s*array\(\s*\)\s*;$/i', $line, $matches)) { + $global = $matches[1]; + continue; + } + + // Assignation + if (preg_match('/^\$'.preg_quote($global, '/').'\[\''._PS_TRANS_PATTERN_.'\'\]\s*=\s*\''._PS_TRANS_PATTERN_.'\'\s*;$/i', $line)) { + continue; + } + + // Sometimes the global variable is returned... + if (preg_match('/^return\s+\$'.preg_quote($global, '/').'\s*;$/i', $line, $matches)) { + continue; + } + return false; + } + return true; + } + + public function submitImportLang() + { + if (!isset($_FILES['file']['tmp_name']) || !$_FILES['file']['tmp_name']) { + $this->errors[] = Tools::displayError('No file has been selected.'); + } else { + require_once(_PS_TOOL_DIR_.'tar/Archive_Tar.php'); + $gz = new Archive_Tar($_FILES['file']['tmp_name'], true); + $filename = $_FILES['file']['name']; + $iso_code = str_replace(array('.tar.gz', '.gzip'), '', $filename); + if (Validate::isLangIsoCode($iso_code)) { + $themes_selected = Tools::getValue('theme', array(self::DEFAULT_THEME_NAME)); + $files_list = AdminTranslationsController::filterTranslationFiles($gz->listContent()); + $files_paths = AdminTranslationsController::filesListToPaths($files_list); + + $uniqid = uniqid(); + $sandbox = _PS_CACHE_DIR_.'sandbox'.DIRECTORY_SEPARATOR.$uniqid.DIRECTORY_SEPARATOR; + if ($gz->extractList($files_paths, $sandbox)) { + foreach ($files_list as $file2check) { + //don't validate index.php, will be overwrite when extract in translation directory + if (pathinfo($file2check['filename'], PATHINFO_BASENAME) == 'index.php') { + continue; + } + + if (preg_match('@^[0-9a-z-_/\\\\]+\.php$@i', $file2check['filename'])) { + if (!@filemtime($sandbox.$file2check['filename']) || !AdminTranslationsController::checkTranslationFile(file_get_contents($sandbox.$file2check['filename']))) { + $this->errors[] = sprintf(Tools::displayError('Validation failed for: %s'), $file2check['filename']); + } + } elseif (!preg_match('@mails[0-9a-z-_/\\\\]+\.(html|tpl|txt)$@i', $file2check['filename'])) { + $this->errors[] = sprintf(Tools::displayError('Unidentified file found: %s'), $file2check['filename']); + } + } + Tools::deleteDirectory($sandbox, true); + } + + $i = 0; + $tmp_array = array(); + foreach ($files_paths as $files_path) { + $path = dirname($files_path); + if (is_dir(_PS_TRANSLATIONS_DIR_.'../'.$path) && !is_writable(_PS_TRANSLATIONS_DIR_.'../'.$path) && !in_array($path, $tmp_array)) { + $this->errors[] = (!$i++? Tools::displayError('The archive cannot be extracted.').' ' : '').Tools::displayError('The server does not have permissions for writing.').' '.sprintf(Tools::displayError('Please check rights for %s'), $path); + $tmp_array[] = $path; + } + } + + if (count($this->errors)) { + return false; + } + + if ($error = $gz->extractList($files_paths, _PS_TRANSLATIONS_DIR_.'../')) { + if (is_object($error) && !empty($error->message)) { + $this->errors[] = Tools::displayError('The archive cannot be extracted.'). ' '.$error->message; + } else { + foreach ($files_list as $file2check) { + if (pathinfo($file2check['filename'], PATHINFO_BASENAME) == 'index.php' && file_put_contents(_PS_TRANSLATIONS_DIR_.'../'.$file2check['filename'], Tools::getDefaultIndexContent())) { + continue; + } + } + + // Clear smarty modules cache + Tools::clearCache(); + + if (Validate::isLanguageFileName($filename)) { + if (!Language::checkAndAddLanguage($iso_code)) { + $conf = 20; + } else { + // Reset cache + Language::loadLanguages(); + + AdminTranslationsController::checkAndAddMailsFiles($iso_code, $files_list); + $this->checkAndAddThemesFiles($files_list, $themes_selected); + $tab_errors = AdminTranslationsController::addNewTabs($iso_code, $files_list); + + if (count($tab_errors)) { + $this->errors += $tab_errors; + return false; + } + } + } + $this->redirect(false, (isset($conf) ? $conf : '15')); + } + } + $this->errors[] = Tools::displayError('The archive cannot be extracted.'); + } else { + $this->errors[] = sprintf(Tools::displayError('ISO CODE invalid "%1$s" for the following file: "%2$s"'), $iso_code, $filename); + } + } + } + + /** + * Filter the translation files contained in a .gzip pack + * and return only the ones that we want. + * + * Right now the function only needs to check that + * the modules for which we want to add translations + * are present on the shop (installed or not). + * + * @param array $list Is the output of Archive_Tar::listContent() + * + * @return array + */ + public static function filterTranslationFiles($list) + { + $kept = array(); + foreach ($list as $file) { + if ('index.php' == basename($file['filename'])) { + continue; + } + if (preg_match('#^modules/([^/]+)/#', $file['filename'], $m)) { + if (is_dir(_PS_MODULE_DIR_.$m[1])) { + $kept[] = $file; + } + } else { + $kept[] = $file; + } + } + return $kept; + } + + /** + * Turn the list returned by + * AdminTranslationsController::filterTranslationFiles() + * into a list of paths that can be passed to + * Archive_Tar::extractList() + * + * @param array $list + * + * @return array + */ + public static function filesListToPaths($list) + { + $paths = array(); + foreach ($list as $item) { + $paths[] = $item['filename']; + } + return $paths; + } + + public function submitAddLang() + { + $arr_import_lang = explode('|', Tools::getValue('params_import_language')); /* 0 = Language ISO code, 1 = PS version */ + if (Validate::isLangIsoCode($arr_import_lang[0])) { + $array_stream_context = @stream_context_create(array('http' => array('method' => 'GET', 'timeout' => 10))); + $content = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/gzip/'.$arr_import_lang[1].'/'.Tools::strtolower($arr_import_lang[0]).'.gzip', false, $array_stream_context); + if ($content) { + $file = _PS_TRANSLATIONS_DIR_.$arr_import_lang[0].'.gzip'; + if ((bool)@file_put_contents($file, $content)) { + require_once(_PS_TOOL_DIR_.'/tar/Archive_Tar.php'); + $gz = new Archive_Tar($file, true); + if (_PS_MODE_DEV_) { + $gz->setErrorHandling(PEAR_ERROR_TRIGGER, E_USER_WARNING); + } + $files_list = AdminTranslationsController::filterTranslationFiles($gz->listContent()); + + if ($error = $gz->extractList(AdminTranslationsController::filesListToPaths($files_list), _PS_TRANSLATIONS_DIR_.'../')) { + if (is_object($error) && !empty($error->message)) { + $this->errors[] = Tools::displayError('The archive cannot be extracted.'). ' '.$error->message; + } else { + if (!Language::checkAndAddLanguage($arr_import_lang[0])) { + $conf = 20; + } else { + // Reset cache + Language::loadLanguages(); + // Clear smarty modules cache + Tools::clearCache(); + + AdminTranslationsController::checkAndAddMailsFiles($arr_import_lang[0], $files_list); + if ($tab_errors = AdminTranslationsController::addNewTabs($arr_import_lang[0], $files_list)) { + $this->errors += $tab_errors; + } + } + if (!unlink($file)) { + $this->errors[] = sprintf(Tools::displayError('Cannot delete the archive %s.'), $file); + } + + $this->redirect(false, (isset($conf) ? $conf : '15')); + } + } else { + $this->errors[] = sprintf(Tools::displayError('Cannot decompress the translation file for the following language: %s'), $arr_import_lang[0]); + $checks= array(); + foreach ($files_list as $f) { + if (isset($f['filename'])) { + if (is_file(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$f['filename']) && !is_writable(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$f['filename'])) { + $checks[] = dirname($f['filename']); + } elseif (is_dir(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.$f['filename']) && !is_writable(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.dirname($f['filename']))) { + $checks[] = dirname($f['filename']); + } + } + } + + $checks = array_unique($checks); + foreach ($checks as $check) { + $this->errors[] = sprintf(Tools::displayError('Please check rights for folder and files in %s'), $check); + } + if (!unlink($file)) { + $this->errors[] = sprintf(Tools::displayError('Cannot delete the archive %s.'), $file); + } + } + } else { + $this->errors[] = Tools::displayError('The server does not have permissions for writing.').' '.sprintf(Tools::displayError('Please check rights for %s'), dirname($file)); + } + } else { + $this->errors[] = Tools::displayError('Language not found.'); + } + } else { + $this->errors[] = Tools::displayError('Invalid parameter.'); + } + } + + /** + * This method check each file (tpl or php file), get its sentences to translate, + * compare with posted values and write in iso code translation file. + * + * @param string $file_name + * @param array $files + * @param string $theme_name + * @param string $module_name + * @param string|bool $dir + * + * @throws PrestaShopException + */ + protected function findAndWriteTranslationsIntoFile($file_name, $files, $theme_name, $module_name, $dir = false) + { + // These static vars allow to use file to write just one time. + static $cache_file = array(); + static $str_write = ''; + static $array_check_duplicate = array(); + + // Set file_name in static var, this allow to open and wright the file just one time + if (!isset($cache_file[$theme_name.'-'.$file_name])) { + $str_write = ''; + $cache_file[$theme_name.'-'.$file_name] = true; + if (!Tools::file_exists_cache(dirname($file_name))) { + mkdir(dirname($file_name), 0777, true); + } + if (!Tools::file_exists_cache($file_name)) { + file_put_contents($file_name, ''); + } + if (!is_writable($file_name)) { + throw new PrestaShopException(sprintf( + Tools::displayError('Cannot write to the theme\'s language file (%s). Please check writing permissions.'), + $file_name + )); + } + + // this string is initialized one time for a file + $str_write .= "<?php\n\nglobal \$_MODULE;\n\$_MODULE = array();\n"; + $array_check_duplicate = array(); + } + + foreach ($files as $file) { + if (preg_match('/^(.*)\.(tpl|php)$/', $file) && Tools::file_exists_cache($dir.$file) && !in_array($file, self::$ignore_folder)) { + // Get content for this file + $content = file_get_contents($dir.$file); + + // Get file type + $type_file = substr($file, -4) == '.tpl' ? 'tpl' : 'php'; + + // Parse this content + $matches = $this->userParseFile($content, $this->type_selected, $type_file, $module_name); + + // Write each translation on its module file + $template_name = substr(basename($file), 0, -4); + + foreach ($matches as $key) { + if ($theme_name) { + $post_key = md5(strtolower($module_name).'_'.strtolower($theme_name).'_'.strtolower($template_name).'_'.md5($key)); + $pattern = '\'<{'.strtolower($module_name).'}'.strtolower($theme_name).'>'.strtolower($template_name).'_'.md5($key).'\''; + } else { + $post_key = md5(strtolower($module_name).'_'.strtolower($template_name).'_'.md5($key)); + $pattern = '\'<{'.strtolower($module_name).'}prestashop>'.strtolower($template_name).'_'.md5($key).'\''; + } + + if (array_key_exists($post_key, $_POST) && !in_array($pattern, $array_check_duplicate)) { + if ($_POST[$post_key] == '') { + continue; + } + $array_check_duplicate[] = $pattern; + $str_write .= '$_MODULE['.$pattern.'] = \''.pSQL(str_replace(array("\r\n", "\r", "\n"), ' ', $_POST[$post_key])).'\';'."\n"; + $this->total_expression++; + } + } + } + } + + if (isset($cache_file[$theme_name.'-'.$file_name]) && $str_write != "<?php\n\nglobal \$_MODULE;\n\$_MODULE = array();\n") { + file_put_contents($file_name, $str_write); + } + } + + /** + * Clear the list of module file by type (file or directory) + * + * @param $files : list of files + * @param string $type_clear (file|directory) + * @param string $path + * @return array : list of a good files + */ + public function clearModuleFiles($files, $type_clear = 'file', $path = '') + { + // List of directory which not must be parsed + $arr_exclude = array('img', 'js', 'mails','override'); + + // List of good extention files + $arr_good_ext = array('.tpl', '.php'); + + foreach ($files as $key => $file) { + if ($file{0} === '.' || in_array(substr($file, 0, strrpos($file, '.')), $this->all_iso_lang)) { + unset($files[$key]); + } elseif ($type_clear === 'file' && !in_array(substr($file, strrpos($file, '.')), $arr_good_ext)) { + unset($files[$key]); + } elseif ($type_clear === 'directory' && (!is_dir($path.$file) || in_array($file, $arr_exclude))) { + unset($files[$key]); + } + } + + return $files; + } + + /** + * This method get translation for each files of a module, + * compare with global $_MODULES array and fill AdminTranslations::modules_translations array + * With key as English sentences and values as their iso code translations. + * + * @param array $files + * @param string $theme_name + * @param string $module_name + * @param string|bool $dir + */ + protected function findAndFillTranslations($files, $theme_name, $module_name, $dir = false) + { + $name_var = $this->translations_informations[$this->type_selected]['var']; + + // added for compatibility + $GLOBALS[$name_var] = array_change_key_case($GLOBALS[$name_var]); + + // Thank to this var similar keys are not duplicate + // in AndminTranslation::modules_translations array + // see below + $array_check_duplicate = array(); + foreach ($files as $file) { + if ((preg_match('/^(.*).tpl$/', $file) || preg_match('/^(.*).php$/', $file)) && Tools::file_exists_cache($file_path = $dir.$file)) { + // Get content for this file + $content = file_get_contents($file_path); + + // Module files can now be ignored by adding this string in a file + if (strpos($content, 'IGNORE_THIS_FILE_FOR_TRANSLATION') !== false) { + continue; + } + + // Get file type + $type_file = substr($file, -4) == '.tpl' ? 'tpl' : 'php'; + + // Parse this content + $matches = $this->userParseFile($content, $this->type_selected, $type_file, $module_name); + + // Write each translation on its module file + $template_name = substr(basename($file), 0, -4); + + foreach ($matches as $key) { + $md5_key = md5($key); + $module_key = '<{'.Tools::strtolower($module_name).'}'.strtolower($theme_name).'>'.Tools::strtolower($template_name).'_'.$md5_key; + $default_key = '<{'.Tools::strtolower($module_name).'}prestashop>'.Tools::strtolower($template_name).'_'.$md5_key; + // to avoid duplicate entry + if (!in_array($module_key, $array_check_duplicate)) { + $array_check_duplicate[] = $module_key; + if (!isset($this->modules_translations[$theme_name][$module_name][$template_name][$key]['trad'])) { + $this->total_expression++; + } + if ($theme_name && array_key_exists($module_key, $GLOBALS[$name_var])) { + $this->modules_translations[$theme_name][$module_name][$template_name][$key]['trad'] = html_entity_decode($GLOBALS[$name_var][$module_key], ENT_COMPAT, 'UTF-8'); + } elseif (array_key_exists($default_key, $GLOBALS[$name_var])) { + $this->modules_translations[$theme_name][$module_name][$template_name][$key]['trad'] = html_entity_decode($GLOBALS[$name_var][$default_key], ENT_COMPAT, 'UTF-8'); + } else { + $this->modules_translations[$theme_name][$module_name][$template_name][$key]['trad'] = ''; + $this->missing_translations++; + } + $this->modules_translations[$theme_name][$module_name][$template_name][$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); + } + } + } + } + } + + /** + * Get list of files which must be parsed by directory and by type of translations + * + * @return array : list of files by directory + */ + public function getFileToParseByTypeTranslation() + { + $directories = array(); + + switch ($this->type_selected) { + case 'front': + $directories['tpl'] = array(_PS_ALL_THEMES_DIR_ => scandir(_PS_ALL_THEMES_DIR_)); + self::$ignore_folder[] = 'modules'; + $directories['tpl'] = array_merge($directories['tpl'], $this->listFiles(_PS_THEME_SELECTED_DIR_)); + if (isset($directories['tpl'][_PS_THEME_SELECTED_DIR_.'pdf/'])) { + unset($directories['tpl'][_PS_THEME_SELECTED_DIR_.'pdf/']); + } + + if (Tools::file_exists_cache(_PS_THEME_OVERRIDE_DIR_)) { + $directories['tpl'] = array_merge($directories['tpl'], $this->listFiles(_PS_THEME_OVERRIDE_DIR_)); + } + + break; + + case 'back': + $directories = array( + 'php' => array( + _PS_ADMIN_CONTROLLER_DIR_ => scandir(_PS_ADMIN_CONTROLLER_DIR_), + _PS_OVERRIDE_DIR_.'controllers/admin/' => scandir(_PS_OVERRIDE_DIR_.'controllers/admin/'), + _PS_CLASS_DIR_.'helper/' => scandir(_PS_CLASS_DIR_.'helper/'), + _PS_CLASS_DIR_.'controller/' => array('AdminController.php'), + _PS_CLASS_DIR_ => array('PaymentModule.php') + ), + 'tpl' => $this->listFiles(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes/'), + 'specific' => array( + _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR => array( + 'header.inc.php', + 'footer.inc.php', + 'index.php', + 'functions.php' + ) + ) + ); + + // For translate the template which are overridden + if (file_exists(_PS_OVERRIDE_DIR_.'controllers'.DIRECTORY_SEPARATOR.'admin'.DIRECTORY_SEPARATOR.'templates')) { + $directories['tpl'] = array_merge($directories['tpl'], $this->listFiles(_PS_OVERRIDE_DIR_.'controllers'.DIRECTORY_SEPARATOR.'admin'.DIRECTORY_SEPARATOR.'templates')); + } + + break; + + case 'errors': + $directories['php'] = array( + _PS_ROOT_DIR_ => scandir(_PS_ROOT_DIR_), + _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR => scandir(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR), + _PS_FRONT_CONTROLLER_DIR_ => scandir(_PS_FRONT_CONTROLLER_DIR_), + _PS_ADMIN_CONTROLLER_DIR_ => scandir(_PS_ADMIN_CONTROLLER_DIR_), + _PS_OVERRIDE_DIR_.'controllers/front/' => scandir(_PS_OVERRIDE_DIR_.'controllers/front/'), + _PS_OVERRIDE_DIR_.'controllers/admin/' => scandir(_PS_OVERRIDE_DIR_.'controllers/admin/') + ); + + // Get all files for folders classes/ and override/classes/ recursively + $directories['php'] = array_merge($directories['php'], $this->listFiles(_PS_CLASS_DIR_, array(), 'php')); + $directories['php'] = array_merge($directories['php'], $this->listFiles(_PS_OVERRIDE_DIR_.'classes/', array(), 'php')); + break; + + case 'fields': + $directories['php'] = $this->listFiles(_PS_CLASS_DIR_, array(), 'php'); + break; + + case 'pdf': + $tpl_theme = Tools::file_exists_cache(_PS_THEME_SELECTED_DIR_.'pdf/') ? scandir(_PS_THEME_SELECTED_DIR_.'pdf/') : array(); + $directories = array( + 'php' => array( + _PS_CLASS_DIR_.'pdf/' => scandir(_PS_CLASS_DIR_.'pdf/'), + _PS_OVERRIDE_DIR_.'classes/pdf/' => scandir(_PS_OVERRIDE_DIR_.'classes/pdf/') + ), + 'tpl' => array( + _PS_PDF_DIR_ => scandir(_PS_PDF_DIR_), + _PS_THEME_SELECTED_DIR_.'pdf/' => $tpl_theme + ) + ); + $directories['tpl'] = array_merge($directories['tpl'], $this->getModulesHasPDF()); + $directories['php'] = array_merge($directories['php'], $this->getModulesHasPDF(true)); + break; + + case 'mails': + $directories['php'] = array( + _PS_FRONT_CONTROLLER_DIR_ => scandir(_PS_FRONT_CONTROLLER_DIR_), + _PS_ADMIN_CONTROLLER_DIR_ => scandir(_PS_ADMIN_CONTROLLER_DIR_), + _PS_OVERRIDE_DIR_.'controllers/front/' => scandir(_PS_OVERRIDE_DIR_.'controllers/front/'), + _PS_OVERRIDE_DIR_.'controllers/admin/' => scandir(_PS_OVERRIDE_DIR_.'controllers/admin/'), + _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR => scandir(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR), + _PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'tabs/' => scandir(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'/tabs') + ); + + // Get all files for folders classes/ and override/classes/ recursively + $directories['php'] = array_merge($directories['php'], $this->listFiles(_PS_CLASS_DIR_, array(), 'php')); + $directories['php'] = array_merge($directories['php'], $this->listFiles(_PS_OVERRIDE_DIR_.'classes/', array(), 'php')); + $directories['php'] = array_merge($directories['php'], $this->getModulesHasMails()); + break; + + } + + return $directories; + } + + /** + * This method parse a file by type of translation and type file + * + * @param $content + * @param $type_translation : front, back, errors, modules... + * @param string|bool $type_file : (tpl|php) + * @param string $module_name : name of the module + * @return array + */ + protected function userParseFile($content, $type_translation, $type_file = false, $module_name = '') + { + switch ($type_translation) { + case 'front': + // Parsing file in Front office + $regex = '/\{l\s*s=([\'\"])'._PS_TRANS_PATTERN_.'\1(\s*sprintf=.*)?(\s*js=1)?\s*\}/U'; + break; + + case 'back': + // Parsing file in Back office + if ($type_file == 'php') { + $regex = '/this->l\((\')'._PS_TRANS_PATTERN_.'\'[\)|\,]/U'; + } elseif ($type_file == 'specific') { + $regex = '/Translate::getAdminTranslation\((\')'._PS_TRANS_PATTERN_.'\'(?:,.*)*\)/U'; + } else { + $regex = '/\{l\s*s\s*=([\'\"])'._PS_TRANS_PATTERN_.'\1(\s*sprintf=.*)?(\s*js=1)?(\s*slashes=1)?.*\}/U'; + } + break; + + case 'errors': + // Parsing file for all errors syntax + $regex = '/Tools::displayError\((\')'._PS_TRANS_PATTERN_.'\'(,\s*(.+))?\)/U'; + break; + + case 'modules': + // Parsing modules file + if ($type_file == 'php') { + $regex = '/->l\((\')'._PS_TRANS_PATTERN_.'\'(, ?\'(.+)\')?(, ?(.+))?\)/U'; + } else { + // In tpl file look for something that should contain mod='module_name' according to the documentation + $regex = '/\{l\s*s=([\'\"])'._PS_TRANS_PATTERN_.'\1.*\s+mod=\''.$module_name.'\'.*\}/U'; + } + break; + + case 'pdf': + // Parsing PDF file + if ($type_file == 'php') { + $regex = array( + '/HTMLTemplate.*::l\((\')'._PS_TRANS_PATTERN_.'\'[\)|\,]/U', + '/->l\((\')'._PS_TRANS_PATTERN_.'\'(, ?\'(.+)\')?(, ?(.+))?\)/U' + ); + } else { + $regex = '/\{l\s*s=([\'\"])'._PS_TRANS_PATTERN_.'\1(\s*sprintf=.*)?(\s*js=1)?(\s*pdf=\'true\')?\s*\}/U'; + } + break; + } + + if (!is_array($regex)) { + $regex = array($regex); + } + + $strings = array(); + foreach ($regex as $regex_row) { + $matches = array(); + $n = preg_match_all($regex_row, $content, $matches); + for ($i = 0; $i < $n; $i += 1) { + $quote = $matches[1][$i]; + $string = $matches[2][$i]; + + if ($quote === '"') { + // Escape single quotes because the core will do it when looking for the translation of this string + $string = str_replace('\'', '\\\'', $string); + // Unescape double quotes + $string = preg_replace('/\\\\+"/', '"', $string); + } + + $strings[] = $string; + } + } + + return array_unique($strings); + } + + /** + * Get all translations informations for all type of translations + * + * array( + * 'type' => array( + * 'name' => string : title for the translation type, + * 'var' => string : name of var for the translation file, + * 'dir' => string : dir of translation file + * 'file' => string : file name of translation file + * ) + * ) + */ + public function getTranslationsInformations() + { + $this->translations_informations = array( + 'front' => array( + 'name' => $this->l('Front office translations'), + 'var' => '_LANG', + 'dir' => defined('_PS_THEME_SELECTED_DIR_') ? _PS_THEME_SELECTED_DIR_.'lang/' : '', + 'file' => $this->lang_selected->iso_code.'.php' + ), + 'back' => array( + 'name' => $this->l('Back office translations'), + 'var' => '_LANGADM', + 'dir' => _PS_TRANSLATIONS_DIR_.$this->lang_selected->iso_code.'/', + 'file' => 'admin.php' + ), + 'errors' => array( + 'name' => $this->l('Error message translations'), + 'var' => '_ERRORS', + 'dir' => _PS_TRANSLATIONS_DIR_.$this->lang_selected->iso_code.'/', + 'file' => 'errors.php' + ), + 'fields' => array( + 'name' => $this->l('Field name translations'), + 'var' => '_FIELDS', + 'dir' => _PS_TRANSLATIONS_DIR_.$this->lang_selected->iso_code.'/', + 'file' => 'fields.php' + ), + 'modules' => array( + 'name' => $this->l('Installed modules translations'), + 'var' => '_MODULES', + 'dir' => _PS_MODULE_DIR_, + 'file' => '' + ), + 'pdf' => array( + 'name' => $this->l('PDF translations'), + 'var' => '_LANGPDF', + 'dir' => _PS_TRANSLATIONS_DIR_.$this->lang_selected->iso_code.'/', + 'file' => 'pdf.php' + ), + 'mails' => array( + 'name' => $this->l('Email templates translations'), + 'var' => '_LANGMAIL', + 'dir' => _PS_MAIL_DIR_.$this->lang_selected->iso_code.'/', + 'file' => 'lang.php' + ) + ); + + if (defined('_PS_THEME_SELECTED_DIR_')) { + $this->translations_informations['modules']['override'] = array('dir' => _PS_THEME_SELECTED_DIR_.'modules/', 'file' => ''); + $this->translations_informations['pdf']['override'] = array('dir' => _PS_THEME_SELECTED_DIR_.'pdf/lang/', 'file' => $this->lang_selected->iso_code.'.php'); + $this->translations_informations['mails']['override'] = array('dir' => _PS_THEME_SELECTED_DIR_.'mails/'.$this->lang_selected->iso_code.'/', 'file' => 'lang.php'); + } + } + + /** + * Get all informations on : languages, theme and the translation type. + */ + public function getInformations() + { + // Get all Languages + $this->languages = Language::getLanguages(false); + + // Get all iso_code of languages + foreach ($this->languages as $language) { + $this->all_iso_lang[] = $language['iso_code']; + } + + // Get all themes + $this->themes = Theme::getThemes(); + + // Get folder name of theme + if (($theme = Tools::getValue('theme')) && !is_array($theme)) { + $theme_exists = $this->theme_exists($theme); + if (!$theme_exists) { + throw new PrestaShopException(sprintf(Tools::displayError('Invalid theme "%s"'), Tools::safeOutput($theme))); + } + $this->theme_selected = Tools::safeOutput($theme); + } + + // Set the path of selected theme + if ($this->theme_selected) { + define('_PS_THEME_SELECTED_DIR_', _PS_ROOT_DIR_.'/themes/'.$this->theme_selected.'/'); + } else { + define('_PS_THEME_SELECTED_DIR_', ''); + } + + // Get type of translation + if (($type = Tools::getValue('type')) && !is_array($type)) { + $this->type_selected = strtolower(Tools::safeOutput($type)); + } + + // Get selected language + if (Tools::getValue('lang') || Tools::getValue('iso_code')) { + $iso_code = Tools::getValue('lang') ? Tools::getValue('lang') : Tools::getValue('iso_code'); + + if (!Validate::isLangIsoCode($iso_code) || !in_array($iso_code, $this->all_iso_lang)) { + throw new PrestaShopException(sprintf(Tools::displayError('Invalid iso code "%s"'), Tools::safeOutput($iso_code))); + } + + $this->lang_selected = new Language((int)Language::getIdByIso($iso_code)); + } else { + $this->lang_selected = new Language((int)Language::getIdByIso('en')); + } + + // Get all information for translations + $this->getTranslationsInformations(); + } + + public function renderKpis() + { + $time = time(); + $kpis = array(); + + /* The data generation is located in AdminStatsControllerCore */ + + $helper = new HelperKpi(); + $helper->id = 'box-languages'; + $helper->icon = 'icon-microphone'; + $helper->color = 'color1'; + $helper->href = $this->context->link->getAdminLink('AdminLanguages'); + $helper->title = $this->l('Enabled Languages', null, null, false); + if (ConfigurationKPI::get('ENABLED_LANGUAGES') !== false) { + $helper->value = ConfigurationKPI::get('ENABLED_LANGUAGES'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=enabled_languages'; + $helper->refresh = (bool)(ConfigurationKPI::get('ENABLED_LANGUAGES_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-country'; + $helper->icon = 'icon-home'; + $helper->color = 'color2'; + $helper->title = $this->l('Main Country', null, null, false); + $helper->subtitle = $this->l('30 Days', null, null, false); + if (ConfigurationKPI::get('MAIN_COUNTRY', $this->context->language->id) !== false) { + $helper->value = ConfigurationKPI::get('MAIN_COUNTRY', $this->context->language->id); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=main_country'; + $helper->refresh = (bool)(ConfigurationKPI::get('MAIN_COUNTRY_EXPIRE', $this->context->language->id) < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpi(); + $helper->id = 'box-translations'; + $helper->icon = 'icon-list'; + $helper->color = 'color3'; + $helper->title = $this->l('Front office Translations', null, null, false); + if (ConfigurationKPI::get('FRONTOFFICE_TRANSLATIONS') !== false) { + $helper->value = ConfigurationKPI::get('FRONTOFFICE_TRANSLATIONS'); + } + $helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=frontoffice_translations'; + $helper->refresh = (bool)(ConfigurationKPI::get('FRONTOFFICE_TRANSLATIONS_EXPIRE') < $time); + $kpis[] = $helper->generate(); + + $helper = new HelperKpiRow(); + $helper->kpis = $kpis; + return $helper->generate(); + } + + /** + * AdminController::postProcess() override + * @see AdminController::postProcess() + */ + public function postProcess() + { + $this->getInformations(); + + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) { + $this->errors[] = Tools::displayError('This functionality has been disabled.'); + return; + } + /* PrestaShop demo mode */ + + try { + if (Tools::isSubmit('submitCopyLang')) { + if ($this->tabAccess['add'] === '1') { + $this->submitCopyLang(); + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } elseif (Tools::isSubmit('submitExport')) { + if ($this->tabAccess['add'] === '1') { + $this->submitExportLang(); + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } elseif (Tools::isSubmit('submitImport')) { + if ($this->tabAccess['add'] === '1') { + $this->submitImportLang(); + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } elseif (Tools::isSubmit('submitAddLanguage')) { + if ($this->tabAccess['add'] === '1') { + $this->submitAddLang(); + } else { + $this->errors[] = Tools::displayError('You do not have permission to add this.'); + } + } elseif (Tools::isSubmit('submitTranslationsPdf')) { + if ($this->tabAccess['edit'] === '1') { + // Only the PrestaShop team should write the translations into the _PS_TRANSLATIONS_DIR_ + if (!$this->theme_selected) { + $this->writeTranslationFile(); + } else { + $this->writeTranslationFile(true); + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('submitTranslationsBack') || Tools::isSubmit('submitTranslationsErrors') || Tools::isSubmit('submitTranslationsFields') || Tools::isSubmit('submitTranslationsFront')) { + if ($this->tabAccess['edit'] === '1') { + $this->writeTranslationFile(); + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('submitTranslationsMails') || Tools::isSubmit('submitTranslationsMailsAndStay')) { + if ($this->tabAccess['edit'] === '1') { + $this->submitTranslationsMails(); + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } elseif (Tools::isSubmit('submitTranslationsModules')) { + if ($this->tabAccess['edit'] === '1') { + // Get list of modules + if ($modules = $this->getListModules()) { + // Get files of all modules + $arr_files = $this->getAllModuleFiles($modules, null, $this->lang_selected->iso_code, true); + + // Find and write all translation modules files + foreach ($arr_files as $value) { + $this->findAndWriteTranslationsIntoFile($value['file_name'], $value['files'], $value['theme'], $value['module'], $value['dir']); + } + + // Clear modules cache + Tools::clearCache(); + + // Redirect + if (Tools::getIsset('submitTranslationsModulesAndStay')) { + $this->redirect(true); + } else { + $this->redirect(); + } + } + } else { + $this->errors[] = Tools::displayError('You do not have permission to edit this.'); + } + } + } catch (PrestaShopException $e) { + $this->errors[] = $e->getMessage(); + } + } + + /** + * This method redirect in the translation main page or in the translation page + * + * @param bool $save_and_stay : true if the user has clicked on the button "save and stay" + * @param bool $conf : id of confirmation message + */ + protected function redirect($save_and_stay = false, $conf = false) + { + $conf = !$conf ? 4 : $conf; + $url_base = self::$currentIndex.'&token='.$this->token.'&conf='.$conf; + if ($save_and_stay) { + Tools::redirectAdmin($url_base.'&lang='.$this->lang_selected->iso_code.'&type='.$this->type_selected.'&theme='.$this->theme_selected); + } else { + Tools::redirectAdmin($url_base); + } + } + + protected function getMailPattern() + { + // Let the indentation like it. + return '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> @@ -1578,751 +1579,754 @@ class AdminTranslationsControllerCore extends AdminController #content </body> </html>'; - } + } - /** - * This method is used to write translation for mails. - * This writes subject translation files - * (in root/mails/lang_choosen/lang.php or root/_PS_THEMES_DIR_/mails/lang_choosen/lang.php) - * and mails files. - */ - protected function submitTranslationsMails() - { - $arr_mail_content = array(); - $arr_mail_path = array(); + /** + * This method is used to write translation for mails. + * This writes subject translation files + * (in root/mails/lang_choosen/lang.php or root/_PS_THEMES_DIR_/mails/lang_choosen/lang.php) + * and mails files. + */ + protected function submitTranslationsMails() + { + $arr_mail_content = array(); + $arr_mail_path = array(); - if (Tools::getValue('core_mail')) - { - $arr_mail_content['core_mail'] = Tools::getValue('core_mail'); + if (Tools::getValue('core_mail')) { + $arr_mail_content['core_mail'] = Tools::getValue('core_mail'); - // Get path of directory for find a good path of translation file - if (!$this->theme_selected) - $arr_mail_path['core_mail'] = $this->translations_informations[$this->type_selected]['dir']; - else - $arr_mail_path['core_mail'] = $this->translations_informations[$this->type_selected]['override']['dir']; - } + // Get path of directory for find a good path of translation file + if (!$this->theme_selected) { + $arr_mail_path['core_mail'] = $this->translations_informations[$this->type_selected]['dir']; + } else { + $arr_mail_path['core_mail'] = $this->translations_informations[$this->type_selected]['override']['dir']; + } + } - if (Tools::getValue('module_mail')) - { - $arr_mail_content['module_mail'] = Tools::getValue('module_mail'); + if (Tools::getValue('module_mail')) { + $arr_mail_content['module_mail'] = Tools::getValue('module_mail'); - // Get path of directory for find a good path of translation file - if (!$this->theme_selected) - $arr_mail_path['module_mail'] = $this->translations_informations['modules']['dir'].'{module}/mails/'.$this->lang_selected->iso_code.'/'; - else - $arr_mail_path['module_mail'] = $this->translations_informations['modules']['override']['dir'].'{module}/mails/'.$this->lang_selected->iso_code.'/'; - } + // Get path of directory for find a good path of translation file + if (!$this->theme_selected) { + $arr_mail_path['module_mail'] = $this->translations_informations['modules']['dir'].'{module}/mails/'.$this->lang_selected->iso_code.'/'; + } else { + $arr_mail_path['module_mail'] = $this->translations_informations['modules']['override']['dir'].'{module}/mails/'.$this->lang_selected->iso_code.'/'; + } + } - // Save each mail content - foreach ($arr_mail_content as $group_name => $all_content) - { - foreach ($all_content as $type_content => $mails) - { - foreach ($mails as $mail_name => $content) - { + // Save each mail content + foreach ($arr_mail_content as $group_name => $all_content) { + foreach ($all_content as $type_content => $mails) { + foreach ($mails as $mail_name => $content) { + $module_name = false; + $module_name_pipe_pos = stripos($mail_name, '|'); + if ($module_name_pipe_pos) { + $module_name = substr($mail_name, 0, $module_name_pipe_pos); + if (!Validate::isModuleName($module_name)) { + throw new PrestaShopException(sprintf(Tools::displayError('Invalid module name "%s"'), Tools::safeOutput($module_name))); + } + $mail_name = substr($mail_name, $module_name_pipe_pos + 1); + if (!Validate::isTplName($mail_name)) { + throw new PrestaShopException(sprintf(Tools::displayError('Invalid mail name "%s"'), Tools::safeOutput($mail_name))); + } + } - $module_name = false; - $module_name_pipe_pos = stripos($mail_name, '|'); - if ($module_name_pipe_pos) - { - $module_name = substr($mail_name, 0, $module_name_pipe_pos); - if (!Validate::isModuleName($module_name)) - throw new PrestaShopException(sprintf(Tools::displayError('Invalid module name "%s"'), Tools::safeOutput($module_name))); - $mail_name = substr($mail_name, $module_name_pipe_pos + 1); - if (!Validate::isTplName($mail_name)) - throw new PrestaShopException(sprintf(Tools::displayError('Invalid mail name "%s"'), Tools::safeOutput($mail_name))); - } + if ($type_content == 'html') { + $content = Tools::htmlentitiesUTF8($content); + $content = htmlspecialchars_decode($content); + // replace correct end of line + $content = str_replace("\r\n", PHP_EOL, $content); - if ($type_content == 'html') - { - $content = Tools::htmlentitiesUTF8($content); - $content = htmlspecialchars_decode($content); - // replace correct end of line - $content = str_replace("\r\n", PHP_EOL, $content); + $title = ''; + if (Tools::getValue('title_'.$group_name.'_'.$mail_name)) { + $title = Tools::getValue('title_'.$group_name.'_'.$mail_name); + } + $string_mail = $this->getMailPattern(); + $content = str_replace(array('#title', '#content'), array($title, $content), $string_mail); - $title = ''; - if (Tools::getValue('title_'.$group_name.'_'.$mail_name)) - $title = Tools::getValue('title_'.$group_name.'_'.$mail_name); - $string_mail = $this->getMailPattern(); - $content = str_replace(array('#title', '#content'), array($title, $content), $string_mail); + // Magic Quotes shall... not.. PASS! + if (_PS_MAGIC_QUOTES_GPC_) { + $content = stripslashes($content); + } + } - // Magic Quotes shall... not.. PASS! - if (_PS_MAGIC_QUOTES_GPC_) - $content = stripslashes($content); - } + if (Validate::isCleanHTML($content)) { + $path = $arr_mail_path[$group_name]; + if ($module_name) { + $path = str_replace('{module}', $module_name, $path); + } + if (!file_exists($path) && !mkdir($path, 0777, true)) { + throw new PrestaShopException(sprintf(Tools::displayError('Directory "%s" cannot be created'), dirname($path))); + } + file_put_contents($path.$mail_name.'.'.$type_content, Tools::purifyHTML($content, array('{', '}'), true)); + } else { + throw new PrestaShopException(Tools::displayError('Your HTML email templates cannot contain JavaScript code.')); + } + } + } + } - if (Validate::isCleanHTML($content)) - { - $path = $arr_mail_path[$group_name]; - if ($module_name) - $path = str_replace('{module}', $module_name, $path); - if (!file_exists($path) && !mkdir($path, 0777, true)) - throw new PrestaShopException(sprintf(Tools::displayError('Directory "%s" cannot be created'), dirname($path))); - file_put_contents($path.$mail_name.'.'.$type_content, Tools::purifyHTML($content, array('{', '}'), true)); - } - else - throw new PrestaShopException(Tools::displayError('Your HTML email templates cannot contain JavaScript code.')); - } - } - } + // Update subjects + $array_subjects = array(); + if (($subjects = Tools::getValue('subject')) && is_array($subjects)) { + $array_subjects['core_and_modules'] = array('translations' => array(), 'path' => $arr_mail_path['core_mail'].'lang.php'); + foreach ($subjects as $subject_translation) { + $array_subjects['core_and_modules']['translations'] = array_merge($array_subjects['core_and_modules']['translations'], $subject_translation); + } + } + if (!empty($array_subjects)) { + foreach ($array_subjects as $infos) { + $this->writeSubjectTranslationFile($infos['translations'], $infos['path']); + } + } - // Update subjects - $array_subjects = array(); - if (($subjects = Tools::getValue('subject')) && is_array($subjects)) - { - $array_subjects['core_and_modules'] = array('translations' => array(), 'path' => $arr_mail_path['core_mail'].'lang.php'); - foreach ($subjects as $subject_translation) - $array_subjects['core_and_modules']['translations'] = array_merge($array_subjects['core_and_modules']['translations'], $subject_translation); - } - if (!empty($array_subjects)) - foreach ($array_subjects as $infos) - $this->writeSubjectTranslationFile($infos['translations'], $infos['path']); + if (Tools::isSubmit('submitTranslationsMailsAndStay')) { + $this->redirect(true); + } else { + $this->redirect(); + } + } - if (Tools::isSubmit('submitTranslationsMailsAndStay')) - $this->redirect(true); - else - $this->redirect(); - } + /** + * Include file $dir/$file and return the var $var declared in it. + * This create the file if not exists + * + * return array : translations + */ + public function fileExists() + { + $var = $this->translations_informations[$this->type_selected]['var']; + $dir = $this->translations_informations[$this->type_selected]['dir']; + $file = $this->translations_informations[$this->type_selected]['file']; - /** - * Include file $dir/$file and return the var $var declared in it. - * This create the file if not exists - * - * return array : translations - */ - public function fileExists() - { - $var = $this->translations_informations[$this->type_selected]['var']; - $dir = $this->translations_informations[$this->type_selected]['dir']; - $file = $this->translations_informations[$this->type_selected]['file']; + $$var = array(); + if (!Tools::file_exists_cache($dir)) { + if (!mkdir($dir, 0700)) { + throw new PrestaShopException('Directory '.$dir.' cannot be created.'); + } + } + if (!Tools::file_exists_cache($dir.DIRECTORY_SEPARATOR.$file)) { + if (!file_put_contents($dir.'/'.$file, "<?php\n\nglobal \$".$var.";\n\$".$var." = array();\n\n?>")) { + throw new PrestaShopException('File "'.$file.'" doesn\'t exists and cannot be created in '.$dir); + } + } + if (!is_writable($dir.DIRECTORY_SEPARATOR.$file)) { + $this->displayWarning(Tools::displayError('This file must be writable:').' '.$dir.'/'.$file); + } + include($dir.DIRECTORY_SEPARATOR.$file); + return $$var; + } - $$var = array(); - if (!Tools::file_exists_cache($dir)) - if (!mkdir($dir, 0700)) - throw new PrestaShopException('Directory '.$dir.' cannot be created.'); - if (!Tools::file_exists_cache($dir.DIRECTORY_SEPARATOR.$file)) - if (!file_put_contents($dir.'/'.$file, "<?php\n\nglobal \$".$var.";\n\$".$var." = array();\n\n?>")) - throw new PrestaShopException('File "'.$file.'" doesn\'t exists and cannot be created in '.$dir); - if (!is_writable($dir.DIRECTORY_SEPARATOR.$file)) - $this->displayWarning(Tools::displayError('This file must be writable:').' '.$dir.'/'.$file); - include($dir.DIRECTORY_SEPARATOR.$file); - return $$var; - } - - public function displayToggleButton($closed = false) - { - $str_output = ' + public function displayToggleButton($closed = false) + { + $str_output = ' <script type="text/javascript">'; - if (Tools::getValue('type') == 'mails') - $str_output .= '$(document).ready(function(){ + if (Tools::getValue('type') == 'mails') { + $str_output .= '$(document).ready(function(){ toggleDiv(\''.$this->type_selected.'_div\'); toggleButtonValue(this.id, openAll, closeAll); });'; - $str_output .= ' + } + $str_output .= ' var openAll = \''.html_entity_decode($this->l('Expand all fieldsets'), ENT_NOQUOTES, 'UTF-8').'\'; var closeAll = \''.html_entity_decode($this->l('Close all fieldsets'), ENT_NOQUOTES, 'UTF-8').'\'; </script> <button type="button" class="btn btn-default" id="buttonall" data-status="open" onclick="toggleDiv(\''.$this->type_selected.'_div\', $(this).data(\'status\')); toggleButtonValue(this.id, openAll, closeAll);"><i class="process-icon-compress"></i> <span>'.$this->l('Close all fieldsets').'</span></button>'; - return $str_output; - } - - public function displayLimitPostWarning($count) - { - $return = array(); - if ((ini_get('suhosin.post.max_vars') && ini_get('suhosin.post.max_vars') < $count) || (ini_get('suhosin.request.max_vars') && ini_get('suhosin.request.max_vars') < $count)) - { - $return['error_type'] = 'suhosin'; - $return['post.max_vars'] = ini_get('suhosin.post.max_vars'); - $return['request.max_vars'] = ini_get('suhosin.request.max_vars'); - $return['needed_limit'] = $count + 100; - } - elseif (ini_get('max_input_vars') && ini_get('max_input_vars') < $count) - { - $return['error_type'] = 'conf'; - $return['max_input_vars'] = ini_get('max_input_vars'); - $return['needed_limit'] = $count + 100; - } - return $return; - } - - /** - * Find sentence which use %d, %s, %%, %1$d, %1$s... - * - * @param $key : english sentence - * @return array|bool return list of matches - */ - public function checkIfKeyUseSprintf($key) - { - if (preg_match_all('#(?:%%|%(?:[0-9]+\$)?[+-]?(?:[ 0]|\'.)?-?[0-9]*(?:\.[0-9]+)?[bcdeufFosxX])#', $key, $matches)) - return implode(', ', $matches[0]); - return false; - } - - /** - * This method generate the form for front translations - */ - public function initFormFront() - { - if (!$this->theme_exists(Tools::getValue('theme'))) - { - $this->errors[] = sprintf(Tools::displayError('Invalid theme "%s"'), Tools::getValue('theme')); - return; - } - - $missing_translations_front = array(); - $name_var = $this->translations_informations[$this->type_selected]['var']; - $GLOBALS[$name_var] = $this->fileExists(); - - /* List templates to parse */ - $files_by_directory = $this->getFileToParseByTypeTranslation(); - $count = 0; - $tabs_array = array(); - foreach ($files_by_directory['tpl'] as $dir => $files) - { - $prefix = ''; - if ($dir == _PS_THEME_OVERRIDE_DIR_) - $prefix = 'override_'; - - foreach ($files as $file) - { - if (preg_match('/^(.*).tpl$/', $file) && (Tools::file_exists_cache($file_path = $dir.$file))) - { - $prefix_key = $prefix.substr(basename($file), 0, -4); - $new_lang = array(); - - // Get content for this file - $content = file_get_contents($file_path); - - // Parse this content - $matches = $this->userParseFile($content, $this->type_selected); - - /* Get string translation */ - foreach ($matches as $key) - { - if (empty($key)) - { - $this->errors[] = sprintf($this->l('Empty string found, please edit: "%s"'), $file_path); - $new_lang[$key] = ''; - } - else - { - // Caution ! front has underscore between prefix key and md5, back has not - if (isset($GLOBALS[$name_var][$prefix_key.'_'.md5($key)])) - $new_lang[$key]['trad'] = stripslashes(html_entity_decode($GLOBALS[$name_var][$prefix_key.'_'.md5($key)], ENT_COMPAT, 'UTF-8')); - else - { - if (!isset($new_lang[$key]['trad'])) - { - $new_lang[$key]['trad'] = ''; - if (!isset($missing_translations_front[$prefix_key])) - $missing_translations_front[$prefix_key] = 1; - else - $missing_translations_front[$prefix_key]++; - } - } - $new_lang[$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); - } - } - - if (isset($tabs_array[$prefix_key])) - $tabs_array[$prefix_key] = array_merge($tabs_array[$prefix_key], $new_lang); - else - $tabs_array[$prefix_key] = $new_lang; - - $count += count($new_lang); - } - } - } - - $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( - 'missing_translations' => $missing_translations_front, - 'count' => $count, - 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), - 'limit_warning' => $this->displayLimitPostWarning($count), - 'mod_security_warning' => Tools::apacheModExists('mod_security'), - 'tabsArray' => $tabs_array, - )); - - $this->initToolbar(); - $this->base_tpl_view = 'translation_form.tpl'; - return parent::renderView(); - } - - /** - * This method generate the form for back translations - */ - public function initFormBack() - { - $name_var = $this->translations_informations[$this->type_selected]['var']; - $GLOBALS[$name_var] = $this->fileExists(); - $missing_translations_back = array(); - - // Get all types of file (PHP, TPL...) and a list of files to parse by folder - $files_per_directory = $this->getFileToParseByTypeTranslation(); - - foreach ($files_per_directory['php'] as $dir => $files) - foreach ($files as $file) - // Check if is a PHP file and if the override file exists - if (preg_match('/^(.*)\.php$/', $file) && Tools::file_exists_cache($file_path = $dir.$file) && !in_array($file, self::$ignore_folder)) - { - $prefix_key = basename($file); - // -4 becomes -14 to remove the ending "Controller.php" from the filename - if (strpos($file, 'Controller.php') !== false) - $prefix_key = basename(substr($file, 0, -14)); - elseif (strpos($file, 'Helper') !== false) - $prefix_key = 'Helper'; - - if ($prefix_key == 'Admin') - $prefix_key = 'AdminController'; - - if ($prefix_key == 'PaymentModule.php') - $prefix_key = 'PaymentModule'; - - // Get content for this file - $content = file_get_contents($file_path); - - // Parse this content - $matches = $this->userParseFile($content, $this->type_selected, 'php'); - - foreach ($matches as $key) - { - // Caution ! front has underscore between prefix key and md5, back has not - if (isset($GLOBALS[$name_var][$prefix_key.md5($key)])) - $tabs_array[$prefix_key][$key]['trad'] = stripslashes(html_entity_decode($GLOBALS[$name_var][$prefix_key.md5($key)], ENT_COMPAT, 'UTF-8')); - else - { - if (!isset($tabs_array[$prefix_key][$key]['trad'])) - { - $tabs_array[$prefix_key][$key]['trad'] = ''; - if (!isset($missing_translations_back[$prefix_key])) - $missing_translations_back[$prefix_key] = 1; - else - $missing_translations_back[$prefix_key]++; - } - } - $tabs_array[$prefix_key][$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); - } - } - - foreach ($files_per_directory['specific'] as $dir => $files) - foreach ($files as $file) - if (Tools::file_exists_cache($file_path = $dir.$file) && !in_array($file, self::$ignore_folder)) - { - $prefix_key = 'index'; - - // Get content for this file - $content = file_get_contents($file_path); - - // Parse this content - $matches = $this->userParseFile($content, $this->type_selected, 'specific'); - - foreach ($matches as $key) - { - // Caution ! front has underscore between prefix key and md5, back has not - if (isset($GLOBALS[$name_var][$prefix_key.md5($key)])) - $tabs_array[$prefix_key][$key]['trad'] = stripslashes(html_entity_decode($GLOBALS[$name_var][$prefix_key.md5($key)], ENT_COMPAT, 'UTF-8')); - else - { - if (!isset($tabs_array[$prefix_key][$key]['trad'])) - { - $tabs_array[$prefix_key][$key]['trad'] = ''; - if (!isset($missing_translations_back[$prefix_key])) - $missing_translations_back[$prefix_key] = 1; - else - $missing_translations_back[$prefix_key]++; - } - } - $tabs_array[$prefix_key][$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); - } - } - - foreach ($files_per_directory['tpl'] as $dir => $files) - foreach ($files as $file) - if (preg_match('/^(.*).tpl$/', $file) && Tools::file_exists_cache($file_path = $dir.$file)) - { - // get controller name instead of file name - $prefix_key = Tools::toCamelCase(str_replace(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes', '', $file_path), true); - $pos = strrpos($prefix_key, DIRECTORY_SEPARATOR); - $tmp = substr($prefix_key, 0, $pos); - - if (preg_match('#controllers#', $tmp)) - { - $parent_class = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $tmp)); - $override = array_search('override', $parent_class); - if ($override !== false) - // case override/controllers/admin/templates/controller_name - $prefix_key = 'Admin'.ucfirst($parent_class[$override + 4]); - else - { - // case admin_name/themes/theme_name/template/controllers/controller_name - $key = array_search('controllers', $parent_class); - $prefix_key = 'Admin'.ucfirst($parent_class[$key + 1]); - } - } - else - $prefix_key = 'Admin'.ucfirst(substr($tmp, strrpos($tmp, DIRECTORY_SEPARATOR) + 1, $pos)); - - // Adding list, form, option in Helper Translations - $list_prefix_key = array('AdminHelpers', 'AdminList', 'AdminView', 'AdminOptions', 'AdminForm', - 'AdminCalendar', 'AdminTree', 'AdminUploader', 'AdminDataviz', 'AdminKpi', 'AdminModule_list', 'AdminModulesList'); - if (in_array($prefix_key, $list_prefix_key)) - $prefix_key = 'Helper'; - - // Adding the folder backup/download/ in AdminBackup Translations - if ($prefix_key == 'AdminDownload') - $prefix_key = 'AdminBackup'; - - // use the prefix "AdminController" (like old php files 'header', 'footer.inc', 'index', 'login', 'password', 'functions' - if ($prefix_key == 'Admin' || $prefix_key == 'AdminTemplate') - $prefix_key = 'AdminController'; - - $new_lang = array(); - - // Get content for this file - $content = file_get_contents($file_path); - - // Parse this content - $matches = $this->userParseFile($content, $this->type_selected, 'tpl'); - - /* Get string translation for each tpl file */ - foreach ($matches as $english_string) - { - if (empty($english_string)) - { - $this->errors[] = sprintf($this->l('There is an error in template, an empty string has been found. Please edit: "%s"'), $file_path); - $new_lang[$english_string] = ''; - } - else - { - $trans_key = $prefix_key.md5($english_string); - - if (isset($GLOBALS[$name_var][$trans_key])) - $new_lang[$english_string]['trad'] = html_entity_decode($GLOBALS[$name_var][$trans_key], ENT_COMPAT, 'UTF-8'); - else - { - if (!isset($new_lang[$english_string]['trad'])) - { - $new_lang[$english_string]['trad'] = ''; - if (!isset($missing_translations_back[$prefix_key])) - $missing_translations_back[$prefix_key] = 1; - else - $missing_translations_back[$prefix_key]++; - } - } - $new_lang[$english_string]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); - } - } - if (isset($tabs_array[$prefix_key])) - $tabs_array[$prefix_key] = array_merge($tabs_array[$prefix_key], $new_lang); - else - $tabs_array[$prefix_key] = $new_lang; - } - - - // count will contain the number of expressions of the page - $count = 0; - foreach ($tabs_array as $array) - $count += count($array); - - $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( - 'count' => $count, - 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), - 'limit_warning' => $this->displayLimitPostWarning($count), - 'mod_security_warning' => Tools::apacheModExists('mod_security'), - 'tabsArray' => $tabs_array, - 'missing_translations' => $missing_translations_back - )); - - $this->initToolbar(); - $this->base_tpl_view = 'translation_form.tpl'; - return parent::renderView(); - } - - /** - * Check if directory and file exist and return an list of modules - * - * @return array List of modules - * @throws PrestaShopException - */ - public function getListModules() - { - if (!Tools::file_exists_cache($this->translations_informations['modules']['dir'])) - throw new PrestaShopException(Tools::displayError('Fatal error: The module directory does not exist.').'('.$this->translations_informations['modules']['dir'].')'); - if (!is_writable($this->translations_informations['modules']['dir'])) - throw new PrestaShopException(Tools::displayError('The module directory must be writable.')); - - $modules = array(); - // Get all module which are installed for to have a minimum of POST - $modules = Module::getModulesInstalled(); - foreach ($modules as &$module) - $module = $module['name']; - - return $modules; - } - - /** - * This method generate the form for errors translations - */ - public function initFormErrors() - { - $name_var = $this->translations_informations[$this->type_selected]['var']; - $GLOBALS[$name_var] = $this->fileExists(); - $count_empty = array(); - - /* List files to parse */ - $string_to_translate = array(); - $file_by_directory = $this->getFileToParseByTypeTranslation(); - - if ($modules = $this->getListModules()) - { - foreach ($modules as $module) - if (is_dir(_PS_MODULE_DIR_.$module) && !in_array($module, self::$ignore_folder)) - $file_by_directory['php'] = array_merge($file_by_directory['php'], $this->listFiles(_PS_MODULE_DIR_.$module.'/', array(), 'php')); - } - - foreach ($file_by_directory['php'] as $dir => $files) - foreach ($files as $file) - if (preg_match('/\.php$/', $file) && Tools::file_exists_cache($file_path = $dir.$file) && !in_array($file, self::$ignore_folder)) - { - if (!filesize($file_path)) - continue; - - // Get content for this file - $content = file_get_contents($file_path); - - // Parse this content - $matches = $this->userParseFile($content, $this->type_selected); - - foreach ($matches as $key) - { - if (array_key_exists(md5($key), $GLOBALS[$name_var])) - $string_to_translate[$key]['trad'] = html_entity_decode($GLOBALS[$name_var][md5($key)], ENT_COMPAT, 'UTF-8'); - else - { - $string_to_translate[$key]['trad'] = ''; - if (!isset($count_empty[$key])) - $count_empty[$key] = 1; - } - $string_to_translate[$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); - } - } - - $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( - 'count' => count($string_to_translate), - 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), - 'limit_warning' => $this->displayLimitPostWarning(count($string_to_translate)), - 'mod_security_warning' => Tools::apacheModExists('mod_security'), - 'errorsArray' => $string_to_translate, - 'missing_translations' => $count_empty - )); - - $this->initToolbar(); - $this->base_tpl_view = 'translation_errors.tpl'; - return parent::renderView(); - } - - /** - * This method generate the form for fields translations - */ - public function initFormFields() - { - $name_var = $this->translations_informations[$this->type_selected]['var']; - $GLOBALS[$name_var] = $this->fileExists(); - $missing_translations_fields = array(); - $class_array = array(); - $tabs_array = array(); - $count = 0; - - $files_by_directory = $this->getFileToParseByTypeTranslation(); - - foreach ($files_by_directory['php'] as $dir => $files) - foreach ($files as $file) - { - $exclude_files = array('index.php', 'PrestaShopAutoload.php', 'StockManagerInterface.php', - 'TaxManagerInterface.php', 'WebserviceOutputInterface.php', 'WebserviceSpecificManagementInterface.php'); - - if (!preg_match('/\.php$/', $file) || in_array($file, $exclude_files)) - continue; - - $class_name = substr($file, 0, -4); - - if (!class_exists($class_name, false) && !class_exists($class_name.'Core', false)) - PrestaShopAutoload::getInstance()->load($class_name); - - if (!is_subclass_of($class_name.'Core', 'ObjectModel')) - continue; - $class_array[$class_name] = call_user_func(array($class_name, 'getValidationRules'), $class_name); - } - foreach ($class_array as $prefix_key => $rules) - { - if (isset($rules['validate'])) - foreach ($rules['validate'] as $key => $value) - { - if (isset($GLOBALS[$name_var][$prefix_key.'_'.md5($key)])) - { - $tabs_array[$prefix_key][$key]['trad'] = html_entity_decode($GLOBALS[$name_var][$prefix_key.'_'.md5($key)], ENT_COMPAT, 'UTF-8'); - $count++; - } - else - { - if (!isset($tabs_array[$prefix_key][$key]['trad'])) - { - $tabs_array[$prefix_key][$key]['trad'] = ''; - if (!isset($missing_translations_fields[$prefix_key])) - $missing_translations_fields[$prefix_key] = 1; - else - $missing_translations_fields[$prefix_key]++; - $count++; - } - } - } - if (isset($rules['validateLang'])) - foreach ($rules['validateLang'] as $key => $value) - { - if (isset($GLOBALS[$name_var][$prefix_key.'_'.md5($key)])) - { - $tabs_array[$prefix_key][$key]['trad'] = ''; - if (array_key_exists($prefix_key.'_'.md5(addslashes($key)), $GLOBALS[$name_var])) - $tabs_array[$prefix_key][$key]['trad'] = html_entity_decode($GLOBALS[$name_var][$prefix_key.'_'.md5(addslashes($key))], ENT_COMPAT, 'UTF-8'); - - $count++; - } - else - { - if (!isset($tabs_array[$prefix_key][$key]['trad'])) - { - $tabs_array[$prefix_key][$key]['trad'] = ''; - if (!isset($missing_translations_fields[$prefix_key])) - $missing_translations_fields[$prefix_key] = 1; - else - $missing_translations_fields[$prefix_key]++; - $count++; - } - } - } - } - - $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( - 'count' => $count, - 'limit_warning' => $this->displayLimitPostWarning($count), - 'mod_security_warning' => Tools::apacheModExists('mod_security'), - 'tabsArray' => $tabs_array, - 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), - 'missing_translations' => $missing_translations_fields - )); - - $this->initToolbar(); - $this->base_tpl_view = 'translation_form.tpl'; - return parent::renderView(); - } - - /** - * Get each informations for each mails found in the folder $dir. - * - * @since 1.4.0.14 - * @param string $dir - * @param string $group_name - * @return array : list of mails - */ - public function getMailFiles($dir, $group_name = 'mail') - { - $arr_return = array(); - if (Language::getIdByIso('en')) - $default_language = 'en'; - else - $default_language = Language::getIsoById((int)Configuration::get('PS_LANG_DEFAULT')); - if (!$default_language || !Validate::isLanguageIsoCode($default_language)) - return false; - - // Very usefull to name input and textarea fields - $arr_return['group_name'] = $group_name; - $arr_return['empty_values'] = 0; - $arr_return['total_filled'] = 0; - $arr_return['directory'] = $dir; - - // Get path for english mail directory - $dir_en = str_replace('/'.$this->lang_selected->iso_code.'/', '/'.$default_language.'/', $dir); - - if (Tools::file_exists_cache($dir_en)) - { - // Get all english files to compare with the language to translate - foreach (scandir($dir_en) as $email_file) - { - if (strripos($email_file, '.html') > 0 || strripos($email_file, '.txt') > 0) - { - $email_name = substr($email_file, 0, strripos($email_file, '.')); - $type = substr($email_file, strripos($email_file, '.') + 1); - if (!isset($arr_return['files'][$email_name])) - $arr_return['files'][$email_name] = array(); - // $email_file is from scandir ($dir), so we already know that file exists - $arr_return['files'][$email_name][$type]['en'] = $this->getMailContent($dir_en, $email_file); - - // check if the file exists in the language to translate - if (Tools::file_exists_cache($dir.'/'.$email_file)) - { - $arr_return['files'][$email_name][$type][$this->lang_selected->iso_code] = $this->getMailContent($dir, $email_file); - $this->total_expression++; - } - else - $arr_return['files'][$email_name][$type][$this->lang_selected->iso_code] = ''; - - if ($arr_return['files'][$email_name][$type][$this->lang_selected->iso_code] == '') - $arr_return['empty_values']++; - else - $arr_return['total_filled']++; - } - } - } - else - $this->warnings[] = sprintf(Tools::displayError('A mail directory exists for the "%1$s" language, but not for the default language (%3$s) in %2$s'), - $this->lang_selected->iso_code, str_replace(_PS_ROOT_DIR_, '', dirname($dir)), $default_language); - return $arr_return; - } - - /** - * Get content of the mail file. - * - * @since 1.4.0.14 - * @param string $dir - * @param string $file - * @return array : content of file - */ - protected function getMailContent($dir, $file) - { - $content = file_get_contents($dir.'/'.$file); - - if (Tools::strlen($content) === 0) - $content = ''; - return $content; - } - - /** - * Display mails in html format. - * This was create for factorize the html displaying - * @since 1.4.0.14 - * - * @param array $mails - * @param array $all_subject_mail - * @param Language $obj_lang - * @param string $id_html Use for set html id attribute for the block - * @param string $title Set the title for the block - * @param string|bool $name_for_module Is not false define add a name for distinguish mails module - * - * @return string - */ - protected function displayMailContent($mails, $all_subject_mail, $obj_lang, $id_html, $title, $name_for_module = false) - { - $str_return = ''; - $group_name = 'mail'; - if (array_key_exists('group_name', $mails)) - $group_name = $mails['group_name']; - - if($mails['empty_values'] == 0) { - $translation_missing_badge_type = 'badge-success'; - } else { - $translation_missing_badge_type = 'badge-danger'; - } - - $str_return .= '<div class="mails_field"> + return $str_output; + } + + public function displayLimitPostWarning($count) + { + $return = array(); + if ((ini_get('suhosin.post.max_vars') && ini_get('suhosin.post.max_vars') < $count) || (ini_get('suhosin.request.max_vars') && ini_get('suhosin.request.max_vars') < $count)) { + $return['error_type'] = 'suhosin'; + $return['post.max_vars'] = ini_get('suhosin.post.max_vars'); + $return['request.max_vars'] = ini_get('suhosin.request.max_vars'); + $return['needed_limit'] = $count + 100; + } elseif (ini_get('max_input_vars') && ini_get('max_input_vars') < $count) { + $return['error_type'] = 'conf'; + $return['max_input_vars'] = ini_get('max_input_vars'); + $return['needed_limit'] = $count + 100; + } + return $return; + } + + /** + * Find sentence which use %d, %s, %%, %1$d, %1$s... + * + * @param $key : english sentence + * @return array|bool return list of matches + */ + public function checkIfKeyUseSprintf($key) + { + if (preg_match_all('#(?:%%|%(?:[0-9]+\$)?[+-]?(?:[ 0]|\'.)?-?[0-9]*(?:\.[0-9]+)?[bcdeufFosxX])#', $key, $matches)) { + return implode(', ', $matches[0]); + } + return false; + } + + /** + * This method generate the form for front translations + */ + public function initFormFront() + { + if (!$this->theme_exists(Tools::getValue('theme'))) { + $this->errors[] = sprintf(Tools::displayError('Invalid theme "%s"'), Tools::getValue('theme')); + return; + } + + $missing_translations_front = array(); + $name_var = $this->translations_informations[$this->type_selected]['var']; + $GLOBALS[$name_var] = $this->fileExists(); + + /* List templates to parse */ + $files_by_directory = $this->getFileToParseByTypeTranslation(); + $count = 0; + $tabs_array = array(); + foreach ($files_by_directory['tpl'] as $dir => $files) { + $prefix = ''; + if ($dir == _PS_THEME_OVERRIDE_DIR_) { + $prefix = 'override_'; + } + + foreach ($files as $file) { + if (preg_match('/^(.*).tpl$/', $file) && (Tools::file_exists_cache($file_path = $dir.$file))) { + $prefix_key = $prefix.substr(basename($file), 0, -4); + $new_lang = array(); + + // Get content for this file + $content = file_get_contents($file_path); + + // Parse this content + $matches = $this->userParseFile($content, $this->type_selected); + + /* Get string translation */ + foreach ($matches as $key) { + if (empty($key)) { + $this->errors[] = sprintf($this->l('Empty string found, please edit: "%s"'), $file_path); + $new_lang[$key] = ''; + } else { + // Caution ! front has underscore between prefix key and md5, back has not + if (isset($GLOBALS[$name_var][$prefix_key.'_'.md5($key)])) { + $new_lang[$key]['trad'] = stripslashes(html_entity_decode($GLOBALS[$name_var][$prefix_key.'_'.md5($key)], ENT_COMPAT, 'UTF-8')); + } else { + if (!isset($new_lang[$key]['trad'])) { + $new_lang[$key]['trad'] = ''; + if (!isset($missing_translations_front[$prefix_key])) { + $missing_translations_front[$prefix_key] = 1; + } else { + $missing_translations_front[$prefix_key]++; + } + } + } + $new_lang[$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); + } + } + + if (isset($tabs_array[$prefix_key])) { + $tabs_array[$prefix_key] = array_merge($tabs_array[$prefix_key], $new_lang); + } else { + $tabs_array[$prefix_key] = $new_lang; + } + + $count += count($new_lang); + } + } + } + + $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( + 'missing_translations' => $missing_translations_front, + 'count' => $count, + 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), + 'limit_warning' => $this->displayLimitPostWarning($count), + 'mod_security_warning' => Tools::apacheModExists('mod_security'), + 'tabsArray' => $tabs_array, + )); + + $this->initToolbar(); + $this->base_tpl_view = 'translation_form.tpl'; + return parent::renderView(); + } + + /** + * This method generate the form for back translations + */ + public function initFormBack() + { + $name_var = $this->translations_informations[$this->type_selected]['var']; + $GLOBALS[$name_var] = $this->fileExists(); + $missing_translations_back = array(); + + // Get all types of file (PHP, TPL...) and a list of files to parse by folder + $files_per_directory = $this->getFileToParseByTypeTranslation(); + + foreach ($files_per_directory['php'] as $dir => $files) { + foreach ($files as $file) { + // Check if is a PHP file and if the override file exists + if (preg_match('/^(.*)\.php$/', $file) && Tools::file_exists_cache($file_path = $dir.$file) && !in_array($file, self::$ignore_folder)) { + $prefix_key = basename($file); + // -4 becomes -14 to remove the ending "Controller.php" from the filename + if (strpos($file, 'Controller.php') !== false) { + $prefix_key = basename(substr($file, 0, -14)); + } elseif (strpos($file, 'Helper') !== false) { + $prefix_key = 'Helper'; + } + + if ($prefix_key == 'Admin') { + $prefix_key = 'AdminController'; + } + + if ($prefix_key == 'PaymentModule.php') { + $prefix_key = 'PaymentModule'; + } + + // Get content for this file + $content = file_get_contents($file_path); + + // Parse this content + $matches = $this->userParseFile($content, $this->type_selected, 'php'); + + foreach ($matches as $key) { + // Caution ! front has underscore between prefix key and md5, back has not + if (isset($GLOBALS[$name_var][$prefix_key.md5($key)])) { + $tabs_array[$prefix_key][$key]['trad'] = stripslashes(html_entity_decode($GLOBALS[$name_var][$prefix_key.md5($key)], ENT_COMPAT, 'UTF-8')); + } else { + if (!isset($tabs_array[$prefix_key][$key]['trad'])) { + $tabs_array[$prefix_key][$key]['trad'] = ''; + if (!isset($missing_translations_back[$prefix_key])) { + $missing_translations_back[$prefix_key] = 1; + } else { + $missing_translations_back[$prefix_key]++; + } + } + } + $tabs_array[$prefix_key][$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); + } + } + } + } + + foreach ($files_per_directory['specific'] as $dir => $files) { + foreach ($files as $file) { + if (Tools::file_exists_cache($file_path = $dir.$file) && !in_array($file, self::$ignore_folder)) { + $prefix_key = 'index'; + + // Get content for this file + $content = file_get_contents($file_path); + + // Parse this content + $matches = $this->userParseFile($content, $this->type_selected, 'specific'); + + foreach ($matches as $key) { + // Caution ! front has underscore between prefix key and md5, back has not + if (isset($GLOBALS[$name_var][$prefix_key.md5($key)])) { + $tabs_array[$prefix_key][$key]['trad'] = stripslashes(html_entity_decode($GLOBALS[$name_var][$prefix_key.md5($key)], ENT_COMPAT, 'UTF-8')); + } else { + if (!isset($tabs_array[$prefix_key][$key]['trad'])) { + $tabs_array[$prefix_key][$key]['trad'] = ''; + if (!isset($missing_translations_back[$prefix_key])) { + $missing_translations_back[$prefix_key] = 1; + } else { + $missing_translations_back[$prefix_key]++; + } + } + } + $tabs_array[$prefix_key][$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); + } + } + } + } + + foreach ($files_per_directory['tpl'] as $dir => $files) { + foreach ($files as $file) { + if (preg_match('/^(.*).tpl$/', $file) && Tools::file_exists_cache($file_path = $dir.$file)) { + // get controller name instead of file name + $prefix_key = Tools::toCamelCase(str_replace(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes', '', $file_path), true); + $pos = strrpos($prefix_key, DIRECTORY_SEPARATOR); + $tmp = substr($prefix_key, 0, $pos); + + if (preg_match('#controllers#', $tmp)) { + $parent_class = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $tmp)); + $override = array_search('override', $parent_class); + if ($override !== false) { + // case override/controllers/admin/templates/controller_name + $prefix_key = 'Admin'.ucfirst($parent_class[$override + 4]); + } else { + // case admin_name/themes/theme_name/template/controllers/controller_name + $key = array_search('controllers', $parent_class); + $prefix_key = 'Admin'.ucfirst($parent_class[$key + 1]); + } + } else { + $prefix_key = 'Admin'.ucfirst(substr($tmp, strrpos($tmp, DIRECTORY_SEPARATOR) + 1, $pos)); + } + + // Adding list, form, option in Helper Translations + $list_prefix_key = array('AdminHelpers', 'AdminList', 'AdminView', 'AdminOptions', 'AdminForm', + 'AdminCalendar', 'AdminTree', 'AdminUploader', 'AdminDataviz', 'AdminKpi', 'AdminModule_list', 'AdminModulesList'); + if (in_array($prefix_key, $list_prefix_key)) { + $prefix_key = 'Helper'; + } + + // Adding the folder backup/download/ in AdminBackup Translations + if ($prefix_key == 'AdminDownload') { + $prefix_key = 'AdminBackup'; + } + + // use the prefix "AdminController" (like old php files 'header', 'footer.inc', 'index', 'login', 'password', 'functions' + if ($prefix_key == 'Admin' || $prefix_key == 'AdminTemplate') { + $prefix_key = 'AdminController'; + } + + $new_lang = array(); + + // Get content for this file + $content = file_get_contents($file_path); + + // Parse this content + $matches = $this->userParseFile($content, $this->type_selected, 'tpl'); + + /* Get string translation for each tpl file */ + foreach ($matches as $english_string) { + if (empty($english_string)) { + $this->errors[] = sprintf($this->l('There is an error in template, an empty string has been found. Please edit: "%s"'), $file_path); + $new_lang[$english_string] = ''; + } else { + $trans_key = $prefix_key.md5($english_string); + + if (isset($GLOBALS[$name_var][$trans_key])) { + $new_lang[$english_string]['trad'] = html_entity_decode($GLOBALS[$name_var][$trans_key], ENT_COMPAT, 'UTF-8'); + } else { + if (!isset($new_lang[$english_string]['trad'])) { + $new_lang[$english_string]['trad'] = ''; + if (!isset($missing_translations_back[$prefix_key])) { + $missing_translations_back[$prefix_key] = 1; + } else { + $missing_translations_back[$prefix_key]++; + } + } + } + $new_lang[$english_string]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); + } + } + if (isset($tabs_array[$prefix_key])) { + $tabs_array[$prefix_key] = array_merge($tabs_array[$prefix_key], $new_lang); + } else { + $tabs_array[$prefix_key] = $new_lang; + } + } + } + } + + + // count will contain the number of expressions of the page + $count = 0; + foreach ($tabs_array as $array) { + $count += count($array); + } + + $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( + 'count' => $count, + 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), + 'limit_warning' => $this->displayLimitPostWarning($count), + 'mod_security_warning' => Tools::apacheModExists('mod_security'), + 'tabsArray' => $tabs_array, + 'missing_translations' => $missing_translations_back + )); + + $this->initToolbar(); + $this->base_tpl_view = 'translation_form.tpl'; + return parent::renderView(); + } + + /** + * Check if directory and file exist and return an list of modules + * + * @return array List of modules + * @throws PrestaShopException + */ + public function getListModules() + { + if (!Tools::file_exists_cache($this->translations_informations['modules']['dir'])) { + throw new PrestaShopException(Tools::displayError('Fatal error: The module directory does not exist.').'('.$this->translations_informations['modules']['dir'].')'); + } + if (!is_writable($this->translations_informations['modules']['dir'])) { + throw new PrestaShopException(Tools::displayError('The module directory must be writable.')); + } + + $modules = array(); + // Get all module which are installed for to have a minimum of POST + $modules = Module::getModulesInstalled(); + foreach ($modules as &$module) { + $module = $module['name']; + } + + return $modules; + } + + /** + * This method generate the form for errors translations + */ + public function initFormErrors() + { + $name_var = $this->translations_informations[$this->type_selected]['var']; + $GLOBALS[$name_var] = $this->fileExists(); + $count_empty = array(); + + /* List files to parse */ + $string_to_translate = array(); + $file_by_directory = $this->getFileToParseByTypeTranslation(); + + if ($modules = $this->getListModules()) { + foreach ($modules as $module) { + if (is_dir(_PS_MODULE_DIR_.$module) && !in_array($module, self::$ignore_folder)) { + $file_by_directory['php'] = array_merge($file_by_directory['php'], $this->listFiles(_PS_MODULE_DIR_.$module.'/', array(), 'php')); + } + } + } + + foreach ($file_by_directory['php'] as $dir => $files) { + foreach ($files as $file) { + if (preg_match('/\.php$/', $file) && Tools::file_exists_cache($file_path = $dir.$file) && !in_array($file, self::$ignore_folder)) { + if (!filesize($file_path)) { + continue; + } + + // Get content for this file + $content = file_get_contents($file_path); + + // Parse this content + $matches = $this->userParseFile($content, $this->type_selected); + + foreach ($matches as $key) { + if (array_key_exists(md5($key), $GLOBALS[$name_var])) { + $string_to_translate[$key]['trad'] = html_entity_decode($GLOBALS[$name_var][md5($key)], ENT_COMPAT, 'UTF-8'); + } else { + $string_to_translate[$key]['trad'] = ''; + if (!isset($count_empty[$key])) { + $count_empty[$key] = 1; + } + } + $string_to_translate[$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); + } + } + } + } + + $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( + 'count' => count($string_to_translate), + 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), + 'limit_warning' => $this->displayLimitPostWarning(count($string_to_translate)), + 'mod_security_warning' => Tools::apacheModExists('mod_security'), + 'errorsArray' => $string_to_translate, + 'missing_translations' => $count_empty + )); + + $this->initToolbar(); + $this->base_tpl_view = 'translation_errors.tpl'; + return parent::renderView(); + } + + /** + * This method generate the form for fields translations + */ + public function initFormFields() + { + $name_var = $this->translations_informations[$this->type_selected]['var']; + $GLOBALS[$name_var] = $this->fileExists(); + $missing_translations_fields = array(); + $class_array = array(); + $tabs_array = array(); + $count = 0; + + $files_by_directory = $this->getFileToParseByTypeTranslation(); + + foreach ($files_by_directory['php'] as $dir => $files) { + foreach ($files as $file) { + $exclude_files = array('index.php', 'PrestaShopAutoload.php', 'StockManagerInterface.php', + 'TaxManagerInterface.php', 'WebserviceOutputInterface.php', 'WebserviceSpecificManagementInterface.php'); + + if (!preg_match('/\.php$/', $file) || in_array($file, $exclude_files)) { + continue; + } + + $class_name = substr($file, 0, -4); + + if (!class_exists($class_name, false) && !class_exists($class_name.'Core', false)) { + PrestaShopAutoload::getInstance()->load($class_name); + } + + if (!is_subclass_of($class_name.'Core', 'ObjectModel')) { + continue; + } + $class_array[$class_name] = call_user_func(array($class_name, 'getValidationRules'), $class_name); + } + } + foreach ($class_array as $prefix_key => $rules) { + if (isset($rules['validate'])) { + foreach ($rules['validate'] as $key => $value) { + if (isset($GLOBALS[$name_var][$prefix_key.'_'.md5($key)])) { + $tabs_array[$prefix_key][$key]['trad'] = html_entity_decode($GLOBALS[$name_var][$prefix_key.'_'.md5($key)], ENT_COMPAT, 'UTF-8'); + $count++; + } else { + if (!isset($tabs_array[$prefix_key][$key]['trad'])) { + $tabs_array[$prefix_key][$key]['trad'] = ''; + if (!isset($missing_translations_fields[$prefix_key])) { + $missing_translations_fields[$prefix_key] = 1; + } else { + $missing_translations_fields[$prefix_key]++; + } + $count++; + } + } + } + } + if (isset($rules['validateLang'])) { + foreach ($rules['validateLang'] as $key => $value) { + if (isset($GLOBALS[$name_var][$prefix_key.'_'.md5($key)])) { + $tabs_array[$prefix_key][$key]['trad'] = ''; + if (array_key_exists($prefix_key.'_'.md5(addslashes($key)), $GLOBALS[$name_var])) { + $tabs_array[$prefix_key][$key]['trad'] = html_entity_decode($GLOBALS[$name_var][$prefix_key.'_'.md5(addslashes($key))], ENT_COMPAT, 'UTF-8'); + } + + $count++; + } else { + if (!isset($tabs_array[$prefix_key][$key]['trad'])) { + $tabs_array[$prefix_key][$key]['trad'] = ''; + if (!isset($missing_translations_fields[$prefix_key])) { + $missing_translations_fields[$prefix_key] = 1; + } else { + $missing_translations_fields[$prefix_key]++; + } + $count++; + } + } + } + } + } + + $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( + 'count' => $count, + 'limit_warning' => $this->displayLimitPostWarning($count), + 'mod_security_warning' => Tools::apacheModExists('mod_security'), + 'tabsArray' => $tabs_array, + 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), + 'missing_translations' => $missing_translations_fields + )); + + $this->initToolbar(); + $this->base_tpl_view = 'translation_form.tpl'; + return parent::renderView(); + } + + /** + * Get each informations for each mails found in the folder $dir. + * + * @since 1.4.0.14 + * @param string $dir + * @param string $group_name + * @return array : list of mails + */ + public function getMailFiles($dir, $group_name = 'mail') + { + $arr_return = array(); + if (Language::getIdByIso('en')) { + $default_language = 'en'; + } else { + $default_language = Language::getIsoById((int)Configuration::get('PS_LANG_DEFAULT')); + } + if (!$default_language || !Validate::isLanguageIsoCode($default_language)) { + return false; + } + + // Very usefull to name input and textarea fields + $arr_return['group_name'] = $group_name; + $arr_return['empty_values'] = 0; + $arr_return['total_filled'] = 0; + $arr_return['directory'] = $dir; + + // Get path for english mail directory + $dir_en = str_replace('/'.$this->lang_selected->iso_code.'/', '/'.$default_language.'/', $dir); + + if (Tools::file_exists_cache($dir_en)) { + // Get all english files to compare with the language to translate + foreach (scandir($dir_en) as $email_file) { + if (strripos($email_file, '.html') > 0 || strripos($email_file, '.txt') > 0) { + $email_name = substr($email_file, 0, strripos($email_file, '.')); + $type = substr($email_file, strripos($email_file, '.') + 1); + if (!isset($arr_return['files'][$email_name])) { + $arr_return['files'][$email_name] = array(); + } + // $email_file is from scandir ($dir), so we already know that file exists + $arr_return['files'][$email_name][$type]['en'] = $this->getMailContent($dir_en, $email_file); + + // check if the file exists in the language to translate + if (Tools::file_exists_cache($dir.'/'.$email_file)) { + $arr_return['files'][$email_name][$type][$this->lang_selected->iso_code] = $this->getMailContent($dir, $email_file); + $this->total_expression++; + } else { + $arr_return['files'][$email_name][$type][$this->lang_selected->iso_code] = ''; + } + + if ($arr_return['files'][$email_name][$type][$this->lang_selected->iso_code] == '') { + $arr_return['empty_values']++; + } else { + $arr_return['total_filled']++; + } + } + } + } else { + $this->warnings[] = sprintf(Tools::displayError('A mail directory exists for the "%1$s" language, but not for the default language (%3$s) in %2$s'), + $this->lang_selected->iso_code, str_replace(_PS_ROOT_DIR_, '', dirname($dir)), $default_language); + } + return $arr_return; + } + + /** + * Get content of the mail file. + * + * @since 1.4.0.14 + * @param string $dir + * @param string $file + * @return array : content of file + */ + protected function getMailContent($dir, $file) + { + $content = file_get_contents($dir.'/'.$file); + + if (Tools::strlen($content) === 0) { + $content = ''; + } + return $content; + } + + /** + * Display mails in html format. + * This was create for factorize the html displaying + * @since 1.4.0.14 + * + * @param array $mails + * @param array $all_subject_mail + * @param Language $obj_lang + * @param string $id_html Use for set html id attribute for the block + * @param string $title Set the title for the block + * @param string|bool $name_for_module Is not false define add a name for distinguish mails module + * + * @return string + */ + protected function displayMailContent($mails, $all_subject_mail, $obj_lang, $id_html, $title, $name_for_module = false) + { + $str_return = ''; + $group_name = 'mail'; + if (array_key_exists('group_name', $mails)) { + $group_name = $mails['group_name']; + } + + if ($mails['empty_values'] == 0) { + $translation_missing_badge_type = 'badge-success'; + } else { + $translation_missing_badge_type = 'badge-danger'; + } + + $str_return .= '<div class="mails_field"> <h4> <span class="badge">'.((int)$mails['empty_values'] + (int)$mails['total_filled']).' <i class="icon-envelope-o"></i></span> <a href="javascript:void(0);" onclick="$(\'#'.$id_html.'\').slideToggle();">'.$title.'</a> @@ -2330,136 +2334,129 @@ class AdminTranslationsControllerCore extends AdminController </h4> <div name="mails_div" id="'.$id_html.'" class="panel-group">'; - if (!empty($mails['files'])) - { - $topic_already_displayed = array(); - foreach ($mails['files'] as $mail_name => $mail_files) - { - $str_return .= '<div class="panel translations-email-panel">'; - $str_return .= '<a href="#email-'.$mail_name.'" class="panel-title" data-toggle="collapse" data-parent="#'.$id_html.'" >'.$mail_name.' <i class="icon-caret-down"></i> </a>'; - $str_return .= '<div id="email-'.$mail_name.'" class="email-collapse panel-collapse collapse">'; - if (array_key_exists('html', $mail_files) || array_key_exists('txt', $mail_files)) - { - if (array_key_exists($mail_name, $all_subject_mail)) - { - foreach ($all_subject_mail[$mail_name] as $subject_mail) - { - $subject_key = 'subject['.Tools::htmlentitiesUTF8($group_name).']['.Tools::htmlentitiesUTF8($subject_mail).']'; - if (in_array($subject_key, $topic_already_displayed)) - continue; - $topic_already_displayed[] = $subject_key; - $value_subject_mail = isset($mails['subject'][$subject_mail]) ? $mails['subject'][$subject_mail] : ''; - $str_return .= ' + if (!empty($mails['files'])) { + $topic_already_displayed = array(); + foreach ($mails['files'] as $mail_name => $mail_files) { + $str_return .= '<div class="panel translations-email-panel">'; + $str_return .= '<a href="#email-'.$mail_name.'" class="panel-title" data-toggle="collapse" data-parent="#'.$id_html.'" >'.$mail_name.' <i class="icon-caret-down"></i> </a>'; + $str_return .= '<div id="email-'.$mail_name.'" class="email-collapse panel-collapse collapse">'; + if (array_key_exists('html', $mail_files) || array_key_exists('txt', $mail_files)) { + if (array_key_exists($mail_name, $all_subject_mail)) { + foreach ($all_subject_mail[$mail_name] as $subject_mail) { + $subject_key = 'subject['.Tools::htmlentitiesUTF8($group_name).']['.Tools::htmlentitiesUTF8($subject_mail).']'; + if (in_array($subject_key, $topic_already_displayed)) { + continue; + } + $topic_already_displayed[] = $subject_key; + $value_subject_mail = isset($mails['subject'][$subject_mail]) ? $mails['subject'][$subject_mail] : ''; + $str_return .= ' <div class="label-subject row"> <label class="control-label col-lg-3">'.sprintf($this->l('Email subject')); - if (isset($value_subject_mail['use_sprintf']) && $value_subject_mail['use_sprintf']) - $str_return .= '<span class="useSpecialSyntax" title="'.$this->l('This expression uses a special syntax:').' '.$value_subject_mail['use_sprintf'].'"> + if (isset($value_subject_mail['use_sprintf']) && $value_subject_mail['use_sprintf']) { + $str_return .= '<span class="useSpecialSyntax" title="'.$this->l('This expression uses a special syntax:').' '.$value_subject_mail['use_sprintf'].'"> <i class="icon-exclamation-triangle"></i> </span>'; - $str_return .= '</label><div class="col-lg-9">'; - if (isset($value_subject_mail['trad']) && $value_subject_mail['trad']) - $str_return .= '<input class="form-control" type="text" name="subject['.Tools::htmlentitiesUTF8($group_name).']['.Tools::htmlentitiesUTF8($subject_mail).']" value="'.$value_subject_mail['trad'].'" />'; - else - $str_return .= '<input class="form-control" type="text" name="subject['.Tools::htmlentitiesUTF8($group_name).']['.Tools::htmlentitiesUTF8($subject_mail).']" value="" />'; - $str_return .= '<p class="help-block">'.stripcslashes($subject_mail).'</p>'; - $str_return .= '</div></div>'; - } - } - else - { - $str_return .= ' + } + $str_return .= '</label><div class="col-lg-9">'; + if (isset($value_subject_mail['trad']) && $value_subject_mail['trad']) { + $str_return .= '<input class="form-control" type="text" name="subject['.Tools::htmlentitiesUTF8($group_name).']['.Tools::htmlentitiesUTF8($subject_mail).']" value="'.$value_subject_mail['trad'].'" />'; + } else { + $str_return .= '<input class="form-control" type="text" name="subject['.Tools::htmlentitiesUTF8($group_name).']['.Tools::htmlentitiesUTF8($subject_mail).']" value="" />'; + } + $str_return .= '<p class="help-block">'.stripcslashes($subject_mail).'</p>'; + $str_return .= '</div></div>'; + } + } else { + $str_return .= ' <hr><div class="alert alert-info">' - .sprintf($this->l('No Subject was found for %s in the database.'), $mail_name) - .'</div>'; - } - // tab menu - $str_return .= '<hr><ul class="nav nav-pills"> + .sprintf($this->l('No Subject was found for %s in the database.'), $mail_name) + .'</div>'; + } + // tab menu + $str_return .= '<hr><ul class="nav nav-pills"> <li class="active"><a href="#'.$mail_name.'-html" data-toggle="tab">'.$this->l('View HTML version').'</a></li> <li><a href="#'.$mail_name.'-editor" data-toggle="tab">'.$this->l('Edit HTML version').'</a></li> <li><a href="#'.$mail_name.'-text" data-toggle="tab">'.$this->l('View/Edit TXT version').'</a></li> </ul>'; - // tab-content - $str_return .= '<div class="tab-content">'; + // tab-content + $str_return .= '<div class="tab-content">'; - if (array_key_exists('html', $mail_files)) - { - $str_return .= '<div class="tab-pane active" id="'.$mail_name.'-html">'; - $base_uri = str_replace(_PS_ROOT_DIR_, __PS_BASE_URI__, $mails['directory']); - $base_uri = str_replace('//', '/', $base_uri); - $url_mail = $base_uri.$mail_name.'.html'; - $str_return .= $this->displayMailBlockHtml($mail_files['html'], $obj_lang->iso_code, $url_mail, $mail_name, $group_name, $name_for_module); - $str_return .= '</div>'; - } + if (array_key_exists('html', $mail_files)) { + $str_return .= '<div class="tab-pane active" id="'.$mail_name.'-html">'; + $base_uri = str_replace(_PS_ROOT_DIR_, __PS_BASE_URI__, $mails['directory']); + $base_uri = str_replace('//', '/', $base_uri); + $url_mail = $base_uri.$mail_name.'.html'; + $str_return .= $this->displayMailBlockHtml($mail_files['html'], $obj_lang->iso_code, $url_mail, $mail_name, $group_name, $name_for_module); + $str_return .= '</div>'; + } - if (array_key_exists('txt', $mail_files)) - { - $str_return .= '<div class="tab-pane" id="'.$mail_name.'-text">'; - $str_return .= $this->displayMailBlockTxt($mail_files['txt'], $obj_lang->iso_code, $mail_name, $group_name, $name_for_module); - $str_return .= '</div>'; - } + if (array_key_exists('txt', $mail_files)) { + $str_return .= '<div class="tab-pane" id="'.$mail_name.'-text">'; + $str_return .= $this->displayMailBlockTxt($mail_files['txt'], $obj_lang->iso_code, $mail_name, $group_name, $name_for_module); + $str_return .= '</div>'; + } - $str_return .= '<div class="tab-pane" id="'.$mail_name.'-editor">'; - if (isset($mail_files['html'])) - $str_return .= $this->displayMailEditor($mail_files['html'], $obj_lang->iso_code, $url_mail, $mail_name, $group_name, $name_for_module); - $str_return .= '</div>'; + $str_return .= '<div class="tab-pane" id="'.$mail_name.'-editor">'; + if (isset($mail_files['html'])) { + $str_return .= $this->displayMailEditor($mail_files['html'], $obj_lang->iso_code, $url_mail, $mail_name, $group_name, $name_for_module); + } + $str_return .= '</div>'; - $str_return .= '</div>'; - $str_return .= '</div><!--end .panel-collapse -->'; - $str_return .= '</div><!--end .panel -->'; - } - } - } - else - { - $str_return .= '<p class="error"> + $str_return .= '</div>'; + $str_return .= '</div><!--end .panel-collapse -->'; + $str_return .= '</div><!--end .panel -->'; + } + } + } else { + $str_return .= '<p class="error"> '.$this->l('There was a problem getting the mail files.').'<br> '.sprintf($this->l('English language files must exist in %s folder'), '<em>'.preg_replace('@/[a-z]{2}(/?)$@', '/en$1', $mails['directory']).'</em>').' </p>'; - } + } - $str_return .= '</div><!-- #'.$id_html.' --></div><!-- end .mails_field -->'; - return $str_return; - } - /** - * Just build the html structure for display txt mails - * @since 1.4.0.14 - * - * @param array $content With english and language needed contents - * @param string $lang ISO code of the needed language - * @param string $mail_name Name of the file to translate (same for txt and html files) - * @param string $group_name Group name allow to distinguish each block of mail. - * @param string|bool $name_for_module Is not false define add a name for distinguish mails module - * - * @return string - */ - protected function displayMailBlockTxt($content, $lang, $mail_name, $group_name, $name_for_module = false) - { - return '<div class="block-mail" > + $str_return .= '</div><!-- #'.$id_html.' --></div><!-- end .mails_field -->'; + return $str_return; + } + /** + * Just build the html structure for display txt mails + * @since 1.4.0.14 + * + * @param array $content With english and language needed contents + * @param string $lang ISO code of the needed language + * @param string $mail_name Name of the file to translate (same for txt and html files) + * @param string $group_name Group name allow to distinguish each block of mail. + * @param string|bool $name_for_module Is not false define add a name for distinguish mails module + * + * @return string + */ + protected function displayMailBlockTxt($content, $lang, $mail_name, $group_name, $name_for_module = false) + { + return '<div class="block-mail" > <div class="mail-form"> - <div><textarea class="rte noEditor" name="'.$group_name.'[txt]['.($name_for_module ? $name_for_module.'|' : '' ).$mail_name.']">'.Tools::htmlentitiesUTF8(stripslashes(strip_tags($content[$lang]))).'</textarea></div> + <div><textarea class="rte noEditor" name="'.$group_name.'[txt]['.($name_for_module ? $name_for_module.'|' : '').$mail_name.']">'.Tools::htmlentitiesUTF8(stripslashes(strip_tags($content[$lang]))).'</textarea></div> </div> </div>'; - } + } - /** - * Just build the html structure for display html mails. - * - * @since 1.4.0.14 - * @param array $content With english and language needed contents - * @param string $lang ISO code of the needed language - * @param string $url for The html page and displaying an outline - * @param string $mail_name Name of the file to translate (same for txt and html files) - * @param string $group_name Group name allow to distinguish each block of mail. - * @param string|bool $name_for_module Is not false define add a name for distinguish mails module - * - * @return string - */ - protected function displayMailBlockHtml($content, $lang, $url, $mail_name, $group_name, $name_for_module = false) - { - $title = array(); - $this->cleanMailContent($content, $lang, $title); - $name_for_module = $name_for_module ? $name_for_module.'|' : ''; - return '<div class="block-mail" > + /** + * Just build the html structure for display html mails. + * + * @since 1.4.0.14 + * @param array $content With english and language needed contents + * @param string $lang ISO code of the needed language + * @param string $url for The html page and displaying an outline + * @param string $mail_name Name of the file to translate (same for txt and html files) + * @param string $group_name Group name allow to distinguish each block of mail. + * @param string|bool $name_for_module Is not false define add a name for distinguish mails module + * + * @return string + */ + protected function displayMailBlockHtml($content, $lang, $url, $mail_name, $group_name, $name_for_module = false) + { + $title = array(); + $this->cleanMailContent($content, $lang, $title); + $name_for_module = $name_for_module ? $name_for_module.'|' : ''; + return '<div class="block-mail" > <div class="mail-form"> <div class="form-group"> <label class="control-label col-lg-3">'.$this->l('HTML "title" tag').'</label> @@ -2471,115 +2468,112 @@ class AdminTranslationsControllerCore extends AdminController <div class="thumbnail email-html-frame" data-email-src="'.$url.'?'.(rand(0, 1000000000)).'"></div> </div> </div>'; - } + } - protected function displayMailEditor($content, $lang, $url, $mail_name, $group_name, $name_for_module = false) - { - $title = array(); - $this->cleanMailContent($content, $lang, $title); - $name_for_module = $name_for_module ? $name_for_module.'|' : ''; - return '<textarea class="rte-mail rte-mail-'.$mail_name.' form-control" data-rte="'.$mail_name.'" name="'.$group_name.'[html]['.$name_for_module.$mail_name.']">'.$content[$lang].'</textarea>'; - } + protected function displayMailEditor($content, $lang, $url, $mail_name, $group_name, $name_for_module = false) + { + $title = array(); + $this->cleanMailContent($content, $lang, $title); + $name_for_module = $name_for_module ? $name_for_module.'|' : ''; + return '<textarea class="rte-mail rte-mail-'.$mail_name.' form-control" data-rte="'.$mail_name.'" name="'.$group_name.'[html]['.$name_for_module.$mail_name.']">'.$content[$lang].'</textarea>'; + } - protected function cleanMailContent(&$content, $lang, &$title) - { - // Because TinyMCE don't work correctly with <DOCTYPE>, <html> and <body> tags - if (stripos($content[$lang], '<body')) - { - $array_lang = $lang != 'en' ? array('en', $lang) : array($lang); - foreach ($array_lang as $language) - { - $title[$language] = substr($content[$language], 0, stripos($content[$language], '<body')); - preg_match('#<title>([^<]+)#Ui', $title[$language], $matches); - $title[$language] = empty($matches[1])?'':$matches[1]; - // The 2 lines below allow to exlude tag from the content. - // This allow to exclude body tag even if attributs are setted. - $content[$language] = substr($content[$language], stripos($content[$language], '') + 1); - $content[$language] = substr($content[$language], 0, stripos($content[$language], '')); - } - } - $content[$lang] = (isset($content[$lang]) ? Tools::htmlentitiesUTF8(stripslashes($content[$lang])) : ''); - } + protected function cleanMailContent(&$content, $lang, &$title) + { + // Because TinyMCE don't work correctly with , and tags + if (stripos($content[$lang], '([^<]+)#Ui', $title[$language], $matches); + $title[$language] = empty($matches[1])?'':$matches[1]; + // The 2 lines below allow to exlude tag from the content. + // This allow to exclude body tag even if attributs are setted. + $content[$language] = substr($content[$language], stripos($content[$language], '') + 1); + $content[$language] = substr($content[$language], 0, stripos($content[$language], '')); + } + } + $content[$lang] = (isset($content[$lang]) ? Tools::htmlentitiesUTF8(stripslashes($content[$lang])) : ''); + } - /** - * Check in each module if contains mails folder. - * - * @param bool $with_module_name - * - * @return array Array of modules which have mails - */ - public function getModulesHasMails($with_module_name = false) - { - $arr_modules = array(); - foreach (scandir($this->translations_informations['modules']['dir']) as $module_dir) - { - if (!in_array($module_dir, self::$ignore_folder)) - { - $dir = false; - if ($this->theme_selected && Tools::file_exists_cache($this->translations_informations['modules']['override']['dir'].$module_dir.'/mails/')) - $dir = $this->translations_informations['modules']['override']['dir'].$module_dir.'/'; - elseif (Tools::file_exists_cache($this->translations_informations['modules']['dir'].$module_dir.'/mails/')) - $dir = $this->translations_informations['modules']['dir'].$module_dir.'/'; - if ($dir !== false) - { - if ($with_module_name) - $arr_modules[$module_dir] = $dir; - else - { - if ($this->theme_selected) - $dir = $this->translations_informations['modules']['dir'].$module_dir.'/'; - $arr_modules[$dir] = scandir($dir); - } - } - } - } - return $arr_modules; - } + /** + * Check in each module if contains mails folder. + * + * @param bool $with_module_name + * + * @return array Array of modules which have mails + */ + public function getModulesHasMails($with_module_name = false) + { + $arr_modules = array(); + foreach (scandir($this->translations_informations['modules']['dir']) as $module_dir) { + if (!in_array($module_dir, self::$ignore_folder)) { + $dir = false; + if ($this->theme_selected && Tools::file_exists_cache($this->translations_informations['modules']['override']['dir'].$module_dir.'/mails/')) { + $dir = $this->translations_informations['modules']['override']['dir'].$module_dir.'/'; + } elseif (Tools::file_exists_cache($this->translations_informations['modules']['dir'].$module_dir.'/mails/')) { + $dir = $this->translations_informations['modules']['dir'].$module_dir.'/'; + } + if ($dir !== false) { + if ($with_module_name) { + $arr_modules[$module_dir] = $dir; + } else { + if ($this->theme_selected) { + $dir = $this->translations_informations['modules']['dir'].$module_dir.'/'; + } + $arr_modules[$dir] = scandir($dir); + } + } + } + } + return $arr_modules; + } - /** - * Check in each module if contains pdf folder. - * - * @param bool $classes - * - * @return array Array of modules which have pdf - */ - public function getModulesHasPDF($classes = false) - { - $arr_modules = array(); - foreach (scandir($this->translations_informations['modules']['dir']) as $module_dir) - if (!in_array($module_dir, self::$ignore_folder)) - { - $dir = false; - if ($classes) - { - if ($this->theme_selected && Tools::file_exists_cache($this->translations_informations['modules']['override']['dir'].$module_dir.'/classes/')) - $dir = $this->translations_informations['modules']['override']['dir'].$module_dir.'/classes/'; - elseif (Tools::file_exists_cache($this->translations_informations['modules']['dir'].$module_dir.'/classes/')) - $dir = $this->translations_informations['modules']['dir'].$module_dir.'/classes/'; - if ($dir !== false) - $arr_modules[$dir] = scandir($dir); - } - else - { - if ($this->theme_selected && Tools::file_exists_cache($this->translations_informations['modules']['override']['dir'].$module_dir.'/pdf/')) - $dir = $this->translations_informations['modules']['override']['dir'].$module_dir.'/pdf/'; - elseif (Tools::file_exists_cache($this->translations_informations['modules']['dir'].$module_dir.'/pdf/')) - $dir = $this->translations_informations['modules']['dir'].$module_dir.'/pdf/'; - if ($dir !== false) - $arr_modules[$dir] = scandir($dir); - } - } - return $arr_modules; - } + /** + * Check in each module if contains pdf folder. + * + * @param bool $classes + * + * @return array Array of modules which have pdf + */ + public function getModulesHasPDF($classes = false) + { + $arr_modules = array(); + foreach (scandir($this->translations_informations['modules']['dir']) as $module_dir) { + if (!in_array($module_dir, self::$ignore_folder)) { + $dir = false; + if ($classes) { + if ($this->theme_selected && Tools::file_exists_cache($this->translations_informations['modules']['override']['dir'].$module_dir.'/classes/')) { + $dir = $this->translations_informations['modules']['override']['dir'].$module_dir.'/classes/'; + } elseif (Tools::file_exists_cache($this->translations_informations['modules']['dir'].$module_dir.'/classes/')) { + $dir = $this->translations_informations['modules']['dir'].$module_dir.'/classes/'; + } + if ($dir !== false) { + $arr_modules[$dir] = scandir($dir); + } + } else { + if ($this->theme_selected && Tools::file_exists_cache($this->translations_informations['modules']['override']['dir'].$module_dir.'/pdf/')) { + $dir = $this->translations_informations['modules']['override']['dir'].$module_dir.'/pdf/'; + } elseif (Tools::file_exists_cache($this->translations_informations['modules']['dir'].$module_dir.'/pdf/')) { + $dir = $this->translations_informations['modules']['dir'].$module_dir.'/pdf/'; + } + if ($dir !== false) { + $arr_modules[$dir] = scandir($dir); + } + } + } + } + return $arr_modules; + } - protected function getTinyMCEForMails($iso_lang) - { - // TinyMCE - $iso_tiny_mce = (Tools::file_exists_cache(_PS_ROOT_DIR_.'/js/tiny_mce/langs/'.$iso_lang.'.js') ? $iso_lang : 'en'); - $ad = __PS_BASE_URI__.basename(_PS_ADMIN_DIR_); - //return false; - return ' + protected function getTinyMCEForMails($iso_lang) + { + // TinyMCE + $iso_tiny_mce = (Tools::file_exists_cache(_PS_ROOT_DIR_.'/js/tiny_mce/langs/'.$iso_lang.'.js') ? $iso_lang : 'en'); + $ad = __PS_BASE_URI__.basename(_PS_ADMIN_DIR_); + //return false; + return ' '; - } + } - /** - * This method generate the form for mails translations - * - * @param bool $no_display - * - * @return array|string - */ - public function initFormMails($no_display = false) - { - $module_mails = array(); + /** + * This method generate the form for mails translations + * + * @param bool $no_display + * + * @return array|string + */ + public function initFormMails($no_display = false) + { + $module_mails = array(); - // get all mail subjects, this method parse each files in Prestashop !! - $subject_mail = array(); + // get all mail subjects, this method parse each files in Prestashop !! + $subject_mail = array(); - $modules_has_mails = $this->getModulesHasMails(true); + $modules_has_mails = $this->getModulesHasMails(true); - $files_by_directiories = $this->getFileToParseByTypeTranslation(); + $files_by_directiories = $this->getFileToParseByTypeTranslation(); - if (!$this->theme_selected || !@filemtime($this->translations_informations[$this->type_selected]['override']['dir'])) - $this->copyMailFilesForAllLanguages(); + if (!$this->theme_selected || !@filemtime($this->translations_informations[$this->type_selected]['override']['dir'])) { + $this->copyMailFilesForAllLanguages(); + } - foreach ($files_by_directiories['php'] as $dir => $files) - foreach ($files as $file) - // If file exist and is not in ignore_folder, in the next step we check if a folder or mail - if (Tools::file_exists_cache($dir.$file) && !in_array($file, self::$ignore_folder)) - $subject_mail = $this->getSubjectMail($dir, $file, $subject_mail); + foreach ($files_by_directiories['php'] as $dir => $files) { + foreach ($files as $file) { + // If file exist and is not in ignore_folder, in the next step we check if a folder or mail + if (Tools::file_exists_cache($dir.$file) && !in_array($file, self::$ignore_folder)) { + $subject_mail = $this->getSubjectMail($dir, $file, $subject_mail); + } + } + } - // Get path of directory for find a good path of translation file - if ($this->theme_selected && @filemtime($this->translations_informations[$this->type_selected]['override']['dir'])) - $i18n_dir = $this->translations_informations[$this->type_selected]['override']['dir']; - else - $i18n_dir = $this->translations_informations[$this->type_selected]['dir']; + // Get path of directory for find a good path of translation file + if ($this->theme_selected && @filemtime($this->translations_informations[$this->type_selected]['override']['dir'])) { + $i18n_dir = $this->translations_informations[$this->type_selected]['override']['dir']; + } else { + $i18n_dir = $this->translations_informations[$this->type_selected]['dir']; + } - $core_mails = $this->getMailFiles($i18n_dir, 'core_mail'); - $core_mails['subject'] = $this->getSubjectMailContent($i18n_dir); + $core_mails = $this->getMailFiles($i18n_dir, 'core_mail'); + $core_mails['subject'] = $this->getSubjectMailContent($i18n_dir); - foreach ($modules_has_mails as $module_name => $module_path) - { - $module_path = rtrim($module_path, '/'); - $module_mails[$module_name] = $this->getMailFiles($module_path.'/mails/'.$this->lang_selected->iso_code.'/', 'module_mail'); - $module_mails[$module_name]['subject'] = $core_mails['subject']; - $module_mails[$module_name]['display'] = $this->displayMailContent($module_mails[$module_name], $subject_mail, $this->lang_selected, Tools::strtolower($module_name), $module_name, $module_name); - } + foreach ($modules_has_mails as $module_name => $module_path) { + $module_path = rtrim($module_path, '/'); + $module_mails[$module_name] = $this->getMailFiles($module_path.'/mails/'.$this->lang_selected->iso_code.'/', 'module_mail'); + $module_mails[$module_name]['subject'] = $core_mails['subject']; + $module_mails[$module_name]['display'] = $this->displayMailContent($module_mails[$module_name], $subject_mail, $this->lang_selected, Tools::strtolower($module_name), $module_name, $module_name); + } - if ($no_display) - { - $empty = 0; - $total = 0; - $total += (int)$core_mails['total_filled']; - $empty += (int)$core_mails['empty_values']; - foreach ($module_mails as $mod_infos) - { - $total += (int)$mod_infos['total_filled']; - $empty += (int)$mod_infos['empty_values']; - } - return array('total' => $total, 'empty' => $empty); - } + if ($no_display) { + $empty = 0; + $total = 0; + $total += (int)$core_mails['total_filled']; + $empty += (int)$core_mails['empty_values']; + foreach ($module_mails as $mod_infos) { + $total += (int)$mod_infos['total_filled']; + $empty += (int)$mod_infos['empty_values']; + } + return array('total' => $total, 'empty' => $empty); + } - $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( - 'limit_warning' => $this->displayLimitPostWarning($this->total_expression), - 'mod_security_warning' => Tools::apacheModExists('mod_security'), - 'tinyMCE' => $this->getTinyMCEForMails($this->lang_selected->iso_code), - 'mail_content' => $this->displayMailContent($core_mails, $subject_mail, $this->lang_selected, 'core', $this->l('Core emails')), - 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), - 'module_mails' => $module_mails, - 'theme_name' => $this->theme_selected - )); + $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( + 'limit_warning' => $this->displayLimitPostWarning($this->total_expression), + 'mod_security_warning' => Tools::apacheModExists('mod_security'), + 'tinyMCE' => $this->getTinyMCEForMails($this->lang_selected->iso_code), + 'mail_content' => $this->displayMailContent($core_mails, $subject_mail, $this->lang_selected, 'core', $this->l('Core emails')), + 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), + 'module_mails' => $module_mails, + 'theme_name' => $this->theme_selected + )); - $this->initToolbar(); - $this->base_tpl_view = 'translation_mails.tpl'; - return parent::renderView(); - } + $this->initToolbar(); + $this->base_tpl_view = 'translation_mails.tpl'; + return parent::renderView(); + } - public function copyMailFilesForAllLanguages() - { - $current_theme = Tools::safeOutput($this->context->theme->name); - $languages = Language::getLanguages(); + public function copyMailFilesForAllLanguages() + { + $current_theme = Tools::safeOutput($this->context->theme->name); + $languages = Language::getLanguages(); - foreach ($languages as $key => $lang) { + foreach ($languages as $key => $lang) { + $dir_to_copy_iso = array(); + $files_to_copy_iso = array(); + $current_iso_code = $lang['iso_code']; - $dir_to_copy_iso = array(); - $files_to_copy_iso = array(); - $current_iso_code = $lang['iso_code']; + $dir_to_copy_iso[] = _PS_MAIL_DIR_.$current_iso_code.'/'; - $dir_to_copy_iso[] = _PS_MAIL_DIR_.$current_iso_code.'/'; + $modules_has_mails = $this->getModulesHasMails(true); + foreach ($modules_has_mails as $module_name => $module_path) { + if ($pos = strpos($module_path, '/modules')) { + $dir_to_copy_iso[] = _PS_ROOT_DIR_.substr($module_path, $pos).'mails/'.$current_iso_code.'/'; + } + } - $modules_has_mails = $this->getModulesHasMails(true); - foreach ($modules_has_mails as $module_name => $module_path) - { - if ($pos = strpos($module_path, '/modules')) - $dir_to_copy_iso[] = _PS_ROOT_DIR_.substr($module_path, $pos).'mails/'.$current_iso_code.'/'; - } + foreach ($dir_to_copy_iso as $dir) { + foreach (scandir($dir) as $file) { + if (!in_array($file, self::$ignore_folder)) { + $files_to_copy_iso[] = array( + "from" => $dir.$file, + "to" => str_replace(_PS_ROOT_DIR_, _PS_ROOT_DIR_.'/themes/'.$current_theme, $dir).$file + ); + } + } + } - foreach ($dir_to_copy_iso as $dir) - foreach (scandir($dir) as $file) - if (!in_array($file, self::$ignore_folder)) - $files_to_copy_iso[] = array( - "from" => $dir.$file, - "to" => str_replace(_PS_ROOT_DIR_, _PS_ROOT_DIR_.'/themes/'.$current_theme, $dir).$file - ); + foreach ($files_to_copy_iso as $file) { + if (!file_exists($file['to'])) { + $content = file_get_contents($file['from']); - foreach ($files_to_copy_iso as $file) - { - if (!file_exists($file['to'])) - { - $content = file_get_contents($file['from']); + $stack = array(); + $folder = dirname($file['to']); + while (!is_dir($folder)) { + array_push($stack, $folder); + $folder = dirname($folder); + } + while ($folder = array_pop($stack)) { + mkdir($folder); + } - $stack = array(); - $folder = dirname($file['to']); - while (!is_dir($folder)) - { - array_push($stack, $folder); - $folder = dirname($folder); - } - while ($folder = array_pop($stack)) - mkdir($folder); + $success = file_put_contents($file['to'], $content); + if ($success === false) { + Tools::dieOrLog(sprintf("%s cannot be copied to %s", $file['from'], $file['to']), false); + } + } + } + } - $success = file_put_contents($file['to'], $content); - if ($success === false) - Tools::dieOrLog(sprintf("%s cannot be copied to %s", $file['from'], $file['to']), false); - } - } - } + return true; + } - return true; - } + /** + * Get list of subjects of mails + * + * @param $dir + * @param $file + * @param $subject_mail + * @return array : list of subjects of mails + */ + protected function getSubjectMail($dir, $file, $subject_mail) + { + $dir = rtrim($dir, '/'); + // If is file and is not in ignore_folder + if (is_file($dir.'/'.$file) && !in_array($file, self::$ignore_folder) && preg_match('/\.php$/', $file)) { + $content = file_get_contents($dir.'/'.$file); + $content = str_replace("\n", ' ', $content); - /** - * Get list of subjects of mails - * - * @param $dir - * @param $file - * @param $subject_mail - * @return array : list of subjects of mails - */ - protected function getSubjectMail($dir, $file, $subject_mail) - { - $dir = rtrim($dir, '/'); - // If is file and is not in ignore_folder - if (is_file($dir.'/'.$file) && !in_array($file, self::$ignore_folder) && preg_match('/\.php$/', $file)) - { - $content = file_get_contents($dir.'/'.$file); - $content = str_replace("\n", ' ', $content); + // Subject must match with a template, therefore we first grep the Mail::Send() function then the Mail::l() inside. + if (preg_match_all('/Mail::Send([^;]*);/si', $content, $tab)) { + for ($i = 0; isset($tab[1][$i]); $i++) { + $tab2 = explode(',', $tab[1][$i]); + if (is_array($tab2) && isset($tab2[1])) { + $template = trim(str_replace('\'', '', $tab2[1])); + foreach ($tab2 as $tab3) { + if (preg_match('/Mail::l\(\''._PS_TRANS_PATTERN_.'\'\)/Us', $tab3.')', $matches)) { + if (!isset($subject_mail[$template])) { + $subject_mail[$template] = array(); + } + if (!in_array($matches[1], $subject_mail[$template])) { + $subject_mail[$template][] = $matches[1]; + } + } + } + } + } + } + } + // Or if is folder, we scan folder for check if found in folder and subfolder + elseif (!in_array($file, self::$ignore_folder) && is_dir($dir.'/'.$file)) { + foreach (scandir($dir.'/'.$file) as $temp) { + if ($temp[0] != '.') { + $subject_mail = $this->getSubjectMail($dir.'/'.$file, $temp, $subject_mail); + } + } + } - // Subject must match with a template, therefore we first grep the Mail::Send() function then the Mail::l() inside. - if (preg_match_all('/Mail::Send([^;]*);/si', $content, $tab)) - { - for ($i = 0; isset($tab[1][$i]); $i++) - { - $tab2 = explode(',', $tab[1][$i]); - if (is_array($tab2) && isset($tab2[1])) - { - $template = trim(str_replace('\'', '', $tab2[1])); - foreach ($tab2 as $tab3) - if (preg_match('/Mail::l\(\''._PS_TRANS_PATTERN_.'\'\)/Us', $tab3.')', $matches)) - { - if (!isset($subject_mail[$template])) - $subject_mail[$template] = array(); - if (!in_array($matches[1], $subject_mail[$template])) - $subject_mail[$template][] = $matches[1]; - } - } - } - } - } - // Or if is folder, we scan folder for check if found in folder and subfolder - elseif (!in_array($file, self::$ignore_folder) && is_dir($dir.'/'.$file)) - foreach(scandir($dir.'/'.$file ) as $temp) - if ($temp[0] != '.') - $subject_mail = $this->getSubjectMail($dir.'/'.$file, $temp, $subject_mail); + return $subject_mail; + } - return $subject_mail; - } + /** + * @param $directory : name of directory + * @return array + */ + protected function getSubjectMailContent($directory) + { + $subject_mail_content = array(); - /** - * @param $directory : name of directory - * @return array - */ - protected function getSubjectMailContent($directory) - { - $subject_mail_content = array(); + if (Tools::file_exists_cache($directory.'/lang.php')) { + // we need to include this even if already included (no include once) + include($directory.'/lang.php'); + foreach ($GLOBALS[$this->translations_informations[$this->type_selected]['var']] as $key => $subject) { + $this->total_expression++; + $subject = str_replace('\n', ' ', $subject); + $subject = str_replace("\\'", "\'", $subject); - if (Tools::file_exists_cache($directory.'/lang.php')) - { - // we need to include this even if already included (no include once) - include($directory.'/lang.php'); - foreach ($GLOBALS[$this->translations_informations[$this->type_selected]['var']] as $key => $subject) - { - $this->total_expression++; - $subject = str_replace('\n', ' ', $subject); - $subject = str_replace("\\'", "\'", $subject); + $subject_mail_content[$key]['trad'] = htmlentities($subject, ENT_QUOTES, 'UTF-8'); + $subject_mail_content[$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); + } + } else { + $this->errors[] = sprintf($this->l('Email subject translation file not found in "%s".'), $directory); + } + return $subject_mail_content; + } - $subject_mail_content[$key]['trad'] = htmlentities($subject, ENT_QUOTES, 'UTF-8'); - $subject_mail_content[$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); - } - } - else - $this->errors[] = sprintf($this->l('Email subject translation file not found in "%s".'), $directory); - return $subject_mail_content; - } + protected function writeSubjectTranslationFile($sub, $path) + { + if (!Tools::file_exists_cache(dirname($path))) { + if (!mkdir(dirname($path), 0700)) { + throw new PrestaShopException('Directory '.dirname($path).' cannot be created.'); + } + } + if ($fd = @fopen($path, 'w')) { + $tab = 'LANGMAIL'; + fwrite($fd, " $value) { + // Magic Quotes shall... not.. PASS! + if (_PS_MAGIC_QUOTES_GPC_) { + $value = stripslashes($value); + } + fwrite($fd, '$_'.$tab.'[\''.pSQL($key).'\'] = \''.pSQL($value).'\';'."\n"); + } - foreach ($sub as $key => $value) - { - // Magic Quotes shall... not.. PASS! - if (_PS_MAGIC_QUOTES_GPC_) - $value = stripslashes($value); - fwrite($fd, '$_'.$tab.'[\''.pSQL($key).'\'] = \''.pSQL($value).'\';'."\n"); - } + fwrite($fd, "\n?>"); + fclose($fd); + } else { + throw new PrestaShopException(sprintf(Tools::displayError('Cannot write language file for email subjects. Path is: %s'), $path)); + } + } - fwrite($fd, "\n?>"); - fclose($fd); - } - else - throw new PrestaShopException(sprintf(Tools::displayError('Cannot write language file for email subjects. Path is: %s'), $path)); - } + /** + * This get files to translate in module directory. + * Recursive method allow to get each files for a module no matter his depth. + * + * @param string $path directory path to scan + * @param array $array_files by reference - array which saved files to parse. + * @param string $module_name module name + * @param string $lang_file full path of translation file + * @param bool $is_default + */ + protected function recursiveGetModuleFiles($path, &$array_files, $module_name, $lang_file, $is_default = false) + { + $files_module = array(); + if (Tools::file_exists_cache($path)) { + $files_module = scandir($path); + } + $files_for_module = $this->clearModuleFiles($files_module, 'file'); + if (!empty($files_for_module)) { + $array_files[] = array( + 'file_name' => $lang_file, + 'dir' => $path, + 'files' => $files_for_module, + 'module' => $module_name, + 'is_default' => $is_default, + 'theme' => $this->theme_selected, + ); + } - /** - * This get files to translate in module directory. - * Recursive method allow to get each files for a module no matter his depth. - * - * @param string $path directory path to scan - * @param array $array_files by reference - array which saved files to parse. - * @param string $module_name module name - * @param string $lang_file full path of translation file - * @param bool $is_default - */ - protected function recursiveGetModuleFiles($path, &$array_files, $module_name, $lang_file, $is_default = false) - { - $files_module = array(); - if (Tools::file_exists_cache($path)) - $files_module = scandir($path); - $files_for_module = $this->clearModuleFiles($files_module, 'file'); - if (!empty($files_for_module)) - $array_files[] = array( - 'file_name' => $lang_file, - 'dir' => $path, - 'files' => $files_for_module, - 'module' => $module_name, - 'is_default' => $is_default, - 'theme' => $this->theme_selected, - ); + $dir_module = $this->clearModuleFiles($files_module, 'directory', $path); - $dir_module = $this->clearModuleFiles($files_module, 'directory', $path); + if (!empty($dir_module)) { + foreach ($dir_module as $folder) { + $this->recursiveGetModuleFiles($path.$folder.'/', $array_files, $module_name, $lang_file, $is_default); + } + } + } - if (!empty($dir_module)) - foreach ($dir_module as $folder) - $this->recursiveGetModuleFiles($path.$folder.'/', $array_files, $module_name, $lang_file, $is_default); - } + /** + * This method get translation in each translations file. + * The file depend on $lang param. + * + * @param array $modules List of modules + * @param string|null $root_dir path where it get each modules + * @param string $lang ISO code of chosen language to translate + * @param bool $is_default Set it if modules are located in root/prestashop/modules folder + * This allow to distinguish overridden prestashop theme and original module + * + * @return array + */ + protected function getAllModuleFiles($modules, $root_dir = null, $lang, $is_default = false) + { + $array_files = array(); + $initial_root_dir = $root_dir; + foreach ($modules as $module) { + $root_dir = $initial_root_dir; + if ($module{0} == '.') { + continue; + } - /** - * This method get translation in each translations file. - * The file depend on $lang param. - * - * @param array $modules List of modules - * @param string|null $root_dir path where it get each modules - * @param string $lang ISO code of chosen language to translate - * @param bool $is_default Set it if modules are located in root/prestashop/modules folder - * This allow to distinguish overridden prestashop theme and original module - * - * @return array - */ - protected function getAllModuleFiles($modules, $root_dir = null, $lang, $is_default = false) - { - $array_files = array(); - $initial_root_dir = $root_dir; - foreach ($modules as $module) - { - $root_dir = $initial_root_dir; - if ($module{0} == '.') - continue; + // First we load the default translation file + if ($root_dir == null) { + $i18n_dir = $this->translations_informations[$this->type_selected]['dir']; + if (is_dir($i18n_dir.$module)) { + $root_dir = $i18n_dir; + } - // First we load the default translation file - if ($root_dir == null) - { - $i18n_dir = $this->translations_informations[$this->type_selected]['dir']; - if (is_dir($i18n_dir.$module)) - $root_dir = $i18n_dir; + $lang_file = $root_dir.$module.'/translations/'.$lang.'.php'; + if (!Tools::file_exists_cache($root_dir.$module.'/translations/'.$lang.'.php') && Tools::file_exists_cache($root_dir.$module.'/'.$lang.'.php')) { + $lang_file = $root_dir.$module.'/'.$lang.'.php'; + } + @include($lang_file); + $this->getModuleTranslations(); + // If a theme is selected, then the destination translation file must be in the theme + if ($this->theme_selected) { + $lang_file = $this->translations_informations[$this->type_selected]['override']['dir'].$module.'/translations/'.$lang.'.php'; + } + $this->recursiveGetModuleFiles($root_dir.$module.'/', $array_files, $module, $lang_file, $is_default); + } - $lang_file = $root_dir.$module.'/translations/'.$lang.'.php'; - if (!Tools::file_exists_cache($root_dir.$module.'/translations/'.$lang.'.php') && Tools::file_exists_cache($root_dir.$module.'/'.$lang.'.php')) - $lang_file = $root_dir.$module.'/'.$lang.'.php'; - @include($lang_file); - $this->getModuleTranslations(); - // If a theme is selected, then the destination translation file must be in the theme - if ($this->theme_selected) - $lang_file = $this->translations_informations[$this->type_selected]['override']['dir'].$module.'/translations/'.$lang.'.php'; - $this->recursiveGetModuleFiles($root_dir.$module.'/', $array_files, $module, $lang_file, $is_default); - } + $root_dir = $initial_root_dir; + // Then we load the overriden translation file + if ($this->theme_selected && isset($this->translations_informations[$this->type_selected]['override'])) { + $i18n_dir = $this->translations_informations[$this->type_selected]['override']['dir']; + if (is_dir($i18n_dir.$module)) { + $root_dir = $i18n_dir; + } + if (Tools::file_exists_cache($root_dir.$module.'/translations/'.$lang.'.php')) { + $lang_file = $root_dir.$module.'/translations/'.$lang.'.php'; + } elseif (Tools::file_exists_cache($root_dir.$module.'/'.$lang.'.php')) { + $lang_file = $root_dir.$module.'/'.$lang.'.php'; + } + @include($lang_file); + $this->getModuleTranslations(); + $this->recursiveGetModuleFiles($root_dir.$module.'/', $array_files, $module, $lang_file, $is_default); + } + } + return $array_files; + } - $root_dir = $initial_root_dir; - // Then we load the overriden translation file - if ($this->theme_selected && isset($this->translations_informations[$this->type_selected]['override'])) - { - $i18n_dir = $this->translations_informations[$this->type_selected]['override']['dir']; - if (is_dir($i18n_dir.$module)) - $root_dir = $i18n_dir; - if (Tools::file_exists_cache($root_dir.$module.'/translations/'.$lang.'.php')) - $lang_file = $root_dir.$module.'/translations/'.$lang.'.php'; - elseif (Tools::file_exists_cache($root_dir.$module.'/'.$lang.'.php')) - $lang_file = $root_dir.$module.'/'.$lang.'.php'; - @include($lang_file); - $this->getModuleTranslations(); - $this->recursiveGetModuleFiles($root_dir.$module.'/', $array_files, $module, $lang_file, $is_default); - } - } - return $array_files; - } + /** + * This method generate the form for modules translations + */ + public function initFormModules() + { + // Get list of modules + $modules = $this->getListModules(); - /** - * This method generate the form for modules translations - */ - public function initFormModules() - { - // Get list of modules - $modules = $this->getListModules(); + if (!empty($modules)) { + // Get all modules files and include all translation files + $arr_files = $this->getAllModuleFiles($modules, null, $this->lang_selected->iso_code, true); + foreach ($arr_files as $value) { + $this->findAndFillTranslations($value['files'], $value['theme'], $value['module'], $value['dir']); + } - if (!empty($modules)) - { - // Get all modules files and include all translation files - $arr_files = $this->getAllModuleFiles($modules, null, $this->lang_selected->iso_code, true); - foreach ($arr_files as $value) - $this->findAndFillTranslations($value['files'], $value['theme'], $value['module'], $value['dir']); + $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( + 'default_theme_name' => self::DEFAULT_THEME_NAME, + 'count' => $this->total_expression, + 'limit_warning' => $this->displayLimitPostWarning($this->total_expression), + 'mod_security_warning' => Tools::apacheModExists('mod_security'), + 'textarea_sized' => AdminTranslationsControllerCore::TEXTAREA_SIZED, + 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), + 'modules_translations' => isset($this->modules_translations) ? $this->modules_translations : array(), + 'missing_translations' => $this->missing_translations + )); - $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( - 'default_theme_name' => self::DEFAULT_THEME_NAME, - 'count' => $this->total_expression, - 'limit_warning' => $this->displayLimitPostWarning($this->total_expression), - 'mod_security_warning' => Tools::apacheModExists('mod_security'), - 'textarea_sized' => AdminTranslationsControllerCore::TEXTAREA_SIZED, - 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), - 'modules_translations' => isset($this->modules_translations) ? $this->modules_translations : array(), - 'missing_translations' => $this->missing_translations - )); + $this->initToolbar(); + $this->base_tpl_view = 'translation_modules.tpl'; + return parent::renderView(); + } + } - $this->initToolbar(); - $this->base_tpl_view = 'translation_modules.tpl'; - return parent::renderView(); - } - } + /** + * Parse PDF class + * @since 1.4.5.0 + * + * @param string $file_path File to parse + * @param string $file_type Type of file + * @param array $lang_array Contains expression in the chosen language + * @param string $tab name To use with the md5 key + * @param array $tabs_array + * @param array $count_missing + * + * @return array Array Containing all datas needed for building the translation form + */ + protected function parsePdfClass($file_path, $file_type, $lang_array, $tab, $tabs_array, &$count_missing) + { + // Get content for this file + $content = file_get_contents($file_path); - /** - * Parse PDF class - * @since 1.4.5.0 - * - * @param string $file_path File to parse - * @param string $file_type Type of file - * @param array $lang_array Contains expression in the chosen language - * @param string $tab name To use with the md5 key - * @param array $tabs_array - * @param array $count_missing - * - * @return array Array Containing all datas needed for building the translation form - */ - protected function parsePdfClass($file_path, $file_type, $lang_array, $tab, $tabs_array, &$count_missing) - { - // Get content for this file - $content = file_get_contents($file_path); + // Parse this content + $matches = $this->userParseFile($content, $this->type_selected, $file_type); - // Parse this content - $matches = $this->userParseFile($content, $this->type_selected, $file_type); + foreach ($matches as $key) { + if (stripslashes(array_key_exists($tab.md5(addslashes($key)), $lang_array))) { + $tabs_array[$tab][$key]['trad'] = html_entity_decode($lang_array[$tab.md5(addslashes($key))], ENT_COMPAT, 'UTF-8'); + } else { + $tabs_array[$tab][$key]['trad'] = ''; + if (!isset($count_missing[$tab])) { + $count_missing[$tab] = 1; + } else { + $count_missing[$tab]++; + } + } + $tabs_array[$tab][$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); + } - foreach ($matches as $key) - { - if (stripslashes(array_key_exists($tab.md5(addslashes($key)), $lang_array))) - $tabs_array[$tab][$key]['trad'] = html_entity_decode($lang_array[$tab.md5(addslashes($key))], ENT_COMPAT, 'UTF-8'); - else - { - $tabs_array[$tab][$key]['trad'] = ''; - if (!isset($count_missing[$tab])) - $count_missing[$tab] = 1; - else - $count_missing[$tab]++; - } - $tabs_array[$tab][$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); - } + return $tabs_array; + } - return $tabs_array; - } + /** + * This method generate the form for PDF translations + */ + public function initFormPDF() + { + $name_var = $this->translations_informations[$this->type_selected]['var']; + $GLOBALS[$name_var] = array(); + $missing_translations_pdf = array(); - /** - * This method generate the form for PDF translations - */ - public function initFormPDF() - { - $name_var = $this->translations_informations[$this->type_selected]['var']; - $GLOBALS[$name_var] = array(); - $missing_translations_pdf = array(); + $i18n_dir = $this->translations_informations[$this->type_selected]['dir']; + $default_i18n_file = $i18n_dir.$this->translations_informations[$this->type_selected]['file']; - $i18n_dir = $this->translations_informations[$this->type_selected]['dir']; - $default_i18n_file = $i18n_dir.$this->translations_informations[$this->type_selected]['file']; + if (!$this->theme_selected) { + $i18n_file = $default_i18n_file; + } else { + $i18n_dir = $this->translations_informations[$this->type_selected]['override']['dir']; + $i18n_file = $i18n_dir.$this->translations_informations[$this->type_selected]['override']['file']; + } - if (!$this->theme_selected) - $i18n_file = $default_i18n_file; - else - { - $i18n_dir = $this->translations_informations[$this->type_selected]['override']['dir']; - $i18n_file = $i18n_dir.$this->translations_informations[$this->type_selected]['override']['file']; - } + $this->checkDirAndCreate($i18n_file); + if ((!file_exists($i18n_file) && !is_writable($i18n_dir)) && !is_writable($i18n_file)) { + $this->errors[] = sprintf(Tools::displayError('Cannot write into the "%s"'), $i18n_file); + } - $this->checkDirAndCreate($i18n_file); - if ((!file_exists($i18n_file) && !is_writable($i18n_dir)) && !is_writable($i18n_file)) - $this->errors[] = sprintf(Tools::displayError('Cannot write into the "%s"'), $i18n_file); + @include($i18n_file); - @include($i18n_file); + // if the override's translation file is empty load the default file + if (!isset($GLOBALS[$name_var]) || count($GLOBALS[$name_var]) == 0) { + @include($default_i18n_file); + } - // if the override's translation file is empty load the default file - if (!isset($GLOBALS[$name_var]) || count($GLOBALS[$name_var]) == 0) - @include($default_i18n_file); + $prefix_key = 'PDF'; + $tabs_array = array($prefix_key => array()); - $prefix_key = 'PDF'; - $tabs_array = array($prefix_key => array()); + $files_by_directory = $this->getFileToParseByTypeTranslation(); - $files_by_directory = $this->getFileToParseByTypeTranslation(); + foreach ($files_by_directory as $type => $directories) { + foreach ($directories as $dir => $files) { + foreach ($files as $file) { + if (!in_array($file, self::$ignore_folder) && Tools::file_exists_cache($file_path = $dir.$file)) { + if ($type == 'tpl') { + if (Tools::file_exists_cache($file_path) && is_file($file_path)) { + // Get content for this file + $content = file_get_contents($file_path); - foreach ($files_by_directory as $type => $directories) - foreach ($directories as $dir => $files) - foreach ($files as $file) - if (!in_array($file, self::$ignore_folder) && Tools::file_exists_cache($file_path = $dir.$file)) - { - if ($type == 'tpl') - { - if (Tools::file_exists_cache($file_path) && is_file($file_path)) - { - // Get content for this file - $content = file_get_contents($file_path); + // Parse this content + $matches = $this->userParseFile($content, $this->type_selected, 'tpl'); - // Parse this content - $matches = $this->userParseFile($content, $this->type_selected, 'tpl'); + foreach ($matches as $key) { + if (isset($GLOBALS[$name_var][$prefix_key.md5($key)])) { + $tabs_array[$prefix_key][$key]['trad'] = (html_entity_decode($GLOBALS[$name_var][$prefix_key.md5($key)], ENT_COMPAT, 'UTF-8')); + } else { + if (!isset($tabs_array[$prefix_key][$key]['trad'])) { + $tabs_array[$prefix_key][$key]['trad'] = ''; + if (!isset($missing_translations_pdf[$prefix_key])) { + $missing_translations_pdf[$prefix_key] = 1; + } else { + $missing_translations_pdf[$prefix_key]++; + } + } + } + $tabs_array[$prefix_key][$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); + } + } + } elseif (Tools::file_exists_cache($file_path)) { + $tabs_array = $this->parsePdfClass($file_path, 'php', $GLOBALS[$name_var], $prefix_key, $tabs_array, $missing_translations_pdf); + } + } + } + } + } - foreach ($matches as $key) - { - if (isset($GLOBALS[$name_var][$prefix_key.md5($key)])) - $tabs_array[$prefix_key][$key]['trad'] = (html_entity_decode($GLOBALS[$name_var][$prefix_key.md5($key)], ENT_COMPAT, 'UTF-8')); - else - { - if (!isset($tabs_array[$prefix_key][$key]['trad'])) - { - $tabs_array[$prefix_key][$key]['trad'] = ''; - if (!isset($missing_translations_pdf[$prefix_key])) - $missing_translations_pdf[$prefix_key] = 1; - else - $missing_translations_pdf[$prefix_key]++; - } - } - $tabs_array[$prefix_key][$key]['use_sprintf'] = $this->checkIfKeyUseSprintf($key); - } - } - } - else - if (Tools::file_exists_cache($file_path)) - $tabs_array = $this->parsePdfClass($file_path, 'php', $GLOBALS[$name_var], $prefix_key, $tabs_array, $missing_translations_pdf); - } + $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( + 'count' => count($tabs_array['PDF']), + 'limit_warning' => $this->displayLimitPostWarning(count($tabs_array['PDF'])), + 'mod_security_warning' => Tools::apacheModExists('mod_security'), + 'tabsArray' => $tabs_array, + 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), + 'missing_translations' => $missing_translations_pdf + )); - $this->tpl_view_vars = array_merge($this->tpl_view_vars, array( - 'count' => count($tabs_array['PDF']), - 'limit_warning' => $this->displayLimitPostWarning(count($tabs_array['PDF'])), - 'mod_security_warning' => Tools::apacheModExists('mod_security'), - 'tabsArray' => $tabs_array, - 'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'), - 'missing_translations' => $missing_translations_pdf - )); + $this->initToolbar(); + $this->base_tpl_view = 'translation_form.tpl'; + return parent::renderView(); + } - $this->initToolbar(); - $this->base_tpl_view = 'translation_form.tpl'; - return parent::renderView(); - } + /** + * Recursively list files in directory $dir + * + * @param string $dir + * @param array $list + * @param string $file_ext + * + * @return array + */ + public function listFiles($dir, $list = array(), $file_ext = 'tpl') + { + $dir = rtrim($dir, '/').DIRECTORY_SEPARATOR; - /** - * Recursively list files in directory $dir - * - * @param string $dir - * @param array $list - * @param string $file_ext - * - * @return array - */ - public function listFiles($dir, $list = array(), $file_ext = 'tpl') - { - $dir = rtrim($dir, '/').DIRECTORY_SEPARATOR; + $to_parse = scandir($dir); + // copied (and kind of) adapted from AdminImages.php + foreach ($to_parse as $file) { + if (!in_array($file, self::$ignore_folder)) { + if (preg_match('#'.preg_quote($file_ext, '#').'$#i', $file)) { + $list[$dir][] = $file; + } elseif (is_dir($dir.$file)) { + $list = $this->listFiles($dir.$file, $list, $file_ext); + } + } + } + return $list; + } - $to_parse = scandir($dir); - // copied (and kind of) adapted from AdminImages.php - foreach ($to_parse as $file) - { - if (!in_array($file, self::$ignore_folder)) - { - if (preg_match('#'.preg_quote($file_ext, '#').'$#i', $file)) - $list[$dir][] = $file; - elseif (is_dir($dir.$file)) - $list = $this->listFiles($dir.$file, $list, $file_ext); - } - } - return $list; - } + /** + * Checks if theme exists + * + * @param string $theme + * + * @return bool + */ + protected function theme_exists($theme) + { + if (!is_array($this->themes)) { + $this->themes = Theme::getThemes(); + } - /** - * Checks if theme exists - * - * @param string $theme - * - * @return bool - */ - protected function theme_exists($theme) - { - if (!is_array($this->themes)) - $this->themes = Theme::getThemes(); + $theme_exists = false; + foreach ($this->themes as $existing_theme) { + /** @var Theme $existing_theme */ + if ($existing_theme->directory == $theme) { + return true; + } + } - $theme_exists = false; - foreach ($this->themes as $existing_theme) - { - /** @var Theme $existing_theme */ - if ($existing_theme->directory == $theme) - return true; - } - - return false; - } + return false; + } } diff --git a/controllers/admin/AdminWarehousesController.php b/controllers/admin/AdminWarehousesController.php index 86d27e4c..9497406f 100644 --- a/controllers/admin/AdminWarehousesController.php +++ b/controllers/admin/AdminWarehousesController.php @@ -30,87 +30,88 @@ */ class AdminWarehousesControllerCore extends AdminController { - public function __construct() - { - $this->bootstrap = true; - $this->table = 'warehouse'; - $this->className = 'Warehouse'; - $this->deleted = true; - $this->lang = false; - $this->multishop_context = Shop::CONTEXT_ALL; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'warehouse'; + $this->className = 'Warehouse'; + $this->deleted = true; + $this->lang = false; + $this->multishop_context = Shop::CONTEXT_ALL; - $this->fields_list = array( - 'id_warehouse' => array( - 'title' => $this->l('ID'), - 'width' => 50, - ), - 'reference' => array( - 'title' => $this->l('Reference'), - ), - 'name' => array( - 'title' => $this->l('Name'), - ), - 'management_type' => array( - 'title' => $this->l('Management type'), - ), - 'employee' => array( - 'title' => $this->l('Manager'), - 'filter_key' => 'employee', - 'havingFilter' => true - ), - 'location' => array( - 'title' => $this->l('Location'), - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - 'contact' => array( - 'title' => $this->l('Phone Number'), - 'orderby' => false, - 'filter' => false, - 'search' => false, - ), - ); + $this->fields_list = array( + 'id_warehouse' => array( + 'title' => $this->l('ID'), + 'width' => 50, + ), + 'reference' => array( + 'title' => $this->l('Reference'), + ), + 'name' => array( + 'title' => $this->l('Name'), + ), + 'management_type' => array( + 'title' => $this->l('Management type'), + ), + 'employee' => array( + 'title' => $this->l('Manager'), + 'filter_key' => 'employee', + 'havingFilter' => true + ), + 'location' => array( + 'title' => $this->l('Location'), + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + 'contact' => array( + 'title' => $this->l('Phone Number'), + 'orderby' => false, + 'filter' => false, + 'search' => false, + ), + ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'icon' => 'icon-trash', - 'confirm' => $this->l('Delete selected items?') - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'icon' => 'icon-trash', + 'confirm' => $this->l('Delete selected items?') + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - if(empty($this->display)) - $this->page_header_toolbar_btn['new_warehouse'] = array( - 'href' => self::$currentIndex.'&addwarehouse&token='.$this->token, - 'desc' => $this->l('Add new warehouse', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_warehouse'] = array( + 'href' => self::$currentIndex.'&addwarehouse&token='.$this->token, + 'desc' => $this->l('Add new warehouse', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - /** - * AdminController::renderList() override - * @see AdminController::renderList() - */ - public function renderList() - { - // removes links on rows - $this->list_no_link = true; + /** + * AdminController::renderList() override + * @see AdminController::renderList() + */ + public function renderList() + { + // removes links on rows + $this->list_no_link = true; - // adds actions on rows - $this->addRowAction('edit'); - $this->addRowAction('view'); - $this->addRowAction('delete'); + // adds actions on rows + $this->addRowAction('edit'); + $this->addRowAction('view'); + $this->addRowAction('delete'); - // query: select - $this->_select = ' + // query: select + $this->_select = ' reference, name, management_type, @@ -118,551 +119,562 @@ class AdminWarehousesControllerCore extends AdminController ad.phone as contact, CONCAT(ad.city, \' - \', c.iso_code) as location'; - // query: join - $this->_join = ' + // query: join + $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'employee` e ON (e.id_employee = a.id_employee) LEFT JOIN `'._DB_PREFIX_.'address` ad ON (ad.id_address = a.id_address) LEFT JOIN `'._DB_PREFIX_.'country` c ON (c.id_country = ad.id_country)'; - $this->_use_found_rows = false; - // display help informations - $this->displayInformation($this->l('This interface allows you to manage your warehouses.').'
'); - $this->displayInformation($this->l('Before adding stock in your warehouses, you should check the default currency used.').'
'); - $this->displayInformation($this->l('You should also check the management type (according to the law in your country), the valuation currency and its associated carriers and shops.').'
'); - $this->displayInformation($this->l('You can also see detailed information about your stock, such as its overall value, the number of products and quantities stored, etc.')); - $this->displayInformation($this->l('Be careful! Products from different warehouses will need to be shipped in different packages.')); + $this->_use_found_rows = false; + // display help informations + $this->displayInformation($this->l('This interface allows you to manage your warehouses.').'
'); + $this->displayInformation($this->l('Before adding stock in your warehouses, you should check the default currency used.').'
'); + $this->displayInformation($this->l('You should also check the management type (according to the law in your country), the valuation currency and its associated carriers and shops.').'
'); + $this->displayInformation($this->l('You can also see detailed information about your stock, such as its overall value, the number of products and quantities stored, etc.')); + $this->displayInformation($this->l('Be careful! Products from different warehouses will need to be shipped in different packages.')); - return parent::renderList(); - } + return parent::renderList(); + } - /** - * AdminController::renderForm() override - * @see AdminController::renderForm() - */ - public function renderForm() - { - /** @var Warehouse $obj */ - // loads current warehouse - if (!($obj = $this->loadObject(true))) - return; + /** + * AdminController::renderForm() override + * @see AdminController::renderForm() + */ + public function renderForm() + { + /** @var Warehouse $obj */ + // loads current warehouse + if (!($obj = $this->loadObject(true))) { + return; + } - // gets the manager of the warehouse - $query = new DbQuery(); - $query->select('id_employee, CONCAT(lastname," ",firstname) as name'); - $query->from('employee'); - $query->where('active = 1'); - $employees_array = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + // gets the manager of the warehouse + $query = new DbQuery(); + $query->select('id_employee, CONCAT(lastname," ",firstname) as name'); + $query->from('employee'); + $query->where('active = 1'); + $employees_array = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); - // sets the title of the toolbar - if (Tools::isSubmit('add'.$this->table)) - $this->toolbar_title = $this->l('Stock: Create a warehouse'); - else - $this->toolbar_title = $this->l('Stock: Warehouse management'); + // sets the title of the toolbar + if (Tools::isSubmit('add'.$this->table)) { + $this->toolbar_title = $this->l('Stock: Create a warehouse'); + } else { + $this->toolbar_title = $this->l('Stock: Warehouse management'); + } - $tmp_addr = new Address(); - $res = $tmp_addr->getFieldsRequiredDatabase(); - $required_fields = array(); - foreach ($res as $row) - $required_fields[(int)$row['id_required_field']] = $row['field_name']; + $tmp_addr = new Address(); + $res = $tmp_addr->getFieldsRequiredDatabase(); + $required_fields = array(); + foreach ($res as $row) { + $required_fields[(int)$row['id_required_field']] = $row['field_name']; + } - // sets the fields of the form - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Warehouse information'), - 'icon' => 'icon-pencil' - ), - 'input' => array( - array( - 'type' => 'hidden', - 'name' => 'id_address', - ), - array( - 'type' => 'text', - 'label' => $this->l('Reference'), - 'name' => 'reference', - 'maxlength' => 32, - 'required' => true, - 'hint' => $this->l('Reference for this warehouse.'), - ), - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'maxlength' => 45, - 'required' => true, - 'hint' => array( - $this->l('Name of this warehouse.'), - $this->l('Invalid characters:').' !<>,;?=+()@#"�{}_$%:', - ) - ), - array( - 'type' => 'text', - 'label' => $this->l('Phone'), - 'name' => 'phone', - 'maxlength' => 16, - 'hint' => $this->l('Phone number for this warehouse.'), - 'required' => in_array('phone', $required_fields) - ), - array( - 'type' => 'text', - 'label' => $this->l('Mobile phone'), - 'name' => 'phone_mobile', - 'required' => in_array('phone_mobile', $required_fields), - 'maxlength' => 16, - 'hint' => $this->l('Mobile phone number for this supplier.') - ), - array( - 'type' => 'text', - 'label' => $this->l('Address'), - 'name' => 'address', - 'maxlength' => 128, - 'required' => true - ), - array( - 'type' => 'text', - 'label' => $this->l('Address').' (2)', - 'name' => 'address2', - 'maxlength' => 128, - 'hint' => $this->l('Complementary address (optional).'), - 'required' => in_array('address2', $required_fields) - ), - array( - 'type' => 'text', - 'label' => $this->l('Zip/postal code'), - 'name' => 'postcode', - 'maxlength' => 12, - 'required' => in_array('postcode', $required_fields) - ), - array( - 'type' => 'text', - 'label' => $this->l('City'), - 'name' => 'city', - 'maxlength' => 32, - 'required' => true, - ), - array( - 'type' => 'select', - 'label' => $this->l('Country'), - 'name' => 'id_country', - 'required' => true, - 'default_value' => (int)$this->context->country->id, - 'options' => array( - 'query' => Country::getCountries($this->context->language->id, false), - 'id' => 'id_country', - 'name' => 'name', - ), - 'hint' => $this->l('Country of location of the warehouse.') - ), - array( - 'type' => 'select', - 'label' => $this->l('State'), - 'name' => 'id_state', - 'required' => true, - 'options' => array( - 'query' => array(), - 'id' => 'id_state', - 'name' => 'name' - ) - ), - array( - 'type' => 'select', - 'label' => $this->l('Manager'), - 'name' => 'id_employee', - 'required' => true, - 'options' => array( - 'query' => $employees_array, - 'id' => 'id_employee', - 'name' => 'name' - ), - ), - array( - 'type' => 'swap', - 'label' => $this->l('Carriers'), - 'name' => 'ids_carriers', - 'required' => false, - 'multiple' => true, - 'options' => array( - 'query' => Carrier::getCarriers($this->context->language->id, false, false, false, null, Carrier::ALL_CARRIERS), - 'id' => 'id_reference', - 'name' => 'name' - ), - 'hint' => array( - $this->l('Associated carriers.'), - $this->l('You can choose which carriers can ship orders from particular warehouses.'), - $this->l('If you do not select any carrier, all the carriers will be able to ship from this warehouse.'), - ), - 'desc' => $this->l('If no carrier is selected, all the carriers will be allowed to ship from this warehouse. Use CTRL+Click to select more than one carrier.'), - ), - ), + // sets the fields of the form + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Warehouse information'), + 'icon' => 'icon-pencil' + ), + 'input' => array( + array( + 'type' => 'hidden', + 'name' => 'id_address', + ), + array( + 'type' => 'text', + 'label' => $this->l('Reference'), + 'name' => 'reference', + 'maxlength' => 32, + 'required' => true, + 'hint' => $this->l('Reference for this warehouse.'), + ), + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'maxlength' => 45, + 'required' => true, + 'hint' => array( + $this->l('Name of this warehouse.'), + $this->l('Invalid characters:').' !<>,;?=+()@#"�{}_$%:', + ) + ), + array( + 'type' => 'text', + 'label' => $this->l('Phone'), + 'name' => 'phone', + 'maxlength' => 16, + 'hint' => $this->l('Phone number for this warehouse.'), + 'required' => in_array('phone', $required_fields) + ), + array( + 'type' => 'text', + 'label' => $this->l('Mobile phone'), + 'name' => 'phone_mobile', + 'required' => in_array('phone_mobile', $required_fields), + 'maxlength' => 16, + 'hint' => $this->l('Mobile phone number for this supplier.') + ), + array( + 'type' => 'text', + 'label' => $this->l('Address'), + 'name' => 'address', + 'maxlength' => 128, + 'required' => true + ), + array( + 'type' => 'text', + 'label' => $this->l('Address').' (2)', + 'name' => 'address2', + 'maxlength' => 128, + 'hint' => $this->l('Complementary address (optional).'), + 'required' => in_array('address2', $required_fields) + ), + array( + 'type' => 'text', + 'label' => $this->l('Zip/postal code'), + 'name' => 'postcode', + 'maxlength' => 12, + 'required' => in_array('postcode', $required_fields) + ), + array( + 'type' => 'text', + 'label' => $this->l('City'), + 'name' => 'city', + 'maxlength' => 32, + 'required' => true, + ), + array( + 'type' => 'select', + 'label' => $this->l('Country'), + 'name' => 'id_country', + 'required' => true, + 'default_value' => (int)$this->context->country->id, + 'options' => array( + 'query' => Country::getCountries($this->context->language->id, false), + 'id' => 'id_country', + 'name' => 'name', + ), + 'hint' => $this->l('Country of location of the warehouse.') + ), + array( + 'type' => 'select', + 'label' => $this->l('State'), + 'name' => 'id_state', + 'required' => true, + 'options' => array( + 'query' => array(), + 'id' => 'id_state', + 'name' => 'name' + ) + ), + array( + 'type' => 'select', + 'label' => $this->l('Manager'), + 'name' => 'id_employee', + 'required' => true, + 'options' => array( + 'query' => $employees_array, + 'id' => 'id_employee', + 'name' => 'name' + ), + ), + array( + 'type' => 'swap', + 'label' => $this->l('Carriers'), + 'name' => 'ids_carriers', + 'required' => false, + 'multiple' => true, + 'options' => array( + 'query' => Carrier::getCarriers($this->context->language->id, false, false, false, null, Carrier::ALL_CARRIERS), + 'id' => 'id_reference', + 'name' => 'name' + ), + 'hint' => array( + $this->l('Associated carriers.'), + $this->l('You can choose which carriers can ship orders from particular warehouses.'), + $this->l('If you do not select any carrier, all the carriers will be able to ship from this warehouse.'), + ), + 'desc' => $this->l('If no carrier is selected, all the carriers will be allowed to ship from this warehouse. Use CTRL+Click to select more than one carrier.'), + ), + ), - ); + ); - // Shop Association - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - 'disable_shared' => Shop::SHARE_STOCK - ); - } + // Shop Association + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + 'disable_shared' => Shop::SHARE_STOCK + ); + } - // if it is still possible to change currency valuation and management type - if (Tools::isSubmit('addwarehouse') || Tools::isSubmit('submitAddwarehouse')) - { - // adds input management type - $this->fields_form['input'][] = array( - 'type' => 'select', - 'label' => $this->l('Management type'), - 'hint' => $this->l('Inventory valuation method. Be careful! You won\'t be able to change this value later!'), - 'name' => 'management_type', - 'required' => true, - 'options' => array( - 'query' => array( - array( - 'id' => 'WA', - 'name' => $this->l('Weighted Average') - ), - array( - 'id' => 'FIFO', - 'name' => $this->l('First In, First Out') - ), - array( - 'id' => 'LIFO', - 'name' => $this->l('Last In, First Out') - ), - ), - 'id' => 'id', - 'name' => 'name' - ), - ); + // if it is still possible to change currency valuation and management type + if (Tools::isSubmit('addwarehouse') || Tools::isSubmit('submitAddwarehouse')) { + // adds input management type + $this->fields_form['input'][] = array( + 'type' => 'select', + 'label' => $this->l('Management type'), + 'hint' => $this->l('Inventory valuation method. Be careful! You won\'t be able to change this value later!'), + 'name' => 'management_type', + 'required' => true, + 'options' => array( + 'query' => array( + array( + 'id' => 'WA', + 'name' => $this->l('Weighted Average') + ), + array( + 'id' => 'FIFO', + 'name' => $this->l('First In, First Out') + ), + array( + 'id' => 'LIFO', + 'name' => $this->l('Last In, First Out') + ), + ), + 'id' => 'id', + 'name' => 'name' + ), + ); - // adds input valuation currency - $this->fields_form['input'][] = array( - 'type' => 'select', - 'label' => $this->l('Stock valuation currency'), - 'hint' => $this->l('Be careful! You won\'t be able to change this value later!'), - 'name' => 'id_currency', - 'required' => true, - 'options' => array( - 'query' => Currency::getCurrencies(), - 'id' => 'id_currency', - 'name' => 'name' - ) - ); - } - else // else hide input - { - $this->fields_form['input'][] = array( - 'type' => 'hidden', - 'name' => 'management_type' - ); + // adds input valuation currency + $this->fields_form['input'][] = array( + 'type' => 'select', + 'label' => $this->l('Stock valuation currency'), + 'hint' => $this->l('Be careful! You won\'t be able to change this value later!'), + 'name' => 'id_currency', + 'required' => true, + 'options' => array( + 'query' => Currency::getCurrencies(), + 'id' => 'id_currency', + 'name' => 'name' + ) + ); + } else { + // else hide input - $this->fields_form['input'][] = array( - 'type' => 'hidden', - 'name' => 'id_currency' - ); - } + $this->fields_form['input'][] = array( + 'type' => 'hidden', + 'name' => 'management_type' + ); - $this->fields_form['submit'] = array( - 'title' => $this->l('Save'), - ); + $this->fields_form['input'][] = array( + 'type' => 'hidden', + 'name' => 'id_currency' + ); + } - $address = null; - // loads current address for this warehouse - if possible - if ($obj->id_address > 0) - $address = new Address($obj->id_address); + $this->fields_form['submit'] = array( + 'title' => $this->l('Save'), + ); - // loads current shops associated with this warehouse - $shops = $obj->getShops(); - $ids_shop = array(); - foreach ($shops as $shop) - $ids_shop[] = $shop['id_shop']; + $address = null; + // loads current address for this warehouse - if possible + if ($obj->id_address > 0) { + $address = new Address($obj->id_address); + } - // loads current carriers associated with this warehouse - $carriers = $obj->getCarriers(true); + // loads current shops associated with this warehouse + $shops = $obj->getShops(); + $ids_shop = array(); + foreach ($shops as $shop) { + $ids_shop[] = $shop['id_shop']; + } - // if an address is available : force specific fields values - if ($address != null) - $this->fields_value = array( - 'id_address' => $address->id, - 'phone' => $address->phone, - 'address' => $address->address1, - 'address2' => $address->address2, - 'postcode' => $address->postcode, - 'city' => $address->city, - 'id_country' => $address->id_country, - 'id_state' => $address->id_state, - ); - else // loads default country - $this->fields_value = array( - 'id_address' => 0, - 'id_country' => Configuration::get('PS_COUNTRY_DEFAULT') - ); + // loads current carriers associated with this warehouse + $carriers = $obj->getCarriers(true); - // loads shops and carriers - $this->fields_value['ids_shops[]'] = $ids_shop; - $this->fields_value['ids_carriers'] = $carriers; + // if an address is available : force specific fields values + if ($address != null) { + $this->fields_value = array( + 'id_address' => $address->id, + 'phone' => $address->phone, + 'address' => $address->address1, + 'address2' => $address->address2, + 'postcode' => $address->postcode, + 'city' => $address->city, + 'id_country' => $address->id_country, + 'id_state' => $address->id_state, + ); + } else { // loads default country + $this->fields_value = array( + 'id_address' => 0, + 'id_country' => Configuration::get('PS_COUNTRY_DEFAULT') + ); + } - if (!Validate::isLoadedObject($obj)) - $this->fields_value['id_currency'] = (int)Configuration::get('PS_CURRENCY_DEFAULT'); + // loads shops and carriers + $this->fields_value['ids_shops[]'] = $ids_shop; + $this->fields_value['ids_carriers'] = $carriers; - return parent::renderForm(); - } + if (!Validate::isLoadedObject($obj)) { + $this->fields_value['id_currency'] = (int)Configuration::get('PS_CURRENCY_DEFAULT'); + } - /** - * @see AdminController::renderView() - */ - public function renderView() - { - // gets necessary objects - $id_warehouse = (int)Tools::getValue('id_warehouse'); - $warehouse = new Warehouse($id_warehouse); - $employee = new Employee($warehouse->id_employee); - $currency = new Currency($warehouse->id_currency); - $address = new Address($warehouse->id_address); - $shops = $warehouse->getShops(); + return parent::renderForm(); + } - $this->toolbar_title = $warehouse->name; + /** + * @see AdminController::renderView() + */ + public function renderView() + { + // gets necessary objects + $id_warehouse = (int)Tools::getValue('id_warehouse'); + $warehouse = new Warehouse($id_warehouse); + $employee = new Employee($warehouse->id_employee); + $currency = new Currency($warehouse->id_currency); + $address = new Address($warehouse->id_address); + $shops = $warehouse->getShops(); - // checks objects - if (!Validate::isLoadedObject($warehouse) || - !Validate::isLoadedObject($employee) || - !Validate::isLoadedObject($currency) || - !Validate::isLoadedObject($address)) - return parent::renderView(); + $this->toolbar_title = $warehouse->name; - // assigns to our view - $this->tpl_view_vars = array( - 'warehouse' => $warehouse, - 'employee' => $employee, - 'currency' => $currency, - 'address' => $address, - 'shops' => $shops, - 'warehouse_num_products' => $warehouse->getNumberOfProducts(), - 'warehouse_value' => Tools::displayPrice(Tools::ps_round($warehouse->getStockValue(), 2), $currency), - 'warehouse_quantities' => $warehouse->getQuantitiesofProducts(), - ); + // checks objects + if (!Validate::isLoadedObject($warehouse) || + !Validate::isLoadedObject($employee) || + !Validate::isLoadedObject($currency) || + !Validate::isLoadedObject($address)) { + return parent::renderView(); + } - return parent::renderView(); - } + // assigns to our view + $this->tpl_view_vars = array( + 'warehouse' => $warehouse, + 'employee' => $employee, + 'currency' => $currency, + 'address' => $address, + 'shops' => $shops, + 'warehouse_num_products' => $warehouse->getNumberOfProducts(), + 'warehouse_value' => Tools::displayPrice(Tools::ps_round($warehouse->getStockValue(), 2), $currency), + 'warehouse_quantities' => $warehouse->getQuantitiesofProducts(), + ); - /** - * Called once $object is set. - * Used to process the associations with address/shops/carriers - * @see AdminController::afterAdd() - * - * @param Warehouse $object - * - * @return bool - */ - protected function afterAdd($object) - { - // handles address association - $address = new Address($object->id_address); - if (Validate::isLoadedObject($address)) - { - $address->id_warehouse = (int)$object->id; - $address->save(); - } + return parent::renderView(); + } - // handles carriers associations - $ids_carriers_selected = Tools::getValue('ids_carriers_selected'); - if (Tools::isSubmit('ids_carriers_selected') && !empty($ids_carriers_selected)) - $object->setCarriers($ids_carriers_selected); - else - $object->setCarriers(Tools::getValue('ids_carriers_available')); + /** + * Called once $object is set. + * Used to process the associations with address/shops/carriers + * @see AdminController::afterAdd() + * + * @param Warehouse $object + * + * @return bool + */ + protected function afterAdd($object) + { + // handles address association + $address = new Address($object->id_address); + if (Validate::isLoadedObject($address)) { + $address->id_warehouse = (int)$object->id; + $address->save(); + } - return true; - } + // handles carriers associations + $ids_carriers_selected = Tools::getValue('ids_carriers_selected'); + if (Tools::isSubmit('ids_carriers_selected') && !empty($ids_carriers_selected)) { + $object->setCarriers($ids_carriers_selected); + } else { + $object->setCarriers(Tools::getValue('ids_carriers_available')); + } - /** - * AdminController::getList() override - * @see AdminController::getList() - * - * @param int $id_lang - * @param string|null $order_by - * @param string|null $order_way - * @param int $start - * @param int|null $limit - * @param int|bool $id_lang_shop - * - * @throws PrestaShopException - */ - public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) - { - parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); + return true; + } - // foreach item in the list to render - $nb_items = count($this->_list); - for ($i = 0; $i < $nb_items; ++$i) - { - // depending on the management type, translates the management type - $item = &$this->_list[$i]; - switch ($item['management_type']) // management type can be either WA/FIFO/LIFO - { - case 'WA': - $item['management_type'] = $this->l('WA: Weighted Average'); - break; + /** + * AdminController::getList() override + * @see AdminController::getList() + * + * @param int $id_lang + * @param string|null $order_by + * @param string|null $order_way + * @param int $start + * @param int|null $limit + * @param int|bool $id_lang_shop + * + * @throws PrestaShopException + */ + public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false) + { + parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop); - case 'FIFO': - $item['management_type'] = $this->l('FIFO: First In, First Out'); - break; + // foreach item in the list to render + $nb_items = count($this->_list); + for ($i = 0; $i < $nb_items; ++$i) { + // depending on the management type, translates the management type + $item = &$this->_list[$i]; + switch ($item['management_type']) {// management type can be either WA/FIFO/LIFO - case 'LIFO': - $item['management_type'] = $this->l('LIFO: Last In, First Out'); - break; - } - } - } + case 'WA': + $item['management_type'] = $this->l('WA: Weighted Average'); + break; - public function initContent() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); - return false; - } - parent::initContent(); - } + case 'FIFO': + $item['management_type'] = $this->l('FIFO: First In, First Out'); + break; - public function initProcess() - { - if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) - { - $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); - return false; - } - parent::initProcess(); - } + case 'LIFO': + $item['management_type'] = $this->l('LIFO: Last In, First Out'); + break; + } + } + } - /** - * @see AdminController::processAdd(); - */ - public function processAdd() - { - if (Tools::isSubmit('submitAdd'.$this->table)) - { - if (!($obj = $this->loadObject(true))) - return; + public function initContent() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); + return false; + } + parent::initContent(); + } - $this->updateAddress(); + public function initProcess() + { + if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { + $this->warnings[md5('PS_ADVANCED_STOCK_MANAGEMENT')] = $this->l('You need to activate advanced stock management before using this feature.'); + return false; + } + parent::initProcess(); + } - // hack for enable the possibility to update a warehouse without recreate new id - $this->deleted = false; + /** + * @see AdminController::processAdd(); + */ + public function processAdd() + { + if (Tools::isSubmit('submitAdd'.$this->table)) { + if (!($obj = $this->loadObject(true))) { + return; + } - return parent::processAdd(); - } - } + $this->updateAddress(); - protected function updateAddress() - { - // updates/creates address if it does not exist - if (Tools::isSubmit('id_address') && (int)Tools::getValue('id_address') > 0) - $address = new Address((int)Tools::getValue('id_address')); // updates address - else - $address = new Address(); // creates address - // sets the address - $address->alias = Tools::getValue('reference', null); - $address->lastname = 'warehouse'; // skip problem with numeric characters in warehouse name - $address->firstname = 'warehouse'; // skip problem with numeric characters in warehouse name - $address->address1 = Tools::getValue('address', null); - $address->address2 = Tools::getValue('address2', null); - $address->postcode = Tools::getValue('postcode', null); - $address->phone = Tools::getValue('phone', null); - $address->id_country = Tools::getValue('id_country', null); - $address->id_state = Tools::getValue('id_state', null); - $address->city = Tools::getValue('city', null); + // hack for enable the possibility to update a warehouse without recreate new id + $this->deleted = false; - if (!($country = new Country($address->id_country, Configuration::get('PS_LANG_DEFAULT'))) || !Validate::isLoadedObject($country)) - $this->errors[] = Tools::displayError('Country is invalid'); - $contains_state = isset($country) && is_object($country) ? (int)$country->contains_states: 0; - $id_state = isset($address) && is_object($address) ? (int)$address->id_state: 0; - if ($contains_state && !$id_state) - $this->errors[] = Tools::displayError('This country requires you to choose a State.'); + return parent::processAdd(); + } + } - // validates the address - $validation = $address->validateController(); + protected function updateAddress() + { + // updates/creates address if it does not exist + if (Tools::isSubmit('id_address') && (int)Tools::getValue('id_address') > 0) { + $address = new Address((int)Tools::getValue('id_address')); + } // updates address + else { + $address = new Address(); + } // creates address + // sets the address + $address->alias = Tools::getValue('reference', null); + $address->lastname = 'warehouse'; // skip problem with numeric characters in warehouse name + $address->firstname = 'warehouse'; // skip problem with numeric characters in warehouse name + $address->address1 = Tools::getValue('address', null); + $address->address2 = Tools::getValue('address2', null); + $address->postcode = Tools::getValue('postcode', null); + $address->phone = Tools::getValue('phone', null); + $address->id_country = Tools::getValue('id_country', null); + $address->id_state = Tools::getValue('id_state', null); + $address->city = Tools::getValue('city', null); - // checks address validity - if (count($validation) > 0) // if not valid - { - foreach ($validation as $item) - $this->errors[] = $item; - $this->errors[] = Tools::displayError('The address is not correct. Please make sure all of the required fields are completed.'); - } - else // valid - { - if (Tools::isSubmit('id_address') && Tools::getValue('id_address') > 0) - $address->update(); - else - { - $address->save(); - $_POST['id_address'] = $address->id; - } - } - } + if (!($country = new Country($address->id_country, Configuration::get('PS_LANG_DEFAULT'))) || !Validate::isLoadedObject($country)) { + $this->errors[] = Tools::displayError('Country is invalid'); + } + $contains_state = isset($country) && is_object($country) ? (int)$country->contains_states: 0; + $id_state = isset($address) && is_object($address) ? (int)$address->id_state: 0; + if ($contains_state && !$id_state) { + $this->errors[] = Tools::displayError('This country requires you to choose a State.'); + } - /** - * @see AdminController::processDelete(); - */ - public function processDelete() - { - if (Tools::isSubmit('delete'.$this->table)) - { - /** @var Warehouse $obj */ - // check if the warehouse exists and can be deleted - if (!($obj = $this->loadObject(true))) - return; - elseif ($obj->getQuantitiesOfProducts() > 0) // not possible : products - $this->errors[] = $this->l('It is not possible to delete a warehouse when there are products in it.'); - elseif (SupplyOrder::warehouseHasPendingOrders($obj->id)) // not possible : supply orders - $this->errors[] = $this->l('It is not possible to delete a Warehouse if it has pending supply orders.'); - else // else, it can be deleted - { - // sets the address of the warehouse as deleted - $address = new Address($obj->id_address); - $address->deleted = 1; - $address->save(); + // validates the address + $validation = $address->validateController(); - // removes associations with carriers/shops/products location - $obj->setCarriers(array()); - $obj->resetProductsLocations(); + // checks address validity + if (count($validation) > 0) { + // if not valid - return parent::processDelete(); - } - } - } + foreach ($validation as $item) { + $this->errors[] = $item; + } + $this->errors[] = Tools::displayError('The address is not correct. Please make sure all of the required fields are completed.'); + } else { + // valid - /** - * @see AdminController::processUpdate(); - */ - public function processUpdate() - { - // loads object - if (!($object = $this->loadObject(true))) - return; + if (Tools::isSubmit('id_address') && Tools::getValue('id_address') > 0) { + $address->update(); + } else { + $address->save(); + $_POST['id_address'] = $address->id; + } + } + } - /** @var Warehouse $object */ + /** + * @see AdminController::processDelete(); + */ + public function processDelete() + { + if (Tools::isSubmit('delete'.$this->table)) { + /** @var Warehouse $obj */ + // check if the warehouse exists and can be deleted + if (!($obj = $this->loadObject(true))) { + return; + } elseif ($obj->getQuantitiesOfProducts() > 0) { // not possible : products + $this->errors[] = $this->l('It is not possible to delete a warehouse when there are products in it.'); + } elseif (SupplyOrder::warehouseHasPendingOrders($obj->id)) { // not possible : supply orders + $this->errors[] = $this->l('It is not possible to delete a Warehouse if it has pending supply orders.'); + } else { + // else, it can be deleted - $this->updateAddress(); - // handles carriers associations - $ids_carriers_selected = Tools::getValue('ids_carriers_selected'); - if (Tools::isSubmit('ids_carriers_selected') && !empty($ids_carriers_selected)) - $object->setCarriers($ids_carriers_selected); - else - $object->setCarriers(Tools::getValue('ids_carriers_available')); + // sets the address of the warehouse as deleted + $address = new Address($obj->id_address); + $address->deleted = 1; + $address->save(); - return parent::processUpdate(); - } + // removes associations with carriers/shops/products location + $obj->setCarriers(array()); + $obj->resetProductsLocations(); - protected function updateAssoShop($id_object) - { - parent::updateAssoShop($id_object); - if (!($obj = $this->loadObject(true))) - return; + return parent::processDelete(); + } + } + } - /** @var Warehouse $obj */ - $obj->resetStockAvailable(); - } + /** + * @see AdminController::processUpdate(); + */ + public function processUpdate() + { + // loads object + if (!($object = $this->loadObject(true))) { + return; + } + + /** @var Warehouse $object */ + + $this->updateAddress(); + // handles carriers associations + $ids_carriers_selected = Tools::getValue('ids_carriers_selected'); + if (Tools::isSubmit('ids_carriers_selected') && !empty($ids_carriers_selected)) { + $object->setCarriers($ids_carriers_selected); + } else { + $object->setCarriers(Tools::getValue('ids_carriers_available')); + } + + return parent::processUpdate(); + } + + protected function updateAssoShop($id_object) + { + parent::updateAssoShop($id_object); + if (!($obj = $this->loadObject(true))) { + return; + } + + /** @var Warehouse $obj */ + $obj->resetStockAvailable(); + } } diff --git a/controllers/admin/AdminWebserviceController.php b/controllers/admin/AdminWebserviceController.php index 6aaf9da9..be399642 100644 --- a/controllers/admin/AdminWebserviceController.php +++ b/controllers/admin/AdminWebserviceController.php @@ -29,265 +29,274 @@ */ class AdminWebserviceControllerCore extends AdminController { - /** this will be filled later */ - public $fields_form = array('webservice form'); - protected $toolbar_scroll = false; + /** this will be filled later */ + public $fields_form = array('webservice form'); + protected $toolbar_scroll = false; - public function __construct() - { - $this->bootstrap = true; - $this->table = 'webservice_account'; - $this->className = 'WebserviceKey'; - $this->lang = false; - $this->edit = true; - $this->delete = true; - $this->id_lang_default = Configuration::get('PS_LANG_DEFAULT'); + public function __construct() + { + $this->bootstrap = true; + $this->table = 'webservice_account'; + $this->className = 'WebserviceKey'; + $this->lang = false; + $this->edit = true; + $this->delete = true; + $this->id_lang_default = Configuration::get('PS_LANG_DEFAULT'); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - $this->fields_list = array( - 'key' => array( - 'title' => $this->l('Key'), - 'class' => 'fixed-width-md' - ), - 'description' => array( - 'title' => $this->l('Key description'), - 'align' => 'left', - 'orderby' => false - ), - 'active' => array( - 'title' => $this->l('Enabled'), - 'align' => 'center', - 'active' => 'status', - 'type' => 'bool', - 'orderby' => false, - 'class' => 'fixed-width-xs' - ) - ); + $this->fields_list = array( + 'key' => array( + 'title' => $this->l('Key'), + 'class' => 'fixed-width-md' + ), + 'description' => array( + 'title' => $this->l('Key description'), + 'align' => 'left', + 'orderby' => false + ), + 'active' => array( + 'title' => $this->l('Enabled'), + 'align' => 'center', + 'active' => 'status', + 'type' => 'bool', + 'orderby' => false, + 'class' => 'fixed-width-xs' + ) + ); - $this->fields_options = array( - 'general' => array( - 'title' => $this->l('Configuration'), - 'fields' => array( - 'PS_WEBSERVICE' => array('title' => $this->l('Enable PrestaShop\'s webservice'), - 'desc' => $this->l('Before activating the webservice, you must be sure to: '). - '
    + $this->fields_options = array( + 'general' => array( + 'title' => $this->l('Configuration'), + 'fields' => array( + 'PS_WEBSERVICE' => array('title' => $this->l('Enable PrestaShop\'s webservice'), + 'desc' => $this->l('Before activating the webservice, you must be sure to: '). + '
    1. '.$this->l('Check that URL rewriting is available on this server.').'
    2. '.$this->l('Check that the five methods GET, POST, PUT, DELETE and HEAD are supported by this server.').'
    ', - 'cast' => 'intval', - 'type' => 'bool'), - ), - 'submit' => array('title' => $this->l('Save')) - ), - ); + 'cast' => 'intval', + 'type' => 'bool'), + ), + 'submit' => array('title' => $this->l('Save')) + ), + ); - if (!defined('_PS_HOST_MODE_')) - $this->fields_options['general']['fields']['PS_WEBSERVICE_CGI_HOST'] = array( - 'title' => $this->l('Enable CGI mode for PHP'), - 'desc' => $this->l('Before choosing "Yes", check that PHP is not configured as an Apache module on your server.'), - 'cast' => 'intval', - 'type' => 'bool' - ); + if (!defined('_PS_HOST_MODE_')) { + $this->fields_options['general']['fields']['PS_WEBSERVICE_CGI_HOST'] = array( + 'title' => $this->l('Enable CGI mode for PHP'), + 'desc' => $this->l('Before choosing "Yes", check that PHP is not configured as an Apache module on your server.'), + 'cast' => 'intval', + 'type' => 'bool' + ); + } - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_webservice'] = array( - 'href' => self::$currentIndex.'&addwebservice_account&token='.$this->token, - 'desc' => $this->l('Add new webservice key', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_webservice'] = array( + 'href' => self::$currentIndex.'&addwebservice_account&token='.$this->token, + 'desc' => $this->l('Add new webservice key', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - protected function processUpdateOptions() - { - parent::processUpdateOptions(); - Tools::generateHtaccess(); - } + protected function processUpdateOptions() + { + parent::processUpdateOptions(); + Tools::generateHtaccess(); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Webservice Accounts'), - 'icon' => 'icon-lock' - ), - 'input' => array( - array( - 'type' => 'textbutton', - 'label' => $this->l('Key'), - 'name' => 'key', - 'id' => 'code', - 'required' => true, - 'hint' => $this->l('Webservice account key.'), - 'button' => array( - 'label' => $this->l('Generate!'), - 'attributes' => array( - 'onclick' => 'gencode(32)' - ) - ) - ), - array( - 'type' => 'textarea', - 'label' => $this->l('Key description'), - 'name' => 'description', - 'rows' => 3, - 'cols' => 110, - 'hint' => $this->l('Quick description of the key: who it is for, what permissions it has, etc.'), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Status'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ) - ), - array( - 'type' => 'resources', - 'label' => $this->l('Permissions'), - 'name' => 'resources', - ) - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Webservice Accounts'), + 'icon' => 'icon-lock' + ), + 'input' => array( + array( + 'type' => 'textbutton', + 'label' => $this->l('Key'), + 'name' => 'key', + 'id' => 'code', + 'required' => true, + 'hint' => $this->l('Webservice account key.'), + 'button' => array( + 'label' => $this->l('Generate!'), + 'attributes' => array( + 'onclick' => 'gencode(32)' + ) + ) + ), + array( + 'type' => 'textarea', + 'label' => $this->l('Key description'), + 'name' => 'description', + 'rows' => 3, + 'cols' => 110, + 'hint' => $this->l('Quick description of the key: who it is for, what permissions it has, etc.'), + ), + array( + 'type' => 'switch', + 'label' => $this->l('Status'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ) + ), + array( + 'type' => 'resources', + 'label' => $this->l('Permissions'), + 'name' => 'resources', + ) + ) + ); - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - $this->fields_form['submit'] = array( - 'title' => $this->l('Save'), - ); + $this->fields_form['submit'] = array( + 'title' => $this->l('Save'), + ); - if (!($obj = $this->loadObject(true))) - return; + if (!($obj = $this->loadObject(true))) { + return; + } - $ressources = WebserviceRequest::getResources(); - $permissions = WebserviceKey::getPermissionForAccount($obj->key); + $ressources = WebserviceRequest::getResources(); + $permissions = WebserviceKey::getPermissionForAccount($obj->key); - $this->tpl_form_vars = array( - 'ressources' => $ressources, - 'permissions' => $permissions - ); + $this->tpl_form_vars = array( + 'ressources' => $ressources, + 'permissions' => $permissions + ); - return parent::renderForm(); - } + return parent::renderForm(); + } - public function initContent() - { - if ($this->display != 'add' && $this->display != 'edit') - $this->checkForWarning(); + public function initContent() + { + if ($this->display != 'add' && $this->display != 'edit') { + $this->checkForWarning(); + } - parent::initContent(); - } + parent::initContent(); + } - /** - * Function used to render the options for this controller - */ - public function renderOptions() - { - if ($this->fields_options && is_array($this->fields_options)) - { - $helper = new HelperOptions($this); - $this->setHelperDisplay($helper); - $helper->toolbar_scroll = true; - $helper->toolbar_btn = array('save' => array( - 'href' => '#', - 'desc' => $this->l('Save') - )); - $helper->id = $this->id; - $helper->tpl_vars = $this->tpl_option_vars; - $options = $helper->generateOptions($this->fields_options); + /** + * Function used to render the options for this controller + */ + public function renderOptions() + { + if ($this->fields_options && is_array($this->fields_options)) { + $helper = new HelperOptions($this); + $this->setHelperDisplay($helper); + $helper->toolbar_scroll = true; + $helper->toolbar_btn = array('save' => array( + 'href' => '#', + 'desc' => $this->l('Save') + )); + $helper->id = $this->id; + $helper->tpl_vars = $this->tpl_option_vars; + $options = $helper->generateOptions($this->fields_options); - return $options; - } - } + return $options; + } + } - public function initProcess() - { - parent::initProcess(); - // This is a composite page, we don't want the "options" display mode - if ($this->display == 'options') - $this->display = ''; - } + public function initProcess() + { + parent::initProcess(); + // This is a composite page, we don't want the "options" display mode + if ($this->display == 'options') { + $this->display = ''; + } + } - public function postProcess() - { - if (Tools::getValue('key') && strlen(Tools::getValue('key')) < 32) - $this->errors[] = Tools::displayError('Key length must be 32 character long.'); - if (WebserviceKey::keyExists(Tools::getValue('key')) && !Tools::getValue('id_webservice_account')) - $this->errors[] = Tools::displayError('This key already exists.'); - return parent::postProcess(); - } + public function postProcess() + { + if (Tools::getValue('key') && strlen(Tools::getValue('key')) < 32) { + $this->errors[] = Tools::displayError('Key length must be 32 character long.'); + } + if (WebserviceKey::keyExists(Tools::getValue('key')) && !Tools::getValue('id_webservice_account')) { + $this->errors[] = Tools::displayError('This key already exists.'); + } + return parent::postProcess(); + } - protected function afterAdd($object) - { - Tools::generateHtaccess(); - WebserviceKey::setPermissionForAccount($object->id, Tools::getValue('resources', array())); - } + protected function afterAdd($object) + { + Tools::generateHtaccess(); + WebserviceKey::setPermissionForAccount($object->id, Tools::getValue('resources', array())); + } - protected function afterUpdate($object) - { - Tools::generateHtaccess(); - WebserviceKey::setPermissionForAccount($object->id, Tools::getValue('resources', array())); - } + protected function afterUpdate($object) + { + Tools::generateHtaccess(); + WebserviceKey::setPermissionForAccount($object->id, Tools::getValue('resources', array())); + } - public function checkForWarning() - { - if (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === false) - { - $this->warnings[] = $this->l('To avoid operating problems, please use an Apache server.'); - if (function_exists('apache_get_modules')) - { - $apache_modules = apache_get_modules(); - if (!in_array('mod_auth_basic', $apache_modules)) - $this->warnings[] = $this->l('Please activate the \'mod_auth_basic\' Apache module to allow authentication of PrestaShop\'s webservice.'); - if (!in_array('mod_rewrite', $apache_modules)) - $this->warnings[] = $this->l('Please activate the \'mod_rewrite\' Apache module to allow the PrestaShop webservice.'); - } - else - $this->warnings[] = $this->l('We could not check to see if basic authentication and rewrite extensions have been activated. Please manually check if they\'ve been activated in order to use the PrestaShop webservice.'); - } - if (!extension_loaded('SimpleXML')) - $this->warnings[] = $this->l('Please activate the \'SimpleXML\' PHP extension to allow testing of PrestaShop\'s webservice.'); - if (!configuration::get('PS_SSL_ENABLED')) - $this->warnings[] = $this->l('It is preferable to use SSL (https:) for webservice calls, as it avoids the "man in the middle" type security issues.'); + public function checkForWarning() + { + if (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === false) { + $this->warnings[] = $this->l('To avoid operating problems, please use an Apache server.'); + if (function_exists('apache_get_modules')) { + $apache_modules = apache_get_modules(); + if (!in_array('mod_auth_basic', $apache_modules)) { + $this->warnings[] = $this->l('Please activate the \'mod_auth_basic\' Apache module to allow authentication of PrestaShop\'s webservice.'); + } + if (!in_array('mod_rewrite', $apache_modules)) { + $this->warnings[] = $this->l('Please activate the \'mod_rewrite\' Apache module to allow the PrestaShop webservice.'); + } + } else { + $this->warnings[] = $this->l('We could not check to see if basic authentication and rewrite extensions have been activated. Please manually check if they\'ve been activated in order to use the PrestaShop webservice.'); + } + } + if (!extension_loaded('SimpleXML')) { + $this->warnings[] = $this->l('Please activate the \'SimpleXML\' PHP extension to allow testing of PrestaShop\'s webservice.'); + } + if (!configuration::get('PS_SSL_ENABLED')) { + $this->warnings[] = $this->l('It is preferable to use SSL (https:) for webservice calls, as it avoids the "man in the middle" type security issues.'); + } - foreach ($this->_list as $k => $item) - if ($item['is_module'] && $item['class_name'] && $item['module_name'] && - ($instance = Module::getInstanceByName($item['module_name'])) && - !$instance->useNormalPermissionBehaviour()) - unset($this->_list[$k]); + foreach ($this->_list as $k => $item) { + if ($item['is_module'] && $item['class_name'] && $item['module_name'] && + ($instance = Module::getInstanceByName($item['module_name'])) && + !$instance->useNormalPermissionBehaviour()) { + unset($this->_list[$k]); + } + } - $this->renderList(); - } + $this->renderList(); + } } diff --git a/controllers/admin/AdminZonesController.php b/controllers/admin/AdminZonesController.php index faf8d5f5..eaa57dd0 100644 --- a/controllers/admin/AdminZonesController.php +++ b/controllers/admin/AdminZonesController.php @@ -29,115 +29,115 @@ */ class AdminZonesControllerCore extends AdminController { - public $asso_type = 'shop'; + public $asso_type = 'shop'; - public function __construct() - { - $this->bootstrap = true; - $this->table = 'zone'; - $this->className = 'Zone'; - $this->lang = false; + public function __construct() + { + $this->bootstrap = true; + $this->table = 'zone'; + $this->className = 'Zone'; + $this->lang = false; - $this->fields_list = array( - 'id_zone' => array( - 'title' => $this->l('ID'), - 'align' => 'center', - 'class' => 'fixed-width-xs' - ), - 'name' => array( - 'title' => $this->l('Zone'), - ), - 'active' => array( - 'title' => $this->l('Enabled'), - 'align' => 'center', - 'active' => 'status', - 'type' => 'bool', - 'orderby' => false, - 'class' => 'fixed-width-sm' - ) - ); - $this->bulk_actions = array( - 'delete' => array( - 'text' => $this->l('Delete selected'), - 'confirm' => $this->l('Delete selected items?'), - 'icon' => 'icon-trash' - ) - ); + $this->fields_list = array( + 'id_zone' => array( + 'title' => $this->l('ID'), + 'align' => 'center', + 'class' => 'fixed-width-xs' + ), + 'name' => array( + 'title' => $this->l('Zone'), + ), + 'active' => array( + 'title' => $this->l('Enabled'), + 'align' => 'center', + 'active' => 'status', + 'type' => 'bool', + 'orderby' => false, + 'class' => 'fixed-width-sm' + ) + ); + $this->bulk_actions = array( + 'delete' => array( + 'text' => $this->l('Delete selected'), + 'confirm' => $this->l('Delete selected items?'), + 'icon' => 'icon-trash' + ) + ); - parent::__construct(); - } + parent::__construct(); + } - public function initPageHeaderToolbar() - { - if (empty($this->display)) - $this->page_header_toolbar_btn['new_zone'] = array( - 'href' => self::$currentIndex.'&addzone&token='.$this->token, - 'desc' => $this->l('Add new zone', null, null, false), - 'icon' => 'process-icon-new' - ); + public function initPageHeaderToolbar() + { + if (empty($this->display)) { + $this->page_header_toolbar_btn['new_zone'] = array( + 'href' => self::$currentIndex.'&addzone&token='.$this->token, + 'desc' => $this->l('Add new zone', null, null, false), + 'icon' => 'process-icon-new' + ); + } - parent::initPageHeaderToolbar(); - } + parent::initPageHeaderToolbar(); + } - public function renderList() - { - $this->addRowAction('edit'); - $this->addRowAction('delete'); + public function renderList() + { + $this->addRowAction('edit'); + $this->addRowAction('delete'); - return parent::renderList(); - } + return parent::renderList(); + } - public function renderForm() - { - $this->fields_form = array( - 'legend' => array( - 'title' => $this->l('Zones'), - 'icon' => 'icon-globe' - ), - 'input' => array( - array( - 'type' => 'text', - 'label' => $this->l('Name'), - 'name' => 'name', - 'required' => true, - 'hint' => $this->l('Zone name (e.g. Africa, West Coast, Neighboring Countries).'), - ), - array( - 'type' => 'switch', - 'label' => $this->l('Active'), - 'name' => 'active', - 'required' => false, - 'is_bool' => true, - 'values' => array( - array( - 'id' => 'active_on', - 'value' => 1, - 'label' => $this->l('Enabled') - ), - array( - 'id' => 'active_off', - 'value' => 0, - 'label' => $this->l('Disabled') - ) - ), - 'hint' => $this->l('Allow or disallow shipping to this zone.') - ) - ) - ); + public function renderForm() + { + $this->fields_form = array( + 'legend' => array( + 'title' => $this->l('Zones'), + 'icon' => 'icon-globe' + ), + 'input' => array( + array( + 'type' => 'text', + 'label' => $this->l('Name'), + 'name' => 'name', + 'required' => true, + 'hint' => $this->l('Zone name (e.g. Africa, West Coast, Neighboring Countries).'), + ), + array( + 'type' => 'switch', + 'label' => $this->l('Active'), + 'name' => 'active', + 'required' => false, + 'is_bool' => true, + 'values' => array( + array( + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Enabled') + ), + array( + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('Disabled') + ) + ), + 'hint' => $this->l('Allow or disallow shipping to this zone.') + ) + ) + ); - if (Shop::isFeatureActive()) - { - $this->fields_form['input'][] = array( - 'type' => 'shop', - 'label' => $this->l('Shop association'), - 'name' => 'checkBoxShopAsso', - ); - } + if (Shop::isFeatureActive()) { + $this->fields_form['input'][] = array( + 'type' => 'shop', + 'label' => $this->l('Shop association'), + 'name' => 'checkBoxShopAsso', + ); + } - $this->fields_form['submit'] = array( - 'title' => $this->l('Save'), - ); + $this->fields_form['submit'] = array( + 'title' => $this->l('Save'), + ); - return parent::renderForm(); - } -} \ No newline at end of file + return parent::renderForm(); + } +} diff --git a/controllers/admin/index.php b/controllers/admin/index.php index c642967a..91fa49fb 100644 --- a/controllers/admin/index.php +++ b/controllers/admin/index.php @@ -32,4 +32,4 @@ header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Location: ../../'); -exit; \ No newline at end of file +exit; diff --git a/controllers/front/CategoryCmsController.php b/controllers/front/CategoryCmsController.php index 9704656b..dc4454fc 100644 --- a/controllers/front/CategoryCmsController.php +++ b/controllers/front/CategoryCmsController.php @@ -11,7 +11,7 @@ class CategoryCmsControllerCore extends FrontController public $page; public $order_by; - const PER_PAGE = 4; + const PER_PAGE = 12; public function canonicalRedirection($canonical_url = '') { parent::canonicalRedirection($this->context->link->getCategoryCmsLink($this->categorycms->id)); diff --git a/modules/paypal/Readme.md b/modules/paypal/Readme.md new file mode 100644 index 00000000..e8d45072 --- /dev/null +++ b/modules/paypal/Readme.md @@ -0,0 +1,36 @@ +# PayPal + +## About + +Let customer pay with PayPal Express Checkout or PayPal Integral Evolution. + +## Contributing + +PrestaShop modules are open-source extensions to the PrestaShop e-commerce solution. Everyone is welcome and even encouraged to contribute with their own improvements. + +### Requirements + +Contributors **must** follow the following rules: + +* **Make your Pull Request on the "dev" branch**, NOT the "master" branch. +* Do not update the module's version number. +* Follow [the coding standards][1]. + +### Process in details + +Contributors wishing to edit a module's files should follow the following process: + +1. Create your GitHub account, if you do not have one already. +2. Fork the bankwire project to your GitHub account. +3. Clone your fork to your local machine in the ```/modules``` directory of your PrestaShop installation. +4. Create a branch in your local clone of the module for your changes. +5. Change the files in your branch. Be sure to follow [the coding standards][1]! +6. Push your changed branch to your fork in your GitHub account. +7. Create a pull request for your changes **on the _'dev'_ branch** of the module's project. Be sure to follow [the commit message norm][2] in your pull request. If you need help to make a pull request, read the [Github help page about creating pull requests][3]. +8. Wait for one of the core developers either to include your change in the codebase, or to comment on possible improvements you should make to your code. + +That's it: you have contributed to this open-source project! Congratulations! + +[1]: http://doc.prestashop.com/display/PS16/Coding+Standards +[2]: http://doc.prestashop.com/display/PS16/How+to+write+a+commit+message +[3]: https://help.github.com/articles/using-pull-requests diff --git a/modules/paypal/about.php b/modules/paypal/about.php new file mode 100644 index 00000000..d2001d77 --- /dev/null +++ b/modules/paypal/about.php @@ -0,0 +1,44 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +require_once(dirname(__FILE__).'/../../config/config.inc.php'); +require_once(dirname(__FILE__).'/../../init.php'); + +include_once(dirname(__FILE__).'/paypal.php'); +include_once(dirname(__FILE__).'/backward_compatibility/backward.php'); + +$paypal = new PayPal(); + +$context = Context::getContext(); + +$id_lang = (int)($context->cookie->id_lang ? $context->cookie->id_lang : Configuration::get('PS_LANG_DEFAULT')); +$iso_lang = Tools::strtolower(Language::getIsoById($id_lang)); + +$paypal->context->smarty->assign('iso_code', $iso_lang); + +$display = new BWDisplay(); +$display->setTemplate(_PS_MODULE_DIR_.'paypal/views/templates/front/about.tpl'); +$display->run(); diff --git a/modules/paypal/api/index.php b/modules/paypal/api/index.php new file mode 100644 index 00000000..4a869b3d --- /dev/null +++ b/modules/paypal/api/index.php @@ -0,0 +1,33 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/api/paypal_connect.php b/modules/paypal/api/paypal_connect.php new file mode 100644 index 00000000..1f2acffe --- /dev/null +++ b/modules/paypal/api/paypal_connect.php @@ -0,0 +1,140 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +class PayPalConnect +{ + private $_logs = array(); + private $paypal = null; + + public function __construct() + { + $this->paypal = new PayPal(); + } + + public function makeConnection($host, $script, $body, $simple_mode = false, $http_header = false, $identify = false) + { + $this->_logs[] = $this->paypal->l('Making new connection to').' \''.$host.$script.'\''; + + if (function_exists('curl_exec')) + $return = $this->_connectByCURL($host.$script, $body, $http_header, $identify); + + if (isset($return) && $return) + return $return; + + $tmp = $this->_connectByFSOCK($host, $script, $body); + + if (!$simple_mode || !preg_match('/[A-Z]+=/', $tmp, $result)) + return $tmp; + + return Tools::substr($tmp, strpos($tmp, $result[0])); + } + + public function getLogs() + { + return $this->_logs; + } + + /************************************************************/ + /********************** CONNECT METHODS *********************/ + /************************************************************/ + private function _connectByCURL($url, $body, $http_header = false, $identify = false) + { + $ch = @curl_init(); + + if (!$ch) + $this->_logs[] = $this->paypal->l('Connect failed with CURL method'); + else + { + $this->_logs[] = $this->paypal->l('Connect with CURL method successful'); + $this->_logs[] = ''.$this->paypal->l('Sending this params:').''; + $this->_logs[] = $body; + + @curl_setopt($ch, CURLOPT_URL, 'https://'.$url); + + if ($identify) + @curl_setopt($ch, CURLOPT_USERPWD, Configuration::get('PAYPAL_LOGIN_CLIENT_ID').':'.Configuration::get('PAYPAL_LOGIN_SECRET')); + + @curl_setopt($ch, CURLOPT_POST, true); + if ($body) + @curl_setopt($ch, CURLOPT_POSTFIELDS, $body); + @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + @curl_setopt($ch, CURLOPT_HEADER, false); + @curl_setopt($ch, CURLOPT_TIMEOUT, 30); + @curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + @curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + @curl_setopt($ch, CURLOPT_SSLVERSION, defined('CURL_SSLVERSION_TLSv1') ? CURL_SSLVERSION_TLSv1 : 1); + @curl_setopt($ch, CURLOPT_VERBOSE, false); + if ($http_header) + @curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header); + + $result = @curl_exec($ch); + + if (!$result) + $this->_logs[] = $this->paypal->l('Send with CURL method failed ! Error:').' '.curl_error($ch); + else + $this->_logs[] = $this->paypal->l('Send with CURL method successful'); + + @curl_close($ch); + } + return $result ? $result : false; + } + + private function _connectByFSOCK($host, $script, $body) + { + $fp = @fsockopen('tls://'.$host, 443, $errno, $errstr, 4); + + if (!$fp) + $this->_logs[] = $this->paypal->l('Connect failed with fsockopen method'); + else + { + $header = $this->_makeHeader($host, $script, Tools::strlen($body)); + $this->_logs[] = $this->paypal->l('Sending this params:').' '.$header.$body; + + @fputs($fp, $header.$body); + + $tmp = ''; + while (!feof($fp)) + $tmp .= trim(fgets($fp, 1024)); + + fclose($fp); + + if (!isset($tmp) || $tmp == false) + $this->_logs[] = $this->paypal->l('Send with fsockopen method failed !'); + else + $this->_logs[] = $this->paypal->l('Send with fsockopen method successful'); + } + return isset($tmp) ? $tmp : false; + } + + private function _makeHeader($host, $script, $lenght) + { + return 'POST '.(string)$script.' HTTP/1.1'."\r\n". + 'Host: '.(string)$host."\r\n". + 'Content-Type: application/x-www-form-urlencoded'."\r\n". + 'Content-Length: '.(int)$lenght."\r\n". + 'Connection: close'."\r\n\r\n"; + } +} \ No newline at end of file diff --git a/modules/paypal/api/paypal_lib.php b/modules/paypal/api/paypal_lib.php new file mode 100644 index 00000000..5148cf9e --- /dev/null +++ b/modules/paypal/api/paypal_lib.php @@ -0,0 +1,114 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +include_once(_PS_MODULE_DIR_.'paypal/api/paypal_connect.php'); + +define('PAYPAL_API_VERSION', '106.0'); + +class PaypalLib +{ + + private $enable_log = true; + private $_logs = array(); + protected $paypal = null; + public function __construct() + { + $this->paypal = new PayPal(); + } + + public function getLogs() + { + return $this->_logs; + } + + public function makeCall($host, $script, $method_name, $data, $method_version = '') + { + // Making request string + $method_version = (!empty($method_version)) ? $method_version : PAYPAL_API_VERSION; + + $params = array( + 'METHOD' => $method_name, + 'VERSION' => $method_version, + 'PWD' => Configuration::get('PAYPAL_API_PASSWORD'), + 'USER' => Configuration::get('PAYPAL_API_USER'), + 'SIGNATURE' => Configuration::get('PAYPAL_API_SIGNATURE') + ); + + $request = http_build_query($params, '', '&'); + $request .= '&'.(!is_array($data) ? $data : http_build_query($data, '', '&')); + + // Making connection + $result = $this->makeSimpleCall($host, $script, $request, true); + $response = explode('&', $result); + $logs_request = $this->_logs; + $return = array(); + + if ($this->enable_log === true) + { + $handle = fopen(dirname(__FILE__).'/Results.txt', 'a+'); + fwrite($handle, 'Host : '.print_r($host, true)."\r\n"); + fwrite($handle, 'Request : '.print_r($request, true)."\r\n"); + fwrite($handle, 'Result : '.print_r($result, true)."\r\n"); + fwrite($handle, 'Logs : '.print_r($this->_logs, true."\r\n")); + fclose($handle); + } + + foreach ($response as $value) + { + $tmp = explode('=', $value); + $return[$tmp[0]] = urldecode(!isset($tmp[1]) ? $tmp[0] : $tmp[1]); + } + + if (!Configuration::get('PAYPAL_DEBUG_MODE')) + $this->_logs = array(); + + $to_exclude = array('TOKEN', 'SUCCESSPAGEREDIRECTREQUESTED', 'VERSION', 'BUILD', 'ACK', 'CORRELATIONID'); + $this->_logs[] = ''.$this->paypal->l('PayPal response:').''; + + foreach ($return as $key => $value) + { + if (!Configuration::get('PAYPAL_DEBUG_MODE') && in_array($key, $to_exclude)) + continue; + $this->_logs[] = $key.' -> '.$value; + } + + if (count($this->_logs) <= 2) + $this->_logs = array_merge($this->_logs, $logs_request); + + return $return; + } + + public function makeSimpleCall($host, $script, $request, $simple_mode = false) + { + // Making connection + $paypal_connect = new PayPalConnect(); + + $result = $paypal_connect->makeConnection($host, $script, $request, $simple_mode); + $this->_logs = $paypal_connect->getLogs(); + + return $result; + } +} diff --git a/modules/paypal/backward_compatibility/Context.php b/modules/paypal/backward_compatibility/Context.php new file mode 100644 index 00000000..5f1f3604 --- /dev/null +++ b/modules/paypal/backward_compatibility/Context.php @@ -0,0 +1,347 @@ + +* @copyright 2007-2014 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +if ((bool)Configuration::get('PS_MOBILE_DEVICE')) + require_once(_PS_MODULE_DIR_ . '/mobile_theme/Mobile_Detect.php'); + +// Retro 1.3, 'class_exists' cause problem with autoload... +if (version_compare(_PS_VERSION_, '1.4', '<')) +{ + // Not exist for 1.3 + class Shop extends ObjectModel + { + public $id = 1; + public $id_shop_group = 1; + + public function __construct() + { + } + + + public static function getShops() + { + return array( + array('id_shop' => 1, 'name' => 'Default shop') + ); + } + + public static function getCurrentShop() + { + return 1; + } + } + + class Logger + { + public static function AddLog($message, $severity = 2) + { + $fp = fopen(dirname(__FILE__).'/../logs.txt', 'a+'); + fwrite($fp, '['.(int)$severity.'] '.Tools::safeOutput($message)); + fclose($fp); + } + } + +} + +// Not exist for 1.3 and 1.4 +class Context +{ + /** + * @var Context + */ + protected static $instance; + + /** + * @var Cart + */ + public $cart; + + /** + * @var Customer + */ + public $customer; + + /** + * @var Cookie + */ + public $cookie; + + /** + * @var Link + */ + public $link; + + /** + * @var Country + */ + public $country; + + /** + * @var Employee + */ + public $employee; + + /** + * @var Controller + */ + public $controller; + + /** + * @var Language + */ + public $language; + + /** + * @var Currency + */ + public $currency; + + /** + * @var AdminTab + */ + public $tab; + + /** + * @var Shop + */ + public $shop; + + /** + * @var Smarty + */ + public $smarty; + + /** + * @ var Mobile Detect + */ + public $mobile_detect; + + /** + * @var boolean|string mobile device of the customer + */ + protected $mobile_device; + + public function __construct() + { + global $cookie, $cart, $smarty, $link; + + $this->tab = null; + + $this->cookie = $cookie; + $this->cart = $cart; + $this->smarty = $smarty; + $this->link = $link; + + $this->controller = new ControllerBackwardModule(); + if (is_object($cookie)) + { + $this->currency = new Currency((int)$cookie->id_currency); + $this->language = new Language((int)$cookie->id_lang); + $this->country = new Country((int)$cookie->id_country); + $this->customer = new CustomerBackwardModule((int)$cookie->id_customer); + $this->employee = new Employee((int)$cookie->id_employee); + } + else + { + $this->currency = null; + $this->language = null; + $this->country = null; + $this->customer = null; + $this->employee = null; + } + + $this->shop = new ShopBackwardModule(); + + if ((bool)Configuration::get('PS_MOBILE_DEVICE')) + $this->mobile_detect = new Mobile_Detect(); + } + + public function getMobileDevice() + { + if (is_null($this->mobile_device)) + { + $this->mobile_device = false; + if ($this->checkMobileContext()) + { + switch ((int)Configuration::get('PS_MOBILE_DEVICE')) + { + case 0: // Only for mobile device + if ($this->mobile_detect->isMobile() && !$this->mobile_detect->isTablet()) + $this->mobile_device = true; + break; + case 1: // Only for touchpads + if ($this->mobile_detect->isTablet() && !$this->mobile_detect->isMobile()) + $this->mobile_device = true; + break; + case 2: // For touchpad or mobile devices + if ($this->mobile_detect->isMobile() || $this->mobile_detect->isTablet()) + $this->mobile_device = true; + break; + } + } + } + + return $this->mobile_device; + } + + protected function checkMobileContext() + { + return isset($_SERVER['HTTP_USER_AGENT']) + && (bool)Configuration::get('PS_MOBILE_DEVICE') + && !Context::getContext()->cookie->no_mobile; + } + + /** + * Get a singleton context + * + * @return Context + */ + public static function getContext() + { + if (!isset(self::$instance)) + self::$instance = new Context(); + return self::$instance; + } + + /** + * Clone current context + * + * @return Context + */ + public function cloneContext() + { + return clone($this); + } + + /** + * @return int Shop context type (Shop::CONTEXT_ALL, etc.) + */ + public static function shop() + { + if (!self::$instance->shop->getContextType()) + return ShopBackwardModule::CONTEXT_ALL; + return self::$instance->shop->getContextType(); + } +} + +/** + * Class Shop for Backward compatibility + */ +class ShopBackwardModule extends Shop +{ + const CONTEXT_ALL = 1; + + public $id = 1; + public $id_shop_group = 1; + + + public function getContextType() + { + return ShopBackwardModule::CONTEXT_ALL; + } + + // Simulate shop for 1.3 / 1.4 + public function getID() + { + return 1; + } + + /** + * Get shop theme name + * + * @return string + */ + public function getTheme() + { + return _THEME_NAME_; + } + + public function isFeatureActive() + { + return false; + } +} + +/** + * Class Controller for a Backward compatibility + * Allow to use method declared in 1.5 + */ +class ControllerBackwardModule +{ + /** + * @param $js_uri + * @return void + */ + public function addJS($js_uri) + { + Tools::addJS($js_uri); + } + + /** + * @param $css_uri + * @param string $css_media_type + * @return void + */ + public function addCSS($css_uri, $css_media_type = 'all') + { + Tools::addCSS($css_uri, $css_media_type); + } + + public function addJquery() + { + if (_PS_VERSION_ < '1.5') + $this->addJS(_PS_JS_DIR_.'jquery/jquery-1.4.4.min.js'); + elseif (_PS_VERSION_ >= '1.5') + $this->addJS(_PS_JS_DIR_.'jquery/jquery-1.7.2.min.js'); + } + +} + +/** + * Class Customer for a Backward compatibility + * Allow to use method declared in 1.5 + */ +class CustomerBackwardModule extends Customer +{ + public $logged = false; + /** + * Check customer informations and return customer validity + * + * @since 1.5.0 + * @param boolean $with_guest + * @return boolean customer validity + */ + public function isLogged($with_guest = false) + { + if (!$with_guest && $this->is_guest == 1) + return false; + + /* Customer is valid only if it can be load and if object password is the same as database one */ + if ($this->logged == 1 && $this->id && Validate::isUnsignedId($this->id) && Customer::checkPassword($this->id, $this->passwd)) + return true; + return false; + } +} diff --git a/modules/paypal/backward_compatibility/Display.php b/modules/paypal/backward_compatibility/Display.php new file mode 100644 index 00000000..309e8579 --- /dev/null +++ b/modules/paypal/backward_compatibility/Display.php @@ -0,0 +1,48 @@ + +* @copyright 2007-2014 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +/** + * Class allow to display tpl on the FO + */ +class BWDisplay extends FrontController +{ + // Assign template, on 1.4 create it else assign for 1.5 + public function setTemplate($template) + { + if (_PS_VERSION_ >= '1.5') + parent::setTemplate($template); + else + $this->template = $template; + } + + // Overload displayContent for 1.4 + public function displayContent() + { + parent::displayContent(); + + echo Context::getContext()->smarty->fetch($this->template); + } +} diff --git a/modules/paypal/backward_compatibility/backward.ini b/modules/paypal/backward_compatibility/backward.ini new file mode 100644 index 00000000..6520fb7a --- /dev/null +++ b/modules/paypal/backward_compatibility/backward.ini @@ -0,0 +1 @@ +version = 0.4 \ No newline at end of file diff --git a/modules/paypal/backward_compatibility/backward.php b/modules/paypal/backward_compatibility/backward.php new file mode 100644 index 00000000..21f9eb41 --- /dev/null +++ b/modules/paypal/backward_compatibility/backward.php @@ -0,0 +1,55 @@ + +* @copyright 2007-2014 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +/** + * Backward function compatibility + * Need to be called for each module in 1.4 + */ + +// Get out if the context is already defined +if (!in_array('Context', get_declared_classes())) + require_once(dirname(__FILE__).'/Context.php'); + +// Get out if the Display (BWDisplay to avoid any conflict)) is already defined +if (!in_array('BWDisplay', get_declared_classes())) + require_once(dirname(__FILE__).'/Display.php'); + +// If not under an object we don't have to set the context +if (!isset($this)) + return; +else if (isset($this->context)) +{ + // If we are under an 1.5 version and backoffice, we have to set some backward variable + if (_PS_VERSION_ >= '1.5' && isset($this->context->employee->id) && $this->context->employee->id && isset(AdminController::$currentIndex) && !empty(AdminController::$currentIndex)) + { + global $currentIndex; + $currentIndex = AdminController::$currentIndex; + } + return; +} + +$this->context = Context::getContext(); +$this->smarty = $this->context->smarty; diff --git a/cache/smarty/compile/index.php b/modules/paypal/backward_compatibility/index.php similarity index 98% rename from cache/smarty/compile/index.php rename to modules/paypal/backward_compatibility/index.php index 369a7a3f..b856f563 100644 --- a/cache/smarty/compile/index.php +++ b/modules/paypal/backward_compatibility/index.php @@ -23,13 +23,13 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * International Registered Trademark & Property of PrestaShop SA */ - + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); - + header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); - + header("Location: ../"); -exit; +exit; \ No newline at end of file diff --git a/modules/paypal/br.php b/modules/paypal/br.php new file mode 100644 index 00000000..739424bd --- /dev/null +++ b/modules/paypal/br.php @@ -0,0 +1,133 @@ +paypal_abstract_ad69e733ebae8d264bccaa38d68830e8'] = 'Paypal'; +$_MODULE['<{paypal}prestashop>paypal_abstract_6e7012516038a096b9f6bb71ba2cc5a3'] = 'Aceita pagamentos por cartão de crédito (CB, Visa, MasterCard, Amex, Aurore, Cofinoga, 4 stars) com Paypal.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_69a1a3ad8dd5da6db3c4da838a0cf9c7'] = 'Você tem certeza que você quer deletar seus dados?'; +$_MODULE['<{paypal}prestashop>paypal_abstract_c91f1fb5e06286c3e0a33fc552dffbea'] = 'Você deve definir suas credenciais do PayPal Integral, para que o tema de telefonia móvel funcione corretamente.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_bd6b3cca1e559117a964cdfab6a977cf'] = 'O tema de telefonia móvel somente funciona com o módulo de pagamento Paypal neste momento. Por favor, ative o módulo para permitir pagamentos. '; +$_MODULE['<{paypal}prestashop>paypal_abstract_ea5eb3f904bf42377277255cbd0e2251'] = 'Para funcionar corretamente o módulo requer o módulo de compatibilidade com versões anteriores habilitado'; +$_MODULE['<{paypal}prestashop>paypal_abstract_48878e69ef59b9e9d2d9a8c18e4de520'] = 'Para funcionar corretamente o módulo requer pelo menos o módulo de compatibilidade com versões anteriores v'; +$_MODULE['<{paypal}prestashop>paypal_abstract_c9d8a8d3c76c69e9a5ba6387acb8655a'] = 'Para usar o módulo você precisa instalar o módulo de compatibilidade com versões anteriores.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_d739f6e2d6351c3a587d44190a8253af'] = 'Todos recursos do módulo API do Paypal estão incluídos no novo módulo Paypal. Para que não haja nenhum conflito, por favor, não use e remova o módulo PaypalAPI.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_32af90c3cfef1bacf43b0c3a8f60a4da'] = 'Fundos foram recuperados.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_d238649ac5ec14afc894fad36c0b50fc'] = 'Sem sucesso na recuperação dos fundos solicitados. Por favor, veja mensagem de registro!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_05b998de2c4fb46a7bdd37bd378b81d9'] = 'Validação bem sucedida. Por favor, veja mensagem de registro!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_aeca7e93a1b3d77e38c3cffa131774d5'] = 'Reembolso foi efetuado.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_cba030a50c8a99c7e224adbe1cf58544'] = 'Reembolso solicitado sem sucesso. Por favor, veja mensagem de registro!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_20fda49ece75d93bea97648ab1f1f1cf'] = 'Resultado de cancelamento de produtos:'; +$_MODULE['<{paypal}prestashop>paypal_abstract_90ab0cfd410722553c79e614207a789a'] = 'Alguns campos estão vazios.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_ce0e2b401002ca796d2e8aca7deb8f00'] = 'Campos de credenciais não podem estar vazios'; +$_MODULE['<{paypal}prestashop>paypal_abstract_3f7145179c909f0e87a911a3171986b6'] = 'Campo para e-mail comercial não pode estar vazio'; +$_MODULE['<{paypal}prestashop>paypal_abstract_e5d5d9f40763cfe6549bef705e3529a7'] = 'Mensagem de pagamento não é válida, por favor verifique seu módulo.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_ee9dc1e678d54c517f481583c3fb2db8'] = 'Não é uma moeda válida'; +$_MODULE['<{paypal}prestashop>paypal_abstract_eec39bf42bd135971fb2d838c67d1449'] = 'Resultado de operação de reembolso:'; +$_MODULE['<{paypal}prestashop>paypal_abstract_2ab62d1a578713d0862b56819295630e'] = 'Reembolso do Paypal efetuado com sucesso!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_a64db959966ba8d07c8b5d9493fcc21f'] = 'Erro de transação!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_67962779da962e3d4225055afc05e7bd'] = 'Resultado de operação de captura:'; +$_MODULE['<{paypal}prestashop>paypal_abstract_8778ee03f6592d5fec9a1f2ee851e476'] = 'Terminado o pedido com Paypal'; +$_MODULE['<{paypal}prestashop>paypal_abstract_672d40feac6437e49f771019bc330790'] = 'Status de verificação:'; +$_MODULE['<{paypal}prestashop>paypal_abstract_1828820cc60e36b6f9fdf60cab103ed7'] = 'Você está usando o e-mail padrão que vem com o Paypal, por favor coloque seu próprio e-mail.'; +$_MODULE['<{paypal}prestashop>validation_20dfea1a472e5be3f15f6b5f36ca335c'] = 'Problema conectando com o servidor do Paypal.'; +$_MODULE['<{paypal}prestashop>validation_f7799c2ded739cf3c3e9babffc5f315b'] = 'Conexão usando cURL falhou'; +$_MODULE['<{paypal}prestashop>validation_eca77e208634d52703b07672abbf16ec'] = 'Falha na verificação (usando cURL). Retornou:'; +$_MODULE['<{paypal}prestashop>validation_8358ec19f397d4cdd632688d4f79e535'] = 'Falha na verificação (usando fsockopen). Retornou:'; +$_MODULE['<{paypal}prestashop>validation_76ee8dc73701e846f7bccdf98dae079b'] = 'Sem transporte de comunicação disponível.'; +$_MODULE['<{paypal}prestashop>validation_2818bed1f235637049f4d46fd455dc1c'] = 'A chave Paypal \'mc_gross\' não foi especificada, não pode controlar a quantia paga.'; +$_MODULE['<{paypal}prestashop>validation_be59cbfbf305dc45cd0c3e9841b17ecf'] = 'A chave Paypal \'payment_status\' não foi especificada, não pode controlar a validade de pagamento'; +$_MODULE['<{paypal}prestashop>validation_bd0e34e5be6447844e6f262d51f1a9dc'] = 'Pagamento:'; +$_MODULE['<{paypal}prestashop>validation_e0395c4ce35d0b1e59ca3f2d5e260d23'] = 'A chave Paypal \'custom\' não foi especificada, não pode transmitir ao carrinho'; +$_MODULE['<{paypal}prestashop>validation_765261b630ee773659fae89e9ad762f5'] = 'A chave Paypal \'txn_id\' não foi especificada, transação desconhecida'; +$_MODULE['<{paypal}prestashop>validation_01634612f84d2b7ba56ccdf467e604b7'] = 'A chave Paypal \'mc_currency\' não foi especificada, moeda desconhecida'; +$_MODULE['<{paypal}prestashop>validation_e61f52d02b9f52fbe1fd41ed320e29c3'] = 'Carrinho não foi encontrado'; +$_MODULE['<{paypal}prestashop>validation_0617900b1aff826081d07f5a3e2e7cd0'] = 'Pedido já foi feito'; +$_MODULE['<{paypal}prestashop>validation_f5209b3301a46f3057ffbf34d903e205'] = 'ID de Transação Paypal: '; +$_MODULE['<{paypal}prestashop>validation_7b19e875ff64b09d80ee05dcc84b9975'] = 'A transação do Paypal não pode ser VERIFICADA.'; +$_MODULE['<{paypal}prestashop>paypal_connect_d1f14cc4a2dade80c92421d26422fea0'] = 'Fazendo nova conexão com'; +$_MODULE['<{paypal}prestashop>paypal_connect_94a27811a721ef512ad7bfa06cab34e0'] = 'Falha ao conectar com método CURL'; +$_MODULE['<{paypal}prestashop>paypal_connect_70215486455daee13382c68b1a230b82'] = 'Conexão com método CURL com sucesso'; +$_MODULE['<{paypal}prestashop>paypal_connect_e4c4ad49bced42265b5facc2175cdafd'] = 'Enviando este params:'; +$_MODULE['<{paypal}prestashop>paypal_connect_445583f6641da98fc7ac8fd9d13a564b'] = 'Envio com método CURL falhou! Erro:'; +$_MODULE['<{paypal}prestashop>paypal_connect_ef4fbf36eaa2083442d386990ba063c2'] = 'Envio com método CURL com sucesso'; +$_MODULE['<{paypal}prestashop>paypal_connect_bf059c9751bb1a20b449b7917b1df374'] = 'Conexão com método fsockopen falhou'; +$_MODULE['<{paypal}prestashop>paypal_connect_ea800e3536f81238a4cbc32eb6db4eaf'] = 'Conexão com método fsockopen com sucesso'; +$_MODULE['<{paypal}prestashop>paypal_connect_6e9aa4cb541e09b07602d4ea96080811'] = 'Envio com método fsockopen falhou!'; +$_MODULE['<{paypal}prestashop>paypal_connect_842a183be225d415b2b4375ba1dd1c94'] = 'Envio com método fsockopen com sucesso!'; +$_MODULE['<{paypal}prestashop>paypal_lib_7c2d00d8c94d1ce0f515db8b0481db40'] = 'Resposta do Paypal'; +$_MODULE['<{paypal}prestashop>paypal_express_checkout_ee9dc1e678d54c517f481583c3fb2db8'] = 'Não é uma moeda válida'; +$_MODULE['<{paypal}prestashop>paypal_express_checkout_484f5a79672cebe198ebdde45a1d672f'] = 'Papel de presente'; +$_MODULE['<{paypal}prestashop>submit_1e97d97a923eaddd810e056c828e99ea'] = 'Erro no pagamento'; +$_MODULE['<{paypal}prestashop>submit_7ef8c0c75056a5d1f988e352efcd0f09'] = 'Este produto não está mais em estoque com estes atributos mas está disponível com outros'; +$_MODULE['<{paypal}prestashop>submit_d141a42a5e72c871a3116414bb5c64c1'] = 'Não é possível criar novo carrinho'; +$_MODULE['<{paypal}prestashop>submit_5b5adcef5e3f2e5e1b6f60eb3e7e41ed'] = 'Ocorreu um erro:'; +$_MODULE['<{paypal}prestashop>submit_58f53d0306ffc9cc9820eab866e90efe'] = 'Erro durante a preparação do pagamento express checkout'; +$_MODULE['<{paypal}prestashop>submit_51da74120dd5e11817ef21e27d2599bc'] = 'Não foi possível criar cliente'; +$_MODULE['<{paypal}prestashop>submit_bcf08b34ab427cb871635151c6976eb0'] = 'Não foi possível criar endereço'; +$_MODULE['<{paypal}prestashop>submit_ca5cecfc8fd8e585ba1e684757168158'] = 'Não foi possível atualizar o carrinho existente'; +$_MODULE['<{paypal}prestashop>submit_36ec50c0e914dd2fb48a1b27540512ce'] = 'Pagamento aceito.'; +$_MODULE['<{paypal}prestashop>submit_28060413b9f346d871b633018d03c7b0'] = 'Preço pago no Paypal não é o mesmo que no PrestaShop.'; +$_MODULE['<{paypal}prestashop>submit_98825385aadb1d0dd0fd133ef8acd23d'] = 'Não é possível criar pedido'; +$_MODULE['<{paypal}prestashop>submit_085b78e060c3ef4cc37bd25abd06ff66'] = 'Carrinho mudou desde o último checkout express, por favor faça um novo pagamento no checkout Paypal'; +$_MODULE['<{paypal}prestashop>notifier_28060413b9f346d871b633018d03c7b0'] = 'Preço pago no Paypal não é o msmo que no PrestaShop.'; +$_MODULE['<{paypal}prestashop>notifier_572f9af7615560af2cba038cc1948287'] = 'Carrinho mudou, por favor entre dados novamente.'; +$_MODULE['<{paypal}prestashop>notifier_36ec50c0e914dd2fb48a1b27540512ce'] = 'Pagamento aceito.'; +$_MODULE['<{paypal}prestashop>back_office_2d801c24938b12e4ca9a2cf9b980c759'] = 'Erro!'; +$_MODULE['<{paypal}prestashop>capture_81e826adb70e2e6b189c2eef739d52d4'] = 'Captura Paypal'; +$_MODULE['<{paypal}prestashop>capture_e8fdd4382b75b42bfbd96eb7b032cf47'] = 'Informação:'; +$_MODULE['<{paypal}prestashop>capture_ce64b2ea82cf4fa861a6512e2c32b84b'] = 'Fundos prontos para serem capturados antes do envio'; +$_MODULE['<{paypal}prestashop>capture_99e64593868df2b7b32231c1ae5ddc04'] = 'Obter o dinheiro'; +$_MODULE['<{paypal}prestashop>refund_8ba079f305b81b172792bc0469b6a690'] = 'Reembolso Paypal'; +$_MODULE['<{paypal}prestashop>refund_e8fdd4382b75b42bfbd96eb7b032cf47'] = 'Informação:'; +$_MODULE['<{paypal}prestashop>refund_016e1f278eccd700eaf33f74a501d050'] = 'Pagamento aceito'; +$_MODULE['<{paypal}prestashop>refund_a8b1cc445942a2e1a7d7cca641c86d67'] = 'Quando você reembolsa um produto, um reembolso parcial é feito a menos que você selecione \"Generate a voucher\".'; +$_MODULE['<{paypal}prestashop>refund_c2a5e2e23d8ec9cad779d657b7d33fc1'] = 'Reembolso total da transação'; +$_MODULE['<{paypal}prestashop>refund_729a51874fe901b092899e9e8b31c97a'] = 'Você tem certeza?'; +$_MODULE['<{paypal}prestashop>validation_b630aa9b5e25da971949cae62dd109aa'] = 'Validação Paypal'; +$_MODULE['<{paypal}prestashop>validation_e8fdd4382b75b42bfbd96eb7b032cf47'] = 'Informação:'; +$_MODULE['<{paypal}prestashop>validation_9119a92adbbf6c67bfb8a3aee0bdb720'] = 'Captura Pendente - Sem meio de envio'; +$_MODULE['<{paypal}prestashop>validation_c14eb95a724174f336b8ffdd98ef2f35'] = 'Pagamento Pendente - Sem meio de envio'; +$_MODULE['<{paypal}prestashop>validation_5b18ff32c2aaaf4b79bdead10b10fe29'] = 'Obtenha o status do pagamento'; +$_MODULE['<{paypal}prestashop>about_e816e21c1c8e0eba0620fa3df6bd6795'] = 'O que é Paypal?'; +$_MODULE['<{paypal}prestashop>about_16ea57badae98f402bb8f2b2f49d4e77'] = 'PayPal, uma confiável empresa líder em pagamentos on-line, permite que compradores e empresas enviem e recebam dinheiro online. PayPal tem mais de 100 milhões de contas de membros em 190 países e regiões. Ele é aceito por comerciantes em toda parte, dentro e fora do eBay.'; +$_MODULE['<{paypal}prestashop>about_d20adade7baa1b60b713521031ea676c'] = 'É seguro para usar?'; +$_MODULE['<{paypal}prestashop>about_64f7b897c6d56fc62428f692ee5737cd'] = 'PayPal ajuda a proteger suas informações de cartão de crédito com líderes de mercado em segurança e sistemas de prevenção de fraude. Quando você usa o PayPal, suas informações financeiras nunca são compartilhadas com o comerciante.'; +$_MODULE['<{paypal}prestashop>about_5ef30813484389e4200640c2f006004d'] = 'Porque usar Paypal?'; +$_MODULE['<{paypal}prestashop>about_86550d4ea832930db4366f03b90bdfb8'] = 'Faça compras ou envie dinheiro com o Paypal - é grátis!'; +$_MODULE['<{paypal}prestashop>about_7dc9e529337e5a55a12bf362b8e68cac'] = 'Compre e pague de forma conveniente salvando suas informações com o Paypal'; +$_MODULE['<{paypal}prestashop>about_32098ae6a7ecd96805df9e48fb6cc739'] = 'O Paypal é aceito por milhões de empresas em todo o mundo e é o método preferido no eBay'; +$_MODULE['<{paypal}prestashop>about_7934d7d1280bfbb8778743e39292af30'] = 'Comece a usar o Paypal hoje!'; +$_MODULE['<{paypal}prestashop>column_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Pague com Paypal'; +$_MODULE['<{paypal}prestashop>confirmation_2e2117b7c81aa9ea6931641ea2c6499f'] = 'Seu pedido no'; +$_MODULE['<{paypal}prestashop>confirmation_75fbf512d744977d62599cc3f0ae2bb4'] = 'está completo.'; +$_MODULE['<{paypal}prestashop>confirmation_15b0f8e55c6bdfc3d5fd0b6b3b6cb3ee'] = 'Você escolheu o método Paypal.'; +$_MODULE['<{paypal}prestashop>confirmation_e6dc7945b557a1cd949bea92dd58963e'] = 'Seu pedido será enviado em breve.'; +$_MODULE['<{paypal}prestashop>confirmation_0db71da7150c27142eef9d22b843b4a9'] = 'Para qualquer pergunta ou mais informações, por favor contate nosso '; +$_MODULE['<{paypal}prestashop>confirmation_64430ad2835be8ad60c59e7d44e4b0b1'] = 'serviço de atendimento ao cliente'; +$_MODULE['<{paypal}prestashop>error_a40cab5994f36d4c48103a22ca082e8f'] = 'Seu carrinho de compra'; +$_MODULE['<{paypal}prestashop>error_ad69e733ebae8d264bccaa38d68830e8'] = 'Paypal'; +$_MODULE['<{paypal}prestashop>error_425551a2289ed60c9260933d1c45ef00'] = 'Por favor consulte os registros:'; +$_MODULE['<{paypal}prestashop>error_0557fa923dcee4d0f86b1409f5c2167f'] = 'Voltar'; +$_MODULE['<{paypal}prestashop>order-confirmation_fb077ecba55e5552916bde26d8b9e794'] = 'Confirmação do Pedido'; +$_MODULE['<{paypal}prestashop>order-confirmation_d5860edcd3078f86ee963c27654bc6cf'] = 'Total da transação (impostos incluídos) :'; +$_MODULE['<{paypal}prestashop>order-confirmation_a378cd7a0839cbd4ec3e45bbdeeb69be'] = 'A ID do seu pedido é:'; +$_MODULE['<{paypal}prestashop>order-confirmation_6e860dc1cf94ca08b3fd99993aa2dc68'] = 'A ID da sua transação Paypal é:'; +$_MODULE['<{paypal}prestashop>order-confirmation_4082ea29b4f196c4f60533500139725a'] = 'Acompanhar meu pedido'; +$_MODULE['<{paypal}prestashop>order-confirmation_9390390581f54c65d6acfc8da4e17362'] = 'Voltar para pedidos'; +$_MODULE['<{paypal}prestashop>order-summary_a40cab5994f36d4c48103a22ca082e8f'] = 'Seu carrinho de compra'; +$_MODULE['<{paypal}prestashop>order-summary_ad69e733ebae8d264bccaa38d68830e8'] = 'Paypal'; +$_MODULE['<{paypal}prestashop>order-summary_f1d3b424cd68795ecaa552883759aceb'] = 'Resumo do pedido'; +$_MODULE['<{paypal}prestashop>order-summary_dd23adc5fb6bda9c384397b31e57fc53'] = 'Pagamento Paypal'; +$_MODULE['<{paypal}prestashop>order-summary_62d74398cb6ebaa69ab7339052ca5c92'] = 'Você escolheu pagar com Paypal.'; +$_MODULE['<{paypal}prestashop>order-summary_c884ed19483d45970c5bf23a681e2dd2'] = 'Aqui está um curto resumo do seu pedido:'; +$_MODULE['<{paypal}prestashop>order-summary_e2867a925cba382f1436d1834bb52a1c'] = 'O valor total do seu pedido é'; +$_MODULE['<{paypal}prestashop>order-summary_1f87346a16cf80c372065de3c54c86d9'] = '(imposto incluído)'; +$_MODULE['<{paypal}prestashop>order-summary_8ed356c32b198c9cb2abab7c3d262b93'] = 'Nós aceitamos as seguintes moedas para serem enviadas pelo Paypal:'; +$_MODULE['<{paypal}prestashop>order-summary_0881a11f7af33bc1b43e437391129d66'] = 'Por favor confirme seu pedido clicando \'Eu confirmo meu pedido\''; +$_MODULE['<{paypal}prestashop>order-summary_46b9e3665f187c739c55983f757ccda0'] = 'Eu confirmo meu pedido'; +$_MODULE['<{paypal}prestashop>express_checkout_form_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Pague com o Paypal'; +$_MODULE['<{paypal}prestashop>paypal_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Pague com o Paypal'; +$_MODULE['<{paypal}prestashop>iframe_ecab922bc1f9b5726e2a6deb4acaec4e'] = 'Volte para o website do comerciante'; +$_MODULE['<{paypal}prestashop>payment_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Pague com o Paypal'; +$_MODULE['<{paypal}prestashop>payment_a3f2caee6ef8e68fbd26e42d83f2bf65'] = 'Pague com sua conta Paypal, cartão de crédito (CB, Visa, Mastercard...), ou cartão de crédito privado'; +$_MODULE['<{paypal}prestashop>payment_b08008a2de4331ba13f006c9bcf37b62'] = 'Pague com sua conta Paypal'; diff --git a/modules/paypal/classes/PaypalCapture.php b/modules/paypal/classes/PaypalCapture.php new file mode 100644 index 00000000..120a7bab --- /dev/null +++ b/modules/paypal/classes/PaypalCapture.php @@ -0,0 +1,181 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +if (!defined('_PS_VERSION_')) + exit; + +class PaypalCapture extends ObjectModel +{ + + public $id_order; + public $capture_amount; + public $result; + public $date_add; + public $date_upd; + public $id_paypal_capture; + + /** + * @see ObjectModel::$definition + */ + public static $definition; + + // for Prestashop 1.4 + protected $tables; + protected $fieldsRequired; + protected $fieldsSize; + protected $fieldsValidate; + protected $table = 'paypal_capture'; + protected $identifier = 'id_paypal_capture'; + + + + + public function __construct($id = null, $id_lang = null, $id_shop = null) + { + if (version_compare(_PS_VERSION_, '1.5', '>')) + self::$definition = array( + 'table' => 'paypal_capture', + 'primary' => 'id_paypal_capture', + 'fields' => array( + 'id_order' => array('type' => 1, 'validate' => 'isUnsignedId'), + 'result' => array('type' => 3, 'validate' => 'isString'), + 'capture_amount' => array('type' => 4, 'validate' => 'isFloat'), + 'date_add' => array('type' => 5, 'validate' => 'isDate'), + 'date_upd' => array('type' => 5, 'validate' => 'isDate'), + ), + ); + else + { + $tables = array ('paypal_capture'); + $fieldsRequired = array('id_order', 'result', 'capture_amount', 'date_add', 'date_upd'); + $fieldsValidate = array(); + } + + $this->date_add = date('Y-m-d H:i:s'); + $this->date_upd = date('Y-m-d H:i:s'); + + return parent::__construct($id, $id_lang, $id_shop); + } + + public function getFields() + { + $fields = parent::getFields(); + + if (version_compare(_PS_VERSION_, '1.5', '<')) + { + $fields['result'] = pSQL($this->result); + $fields['capture_amount'] = pSQL($this->capture_amount); + $fields['date_add'] = pSQL($this->date_add); + $fields['date_upd'] = pSQL($this->date_upd); + $fields['id_order'] = pSQL($this->id_order); + } + + return $fields; + } + + public static function getTotalAmountCapturedByIdOrder($id_order) + { + //Tester la version de prestashop + + if (version_compare(_PS_VERSION_, '1.5', '<')) + { + $query = 'SELECT SUM(capture_amount) AS tt FROM '._DB_PREFIX_.'paypal_capture WHERE id_order ='.(int)$id_order.' AND result="Completed" '; + $result = Db::getInstance()->getRow($query); + + return Tools::ps_round($result['tt'], 2); + } + else + { + $query = new DbQuery(); + $query->select('SUM(capture_amount)'); + $query->from(self::$definition['table']); + $query->where('id_order = '.(int)$id_order); + $query->where('result = "Completed"'); + return Tools::ps_round(DB::getInstance()->getValue($query), 2); + } + + } + + public function getRestToPaid(Order $order) + { + $cart = new Cart($order->id_cart); + $totalPaid = Tools::ps_round($cart->getOrderTotal(), 2); + return Tools::ps_round($totalPaid, 2) - Tools::ps_round(self::getTotalAmountCapturedByIdOrder($order->id), 2); + } + + public function getRestToCapture($id_order) + { + $cart = Cart::getCartByOrderId($id_order); + $total = Tools::ps_round($cart->getOrderTotal(), 2) - Tools::ps_round(self::getTotalAmountCapturedByIdOrder($id_order), 2); + + if ($total > Tools::ps_round(0, 2)) + return true; + else + return false; + } + + public function getListCaptured() + { + if (version_compare(_PS_VERSION_, '1.5', '<')) + $query = 'SELECT * FROM '._DB_PREFIX_.'paypal_capture WHERE id_order ='.$this->id_order.' ORDER BY date_add DESC ;'; + else + { + $query = new DbQuery(); + $query->from(self::$definition['table']); + $query->where('id_order = '.$this->id_order); + $query->orderBy('date_add DESC'); + } + + $result = DB::getInstance()->executeS($query); + + if (version_compare(_PS_VERSION_, '1.5', '<')) + { + foreach ($result as &$foo) + $foo['date'] = Tools::displayDate($foo['date_add'], Configuration::get('PS_LANG_DEFAULT'), true); + } + return $result; + } + + public static function parsePrice($price) + { + $regexp = "/^([0-9\s]{0,10})((\.|,)[0-9]{0,2})?$/isD"; + + if (preg_match($regexp, $price)) + { + $array_regexp = array("#,#isD", "# #isD"); + $array_replace = array(".", ""); + $price = preg_replace($array_regexp, $array_replace, $price); + + return Tools::ps_round($price, 2); + } + else + return false; + } + + +} + +?> \ No newline at end of file diff --git a/modules/paypal/classes/index.php b/modules/paypal/classes/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/classes/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/config.xml b/modules/paypal/config.xml new file mode 100644 index 00000000..36b32251 --- /dev/null +++ b/modules/paypal/config.xml @@ -0,0 +1,13 @@ + + + paypal + + + + + + Are you sure you want to delete your details? + 1 + 1 + + diff --git a/modules/paypal/config_fr.xml b/modules/paypal/config_fr.xml new file mode 100644 index 00000000..af5c904d --- /dev/null +++ b/modules/paypal/config_fr.xml @@ -0,0 +1,13 @@ + + + paypal + + + + + + + 1 + 1 + + \ No newline at end of file diff --git a/modules/paypal/controllers/front/confirm.php b/modules/paypal/controllers/front/confirm.php new file mode 100644 index 00000000..ceeb18cf --- /dev/null +++ b/modules/paypal/controllers/front/confirm.php @@ -0,0 +1,59 @@ + + * @copyright 2007-2015 PrestaShop SA + * @version Release: $Revision: 13573 $ + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +/** + * @since 1.5.0 + */ + +class PayPalConfirmModuleFrontController extends ModuleFrontController +{ + public $display_column_left = false; + + public function initContent() + { + if (!$this->context->customer->isLogged(true) || empty($this->context->cart)) + Tools::redirect('index.php'); + + parent::initContent(); + + $this->paypal = new PayPal(); + $this->context = Context::getContext(); + $this->id_module = (int)Tools::getValue('id_module'); + + $currency = new Currency((int)$this->context->cart->id_currency); + + $this->context->smarty->assign(array( + 'form_action' => PayPal::getShopDomainSsl(true, true)._MODULE_DIR_.$this->paypal->name.'/express_checkout/payment.php', + 'total' => Tools::displayPrice($this->context->cart->getOrderTotal(true), $currency), + 'logos' => $this->paypal->paypal_logos->getLogos(), + 'use_mobile' => (bool)$this->paypal->useMobile(), + 'address' => new Address($this->context->cart->id_address_delivery) + )); + + $this->setTemplate('order-summary.tpl'); + } +} diff --git a/modules/paypal/controllers/front/expresscheckoutsubmit.php b/modules/paypal/controllers/front/expresscheckoutsubmit.php new file mode 100644 index 00000000..ab111c31 --- /dev/null +++ b/modules/paypal/controllers/front/expresscheckoutsubmit.php @@ -0,0 +1,33 @@ + + * @copyright 2007-2015 PrestaShop SA + * @version Release: $Revision: 13573 $ + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + + /** + * @since 1.5.0 + */ + +include_once(dirname(__FILE__).'/payment.php'); +include_once(dirname(__FILE__).'/../../express_checkout/payment.php'); diff --git a/modules/paypal/controllers/front/index.php b/modules/paypal/controllers/front/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/controllers/front/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/controllers/front/integralevolutionsubmit.php b/modules/paypal/controllers/front/integralevolutionsubmit.php new file mode 100644 index 00000000..eb06e219 --- /dev/null +++ b/modules/paypal/controllers/front/integralevolutionsubmit.php @@ -0,0 +1,33 @@ + + * @copyright 2007-2015 PrestaShop SA + * @version Release: $Revision: 13573 $ + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + + /** + * @since 1.5.0 + */ + +include_once(dirname(__FILE__).'/submit.php'); +include_once(dirname(__FILE__).'/../../integral_evolution/submit.php'); \ No newline at end of file diff --git a/modules/paypal/controllers/front/submit.php b/modules/paypal/controllers/front/submit.php new file mode 100644 index 00000000..79ee802c --- /dev/null +++ b/modules/paypal/controllers/front/submit.php @@ -0,0 +1,151 @@ + + * @copyright 2007-2015 PrestaShop SA + * @version Release: $Revision: 13573 $ + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +/** + * @since 1.5.0 + */ + +class PayPalSubmitModuleFrontController extends ModuleFrontController +{ + public $display_column_left = false; + public $ssl = true; + + public function initContent() + { + parent::initContent(); + + $this->paypal = new PayPal(); + $this->context = Context::getContext(); + + $this->id_module = (int)Tools::getValue('id_module'); + $this->id_order = (int)Tools::getValue('id_order'); + $order = new Order($this->id_order); + $order_state = new OrderState($order->current_state); + $paypal_order = PayPalOrder::getOrderById($this->id_order); + + if ($order_state->template[$this->context->language->id] == 'payment_error') + { + $this->context->smarty->assign( + array( + 'message' => $order_state->name[$this->context->language->id], + 'logs' => array( + $this->paypal->l('An error occurred while processing payment.') + ), + 'order' => $paypal_order, + 'price' => Tools::displayPrice($paypal_order['total_paid'], $this->context->currency), + ) + ); + + return $this->setTemplate('error.tpl'); + } + + $order_currency = new Currency((int)$order->id_currency); + $display_currency = new Currency((int)$this->context->currency->id); + + $price = Tools::convertPriceFull($paypal_order['total_paid'], $order_currency, $display_currency); + + $this->context->smarty->assign( + array( + 'is_guest' => (($this->context->customer->is_guest) || $this->context->customer->id == false), + 'order' => $paypal_order, + 'price' => Tools::displayPrice($price, $this->context->currency->id), + 'HOOK_ORDER_CONFIRMATION' => $this->displayOrderConfirmation(), + 'HOOK_PAYMENT_RETURN' => $this->displayPaymentReturn() + ) + ); + if(version_compare(_PS_VERSION_, '1.5', '>')) + { + $this->context->smarty->assign(array( + 'reference_order' => Order::getUniqReferenceOf($paypal_order['id_order']) + )); + } + + if (($this->context->customer->is_guest) || $this->context->customer->id == false) + { + $this->context->smarty->assign( + array( + 'id_order' => (int)$this->id_order, + 'id_order_formatted' => sprintf('#%06d', (int)$this->id_order), + 'order_reference' => $order->reference, + ) + ); + + /* If guest we clear the cookie for security reason */ + $this->context->customer->mylogout(); + } + if ($this->context->getMobileDevice() == true) + $this->setTemplate('order-confirmation-mobile.tpl'); + else + $this->setTemplate('order-confirmation.tpl'); + } + + private function displayHook() + { + if (Validate::isUnsignedId($this->id_order) && Validate::isUnsignedId($this->id_module)) + { + $order = new Order((int)$this->id_order); + $currency = new Currency((int)$order->id_currency); + + if (Validate::isLoadedObject($order)) + { + $params = array(); + $params['objOrder'] = $order; + $params['currencyObj'] = $currency; + $params['currency'] = $currency->sign; + $params['total_to_pay'] = $order->getOrdersTotalPaid(); + + return $params; + } + } + + return false; + } + + /** + * Execute the hook displayPaymentReturn + */ + public function displayPaymentReturn() + { + $params = $this->displayHook(); + + if ($params && is_array($params)) + return Hook::exec('displayPaymentReturn', $params, (int)$this->id_module); + return false; + } + + /** + * Execute the hook displayOrderConfirmation + */ + public function displayOrderConfirmation() + { + $params = $this->displayHook(); + + if ($params && is_array($params)) + return Hook::exec('displayOrderConfirmation', $params); + return false; + } +} diff --git a/modules/paypal/controllers/index.php b/modules/paypal/controllers/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/controllers/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/de.php b/modules/paypal/de.php new file mode 100644 index 00000000..a6007ca9 --- /dev/null +++ b/modules/paypal/de.php @@ -0,0 +1,197 @@ +ipn_8a34d4a5b0c3928059f6f92ead9e8aa6'] = 'Die Preise bei PayPal und PrestaShop sind nicht identisch.'; +$_MODULE['<{paypal}prestashop>ipn_572f9af7615560af2cba038cc1948287'] = 'Warenkorb geändert, versuchen Sie es erneut.'; +$_MODULE['<{paypal}prestashop>ipn_ada2b5d5bbf3065de283d61526141780'] = 'Offene Zahlung einziehen'; +$_MODULE['<{paypal}prestashop>ipn_36ec50c0e914dd2fb48a1b27540512ce'] = 'Zahlung akzeptiert'; +$_MODULE['<{paypal}prestashop>ipn_c8a31175ee6991be6a0d7a6d32ca4268'] = 'Offene Zahlung bestätigen'; +$_MODULE['<{paypal}prestashop>paypal_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>paypal_6e7012516038a096b9f6bb71ba2cc5a3'] = 'Akzeptiert Kreditkartenzahlungen (CB, Visa, MasterCard, Amex, Aurore, Cofinoga, 4 stars) mit PayPal'; +$_MODULE['<{paypal}prestashop>paypal_69a1a3ad8dd5da6db3c4da838a0cf9c7'] = 'Möchten Sie Ihre Daten wirklich löschen?'; +$_MODULE['<{paypal}prestashop>paypal_8b57f95f1e9cf09dc028fa5a671781ff'] = 'Alle Funktionen des PayPal-API-Moduls werden vom neuen PayPal-Modul unterstützt. Entfernen Sie das PayPal-API-Modul, um Konflikte zu vermeiden.'; +$_MODULE['<{paypal}prestashop>paypal_c91f1fb5e06286c3e0a33fc552dffbea'] = 'Sie müssen Ihre PayPal Integral-Zugangsdaten einrichten, damit die mobile Ansicht richtig funktioniert.'; +$_MODULE['<{paypal}prestashop>paypal_bd6b3cca1e559117a964cdfab6a977cf'] = 'Derzeit funktioniert die mobile Ansicht nur mit dem PayPal-Zahlungsmodul. Aktivieren Sie das Modul, damit Sie Zahlungen empfangen können.'; +$_MODULE['<{paypal}prestashop>paypal_c9d8a8d3c76c69e9a5ba6387acb8655a'] = 'Damit Sie das Modul nutzen können, müssen Sie das Modul "Abwärtskompatibilität" installieren.'; +$_MODULE['<{paypal}prestashop>paypal_ea5eb3f904bf42377277255cbd0e2251'] = 'Damit das Modul ordnungsgemäß funktioniert, muss das Modul "Abwärtskompatibilität" aktiviert sein.'; +$_MODULE['<{paypal}prestashop>paypal_48878e69ef59b9e9d2d9a8c18e4de520'] = 'Damit das Modul ordnungsgemäß funktioniert, muss mindestens das Modul V für die Abwärtskompatibilität installiert sein.'; +$_MODULE['<{paypal}prestashop>paypal_9b88c95a15e018c3f8038a7d0160145c'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>paypal_20fda49ece75d93bea97648ab1f1f1cf'] = 'Produktauswahl verwerfen:'; +$_MODULE['<{paypal}prestashop>paypal_90ab0cfd410722553c79e614207a789a'] = 'Einige Felder sind leer.'; +$_MODULE['<{paypal}prestashop>paypal_ce0e2b401002ca796d2e8aca7deb8f00'] = 'Die Felder für Zugangsdaten dürfen nicht leer sein.'; +$_MODULE['<{paypal}prestashop>paypal_3f7145179c909f0e87a911a3171986b6'] = 'Das Feld "Geschäftliche E-Mail-Adresse" darf nicht leer sein.'; +$_MODULE['<{paypal}prestashop>paypal_e5d5d9f40763cfe6549bef705e3529a7'] = 'Zahlungstext ungültig, überprüfen Sie Ihr Modul.'; +$_MODULE['<{paypal}prestashop>paypal_ee9dc1e678d54c517f481583c3fb2db8'] = 'Keine gültige Währung'; +$_MODULE['<{paypal}prestashop>paypal_eec39bf42bd135971fb2d838c67d1449'] = 'Ergebnis des Vorgangs "Rückzahlung":'; +$_MODULE['<{paypal}prestashop>paypal_2ab62d1a578713d0862b56819295630e'] = 'PayPal-Rückzahlung war erfolgreich.'; +$_MODULE['<{paypal}prestashop>paypal_a64db959966ba8d07c8b5d9493fcc21f'] = 'Transaktionsfehler'; +$_MODULE['<{paypal}prestashop>paypal_67962779da962e3d4225055afc05e7bd'] = 'Ergebnis des Vorgangs "Einziehen":'; +$_MODULE['<{paypal}prestashop>paypal_8778ee03f6592d5fec9a1f2ee851e476'] = 'Bestellung mit PayPal abgeschlossen'; +$_MODULE['<{paypal}prestashop>paypal_672d40feac6437e49f771019bc330790'] = 'Status der Verifizierung:'; +$_MODULE['<{paypal}prestashop>paypal_1828820cc60e36b6f9fdf60cab103ed7'] = 'Sie verwenden die Standard-E-Mail-Adresse von PayPal. Geben Sie Ihre eigene E-Mail-Adresse ein.'; +$_MODULE['<{paypal}prestashop>paypal_11582f323e3cac72252135e07b353c1c'] = 'Aktivieren Sie cURL (PHP-Erweiterung), damit Sie Ihr Modul verwenden können.'; +$_MODULE['<{paypal}prestashop>paypal_connect_d1f14cc4a2dade80c92421d26422fea0'] = 'Neue Verbindung herstellen zu'; +$_MODULE['<{paypal}prestashop>paypal_connect_94a27811a721ef512ad7bfa06cab34e0'] = 'Verbindung fehlgeschlagen mit CURL Methode'; +$_MODULE['<{paypal}prestashop>paypal_connect_70215486455daee13382c68b1a230b82'] = 'Verbindung erfolgreich mit CURL Methode'; +$_MODULE['<{paypal}prestashop>paypal_connect_e4c4ad49bced42265b5facc2175cdafd'] = 'Senden dieser Parameter:'; +$_MODULE['<{paypal}prestashop>paypal_connect_445583f6641da98fc7ac8fd9d13a564b'] = 'Sendung mit CURL Methode fehlgeschlagen! Fehler:'; +$_MODULE['<{paypal}prestashop>paypal_connect_ef4fbf36eaa2083442d386990ba063c2'] = 'Sendung mit CURL Methode erfolgreich'; +$_MODULE['<{paypal}prestashop>paypal_connect_bf059c9751bb1a20b449b7917b1df374'] = 'Verbindung fehlgeschlagen mit fsockopen Methode'; +$_MODULE['<{paypal}prestashop>paypal_connect_6e9aa4cb541e09b07602d4ea96080811'] = 'Sendung mit fsockopen Methode fehlgeschlagen!'; +$_MODULE['<{paypal}prestashop>paypal_connect_842a183be225d415b2b4375ba1dd1c94'] = 'Sendung mit fsockopen Methode erfolgreich'; +$_MODULE['<{paypal}prestashop>paypal_lib_7c2d00d8c94d1ce0f515db8b0481db40'] = 'PayPal Antwort:'; +$_MODULE['<{paypal}prestashop>submit_67a3fcdb7708219b9d5d6269ad8c4a86'] = 'Beim Verarbeiten Ihrer Zahlung ist ein Fehler aufgetreten.'; +$_MODULE['<{paypal}prestashop>payment_d141a42a5e72c871a3116414bb5c64c1'] = 'Neuer Warenkorb kann nicht erstellt werden.'; +$_MODULE['<{paypal}prestashop>payment_5b5adcef5e3f2e5e1b6f60eb3e7e41ed'] = 'Fehler:'; +$_MODULE['<{paypal}prestashop>payment_dca16503c563d9fdec70d18f2ab653a4'] = 'Fehler bei der Vorbereitung der PayPal Express-Zahlung'; +$_MODULE['<{paypal}prestashop>payment_51da74120dd5e11817ef21e27d2599bc'] = 'Kundenkonto kann nicht erstellt werden.'; +$_MODULE['<{paypal}prestashop>payment_bcf08b34ab427cb871635151c6976eb0'] = 'Adresse kann nicht erstellt werden.'; +$_MODULE['<{paypal}prestashop>payment_ca5cecfc8fd8e585ba1e684757168158'] = 'Bestehender Warenkorb kann nicht aktualisiert werden.'; +$_MODULE['<{paypal}prestashop>payment_ada2b5d5bbf3065de283d61526141780'] = 'Offene Zahlung einziehen'; +$_MODULE['<{paypal}prestashop>payment_36ec50c0e914dd2fb48a1b27540512ce'] = 'Zahlung akzeptiert'; +$_MODULE['<{paypal}prestashop>payment_c8a31175ee6991be6a0d7a6d32ca4268'] = 'Offene Zahlung bestätigen'; +$_MODULE['<{paypal}prestashop>payment_8a34d4a5b0c3928059f6f92ead9e8aa6'] = 'Die Preise bei PayPal und PrestaShop sind nicht identisch.'; +$_MODULE['<{paypal}prestashop>payment_98825385aadb1d0dd0fd133ef8acd23d'] = 'Bestellung kann nicht erstellt werden.'; +$_MODULE['<{paypal}prestashop>payment_085b78e060c3ef4cc37bd25abd06ff66'] = 'Warenkorb geändert seit der letzten PayPal Express-Zahlung – nehmen Sie eine neue PayPal-Zahlung vor.'; +$_MODULE['<{paypal}prestashop>payment_572da7ef1411f2a12409e752f3eb2f7a'] = 'Ihr Warenkorb ist leer.'; +$_MODULE['<{paypal}prestashop>process_ee9dc1e678d54c517f481583c3fb2db8'] = 'Keine gültige Währung'; +$_MODULE['<{paypal}prestashop>process_484f5a79672cebe198ebdde45a1d672f'] = 'Geschenkverpackung'; +$_MODULE['<{paypal}prestashop>notifier_8a34d4a5b0c3928059f6f92ead9e8aa6'] = 'Die Preise bei PayPal und PrestaShop sind nicht identisch.'; +$_MODULE['<{paypal}prestashop>notifier_572f9af7615560af2cba038cc1948287'] = 'Warenkorb geändert, versuchen Sie es erneut.'; +$_MODULE['<{paypal}prestashop>notifier_36ec50c0e914dd2fb48a1b27540512ce'] = 'Zahlung akzeptiert.'; +$_MODULE['<{paypal}prestashop>back_office_ae3cebe661e92cdfd12516419fef4f2d'] = 'Laden Sie den'; +$_MODULE['<{paypal}prestashop>back_office_e73756d0d2306110f29ccf28cb69c412'] = 'Integrationsleitfaden'; +$_MODULE['<{paypal}prestashop>back_office_6506302a6e11077ecbc04b5932a65c4c'] = 'aus dem PrestaShop herunter und führen Sie die Konfigurationsschritte durch.'; +$_MODULE['<{paypal}prestashop>back_office_748eadce9cf4f2bde207b63c5441da07'] = 'Nutzen Sie die Funktion "PayPal-Login"'; +$_MODULE['<{paypal}prestashop>back_office_cded4ac9f77c68c750c243af1f5263c5'] = '(*siehe'; +$_MODULE['<{paypal}prestashop>back_office_606d8f704cf61d29bffd5195f28af29e'] = 'Integrationsleitfaden)'; +$_MODULE['<{paypal}prestashop>back_office_a1694ad810c4ac5b56b59c47db01cb05'] = 'und folgen Sie den Anweisungen.'; +$_MODULE['<{paypal}prestashop>back_office_3650f874df7e9c6e822a872d02cee6d5'] = 'Diese Funktion ermöglicht Ihren Kunden einen Login mit den PayPal-Zugangsdaten und somit eine schnellere Kaufabwicklung.'; +$_MODULE['<{paypal}prestashop>back_office_93cba07454f06a4a960172bbd6e2a435'] = 'Ja'; +$_MODULE['<{paypal}prestashop>back_office_bafd7322c6e97d25b6299b5d6fe8920b'] = 'Nein'; +$_MODULE['<{paypal}prestashop>back_office_9be4e88898c4e88363208d2472f4a406'] = 'Geben Sie Ihre PayPal-Kontodaten ein.'; +$_MODULE['<{paypal}prestashop>back_office_4ff2e716a7d06ce5274b4090b39abad3'] = 'Siehe'; +$_MODULE['<{paypal}prestashop>back_office_8646a5d7b2817d30950357da8d80a11f'] = 'Integrationsleitfaden'; +$_MODULE['<{paypal}prestashop>back_office_2d801c24938b12e4ca9a2cf9b980c759'] = 'Fehler!'; +$_MODULE['<{paypal}prestashop>capture_81e826adb70e2e6b189c2eef739d52d4'] = 'PayPal-Zahlungseinzug'; +$_MODULE['<{paypal}prestashop>capture_e8fdd4382b75b42bfbd96eb7b032cf47'] = 'Hinweis:'; +$_MODULE['<{paypal}prestashop>capture_ce64b2ea82cf4fa861a6512e2c32b84b'] = 'Betrag, der vor dem Versand eingezogen werden kann.'; +$_MODULE['<{paypal}prestashop>capture_a61a9250ef6cc54f0d7dc8dd0c13da98'] = 'Möchten Sie das Geld wirklich einziehen?'; +$_MODULE['<{paypal}prestashop>capture_99e64593868df2b7b32231c1ae5ddc04'] = 'Geld einziehen'; +$_MODULE['<{paypal}prestashop>refund_8ba079f305b81b172792bc0469b6a690'] = 'PayPal-Rückzahlung'; +$_MODULE['<{paypal}prestashop>refund_e8fdd4382b75b42bfbd96eb7b032cf47'] = 'Hinweis:'; +$_MODULE['<{paypal}prestashop>refund_016e1f278eccd700eaf33f74a501d050'] = 'Zahlung akzeptiert'; +$_MODULE['<{paypal}prestashop>refund_a8b1cc445942a2e1a7d7cca641c86d67'] = 'Bei Rückzahlungen wird standardmäßig eine Teilrückzahlung vorgenommen, sofern Sie nicht die Option "Gutschein ausstellen" wählen.'; +$_MODULE['<{paypal}prestashop>refund_729a51874fe901b092899e9e8b31c97a'] = 'Sind Sie sicher?'; +$_MODULE['<{paypal}prestashop>refund_c2a5e2e23d8ec9cad779d657b7d33fc1'] = 'Gesamten Transaktionsbetrag zurückzahlen'; +$_MODULE['<{paypal}prestashop>validation_b630aa9b5e25da971949cae62dd109aa'] = 'PayPal-Prüfung'; +$_MODULE['<{paypal}prestashop>validation_e8fdd4382b75b42bfbd96eb7b032cf47'] = 'Hinweis:'; +$_MODULE['<{paypal}prestashop>validation_9119a92adbbf6c67bfb8a3aee0bdb720'] = 'Offener Einzugsbetrag – ohne Versandkosten'; +$_MODULE['<{paypal}prestashop>validation_c14eb95a724174f336b8ffdd98ef2f35'] = 'Offene Zahlung – ohne Versandkosten'; +$_MODULE['<{paypal}prestashop>validation_5b18ff32c2aaaf4b79bdead10b10fe29'] = 'Zahlungsstatus abrufen'; +$_MODULE['<{paypal}prestashop>about_e816e21c1c8e0eba0620fa3df6bd6795'] = 'Was ist PayPal?'; +$_MODULE['<{paypal}prestashop>about_16ea57badae98f402bb8f2b2f49d4e77'] = 'PayPal ist ein bewährter Marktführer bei Online-Shop-Zahlungen, der es Käufern und Unternehmen ermöglicht, Geld online zu senden und zu empfangen. PayPal hat über 100 Millionen Mitgliedskonten in 190 Ländern und Regionen. Es wird von Händlern allerorten, sowohl auf als auch außerhalb von eBay, akzeptiert.'; +$_MODULE['<{paypal}prestashop>about_d20adade7baa1b60b713521031ea676c'] = 'Ist es sicher?'; +$_MODULE['<{paypal}prestashop>about_64f7b897c6d56fc62428f692ee5737cd'] = 'PayPal schützt Ihre Kreditkarteninformationen mit branchenweit führenden Sicherheits-und Betrugsbekämpfungssystemen. Wenn Sie PayPal verwenden, werden Ihre finanziellen Informationen dem Händler niemals sichtbar gemacht.'; +$_MODULE['<{paypal}prestashop>about_5ef30813484389e4200640c2f006004d'] = 'Warum PayPal?'; +$_MODULE['<{paypal}prestashop>about_86550d4ea832930db4366f03b90bdfb8'] = 'Gebührenfrei einkaufen oder Geld senden mit PayPal'; +$_MODULE['<{paypal}prestashop>about_7dc9e529337e5a55a12bf362b8e68cac'] = 'Bequem einkaufen und zahlen durch gespeicherte Daten bei PayPal'; +$_MODULE['<{paypal}prestashop>about_32098ae6a7ecd96805df9e48fb6cc739'] = 'PayPal wird von Millionen von Händlern weltweit akzeptiert und ist die bevorzugte Zahlungsmethode bei eBay'; +$_MODULE['<{paypal}prestashop>about_7934d7d1280bfbb8778743e39292af30'] = 'Nutzen Sie PayPal noch heute!'; +$_MODULE['<{paypal}prestashop>error_a40cab5994f36d4c48103a22ca082e8f'] = 'Ihr Warenkorb'; +$_MODULE['<{paypal}prestashop>error_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>error_f47106270a2928f350f357e255a2c2ac'] = 'Setzen Sie sich mit dem Händler in Verbindung:'; +$_MODULE['<{paypal}prestashop>error_d5860edcd3078f86ee963c27654bc6cf'] = 'Gesamter Transaktionsbetrag (inkl. Steuer) :'; +$_MODULE['<{paypal}prestashop>error_a378cd7a0839cbd4ec3e45bbdeeb69be'] = 'Ihre Bestellnummer lautet:'; +$_MODULE['<{paypal}prestashop>error_0557fa923dcee4d0f86b1409f5c2167f'] = 'Zurück'; +$_MODULE['<{paypal}prestashop>order-confirmation-mobile_fb077ecba55e5552916bde26d8b9e794'] = 'Bestellbestätigung'; +$_MODULE['<{paypal}prestashop>order-confirmation-mobile_d5860edcd3078f86ee963c27654bc6cf'] = 'Gesamter Transaktionsbetrag (inkl. Steuer) :'; +$_MODULE['<{paypal}prestashop>order-confirmation-mobile_a378cd7a0839cbd4ec3e45bbdeeb69be'] = 'Ihre Bestellnummer lautet:'; +$_MODULE['<{paypal}prestashop>order-confirmation-mobile_6e860dc1cf94ca08b3fd99993aa2dc68'] = 'Ihr PayPal-Transaktionscode lautet:'; +$_MODULE['<{paypal}prestashop>order-confirmation-mobile_300225ee958b6350abc51805dab83c24'] = 'Einkauf fortsetzen'; +$_MODULE['<{paypal}prestashop>order-confirmation-mobile_9390390581f54c65d6acfc8da4e17362'] = 'Zurück zu Bestellungen'; +$_MODULE['<{paypal}prestashop>order-confirmation_fb077ecba55e5552916bde26d8b9e794'] = 'Bestellbestätigung'; +$_MODULE['<{paypal}prestashop>order-confirmation_d5860edcd3078f86ee963c27654bc6cf'] = 'Gesamter Transaktionsbetrag (inkl. Steuer) :'; +$_MODULE['<{paypal}prestashop>order-confirmation_a378cd7a0839cbd4ec3e45bbdeeb69be'] = 'Ihre Bestellnummer lautet:'; +$_MODULE['<{paypal}prestashop>order-confirmation_6e860dc1cf94ca08b3fd99993aa2dc68'] = 'Ihr PayPal-Transaktionscode lautet:'; +$_MODULE['<{paypal}prestashop>order-confirmation_4082ea29b4f196c4f60533500139725a'] = 'Bestellung verfolgen'; +$_MODULE['<{paypal}prestashop>order-confirmation_9390390581f54c65d6acfc8da4e17362'] = 'Zurück zu Bestellungen'; +$_MODULE['<{paypal}prestashop>order-summary_a40cab5994f36d4c48103a22ca082e8f'] = 'Ihr Warenkorb'; +$_MODULE['<{paypal}prestashop>order-summary_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>order-summary_f1d3b424cd68795ecaa552883759aceb'] = 'Bestellübersicht'; +$_MODULE['<{paypal}prestashop>order-summary_dd23adc5fb6bda9c384397b31e57fc53'] = 'PayPal-Zahlung'; +$_MODULE['<{paypal}prestashop>order-summary_62d74398cb6ebaa69ab7339052ca5c92'] = 'Sie möchten mit PayPal bezahlen.'; +$_MODULE['<{paypal}prestashop>order-summary_c884ed19483d45970c5bf23a681e2dd2'] = 'Ihre Bestellübersicht:'; +$_MODULE['<{paypal}prestashop>order-summary_0c458988127eb2150776881e2ef3f0c4'] = 'Liefeadresse'; +$_MODULE['<{paypal}prestashop>order-summary_e2867a925cba382f1436d1834bb52a1c'] = 'Der Gesamtbetrag Ihrer Bestellung:'; +$_MODULE['<{paypal}prestashop>order-summary_1f87346a16cf80c372065de3c54c86d9'] = '(inkl. Steuer)'; +$_MODULE['<{paypal}prestashop>order-summary_8ed356c32b198c9cb2abab7c3d262b93'] = 'Wir akzeptieren die folgende Währung:'; +$_MODULE['<{paypal}prestashop>order-summary_0881a11f7af33bc1b43e437391129d66'] = 'Bestätigen Sie Ihre Bestellung durch Klicken auf "Bestellung bestätigen".'; +$_MODULE['<{paypal}prestashop>order-summary_46b9e3665f187c739c55983f757ccda0'] = 'Bestellung bestätigen'; +$_MODULE['<{paypal}prestashop>column_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Mit PayPal bezahlen'; +$_MODULE['<{paypal}prestashop>confirmation_2e2117b7c81aa9ea6931641ea2c6499f'] = 'Ihre Bestellung vom'; +$_MODULE['<{paypal}prestashop>confirmation_75fbf512d744977d62599cc3f0ae2bb4'] = 'ist abgeschlossen.'; +$_MODULE['<{paypal}prestashop>confirmation_15b0f8e55c6bdfc3d5fd0b6b3b6cb3ee'] = 'Sie haben die PayPal-Methode gewählt.'; +$_MODULE['<{paypal}prestashop>confirmation_e6dc7945b557a1cd949bea92dd58963e'] = 'Ihre Bestellung wird sehr bald geschickt werden.'; +$_MODULE['<{paypal}prestashop>confirmation_0db71da7150c27142eef9d22b843b4a9'] = 'Bei Fragen oder für weitere Informationen, kontaktieren Sie bitte unseren'; +$_MODULE['<{paypal}prestashop>confirmation_64430ad2835be8ad60c59e7d44e4b0b1'] = 'Kunden-Support'; +$_MODULE['<{paypal}prestashop>express_checkout_payment_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Mit PayPal bezahlen'; +$_MODULE['<{paypal}prestashop>express_checkout_payment_eu_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Mit PayPal bezahlen'; +$_MODULE['<{paypal}prestashop>express_checkout_shortcut_form_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Mit PayPal bezahlen'; +$_MODULE['<{paypal}prestashop>integral_evolution_payment_ecab922bc1f9b5726e2a6deb4acaec4e'] = 'Zurück zur Website des Händlers'; +$_MODULE['<{paypal}prestashop>integral_evolution_payment_eu_ecab922bc1f9b5726e2a6deb4acaec4e'] = 'Zurück zur Website des Händlers'; +$_MODULE['<{paypal}prestashop>paypal_abstract_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>paypal_abstract_6e7012516038a096b9f6bb71ba2cc5a3'] = 'Zahlungen per Kreditkarte (CB, Visa, MasterCard, Amex, Aurore, Cofinoga, 4 stars) mit PayPal akzeptieren'; +$_MODULE['<{paypal}prestashop>paypal_abstract_69a1a3ad8dd5da6db3c4da838a0cf9c7'] = 'Sind Sie sicher, dass Sie Ihre Details löschen möchten?'; +$_MODULE['<{paypal}prestashop>paypal_abstract_32af90c3cfef1bacf43b0c3a8f60a4da'] = 'Geldbetrag wurde überwiesen'; +$_MODULE['<{paypal}prestashop>paypal_abstract_d238649ac5ec14afc894fad36c0b50fc'] = 'Die Anfrage nach Geldüberweisung war nicht erfolgreich, bitte lesen Sie die Protokollnachricht!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_05b998de2c4fb46a7bdd37bd378b81d9'] = 'Die Bestätigung ist erfolgt, siehe Protokollnachricht!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_aeca7e93a1b3d77e38c3cffa131774d5'] = 'Der Betrag wurde überwiesen'; +$_MODULE['<{paypal}prestashop>paypal_abstract_cba030a50c8a99c7e224adbe1cf58544'] = 'Die Anfrage nach Geldüberweisung war nicht erfolgreich, bitte lesen Sie die Protokollnachricht!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_20fda49ece75d93bea97648ab1f1f1cf'] = 'Produktergebnisse löschen'; +$_MODULE['<{paypal}prestashop>paypal_abstract_e5d5d9f40763cfe6549bef705e3529a7'] = 'Die Zahlungsnachricht ist nicht gültig, prüfen Sie bitte Ihr Modul!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_ee9dc1e678d54c517f481583c3fb2db8'] = 'Keine gültige Währung'; +$_MODULE['<{paypal}prestashop>paypal_abstract_eec39bf42bd135971fb2d838c67d1449'] = 'Ergebnis Rückerstattungsoperation'; +$_MODULE['<{paypal}prestashop>paypal_abstract_2ab62d1a578713d0862b56819295630e'] = 'Rückerstattung abgeschlossen mit PayPal!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_a64db959966ba8d07c8b5d9493fcc21f'] = 'Fehler bei der Transaktion!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_67962779da962e3d4225055afc05e7bd'] = 'Ergebnis Einzugsoperation'; +$_MODULE['<{paypal}prestashop>paypal_abstract_8778ee03f6592d5fec9a1f2ee851e476'] = 'Bestellung mit PayPal abgeschlossen!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_672d40feac6437e49f771019bc330790'] = 'Überprüfungsstatus:'; +$_MODULE['<{paypal}prestashop>paypal_abstract_1828820cc60e36b6f9fdf60cab103ed7'] = 'Sie nutzenzur Zeit die Standard-PayPal-Mail-Adresse, Sie müssen Ihre eigene E-Mail-Adresse verwenden'; +$_MODULE['<{paypal}prestashop>validation_20dfea1a472e5be3f15f6b5f36ca335c'] = 'Problem beim Verbinden mit dem PayPal-Server.'; +$_MODULE['<{paypal}prestashop>validation_f7799c2ded739cf3c3e9babffc5f315b'] = 'Verbindung über cURL fehlgeschlagen'; +$_MODULE['<{paypal}prestashop>validation_eca77e208634d52703b07672abbf16ec'] = 'Fehler in der Überprüfung (mit cURL). Zurückgegeben:'; +$_MODULE['<{paypal}prestashop>validation_8358ec19f397d4cdd632688d4f79e535'] = 'Fehler in der Überprüfung (mit fsockopen). Zurückgegeben:'; +$_MODULE['<{paypal}prestashop>validation_76ee8dc73701e846f7bccdf98dae079b'] = 'Keine Kommunikationsmittel zur Verfügung.'; +$_MODULE['<{paypal}prestashop>validation_bd0e34e5be6447844e6f262d51f1a9dc'] = 'Zahlung:'; +$_MODULE['<{paypal}prestashop>validation_e0395c4ce35d0b1e59ca3f2d5e260d23'] = 'Paypal Schlüssel \'custom\' nicht angegeben, kann keine Verbindung zum Warenkorb herstellen'; +$_MODULE['<{paypal}prestashop>validation_765261b630ee773659fae89e9ad762f5'] = 'Paypal-Schlüssel \'txn_id\' nicht angegeben, Transaktion unbekannt'; +$_MODULE['<{paypal}prestashop>validation_01634612f84d2b7ba56ccdf467e604b7'] = 'Paypal-Schlüssel \'mc_currency\' nicht angegeben, Währung unbekannt'; +$_MODULE['<{paypal}prestashop>validation_e61f52d02b9f52fbe1fd41ed320e29c3'] = 'Warenkorb nicht gefunden'; +$_MODULE['<{paypal}prestashop>validation_0617900b1aff826081d07f5a3e2e7cd0'] = 'Bestellauftrag wurde bereits gestellt'; +$_MODULE['<{paypal}prestashop>validation_f5209b3301a46f3057ffbf34d903e205'] = 'PayPal-Transaktion-ID:'; +$_MODULE['<{paypal}prestashop>validation_7b19e875ff64b09d80ee05dcc84b9975'] = 'Die PayPal-Transaktion konnte nicht VERIFIZIERT werden.'; +$_MODULE['<{paypal}prestashop>paypal_connect_ea800e3536f81238a4cbc32eb6db4eaf'] = 'Verbindung erfolgreich mit fsockopen Methode'; +$_MODULE['<{paypal}prestashop>paypal_express_checkout_ee9dc1e678d54c517f481583c3fb2db8'] = 'Keine gültige Währung'; +$_MODULE['<{paypal}prestashop>paypal_express_checkout_484f5a79672cebe198ebdde45a1d672f'] = 'Geschenkverpackung:'; +$_MODULE['<{paypal}prestashop>submit_36ec50c0e914dd2fb48a1b27540512ce'] = 'Zahlung akzeptiert.'; +$_MODULE['<{paypal}prestashop>error_425551a2289ed60c9260933d1c45ef00'] = 'Bitte lesen Sie die Protokolle:'; +$_MODULE['<{paypal}prestashop>express_checkout_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Mit PayPal bezahlen'; +$_MODULE['<{paypal}prestashop>payment_a40cab5994f36d4c48103a22ca082e8f'] = 'Ihr Warenkorb'; +$_MODULE['<{paypal}prestashop>payment_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>payment_f1d3b424cd68795ecaa552883759aceb'] = 'Bestellsumme'; +$_MODULE['<{paypal}prestashop>payment_dd23adc5fb6bda9c384397b31e57fc53'] = 'PayPal-Zahlung'; +$_MODULE['<{paypal}prestashop>payment_62d74398cb6ebaa69ab7339052ca5c92'] = 'Sie haben PayPal für Ihre Zahlung gewählt.'; +$_MODULE['<{paypal}prestashop>payment_c884ed19483d45970c5bf23a681e2dd2'] = 'Hier ist eine kurze Zusammenfassung Ihrer Bestellung:'; +$_MODULE['<{paypal}prestashop>payment_e2867a925cba382f1436d1834bb52a1c'] = 'Der Gesamtbetrag Ihrer Bestellung beträgt'; +$_MODULE['<{paypal}prestashop>payment_1f87346a16cf80c372065de3c54c86d9'] = '(inkl. MwSt.)'; +$_MODULE['<{paypal}prestashop>payment_8ed356c32b198c9cb2abab7c3d262b93'] = 'Wir akzeptieren die folgenden Währungen über PayPal:'; +$_MODULE['<{paypal}prestashop>payment_0881a11f7af33bc1b43e437391129d66'] = 'Bitte bestätigen Sie Ihre Bestellung durch Klicken auf \"BESTELLEN\"'; +$_MODULE['<{paypal}prestashop>payment_46b9e3665f187c739c55983f757ccda0'] = 'BESTELLEN'; +$_MODULE['<{paypal}prestashop>payment_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Bezahlen mit PayPal'; +$_MODULE['<{paypal}prestashop>payment_a3f2caee6ef8e68fbd26e42d83f2bf65'] = 'Bezahlen Sie mit Ihrem PayPal-Konto, Kreditkarte (CB, Visa, Mastercard ...), oder privaten Kreditkarte'; +$_MODULE['<{paypal}prestashop>payment_b08008a2de4331ba13f006c9bcf37b62'] = 'Bezahlen Sie mit Ihrem PayPal-Konto'; +$_MODULE['<{paypal}prestashop>paypal_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Bezahlen mit PayPal'; diff --git a/modules/paypal/es.php b/modules/paypal/es.php new file mode 100644 index 00000000..eb5c33c3 --- /dev/null +++ b/modules/paypal/es.php @@ -0,0 +1,90 @@ +paypal_abstract_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>paypal_abstract_6e7012516038a096b9f6bb71ba2cc5a3'] = 'Acepta pagos con tarjetas de débito y crédito (Visa, MasterCard, Amex, Aurora) con PayPal'; +$_MODULE['<{paypal}prestashop>paypal_abstract_69a1a3ad8dd5da6db3c4da838a0cf9c7'] = '¿Está seguro de querer borrar los detalles?'; +$_MODULE['<{paypal}prestashop>paypal_abstract_32af90c3cfef1bacf43b0c3a8f60a4da'] = 'Se han recuperado los fondos'; +$_MODULE['<{paypal}prestashop>paypal_abstract_d238649ac5ec14afc894fad36c0b50fc'] = 'La solicitud de recuperación de fondos no se ha hecho correctamente, consulte el mensaje de registro.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_05b998de2c4fb46a7bdd37bd378b81d9'] = 'Se ha completado la validación, consulte el mensaje de registro.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_aeca7e93a1b3d77e38c3cffa131774d5'] = 'Se ha hecho un reintegro.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_cba030a50c8a99c7e224adbe1cf58544'] = 'La solicitud de reintegro no se ha hecho correctamente, consulte el mensaje de registro.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_20fda49ece75d93bea97648ab1f1f1cf'] = 'Cancelar resultados de productos:'; +$_MODULE['<{paypal}prestashop>paypal_abstract_e5d5d9f40763cfe6549bef705e3529a7'] = 'El mensaje de pago no es válido, compruebe su módulo.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_ee9dc1e678d54c517f481583c3fb2db8'] = 'Divisa incorrecta'; +$_MODULE['<{paypal}prestashop>paypal_abstract_eec39bf42bd135971fb2d838c67d1449'] = 'Resultado de la operación de reintegro:'; +$_MODULE['<{paypal}prestashop>paypal_abstract_2ab62d1a578713d0862b56819295630e'] = 'Reintegro completado con PayPal.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_a64db959966ba8d07c8b5d9493fcc21f'] = 'Error de transacción.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_67962779da962e3d4225055afc05e7bd'] = 'Resultado de la operación de captura:'; +$_MODULE['<{paypal}prestashop>paypal_abstract_8778ee03f6592d5fec9a1f2ee851e476'] = 'Pedido completado con PayPal'; +$_MODULE['<{paypal}prestashop>paypal_abstract_672d40feac6437e49f771019bc330790'] = 'Estado de verificación:'; +$_MODULE['<{paypal}prestashop>paypal_abstract_1828820cc60e36b6f9fdf60cab103ed7'] = 'Actualmente está utilizando la dirección email PayPal por defecto, debe sustituirla por sus propia dirección'; +$_MODULE['<{paypal}prestashop>validation_20dfea1a472e5be3f15f6b5f36ca335c'] = ' Error de conexión con el servidor de PayPal. '; +$_MODULE['<{paypal}prestashop>validation_f7799c2ded739cf3c3e9babffc5f315b'] = 'Error de conexión con protocolo cURL. '; +$_MODULE['<{paypal}prestashop>validation_eca77e208634d52703b07672abbf16ec'] = 'Error de verificación (protocolo cURL) . Retroceso: '; +$_MODULE['<{paypal}prestashop>validation_8358ec19f397d4cdd632688d4f79e535'] = 'Error de verificación (protocolo fsockopen) . Retroceso: '; +$_MODULE['<{paypal}prestashop>validation_76ee8dc73701e846f7bccdf98dae079b'] = 'No hay protocolos de comunicación disponibles. '; +$_MODULE['<{paypal}prestashop>validation_bd0e34e5be6447844e6f262d51f1a9dc'] = 'Pago: '; +$_MODULE['<{paypal}prestashop>validation_e0395c4ce35d0b1e59ca3f2d5e260d23'] = 'El token proporcionado por PayPal no es el mismo que el del cookie'; +$_MODULE['<{paypal}prestashop>validation_765261b630ee773659fae89e9ad762f5'] = 'No se ha especificado la clave PayPal \'txn_id\', transacción no reconocida'; +$_MODULE['<{paypal}prestashop>validation_01634612f84d2b7ba56ccdf467e604b7'] = 'No se ha especificado la clave PayPal \'mc_currency\', divisa no reconocida'; +$_MODULE['<{paypal}prestashop>validation_e61f52d02b9f52fbe1fd41ed320e29c3'] = ' No se puede encontrar el carro de la compra'; +$_MODULE['<{paypal}prestashop>validation_0617900b1aff826081d07f5a3e2e7cd0'] = 'Ya se ha procesado el pedido'; +$_MODULE['<{paypal}prestashop>validation_f5209b3301a46f3057ffbf34d903e205'] = 'Id. de la transacción de PayPal: '; +$_MODULE['<{paypal}prestashop>validation_7b19e875ff64b09d80ee05dcc84b9975'] = 'No se ha podido verificar la transacción de PayPal. '; +$_MODULE['<{paypal}prestashop>paypal_connect_d1f14cc4a2dade80c92421d26422fea0'] = 'Abrir una nueva conexión con'; +$_MODULE['<{paypal}prestashop>paypal_connect_94a27811a721ef512ad7bfa06cab34e0'] = 'Error de la conexión con el método cURL'; +$_MODULE['<{paypal}prestashop>paypal_connect_70215486455daee13382c68b1a230b82'] = 'La conexión con el método cURL se ha desarrollado con éxito'; +$_MODULE['<{paypal}prestashop>paypal_connect_e4c4ad49bced42265b5facc2175cdafd'] = 'Envío de parámetros:'; +$_MODULE['<{paypal}prestashop>paypal_connect_445583f6641da98fc7ac8fd9d13a564b'] = 'Error de envío con el método cURL. Error:'; +$_MODULE['<{paypal}prestashop>paypal_connect_ef4fbf36eaa2083442d386990ba063c2'] = 'Envío con éxito con el método cURL'; +$_MODULE['<{paypal}prestashop>paypal_connect_bf059c9751bb1a20b449b7917b1df374'] = 'Error de la conexión con el método fsockopen'; +$_MODULE['<{paypal}prestashop>paypal_connect_ea800e3536f81238a4cbc32eb6db4eaf'] = 'La conexión con el método fsockopen se ha desarrollado con éxito'; +$_MODULE['<{paypal}prestashop>paypal_connect_6e9aa4cb541e09b07602d4ea96080811'] = 'Error de envío con el método fsockopen. Error:'; +$_MODULE['<{paypal}prestashop>paypal_connect_842a183be225d415b2b4375ba1dd1c94'] = 'Envío con éxito con el método fsockopen'; +$_MODULE['<{paypal}prestashop>paypal_lib_7c2d00d8c94d1ce0f515db8b0481db40'] = ' Respuesta de PayPal : '; +$_MODULE['<{paypal}prestashop>paypal_express_checkout_ee9dc1e678d54c517f481583c3fb2db8'] = 'Divisa incorrecta'; +$_MODULE['<{paypal}prestashop>paypal_express_checkout_484f5a79672cebe198ebdde45a1d672f'] = 'Mensaje para regalo:'; +$_MODULE['<{paypal}prestashop>submit_36ec50c0e914dd2fb48a1b27540512ce'] = 'Pago aceptado'; +$_MODULE['<{paypal}prestashop>notifier_36ec50c0e914dd2fb48a1b27540512ce'] = 'Pago aceptado'; +$_MODULE['<{paypal}prestashop>about_e816e21c1c8e0eba0620fa3df6bd6795'] = '¿Qué es PayPal?'; +$_MODULE['<{paypal}prestashop>about_16ea57badae98f402bb8f2b2f49d4e77'] = 'PayPal es el líder indiscutible de pagos por Internet: tiene más de 100 millones de cuentas repartidas en 190 países de todo el mundo. Es aceptado como forma de pago por muchos vendedores, tanto dentro como fuera de eBay. '; +$_MODULE['<{paypal}prestashop>about_d20adade7baa1b60b713521031ea676c'] = '¿Es un servicio seguro?'; +$_MODULE['<{paypal}prestashop>about_64f7b897c6d56fc62428f692ee5737cd'] = 'PayPal protege sus datos financieros con los mejores sistemas de seguridad y prevención de fraude del mercado. PayPal nunca revela sus datos financieros al vendedor. '; +$_MODULE['<{paypal}prestashop>about_5ef30813484389e4200640c2f006004d'] = '¿Por qué utilizar PayPal?'; +$_MODULE['<{paypal}prestashop>about_86550d4ea832930db4366f03b90bdfb8'] = ' Haga compras y envíe pagos con PayPal: es gratuito (consulte las condicio'; +$_MODULE['<{paypal}prestashop>about_7dc9e529337e5a55a12bf362b8e68cac'] = 'Registre sus datos en PayPal y compre con toda tranquilidad . '; +$_MODULE['<{paypal}prestashop>about_32098ae6a7ecd96805df9e48fb6cc739'] = 'Millones de vendedores de todo el mundo aceptan PayPal y es la forma de pago más utilizada en eBay. '; +$_MODULE['<{paypal}prestashop>about_7934d7d1280bfbb8778743e39292af30'] = '¡Utilice PayPal ya!'; +$_MODULE['<{paypal}prestashop>column_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Pagar con PayPal'; +$_MODULE['<{paypal}prestashop>confirmation_2e2117b7c81aa9ea6931641ea2c6499f'] = ' El pedido de '; +$_MODULE['<{paypal}prestashop>confirmation_75fbf512d744977d62599cc3f0ae2bb4'] = ' se ha guardado correctamente'; +$_MODULE['<{paypal}prestashop>confirmation_15b0f8e55c6bdfc3d5fd0b6b3b6cb3ee'] = ' Ha seleccionado PayPal como forma de pago'; +$_MODULE['<{paypal}prestashop>confirmation_e6dc7945b557a1cd949bea92dd58963e'] = ' Le enviaremos el pedido lo antes posible'; +$_MODULE['<{paypal}prestashop>confirmation_0db71da7150c27142eef9d22b843b4a9'] = ' Si tiene dudas o necesita información adicional, póngase en contacto con nuestro'; +$_MODULE['<{paypal}prestashop>confirmation_64430ad2835be8ad60c59e7d44e4b0b1'] = ' servicio de atención al cliente '; +$_MODULE['<{paypal}prestashop>error_a40cab5994f36d4c48103a22ca082e8f'] = 'Carrito de la compra'; +$_MODULE['<{paypal}prestashop>error_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>error_425551a2289ed60c9260933d1c45ef00'] = 'Compruebe los registros: '; +$_MODULE['<{paypal}prestashop>error_0557fa923dcee4d0f86b1409f5c2167f'] = 'Anterior'; +$_MODULE['<{paypal}prestashop>order-confirmation_fb077ecba55e5552916bde26d8b9e794'] = 'Confirmación de pedido'; +$_MODULE['<{paypal}prestashop>order-confirmation_a378cd7a0839cbd4ec3e45bbdeeb69be'] = 'Su ID de pedido es:'; +$_MODULE['<{paypal}prestashop>order-confirmation_4082ea29b4f196c4f60533500139725a'] = 'Seguimiento de mi pedido'; +$_MODULE['<{paypal}prestashop>order-confirmation_9390390581f54c65d6acfc8da4e17362'] = 'Volver a pedidos'; +$_MODULE['<{paypal}prestashop>express_checkout_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Pagar con PayPal'; +$_MODULE['<{paypal}prestashop>payment_a40cab5994f36d4c48103a22ca082e8f'] = 'Su cesta'; +$_MODULE['<{paypal}prestashop>payment_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>payment_f1d3b424cd68795ecaa552883759aceb'] = 'Resumen del pedido'; +$_MODULE['<{paypal}prestashop>payment_dd23adc5fb6bda9c384397b31e57fc53'] = 'Pago con PayPal '; +$_MODULE['<{paypal}prestashop>payment_62d74398cb6ebaa69ab7339052ca5c92'] = 'Ha elegido pagar con PayPal. '; +$_MODULE['<{paypal}prestashop>payment_c884ed19483d45970c5bf23a681e2dd2'] = 'Resumen de su pedido:'; +$_MODULE['<{paypal}prestashop>payment_e2867a925cba382f1436d1834bb52a1c'] = 'El importe total de su pedido asciende a'; +$_MODULE['<{paypal}prestashop>payment_1f87346a16cf80c372065de3c54c86d9'] = 'con IVA'; +$_MODULE['<{paypal}prestashop>payment_8ed356c32b198c9cb2abab7c3d262b93'] = 'Aceptamos esta divisa para el pago : '; +$_MODULE['<{paypal}prestashop>payment_0881a11f7af33bc1b43e437391129d66'] = 'Por favor, confirme su pedido pulsando en \"Confirmo mi pedido\"'; +$_MODULE['<{paypal}prestashop>payment_46b9e3665f187c739c55983f757ccda0'] = 'Confirmo mi pedido'; +$_MODULE['<{paypal}prestashop>payment_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Pagar con PayPal'; +$_MODULE['<{paypal}prestashop>payment_a3f2caee6ef8e68fbd26e42d83f2bf65'] = 'Pague con su cuenta PayPal, tarjeta de crédito (CB, Visa, Mastercard ...), o tarjeta de crédito privado'; +$_MODULE['<{paypal}prestashop>payment_b08008a2de4331ba13f006c9bcf37b62'] = 'Pague con su cuenta PayPal'; +$_MODULE['<{paypal}prestashop>paypal_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Pagar con PayPal'; diff --git a/modules/paypal/express_checkout/ajax.php b/modules/paypal/express_checkout/ajax.php new file mode 100644 index 00000000..14258127 --- /dev/null +++ b/modules/paypal/express_checkout/ajax.php @@ -0,0 +1,55 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +include_once(dirname(__FILE__).'/../../../config/config.inc.php'); +include_once(dirname(__FILE__).'/../../../init.php'); +include_once(dirname(__FILE__).'/../paypal.php'); + +// Ajax query +$quantity = Tools::getValue('get_qty'); + +if (Configuration::get('PS_CATALOG_MODE') == 1) + die('0'); + +if ($quantity && $quantity > 0) +{ + /* Ajax response */ + $id_product = (int)Tools::getValue('id_product'); + $id_product_attribute = (int)Tools::getValue('id_product_attribute'); + $product_quantity = Product::getQuantity($id_product, $id_product_attribute); + $product = new Product($id_product); + + if (!$product->available_for_order) + die('0'); + + if ($product_quantity > 0) + die('1'); + + if ($product_quantity <= 0 && $product->isAvailableWhenOutOfStock((int)$product->out_of_stock)) + die('1'); + +} +die('0'); diff --git a/modules/paypal/express_checkout/index.php b/modules/paypal/express_checkout/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/express_checkout/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/express_checkout/payment.php b/modules/paypal/express_checkout/payment.php new file mode 100644 index 00000000..0fc3cf95 --- /dev/null +++ b/modules/paypal/express_checkout/payment.php @@ -0,0 +1,407 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +include_once(dirname(__FILE__).'/../../../config/config.inc.php'); +include_once(dirname(__FILE__).'/../../../init.php'); + +include_once(_PS_MODULE_DIR_.'paypal/express_checkout/process.php'); +include_once(_PS_MODULE_DIR_.'paypal/express_checkout/submit.php'); +include_once(_PS_MODULE_DIR_.'paypal/paypal_login/PayPalLoginUser.php'); + +/* Normal payment process */ +$id_cart = Tools::getValue('id_cart'); +$id_order = Tools::getValue('id_order'); +$id_module = Tools::getValue('id_module'); +$paypal_key = Tools::getValue('key'); + +if ($id_cart && $id_order && $id_module && $paypal_key) +{ + if (version_compare(_PS_VERSION_, '1.5', '<')) + new PayPalExpressCheckoutSubmit(); + return; +} + +$request_type = Tools::getValue('express_checkout'); +$ppec = new PaypalExpressCheckout($request_type); + +$token = Tools::getValue('token'); +$payer_id = Tools::getValue('PayerID'); + + +function setContextData($ppec) +{ + // Create new Cart to avoid any refresh or other bad manipulations + $ppec->context->cart = new Cart(); + $ppec->context->cart->id_currency = (int)$ppec->context->currency->id; + $ppec->context->cart->id_lang = (int)$ppec->context->language->id; + + // Customer settings + $ppec->context->cart->id_guest = (int)$ppec->context->cookie->id_guest; + $ppec->context->cart->id_customer = (int)$ppec->context->customer->id; + + // Secure key information + $secure_key = isset($ppec->context->customer) ? $ppec->context->customer->secure_key : null; + $ppec->context->cart->secure_key = $secure_key; +} + +/** + * Set customer information + * Used to create user account with PayPal account information + */ +function setCustomerInformation($ppec, $email) +{ + $customer = new Customer(); + $customer->email = $email; + $customer->lastname = $ppec->result['LASTNAME']; + $customer->firstname = $ppec->result['FIRSTNAME']; + $customer->passwd = Tools::encrypt(Tools::passwdGen()); + return $customer; +} + + +/** + * Set customer address (when not logged in) + * Used to create user address with PayPal account information + */ +function setCustomerAddress($ppec, $customer, $id = null) +{ + $address = new Address($id); + $address->id_country = Country::getByIso($ppec->result['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE']); + if ($id == null) + $address->alias = 'Paypal_Address'; + + $address->lastname = $customer->lastname; + $address->firstname = $customer->firstname; + $address->address1 = $ppec->result['PAYMENTREQUEST_0_SHIPTOSTREET']; + if (isset($ppec->result['PAYMENTREQUEST_0_SHIPTOSTREET2'])) + $address->address2 = $ppec->result['PAYMENTREQUEST_0_SHIPTOSTREET2']; + $address->city = $ppec->result['PAYMENTREQUEST_0_SHIPTOCITY']; + if (Country::containsStates($address->id_country)) + $address->id_state = (int)State::getIdByIso($ppec->result['PAYMENTREQUEST_0_SHIPTOSTATE'], $address->id_country); + $address->postcode = $ppec->result['PAYMENTREQUEST_0_SHIPTOZIP']; + if (isset($ppec->result['PAYMENTREQUEST_0_SHIPTOPHONENUM'])) + $address->phone = $ppec->result['PAYMENTREQUEST_0_SHIPTOPHONENUM']; + $address->id_customer = $customer->id; + return $address; +} +if ($request_type && $ppec->type) +{ + $id_product = (int)Tools::getValue('id_product'); + $product_quantity = (int)Tools::getValue('quantity'); + $id_product_attribute = Tools::getValue('id_p_attr'); + + if (($id_product > 0) && $id_product_attribute !== false && ($product_quantity > 0)) + { + setContextData($ppec); + + if (!$ppec->context->cart->add()) + { + $ppec->logs[] = $ppec->l('Cannot create new cart'); + $display = (_PS_VERSION_ < '1.5') ? new BWDisplay() : new FrontController(); + + $ppec->context->smarty->assign(array( + 'logs' => $ppec->logs, + 'message' => $ppec->l('Error occurred:'), + 'use_mobile' => (bool)$ppec->useMobile() + )); + + $template = 'error.tpl'; + } + else + $ppec->context->cookie->id_cart = (int)$ppec->context->cart->id; + + $ppec->context->cart->updateQty((int)$product_quantity, (int)$id_product, (int)$id_product_attribute); + $ppec->context->cart->update(); + } + + $login_user = PaypalLoginUser::getByIdCustomer((int)$ppec->context->customer->id); + + if ($login_user && $login_user->expires_in <= time()) + { + $obj = new PayPalLogin(); + $login_user = $obj->getRefreshToken(); + } + + /* Set details for a payment */ + $ppec->setExpressCheckout(($login_user ? $login_user->access_token : false)); + + if(Tools::getValue('ajax') && Configuration::get('PAYPAL_IN_CONTEXT_CHECKOUT')) + { + $ppec->displayPaypalInContextCheckout(); + } + if ($ppec->hasSucceedRequest() && !empty($ppec->token)) + $ppec->redirectToAPI(); + /* Display Error and die with this method */ + else + $ppec->displayPayPalAPIError($ppec->l('Error during the preparation of the Express Checkout payment'), $ppec->logs); +} +//If a token exist with payer_id, then we are back from the PayPal API +elseif (!empty($ppec->token) && ($ppec->token == $token) && ($ppec->payer_id = $payer_id)) +{ + /* Get payment infos from paypal */ + $ppec->getExpressCheckout(); + + if ($ppec->hasSucceedRequest() && !empty($ppec->token)) + { + $address = $customer = null; + $email = $ppec->result['EMAIL']; + + /* Create Customer if not exist with address etc */ + if ($ppec->context->cookie->logged) + { + $id_customer = Paypal::getPayPalCustomerIdByEmail($email); + if (!$id_customer) + PayPal::addPayPalCustomer($ppec->context->customer->id, $email); + $customer = $ppec->context->customer; + } + elseif ($id_customer = Customer::customerExists($email, true)) + $customer = new Customer($id_customer); + else + { + $customer = setCustomerInformation($ppec, $email); + $customer->add(); + + PayPal::addPayPalCustomer($customer->id, $email); + } + + if (!$customer->id) + $ppec->logs[] = $ppec->l('Cannot create customer'); + + if (!isset($ppec->result['PAYMENTREQUEST_0_SHIPTOSTREET']) || !isset($ppec->result['PAYMENTREQUEST_0_SHIPTOCITY']) + || !isset($ppec->result['SHIPTOZIP']) || !isset($ppec->result['COUNTRYCODE'])) + $ppec->redirectToCheckout($customer, ($ppec->type != 'payment_cart')); + + $addresses = $customer->getAddresses($ppec->context->language->id); + foreach ($addresses as $address) + if ($address['alias'] == 'Paypal_Address') + {//If address has already been created + $address = new Address($address['id_address']); + break; + } + + /* Create address */ + if (is_array($address) && isset($address['id_address'])) + $address = new Address($address['id_address']); + + if ((!$address || !$address->id) && $customer->id) + {//If address does not exists, we create it + $address = setCustomerAddress($ppec, $customer); + $address->add(); + } + + if ($customer->id && !$address->id) + $ppec->logs[] = $ppec->l('Cannot create Address'); + + /* Create Order */ + if ($customer->id && $address->id) + { + $ppec->context->cart->id_customer = $customer->id; + $ppec->context->cart->id_guest = $ppec->context->cookie->id_guest; + + if (!$ppec->context->cart->update()) + $ppec->logs[] = $ppec->l('Cannot update existing cart'); + else + { + $payment_cart = (bool)($ppec->type != 'payment_cart'); + $ppec->redirectToCheckout($customer, $payment_cart); + } + } + } +} +/** + * Check payment return + */ +function validateOrder($customer, $cart, $ppec) +{ + $amount_match = $ppec->rightPaymentProcess(); + $order_total = (float)$cart->getOrderTotal(true, Cart::BOTH); + + // Payment succeed + if ($ppec->hasSucceedRequest() && !empty($ppec->token) && $amount_match) + { + if ((bool)Configuration::get('PAYPAL_CAPTURE')) + { + $payment_type = (int)Configuration::get('PS_OS_PAYPAL'); + $payment_status = 'Pending_capture'; + $message = $ppec->l('Pending payment capture.').'
    '; + } + else + { + if (isset($ppec->result['PAYMENTINFO_0_PAYMENTSTATUS'])) + $payment_status = $ppec->result['PAYMENTINFO_0_PAYMENTSTATUS']; + else + $payment_status = 'Error'; + + if ((strcasecmp($payment_status, 'Completed') === 0) || (strcasecmp($payment_status, 'Completed_Funds_Held') === 0)) + { + $payment_type = (int)Configuration::get('PS_OS_PAYMENT'); + $message = $ppec->l('Payment accepted.').'
    '; + } + elseif (Tools::getValue('banktxnpendingurl') && Tools::getValue('banktxnpendingurl') == 'true') + { + $payment_type = (int)Configuration::get('PS_OS_PAYPAL'); + $message = $ppec->l('eCheck').'
    '; + } + elseif (strcasecmp($payment_status, 'Pending') === 0) + { + $payment_type = (int)Configuration::get('PS_OS_PAYPAL'); + $message = $ppec->l('Pending payment confirmation.').'
    '; + } + } + } + // Payment error + else + { + //Check if error is 10486, if it is redirect user to paypal + if ($ppec->result['L_ERRORCODE0'] == 10486) + $ppec->redirectToAPI(); + + $payment_status = $ppec->result['PAYMENTINFO_0_PAYMENTSTATUS']; + $payment_type = (int)Configuration::get('PS_OS_ERROR'); + + if ($amount_match) + $message = implode('
    ', $ppec->logs).'
    '; + else + $message = $ppec->l('Price paid on paypal is not the same that on PrestaShop.').'
    '; + } + + $transaction = PayPalOrder::getTransactionDetails($ppec, $payment_status); + $ppec->context->cookie->id_cart = $cart->id; + + $ppec->validateOrder((int)$cart->id, $payment_type, $order_total, $ppec->displayName, $message, $transaction, + (int)$cart->id_currency, false, $customer->secure_key, $ppec->context->shop); +} + +/* If Previous steps succeed, ready (means 'ready to pay') will be set to true */ +if ($ppec->ready && !empty($ppec->token) && (Tools::isSubmit('confirmation') || $ppec->type == 'payment_cart')) +{ + /* Check modification on the product cart / quantity */ + if ($ppec->isProductsListStillRight()) + { + $cart = $ppec->context->cart; + $customer = new Customer((int)$cart->id_customer); + + // When all information are checked before, we can validate the payment to paypal + // and create the prestashop order + $ppec->doExpressCheckout(); + + + if ($ppec->result['RedirectRequired'] == 'true') + $ppec->redirectToAPI(); + + validateOrder($customer, $cart, $ppec); + + unset($ppec->context->cookie->{PaypalExpressCheckout::$cookie_name}); + + if (!$ppec->currentOrder) + $ppec->logs[] = $ppec->l('Cannot create order'); + else + { + $id_order = (int)$ppec->currentOrder; + $order = new Order($id_order); + } + + /* Check payment details to display the appropriate content */ + if (isset($order) && ($ppec->result['ACK'] != 'Failure')) + { + $values = array( + 'key' => $customer->secure_key, + 'id_module' => (int)$ppec->id, + 'id_cart' => (int)$cart->id, + 'id_order' => (int)$ppec->currentOrder + ); + + if (version_compare(_PS_VERSION_, '1.5', '<')) + { + $query = http_build_query($values, '', '&'); + Tools::redirectLink(_MODULE_DIR_.$ppec->name.'/express_checkout/payment.php?'.$query); + } + else + { + $link = $ppec->context->link->getModuleLink('paypal', 'submit', $values); + Tools::redirect($link); + } + } + elseif ($ppec->result['ACK'] != 'Failure') + { + $ppec->context->smarty->assign(array( + 'logs' => $ppec->logs, + 'message' => $ppec->l('Error occurred:'), + )); + + $template = 'error.tpl'; + } + } + else + { + /* If Cart changed, no need to keep the paypal data */ + unset($ppec->context->cookie->{PaypalExpressCheckout::$cookie_name}); + $ppec->logs[] = $ppec->l('Cart changed since the last checkout express, please make a new Paypal checkout payment'); + } +} + +$display = (_PS_VERSION_ < '1.5') ? new BWDisplay() : new FrontController(); +$payment_confirmation = Tools::getValue('get_confirmation'); + +if ($ppec->ready && $payment_confirmation && (_PS_VERSION_ < '1.5')) +{ + $shop_domain = PayPal::getShopDomainSsl(true, true); + $form_action = $shop_domain._MODULE_DIR_.$ppec->name.'/express_checkout/payment.php'; + $order_total = $ppec->context->cart->getOrderTotal(true); + $currency = new Currency((int)$ppec->context->cart->id_currency); + + $ppec->context->smarty->assign(array( + 'form_action' => $form_action, + 'total' => Tools::displayPrice($order_total, $currency), + 'logos' => $ppec->paypal_logos->getLogos(), + )); + + $template = 'order-summary.tpl'; +} +/* Display result if error occurred */ +else +{ + if (!$ppec->context->cart->id) + { + $ppec->context->cart->delete(); + $ppec->logs[] = $ppec->l('Your cart is empty.'); + } + $ppec->context->smarty->assign(array( + 'logs' => $ppec->logs, + 'message' => $ppec->l('Error occurred:'), + )); + + $template = 'error.tpl'; +} + +/** + * Detect if we are using mobile or not + * Check the 'ps_mobile_site' parameter. + */ +$ppec->context->smarty->assign('use_mobile', (bool)$ppec->useMobile()); + +$display->setTemplate(_PS_MODULE_DIR_.'paypal/views/templates/front/'.$template); +$display->run(); diff --git a/modules/paypal/express_checkout/process.php b/modules/paypal/express_checkout/process.php new file mode 100644 index 00000000..62bb369d --- /dev/null +++ b/modules/paypal/express_checkout/process.php @@ -0,0 +1,551 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +include_once(_PS_MODULE_DIR_.'paypal/paypal.php'); +include_once(_PS_MODULE_DIR_.'paypal/api/paypal_lib.php'); + +class PaypalExpressCheckout extends Paypal +{ + public $logs = array(); + + public $method_version = '106'; + + public $method; + + /** @var currency Currency used for the payment process **/ + public $currency; + + /** @var decimals Used to set prices precision **/ + public $decimals; + + /** @var result Contains the last request result **/ + public $result; + + /** @var token Contains the last token **/ + public $token; + + /* Depending of the type set, id_cart or id_product will be set */ + public $id_cart; + + // Depending of the type set, id_cart or id_product will be set + public $id_product; + + public $id_p_attr; + + public $quantity; + + public $payer_id; + + public $available_type = array('cart', 'product', 'payment_cart'); + + public $total_different_product; + + public $product_list = array(); + + /* Used to know if user can validated his payment after shipping / address selection */ + public $ready = false; + + /* Take for now cart or product value */ + public $type = false; + + static public $cookie_name = 'express_checkout'; + + public $cookie_key = array( + 'token', 'id_product', 'id_p_attr', + 'quantity', 'type', 'total_different_product', + 'secure_key', 'ready', 'payer_id' + ); + + public function __construct($type = false) + { + parent::__construct(); + + // If type is sent, the cookie has to be delete + if ($type) + { + unset($this->context->cookie->{self::$cookie_name}); + $this->setExpressCheckoutType($type); + } + + // Store back the PayPal data if present under the cookie + if (isset($this->context->cookie->{self::$cookie_name})) + { + $paypal = unserialize($this->context->cookie->{self::$cookie_name}); + + foreach ($this->cookie_key as $key) + $this->{$key} = $paypal[$key]; + } + + $this->currency = new Currency((int)$this->context->cart->id_currency); + + if (!Validate::isLoadedObject($this->currency)) + $this->_errors[] = $this->l('Not a valid currency'); + + if (count($this->_errors)) + return false; + + $currency_decimals = is_array($this->currency) ? (int)$this->currency['decimals'] : (int)$this->currency->decimals; + $this->decimals = $currency_decimals * _PS_PRICE_DISPLAY_PRECISION_; + } + + // Will build the product_list depending of the type + private function initParameters() + { + if (!$this->context->cart || !$this->context->cart->id) + return false; + + $cart_currency = new Currency((int)$this->context->cart->id_currency); + $currency_module = $this->getCurrency((int)$this->context->cart->id_currency); + + if ($cart_currency !== $currency_module) + { + $this->context->cart->id_currency = $currency_module->id; + $this->context->cart->update(); + } + + $this->context->currency = $currency_module; + $this->product_list = $this->context->cart->getProducts(true); + return (bool)count($this->product_list); + } + + public function setExpressCheckout($access_token = false) + { + $this->method = 'SetExpressCheckout'; + $fields = array(); + $this->setCancelUrl($fields); + + // Only this call need to get the value from the $_GET / $_POST array + if (!$this->initParameters(true) || !$fields['CANCELURL']) + return false; + + // Set payment detail (reference) + $this->_setPaymentDetails($fields); + $fields['SOLUTIONTYPE'] = 'Sole'; + $fields['LANDINGPAGE'] = 'Login'; + + // Seller informations + $fields['USER'] = Configuration::get('PAYPAL_API_USER'); + $fields['PWD'] = Configuration::get('PAYPAL_API_PASSWORD'); + $fields['SIGNATURE'] = Configuration::get('PAYPAL_API_SIGNATURE'); + + if ($access_token) + $fields['IDENTITYACCESSTOKEN'] = $access_token; + + if (Country::getIsoById(Configuration::get('PAYPAL_COUNTRY_DEFAULT')) == 'de') + $fields['BANKTXNPENDINGURL'] = 'payment.php?banktxnpendingurl=true'; + + $this->callAPI($fields); + $this->_storeToken(); + } + + public function setCancelUrl(&$fields) + { + $url = urldecode(Tools::getValue('current_shop_url')); + $parsed_data = parse_url($url); + + $parsed_data['scheme'] .= '://'; + + if (isset($parsed_data['path'])) + { + $parsed_data['path'] .= '?paypal_ec_canceled=1&'; + $parsed_data['query'] = isset($parsed_data['query']) ? $parsed_data['query'] : null; + } + else + { + $parsed_data['path'] = '?paypal_ec_canceled=1&'; + $parsed_data['query'] = '/'.(isset($parsed_data['query']) ? $parsed_data['query'] : null); + } + + $cancel_url = implode($parsed_data); + + if (!empty($cancel_url)) + $fields['CANCELURL'] = $cancel_url; + } + + public function getExpressCheckout() + { + $this->method = 'GetExpressCheckoutDetails'; + $fields = array(); + $fields['TOKEN'] = $this->token; + + $this->initParameters(); + $this->callAPI($fields); + + // The same token of SetExpressCheckout + $this->_storeToken(); + } + + public function doExpressCheckout() + { + $this->method = 'DoExpressCheckoutPayment'; + $fields = array(); + $fields['TOKEN'] = $this->token; + $fields['PAYERID'] = $this->payer_id; + + if (Configuration::get('PAYPAL_COUNTRY_DEFAULT') == 1) + $fields['BANKTXNPENDINGURL'] = ''; + + if (count($this->product_list) <= 0) + $this->initParameters(); + + // Set payment detail (reference) + $this->_setPaymentDetails($fields); + $this->callAPI($fields); + + $this->result += $fields; + } + + private function callAPI($fields) + { + $this->logs = array(); + $paypal_lib = new PaypalLib(); + + $this->result = $paypal_lib->makeCall($this->getAPIURL(), $this->getAPIScript(), $this->method, $fields, $this->method_version); + $this->logs = array_merge($this->logs, $paypal_lib->getLogs()); + + $this->_storeToken(); + } + + private function _setPaymentDetails(&$fields) + { + // Required field + $fields['RETURNURL'] = PayPal::getShopDomainSsl(true, true)._MODULE_DIR_.$this->name.'/express_checkout/payment.php'; + $fields['NOSHIPPING'] = '1'; + $fields['BUTTONSOURCE'] = $this->getTrackingCode((int)Configuration::get('PAYPAL_PAYMENT_METHOD')); + + // Products + $taxes = $total = 0; + $index = -1; + + // Set cart products list + $this->setProductsList($fields, $index, $total, $taxes); + $this->setDiscountsList($fields, $index, $total, $taxes); + $this->setGiftWrapping($fields, $index, $total); + + // Payment values + $this->setPaymentValues($fields, $index, $total, $taxes); + + $id_address = (int)$this->context->cart->id_address_delivery; + if (($id_address == 0) && ($this->context->customer)) + $id_address = Address::getFirstCustomerAddressId($this->context->customer->id); + + if ($id_address && method_exists($this->context->cart, 'isVirtualCart') && !$this->context->cart->isVirtualCart()) + $this->setShippingAddress($fields, $id_address); + else + $fields['NOSHIPPING'] = '0'; + + foreach ($fields as &$field) + if (is_numeric($field)) + $field = str_replace(',', '.', $field); + } + + private function setShippingAddress(&$fields, $id_address) + { + $address = new Address($id_address); + + $fields['ADDROVERRIDE'] = '1'; + $fields['EMAIL'] = $this->context->customer->email; + $fields['PAYMENTREQUEST_0_SHIPTONAME'] = $address->firstname.' '.$address->lastname; + $fields['PAYMENTREQUEST_0_SHIPTOPHONENUM'] = (empty($address->phone)) ? $address->phone_mobile : $address->phone; + $fields['PAYMENTREQUEST_0_SHIPTOSTREET'] = $address->address1; + $fields['PAYMENTREQUEST_0_SHIPTOSTREET2'] = $address->address2; + $fields['PAYMENTREQUEST_0_SHIPTOCITY'] = $address->city; + + if ($address->id_state) + { + $state = new State((int)$address->id_state); + $fields['PAYMENTREQUEST_0_SHIPTOSTATE'] = $state->iso_code; + } + + $country = new Country((int)$address->id_country); + $fields['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE'] = $country->iso_code; + $fields['PAYMENTREQUEST_0_SHIPTOZIP'] = $address->postcode; + } + + private function setProductsList(&$fields, &$index, &$total) + { + foreach ($this->product_list as $product) + { + $fields['L_PAYMENTREQUEST_0_NUMBER'.++$index] = (int)$product['id_product']; + + $fields['L_PAYMENTREQUEST_0_NAME'.$index] = $product['name']; + + if (isset($product['attributes']) && (empty($product['attributes']) === false)) + $fields['L_PAYMENTREQUEST_0_NAME'.$index] .= ' - '.$product['attributes']; + + $fields['L_PAYMENTREQUEST_0_DESC'.$index] = Tools::substr(strip_tags($product['description_short']), 0, 50).'...'; + + $fields['L_PAYMENTREQUEST_0_AMT'.$index] = Tools::ps_round($product['price_wt'], $this->decimals); + $fields['L_PAYMENTREQUEST_0_QTY'.$index] = $product['quantity']; + + $total = $total + ($fields['L_PAYMENTREQUEST_0_AMT'.$index] * $product['quantity']); + } + } + + private function setDiscountsList(&$fields, &$index, &$total) + { + $discounts = (_PS_VERSION_ < '1.5') ? $this->context->cart->getDiscounts() : $this->context->cart->getCartRules(); + + if (count($discounts) > 0) + foreach ($discounts as $discount) + { + $fields['L_PAYMENTREQUEST_0_NUMBER'.++$index] = $discount['id_discount']; + + $fields['L_PAYMENTREQUEST_0_NAME'.$index] = $discount['name']; + if (isset($discount['description']) && !empty($discount['description'])) + $fields['L_PAYMENTREQUEST_0_DESC'.$index] = Tools::substr(strip_tags($discount['description']), 0, 50).'...'; + + /* It is a discount so we store a negative value */ + $fields['L_PAYMENTREQUEST_0_AMT'.$index] = - 1 * Tools::ps_round($discount['value_real'], $this->decimals); + $fields['L_PAYMENTREQUEST_0_QTY'.$index] = 1; + + $total = Tools::ps_round($total + $fields['L_PAYMENTREQUEST_0_AMT'.$index], $this->decimals); + } + } + + private function setGiftWrapping(&$fields, &$index, &$total) + { + if ($this->context->cart->gift == 1) + { + $gift_wrapping_price = $this->getGiftWrappingPrice(); + + $fields['L_PAYMENTREQUEST_0_NAME'.++$index] = $this->l('Gift wrapping'); + + $fields['L_PAYMENTREQUEST_0_AMT'.$index] = Tools::ps_round($gift_wrapping_price, $this->decimals); + $fields['L_PAYMENTREQUEST_0_QTY'.$index] = 1; + + $total = Tools::ps_round($total + $gift_wrapping_price, $this->decimals); + } + } + + private function setPaymentValues(&$fields, &$index, &$total, &$taxes) + { + if (version_compare(_PS_VERSION_, '1.5', '<')) + $shipping_cost_wt = $this->context->cart->getOrderShippingCost(); + else + $shipping_cost_wt = $this->context->cart->getTotalShippingCost(); + + if ((bool)Configuration::get('PAYPAL_CAPTURE')) + $fields['PAYMENTREQUEST_0_PAYMENTACTION'] = 'Authorization'; + else + $fields['PAYMENTREQUEST_0_PAYMENTACTION'] = 'Sale'; + + $currency = new Currency((int)$this->context->cart->id_currency); + $fields['PAYMENTREQUEST_0_CURRENCYCODE'] = $currency->iso_code; + + /** + * If the total amount is lower than 1 we put the shipping cost as an item + * so the payment could be valid. + */ + if ($total <= 1) + { + $carrier = new Carrier($this->context->cart->id_carrier); + $fields['L_PAYMENTREQUEST_0_NUMBER'.++$index] = $carrier->id_reference; + $fields['L_PAYMENTREQUEST_0_NAME'.$index] = $carrier->name; + $fields['L_PAYMENTREQUEST_0_AMT'.$index] = Tools::ps_round($shipping_cost_wt, $this->decimals); + $fields['L_PAYMENTREQUEST_0_QTY'.$index] = 1; + + $fields['PAYMENTREQUEST_0_ITEMAMT'] = Tools::ps_round($total, $this->decimals) + Tools::ps_round($shipping_cost_wt, $this->decimals); + $fields['PAYMENTREQUEST_0_AMT'] = $total + Tools::ps_round($shipping_cost_wt, $this->decimals); + } + else + { + if ($currency->iso_code == 'HUF') + { + $fields['PAYMENTREQUEST_0_SHIPPINGAMT'] = round($shipping_cost_wt); + $fields['PAYMENTREQUEST_0_ITEMAMT'] = Tools::ps_round($total, $this->decimals); + $fields['PAYMENTREQUEST_0_AMT'] = sprintf('%.2f', ($total + $fields['PAYMENTREQUEST_0_SHIPPINGAMT'])); + } + else + { + $fields['PAYMENTREQUEST_0_SHIPPINGAMT'] = sprintf('%.2f', $shipping_cost_wt); + $fields['PAYMENTREQUEST_0_ITEMAMT'] = Tools::ps_round($total, $this->decimals); + $fields['PAYMENTREQUEST_0_AMT'] = sprintf('%.2f', ($total + $fields['PAYMENTREQUEST_0_SHIPPINGAMT'])); + } + } + } + + public function rightPaymentProcess() + { + $total = $this->getTotalPaid(); + + // float problem with php, have to use the string cast. + if ((isset($this->result['AMT']) && ((string)$this->result['AMT'] != (string)$total)) || + (isset($this->result['PAYMENTINFO_0_AMT']) && ((string)$this->result['PAYMENTINFO_0_AMT'] != (string)$total))) + return false; + return true; + } + + /** + * @return mixed + */ + public function getTotalPaid() + { + $total = 0.00; + + foreach ($this->product_list as $product) + { + $price = Tools::ps_round($product['price_wt'], $this->decimals); + $quantity = Tools::ps_round($product['quantity'], $this->decimals); + $total = Tools::ps_round($total + ($price * $quantity), $this->decimals); + } + + if ($this->context->cart->gift == 1) + $total = Tools::ps_round($total + $this->getGiftWrappingPrice(), $this->decimals); + + if (version_compare(_PS_VERSION_, '1.5', '<')) + { + $discounts = $this->context->cart->getDiscounts(); + $shipping_cost = $this->context->cart->getOrderShippingCost(); + } + else + { + $discounts = $this->context->cart->getCartRules(); + $shipping_cost = $this->context->cart->getTotalShippingCost(); + } + + if (count($discounts) > 0) + foreach ($discounts as $product) + { + $price = - 1 * Tools::ps_round($product['value_real'], $this->decimals); + $total = Tools::ps_round($total + $price, $this->decimals); + } + + return Tools::ps_round($shipping_cost, $this->decimals) + $total; + } + + private function _storeToken() + { + if (is_array($this->result) && isset($this->result['TOKEN'])) + $this->token = (string)$this->result['TOKEN']; + } + + // Store data for the next reloading page + private function _storeCookieInfo() + { + $tab = array(); + + foreach ($this->cookie_key as $key) + $tab[$key] = $this->{$key}; + + $this->context->cookie->{self::$cookie_name} = serialize($tab); + } + + public function displayPaypalInContextCheckout() + { + $this->secure_key = $this->getSecureKey(); + $this->_storeCookieInfo(); + echo $this->token; + die; + } + + public function hasSucceedRequest() + { + if (is_array($this->result)) + foreach (array('ACK', 'PAYMENTINFO_0_ACK') as $key) + if (isset($this->result[$key]) && Tools::strtoupper($this->result[$key]) == 'SUCCESS') + return true; + + return false; + } + + private function getSecureKey() + { + if (!count($this->product_list)) + $this->initParameters(); + + $key = array(); + + foreach ($this->product_list as $product) + { + $id_product = $product['id_product']; + $id_product_attribute = $product['id_product_attribute']; + $quantity = $product['quantity']; + + $key[] = $id_product.$id_product_attribute.$quantity._COOKIE_KEY_; + } + + return md5(serialize($key)); + } + + public function isProductsListStillRight() + { + return $this->secure_key == $this->getSecureKey(); + } + + public function setExpressCheckoutType($type) + { + if (in_array($type, $this->available_type)) + { + $this->type = $type; + return true; + } + return false; + } + + public function redirectToAPI() + { + $this->secure_key = $this->getSecureKey(); + $this->_storeCookieInfo(); + + if ($this->useMobile()) + $url = '/cgi-bin/webscr?cmd=_express-checkout-mobile'; + else + $url = '/websc&cmd=_express-checkout'; + + if (($this->method == 'SetExpressCheckout') && (Configuration::get('PAYPAL_COUNTRY_DEFAULT') == 1) && ($this->type == 'payment_cart')) + $url .= '&useraction=commit'; + + Tools::redirectLink('https://'.$this->getPayPalURL().$url.'&token='.urldecode($this->token)); + exit(0); + } + + public function redirectToCheckout($customer, $redirect = false) + { + $this->ready = true; + $this->_storeCookieInfo(); + + $this->context->cookie->id_customer = (int)$customer->id; + $this->context->cookie->customer_lastname = $customer->lastname; + $this->context->cookie->customer_firstname = $customer->firstname; + $this->context->cookie->passwd = $customer->passwd; + $this->context->cookie->email = $customer->email; + $this->context->cookie->is_guest = $customer->isGuest(); + $this->context->cookie->logged = 1; + + if (version_compare(_PS_VERSION_, '1.5', '<')) + Module::hookExec('authentication'); + else + Hook::exec('authentication'); + + if ($redirect) + { + $link = $this->context->link->getPageLink('order.php', false, null, array('step' => '3')); + Tools::redirectLink($link); + exit(0); + } + } +} diff --git a/modules/paypal/express_checkout/submit.php b/modules/paypal/express_checkout/submit.php new file mode 100644 index 00000000..316a13dc --- /dev/null +++ b/modules/paypal/express_checkout/submit.php @@ -0,0 +1,101 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +include_once(dirname(__FILE__).'/../../../config/config.inc.php'); +include_once(dirname(__FILE__).'/../../../init.php'); + +if (version_compare(_PS_VERSION_, '1.5', '<')) + require_once(_PS_ROOT_DIR_.'/controllers/OrderConfirmationController.php'); + +/** + * 1.4 Retro-compatibility class + */ +class PayPalExpressCheckoutSubmit extends OrderConfirmationControllerCore +{ + public function __construct() + { + $this->paypal = new PayPal(); + $this->context = $this->paypal->context; + + parent::__construct(); + + $this->run(); + } + + public function displayContent() + { + $id_order = (int)Tools::getValue('id_order'); + + $order = new Order($id_order); + $paypal_order = PayPalOrder::getOrderById($id_order); + + $price = Tools::displayPrice($paypal_order['total_paid'], $this->context->currency); + + $order_state = new OrderState($id_order); + + if ($order_state) + $order_state_message = $order_state->template[$this->context->language->id]; + + if (!$order || !$order_state || (isset($order_state_message) && ($order_state_message == 'payment_error'))) + { + $this->context->smarty->assign( + array( + 'logs' => array($this->paypal->l('An error occurred while processing payment.')), + 'order' => $paypal_order, + 'price' => $price, + ) + ); + + if (isset($order_state_message) && $order_state_message) + $this->context->smarty->assign('message', $order_state_message); + + $template = 'error.tpl'; + } + else + { + $this->context->smarty->assign( + array( + 'order' => $paypal_order, + 'price' => $price, + ) + ); + + if (version_compare(_PS_VERSION_, '1.5', '>')) + { + + $this->context->smarty->assign(array( + 'reference_order' => Order::getUniqReferenceOf($paypal_order['id_order']) + )); + } + + + $template = 'order-confirmation.tpl'; + } + + $this->context->smarty->assign('use_mobile', (bool)$this->paypal->useMobile()); + echo $this->paypal->fetchTemplate($template); + } +} diff --git a/modules/paypal/fr.php b/modules/paypal/fr.php new file mode 100644 index 00000000..735551b9 --- /dev/null +++ b/modules/paypal/fr.php @@ -0,0 +1,126 @@ +paypal_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>paypal_6e7012516038a096b9f6bb71ba2cc5a3'] = 'Acceptez le paiements par cartes de crédits (CB, Visa, MasterCard, Amex, Aurore, Cofinoga, 4 stars) avec PayPal.'; +$_MODULE['<{paypal}prestashop>paypal_69a1a3ad8dd5da6db3c4da838a0cf9c7'] = 'Êtes-vous certain de vouloir supprimer vos informations ?'; +$_MODULE['<{paypal}prestashop>paypal_8b57f95f1e9cf09dc028fa5a671781ff'] = 'Toutes les fonctionnalités du module PayPal API sont incluses dans le nouveau module PayPal. Avant tout, pour ne pas rencontrer de conflits, veuillez ne pas utiliser ou supprimer le module PayPal API.'; +$_MODULE['<{paypal}prestashop>paypal_c91f1fb5e06286c3e0a33fc552dffbea'] = 'Vous devez renseigner vos identifiants PayPal Integral pour que votre thème mobile fonctionne correctement.'; +$_MODULE['<{paypal}prestashop>paypal_bd6b3cca1e559117a964cdfab6a977cf'] = 'Le thème mobile fonctionne seulement avec la solution de paiement mobile PayPal. Veuillez activer le module pour bénéficier de possibilités de paiements.'; +$_MODULE['<{paypal}prestashop>paypal_c9d8a8d3c76c69e9a5ba6387acb8655a'] = 'Avant d\'utiliser le module vous devez installer le module \"Rétro-compatibilité\".'; +$_MODULE['<{paypal}prestashop>paypal_ea5eb3f904bf42377277255cbd0e2251'] = 'Pour fonctionner correctement le module \"Rétro-compatibilité\" doit être activé.'; +$_MODULE['<{paypal}prestashop>paypal_48878e69ef59b9e9d2d9a8c18e4de520'] = 'Pour fonctionner correctement ce module requiert le module \"Rétro-compatibilité\" v'; +$_MODULE['<{paypal}prestashop>paypal_20fda49ece75d93bea97648ab1f1f1cf'] = 'Annulation des produits :'; +$_MODULE['<{paypal}prestashop>paypal_90ab0cfd410722553c79e614207a789a'] = 'Certains champs sont vides.'; +$_MODULE['<{paypal}prestashop>paypal_ce0e2b401002ca796d2e8aca7deb8f00'] = 'Les champs des identifiants ne peuvent être vides'; +$_MODULE['<{paypal}prestashop>paypal_3f7145179c909f0e87a911a3171986b6'] = 'Le champs E-mail professionnel ne peut être vide'; +$_MODULE['<{paypal}prestashop>paypal_e5d5d9f40763cfe6549bef705e3529a7'] = 'Le message de paiement n\'est pas valide, veuillez vérifier votre module'; +$_MODULE['<{paypal}prestashop>paypal_ee9dc1e678d54c517f481583c3fb2db8'] = 'Devise invalide'; +$_MODULE['<{paypal}prestashop>paypal_eec39bf42bd135971fb2d838c67d1449'] = 'Opération de remboursement :'; +$_MODULE['<{paypal}prestashop>paypal_2ab62d1a578713d0862b56819295630e'] = 'Remboursement PayPal confirmé !'; +$_MODULE['<{paypal}prestashop>paypal_a64db959966ba8d07c8b5d9493fcc21f'] = 'Erreur de transaction !'; +$_MODULE['<{paypal}prestashop>paypal_67962779da962e3d4225055afc05e7bd'] = 'Résultat de la capture :'; +$_MODULE['<{paypal}prestashop>paypal_8778ee03f6592d5fec9a1f2ee851e476'] = 'Commande terminée avec PayPal !'; +$_MODULE['<{paypal}prestashop>paypal_672d40feac6437e49f771019bc330790'] = 'Statu de la vérification :'; +$_MODULE['<{paypal}prestashop>paypal_1828820cc60e36b6f9fdf60cab103ed7'] = 'Vous utilisez actuellement l\'adresse PayPal par défaut, veuillez entrer votre propre adresse.'; +$_MODULE['<{paypal}prestashop>paypal_connect_d1f14cc4a2dade80c92421d26422fea0'] = 'Ouvre une nouvelle connection vers'; +$_MODULE['<{paypal}prestashop>paypal_connect_94a27811a721ef512ad7bfa06cab34e0'] = 'Echec de la connection avec la méthode cURL'; +$_MODULE['<{paypal}prestashop>paypal_connect_70215486455daee13382c68b1a230b82'] = 'Connection réussie avec la méthode cURL'; +$_MODULE['<{paypal}prestashop>paypal_connect_e4c4ad49bced42265b5facc2175cdafd'] = 'Envoie des paramètres :'; +$_MODULE['<{paypal}prestashop>paypal_connect_445583f6641da98fc7ac8fd9d13a564b'] = 'Echec de l\'envoie avec la méthode cURL ! Erreur :'; +$_MODULE['<{paypal}prestashop>paypal_connect_ef4fbf36eaa2083442d386990ba063c2'] = 'Envoie réussi avec la méthode cURL'; +$_MODULE['<{paypal}prestashop>paypal_connect_bf059c9751bb1a20b449b7917b1df374'] = 'Echec de la connection avec la méthode fsockopen'; +$_MODULE['<{paypal}prestashop>paypal_connect_6e9aa4cb541e09b07602d4ea96080811'] = 'Echec de l\'envoie avec la méthode fsockopen ! Erreur :'; +$_MODULE['<{paypal}prestashop>paypal_connect_842a183be225d415b2b4375ba1dd1c94'] = 'Envoie réussi avec la méthode fsockopen'; +$_MODULE['<{paypal}prestashop>paypal_lib_7c2d00d8c94d1ce0f515db8b0481db40'] = 'Réponse PayPal :'; +$_MODULE['<{paypal}prestashop>submit_67a3fcdb7708219b9d5d6269ad8c4a86'] = 'Une erreur est survenue pendant le processus de paiement.'; +$_MODULE['<{paypal}prestashop>payment_d141a42a5e72c871a3116414bb5c64c1'] = 'Création du nouveau panier impossible'; +$_MODULE['<{paypal}prestashop>payment_5b5adcef5e3f2e5e1b6f60eb3e7e41ed'] = 'Une erreur est survenue :'; +$_MODULE['<{paypal}prestashop>payment_dca16503c563d9fdec70d18f2ab653a4'] = 'Erreur lors de la préparation du paiement par Express Checkout'; +$_MODULE['<{paypal}prestashop>payment_51da74120dd5e11817ef21e27d2599bc'] = 'Impossible de créer un nouvel utilisateur'; +$_MODULE['<{paypal}prestashop>payment_bcf08b34ab427cb871635151c6976eb0'] = 'Impossible de créer la nouvelle adresse'; +$_MODULE['<{paypal}prestashop>payment_ca5cecfc8fd8e585ba1e684757168158'] = 'Impossible de mettre à jour le panier'; +$_MODULE['<{paypal}prestashop>payment_ada2b5d5bbf3065de283d61526141780'] = 'En attente de capture du paiement.'; +$_MODULE['<{paypal}prestashop>payment_36ec50c0e914dd2fb48a1b27540512ce'] = 'Paiement accepté.'; +$_MODULE['<{paypal}prestashop>payment_8a34d4a5b0c3928059f6f92ead9e8aa6'] = 'Le prix payé sur PayPal est différent du prix renseigné sur la boutique.'; +$_MODULE['<{paypal}prestashop>payment_98825385aadb1d0dd0fd133ef8acd23d'] = 'Impossible de créer la commande'; +$_MODULE['<{paypal}prestashop>payment_085b78e060c3ef4cc37bd25abd06ff66'] = 'Le panier a changé depuis la dernière tentative de paiement. Veuillez recommencer le processus de paiement s\'il vous plait.'; +$_MODULE['<{paypal}prestashop>payment_572da7ef1411f2a12409e752f3eb2f7a'] = 'Votre panier et vide.'; +$_MODULE['<{paypal}prestashop>process_ee9dc1e678d54c517f481583c3fb2db8'] = 'Devise invalide.'; +$_MODULE['<{paypal}prestashop>process_484f5a79672cebe198ebdde45a1d672f'] = 'Emballage cadeau.'; +$_MODULE['<{paypal}prestashop>notifier_8a34d4a5b0c3928059f6f92ead9e8aa6'] = 'Le prix payé sur PayPal est différent du prix renseigné sur la boutique.'; +$_MODULE['<{paypal}prestashop>notifier_572f9af7615560af2cba038cc1948287'] = 'Panier mis à jour, merci de ré-essayer.'; +$_MODULE['<{paypal}prestashop>notifier_36ec50c0e914dd2fb48a1b27540512ce'] = 'Paiement accepté.'; +$_MODULE['<{paypal}prestashop>back_office_ae3cebe661e92cdfd12516419fef4f2d'] = 'Télécharger le'; +$_MODULE['<{paypal}prestashop>back_office_e73756d0d2306110f29ccf28cb69c412'] = 'Guide d\'intégration de PayPal'; +$_MODULE['<{paypal}prestashop>back_office_6506302a6e11077ecbc04b5932a65c4c'] = 'sur PrestaShop et suivez les étapes pas à pas'; +$_MODULE['<{paypal}prestashop>back_office_748eadce9cf4f2bde207b63c5441da07'] = 'Utilisez la Fonction PayPal Login'; +$_MODULE['<{paypal}prestashop>back_office_cded4ac9f77c68c750c243af1f5263c5'] = ' (*voir le '; +$_MODULE['<{paypal}prestashop>back_office_606d8f704cf61d29bffd5195f28af29e'] = 'Guide d\'Intégration'; +$_MODULE['<{paypal}prestashop>back_office_a1694ad810c4ac5b56b59c47db01cb05'] = 'et suivre les étapes de mise en place'; +$_MODULE['<{paypal}prestashop>back_office_3650f874df7e9c6e822a872d02cee6d5'] = 'Cette fonction permet à vos clients de se connecter avec leurs identifiants PayPal pour raccourcir le tunnel d\'achat'; +$_MODULE['<{paypal}prestashop>back_office_93cba07454f06a4a960172bbd6e2a435'] = 'Oui'; +$_MODULE['<{paypal}prestashop>back_office_bafd7322c6e97d25b6299b5d6fe8920b'] = 'Non'; +$_MODULE['<{paypal}prestashop>back_office_9be4e88898c4e88363208d2472f4a406'] = 'Renseignez les informations liées à votre compte PayPal'; +$_MODULE['<{paypal}prestashop>back_office_4ff2e716a7d06ce5274b4090b39abad3'] = 'Voir'; +$_MODULE['<{paypal}prestashop>back_office_8646a5d7b2817d30950357da8d80a11f'] = 'le Guide d\'Intégration'; +$_MODULE['<{paypal}prestashop>back_office_2d801c24938b12e4ca9a2cf9b980c759'] = 'Erreur !'; +$_MODULE['<{paypal}prestashop>capture_81e826adb70e2e6b189c2eef739d52d4'] = 'Capture PayPal'; +$_MODULE['<{paypal}prestashop>capture_e8fdd4382b75b42bfbd96eb7b032cf47'] = 'Informations :'; +$_MODULE['<{paypal}prestashop>capture_ce64b2ea82cf4fa861a6512e2c32b84b'] = 'Les fonds sont prêts à être capturés avant expédition'; +$_MODULE['<{paypal}prestashop>capture_99e64593868df2b7b32231c1ae5ddc04'] = 'Récupérer les fonds'; +$_MODULE['<{paypal}prestashop>refund_8ba079f305b81b172792bc0469b6a690'] = 'Remboursement PayPal'; +$_MODULE['<{paypal}prestashop>refund_e8fdd4382b75b42bfbd96eb7b032cf47'] = 'Informations :'; +$_MODULE['<{paypal}prestashop>refund_016e1f278eccd700eaf33f74a501d050'] = 'Paiement accepté'; +$_MODULE['<{paypal}prestashop>refund_a8b1cc445942a2e1a7d7cca641c86d67'] = 'Lorsque vous remboursez un produit, un remboursement partiel est effectué sauf si vous sélectionnez l\'option \"Générer un bon de réduction\"'; +$_MODULE['<{paypal}prestashop>refund_729a51874fe901b092899e9e8b31c97a'] = 'Etes-vous sûr ?'; +$_MODULE['<{paypal}prestashop>refund_c2a5e2e23d8ec9cad779d657b7d33fc1'] = 'Remboursement total de la transaction'; +$_MODULE['<{paypal}prestashop>validation_b630aa9b5e25da971949cae62dd109aa'] = 'Validation PayPal'; +$_MODULE['<{paypal}prestashop>validation_e8fdd4382b75b42bfbd96eb7b032cf47'] = 'Informations :'; +$_MODULE['<{paypal}prestashop>validation_9119a92adbbf6c67bfb8a3aee0bdb720'] = 'Capture en attente - Pas d\'expédition'; +$_MODULE['<{paypal}prestashop>validation_c14eb95a724174f336b8ffdd98ef2f35'] = 'Paiement en attente - Pas d\'expédition'; +$_MODULE['<{paypal}prestashop>validation_5b18ff32c2aaaf4b79bdead10b10fe29'] = 'Vérifier l\'état du paiement'; +$_MODULE['<{paypal}prestashop>about_e816e21c1c8e0eba0620fa3df6bd6795'] = 'Qu\'est-ce que PayPal ?'; +$_MODULE['<{paypal}prestashop>about_16ea57badae98f402bb8f2b2f49d4e77'] = 'PayPal, leader incontesté en matière de paiement en ligne, permet aux acheteurs et aux vendeurs d\'envoyer et de recevoir des paiements en ligne. PayPal compte plus de 100 millions de comptes dans 190 pays et régions du monde. Il est accepté par les marchands partout, à la fois sur eBay et en dehors d\'eBay.'; +$_MODULE['<{paypal}prestashop>about_d20adade7baa1b60b713521031ea676c'] = 'Est-ce un service sécurisé ?'; +$_MODULE['<{paypal}prestashop>about_64f7b897c6d56fc62428f692ee5737cd'] = 'PayPal contribue à protéger les informations concernant votre carte bancaire grâce aux meilleurs systèmes présents sur le marché pour la sécurité et la prévention contre la fraude. Lorsque vous utilisez PayPal, vos informations financières ne sont jamais communiquées au marchand.'; +$_MODULE['<{paypal}prestashop>about_5ef30813484389e4200640c2f006004d'] = 'Pourquoi utiliser PayPal ?'; +$_MODULE['<{paypal}prestashop>about_86550d4ea832930db4366f03b90bdfb8'] = 'Effectuez des achats ou envoyez des paiements avec PayPal : c\'est gratuit.'; +$_MODULE['<{paypal}prestashop>about_7dc9e529337e5a55a12bf362b8e68cac'] = 'Achetez et payez en toute tranquillité en enregistrant vos informations auprès de PayPal.'; +$_MODULE['<{paypal}prestashop>about_32098ae6a7ecd96805df9e48fb6cc739'] = 'PayPal est accepté par des millions de marchands dans le monde et constitue le mode de paiement le plus utilisé sur eBay.'; +$_MODULE['<{paypal}prestashop>about_7934d7d1280bfbb8778743e39292af30'] = 'Utilisez PayPal dès aujourd\'hui !'; +$_MODULE['<{paypal}prestashop>error_a40cab5994f36d4c48103a22ca082e8f'] = 'Votre panier'; +$_MODULE['<{paypal}prestashop>error_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>error_f47106270a2928f350f357e255a2c2ac'] = 'Veuillez contacter le marchant:'; +$_MODULE['<{paypal}prestashop>error_d5860edcd3078f86ee963c27654bc6cf'] = 'Montant total de la transaction (taxes incl) :'; +$_MODULE['<{paypal}prestashop>error_a378cd7a0839cbd4ec3e45bbdeeb69be'] = 'L\'ID de votre commande est :'; +$_MODULE['<{paypal}prestashop>error_0557fa923dcee4d0f86b1409f5c2167f'] = 'Précédent'; +$_MODULE['<{paypal}prestashop>order-confirmation_fb077ecba55e5552916bde26d8b9e794'] = 'Confirmation de commande'; +$_MODULE['<{paypal}prestashop>order-confirmation_d5860edcd3078f86ee963c27654bc6cf'] = 'Total de la transaction (TTC) :'; +$_MODULE['<{paypal}prestashop>order-confirmation_a378cd7a0839cbd4ec3e45bbdeeb69be'] = 'Votre numéro de commande est le :'; +$_MODULE['<{paypal}prestashop>order-confirmation_6e860dc1cf94ca08b3fd99993aa2dc68'] = 'Votre numéro de transaction PayPal est :'; +$_MODULE['<{paypal}prestashop>order-confirmation_4082ea29b4f196c4f60533500139725a'] = 'Suivre ma commande'; +$_MODULE['<{paypal}prestashop>order-confirmation_9390390581f54c65d6acfc8da4e17362'] = 'Retour aux commandes'; +$_MODULE['<{paypal}prestashop>order-summary_a40cab5994f36d4c48103a22ca082e8f'] = 'Votre panier'; +$_MODULE['<{paypal}prestashop>order-summary_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>order-summary_f1d3b424cd68795ecaa552883759aceb'] = 'Résumé de la commande'; +$_MODULE['<{paypal}prestashop>order-summary_dd23adc5fb6bda9c384397b31e57fc53'] = 'Paiement par PayPal'; +$_MODULE['<{paypal}prestashop>order-summary_62d74398cb6ebaa69ab7339052ca5c92'] = 'Vous avez choisi de payer par PayPal'; +$_MODULE['<{paypal}prestashop>order-summary_c884ed19483d45970c5bf23a681e2dd2'] = 'Voici un résumé de votre commande'; +$_MODULE['<{paypal}prestashop>order-summary_0c458988127eb2150776881e2ef3f0c4'] = 'Adresse de livraison'; +$_MODULE['<{paypal}prestashop>order-summary_e2867a925cba382f1436d1834bb52a1c'] = 'Le montant total de votre commande est'; +$_MODULE['<{paypal}prestashop>order-summary_1f87346a16cf80c372065de3c54c86d9'] = '(tax incl.)'; +$_MODULE['<{paypal}prestashop>order-summary_8ed356c32b198c9cb2abab7c3d262b93'] = 'Nous acceptons les devises suivantes avec PayPal :'; +$_MODULE['<{paypal}prestashop>order-summary_0881a11f7af33bc1b43e437391129d66'] = 'Veuillez confirmer votre commande en cliquant sur \"Je confirme ma commande\"'; +$_MODULE['<{paypal}prestashop>order-summary_46b9e3665f187c739c55983f757ccda0'] = 'Je confirme ma commande'; +$_MODULE['<{paypal}prestashop>column_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Payer par PayPal'; +$_MODULE['<{paypal}prestashop>confirmation_2e2117b7c81aa9ea6931641ea2c6499f'] = 'Votre commande sur'; +$_MODULE['<{paypal}prestashop>confirmation_75fbf512d744977d62599cc3f0ae2bb4'] = 'est bien enregistrée.'; +$_MODULE['<{paypal}prestashop>confirmation_15b0f8e55c6bdfc3d5fd0b6b3b6cb3ee'] = 'Vous avez choisi de payer avec PayPal.'; +$_MODULE['<{paypal}prestashop>confirmation_e6dc7945b557a1cd949bea92dd58963e'] = 'Votre commande vous sera envoyée très prochainement.'; +$_MODULE['<{paypal}prestashop>confirmation_0db71da7150c27142eef9d22b843b4a9'] = 'Pour toute question ou information complémentaire merci de contacter notre'; +$_MODULE['<{paypal}prestashop>confirmation_64430ad2835be8ad60c59e7d44e4b0b1'] = 'support client'; +$_MODULE['<{paypal}prestashop>express_checkout_payment_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Payez avec PayPal'; +$_MODULE['<{paypal}prestashop>express_checkout_shortcut_form_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Payez avec PayPal'; +$_MODULE['<{paypal}prestashop>integral_evolution_payment_ecab922bc1f9b5726e2a6deb4acaec4e'] = 'Retour au site du marchant.'; diff --git a/modules/paypal/index.php b/modules/paypal/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/integral_evolution/confirm.php b/modules/paypal/integral_evolution/confirm.php new file mode 100644 index 00000000..74e9296f --- /dev/null +++ b/modules/paypal/integral_evolution/confirm.php @@ -0,0 +1,41 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +include_once(dirname(__FILE__).'/../../../config/config.inc.php'); +include_once(dirname(__FILE__).'/../../../init.php'); + +if ($id_cart = Tools::getValue('id_cart')) +{ + $id_order = Db::getInstance()->getValue(' + SELECT id_order + FROM `'._DB_PREFIX_.'paypal_order` + WHERE `id_order` = '.(int)Order::getOrderByCartId((int)$id_cart)); + + if ($id_order !== false) + echo (int)$id_order; +} + +die(); diff --git a/modules/paypal/integral_evolution/index.php b/modules/paypal/integral_evolution/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/integral_evolution/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/integral_evolution/notifier.php b/modules/paypal/integral_evolution/notifier.php new file mode 100644 index 00000000..94940be1 --- /dev/null +++ b/modules/paypal/integral_evolution/notifier.php @@ -0,0 +1,120 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +include_once(dirname(__FILE__).'/../../../config/config.inc.php'); +include_once(_PS_MODULE_DIR_.'paypal/paypal.php'); + +/* + * Instant payment notification class. + * (wait for PayPal payment confirmation, then validate order) + */ +class PayPalNotifier extends PayPal +{ + public function confirmOrder($custom) + { + $cart = new Cart((int)$custom['id_cart']); + + $cart_details = $cart->getSummaryDetails(null, true); + $cart_hash = sha1(serialize($cart->nbProducts())); + + $this->context->cart = $cart; + $address = new Address((int)$cart->id_address_invoice); + $this->context->country = new Country((int)$address->id_country); + $this->context->customer = new Customer((int)$cart->id_customer); + $this->context->language = new Language((int)$cart->id_lang); + $this->context->currency = new Currency((int)$cart->id_currency); + + if (isset($cart->id_shop)) + $this->context->shop = new Shop($cart->id_shop); + + $result = $this->getResult(); + + if (strcmp(trim($result), "VERIFIED") == 0) + { + $currency_decimals = is_array($this->context->currency) ? (int)$this->context->currency['decimals'] : (int)$this->context->currency->decimals; + $this->decimals = $currency_decimals * _PS_PRICE_DISPLAY_PRECISION_; + + $message = null; + $mc_gross = Tools::ps_round(Tools::getValue('mc_gross'), $this->decimals); + + $cart_details = $cart->getSummaryDetails(null, true); + + $shipping = $cart_details['total_shipping_tax_exc']; + $subtotal = $cart_details['total_price_without_tax'] - $cart_details['total_shipping_tax_exc']; + $tax = $cart_details['total_tax']; + + $total_price = Tools::ps_round($shipping + $subtotal + $tax, $this->decimals); + + if ($this->comp($mc_gross, $total_price, 2) !== 0) + { + $payment = (int)Configuration::get('PS_OS_ERROR'); + $message = $this->l('Price paid on paypal is not the same that on PrestaShop.').'
    '; + } + elseif ($custom['hash'] != $cart_hash) + { + $payment = (int)Configuration::get('PS_OS_ERROR'); + $message = $this->l('Cart changed, please retry.').'
    '; + } + else + { + $payment = (int)Configuration::get('PS_OS_PAYMENT'); + $message = $this->l('Payment accepted.').'
    '; + } + + $customer = new Customer((int)$cart->id_customer); + $transaction = PayPalOrder::getTransactionDetails(false); + + if (_PS_VERSION_ < '1.5') + $shop = null; + else + { + $shop_id = $this->context->shop->id; + $shop = new Shop($shop_id); + } + + $this->validateOrder($cart->id, $payment, $total_price, $this->displayName, $message, $transaction, $cart->id_currency, false, $customer->secure_key, $shop); + } + } + + public function getResult() + { + if ((int)Configuration::get('PAYPAL_SANDBOX') == 1) + $action_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_notify-validate'; + else + $action_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_notify-validate'; + + $request = '&'.http_build_query($_POST, '&'); + return Tools::file_get_contents($action_url.$request); + } + +} + +if ($custom = Tools::getValue('custom')) +{ + $notifier = new PayPalNotifier(); + $result = Tools::jsonDecode($custom, true); + $notifier->confirmOrder($result); +} diff --git a/modules/paypal/integral_evolution/submit.php b/modules/paypal/integral_evolution/submit.php new file mode 100644 index 00000000..9a55974b --- /dev/null +++ b/modules/paypal/integral_evolution/submit.php @@ -0,0 +1,107 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +include_once(dirname(__FILE__).'/../../../config/config.inc.php'); +include_once(dirname(__FILE__).'/../../../init.php'); + +if (version_compare(_PS_VERSION_, '1.5', '<')) + require_once(_PS_ROOT_DIR_.'/controllers/OrderConfirmationController.php'); + +class PayPalIntegralEvolutionSubmit extends OrderConfirmationControllerCore +{ + public $context; + + public function __construct() + { + /** Backward compatibility */ + include_once(_PS_MODULE_DIR_.'paypal/backward_compatibility/backward.php'); + $this->context = Context::getContext(); + parent::__construct(); + } + + /* + * Display PayPal order confirmation page + */ + public function displayContent() + { + $id_order = (int)Tools::getValue('id_order'); + $order = PayPalOrder::getOrderById($id_order); + $price = Tools::displayPrice($order['total_paid'], $this->context->currency); + + $this->context->smarty->assign(array( + 'order' => $order, + 'price' => $price, + )); + if (version_compare(_PS_VERSION_, '1.5', '>')) + { + $this->context->smarty->assign(array( + 'reference_order' => Order::getUniqReferenceOf($id_order) + )); + } + + echo $this->context->smarty->fetch(_PS_MODULE_DIR_.'paypal/views/templates/front/order-confirmation.tpl'); + } +} + +$id_cart = Tools::getValue('id_cart'); +$id_module = Tools::getValue('id_module'); +$id_order = Tools::getValue('id_order'); +$key = Tools::getValue('key'); + +if ($id_module && $id_order && $id_cart && $key) +{ + if (version_compare(_PS_VERSION_, '1.5', '<')) + { + $integral_evolution_submit = new PayPalIntegralEvolutionSubmit(); + $integral_evolution_submit->run(); + } +} +elseif ($id_cart) +{ + // Redirection + $values = array( + 'id_cart' => (int)$id_cart, + 'id_module' => (int)Module::getInstanceByName('paypal')->id, + 'id_order' => (int)Order::getOrderByCartId((int)$id_cart), + ); + + if (version_compare(_PS_VERSION_, '1.5', '<')) + { + $customer = new Customer(Context::getContext()->cookie->id_customer); + $values['key'] = $customer->secure_key; + $url = _MODULE_DIR_.'/paypal/integral_evolution/submit.php'; + Tools::redirectLink($url.'?'.http_build_query($values, '', '&')); + } + else + { + $values['key'] = Context::getContext()->customer->secure_key; + $link = Context::getContext()->link->getModuleLink('paypal', 'submit', $values); + Tools::redirect($link); + } +} +else + Tools::redirectLink(__PS_BASE_URI__); +exit(0); diff --git a/modules/paypal/ipn.php b/modules/paypal/ipn.php new file mode 100644 index 00000000..151ae81a --- /dev/null +++ b/modules/paypal/ipn.php @@ -0,0 +1,250 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +include_once(dirname(__FILE__).'/../../config/config.inc.php'); +include_once(_PS_MODULE_DIR_.'paypal/paypal.php'); + +/* + * Instant payment notification class. + * (wait for PayPal payment confirmation, then validate order) + */ +class PayPalIPN extends PayPal +{ + + public function getIPNTransactionDetails($result) + { + if (is_array($result) || (strcmp(trim($result), "VERIFIED") === false)) + { + $transaction_id = pSQL($result['txn_id']); + + return array( + 'id_transaction' => $transaction_id, + 'transaction_id' => $transaction_id, + 'id_invoice' => $result['invoice'], + 'currency' => pSQL($result['mc_currency']), + 'total_paid' => (float)$result['mc_gross'], + 'shipping' => (float)$result['mc_shipping'], + 'payment_date' => pSQL($result['payment_date']), + 'payment_status' => pSQL($result['payment_status']), + ); + } + else + { + $transaction_id = pSQL(Tools::getValue('txn_id')); + + return array( + 'id_transaction' => $transaction_id, + 'transaction_id' => $transaction_id, + 'id_invoice' => pSQL(Tools::getValue('invoice')), + 'currency' => pSQL(Tools::getValue('mc_currency')), + 'total_paid' => (float)Tools::getValue('mc_gross'), + 'shipping' => (float)Tools::getValue('mc_shipping'), + 'payment_date' => pSQL(Tools::getValue('payment_date')), + 'payment_status' => pSQL(Tools::getValue('payment_status')), + ); + } + } + + public function confirmOrder($custom) + { + $result = $this->getResult(); + + $payment_status = Tools::getValue('payment_status'); + $mc_gross = Tools::getValue('mc_gross'); + $txn_id = Tools::getValue('txn_id'); + + $id_order = (int)PayPalOrder::getIdOrderByTransactionId($txn_id); + + if ($id_order != 0) + Context::getContext()->cart = new Cart((int)$id_order); + elseif (isset($custom['id_cart'])) + Context::getContext()->cart = new Cart((int)$custom['id_cart']); + + $address = new Address((int)Context::getContext()->cart->id_address_invoice); + Context::getContext()->country = new Country((int)$address->id_country); + Context::getContext()->customer = new Customer((int)Context::getContext()->cart->id_customer); + Context::getContext()->language = new Language((int)Context::getContext()->cart->id_lang); + Context::getContext()->currency = new Currency((int)Context::getContext()->cart->id_currency); + + if (isset(Context::getContext()->cart->id_shop)) + Context::getContext()->shop = new Shop(Context::getContext()->cart->id_shop); + + if (strcmp(trim($result), "VERIFIED") === false) + { + $details = $this->getIPNTransactionDetails($result); + + if ($id_order != 0) + { + $history = new OrderHistory(); + $history->id_order = (int)$id_order; + + PayPalOrder::updateOrder($id_order, $details); + $history->changeIdOrderState((int)Configuration::get('PS_OS_ERROR'), $history->id_order); + + $history->addWithemail(); + $history->save(); + } + } + elseif (strcmp(trim($result), "VERIFIED") === 0) + { + $details = $this->getIPNTransactionDetails($result); + + if (version_compare(_PS_VERSION_, '1.5', '<')) + $shop = null; + else + { + $shop_id = Context::getContext()->shop->id; + $shop = new Shop($shop_id); + } + + if ($id_order != 0) + { + $order = new Order((int)$id_order); + $values = $this->checkPayment($payment_status, $mc_gross, false); + + if ((int)$order->current_state == (int)$values['payment_type']) + return; + + $history = new OrderHistory(); + $history->id_order = (int)$id_order; + + PayPalOrder::updateOrder($id_order, $details); + $history->changeIdOrderState($values['payment_type'], $history->id_order); + + $history->addWithemail(); + $history->save(); + } + else + { + $values = $this->checkPayment($payment_status, $mc_gross, true); + $customer = new Customer((int)Context::getContext()->cart->id_customer); + $this->validateOrder(Context::getContext()->cart->id, $values['payment_type'], $values['total_price'], $this->displayName, $values['message'], $details, Context::getContext()->cart->id_currency, false, $customer->secure_key, $shop); + } + } + } + + public function checkPayment($payment_status, $mc_gross_not_rounded, $new_order) + { + $currency_decimals = is_array(Context::getContext()->currency) ? (int)Context::getContext()->currency['decimals'] : (int)Context::getContext()->currency->decimals; + $this->decimals = $currency_decimals * _PS_PRICE_DISPLAY_PRECISION_; + + $mc_gross = Tools::ps_round($mc_gross_not_rounded, $this->decimals); + + $cart_details = Context::getContext()->cart->getSummaryDetails(null, true); + $cart_hash = sha1(serialize(Context::getContext()->cart->nbProducts())); + $custom = Tools::jsonDecode(Tools::getValue('custom'), true); + + $shipping = $cart_details['total_shipping_tax_exc']; + $subtotal = $cart_details['total_price_without_tax'] - $cart_details['total_shipping_tax_exc']; + $tax = $cart_details['total_tax']; + + $total_price = Tools::ps_round($shipping + $subtotal + $tax, $this->decimals); + + if (($new_order == true) && ($this->comp($mc_gross, $total_price, 2) !== 0)) + { + $payment_type = (int)Configuration::get('PS_OS_ERROR'); + $message = $this->l('Price paid on paypal is not the same that on PrestaShop.').'
    '; + } + elseif (($new_order == true) && ($custom['hash'] != $cart_hash)) + { + $payment_type = (int)Configuration::get('PS_OS_ERROR'); + $message = $this->l('Cart changed, please retry.').'
    '; + } + else + { + return $this->getDetails($payment_status) + array( + 'payment_status' => $payment_status, + 'total_price' => $total_price + ); + } + + return array( + 'message' => $message, + 'payment_type' => $payment_type, + 'payment_status' => $payment_status, + 'total_price' => $total_price + ); + } + + public function getDetails($payment_status) + { + if ((bool)Configuration::get('PAYPAL_CAPTURE')) + { + $payment_type = (int)Configuration::get('PS_OS_WS_PAYMENT'); + $message = $this->l('Pending payment capture.').'
    '; + } + else + { + if (strcmp($payment_status, 'Completed') === 0) + { + $payment_type = (int)Configuration::get('PS_OS_PAYMENT'); + $message = $this->l('Payment accepted.').'
    '; + } + elseif (strcmp($payment_status, 'Pending') === 0) + { + $payment_type = (int)Configuration::get('PS_OS_PAYPAL'); + $message = $this->l('Pending payment confirmation.').'
    '; + } + else + { + $payment_type = (int)Configuration::get('PS_OS_ERROR'); + $message = $this->l('Cart changed, please retry.').'
    '; + } + } + + return array( + 'message' => $message, + 'payment_type' => (int)$payment_type + ); + } + + public function getResult() + { + if ((int)Configuration::get('PAYPAL_SANDBOX') == 1) + $action_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_notify-validate'; + else + $action_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_notify-validate'; + + $request = ''; + foreach ($_POST as $key => $value) + { + $value = urlencode(Tools::stripslashes($value)); + $request .= "&$key=$value"; + } + + $handle = fopen(dirname(__FILE__).'/log.txt', 'w+'); + fwrite($handle, $action_url.$request); + return Tools::file_get_contents($action_url.$request); + } + +} + +if (Tools::getIsset('custom')) +{ + $ipn = new PayPalIPN(); + $custom = Tools::jsonDecode(Tools::getValue('custom'), true); + $ipn->confirmOrder($custom); +} \ No newline at end of file diff --git a/modules/paypal/it.php b/modules/paypal/it.php new file mode 100644 index 00000000..8c75a184 --- /dev/null +++ b/modules/paypal/it.php @@ -0,0 +1,90 @@ +paypal_abstract_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>paypal_abstract_6e7012516038a096b9f6bb71ba2cc5a3'] = 'Si accettano pagamenti con carte di credito e prepagate (Visa, MasterCard, Amex, Aurora) associate al conto PayPal'; +$_MODULE['<{paypal}prestashop>paypal_abstract_69a1a3ad8dd5da6db3c4da838a0cf9c7'] = 'Sei sicuro di voler cancellare i tuoi dati?'; +$_MODULE['<{paypal}prestashop>paypal_abstract_32af90c3cfef1bacf43b0c3a8f60a4da'] = 'Il denaro è stato recuperato '; +$_MODULE['<{paypal}prestashop>paypal_abstract_d238649ac5ec14afc894fad36c0b50fc'] = 'La richiesta di recupero fondi non è andata a buon fine, vedi il messaggio nella cronologia.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_05b998de2c4fb46a7bdd37bd378b81d9'] = 'La convalida è stata eseguita, vedi il messaggio nella cronologia. '; +$_MODULE['<{paypal}prestashop>paypal_abstract_aeca7e93a1b3d77e38c3cffa131774d5'] = 'Il rimborso è stato completato '; +$_MODULE['<{paypal}prestashop>paypal_abstract_cba030a50c8a99c7e224adbe1cf58544'] = 'La richiesta di rimborso non è andata a buon fine, vedi il messaggio nella cronologia.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_20fda49ece75d93bea97648ab1f1f1cf'] = 'Annulla i risultati per i prodotti: '; +$_MODULE['<{paypal}prestashop>paypal_abstract_e5d5d9f40763cfe6549bef705e3529a7'] = 'Il messaggio di pagamento non è valido, rivedi il tuo modulo. '; +$_MODULE['<{paypal}prestashop>paypal_abstract_ee9dc1e678d54c517f481583c3fb2db8'] = 'Non è una valuta valida'; +$_MODULE['<{paypal}prestashop>paypal_abstract_eec39bf42bd135971fb2d838c67d1449'] = 'Risultato dell\'operazione di rimborso: '; +$_MODULE['<{paypal}prestashop>paypal_abstract_2ab62d1a578713d0862b56819295630e'] = 'Rimborso PayPal completato. '; +$_MODULE['<{paypal}prestashop>paypal_abstract_a64db959966ba8d07c8b5d9493fcc21f'] = 'Errore durante la transazione '; +$_MODULE['<{paypal}prestashop>paypal_abstract_67962779da962e3d4225055afc05e7bd'] = 'Risultato operazione di riscossione: '; +$_MODULE['<{paypal}prestashop>paypal_abstract_8778ee03f6592d5fec9a1f2ee851e476'] = 'Ordine PayPal completato '; +$_MODULE['<{paypal}prestashop>paypal_abstract_672d40feac6437e49f771019bc330790'] = 'Stato della verifica: '; +$_MODULE['<{paypal}prestashop>paypal_abstract_1828820cc60e36b6f9fdf60cab103ed7'] = 'Si sta attualmente utilizzando l\'indirizzo di posta elettronica predefinito, è necessario utilizzare il proprio indirizzo e-mail'; +$_MODULE['<{paypal}prestashop>validation_20dfea1a472e5be3f15f6b5f36ca335c'] = 'Problema di connessione al server di PayPal.'; +$_MODULE['<{paypal}prestashop>validation_f7799c2ded739cf3c3e9babffc5f315b'] = 'Collegamento tramite cURL non riuscita'; +$_MODULE['<{paypal}prestashop>validation_eca77e208634d52703b07672abbf16ec'] = 'Verifica fallimento (con cURL). Restituito:'; +$_MODULE['<{paypal}prestashop>validation_8358ec19f397d4cdd632688d4f79e535'] = 'Verifica fallimento (usando fsockopen). Restituito:'; +$_MODULE['<{paypal}prestashop>validation_76ee8dc73701e846f7bccdf98dae079b'] = 'Nessuna comunicazione di trasporto disponibile.'; +$_MODULE['<{paypal}prestashop>validation_bd0e34e5be6447844e6f262d51f1a9dc'] = 'Pagamento:'; +$_MODULE['<{paypal}prestashop>validation_e0395c4ce35d0b1e59ca3f2d5e260d23'] = 'Chiave Paypal \'Custom\' non specificata, non in grado di inoltrare al carrello'; +$_MODULE['<{paypal}prestashop>validation_765261b630ee773659fae89e9ad762f5'] = 'Chiave Paypal \'Txn_id\' non specificata, operazione sconosciuta'; +$_MODULE['<{paypal}prestashop>validation_01634612f84d2b7ba56ccdf467e604b7'] = 'Chiave Paypal \'Mc_currency\' non specificata, valuta sconosciuto'; +$_MODULE['<{paypal}prestashop>validation_e61f52d02b9f52fbe1fd41ed320e29c3'] = 'Carrello non trovato'; +$_MODULE['<{paypal}prestashop>validation_0617900b1aff826081d07f5a3e2e7cd0'] = 'Ordine è già stato effettuato'; +$_MODULE['<{paypal}prestashop>validation_f5209b3301a46f3057ffbf34d903e205'] = 'ID Transazione PayPal:'; +$_MODULE['<{paypal}prestashop>validation_7b19e875ff64b09d80ee05dcc84b9975'] = 'La transazione PayPal non è stata VERIFICATA.'; +$_MODULE['<{paypal}prestashop>paypal_connect_d1f14cc4a2dade80c92421d26422fea0'] = 'Fare nuova connessione'; +$_MODULE['<{paypal}prestashop>paypal_connect_94a27811a721ef512ad7bfa06cab34e0'] = 'Connessione non riuscita con metodo CURL'; +$_MODULE['<{paypal}prestashop>paypal_connect_70215486455daee13382c68b1a230b82'] = 'Connessione con metodo CURL riuscita'; +$_MODULE['<{paypal}prestashop>paypal_connect_e4c4ad49bced42265b5facc2175cdafd'] = 'Invio di questo param.:'; +$_MODULE['<{paypal}prestashop>paypal_connect_445583f6641da98fc7ac8fd9d13a564b'] = 'Invio con metodo CURL fallito! Errore:'; +$_MODULE['<{paypal}prestashop>paypal_connect_ef4fbf36eaa2083442d386990ba063c2'] = 'Invio con metodo CURL riuscito'; +$_MODULE['<{paypal}prestashop>paypal_connect_bf059c9751bb1a20b449b7917b1df374'] = 'Connessione non riuscita con metodo fsockopen'; +$_MODULE['<{paypal}prestashop>paypal_connect_ea800e3536f81238a4cbc32eb6db4eaf'] = 'Connettiti con metodo fsockopen riuscita'; +$_MODULE['<{paypal}prestashop>paypal_connect_6e9aa4cb541e09b07602d4ea96080811'] = 'Invio con metodo fsockopen non riuscito!'; +$_MODULE['<{paypal}prestashop>paypal_connect_842a183be225d415b2b4375ba1dd1c94'] = 'Invio con metodo fsockopen riuscito'; +$_MODULE['<{paypal}prestashop>paypal_lib_7c2d00d8c94d1ce0f515db8b0481db40'] = 'risposta di PayPal:'; +$_MODULE['<{paypal}prestashop>paypal_express_checkout_ee9dc1e678d54c517f481583c3fb2db8'] = 'Non è una valuta valida'; +$_MODULE['<{paypal}prestashop>paypal_express_checkout_484f5a79672cebe198ebdde45a1d672f'] = 'Pacchetto regalo:'; +$_MODULE['<{paypal}prestashop>submit_36ec50c0e914dd2fb48a1b27540512ce'] = 'Pagamento accettato.'; +$_MODULE['<{paypal}prestashop>notifier_36ec50c0e914dd2fb48a1b27540512ce'] = 'Pagamento accettato.'; +$_MODULE['<{paypal}prestashop>about_e816e21c1c8e0eba0620fa3df6bd6795'] = 'Che cos\'è PayPal?'; +$_MODULE['<{paypal}prestashop>about_16ea57badae98f402bb8f2b2f49d4e77'] = 'PayPal, leader di fiducia nei pagamenti online, consente ad acquirenti e aziende di inviare e ricevere pagamenti online. PayPal vanta oltre 100 milioni di conti in 190 Paesi e territori. È accettato dai commercianti di tutto il mondo, dentro e fuori di eBay.'; +$_MODULE['<{paypal}prestashop>about_d20adade7baa1b60b713521031ea676c'] = 'E\' sicuro?'; +$_MODULE['<{paypal}prestashop>about_64f7b897c6d56fc62428f692ee5737cd'] = 'PayPal consente di proteggere i dati della carta di credito con la sicurezza dei leader di settore e dei sistemi di prevenzione delle frodi. Quando utilizzi PayPal, le tue informazioni finanziarie non vengono mai condivise con il commerciante.'; +$_MODULE['<{paypal}prestashop>about_5ef30813484389e4200640c2f006004d'] = 'Perché utilizzare PayPal?'; +$_MODULE['<{paypal}prestashop>about_86550d4ea832930db4366f03b90bdfb8'] = 'Fai acquisti o invia denaro con PayPal - è gratis'; +$_MODULE['<{paypal}prestashop>about_7dc9e529337e5a55a12bf362b8e68cac'] = 'Fai acquisti e paga comodamente salvando le tue informazioni con PayPal'; +$_MODULE['<{paypal}prestashop>about_32098ae6a7ecd96805df9e48fb6cc739'] = 'PayPal è accettato da milioni di aziende in tutto il mondo ed è il metodo di pagamento preferito su eBay'; +$_MODULE['<{paypal}prestashop>about_7934d7d1280bfbb8778743e39292af30'] = 'Inizia a utilizzare PayPal oggi stesso!'; +$_MODULE['<{paypal}prestashop>column_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Paga con PayPal'; +$_MODULE['<{paypal}prestashop>confirmation_2e2117b7c81aa9ea6931641ea2c6499f'] = 'Il tuo ordine'; +$_MODULE['<{paypal}prestashop>confirmation_75fbf512d744977d62599cc3f0ae2bb4'] = 'è completo.'; +$_MODULE['<{paypal}prestashop>confirmation_15b0f8e55c6bdfc3d5fd0b6b3b6cb3ee'] = 'Hai scelto il metodo PayPal.'; +$_MODULE['<{paypal}prestashop>confirmation_e6dc7945b557a1cd949bea92dd58963e'] = 'Il tuo ordine verrà inviato al più presto.'; +$_MODULE['<{paypal}prestashop>confirmation_0db71da7150c27142eef9d22b843b4a9'] = 'Per eventuali domande o per ulteriori informazioni, contatta la nostra'; +$_MODULE['<{paypal}prestashop>confirmation_64430ad2835be8ad60c59e7d44e4b0b1'] = 'assistenza clienti'; +$_MODULE['<{paypal}prestashop>error_a40cab5994f36d4c48103a22ca082e8f'] = 'Il tuo carrello'; +$_MODULE['<{paypal}prestashop>error_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>error_425551a2289ed60c9260933d1c45ef00'] = 'Si prega di fare riferimento ai log:'; +$_MODULE['<{paypal}prestashop>error_0557fa923dcee4d0f86b1409f5c2167f'] = 'Indietro'; +$_MODULE['<{paypal}prestashop>order-confirmation_fb077ecba55e5552916bde26d8b9e794'] = 'Conferma ordine'; +$_MODULE['<{paypal}prestashop>order-confirmation_a378cd7a0839cbd4ec3e45bbdeeb69be'] = 'Il tuo numero di ordine è:'; +$_MODULE['<{paypal}prestashop>order-confirmation_4082ea29b4f196c4f60533500139725a'] = 'Segui il mio ordine'; +$_MODULE['<{paypal}prestashop>order-confirmation_9390390581f54c65d6acfc8da4e17362'] = 'Torna agli ordini'; +$_MODULE['<{paypal}prestashop>express_checkout_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Paga con PayPal'; +$_MODULE['<{paypal}prestashop>payment_a40cab5994f36d4c48103a22ca082e8f'] = 'Il tuo carrello'; +$_MODULE['<{paypal}prestashop>payment_ad69e733ebae8d264bccaa38d68830e8'] = 'PayPal'; +$_MODULE['<{paypal}prestashop>payment_f1d3b424cd68795ecaa552883759aceb'] = 'Riepilogo dell\'ordine'; +$_MODULE['<{paypal}prestashop>payment_dd23adc5fb6bda9c384397b31e57fc53'] = 'pagamento PayPal'; +$_MODULE['<{paypal}prestashop>payment_62d74398cb6ebaa69ab7339052ca5c92'] = 'Hai scelto di pagare con PayPal.'; +$_MODULE['<{paypal}prestashop>payment_c884ed19483d45970c5bf23a681e2dd2'] = 'Ecco un breve riepilogo del tuo ordine:'; +$_MODULE['<{paypal}prestashop>payment_e2867a925cba382f1436d1834bb52a1c'] = 'L\'importo totale del tuo ordine è'; +$_MODULE['<{paypal}prestashop>payment_1f87346a16cf80c372065de3c54c86d9'] = '(tasse incl.)'; +$_MODULE['<{paypal}prestashop>payment_8ed356c32b198c9cb2abab7c3d262b93'] = 'Accettiamo che la seguente valuta sia inviata tramite PayPal:'; +$_MODULE['<{paypal}prestashop>payment_0881a11f7af33bc1b43e437391129d66'] = 'Conferma l\'ordine cliccando su \'confermo il mio ordine\''; +$_MODULE['<{paypal}prestashop>payment_46b9e3665f187c739c55983f757ccda0'] = 'Confermo il mio ordine'; +$_MODULE['<{paypal}prestashop>payment_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Paga con PayPal'; +$_MODULE['<{paypal}prestashop>payment_a3f2caee6ef8e68fbd26e42d83f2bf65'] = 'Paga con il tuo conto PayPal, carta di credito (Visa, Mastercard ...), o carta di credito privata'; +$_MODULE['<{paypal}prestashop>payment_b08008a2de4331ba13f006c9bcf37b62'] = 'Paga con il tuo conto PayPal'; +$_MODULE['<{paypal}prestashop>paypal_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Paga con PayPal'; diff --git a/modules/paypal/logo.gif b/modules/paypal/logo.gif new file mode 100644 index 00000000..455c8999 Binary files /dev/null and b/modules/paypal/logo.gif differ diff --git a/modules/paypal/logo.png b/modules/paypal/logo.png new file mode 100644 index 00000000..e3248193 Binary files /dev/null and b/modules/paypal/logo.png differ diff --git a/modules/paypal/logos.xml b/modules/paypal/logos.xml new file mode 100644 index 00000000..87fac87d --- /dev/null +++ b/modules/paypal/logos.xml @@ -0,0 +1,349 @@ + + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + /views/img/default_logos/default_horizontal.png + /views/img/default_logos/default_logo.gif + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_AU/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_AU/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_AU/i/logo/PayPal_mark_60x38.gif + + https://www.paypalobjects.com/en_AU/AU/i/bnr/horizontal_solution_PP.gif + + + /views/img/default_logos/AU_vertical_solution_PP.png + + + + https://www.paypal.com/fr_FR/BE/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/fr_FR/BE/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/fr_FR/BE/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_US/BE/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/fr_FR/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/fr_FR/i/logo/PayPal_mark_60x38.gif + https://www.paypal.com/fr_FR/i/logo/PayPal_mark_180x113.gif + + + /views/img/default_logos/BE_horizontal_solution_PP.png + + + /views/img/default_logos/BE_vertical_solution_PP.png + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/zh_CN/CN/i/logo/PayPal_mark_60x38.gif + https://www.paypal.com/zh_CN/CN/i/logo/PayPal_mark_180x113.gif + + https://www.paypal.com/zh_CN/i/bnr/horizontal_solution_PP.gif + https://www.paypal.com/zh_CN/i/bnr/vertical_solution_PP.gif + + + + https://www.paypalobjects.com/webstatic/de_DE/i/de-pp-logo-100px.png + https://www.paypalobjects.com/webstatic/de_DE/i/de-pp-logo-150px.png + https://www.paypalobjects.com/webstatic/de_DE/i/de-pp-logo-200px.png + + https://www.paypalobjects.com/webstatic/de_DE/i/de-pp-logo-200px.png + /views/img/default_logos/DE_horizontal_solution_PP.gif + + https://www.paypalobjects.com/webstatic/de_DE/i/de-btn-expresscheckout.gif + + https://www.paypalobjects.com/webstatic/mktg/logo/pp_cc_mark_37x23.jpg + https://www.paypalobjects.com/webstatic/mktg/logo/pp_cc_mark_74x46.jpg + https://www.paypalobjects.com/webstatic/mktg/logo/pp_cc_mark_111x69.jpg + + + /views/img/default_logos/DE_vertical_solution_PP.gif + + + + + https://www.paypal.com/es_ES/ES/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/es_ES/ES/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/es_ES/ES/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/es_ES/ES/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/es_ES/ES/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/es_ES/ES/i/logo/PayPal_mark_60x38.gif + + https://www.paypal.com/es_ES/ES/i/bnr/horizontal_solution_PP.gif + https://www.paypal.com/es_ES/ES/i/bnr/vertical_solution_PP.gif + + + + https://www.paypalobjects.com/webstatic/mktg/logo/pp_cc_mark_37x23.jpg + https://www.paypalobjects.com/webstatic/mktg/logo/pp_cc_mark_74x46.jpg + https://www.paypalobjects.com/webstatic/mktg/logo/pp_cc_mark_111x69.jpg + + https://www.paypalobjects.com/webstatic/mktg/logo/pp_cc_mark_37x23.jpg + https://www.paypalobjects.com/webstatic/mktg/logo/pp_cc_mark_74x46.jpg + https://www.paypalobjects.com/webstatic/mktg/logo/pp_cc_mark_111x69.jpg + + https://www.paypalobjects.com/webstatic/mktg/logo-center/logo_paypal_moyens_paiement_fr.jpg + + + + /views/img/default_logos/FR_vertical_solution_PP.png + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + https://www.paypal.com/en_GB/i/bnr/horizontal_solution_PP.gif + https://www.paypal.com/en_GB/i/bnr/vertical_solution_PP.gif + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + https://www.paypal.com/en_GB/HK/i/bnr/horizontal_solution_4_hk.gif + https://www.paypalobjects.com/en_GB/HK/i/bnr/vertical_solution_4_hk.gif + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + https://www.paypalobjects.com/en_US/PL/i/bnr/bnr_horizontal_solution_PP_166wx80h.gif + https://www.paypalobjects.com/en_US/PL/i/bnr/bnr_horizontal_solution_PP_166wx80h.gif + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + https://www.paypal.com/en_GB/SG/i/bnr/horizontal_solution_mc_visa.gif + https://www.paypalobjects.com/en_GB/SG/i/bnr/vertical_solution_4_hk.gif + + + + https://www.paypal.com/it_IT/IT/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/it_IT/IT/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/it_IT/IT/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/it_IT/IT/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/it_IT/IT/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/it_IT/IT/i/logo/PayPal_mark_60x38.gif + + https://www.paypalobjects.com/it_IT/IT/Marketing/i/bnr/bnr_horizontal_solutiongraphic_335x80.gif + https://www.paypalobjects.com/it_IT/IT/Marketing/i/bnr/bnr_vertical_solutiongraphic_150x172.gif + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + https://www.paypal.com/en_US/JP/i/bnr/horizontal_solution_4_jcb.gif + https://www.paypal.com/en_US/JP/i/bnr/vertical_solution_4_jcb.gif + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + https://www.paypalobjects.com/en_GB/SG/i/bnr/horizontal_solution_4_hk.gif + https://www.paypalobjects.com/en_GB/SG/i/bnr/vertical_solution_4_hk.gif + + + + https://www.paypal.com/nl_NL/NL/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/nl_NL/NL/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/nl_NL/NL/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/nl_NL/NL/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/nl_NL/NL/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/nl_NL/NL/i/logo/PayPal_mark_60x38.gif + + https://www.paypalobjects.com/nl_NL/NL/i/bnr/horizontal_solution_PP.gif + + + + https://www.paypal.com/nl_NL/NL/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/nl_NL/NL/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/nl_NL/NL/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/nl_NL/NL/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/nl_NL/NL/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/nl_NL/NL/i/logo/PayPal_mark_60x38.gif + + https://www.paypalobjects.com/en_AU/AU/i/bnr/horizontal_solution_PP.gif + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + + /views/img/default_logos/PL_horizontal_solution_PP.png + + + /views/img/default_logos/PL_vertical_solution_PP.png + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + https://www.paypalobjects.com/fr_XC/i/bnr/horizontal_solution_PPeCheck.gif + https://www.paypalobjects.com/fr_XC/i/bnr/vertical_solution_PPeCheck.gif + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + https://www.paypalobjects.com/en_US/PL/i/bnr/bnr_horizontal_solution_PP_166wx80h.gif + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + + /views/img/default_logos/RA_horizontal_solution_PP.png + + + /views/img/default_logos/RA_vertical_solution_PP.png + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + + /views/img/default_logos/RE_horizontal_solution_PP.png + + + /views/img/default_logos/RE_vertical_solution_PP.png + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + https://www.paypalobjects.com/en_GB/SG/i/bnr/horizontal_solution_4_hk.gif + https://www.paypalobjects.com/en_GB/SG/i/bnr/vertical_solution_4_hk.gif + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + https://www.paypalobjects.com/en_GB/TH/i/bnr/horizontal_solution_4_hk.gif + https://www.paypalobjects.com/en_GB/TH/i/bnr/vertical_solution_4_hk.gif + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + https://www.paypal.com/en_GB/HK/i/bnr/horizontal_solution_4_hk.gif + https://www.paypal.com/en_GB/HK/i/bnr/vertical_solution_4_hk.gif + + + + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_80x35.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_100x45.gif + https://www.paypal.com/en_GB/Marketing/i/logo/PayPal_logo_150x65.gif + + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_37x23.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_50x34.gif + https://www.paypal.com/en_GB/GB/i/logo/PayPal_mark_60x38.gif + + https://www.paypalobjects.com/fr_XC/i/bnr/horizontal_solution_PPeCheck.gif + https://www.paypalobjects.com/fr_XC/i/bnr/vertical_solution_PPeCheck.gif + + + diff --git a/modules/paypal/mails/en/error_reporting.html b/modules/paypal/mails/en/error_reporting.html new file mode 100644 index 00000000..139e8749 --- /dev/null +++ b/modules/paypal/mails/en/error_reporting.html @@ -0,0 +1,42 @@ + + + + + Message from {shop_name} + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + {shop_name} +
     
    Hi,
     
    Error reporting from your PayPalAPI module
     
    + A client has encountered a problem with the module PayPalAPI, see the report: +
     
    + {logs} +
     
    + {shop_name} powered with PrestaShop™ +
    + + diff --git a/modules/paypal/mails/en/error_reporting.txt b/modules/paypal/mails/en/error_reporting.txt new file mode 100644 index 00000000..802ac51a --- /dev/null +++ b/modules/paypal/mails/en/error_reporting.txt @@ -0,0 +1,9 @@ + Hi, + + Error reporting from your PayPalAPI module + + A client has encountered a problem with the module PayPalAPI, see the report: + + {logs} + + {shop_url} powered by PrestaShop™ diff --git a/modules/paypal/mails/en/index.php b/modules/paypal/mails/en/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/mails/en/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/paypal.php b/modules/paypal/paypal.php new file mode 100644 index 00000000..9ea07d05 --- /dev/null +++ b/modules/paypal/paypal.php @@ -0,0 +1,1643 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +if (!defined('_PS_VERSION_')) + exit; + +include_once(_PS_MODULE_DIR_.'paypal/api/paypal_lib.php'); +include_once(_PS_MODULE_DIR_.'paypal/paypal_logos.php'); +include_once(_PS_MODULE_DIR_.'paypal/paypal_orders.php'); +include_once(_PS_MODULE_DIR_.'paypal/paypal_tools.php'); +include_once(_PS_MODULE_DIR_.'paypal/paypal_login/paypal_login.php'); +include_once(_PS_MODULE_DIR_.'paypal/paypal_login/PayPalLoginUser.php'); +include_once(_PS_MODULE_DIR_.'paypal/classes/PaypalCapture.php'); + +define('WPS', 1); //Paypal Integral +define('HSS', 2); //Paypal Integral Evolution +define('ECS', 4); //Paypal Option + + +define('TRACKING_INTEGRAL_EVOLUTION', 'FR_PRESTASHOP_H3S'); +define('TRACKING_INTEGRAL', 'PRESTASHOP_EC'); +define('TRACKING_OPTION_PLUS', 'PRESTASHOP_ECM'); +define('PAYPAL_HSS_REDIRECTION', 0); +define('PAYPAL_HSS_IFRAME', 1); +define('TRACKING_EXPRESS_CHECKOUT_SEAMLESS', 'PrestaShopCEMEA_Cart_LIPP'); + + +define('TRACKING_CODE', 'FR_PRESTASHOP_H3S'); +define('SMARTPHONE_TRACKING_CODE', 'Prestashop_Cart_smartphone_EC'); +define('TABLET_TRACKING_CODE', 'Prestashop_Cart_tablet_EC'); + +define('_PAYPAL_LOGO_XML_', 'logos.xml'); +define('_PAYPAL_MODULE_DIRNAME_', 'paypal'); +define('_PAYPAL_TRANSLATIONS_XML_', 'translations.xml'); + +class PayPal extends PaymentModule +{ + protected $_html = ''; + + public $_errors = array(); + + public $context; + public $iso_code; + public $default_country; + + public $paypal_logos; + + public $module_key = '646dcec2b7ca20c4e9a5aebbbad98d7e'; + + const BACKWARD_REQUIREMENT = '0.4'; + const DEFAULT_COUNTRY_ISO = 'GB'; + + const ONLY_PRODUCTS = 1; + const ONLY_DISCOUNTS = 2; + const BOTH = 3; + const BOTH_WITHOUT_SHIPPING = 4; + const ONLY_SHIPPING = 5; + const ONLY_WRAPPING = 6; + const ONLY_PRODUCTS_WITHOUT_SHIPPING = 7; + + public function __construct() + { + $this->name = 'paypal'; + $this->tab = 'payments_gateways'; + $this->version = '3.10.2'; + $this->author = 'PrestaShop'; + $this->is_eu_compatible = 1; + + + $this->currencies = true; + $this->currencies_mode = 'radio'; + + parent::__construct(); + + $this->displayName = $this->l('PayPal'); + $this->description = $this->l('Accepts payments by credit cards (CB, Visa, MasterCard, Amex, Aurore, Cofinoga, 4 stars) with PayPal.'); + $this->confirmUninstall = $this->l('Are you sure you want to delete your details?'); + + + $this->page = basename(__FILE__, '.php'); + + if (version_compare(_PS_VERSION_, '1.5', '<')) + { + $mobile_enabled = (int)Configuration::get('PS_MOBILE_DEVICE'); + require(_PS_MODULE_DIR_.$this->name.'/backward_compatibility/backward.php'); + } + else + $mobile_enabled = (int)Configuration::get('PS_ALLOW_MOBILE_DEVICE'); + + if (self::isInstalled($this->name)) + { + $this->loadDefaults(); + if ($mobile_enabled && $this->active) + $this->checkMobileCredentials(); + elseif ($mobile_enabled && !$this->active) + $this->checkMobileNeeds(); + } + else + $this->checkMobileNeeds(); + } + + public function install() + { + if (!parent::install() || !$this->registerHook('payment') || !$this->registerHook('displayPaymentEU') || !$this->registerHook('paymentReturn') || + !$this->registerHook('shoppingCartExtra') || !$this->registerHook('backBeforePayment') || !$this->registerHook('rightColumn') || + !$this->registerHook('cancelProduct') || !$this->registerHook('productFooter') || !$this->registerHook('header') || + !$this->registerHook('adminOrder') || !$this->registerHook('backOfficeHeader') || !$this->registerHook('actionPSCleanerGetModulesTables')) + return false; + + if ((_PS_VERSION_ >= '1.5') && (!$this->registerHook('displayMobileHeader') || + !$this->registerHook('displayMobileShoppingCartTop') || !$this->registerHook('displayMobileAddToCartTop'))) + return false; + + include_once(_PS_MODULE_DIR_.$this->name.'/paypal_install.php'); + $paypal_install = new PayPalInstall(); + $paypal_install->createTables(); + $paypal_install->updateConfiguration($this->version); + $paypal_install->createOrderState(); + + $paypal_tools = new PayPalTools($this->name); + $paypal_tools->moveTopPayments(1); + $paypal_tools->moveRightColumn(3); + + $this->runUpgrades(true); + + return true; + } + + public function uninstall() + { + include_once(_PS_MODULE_DIR_.$this->name.'/paypal_install.php'); + $paypal_install = new PayPalInstall(); + $paypal_install->deleteConfiguration(); + return parent::uninstall(); + } + + /** + * Launch upgrade process + */ + public function runUpgrades($install = false) + { + if (version_compare(_PS_VERSION_, '1.5', '<')) + foreach (array('2.8', '3.0', '3.7', '3.8.3', '3.9', '3.10.1') as $version) + { + $file = dirname(__FILE__).'/upgrade/install-'.$version.'.php'; + if (Configuration::get('PAYPAL_VERSION') < $version && file_exists($file)) + { + include_once($file); + call_user_func('upgrade_module_'.str_replace('.', '_', $version), $this, $install); + } + } + } + + private function compatibilityCheck() + { + if (file_exists(_PS_MODULE_DIR_.'paypalapi/paypalapi.php') && $this->active) + $this->warning = $this->l('All features of Paypal API module are included in the new Paypal module. In order to do not have any conflict, please do not use and remove PayPalAPI module.').'
    '; + + /* For 1.4.3 and less compatibility */ + $update_config = array('PS_OS_CHEQUE' => 1, 'PS_OS_PAYMENT' => 2, 'PS_OS_PREPARATION' => 3, 'PS_OS_SHIPPING' => 4, + 'PS_OS_DELIVERED' => 5, 'PS_OS_CANCELED' => 6, 'PS_OS_REFUND' => 7, 'PS_OS_ERROR' => 8, 'PS_OS_OUTOFSTOCK' => 9, + 'PS_OS_BANKWIRE' => 10, 'PS_OS_PAYPAL' => 11, 'PS_OS_WS_PAYMENT' => 12); + + foreach ($update_config as $key => $value) + if (!Configuration::get($key) || (int)Configuration::get($key) < 1) + { + if (defined('_'.$key.'_') && (int)constant('_'.$key.'_') > 0) + Configuration::updateValue($key, constant('_'.$key.'_')); + else + Configuration::updateValue($key, $value); + } + } + + public function isPayPalAPIAvailable() + { + $payment_method = Configuration::get('PAYPAL_PAYMENT_METHOD'); + + if ($payment_method != HSS && !is_null(Configuration::get('PAYPAL_API_USER')) && + !is_null(Configuration::get('PAYPAL_API_PASSWORD')) && !is_null(Configuration::get('PAYPAL_API_SIGNATURE'))) + return true; + elseif ($payment_method == HSS && !is_null(Configuration::get('PAYPAL_BUSINESS_ACCOUNT'))) + return true; + + return false; + } + + /** + * Initialize default values + */ + protected function loadDefaults() + { + $this->loadLangDefault(); + $this->paypal_logos = new PayPalLogos($this->iso_code); + $payment_method = Configuration::get('PAYPAL_PAYMENT_METHOD'); + $order_process_type = (int)Configuration::get('PS_ORDER_PROCESS_TYPE'); + + if (Tools::getValue('paypal_ec_canceled') || $this->context->cart === false) + unset($this->context->cookie->express_checkout); + + if (version_compare(_PS_VERSION_, '1.5.0.2', '>=')) + { + $version = Db::getInstance()->getValue('SELECT version FROM `'._DB_PREFIX_.'module` WHERE name = \''.$this->name.'\''); + if (empty($version) === true) + Db::getInstance()->execute(' + UPDATE `'._DB_PREFIX_.'module` m + SET m.version = \''.bqSQL($this->version).'\' + WHERE m.name = \''.bqSQL($this->name).'\''); + } + + if (defined('_PS_ADMIN_DIR_')) + { + /* Backward compatibility */ + if (version_compare(_PS_VERSION_, '1.5', '<')) + $this->backwardCompatibilityChecks(); + + /* Upgrade and compatibility checks */ + $this->runUpgrades(); + $this->compatibilityCheck(); + $this->warningsCheck(); + } + else + { + if (isset($this->context->cookie->express_checkout)) + $this->context->smarty->assign('paypal_authorization', true); + + if (($order_process_type == 1) && ((int)$payment_method == HSS) && !$this->useMobile()) + $this->context->smarty->assign('paypal_order_opc', true); + elseif (($order_process_type == 1) && ((bool)Tools::getValue('isPaymentStep') == true)) + { + $shop_url = PayPal::getShopDomainSsl(true, true); + if (version_compare(_PS_VERSION_, '1.5', '<')) + { + $link = $shop_url._MODULE_DIR_.$this->name.'/express_checkout/payment.php'; + $this->context->smarty->assign('paypal_confirmation', $link.'?'.http_build_query(array('get_confirmation' => true), '', '&')); + } + else + { + $values = array('fc' => 'module', 'module' => 'paypal', 'controller' => 'confirm', 'get_confirmation' => true); + $this->context->smarty->assign('paypal_confirmation', $shop_url.__PS_BASE_URI__.'?'.http_build_query($values)); + } + } + } + } + + protected function checkMobileCredentials() + { + $payment_method = Configuration::get('PAYPAL_PAYMENT_METHOD'); + + if (((int)$payment_method == HSS) && ( + (!(bool)Configuration::get('PAYPAL_API_USER')) && + (!(bool)Configuration::get('PAYPAL_API_PASSWORD')) && + (!(bool)Configuration::get('PAYPAL_API_SIGNATURE')))) + $this->warning .= $this->l('You must set your PayPal Integral credentials in order to have the mobile theme work correctly.').'
    '; + } + + protected function checkMobileNeeds() + { + $iso_code = Country::getIsoById((int)Configuration::get('PS_COUNTRY_DEFAULT')); + $paypal_countries = array('ES', 'FR', 'PL', 'IT'); + + if (method_exists($this->context->shop, 'getTheme')) + { + if (($this->context->shop->getTheme() == 'default') && in_array($iso_code, $paypal_countries)) + $this->warning .= $this->l('The mobile theme only works with the PayPal\'s payment module at this time. Please activate the module to enable payments.').'
    '; + } + else + $this->warning .= $this->l('In order to use the module you need to install the backward compatibility.').'
    '; + } + + /* Check status of backward compatibility module*/ + protected function backwardCompatibilityChecks() + { + if (Module::isInstalled('backwardcompatibility')) + { + $backward_module = Module::getInstanceByName('backwardcompatibility'); + if (!$backward_module->active) + $this->warning .= $this->l('To work properly the module requires the backward compatibility module enabled').'
    '; + elseif ($backward_module->version < PayPal::BACKWARD_REQUIREMENT) + $this->warning .= $this->l('To work properly the module requires at least the backward compatibility module v').PayPal::BACKWARD_REQUIREMENT.'.
    '; + } + else + $this->warning .= $this->l('In order to use the module you need to install the backward compatibility.').'
    '; + } + + public function getContent() + { + $this->_postProcess(); + + if (($id_lang = Language::getIdByIso('EN')) == 0) + $english_language_id = (int)$this->context->employee->id_lang; + else + $english_language_id = (int)$id_lang; + + $this->context->smarty->assign(array( + 'PayPal_WPS' => (int)WPS, + 'PayPal_HSS' => (int)HSS, + 'PayPal_ECS' => (int)ECS, + 'PP_errors' => $this->_errors, + 'PayPal_logo' => $this->paypal_logos->getLogos(), + 'PayPal_allowed_methods' => $this->getPaymentMethods(), + 'PayPal_country' => Country::getNameById((int)$english_language_id, (int)$this->default_country), + 'PayPal_country_id' => (int)$this->default_country, + 'PayPal_business' => Configuration::get('PAYPAL_BUSINESS'), + 'PayPal_payment_method' => (int)Configuration::get('PAYPAL_PAYMENT_METHOD'), + 'PayPal_api_username' => Configuration::get('PAYPAL_API_USER'), + 'PayPal_api_password' => Configuration::get('PAYPAL_API_PASSWORD'), + 'PayPal_api_signature' => Configuration::get('PAYPAL_API_SIGNATURE'), + 'PayPal_api_business_account' => Configuration::get('PAYPAL_BUSINESS_ACCOUNT'), + 'PayPal_express_checkout_shortcut' => (int)Configuration::get('PAYPAL_EXPRESS_CHECKOUT_SHORTCUT'), + 'PayPal_in_context_checkout' => (int)Configuration::get('PAYPAL_IN_CONTEXT_CHECKOUT'), + 'PayPal_in_context_checkout_merchant_id' => Configuration::get('PAYPAL_IN_CONTEXT_CHECKOUT_M_ID'), + 'PayPal_sandbox_mode' => (int)Configuration::get('PAYPAL_SANDBOX'), + 'PayPal_payment_capture' => (int)Configuration::get('PAYPAL_CAPTURE'), + 'PayPal_country_default' => (int)$this->default_country, + 'PayPal_change_country_url' => 'index.php?tab=AdminCountries&token='.Tools::getAdminTokenLite('AdminCountries').'#footer', + 'Countries' => Country::getCountries($english_language_id), + 'One_Page_Checkout' => (int)Configuration::get('PS_ORDER_PROCESS_TYPE'), + 'PayPal_integral_evolution_template' => Configuration::get('PAYPAL_HSS_TEMPLATE'), + 'PayPal_integral_evolution_solution' => Configuration::get('PAYPAL_HSS_SOLUTION'), + 'PayPal_login' => (int)Configuration::get('PAYPAL_LOGIN'), + 'PayPal_login_client_id' => Configuration::get('PAYPAL_LOGIN_CLIENT_ID'), + 'PayPal_login_secret' => Configuration::get('PAYPAL_LOGIN_SECRET'), + 'PayPal_login_tpl' => (int)Configuration::get('PAYPAL_LOGIN_TPL'), + 'default_lang_iso' => Language::getIsoById($this->context->employee->id_lang), + )); + + $this->getTranslations(); + + $output = $this->fetchTemplate('/views/templates/admin/back_office.tpl'); + + if ($this->active == false) + return $output.$this->hookBackOfficeHeader(); + + return $output; + } + + /** + * Hooks methods + */ + public function hookHeader() + { + if ($this->useMobile()) + { + $id_hook = (int)Configuration::get('PS_MOBILE_HOOK_HEADER_ID'); + if ($id_hook > 0) + { + $module = Hook::getModulesFromHook($id_hook, $this->id); + if (!$module) + $this->registerHook('displayMobileHeader'); + } + } + + if (isset($this->context->cart) && $this->context->cart->id) + $this->context->smarty->assign('id_cart', (int)$this->context->cart->id); + + /* Added for PrestaBox */ + if (method_exists($this->context->controller, 'addCSS')) + $this->context->controller->addCSS(_MODULE_DIR_.$this->name.'/views/css/paypal.css'); + else + Tools::addCSS(_MODULE_DIR_.$this->name.'/views/css/paypal.css'); + + $smarty = $this->context->smarty; + $smarty->assign(array( + 'ssl_enabled' => Configuration::get('PS_SSL_ENABLED'), + 'PAYPAL_SANDBOX' => Configuration::get('PAYPAL_SANDBOX'), + 'PayPal_in_context_checkout' => Configuration::get('PAYPAL_IN_CONTEXT_CHECKOUT'), + 'PayPal_in_context_checkout_merchant_id' => Configuration::get('PAYPAL_IN_CONTEXT_CHECKOUT_M_ID') + )); + + $process = ''; + if(Configuration::get('PAYPAL_IN_CONTEXT_CHECKOUT')) + $process .= ''; + + if (( + (method_exists($smarty, 'getTemplateVars') && ($smarty->getTemplateVars('page_name') == 'authentication' || $smarty->getTemplateVars('page_name') == 'order-opc' )) + || (isset($smarty->_tpl_vars) && ($smarty->_tpl_vars['page_name'] == 'authentication' || $smarty->_tpl_vars['page_name'] == 'order-opc'))) + && + (int)Configuration::get('PAYPAL_LOGIN') == 1) + { + $this->context->smarty->assign(array( + 'paypal_locale' => $this->getLocale(), + 'PAYPAL_LOGIN_CLIENT_ID' => Configuration::get('PAYPAL_LOGIN_CLIENT_ID'), + 'PAYPAL_LOGIN_TPL' => Configuration::get('PAYPAL_LOGIN_TPL'), + 'PAYPAL_RETURN_LINK' => PayPalLogin::getReturnLink(), + )); + $process .= ' + + '; + } + + return $process; + } + + + + public function getLocale() + { + switch (Language::getIsoById($this->context->language->id)) + { + case 'fr': + return 'fr-fr'; + case 'hk': + return 'zh-hk'; + case 'cn': + return 'zh-cn'; + case 'tw': + return 'zh-tw'; + case 'xc': + return 'zh-xc'; + case 'dk': + return 'da-dk'; + case 'nl': + return 'nl-nl'; + case 'gb': + return 'en-gb'; + case 'de': + return 'de-de'; + case 'il': + return 'he-il'; + case 'id': + return 'id-id'; + case 'il': + return 'it-it'; + case 'jp': + return 'ja-jp'; + case 'no': + return 'no-no'; + case 'pt': + return 'pt-pt'; + case 'pl': + return 'pl-pl'; + case 'ru': + return 'ru-ru'; + case 'es': + return 'es-es'; + case 'se': + return 'sv-se'; + case 'th': + return 'th-th'; + case 'tr': + return 'tr-tr'; + default : + return 'en-gb'; + } + } + + public function hookDisplayMobileHeader() + { + return $this->hookHeader(); + } + + public function hookDisplayMobileShoppingCartTop() + { + return $this->renderExpressCheckoutButton('cart').$this->renderExpressCheckoutForm('cart'); + } + + public function hookDisplayMobileAddToCartTop() + { + return $this->renderExpressCheckoutButton('cart'); + } + + public function hookProductFooter() + { + $content = (!$this->useMobile()) ? $this->renderExpressCheckoutButton('product') : null; + return $content.$this->renderExpressCheckoutForm('product'); + } + + public function hookPayment($params) + { + if (!$this->active) + return; + + $use_mobile = $this->useMobile(); + + if ($use_mobile) + $method = ECS; + else + $method = (int)Configuration::get('PAYPAL_PAYMENT_METHOD'); + + if (isset($this->context->cookie->express_checkout)) + $this->redirectToConfirmation(); + + $iso_lang = array( + 'en' => 'en_US', + 'fr' => 'fr_FR', + 'de' => 'de_DE', + ); + + $this->context->smarty->assign(array( + 'logos' => $this->paypal_logos->getLogos(), + 'sandbox_mode' => Configuration::get('PAYPAL_SANDBOX'), + 'use_mobile' => $use_mobile, + 'PayPal_lang_code' => (isset($iso_lang[$this->context->language->iso_code])) ? $iso_lang[$this->context->language->iso_code] : 'en_US' + )); + + if ($method == HSS) + { + $billing_address = new Address($this->context->cart->id_address_invoice); + $delivery_address = new Address($this->context->cart->id_address_delivery); + $billing_address->country = new Country($billing_address->id_country); + $delivery_address->country = new Country($delivery_address->id_country); + $billing_address->state = new State($billing_address->id_state); + $delivery_address->state = new State($delivery_address->id_state); + + $cart = $this->context->cart; + $cart_details = $cart->getSummaryDetails(null, true); + + if ((int)Configuration::get('PAYPAL_SANDBOX') == 1) + $action_url = 'https://securepayments.sandbox.paypal.com/acquiringweb'; + else + $action_url = 'https://securepayments.paypal.com/acquiringweb'; + + $shop_url = PayPal::getShopDomainSsl(true, true); + + $this->context->smarty->assign(array( + 'action_url' => $action_url, + 'cart' => $cart, + 'cart_details' => $cart_details, + 'currency' => new Currency((int)$cart->id_currency), + 'customer' => $this->context->customer, + 'business_account' => Configuration::get('PAYPAL_BUSINESS_ACCOUNT'), + 'custom' => Tools::jsonEncode(array('id_cart' => $cart->id, 'hash' => sha1(serialize($cart->nbProducts())))), + 'gift_price' => (float)$this->getGiftWrappingPrice(), + 'billing_address' => $billing_address, + 'delivery_address' => $delivery_address, + 'shipping' => $cart_details['total_shipping_tax_exc'], + 'subtotal' => $cart_details['total_price_without_tax'] - $cart_details['total_shipping_tax_exc'], + 'time' => time(), + 'cancel_return' => $this->context->link->getPageLink('order.php'), + 'notify_url' => $shop_url._MODULE_DIR_.$this->name.'/ipn.php', + 'return_url' => $shop_url._MODULE_DIR_.$this->name.'/integral_evolution/submit.php?id_cart='.(int)$cart->id, + 'tracking_code' => $this->getTrackingCode($method), + 'iso_code' => Tools::strtoupper($this->context->language->iso_code), + 'payment_hss_solution' => Configuration::get('PAYPAL_HSS_SOLUTION'), + 'payment_hss_template' => Configuration::get('PAYPAL_HSS_TEMPLATE'), + )); + $this->getTranslations(); + return $this->fetchTemplate('integral_evolution_payment.tpl'); + } + elseif ($method == WPS || $method == ECS) + { + $this->getTranslations(); + $this->context->smarty->assign(array( + 'PayPal_integral' => WPS, + 'PayPal_express_checkout' => ECS, + 'PayPal_payment_method' => $method, + 'PayPal_payment_type' => 'payment_cart', + 'PayPal_current_page' => $this->getCurrentUrl(), + 'PayPal_tracking_code' => $this->getTrackingCode($method), + 'PayPal_in_context_checkout' => Configuration::get('PAYPAL_IN_CONTEXT_CHECKOUT'), + 'PayPal_in_context_checkout_merchant_id' => Configuration::get('PAYPAL_IN_CONTEXT_CHECKOUT_M_ID') + )); + + return $this->fetchTemplate('express_checkout_payment.tpl'); + } + + return null; + } + + public function hookDisplayPaymentEU($params) + { + if (!$this->active) + return; + + if ($this->hookPayment($params) == null) + return null; + + $use_mobile = $this->useMobile(); + + if ($use_mobile) + $method = ECS; + else + $method = (int)Configuration::get('PAYPAL_PAYMENT_METHOD'); + + if (isset($this->context->cookie->express_checkout)) + $this->redirectToConfirmation(); + + $logos = $this->paypal_logos->getLogos(); + + if (isset($logos['LocalPayPalHorizontalSolutionPP']) && $method == WPS) + $logo = $logos['LocalPayPalHorizontalSolutionPP']; + else + $logo = $logos['LocalPayPalLogoMedium']; + + if ($method == HSS) + { + return array( + 'cta_text' => $this->l('Paypal'), + 'logo' => $logo, + 'form' => $this->fetchTemplate('integral_evolution_payment_eu.tpl') + ); + } + elseif ($method == WPS || $method == ECS) + { + return array( + 'cta_text' => $this->l('Paypal'), + 'logo' => $logo, + 'form' => $this->fetchTemplate('express_checkout_payment_eu.tpl') + ); + } + } + + public function hookShoppingCartExtra() + { + if (!$this->active || (((int)Configuration::get('PAYPAL_PAYMENT_METHOD') == HSS) && !$this->context->getMobileDevice()) || + !Configuration::get('PAYPAL_EXPRESS_CHECKOUT_SHORTCUT') || !in_array(ECS, $this->getPaymentMethods()) || isset($this->context->cookie->express_checkout)) + return null; + + $values = array('en' => 'en_US', 'fr' => 'fr_FR', 'de' => 'de_DE'); + $paypal_logos = $this->paypal_logos->getLogos(); + + $this->context->smarty->assign(array( + 'PayPal_payment_type' => 'cart', + 'paypal_express_checkout_shortcut_logo' => isset($paypal_logos['ExpressCheckoutShortcutButton']) ? $paypal_logos['ExpressCheckoutShortcutButton'] : false, + 'PayPal_current_page' => $this->getCurrentUrl(), + 'PayPal_lang_code' => (isset($values[$this->context->language->iso_code]) ? $values[$this->context->language->iso_code] : 'en_US'), + 'PayPal_tracking_code' => $this->getTrackingCode((int)Configuration::get('PAYPAL_PAYMENT_METHOD')), + 'include_form' => true, + 'template_dir' => dirname(__FILE__).'/views/templates/hook/')); + + return $this->fetchTemplate('express_checkout_shortcut_button.tpl'); + } + + public function hookPaymentReturn() + { + if (!$this->active) + return null; + + return $this->fetchTemplate('confirmation.tpl'); + } + + public function hookRightColumn() + { + $this->context->smarty->assign('logo', $this->paypal_logos->getCardsLogo(true)); + return $this->fetchTemplate('column.tpl'); + } + + public function hookLeftColumn() + { + return $this->hookRightColumn(); + } + + public function hookBackBeforePayment($params) + { + if (!$this->active) + return null; + + /* Only execute if you use PayPal API for payment */ + if (((int)Configuration::get('PAYPAL_PAYMENT_METHOD') != HSS) && $this->isPayPalAPIAvailable()) + { + if ($params['module'] != $this->name || !$this->context->cookie->paypal_token || !$this->context->cookie->paypal_payer_id) + return false; + Tools::redirect('modules/'.$this->name.'/express_checkout/submit.php?confirm=1&token='.$this->context->cookie->paypal_token.'&payerID='.$this->context->cookie->paypal_payer_id); + } + } + + public function setPayPalAsConfigured() + { + Configuration::updateValue('PAYPAL_CONFIGURATION_OK', true); + } + + public function hookAdminOrder($params) + { + if (Tools::isSubmit('submitPayPalCapture')) + { + if ($capture_amount = Tools::getValue('totalCaptureMoney')) + { + if ($capture_amount = PaypalCapture::parsePrice($capture_amount)) + { + if (Validate::isFloat($capture_amount)) + { + $capture_amount = Tools::ps_round($capture_amount, '6'); + $ord = new Order((int)$params['id_order']); + $cpt = new PaypalCapture(); + + if (($capture_amount > Tools::ps_round(0, '6')) && (Tools::ps_round($cpt->getRestToPaid($ord), '6') >= $capture_amount)) + { + $complete = false; + + if ($capture_amount > Tools::ps_round((float)$ord->total_paid, '6')) + { + $capture_amount = Tools::ps_round((float)$ord->total_paid, '6'); + $complete = true; + } + if ($capture_amount == Tools::ps_round($cpt->getRestToPaid($ord), '6')) + $complete = true; + $this->_doCapture($params['id_order'], $capture_amount, $complete); + } + } + } + } + } + elseif (Tools::isSubmit('submitPayPalRefund')) + $this->_doTotalRefund($params['id_order']); + + $admin_templates = array(); + if ($this->isPayPalAPIAvailable()) + { + if ($this->_needValidation((int)$params['id_order'])) + $admin_templates[] = 'validation'; + if ($this->_needCapture((int)$params['id_order'])) + $admin_templates[] = 'capture'; + if ($this->_canRefund((int)$params['id_order'])) + $admin_templates[] = 'refund'; + } + + if (count($admin_templates) > 0) + { + $order = new Order((int)$params['id_order']); + $currency = new Currency($order->id_currency); + $cpt = new PaypalCapture(); + $cpt->id_order = (int)$order->id; + + if (version_compare(_PS_VERSION_, '1.5', '>=')) + $order_state = $order->current_state; + else + $order_state = OrderHistory::getLastOrderState($order->id); + + $this->context->smarty->assign( + array( + 'authorization' => (int)Configuration::get('PAYPAL_OS_AUTHORIZATION'), + 'base_url' => _PS_BASE_URL_.__PS_BASE_URI__, + 'module_name' => $this->name, + 'order_state' => $order_state, + 'params' => $params, + 'id_currency' => $currency->getSign(), + 'rest_to_capture' => Tools::ps_round($cpt->getRestToPaid($order), '6'), + 'list_captures' => $cpt->getListCaptured(), + 'ps_version' => _PS_VERSION_ + ) + ); + + foreach ($admin_templates as $admin_template) + { + $this->_html .= $this->fetchTemplate('/views/templates/admin/admin_order/'.$admin_template.'.tpl'); + $this->_postProcess(); + $this->_html .= ''; + } + } + + return $this->_html; + } + + public function hookCancelProduct($params) + { + if (Tools::isSubmit('generateDiscount') || !$this->isPayPalAPIAvailable() || Tools::isSubmit('generateCreditSlip')) + return false; + elseif ($params['order']->module != $this->name || !($order = $params['order']) || !Validate::isLoadedObject($order)) + return false; + elseif (!$order->hasBeenPaid()) + return false; + + $order_detail = new OrderDetail((int)$params['id_order_detail']); + if (!$order_detail || !Validate::isLoadedObject($order_detail)) + return false; + + $paypal_order = PayPalOrder::getOrderById((int)$order->id); + if (!$paypal_order) + return false; + + $products = $order->getProducts(); + $cancel_quantity = Tools::getValue('cancelQuantity'); + $message = $this->l('Cancel products result:').'
    '; + + $amount = (float)($products[(int)$order_detail->id]['product_price_wt'] * (int)$cancel_quantity[(int)$order_detail->id]); + $refund = $this->_makeRefund($paypal_order['id_transaction'], (int)$order->id, $amount); + $this->formatMessage($refund, $message); + $this->_addNewPrivateMessage((int)$order->id, $message); + } + + public function hookActionPSCleanerGetModulesTables() + { + return array('paypal_customer', 'paypal_order'); + } + + public function hookBackOfficeHeader() + { + if ((strcmp(Tools::getValue('configure'), $this->name) === 0) || + (strcmp(Tools::getValue('module_name'), $this->name) === 0)) + { + if (version_compare(_PS_VERSION_, '1.5', '<')) + { + $output = ' + + + '; + } + else + { + $this->context->controller->addJquery(); + $this->context->controller->addJQueryPlugin('fancybox'); + $this->context->controller->addCSS(_MODULE_DIR_.$this->name.'/views/css/paypal.css'); + } + + $this->context->smarty->assign(array( + 'PayPal_module_dir' => _MODULE_DIR_.$this->name, + 'PayPal_WPS' => (int)WPS, + 'PayPal_HSS' => (int)HSS, + 'PayPal_ECS' => (int)ECS + )); + + return (isset($output) ? $output : null).$this->fetchTemplate('/views/templates/admin/header.tpl'); + } + return null; + } + + public function renderExpressCheckoutButton($type) + { + if ((!Configuration::get('PAYPAL_EXPRESS_CHECKOUT_SHORTCUT') && !$this->useMobile())) + return null; + + if (!in_array(ECS, $this->getPaymentMethods()) || (((int)Configuration::get('PAYPAL_BUSINESS') == 1) && + (int)Configuration::get('PAYPAL_PAYMENT_METHOD') == HSS) && !$this->useMobile()) + return null; + $paypal_logos = $this->paypal_logos->getLogos(); + $iso_lang = array( + 'en' => 'en_US', + 'fr' => 'fr_FR', + 'de' => 'de_DE', + ); + + $this->context->smarty->assign(array( + 'use_mobile' => (bool)$this->useMobile(), + 'PayPal_payment_type' => $type, + 'PayPal_current_page' => $this->getCurrentUrl(), + 'PayPal_lang_code' => (isset($iso_lang[$this->context->language->iso_code])) ? $iso_lang[$this->context->language->iso_code] : 'en_US', + 'PayPal_tracking_code' => $this->getTrackingCode((int)Configuration::get('PAYPAL_PAYMENT_METHOD')), + 'paypal_express_checkout_shortcut_logo' => isset($paypal_logos['ExpressCheckoutShortcutButton']) ? $paypal_logos['ExpressCheckoutShortcutButton'] : false, + )); + + return $this->fetchTemplate('express_checkout_shortcut_button.tpl'); + } + + public function renderExpressCheckoutForm($type) + { + if ((!Configuration::get('PAYPAL_EXPRESS_CHECKOUT_SHORTCUT') && !$this->useMobile()) || !in_array(ECS, $this->getPaymentMethods()) || + (((int)Configuration::get('PAYPAL_BUSINESS') == 1) && ((int)Configuration::get('PAYPAL_PAYMENT_METHOD') == HSS) && !$this->useMobile())) + return; + + $this->context->smarty->assign(array( + 'PayPal_payment_type' => $type, + 'PayPal_current_page' => $this->getCurrentUrl(), + 'PayPal_tracking_code' => $this->getTrackingCode((int)Configuration::get('PAYPAL_PAYMENT_METHOD')), + + )); + + return $this->fetchTemplate('express_checkout_shortcut_form.tpl'); + } + + public function useMobile() + { + if ((method_exists($this->context, 'getMobileDevice') && $this->context->getMobileDevice()) || Tools::getValue('ps_mobile_site')) + return true; + return false; + } + + public function getTrackingCode($method) + { + if ((_PS_VERSION_ < '1.5') && (_THEME_NAME_ == 'prestashop_mobile' || Tools::getValue('ps_mobile_site') == 1)) + { + if (_PS_MOBILE_TABLET_) + return TABLET_TRACKING_CODE; + elseif (_PS_MOBILE_PHONE_) + return SMARTPHONE_TRACKING_CODE; + } + //Get Seamless checkout + + $login_user = false; + if (Configuration::get('PAYPAL_LOGIN')) + { + $login_user = PaypalLoginUser::getByIdCustomer((int)$this->context->customer->id); + + if ($login_user && $login_user->expires_in <= time()) + { + $obj = new PayPalLogin(); + $login_user = $obj->getRefreshToken(); + } + } + + if ($method == WPS) + { + if ($login_user) + return TRACKING_EXPRESS_CHECKOUT_SEAMLESS; + else + return TRACKING_INTEGRAL; + } + if ($method == HSS) + return TRACKING_INTEGRAL_EVOLUTION; + if ($method == ECS) + { + if ($login_user) + return TRACKING_EXPRESS_CHECKOUT_SEAMLESS; + else + return TRACKING_OPTION_PLUS; + } + + return TRACKING_CODE; + } + + public function getTranslations() + { + $file = dirname(__FILE__).'/'._PAYPAL_TRANSLATIONS_XML_; + if (file_exists($file)) + { + $xml = simplexml_load_file($file); + if (isset($xml) && $xml) + { + $index = -1; + $content = $default = array(); + + while (isset($xml->country[++$index])) + { + $country = $xml->country[$index]; + $country_iso = $country->attributes()->iso_code; + + if (($this->iso_code != 'default') && ($country_iso == $this->iso_code)) + $content = (array)$country; + elseif ($country_iso == 'default') + $default = (array)$country; + } + + $content += $default; + $this->context->smarty->assign('PayPal_content', $content); + + return true; + } + } + return false; + } + + public function getPayPalURL() + { + return 'www'.(Configuration::get('PAYPAL_SANDBOX') ? '.sandbox' : '').'.paypal.com'; + } + + public function getPaypalIntegralEvolutionUrl() + { + if (Configuration::get('PAYPAL_SANDBOX')) + return 'https://'.$this->getPayPalURL().'/cgi-bin/acquiringweb'; + return 'https://securepayments.paypal.com/acquiringweb?cmd=_hosted-payment'; + } + + public function getPaypalStandardUrl() + { + return 'https://'.$this->getPayPalURL().'/cgi-bin/webscr'; + } + + public function getAPIURL() + { + return 'api-3t'.(Configuration::get('PAYPAL_SANDBOX') ? '.sandbox' : '').'.paypal.com'; + } + + public function getAPIScript() + { + return '/nvp'; + } + + public function getCountryDependency($iso_code) + { + $localizations = array( + 'AU' => array('AU'), 'BE' => array('BE'), 'CN' => array('CN', 'MO'), 'CZ' => array('CZ'), 'DE' => array('DE'), 'ES' => array('ES'), + 'FR' => array('FR'), 'GB' => array('GB'), 'HK' => array('HK'), 'IL' => array('IL'), 'IN' => array('IN'), 'IT' => array('IT', 'VA'), + 'JP' => array('JP'), 'MY' => array('MY'), 'NL' => array('AN', 'NL'), 'NZ' => array('NZ'), 'PL' => array('PL'), 'PT' => array('PT', 'BR'), + 'RA' => array('AF', 'AS', 'BD', 'BN', 'BT', 'CC', 'CK', 'CX', 'FM', 'HM', 'ID', 'KH', 'KI', 'KN', 'KP', 'KR', 'KZ', 'LA', 'LK', 'MH', + 'MM', 'MN', 'MV', 'MX', 'NF', 'NP', 'NU', 'OM', 'PG', 'PH', 'PW', 'QA', 'SB', 'TJ', 'TK', 'TL', 'TM', 'TO', 'TV', 'TZ', 'UZ', 'VN', + 'VU', 'WF', 'WS'), + 'RE' => array('IE', 'ZA', 'GP', 'GG', 'JE', 'MC', 'MS', 'MP', 'PA', 'PY', 'PE', 'PN', 'PR', 'LC', 'SR', 'TT', + 'UY', 'VE', 'VI', 'AG', 'AR', 'CA', 'BO', 'BS', 'BB', 'BZ', 'CL', 'CO', 'CR', 'CU', 'SV', 'GD', 'GT', 'HN', 'JM', 'NI', 'AD', 'AE', + 'AI', 'AL', 'AM', 'AO', 'AQ', 'AT', 'AW', 'AX', 'AZ', 'BA', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BV', 'BW', 'BY', 'CD', 'CF', 'CG', + 'CH', 'CI', 'CM', 'CV', 'CY', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG', 'EH', 'ER', 'ET', 'FI', 'FJ', 'FK', 'FO', 'GA', 'GE', 'GF', + 'GH', 'GI', 'GL', 'GM', 'GN', 'GQ', 'GR', 'GS', 'GU', 'GW', 'GY', 'HR', 'HT', 'HU', 'IM', 'IO', 'IQ', 'IR', 'IS', 'JO', 'KE', 'KM', 'KW', + 'KY', 'LB', 'LI', 'LR', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MD', 'ME', 'MF', 'MG', 'MK', 'ML', 'MQ', 'MR', 'MT', 'MU', 'MW', 'MZ', 'NA', + 'NC', 'NE', 'NG', 'NO', 'NR', 'PF', 'PK', 'PM', 'PS', 'RE', 'RO', 'RS', 'RU', 'RW', 'SA', 'SC', 'SD', 'SE', 'SI', 'SJ', 'SK', 'SL', + 'SM', 'SN', 'SO', 'ST', 'SY', 'SZ', 'TC', 'TD', 'TF', 'TG', 'TN', 'UA', 'UG', 'VC', 'VG', 'YE', 'YT', 'ZM', 'ZW'), + 'SG' => array('SG'), 'TH' => array('TH'), 'TR' => array('TR'), 'TW' => array('TW'), 'US' => array('US')); + + foreach ($localizations as $key => $value) + if (in_array($iso_code, $value)) + return $key; + + return $this->getCountryDependency(self::DEFAULT_COUNTRY_ISO); + } + + public function getPaymentMethods() + { + // WPS -> Web Payment Standard + // HSS -> Web Payment Pro / Integral Evolution + // ECS -> Express Checkout Solution + + $payment_method = array('AU' => array(WPS, HSS, ECS), 'BE' => array(WPS, ECS), 'CN' => array(WPS, ECS), 'CZ' => array(), 'DE' => array(WPS, ECS), + 'ES' => array(WPS, HSS, ECS), 'FR' => array(WPS, HSS, ECS), 'GB' => array(WPS, HSS, ECS), 'HK' => array(WPS, HSS, ECS), + 'IL' => array(WPS, ECS), 'IN' => array(WPS, ECS), 'IT' => array(WPS, HSS, ECS), 'JP' => array(WPS, HSS, ECS), 'MY' => array(WPS, ECS), + 'NL' => array(WPS, ECS), 'NZ' => array(WPS, ECS), 'PL' => array(WPS, ECS), 'PT' => array(WPS, ECS), 'RA' => array(WPS, ECS), 'RE' => array(WPS, ECS), + 'SG' => array(WPS, ECS), 'TH' => array(WPS, ECS), 'TR' => array(WPS, ECS), 'TW' => array(WPS, ECS), 'US' => array(WPS, ECS), + 'ZA' => array(WPS, ECS)); + + return isset($payment_method[$this->iso_code]) ? $payment_method[$this->iso_code] : $payment_method[self::DEFAULT_COUNTRY_ISO]; + } + + public function getCountryCode() + { + $cart = new Cart((int)$this->context->cookie->id_cart); + $address = new Address((int)$cart->id_address_invoice); + $country = new Country((int)$address->id_country); + + return $country->iso_code; + } + + public function displayPayPalAPIError($message, $log = false) + { + $send = true; + // Sanitize log + foreach ($log as $key => $string) + { + if ($string == 'ACK -> Success') + $send = false; + elseif (Tools::substr($string, 0, 6) == 'METHOD') + { + $values = explode('&', $string); + foreach ($values as $key2 => $value) + { + $values2 = explode('=', $value); + foreach ($values2 as $key3 => $value2) + if ($value2 == 'PWD' || $value2 == 'SIGNATURE') + $values2[$key3 + 1] = '*********'; + $values[$key2] = implode('=', $values2); + } + $log[$key] = implode('&', $values); + } + } + + $this->context->smarty->assign(array('message' => $message, 'logs' => $log)); + + if ($send) + { + $id_lang = (int)$this->context->language->id; + $iso_lang = Language::getIsoById($id_lang); + + if (!is_dir(dirname(__FILE__).'/mails/'.Tools::strtolower($iso_lang))) + $id_lang = Language::getIdByIso('en'); + + Mail::Send($id_lang, 'error_reporting', Mail::l('Error reporting from your PayPal module', + (int)$this->context->language->id), array('{logs}' => implode('
    ', $log)), Configuration::get('PS_SHOP_EMAIL'), + null, null, null, null, null, _PS_MODULE_DIR_.$this->name.'/mails/'); + } + + return $this->fetchTemplate('error.tpl'); + } + + private function _canRefund($id_order) + { + if (!(bool)$id_order) + return false; + + $paypal_order = Db::getInstance()->getRow(' + SELECT `payment_status`, `capture` + FROM `'._DB_PREFIX_.'paypal_order` + WHERE `id_order` = '.(int)$id_order); + + return $paypal_order && $paypal_order['payment_status'] == 'Completed' && $paypal_order['capture'] == 0; + } + + private function _needValidation($id_order) + { + if (!(int)$id_order) + return false; + + $order = Db::getInstance()->getRow(' + SELECT `payment_method`, `payment_status` + FROM `'._DB_PREFIX_.'paypal_order` + WHERE `id_order` = '.(int)$id_order); + + return $order && $order['payment_method'] != HSS && $order['payment_status'] == 'Pending_validation'; + } + + private function _needCapture($id_order) + { + if (!(int)$id_order) + return false; + + $result = Db::getInstance()->getRow(' + SELECT `payment_method`, `payment_status` + FROM `'._DB_PREFIX_.'paypal_order` + WHERE `id_order` = '.(int)$id_order.' AND `capture` = 1'); + + return $result && $result['payment_method'] != HSS && $result['payment_status'] == 'Pending_capture'; + } + + private function _preProcess() + { + if (Tools::isSubmit('submitPaypal')) + { + $business = Tools::getValue('business') !== false ? (int)Tools::getValue('business') : false; + $payment_method = Tools::getValue('paypal_payment_method') !== false ? (int)Tools::getValue('paypal_payment_method') : false; + $payment_capture = Tools::getValue('payment_capture') !== false ? (int)Tools::getValue('payment_capture') : false; + $sandbox_mode = Tools::getValue('sandbox_mode') !== false ? (int)Tools::getValue('sandbox_mode') : false; + + if ($this->default_country === false || $sandbox_mode === false || $payment_capture === false || $business === false || $payment_method === false) + $this->_errors[] = $this->l('Some fields are empty.'); + elseif (($business == 0 || ($business == 1 && $payment_method != HSS)) && (!Tools::getValue('api_username') || !Tools::getValue('api_password') || !Tools::getValue('api_signature'))) + $this->_errors[] = $this->l('Credentials fields cannot be empty'); + elseif ($business == 1 && $payment_method == HSS && !Tools::getValue('api_business_account')) + $this->_errors[] = $this->l('Business e-mail field cannot be empty'); + } + + return !count($this->_errors); + } + + private function _postProcess() + { + if (Tools::isSubmit('submitPaypal')) + { + if (Tools::getValue('paypal_country_only')) + Configuration::updateValue('PAYPAL_COUNTRY_DEFAULT', (int)Tools::getValue('paypal_country_only')); + elseif ($this->_preProcess()) + { + Configuration::updateValue('PAYPAL_BUSINESS', (int)Tools::getValue('business')); + Configuration::updateValue('PAYPAL_PAYMENT_METHOD', (int)Tools::getValue('paypal_payment_method')); + Configuration::updateValue('PAYPAL_API_USER', trim(Tools::getValue('api_username'))); + Configuration::updateValue('PAYPAL_API_PASSWORD', trim(Tools::getValue('api_password'))); + Configuration::updateValue('PAYPAL_API_SIGNATURE', trim(Tools::getValue('api_signature'))); + Configuration::updateValue('PAYPAL_BUSINESS_ACCOUNT', trim(Tools::getValue('api_business_account'))); + Configuration::updateValue('PAYPAL_EXPRESS_CHECKOUT_SHORTCUT', (int)Tools::getValue('express_checkout_shortcut')); + Configuration::updateValue('PAYPAL_IN_CONTEXT_CHECKOUT_M_ID', Tools::getValue('in_context_checkout_merchant_id')); + Configuration::updateValue('PAYPAL_SANDBOX', (int)Tools::getValue('sandbox_mode')); + Configuration::updateValue('PAYPAL_CAPTURE', (int)Tools::getValue('payment_capture')); + /* USE PAYPAL LOGIN */ + Configuration::updateValue('PAYPAL_LOGIN', (int)Tools::getValue('paypal_login')); + Configuration::updateValue('PAYPAL_LOGIN_CLIENT_ID', Tools::getValue('paypal_login_client_id')); + Configuration::updateValue('PAYPAL_LOGIN_SECRET', Tools::getValue('paypal_login_client_secret')); + Configuration::updateValue('PAYPAL_LOGIN_TPL', (int)Tools::getValue('paypal_login_client_template')); + /* /USE PAYPAL LOGIN */ + + /* IS IN_CONTEXT_CHECKOUT ENABLED */ + if((int)Tools::getValue('paypal_payment_method') != 2) + Configuration::updateValue('PAYPAL_IN_CONTEXT_CHECKOUT', (int)Tools::getValue('in_context_checkout')); + else + Configuration::updateValue('PAYPAL_IN_CONTEXT_CHECKOUT', 0); + /* /IS IN_CONTEXT_CHECKOUT ENABLED */ + + //EXPRESS CHECKOUT TEMPLATE + Configuration::updateValue('PAYPAL_HSS_SOLUTION', (int)Tools::getValue('integral_evolution_solution')); + if (Tools::getValue('integral_evolution_solution') == PAYPAL_HSS_IFRAME) + Configuration::updateValue('PAYPAL_HSS_TEMPLATE', 'D'); + else + Configuration::updateValue('PAYPAL_HSS_TEMPLATE', Tools::getValue('integral_evolution_template')); + $this->context->smarty->assign('PayPal_save_success', true); + } + else + { + $this->_html = $this->displayError(implode('
    ', $this->_errors)); // Not displayed at this time + $this->context->smarty->assign('PayPal_save_failure', true); + } + } + + return $this->loadLangDefault(); + } + + private function _makeRefund($id_transaction, $id_order, $amt = false) + { + if (!$this->isPayPalAPIAvailable()) + die(Tools::displayError('Fatal Error: no API Credentials are available')); + elseif (!$id_transaction) + die(Tools::displayError('Fatal Error: id_transaction is null')); + + if (!$amt) + $params = array('TRANSACTIONID' => $id_transaction, 'REFUNDTYPE' => 'Full'); + else + { + $iso_currency = Db::getInstance()->getValue(' + SELECT `iso_code` + FROM `'._DB_PREFIX_.'orders` o + LEFT JOIN `'._DB_PREFIX_.'currency` c ON (o.`id_currency` = c.`id_currency`) + WHERE o.`id_order` = '.(int)$id_order); + + $params = array('TRANSACTIONID' => $id_transaction, 'REFUNDTYPE' => 'Partial', 'AMT' => (float)$amt, 'CURRENCYCODE' => Tools::strtoupper($iso_currency)); + } + + $paypal_lib = new PaypalLib(); + + return $paypal_lib->makeCall($this->getAPIURL(), $this->getAPIScript(), 'RefundTransaction', '&'.http_build_query($params, '', '&')); + } + + public function _addNewPrivateMessage($id_order, $message) + { + if (!(bool)$id_order) + return false; + + $new_message = new Message(); + $message = strip_tags($message, '
    '); + + if (!Validate::isCleanHtml($message)) + $message = $this->l('Payment message is not valid, please check your module.'); + + $new_message->message = $message; + $new_message->id_order = (int)$id_order; + $new_message->private = 1; + + return $new_message->add(); + } + + private function _doTotalRefund($id_order) + { + $paypal_order = PayPalOrder::getOrderById((int)$id_order); + if (!$this->isPayPalAPIAvailable() || !$paypal_order) + return false; + + $order = new Order((int)$id_order); + if (!Validate::isLoadedObject($order)) + return false; + + $products = $order->getProducts(); + $currency = new Currency((int)$order->id_currency); + if (!Validate::isLoadedObject($currency)) + $this->_errors[] = $this->l('Not a valid currency'); + + if (count($this->_errors)) + return false; + + $decimals = (is_array($currency) ? (int)$currency['decimals'] : (int)$currency->decimals) * _PS_PRICE_DISPLAY_PRECISION_; + + // Amount for refund + $amt = 0.00; + + foreach ($products as $product) + $amt += (float)($product['product_price_wt']) * ($product['product_quantity'] - $product['product_quantity_refunded']); + $amt += (float)($order->total_shipping) + (float)($order->total_wrapping) - (float)($order->total_discounts); + + // check if total or partial + if (Tools::ps_round($order->total_paid_real, $decimals) == Tools::ps_round($amt, $decimals)) + $response = $this->_makeRefund($paypal_order['id_transaction'], $id_order); + else + $response = $this->_makeRefund($paypal_order['id_transaction'], $id_order, (float)($amt)); + + $message = $this->l('Refund operation result:').'
    '; + foreach ($response as $key => $value) + $message .= $key.': '.$value.'
    '; + + if (array_key_exists('ACK', $response) && $response['ACK'] == 'Success' && $response['REFUNDTRANSACTIONID'] != '') + { + $message .= $this->l('PayPal refund successful!'); + if (!Db::getInstance()->Execute('UPDATE `'._DB_PREFIX_.'paypal_order` SET `payment_status` = \'Refunded\' WHERE `id_order` = '.(int)$id_order)) + die(Tools::displayError('Error when updating PayPal database')); + + $history = new OrderHistory(); + $history->id_order = (int)$id_order; + $history->changeIdOrderState((int)Configuration::get('PS_OS_REFUND'), $history->id_order); + $history->addWithemail(); + $history->save(); + } + else + $message .= $this->l('Transaction error!'); + + $this->_addNewPrivateMessage((int)$id_order, $message); + + Tools::redirect($_SERVER['HTTP_REFERER']); + } + + private function _doCapture($id_order, $capture_amount = false, $is_complete = false) + { + $paypal_order = PayPalOrder::getOrderById((int)$id_order); + if (!$this->isPayPalAPIAvailable() || !$paypal_order) + return false; + + $order = new Order((int)$id_order); + $currency = new Currency((int)$order->id_currency); + + + + if (!$capture_amount) + $capture_amount = (float)$order->total_paid; + + $complete = 'Complete'; + if (!$is_complete) + $complete = 'NotComplete'; + + $paypal_lib = new PaypalLib(); + $response = $paypal_lib->makeCall($this->getAPIURL(), $this->getAPIScript(), 'DoCapture', + '&'.http_build_query(array('AMT' => $capture_amount, 'AUTHORIZATIONID' => $paypal_order['id_transaction'], + 'CURRENCYCODE' => $currency->iso_code, 'COMPLETETYPE' => $complete), '', '&')); + $message = $this->l('Capture operation result:').'
    '; + + foreach ($response as $key => $value) + $message .= $key.': '.$value.'
    '; + + + $capture = new PaypalCapture(); + $capture->id_order = (int)$id_order; + $capture->capture_amount = (float)$capture_amount; + + if ((array_key_exists('ACK', $response)) && ($response['ACK'] == 'Success') && ($response['PAYMENTSTATUS'] == 'Completed')) + { + $capture->result = pSQL($response['PAYMENTSTATUS']); + if ($capture->save()) + { + if (!($capture->getRestToCapture($capture->id_order))) + { + //plus d'argent a capturer + if (!Db::getInstance()->Execute(' + UPDATE `'._DB_PREFIX_.'paypal_order` + SET `capture` = 0, `payment_status` = \''.pSQL($response['PAYMENTSTATUS']).'\', `id_transaction` = \''.pSQL($response['TRANSACTIONID']).'\' + WHERE `id_order` = '.(int)$id_order)) + die(Tools::displayError('Error when updating PayPal database')); + + $order_history = new OrderHistory(); + $order_history->id_order = (int)$id_order; + + if (version_compare(_PS_VERSION_, '1.5', '<')) + $order_history->changeIdOrderState(Configuration::get('PS_OS_WS_PAYMENT'), (int)$id_order); + else + $order_history->changeIdOrderState(Configuration::get('PS_OS_WS_PAYMENT'), $order); + $order_history->addWithemail(); + $message .= $this->l('Order finished with PayPal!'); + } + } + } + elseif (isset($response['PAYMENTSTATUS'])) + { + $capture->result = pSQL($response['PAYMENTSTATUS']); + $capture->save(); + $message .= $this->l('Transaction error!'); + } + + + $this->_addNewPrivateMessage((int)$id_order, $message); + + Tools::redirect($_SERVER['HTTP_REFERER']); + } + + private function _updatePaymentStatusOfOrder($id_order) + { + if (!(bool)$id_order || !$this->isPayPalAPIAvailable()) + return false; + + $paypal_order = PayPalOrder::getOrderById((int)$id_order); + if (!$paypal_order) + return false; + + $paypal_lib = new PaypalLib(); + $response = $paypal_lib->makeCall($this->getAPIURL(), $this->getAPIScript(), 'GetTransactionDetails', + '&'.http_build_query(array('TRANSACTIONID' => $paypal_order['id_transaction']), '', '&')); + + if (array_key_exists('ACK', $response)) + { + if ($response['ACK'] == 'Success' && isset($response['PAYMENTSTATUS'])) + { + $history = new OrderHistory(); + $history->id_order = (int)$id_order; + + if ($response['PAYMENTSTATUS'] == 'Completed') + $history->changeIdOrderState(Configuration::get('PS_OS_PAYMENT'), (int)$id_order); + elseif (($response['PAYMENTSTATUS'] == 'Pending') && ($response['PENDINGREASON'] == 'authorization')) + $history->changeIdOrderState((int)(Configuration::get('PAYPAL_OS_AUTHORIZATION')), (int)$id_order); + elseif ($response['PAYMENTSTATUS'] == 'Reversed') + $history->changeIdOrderState(Configuration::get('PS_OS_ERROR'), (int)$id_order); + $history->addWithemail(); + + if (!Db::getInstance()->Execute(' + UPDATE `'._DB_PREFIX_.'paypal_order` + SET `payment_status` = \''.pSQL($response['PAYMENTSTATUS']).($response['PENDINGREASON'] == 'authorization' ? '_authorization' : '').'\' + WHERE `id_order` = '.(int)$id_order)) + die(Tools::displayError('Error when updating PayPal database')); + } + + $message = $this->l('Verification status :').'
    '; + $this->formatMessage($response, $message); + $this->_addNewPrivateMessage((int)$id_order, $message); + + return $response; + } + + return false; + } + + public function fetchTemplate($name) + { + if (version_compare(_PS_VERSION_, '1.4', '<')) + $this->context->smarty->currentTemplate = $name; + elseif (version_compare(_PS_VERSION_, '1.5', '<')) + { + $views = 'views/templates/'; + if (@filemtime(dirname(__FILE__).'/'.$name)) + return $this->display(__FILE__, $name); + elseif (@filemtime(dirname(__FILE__).'/'.$views.'hook/'.$name)) + return $this->display(__FILE__, $views.'hook/'.$name); + elseif (@filemtime(dirname(__FILE__).'/'.$views.'front/'.$name)) + return $this->display(__FILE__, $views.'front/'.$name); + elseif (@filemtime(dirname(__FILE__).'/'.$views.'admin/'.$name)) + return $this->display(__FILE__, $views.'admin/'.$name); + } + + return $this->display(__FILE__, $name); + } + + public static function getPayPalCustomerIdByEmail($email) + { + return Db::getInstance()->getValue(' + SELECT `id_customer` + FROM `'._DB_PREFIX_.'paypal_customer` + WHERE paypal_email = \''.pSQL($email).'\''); + } + + public static function getPayPalEmailByIdCustomer($id_customer) + { + return Db::getInstance()->getValue(' + SELECT `paypal_email` + FROM `'._DB_PREFIX_.'paypal_customer` + WHERE `id_customer` = '.(int)$id_customer); + } + + public static function addPayPalCustomer($id_customer, $email) + { + if (!PayPal::getPayPalEmailByIdCustomer($id_customer)) + { + Db::getInstance()->Execute(' + INSERT INTO `'._DB_PREFIX_.'paypal_customer` (`id_customer`, `paypal_email`) + VALUES('.(int)$id_customer.', \''.pSQL($email).'\')'); + + return Db::getInstance()->Insert_ID(); + } + + return false; + } + + private function warningsCheck() + { + if (Configuration::get('PAYPAL_PAYMENT_METHOD') == HSS && Configuration::get('PAYPAL_BUSINESS_ACCOUNT') == 'paypal@prestashop.com') + $this->warning = $this->l('You are currently using the default PayPal e-mail address, please enter your own e-mail address.').'
    '; + + /* Check preactivation warning */ + if (Configuration::get('PS_PREACTIVATION_PAYPAL_WARNING')) + $this->warning .= (!empty($this->warning)) ? ', ' : Configuration::get('PS_PREACTIVATION_PAYPAL_WARNING').'
    '; + + if (!function_exists('curl_init')) + $this->warning .= $this->l('In order to use your module, please activate cURL (PHP extension)'); + } + + private function loadLangDefault() + { + $paypal_country_default = (int)Configuration::get('PAYPAL_COUNTRY_DEFAULT'); + $this->default_country = ($paypal_country_default ? (int)$paypal_country_default : (int)Configuration::get('PS_COUNTRY_DEFAULT')); + $this->iso_code = $this->getCountryDependency(Tools::strtoupper($this->context->language->iso_code)); + } + + public function formatMessage($response, &$message) + { + foreach ($response as $key => $value) + $message .= $key.': '.$value.'
    '; + } + + private function checkCurrency($cart) + { + $currency_module = $this->getCurrency((int)$cart->id_currency); + + if ((int)$cart->id_currency == (int)$currency_module->id) + return true; + else + return false; + } + + public static function getShopDomainSsl($http = false, $entities = false) + { + if (method_exists('Tools', 'getShopDomainSsl')) + return Tools::getShopDomainSsl($http, $entities); + else + { + if (!($domain = Configuration::get('PS_SHOP_DOMAIN_SSL'))) + $domain = self::getHttpHost(); + if ($entities) + $domain = htmlspecialchars($domain, ENT_COMPAT, 'UTF-8'); + if ($http) + $domain = (Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://').$domain; + return $domain; + } + } + + public function validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method = 'Unknown', $message = null, $transaction = array(), $currency_special = null, $dont_touch_amount = false, $secure_key = false, Shop $shop = null) + { + if ($this->active) + { + // Set transaction details if pcc is defined in PaymentModule class_exists + if (isset($this->pcc)) + $this->pcc->transaction_id = (isset($transaction['transaction_id']) ? $transaction['transaction_id'] : ''); + + if (version_compare(_PS_VERSION_, '1.5', '<')) + parent::validateOrder((int)$id_cart, (int)$id_order_state, (float)$amount_paid, $payment_method, $message, $transaction, $currency_special, $dont_touch_amount, $secure_key); + else + parent::validateOrder((int)$id_cart, (int)$id_order_state, (float)$amount_paid, $payment_method, $message, $transaction, $currency_special, $dont_touch_amount, $secure_key, $shop); + + if (count($transaction) > 0) + PayPalOrder::saveOrder((int)$this->currentOrder, $transaction); + + $this->setPayPalAsConfigured(); + } + } + + protected function getGiftWrappingPrice() + { + if (version_compare(_PS_VERSION_, '1.5.3.0', '>=')) + $wrapping_fees_tax_inc = $this->context->cart->getGiftWrappingPrice(); + else + { + $wrapping_fees = (float)(Configuration::get('PS_GIFT_WRAPPING_PRICE')); + $wrapping_fees_tax = new Tax((int)(Configuration::get('PS_GIFT_WRAPPING_TAX'))); + $wrapping_fees_tax_inc = $wrapping_fees * (1 + (((float)($wrapping_fees_tax->rate) / 100))); + } + + return (float)Tools::convertPrice($wrapping_fees_tax_inc, $this->context->currency); + } + + public function redirectToConfirmation() + { + $shop_url = PayPal::getShopDomainSsl(true, true); + + // Check if user went through the payment preparation detail and completed it + $detail = unserialize($this->context->cookie->express_checkout); + + if (!empty($detail['payer_id']) && !empty($detail['token'])) + { + $values = array('get_confirmation' => true); + $link = $shop_url._MODULE_DIR_.$this->name.'/express_checkout/payment.php'; + + if (version_compare(_PS_VERSION_, '1.5', '<')) + Tools::redirectLink($link.'?'.http_build_query($values, '', '&')); + else + Tools::redirect(Context::getContext()->link->getModuleLink('paypal', 'confirm', $values)); + } + } + + /** + * Check if the current page use SSL connection on not + * + * @return bool uses SSL + */ + public function usingSecureMode() + { + if (isset($_SERVER['HTTPS'])) + return ($_SERVER['HTTPS'] == 1 || Tools::strtolower($_SERVER['HTTPS']) == 'on'); + // $_SERVER['SSL'] exists only in some specific configuration + if (isset($_SERVER['SSL'])) + return ($_SERVER['SSL'] == 1 || Tools::strtolower($_SERVER['SSL']) == 'on'); + + return false; + } + + protected function getCurrentUrl() + { + $protocol_link = $this->usingSecureMode() ? 'https://' : 'http://'; + $request = $_SERVER['REQUEST_URI']; + $pos = strpos($request, '?'); + + if (($pos !== false) && ($pos >= 0)) + $request = Tools::substr($request, 0, $pos); + + $params = urlencode($_SERVER['QUERY_STRING']); + + return $protocol_link.Tools::getShopDomainSsl().$request.'?'.$params; + } + + /** + * Use $this->comp instead of bccomp which is not added in all versions of PHP + * @param float $num1 number 1 to compare + * @param float $num2 number 2 to compare + * @param [type] $scale [description] + */ + public function comp($num1, $num2, $scale = null) + { + // check if they're valid positive numbers, extract the whole numbers and decimals + if (!preg_match("/^\+?(\d+)(\.\d+)?$/", $num1, $tmp1) || !preg_match("/^\+?(\d+)(\.\d+)?$/", $num2, $tmp2)) + return ('0'); + + // remove leading zeroes from whole numbers + $num1 = ltrim($tmp1[1], '0'); + $num2 = ltrim($tmp2[1], '0'); + + // first, we can just check the lengths of the numbers, this can help save processing time + // if $num1 is longer than $num2, return 1.. vice versa with the next step. + if (Tools::strlen($num1) > Tools::strlen($num2)) + return 1; + else + { + if (Tools::strlen($num1) < Tools::strlen($num2)) + return -1; + + // if the two numbers are of equal length, we check digit-by-digit + else + { + + // remove ending zeroes from decimals and remove point + $dec1 = isset($tmp1[2]) ? rtrim(Tools::substr($tmp1[2], 1), '0') : ''; + $dec2 = isset($tmp2[2]) ? rtrim(Tools::substr($tmp2[2], 1), '0') : ''; + + // if the user defined $scale, then make sure we use that only + if ($scale != null) + { + $dec1 = Tools::substr($dec1, 0, $scale); + $dec2 = Tools::substr($dec2, 0, $scale); + } + + // calculate the longest length of decimals + $d_len = max(Tools::strlen($dec1), Tools::strlen($dec2)); + + // append the padded decimals onto the end of the whole numbers + $num1 .= str_pad($dec1, $d_len, '0'); + $num2 .= str_pad($dec2, $d_len, '0'); + + // check digit-by-digit, if they have a difference, return 1 or -1 (greater/lower than) + for ($i = 0; $i < Tools::strlen($num1); $i++) + { + if ((int)$num1{$i} > (int)$num2{$i}) + return 1; + elseif ((int)$num1{$i} < (int)$num2{$i}) + return -1; + } + + // if the two numbers have no difference (they're the same).. return 0 + return 0; + } + } + } +} diff --git a/modules/paypal/paypal_install.php b/modules/paypal/paypal_install.php new file mode 100644 index 00000000..84fc32e4 --- /dev/null +++ b/modules/paypal/paypal_install.php @@ -0,0 +1,186 @@ + + * @copyright 2007-2015 PrestaShop SA + * @version Release: $Revision: 14390 $ + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +if (!defined('_PS_VERSION_')) + exit; + +class PayPalInstall +{ + /** + * Create PayPal tables + */ + public function createTables() + { + /* Set database */ + if (!Db::getInstance()->Execute(' + CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'paypal_order` ( + `id_order` int(10) unsigned NOT NULL, + `id_transaction` varchar(255) NOT NULL, + `id_invoice` varchar(255) DEFAULT NULL, + `currency` varchar(10) NOT NULL, + `total_paid` varchar(50) NOT NULL, + `shipping` varchar(50) NOT NULL, + `capture` int(2) NOT NULL, + `payment_date` varchar(50) NOT NULL, + `payment_method` int(2) unsigned NOT NULL, + `payment_status` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id_order`) + ) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8')) + return false; + + /* Set database */ + if (!Db::getInstance()->Execute(' + CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'paypal_customer` ( + `id_paypal_customer` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id_customer` int(10) unsigned NOT NULL, + `paypal_email` varchar(255) NOT NULL, + PRIMARY KEY (`id_paypal_customer`) + ) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8 AUTO_INCREMENT=1')) + return false; + + if (!Db::getInstance()->Execute(' + CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'paypal_login_user` ( + `id_paypal_login_user` INT(11) AUTO_INCREMENT, + `id_customer` INT(11) NOT NULL, + `token_type` VARCHAR(255) NOT NULL, + `expires_in` VARCHAR(255) NOT NULL, + `refresh_token` VARCHAR(255) NOT NULL, + `id_token` VARCHAR(255) NOT NULL, + `access_token` VARCHAR(255) NOT NULL, + `account_type` VARCHAR(255) NOT NULL, + `user_id` VARCHAR(255) NOT NULL, + `verified_account` VARCHAR(255) NOT NULL, + `zoneinfo` VARCHAR(255) NOT NULL, + `age_range` VARCHAR(255) NOT NULL, + PRIMARY KEY (`id_paypal_login_user`) + ) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8')) + return false; + if (!Db::getInstance()->Execute(' + CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'paypal_capture` ( + `id_paypal_capture` int(11) NOT NULL AUTO_INCREMENT, + `id_order` int(11) NOT NULL, + `capture_amount` float NOT NULL, + `result` text NOT NULL, + `date_add` datetime NOT NULL, + `date_upd` datetime NOT NULL, + PRIMARY KEY (`id_paypal_capture`) + ) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;')) + return false; + + } + + /** + * Set configuration table + */ + public function updateConfiguration($paypal_version) + { + Configuration::updateValue('PAYPAL_SANDBOX', 0); + Configuration::updateValue('PAYPAL_HEADER', ''); + Configuration::updateValue('PAYPAL_BUSINESS', 0); + Configuration::updateValue('PAYPAL_BUSINESS_ACCOUNT', 'paypal@prestashop.com'); + Configuration::updateValue('PAYPAL_API_USER', ''); + Configuration::updateValue('PAYPAL_API_PASSWORD', ''); + Configuration::updateValue('PAYPAL_API_SIGNATURE', ''); + Configuration::updateValue('PAYPAL_EXPRESS_CHECKOUT', 0); + Configuration::updateValue('PAYPAL_CAPTURE', 0); + Configuration::updateValue('PAYPAL_PAYMENT_METHOD', WPS); + Configuration::updateValue('PAYPAL_NEW', 1); + Configuration::updateValue('PAYPAL_DEBUG_MODE', 0); + Configuration::updateValue('PAYPAL_SHIPPING_COST', 20.00); + Configuration::updateValue('PAYPAL_VERSION', $paypal_version); + Configuration::updateValue('PAYPAL_COUNTRY_DEFAULT', (int)Configuration::get('PS_COUNTRY_DEFAULT')); + + // PayPal v3 configuration + Configuration::updateValue('PAYPAL_EXPRESS_CHECKOUT_SHORTCUT', 1); + } + + /** + * Delete PayPal configuration + */ + public function deleteConfiguration() + { + Configuration::deleteByName('PAYPAL_SANDBOX'); + Configuration::deleteByName('PAYPAL_HEADER'); + Configuration::deleteByName('PAYPAL_BUSINESS'); + Configuration::deleteByName('PAYPAL_API_USER'); + Configuration::deleteByName('PAYPAL_API_PASSWORD'); + Configuration::deleteByName('PAYPAL_API_SIGNATURE'); + Configuration::deleteByName('PAYPAL_BUSINESS_ACCOUNT'); + Configuration::deleteByName('PAYPAL_EXPRESS_CHECKOUT'); + Configuration::deleteByName('PAYPAL_PAYMENT_METHOD'); + Configuration::deleteByName('PAYPAL_TEMPLATE'); + Configuration::deleteByName('PAYPAL_CAPTURE'); + Configuration::deleteByName('PAYPAL_DEBUG_MODE'); + Configuration::deleteByName('PAYPAL_COUNTRY_DEFAULT'); + Configuration::deleteByName('PAYPAL_VERSION'); + + /* USE PAYPAL LOGIN */ + Configuration::deleteByName('PAYPAL_LOGIN'); + Configuration::deleteByName('PAYPAL_LOGIN_CLIENT_ID'); + Configuration::deleteByName('PAYPAL_LOGIN_SECRET'); + Configuration::deleteByName('PAYPAL_LOGIN_TPL'); + /* /USE PAYPAL LOGIN */ + + // PayPal v3 configuration + Configuration::deleteByName('PAYPAL_EXPRESS_CHECKOUT_SHORTCUT'); + } + + /** + * Create a new order state + */ + public function createOrderState() + { + if (!Configuration::get('PAYPAL_OS_AUTHORIZATION')) + { + $order_state = new OrderState(); + $order_state->name = array(); + + foreach (Language::getLanguages() as $language) + { + if (Tools::strtolower($language['iso_code']) == 'fr') + $order_state->name[$language['id_lang']] = 'Autorisation acceptée par PayPal'; + else + $order_state->name[$language['id_lang']] = 'Authorization accepted from PayPal'; + } + + $order_state->send_email = false; + $order_state->color = '#DDEEFF'; + $order_state->hidden = false; + $order_state->delivery = false; + $order_state->logable = true; + $order_state->invoice = true; + + if ($order_state->add()) + { + $source = dirname(__FILE__).'/../../img/os/'.Configuration::get('PS_OS_PAYPAL').'.gif'; + $destination = dirname(__FILE__).'/../../img/os/'.(int)$order_state->id.'.gif'; + copy($source, $destination); + } + Configuration::updateValue('PAYPAL_OS_AUTHORIZATION', (int)$order_state->id); + } + } +} diff --git a/modules/paypal/paypal_login/PayPalLoginUser.php b/modules/paypal/paypal_login/PayPalLoginUser.php new file mode 100644 index 00000000..d55bf6b3 --- /dev/null +++ b/modules/paypal/paypal_login/PayPalLoginUser.php @@ -0,0 +1,135 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +if (!defined('_PS_VERSION_')) + die(header('HTTP/1.0 404 Not Found')); + +/** + * Description of totRules + * + * @author 202-ecommerce + */ +class PaypalLoginUser extends ObjectModel { + + public $id_customer; + public $token_type; + public $expires_in; + public $refresh_token; + public $id_token; + public $access_token; + public $account_type; + public $user_id; + public $verified_account; + public $zoneinfo; + public $age_range; + + protected $table = 'paypal_login_user'; + protected $identifier = 'id_paypal_login_user'; + protected $fieldsRequired = array( + 'id_customer', + 'token_type', + 'expires_in', + 'refresh_token', + 'id_token', + 'access_token', + 'user_id', + 'verified_account', + 'zoneinfo', + ); + + protected $fieldsValidate = array( + 'id_customer' => 'isInt', + 'token_type' => 'isString', + 'expires_in' => 'isString', + 'refresh_token' => 'isString', + 'id_token' => 'isString', + 'access_token' => 'isString', + 'account_type' => 'isString', + 'user_id' => 'isString', + 'verified_account' => 'isString', + 'zoneinfo' => 'isString', + 'age_range' => 'isString', + + ); + + public function __construct($id = false, $id_lang = false) + { + parent::__construct($id, $id_lang); + } + + public function getFields() + { + parent::validateFields(); + $fields = array(); + foreach (array_keys($this->fieldsValidate) as $field) + $fields[$field] = $this->$field; + return $fields; + } + + public static function getPaypalLoginUsers($id_paypal_login_user = false, $id_customer = false, $refresh_token = false) + { + $sql = " + SELECT `id_paypal_login_user` + FROM `"._DB_PREFIX_."paypal_login_user` + WHERE 1 + "; + + if ($id_paypal_login_user && Validate::isInt($id_paypal_login_user)) + $sql .= " AND `id_paypal_login_user` = '".(int)$id_paypal_login_user."' "; + + if ($id_customer && Validate::isInt($id_customer)) + $sql .= " AND `id_customer` = '".(int)$id_customer."' "; + + if ($refresh_token) + $sql .= " AND `refresh_token` = '".$refresh_token."' "; + + $results = DB::getInstance()->executeS($sql); + $logins = array(); + + if ($results && count($results)) + { + foreach ($results as $result) + $logins[$result['id_paypal_login_user']] = new PaypalLoginUser((int)$result['id_paypal_login_user']); + } + + return $logins; + } + + public static function getByIdCustomer($id_customer) + { + $login = self::getPaypalLoginUsers(false, $id_customer); + + if ($login && count($login)) + $login = current($login); + else + $login = false; + + return $login; + } +} + + +?> \ No newline at end of file diff --git a/modules/paypal/paypal_login/index.php b/modules/paypal/paypal_login/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/paypal_login/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/paypal_login/paypal_login.php b/modules/paypal/paypal_login/paypal_login.php new file mode 100644 index 00000000..71a0c5aa --- /dev/null +++ b/modules/paypal/paypal_login/paypal_login.php @@ -0,0 +1,243 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +class PayPalLogin +{ + private $_logs = array(); + private $enable_log = false; + + private $paypal_connect = null; + + public function __construct() + { + $this->paypal_connect = new PayPalConnect(); + } + + public function getIdentityAPIURL() + { + if (Configuration::get('PAYPAL_SANDBOX')) + //return 'www.sandbox.paypal.com'; + return 'api.sandbox.paypal.com'; + else + return 'api.paypal.com'; + } + + public function getTokenServiceEndpoint() + { + if (Configuration::get('PAYPAL_SANDBOX')) + // return '/webapps/auth/protocol/openidconnect/v1/tokenservice'; + return '/v1/identity/openidconnect/tokenservice'; + else + return '/v1/identity/openidconnect/tokenservice'; + } + + public function getUserInfoEndpoint() + { + return '/v1/identity/openidconnect/userinfo'; + } + + public static function getReturnLink() + { + // return 'http://requestb.in/1jlaizq1'; + if (method_exists(Context::getContext()->shop, 'getBaseUrl')) + return Context::getContext()->shop->getBaseUrl().'modules/paypal/paypal_login/paypal_login_token.php'; + else + return 'http://'.Configuration::get('PS_SHOP_DOMAIN').'/modules/paypal/paypal_login/paypal_login_token.php'; + } + + + + public function getAuthorizationCode() + { + unset($this->_logs); + + if (Context::getContext()->cookie->isLogged()) + return $this->getRefreshToken(); + + $params = array( + 'grant_type' => 'authorization_code', + 'code' => Tools::getValue('code'), + 'redirect_url' => PayPalLogin::getReturnLink() + ); + + $request = http_build_query($params, '', '&'); + $result = $this->paypal_connect->makeConnection($this->getIdentityAPIURL(), $this->getTokenServiceEndpoint(), $request, false, false, true); + + if ($this->enable_log === true) + { + $handle = fopen(dirname(__FILE__).'/Results.txt', 'a+'); + fwrite($handle, "Request => ".print_r($request, true)."\r\n"); + fwrite($handle, "Result => ".print_r($result, true)."\r\n"); + fwrite($handle, "Journal => ".print_r($this->_logs, true."\r\n")); + fclose($handle); + } + + $result = Tools::jsonDecode($result); + + if ($result) + { + + $login = new PayPalLoginUser(); + + $customer = $this->getUserInformations($result->access_token, $login); + + if (!$customer) + return false; + + $temp = PaypalLoginUser::getByIdCustomer((int)Context::getContext()->customer->id); + + if ($temp) + $login = $temp; + + $login->id_customer = $customer->id; + $login->token_type = $result->token_type; + $login->expires_in = (string)(time() + (int)$result->expires_in); + $login->refresh_token = $result->refresh_token; + $login->id_token = $result->id_token; + $login->access_token = $result->access_token; + + $login->save(); + + return $login; + } + } + + public function getRefreshToken() + { + unset($this->_logs); + $login = PaypalLoginUser::getByIdCustomer((int)Context::getContext()->customer->id); + + if (!is_object($login)) + return false; + + $params = array( + 'grant_type' => 'refresh_token', + 'refresh_token' => $login->refresh_token + ); + + $request = http_build_query($params, '', '&'); + $result = $this->paypal_connect->makeConnection($this->getIdentityAPIURL(), $this->getTokenServiceEndpoint(), $request, false, false, true); + + if ($this->enable_log === true) + { + $handle = fopen(dirname(__FILE__).'/Results.txt', 'a+'); + fwrite($handle, "Request => ".print_r($request, true)."\r\n"); + fwrite($handle, "Result => ".print_r($result, true)."\r\n"); + fwrite($handle, "Journal => ".print_r($this->_logs, true."\r\n")); + fclose($handle); + } + + $result = Tools::jsonDecode($result); + + if ($result) + { + $login->access_token = $result->access_token; + $login->expires_in = (string)(time() + $result->expires_in); + $login->save(); + return $login; + } + + return false; + } + + private function getUserInformations($access_token, &$login) + { + unset($this->_logs); + $headers = array( + // 'Content-Type:application/json', + 'Authorization: Bearer '.$access_token + ); + + $params = array( + 'schema' => 'openid' + ); + + $request = http_build_query($params, '', '&'); + $result = $this->paypal_connect->makeConnection($this->getIdentityAPIURL(), $this->getUserInfoEndpoint(), $request, false, $headers, true); + + if ($this->enable_log === true) + { + $handle = fopen(dirname(__FILE__).'/Results.txt', 'a+'); + fwrite($handle, "Request => ".print_r($request, true)."\r\n"); + fwrite($handle, "Result => ".print_r($result, true)."\r\n"); + fwrite($handle, "Headers => ".print_r($headers, true)."\r\n"); + fwrite($handle, "Journal => ".print_r($this->_logs, true."\r\n")); + fclose($handle); + } + + $result = Tools::jsonDecode($result); + + if ($result) + { + $customer = new Customer(); + $customer = $customer->getByEmail($result->email); + + if (!$customer) + $customer = $this->setCustomer($result); + + $login->account_type = $result->account_type; + $login->user_id = $result->user_id; + $login->verified_account = $result->verified_account; + $login->zoneinfo = $result->zoneinfo; + $login->age_range = $result->age_range; + + return $customer; + } + + return false; + } + + + private function setCustomer($result) + { + $customer = new Customer(); + $customer->firstname = $result->given_name; + $customer->lastname = $result->family_name; + if (version_compare(_PS_VERSION_, '1.5.0', '>')) + $customer->id_lang = Language::getIdByIso(strstr($result->language, '_', true)); + $customer->birthday = $result->birthday; + $customer->email = $result->email; + $customer->passwd = Tools::encrypt(Tools::passwdGen()); + $customer->save(); + + $result_address = $result->address; + + $address = new Address(); + $address->id_customer = $customer->id; + $address->id_country = Country::getByIso($result_address->country); + $address->alias = 'My address'; + $address->lastname = $customer->lastname; + $address->firstname = $customer->firstname; + $address->address1 = $result_address->street_address; + $address->postcode = $result_address->postal_code; + $address->city = $result_address->locality; + $address->phone = $result->phone_number; + + $address->save(); + + return $customer; + } +} diff --git a/modules/paypal/paypal_login/paypal_login_token.php b/modules/paypal/paypal_login/paypal_login_token.php new file mode 100644 index 00000000..6eea36fe --- /dev/null +++ b/modules/paypal/paypal_login/paypal_login_token.php @@ -0,0 +1,59 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header('Content-Type: text/html; charset=utf-8'); +include_once(dirname(__FILE__).'/../../../config/config.inc.php'); +include_once(dirname(__FILE__).'/../../../init.php'); + +include_once(_PS_MODULE_DIR_.'paypal/paypal.php'); +include_once(_PS_MODULE_DIR_.'paypal/paypal_login/paypal_login.php'); +include_once(_PS_MODULE_DIR_.'paypal/paypal_login/PayPalLoginUser.php'); + +$login = new PayPalLogin(); + +$obj = $login->getAuthorizationCode(); +if ($obj) +{ + $context = Context::getContext(); + $customer = new Customer((int)$obj->id_customer); + $context->cookie->id_customer = (int)($customer->id); + $context->cookie->customer_lastname = $customer->lastname; + $context->cookie->customer_firstname = $customer->firstname; + $context->cookie->logged = 1; + $customer->logged = 1; + $context->cookie->is_guest = $customer->isGuest(); + $context->cookie->passwd = $customer->passwd; + $context->cookie->email = $customer->email; + $context->customer = $customer; + $context->cookie->write(); +} + +?> + + \ No newline at end of file diff --git a/modules/paypal/paypal_logos.php b/modules/paypal/paypal_logos.php new file mode 100644 index 00000000..e9280659 --- /dev/null +++ b/modules/paypal/paypal_logos.php @@ -0,0 +1,148 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +if (!defined('_PS_VERSION_')) + exit; + +class PayPalLogos +{ + private $iso_code = null; + + const LOCAL = 'Local'; + const HORIZONTAL = 'Horizontal'; + const VERTICAL = 'Vertical'; + + public function __construct($iso_code) + { + $this->iso_code = $iso_code; + } + + public function getLogos() + { + $file = dirname(__FILE__).'/'._PAYPAL_LOGO_XML_; + + if (!file_exists($file)) + return false; + + $xml = simplexml_load_file($file); + $logos = array(); + + if (isset($xml) && $xml != false) + { + foreach ($xml->country as $item) + { + $tmp_iso_code = (string)$item->attributes()->iso_code; + $logos[$tmp_iso_code] = (array)$item; + } + + if (!isset($logos[$this->iso_code])) + $result = $this->getLocalLogos($logos['default'], 'default'); + else + $result = $this->getLocalLogos($logos[$this->iso_code], $this->iso_code); + + $result['default'] = $this->getLocalLogos($logos['default'], 'default'); + + return $result; + } + + return false; + } + + public function getCardsLogo($vertical = false) + { + $logos = $this->getLogos(); + + $orientation = $vertical === true ? self::VERTICAL : self::HORIZONTAL; + $logo_ref = self::LOCAL.'PayPal'.$orientation.'SolutionPP'; + + if (array_key_exists($logo_ref, $logos)) + return $logos[$logo_ref]; + elseif (($vertical !== false) && isset($logos[self::LOCAL.'PayPal'.self::HORIZONTAL.'SolutionPP'])) + return $logos[self::LOCAL.'PayPal'.self::HORIZONTAL.'SolutionPP']; + + if (isset($logos['default'][self::LOCAL.'Local'.$orientation.'SolutionPP'])) + return _MODULE_DIR_._PAYPAL_MODULE_DIRNAME_.$logos['default'][self::LOCAL.'Local'.$orientation.'SolutionPP']; + + return false; + } + + public function getLocalLogos(array $values, $iso_code) + { + foreach ($values as $key => $value) + if (!is_array($value)) + { + // Search for image file name + preg_match('#.*/([\w._-]*)$#', $value, $logo); + + if ((count($logo) == 2) && (strstr($key, 'Local') === false)) + { + $destination = _PAYPAL_MODULE_DIRNAME_.'/views/img/logos/'.$iso_code.'_'.$logo[1]; + $this->updatePictures($logo[0], $destination); + + // Define the local path after picture have been downloaded + $values['Local'.$key] = _MODULE_DIR_.$destination; + + // Load back office cards path + if (file_exists(dirname(__FILE__).'/views/img/bo-cards/'.Tools::strtoupper($iso_code).'_bo_cards.png')) + $values['BackOfficeCards'] = _MODULE_DIR_._PAYPAL_MODULE_DIRNAME_.'/views/img/bo-cards/'.Tools::strtoupper($iso_code).'_bo_cards.png'; + else if (file_exists(dirname(__FILE__).'/views/img/bo-cards/default.png')) + $values['BackOfficeCards'] = _MODULE_DIR_._PAYPAL_MODULE_DIRNAME_.'/views/img/bo-cards/default.png'; + } + // Use the local version + else if (isset($values['Local'.$key])) + $values['Local'.$key] = _MODULE_DIR_._PAYPAL_MODULE_DIRNAME_.$values['Local'.$key]; + } + + return $values; + } + + private function updatePictures($source, $destination, $force = false) + { + $wrappers = stream_get_wrappers(); + $https_wrapper = in_array('https', $wrappers) ? true : false; + + // 604800 => One week timestamp + if (!file_exists(_PS_MODULE_DIR_.$destination) || ((time() - filemtime(_PS_MODULE_DIR_.$destination)) > 604800) || $force) + { + $picture = Tools::file_get_contents($source); + if ((bool)$picture !== false) + { + if ($handle = @fopen(_PS_MODULE_DIR_.$destination, 'w+')) + { + $size = fwrite($handle, $picture); + if ($size > 0 || (file_exists(_MODULE_DIR_.$destination) && (@filesize(_MODULE_DIR_.$destination) > 0))) + return _MODULE_DIR_.$destination; + } + } + elseif (strstr($source, 'https')) + return $this->updatePictures(str_replace('https', 'http', $source), $destination); + else + return false; + } + + return _MODULE_DIR_.$destination; + } +} diff --git a/modules/paypal/paypal_orders.php b/modules/paypal/paypal_orders.php new file mode 100644 index 00000000..c0cd00cc --- /dev/null +++ b/modules/paypal/paypal_orders.php @@ -0,0 +1,152 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +if (!defined('_PS_VERSION_')) + exit; + +/* + * PayPal notification fields + */ +define('ID_INVOICE', 'invoice'); +define('ID_PAYER', 'payer_id'); +define('ID_TRANSACTION', 'txn_id'); +define('CURRENCY', 'mc_currency'); +define('PAYER_EMAIL', 'payer_email'); +define('PAYMENT_DATE', 'payment_date'); +define('TOTAL_PAID', 'mc_gross'); +define('SHIPPING', 'shipping'); +define('VERIFY_SIGN', 'verify_sign'); + +class PayPalOrder +{ + /* + * Get PayPal order data + * - ID Order + * - ID Transaction + * - ID Invoice + * - Currency (ISO) + * - Total paid + * - Shipping + * - Capture (bool) + * - Payment date + * - Payment method (int) + * - Payment status + */ + + public static function getTransactionDetails($ppec = false, $payment_status = false) + { + if ($ppec && $payment_status) + { + $transaction_id = pSQL($ppec->result['PAYMENTINFO_0_TRANSACTIONID']); + return array( + 'currency' => pSQL($ppec->result['PAYMENTINFO_0_CURRENCYCODE']), + 'id_invoice' => null, + 'id_transaction' => $transaction_id, + 'transaction_id' => $transaction_id, + 'total_paid' => (float)$ppec->result['PAYMENTINFO_0_AMT'], + 'shipping' => (float)$ppec->result['PAYMENTREQUEST_0_SHIPPINGAMT'], + 'payment_date' => pSQL($ppec->result['PAYMENTINFO_0_ORDERTIME']), + 'payment_status' => pSQL($payment_status) + ); + } + else + { + $transaction_id = pSQL(Tools::getValue(ID_TRANSACTION)); + return array( + 'currency' => pSQL(Tools::getValue(CURRENCY)), + 'id_invoice' => pSQL(Tools::getValue(ID_INVOICE)), + 'id_transaction' => $transaction_id, + 'transaction_id' => $transaction_id, + 'total_paid' => (float)Tools::getValue(TOTAL_PAID), + 'shipping' => (float)Tools::getValue(SHIPPING), + 'payment_date' => pSQL(Tools::getValue(PAYMENT_DATE)), + 'payment_status' => pSQL($payment_status) + ); + } + } + + public static function getOrderById($id_order) + { + return Db::getInstance()->getRow( + 'SELECT * FROM `'._DB_PREFIX_.'paypal_order` + WHERE `id_order` = '.(int)$id_order + ); + } + + public static function getIdOrderByTransactionId($id_transaction) + { + $sql = 'SELECT `id_order` + FROM `'._DB_PREFIX_.'paypal_order` + WHERE `id_transaction` = \''.pSQL($id_transaction).'\''; + + $result = Db::getInstance()->getRow($sql); + + if ($result != false) + return (int)$result['id_order']; + return 0; + } + + public static function saveOrder($id_order, $transaction) + { + $order = new Order((int)$id_order); + $total_paid = (float)$transaction['total_paid']; + + if (!isset($transaction['payment_status']) || !$transaction['payment_status']) + $transaction['payment_status'] = 'NULL'; + + Db::getInstance()->Execute(' + INSERT INTO `'._DB_PREFIX_.'paypal_order` + (`id_order`, `id_transaction`, `id_invoice`, `currency`, `total_paid`, `shipping`, `capture`, `payment_date`, `payment_method`, `payment_status`) + VALUES ('.(int)$id_order.', \''.pSQL($transaction['id_transaction']).'\', \''.pSQL($transaction['id_invoice']).'\', + \''.pSQL($transaction['currency']).'\', + \''.$total_paid.'\', + \''.(float)$transaction['shipping'].'\', + \''.(int)Configuration::get('PAYPAL_CAPTURE').'\', + \''.pSQL($transaction['payment_date']).'\', + \''.(int)Configuration::get('PAYPAL_PAYMENT_METHOD').'\', + \''.pSQL($transaction['payment_status']).'\')' + ); + } + + public static function updateOrder($id_order, $transaction) + { + $total_paid = (float)$transaction['total_paid']; + + if (!isset($transaction['payment_status']) || !$transaction['payment_status']) + $transaction['payment_status'] = 'NULL'; + + $sql = 'UPDATE `'._DB_PREFIX_.'paypal_order` + SET `payment_status` = \''.pSQL($transaction['payment_status']).'\' + WHERE `id_order` = \''.(int)$id_order.'\' + AND `id_transaction` = \''.pSQL($transaction['id_transaction']).'\' + AND `currency` = \''.pSQL($transaction['currency']).'\''; + if ((int)Configuration::get('PAYPAL_SANDBOX') != 1) + $sql .= 'AND `total_paid` = \''.$transaction['total_paid'].'\' + AND `shipping` = \''.(float)$transaction['shipping'].'\';'; + + Db::getInstance()->Execute($sql); + } +} diff --git a/modules/paypal/paypal_tools.php b/modules/paypal/paypal_tools.php new file mode 100644 index 00000000..979cbbea --- /dev/null +++ b/modules/paypal/paypal_tools.php @@ -0,0 +1,79 @@ + + * @copyright 2007-2015 PrestaShop SA + * @version Release: $Revision: 14390 $ + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +if (!defined('_PS_VERSION_')) + exit; + +class PayPalTools +{ + protected $name = null; + + public function __construct($module_name) + { + $this->name = $module_name; + } + + public function moveTopPayments($position) + { + if (version_compare(_PS_VERSION_, '1.5', '<')) + $hook_payment = (int)Hook::get('payment'); + else + $hook_payment = (int)Hook::getIdByName('payment'); + + $module_instance = Module::getInstanceByName($this->name); + + if (version_compare(_PS_VERSION_, '1.5', '<')) + $module_info = Hook::getModuleFromHook($hook_payment, $module_instance->id); + else + $module_info = Hook::getModulesFromHook($hook_payment, $module_instance->id); + + if ((isset($module_info['position']) && (int)$module_info['position'] > (int)$position) || + (isset($module_info['m.position']) && (int)$module_info['m.position'] > (int)$position)) + return $module_instance->updatePosition($hook_payment, 0, (int)$position); + return $module_instance->updatePosition($hook_payment, 1, (int)$position); + } + + public function moveRightColumn($position) + { + if (version_compare(_PS_VERSION_, '1.5', '<')) + $hook_right = (int)Hook::get('rightColumn'); + else + $hook_right = (int)Hook::getIdByName('rightColumn'); + + $module_instance = Module::getInstanceByName($this->name); + + if (version_compare(_PS_VERSION_, '1.5', '<')) + $module_info = Hook::getModuleFromHook($hook_right, $module_instance->id); + else + $module_info = Hook::getModulesFromHook($hook_right, $module_instance->id); + + if ((isset($module_info['position']) && (int)$module_info['position'] > (int)$position) || + (isset($module_info['m.position']) && (int)$module_info['m.position'] > (int)$position)) + return $module_instance->updatePosition($hook_right, 0, (int)$position); + return $module_instance->updatePosition($hook_right, 1, (int)$position); + } +} diff --git a/modules/paypal/pt.php b/modules/paypal/pt.php new file mode 100644 index 00000000..739424bd --- /dev/null +++ b/modules/paypal/pt.php @@ -0,0 +1,133 @@ +paypal_abstract_ad69e733ebae8d264bccaa38d68830e8'] = 'Paypal'; +$_MODULE['<{paypal}prestashop>paypal_abstract_6e7012516038a096b9f6bb71ba2cc5a3'] = 'Aceita pagamentos por cartão de crédito (CB, Visa, MasterCard, Amex, Aurore, Cofinoga, 4 stars) com Paypal.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_69a1a3ad8dd5da6db3c4da838a0cf9c7'] = 'Você tem certeza que você quer deletar seus dados?'; +$_MODULE['<{paypal}prestashop>paypal_abstract_c91f1fb5e06286c3e0a33fc552dffbea'] = 'Você deve definir suas credenciais do PayPal Integral, para que o tema de telefonia móvel funcione corretamente.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_bd6b3cca1e559117a964cdfab6a977cf'] = 'O tema de telefonia móvel somente funciona com o módulo de pagamento Paypal neste momento. Por favor, ative o módulo para permitir pagamentos. '; +$_MODULE['<{paypal}prestashop>paypal_abstract_ea5eb3f904bf42377277255cbd0e2251'] = 'Para funcionar corretamente o módulo requer o módulo de compatibilidade com versões anteriores habilitado'; +$_MODULE['<{paypal}prestashop>paypal_abstract_48878e69ef59b9e9d2d9a8c18e4de520'] = 'Para funcionar corretamente o módulo requer pelo menos o módulo de compatibilidade com versões anteriores v'; +$_MODULE['<{paypal}prestashop>paypal_abstract_c9d8a8d3c76c69e9a5ba6387acb8655a'] = 'Para usar o módulo você precisa instalar o módulo de compatibilidade com versões anteriores.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_d739f6e2d6351c3a587d44190a8253af'] = 'Todos recursos do módulo API do Paypal estão incluídos no novo módulo Paypal. Para que não haja nenhum conflito, por favor, não use e remova o módulo PaypalAPI.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_32af90c3cfef1bacf43b0c3a8f60a4da'] = 'Fundos foram recuperados.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_d238649ac5ec14afc894fad36c0b50fc'] = 'Sem sucesso na recuperação dos fundos solicitados. Por favor, veja mensagem de registro!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_05b998de2c4fb46a7bdd37bd378b81d9'] = 'Validação bem sucedida. Por favor, veja mensagem de registro!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_aeca7e93a1b3d77e38c3cffa131774d5'] = 'Reembolso foi efetuado.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_cba030a50c8a99c7e224adbe1cf58544'] = 'Reembolso solicitado sem sucesso. Por favor, veja mensagem de registro!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_20fda49ece75d93bea97648ab1f1f1cf'] = 'Resultado de cancelamento de produtos:'; +$_MODULE['<{paypal}prestashop>paypal_abstract_90ab0cfd410722553c79e614207a789a'] = 'Alguns campos estão vazios.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_ce0e2b401002ca796d2e8aca7deb8f00'] = 'Campos de credenciais não podem estar vazios'; +$_MODULE['<{paypal}prestashop>paypal_abstract_3f7145179c909f0e87a911a3171986b6'] = 'Campo para e-mail comercial não pode estar vazio'; +$_MODULE['<{paypal}prestashop>paypal_abstract_e5d5d9f40763cfe6549bef705e3529a7'] = 'Mensagem de pagamento não é válida, por favor verifique seu módulo.'; +$_MODULE['<{paypal}prestashop>paypal_abstract_ee9dc1e678d54c517f481583c3fb2db8'] = 'Não é uma moeda válida'; +$_MODULE['<{paypal}prestashop>paypal_abstract_eec39bf42bd135971fb2d838c67d1449'] = 'Resultado de operação de reembolso:'; +$_MODULE['<{paypal}prestashop>paypal_abstract_2ab62d1a578713d0862b56819295630e'] = 'Reembolso do Paypal efetuado com sucesso!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_a64db959966ba8d07c8b5d9493fcc21f'] = 'Erro de transação!'; +$_MODULE['<{paypal}prestashop>paypal_abstract_67962779da962e3d4225055afc05e7bd'] = 'Resultado de operação de captura:'; +$_MODULE['<{paypal}prestashop>paypal_abstract_8778ee03f6592d5fec9a1f2ee851e476'] = 'Terminado o pedido com Paypal'; +$_MODULE['<{paypal}prestashop>paypal_abstract_672d40feac6437e49f771019bc330790'] = 'Status de verificação:'; +$_MODULE['<{paypal}prestashop>paypal_abstract_1828820cc60e36b6f9fdf60cab103ed7'] = 'Você está usando o e-mail padrão que vem com o Paypal, por favor coloque seu próprio e-mail.'; +$_MODULE['<{paypal}prestashop>validation_20dfea1a472e5be3f15f6b5f36ca335c'] = 'Problema conectando com o servidor do Paypal.'; +$_MODULE['<{paypal}prestashop>validation_f7799c2ded739cf3c3e9babffc5f315b'] = 'Conexão usando cURL falhou'; +$_MODULE['<{paypal}prestashop>validation_eca77e208634d52703b07672abbf16ec'] = 'Falha na verificação (usando cURL). Retornou:'; +$_MODULE['<{paypal}prestashop>validation_8358ec19f397d4cdd632688d4f79e535'] = 'Falha na verificação (usando fsockopen). Retornou:'; +$_MODULE['<{paypal}prestashop>validation_76ee8dc73701e846f7bccdf98dae079b'] = 'Sem transporte de comunicação disponível.'; +$_MODULE['<{paypal}prestashop>validation_2818bed1f235637049f4d46fd455dc1c'] = 'A chave Paypal \'mc_gross\' não foi especificada, não pode controlar a quantia paga.'; +$_MODULE['<{paypal}prestashop>validation_be59cbfbf305dc45cd0c3e9841b17ecf'] = 'A chave Paypal \'payment_status\' não foi especificada, não pode controlar a validade de pagamento'; +$_MODULE['<{paypal}prestashop>validation_bd0e34e5be6447844e6f262d51f1a9dc'] = 'Pagamento:'; +$_MODULE['<{paypal}prestashop>validation_e0395c4ce35d0b1e59ca3f2d5e260d23'] = 'A chave Paypal \'custom\' não foi especificada, não pode transmitir ao carrinho'; +$_MODULE['<{paypal}prestashop>validation_765261b630ee773659fae89e9ad762f5'] = 'A chave Paypal \'txn_id\' não foi especificada, transação desconhecida'; +$_MODULE['<{paypal}prestashop>validation_01634612f84d2b7ba56ccdf467e604b7'] = 'A chave Paypal \'mc_currency\' não foi especificada, moeda desconhecida'; +$_MODULE['<{paypal}prestashop>validation_e61f52d02b9f52fbe1fd41ed320e29c3'] = 'Carrinho não foi encontrado'; +$_MODULE['<{paypal}prestashop>validation_0617900b1aff826081d07f5a3e2e7cd0'] = 'Pedido já foi feito'; +$_MODULE['<{paypal}prestashop>validation_f5209b3301a46f3057ffbf34d903e205'] = 'ID de Transação Paypal: '; +$_MODULE['<{paypal}prestashop>validation_7b19e875ff64b09d80ee05dcc84b9975'] = 'A transação do Paypal não pode ser VERIFICADA.'; +$_MODULE['<{paypal}prestashop>paypal_connect_d1f14cc4a2dade80c92421d26422fea0'] = 'Fazendo nova conexão com'; +$_MODULE['<{paypal}prestashop>paypal_connect_94a27811a721ef512ad7bfa06cab34e0'] = 'Falha ao conectar com método CURL'; +$_MODULE['<{paypal}prestashop>paypal_connect_70215486455daee13382c68b1a230b82'] = 'Conexão com método CURL com sucesso'; +$_MODULE['<{paypal}prestashop>paypal_connect_e4c4ad49bced42265b5facc2175cdafd'] = 'Enviando este params:'; +$_MODULE['<{paypal}prestashop>paypal_connect_445583f6641da98fc7ac8fd9d13a564b'] = 'Envio com método CURL falhou! Erro:'; +$_MODULE['<{paypal}prestashop>paypal_connect_ef4fbf36eaa2083442d386990ba063c2'] = 'Envio com método CURL com sucesso'; +$_MODULE['<{paypal}prestashop>paypal_connect_bf059c9751bb1a20b449b7917b1df374'] = 'Conexão com método fsockopen falhou'; +$_MODULE['<{paypal}prestashop>paypal_connect_ea800e3536f81238a4cbc32eb6db4eaf'] = 'Conexão com método fsockopen com sucesso'; +$_MODULE['<{paypal}prestashop>paypal_connect_6e9aa4cb541e09b07602d4ea96080811'] = 'Envio com método fsockopen falhou!'; +$_MODULE['<{paypal}prestashop>paypal_connect_842a183be225d415b2b4375ba1dd1c94'] = 'Envio com método fsockopen com sucesso!'; +$_MODULE['<{paypal}prestashop>paypal_lib_7c2d00d8c94d1ce0f515db8b0481db40'] = 'Resposta do Paypal'; +$_MODULE['<{paypal}prestashop>paypal_express_checkout_ee9dc1e678d54c517f481583c3fb2db8'] = 'Não é uma moeda válida'; +$_MODULE['<{paypal}prestashop>paypal_express_checkout_484f5a79672cebe198ebdde45a1d672f'] = 'Papel de presente'; +$_MODULE['<{paypal}prestashop>submit_1e97d97a923eaddd810e056c828e99ea'] = 'Erro no pagamento'; +$_MODULE['<{paypal}prestashop>submit_7ef8c0c75056a5d1f988e352efcd0f09'] = 'Este produto não está mais em estoque com estes atributos mas está disponível com outros'; +$_MODULE['<{paypal}prestashop>submit_d141a42a5e72c871a3116414bb5c64c1'] = 'Não é possível criar novo carrinho'; +$_MODULE['<{paypal}prestashop>submit_5b5adcef5e3f2e5e1b6f60eb3e7e41ed'] = 'Ocorreu um erro:'; +$_MODULE['<{paypal}prestashop>submit_58f53d0306ffc9cc9820eab866e90efe'] = 'Erro durante a preparação do pagamento express checkout'; +$_MODULE['<{paypal}prestashop>submit_51da74120dd5e11817ef21e27d2599bc'] = 'Não foi possível criar cliente'; +$_MODULE['<{paypal}prestashop>submit_bcf08b34ab427cb871635151c6976eb0'] = 'Não foi possível criar endereço'; +$_MODULE['<{paypal}prestashop>submit_ca5cecfc8fd8e585ba1e684757168158'] = 'Não foi possível atualizar o carrinho existente'; +$_MODULE['<{paypal}prestashop>submit_36ec50c0e914dd2fb48a1b27540512ce'] = 'Pagamento aceito.'; +$_MODULE['<{paypal}prestashop>submit_28060413b9f346d871b633018d03c7b0'] = 'Preço pago no Paypal não é o mesmo que no PrestaShop.'; +$_MODULE['<{paypal}prestashop>submit_98825385aadb1d0dd0fd133ef8acd23d'] = 'Não é possível criar pedido'; +$_MODULE['<{paypal}prestashop>submit_085b78e060c3ef4cc37bd25abd06ff66'] = 'Carrinho mudou desde o último checkout express, por favor faça um novo pagamento no checkout Paypal'; +$_MODULE['<{paypal}prestashop>notifier_28060413b9f346d871b633018d03c7b0'] = 'Preço pago no Paypal não é o msmo que no PrestaShop.'; +$_MODULE['<{paypal}prestashop>notifier_572f9af7615560af2cba038cc1948287'] = 'Carrinho mudou, por favor entre dados novamente.'; +$_MODULE['<{paypal}prestashop>notifier_36ec50c0e914dd2fb48a1b27540512ce'] = 'Pagamento aceito.'; +$_MODULE['<{paypal}prestashop>back_office_2d801c24938b12e4ca9a2cf9b980c759'] = 'Erro!'; +$_MODULE['<{paypal}prestashop>capture_81e826adb70e2e6b189c2eef739d52d4'] = 'Captura Paypal'; +$_MODULE['<{paypal}prestashop>capture_e8fdd4382b75b42bfbd96eb7b032cf47'] = 'Informação:'; +$_MODULE['<{paypal}prestashop>capture_ce64b2ea82cf4fa861a6512e2c32b84b'] = 'Fundos prontos para serem capturados antes do envio'; +$_MODULE['<{paypal}prestashop>capture_99e64593868df2b7b32231c1ae5ddc04'] = 'Obter o dinheiro'; +$_MODULE['<{paypal}prestashop>refund_8ba079f305b81b172792bc0469b6a690'] = 'Reembolso Paypal'; +$_MODULE['<{paypal}prestashop>refund_e8fdd4382b75b42bfbd96eb7b032cf47'] = 'Informação:'; +$_MODULE['<{paypal}prestashop>refund_016e1f278eccd700eaf33f74a501d050'] = 'Pagamento aceito'; +$_MODULE['<{paypal}prestashop>refund_a8b1cc445942a2e1a7d7cca641c86d67'] = 'Quando você reembolsa um produto, um reembolso parcial é feito a menos que você selecione \"Generate a voucher\".'; +$_MODULE['<{paypal}prestashop>refund_c2a5e2e23d8ec9cad779d657b7d33fc1'] = 'Reembolso total da transação'; +$_MODULE['<{paypal}prestashop>refund_729a51874fe901b092899e9e8b31c97a'] = 'Você tem certeza?'; +$_MODULE['<{paypal}prestashop>validation_b630aa9b5e25da971949cae62dd109aa'] = 'Validação Paypal'; +$_MODULE['<{paypal}prestashop>validation_e8fdd4382b75b42bfbd96eb7b032cf47'] = 'Informação:'; +$_MODULE['<{paypal}prestashop>validation_9119a92adbbf6c67bfb8a3aee0bdb720'] = 'Captura Pendente - Sem meio de envio'; +$_MODULE['<{paypal}prestashop>validation_c14eb95a724174f336b8ffdd98ef2f35'] = 'Pagamento Pendente - Sem meio de envio'; +$_MODULE['<{paypal}prestashop>validation_5b18ff32c2aaaf4b79bdead10b10fe29'] = 'Obtenha o status do pagamento'; +$_MODULE['<{paypal}prestashop>about_e816e21c1c8e0eba0620fa3df6bd6795'] = 'O que é Paypal?'; +$_MODULE['<{paypal}prestashop>about_16ea57badae98f402bb8f2b2f49d4e77'] = 'PayPal, uma confiável empresa líder em pagamentos on-line, permite que compradores e empresas enviem e recebam dinheiro online. PayPal tem mais de 100 milhões de contas de membros em 190 países e regiões. Ele é aceito por comerciantes em toda parte, dentro e fora do eBay.'; +$_MODULE['<{paypal}prestashop>about_d20adade7baa1b60b713521031ea676c'] = 'É seguro para usar?'; +$_MODULE['<{paypal}prestashop>about_64f7b897c6d56fc62428f692ee5737cd'] = 'PayPal ajuda a proteger suas informações de cartão de crédito com líderes de mercado em segurança e sistemas de prevenção de fraude. Quando você usa o PayPal, suas informações financeiras nunca são compartilhadas com o comerciante.'; +$_MODULE['<{paypal}prestashop>about_5ef30813484389e4200640c2f006004d'] = 'Porque usar Paypal?'; +$_MODULE['<{paypal}prestashop>about_86550d4ea832930db4366f03b90bdfb8'] = 'Faça compras ou envie dinheiro com o Paypal - é grátis!'; +$_MODULE['<{paypal}prestashop>about_7dc9e529337e5a55a12bf362b8e68cac'] = 'Compre e pague de forma conveniente salvando suas informações com o Paypal'; +$_MODULE['<{paypal}prestashop>about_32098ae6a7ecd96805df9e48fb6cc739'] = 'O Paypal é aceito por milhões de empresas em todo o mundo e é o método preferido no eBay'; +$_MODULE['<{paypal}prestashop>about_7934d7d1280bfbb8778743e39292af30'] = 'Comece a usar o Paypal hoje!'; +$_MODULE['<{paypal}prestashop>column_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Pague com Paypal'; +$_MODULE['<{paypal}prestashop>confirmation_2e2117b7c81aa9ea6931641ea2c6499f'] = 'Seu pedido no'; +$_MODULE['<{paypal}prestashop>confirmation_75fbf512d744977d62599cc3f0ae2bb4'] = 'está completo.'; +$_MODULE['<{paypal}prestashop>confirmation_15b0f8e55c6bdfc3d5fd0b6b3b6cb3ee'] = 'Você escolheu o método Paypal.'; +$_MODULE['<{paypal}prestashop>confirmation_e6dc7945b557a1cd949bea92dd58963e'] = 'Seu pedido será enviado em breve.'; +$_MODULE['<{paypal}prestashop>confirmation_0db71da7150c27142eef9d22b843b4a9'] = 'Para qualquer pergunta ou mais informações, por favor contate nosso '; +$_MODULE['<{paypal}prestashop>confirmation_64430ad2835be8ad60c59e7d44e4b0b1'] = 'serviço de atendimento ao cliente'; +$_MODULE['<{paypal}prestashop>error_a40cab5994f36d4c48103a22ca082e8f'] = 'Seu carrinho de compra'; +$_MODULE['<{paypal}prestashop>error_ad69e733ebae8d264bccaa38d68830e8'] = 'Paypal'; +$_MODULE['<{paypal}prestashop>error_425551a2289ed60c9260933d1c45ef00'] = 'Por favor consulte os registros:'; +$_MODULE['<{paypal}prestashop>error_0557fa923dcee4d0f86b1409f5c2167f'] = 'Voltar'; +$_MODULE['<{paypal}prestashop>order-confirmation_fb077ecba55e5552916bde26d8b9e794'] = 'Confirmação do Pedido'; +$_MODULE['<{paypal}prestashop>order-confirmation_d5860edcd3078f86ee963c27654bc6cf'] = 'Total da transação (impostos incluídos) :'; +$_MODULE['<{paypal}prestashop>order-confirmation_a378cd7a0839cbd4ec3e45bbdeeb69be'] = 'A ID do seu pedido é:'; +$_MODULE['<{paypal}prestashop>order-confirmation_6e860dc1cf94ca08b3fd99993aa2dc68'] = 'A ID da sua transação Paypal é:'; +$_MODULE['<{paypal}prestashop>order-confirmation_4082ea29b4f196c4f60533500139725a'] = 'Acompanhar meu pedido'; +$_MODULE['<{paypal}prestashop>order-confirmation_9390390581f54c65d6acfc8da4e17362'] = 'Voltar para pedidos'; +$_MODULE['<{paypal}prestashop>order-summary_a40cab5994f36d4c48103a22ca082e8f'] = 'Seu carrinho de compra'; +$_MODULE['<{paypal}prestashop>order-summary_ad69e733ebae8d264bccaa38d68830e8'] = 'Paypal'; +$_MODULE['<{paypal}prestashop>order-summary_f1d3b424cd68795ecaa552883759aceb'] = 'Resumo do pedido'; +$_MODULE['<{paypal}prestashop>order-summary_dd23adc5fb6bda9c384397b31e57fc53'] = 'Pagamento Paypal'; +$_MODULE['<{paypal}prestashop>order-summary_62d74398cb6ebaa69ab7339052ca5c92'] = 'Você escolheu pagar com Paypal.'; +$_MODULE['<{paypal}prestashop>order-summary_c884ed19483d45970c5bf23a681e2dd2'] = 'Aqui está um curto resumo do seu pedido:'; +$_MODULE['<{paypal}prestashop>order-summary_e2867a925cba382f1436d1834bb52a1c'] = 'O valor total do seu pedido é'; +$_MODULE['<{paypal}prestashop>order-summary_1f87346a16cf80c372065de3c54c86d9'] = '(imposto incluído)'; +$_MODULE['<{paypal}prestashop>order-summary_8ed356c32b198c9cb2abab7c3d262b93'] = 'Nós aceitamos as seguintes moedas para serem enviadas pelo Paypal:'; +$_MODULE['<{paypal}prestashop>order-summary_0881a11f7af33bc1b43e437391129d66'] = 'Por favor confirme seu pedido clicando \'Eu confirmo meu pedido\''; +$_MODULE['<{paypal}prestashop>order-summary_46b9e3665f187c739c55983f757ccda0'] = 'Eu confirmo meu pedido'; +$_MODULE['<{paypal}prestashop>express_checkout_form_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Pague com o Paypal'; +$_MODULE['<{paypal}prestashop>paypal_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Pague com o Paypal'; +$_MODULE['<{paypal}prestashop>iframe_ecab922bc1f9b5726e2a6deb4acaec4e'] = 'Volte para o website do comerciante'; +$_MODULE['<{paypal}prestashop>payment_dac2693baa5c5c9a5318609ed81c4f2a'] = 'Pague com o Paypal'; +$_MODULE['<{paypal}prestashop>payment_a3f2caee6ef8e68fbd26e42d83f2bf65'] = 'Pague com sua conta Paypal, cartão de crédito (CB, Visa, Mastercard...), ou cartão de crédito privado'; +$_MODULE['<{paypal}prestashop>payment_b08008a2de4331ba13f006c9bcf37b62'] = 'Pague com sua conta Paypal'; diff --git a/modules/paypal/translations.xml b/modules/paypal/translations.xml new file mode 100644 index 00000000..63d2e362 --- /dev/null +++ b/modules/paypal/translations.xml @@ -0,0 +1,3826 @@ + + + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + Getting started with PayPal only takes 5 minutes + + Get more buyers
    100 million-plus PayPal accounts worldwide +
  1. Access international buyers
    190 countries, 25 currencies
  2. +
  3. Reassure your buyers
    Buyers don’t need to share their private data
  4. +
  5. Accept all major payment method
  6. + ]]> +
    + + Your country + change + Select your country + + + Use PayPal In Context Checkout + Make your client pay without leaving your website + Merchant ID + + Translated in your language + + Need help ?]]> Give us a call : xxxx + call + + + You already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, pay only when you get paid. + + + Website Payments Pro + + A professional platform to accept payments through credit cards and PayPal account, covered by seller protection.]]> + Customized payments pages. Monthly subscription of 25€. + + Click on the SAVE button only when PayPal has approved your subscription for this product. This process can take up to 3-5 days. + + Express Checkout + Boost your online sales by 30%*. + *Source: Forrester research realized in march 2011 + + Apply or open your PayPal Business account + + Enable your online shop to process payments + Give your PayPal Identification info, finish to set-up your account and start accepting payments + Communicate your PayPal identification info to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal identification info + After clicking on the “Get my PayPal identification info” button, enter your login and password in the pop up, copy your PayPal identification info from the pop up and paste them is the below fields. + API username + API password + API signature + API business e-mail + Please check once more that you pasted all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Use express checkout shortcut + Offer your customers a 2-click payment option + + Use Sand box + (recommanded) + Activate a test environment in your PayPal account (only if you are a developer). + Learn more + https://developer.paypal.com/ + Live mode + Test mode + + Activating the test mode implies that + + You won’t be able to accept payment +
  7. You will need to come back to the PayPal module page in order to complete the Step 3 before going live.
  8. +
  9. You’ll need to create an account on the PayPal sandbox site (learn more)
  10. +
  11. You’ll need programming skills
  12. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to complete the PayPal identification Information in step 3 otherwise you won’t be able to accept payment. + + Congratulation ! + You can now start accepting Payment with PayPal. + You can now start testing PayPal solutions. Don’t forget to comeback to this page and activate the live mode in order to start accepting payements. + Client ID + Secret + PayPal Blue + Neutral + + + Sign Up + Once your account is created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=2 + + + Subscribe + + Click on the SAVE button only when PayPal has approved your subscription for this product,]]> + otherwise you won't be able to process payment. This process can take up to 3-5 days. + + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=4 + + + Sign Up + Once your account is created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=3 + + + + + + + + Subscribe + + Click on the SAVE button only when PayPal has approved your subscription for this product,]]> + otherwise you won’t be able to process payment. This process can take up to 3-5 days.]]> + ]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to ]]>step 3]]>. + + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=4 + + + + + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  13. Access international buyers
    190 countries, 25 currencies
  14. +
  15. Reassure your buyers
    Buyers don’t need to share their private data
  16. +
  17. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  18. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call : 1800-073-263 + + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + Website Payments Pro - Hosted Solution + A professional platform that enables you to accept debit card, credit card and PayPal payments.]]>Customised payment pages. Monthly subscription of 25$. + Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days. + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  19. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  20. +
  21. You’ll need to create an account on the PayPal sandbox site (learn more)
  22. +
  23. You’ll need programming skills
  24. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=48 + + + Apply + Please only click the SAVE button at the bottom of the page once PayPal has approved your application for this product, otherwise you won't be able to process any card payments. This process can take up to 3-5 days + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=50 + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=49 + + + Sign Up + + + + + Apply + Important: Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days.]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to step 3]]>. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=50 + + + + + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  25. Access international buyers
    190 countries, 25 currencies
  26. +
  27. Reassure your buyers
    Buyers don’t need to share their private data
  28. +
  29. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  30. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call : 0800 50970 + call + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + + + + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  31. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  32. +
  33. You’ll need to create an account on the PayPal sandbox site (learn more)
  34. +
  35. You’ll need programming skills
  36. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=42 + + + + + + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=43 + + + Sign Up + + + + + Apply + + + + + + + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  37. Access international buyers
    190 countries, 25 currencies
  38. +
  39. Reassure your buyers
    Buyers don’t need to share their private data
  40. +
  41. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  42. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call : 400-680-6220 + call + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + + + + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  43. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  44. +
  45. You’ll need to create an account on the PayPal sandbox site (learn more)
  46. +
  47. You’ll need programming skills
  48. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=58 + + + + + + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=59 + + + Sign Up + + + + + Apply + + Important: Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days.]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to step 3. + + + + + + + + +
    + + + Ja + Nein + Schnell, einfach, sicher + Mit Sicherheit + mehr Umsatz + + PayPal in Ihrem Shop zu aktivieren dauert nur 5 Minuten + + Mehr Kunden akquirieren
    15 Millionen PayPal-Kunden in Deutschland +
  49. Mehr Sicherheit genießen
    Der PayPal-Verkäuferschutz sichert Sie im Fall der Fälle ab
  50. +
  51. Mehr Umsatz generieren
    Steigern Sie Ihren Umsatz um durchschnittlich 18,7%
  52. +
  53. Mehr Schutz schaffen
    Ihre Warenkorb-Informationen werden nicht weitergegeben
  54. + ]]> +
    + + Ihr Land + Ändern + Land auswählen + + Übersetzt in Ihre Sprache + + Haben Sie Fragen?]]> Rufen Sie uns an: 01805 23 32 05 + call + (Maximal 14 Cent/Min. aus dem Festnetz. Für Anrufe aus Mobilfunknetzen fallen Gebühren von maximal 42 Cent/Min. an.) + + Haben Sie bereits ein PayPal-Konto + Wählen Sie Ihre PayPal-Lösung aus + Mehr erfahren]]> + + Möchten Sie PayPal in Ihrem Online-Shop anbieten ? + Need PayPal in addition to your existing card processor ? + + Wählen Sie + + PayPal Express + + Sie profitieren von weniger Kaufabbrüchen und profitieren so von mehr Umsatz. + + + Website Payments Pro + Eine professionelle Plattform für eingehende Kreditkarten- und PayPal-Zahlungen, inklusive Verkäuferschutz.]]>Angepasste Zahlungsseiten. 25,00 EUR monatlich. + Klicken Sie erst dann auf "Speichern", nachdem PayPal dieses Produkt für Sie freigeschaltet hat. Das dauert in der Regel 3-5 Tage. + + Express Checkout + Steigern Sie Ihre Online-Umsätze um 30%* + * Quelle: Forrester-Studie vom März 2011 + + Eröffnen Sie ein PayPal-Geschäftskonto + + So aktivieren Sie PayPal in Ihrem Online-Shop oder auf Ihrer Webseite + Einfach Ihre PayPal-Daten eingeben, Konto einrichten und sofort Zahlungen akzeptieren + Übermitteln Sie die Daten Ihrer API-Schnittstelle an PrestaShop + Geben Sie dieselbe E-Mail-Adresse an wie bei der Eröffnung Ihres PayPal-Geschäftskontos. + API Informationen abrufen + Nachdem Sie auf "API Informationen abrufen" geklickt haben, geben Sie bitte Ihren PayPal Login-Namen und das Passwort in das Pop-Up ein, kopieren Sie dann die Infos, um Sie in die unten stehenden Felder einzusetzen. + API-Name + API-Passwort + API-Signatur + API business e-mail + Bitte überprüfen Sie Ihre Angaben auf Vollständigkeit. + + Schließen Sie den Anmeldeprozess für Ihr PayPal-Konto ab + Bestätigen Sie Ihre E-Mail-Adresse: PayPal hat Ihnen nach der Kontoeröffnung eine mail mit weiteren Informatonen gesendet. + Fügen Sie in Ihrem PayPal-Konto Ihr Bankkonto oder Ihre Kreditkarte hinzu. Loggen Sie sich in Ihren PayPal Account ein und klicken auf "Mein Geschäftskonto einrichten". + + Weitere Einstellungen + + Bitte wählen Sie, welche Lösung Sie nutzen möchten + iFrame + Vollständige Weiterleitung + Bitte wählen Sie Ihr Template + + + Nutzen Sie Express Checkout Shortcut + Per Klick gelangen Ihre Kunden ohne Umwege direkt zur PayPal-Zahlungsseite + + Nutzen Sie die Sandbox + (empfohlen) + Damit können Sie den PayPal-Bezahlfluss in einer Test-Umgebung ausprobieren. + Mehr erfahren. + http://www.paypalobjects.com/de_DE/html/IntegrationCenter/ic_sandbox.html + Reale Umgebung (empfohlen) + Test-Umgebung + + Wenn Sie die Test-Umgebung aktivieren + + Können Sie keine Zahlungen empfangen. +
  55. Müssen Sie auf diese Seite zurückkehren, um Schritt 3 abzuschließen.
  56. +
  57. Sollten Sie einen Zugang zur PayPal-Sanbox einrichten. (Mehr erfahren)
  58. +
  59. Sollten Sie Programierkenntnisse mitbringen.
  60. + ]]> +
    + Sind Sie sicher, die Test-Umgebung jetzt zu aktivieren ? + + Zahlungsweise + + Wählen Sie Ihren Weg der Zahlungsabwicklung (automatische oder manuelle Autorisierung).]]> + Der PayPal-Verkäuferschutz sichert Sie ab, wenn Ihre Käufer mit PayPal bezahlen. ]]>Und so funktioniert es]]>. + + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Speichern + + Sie können keine Zahlungen empfangen, wenn Sie nicht die notwendigen Informationen in Schritt 3 angeben. + + Herzlichen Glückwunsch ! + Nun ist PayPal aktiviert und Sie können Zahlungen empfangen. + Jetzt können Sie die PayPal-Lösungen ausprobieren. Vergessen Sie bitte nicht, hierher zurückzukommen, um die reale Umgebung zu aktivieren. Denn sonst können Sie keine Zahlungen empfangen. + + + JETZT ANMELDEN + Sobald Sie das Konto eröffnet haben, fahren Sie bitte mit Schritt 3 fort. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=14 + + + Abonnieren + Klicken Sie erst dann auf "Speichern", nachdem PayPal dieses Produkt für Sie freigeschaltet hat.]]> + Andernfalls werden Sie keine Zahlungen verarbeiten können. Das dauert in der Regel 3-5 Tage. + + + Anmelden + Nachdem Sie Ihr Konto erstellt haben, schließen Sie auf dieser Seite Schritt 3 ab. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=3 + + + + + + + + Abonnieren + Klicken Sie erst dann auf "Speichern", nachdem PayPal dieses Produkt für Sie freigeschaltet hat.]]>Andernfalls werden Sie keine Zahlungen verarbeiten können. Das dauert in der Regel 3-5 Tage.]]>]]>Falls PayPal für Sie Website Payments Pro bereits freigeschaltet hat, gehen Sie direkt zu + + + + + + + +
    + + + + No + Pague con su tarjeta de débito, crédito o su cuenta PayPal + + + La forma rápida y segura de pagar en Internet + Aceptar pagos con PayPal sólo le llevará ]]>unos minutos]]> + + Consiga más clientes
    Más de 100 millones de cuentas activas en el mundo +
  61. Acceda a clientes internacionales
    En 190 países y en 25 divisas
  62. +
  63. Facilite y mejore la experiencia de compra a sus clientes
    Sus clientes pagan en dos clicos
  64. +
  65. Pagos sin compartir los datos financieros.
    Acepte pagos con tarjeta y cuenta bancaria
  66. + ]]> +
    + + Su país + change + Select your country + + ¿Necesita ayuda? Póngase en contacto con nosotros]]> + mail + + + ¿Ya tiene una cuenta PayPal Empresas? + Seleccione su solución + Más información]]> + + ¿Necesita PayPal para procesar todos sus pagos con tarjeta? + ¿Desea aceptar PayPal como forma de pago adicional a su pasarela actual? + + Elija + + Pago estándar + Comience a aceptar pagos al instante. Sin comisiones de alta, mantenimiento o cancelación, la única tarifa que se paga es cuando se recibe un pago. + + PayPal Pasarela Integral + + Una pasarela todo en uno para aceptar pagos con tarjetas y con cuenta PayPal.]]> + Además de poder personalizar su flujo de pago, cuenta con un programa de protección*.]]> + Flujo de pago personalizado. Todo por una tarifa mensual de 15 eur.]]> + * Ver téminos y condiciones de Pasarela Integral de PayPal]]> + + Haga clic en el botón GUARDAR solo cuando PayPal apruebe su suscripción para este producto. Este proceso puede tardar 3-5 días. + + Pago exprés + Aumente sus ventas online en un 18%* + *Fuente: Estudio independiente realizado por Ipsos Public Affairs en julio de 2010, los vendedores online reportaron un incremento medio del 18% en sus ventas al añadir Pago exprés en su web. + + Abra su cuenta PayPal Empresas + + Active su tienda online para aceptar pagos con PayPal + + Comunique su información de identificación de PayPal a PrestaShop + Indique el correo electrónico asociado a su cuenta PayPal Empresas + Obtener mis datos de Identificación de PayPal + Después de hacer clic en el botón "Obtener mis datos de identificación en PayPal", introduzca su nombre de usuario y contraseña en la ventana emergente, copie sus datos de identificación de la ventana emergente y péguelos en los campos correspondientes. + Nombre de usuario de API + Contraseña de API + Firma + Correo electrónico en PayPal + Asegúrese de incluir todos los caracteres, comprueba una vez más que ha pegado todos los caracteres. + + Para finalizar configure su cuenta PayPal siguiendo estos pasos + Confirme su dirección de correo electrónico: compruebe el correo electrónico enviado por PayPal al crear su cuenta + Añada una tarjeta o cuenta bancaria a su cuenta PayPal: inicie sesión en su cuenta PayPal y vaya a "Verificar mi tarjeta" + + Opciones de configuración + + Seleccione la solución que desea usar + Iframe + Redirección de página completa + Seleccione una plantilla + + Utilice Pago exprés (acceso rápido) + Ofrezca a sus clientes una opción de pago con tan solo 2 clics + + Utilice el entorno de prueba Sandbox + (recomendado) + Active un entorno de prueba en su cuenta PayPal (solo si es programador). + Más Información + Modo real (recomendado) + Modo de prueba + + La activación del modo de prueba implica que + + No podrá aceptar pagos. +
  67. Tendrá que regresar a la página de PayPal para completar el paso 3 antes de estar en modo real.
  68. +
  69. Tendrá que crear una cuenta en el entorno Sandbox de PayPal (Más información)
  70. +
  71. Necesitará conocimientos de programación
  72. + ]]> +
    + ¿Está seguro que desea activar el modo de prueba? + + Método de pago + Elija su forma de procesar los pagos (autorización automática o manual). + Direct sales + Authorization/Manual capture (payment shipping) + + Guardar + + Tiene que completar los datos de Identificación de PayPal en el paso 3 para que pueda aceptar pagos. + + Enhorabuena ! + Ya puede aceptar pagos con PayPal. + Ya puede probar las soluciones de PayPal. No olvide volver a esta página para activar el modo real y poder aceptar pagos. + + + Abrir una cuenta + Una vez que haya abierto su cuenta, regrese a esta página para completar el paso 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=10 + + + Solicitar + + Haga clic en el botón GUARDAR solo cuando PayPal apruebe su suscripción para este producto. Este proceso puede tardar 3-5 días. + + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=12 + + + Abrir una cuenta + Una vez que haya abierto su cuenta, regrese a esta página para completar el paso 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=11 + + + + Solicitar + + Haga clic en el botón GUARDAR solo cuando PayPal apruebe su suscripción para este producto. Este proceso puede tardar 3-5 días]]> + Si PayPal ya ha aprobado su solicitud de Pasarela integral, vaya directamente ]]>al paso 3.]]>. + + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=12 + + +
    + + + Oui + Non + Payez par carte ou par compte PayPal + Leader des + paiements en ligne + Plus simple, plus rapide et plus sûr pour vos clients. + Commencer avec PayPal ne prend que ]]>5 minutes]]> + + Touchez plus de clients
    Plus de 100 millions de comptes actifs à travers le monde +
  73. Acceptez les paiements à l'international
    190 pays, 25 devises
  74. +
  75. Rassurez vos clients
    Ils n'ont pas besoin de partager leurs informations confidentielles
  76. +
  77. Acceptez les principaux moyens de paiements
    Visa, Mastercard, Carte Bleue, Aurore, Cofinoga, 4 Etoiles, PayPal
  78. + ]]> +
    + + Traduis dans votre langue + + Votre pays + changer + Select your country + + Besoin d'aide ?]]> Appelez nous au 0800 942 850* + call + * Appel gratuit depuis un poste fixe, 7 jours /7 de 9h00 à 18h30. + + Vous possédez déjà un compte PayPal Professionnel + Choisissez votre solution + En savoir plus]]> + + Besoin de PayPal pour accepter tous les paiements par carte ? + Besoin d'ajouter le bouton PayPal en tant que moyen de paiement supplémentaire ? + + Choisissez + + PayPal Intégral + + Acceptez immédiatement les principaux moyens de paiements du web. Pas de frais fixe ni d'engagement de durée. Payez seulement à la réception des paiements. + + + PayPal Intégral Evolution + + Une plateforme de paiement complète, une protection des paiements en plus*.]]> + Ayez la possibilité de personnaliser votre page de paiement. Abonnement mensuel de 25€. + ]]>*Soumis à conditions, voir les ]]>conditions d'utilisation]]> + + PayPal Integral Evolution est soumis à conditions et le traitement de votre inscription peut prendre 3 à 5 jours ouvrés. Merci de ne cliquer sur le bouton "Sauvegardez" en bas de la page qu'une fois votre inscription validée par PayPal. + + PayPal Option + + Ajoutez PayPal Option + peut générer 20 à 30 % de ventes additionnelles*. + *Source: Étude Forrester réalisée en mars 2011 + + Souscrivez ou ouvrez un compte PayPal Professionnel + + Configurez votre solution pour commencer à accepter les paiements + + Communiquez vos informations d'identification PayPal à PrestaShop + Indiquez l'email que vous avez utilisé pour créer votre compte PayPal professionnel + Obtenir mes informations d'identification PayPal + Après avoir cliqué sur le bouton "Obtenir mes informations d'identification PayPal", entrez vos identifiant et mot de passe PayPal dans la fenêtre qui s'affichera, copier les informations fournies par PayPal et collez les dans les champs ci-dessous. + Identifiant API + Mot de passe API + Signature + E-mail compte PayPal professionnel + Merci de vérifier que vous avez bien collé l'ensemble des caractères, certain champs contiennent beaucoup de caractères. + + Pour finir la configuration de votre compte PayPal + Confirmer votre adresse e-mail en suivant la procédure envoyée par PayPal lors de la création de votre compte + Lier votre compte PayPal à un compte bancaire ou à une carte bancaire. Connectez-vous à votre compte PayPal et rendez-vous dans la section "Premier pas" + + Options de configuration PayPal + + Choisissez votre solution + Iframe + Redirection complète de la page + Choisissez un template + + Utilisez PayPal Express + Offrez à vos clients la possibilité de payer en 2 clics + + Utilisez PayPal In Context Checkout + Faites payer votre client sans quitter votre site + ID du marchant + + Utilisez la Sandbox + (recommandé) + Mettez en place un environnement de test dans votre compte PayPal (seulement si vous êtes un développeur). + Plus d'infos + Mode réel (recommandé) + Mode test + + Activer le mode test implique que + + Vous ne serez pas en mesure d'accepter les paiements immédiatement +
  79. Vous devrez créer un compte test sur le site PayPal sandbox. (plus d'infos)
  80. +
  81. Vous aurez besoin de compétences en développement
  82. +
  83. Vous devrez revenir à la page du module PayPal afin de compléter l'étape 3 avec les informations d'identification de votre compte test
  84. +
  85. Pour passer en mode réel, vous devrez revenir sur la page du module PayPal et indiquer vos informations d'identification PayPal à nouveau
  86. + ]]> +
    + Êtes vous sûr de vouloir activer le mode test ? + + Type de paiement + Choisissez votre manière de valider les paiements (Automatique vs. Autorisation manuelle). + Direct sales + Authorization/Manual capture (payment shipping) + + Sauvegardez + + Vous devrez compléter l'ensemble des informations d'identification PayPal durant l'étape 3 autrement vous ne serez pas en mesure d'accepter les paiements. + + Bravo ! + Vous pouvez maintenant commencer à accepter les paiements avec PayPal. + Vous pouvez maintenant commencer à tester les solutions PayPal. N'oubliez surtout pas de revenir sur cette page et d'activer le mode réel afin de commencer à accepter les paiements. + + + Ouvrez un compte + Une fois votre compte créé, revenez sur cette page pour compléter l'étape 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=2 + + + Souscrivez + + PayPal Integral Evolution est soumis à conditions et la validation de votre inscription peut prendre 3 à 5 jours ouvrés.]]> + Veuillez ne cliquer sur le bouton "Sauvegardez" en bas de la page qu'une fois votre inscription validée par PayPal + + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=4 + + + Ouvrez un compte + Une fois votre compte créé, revenez sur cette page pour compléter l'étape 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=3 + + + + Souscrivez + + PayPal Integral Evolution est soumis à conditions et la validation de votre inscription peut prendre 3 à 5 jours ouvrés.]]> + Veuillez ne cliquer sur le bouton "Sauvez" en bas de la page qu'une fois votre inscription validée par PayPal sinon vous ne serez pas en mesure d'accepter les paiements.]]> + Si votre souscription à PayPal Intégral Evolution a déjà été validée par PayPal, merci d'aller directement à ]]>l'étape 3]]>. + + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=4 + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  87. Access international buyers
    190 countries, 25 currencies
  88. +
  89. Reassure your buyers
    Buyers don’t need to share their private data
  90. +
  91. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  92. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call on 0844 338 0470 + call + + + Already have a PayPal Business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + Website Payments Pro Hosted + A professional platform that enables you to accept debit card, credit card and PayPal payments. Customised payment pages.]]> Monthly subscription of £20. + Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days. + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + PayPal Business account e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  93. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  94. +
  95. You’ll need to create an account on the PayPal sandbox site (learn more)
  96. +
  97. You’ll need programming skills
  98. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=39 + + + Apply + Please only click the SAVE button at the bottom of the page once PayPal has approved your application for this product, otherwise you won't be able to process any card payments. This process can take up to 3-5 days + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=40 + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=39 + + + Sign Up + + + + + Apply + Important: Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days.]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to ]]>step 3]]>. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=40 + + + + + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  99. Access international buyers
    190 countries, 25 currencies
  100. +
  101. Reassure your buyers
    Buyers don’t need to share their private data
  102. +
  103. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  104. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call : 852-3550-8574 + call + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + Website Payments Pro Hosted Solution + A professional platform that enables you to accept debit card, credit card and PayPal payments. Customised payment pages.]]>Monthly subscription of HKD$200. To sign-up, please contact a PayPal customer service representative. + Please only click the SAVE button at the bottom of the page once PayPal has approved your application for this product, otherwise you won't be able to process any card payments. This process can take up to 3-5 days + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  105. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  106. +
  107. You’ll need to create an account on the PayPal sandbox site (learn more)
  108. +
  109. You’ll need programming skills
  110. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=61 + + + Apply + + "Contact a PayPal sales representative at +852 3550 8584 or email us via the following button]]> + Please only click the SAVE button at the bottom of the page once PayPal has approved your application for this product, otherwise you won't be able to process any card payments. This process can take up to 3-5 days" + + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=81 + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=62 + + + Sign Up + + + + + Apply + + Important: Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days.]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to step 3. + + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=81 + + + + + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  111. Access international buyers
    190 countries, 25 currencies
  112. +
  113. Reassure your buyers
    Buyers don’t need to share their private data
  114. +
  115. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  116. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Visit www.Paypal.com]]> + + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + + + + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  117. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  118. +
  119. You’ll need to create an account on the PayPal sandbox site (learn more)
  120. +
  121. You’ll need programming skills
  122. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=23 + + + + + + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=24 + + + Sign Up + + + + + Apply + + + + + + + + +
    + + + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  123. Access international buyers
    190 countries, 25 currencies
  124. +
  125. Reassure your buyers
    Buyers don’t need to share their private data
  126. +
  127. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  128. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call : +1 402 938-3740]]>(a US telephone number) + call + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + + + + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  129. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  130. +
  131. You’ll need to create an account on the PayPal sandbox site (learn more)
  132. +
  133. You’ll need programming skills
  134. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=76 + + + + + + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=77 + + + Sign Up + + + + + Apply + + Important: Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days.]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to step 3. + + + + + + + + +
    + + + + No + Paga con la carta o con il tuo conto PayPal + Il metodo ideale + per farsi pagare online + Rapido, affidabile, innovativo + Inizia subito a vendere con PayPal. Bastano 5 minuti + + Conquista nuovi clienti
    Oltre 110 milioni di conti PayPal attivi nel mondo +
  135. Espandi la tua base utenti anche all'estero
    190 Paesi e 25 valute diverse
  136. +
  137. Offri più protezione ai tuoi clienti
    Chi compra non condivide i dati personali
  138. +
  139. Accetta le principali carte di credito e prepagate
    Visa, Mastecard, Amex, Aura, PayPal, etc.
  140. + ]]> +
    + + Il tuo Paese + change + Select your country + + Hai bisogno di aiuto?]]> Chiamaci: 848 390 110 + call + * Costo da rete fissa: 6,8 cent. di euro per il primo minuto e 1,6 cent. di euro per quelli successivi. Per conoscere il costo della chiamata da telefono cellulare, contatta il tuo gestore mobile. Per le chiamate internazionali, rivolgiti al numero: + 353 1436 9021 (possono essere applicate le tariffe internazionali). + + Hai già un conto PayPal Business + Seleziona il prodotto che fa per te + Scopri di più]]> + + Vuoi usare PayPal per elaborare tutti i tuoi i pagamenti online ? + Vuoi PayPal come metodo di pagamento aggiuntivo ? + + Scegli + + Pagamenti su sito web + + Inizia subito a vendere online.]]> + Nessun costo iniziale né tariffe mensili. Paghi solo quando ricevi pagamenti. + + + PayPal Pro + + Il POS Virtuale completo, protezione delle vendite inclusa.]]> + *Accetti le principali carte di credito o prepagate e personalizzi la pagina di pagamento.]]> + Abbonamento mensile: €29 EUR. + *Soggetto ai termini e alle limitazioni delle ]]>Condizioni d'Uso]]>. + + Clicca il pulsante SALVA in fondo alla pagina solo dopo che PayPal avrà approvato la tua richiesta per PayPal Pro. Può richiedere 3-5 giorni. + + Pagamento express + Puoi conquistare nuovi clienti in tutto il mondo e aumentare le vendite. Gli acquirenti pagano in 3 clic e tu vendi anche su cellulare. + + + Richiedi PayPal Pro o apri un conto PayPal Business + + Accetta pagamenti online sul tuo sito + + Clicca il pulsante di seguito per fornire le tue credenziali PayPal a PrestaShop + + Richiedi le credenziali PayPal + Dopo aver cliccato il pulsante, inserisci nome utente e password nella finestra di pop up: da qui copia le credenziali PayPal ottenute e incollale nei campi di seguito. + Username API + Password API + Firma API + API business e-mail + Controlla di aver inserito correttamente tutti i caratteri. + + Completa l'attivazione del tuo conto PayPal + Conferma il tuo indirizzo email: controlla l'email inviata da PayPal quando hai creato il conto + Collega il conto bancario o la carta di credito al tuo conto PayPal: accedi alla sezione “Informazioni generali" del tuo conto. + + Opzioni di configurazione + + Scegli la soluzione che vuoi utilizzare + iFrame + Reindirizzamento completo della pagina + Scegli il template + + Scegli il pulsante di Pagamento express + I tuoi clienti pagano in soli 2 clic + + Scegli Sand box + (consigliato) + Avrai a disposizione un ambiente di test sul tuo conto PayPal. + Scopri di più + Modalità Live (consigliato) + Modalità Test + + Se attivi la modalità Test + + Non potrai accettare pagamenti +
  141. Dovrai tornare alla pagina PayPal e completare il terzo passaggio prima di andare live.
  142. +
  143. Dovrai creare un conto sul sito Sandbox di PayPal. (Scopri di più)
  144. +
  145. Devi avere competenze informatiche
  146. + ]]> + + Sei sicuro di voler attivare la modalità test ? + + Tipo di pagamento + Scegli il tuo metodo per processare pagamenti: (automatico vs autorizzazione manuale). + Direct sales + Authorization/Manual capture (payment shipping) + + Salva + + Per ricevere i pagamenti online, devi completare il terzo passaggio. + + Complimenti. + Ora puoi ricevere pagamenti con PayPal. + Ora puoi provare i prodotti PayPal. Ricorda di tornare su questa pagina e attivare la modalità live per iniziare ad accettare pagamenti. + + + Registrati + Quando avrai aperto il conto, torna su questa pagina e completa il terzo passaggio. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=6 + + + Richiedilo + + Clicca il pulsante SALVA in fondo alla pagina solo dopo che PayPal avrà approvato la tua richiesta per PayPal Pro,]]> + altrimenti non potrai elaborare i pagamenti. Può richiedere 3-5 giorni. + + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=8 + + + Registrati + Quando avrai aperto il conto, torna in questa pagina e completa il terzo passaggio. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=7 + + + + Richiedilo + + Importante! Clicca il pulsante SALVA in fondo alla pagina solo dopo che PayPal avrà approvato la tua richiesta per PayPal Pro,]]> + altrimenti non potrai elaborare il pagamento. Può richiedere 3-5 giorni.]]> + ]]> + Se invece PayPal ha già approvato la tua richiesta per PayPal Pro, vai direttamente al ]]>terzo passaggio]]>. + + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=8 + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  147. Access international buyers
    190 countries, 25 currencies
  148. +
  149. Reassure your buyers
    Buyers don’t need to share their private data
  150. +
  151. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  152. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call : 03-6739-7360 or 0120-271-888 + call + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + Website Payments Plus + A professional platform that enables you to accept debit card, credit card and PayPal payments. Customised payment pages. Monthly subscription of JPY 3,000. To sign-up, please contact a PayPal customer service representative. + Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days. + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  153. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  154. +
  155. You’ll need to create an account on the PayPal sandbox site (learn more)
  156. +
  157. You’ll need programming skills
  158. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=55 + + + Apply + + "Contact a PayPal sales representative at 03-6739-7360 or 0120-271-888]]> + Please only click the SAVE button at the bottom of the page once PayPal has approved your application for this product, otherwise you won't be able to process any card payments. This process can take up to 3-5 days" + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=82 + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=56 + + + Sign Up + + + + + Apply + Contact a PayPal sales representative at 03-6739-7360 or 0120-271-888 + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=39 + + + + + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  159. Access international buyers
    190 countries, 25 currencies
  160. +
  161. Reassure your buyers
    Buyers don’t need to share their private data
  162. +
  163. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  164. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call : 60-3-77237155 + call + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + + + + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  165. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  166. +
  167. You’ll need to create an account on the PayPal sandbox site (learn more)
  168. +
  169. You’ll need programming skills
  170. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=70 + + + + + + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=71 + + + Sign Up + + + + + Apply + + Important: Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days.]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to step 3. + + + + + + + + +
    + + + Ja + Nee + Betaal met uw creditcard of PayPal-account + Het + Nieuwe Betalen + Makkelijk, Veilig en Overal. + Het openen van een PayPal-rekening neemt maar enkele minuten in beslag + + De ideale manier om te betalen en betaald te worden. +
  171. Miljoenen kopers kiezen PayPal vanwege de veilige en snelle koopervaring.
  172. +
  173. Verkopers zijn dol op PayPal, omdat ze daarmee hun omzet kunnen vergroten en betalingen beter kunnen beheren.
  174. + ]]> +
    + + Land + Wijzig + Selecteer uw land + + Hulp nodig?]]> Neem contact op met een van onze adviseurs: 0900 265 8950 + call + + + Heeft u al een zakelijke PayPal-rekening + Kies het product wat bij u past + Meer weten]]> + + U wilt betalingen via creditcard en bankoverschrijving accepteren? + Wilt u PayPal als aanvulling op uw huidige betaalsysteem? + + Kies + + PayPal Standard Checkout + als u binnen enkele minuten met online verkopen wilt beginnen. ]]> + Geen vaste, opstart- of annuleringskosten: enkel een laag tarief voor het ontvangen van betalingen. + + + + + + + Express Checkout + u vergroot uw omzet en ontvangt uw betaling in slechts drie klikken (ook op mobiele apparaten). + + + Open nu uw zakelijke PayPal-rekening. + + Configureer uw instellingen om betalingen te kunnen accepteren + + Vul uw identificatiegegevens van PayPal in de PrestaShop omgeving + Indicate the email you used when you signed up for a PayPal Business account + Vraag mijn identificatiegegevens op bij PayPal + Klik op de knop "Vraag mijn identificatiegegevens op bij PayPal" en kopieer je gebruikersnaam en wachtwoord uit het informatieveld in de onderstaande velden. + API gebruikersnaam + API wachtwoord + Handtekening + API business e-mail + Kijk de gegevens die je net hebt gekopieerd goed na. Sommige velden bevatten namelijk veel karakters. + + Om de configuratie van je PayPal account te finaliseren zijn onderstaande acties noodzakelijk + Volg de procedure die via PayPal verstuurd is tijdens het aanmaken van je account om je e-mail te bevestigen. + Koppel je PayPal account aan een bankrekening of bankkaart. Om dit te doen log je in in je PayPal account en ga je naar de sectie "eerste stappen". + + PayPal configuratieopties + + Kies de betaaloplossing die u wilt gebruiken + Iframe + Full page redirect + Kies uw sjabloon + + Gebruik PayPal Express Checkout Shortcut + Geef je klanten de mogelijkheid om in twee stappen te betalen + + Gebruik de Sandbox + (aanbevolen) + Stel een testomgeving in in je PayPal account (enkel voor ontwikkelaars) + Meer info + Productieomgeving (aanbevolen) + Testomgeving + + Bij activeren van de test-modus + + Bent u nog niet in staat om betalingen te accepteren. +
  175. Dient u, voor u live kunt gaan, de PayPal-identificatie gegevens in te vullen bij stap 3.
  176. +
  177. Heeft u een PayPal Sandbox account nodig (learn more).
  178. +
  179. Dient u kennis van programmeren of een programmeur beschikbaar te hebben.
  180. + ]]> +
    + Weet u zeker dat de test wilt activeren ? + + Payment type + Kies de manier waarop je betaling wordt verwerkt (automatisch of handmatige autorisatie). + Direct sales (aanbevolen) + Authorization/Manual capture (automatische of handmatige autorisatie) + + Opslaan + + Om betalingen te kunnen ontvangen, dient u de PayPal-identificatie gegevens in te vullen bij stap 3. + + Gefeliciteerd ! + U kunt nu betalingen met PayPal ontvangen! + U kunt nu beginnen met het testen van PayPal oplossingen. Indien u de live-modus wilt activeren, kunt u de instelling op deze pagina + wijzigen en direct beginnen met het accepteren van betalingen via PayPal. + + + Rekening openen + Zodra u uw PayPal-rekening geopend heeft, kunt u op deze pagina stap 3 voltooien. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=17 + + + Rekening openen + + + + + Rekening openen + Zodra u uw PayPal-rekening geopend heeft, kunt u op deze pagina stap 3 voltooien + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=18 + + + Rekening openen + Overslaan + + + + Overslaan + + + + Rekening openen +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  181. Access international buyers
    190 countries, 25 currencies
  182. +
  183. Reassure your buyers
    Buyers don’t need to share their private data
  184. +
  185. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  186. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call : (888) 221-1161 + call + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + + + + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  187. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  188. +
  189. You’ll need to create an account on the PayPal sandbox site (learn more)
  190. +
  191. You’ll need programming skills
  192. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=52 + + + + + + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=53 + + + Sign Up + + + + + Apply + Important: Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days.]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to step 3. + + + + + + + +
    + + + Tak + Nie + Pay with your card or your PayPal account + ŚWIATOWY LIDER + PŁATNOŚCI ONLINE + Łatwiejsze, szybsze i bezpieczniejsze płatności dla Twoich kupujących. + Wdrożenie płatności PayPal zajmie Ci tylko kilka minut + + Dodatkowi klienci
    Na świecie jest już ponad 100 milionów aktywnych kont PayPal +
  193. Międzynarodowy zasięg
    PayPal jest dostępny w 190 krajach i 25 walutach
  194. +
  195. Bezpieczeństwo dla Twoich klientów
    Kupujący nie muszą ujawniać swoich danych finansowych
  196. +
  197. Lokalne metody płatności
    Ulubione, lokalne metody płatności są podane jak na tacy
  198. + ]]> +
    + + Twój kraj + Zmień + Select your country + + Potrzebujesz pomocy ?]]> Zadzwoń do nas pod numer 801 386 686 + call + + + Masz już firmowe konto PayPal + WYBIERZ ROZWIĄZANIE DOPASOWANE DO TWOICH POTRZEB + Dowiedz się więcej]]> + + Chcesz akceptować płatności za pomocą systemu PayPal? + Chcesz akceptować PayPal jako dodatkową metodę płatności? + + Wybierz + + PayPal Standard + + Akceptuj płatności PayPal już dziś. Możesz wykorzystać gotowe przyciski płatności PayPal lub samodzielnie dostosować rozwiązanie oparte na kodzie HTML.]]> + Bez opłat abonamentowych. Opłaty naliczane są tylko za odbiór płatności. + + + + + + + PayPal Express + + Dzięki prostocie procesu realizacji transakcji klienci częściej i regularniej kupują w Twoim sklepie, a Twoja sprzedaż wzrasta nawet o 30%*.]]> + Bez opłat abonamentowych. Opłaty naliczane są tylko za odbiór płatności. + + *Źródło: badania firmy Forrester zrealizowane w marcu 2011 + + ZAŁÓŻ FIRMOWE KONTO PAYPAL + + ODBIERAJ PŁATNOŚCI BEZPOŚREDNIO ZA POMOCĄ SWOJEGO SKLEPU INTERNETOWEGO + + Przekaż dane uwierzytelniające API swojego konta PayPal do systemu PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + UZYSKAJ DANE UWIERZYTELNIAJĄCE SWOJEGO KONTA PAYPAL + Po kliknięciu przycisku Uzyskaj dane uwierzytelniające swojego konta PayPal wprowadź w małym oknie pojawiającym się na tle bieżącej strony adres e-mail i hasło swojego konta PayPal, skopiuj dane uwierzytelniające API swojego konta PayPal, a następnie wklej w polach poniżej. + Użytkownik API + Hasło API + Podpis API + API business e-mail + Upewnij się, że wszystkie znaki zostały przez Ciebie poprawnie skopiowane i wklejone. + + Aby zakończyć konfigurację konta PayPal, musisz + Potwierdzić swój adres email: odszukaj wiadomość e-mail wysłaną przez system PayPal po założeniu konta PayPal. + Powiąż ze swoim kontem PayPal kartę kredytową lub rachunek bankowy: zaloguj się do swojego konta PayPal i kliknij łącze ]]>Powiąż kartę z kontem PayPal]]> i potwierdź ją lub łącze ]]>Powiąż rachunek bankowy z kontem PayPal]]> i potwierdź go. + + Opcje konfiguracji + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Wybierz PayPal Express + pozwól swoim klientom płacić dwoma kliknięciami + + Skorzystaj z platformy testowej Sandbox + + skorzystaj ze środowiska testowego, aby wypróbować system PayPal. + Dowiedz się więcej + Tryb rzeczywisty + Tryb testowy + + W środowisku testowym Sandbox + + konieczne będzie stworzenie testowych kont PayPal dla sprzedawcy i kupującego (dowiedz sie więcej) +
  199. nie będzie można akceptować rzeczywistych płatności
  200. +
  201. Aby akceptować rzeczywiste płatności, przejdź do kroku numer 3 na tej stronie.
  202. + ]]> +
    + Chcesz skorzystać ze środowiska testowego ? + + Metoda płatności + Wybierz sposób dokonywania płatności (automatycznie vs. ręczna autoryzacja). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Zachowaj + + Musisz uzupełnić dane uwierzytelniające swojego konta PayPal w kroku numer 3, aby móc akceptować rzeczywiste płatności. + + Konfiguracja przebiegła pomyślnie ! + Teraz możesz już akceptować płatności PayPal. + Teraz możesz już testować płatności PayPal. Pamiętaj, że musisz wrócić do tej strony, aby aktywować tryb rzeczywisty i akceptować płatności PayPal. + + + Załóż konto + Po założeniu konta, wróć do tej strony, aby dokończyć proces. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=32 + + + + + + + + Załóż konto + Po założeniu konta, wróć do tej strony, aby dokończyć proces. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=33 + + + + + + + + + + + + + Pomiń ten krok + + + +
    + + + Sim + Não + Pague com o PayPal em 8x sem juros + Líder em + Pagamentos online + Fácil, seguro, rápido pagamento para seus clientes. + Só leva alguns minutos para começar com o PayPal + + Conquiste mais clientes
    Mais de 100 milhões de contas ativas no Paypal mundialmente +
  203. Acesse clientes internacionais
    190 países, 25 moedas
  204. +
  205. Dê garantia aos seus clientes
    Compradores não precisam compartilhar informações privadas
  206. +
  207. Aceite todos os principais métodos de pagamento
    Visa, Mastercard, PayPal, etc.
  208. + ]]> +
    + + Seu país + Mudar + Selecione seu país + + Precisa de Ajuda?]]> Entre em contato:08008921555]]>(Serviço de atendimento ao cliente) + Ligue + + + Já tem uma conta PayPal para empresa + Selecione sua solução + Saiba mais]]> + + Precisa do Paypal para processar todos seus pagamentos por cartão? + Precisa do Paypal além do seu processador de cartão de crédito atual? + + Escolher + + Website Payments Standard + + Comece a aceitar pagamentos imediatamente.]]> + Sem taxa de assinatura, somente uma pequena taxa de transação quando você recebe pagamento. + + + + + + + Checkout Express + Aumente em 30% suas vendas on-line * com um simples processo de 3 cliques para a finalização da compra. + *Fonte1: Pesquisa Forrester conduzida em março de 2011 + + Registre-se para sua conta para empresa gratuíta do Paypal + + Processe pagamentos na sua loja virtual + + Forneça suas credenciais da API do Paypal para o PrestaShop + Indique o email que você usou quando você se cadastrou para uma conta para empresa do Paypal + Obtenha minhas credenciais da API do PayPal + Clique aqui e coloque no pop-up seu email e senha de login no Paypal, então copie e cole suas credenciais da API do PayPal nos campos abaixo. + API usuário + API senha + API assinatura + API e-mail da empresa + Por favor verifique que você tenha copiado todos os caractéres. + + Para finalizar a configuração da sua conta Paypal, você precisa + Confirmar seu endereço de email : veja o email enviado pelo Paypal quando você criou sua conta + Vincule sua conta do Paypal à uma conta bancária ou uma conta de cartão de crédito: Acesse sua conta PayPal e vá à “My business setup” + + Opções de Configuração + + Escolha a solução que quer utilizar + iFrame + Redireccionamento de página completa + Seleccione um template + + Atalho para Checkout Express + Ofereça ao seu cliente uma experiência de 3 cliques para finalização da compra + + Use uma Sandbox + + Ative um ambiente teste em sua conta Paypal (somente para desenvolvedores). + Saiba mais + Modo Live (recomendado) + Modo teste + + Por favor note que se você escolher ativar o modo teste + + Você ainda não poderá aceitar pagamentos +
  209. Você vai precisar voltar para a página do módulo PayPal para poder completar o Passo 3 antes de colocar no ar
  210. +
  211. Você vai precisar criar uma conta no site sandbox do PayPal (saiba mais)
  212. +
  213. Você vai precisar entender de programação
  214. + ]]> +
    + Você tem certeza que você quer ativar o modo teste? + + Tipo de pagamento + Escolha sua maneira de processar pagamentos (automaticamente vs.autorização manual). + Vendas diretas (recomendado) + Autorização/Captura manual (payment shipping) + + Salvar + + Você precisa fornecer suas credenciais da API do Paypal no passo 3 para poder aceitar pagamentos. + + Parabéns! + Você pode começar agora a aceitar pagamentos com PayPal. + Você pode começar agora a testar as soluções do PayPal. Uma vez que você realizar seus testes, não esqueça de voltar para esta página e ativar o modo live para começar a aceitar pagamentos. + + + Cadastre-se + Uma vez que você abriu sua conta PayPal, ou se você já tem uma, continue no passo 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=79 + + + + + + + + Cadastre-se + Uma vez que sua conta for criada, volte nesta página para completar o passo 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=80 + + + Cadastre-se + + + + + Cadastre-se + + Importante: Por favor clique no botão SALVAR no pé da página quando o Paypal aprovar seu pedido de cadastro para este produto, ao contrário você não conseguirá processar nenhum pagamento por cartão. Este processo pode levar de 3 a 5 dias.]]> + Se o seu pedido de cadastro para Website Payments Pro já foi aprovado pelo Paypal, por favor vá diretamente para o passo 3. + + + + + + + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  215. Access international buyers
    190 countries, 25 currencies
  216. +
  217. Reassure your buyers
    Buyers don’t need to share their private data
  218. +
  219. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  220. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call :+65 6510 4584]]>(a Singapore telephone number) + call + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + + + + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  221. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  222. +
  223. You’ll need to create an account on the PayPal sandbox site (learn more)
  224. +
  225. You’ll need programming skills
  226. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=79 + + + + + + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=80 + + + Sign Up + + + + + Apply + + Important: Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days.]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to step 3. + + + + + + + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  227. Access international buyers
    190 countries, 25 currencies
  228. +
  229. Reassure your buyers
    Buyers don’t need to share their private data
  230. +
  231. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  232. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Visit www.Paypal.com]]> + + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + + + + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  233. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  234. +
  235. You’ll need to create an account on the PayPal sandbox site (learn more)
  236. +
  237. You’ll need programming skills
  238. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=45 + + + + + + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=46 + + + Sign Up + + + + + Apply + + + + + + + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  239. Access international buyers
    190 countries, 25 currencies
  240. +
  241. Reassure your buyers
    Buyers don’t need to share their private data
  242. +
  243. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  244. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call : 65-6510-4650 + call + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + + + + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  245. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  246. +
  247. You’ll need to create an account on the PayPal sandbox site (learn more)
  248. +
  249. You’ll need programming skills
  250. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=67 + + + + + + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=68 + + + Sign Up + + + + + Apply + + Important: Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days.]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to step 3. + + + + + + + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  251. Access international buyers
    190 countries, 25 currencies
  252. +
  253. Reassure your buyers
    Buyers don’t need to share their private data
  254. +
  255. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  256. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call : +65 6590-5502]]>(a Singapore telephone number) + call + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + + + + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  257. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  258. +
  259. You’ll need to create an account on the PayPal sandbox site (learn more)
  260. +
  261. You’ll need programming skills
  262. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=73 + + + + + + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=74 + + + Sign Up + + + + + Apply + + Important: Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days.]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to step 3. + + + + + + + + +
    + + + Evet + Hayır + Pay with your card or your PayPal account + ONLINE ÖDEME + ÇÖZÜMLERİNDE LİDER MARKA + Müşterileriniz için güvenli ve pratik ödeme yöntemi. + PayPal ile satış yapmaya başlamak yalnızca birkaç dakikanızı alır + + Müşteri tabanınızı genişletin
    PayPal ile başlıca kredi kartlarından ödeme alın ve PayPal'ı tercih eden 100 milyondan fazla aktif kullanıcıya erişin +
  263. Uluslararası pazarlara açılın
    PayPal 190 ülkede ve 25 para birimi ile kullanılıyor
  264. +
  265. Müşterilerinizi güvende hissettirin
  266. +
  267. PayPal ile müşterileriniz kart bilgileri gibi hassas bilgileri paylaşmadan alışveriş yapabilirler
  268. + ]]> +
    + + Ülkeniz + Değiştir + Select your country + + Yardıma mı ihtiyacınız var ?]]> Bize ulaşın : 444 77 01 + call + + + Zaten PayPal Ticari hesap sahibi misiniz + Bir ödeme çözümü seçin + Daha fazla bilgi alın]]> + + Tüm kart işlenmesini PayPal tarafından işlenmesini mi istiyorsunuz ? + Varolan ödeme çözümünüze ek olarak PayPal'ı mı eklemek istiyorsunuz? + + Önerimiz + + PayPal Website Payments Standard + Hemen ödeme almaya başlayın. Hayır. + + + + + + PayPal Express Checkout + Satışlarınızı artırmanın güvenli yolu + + + PayPal Tícarí hesabı açın + + ÖDEME ALABİLMEK İÇİN WEB MAĞAZANIZI ETKİNLEŞTİRİN + + PayPal kimlik bilgilerinizi PrestaShop'a gönderin: + Indicate the email you used when you signed up for a PayPal Business account + PAYPAL KİMLİK BİLGİLERİMİ GÖRMEK İSTİYORUM + Yukarıdaki düğmeyi tıkladıktan sonra açılan sayfada PayPal kullanıcı adınızı ve şifrenizi girin. PayPal kimlik bilgilerinizi kopyalayın ve aşağıdaki alanlara yapıştırın. + API kullanıcı ismi + API şifresi + API imzanız + API business e-mail + Lütfen doğru karakterleri girdiğinizden emin olun. + + PayPal hesabınızın kurulumunu tamamlamak için + E-posta adresinizi onaylayın: PayPal'dan size gönderilecek onay e-postasındaki adımları izleyin + PayPal hesabınıza kredi kartınızı ekleyin ve onaylayın: PayPal hesabınıza giriş yapın ve Hesap Araçlarım kutusundaki "Ticari Ayarlarım" bağlantısını tıklayın + + Hesap ayarı seçenekleriniz + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + PayPal Express Checkout kullanın + Müşterilerinize 2 tıkla ödeme seçeneği sunun + + Sandbox kullanın + + PayPal hesabınızda bir test ortamı oluşturun (programlamcılar içindir) + Daha fazla bilgi alın + Canlı mod + Test modu + + Test modunu aktive etmek + + Ödeme alamayacağınız +
  269. 3. adımı tamamlamak için PayPal modül sayfasına geri gelmeniz gerektiği
  270. +
  271. PayPal sandbox hesabı oluşturmanız (daha fazla bilgi alın)
  272. +
  273. Programlama becerilerine sahip olduğunuz
  274. + ]]> +
    + anlamına gelir. Test modunu aktive etmek istediğinizden emin misiniz? + + Ödeme türü + Ödemelerin nasıl işlenmesini istediğinizi seçin (otomatik olarak veya manuel yetkilendirme). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Kaydedin + + 3. adımda açıklanan PayPal kimlik bilgilerini tamamlamanız gerekmektedir. Aksi halde ödeme alamazsınız. + + Tebrikler ! + Artık PayPal ile ödeme almaya başlayabilirsiniz. + Artık PayPal ödeme çözümlerini test edebilirsiniz. Daha sonra bu sayfaya gelip canlı modu aktive ederek ödeme almayı unutmayın. + + + HESAP AÇIN + Hesabınızı açtıktan sonra ödeme çözümünüzü eklemek için aşağıdaki adrese gidin + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=35 + + + + + + + + HESAP AÇIN + Hesabınızı açtıktan sonra 3. adımı tamamlamak için aşağıdaki adrese gidin: + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=36 + + + HESAP AÇIN + Bu adımı atlayın + + + + + + + + + + Bu adımı atlayın + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  275. Access international buyers
    190 countries, 25 currencies
  276. +
  277. Reassure your buyers
    Buyers don’t need to share their private data
  278. +
  279. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  280. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call : 02-8729-6625 + call + + + Already have a PayPal business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + + + + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + API business e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  281. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  282. +
  283. You’ll need to create an account on the PayPal sandbox site (learn more)
  284. +
  285. You’ll need programming skills
  286. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=64 + + + + + + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=65 + + + Sign Up + + + + + Apply + + Important: Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days.]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to step 3. + + + + + + + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  287. Access international buyers
    190 countries, 25 currencies
  288. +
  289. Reassure your buyers
    Buyers don’t need to share their private data
  290. +
  291. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  292. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call on 1-877-419-7765 + call + + + Already have a PayPal Business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + Website Payments Pro Hosted + A professional platform that enables you to accept debit card, credit card and PayPal payments. Customised payment pages.]]> Monthly subscription of £20. + Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days. + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + PayPal Business account e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  293. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  294. +
  295. You’ll need to create an account on the PayPal sandbox site (learn more)
  296. +
  297. You’ll need programming skills
  298. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=84 + + + Apply + Please only click the SAVE button at the bottom of the page once PayPal has approved your application for this product, otherwise you won't be able to process any card payments. This process can take up to 3-5 days + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=85 + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=86 + + + Sign Up + + + + + Apply + Important: Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days.]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to ]]>step 3]]>. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=85 + + + + + + +
    + + + Yes + No + Pay with your card or your PayPal account + Leader in + online payments + Easy, secure, fast payments for your buyers. + It only takes a few minutes to get started with PayPal + + Get more buyers
    Over 100 million active PayPal accounts worldwide +
  299. Access international buyers
    190 countries, 25 currencies
  300. +
  301. Reassure your buyers
    Buyers don’t need to share their private data
  302. +
  303. Accept all major payment methods
    Visa, Mastercard, PayPal, etc.
  304. + ]]> +
    + + Your country + change + Select your country + + Need help?]]> Give us a call on 1-877-419-7765 + call + + + Already have a PayPal Business account + Select your solution + Learn more]]> + + Need PayPal to process all your card payments ? + Need PayPal in addition to your existing card processor ? + + Choose + + Website Payments Standard + + Start accepting payments immediately.]]> + No subscription fees, only a small transaction fee when you get paid. + + + Website Payments Pro Hosted + A professional platform that enables you to accept debit card, credit card and PayPal payments. Customised payment pages.]]> Monthly subscription of £20. + Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days. + + Express Checkout + Boost your online sales by 30%* with a simple 3-click checkout process. + *Source: Forrester research conducted in March 2011 + + Sign up for your free PayPal Business account + + Process payments on your online shop + + Provide your PayPal API credentials to PrestaShop + Indicate the email you used when you signed up for a PayPal Business account + Get my PayPal API credentials + Click here and enter your PayPal email login and password in the pop-up, then copy and paste your PayPal API credentials into the fields below. + API username + API password + API signature + PayPal Business account e-mail + Please check that you have copied in all the characters. + + To finalize setting up your PayPal account, you need to + Confirm your email address : check the email sent by PayPal when you created your account + Link your PayPal account to a bank account or a credit card : log into your PayPal account and go to “My business setup” + + Configuration options + + Choose the solution you want to use + Iframe + Full page redirect + Choose your template + + Express Checkout shortcut + Offer your customers a 3-click checkout experience + + Use a Sandbox + + Activate a test environment in your PayPal account (developer only). + Learn more + Live mode (recommended) + Test mode + + Please note that if you choose to activate the test mode + + You won’t be able to accept payments yet +
  305. You will need to come back to the PayPal module page in order to complete Step 3 before going live
  306. +
  307. You’ll need to create an account on the PayPal sandbox site (learn more)
  308. +
  309. You’ll need programming skills
  310. + ]]> +
    + Are you sure you want to activate the test mode ? + + Payment type + Choose your way of processing payments (automatically vs.manual authorization). + Direct sales (recommended) + Authorization/Manual capture (payment shipping) + + Save + + You need to provide your PayPal API credentials in step 3 in order to accept payments. + + Congratulation ! + You can now start accepting payments with PayPal. + You can now start testing PayPal solutions. Once you've carried out your tests, don’t forget to come back to this page and activate the live mode in order to start accepting payments. + + + Sign Up + Once you've opened your PayPal account or if you have one already, then continue to step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=84 + + + Apply + Please only click the SAVE button at the bottom of the page once PayPal has approved your application for this product, otherwise you won't be able to process any card payments. This process can take up to 3-5 days + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=86 + + + Sign Up + Once your account has been created, come back to this page in order to complete step 3. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=85 + + + Sign Up + + + + + Apply + Important: Please click on the SAVE button at the bottom of the page only once PayPal has approved your application for this product, otherwise you won’t be able to process any card payments. This process can take up to 3-5 days.]]> + If your application for Website Payments Pro has already been approved by PayPal, please go directly to ]]>step 3]]>. + https://altfarm.mediaplex.com/ad/ck/3484-148727-12439-23?ID=40 + + + + + + +
    + +
    diff --git a/modules/paypal/upgrade/index.php b/modules/paypal/upgrade/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/upgrade/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/upgrade/install-2.8.php b/modules/paypal/upgrade/install-2.8.php new file mode 100644 index 00000000..9f2290af --- /dev/null +++ b/modules/paypal/upgrade/install-2.8.php @@ -0,0 +1,121 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +if (!defined('_PS_VERSION_')) + exit; + +function upgrade_module_2_8($object, $install = false) +{ + if (!Configuration::get('PAYPAL_NEW') && ($object->active || $install)) + { + $result = true; + + /* Check PayPal API */ + if (file_exists(_PS_MODULE_DIR_.'paypalapi/paypalapi.php')) + { + $confs = Configuration::getMultiple(array('PAYPAL_HEADER', 'PAYPAL_SANDBOX', 'PAYPAL_API_USER', 'PAYPAL_API_PASSWORD', + 'PAYPAL_API_SIGNATURE', 'PAYPAL_EXPRESS_CHECKOUT')); + + include_once(_PS_MODULE_DIR_.'paypalapi/paypalapi.php'); + $paypalapi = new PayPalAPI(); + + if ($paypalapi->active) + { + if (Configuration::get('PAYPAL_INTEGRAL') == 1) + Configuration::updateValue('PAYPAL_PAYMENT_METHOD', WPS); + elseif (Configuration::get('PAYPAL_INTEGRAL') == 0) + Configuration::updateValue('PAYPAL_PAYMENT_METHOD', ECS); + + $paypalapi->uninstall(); + Configuration::loadConfiguration(); + + foreach ($confs as $key => $value) + Configuration::updateValue($key, $value); + } + } + + /* Create Table */ + if (!Db::getInstance()->Execute(' + CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'paypal_order` ( + `id_order` int(10) unsigned NOT null auto_increment, + `id_transaction` varchar(255) NOT null, + PRIMARY KEY (`id_order`) + ) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8')) + $result = false; + + if (!Db::getInstance()->Execute(' + ALTER TABLE `'._DB_PREFIX_.'paypal_order` ADD `payment_method` INT NOT null, + ADD `payment_status` VARCHAR(255) NOT null, + ADD `capture` INT NOT null')) + $result = false; + + /* Hook */ + $object->registerHook('cancelProduct'); + $object->registerHook('adminOrder'); + + /* Create OrderState */ + if (!Configuration::get('PAYPAL_OS_AUTHORIZATION')) + { + $order_state = new OrderState(); + $order_state->name = array(); + + foreach (Language::getLanguages() as $language) + { + if (Tools::strtolower($language['iso_code']) == 'fr') + $order_state->name[$language['id_lang']] = 'Autorisation acceptée par PayPal'; + else + $order_state->name[$language['id_lang']] = 'Authorization accepted from PayPal'; + } + + $order_state->send_email = false; + $order_state->color = '#DDEEFF'; + $order_state->hidden = false; + $order_state->delivery = false; + $order_state->logable = true; + $order_state->invoice = true; + + if ($order_state->add()) + copy(_PS_ROOT_DIR_.'/img/os/'.Configuration::get('PS_OS_PAYPAL').'.gif', _PS_ROOT_DIR_.'/img/os/'.(int)$order_state->id.'.gif'); + + Configuration::updateValue('PAYPAL_OS_AUTHORIZATION', (int)$order_state->id); + } + /* Delete unseless configuration */ + Configuration::deleteByName('PAYPAL_INTEGRAL'); + + /* Add new Configurations */ + if (!Configuration::get('PAYPAL_PAYMENT_METHOD')) + Configuration::updateValue('PAYPAL_PAYMENT_METHOD', WPS); + Configuration::updateValue('PAYPAL_CAPTURE', 0); + Configuration::updateValue('PAYPAL_TEMPLATE', 'A'); + + if ($result) + Configuration::updateValue('PAYPAL_NEW', 1); + return $result; + } + + $object->upgrade_detail['2.8'][] = 'PayPalAPI upgrade error !'; + return false; +} \ No newline at end of file diff --git a/modules/paypal/upgrade/install-3.0.php b/modules/paypal/upgrade/install-3.0.php new file mode 100644 index 00000000..3335310a --- /dev/null +++ b/modules/paypal/upgrade/install-3.0.php @@ -0,0 +1,82 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +if (!defined('_PS_VERSION_')) + exit; + +function upgrade_module_3_0($object, $install = false) +{ + $paypal_version = Configuration::get('PAYPAL_VERSION'); + + if ((!$paypal_version) || (empty($paypal_version)) || ($paypal_version < $object->version)) + { + /* Update hooks */ + $object->registerHook('payment'); + $object->registerHook('paymentReturn'); + $object->registerHook('shoppingCartExtra'); + $object->registerHook('backBeforePayment'); + $object->registerHook('cancelProduct'); + $object->registerHook('productFooter'); + $object->registerHook('header'); + $object->registerHook('adminOrder'); + $object->registerHook('backOfficeHeader'); + + Configuration::updateValue('PAYPAL_VERSION', $object->version); + + $payment_method = (int)Configuration::get('PAYPAL_PAYMENT_METHOD'); + $payment_methods = array(0 => WPS, 2 => HSS, 1 => ECS); + + Configuration::updateValue('PAYPAL_PAYMENT_METHOD', (int)$payment_methods[$payment_method]); + Configuration::updateValue('PAYPAL_BUSINESS_ACCOUNT', Configuration::get('PAYPAL_BUSINESS')); + Configuration::updateValue('PAYPAL_BUSINESS', 0); + } + + if (count(Db::getInstance()->ExecuteS('SHOW TABLES FROM `'._DB_NAME_.'` LIKE \''._DB_PREFIX_.'paypal_order\'')) > 0) + { + $columns = array(array('name' => 'id_invoice', 'type' => 'varchar(255) DEFAULT NULL'), + array('name' => 'currency', 'type' => 'varchar(10) NOT NULL'), + array('name' => 'total_paid', 'type' => 'varchar(50) NOT NULL'), + array('name' => 'shipping', 'type' => 'varchar(50) NOT NULL'), + array('name' => 'payment_date', 'type' => 'varchar(50) NOT NULL'), + array('name' => 'capture', 'type' => 'int(2) NOT NULL')); + + foreach ($columns as $column) + if (!Db::getInstance()->ExecuteS('SHOW COLUMNS FROM `'._DB_PREFIX_.'paypal_order` LIKE \''.pSQL($column['name']).'\'')) + Db::getInstance()->Execute('ALTER TABLE `'._DB_PREFIX_.'paypal_order` ADD `'.pSQL($column['name']).'` '.$column['type']); + } + + if (count(Db::getInstance()->ExecuteS('SHOW TABLES FROM `'._DB_NAME_.'` LIKE \''._DB_PREFIX_.'paypal_customer\'')) <= 0) + { + Db::getInstance()->Execute(' + CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'paypal_customer` ( + `id_paypal_customer` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id_customer` int(10) unsigned NOT NULL, + `paypal_email` varchar(255) NOT NULL, + PRIMARY KEY (`id_paypal_customer`) + ) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8 AUTO_INCREMENT=1'); + } + return true; +} diff --git a/modules/paypal/upgrade/install-3.10.1.php b/modules/paypal/upgrade/install-3.10.1.php new file mode 100644 index 00000000..16c88f44 --- /dev/null +++ b/modules/paypal/upgrade/install-3.10.1.php @@ -0,0 +1,42 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +if (!defined('_PS_VERSION_')) + exit; + +function upgrade_module_3_10_1($object, $install = false) +{ + $paypal_version = Configuration::get('PAYPAL_VERSION'); + + if(Configuration::get('PAYPAL_IN_CONTEXT_CHECKOUT_MERCHANT_ID') != false) + { + Configuration::updateValue('PAYPAL_IN_CONTEXT_CHECKOUT_M_ID', Configuration::get('PAYPAL_IN_CONTEXT_CHECKOUT_MERCHANT_ID')); + Configuration::deleteByName('PAYPAL_IN_CONTEXT_CHECKOUT_MERCHANT_ID'); + } + + Configuration::updateValue('PAYPAL_VERSION', '3.10.1'); + return true; +} diff --git a/modules/paypal/upgrade/install-3.7.php b/modules/paypal/upgrade/install-3.7.php new file mode 100644 index 00000000..3682c99a --- /dev/null +++ b/modules/paypal/upgrade/install-3.7.php @@ -0,0 +1,58 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +if (!defined('_PS_VERSION_')) + exit; + +function upgrade_module_3_7($object, $install = false) +{ + $paypal_version = Configuration::get('PAYPAL_VERSION'); + + if ((!$paypal_version) || (empty($paypal_version)) || ($paypal_version < $object->version)) + { + if (!Db::getInstance()->Execute(' + CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'paypal_login_user` ( + `id_paypal_login_user` INT(11) AUTO_INCREMENT, + `id_customer` INT(11) NOT NULL, + `token_type` VARCHAR(255) NOT NULL, + `expires_in` VARCHAR(255) NOT NULL, + `refresh_token` VARCHAR(255) NOT NULL, + `id_token` VARCHAR(255) NOT NULL, + `access_token` VARCHAR(255) NOT NULL, + `account_type` VARCHAR(255) NOT NULL, + `user_id` VARCHAR(255) NOT NULL, + `verified_account` VARCHAR(255) NOT NULL, + `zoneinfo` VARCHAR(255) NOT NULL, + `age_range` VARCHAR(255) NOT NULL, + PRIMARY KEY (`id_paypal_login_user`) + ) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8')) + return false; + Configuration::updateValue('PAYPAL_VERSION', '3.7.0'); + } + + + return true; +} diff --git a/modules/paypal/upgrade/install-3.8.3.php b/modules/paypal/upgrade/install-3.8.3.php new file mode 100644 index 00000000..13a40ea4 --- /dev/null +++ b/modules/paypal/upgrade/install-3.8.3.php @@ -0,0 +1,53 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +if (!defined('_PS_VERSION_')) + exit; + +function upgrade_module_3_8_3($object, $install = false) +{ + $paypal_version = Configuration::get('PAYPAL_VERSION'); + + if ((!$paypal_version) || (empty($paypal_version)) || ($paypal_version < $object->version)) + { + if (Db::getInstance()->ExecuteS('SHOW COLUMNS FROM `'._DB_PREFIX_.'paypal_order` LIKE \'id_invoice\'') == false) + Db::getInstance()->Execute('ALTER TABLE `'._DB_PREFIX_.'paypal_order` ADD `id_invoice` varchar(255) DEFAULT NULL'); + if (Db::getInstance()->ExecuteS('SHOW COLUMNS FROM `'._DB_PREFIX_.'paypal_order` LIKE \'currency\'') == false) + Db::getInstance()->Execute('ALTER TABLE `'._DB_PREFIX_.'paypal_order` ADD `currency` varchar(10) DEFAULT NULL'); + if (Db::getInstance()->ExecuteS('SHOW COLUMNS FROM `'._DB_PREFIX_.'paypal_order` LIKE \'total_paid\'') == false) + Db::getInstance()->Execute('ALTER TABLE `'._DB_PREFIX_.'paypal_order` ADD `total_paid` varchar(50) DEFAULT NULL'); + if (Db::getInstance()->ExecuteS('SHOW COLUMNS FROM `'._DB_PREFIX_.'paypal_order` LIKE \'shipping\'') == false) + Db::getInstance()->Execute('ALTER TABLE `'._DB_PREFIX_.'paypal_order` ADD `shipping` varchar(50) DEFAULT NULL'); + if (Db::getInstance()->ExecuteS('SHOW COLUMNS FROM `'._DB_PREFIX_.'paypal_order` LIKE \'payment_date\'') == false) + Db::getInstance()->Execute('ALTER TABLE `'._DB_PREFIX_.'paypal_order` ADD `payment_date` varchar(50) DEFAULT NULL'); + + + Configuration::updateValue('PAYPAL_VERSION', '3.8.3'); + } + + + return true; +} \ No newline at end of file diff --git a/modules/paypal/upgrade/install-3.9.php b/modules/paypal/upgrade/install-3.9.php new file mode 100644 index 00000000..ceaa28c1 --- /dev/null +++ b/modules/paypal/upgrade/install-3.9.php @@ -0,0 +1,52 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +if (!defined('_PS_VERSION_')) + exit; + +function upgrade_module_3_9($object, $install = false) +{ + $paypal_version = Configuration::get('PAYPAL_VERSION'); + + if ((!$paypal_version) || (empty($paypal_version)) || ($paypal_version < $object->version)) + { + if (!Db::getInstance()->Execute(' + CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'paypal_capture` ( + `id_paypal_capture` int(11) NOT NULL AUTO_INCREMENT, + `id_order` int(11) NOT NULL, + `capture_amount` float NOT NULL, + `result` text NOT NULL, + `date_add` datetime NOT NULL, + `date_upd` datetime NOT NULL, + PRIMARY KEY (`id_paypal_capture`) + ) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;')) + return false; + Configuration::updateValue('PAYPAL_VERSION', '3.9.0'); + } + + + return true; +} \ No newline at end of file diff --git a/modules/paypal/views/css/index.php b/modules/paypal/views/css/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/views/css/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/views/css/paypal.css b/modules/paypal/views/css/paypal.css new file mode 100644 index 00000000..5cdc8f63 --- /dev/null +++ b/modules/paypal/views/css/paypal.css @@ -0,0 +1,58 @@ +#paypal-column-block p{text-align:center} +.bold{font-weight:700} +.clear{clear:both} +#paypal-wrapper .half{width:44%} +#paypal-wrapper{font-size:1.1em;position:relative} +#paypal-wrapper ul li{text-align:left} +#paypal-wrapper hr{border-top:1px solid #ccc!important;margin-bottom:0;margin-top:20px} +#paypal-wrapper .toolbox{background:#fff2cf;border:1px solid #aaa;color:#000;display:none;font-size:10px;font-weight:400;left:730px;line-height:12px;padding:6px!important;position:absolute;text-transform:none;top:-10px!important;width:180px;z-index:100} +.disabled,.disabled *,.disabled * *,.disabled * * *{color:#888!important} +.disabled .paypal-button,.disabled input[type=submit]{background:#DDD!important;border:1px solid #999!important} +#paypal-wrapper .inline{display:inline;margin-right:5px} +#paypal-wrapper .box{margin:6px 1%;padding:12px;text-align:left} +#paypal-wrapper .box ul{list-style:none;margin:0;padding:0} +#paypal-wrapper .box ul.tick li{background:url(../img/blue_tick.png) no-repeat left 3px;padding:4px 26px} +span.paypal-section{background:url(../img/sprites.png) no-repeat 0 0;color:#FFF!important;float:left;height:24px;line-height:24px;margin-right:8px;text-align:center;width:24px} +.disabled span.paypal-section{background:url(../img/sprites.png) 0 24px} +#paypal-slogan{font-size:1.8em;margin:0 0 5px;text-transform:uppercase} +#paypal-slogan .light{color:#369} +#paypal-slogan .dark{color:#036} +#paypal-call-button{margin:-6px 0 0;padding:0} +#paypal-call,#paypal-call-foonote{background:#e1e1e1 url(../img/bg-call-button.png) repeat-x;border:1px solid #d2d2d2;border-left-color:#ddd;border-radius:5px;border-right-color:#ddd;border-top-color:#e9e9e9;color:#369;display:block;margin:0;padding:10px 20px;width:auto} +#paypal-call-foonote{background:none;border:none;font-size:.8em;max-width:320px;padding:2px 10px;text-align:justify} +#paypal-get-identification{display:block;min-width:378px;text-align:center} +#paypal-wrapper a,#paypal-test-mode-confirmation a{color:#036;text-decoration:underline} +#paypal-wrapper h1,#paypal-wrapper h2,#paypal-wrapper h3,#paypal-wrapper h4,#paypal-wrapper h5,#paypal-wrapper h6,#paypal-country-form h1, #paypal-test-mode-confirmation h1,#paypal-country-form h2, #paypal-test-mode-confirmation h2,#paypal-country-form h3, #paypal-test-mode-confirmation h3,#paypal-country-form h4, #paypal-test-mode-confirmation h4,#paypal-country-form h5, #paypal-test-mode-confirmation h5,#paypal-country-form h6, #paypal-test-mode-confirmation h6{color:#036;font-family:Arial, Verdana, Helvetica, sans-serif;font-weight:400;text-transform:uppercase} +#paypal-country-form h3, #paypal-test-mode-confirmation h3,#paypal-wrapper h3{font-size:1.4em;line-height:24px} +#paypal-country-form h4, #paypal-test-mode-confirmation h4,#paypal-wrapper h4{font-size:1.2em;margin-bottom:5px;text-transform:none} +#paypal-wrapper h1.inline + img,#paypal-wrapper h2.inline + img,#paypal-wrapper h3.inline + img,#paypal-wrapper h4.inline + img,#paypal-wrapper h5.inline + img,#paypal-wrapper h6.inline + img{vertical-align:-6px} +#paypal-wrapper p{margin-top:10px;padding-bottom:0} +#paypal-wrapper .form-block{margin-top:5px} +#paypal-wrapper .form-block input{vertical-align:top} +#paypal-wrapper dl dt{clear:both;line-height:20px;margin-bottom:2px;text-align:right;width:220px} +#paypal-wrapper dl dd{margin:0 0 16px 10px} +#paypal-wrapper label{display:inline-block;float:none;font-size:.9em;font-weight:400;margin-bottom:5px;padding-left:6px;padding-top:0;position:relative;text-align:left;width:auto} +#paypal-wrapper dl dt label{margin:0;padding:0} +#paypal-wrapper .description,#paypal-wrapper .paypal-signup-content{color:#666;font-size:.9em;font-weight:400;margin:2px 0;font-size:11px; font-style:italic;} +label span.description{display:block;padding-left:16px} +#paypal-wrapper input[type=submit],#paypal-country-form button, #paypal-test-mode-confirmation button,#paypal-wrapper .paypal-button{background:url(../img/bg-button.png) repeat-x;border:1px solid #f29116;border-radius:4px;color:#292929;cursor:pointer;display:inline-block;font-weight:700;height:25px;line-height:26px;padding:0 10px;text-decoration:none;text-shadow:0 1px 1px #DDD;text-transform:uppercase} +#paypal-country-form ul, #paypal-test-mode-confirmation ul{font-size:1.1em;padding-left:10px} +#paypal-country-form button, #paypal-test-mode-confirmation button{line-height:20px} +#paypal-test-mode-confirmation{margin:30px;text-align:left;width:500px} +#paypal-country-form #buttons, paypal-test-mode-confirmation#buttons{margin-top:20px;text-align:right} +#paypal-test-mode-confirmation button + button{margin-left:20px;margin-right:20px} +#paypal-save-success,#paypal-save-failure{width:450px} +#container_express_checkout{margin:auto;text-align:left} +#payment_paypal_express_checkout{cursor:pointer} +.paypal_error span{color:red;font-weight:bolder} +.paypal_payment_acccepted span{color:green;font-weight:bolder} +#paypal_configuration > .box{margin-left:0;margin-right:0;padding-left:0;padding-right:0} +#paypal-wrapper .left,#paypal-wrapper dl > *{float:left} +#paypal-wrapper .right,.box ul.tick{float:right} +.paypal-hide{display:none} +#paypal-wrapper .merchant_id { + margin-top: 0px; +} +#paypal-wrapper .merchant_id label { + padding-left: 0px; +} \ No newline at end of file diff --git a/modules/paypal/views/img/bg-button.png b/modules/paypal/views/img/bg-button.png new file mode 100644 index 00000000..e7b1a9a0 Binary files /dev/null and b/modules/paypal/views/img/bg-button.png differ diff --git a/modules/paypal/views/img/bg-call-button.png b/modules/paypal/views/img/bg-call-button.png new file mode 100644 index 00000000..e0455ae7 Binary files /dev/null and b/modules/paypal/views/img/bg-call-button.png differ diff --git a/modules/paypal/views/img/blue_tick.png b/modules/paypal/views/img/blue_tick.png new file mode 100644 index 00000000..9b27b496 Binary files /dev/null and b/modules/paypal/views/img/blue_tick.png differ diff --git a/modules/paypal/views/img/bo-cards/AU_bo_cards.png b/modules/paypal/views/img/bo-cards/AU_bo_cards.png new file mode 100644 index 00000000..665df4c5 Binary files /dev/null and b/modules/paypal/views/img/bo-cards/AU_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/CN_bo_cards.png b/modules/paypal/views/img/bo-cards/CN_bo_cards.png new file mode 100644 index 00000000..be7071ff Binary files /dev/null and b/modules/paypal/views/img/bo-cards/CN_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/DE_bo_cards.png b/modules/paypal/views/img/bo-cards/DE_bo_cards.png new file mode 100644 index 00000000..18d0bbd5 Binary files /dev/null and b/modules/paypal/views/img/bo-cards/DE_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/ES_bo_cards.png b/modules/paypal/views/img/bo-cards/ES_bo_cards.png new file mode 100644 index 00000000..e1fe0c5e Binary files /dev/null and b/modules/paypal/views/img/bo-cards/ES_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/FR_bo_cards.png b/modules/paypal/views/img/bo-cards/FR_bo_cards.png new file mode 100644 index 00000000..088bdcb1 Binary files /dev/null and b/modules/paypal/views/img/bo-cards/FR_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/GB_bo_cards.png b/modules/paypal/views/img/bo-cards/GB_bo_cards.png new file mode 100644 index 00000000..52fb111b Binary files /dev/null and b/modules/paypal/views/img/bo-cards/GB_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/HK_bo_cards.png b/modules/paypal/views/img/bo-cards/HK_bo_cards.png new file mode 100644 index 00000000..2b72a3b0 Binary files /dev/null and b/modules/paypal/views/img/bo-cards/HK_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/IT_bo_cards.png b/modules/paypal/views/img/bo-cards/IT_bo_cards.png new file mode 100644 index 00000000..07d62529 Binary files /dev/null and b/modules/paypal/views/img/bo-cards/IT_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/MY_bo_cards.png b/modules/paypal/views/img/bo-cards/MY_bo_cards.png new file mode 100644 index 00000000..63a9693f Binary files /dev/null and b/modules/paypal/views/img/bo-cards/MY_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/NZ_bo_cards.png b/modules/paypal/views/img/bo-cards/NZ_bo_cards.png new file mode 100644 index 00000000..0a820b0f Binary files /dev/null and b/modules/paypal/views/img/bo-cards/NZ_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/PL_bo_cards.png b/modules/paypal/views/img/bo-cards/PL_bo_cards.png new file mode 100644 index 00000000..c3d47f8f Binary files /dev/null and b/modules/paypal/views/img/bo-cards/PL_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/PayPal_bo_cards.png b/modules/paypal/views/img/bo-cards/PayPal_bo_cards.png new file mode 100644 index 00000000..b4e6392f Binary files /dev/null and b/modules/paypal/views/img/bo-cards/PayPal_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/RA_bo_cards.png b/modules/paypal/views/img/bo-cards/RA_bo_cards.png new file mode 100644 index 00000000..0eea77fa Binary files /dev/null and b/modules/paypal/views/img/bo-cards/RA_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/RE_bo_cards.png b/modules/paypal/views/img/bo-cards/RE_bo_cards.png new file mode 100644 index 00000000..0eea77fa Binary files /dev/null and b/modules/paypal/views/img/bo-cards/RE_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/SG_bo_cards.png b/modules/paypal/views/img/bo-cards/SG_bo_cards.png new file mode 100644 index 00000000..4713d912 Binary files /dev/null and b/modules/paypal/views/img/bo-cards/SG_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/TH_bo_cards.png b/modules/paypal/views/img/bo-cards/TH_bo_cards.png new file mode 100644 index 00000000..483d63fa Binary files /dev/null and b/modules/paypal/views/img/bo-cards/TH_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/TR_bo_cards.png b/modules/paypal/views/img/bo-cards/TR_bo_cards.png new file mode 100644 index 00000000..483d63fa Binary files /dev/null and b/modules/paypal/views/img/bo-cards/TR_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/TW_bo_cards.png b/modules/paypal/views/img/bo-cards/TW_bo_cards.png new file mode 100644 index 00000000..483d63fa Binary files /dev/null and b/modules/paypal/views/img/bo-cards/TW_bo_cards.png differ diff --git a/modules/paypal/views/img/bo-cards/default.png b/modules/paypal/views/img/bo-cards/default.png new file mode 100644 index 00000000..405131a3 Binary files /dev/null and b/modules/paypal/views/img/bo-cards/default.png differ diff --git a/modules/paypal/views/img/bo-cards/index.php b/modules/paypal/views/img/bo-cards/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/views/img/bo-cards/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/views/img/call.png b/modules/paypal/views/img/call.png new file mode 100644 index 00000000..2f7e284b Binary files /dev/null and b/modules/paypal/views/img/call.png differ diff --git a/modules/paypal/views/img/default_logos/AU_vertical_solution_PP.png b/modules/paypal/views/img/default_logos/AU_vertical_solution_PP.png new file mode 100644 index 00000000..6e932ef9 Binary files /dev/null and b/modules/paypal/views/img/default_logos/AU_vertical_solution_PP.png differ diff --git a/modules/paypal/views/img/default_logos/BE_horizontal_solution_PP.png b/modules/paypal/views/img/default_logos/BE_horizontal_solution_PP.png new file mode 100644 index 00000000..c5bbfaf3 Binary files /dev/null and b/modules/paypal/views/img/default_logos/BE_horizontal_solution_PP.png differ diff --git a/modules/paypal/views/img/default_logos/BE_vertical_solution_PP.png b/modules/paypal/views/img/default_logos/BE_vertical_solution_PP.png new file mode 100644 index 00000000..cb799f54 Binary files /dev/null and b/modules/paypal/views/img/default_logos/BE_vertical_solution_PP.png differ diff --git a/modules/paypal/views/img/default_logos/DE_horizontal_solution_PP.gif b/modules/paypal/views/img/default_logos/DE_horizontal_solution_PP.gif new file mode 100644 index 00000000..b4324141 Binary files /dev/null and b/modules/paypal/views/img/default_logos/DE_horizontal_solution_PP.gif differ diff --git a/modules/paypal/views/img/default_logos/DE_vertical_solution_PP.gif b/modules/paypal/views/img/default_logos/DE_vertical_solution_PP.gif new file mode 100644 index 00000000..b4324141 Binary files /dev/null and b/modules/paypal/views/img/default_logos/DE_vertical_solution_PP.gif differ diff --git a/modules/paypal/views/img/default_logos/FR_vertical_solution_PP.png b/modules/paypal/views/img/default_logos/FR_vertical_solution_PP.png new file mode 100644 index 00000000..826baa20 Binary files /dev/null and b/modules/paypal/views/img/default_logos/FR_vertical_solution_PP.png differ diff --git a/modules/paypal/views/img/default_logos/PL_horizontal_solution_PP.png b/modules/paypal/views/img/default_logos/PL_horizontal_solution_PP.png new file mode 100644 index 00000000..9ab199cb Binary files /dev/null and b/modules/paypal/views/img/default_logos/PL_horizontal_solution_PP.png differ diff --git a/modules/paypal/views/img/default_logos/PL_vertical_solution_PP.png b/modules/paypal/views/img/default_logos/PL_vertical_solution_PP.png new file mode 100644 index 00000000..dbdaf65e Binary files /dev/null and b/modules/paypal/views/img/default_logos/PL_vertical_solution_PP.png differ diff --git a/modules/paypal/views/img/default_logos/RA_horizontal_solution_PP.png b/modules/paypal/views/img/default_logos/RA_horizontal_solution_PP.png new file mode 100644 index 00000000..9ab199cb Binary files /dev/null and b/modules/paypal/views/img/default_logos/RA_horizontal_solution_PP.png differ diff --git a/modules/paypal/views/img/default_logos/RA_vertical_solution_PP.png b/modules/paypal/views/img/default_logos/RA_vertical_solution_PP.png new file mode 100644 index 00000000..dbdaf65e Binary files /dev/null and b/modules/paypal/views/img/default_logos/RA_vertical_solution_PP.png differ diff --git a/modules/paypal/views/img/default_logos/RE_horizontal_solution_PP.png b/modules/paypal/views/img/default_logos/RE_horizontal_solution_PP.png new file mode 100644 index 00000000..9ab199cb Binary files /dev/null and b/modules/paypal/views/img/default_logos/RE_horizontal_solution_PP.png differ diff --git a/modules/paypal/views/img/default_logos/RE_vertical_solution_PP.png b/modules/paypal/views/img/default_logos/RE_vertical_solution_PP.png new file mode 100644 index 00000000..dbdaf65e Binary files /dev/null and b/modules/paypal/views/img/default_logos/RE_vertical_solution_PP.png differ diff --git a/modules/paypal/views/img/default_logos/default_horizontal.png b/modules/paypal/views/img/default_logos/default_horizontal.png new file mode 100644 index 00000000..8c57be0e Binary files /dev/null and b/modules/paypal/views/img/default_logos/default_horizontal.png differ diff --git a/modules/paypal/views/img/default_logos/default_logo.gif b/modules/paypal/views/img/default_logos/default_logo.gif new file mode 100644 index 00000000..2a587165 Binary files /dev/null and b/modules/paypal/views/img/default_logos/default_logo.gif differ diff --git a/modules/paypal/views/img/default_logos/default_vertical.png b/modules/paypal/views/img/default_logos/default_vertical.png new file mode 100644 index 00000000..ee99c030 Binary files /dev/null and b/modules/paypal/views/img/default_logos/default_vertical.png differ diff --git a/modules/paypal/views/img/default_logos/index.php b/modules/paypal/views/img/default_logos/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/views/img/default_logos/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/views/img/index.php b/modules/paypal/views/img/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/views/img/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/views/img/logos/default_PayPal_logo_100x45.gif b/modules/paypal/views/img/logos/default_PayPal_logo_100x45.gif new file mode 100644 index 00000000..5f9ff8bc Binary files /dev/null and b/modules/paypal/views/img/logos/default_PayPal_logo_100x45.gif differ diff --git a/modules/paypal/views/img/logos/default_PayPal_logo_150x65.gif b/modules/paypal/views/img/logos/default_PayPal_logo_150x65.gif new file mode 100644 index 00000000..1e2a9546 Binary files /dev/null and b/modules/paypal/views/img/logos/default_PayPal_logo_150x65.gif differ diff --git a/modules/paypal/views/img/logos/default_PayPal_logo_80x35.gif b/modules/paypal/views/img/logos/default_PayPal_logo_80x35.gif new file mode 100644 index 00000000..a94b479c Binary files /dev/null and b/modules/paypal/views/img/logos/default_PayPal_logo_80x35.gif differ diff --git a/modules/paypal/views/img/logos/default_PayPal_mark_37x23.gif b/modules/paypal/views/img/logos/default_PayPal_mark_37x23.gif new file mode 100644 index 00000000..25333b17 Binary files /dev/null and b/modules/paypal/views/img/logos/default_PayPal_mark_37x23.gif differ diff --git a/modules/paypal/views/img/logos/default_PayPal_mark_50x34.gif b/modules/paypal/views/img/logos/default_PayPal_mark_50x34.gif new file mode 100644 index 00000000..9640eb0b Binary files /dev/null and b/modules/paypal/views/img/logos/default_PayPal_mark_50x34.gif differ diff --git a/modules/paypal/views/img/logos/default_PayPal_mark_60x38.gif b/modules/paypal/views/img/logos/default_PayPal_mark_60x38.gif new file mode 100644 index 00000000..2a587165 Binary files /dev/null and b/modules/paypal/views/img/logos/default_PayPal_mark_60x38.gif differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/CO_de_DE_orange_295x43.png b/modules/paypal/views/img/logos/express_checkout_mobile/CO_de_DE_orange_295x43.png new file mode 100644 index 00000000..103b8253 Binary files /dev/null and b/modules/paypal/views/img/logos/express_checkout_mobile/CO_de_DE_orange_295x43.png differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/CO_en_EN_orange_295x43.png b/modules/paypal/views/img/logos/express_checkout_mobile/CO_en_EN_orange_295x43.png new file mode 100644 index 00000000..57d24de9 Binary files /dev/null and b/modules/paypal/views/img/logos/express_checkout_mobile/CO_en_EN_orange_295x43.png differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/CO_en_US_orange_295x43.png b/modules/paypal/views/img/logos/express_checkout_mobile/CO_en_US_orange_295x43.png new file mode 100644 index 00000000..57d24de9 Binary files /dev/null and b/modules/paypal/views/img/logos/express_checkout_mobile/CO_en_US_orange_295x43.png differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/CO_es_ES_orange_295x43.png b/modules/paypal/views/img/logos/express_checkout_mobile/CO_es_ES_orange_295x43.png new file mode 100644 index 00000000..f64cf4be Binary files /dev/null and b/modules/paypal/views/img/logos/express_checkout_mobile/CO_es_ES_orange_295x43.png differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/CO_fr_FR_orange_295x43.png b/modules/paypal/views/img/logos/express_checkout_mobile/CO_fr_FR_orange_295x43.png new file mode 100644 index 00000000..19435467 Binary files /dev/null and b/modules/paypal/views/img/logos/express_checkout_mobile/CO_fr_FR_orange_295x43.png differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/CO_it_IT_orange_295x43.png b/modules/paypal/views/img/logos/express_checkout_mobile/CO_it_IT_orange_295x43.png new file mode 100644 index 00000000..d8b73d0d Binary files /dev/null and b/modules/paypal/views/img/logos/express_checkout_mobile/CO_it_IT_orange_295x43.png differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/CO_ja_JP_orange_295x43.png b/modules/paypal/views/img/logos/express_checkout_mobile/CO_ja_JP_orange_295x43.png new file mode 100644 index 00000000..dc563323 Binary files /dev/null and b/modules/paypal/views/img/logos/express_checkout_mobile/CO_ja_JP_orange_295x43.png differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/CO_nl_NL_orange_295x43.png b/modules/paypal/views/img/logos/express_checkout_mobile/CO_nl_NL_orange_295x43.png new file mode 100644 index 00000000..4220f846 Binary files /dev/null and b/modules/paypal/views/img/logos/express_checkout_mobile/CO_nl_NL_orange_295x43.png differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/CO_pl_PL_orange_295x43.png b/modules/paypal/views/img/logos/express_checkout_mobile/CO_pl_PL_orange_295x43.png new file mode 100644 index 00000000..41f6ef53 Binary files /dev/null and b/modules/paypal/views/img/logos/express_checkout_mobile/CO_pl_PL_orange_295x43.png differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/CO_pt_BR_orange_295x43.png b/modules/paypal/views/img/logos/express_checkout_mobile/CO_pt_BR_orange_295x43.png new file mode 100644 index 00000000..d59b9c23 Binary files /dev/null and b/modules/paypal/views/img/logos/express_checkout_mobile/CO_pt_BR_orange_295x43.png differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/CO_zh_CN_orange_295x43.png b/modules/paypal/views/img/logos/express_checkout_mobile/CO_zh_CN_orange_295x43.png new file mode 100644 index 00000000..a57d817b Binary files /dev/null and b/modules/paypal/views/img/logos/express_checkout_mobile/CO_zh_CN_orange_295x43.png differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/CO_zh_HK_orange_295x43.png b/modules/paypal/views/img/logos/express_checkout_mobile/CO_zh_HK_orange_295x43.png new file mode 100644 index 00000000..d10ff5e3 Binary files /dev/null and b/modules/paypal/views/img/logos/express_checkout_mobile/CO_zh_HK_orange_295x43.png differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/CO_zh_TW_orange_295x43.png b/modules/paypal/views/img/logos/express_checkout_mobile/CO_zh_TW_orange_295x43.png new file mode 100644 index 00000000..d10ff5e3 Binary files /dev/null and b/modules/paypal/views/img/logos/express_checkout_mobile/CO_zh_TW_orange_295x43.png differ diff --git a/modules/paypal/views/img/logos/express_checkout_mobile/index.php b/modules/paypal/views/img/logos/express_checkout_mobile/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/views/img/logos/express_checkout_mobile/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/views/img/logos/index.php b/modules/paypal/views/img/logos/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/views/img/logos/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/views/img/mail.png b/modules/paypal/views/img/mail.png new file mode 100644 index 00000000..a6197415 Binary files /dev/null and b/modules/paypal/views/img/mail.png differ diff --git a/modules/paypal/views/img/paypal.gif b/modules/paypal/views/img/paypal.gif new file mode 100644 index 00000000..e480d4b0 Binary files /dev/null and b/modules/paypal/views/img/paypal.gif differ diff --git a/modules/paypal/views/img/paypal_login_blue.png b/modules/paypal/views/img/paypal_login_blue.png new file mode 100644 index 00000000..dad37879 Binary files /dev/null and b/modules/paypal/views/img/paypal_login_blue.png differ diff --git a/modules/paypal/views/img/paypal_login_grey.png b/modules/paypal/views/img/paypal_login_grey.png new file mode 100644 index 00000000..a6973ec0 Binary files /dev/null and b/modules/paypal/views/img/paypal_login_grey.png differ diff --git a/modules/paypal/views/img/sprites.png b/modules/paypal/views/img/sprites.png new file mode 100644 index 00000000..de5a4148 Binary files /dev/null and b/modules/paypal/views/img/sprites.png differ diff --git a/modules/paypal/views/img/template.png b/modules/paypal/views/img/template.png new file mode 100644 index 00000000..7221d5bc Binary files /dev/null and b/modules/paypal/views/img/template.png differ diff --git a/modules/paypal/views/index.php b/modules/paypal/views/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/views/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/views/js/back_office.js b/modules/paypal/views/js/back_office.js new file mode 100644 index 00000000..9d844bd8 --- /dev/null +++ b/modules/paypal/views/js/back_office.js @@ -0,0 +1,308 @@ +/* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +$(document).ready( function() { + var identificationButtonClicked = false; + + /* Display correct block according to different choices. */ + function displayConfiguration() { + identificationButtonClicked = false; + + var paypal_business = $('input[name="business"]:checked').val(); + var paypal_payment_method = $('input[name="paypal_payment_method"]:checked').val(); + var integral_evolution_solution = $('input[name="integral_evolution_solution"]:checked').val(); + $('#signup span.paypal-signup-content').hide(); + $('#signup .paypal-signup-button').hide(); + + switch (paypal_business) { + case '0': + $('#signup').slideDown(); + $('#account').removeClass('disabled'); + $('#credentials').addClass('disabled'); + $('input[type="submit"]').attr('disabled', 'disabled'); + + switch (paypal_payment_method) { + case PayPal_WPS: + $('.toolbox').slideUp(); + $('#integral-credentials').slideUp(); + $('#standard-credentials').slideDown(); + $('#paypal-signup-button-u1').show(); + $('#paypal-signup-content-u1').show(); + $('#integral_evolution_solution').slideUp(); + $('#express_checkout_shortcut').slideDown(); + $('#in_context_checkout').slideDown(); + break; + case PayPal_HSS: + $('#signup').slideDown(); + $('#paypal-signup-button-u2').show(); + $('#paypal-signup-content-u2').show(); + $('#standard-credentials').slideUp(); + $('#account').removeClass('disabled'); + $('#standard-credentials').slideUp(); + $('#express_checkout_shortcut').slideUp(); + $('#integral-credentials').slideDown(); + $('#integral_evolution_solution').slideDown(); + $('label[for="paypal_payment_wpp"] .toolbox').slideDown(); + $('#in_context_checkout').slideUp(); + switch (integral_evolution_solution) + { + case "1": //Iframe + $('#integral_evolution_template').slideUp(); + break; + case "0": //Redirection + $('#integral_evolution_template').slideDown(); + break; + } + break; + case PayPal_ECS: + $('.toolbox').slideUp(); + $('#integral-credentials').slideUp(); + $('#standard-credentials').slideDown(); + $('#paypal-signup-button-u3').show(); + $('#paypal-signup-content-u3').show(); + $('#integral_evolution_solution').slideUp(); + $('#express_checkout_shortcut').slideDown(); + $('#in_context_checkout').slideDown(); + break; + } + break; + case '1': + $('#configuration').slideDown(); + $('#account').addClass('disabled'); + $('#credentials').removeClass('disabled'); + $('input[type="submit"]').removeAttr('disabled'); + + switch (paypal_payment_method) { + case PayPal_WPS: + $('#signup').slideUp(); + $('#integral-credentials').slideUp(); + $('#standard-credentials').slideDown(); + $('#paypal-signup-button-u4').show(); + $('#integral_evolution_solution').slideUp(); + $('#express_checkout_shortcut').slideDown(); + $('#in_context_checkout').slideDown(); + break; + case PayPal_HSS: + $('#signup').slideDown(); + $('#paypal-signup-button-u5').show(); + $('#paypal-signup-content-u5').show(); + $('#account').removeClass('disabled'); + $('#standard-credentials').slideUp(); + $('#express_checkout_shortcut').slideUp(); + $('#integral-credentials').slideDown(); + $('#integral_evolution_solution').slideDown(); + $('label[for="paypal_payment_wpp"] .toolbox').slideDown(); + $('#in_context_checkout').slideUp(); + switch (integral_evolution_solution) + { + case "1": //Iframe + $('#integral_evolution_template').slideUp(); + break; + case "0": //Redirection + $('#integral_evolution_template').slideDown(); + break; + } + break; + case PayPal_ECS: + $('#signup').slideUp(); + $('#integral-credentials').slideUp(); + $('#standard-credentials').slideDown(); + $('#paypal-signup-button-u6').show(); + $('#integral_evolution_solution').slideUp(); + $('#express_checkout_shortcut').slideDown(); + $('#in_context_checkout').slideDown(); + break; + } + break; + } + + displayCredentials(); + return; + } + + if ($('#paypal-wrapper').length != 0) { + $('.hide').hide(); + displayConfiguration(); + } + + if ($('input[name="paypal_payment_method"]').length == 1) { + $('input[name="paypal_payment_method"]').attr('checked', 'checked'); + } + + function displayCredentials() { + var paypal_business = $('input[name="business"]:checked').val(); + var paypal_payment_method = $('input[name="paypal_payment_method"]:checked').val(); + + if (paypal_payment_method != PayPal_HSS && + ($('input[name="api_username"]').val().length > 0 || + $('input[name="api_password"]').val().length > 0 || + $('input[name="api_signature"]').val().length > 0)) { + $('#credentials').removeClass('disabled'); + $('#configuration').slideDown(); + $('input[type="submit"]').removeAttr('disabled'); + $('#standard-credentials').slideDown(); + $('#express_checkout_shortcut').slideDown(); + $('#integral-credentials').slideUp(); + } + else if (paypal_payment_method == PayPal_HSS && + ($('input[name="api_business_account"]').val().length > 0)) { + $('#credentials').removeClass('disabled'); + $('#configuration').slideDown(); + $('input[type="submit"]').removeAttr('disabled'); + $('#standard-credentials').slideUp(); + $('#express_checkout_shortcut').slideUp(); + $('#integral-credentials').slideDown(); + } + else if (paypal_business != 1) { + $('#configuration').slideUp(); + } + } + + $('input[name="business"], input[name="paypal_payment_method"], input[name="integral_evolution_solution"]').live('change', function() { + displayConfiguration(); + }); + + $('label, a').live('mouseover', function() { + $(this).children('.toolbox').show(); + }).live('mouseout', function() { + var id = $(this).attr('for'); + var input = $('input#'+id); + + if (!input.is(':checked')) + $(this).children('.toolbox').hide(); + if (($(this).attr('id') == 'paypal-get-identification') && + (identificationButtonClicked == false)) + $(this).children('.toolbox').hide(); + }); + + $('a.paypal-signup-button, a#step3').live('click', function() { + var paypal_business = $('input[name="business"]:checked').val(); + var paypal_payment_method = $('input[name="paypal_payment_method"]:checked').val(); + + $('#credentials').removeClass('disabled'); + if ($(this).attr('id') != 'paypal-signup-button-u3') + $('#account').addClass('disabled'); + + $('#configuration').slideDown(); + if (paypal_payment_method == PayPal_HSS) { + $('#standard-credentials').slideUp(); + $('#express_checkout_shortcut').slideUp(); + $('#integral-credentials').slideDown(); + } else { + $('#standard-credentials').slideDown(); + $('#express_checkout_shortcut').slideDown(); + $('#integral-credentials').slideUp(); + } + $('input[type="submit"]').removeAttr('disabled'); + + if ($(this).is('#step3')) { + return false; + } + return true; + }); + + + + if ($("#paypal-wrapper").length > 0) { + $('input[type="submit"]').live('click', function() { + var paypal_business = $('input[name="business"]:checked').val(); + var paypal_payment_method = $('input[name="paypal_payment_method"]:checked').val(); + + if ((paypal_payment_method != PayPal_HSS && + (($('input[name="api_username"]').val().length <= 0) || + ($('input[name="api_password"]').val().length <= 0) || + ($('input[name="api_signature"]').val().length <= 0))) || + ((paypal_payment_method == PayPal_HSS && + ($('input[name="api_business_account"]').val().length <= 0)))) { + $.fancybox({'content' : $('
    ').append($('#js-paypal-save-failure').clone().html())}); + return false; + } + return true; + }); + + $('input[name="sandbox_mode"]').live('change', function() { + if ($('input[name="sandbox_mode"]:checked').val() == '1') { + $('input[name="sandbox_mode"]').filter('[value="0"]').attr('checked', true); + var div = $('
    '); + var inner = $('#paypal-test-mode-confirmation').clone().html(); + $.fancybox({'hideOnOverlayClick' : true, 'content' : div.append(inner)}); + return false; + } + return true; + }); + + $('button.fancy_confirm').live('click', function() { + jQuery.fancybox.close(); + if ($(this).val() == '1') { + $('input[name="sandbox_mode"]').filter('[value="1"]').attr('checked', true); + } else { + $('input[name="sandbox_mode"]').filter('[value="0"]').attr('checked', true); + } + }); + + if ($('#paypal-save-success').length > 0) + $.fancybox({'hideOnOverlayClick' : true, 'content' : $('
    ').append($('#paypal-save-success').clone().html())}); + else if ($('#paypal-save-failure').length > 0) + $.fancybox({'hideOnOverlayClick' : true, 'content' : $('
    ').append($('#paypal-save-failure').clone().html())}); + + $('#paypal-get-identification').live('click', function() { + + identificationButtonClicked = true; + sandbox_prefix = $('#paypal_payment_test_mode').is(':checked') ? 'sandbox.' : ''; + var url = 'https://www.'+sandbox_prefix+'paypal.com/us/cgi-bin/webscr?cmd=_get-api-signature&generic-flow=true'; + var title = 'PayPal identification informations'; + window.open (url, title, config='height=500, width=360, toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, directories=no, status=no'); + return false; + }); + + $('a#paypal_country_change').live('click', function() { + var div = $('
    '); + var inner = $('#paypal-country-form-content').clone().html(); + $.fancybox({'content' : div.append(inner)}); + return false; + }); + + $('#paypal_country_default').live('change', function() { + var form = $('#paypal_configuration'); + form.append(''); + form.submit(); + }); + + + $("#paypal_login_yes_or_no input[name='paypal_login']").change(function(){ + var val = parseInt($(this).val()); + if (val === 1) + { + $("#paypal_login_configuration").slideDown(); + } + else + { + $("#paypal_login_configuration").slideUp(); + } + + }); + } + +}); diff --git a/modules/paypal/views/js/index.php b/modules/paypal/views/js/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/views/js/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/views/js/paypal.js b/modules/paypal/views/js/paypal.js new file mode 100644 index 00000000..3e6c778d --- /dev/null +++ b/modules/paypal/views/js/paypal.js @@ -0,0 +1,226 @@ +/* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +{if $PayPal_in_context_checkout == 1} + window.paypalCheckoutReady = function() { + paypal.checkout.setup("{$PayPal_in_context_checkout_merchant_id}", { + environment: {if $PAYPAL_SANDBOX}"sandbox"{else}"production"{/if}, + click: function(event) { + event.preventDefault(); + + paypal.checkout.initXO(); + updateFormDatas(); + var str = ''; + if($('#paypal_payment_form input[name="id_product"]').length > 0) + str += '&id_product='+$('#paypal_payment_form input[name="id_product"]').val(); + if($('#paypal_payment_form input[name="quantity"]').length > 0) + str += '&quantity='+$('#paypal_payment_form input[name="quantity"]').val(); + if($('#paypal_payment_form input[name="id_p_attr"]').length > 0) + str += '&id_p_attr='+$('#paypal_payment_form input[name="id_p_attr"]').val(); + + $.support.cors = true; + $.ajax({ + url: "{$base_dir_ssl}modules/paypal/express_checkout/payment.php", + type: "GET", + data: '&ajax=1&onlytoken=1&express_checkout='+$('input[name="express_checkout"]').val()+'¤t_shop_url='+$('input[name="current_shop_url"]').val()+'&bn='+$('input[name="bn"]').val()+str, + async: true, + crossDomain: true, + + //Load the minibrowser with the redirection url in the success handler + success: function (token) { + var url = paypal.checkout.urlPrefix +token; + //Loading Mini browser with redirect url, true for async AJAX calls + paypal.checkout.startFlow(url); + }, + error: function (responseData, textStatus, errorThrown) { + alert("Error in ajax post"+responseData.statusText); + //Gracefully Close the minibrowser in case of AJAX errors + paypal.checkout.closeFlow(); + } + }); + }, + button: ['paypal_process_payment', 'payment_paypal_express_checkout'] + }); + } +{/if} +{literal} + +function updateFormDatas() +{ + var nb = $('#quantity_wanted').val(); + var id = $('#idCombination').val(); + + $('#paypal_payment_form input[name=quantity]').val(nb); + $('#paypal_payment_form input[name=id_p_attr]').val(id); +} + +$(document).ready( function() { + + if($('#in_context_checkout_enabled').val() != 1) + { + $('#payment_paypal_express_checkout').click(function() { + $('#paypal_payment_form').submit(); + return false; + }); + } + + + + $('#paypal_payment_form').live('submit', function() { + updateFormDatas(); + }); + + function displayExpressCheckoutShortcut() { + var id_product = $('input[name="id_product"]').val(); + var id_product_attribute = $('input[name="id_product_attribute"]').val(); + $.ajax({ + type: "GET", + url: baseDir+'/modules/paypal/express_checkout/ajax.php', + data: { get_qty: "1", id_product: id_product, id_product_attribute: id_product_attribute }, + cache: false, + success: function(result) { + if (result == '1') { + $('#container_express_checkout').slideDown(); + } else { + $('#container_express_checkout').slideUp(); + } + return true; + } + }); + } + + $('select[name^="group_"]').change(function () { + setTimeout(function(){displayExpressCheckoutShortcut()}, 500); + }); + + $('.color_pick').click(function () { + setTimeout(function(){displayExpressCheckoutShortcut()}, 500); + }); + + if($('body#product').length > 0) + setTimeout(function(){displayExpressCheckoutShortcut()}, 500); + + {/literal} + {if isset($paypal_authorization)} + {literal} + + /* 1.5 One page checkout*/ + var qty = $('.qty-field.cart_quantity_input').val(); + $('.qty-field.cart_quantity_input').after(qty); + $('.qty-field.cart_quantity_input, .cart_total_bar, .cart_quantity_delete, #cart_voucher *').remove(); + + var br = $('.cart > a').prev(); + br.prev().remove(); + br.remove(); + $('.cart.ui-content > a').remove(); + + var gift_fieldset = $('#gift_div').prev(); + var gift_title = gift_fieldset.prev(); + $('#gift_div, #gift_mobile_div').remove(); + gift_fieldset.remove(); + gift_title.remove(); + + {/literal} + {/if} + {if isset($paypal_confirmation)} + {literal} + + $('#container_express_checkout').hide(); + + $('#cgv').live('click', function() { + if ($('#cgv:checked').length != 0) + $(location).attr('href', '{/literal}{$paypal_confirmation}{literal}'); + }); + + // old jQuery compatibility + $('#cgv').click(function() { + if ($('#cgv:checked').length != 0) + $(location).attr('href', '{/literal}{$paypal_confirmation}{literal}'); + }); + + {/literal} + {else if isset($paypal_order_opc)} + {literal} + + $('#cgv').live('click', function() { + if ($('#cgv:checked').length != 0) + checkOrder(); + }); + + // old jQuery compatibility + $('#cgv').click(function() { + if ($('#cgv:checked').length != 0) + checkOrder(); + }); + + {/literal} + {/if} + {literal} + + var modulePath = 'modules/paypal'; + var subFolder = '/integral_evolution'; + {/literal} + {if $ssl_enabled} + var baseDirPP = baseDir.replace('http:', 'https:'); + {else} + var baseDirPP = baseDir; + {/if} + {literal} + var fullPath = baseDirPP + modulePath + subFolder; + var confirmTimer = false; + + if ($('form[target="hss_iframe"]').length == 0) { + if ($('select[name^="group_"]').length > 0) + displayExpressCheckoutShortcut(); + return false; + } else { + checkOrder(); + } + + function checkOrder() { + if(confirmTimer == false) + confirmTimer = setInterval(getOrdersCount, 1000); + } + + {/literal}{if isset($id_cart)}{literal} + function getOrdersCount() { + + + $.get( + fullPath + '/confirm.php', + { id_cart: '{/literal}{$id_cart}{literal}' }, + function (data) { + if ((typeof(data) != 'undefined') && (data > 0)) { + clearInterval(confirmTimer); + window.location.replace(fullPath + '/submit.php?id_cart={/literal}{$id_cart}{literal}'); + $('p.payment_module, p.cart_navigation').hide(); + } + } + ); + } + {/literal}{/if}{literal} +}); + +{/literal} diff --git a/modules/paypal/views/js/paypal_login.js b/modules/paypal/views/js/paypal_login.js new file mode 100644 index 00000000..13042be6 --- /dev/null +++ b/modules/paypal/views/js/paypal_login.js @@ -0,0 +1,68 @@ +/* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +$(function(){ldelim} + if($("#create-account_form").length > 0) + {if $smarty.const._PS_VERSION_ >= 1.6} + $("#create-account_form").parent().before('
    '); + {else} + $("#create-account_form").before('
    '); + {/if} + else + {ldelim} + {if $smarty.const._PS_VERSION_ >= 1.6} + $("#login_form").parent().before('
    '); + {else} + $("#login_form").before('
    '); + {/if} + $("#buttonPaypalLogin1").css({ldelim} + "clear" : "both", + "margin-bottom" : "13px" + {rdelim}); + {rdelim} + + $("#buttonPaypalLogin1").css({ldelim} + "clear" : "both", + 'margin-bottom' : '10px', + {if $smarty.const._PS_VERSION_ >= 1.6} + 'margin-left' : '20px', + 'width' : '100%' + {/if} + {rdelim}); + + paypal.use( ["login"], function(login) {ldelim} + login.render ({ldelim} + "appid": "{$PAYPAL_LOGIN_CLIENT_ID}", + {if $PAYPAL_SANDBOX == 1} "authend" : "sandbox",{/if} + "scopes": "openid profile email address phone https://uri.paypal.com/services/paypalattributes https://uri.paypal.com/services/expresscheckout", + "containerid": "buttonPaypalLogin1", + {if $PAYPAL_LOGIN_TPL == 2} "theme" : "neutral", {/if} + "returnurl": "{$PAYPAL_RETURN_LINK}?{$page_name}", + 'locale' : '{$paypal_locale}', + {rdelim}); + {rdelim}); +{rdelim}); + + diff --git a/modules/paypal/views/templates/admin/admin_order/capture.tpl b/modules/paypal/views/templates/admin/admin_order/capture.tpl new file mode 100644 index 00000000..65242557 --- /dev/null +++ b/modules/paypal/views/templates/admin/admin_order/capture.tpl @@ -0,0 +1,100 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +{if $smarty.const._PS_VERSION_ >= 1.6} +
    +
    +
    +
    {l s='PayPal Capture' mod='paypal'}
    + {if $list_captures|@count gt 0} + + + + + + + {foreach from=$list_captures item=list} + + + + + + {/foreach} +
    {l s='Capture date' mod='paypal'}{l s='Capture Amount' mod='paypal'}{l s='Result Capture' mod='paypal'}
    {Tools::displayDate($list.date_add, $smarty.const.null,true)}{$list.capture_amount}{$list.result}
    + {/if} +
    +

    {l s='There is still' mod='paypal'} {$rest_to_capture} {$id_currency} {l s='to capture.' mod='paypal'} {l s='How many do you want to capture :' mod='paypal'}

    + + + +

    {l s='Information:' mod='paypal'} {l s='Funds ready to be captured before shipping' mod='paypal'}

    +

    + +

    +
    +
    +
    +
    +{else} +
    +
    + {l s='PayPal Capture' mod='paypal'} +

    {l s='Information:' mod='paypal'} {l s='Funds ready to be captured before shipping' mod='paypal'}

    + {if $list_captures|@count gt 0} + + + + + + + {foreach from=$list_captures item=list} + + + + + + {/foreach} +
    {l s='Capture date' mod='paypal'}{l s='Capture Amount' mod='paypal'}{l s='Result Capture' mod='paypal'}
    {Tools::displayDate($list.date_add, $smarty.const.null,true)}{$list.capture_amount}{$list.result}
    + {/if} +
    +

    {l s='There is still' mod='paypal'} {$rest_to_capture} {$id_currency} {l s='to capture.' mod='paypal'} {l s='How many do you want to capture :' mod='paypal'}

    + + +

    +
    +
    +{literal} + +{/literal} +{/if} diff --git a/modules/paypal/views/templates/admin/admin_order/index.php b/modules/paypal/views/templates/admin/admin_order/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/views/templates/admin/admin_order/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/views/templates/admin/admin_order/refund.tpl b/modules/paypal/views/templates/admin/admin_order/refund.tpl new file mode 100644 index 00000000..ec1ef16b --- /dev/null +++ b/modules/paypal/views/templates/admin/admin_order/refund.tpl @@ -0,0 +1,86 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} +{if $smarty.const._PS_VERSION_ >= 1.6} +
    +
    +
    +
    {l s='PayPal Refund' mod='paypal'}
    + + + + + + + {foreach from=$list_captures item=list} + + + + + + {/foreach} +
    {l s='Capture date' mod='paypal'}{l s='Capture Amount' mod='paypal'}{l s='Result Capture' mod='paypal'}
    {Tools::displayDate($list.date_add, $smarty.const.null,true)}{$list.capture_amount}{$list.result}
    +
    + +

    {l s='Information:' mod='paypal'} {l s='Payment accepted' mod='paypal'}

    +

    {l s='Information:' mod='paypal'} {l s='When you refund a product, a partial refund is made unless you select "Generate a voucher".' mod='paypal'}

    +

    + +

    +
    +
    +
    +
    +{else} +
    +
    + {l s='PayPal Refund' mod='paypal'} +

    {l s='Information:' mod='paypal'} {l s='Payment accepted' mod='paypal'}

    +

    {l s='Information:' mod='paypal'} {l s='When you refund a product, a partial refund is made unless you select "Generate a voucher".' mod='paypal'}

    + + + + + + + {foreach from=$list_captures item=list} + + + + + + {/foreach} +
    {l s='Capture date' mod='paypal'}{l s='Capture Amount' mod='paypal'}{l s='Result Capture' mod='paypal'}
    {$list.date}{$list.capture_amount}{$list.result}
    +
    + +

    + +

    +
    +
    + +{/if} diff --git a/modules/paypal/views/templates/admin/admin_order/validation.tpl b/modules/paypal/views/templates/admin/admin_order/validation.tpl new file mode 100644 index 00000000..32718547 --- /dev/null +++ b/modules/paypal/views/templates/admin/admin_order/validation.tpl @@ -0,0 +1,56 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +{if $smarty.const._PS_VERSION_ >= 1.6} +
    +
    +
    +
    {l s='PayPal Validation' mod='paypal'}
    +
    + +

    {l s='Information:' mod='paypal'} {if $order_state == $authorization}{l s='Pending Capture - No shipping' mod='paypal'}{else}{l s='Pending Payment - No shipping' mod='paypal'}{/if}

    +

    + +

    +
    +
    +
    +
    +{else} +
    +
    + {l s='PayPal Validation' mod='paypal'} +

    {l s='Information:' mod='paypal'} {if $order_state == $authorization}{l s='Pending Capture - No shipping' mod='paypal'}{else}{l s='Pending Payment - No shipping' mod='paypal'}{/if}

    +
    + +

    +
    +
    +{/if} + + diff --git a/modules/paypal/views/templates/admin/back_office.tpl b/modules/paypal/views/templates/admin/back_office.tpl new file mode 100644 index 00000000..f6869083 --- /dev/null +++ b/modules/paypal/views/templates/admin/back_office.tpl @@ -0,0 +1,389 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +
    + + {* PayPal configuration page header *} + +
    + {if isset($PayPal_logo.LocalPayPalLogoLarge)} + + {/if} +

    {$PayPal_content.leader} {$PayPal_content.online_payment}

    +

    {$PayPal_content.tagline}

    +
    + +
    +
      {$PayPal_content.benefits}
    +
    + + {if $default_lang_iso == 'fr'} +

    +
    + {l s='Download the ' mod='paypal'} {l s='Paypal Integration Guide' mod='paypal'} {l s='on PrestaShop and follow the configuration step by step' mod='paypal'} + +
    + {else} +

    +
    + {l s='Download the ' mod='paypal'} {l s='Paypal Integration Guide' mod='paypal'} {l s='on PrestaShop and follow the configuration step by step' mod='paypal'} + +
    + + {/if} +

    + +
    + {* PayPal configuration blocks *} +
    +
    {$PayPal_content.expectations}
    +
    +
    + + +
    +

    {$PayPal_content.country_change_title} :

    + + + +
    +
    +
    +
    + + + + +
    +
    + +

    + + {* SELECT YOUR SOLUTION *} +
    + +
    +
    {$PayPal_content.customer_support} {if !empty($PayPal_content.customer_support_image)}Phone{/if}
    +
    {$PayPal_content.support_foonote}
    +
    + + 1

    {$PayPal_content.select_solution}

    {$PayPal_content.learn_more} + +


    + + {if (in_array($PayPal_WPS, $PayPal_allowed_methods) || in_array($PayPal_HSS, $PayPal_allowed_methods))} +

    {$PayPal_content.sole_solution_section_title}

    +
    +
    + {if (in_array($PayPal_WPS, $PayPal_allowed_methods))} + {* WEBSITE PAYMENT STANDARD *} + + {/if} + + {if (in_array($PayPal_HSS, $PayPal_allowed_methods))} + {* WEBSITE PAYMENT PRO *} +
    + + {/if} +
    + {/if} + + {if (in_array($PayPal_ECS, $PayPal_allowed_methods))} +

    {$PayPal_content.additional_solution_tagline}

    +
    + {* EXPRESS CHECKOUT SOLUTION *} + +
    + {/if} + +
    +
    + + + + {* END OF USE PAYPAL LOGIN *} + + {* SUBSCRIBE OR OPEN YOUR PAYPAL BUSINESS ACCOUNT *} +
    + + 2

    {$PayPal_content.account_section_title}

    + +

    + +
    + {* Use cases 1 - 3 *} + + + + + {* Use cases 4 - 6 *} + {**} + + {**} + +

    + + {* Use cases 1 - 3 *} + + + + + {* Use cases 4 - 6 *} + + + + +
    + +
    + +
    + + {* ENABLE YOUR ONLINE SHOP TO PROCESS PAYMENT *} +
    + 3

    {$PayPal_content.credentials_section_title|escape:'htmlall':'UTF-8'}

    + +

    + + {$PayPal_content.credentials_tagline|escape:'htmlall':'UTF-8'} + +
    + {* Credentials *} + +
    +

    {$PayPal_content.credentials_description|escape:'htmlall':'UTF-8'}

    + +
    + + + {$PayPal_content.credentials_button|escape:'htmlall':'UTF-8'}

    {$PayPal_content.credentials_button_disclaimer|escape:'htmlall':'UTF-8'}

    +
    + +

    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + {$PayPal_content.credentials_fields_disclaimer|escape:'htmlall':'UTF-8'} +
    + + +
    +

    {$PayPal_content.credentials_integral_description|escape:'htmlall':'UTF-8'}

    + +
    + +
    +
    +
    +
    +
    + +
    + +

    {$PayPal_content.setup_finalize_title|escape:'htmlall':'UTF-8'} :

    +

    1. {$PayPal_content.setup_reminder_1|escape:'htmlall':'UTF-8'}

    +

    2. {$PayPal_content.setup_reminder_2|escape:'htmlall':'UTF-8'}

    + +

    {$PayPal_content.configuration_options_title|escape:'htmlall':'UTF-8'}

    +
    +

    + {$PayPal_content.integral_evolution_solution|escape:'htmlall':'UTF-8'} +

    +
    +
    +
    +

    + {$PayPal_content.template_to_choose|escape:'htmlall':'UTF-8'} +

    +
    +      +           +           +
    + + +
    + +
    +

    {$PayPal_content.express_checkout_shortcut_title|escape:'htmlall':'UTF-8'}

    +

    {$PayPal_content.express_checkout_shortcut_tagline|escape:'htmlall':'UTF-8'}

    +
    + +
    + +
    +

    {$PayPal_content.in_context_checkout_title|escape:'htmlall':'UTF-8'}

    +

    {$PayPal_content.in_context_checkout_tagline|escape:'htmlall':'UTF-8'}

    +
    + +

    + + +

    +
    + +
    +

    {l s='Use the PayPal Login functionnality' mod='paypal'}{if $default_lang_iso == 'fr'}{l s='(*see the ' mod='paypal'} {l s='integration guide' mod='paypal'} {l s='and follow the steps' mod='paypal'}){else}{l s='(*see the ' mod='paypal'} {l s='integration guide' mod='paypal'} {l s='and follow the steps' mod='paypal'}){/if}

    +

    + {l s='This function allows to your clients to connect with their PayPal credentials to shorten the check out' mod='paypal'} +

    +
    +

    +
    + +
    + +
    + + +

    {$PayPal_content.sandbox_title|escape:'htmlall':'UTF-8'}

    +

    {$PayPal_content.sandbox_tagline|escape:'htmlall':'UTF-8'} {$PayPal_content.sandbox_learn_more|escape:'htmlall':'UTF-8'}

    +
    + + +
    + +

    {$PayPal_content.payment_type_title|escape:'htmlall':'UTF-8'}

    +

    {$PayPal_content.payment_type_tagline|escape:'htmlall':'UTF-8'}

    +
    + + +

    +
    + + + + +
    +

    {$PayPal_content.sandbox_confirmation_title} :

    +
      + {$PayPal_content.sandbox_confirmation_content} +
    + +

    {$PayPal_content.sandbox_confirmation_question}

    + +
    + + +
    +
    + + {if isset($PayPal_save_success)} +
    +

    {$PayPal_content.congratulation_title|escape:'htmlall':'UTF-8'}

    + {if $PayPal_sandbox_mode == 0} +

    {$PayPal_content.congratulation_live_mode|escape:'htmlall':'UTF-8'}

    + {elseif $PayPal_sandbox_mode == 1} +

    {$PayPal_content.congratulation_test_mode|escape:'htmlall':'UTF-8'}

    + {/if} +
    + {/if} + {if isset($PayPal_save_failure)} +
    +

    {l s='Error !' mod='paypal'}

    +

    {$PayPal_content.error_message|escape:'htmlall':'UTF-8'}

    +
    + {/if} + +
    +

    {l s='Error !' mod='paypal'}

    +

    {$PayPal_content.error_message|escape:'htmlall':'UTF-8'}

    +
    + +
    +
    +
    + +
    +

    + {$PayPal_content.express_checkout_tagline_source|escape:'htmlall':'UTF-8'} +

    +
    + +
    diff --git a/modules/paypal/views/templates/admin/header.tpl b/modules/paypal/views/templates/admin/header.tpl new file mode 100644 index 00000000..7a64e53a --- /dev/null +++ b/modules/paypal/views/templates/admin/header.tpl @@ -0,0 +1,32 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + + + + \ No newline at end of file diff --git a/modules/paypal/views/templates/admin/index.php b/modules/paypal/views/templates/admin/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/views/templates/admin/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/views/templates/front/about.tpl b/modules/paypal/views/templates/front/about.tpl new file mode 100644 index 00000000..8db3b399 --- /dev/null +++ b/modules/paypal/views/templates/front/about.tpl @@ -0,0 +1,41 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +

    {l s='What Is PayPal?' mod='paypal'}

    + +
    +

    {l s='PayPal, the trusted leader in online payments, enables buyers and businesses to send and receive money online. PayPal has over 100 million member accounts in 190 countries and regions. It\'s accepted by merchants everywhere, both on and off eBay.' mod='paypal'}

    +

    {l s='Is it safe to use?' mod='paypal'}

    +

    {l s='PayPal helps protect your credit card information with industry-leading security and fraud prevention systems. When you use PayPal, your financial information is never shared with the merchant.' mod='paypal'}

    +

    {l s='Why use PayPal?' mod='paypal'}

    +

    +

      +
    • {l s='Make purchases or send money with PayPal - it\'s free' mod='paypal'}
    • +
    • {l s='Shop and pay conveniently by saving your information with PayPal' mod='paypal'}
    • +
    • {l s='PayPal is accepted by millions of businesses worldwide and is the preferred payment method on eBay' mod='paypal'}
    • +
    +

    +

    {l s='Start using PayPal today!' mod='paypal'}

    +
    \ No newline at end of file diff --git a/modules/paypal/views/templates/front/error.tpl b/modules/paypal/views/templates/front/error.tpl new file mode 100644 index 00000000..71c93671 --- /dev/null +++ b/modules/paypal/views/templates/front/error.tpl @@ -0,0 +1,57 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +{if $smarty.const._PS_VERSION_ < 1.5 && isset($use_mobile) && $use_mobile} + {include file="$tpl_dir./modules/paypal/views/templates/front/error.tpl"} +{else} + {capture name=path}{l s='Your shopping cart' mod='paypal'} {$navigationPipe|escape:'htmlall':'UTF-8'} {l s='PayPal' mod='paypal'}{/capture} + {include file="$tpl_dir./breadcrumb.tpl"} + +

    {$message|escape:'htmlall':'UTF-8'}

    + {if isset($logs) && $logs} +
    +

    {l s='Please try to contact the merchant:' mod='paypal'}

    + +
      + {foreach from=$logs key=key item=log} +
    1. {$log|escape:'htmlall':'UTF-8'}
    2. + {/foreach} +
    + +
    + + {if isset($order)} +

    + {l s='Total of the transaction (taxes incl.) :' mod='paypal'} {$price|escape:'htmlall':'UTF-8'}
    + {l s='Your order ID is :' mod='paypal'} {$order.id_order|intval}
    +

    + {/if} + +

    « {l s='Back' mod='paypal'}

    +
    + + {/if} + +{/if} diff --git a/modules/paypal/views/templates/front/index.php b/modules/paypal/views/templates/front/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/views/templates/front/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/views/templates/front/order-confirmation-mobile.tpl b/modules/paypal/views/templates/front/order-confirmation-mobile.tpl new file mode 100644 index 00000000..f400d5db --- /dev/null +++ b/modules/paypal/views/templates/front/order-confirmation-mobile.tpl @@ -0,0 +1,69 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +
    + {include file="$tpl_dir./errors.tpl"} + +

    {l s='Order confirmation' mod='paypal'}

    + + {assign var='current_step' value='payment'} + + {include file="$tpl_dir./errors.tpl"} + + {$HOOK_ORDER_CONFIRMATION} + {$HOOK_PAYMENT_RETURN} + +
    + + {if $order} +

    {l s='Total of the transaction (taxes incl.) :' mod='paypal'} {$price|escape:'htmlall':'UTF-8'}

    +

    {l s='Your order ID is :' mod='paypal'} + + {if $smarty.const._PS_VERSION_ >= 1.5} + {Order::getUniqReferenceOf($order.id_order)} + {else} + {$order.id_order|intval} + {/if} + +

    +

    {l s='Your PayPal transaction ID is :' mod='paypal'} {$order.id_transaction|escape:'htmlall':'UTF-8'}

    + {/if} + +
    + + {if !$is_guest} + {l s='Continue shopping' mod='paypal'} + {else} + + {/if} +
    +
    diff --git a/modules/paypal/views/templates/front/order-confirmation.tpl b/modules/paypal/views/templates/front/order-confirmation.tpl new file mode 100644 index 00000000..a0340981 --- /dev/null +++ b/modules/paypal/views/templates/front/order-confirmation.tpl @@ -0,0 +1,81 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +{if $smarty.const._PS_VERSION_ < 1.5 && isset($use_mobile) && $use_mobile} + {include file="$tpl_dir./modules/paypal/views/templates/front/order-confirmation.tpl"} +{else} + {capture name=path}{l s='Order confirmation' mod='paypal'}{/capture} + {if $smarty.const._PS_VERSION_ < 1.6} + {include file="$tpl_dir./breadcrumb.tpl"} + {/if} +

    {l s='Order confirmation' mod='paypal'}

    + + {assign var='current_step' value='payment'} + {include file="$tpl_dir./order-steps.tpl"} + + {include file="$tpl_dir./errors.tpl"} + + {$HOOK_ORDER_CONFIRMATION} + {$HOOK_PAYMENT_RETURN} + +
    + + {if $order} +

    {l s='Total of the transaction (taxes incl.) :' mod='paypal'} {$price|escape:'htmlall':'UTF-8'}

    +

    {l s='Your order ID is :' mod='paypal'} + + {if $smarty.const._PS_VERSION_ >= 1.5} + {if isset($reference_order)} + {$reference_order|escape:'htmlall':'UTF-8'} + {else} + {$order.id_order|intval} + {/if} + {else} + {$order.id_order|intval} + {/if} + +

    +

    {l s='Your PayPal transaction ID is :' mod='paypal'} {$order.id_transaction|escape:'htmlall':'UTF-8'}

    + {/if} +
    + + {if $is_guest} + + {if $smarty.const._PS_VERSION_ < 1.6} + {l s='Follow my order' mod='paypal'} + {else} + + {/if} + + {l s='Follow my order' mod='paypal'} + {else} + {if $smarty.const._PS_VERSION_ < 1.6} + {l s='Follow my order' mod='paypal'} + {else} + + {/if} + {l s='Back to orders' mod='paypal'} + {/if} +{/if} diff --git a/modules/paypal/views/templates/front/order-summary.tpl b/modules/paypal/views/templates/front/order-summary.tpl new file mode 100644 index 00000000..30222ae1 --- /dev/null +++ b/modules/paypal/views/templates/front/order-summary.tpl @@ -0,0 +1,64 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} +{if $smarty.const._PS_VERSION_ < 1.5 && isset($use_mobile) && $use_mobile} + {include file="$tpl_dir./modules/paypal/views/templates/front/order-summary.tpl"} +{else} + {capture name=path}{l s='Your shopping cart' mod='paypal'} {$navigationPipe|escape:'htmlall':'UTF-8'} {l s='PayPal' mod='paypal'}{/capture} + {if $smarty.const._PS_VERSION_ < 1.6} + {include file="$tpl_dir./breadcrumb.tpl"} + {/if} +

    {l s='Order summary' mod='paypal'}

    + + {assign var='current_step' value='payment'} + {include file="$tpl_dir./order-steps.tpl"} + +

    {l s='PayPal payment' mod='paypal'}

    +
    +

    + {l s='PayPal' mod='paypal'} +
    {l s='You have chosen to pay with PayPal.' mod='paypal'} +

    + {l s='Here is a short summary of your order:' mod='paypal'} +

    +

    + {l s='Shipping address' mod='paypal'}
    + {AddressFormat::generateAddress($address, array(), '
    ')} + +

    +

    + - {l s='The total amount of your order is' mod='paypal'} + {$total|escape:'htmlall':'UTF-8'} {if $use_taxes == 1}{l s='(tax incl.)' mod='paypal'}{/if} +

    +

    + - {l s='We accept the following currency to be sent by PayPal:' mod='paypal'} {$currency->name|escape:'htmlall':'UTF-8'} +

    +

    + {l s='Please confirm your order by clicking \'I confirm my order\'' mod='paypal'}. +

    +

    + +

    +
    +{/if} diff --git a/modules/paypal/views/templates/hook/column.tpl b/modules/paypal/views/templates/hook/column.tpl new file mode 100644 index 00000000..8fb2f32e --- /dev/null +++ b/modules/paypal/views/templates/hook/column.tpl @@ -0,0 +1,28 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +
    +

    PayPal

    +
    diff --git a/modules/paypal/views/templates/hook/confirmation.tpl b/modules/paypal/views/templates/hook/confirmation.tpl new file mode 100644 index 00000000..59c7b010 --- /dev/null +++ b/modules/paypal/views/templates/hook/confirmation.tpl @@ -0,0 +1,32 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +

    {l s='Your order on' mod='paypal'} {$shop_name|escape:'htmlall':'UTF-8'} {l s='is complete.' mod='paypal'} +

    + {l s='You have chosen the PayPal method.' mod='paypal'} +

    {l s='Your order will be sent very soon.' mod='paypal'} +

    {l s='For any questions or for further information, please contact our' mod='paypal'} + {l s='customer support' mod='paypal'}. +

    diff --git a/modules/paypal/views/templates/hook/express_checkout_payment.tpl b/modules/paypal/views/templates/hook/express_checkout_payment.tpl new file mode 100644 index 00000000..6852eaf9 --- /dev/null +++ b/modules/paypal/views/templates/hook/express_checkout_payment.tpl @@ -0,0 +1,93 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +{if $smarty.const._PS_VERSION_ >= 1.6} + + + + +{else} +

    + + {if isset($use_mobile) && $use_mobile} + + {else} + {if isset($logos.LocalPayPalHorizontalSolutionPP) && $PayPal_payment_method == $PayPal_integral} + {$PayPal_content.payment_choice|escape:'htmlall':'UTF-8'} + {else} + {$PayPal_content.payment_choice|escape:'htmlall':'UTF-8'} + {/if} + {$PayPal_content.payment_choice} + {/if} + + +

    + +{/if} + + +{if $PayPal_in_context_checkout == 1} + +{else} + +{/if} +
    + + + +
    \ No newline at end of file diff --git a/modules/paypal/views/templates/hook/express_checkout_payment_eu.tpl b/modules/paypal/views/templates/hook/express_checkout_payment_eu.tpl new file mode 100644 index 00000000..0f34a617 --- /dev/null +++ b/modules/paypal/views/templates/hook/express_checkout_payment_eu.tpl @@ -0,0 +1,30 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} +
    + @hiddenSubmit + + + +
    diff --git a/modules/paypal/views/templates/hook/express_checkout_shortcut_button.tpl b/modules/paypal/views/templates/hook/express_checkout_shortcut_button.tpl new file mode 100644 index 00000000..d65b6a9d --- /dev/null +++ b/modules/paypal/views/templates/hook/express_checkout_shortcut_button.tpl @@ -0,0 +1,42 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +
    + {if isset($use_mobile) && $use_mobile} +
    + +
    + {else} + {if $paypal_express_checkout_shortcut_logo != false} + + {else} + + {/if} + {/if} + {if isset($include_form) && $include_form} + {include file="$template_dir./express_checkout_shortcut_form.tpl"} + {/if} +
    +
    diff --git a/modules/paypal/views/templates/hook/express_checkout_shortcut_form.tpl b/modules/paypal/views/templates/hook/express_checkout_shortcut_form.tpl new file mode 100644 index 00000000..01f593b5 --- /dev/null +++ b/modules/paypal/views/templates/hook/express_checkout_shortcut_form.tpl @@ -0,0 +1,42 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +
    + {if isset($smarty.get.id_product)}{/if} + + + + + + +
    + +{if $PayPal_in_context_checkout == 1} + +{else} + +{/if} + + diff --git a/modules/paypal/views/templates/hook/index.php b/modules/paypal/views/templates/hook/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/views/templates/hook/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file diff --git a/modules/paypal/views/templates/hook/integral_evolution_payment.tpl b/modules/paypal/views/templates/hook/integral_evolution_payment.tpl new file mode 100644 index 00000000..9f47410f --- /dev/null +++ b/modules/paypal/views/templates/hook/integral_evolution_payment.tpl @@ -0,0 +1,122 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + + +{*Displaying a button or the iframe*} +{if $payment_hss_solution == $smarty.const.PAYPAL_HSS_REDIRECTION} + {if $smarty.const._PS_VERSION_ >= 1.6} + + + {else} +

    + + + {$PayPal_content.payment_choice|escape:'htmlall':'UTF-8'} + {$PayPal_content.payment_choice|escape:'htmlall':'UTF-8'} + +

    + {/if} +{else} + {if $smarty.const._PS_VERSION_ >= 1.6} +
    +
    +

    + +

    +
    +
    + {else} +
    + + {/if} +{/if} + + + + + +{if $payment_hss_solution == $smarty.const.PAYPAL_HSS_IFRAME} +{literal} + +{/literal} +{/if} diff --git a/modules/paypal/views/templates/hook/integral_evolution_payment_eu.tpl b/modules/paypal/views/templates/hook/integral_evolution_payment_eu.tpl new file mode 100644 index 00000000..2abea483 --- /dev/null +++ b/modules/paypal/views/templates/hook/integral_evolution_payment_eu.tpl @@ -0,0 +1,71 @@ +{* +* 2007-2015 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* If you did not receive a copy of the license and are unable to +* obtain it through the world-wide-web, please send an email +* to license@prestashop.com so we can send you a copy immediately. +* +* DISCLAIMER +* +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer +* versions in the future. If you wish to customize PrestaShop for your +* needs please refer to http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + + diff --git a/modules/paypal/views/templates/index.php b/modules/paypal/views/templates/index.php new file mode 100644 index 00000000..3a5daa1f --- /dev/null +++ b/modules/paypal/views/templates/index.php @@ -0,0 +1,35 @@ + +* @copyright 2007-2015 PrestaShop SA +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); +header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); + +header("Cache-Control: no-store, no-cache, must-revalidate"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +header("Location: ../"); +exit; \ No newline at end of file